Skip to content

📓 feat: Author Files in Attached Workspaces - #15548

Merged
danny-avila merged 6 commits into
devfrom
danny-avila/code-workspace-create
Sep 4, 2026
Merged

danny-avila merged 6 commits into
devfrom
danny-avila/code-workspace-create

Conversation

@danny-avila

@danny-avila danny-avila commented Sep 3, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

I routed the existing create_file and edit_file tools through a selected attached BYOM workspace while preserving their canonical names for approval hooks and managed-environment compatibility. This PR depends on LibreChat #15546 and Code Interpreter #102–#103.

  • Add bounded write_file and atomic batch edit_file validation to LibreChat's worker protocol adapter.
  • Reuse Code API authentication, execution-profile, principal-bound worker selection, cancellation, and safe error normalization for mutations.
  • Require the model-facing workspace/{relativePath} namespace without exposing the worker's absolute host path.
  • Preserve create-only behavior through overwrite: false, and surface deterministic conflict guidance instead of replacing files silently.
  • Apply every exact edit as one worker mutation so a failed replacement leaves the file unchanged.
  • Inspect outbound paths and content through existing tool-argument and file-content protections before dispatch.
  • Keep canonical create_file and edit_file identities so the default permission layer and future customizable approval hooks govern BYOM exactly like managed code environments.
  • Cover the protocol adapter, host callbacks, dependency wiring, tool definitions, approval-facing routing, conflicts, atomic edits, abort propagation, and protected-content blocking.

Change Type

  • New feature (non-breaking change which adds functionality)

Testing

  • Ran 242 focused @librechat/api tests covering workspace protocol, agent handlers, tool registration, and initialization.
  • Ran 147 focused API service tests covering Code process callbacks and agent dependency wiring before the final restack; those files were unchanged by the restack.
  • Ran ESLint, Prettier, import sorting, and git diff --check across all changed files.
  • Ran a live cross-repository E2E with Code API on port 23114, local Redis, and an outbound @librechat/code worker attached to a new empty non-Git directory. Verified create-only conflict (409), two-edit atomic commit, no partial mutation after a later failed batch, persistent readback, traversal rejection, and cleared mutation quarantine.

Test Configuration:

Checklist

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • I have commented in any complex areas of my code
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective or that my feature works
  • Local unit tests pass with my changes
  • Any changes dependent on mine have been merged and published in downstream modules.

Dependency

@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review exact head 13e0046

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-04T04:02:40.592835Z 4770d09 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 13e00464bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread packages/api/src/agents/tools.ts Outdated
Comment thread packages/api/src/code/workspace.ts Outdated
Comment thread packages/api/src/agents/handlers.ts Outdated
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current PR head 91f8063. Confirm that this exact commit is the reviewed commit and ignore findings that apply only to earlier heads.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 91f80633ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread packages/api/src/agents/tools.ts
Comment thread packages/api/src/code/workspace.ts
@danny-avila

Copy link
Copy Markdown
Collaborator Author

Live cross-repo verification passed against Code Interpreter #104 through Code API on port 23114, Redis, and an outbound worker. Verified exact final-content preview, stale revision rejection, fresh fenced commit persistence, and the final BOM-normalized result schema.

Current head includes only the review fixes plus the isolated-declaration annotation and BOM result-shape alignment after the acknowledged review request; no additional Codex request was made.

@danny-avila danny-avila changed the title 🪡 feat(code): Route File Mutations to Attached Workspaces 🖋️ feat(code): Enable File Mutations in Attached Workspaces Sep 3, 2026
Copilot AI lite review requested due to automatic review settings September 4, 2026 04:00
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current PR head 4770d09. Confirm that this exact commit is the reviewed commit and ignore findings that apply only to earlier heads.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 4770d09f6c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

This PR enables create_file / edit_file to safely mutate files inside a selected attached (BYOM) workspace by extending the workspace-tools protocol and routing file-authoring calls through the attached worker while preserving the canonical tool identities and approval behavior.

Changes:

  • Extend the workspace-tools protocol adapter with write_file, edit_file, and preview_edit request/result schemas plus bounded validation.
  • Route host-side create_file / edit_file to attached workspace mutations (with conflict handling, atomic edits, and protected-content preview fencing).
  • Wire new mutation functions through the server Code process + agent deps and add targeted unit tests.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/api/src/code/workspace.ts Adds protocol types + validation for workspace write/edit/preview operations.
