shellCommandExecution.ts ×12

Frontier kind: Code frontier

unlabeled · c_80881519dadf

959 tests · 26830 LOC · 121 files · introduces 0 tests · 123 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
12 ranges123 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
2140 ranges26830 lines · 121 files · Browse complete extent
All tests (intent)
959 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 123 introduced LOC across 12 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/agentHost/node/shared/shellCommandExecution.ts 123 introduced LOC · 12 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- shellCommandExecution.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { DisposableStore, toDisposable } from '../../../../base/common/lifecycle.js';
7 > import * as platform from '../../../../base/common/platform.js';
8 > import { removeAnsiEscapeCodes } from '../../../../base/common/strings.js';
9 > import { generateUuid } from '../../../../base/common/uuid.js';
10 > import { ILogService } from '../../../log/common/log.js';
11 > import { TerminalClaimKind } from '../../common/state/protocol/state.js';
12 > import { IAgentHostTerminalManager } from '../agentHostTerminalManager.js';
13 >
14 > /**
15 > * Maximum scrollback content (in bytes) returned to the model / caller in
16 > * command results.
17 > */
18 > export const SHELL_COMMAND_MAX_OUTPUT_BYTES = 80_000;
19 >
20 > /**
21 > * Default command timeout in milliseconds (120 seconds).
22 > */
23 > export const DEFAULT_SHELL_COMMAND_TIMEOUT_MS = 120_000;
24 >
25 > /**
26 > * The sentinel prefix used to detect command completion in terminal output
27 > * when shell integration is unavailable. The full sentinel format is:
28 > * `<<<COPILOT_SENTINEL_<uuid>_EXIT_<code>>>`.
29 > */
30 > const SENTINEL_PREFIX = '<<<COPILOT_SENTINEL_';
31 >
32 > /**
33 > * The kind of shell a command runs in. Determines sentinel syntax, history
34 > * suppression and bracketed-paste heuristics.
35 > */
36 > export type ShellType = 'bash' | 'powershell';
37 >
38 > /**
39 > * Routes a resolved shell executable to a {@link ShellType}. Falls back to the
40 > * platform default for unknown shells.
41 > */
42 > export function shellTypeForExecutable(shellPath: string): ShellType {
43 // Strip path on either separator and the .exe suffix.
44 const lastSep = Math.max(shellPath.lastIndexOf('/'), shellPath.lastIndexOf('\\'));
74 }
75 }
77 > /**
78 > * For POSIX shells (bash/zsh) that honor `HISTCONTROL=ignorespace` /
79 > * `HIST_IGNORE_SPACE`, prepending a single space prevents the command from
80 > * being recorded in shell history. The shell integration scripts opt these
81 > * settings in via the `VSCODE_PREVENT_SHELL_HISTORY` env var (set when the
82 > * terminal is created with `preventShellHistory: true`). PowerShell
83 > * suppresses history through PSReadLine instead, so no prefix is needed.
84 > */
85 > export function prefixForHistorySuppression(shellType: ShellType): string {
86 return shellType === 'powershell' ? '' : ' ';
87 }
89 > export function isMultilineCommand(command: string): boolean {
90 const normalized = command.replace(/\r\n|\r/g, '\n');
91 return /(?<!\\)\n/.test(normalized);
92 }
94 function shouldUseBracketedPasteMode(command: string): boolean {
95 return platform.isMacintosh || isMultilineCommand(command);
96 }
98 function makeSentinelId(): string {
99 return generateUuid().replace(/-/g, '');
100 }
102 function buildSentinelCommand(sentinelId: string, shellType: ShellType): string {
103 if (shellType === 'powershell') {
106 return `echo "${SENTINEL_PREFIX}${sentinelId}_EXIT_$?>>>"`;
107 }
109 function parseSentinel(content: string, sentinelId: string): { found: boolean; exitCode: number; outputBeforeSentinel: string } {
110 const marker = `${SENTINEL_PREFIX}${sentinelId}_EXIT_`;
131 return { found: false, exitCode: -1, outputBeforeSentinel: content };
132 }
134 > /**
135 > * Strips ANSI escape codes and trims the terminal output to the last
136 > * {@link SHELL_COMMAND_MAX_OUTPUT_BYTES} bytes so it is safe to surface to a
137 > * model or the transcript.
138 > */
139 > export function prepareOutputForModel(rawOutput: string): string {
140 let text = removeAnsiEscapeCodes(rawOutput).trim();
141 if (text.length > SHELL_COMMAND_MAX_OUTPUT_BYTES) {
144 return text;
145 }
147 > /**
148 > * Terminal against which a shell command is executed.
149 > */
150 > export interface IShellCommandTarget {
151 > /** URI of the managed terminal the command runs in. */
152 > readonly terminalUri: string;
153 > /** The kind of shell backing the terminal. */
154 > readonly shellType: ShellType;
155 > }
156 >
157 > /**
158 > * How a shell command execution finished.
159 > *
160 > * - `completed` — the command finished; {@link IShellCommandResult.exitCode} holds the exit code.
161 > * - `timeout` — the command did not finish within the timeout; output is partial.
162 > * - `background` — the terminal claim was narrowed (user chose to continue in background).
163 > * - `altBuffer` — the command switched to the terminal's alternate buffer (interactive UI).
164 > * - `shellExited` — the shell process exited unexpectedly.
165 > */
166 > export type ShellCommandStatus = 'completed' | 'timeout' | 'background' | 'altBuffer' | 'shellExited';
167 >
168 > /**
169 > * Neutral, agent-agnostic result of executing a shell command. Callers map this
170 > * to their own result shape (e.g. an SDK `ToolResultObject` or an AHP tool call
171 > * completion).
172 > */
173 > export interface IShellCommandResult {
174 > /** How the command execution finished. */
175 > readonly status: ShellCommandStatus;
176 > /** Exit code, when known (`completed` and `shellExited`). */
177 > readonly exitCode?: number;
178 > /** Cleaned command output (empty for `background`/`altBuffer`). */
179 > readonly output: string;
180 > }
181 >
182 > /**
183 > * Execute a command on an already-created managed terminal, resolving once the
184 > * command finishes, times out, backgrounds, enters the alternate buffer, or the
185 > * shell exits. Uses shell integration (OSC 633) for completion detection when
186 > * available and falls back to a sentinel echo otherwise.
187 > *
188 > * This is the shared shell-integration primitive used by both the Copilot SDK
189 > * shell tools and the agent-host `!command` runner.
190 > */
191 > export function executeShellCommand(
192 target: IShellCommandTarget,
193 command: string,
200 : executeCommandWithSentinel(target, command, timeoutMs, terminalManager, logService);
201 }
203 function registerAltBufferHandler(
204 target: IShellCommandTarget,
213 });
214 }
216 > /**
217 > * Execute a command using shell integration (OSC 633) for completion detection.
218 > * No sentinel echo is injected — the shell's own command-finished signal
219 > * provides the exit code and cleanly delineated output.
220 > */
221 async function executeCommandWithShellIntegration(
222 target: IShellCommandTarget,
282 return result;
283 }
285 > /**
286 > * Fallback: execute a command using a sentinel echo to detect completion.
287 > * Used when shell integration is not available.
288 > */
289 async function executeCommandWithSentinel(
290 target: IShellCommandTarget,