diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000000..6836901226a
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,31 @@
+# Git
+.git
+.github
+.gitignore
+.gitattributes
+
+# Node (rebuilt in Docker)
+node_modules
+
+# IDE
+.idea
+
+# Documentation
+README.md
+HOW_TO_CONTRIBUTE.md
+VOID_CODEBASE_GUIDE.md
+LICENSE*.txt
+ThirdPartyNotices.txt
+
+# CI/CD
+CodeQL.yml
+
+# Build output (rebuilt in Docker)
+out
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Playwright browsers (not needed for server)
+.playwright
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 00000000000..3010d42a857
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,3 @@
+# Default code owners for all files
+* @danialsamiei
+
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000000..99b0c21cb91
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,12 @@
+version: 2
+updates:
+ - package-ecosystem: "npm"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ open-pull-requests-limit: 5
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ open-pull-requests-limit: 5
diff --git a/.voidrules b/.voidrules
index 55ab5af65de..19702f730b8 100644
--- a/.voidrules
+++ b/.voidrules
@@ -1,4 +1,4 @@
-This is a fork of the VSCode repo called Void.
+This is the Orcide IDE repository, a fork of VSCode.
Most code we care about lives in src/vs/workbench/contrib/void.
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000000..4242b506245
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,61 @@
+# Dockerfile for ide.orcest.ai (VS Code fork) - Render.com deploy
+# Requires X11 libs for native-keymap, node-pty, etc.
+
+FROM node:20-bookworm-slim
+
+# Install build deps for native modules (native-keymap, node-pty, etc.)
+# ripgrep: @vscode/ripgrep postinstall downloads from GitHub and gets 403 in cloud builds
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ python3 \
+ make \
+ g++ \
+ pkg-config \
+ libxkbfile-dev \
+ libx11-dev \
+ libxrandr-dev \
+ libxi-dev \
+ libxtst-dev \
+ libxrender-dev \
+ libxfixes-dev \
+ libxext-dev \
+ libxkbcommon-dev \
+ libsecret-1-dev \
+ libkrb5-dev \
+ git \
+ ripgrep \
+ && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /app
+
+# Copy source (postinstall needs full tree for build/, remote/, etc.)
+COPY . .
+
+# Install deps - requires X11 libs above for native-keymap, node-pty
+# Use --ignore-scripts to skip @vscode/ripgrep postinstall (403 from GitHub in cloud builds),
+# supply system ripgrep, run postinstall (with install not rebuild for subdirs), then rebuild native modules
+RUN npm i --ignore-scripts \
+ && mkdir -p node_modules/@vscode/ripgrep/bin \
+ && cp /usr/bin/rg node_modules/@vscode/ripgrep/bin/rg \
+ && VSCODE_USE_SYSTEM_RIPGREP=1 npm rebuild \
+ && mkdir -p build/node_modules/@vscode/ripgrep/bin \
+ && cp /usr/bin/rg build/node_modules/@vscode/ripgrep/bin/rg \
+ && (cd build && npm rebuild) \
+ && mkdir -p remote/node_modules/@vscode/ripgrep/bin \
+ && cp /usr/bin/rg remote/node_modules/@vscode/ripgrep/bin/rg \
+ && (cd remote && npm rebuild)
+
+# Build: React components first, then compile produces out/ (server + workbench), compile-web adds extension web bundles
+ENV NODE_OPTIONS="--max-old-space-size=4096"
+RUN npm run buildreact \
+ && npm run compile \
+ && npm run compile-web
+
+# VSCODE_DEV=1 tells the server to use the dev workbench template which loads CSS
+# dynamically via import maps. Without this, the server expects a bundled workbench.css
+# that is only produced by the full packaging pipeline (gulp vscode-web-min), not by
+# npm run compile.
+ENV VSCODE_DEV=1
+
+# Render sets PORT; use code-server (production) not code-web (test harness)
+EXPOSE 10000
+CMD ["sh", "-c", "node out/server-main.js --host 0.0.0.0 --port ${PORT:-10000} --without-connection-token --accept-server-license-terms"]
diff --git a/HOW_TO_CONTRIBUTE.md b/HOW_TO_CONTRIBUTE.md
index 443e3540acf..4b4bcab8248 100644
--- a/HOW_TO_CONTRIBUTE.md
+++ b/HOW_TO_CONTRIBUTE.md
@@ -4,15 +4,15 @@ This is the official guide on how to contribute to Void. We want to make it as e
There are a few ways to contribute:
-- ðŦ Complete items on the [Roadmap](https://github.com/orgs/voideditor/projects/2).
+- ðŦ Complete items on the [Roadmap](https://github.com/orgs/orcide/projects/2).
- ðĄ Make suggestions in our [Discord](https://discord.gg/RSNjgaugJs).
-- ðŠī Start new Issues - see [Issues](https://github.com/voideditor/void/issues).
+- ðŠī Start new Issues - see [Issues](https://github.com/orcest-ai/Orcide/issues).
### Codebase Guide
-We [highly recommend reading this](https://github.com/voideditor/void/blob/main/VOID_CODEBASE_GUIDE.md) guide that we put together on Void's sourcecode if you'd like to add new features.
+We [highly recommend reading this](https://github.com/orcest-ai/Orcide/blob/main/VOID_CODEBASE_GUIDE.md) guide that we put together on Void's sourcecode if you'd like to add new features.
The repo is not as intimidating as it first seems if you read the guide!
@@ -56,7 +56,7 @@ First, run `npm install -g node-gyp`. Then:
Here's how to start changing Void's code. These steps cover everything from cloning Void, to opening a Developer Mode window where you can play around with your updates.
-1. `git clone https://github.com/voideditor/void` to clone the repo.
+1. `git clone https://github.com/orcest-ai/Orcide` to clone the repo.
2. `npm install` to install all dependencies.
3. Open Void or VSCode, and initialize Developer Mode (this can take ~5 min to finish, it's done when 2 of the 3 spinners turn to check marks):
- Windows: Press Ctrl+Shift+B.
@@ -85,7 +85,7 @@ If you get any errors, scroll down for common fixes.
- If you get errors like `npm error libtool: error: unrecognised option: '-static'`, when running ./scripts/code.sh, make sure you have GNU libtool instead of BSD libtool (BSD is the default in macos)
- If you get errors like `The SUID sandbox helper binary was found, but is not configured correctly` when running ./scripts/code.sh, run
`sudo chown root:root .build/electron/chrome-sandbox && sudo chmod 4755 .build/electron/chrome-sandbox` and then run `./scripts/code.sh` again.
-- If you have any other questions, feel free to [submit an issue](https://github.com/voideditor/void/issues/new). You can also refer to VSCode's complete [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute) page.
+- If you have any other questions, feel free to [submit an issue](https://github.com/orcest-ai/Orcide/issues/new). You can also refer to VSCode's complete [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute) page.
@@ -103,9 +103,9 @@ To build Void from the terminal instead of from inside VSCode, follow the steps
### Distributing
-Void's maintainers distribute Void on our website and in releases. Our build pipeline is a fork of VSCodium, and it works by running GitHub Actions which create the downloadables. The build repo with more instructions lives [here](https://github.com/voideditor/void-builder).
+Void's maintainers distribute Void on our website and in releases. Our build pipeline is a fork of VSCodium, and it works by running GitHub Actions which create the downloadables. The build repo with more instructions lives [here](https://github.com/orcest-ai/Orcide-builder).
-If you want to completely control Void's build pipeline for your own internal usage, which comes with a lot of time cost (and is typically not recommended), see our [`void-builder`](https://github.com/voideditor/void-builder) repo which builds Void and contains a few important notes about auto-updating and rebasing.
+If you want to completely control Void's build pipeline for your own internal usage, which comes with a lot of time cost (and is typically not recommended), see our [`void-builder`](https://github.com/orcest-ai/Orcide-builder) repo which builds Void and contains a few important notes about auto-updating and rebasing.
#### Building a Local Executible
diff --git a/README.md b/README.md
index 63e779a40f7..5af1a9afe78 100644
--- a/README.md
+++ b/README.md
@@ -1,41 +1,70 @@
-# Welcome to Void.
+
-
+
Orcide: Cloud IDE
+
Part of the Orcest AI Ecosystem
-Void is the open-source Cursor alternative.
+
+
+
+
+
+
+Orcide is an AI-powered cloud IDE that provides intelligent code editing, autocomplete, and refactoring capabilities. It is a core component of the **Orcest AI** ecosystem, integrated with **RainyModel** (rm.orcest.ai) for intelligent LLM routing.
-Use AI agents on your codebase, checkpoint and visualize changes, and bring any model or host locally. Void sends messages directly to providers without retaining your data.
+### Orcest AI Ecosystem
-This repo contains the full sourcecode for Void. If you're new, welcome!
+| Service | Domain | Role |
+|---------|--------|------|
+| **Lamino** | llm.orcest.ai | LLM Workspace |
+| **RainyModel** | rm.orcest.ai | LLM Routing Proxy |
+| **Maestrist** | agent.orcest.ai | AI Agent Platform |
+| **Orcide** | ide.orcest.ai | Cloud IDE |
+| **Login** | login.orcest.ai | SSO Authentication |
-- ð§ [Website](https://voideditor.com)
+## Features
-- ð [Discord](https://discord.gg/RSNjgaugJs)
+- **AI-Powered Code Editing**: Intelligent code suggestions and completions
+- **Chat Interface**: Built-in AI chat for code assistance
+- **Autocomplete**: Context-aware code completion powered by RainyModel
+- **Code Refactoring**: AI-assisted code improvements
+- **RainyModel Integration**: Smart LLM routing with automatic fallback (Free â Internal â Premium)
+- **SSO Authentication**: Enterprise-grade access control via login.orcest.ai
+- **VS Code Compatible**: Full VS Code extension ecosystem support
-- ð [Project Board](https://github.com/orgs/voideditor/projects/2)
+## RainyModel Configuration
+Configure Orcide to use RainyModel as its AI backend:
-## Note
+1. Open Settings (Ctrl+,)
+2. Navigate to AI / LLM settings
+3. Set:
+ - **API Provider**: OpenAI-Compatible
+ - **Base URL**: `https://rm.orcest.ai/v1`
+ - **API Key**: Your RainyModel API key
+ - **Chat Model**: `rainymodel/chat`
+ - **Autocomplete Model**: `rainymodel/code`
-We've paused work on the Void IDE (this repo) to explore a few novel coding ideas. We want to focus on innovation over feature-parity. Void will continue running, but without maintenance some existing features might stop working over time. Depending on the direction of our new work, we might not resume Void as an IDE.
+## Development
-We won't be actively reviewing Issues and PRs, but we will respond to all [email](mailto:hello@voideditor.com) inquiries on building and maintaining your own version of Void while we're paused.
+```bash
+# Install dependencies
+yarn install
-## Reference
+# Build
+yarn build
-Void is a fork of the [vscode](https://github.com/microsoft/vscode) repository. For a guide to the codebase, see [VOID_CODEBASE_GUIDE](https://github.com/voideditor/void/blob/main/VOID_CODEBASE_GUIDE.md).
+# Run in development mode
+yarn watch
+```
-For a guide on how to develop your own version of Void, see [HOW_TO_CONTRIBUTE](https://github.com/voideditor/void/blob/main/HOW_TO_CONTRIBUTE.md) and [void-builder](https://github.com/voideditor/void-builder).
+## Contributing
+See [HOW_TO_CONTRIBUTE.md](HOW_TO_CONTRIBUTE.md) for contribution guidelines.
+## License
+This project is licensed under the [MIT License](LICENSE).
-## Support
-You can always reach us in our Discord server or contact us via email: hello@voideditor.com.
+Part of the [Orcest AI](https://orcest.ai) ecosystem.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000000..608839cf7c7
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,27 @@
+# Security Policy
+
+## Supported Versions
+
+| Version | Supported |
+|---------|-----------|
+| Latest | Yes |
+
+## Reporting a Vulnerability
+
+If you discover a security vulnerability, please report it responsibly:
+
+1. **Do NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/orcest-ai/Orcide/security/advisories/new) to report privately
+3. Or email: support@orcest.ai
+
+We will acknowledge receipt within 48 hours and provide a timeline for resolution.
+
+## Security Best Practices
+
+- All secrets must be stored in environment variables, never in code
+- All services require SSO authentication via login.orcest.ai
+- API keys must be rotated regularly
+- All traffic must use HTTPS/TLS
+
+Part of the [Orcest AI](https://orcest.ai) ecosystem.
+
diff --git a/VOID_CODEBASE_GUIDE.md b/VOID_CODEBASE_GUIDE.md
index 14a04686a6d..1f17ef55162 100644
--- a/VOID_CODEBASE_GUIDE.md
+++ b/VOID_CODEBASE_GUIDE.md
@@ -1,10 +1,10 @@
-# Void Codebase Guide
+# Orcide Codebase Guide
-The Void codebase is not as intimidating as it seems!
+The Orcide codebase is not as intimidating as it seems!
-Most of Void's code lives in the folder `src/vs/workbench/contrib/void/`.
+Most of Orcide's code lives in the folder `src/vs/workbench/contrib/void/`.
-The purpose of this document is to explain how Void's codebase works. If you want build instructions instead, see [Contributing](https://github.com/voideditor/void/blob/main/HOW_TO_CONTRIBUTE.md).
+The purpose of this document is to explain how Orcide's codebase works. If you want build instructions instead, see [Contributing](https://github.com/orcest-ai/Orcide/blob/main/HOW_TO_CONTRIBUTE.md).
@@ -14,10 +14,10 @@ The purpose of this document is to explain how Void's codebase works. If you wan
-## Void Codebase Guide
+## Orcide Codebase Guide
### VSCode Rundown
-Here's a VSCode rundown if you're just getting started with Void. You can also see Microsoft's [wiki](https://github.com/microsoft/vscode/wiki/Source-Code-Organization) for some pictures. VSCode is an Electron app. Electron runs two processes: a **main** process (for internals) and a **browser** process (browser means HTML in general, not just "web browser").
+Here's a VSCode rundown if you're just getting started with Orcide. You can also see Microsoft's [wiki](https://github.com/microsoft/vscode/wiki/Source-Code-Organization) for some pictures. VSCode is an Electron app. Electron runs two processes: a **main** process (for internals) and a **browser** process (browser means HTML in general, not just "web browser").
@@ -54,7 +54,7 @@ Here's some terminology you might want to know about when working inside VSCode:
### Internal LLM Message Pipeline
-Here's a picture of all the dependencies that are relevent between the time you first send a message through Void's sidebar, and the time a request is sent to your provider.
+Here's a picture of all the dependencies that are relevent between the time you first send a message through Orcide's sidebar, and the time a request is sent to your provider.
Sending LLM messages from the main process avoids CSP issues with local providers and lets us use node_modules more easily.
@@ -69,7 +69,7 @@ Sending LLM messages from the main process avoids CSP issues with local provider
### Apply
-Void has two types of Apply: **Fast Apply** (uses Search/Replace, see below), and **Slow Apply** (rewrites whole file).
+Orcide has two types of Apply: **Fast Apply** (uses Search/Replace, see below), and **Slow Apply** (rewrites whole file).
When you click Apply and Fast Apply is enabled, we prompt the LLM to output Search/Replace block(s) like this:
```
@@ -79,7 +79,7 @@ When you click Apply and Fast Apply is enabled, we prompt the LLM to output Sear
// replaced code goes here
>>>>>>> UPDATED
```
-This is what allows Void to quickly apply code even on 1000-line files. It's the same as asking the LLM to press Ctrl+F and enter in a search/replace query.
+This is what allows Orcide to quickly apply code even on 1000-line files. It's the same as asking the LLM to press Ctrl+F and enter in a search/replace query.
### Apply Inner Workings
@@ -97,10 +97,10 @@ How Apply works:
### Writing Files Inner Workings
-When Void wants to change your code, it just writes to a text model. This means all you need to know to write to a file is its URI - you don't have to load it, save it, etc. There are some annoying background URI/model things to think about to get this to work, but we handled them all in `voidModelService`.
+When Orcide wants to change your code, it just writes to a text model. This means all you need to know to write to a file is its URI - you don't have to load it, save it, etc. There are some annoying background URI/model things to think about to get this to work, but we handled them all in `voidModelService`.
-### Void Settings Inner Workings
-We have a service `voidSettingsService` that stores all your Void settings (providers, models, global Void settings, etc). Imagine this as an implicit dependency for any of the core Void services:
+### Orcide Settings Inner Workings
+We have a service `voidSettingsService` that stores all your Orcide settings (providers, models, global Orcide settings, etc). Imagine this as an implicit dependency for any of the core Orcide services:
@@ -126,13 +126,13 @@ Here's a guide to some of the terminology we're using:
### Build process
-If you want to know how our build pipeline works, see our build repo [here](https://github.com/voideditor/void-builder).
+If you want to know how our build pipeline works, see our build repo [here](https://github.com/orcest-ai/Orcide-builder).
## VSCode Codebase Guide
-For additional references, the Void team put together this list of links to get up and running with VSCode.
+For additional references, the Orcide team put together this list of links to get up and running with VSCode.
@@ -155,7 +155,7 @@ For additional references, the Void team put together this list of links to get
#### VSCode's Extension API
-Void is no longer an extension, so these links are no longer required, but they might be useful if we ever build an extension again.
+Orcide is no longer an extension, so these links are no longer required, but they might be useful if we ever build an extension again.
- [Files you need in an extension](https://code.visualstudio.com/api/get-started/extension-anatomy).
- [An extension's `package.json` schema](https://code.visualstudio.com/api/references/extension-manifest).
diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js
index 458847afac5..02b716904ee 100644
--- a/build/npm/postinstall.js
+++ b/build/npm/postinstall.js
@@ -46,7 +46,12 @@ function npmInstall(dir, opts) {
shell: true
};
- const command = process.env['npm_command'] || 'install';
+ // When parent runs "npm rebuild", npm_command=rebuild causes subdirs to run "npm rebuild"
+ // which doesn't install packages. Subdirs need "npm install" to populate node_modules.
+ const rawCommand = opts.npmCommandOverride != null
+ ? opts.npmCommandOverride
+ : (process.env['npm_command'] || 'install');
+ const command = (rawCommand === 'rebuild' ? 'install' : rawCommand);
if (process.env['VSCODE_REMOTE_DEPENDENCIES_CONTAINER_NAME'] && /^(.build\/distro\/npm\/)?remote$/.test(dir)) {
const userinfo = os.userInfo();
@@ -128,6 +133,10 @@ for (let dir of dirs) {
...process.env
},
}
+ // When set, use --ignore-scripts for build to skip @vscode/ripgrep postinstall (403 from GitHub).
+ if (process.env['VSCODE_USE_SYSTEM_RIPGREP']) {
+ opts.npmCommandOverride = 'install --ignore-scripts';
+ }
if (process.env['CC']) { opts.env['CC'] = 'gcc'; }
if (process.env['CXX']) { opts.env['CXX'] = 'g++'; }
if (process.env['CXXFLAGS']) { opts.env['CXXFLAGS'] = ''; }
@@ -145,6 +154,11 @@ for (let dir of dirs) {
...process.env
},
}
+ // When set, use --ignore-scripts for remote to skip @vscode/ripgrep postinstall (403 from GitHub).
+ // Caller must then copy system ripgrep into remote/node_modules/@vscode/ripgrep/bin and run npm rebuild in remote.
+ if (process.env['VSCODE_USE_SYSTEM_RIPGREP']) {
+ opts.npmCommandOverride = 'install --ignore-scripts';
+ }
if (process.env['VSCODE_REMOTE_CC']) {
opts.env['CC'] = process.env['VSCODE_REMOTE_CC'];
} else {
@@ -188,5 +202,8 @@ for (let dir of dirs) {
npmInstall(dir, opts);
}
-cp.execSync('git config pull.rebase merges');
-cp.execSync('git config blame.ignoreRevsFile .git-blame-ignore-revs');
+// Skip git config if not in a git repo (e.g. Docker build where .git is not copied)
+if (fs.existsSync(path.join(root, '.git'))) {
+ cp.execSync('git config pull.rebase merges');
+ cp.execSync('git config blame.ignoreRevsFile .git-blame-ignore-revs');
+}
diff --git a/extensions/open-remote-ssh/package.json b/extensions/open-remote-ssh/package.json
index 48276a7a05f..762ff56547b 100644
--- a/extensions/open-remote-ssh/package.json
+++ b/extensions/open-remote-ssh/package.json
@@ -1,7 +1,7 @@
{
"name": "open-remote-ssh",
"displayName": "Open Remote - SSH",
- "publisher": "voideditor",
+ "publisher": "orcide",
"description": "Use any remote machine with a SSH server as your development environment.",
"version": "0.0.48",
"icon": "resources/icon.png",
@@ -71,7 +71,7 @@
"type": "string",
"description": "The URL from where the vscode server will be downloaded. You can use the following variables and they will be replaced dynamically:\n- ${quality}: vscode server quality, e.g. stable or insiders\n- ${version}: vscode server version, e.g. 1.69.0\n- ${commit}: vscode server release commit\n- ${arch}: vscode server arch, e.g. x64, armhf, arm64\n- ${release}: release number",
"scope": "application",
- "default": "https://github.com/voideditor/binaries/releases/download/${version}/void-reh-${os}-${arch}-${version}.tar.gz"
+ "default": "https://github.com/orcest-ai/Orcide-binaries/releases/download/${version}/void-reh-${os}-${arch}-${version}.tar.gz"
},
"remote.SSH.remotePlatform": {
"type": "object",
diff --git a/extensions/open-remote-ssh/src/serverSetup.ts b/extensions/open-remote-ssh/src/serverSetup.ts
index 673a795746c..70891f9061c 100644
--- a/extensions/open-remote-ssh/src/serverSetup.ts
+++ b/extensions/open-remote-ssh/src/serverSetup.ts
@@ -39,7 +39,7 @@ export class ServerInstallError extends Error {
}
}
-const DEFAULT_DOWNLOAD_URL_TEMPLATE = 'https://github.com/voideditor/binaries/releases/download/${version}/void-reh-${os}-${arch}-${version}.tar.gz';
+const DEFAULT_DOWNLOAD_URL_TEMPLATE = 'https://github.com/orcest-ai/Orcide-binaries/releases/download/${version}/void-reh-${os}-${arch}-${version}.tar.gz';
export async function installCodeServer(conn: SSHConnection, serverDownloadUrlTemplate: string | undefined, extensionIds: string[], envVariables: string[], platform: string | undefined, useSocketPath: boolean, logger: Log): Promise {
let shell = 'powershell';
diff --git a/extensions/open-remote-wsl/package.json b/extensions/open-remote-wsl/package.json
index bba06d81239..4afeb8b582b 100644
--- a/extensions/open-remote-wsl/package.json
+++ b/extensions/open-remote-wsl/package.json
@@ -38,7 +38,7 @@
"type": "string",
"description": "The URL from where the vscode server will be downloaded. You can use the following variables and they will be replaced dynamically:\n- ${quality}: vscode server quality, e.g. stable or insiders\n- ${version}: vscode server version, e.g. 1.69.0\n- ${commit}: vscode server release commit\n- ${arch}: vscode server arch, e.g. x64, armhf, arm64\n- ${release}: release number",
"scope": "application",
- "default": "https://github.com/voideditor/binaries/releases/download/${version}/void-reh-${os}-${arch}-${version}.tar.gz"
+ "default": "https://github.com/orcest-ai/Orcide-binaries/releases/download/${version}/void-reh-${os}-${arch}-${version}.tar.gz"
}
}
},
diff --git a/extensions/open-remote-wsl/src/serverSetup.ts b/extensions/open-remote-wsl/src/serverSetup.ts
index 2f56862cfbb..e33a456df1c 100644
--- a/extensions/open-remote-wsl/src/serverSetup.ts
+++ b/extensions/open-remote-wsl/src/serverSetup.ts
@@ -39,7 +39,7 @@ export class ServerInstallError extends Error {
}
}
-const DEFAULT_DOWNLOAD_URL_TEMPLATE = 'https://github.com/voideditor/binaries/releases/download/${version}/void-reh-${os}-${arch}-${version}.tar.gz';
+const DEFAULT_DOWNLOAD_URL_TEMPLATE = 'https://github.com/orcest-ai/Orcide-binaries/releases/download/${version}/void-reh-${os}-${arch}-${version}.tar.gz';
export async function installCodeServer(wslManager: WSLManager, distroName: string, serverDownloadUrlTemplate: string | undefined, extensionIds: string[], envVariables: string[], logger: Log): Promise {
const scriptId = crypto.randomBytes(12).toString('hex');
diff --git a/package.json b/package.json
index e6341c0903b..862ffc2f172 100644
--- a/package.json
+++ b/package.json
@@ -1,9 +1,9 @@
{
- "name": "code-oss-dev",
- "version": "1.99.3",
+ "name": "orcide",
+ "version": "2.0.0",
"distro": "21c8d8ea1e46d97c5639a7cabda6c0e063cc8dd5",
"author": {
- "name": "Microsoft Corporation"
+ "name": "Orcest AI"
},
"license": "MIT",
"main": "./out/main.js",
@@ -263,10 +263,10 @@
},
"repository": {
"type": "git",
- "url": "https://github.com/microsoft/vscode.git"
+ "url": "https://github.com/orcest-ai/Orcide.git"
},
"bugs": {
- "url": "https://github.com/microsoft/vscode/issues"
+ "url": "https://github.com/orcest-ai/Orcide/issues"
},
"optionalDependencies": {
"windows-foreground-love": "0.5.0"
diff --git a/product.json b/product.json
index b939424b68c..1788d4824cd 100644
--- a/product.json
+++ b/product.json
@@ -1,46 +1,74 @@
{
- "nameShort": "Void",
- "nameLong": "Void",
- "voidVersion": "1.4.9",
- "voidRelease": "0044",
- "applicationName": "void",
- "dataFolderName": ".void-editor",
- "win32MutexName": "voideditor",
+ "nameShort": "Orcide",
+ "nameLong": "Orcide",
+ "orcideVersion": "2.0.0",
+ "orcideRelease": "0001",
+ "applicationName": "orcide",
+ "dataFolderName": ".orcide",
+ "win32MutexName": "orcide",
"licenseName": "MIT",
- "licenseUrl": "https://github.com/voideditor/void/blob/main/LICENSE.txt",
- "serverLicenseUrl": "https://github.com/voideditor/void/blob/main/LICENSE.txt",
+ "licenseUrl": "https://github.com/orcest-ai/Orcide/blob/main/LICENSE.txt",
+ "serverLicenseUrl": "https://github.com/orcest-ai/Orcide/blob/main/LICENSE.txt",
"serverGreeting": [],
"serverLicense": [],
"serverLicensePrompt": "",
- "serverApplicationName": "void-server",
- "serverDataFolderName": ".void-server",
- "tunnelApplicationName": "void-tunnel",
- "win32DirName": "Void",
- "win32NameVersion": "Void",
- "win32RegValueName": "VoidEditor",
+ "serverApplicationName": "orcide-server",
+ "serverDataFolderName": ".orcide-server",
+ "tunnelApplicationName": "orcide-tunnel",
+ "win32DirName": "Orcide",
+ "win32NameVersion": "Orcide",
+ "win32RegValueName": "Orcide",
"win32x64AppId": "{{9D394D01-1728-45A7-B997-A6C82C5452C3}",
"win32arm64AppId": "{{0668DD58-2BDE-4101-8CDA-40252DF8875D}",
"win32x64UserAppId": "{{8BED5DC1-6C55-46E6-9FE6-18F7E6F7C7F1}",
"win32arm64UserAppId": "{{F6C87466-BC82-4A8F-B0FF-18CA366BA4D8}",
- "win32AppUserModelId": "Void.Editor",
- "win32ShellNameShort": "V&oid",
- "win32TunnelServiceMutex": "void-tunnelservice",
- "win32TunnelMutex": "void-tunnel",
- "darwinBundleIdentifier": "com.voideditor.code",
- "linuxIconName": "void-editor",
+ "win32AppUserModelId": "Orcide.Editor",
+ "win32ShellNameShort": "O&rcide",
+ "win32TunnelServiceMutex": "orcide-tunnelservice",
+ "win32TunnelMutex": "orcide-tunnel",
+ "darwinBundleIdentifier": "com.orcide.code",
+ "linuxIconName": "orcide",
"licenseFileName": "LICENSE.txt",
- "reportIssueUrl": "https://github.com/voideditor/void/issues/new",
+ "reportIssueUrl": "https://github.com/orcest-ai/Orcide/issues/new",
"nodejsRepository": "https://nodejs.org",
- "urlProtocol": "void",
+ "urlProtocol": "orcide",
+ "ssoProvider": {
+ "issuer": "https://login.orcest.ai",
+ "clientId": "orcide",
+ "redirectUri": "https://ide.orcest.ai/auth/callback",
+ "scopes": ["openid", "profile", "email"],
+ "authorizationEndpoint": "https://login.orcest.ai/oauth2/authorize",
+ "tokenEndpoint": "https://login.orcest.ai/oauth2/token",
+ "userInfoEndpoint": "https://login.orcest.ai/oauth2/userinfo",
+ "jwksUri": "https://login.orcest.ai/oauth2/jwks",
+ "logoutUrl": "https://login.orcest.ai/logout"
+ },
+ "defaultApiProvider": {
+ "name": "rainymodel",
+ "endpoint": "https://rm.orcest.ai/v1",
+ "displayName": "RainyModel"
+ },
+ "orcestApis": {
+ "rainymodel": "https://rm.orcest.ai",
+ "lamino": "https://llm.orcest.ai",
+ "maestrist": "https://agent.orcest.ai",
+ "ollamafreeapi": "https://ollamafreeapi.orcest.ai"
+ },
"extensionsGallery": {
"serviceUrl": "https://marketplace.visualstudio.com/_apis/public/gallery",
"itemUrl": "https://marketplace.visualstudio.com/items"
},
"builtInExtensions": [],
"linkProtectionTrustedDomains": [
- "https://voideditor.com",
- "https://voideditor.dev",
- "https://github.com/voideditor/void",
+ "https://orcest.ai",
+ "https://login.orcest.ai",
+ "https://ide.orcest.ai",
+ "https://rm.orcest.ai",
+ "https://llm.orcest.ai",
+ "https://agent.orcest.ai",
+ "https://ollamafreeapi.orcest.ai",
+ "https://orcide.dev",
+ "https://github.com/orcest-ai/Orcide",
"https://ollama.com"
]
}
diff --git a/src/vs/server/node/webClientServer.ts b/src/vs/server/node/webClientServer.ts
index e36113b4bfe..807854829cb 100644
--- a/src/vs/server/node/webClientServer.ts
+++ b/src/vs/server/node/webClientServer.ts
@@ -298,6 +298,9 @@ export class WebClientServer {
remoteAuthority = replacePort(remoteAuthority, forwardedPort);
}
+ const forwardedProto = getFirstHeader('x-forwarded-proto');
+ const remoteScheme: 'http' | 'https' = forwardedProto === 'https' ? 'https' : 'http';
+
function asJSON(value: unknown): string {
return JSON.stringify(value).replace(/"/g, '"');
}
@@ -338,7 +341,7 @@ export class WebClientServer {
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
...this._productService.extensionsGallery,
resourceUrlTemplate: this._webExtensionResourceUrlTemplate.with({
- scheme: 'http',
+ scheme: remoteScheme,
authority: remoteAuthority,
path: `${webExtensionRoute}/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
}).toString(true)
@@ -415,10 +418,11 @@ export class WebClientServer {
const webWorkerExtensionHostIframeScriptSHA = 'sha256-2Q+j4hfT09+1+imS46J2YlkCtHWQt0/BE79PXjJ0ZJ8=';
const cspDirectives = [
+ ...(remoteScheme === 'https' ? ['upgrade-insecure-requests;'] : []),
'default-src \'self\';',
'img-src \'self\' https: data: blob:;',
'media-src \'self\';',
- `script-src 'self' 'unsafe-eval' ${WORKBENCH_NLS_BASE_URL ?? ''} blob: 'nonce-1nline-m4p' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' ${useTestResolver ? '' : `http://${remoteAuthority}`};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+ `script-src 'self' 'unsafe-eval' ${WORKBENCH_NLS_BASE_URL ?? ''} blob: 'nonce-1nline-m4p' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' ${useTestResolver ? '' : `${remoteScheme}://${remoteAuthority}`};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
'child-src \'self\';',
`frame-src 'self' https://*.vscode-cdn.net data:;`,
'worker-src \'self\' data: blob:;',
diff --git a/src/vs/workbench/browser/parts/editor/media/editorgroupview.css b/src/vs/workbench/browser/parts/editor/media/editorgroupview.css
index f79d0c9c8fb..4f62a13b571 100644
--- a/src/vs/workbench/browser/parts/editor/media/editorgroupview.css
+++ b/src/vs/workbench/browser/parts/editor/media/editorgroupview.css
@@ -55,7 +55,7 @@
width: 100%;
max-height: 100%;
aspect-ratio: 1/1;
- background-image: url('./void_cube_noshadow.png'); /* // Void */
+ background-image: url('./orcide_logo.svg'); /* Orcide */
background-size: contain;
background-position-x: center;
background-repeat: no-repeat;
@@ -63,17 +63,17 @@
.void-void-icon,
.monaco-workbench.vs-dark .part.editor > .content .editor-group-container .editor-group-watermark > .letterpress {
- background-image: url('./void_cube_noshadow.png'); /* // Void */
+ background-image: url('./orcide_logo.svg'); /* Orcide */
}
.void-void-icon,
.monaco-workbench.hc-light .part.editor > .content .editor-group-container .editor-group-watermark > .letterpress {
- background-image: url('./void_cube_noshadow.png'); /* // Void */
+ background-image: url('./orcide_logo.svg'); /* Orcide */
}
.void-void-icon,
.monaco-workbench.hc-black .part.editor > .content .editor-group-container .editor-group-watermark > .letterpress {
- background-image: url('./void_cube_noshadow.png'); /* // Void */
+ background-image: url('./orcide_logo.svg'); /* Orcide */
}
.monaco-workbench .part.editor > .content:not(.empty) .editor-group-container > .editor-group-watermark > .shortcuts,
diff --git a/src/vs/workbench/browser/parts/editor/media/orcide_logo.svg b/src/vs/workbench/browser/parts/editor/media/orcide_logo.svg
new file mode 100644
index 00000000000..f45a2864f02
--- /dev/null
+++ b/src/vs/workbench/browser/parts/editor/media/orcide_logo.svg
@@ -0,0 +1,19 @@
+
diff --git a/src/vs/workbench/contrib/void/browser/autocompleteService.ts b/src/vs/workbench/contrib/void/browser/autocompleteService.ts
index 22c86eb6afc..6db9e03d7c0 100644
--- a/src/vs/workbench/contrib/void/browser/autocompleteService.ts
+++ b/src/vs/workbench/contrib/void/browser/autocompleteService.ts
@@ -28,7 +28,7 @@ import { IConvertToLLMMessageService } from './convertToLLMMessageService.js';
const allLinebreakSymbols = ['\r\n', '\n']
const _ln = isWindows ? allLinebreakSymbols[0] : allLinebreakSymbols[1]
-// The extension this was called from is here - https://github.com/voideditor/void/blob/autocomplete/extensions/void/src/extension/extension.ts
+// The extension this was called from is here - https://github.com/orcest-ai/Orcide/blob/autocomplete/extensions/void/src/extension/extension.ts
/*
diff --git a/src/vs/workbench/contrib/void/browser/editCodeService.ts b/src/vs/workbench/contrib/void/browser/editCodeService.ts
index 80ee4bc9925..0fd54e65fde 100644
--- a/src/vs/workbench/contrib/void/browser/editCodeService.ts
+++ b/src/vs/workbench/contrib/void/browser/editCodeService.ts
@@ -290,7 +290,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
// run: () => { this._commandService.executeCommand(VOID_OPEN_SETTINGS_ACTION_ID) }
// }]
// },
- // source: details ? `(Hold ${isMacintosh ? 'Option' : 'Alt'} to hover) - ${details}\n\nIf this persists, feel free to [report](https://github.com/voideditor/void/issues/new) it.` : undefined
+ // source: details ? `(Hold ${isMacintosh ? 'Option' : 'Alt'} to hover) - ${details}\n\nIf this persists, feel free to [report](https://github.com/orcest-ai/Orcide/issues/new) it.` : undefined
// })
// }
diff --git a/src/vs/workbench/contrib/void/browser/extensionTransferService.ts b/src/vs/workbench/contrib/void/browser/extensionTransferService.ts
index b8843e98b96..13656cb5b62 100644
--- a/src/vs/workbench/contrib/void/browser/extensionTransferService.ts
+++ b/src/vs/workbench/contrib/void/browser/extensionTransferService.ts
@@ -195,37 +195,37 @@ const transferTheseFilesOfOS = (os: 'mac' | 'windows' | 'linux' | null, fromEdit
if (fromEditor === 'VS Code') {
return [{
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Code', 'User', 'settings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Void', 'User', 'settings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Orcide', 'User', 'settings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Code', 'User', 'keybindings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Void', 'User', 'keybindings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Orcide', 'User', 'keybindings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.vscode', 'extensions'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.void-editor', 'extensions'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.orcide', 'extensions'),
isExtensions: true,
}]
} else if (fromEditor === 'Cursor') {
return [{
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Cursor', 'User', 'settings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Void', 'User', 'settings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Orcide', 'User', 'settings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Cursor', 'User', 'keybindings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Void', 'User', 'keybindings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Orcide', 'User', 'keybindings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.cursor', 'extensions'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.void-editor', 'extensions'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.orcide', 'extensions'),
isExtensions: true,
}]
} else if (fromEditor === 'Windsurf') {
return [{
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Windsurf', 'User', 'settings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Void', 'User', 'settings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Orcide', 'User', 'settings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Windsurf', 'User', 'keybindings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Void', 'User', 'keybindings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, 'Library', 'Application Support', 'Orcide', 'User', 'keybindings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.windsurf', 'extensions'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.void-editor', 'extensions'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.orcide', 'extensions'),
isExtensions: true,
}]
}
@@ -238,37 +238,37 @@ const transferTheseFilesOfOS = (os: 'mac' | 'windows' | 'linux' | null, fromEdit
if (fromEditor === 'VS Code') {
return [{
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Code', 'User', 'settings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Void', 'User', 'settings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Orcide', 'User', 'settings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Code', 'User', 'keybindings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Void', 'User', 'keybindings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Orcide', 'User', 'keybindings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.vscode', 'extensions'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.void-editor', 'extensions'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.orcide', 'extensions'),
isExtensions: true,
}]
} else if (fromEditor === 'Cursor') {
return [{
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Cursor', 'User', 'settings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Void', 'User', 'settings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Orcide', 'User', 'settings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Cursor', 'User', 'keybindings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Void', 'User', 'keybindings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Orcide', 'User', 'keybindings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.cursor', 'extensions'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.void-editor', 'extensions'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.orcide', 'extensions'),
isExtensions: true,
}]
} else if (fromEditor === 'Windsurf') {
return [{
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Windsurf', 'User', 'settings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Void', 'User', 'settings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Orcide', 'User', 'settings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Windsurf', 'User', 'keybindings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Void', 'User', 'keybindings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.config', 'Orcide', 'User', 'keybindings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.windsurf', 'extensions'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.void-editor', 'extensions'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), homeDir, '.orcide', 'extensions'),
isExtensions: true,
}]
}
@@ -283,37 +283,37 @@ const transferTheseFilesOfOS = (os: 'mac' | 'windows' | 'linux' | null, fromEdit
if (fromEditor === 'VS Code') {
return [{
from: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Code', 'User', 'settings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Void', 'User', 'settings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Orcide', 'User', 'settings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Code', 'User', 'keybindings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Void', 'User', 'keybindings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Orcide', 'User', 'keybindings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), userprofile, '.vscode', 'extensions'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), userprofile, '.void-editor', 'extensions'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), userprofile, '.orcide', 'extensions'),
isExtensions: true,
}]
} else if (fromEditor === 'Cursor') {
return [{
from: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Cursor', 'User', 'settings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Void', 'User', 'settings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Orcide', 'User', 'settings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Cursor', 'User', 'keybindings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Void', 'User', 'keybindings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Orcide', 'User', 'keybindings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), userprofile, '.cursor', 'extensions'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), userprofile, '.void-editor', 'extensions'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), userprofile, '.orcide', 'extensions'),
isExtensions: true,
}]
} else if (fromEditor === 'Windsurf') {
return [{
from: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Windsurf', 'User', 'settings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Void', 'User', 'settings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Orcide', 'User', 'settings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Windsurf', 'User', 'keybindings.json'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Void', 'User', 'keybindings.json'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Orcide', 'User', 'keybindings.json'),
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), userprofile, '.windsurf', 'extensions'),
- to: URI.joinPath(URI.from({ scheme: 'file' }), userprofile, '.void-editor', 'extensions'),
+ to: URI.joinPath(URI.from({ scheme: 'file' }), userprofile, '.orcide', 'extensions'),
isExtensions: true,
}]
}
diff --git a/src/vs/workbench/contrib/void/browser/fileService.ts b/src/vs/workbench/contrib/void/browser/fileService.ts
index 93da1b1e2cf..7e45680273c 100644
--- a/src/vs/workbench/contrib/void/browser/fileService.ts
+++ b/src/vs/workbench/contrib/void/browser/fileService.ts
@@ -17,7 +17,7 @@ class FilePromptActionService extends Action2 {
constructor() {
super({
id: FilePromptActionService.VOID_COPY_FILE_PROMPT_ID,
- title: localize2('voidCopyPrompt', 'Void: Copy Prompt'),
+ title: localize2('voidCopyPrompt', 'Orcide: Copy Prompt'),
menu: [{
id: MenuId.ExplorerContext,
group: '8_void',
diff --git a/src/vs/workbench/contrib/void/browser/orcideSSOBrowserService.ts b/src/vs/workbench/contrib/void/browser/orcideSSOBrowserService.ts
new file mode 100644
index 00000000000..1bdb445067e
--- /dev/null
+++ b/src/vs/workbench/contrib/void/browser/orcideSSOBrowserService.ts
@@ -0,0 +1,459 @@
+/*--------------------------------------------------------------------------------------
+ * Copyright 2025 Orcest. All rights reserved.
+ * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
+ *--------------------------------------------------------------------------------------*/
+
+import { Disposable } from '../../../../base/common/lifecycle.js';
+import { INotificationService, Severity } from '../../../../platform/notification/common/notification.js';
+import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
+import { getActiveWindow } from '../../../../base/browser/dom.js';
+import { IOrcideSSOService, ORCIDE_SSO_CONFIG } from '../common/orcideSSOService.js';
+import { localize2 } from '../../../../nls.js';
+import { Action2, registerAction2 } from '../../../../platform/actions/common/actions.js';
+import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js';
+
+
+// âââ Constants ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+
+// Popup window dimensions
+const POPUP_WIDTH = 500;
+const POPUP_HEIGHT = 700;
+
+// Maximum time to wait for the popup to complete (10 minutes)
+const POPUP_TIMEOUT_MS = 10 * 60 * 1000;
+
+// Interval for polling the popup window state
+const POPUP_POLL_INTERVAL_MS = 500;
+
+
+// âââ Browser SSO Contribution âââââââââââââââââââââââââââââââââââââââââââââââââââ
+
+/**
+ * Workbench contribution that handles browser-specific SSO behavior:
+ * - Listens for OAuth2 callback messages from the popup window
+ * - Handles the authorization code exchange
+ * - Manages the popup window lifecycle
+ */
+export class OrcideSSOBrowserContribution extends Disposable implements IWorkbenchContribution {
+ static readonly ID = 'workbench.contrib.orcideSSO';
+
+ private _popupWindow: Window | null = null;
+ private _popupPollTimer: ReturnType | null = null;
+ private _popupTimeoutTimer: ReturnType | null = null;
+
+ constructor(
+ @IOrcideSSOService private readonly _ssoService: IOrcideSSOService,
+ @INotificationService private readonly _notificationService: INotificationService,
+ ) {
+ super();
+ this._initialize();
+ }
+
+ private _initialize(): void {
+ const targetWindow = getActiveWindow();
+
+ // Listen for postMessage from the OAuth2 callback popup.
+ // The callback page at /auth/callback posts a message with the authorization
+ // code and state back to the opener window.
+ const messageHandler = (event: MessageEvent) => {
+ this._handleOAuthMessage(event);
+ };
+ targetWindow.addEventListener('message', messageHandler);
+ this._register({
+ dispose: () => targetWindow.removeEventListener('message', messageHandler),
+ });
+
+ // Also check if the current URL itself is a callback (for redirect-based flow
+ // where the entire IDE is redirected to the callback URL)
+ this._handleRedirectCallback(targetWindow);
+ }
+
+
+ // ââ Redirect Flow Handling âââââââââââââââââââââââââââââââââââââââââââââââââ
+
+ /**
+ * If the IDE is loaded at the callback URL itself (redirect-based OAuth flow),
+ * extract the code and state from the URL parameters and process the callback.
+ */
+ private _handleRedirectCallback(targetWindow: Window): void {
+ try {
+ const url = new URL(targetWindow.location.href);
+ const callbackPath = new URL(ORCIDE_SSO_CONFIG.redirectUri).pathname;
+
+ if (url.pathname !== callbackPath) {
+ return;
+ }
+
+ const code = url.searchParams.get('code');
+ const state = url.searchParams.get('state');
+ const error = url.searchParams.get('error');
+ const errorDescription = url.searchParams.get('error_description');
+
+ // Clean the callback parameters from the URL so they don't persist
+ // in the address bar or browser history
+ url.searchParams.delete('code');
+ url.searchParams.delete('state');
+ url.searchParams.delete('error');
+ url.searchParams.delete('error_description');
+ url.searchParams.delete('session_state');
+ targetWindow.history.replaceState({}, '', url.pathname + url.search + url.hash);
+
+ if (error) {
+ const message = errorDescription ?? error;
+ console.error(`[OrcideSSOBrowser] OAuth error in redirect: ${message}`);
+ this._notificationService.notify({
+ severity: Severity.Error,
+ message: `SSO login failed: ${message}`,
+ });
+ return;
+ }
+
+ if (code && state) {
+ this._processAuthorizationCode(code, state);
+ }
+ } catch (e) {
+ // Not a callback URL, or parsing failed. This is expected in the
+ // common case where the IDE is loaded normally.
+ }
+ }
+
+
+ // ââ Popup Flow Handling ââââââââââââââââââââââââââââââââââââââââââââââââââââ
+
+ /**
+ * Opens the SSO login page in a centered popup window.
+ * Called when the login() method triggers _openAuthorizationUrl.
+ */
+ openLoginPopup(authUrl: string): void {
+ // Close any existing popup
+ this._closePopup();
+
+ const targetWindow = getActiveWindow();
+
+ // Calculate center position for the popup
+ const left = Math.max(0, Math.round(targetWindow.screenX + (targetWindow.outerWidth - POPUP_WIDTH) / 2));
+ const top = Math.max(0, Math.round(targetWindow.screenY + (targetWindow.outerHeight - POPUP_HEIGHT) / 2));
+
+ const features = [
+ `width=${POPUP_WIDTH}`,
+ `height=${POPUP_HEIGHT}`,
+ `left=${left}`,
+ `top=${top}`,
+ 'menubar=no',
+ 'toolbar=no',
+ 'location=yes',
+ 'status=yes',
+ 'resizable=yes',
+ 'scrollbars=yes',
+ ].join(',');
+
+ this._popupWindow = targetWindow.open(authUrl, 'orcide-sso-login', features);
+
+ if (!this._popupWindow) {
+ // Popup was blocked by the browser. Fall back to redirect flow.
+ console.warn('[OrcideSSOBrowser] Popup blocked, falling back to redirect flow');
+ this._notificationService.notify({
+ severity: Severity.Warning,
+ message: 'Popup was blocked by the browser. Redirecting to SSO login page...',
+ });
+ targetWindow.location.href = authUrl;
+ return;
+ }
+
+ // Focus the popup
+ this._popupWindow.focus();
+
+ // Poll the popup to detect if the user closes it manually
+ this._popupPollTimer = setInterval(() => {
+ if (this._popupWindow && this._popupWindow.closed) {
+ this._cleanupPopup();
+ }
+ }, POPUP_POLL_INTERVAL_MS);
+
+ // Set a timeout to auto-close the popup if it takes too long
+ this._popupTimeoutTimer = setTimeout(() => {
+ if (this._popupWindow && !this._popupWindow.closed) {
+ console.warn('[OrcideSSOBrowser] Login popup timed out');
+ this._closePopup();
+ this._notificationService.notify({
+ severity: Severity.Warning,
+ message: 'SSO login timed out. Please try again.',
+ });
+ }
+ }, POPUP_TIMEOUT_MS);
+ }
+
+
+ // ââ Message Handling âââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+
+ /**
+ * Handles postMessage events from the OAuth callback page.
+ * The callback page at the redirect URI should post a message with:
+ * { type: 'orcide-sso-callback', code: string, state: string }
+ * or
+ * { type: 'orcide-sso-callback', error: string, errorDescription?: string }
+ */
+ private _handleOAuthMessage(event: MessageEvent): void {
+ // Validate the origin - only accept messages from our SSO issuer or
+ // from the IDE itself (for same-origin callback pages)
+ const allowedOrigins = [
+ ORCIDE_SSO_CONFIG.issuer,
+ new URL(ORCIDE_SSO_CONFIG.redirectUri).origin,
+ ];
+
+ if (!allowedOrigins.includes(event.origin)) {
+ return;
+ }
+
+ const data = event.data;
+ if (!data || typeof data !== 'object' || data.type !== 'orcide-sso-callback') {
+ return;
+ }
+
+ // Close the popup since we got our response
+ this._closePopup();
+
+ if (data.error) {
+ const message = data.errorDescription ?? data.error;
+ console.error(`[OrcideSSOBrowser] OAuth error from callback: ${message}`);
+ this._notificationService.notify({
+ severity: Severity.Error,
+ message: `SSO login failed: ${message}`,
+ });
+ return;
+ }
+
+ if (data.code && data.state) {
+ this._processAuthorizationCode(data.code, data.state);
+ }
+ }
+
+
+ // ââ Authorization Code Processing ââââââââââââââââââââââââââââââââââââââââââ
+
+ /**
+ * Processes the received authorization code by delegating to the SSO service
+ * to exchange it for tokens and set up the session.
+ */
+ private async _processAuthorizationCode(code: string, state: string): Promise {
+ try {
+ await this._ssoService.handleAuthorizationCallback(code, state);
+
+ const user = this._ssoService.getUserProfile();
+ const displayName = user?.name || user?.email || 'User';
+ this._notificationService.notify({
+ severity: Severity.Info,
+ message: `Welcome, ${displayName}! You are now signed in.`,
+ });
+ } catch (e) {
+ const message = e instanceof Error ? e.message : String(e);
+ console.error('[OrcideSSOBrowser] Failed to process authorization code:', e);
+ this._notificationService.notify({
+ severity: Severity.Error,
+ message: `SSO login failed: ${message}`,
+ });
+ }
+ }
+
+
+ // ââ Popup Lifecycle ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+
+ private _closePopup(): void {
+ if (this._popupWindow && !this._popupWindow.closed) {
+ this._popupWindow.close();
+ }
+ this._cleanupPopup();
+ }
+
+ private _cleanupPopup(): void {
+ this._popupWindow = null;
+
+ if (this._popupPollTimer !== null) {
+ clearInterval(this._popupPollTimer);
+ this._popupPollTimer = null;
+ }
+
+ if (this._popupTimeoutTimer !== null) {
+ clearTimeout(this._popupTimeoutTimer);
+ this._popupTimeoutTimer = null;
+ }
+ }
+
+
+ // ââ Cleanup ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+
+ override dispose(): void {
+ this._closePopup();
+ super.dispose();
+ }
+}
+
+
+// âââ Register the browser contribution ââââââââââââââââââââââââââââââââââââââââââ
+
+registerWorkbenchContribution2(
+ OrcideSSOBrowserContribution.ID,
+ OrcideSSOBrowserContribution,
+ WorkbenchPhase.AfterRestored
+);
+
+
+// âââ Command Palette Actions ââââââââââââââââââââââââââââââââââââââââââââââââââââ
+
+registerAction2(class extends Action2 {
+ constructor() {
+ super({
+ id: 'orcide.sso.login',
+ f1: true,
+ title: localize2('orcideSSOLogin', 'Orcide: Sign In with SSO'),
+ });
+ }
+
+ async run(accessor: ServicesAccessor): Promise {
+ const ssoService = accessor.get(IOrcideSSOService);
+ const notificationService = accessor.get(INotificationService);
+
+ if (ssoService.isAuthenticated()) {
+ const user = ssoService.getUserProfile();
+ notificationService.notify({
+ severity: Severity.Info,
+ message: `Already signed in as ${user?.name ?? user?.email ?? 'unknown user'}.`,
+ });
+ return;
+ }
+
+ try {
+ await ssoService.login();
+ } catch (e) {
+ const message = e instanceof Error ? e.message : String(e);
+ notificationService.notify({
+ severity: Severity.Error,
+ message: `SSO login failed: ${message}`,
+ });
+ }
+ }
+});
+
+
+registerAction2(class extends Action2 {
+ constructor() {
+ super({
+ id: 'orcide.sso.logout',
+ f1: true,
+ title: localize2('orcideSSOLogout', 'Orcide: Sign Out'),
+ });
+ }
+
+ async run(accessor: ServicesAccessor): Promise {
+ const ssoService = accessor.get(IOrcideSSOService);
+ const notificationService = accessor.get(INotificationService);
+
+ if (!ssoService.isAuthenticated()) {
+ notificationService.notify({
+ severity: Severity.Info,
+ message: 'You are not currently signed in.',
+ });
+ return;
+ }
+
+ const user = ssoService.getUserProfile();
+ try {
+ await ssoService.logout();
+ notificationService.notify({
+ severity: Severity.Info,
+ message: `Signed out${user?.name ? ` (${user.name})` : ''}. See you next time!`,
+ });
+ } catch (e) {
+ const message = e instanceof Error ? e.message : String(e);
+ notificationService.notify({
+ severity: Severity.Error,
+ message: `Sign out failed: ${message}`,
+ });
+ }
+ }
+});
+
+
+registerAction2(class extends Action2 {
+ constructor() {
+ super({
+ id: 'orcide.sso.status',
+ f1: true,
+ title: localize2('orcideSSOStatus', 'Orcide: SSO Status'),
+ });
+ }
+
+ async run(accessor: ServicesAccessor): Promise {
+ const ssoService = accessor.get(IOrcideSSOService);
+ const notificationService = accessor.get(INotificationService);
+
+ if (!ssoService.isAuthenticated()) {
+ notificationService.notify({
+ severity: Severity.Info,
+ message: 'Not signed in. Use "Orcide: Sign In with SSO" to authenticate.',
+ });
+ return;
+ }
+
+ const user = ssoService.getUserProfile();
+ const { expiresAt } = ssoService.state;
+ const expiresIn = expiresAt ? Math.max(0, Math.round((expiresAt - Date.now()) / 1000 / 60)) : 'unknown';
+
+ const lines = [
+ `Signed in as: ${user?.name ?? 'Unknown'}`,
+ `Email: ${user?.email ?? 'N/A'}`,
+ `Role: ${user?.role ?? 'N/A'}`,
+ `Token expires in: ${expiresIn} minutes`,
+ ];
+
+ notificationService.notify({
+ severity: Severity.Info,
+ message: lines.join('\n'),
+ });
+ }
+});
+
+
+registerAction2(class extends Action2 {
+ constructor() {
+ super({
+ id: 'orcide.sso.refreshToken',
+ f1: true,
+ title: localize2('orcideSSORefresh', 'Orcide: Refresh SSO Token'),
+ });
+ }
+
+ async run(accessor: ServicesAccessor): Promise {
+ const ssoService = accessor.get(IOrcideSSOService);
+ const notificationService = accessor.get(INotificationService);
+
+ if (!ssoService.isAuthenticated()) {
+ notificationService.notify({
+ severity: Severity.Warning,
+ message: 'Cannot refresh token: not signed in.',
+ });
+ return;
+ }
+
+ try {
+ const success = await ssoService.refreshToken();
+ if (success) {
+ notificationService.notify({
+ severity: Severity.Info,
+ message: 'SSO token refreshed successfully.',
+ });
+ } else {
+ notificationService.notify({
+ severity: Severity.Error,
+ message: 'Failed to refresh SSO token. You may need to sign in again.',
+ });
+ }
+ } catch (e) {
+ const message = e instanceof Error ? e.message : String(e);
+ notificationService.notify({
+ severity: Severity.Error,
+ message: `Token refresh failed: ${message}`,
+ });
+ }
+ }
+});
diff --git a/src/vs/workbench/contrib/void/browser/react/src/util/services.tsx b/src/vs/workbench/contrib/void/browser/react/src/util/services.tsx
index 90455ee0224..bc920307bea 100644
--- a/src/vs/workbench/contrib/void/browser/react/src/util/services.tsx
+++ b/src/vs/workbench/contrib/void/browser/react/src/util/services.tsx
@@ -220,7 +220,7 @@ const getReactAccessor = (accessor: ServicesAccessor) => {
IWorkspaceContextService: accessor.get(IWorkspaceContextService),
IVoidCommandBarService: accessor.get(IVoidCommandBarService),
- INativeHostService: accessor.get(INativeHostService),
+ INativeHostService: (() => { try { return accessor.get(INativeHostService); } catch { return undefined; } })() as any,
IToolsService: accessor.get(IToolsService),
IConvertToLLMMessageService: accessor.get(IConvertToLLMMessageService),
ITerminalService: accessor.get(ITerminalService),
diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-onboarding/VoidOnboarding.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-onboarding/VoidOnboarding.tsx
index a27cbf76039..0358a21608c 100644
--- a/src/vs/workbench/contrib/void/browser/react/src/void-onboarding/VoidOnboarding.tsx
+++ b/src/vs/workbench/contrib/void/browser/react/src/void-onboarding/VoidOnboarding.tsx
@@ -3,15 +3,13 @@
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
-import { useEffect, useRef, useState } from 'react';
+import { useEffect, useState } from 'react';
import { useAccessor, useIsDark, useSettingsState } from '../util/services.js';
import { Brain, Check, ChevronRight, DollarSign, ExternalLink, Lock, X } from 'lucide-react';
import { displayInfoOfProviderName, ProviderName, providerNames, localProviderNames, featureNames, FeatureName, isFeatureNameDisabled } from '../../../../common/voidSettingsTypes.js';
import { ChatMarkdownRender } from '../markdown/ChatMarkdownRender.js';
import { OllamaSetupInstructions, OneClickSwitchButton, SettingsForProvider, ModelDump } from '../void-settings-tsx/Settings.js';
-import { ColorScheme } from '../../../../../../../platform/theme/common/theme.js';
import ErrorBoundary from '../sidebar-tsx/ErrorBoundary.js';
-import { isLinux } from '../../../../../../../base/common/platform.js';
const OVERRIDE_VALUE = false
@@ -39,29 +37,32 @@ export const VoidOnboarding = () => {
)
}
-const VoidIcon = () => {
- const accessor = useAccessor()
- const themeService = accessor.get('IThemeService')
-
- const divRef = useRef(null)
-
- useEffect(() => {
- // void icon style
- const updateTheme = () => {
- const theme = themeService.getColorTheme().type
- const isDark = theme === ColorScheme.DARK || theme === ColorScheme.HIGH_CONTRAST_DARK
- if (divRef.current) {
- divRef.current.style.maxWidth = '220px'
- divRef.current.style.opacity = '50%'
- divRef.current.style.filter = isDark ? '' : 'invert(1)' //brightness(.5)
- }
- }
- updateTheme()
- const d = themeService.onDidColorThemeChange(updateTheme)
- return () => d.dispose()
- }, [])
+const OrcideIcon = () => {
+ const isDark = useIsDark()
- return
+ return (
+
+ )
}
const FADE_DURATION_MS = 2000
@@ -104,14 +105,14 @@ const cloudProviders: ProviderName[] = ['googleVertex', 'liteLLM', 'microsoftAzu
// Data structures for provider tabs
const providerNamesOfTab: Record = {
- Free: ['gemini', 'openRouter'],
+ Free: ['orcestAI', 'gemini', 'openRouter'],
Local: localProviderNames,
- Paid: providerNames.filter(pn => !(['gemini', 'openRouter', ...localProviderNames, ...cloudProviders] as string[]).includes(pn)) as ProviderName[],
+ Paid: providerNames.filter(pn => !(['orcestAI', 'gemini', 'openRouter', ...localProviderNames, ...cloudProviders] as string[]).includes(pn)) as ProviderName[],
'Cloud/Other': cloudProviders,
};
const descriptionOfTab: Record = {
- Free: `Providers with a 100% free tier. Add as many as you'd like!`,
+ Free: `Free providers â Orcest AI works out of the box with no API key!`,
Paid: `Connect directly with any provider (bring your own key).`,
Local: `Active providers should appear automatically. Add as many as you'd like! `,
'Cloud/Other': `Add as many as you'd like! Reach out for custom configuration requests.`,
@@ -204,6 +205,14 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP
Add {displayInfoOfProviderName(providerName).title}
+ {providerName === 'orcestAI' && (
+ *
+ )}
{providerName === 'gemini' && (
{
// Replace the single selectedProviderName with four separate states
// page 2 state - each tab gets its own state
- const [selectedIntelligentProvider, setSelectedIntelligentProvider] = useState('anthropic');
+ const [selectedIntelligentProvider, setSelectedIntelligentProvider] = useState('orcestAI');
const [selectedPrivateProvider, setSelectedPrivateProvider] = useState('ollama');
- const [selectedAffordableProvider, setSelectedAffordableProvider] = useState('gemini');
- const [selectedAllProvider, setSelectedAllProvider] = useState('anthropic');
+ const [selectedAffordableProvider, setSelectedAffordableProvider] = useState('orcestAI');
+ const [selectedAllProvider, setSelectedAllProvider] = useState('orcestAI');
// Helper function to get the current selected provider based on active tab
const getSelectedProvider = (): ProviderName => {
@@ -510,9 +519,9 @@ const VoidOnboardingContent = () => {
}
const providerNamesOfWantToUseOption: { [wantToUseOption in WantToUseOption]: ProviderName[] } = {
- smart: ['anthropic', 'openAI', 'gemini', 'openRouter'],
+ smart: ['orcestAI', 'anthropic', 'openAI', 'gemini', 'openRouter'],
private: ['ollama', 'vLLM', 'openAICompatible', 'lmStudio'],
- cheap: ['gemini', 'deepseek', 'openRouter', 'ollama', 'vLLM'],
+ cheap: ['orcestAI', 'gemini', 'deepseek', 'openRouter', 'ollama', 'vLLM'],
all: providerNames,
}
@@ -547,7 +556,7 @@ const VoidOnboardingContent = () => {
voidMetricsService.capture('Completed Onboarding', { selectedProviderName, wantToUseOption })
}}
ringSize={voidSettingsState.globalSettings.isOnboardingComplete ? 'screen' : undefined}
- >Enter the Void
+ >Enter Orcide
@@ -563,7 +572,7 @@ const VoidOnboardingContent = () => {
// can be md
const detailedDescOfWantToUseOption: { [wantToUseOption in WantToUseOption]: string } = {
smart: "Most intelligent and best for agent mode.",
- private: "Private-hosted so your data never leaves your computer or network. [Email us](mailto:founders@voideditor.com) for help setting up at your company.",
+ private: "Private-hosted so your data never leaves your computer or network. [Email us](mailto:support@orcest.ai) for help setting up at your company.",
cheap: "Use great deals like Gemini 2.5 Pro, or self-host a model with Ollama or vLLM for free.",
all: "",
}
@@ -596,11 +605,11 @@ const VoidOnboardingContent = () => {
0:
-
Welcome to Void
+
Welcome to Orcide
- {/* Slice of Void image */}
+ {/* Orcide logo */}