Skip to content

feat: add Monaco Editor for in-browser code editing#30253

Open
LAOXI-OPS wants to merge 2 commits into
anomalyco:devfrom
LAOXI-OPS:feature/monaco-editor
Open

feat: add Monaco Editor for in-browser code editing#30253
LAOXI-OPS wants to merge 2 commits into
anomalyco:devfrom
LAOXI-OPS:feature/monaco-editor

Conversation

@LAOXI-OPS
Copy link
Copy Markdown

@LAOXI-OPS LAOXI-OPS commented Jun 1, 2026

Issue for this PR

Closes #30205

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

This PR adds Monaco Editor to the OpenCode web UI, enabling direct code editing from the browser.

Problem: The web UI only displays code via the read-only Pierre renderer. Users cannot edit files directly - they must ask the agent to make changes.

Solution: Add Monaco Editor as an overlay that appears when the user clicks an Edit button. The Pierre viewer remains for read-only viewing, so Monaco loading failures do not break existing functionality.

Changes:

  • Backend: Add PUT /file/content API endpoint with File.write() service method and path-escape protection
  • SDK: Add file.write() client method
  • Frontend: Create MonacoEditor SolidJS wrapper with syntax highlighting (80+ languages), Ctrl+S save, dark/light theme sync
  • Frontend: Add Edit/Close buttons to file viewer that toggle Monaco overlay
  • Language detection: Map 80+ file extensions to Monaco language IDs

How did you verify your code works?

  1. Ran opencode serve and bun run dev:web locally
  2. Opened test_sample.py in the web UI - confirmed Pierre read-only viewer works
  3. Clicked Edit button - Monaco Editor opened with Python syntax highlighting
  4. Edited code and pressed Ctrl+S - verified file was saved on disk
  5. Clicked Close button - overlay dismissed, Pierre viewer restored
  6. Tested PUT /file/content via curl directly - confirmed API returns success

Screenshots / recordings

N/A - backend + frontend change, tested locally

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Add Monaco Editor as an overlay to the existing Pierre read-only code
viewer, enabling direct code editing from the web UI with Ctrl+S save.

Changes:
- Add PUT /file/content API endpoint for writing files
- Add File.write() method to the file service
- Add SDK file.write() client method
- Create MonacoEditor SolidJS wrapper component with:
  - Syntax highlighting for 80+ languages
  - Ctrl+S / Cmd+S save shortcut
  - Dark/light theme sync
  - Bracket pair colorization
- Add Edit button to file viewer that opens Monaco overlay
- Wire save through file context to backend API

Co-Authored-By: Claude <noreply@anthropic.com>
@LAOXI-OPS LAOXI-OPS requested a review from adamdotdevin as a code owner June 1, 2026 14:53
Copilot AI review requested due to automatic review settings June 1, 2026 14:53
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label Jun 1, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR adds an in-app Monaco-based editor to allow editing and saving file contents from the UI, backed by a new server file.write HTTP API and SDK method.

Changes:

  • Added Monaco editor component + language detection utility for syntax highlighting.
  • Extended text file viewer to open an edit overlay and persist changes via file.write.
  • Implemented server-side write handler + OpenAPI endpoint and generated JS SDK method.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/ui/src/utils/language-map.ts Adds file extension/name → Monaco language mapping utility.
packages/ui/src/components/monaco-editor.tsx Introduces Monaco editor component with worker wiring and theming.
packages/ui/src/components/file.tsx Adds “Edit” overlay and save wiring for text files.
packages/ui/package.json Adds monaco-editor dependency for UI package.
packages/sdk/js/src/v2/gen/sdk.gen.ts Adds generated file.write SDK method.
packages/opencode/src/server/routes/instance/httpapi/handlers/file.ts Implements write handler and publishes related events.
packages/opencode/src/server/routes/instance/httpapi/groups/file.ts Defines PUT /file/content endpoint schema and OpenAPI metadata.
packages/opencode/src/file/index.ts Adds File.Service.write implementation with path-escape protection.
packages/app/vite.js Adds worker output naming + monaco-editor optimizeDeps include.
packages/app/src/pages/session/file-tabs.tsx Passes filePath + onSave handler into text viewer.
packages/app/src/context/file.tsx Adds save() that calls SDK write then reloads content.
packages/app/package.json Adds monaco-editor dependency for app package.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +120 to +123
HttpApiEndpoint.put("write", "/file/content", {
payload: FileWriteBody,
success: described(Schema.Struct({ success: Schema.Boolean }), "Write result"),
}).annotateMerge(
Comment on lines +1633 to +1639
public write<ThrowOnError extends boolean = false>(
parameters: {
directory?: string
workspace?: string
path: string
content: string
},
Comment on lines +11 to +17
getWorker(_: string, label: string) {
if (label === "json") return new jsonWorker()
if (label === "css" || label === "scss" || label === "less") return new cssWorker()
if (label === "html" || label === "handlebars" || label === "razor") return new htmlWorker()
if (label === "typescript" || label === "javascript") return new tsWorker()
return new editorWorker()
},
Comment on lines +9 to +10
// @ts-ignore
self.MonacoEnvironment = {
Comment thread packages/ui/src/utils/language-map.ts Outdated
Comment on lines +31 to +32
r: "r",
R: "r",
Comment thread packages/ui/src/utils/language-map.ts Outdated
htm: "html",
css: "css",
scss: "scss",
sass: "scss",
Comment on lines +950 to +968
{editing() && props.filePath && props.onSave && (
<div
style={{
position: "absolute",
inset: "0",
"z-index": "20",
background: "var(--background-base)",
}}
>
<MonacoEditor
filePath={props.filePath}
content={editContent()}
onSave={(content) => {
props.onSave!(content)
setEditing(false)
}}
/>
</div>
)}
- Add WorkspaceRoutingQueryFields to write endpoint
- Fix worker routing for typescriptreact/javascriptreact
- Add SSR guard for self.MonacoEnvironment
- Lazy-load Monaco workers via dynamic imports
- Fix language map: remove unreachable R key, fix sass mapping
- Add Close button and ESC handler to Monaco edit overlay

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Jun 1, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

Thanks for updating your PR! It now meets our contributing guidelines. 👍

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.

在 Window 环境下 AI 使用 PowerShell 修改文件添加中文内容会有乱码出现

3 participants