packages/api/src/code/workspace.spec.ts Adds adapter-level tests for write/edit/preview validation and fencing.
packages/api/src/agents/tools.ts Adds attached-workspace tool definitions/descriptions and registration toggles.
packages/api/src/agents/tools.spec.ts Tests attached-workspace descriptions/semantics are registered as expected.
packages/api/src/agents/initialize.ts Plumbs workspaceTools into tool registration during agent init.
packages/api/src/agents/handlers.ts Implements attached-workspace create/edit routing, limits, preview fence, and abort propagation.
packages/api/src/agents/handlers.spec.ts Adds behavioral tests for attached create/edit, conflicts, limits, and protected-content blocking.
api/server/services/Files/Code/process.js Adds Code API forwarding functions for workspace mutations + preview.
api/server/services/Files/Code/process.spec.js Tests forwarding behavior and headers for new workspace mutation calls.
api/server/services/Endpoints/agents/skillDeps.js Exposes new mutation functions to agent handlers via deps wiring.
api/server/services/Endpoints/agents/skillDeps.spec.js Tests deps wiring exposes the new mutation functions.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +3923 to +3931
it('creates a file atomically in an attached workspace', async () => {
const writeWorkspaceFile = jest.fn(async () => ({
protocolVersion: 1 as const,
operation: 'write_file' as const,
workspaceId: 'primary',
path: 'src/new.ts',
created: true,
bytesWritten: 20,
}));
Comment on lines +3537 to +3547
function attachedWorkspaceAuthoringPath(
tc: ToolCallRequest,
filePath: string,
): { filePath: string } | ToolExecuteResult {
if (!filePath.startsWith('workspace/')) {
return errorResult(tc, 'Attached environment file paths must use "workspace/{relativePath}".');
}
const relativePath = filePath.slice('workspace/'.length);
const pathError = invalidSandboxAuthoringPath(relativePath);
return pathError ? errorResult(tc, pathError) : { filePath: relativePath };
}
Comment on lines +3610 to +3616
const action = result.created ? 'Created' : 'Updated';
return successResult(tc, `${action} workspace/${path.filePath} (${content.length} chars).`, {
path: `workspace/${path.filePath}`,
[HOST_FILE_AUTHORING_ARTIFACT_KEY]: true,
bytes_written: result.bytesWritten,
created: result.created,
});
Comment on lines 809 to 823
function isCodeOnlyFileAuthoringDef(def: LCTool | undefined): boolean {
if (def?.name === CREATE_FILE_TOOL_NAME) {
return def.description === CODE_CREATE_FILE_DESCRIPTION;
return (
def.description === CODE_CREATE_FILE_DESCRIPTION ||
def.description === ATTACHED_CODE_CREATE_FILE_DESCRIPTION
);
}
if (def?.name === EDIT_FILE_TOOL_NAME) {
return def.description === CODE_EDIT_FILE_DESCRIPTION;
return (
def.description === CODE_EDIT_FILE_DESCRIPTION ||
def.description === ATTACHED_CODE_EDIT_FILE_DESCRIPTION
);
}
return false;
}
Comment on lines +533 to +548
if (request.operation === 'preview_edit') {
const content = typeof value.content === 'string' ? value.content : null;
return (
hasOnlyKeys(value, PREVIEW_EDIT_RESULT_KEYS) &&
value.path === request.path &&
content != null &&
Buffer.from(content).toString('utf8') === content &&
typeof value.hasUtf8Bom === 'boolean' &&
/^[a-f0-9]{64}$/.test(typeof value.baseSha256 === 'string' ? value.baseSha256 : '') &&
value.replacements === request.edits.length &&
Number.isSafeInteger(value.bytesWritten) &&
Number(value.bytesWritten) ===
new TextEncoder().encode(content).byteLength + (value.hasUtf8Bom ? 3 : 0) &&
Number(value.bytesWritten) <= WORKSPACE_WRITE_MAX_BYTES
);
}
Comment on lines +283 to +303
function areValidWorkspaceEdits(edits: unknown): edits is WorkspaceTextEdit[] {
if (!Array.isArray(edits)) return false;
if (edits.length < 1 || edits.length > WORKSPACE_EDIT_MAX_COUNT) return false;
let bytes = 0;
for (const edit of edits) {
if (
!isRecord(edit) ||
!hasOnlyKeys(edit, TEXT_EDIT_KEYS) ||
!isUtf8StringWithinBytes(edit.oldText, WORKSPACE_WRITE_MAX_BYTES) ||
edit.oldText.length === 0 ||
!isUtf8StringWithinBytes(edit.newText, WORKSPACE_WRITE_MAX_BYTES)
) {
return false;
}
bytes +=
new TextEncoder().encode(edit.oldText).byteLength +
new TextEncoder().encode(edit.newText).byteLength;
if (bytes > WORKSPACE_WRITE_MAX_BYTES) return false;
}
return true;
}
Base automatically changed from danny-avila/code-workspace-command to dev September 4, 2026 15:49
@danny-avila
danny-avila force-pushed the danny-avila/code-workspace-create branch from 709c411 to 50a4d58 Compare September 4, 2026 15:56
@danny-avila danny-avila changed the title 🖋️ feat(code): Enable File Mutations in Attached Workspaces 📓 feat: Author Files in Attached Workspaces Sep 4, 2026
@danny-avila
danny-avila merged commit 7d9db14 into dev Sep 4, 2026
31 checks passed
@danny-avila
danny-avila deleted the danny-avila/code-workspace-create branch September 4, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants