Repository navigation
🛻 feat: Route Bash Through Attached Workspaces - #15546
Conversation
|
Live BYOM verification completed against Code Interpreter #101 exact head
Focused package tests remain 233/233 passing, package declaration build passes, and changed-file ESLint passes. |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. Breezy! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Codex Review: Didn't find any major issues. Bravo. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Pull request overview
Adds support for running the existing approval-gated bash_tool through an attached workspace (“BYOM” worker) transport while keeping the managed Code API execution path intact.
Changes:
- Extends the workspace tool protocol to include an
execute_commandoperation with request/result validation and bounded timeouts/output. - Introduces an attached-workspace-backed bash tool implementation and exports it from the API package.
- Routes
bash_toolto the attached transport whenenvironmentType === 'attached', and updates tool definitions/tests accordingly.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/api/src/code/workspace.ts | Adds execute_command request/result types, protocol validation, and adjusted timeout behavior with a transport grace period |
| packages/api/src/code/workspace.spec.ts | Adds tests for valid/invalid execute_command requests/results |
| packages/api/src/code/index.ts | Exports the new command module |
| packages/api/src/code/command.ts | Implements the attached-workspace bash tool wrapper and command argument quoting/formatting |
| packages/api/src/code/command.spec.ts | Tests attached-workspace bash tool behavior (auth headers, quoting, formatting) |
| packages/api/src/agents/tools.ts | Switches bash tool description/schema when workspace tools are enabled |
| packages/api/src/agents/tools.spec.ts | Updates mocks/assertions for the new attached bash definition behavior |
| api/server/services/tests/ToolService.spec.js | Verifies ToolService loads the attached bash tool for attached environments |
| api/server/services/ToolService.js | Routes bash tool creation via createAttachedWorkspaceBashTool when attached |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if (request.operation === 'execute_command') { | ||
| const stdout = typeof value.stdout === 'string' ? value.stdout : null; | ||
| const stderr = typeof value.stderr === 'string' ? value.stderr : null; | ||
| const outputLimit = request.maxOutputBytes ?? DEFAULT_COMMAND_OUTPUT_BYTES; | ||
| return ( | ||
| hasOnlyKeys(value, COMMAND_RESULT_KEYS) && | ||
| stdout != null && | ||
| stderr != null && | ||
| Buffer.from(stdout).toString('utf8') === stdout && | ||
| Buffer.from(stderr).toString('utf8') === stderr && | ||
| new TextEncoder().encode(stdout).byteLength + new TextEncoder().encode(stderr).byteLength <= | ||
| outputLimit && | ||
| (value.exitCode === null || | ||
| (Number.isSafeInteger(value.exitCode) && | ||
| Number(value.exitCode) >= 0 && | ||
| Number(value.exitCode) <= 255)) && | ||
| (value.signal == null || | ||
| (typeof value.signal === 'string' && | ||
| value.signal.length <= MAX_COMMAND_SIGNAL_LENGTH && | ||
| /^SIG[A-Z0-9]+$/.test(value.signal))) && | ||
| typeof value.timedOut === 'boolean' && | ||
| (value.exitCode === null | ||
| ? value.timedOut === true || value.signal != null | ||
| : value.timedOut === false && value.signal == null) | ||
| ); | ||
| } |
| { | ||
| name: BashExecutionToolDefinition.name, | ||
| description: ATTACHED_WORKSPACE_BASH_DESCRIPTION, | ||
| schema: ATTACHED_WORKSPACE_BASH_SCHEMA, | ||
| responseFormat: 'content_and_artifact', | ||
| }, |
| return ( | ||
| typeof value === 'string' && | ||
| Buffer.from(value).toString('utf8') === value && | ||
| new TextEncoder().encode(value).byteLength <= maximum |
| const bashSchema = BashExecutionToolDefinition.schema as { | ||
| properties?: NonNullable<LCTool['parameters']>['properties']; | ||
| }; | ||
| const attachedCommandSchema: NonNullable<LCTool['parameters']> = { | ||
| ...bashSchema.properties?.command, | ||
| type: 'string', | ||
| description: | ||
| 'The bash command or script to execute from the attached workspace root. Files written in the workspace persist between calls, but each call starts a fresh process.', | ||
| }; |
08a48d8 to
4be4d64
Compare
Summary
I routed the existing approval-gated
bash_toolthrough the selected attached BYOM environment while preserving the managed Code API execution path. This depends on LibreChat #15527 and the Code Interpreter command stack #97–#101.attached.bash_toolname and schema so hook-based tool approvals remain the single permission gate.Change Type
Testing
jest --runInBand --coverage=false src/code/command.spec.ts src/code/workspace.spec.ts src/agents/tools.spec.ts src/agents/handlers.spec.tsfrompackages/api: 233 tests passed.Test Configuration:
primaryChecklist