This commit is contained in:
Danial Samiei 2026-02-22 04:01:42 +00:00 committed by GitHub
commit 6483c67cb9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
145 changed files with 6347 additions and 1821 deletions

31
.dockerignore Normal file
View file

@ -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

3
.github/CODEOWNERS vendored Normal file
View file

@ -0,0 +1,3 @@
# Default code owners for all files
* @danialsamiei

12
.github/dependabot.yml vendored Normal file
View file

@ -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

View file

@ -1,6 +1,6 @@
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.
Most code we care about lives in src/vs/workbench/contrib/orcide.
You may often need to explore the full repo to find relevant parts of code.
Look for services and built-in functions that you might need to use to solve the problem.
@ -9,7 +9,7 @@ In typescript, do NOT cast to types if not neccessary. NEVER lazily cast to 'any
Do not add or remove semicolons to any of my files. Just go with convention and make the least number of changes.
Never modify files outside src/vs/workbench/contrib/void without consulting with the user first.
Never modify files outside src/vs/workbench/contrib/orcide without consulting with the user first.
All types that map from a value A to B should be called bOfA. For example, if you create a hashmap that goes from toolId to toolName, it should be called toolNameOfToolId, etc.

61
Dockerfile Normal file
View file

@ -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"]

View file

@ -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 <kbd>Ctrl+Shift+B</kbd>.
@ -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

View file

@ -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/orcide/`.
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").
<p align="center" >
<img src="https://github.com/user-attachments/assets/eef80306-2bfe-4cac-ba15-6156f65ab3bb" alt="Credit - https://github.com/microsoft/vscode/wiki/Source-Code-Organization" width="700px">
</p>
@ -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 `orcideModelService`.
### 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 `orcideSettingsService` 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:
<div align="center">
<img width="800" src="https://github.com/user-attachments/assets/9f3cb68c-a61b-4810-8429-bb90b992b3fa">
@ -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.
<details>
@ -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).

View file

@ -1,41 +1,70 @@
# Welcome to Void.
<a name="readme-top"></a>
<div align="center">
<img
src="./src/vs/workbench/browser/parts/editor/media/slice_of_void.png"
alt="Void Welcome"
width="300"
height="300"
/>
<h1 align="center" style="border-bottom: none">Orcide: Cloud IDE</h1>
<p align="center"><b>Part of the Orcest AI Ecosystem</b></p>
</div>
Void is the open-source Cursor alternative.
<div align="center">
<a href="https://github.com/orcest-ai/Orcide/blob/main/LICENSE"><img src="https://img.shields.io/badge/LICENSE-MIT-20B2AA?style=for-the-badge" alt="MIT License"></a>
</div>
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.
<hr>
This repo contains the full sourcecode for Void. If you're new, welcome!
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.
- 🧭 [Website](https://voideditor.com)
### Orcest AI Ecosystem
- 👋 [Discord](https://discord.gg/RSNjgaugJs)
| 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 |
- 🚙 [Project Board](https://github.com/orgs/voideditor/projects/2)
## Features
- **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
## Note
## RainyModel Configuration
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.
Configure Orcide to use RainyModel as its AI backend:
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.
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`
## Reference
## Development
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).
```bash
# Install dependencies
yarn install
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).
# Build
yarn build
# Run in development mode
yarn watch
```
## Contributing
See [HOW_TO_CONTRIBUTE.md](HOW_TO_CONTRIBUTE.md) for contribution guidelines.
## Support
You can always reach us in our Discord server or contact us via email: hello@voideditor.com.
## License
This project is licensed under the [MIT License](LICENSE).
Part of the [Orcest AI](https://orcest.ai) ecosystem.

27
SECURITY.md Normal file
View file

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

View file

@ -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');
}

View file

@ -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",

View file

@ -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<ServerInstallResult> {
let shell = 'powershell';

View file

@ -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"
}
}
},

View file

@ -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<ServerInstallResult> {
const scriptId = crypto.randomBytes(12).toString('hex');

View file

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 200 KiB

View file

Before

Width:  |  Height:  |  Size: 813 KiB

After

Width:  |  Height:  |  Size: 813 KiB

View file

Before

Width:  |  Height:  |  Size: 795 KiB

After

Width:  |  Height:  |  Size: 795 KiB

View file

Before

Width:  |  Height:  |  Size: 850 KiB

After

Width:  |  Height:  |  Size: 850 KiB

View file

@ -1,17 +1,17 @@
{
"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",
"type": "module",
"private": true,
"scripts": {
"buildreact": "cd ./src/vs/workbench/contrib/void/browser/react/ && node build.js && cd ../../../../../../../",
"watchreact": "cd ./src/vs/workbench/contrib/void/browser/react/ && node build.js --watch && cd ../../../../../../../",
"buildreact": "cd ./src/vs/workbench/contrib/orcide/browser/react/ && node build.js && cd ../../../../../../../",
"watchreact": "cd ./src/vs/workbench/contrib/orcide/browser/react/ && node build.js --watch && cd ../../../../../../../",
"watchreactd": "deemon npm run watchreact",
"test": "echo Please run any of the test scripts from the scripts folder.",
"test-browser": "npx playwright install && node test/unit/browser/index.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"

View file

@ -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"
]
}

View file

@ -1,12 +1,12 @@
[Desktop Entry]
Name=Void - URL Handler
Name=Orcide - URL Handler
Comment=Open source AI code editor.
GenericName=Text Editor
Exec=void --open-url %U
Icon=void
Exec=orcide --open-url %U
Icon=orcide
Type=Application
NoDisplay=true
StartupNotify=true
Categories=Utility;TextEditor;Development;IDE;
MimeType=x-scheme-handler/void;
Keywords=void;
MimeType=x-scheme-handler/orcide;
Keywords=orcide;

View file

@ -1,15 +1,15 @@
[Desktop Entry]
Name=Void
Name=Orcide
Comment=Open source AI code editor.
GenericName=Text Editor
Exec=void %F
Icon=void
Exec=orcide %F
Icon=orcide
Type=Application
StartupNotify=false
StartupWMClass=Void
StartupWMClass=Orcide
Categories=TextEditor;Development;IDE;
MimeType=application/x-void-workspace;
Keywords=void;
MimeType=application/x-orcide-workspace;
Keywords=orcide;
Actions=new-empty-window;
[Desktop Action new-empty-window]
@ -23,5 +23,5 @@ Name[ko]=새 빈 창
Name[ru]=Новое пустое окно
Name[zh_CN]=
Name[zh_TW]=
Exec=void --new-window %F
Icon=void
Exec=orcide --new-window %F
Icon=orcide

View file

Before

Width:  |  Height:  |  Size: 795 KiB

After

Width:  |  Height:  |  Size: 795 KiB

View file

@ -7,13 +7,13 @@ This is a community-made AppImage creation script.
There are some reported bugs with it.
To generate an AppImage yourself, feel free to look at
stable-linux.yml in the separate `void-builder/` repo,
stable-linux.yml in the separate `orcide-builder/` repo,
which runs a GitHub Action that builds the AppImage you see on our website.
# Void AppImage Creation Script
# Orcide AppImage Creation Script
This script automates the process of creating an AppImage for the Void Editor using Docker. It works on macOS and Linux platforms.
This script automates the process of creating an AppImage for the Orcide Editor using Docker. It works on macOS and Linux platforms.
## Requirements
* **Docker:** The script relies on Docker to build the AppImage inside a container.
@ -87,8 +87,8 @@ These dependencies are installed within the Docker container (Ubuntu 20.04 base)
Copy the following files to the directory where the app binary is being bundled (created during the build process):
* `create_appimage.sh`
* `void.desktop`
* `void.png`
* `orcide.desktop`
* `orcide.png`
4. **Run the Script:**
@ -98,7 +98,7 @@ These dependencies are installed within the Docker container (Ubuntu 20.04 base)
5. **Result:**
After the script completes, it will generate an AppImage named `Void-x86_64.AppImage` (or similar, depending on your architecture) in the current directory.
After the script completes, it will generate an AppImage named `Orcide-x86_64.AppImage` (or similar, depending on your architecture) in the current directory.
## Script Overview
@ -109,9 +109,9 @@ These dependencies are installed within the Docker container (Ubuntu 20.04 base)
* **Dockerfile Creation:** Creates a temporary `Dockerfile.build` for the Ubuntu-based environment.
* **Docker Image Build:** Builds a Docker image and runs the build process.
* **AppImage Creation:**
* Creates the `VoidApp.AppDir` structure.
* Creates the `OrcideApp.AppDir` structure.
* Copies binaries, resources, and the `.desktop` entry.
* Copies `void.desktop` and `void.png`.
* Copies `orcide.desktop` and `orcide.png`.
* Strips unnecessary symbols from the binary.
* Runs `appimagetool` to generate the AppImage.
* **Cleanup:** Removes the temporary `Dockerfile.build`.

View file

@ -125,14 +125,14 @@ import ErrorTelemetry from '../../platform/telemetry/electron-main/errorTelemetr
// in theory this is not allowed
// ignore the eslint errors below
import { IMetricsService } from '../../workbench/contrib/void/common/metricsService.js';
import { IVoidUpdateService } from '../../workbench/contrib/void/common/voidUpdateService.js';
import { MetricsMainService } from '../../workbench/contrib/void/electron-main/metricsMainService.js';
import { VoidMainUpdateService } from '../../workbench/contrib/void/electron-main/voidUpdateMainService.js';
import { LLMMessageChannel } from '../../workbench/contrib/void/electron-main/sendLLMMessageChannel.js';
import { VoidSCMService } from '../../workbench/contrib/void/electron-main/voidSCMMainService.js';
import { IVoidSCMService } from '../../workbench/contrib/void/common/voidSCMTypes.js';
import { MCPChannel } from '../../workbench/contrib/void/electron-main/mcpChannel.js';
import { IMetricsService } from '../../workbench/contrib/orcide/common/metricsService.js';
import { IOrcideUpdateService } from '../../workbench/contrib/orcide/common/orcideUpdateService.js';
import { MetricsMainService } from '../../workbench/contrib/orcide/electron-main/metricsMainService.js';
import { OrcideMainUpdateService } from '../../workbench/contrib/orcide/electron-main/orcideUpdateMainService.js';
import { LLMMessageChannel } from '../../workbench/contrib/orcide/electron-main/sendLLMMessageChannel.js';
import { OrcideSCMService } from '../../workbench/contrib/orcide/electron-main/orcideSCMMainService.js';
import { IOrcideSCMService } from '../../workbench/contrib/orcide/common/orcideSCMTypes.js';
import { MCPChannel } from '../../workbench/contrib/orcide/electron-main/mcpChannel.js';
/**
* The main VS Code application. There will only ever be one instance,
* even if the user starts many instances (e.g. from the command line).
@ -1103,8 +1103,8 @@ export class CodeApplication extends Disposable {
// Void main process services (required for services with a channel for comm between browser and electron-main (node))
services.set(IMetricsService, new SyncDescriptor(MetricsMainService, undefined, false));
services.set(IVoidUpdateService, new SyncDescriptor(VoidMainUpdateService, undefined, false));
services.set(IVoidSCMService, new SyncDescriptor(VoidSCMService, undefined, false));
services.set(IOrcideUpdateService, new SyncDescriptor(OrcideMainUpdateService, undefined, false));
services.set(IOrcideSCMService, new SyncDescriptor(OrcideSCMService, undefined, false));
// Default Extensions Profile Init
services.set(IExtensionsProfileScannerService, new SyncDescriptor(ExtensionsProfileScannerService, undefined, true));
@ -1238,21 +1238,21 @@ export class CodeApplication extends Disposable {
// Void - use loggerChannel as reference
const metricsChannel = ProxyChannel.fromService(accessor.get(IMetricsService), disposables);
mainProcessElectronServer.registerChannel('void-channel-metrics', metricsChannel);
mainProcessElectronServer.registerChannel('orcide-channel-metrics', metricsChannel);
const voidUpdatesChannel = ProxyChannel.fromService(accessor.get(IVoidUpdateService), disposables);
mainProcessElectronServer.registerChannel('void-channel-update', voidUpdatesChannel);
const orcideUpdatesChannel = ProxyChannel.fromService(accessor.get(IOrcideUpdateService), disposables);
mainProcessElectronServer.registerChannel('orcide-channel-update', orcideUpdatesChannel);
const sendLLMMessageChannel = new LLMMessageChannel(accessor.get(IMetricsService));
mainProcessElectronServer.registerChannel('void-channel-llmMessage', sendLLMMessageChannel);
mainProcessElectronServer.registerChannel('orcide-channel-llmMessage', sendLLMMessageChannel);
// Void added this
const voidSCMChannel = ProxyChannel.fromService(accessor.get(IVoidSCMService), disposables);
mainProcessElectronServer.registerChannel('void-channel-scm', voidSCMChannel);
const orcideSCMChannel = ProxyChannel.fromService(accessor.get(IOrcideSCMService), disposables);
mainProcessElectronServer.registerChannel('orcide-channel-scm', orcideSCMChannel);
// Void added this
const mcpChannel = new MCPChannel();
mainProcessElectronServer.registerChannel('void-channel-mcp', mcpChannel);
mainProcessElectronServer.registerChannel('orcide-channel-mcp', mcpChannel);
// Extension Host Debug Broadcasting
const electronExtensionHostDebugBroadcastChannel = new ElectronExtensionHostDebugBroadcastChannel(accessor.get(IWindowsMainService));

View file

@ -65,7 +65,7 @@ export const enum KeybindingWeight {
WorkbenchContrib = 200,
BuiltinExtension = 300,
ExternalExtension = 400,
VoidExtension = 605, // Void - must trump any external extension
OrcideExtension = 605, // Orcide - must trump any external extension
}
export interface ICommandAndKeybindingRule extends IKeybindingRule {

View file

@ -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, '&quot;');
}
@ -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:;',

View file

@ -25,7 +25,7 @@ import { splitRecentLabel } from '../../../../base/common/labels.js';
import { IViewsService } from '../../../services/views/common/viewsService.js';
/* eslint-disable */ // Void
import { VOID_CTRL_K_ACTION_ID, VOID_CTRL_L_ACTION_ID } from '../../../contrib/void/browser/actionIDs.js';
import { ORCIDE_CTRL_K_ACTION_ID, ORCIDE_CTRL_L_ACTION_ID } from '../../../contrib/orcide/browser/actionIDs.js';
import { VIEWLET_ID as REMOTE_EXPLORER_VIEWLET_ID } from '../../../contrib/remote/browser/remoteExplorer.js';
/* eslint-enable */
@ -284,7 +284,7 @@ export class EditorGroupWatermark extends Disposable {
else {
// show them Void keybindings
const keys = this.keybindingService.lookupKeybinding(VOID_CTRL_L_ACTION_ID);
const keys = this.keybindingService.lookupKeybinding(ORCIDE_CTRL_L_ACTION_ID);
const dl = append(voidIconBox, $('dl'));
const dt = append(dl, $('dt'));
dt.textContent = 'Chat'
@ -295,7 +295,7 @@ export class EditorGroupWatermark extends Disposable {
this.currentDisposables.add(label);
const keys2 = this.keybindingService.lookupKeybinding(VOID_CTRL_K_ACTION_ID);
const keys2 = this.keybindingService.lookupKeybinding(ORCIDE_CTRL_K_ACTION_ID);
const dl2 = append(voidIconBox, $('dl'));
const dt2 = append(dl2, $('dt'));
dt2.textContent = 'Quick Edit'

View file

@ -27,7 +27,7 @@ import { ThemeIcon } from '../../../../base/common/themables.js';
import { IExplorerService } from './files.js';
import { Codicon } from '../../../../base/common/codicons.js';
import { Categories } from '../../../../platform/action/common/actionCommonCategories.js';
import { VOID_OPEN_SETTINGS_ACTION_ID } from '../../void/browser/voidSettingsPane.js';
import { ORCIDE_OPEN_SETTINGS_ACTION_ID } from '../../orcide/browser/orcideSettingsPane.js';
// Contribute Global Actions
@ -681,7 +681,7 @@ for (const menuId of [MenuId.EmptyEditorGroupContext, MenuId.EditorTabsBarContex
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
group: '0_void',
command: {
id: VOID_OPEN_SETTINGS_ACTION_ID,
id: ORCIDE_OPEN_SETTINGS_ACTION_ID,
title: nls.localize({ key: 'openVoid', comment: ['&& denotes a mnemonic'] }, "&&Open Void Settings"),
},
order: 1

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { KeyCode, KeyMod } from '../../../../base/common/keyCodes.js';
@ -29,11 +29,11 @@ registerAction2(class extends Action2 {
constructor() {
super({
f1: true,
id: 'void.dummy',
id: 'orcide.dummy',
title: localize2('dummy', 'dummy: Init'),
keybinding: {
primary: KeyMod.CtrlCmd | KeyCode.Digit0,
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
}
});
}
@ -45,7 +45,7 @@ registerAction2(class extends Action2 {
class DummyService extends Disposable implements IWorkbenchContribution, IDummyService {
static readonly ID = 'workbench.contrib.void.dummy' // workbenchContributions need this, services do not
static readonly ID = 'workbench.contrib.orcide.dummy' // workbenchContributions need this, services do not
_serviceBrand: undefined;
constructor(

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable } from '../../../../base/common/lifecycle.js';

View file

@ -0,0 +1,26 @@
// Normally you'd want to put these exports in the files that register them, but if you do that you'll get an import order error if you import them in certain cases.
// (importing them runs the whole file to get the ID, causing an import error). I guess it's best practice to separate out IDs, pretty annoying...
export const ORCIDE_CTRL_L_ACTION_ID = 'orcide.ctrlLAction'
export const ORCIDE_CTRL_K_ACTION_ID = 'orcide.ctrlKAction'
export const ORCIDE_ACCEPT_DIFF_ACTION_ID = 'orcide.acceptDiff'
export const ORCIDE_REJECT_DIFF_ACTION_ID = 'orcide.rejectDiff'
export const ORCIDE_GOTO_NEXT_DIFF_ACTION_ID = 'orcide.goToNextDiff'
export const ORCIDE_GOTO_PREV_DIFF_ACTION_ID = 'orcide.goToPrevDiff'
export const ORCIDE_GOTO_NEXT_URI_ACTION_ID = 'orcide.goToNextUri'
export const ORCIDE_GOTO_PREV_URI_ACTION_ID = 'orcide.goToPrevUri'
export const ORCIDE_ACCEPT_FILE_ACTION_ID = 'orcide.acceptFile'
export const ORCIDE_REJECT_FILE_ACTION_ID = 'orcide.rejectFile'
export const ORCIDE_ACCEPT_ALL_DIFFS_ACTION_ID = 'orcide.acceptAllDiffs'
export const ORCIDE_REJECT_ALL_DIFFS_ACTION_ID = 'orcide.rejectAllDiffs'

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
// 1. search(ai)

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable } from '../../../../base/common/lifecycle.js';
@ -18,8 +18,8 @@ import { extractCodeFromRegular } from '../common/helpers/extractCodeFromResult.
import { registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
import { ILLMMessageService } from '../common/sendLLMMessageService.js';
import { isWindows } from '../../../../base/common/platform.js';
import { IVoidSettingsService } from '../common/voidSettingsService.js';
import { FeatureName } from '../common/voidSettingsTypes.js';
import { IOrcideSettingsService } from '../common/orcideSettingsService.js';
import { FeatureName } from '../common/orcideSettingsTypes.js';
import { IConvertToLLMMessageService } from './convertToLLMMessageService.js';
// import { IContextGatheringService } from './contextGatheringService.js';
@ -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
/*
@ -617,7 +617,7 @@ export const IAutocompleteService = createDecorator<IAutocompleteService>('Autoc
export class AutocompleteService extends Disposable implements IAutocompleteService {
static readonly ID = 'void.autocompleteService'
static readonly ID = 'orcide.autocompleteService'
_serviceBrand: undefined;
@ -893,7 +893,7 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ
@ILLMMessageService private readonly _llmMessageService: ILLMMessageService,
@IEditorService private readonly _editorService: IEditorService,
@IModelService private readonly _modelService: IModelService,
@IVoidSettingsService private readonly _settingsService: IVoidSettingsService,
@IOrcideSettingsService private readonly _settingsService: IOrcideSettingsService,
@IConvertToLLMMessageService private readonly _convertToLLMMessageService: IConvertToLLMMessageService
// @IContextGatheringService private readonly _contextGatheringService: IContextGatheringService,
) {

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable } from '../../../../base/common/lifecycle.js';
@ -14,8 +14,8 @@ import { ILLMMessageService } from '../common/sendLLMMessageService.js';
import { chat_userMessageContent, isABuiltinToolName } from '../common/prompt/prompts.js';
import { AnthropicReasoning, getErrorMessage, RawToolCallObj, RawToolParamsObj } from '../common/sendLLMMessageTypes.js';
import { generateUuid } from '../../../../base/common/uuid.js';
import { FeatureName, ModelSelection, ModelSelectionOptions } from '../common/voidSettingsTypes.js';
import { IVoidSettingsService } from '../common/voidSettingsService.js';
import { FeatureName, ModelSelection, ModelSelectionOptions } from '../common/orcideSettingsTypes.js';
import { IOrcideSettingsService } from '../common/orcideSettingsService.js';
import { approvalTypeOfBuiltinToolName, BuiltinToolCallParams, ToolCallParams, ToolName, ToolResult } from '../common/toolsServiceTypes.js';
import { IToolsService } from './toolsService.js';
import { CancellationToken } from '../../../../base/common/cancellation.js';
@ -24,10 +24,10 @@ import { ChatMessage, CheckpointEntry, CodespanLocationLink, StagingSelectionIte
import { Position } from '../../../../editor/common/core/position.js';
import { IMetricsService } from '../common/metricsService.js';
import { shorten } from '../../../../base/common/labels.js';
import { IVoidModelService } from '../common/voidModelService.js';
import { IOrcideModelService } from '../common/orcideModelService.js';
import { findLast, findLastIdx } from '../../../../base/common/arraysFind.js';
import { IEditCodeService } from './editCodeServiceInterface.js';
import { VoidFileSnapshot } from '../common/editCodeServiceTypes.js';
import { OrcideFileSnapshot } from '../common/editCodeServiceTypes.js';
import { INotificationService, Severity } from '../../../../platform/notification/common/notification.js';
import { truncate } from '../../../../base/common/strings.js';
import { THREAD_STORAGE_KEY } from '../common/storageKeys.js';
@ -314,10 +314,10 @@ class ChatThreadService extends Disposable implements IChatThreadService {
constructor(
@IStorageService private readonly _storageService: IStorageService,
@IVoidModelService private readonly _voidModelService: IVoidModelService,
@IOrcideModelService private readonly _orcideModelService: IOrcideModelService,
@ILLMMessageService private readonly _llmMessageService: ILLMMessageService,
@IToolsService private readonly _toolsService: IToolsService,
@IVoidSettingsService private readonly _settingsService: IVoidSettingsService,
@IOrcideSettingsService private readonly _settingsService: IOrcideSettingsService,
@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,
@IMetricsService private readonly _metricsService: IMetricsService,
@IEditCodeService private readonly _editCodeService: IEditCodeService,
@ -443,11 +443,11 @@ class ChatThreadService extends Disposable implements IChatThreadService {
// set streamState
const messages = newState.allThreads[threadId]?.messages
const lastMessage = messages && messages[messages.length - 1]
// if awaiting user but stream state doesn't indicate it (happens if restart Void)
// if awaiting user but stream state doesn't indicate it (happens if restart Orcide)
if (lastMessage && lastMessage.role === 'tool' && lastMessage.type === 'tool_request')
this._setStreamState(threadId, { isRunning: 'awaiting_user', })
// if running now but stream state doesn't indicate it (happens if restart Void), cancel that last tool
// if running now but stream state doesn't indicate it (happens if restart Orcide), cancel that last tool
if (lastMessage && lastMessage.role === 'tool' && lastMessage.type === 'running_now') {
this._updateLatestTool(threadId, { role: 'tool', type: 'rejected', content: lastMessage.content, id: lastMessage.id, rawParams: lastMessage.rawParams, result: null, name: lastMessage.name, params: lastMessage.params, mcpServerName: lastMessage.mcpServerName })
@ -945,11 +945,11 @@ class ChatThreadService extends Disposable implements IChatThreadService {
private _getCheckpointInfo = (checkpointMessage: ChatMessage & { role: 'checkpoint' }, fsPath: string, opts: { includeUserModifiedChanges: boolean }) => {
const voidFileSnapshot = checkpointMessage.voidFileSnapshotOfURI ? checkpointMessage.voidFileSnapshotOfURI[fsPath] ?? null : null
if (!opts.includeUserModifiedChanges) { return { voidFileSnapshot, } }
const orcideFileSnapshot = checkpointMessage.orcideFileSnapshotOfURI ? checkpointMessage.orcideFileSnapshotOfURI[fsPath] ?? null : null
if (!opts.includeUserModifiedChanges) { return { orcideFileSnapshot, } }
const userModifiedVoidFileSnapshot = fsPath in checkpointMessage.userModifications.voidFileSnapshotOfURI ? checkpointMessage.userModifications.voidFileSnapshotOfURI[fsPath] ?? null : null
return { voidFileSnapshot: userModifiedVoidFileSnapshot ?? voidFileSnapshot, }
const userModifiedOrcideFileSnapshot = fsPath in checkpointMessage.userModifications.orcideFileSnapshotOfURI ? checkpointMessage.userModifications.orcideFileSnapshotOfURI[fsPath] ?? null : null
return { orcideFileSnapshot: userModifiedOrcideFileSnapshot ?? orcideFileSnapshot, }
}
private _computeNewCheckpointInfo({ threadId }: { threadId: string }) {
@ -959,59 +959,59 @@ class ChatThreadService extends Disposable implements IChatThreadService {
const lastCheckpointIdx = findLastIdx(thread.messages, (m) => m.role === 'checkpoint') ?? -1
if (lastCheckpointIdx === -1) return
const voidFileSnapshotOfURI: { [fsPath: string]: VoidFileSnapshot | undefined } = {}
const orcideFileSnapshotOfURI: { [fsPath: string]: OrcideFileSnapshot | undefined } = {}
// add a change for all the URIs in the checkpoint history
const { lastIdxOfURI } = this._getCheckpointsBetween({ threadId, loIdx: 0, hiIdx: lastCheckpointIdx, }) ?? {}
for (const fsPath in lastIdxOfURI ?? {}) {
const { model } = this._voidModelService.getModelFromFsPath(fsPath)
const { model } = this._orcideModelService.getModelFromFsPath(fsPath)
if (!model) continue
const checkpoint2 = thread.messages[lastIdxOfURI[fsPath]] || null
if (!checkpoint2) continue
if (checkpoint2.role !== 'checkpoint') continue
const res = this._getCheckpointInfo(checkpoint2, fsPath, { includeUserModifiedChanges: false })
if (!res) continue
const { voidFileSnapshot: oldVoidFileSnapshot } = res
const { orcideFileSnapshot: oldOrcideFileSnapshot } = res
// if there was any change to the str or diffAreaSnapshot, update. rough approximation of equality, oldDiffAreasSnapshot === diffAreasSnapshot is not perfect
const voidFileSnapshot = this._editCodeService.getVoidFileSnapshot(URI.file(fsPath))
if (oldVoidFileSnapshot === voidFileSnapshot) continue
voidFileSnapshotOfURI[fsPath] = voidFileSnapshot
const orcideFileSnapshot = this._editCodeService.getOrcideFileSnapshot(URI.file(fsPath))
if (oldOrcideFileSnapshot === orcideFileSnapshot) continue
orcideFileSnapshotOfURI[fsPath] = orcideFileSnapshot
}
// // add a change for all user-edited files (that aren't in the history)
// for (const fsPath of this._userModifiedFilesToCheckInCheckpoints.keys()) {
// if (fsPath in lastIdxOfURI) continue // if already visisted, don't visit again
// const { model } = this._voidModelService.getModelFromFsPath(fsPath)
// const { model } = this._orcideModelService.getModelFromFsPath(fsPath)
// if (!model) continue
// currStrOfFsPath[fsPath] = model.getValue(EndOfLinePreference.LF)
// }
return { voidFileSnapshotOfURI }
return { orcideFileSnapshotOfURI }
}
private _addUserCheckpoint({ threadId }: { threadId: string }) {
const { voidFileSnapshotOfURI } = this._computeNewCheckpointInfo({ threadId }) ?? {}
const { orcideFileSnapshotOfURI } = this._computeNewCheckpointInfo({ threadId }) ?? {}
this._addCheckpoint(threadId, {
role: 'checkpoint',
type: 'user_edit',
voidFileSnapshotOfURI: voidFileSnapshotOfURI ?? {},
userModifications: { voidFileSnapshotOfURI: {}, },
orcideFileSnapshotOfURI: orcideFileSnapshotOfURI ?? {},
userModifications: { orcideFileSnapshotOfURI: {}, },
})
}
// call this right after LLM edits a file
private _addToolEditCheckpoint({ threadId, uri, }: { threadId: string, uri: URI }) {
const thread = this.state.allThreads[threadId]
if (!thread) return
const { model } = this._voidModelService.getModel(uri)
const { model } = this._orcideModelService.getModel(uri)
if (!model) return // should never happen
const diffAreasSnapshot = this._editCodeService.getVoidFileSnapshot(uri)
const diffAreasSnapshot = this._editCodeService.getOrcideFileSnapshot(uri)
this._addCheckpoint(threadId, {
role: 'checkpoint',
type: 'tool_edit',
voidFileSnapshotOfURI: { [uri.fsPath]: diffAreasSnapshot },
userModifications: { voidFileSnapshotOfURI: {} },
orcideFileSnapshotOfURI: { [uri.fsPath]: diffAreasSnapshot },
userModifications: { orcideFileSnapshotOfURI: {} },
})
}
@ -1035,7 +1035,7 @@ class ChatThreadService extends Disposable implements IChatThreadService {
for (let i = loIdx; i <= hiIdx; i += 1) {
const message = thread.messages[i]
if (message?.role !== 'checkpoint') continue
for (const fsPath in message.voidFileSnapshotOfURI) { // do not include userModified.beforeStrOfURI here, jumping should not include those changes
for (const fsPath in message.orcideFileSnapshotOfURI) { // do not include userModified.beforeStrOfURI here, jumping should not include those changes
lastIdxOfURI[fsPath] = i
}
}
@ -1055,13 +1055,13 @@ class ChatThreadService extends Disposable implements IChatThreadService {
return [checkpoint, currCheckpointIdx]
}
private _addUserModificationsToCurrCheckpoint({ threadId }: { threadId: string }) {
const { voidFileSnapshotOfURI } = this._computeNewCheckpointInfo({ threadId }) ?? {}
const { orcideFileSnapshotOfURI } = this._computeNewCheckpointInfo({ threadId }) ?? {}
const res = this._readCurrentCheckpoint(threadId)
if (!res) return
const [checkpoint, checkpointIdx] = res
this._editMessageInThread(threadId, checkpointIdx, {
...checkpoint,
userModifications: { voidFileSnapshotOfURI: voidFileSnapshotOfURI ?? {}, },
userModifications: { orcideFileSnapshotOfURI: orcideFileSnapshotOfURI ?? {}, },
})
}
@ -1139,9 +1139,9 @@ We only need to do it for files that were edited since `to`, ie files between to
if (message.role !== 'checkpoint') continue
const res = this._getCheckpointInfo(message, fsPath, { includeUserModifiedChanges: jumpToUserModified })
if (!res) continue
const { voidFileSnapshot } = res
if (!voidFileSnapshot) continue
this._editCodeService.restoreVoidFileSnapshot(URI.file(fsPath), voidFileSnapshot)
const { orcideFileSnapshot } = res
if (!orcideFileSnapshot) continue
this._editCodeService.restoreOrcideFileSnapshot(URI.file(fsPath), orcideFileSnapshot)
break
}
}
@ -1173,9 +1173,9 @@ We only need to do it for files that were edited since `from`, ie files between
if (message.role !== 'checkpoint') continue
const res = this._getCheckpointInfo(message, fsPath, { includeUserModifiedChanges: jumpToUserModified })
if (!res) continue
const { voidFileSnapshot } = res
if (!voidFileSnapshot) continue
this._editCodeService.restoreVoidFileSnapshot(URI.file(fsPath), voidFileSnapshot)
const { orcideFileSnapshot } = res
if (!orcideFileSnapshot) continue
this._editCodeService.restoreOrcideFileSnapshot(URI.file(fsPath), orcideFileSnapshot)
break
}
}
@ -1201,7 +1201,7 @@ We only need to do it for files that were edited since `from`, ie files between
sticky: true,
actions: {
primary: [{
id: 'void.goToChat',
id: 'orcide.goToChat',
enabled: true,
label: `Jump to Chat`,
tooltip: '',
@ -1463,7 +1463,7 @@ We only need to do it for files that were edited since `from`, ie files between
// check all prevUris for the target
for (const uri of prevUris) {
const modelRef = await this._voidModelService.getModelSafe(uri)
const modelRef = await this._orcideModelService.getModelSafe(uri)
const { model } = modelRef
if (!model) continue

View file

@ -9,11 +9,11 @@ import { ChatMessage } from '../common/chatThreadServiceTypes.js';
import { getIsReasoningEnabledState, getReservedOutputTokenSpace, getModelCapabilities } from '../common/modelCapabilities.js';
import { reParsedToolXMLString, chat_systemMessage } from '../common/prompt/prompts.js';
import { AnthropicLLMChatMessage, AnthropicReasoning, GeminiLLMChatMessage, LLMChatMessage, LLMFIMMessage, OpenAILLMChatMessage, RawToolParamsObj } from '../common/sendLLMMessageTypes.js';
import { IVoidSettingsService } from '../common/voidSettingsService.js';
import { ChatMode, FeatureName, ModelSelection, ProviderName } from '../common/voidSettingsTypes.js';
import { IOrcideSettingsService } from '../common/orcideSettingsService.js';
import { ChatMode, FeatureName, ModelSelection, ProviderName } from '../common/orcideSettingsTypes.js';
import { IDirectoryStrService } from '../common/directoryStrService.js';
import { ITerminalToolService } from './terminalToolService.js';
import { IVoidModelService } from '../common/voidModelService.js';
import { IOrcideModelService } from '../common/orcideModelService.js';
import { URI } from '../../../../base/common/uri.js';
import { EndOfLinePreference } from '../../../../editor/common/model.js';
import { ToolName } from '../common/toolsServiceTypes.js';
@ -538,25 +538,25 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
@IEditorService private readonly editorService: IEditorService,
@IDirectoryStrService private readonly directoryStrService: IDirectoryStrService,
@ITerminalToolService private readonly terminalToolService: ITerminalToolService,
@IVoidSettingsService private readonly voidSettingsService: IVoidSettingsService,
@IVoidModelService private readonly voidModelService: IVoidModelService,
@IOrcideSettingsService private readonly orcideSettingsService: IOrcideSettingsService,
@IOrcideModelService private readonly orcideModelService: IOrcideModelService,
@IMCPService private readonly mcpService: IMCPService,
) {
super()
}
// Read .voidrules files from workspace folders
private _getVoidRulesFileContents(): string {
private _getOrcideRulesFileContents(): string {
try {
const workspaceFolders = this.workspaceContextService.getWorkspace().folders;
let voidRules = '';
let orcideRules = '';
for (const folder of workspaceFolders) {
const uri = URI.joinPath(folder.uri, '.voidrules')
const { model } = this.voidModelService.getModel(uri)
const uri = URI.joinPath(folder.uri, '.orciderules')
const { model } = this.orcideModelService.getModel(uri)
if (!model) continue
voidRules += model.getValue(EndOfLinePreference.LF) + '\n\n';
orcideRules += model.getValue(EndOfLinePreference.LF) + '\n\n';
}
return voidRules.trim();
return orcideRules.trim();
}
catch (e) {
return ''
@ -565,12 +565,12 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
// Get combined AI instructions from settings and .voidrules files
private _getCombinedAIInstructions(): string {
const globalAIInstructions = this.voidSettingsService.state.globalSettings.aiInstructions;
const voidRulesFileContent = this._getVoidRulesFileContents();
const globalAIInstructions = this.orcideSettingsService.state.globalSettings.aiInstructions;
const orcideRulesFileContent = this._getOrcideRulesFileContents();
const ans: string[] = []
if (globalAIInstructions) ans.push(globalAIInstructions)
if (voidRulesFileContent) ans.push(voidRulesFileContent)
if (orcideRulesFileContent) ans.push(orcideRulesFileContent)
return ans.join('\n\n')
}
@ -637,7 +637,7 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
prepareLLMSimpleMessages: IConvertToLLMMessageService['prepareLLMSimpleMessages'] = ({ simpleMessages, systemMessage, modelSelection, featureName }) => {
if (modelSelection === null) return { messages: [], separateSystemMessage: undefined }
const { overridesOfModel } = this.voidSettingsService.state
const { overridesOfModel } = this.orcideSettingsService.state
const { providerName, modelName } = modelSelection
const {
@ -646,7 +646,7 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
supportsSystemMessage,
} = getModelCapabilities(providerName, modelName, overridesOfModel)
const modelSelectionOptions = this.voidSettingsService.state.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName]
const modelSelectionOptions = this.orcideSettingsService.state.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName]
// Get combined AI instructions
const aiInstructions = this._getCombinedAIInstructions();
@ -670,7 +670,7 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
prepareLLMChatMessages: IConvertToLLMMessageService['prepareLLMChatMessages'] = async ({ chatMessages, chatMode, modelSelection }) => {
if (modelSelection === null) return { messages: [], separateSystemMessage: undefined }
const { overridesOfModel } = this.voidSettingsService.state
const { overridesOfModel } = this.orcideSettingsService.state
const { providerName, modelName } = modelSelection
const {
@ -679,11 +679,11 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
supportsSystemMessage,
} = getModelCapabilities(providerName, modelName, overridesOfModel)
const { disableSystemMessage } = this.voidSettingsService.state.globalSettings;
const { disableSystemMessage } = this.orcideSettingsService.state.globalSettings;
const fullSystemMessage = await this._generateChatMessagesSystemMessage(chatMode, specialToolFormat)
const systemMessage = disableSystemMessage ? '' : fullSystemMessage;
const modelSelectionOptions = this.voidSettingsService.state.optionsOfModelSelection['Chat'][modelSelection.providerName]?.[modelSelection.modelName]
const modelSelectionOptions = this.orcideSettingsService.state.optionsOfModelSelection['Chat'][modelSelection.providerName]?.[modelSelection.modelName]
// Get combined AI instructions
const aiInstructions = this._getCombinedAIInstructions();

View file

@ -1,28 +1,28 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable } from '../../../../base/common/lifecycle.js';
import { URI } from '../../../../base/common/uri.js';
import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js';
import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
import { IVoidModelService } from '../common/voidModelService.js';
import { IOrcideModelService } from '../common/orcideModelService.js';
class ConvertContribWorkbenchContribution extends Disposable implements IWorkbenchContribution {
static readonly ID = 'workbench.contrib.void.convertcontrib'
static readonly ID = 'workbench.contrib.orcide.convertcontrib'
_serviceBrand: undefined;
constructor(
@IVoidModelService private readonly voidModelService: IVoidModelService,
@IOrcideModelService private readonly orcideModelService: IOrcideModelService,
@IWorkspaceContextService private readonly workspaceContext: IWorkspaceContextService,
) {
super()
const initializeURI = (uri: URI) => {
this.workspaceContext.getWorkspace()
const voidRulesURI = URI.joinPath(uri, '.voidrules')
this.voidModelService.initializeModel(voidRulesURI)
const orcideRulesURI = URI.joinPath(uri, '.orciderules')
this.orcideModelService.initializeModel(orcideRulesURI)
}
// call

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable } from '../../../../base/common/lifecycle.js';
@ -24,9 +24,9 @@ import { Widget } from '../../../../base/browser/ui/widget.js';
import { URI } from '../../../../base/common/uri.js';
import { IConsistentEditorItemService, IConsistentItemService } from './helperServices/consistentItemService.js';
import { voidPrefixAndSuffix, ctrlKStream_userMessage, ctrlKStream_systemMessage, defaultQuickEditFimTags, rewriteCode_systemMessage, rewriteCode_userMessage, searchReplaceGivenDescription_systemMessage, searchReplaceGivenDescription_userMessage, tripleTick, } from '../common/prompt/prompts.js';
import { IVoidCommandBarService } from './voidCommandBarService.js';
import { IOrcideCommandBarService } from './orcideCommandBarService.js';
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
import { VOID_ACCEPT_DIFF_ACTION_ID, VOID_REJECT_DIFF_ACTION_ID } from './actionIDs.js';
import { ORCIDE_ACCEPT_DIFF_ACTION_ID, ORCIDE_REJECT_DIFF_ACTION_ID } from './actionIDs.js';
import { mountCtrlK } from './react/out/quick-edit-tsx/index.js'
import { QuickEditPropsType } from './quickEditActions.js';
@ -39,15 +39,15 @@ import { ILLMMessageService } from '../common/sendLLMMessageService.js';
import { LLMChatMessage } from '../common/sendLLMMessageTypes.js';
import { IMetricsService } from '../common/metricsService.js';
import { IEditCodeService, AddCtrlKOpts, StartApplyingOpts, CallBeforeStartApplyingOpts, } from './editCodeServiceInterface.js';
import { IVoidSettingsService } from '../common/voidSettingsService.js';
import { FeatureName } from '../common/voidSettingsTypes.js';
import { IVoidModelService } from '../common/voidModelService.js';
import { IOrcideSettingsService } from '../common/orcideSettingsService.js';
import { FeatureName } from '../common/orcideSettingsTypes.js';
import { IOrcideModelService } from '../common/orcideModelService.js';
import { deepClone } from '../../../../base/common/objects.js';
import { acceptBg, acceptBorder, buttonFontSize, buttonTextColor, rejectBg, rejectBorder } from '../common/helpers/colors.js';
import { DiffArea, Diff, CtrlKZone, VoidFileSnapshot, DiffAreaSnapshotEntry, diffAreaSnapshotKeys, DiffZone, TrackingZone, ComputedDiff } from '../common/editCodeServiceTypes.js';
import { DiffArea, Diff, CtrlKZone, OrcideFileSnapshot, DiffAreaSnapshotEntry, diffAreaSnapshotKeys, DiffZone, TrackingZone, ComputedDiff } from '../common/editCodeServiceTypes.js';
import { IConvertToLLMMessageService } from './convertToLLMMessageService.js';
// import { isMacintosh } from '../../../../base/common/platform.js';
// import { VOID_OPEN_SETTINGS_ACTION_ID } from './voidSettingsPane.js';
// import { ORCIDE_OPEN_SETTINGS_ACTION_ID } from './orcideSettingsPane.js';
const numLinesOfStr = (str: string) => str.split('\n').length
@ -192,9 +192,9 @@ class EditCodeService extends Disposable implements IEditCodeService {
@IMetricsService private readonly _metricsService: IMetricsService,
@INotificationService private readonly _notificationService: INotificationService,
// @ICommandService private readonly _commandService: ICommandService,
@IVoidSettingsService private readonly _settingsService: IVoidSettingsService,
@IOrcideSettingsService private readonly _settingsService: IOrcideSettingsService,
// @IFileService private readonly _fileService: IFileService,
@IVoidModelService private readonly _voidModelService: IVoidModelService,
@IOrcideModelService private readonly _orcideModelService: IOrcideModelService,
@IConvertToLLMMessageService private readonly _convertToLLMMessageService: IConvertToLLMMessageService,
) {
super();
@ -203,7 +203,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
const registeredModelURIs = new Set<string>()
const initializeModel = async (model: ITextModel) => {
await this._voidModelService.initializeModel(model.uri)
await this._orcideModelService.initializeModel(model.uri)
// do not add listeners to the same model twice - important, or will see duplicates
if (registeredModelURIs.has(model.uri.fsPath)) return
@ -279,18 +279,18 @@ class EditCodeService extends Disposable implements IEditCodeService {
// const details = errorDetails(e.fullError)
// this._notificationService.notify({
// severity: Severity.Warning,
// message: `Void Error: ${e.message}`,
// message: `Orcide Error: ${e.message}`,
// actions: {
// secondary: [{
// id: 'void.onerror.opensettings',
// enabled: true,
// label: `Open Void's settings`,
// label: `Open Orcide's settings`,
// tooltip: '',
// class: undefined,
// run: () => { this._commandService.executeCommand(VOID_OPEN_SETTINGS_ACTION_ID) }
// run: () => { this._commandService.executeCommand(ORCIDE_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
// })
// }
@ -315,7 +315,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
private _addDiffAreaStylesToURI = (uri: URI) => {
const { model } = this._voidModelService.getModel(uri)
const { model } = this._orcideModelService.getModel(uri)
for (const diffareaid of this.diffAreasOfURI[uri.fsPath] || []) {
const diffArea = this.diffAreaOfId[diffareaid]
@ -324,10 +324,10 @@ class EditCodeService extends Disposable implements IEditCodeService {
// add sweep styles to the diffZone
if (diffArea._streamState.isStreaming) {
// sweepLine ... sweepLine
const fn1 = this._addLineDecoration(model, diffArea._streamState.line, diffArea._streamState.line, 'void-sweepIdxBG')
const fn1 = this._addLineDecoration(model, diffArea._streamState.line, diffArea._streamState.line, 'orcide.sweepIdxBG')
// sweepLine+1 ... endLine
const fn2 = diffArea._streamState.line + 1 <= diffArea.endLine ?
this._addLineDecoration(model, diffArea._streamState.line + 1, diffArea.endLine, 'void-sweepBG')
this._addLineDecoration(model, diffArea._streamState.line + 1, diffArea.endLine, 'orcide.sweepBG')
: null
diffArea._removeStylesFns.add(() => { fn1?.(); fn2?.(); })
@ -336,7 +336,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
else if (diffArea.type === 'CtrlKZone' && diffArea._linkedStreamingDiffZone === null) {
// highlight zone's text
const fn = this._addLineDecoration(model, diffArea.startLine, diffArea.endLine, 'void-highlightBG')
const fn = this._addLineDecoration(model, diffArea.startLine, diffArea.endLine, 'orcide.highlightBG')
diffArea._removeStylesFns.add(() => fn?.());
}
}
@ -344,7 +344,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
private _computeDiffsAndAddStylesToURI = (uri: URI) => {
const { model } = this._voidModelService.getModel(uri)
const { model } = this._orcideModelService.getModel(uri)
if (model === null) return
const fullFileText = model.getValue(EndOfLinePreference.LF)
@ -477,11 +477,11 @@ class EditCodeService extends Disposable implements IEditCodeService {
const disposeInThisEditorFns: (() => void)[] = []
const { model } = this._voidModelService.getModel(uri)
const { model } = this._orcideModelService.getModel(uri)
// green decoration and minimap decoration
if (type !== 'deletion') {
const fn = this._addLineDecoration(model, diff.startLine, diff.endLine, 'void-greenBG', {
const fn = this._addLineDecoration(model, diff.startLine, diff.endLine, 'orcide.greenBG', {
minimap: { color: { id: 'minimapGutter.addedBackground' }, position: 2 },
overviewRuler: { color: { id: 'editorOverviewRuler.addedForeground' }, position: 7 }
})
@ -496,7 +496,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
fn: (editor) => {
const domNode = document.createElement('div');
domNode.className = 'void-redBG'
domNode.className = 'orcide.redBG'
const renderOptions = RenderOptions.fromEditor(editor)
@ -585,7 +585,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
offsetLines = 1
}
}
else { throw new Error('Void 1') }
else { throw new Error('Orcide 1') }
const buttonsWidget = this._instantiationService.createInstance(AcceptRejectInlineWidget, {
editor,
@ -625,7 +625,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
weAreWriting = false
private _writeURIText(uri: URI, text: string, range_: IRange | 'wholeFileRange', { shouldRealignDiffAreas, }: { shouldRealignDiffAreas: boolean, }) {
const { model } = this._voidModelService.getModel(uri)
const { model } = this._orcideModelService.getModel(uri)
if (!model) {
this._refreshStylesAndDiffsInURI(uri) // at the end of a write, we still expect to refresh all styles. e.g. sometimes we expect to restore all the decorations even if no edits were made when _writeText is used
return
@ -663,8 +663,8 @@ class EditCodeService extends Disposable implements IEditCodeService {
private _getCurrentVoidFileSnapshot = (uri: URI): VoidFileSnapshot => {
const { model } = this._voidModelService.getModel(uri)
private _getCurrentOrcideFileSnapshot = (uri: URI): OrcideFileSnapshot => {
const { model } = this._orcideModelService.getModel(uri)
const snapshottedDiffAreaOfId: Record<string, DiffAreaSnapshotEntry> = {}
for (const diffareaid in this.diffAreaOfId) {
@ -687,7 +687,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
}
private _restoreVoidFileSnapshot = async (uri: URI, snapshot: VoidFileSnapshot) => {
private _restoreOrcideFileSnapshot = async (uri: URI, snapshot: OrcideFileSnapshot) => {
// for each diffarea in this uri, stop streaming if currently streaming
for (const diffareaid in this.diffAreaOfId) {
const diffArea = this.diffAreaOfId[diffareaid]
@ -737,34 +737,34 @@ class EditCodeService extends Disposable implements IEditCodeService {
}
private _addToHistory(uri: URI, opts?: { onWillUndo?: () => void }) {
const beforeSnapshot: VoidFileSnapshot = this._getCurrentVoidFileSnapshot(uri)
let afterSnapshot: VoidFileSnapshot | null = null
const beforeSnapshot: OrcideFileSnapshot = this._getCurrentOrcideFileSnapshot(uri)
let afterSnapshot: OrcideFileSnapshot | null = null
const elt: IUndoRedoElement = {
type: UndoRedoElementType.Resource,
resource: uri,
label: 'Void Agent',
label: 'Orcide Agent',
code: 'undoredo.editCode',
undo: async () => { opts?.onWillUndo?.(); await this._restoreVoidFileSnapshot(uri, beforeSnapshot) },
redo: async () => { if (afterSnapshot) await this._restoreVoidFileSnapshot(uri, afterSnapshot) }
undo: async () => { opts?.onWillUndo?.(); await this._restoreOrcideFileSnapshot(uri, beforeSnapshot) },
redo: async () => { if (afterSnapshot) await this._restoreOrcideFileSnapshot(uri, afterSnapshot) }
}
this._undoRedoService.pushElement(elt)
const onFinishEdit = async () => {
afterSnapshot = this._getCurrentVoidFileSnapshot(uri)
await this._voidModelService.saveModel(uri)
afterSnapshot = this._getCurrentOrcideFileSnapshot(uri)
await this._orcideModelService.saveModel(uri)
}
return { onFinishEdit }
}
public getVoidFileSnapshot(uri: URI) {
return this._getCurrentVoidFileSnapshot(uri)
public getOrcideFileSnapshot(uri: URI) {
return this._getCurrentOrcideFileSnapshot(uri)
}
public restoreVoidFileSnapshot(uri: URI, snapshot: VoidFileSnapshot): void {
this._restoreVoidFileSnapshot(uri, snapshot)
public restoreOrcideFileSnapshot(uri: URI, snapshot: OrcideFileSnapshot): void {
this._restoreOrcideFileSnapshot(uri, snapshot)
}
@ -997,7 +997,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
else if (lastDiff.type === 'deletion')
endLineInLlmTextSoFar = lastDiff.startLine
else
throw new Error(`Void: diff.type not recognized on: ${lastDiff}`)
throw new Error(`Orcide: diff.type not recognized on: ${lastDiff}`)
}
// at the start, add a newline between the stream and originalCode to make reasoning easier
@ -1127,8 +1127,8 @@ class EditCodeService extends Disposable implements IEditCodeService {
public async callBeforeApplyOrEdit(givenURI: URI | 'current') {
const uri = this._uriOfGivenURI(givenURI)
if (!uri) return
await this._voidModelService.initializeModel(uri)
await this._voidModelService.saveModel(uri) // save the URI
await this._orcideModelService.initializeModel(uri)
await this._orcideModelService.saveModel(uri) // save the URI
}
@ -1269,7 +1269,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
linkedCtrlKZone: CtrlKZone | null,
onWillUndo: () => void,
}) {
const { model } = this._voidModelService.getModel(uri)
const { model } = this._orcideModelService.getModel(uri)
if (!model) return
// treat like full file, unless linkedCtrlKZone was provided in which case use its diff's range
@ -1376,10 +1376,10 @@ class EditCodeService extends Disposable implements IEditCodeService {
startRange = [startLine_, endLine_]
}
else {
throw new Error(`Void: diff.type not recognized on: ${from}`)
throw new Error(`Orcide: diff.type not recognized on: ${from}`)
}
const { model } = this._voidModelService.getModel(uri)
const { model } = this._orcideModelService.getModel(uri)
if (!model) return
let streamRequestIdRef: { current: string | null } = { current: null } // can use this as a proxy to set the diffArea's stream state requestId
@ -1480,7 +1480,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
else if (from === 'ClickApply') {
return extractCodeFromRegular({ text: fullText, recentlyAddedTextLen })
}
throw new Error('Void 1')
throw new Error('Orcide 1')
}
// refresh now in case onText takes a while to get 1st message
@ -1578,7 +1578,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
_fileLengthOfGivenURI(givenURI: URI | 'current') {
const uri = this._uriOfGivenURI(givenURI)
if (!uri) return null
const { model } = this._voidModelService.getModel(uri)
const { model } = this._orcideModelService.getModel(uri)
if (!model) return null
const numCharsInFile = model.getValueLength(EndOfLinePreference.LF)
return numCharsInFile
@ -1617,7 +1617,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
const blocks = extractSearchReplaceBlocks(blocksStr)
if (blocks.length === 0) throw new Error(`No Search/Replace blocks were received!`)
const { model } = this._voidModelService.getModel(uri)
const { model } = this._orcideModelService.getModel(uri)
if (!model) throw new Error(`Error applying Search/Replace blocks: File does not exist.`)
const modelStr = model.getValue(EndOfLinePreference.LF)
// .split('\n').map(l => '\t' + l).join('\n') // for testing purposes only, remember to remove this
@ -1678,7 +1678,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
const uri = this._getURIBeforeStartApplying(opts)
if (!uri) return
const { model } = this._voidModelService.getModel(uri)
const { model } = this._orcideModelService.getModel(uri)
if (!model) return
let streamRequestIdRef: { current: string | null } = { current: null } // can use this as a proxy to set the diffArea's stream state requestId
@ -1968,7 +1968,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
const blocks = extractSearchReplaceBlocks(fullText)
if (blocks.length === 0) {
this._notificationService.info(`Void: We ran Fast Apply, but the LLM didn't output any changes.`)
this._notificationService.info(`Orcide: We ran Fast Apply, but the LLM didn't output any changes.`)
}
this._writeURIText(uri, originalFileCode, 'wholeFileRange', { shouldRealignDiffAreas: true })
@ -2158,7 +2158,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
].join('\n')
}
else {
throw new Error(`Void error: ${diff}.type not recognized`)
throw new Error(`Orcide error: ${diff}.type not recognized`)
}
// console.log('DIFF', diff)
@ -2250,7 +2250,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
toRange = { startLineNumber: diff.startLine, startColumn: 1, endLineNumber: diff.endLine, endColumn: Number.MAX_SAFE_INTEGER } // 1-indexed
}
else {
throw new Error(`Void error: ${diff}.type not recognized`)
throw new Error(`Orcide error: ${diff}.type not recognized`)
}
// update the file
@ -2305,7 +2305,7 @@ class AcceptRejectInlineWidget extends Widget implements IOverlayWidget {
startLine: number,
offsetLines: number
},
@IVoidCommandBarService private readonly _voidCommandBarService: IVoidCommandBarService,
@IOrcideCommandBarService private readonly _orcideCommandBarService: IOrcideCommandBarService,
@IKeybindingService private readonly _keybindingService: IKeybindingService,
@IEditCodeService private readonly _editCodeService: IEditCodeService,
) {
@ -2328,15 +2328,15 @@ class AcceptRejectInlineWidget extends Widget implements IOverlayWidget {
const lineHeight = editor.getOption(EditorOption.lineHeight);
const getAcceptRejectText = () => {
const acceptKeybinding = this._keybindingService.lookupKeybinding(VOID_ACCEPT_DIFF_ACTION_ID);
const rejectKeybinding = this._keybindingService.lookupKeybinding(VOID_REJECT_DIFF_ACTION_ID);
const acceptKeybinding = this._keybindingService.lookupKeybinding(ORCIDE_ACCEPT_DIFF_ACTION_ID);
const rejectKeybinding = this._keybindingService.lookupKeybinding(ORCIDE_REJECT_DIFF_ACTION_ID);
// Use the standalone function directly since we're in a nested class that
// can't access EditCodeService's methods
const acceptKeybindLabel = this._editCodeService.processRawKeybindingText(acceptKeybinding && acceptKeybinding.getLabel() || '');
const rejectKeybindLabel = this._editCodeService.processRawKeybindingText(rejectKeybinding && rejectKeybinding.getLabel() || '');
const commandBarStateAtUri = this._voidCommandBarService.stateOfURI[uri.fsPath];
const commandBarStateAtUri = this._orcideCommandBarService.stateOfURI[uri.fsPath];
const selectedDiffIdx = commandBarStateAtUri?.diffIdx ?? 0; // 0th item is selected by default
const thisDiffIdx = commandBarStateAtUri?.sortedDiffIds.indexOf(diffid) ?? null;
@ -2435,7 +2435,7 @@ class AcceptRejectInlineWidget extends Widget implements IOverlayWidget {
// Listen for state changes in the command bar service
this._register(this._voidCommandBarService.onDidChangeState(e => {
this._register(this._orcideCommandBarService.onDidChangeState(e => {
if (uri && e.uri.fsPath === uri.fsPath) {
const { acceptText, rejectText } = getAcceptRejectText()

View file

@ -1,13 +1,13 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Event } from '../../../../base/common/event.js';
import { URI } from '../../../../base/common/uri.js';
import { ICodeEditor } from '../../../../editor/browser/editorBrowser.js';
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
import { Diff, DiffArea, VoidFileSnapshot } from '../common/editCodeServiceTypes.js';
import { Diff, DiffArea, OrcideFileSnapshot } from '../common/editCodeServiceTypes.js';
export type StartBehavior = 'accept-conflicts' | 'reject-conflicts' | 'keep-conflicts'
@ -73,6 +73,6 @@ export interface IEditCodeService {
interruptURIStreaming(opts: { uri: URI }): void;
// testDiffs(): void;
getVoidFileSnapshot(uri: URI): VoidFileSnapshot;
restoreVoidFileSnapshot(uri: URI, snapshot: VoidFileSnapshot): void;
getOrcideFileSnapshot(uri: URI): OrcideFileSnapshot;
restoreOrcideFileSnapshot(uri: URI, snapshot: OrcideFileSnapshot): void;
}

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { VSBuffer } from '../../../../base/common/buffer.js';
@ -31,7 +31,7 @@ const extensionBlacklist = [
// ignore extensions
'ms-vscode-remote.remote', // ms-vscode-remote.remote-ssh, ms-vscode-remote.remote-wsl
'ms-vscode.remote', // ms-vscode.remote-explorer
// ignore other AI copilots that could conflict with Void keybindings
// ignore other AI copilots that could conflict with Orcide keybindings
'sourcegraph.cody-ai',
'continue.continue',
'codeium.codeium',
@ -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,
}]
}

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { URI } from '../../../../base/common/uri.js'

View file

@ -7,20 +7,20 @@ import { IFileService } from '../../../../platform/files/common/files.js';
import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js';
import { IDirectoryStrService } from '../common/directoryStrService.js';
import { messageOfSelection } from '../common/prompt/prompts.js';
import { IVoidModelService } from '../common/voidModelService.js';
import { IOrcideModelService } from '../common/orcideModelService.js';
class FilePromptActionService extends Action2 {
private static readonly VOID_COPY_FILE_PROMPT_ID = 'void.copyfileprompt'
private static readonly ORCIDE_COPY_FILE_PROMPT_ID = 'orcide.copyfileprompt'
constructor() {
super({
id: FilePromptActionService.VOID_COPY_FILE_PROMPT_ID,
title: localize2('voidCopyPrompt', 'Void: Copy Prompt'),
id: FilePromptActionService.ORCIDE_COPY_FILE_PROMPT_ID,
title: localize2('orcideCopyPrompt', 'Orcide: Copy Prompt'),
menu: [{
id: MenuId.ExplorerContext,
group: '8_void',
group: '8_orcide',
order: 1,
}]
});
@ -31,7 +31,7 @@ class FilePromptActionService extends Action2 {
const fileService = accessor.get(IFileService);
const clipboardService = accessor.get(IClipboardService)
const directoryStrService = accessor.get(IDirectoryStrService)
const voidModelService = accessor.get(IVoidModelService)
const orcideModelService = accessor.get(IOrcideModelService)
const stat = await fileService.stat(uri)
@ -45,7 +45,7 @@ class FilePromptActionService extends Action2 {
m = await messageOfSelection({
type: 'File',
uri,
language: (await voidModelService.getModelSafe(uri)).model?.getLanguageId() || '',
language: (await orcideModelService.getModelSafe(uri)).model?.getLanguageId() || '',
state: { wasAddedAsCurrentFile: false, },
}, {
folderOpts,

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable } from '../../../../../base/common/lifecycle.js';

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { ComputedDiff } from '../../common/editCodeServiceTypes.js';
@ -130,7 +130,7 @@ export function findDiffs(oldStr: string, newStr: string) {
// let keys = new Set([...Object.keys(a), ...Object.keys(b)])
// for (let k of keys) {
// if (a[k] !== b[k]) {
// console.error('Void Test Error:', name_, '\n', `${k}=`, `${JSON.stringify(a[k])}, ${JSON.stringify(b[k])}`)
// console.error('Orcide Test Error:', name_, '\n', `${k}=`, `${JSON.stringify(a[k])}, ${JSON.stringify(b[k])}`)
// // console.error(JSON.stringify(a, null, 4))
// // console.error(JSON.stringify(b, null, 4))
// testsFailed += 1
@ -244,8 +244,8 @@ export function findDiffs(oldStr: string, newStr: string) {
// if (testsFailed === 0) {
// console.log('✅ Void - All tests passed')
// console.log('✅ Orcide - All tests passed')
// }
// else {
// console.log('❌ Void - At least one test failed')
// console.log('❌ Orcide - At least one test failed')
// }

View file

@ -0,0 +1,204 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
.monaco-editor .orcide-sweepIdxBG {
background-color: var(--vscode-orcide-sweepIdxBG);
}
.orcide-sweepBG {
background-color: var(--vscode-orcide-sweepBG);
}
.orcide-highlightBG {
background-color: var(--vscode-orcide-highlightBG);
}
.orcide-greenBG {
background-color: var(--vscode-orcide-greenBG);
}
.orcide-redBG {
background-color: var(--vscode-orcide-redBG);
}
/* Renamed from void-watermark-button to orcide-openfolder-button */
.orcide-openfolder-button {
padding: 8px 20px;
background-color: #306dce;
color: white;
border: none;
border-radius: 4px;
outline: none !important;
box-shadow: none !important;
cursor: pointer;
transition: background-color 0.2s ease;
}
.orcide-openfolder-button:hover {
background-color: #2563eb;
}
.orcide-openfolder-button:active {
background-color: #2563eb;
}
/* Added for Open SSH button with slightly darker color */
.orcide-openssh-button {
padding: 8px 20px;
background-color: #656565; /* Slightly darker than the #5a5a5a in the TS file */
color: white;
border: none;
border-radius: 4px;
outline: none !important;
box-shadow: none !important;
cursor: pointer;
transition: background-color 0.2s ease;
}
.orcide-openssh-button:hover {
background-color: #474747; /* Darker on hover */
}
.orcide-openssh-button:active {
background-color: #474747;
}
.orcide-settings-watermark-button {
margin: 8px 0;
padding: 8px 20px;
background-color: var(--vscode-input-background);
color: var(--vscode-input-foreground);
border: none;
border-radius: 4px;
outline: none !important;
box-shadow: none !important;
cursor: pointer;
transition: all 0.2s ease;
}
.orcide-settings-watermark-button:hover {
filter: brightness(1.1);
}
.orcide-settings-watermark-button:active {
filter: brightness(1.1);
}
.orcide-link {
color: #3b82f6;
cursor: pointer;
transition: all 0.2s ease;
}
.orcide-link:hover {
opacity: 80%;
}
/* styles for all containers used by orcide */
.orcide-scope {
--scrollbar-vertical-width: 8px;
--scrollbar-horizontal-height: 6px;
}
/* Target both orcide-scope and all its descendants with scrollbars */
.orcide-scope,
.orcide-scope * {
scrollbar-width: thin !important;
scrollbar-color: var(--orcide-bg-1) var(--orcide-bg-3) !important;
/* For Firefox */
}
.orcide-scope::-webkit-scrollbar,
.orcide-scope *::-webkit-scrollbar {
width: var(--scrollbar-vertical-width) !important;
height: var(--scrollbar-horizontal-height) !important;
background-color: var(--orcide-bg-3) !important;
}
.orcide-scope::-webkit-scrollbar-thumb,
.orcide-scope *::-webkit-scrollbar-thumb {
background-color: var(--orcide-bg-1) !important;
border-radius: 4px !important;
border: none !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
}
.orcide-scope::-webkit-scrollbar-thumb:hover,
.orcide-scope *::-webkit-scrollbar-thumb:hover {
background-color: var(--orcide-bg-1) !important;
filter: brightness(1.1) !important;
}
.orcide-scope::-webkit-scrollbar-thumb:active,
.orcide-scope *::-webkit-scrollbar-thumb:active {
background-color: var(--orcide-bg-1) !important;
filter: brightness(1.2) !important;
}
.orcide-scope::-webkit-scrollbar-track,
.orcide-scope *::-webkit-scrollbar-track {
background-color: var(--orcide-bg-3) !important;
border: none !important;
}
.orcide-scope::-webkit-scrollbar-corner,
.orcide-scope *::-webkit-scrollbar-corner {
background-color: var(--orcide-bg-3) !important;
}
/* Add orcide-scrollable-element styles to match */
.orcide-scrollable-element {
background-color: var(--vscode-editor-background);
--scrollbar-vertical-width: 14px;
--scrollbar-horizontal-height: 6px;
overflow: auto;
/* Ensure scrollbars are shown when needed */
}
.orcide-scrollable-element,
.orcide-scrollable-element * {
scrollbar-width: thin !important;
/* For Firefox */
scrollbar-color: var(--orcide-bg-1) var(--orcide-bg-3) !important;
/* For Firefox */
}
.orcide-scrollable-element::-webkit-scrollbar,
.orcide-scrollable-element *::-webkit-scrollbar {
width: var(--scrollbar-vertical-width) !important;
height: var(--scrollbar-horizontal-height) !important;
background-color: var(--orcide-bg-3) !important;
}
.orcide-scrollable-element::-webkit-scrollbar-thumb,
.orcide-scrollable-element *::-webkit-scrollbar-thumb {
background-color: var(--orcide-bg-1) !important;
border-radius: 4px !important;
border: none !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
}
.orcide-scrollable-element::-webkit-scrollbar-thumb:hover,
.orcide-scrollable-element *::-webkit-scrollbar-thumb:hover {
background-color: var(--orcide-bg-1) !important;
filter: brightness(1.1) !important;
}
.orcide-scrollable-element::-webkit-scrollbar-thumb:active,
.orcide-scrollable-element *::-webkit-scrollbar-thumb:active {
background-color: var(--orcide-bg-1) !important;
filter: brightness(1.2) !important;
}
.orcide-scrollable-element::-webkit-scrollbar-track,
.orcide-scrollable-element *::-webkit-scrollbar-track {
background-color: var(--orcide-bg-3) !important;
border: none !important;
}
.orcide-scrollable-element::-webkit-scrollbar-corner,
.orcide-scrollable-element *::-webkit-scrollbar-corner {
background-color: var(--orcide-bg-3) !important;
}

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable } from '../../../../base/common/lifecycle.js';

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable } from '../../../../base/common/lifecycle.js';
@ -26,7 +26,7 @@ export class MiscWorkbenchContribs extends Disposable implements IWorkbenchContr
private initialize(): void {
// delete blacklisted extensions once (this is for people who already installed them)
const deleteExtensionsStorageId = 'void-deleted-blacklist-2'
const deleteExtensionsStorageId = 'orcide-deleted-blacklist-2'
const alreadyDeleted = this.storageService.get(deleteExtensionsStorageId, StorageScope.APPLICATION)
if (!alreadyDeleted) {
this.storageService.store(deleteExtensionsStorageId, 'true', StorageScope.APPLICATION, StorageTarget.MACHINE)

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
@ -23,13 +23,13 @@ import './autocompleteService.js'
// import './contextUserChangesService.js'
// settings pane
import './voidSettingsPane.js'
import './orcideSettingsPane.js'
// register css
import './media/void.css'
import './media/orcide.css'
// update (frontend part, also see platform/)
import './voidUpdateActions.js'
import './orcideUpdateActions.js'
import './convertToLLMMessageWorkbenchContrib.js'
@ -47,13 +47,13 @@ import './metricsPollService.js'
import './helperServices/consistentItemService.js'
// register selection helper
import './voidSelectionHelperWidget.js'
import './orcideSelectionHelperWidget.js'
// register tooltip service
import './tooltipService.js'
// register onboarding service
import './voidOnboardingService.js'
import './orcideOnboardingService.js'
// register misc service
import './miscWokrbenchContrib.js'
@ -62,15 +62,20 @@ import './miscWokrbenchContrib.js'
import './fileService.js'
// register source control management
import './voidSCMService.js'
import './orcideSCMService.js'
// ---------- common (unclear if these actually need to be imported, because they're already imported wherever they're used) ----------
// ---------- Orcide SSO & Profile services ----------
// SSO authentication service (browser-side)
import './orcideSSOBrowserService.js'
// ---------- common ----------
// llmMessage
import '../common/sendLLMMessageService.js'
// voidSettings
import '../common/voidSettingsService.js'
// orcideSettings (previously orcideSettings)
import '../common/orcideSettingsService.js'
// refreshModel
import '../common/refreshModelService.js'
@ -79,7 +84,25 @@ import '../common/refreshModelService.js'
import '../common/metricsService.js'
// updates
import '../common/voidUpdateService.js'
import '../common/orcideUpdateService.js'
// model service
import '../common/voidModelService.js'
import '../common/orcideModelService.js'
// Orcide SSO service
import '../common/orcideSSOService.js'
// Orcide user profile service
import '../common/orcideUserProfileService.js'
// Orcide collaboration service
import '../common/orcideCollaborationService.js'
// Orcide LangChain integration service
import '../common/orcideLangChainService.js'
// Orcide Git PR generation & deployment service
import '../common/orcideGitService.js'
// Orcide Enterprise & Cursor Ultra features service
import '../common/orcideEnterpriseService.js'

View file

@ -0,0 +1,294 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable } from '../../../../base/common/lifecycle.js';
import { Emitter, Event } from '../../../../base/common/event.js';
import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js';
import { generateUuid } from '../../../../base/common/uuid.js';
import { ILLMMessageService } from '../common/sendLLMMessageService.js';
import { ServiceSendLLMMessageParams, ServiceModelListParams, OllamaModelResponse, OpenaiCompatibleModelResponse } from '../common/sendLLMMessageTypes.js';
import { IOrcideSettingsService } from '../common/orcideSettingsService.js';
import { IMCPService } from '../common/mcpService.js';
import { MCPToolCallParams, RawMCPToolCall } from '../common/mcpServiceTypes.js';
import { InternalToolInfo } from '../common/prompt/prompts.js';
import { IMetricsService } from '../common/metricsService.js';
import { IOrcideUpdateService } from '../common/orcideUpdateService.js';
import { IGenerateCommitMessageService } from './orcideSCMService.js';
import { ProviderName } from '../common/orcideSettingsTypes.js';
const OPENAI_COMPAT_BASE_URLS: Partial<Record<ProviderName, string>> = {
openRouter: 'https://openrouter.ai/api/v1',
openAI: 'https://api.openai.com/v1',
deepseek: 'https://api.deepseek.com',
groq: 'https://api.groq.com/openai/v1',
xAI: 'https://api.x.ai/v1',
mistral: 'https://api.mistral.ai/v1',
};
class LLMMessageServiceWeb extends Disposable implements ILLMMessageService {
readonly _serviceBrand: undefined;
private readonly _abortControllers = new Map<string, AbortController>();
constructor(
@IOrcideSettingsService private readonly orcideSettingsService: IOrcideSettingsService,
) {
super();
}
sendLLMMessage(params: ServiceSendLLMMessageParams): string | null {
const { onError, modelSelection } = params;
if (modelSelection === null) {
onError({ message: 'Please add a provider in Orcide\'s Settings.', fullError: null });
return null;
}
if (params.messagesType === 'chatMessages' && (params.messages?.length ?? 0) === 0) {
onError({ message: 'No messages detected.', fullError: null });
return null;
}
if (params.messagesType === 'FIMMessage') {
onError({ message: 'Autocomplete (FIM) is not supported in web mode.', fullError: null });
return null;
}
const requestId = generateUuid();
const abortController = new AbortController();
this._abortControllers.set(requestId, abortController);
this._doSendChat(params, requestId, abortController);
return requestId;
}
private async _doSendChat(
params: ServiceSendLLMMessageParams,
requestId: string,
abortController: AbortController
) {
const { onText, onFinalMessage, onError, modelSelection } = params;
if (params.messagesType !== 'chatMessages' || !modelSelection) return;
try {
const { settingsOfProvider } = this.orcideSettingsService.state;
const providerSettings = settingsOfProvider[modelSelection.providerName];
const apiKey = (providerSettings as Record<string, unknown>).apiKey as string | undefined;
if (!apiKey) {
onError({
message: `API key not set for ${modelSelection.providerName}. Please configure it in Orcide Settings.`,
fullError: null
});
return;
}
const baseUrl = this._getBaseUrl(modelSelection.providerName, providerSettings);
if (!baseUrl) {
onError({
message: `Provider "${modelSelection.providerName}" requires the desktop app. Use OpenRouter instead.`,
fullError: null
});
return;
}
const messages = this._buildMessages(params.messages, params.separateSystemMessage);
const body: Record<string, unknown> = {
model: modelSelection.modelName,
messages,
stream: true,
};
const headers: Record<string, string> = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`,
};
if (modelSelection.providerName === 'openRouter') {
headers['HTTP-Referer'] = 'https://ide.orcest.ai';
headers['X-Title'] = 'ide.orcest.ai';
}
const response = await fetch(`${baseUrl}/chat/completions`, {
method: 'POST',
headers,
body: JSON.stringify(body),
signal: abortController.signal,
});
if (!response.ok) {
const errorText = await response.text();
onError({
message: `API error (${response.status}): ${errorText}`,
fullError: new Error(errorText)
});
this._abortControllers.delete(requestId);
return;
}
const reader = response.body!.getReader();
const decoder = new TextDecoder();
let fullText = '';
let fullReasoning = '';
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed.startsWith('data: ')) continue;
const data = trimmed.slice(6);
if (data === '[DONE]') {
onFinalMessage({ fullText, fullReasoning, anthropicReasoning: null });
this._abortControllers.delete(requestId);
return;
}
try {
const parsed = JSON.parse(data);
const delta = parsed.choices?.[0]?.delta;
if (delta?.content) {
fullText += delta.content;
onText({ fullText, fullReasoning });
}
if (delta?.reasoning_content || delta?.reasoning) {
fullReasoning += (delta.reasoning_content || delta.reasoning);
onText({ fullText, fullReasoning });
}
} catch {
// skip malformed SSE chunks
}
}
}
onFinalMessage({ fullText, fullReasoning, anthropicReasoning: null });
this._abortControllers.delete(requestId);
} catch (err: unknown) {
if (err instanceof Error && err.name === 'AbortError') return;
const message = err instanceof Error ? err.message : String(err);
onError({ message, fullError: err instanceof Error ? err : new Error(message) });
this._abortControllers.delete(requestId);
}
}
private _getBaseUrl(providerName: ProviderName, providerSettings: Record<string, unknown>): string | null {
const known = OPENAI_COMPAT_BASE_URLS[providerName];
if (known) return known;
if (providerName === 'openAICompatible' || providerName === 'liteLLM' || providerName === 'awsBedrock') {
return (providerSettings.endpoint as string) || null;
}
return null;
}
private _buildMessages(
messages: unknown[],
separateSystemMessage: string | undefined
): { role: string; content: string }[] {
const result: { role: string; content: string }[] = [];
if (separateSystemMessage) {
result.push({ role: 'system', content: separateSystemMessage });
}
for (const msg of messages) {
const m = msg as { role: string; content: unknown };
if (typeof m.content === 'string') {
result.push({ role: m.role === 'model' ? 'assistant' : m.role, content: m.content });
} else if (Array.isArray(m.content)) {
const textParts = m.content
.filter((p: Record<string, unknown>) => p.type === 'text' || p.text)
.map((p: Record<string, unknown>) => (p.text as string) || '')
.join('');
if (textParts) {
result.push({ role: m.role === 'model' ? 'assistant' : m.role, content: textParts });
}
}
}
return result;
}
abort(requestId: string) {
const controller = this._abortControllers.get(requestId);
if (controller) {
controller.abort();
this._abortControllers.delete(requestId);
}
}
ollamaList(params: ServiceModelListParams<OllamaModelResponse>) {
params.onError({ error: 'Ollama model listing is not available in web mode.' });
}
openAICompatibleList(params: ServiceModelListParams<OpenaiCompatibleModelResponse>) {
params.onError({ error: 'Model listing is not available in web mode.' });
}
}
class MCPServiceWeb extends Disposable implements IMCPService {
readonly _serviceBrand: undefined;
state: { mcpServerOfName: Record<string, never>; error: string | undefined } = {
mcpServerOfName: {},
error: undefined,
};
private readonly _onDidChangeState = new Emitter<void>();
readonly onDidChangeState: Event<void> = this._onDidChangeState.event;
async revealMCPConfigFile(): Promise<void> { }
async toggleServerIsOn(): Promise<void> { }
getMCPTools(): InternalToolInfo[] | undefined { return undefined; }
async callMCPTool(_toolData: MCPToolCallParams): Promise<{ result: RawMCPToolCall }> {
throw new Error('MCP is not available in web mode.');
}
stringifyResult(result: RawMCPToolCall): string {
return JSON.stringify(result);
}
}
class MetricsServiceWeb implements IMetricsService {
readonly _serviceBrand: undefined;
capture(): void { }
setOptOut(): void { }
async getDebuggingProperties(): Promise<object> { return { mode: 'web' }; }
}
class OrcideUpdateServiceWeb implements IOrcideUpdateService {
readonly _serviceBrand: undefined;
check: IOrcideUpdateService['check'] = async () => null;
}
class GenerateCommitMessageServiceWeb implements IGenerateCommitMessageService {
readonly _serviceBrand: undefined;
async generateCommitMessage(): Promise<void> { }
abort(): void { }
}
registerSingleton(ILLMMessageService, LLMMessageServiceWeb, InstantiationType.Eager);
registerSingleton(IMCPService, MCPServiceWeb, InstantiationType.Eager);
registerSingleton(IMetricsService, MetricsServiceWeb, InstantiationType.Eager);
registerSingleton(IOrcideUpdateService, OrcideUpdateServiceWeb, InstantiationType.Eager);
registerSingleton(IGenerateCommitMessageService, GenerateCommitMessageServiceWeb, InstantiationType.Delayed);

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable, IDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
@ -11,7 +11,7 @@ import { Widget } from '../../../../base/browser/ui/widget.js';
import { IOverlayWidget, ICodeEditor, OverlayWidgetPositionPreference } from '../../../../editor/browser/editorBrowser.js';
import { Emitter, Event } from '../../../../base/common/event.js';
import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';
import { mountVoidCommandBar } from './react/out/void-editor-widgets-tsx/index.js'
import { mountOrcideCommandBar } from './react/out/orcide-editor-widgets-tsx/index.js'
import { deepClone } from '../../../../base/common/objects.js';
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
import { IEditCodeService } from './editCodeServiceInterface.js';
@ -19,7 +19,7 @@ import { ITextModel } from '../../../../editor/common/model.js';
import { IModelService } from '../../../../editor/common/services/model.js';
import { generateUuid } from '../../../../base/common/uuid.js';
import { Action2, registerAction2 } from '../../../../platform/actions/common/actions.js';
import { VOID_ACCEPT_DIFF_ACTION_ID, VOID_REJECT_DIFF_ACTION_ID, VOID_GOTO_NEXT_DIFF_ACTION_ID, VOID_GOTO_PREV_DIFF_ACTION_ID, VOID_GOTO_NEXT_URI_ACTION_ID, VOID_GOTO_PREV_URI_ACTION_ID, VOID_ACCEPT_FILE_ACTION_ID, VOID_REJECT_FILE_ACTION_ID, VOID_ACCEPT_ALL_DIFFS_ACTION_ID, VOID_REJECT_ALL_DIFFS_ACTION_ID } from './actionIDs.js';
import { ORCIDE_ACCEPT_DIFF_ACTION_ID, ORCIDE_REJECT_DIFF_ACTION_ID, ORCIDE_GOTO_NEXT_DIFF_ACTION_ID, ORCIDE_GOTO_PREV_DIFF_ACTION_ID, ORCIDE_GOTO_NEXT_URI_ACTION_ID, ORCIDE_GOTO_PREV_URI_ACTION_ID, ORCIDE_ACCEPT_FILE_ACTION_ID, ORCIDE_REJECT_FILE_ACTION_ID, ORCIDE_ACCEPT_ALL_DIFFS_ACTION_ID, ORCIDE_REJECT_ALL_DIFFS_ACTION_ID } from './actionIDs.js';
import { localize2 } from '../../../../nls.js';
import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js';
@ -27,11 +27,11 @@ import { IMetricsService } from '../common/metricsService.js';
import { KeyMod } from '../../../../editor/common/services/editorBaseApi.js';
import { KeyCode } from '../../../../base/common/keyCodes.js';
import { ScrollType } from '../../../../editor/common/editorCommon.js';
import { IVoidModelService } from '../common/voidModelService.js';
import { IOrcideModelService } from '../common/orcideModelService.js';
export interface IVoidCommandBarService {
export interface IOrcideCommandBarService {
readonly _serviceBrand: undefined;
stateOfURI: { [uri: string]: CommandBarStateType };
sortedURIs: URI[];
@ -54,7 +54,7 @@ export interface IVoidCommandBarService {
}
export const IVoidCommandBarService = createDecorator<IVoidCommandBarService>('VoidCommandBarService');
export const IOrcideCommandBarService = createDecorator<IOrcideCommandBarService>('OrcideCommandBarService');
export type CommandBarStateType = undefined | {
@ -75,10 +75,10 @@ const defaultState: NonNullable<CommandBarStateType> = {
}
export class VoidCommandBarService extends Disposable implements IVoidCommandBarService {
export class OrcideCommandBarService extends Disposable implements IOrcideCommandBarService {
_serviceBrand: undefined;
static readonly ID: 'void.VoidCommandBarService'
static readonly ID: 'orcide.OrcideCommandBarService'
// depends on uri -> diffZone -> {streaming, diffs}
public stateOfURI: { [uri: string]: CommandBarStateType } = {}
@ -100,7 +100,7 @@ export class VoidCommandBarService extends Disposable implements IVoidCommandBar
@ICodeEditorService private readonly _codeEditorService: ICodeEditorService,
@IModelService private readonly _modelService: IModelService,
@IEditCodeService private readonly _editCodeService: IEditCodeService,
@IVoidModelService private readonly _voidModelService: IVoidModelService,
@IOrcideModelService private readonly _orcideModelService: IOrcideModelService,
) {
super();
@ -460,7 +460,7 @@ export class VoidCommandBarService extends Disposable implements IVoidCommandBar
if (!nextURI) return;
// Get the model for this URI
const { model } = await this._voidModelService.getModelSafe(nextURI);
const { model } = await this._orcideModelService.getModelSafe(nextURI);
if (!model) return;
// Find an editor to use
@ -488,10 +488,10 @@ export class VoidCommandBarService extends Disposable implements IVoidCommandBar
}
registerSingleton(IVoidCommandBarService, VoidCommandBarService, InstantiationType.Delayed); // delayed is needed here :(
registerSingleton(IOrcideCommandBarService, OrcideCommandBarService, InstantiationType.Delayed); // delayed is needed here :(
export type VoidCommandBarProps = {
export type OrcideCommandBarProps = {
uri: URI | null;
editor: ICodeEditor;
}
@ -535,12 +535,12 @@ class AcceptRejectAllFloatingWidget extends Widget implements IOverlayWidget {
this.instantiationService.invokeFunction(accessor => {
const uri = editor.getModel()?.uri || null
const res = mountVoidCommandBar(root, accessor, { uri, editor } satisfies VoidCommandBarProps)
const res = mountOrcideCommandBar(root, accessor, { uri, editor } satisfies OrcideCommandBarProps)
if (!res) return
this._register(toDisposable(() => res.dispose?.()))
this._register(editor.onWillChangeModel((model) => {
const uri = model.newModelUrl
res.rerender({ uri, editor } satisfies VoidCommandBarProps)
res.rerender({ uri, editor } satisfies OrcideCommandBarProps)
}))
})
}
@ -570,20 +570,20 @@ class AcceptRejectAllFloatingWidget extends Widget implements IOverlayWidget {
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_ACCEPT_DIFF_ACTION_ID,
id: ORCIDE_ACCEPT_DIFF_ACTION_ID,
f1: true,
title: localize2('voidAcceptDiffAction', 'Void: Accept Diff'),
title: localize2('orcideAcceptDiffAction', 'Orcide: Accept Diff'),
keybinding: {
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.Enter,
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.Enter },
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const editCodeService = accessor.get(IEditCodeService);
const commandBarService = accessor.get(IVoidCommandBarService);
const commandBarService = accessor.get(IOrcideCommandBarService);
const metricsService = accessor.get(IMetricsService);
@ -613,20 +613,20 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_REJECT_DIFF_ACTION_ID,
id: ORCIDE_REJECT_DIFF_ACTION_ID,
f1: true,
title: localize2('voidRejectDiffAction', 'Void: Reject Diff'),
title: localize2('orcideRejectDiffAction', 'Orcide: Reject Diff'),
keybinding: {
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.Backspace,
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.Backspace },
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const editCodeService = accessor.get(IEditCodeService);
const commandBarService = accessor.get(IVoidCommandBarService);
const commandBarService = accessor.get(IOrcideCommandBarService);
const metricsService = accessor.get(IMetricsService);
const activeURI = commandBarService.activeURI;
@ -654,19 +654,19 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_GOTO_NEXT_DIFF_ACTION_ID,
id: ORCIDE_GOTO_NEXT_DIFF_ACTION_ID,
f1: true,
title: localize2('voidGoToNextDiffAction', 'Void: Go to Next Diff'),
title: localize2('orcideGoToNextDiffAction', 'Orcide: Go to Next Diff'),
keybinding: {
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.DownArrow,
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.DownArrow },
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const commandBarService = accessor.get(IVoidCommandBarService);
const commandBarService = accessor.get(IOrcideCommandBarService);
const metricsService = accessor.get(IMetricsService);
const nextDiffIdx = commandBarService.getNextDiffIdx(1);
@ -681,19 +681,19 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_GOTO_PREV_DIFF_ACTION_ID,
id: ORCIDE_GOTO_PREV_DIFF_ACTION_ID,
f1: true,
title: localize2('voidGoToPrevDiffAction', 'Void: Go to Previous Diff'),
title: localize2('orcideGoToPrevDiffAction', 'Orcide: Go to Previous Diff'),
keybinding: {
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.UpArrow,
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.UpArrow },
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const commandBarService = accessor.get(IVoidCommandBarService);
const commandBarService = accessor.get(IOrcideCommandBarService);
const metricsService = accessor.get(IMetricsService);
const prevDiffIdx = commandBarService.getNextDiffIdx(-1);
@ -708,19 +708,19 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_GOTO_NEXT_URI_ACTION_ID,
id: ORCIDE_GOTO_NEXT_URI_ACTION_ID,
f1: true,
title: localize2('voidGoToNextUriAction', 'Void: Go to Next File with Diffs'),
title: localize2('orcideGoToNextUriAction', 'Orcide: Go to Next File with Diffs'),
keybinding: {
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.RightArrow,
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.RightArrow },
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const commandBarService = accessor.get(IVoidCommandBarService);
const commandBarService = accessor.get(IOrcideCommandBarService);
const metricsService = accessor.get(IMetricsService);
const nextUriIdx = commandBarService.getNextUriIdx(1);
@ -735,19 +735,19 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_GOTO_PREV_URI_ACTION_ID,
id: ORCIDE_GOTO_PREV_URI_ACTION_ID,
f1: true,
title: localize2('voidGoToPrevUriAction', 'Void: Go to Previous File with Diffs'),
title: localize2('orcideGoToPrevUriAction', 'Orcide: Go to Previous File with Diffs'),
keybinding: {
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.LeftArrow,
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.LeftArrow },
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const commandBarService = accessor.get(IVoidCommandBarService);
const commandBarService = accessor.get(IOrcideCommandBarService);
const metricsService = accessor.get(IMetricsService);
const prevUriIdx = commandBarService.getNextUriIdx(-1);
@ -762,18 +762,18 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_ACCEPT_FILE_ACTION_ID,
id: ORCIDE_ACCEPT_FILE_ACTION_ID,
f1: true,
title: localize2('voidAcceptFileAction', 'Void: Accept All Diffs in Current File'),
title: localize2('orcideAcceptFileAction', 'Orcide: Accept All Diffs in Current File'),
keybinding: {
primary: KeyMod.Alt | KeyMod.Shift | KeyCode.Enter,
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const commandBarService = accessor.get(IVoidCommandBarService);
const commandBarService = accessor.get(IOrcideCommandBarService);
const editCodeService = accessor.get(IEditCodeService);
const metricsService = accessor.get(IMetricsService);
@ -793,18 +793,18 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_REJECT_FILE_ACTION_ID,
id: ORCIDE_REJECT_FILE_ACTION_ID,
f1: true,
title: localize2('voidRejectFileAction', 'Void: Reject All Diffs in Current File'),
title: localize2('orcideRejectFileAction', 'Orcide: Reject All Diffs in Current File'),
keybinding: {
primary: KeyMod.Alt | KeyMod.Shift | KeyCode.Backspace,
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const commandBarService = accessor.get(IVoidCommandBarService);
const commandBarService = accessor.get(IOrcideCommandBarService);
const editCodeService = accessor.get(IEditCodeService);
const metricsService = accessor.get(IMetricsService);
@ -824,18 +824,18 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_ACCEPT_ALL_DIFFS_ACTION_ID,
id: ORCIDE_ACCEPT_ALL_DIFFS_ACTION_ID,
f1: true,
title: localize2('voidAcceptAllDiffsAction', 'Void: Accept All Diffs in All Files'),
title: localize2('orcideAcceptAllDiffsAction', 'Orcide: Accept All Diffs in All Files'),
keybinding: {
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter,
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const commandBarService = accessor.get(IVoidCommandBarService);
const commandBarService = accessor.get(IOrcideCommandBarService);
const metricsService = accessor.get(IMetricsService);
if (commandBarService.anyFileIsStreaming()) return;
@ -849,18 +849,18 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_REJECT_ALL_DIFFS_ACTION_ID,
id: ORCIDE_REJECT_ALL_DIFFS_ACTION_ID,
f1: true,
title: localize2('voidRejectAllDiffsAction', 'Void: Reject All Diffs in All Files'),
title: localize2('orcideRejectAllDiffsAction', 'Orcide: Reject All Diffs in All Files'),
keybinding: {
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Backspace,
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const commandBarService = accessor.get(IVoidCommandBarService);
const commandBarService = accessor.get(IOrcideCommandBarService);
const metricsService = accessor.get(IMetricsService);
if (commandBarService.anyFileIsStreaming()) return;

View file

@ -1,13 +1,13 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable, toDisposable } from '../../../../base/common/lifecycle.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js';
import { mountVoidOnboarding } from './react/out/void-onboarding/index.js'
import { mountOrcideOnboarding } from './react/out/orcide-onboarding/index.js'
import { h, getActiveWindow } from '../../../../base/browser/dom.js';
// Onboarding contribution that mounts the component at startup
@ -30,10 +30,10 @@ export class OnboardingContribution extends Disposable implements IWorkbenchCont
if (workbench) {
const onboardingContainer = h('div.void-onboarding-container').root;
const onboardingContainer = h('div.orcide-onboarding-container').root;
workbench.appendChild(onboardingContainer);
this.instantiationService.invokeFunction((accessor: ServicesAccessor) => {
const result = mountVoidOnboarding(onboardingContainer, accessor);
const result = mountOrcideOnboarding(onboardingContainer, accessor);
if (result && typeof result.dispose === 'function') {
this._register(toDisposable(result.dispose));
}

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { ThemeIcon } from '../../../../base/common/themables.js'
@ -9,18 +9,19 @@ import { Action2, MenuId, registerAction2 } from '../../../../platform/actions/c
import { ContextKeyExpr, IContextKey, IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js'
import { ISCMService } from '../../scm/common/scm.js'
import { ProxyChannel } from '../../../../base/parts/ipc/common/ipc.js'
import { IVoidSCMService } from '../common/voidSCMTypes.js'
import { IOrcideSCMService } from '../common/orcideSCMTypes.js'
import { IMainProcessService } from '../../../../platform/ipc/common/mainProcessService.js'
import { IVoidSettingsService } from '../common/voidSettingsService.js'
import { IOrcideSettingsService } from '../common/orcideSettingsService.js'
import { IConvertToLLMMessageService } from './convertToLLMMessageService.js'
import { ILLMMessageService } from '../common/sendLLMMessageService.js'
import { ModelSelection, OverridesOfModel, ModelSelectionOptions } from '../common/voidSettingsTypes.js'
import { ModelSelection, OverridesOfModel, ModelSelectionOptions } from '../common/orcideSettingsTypes.js'
import { gitCommitMessage_systemMessage, gitCommitMessage_userMessage } from '../common/prompt/prompts.js'
import { LLMChatMessage } from '../common/sendLLMMessageTypes.js'
import { generateUuid } from '../../../../base/common/uuid.js'
import { ThrottledDelayer } from '../../../../base/common/async.js'
import { CancellationError, isCancellationError } from '../../../../base/common/errors.js'
import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js'
import { isWeb } from '../../../../base/common/platform.js'
import { createDecorator, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js'
import { Disposable } from '../../../../base/common/lifecycle.js'
import { INotificationService } from '../../../../platform/notification/common/notification.js'
@ -46,13 +47,13 @@ class GenerateCommitMessageService extends Disposable implements IGenerateCommit
private readonly execute = new ThrottledDelayer(300)
private llmRequestId: string | null = null
private currentRequestId: string | null = null
private voidSCM: IVoidSCMService
private voidSCM: IOrcideSCMService
private loadingContextKey: IContextKey<boolean>
constructor(
@ISCMService private readonly scmService: ISCMService,
@IMainProcessService mainProcessService: IMainProcessService,
@IVoidSettingsService private readonly voidSettingsService: IVoidSettingsService,
@IOrcideSettingsService private readonly orcideSettingsService: IOrcideSettingsService,
@IConvertToLLMMessageService private readonly convertToLLMMessageService: IConvertToLLMMessageService,
@ILLMMessageService private readonly llmMessageService: ILLMMessageService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@ -60,7 +61,7 @@ class GenerateCommitMessageService extends Disposable implements IGenerateCommit
) {
super()
this.loadingContextKey = this.contextKeyService.createKey(loadingContextKey, false)
this.voidSCM = ProxyChannel.toService<IVoidSCMService>(mainProcessService.getChannel('void-channel-scm'))
this.voidSCM = ProxyChannel.toService<IOrcideSCMService>(mainProcessService.getChannel('orcide-channel-scm'))
}
override dispose() {
@ -86,9 +87,9 @@ class GenerateCommitMessageService extends Disposable implements IGenerateCommit
if (!this.isCurrentRequest(requestId)) { throw new CancellationError() }
const modelSelection = this.voidSettingsService.state.modelSelectionOfFeature['SCM'] ?? null
const modelSelectionOptions = modelSelection ? this.voidSettingsService.state.optionsOfModelSelection['SCM'][modelSelection?.providerName]?.[modelSelection.modelName] : undefined
const overridesOfModel = this.voidSettingsService.state.overridesOfModel
const modelSelection = this.orcideSettingsService.state.modelSelectionOfFeature['SCM'] ?? null
const modelSelectionOptions = modelSelection ? this.orcideSettingsService.state.optionsOfModelSelection['SCM'][modelSelection?.providerName]?.[modelSelection.modelName] : undefined
const overridesOfModel = this.orcideSettingsService.state.overridesOfModel
const modelOptions: ModelOptions = { modelSelection, modelSelectionOptions, overridesOfModel }
@ -159,7 +160,7 @@ class GenerateCommitMessageService extends Disposable implements IGenerateCommit
onAbort: () => {
reject(new CancellationError())
},
logging: { loggingName: 'VoidSCM - Commit Message' },
logging: { loggingName: 'OrcideSCM - Commit Message' },
})
})
}
@ -185,10 +186,10 @@ class GenerateCommitMessageService extends Disposable implements IGenerateCommit
class GenerateCommitMessageAction extends Action2 {
constructor() {
super({
id: 'void.generateCommitMessageAction',
title: localize2('voidCommitMessagePrompt', 'Void: Generate Commit Message'),
id: 'orcide.generateCommitMessageAction',
title: localize2('orcideCommitMessagePrompt', 'Orcide: Generate Commit Message'),
icon: ThemeIcon.fromId('sparkle'),
tooltip: localize2('voidCommitMessagePromptTooltip', 'Void: Generate Commit Message'),
tooltip: localize2('orcideCommitMessagePromptTooltip', 'Orcide: Generate Commit Message'),
f1: true,
menu: [{
id: MenuId.SCMInputBox,
@ -207,10 +208,10 @@ class GenerateCommitMessageAction extends Action2 {
class LoadingGenerateCommitMessageAction extends Action2 {
constructor() {
super({
id: 'void.loadingGenerateCommitMessageAction',
title: localize2('voidCommitMessagePromptCancel', 'Void: Cancel Commit Message Generation'),
id: 'orcide.loadingGenerateCommitMessageAction',
title: localize2('orcideCommitMessagePromptCancel', 'Orcide: Cancel Commit Message Generation'),
icon: ThemeIcon.fromId('stop-circle'),
tooltip: localize2('voidCommitMessagePromptCancelTooltip', 'Void: Cancel Commit Message Generation'),
tooltip: localize2('orcideCommitMessagePromptCancelTooltip', 'Orcide: Cancel Commit Message Generation'),
f1: false, //Having a cancel command in the command palette is more confusing than useful.
menu: [{
id: MenuId.SCMInputBox,
@ -227,4 +228,13 @@ class LoadingGenerateCommitMessageAction extends Action2 {
registerAction2(GenerateCommitMessageAction)
registerAction2(LoadingGenerateCommitMessageAction)
registerSingleton(IGenerateCommitMessageService, GenerateCommitMessageService, InstantiationType.Delayed)
if (!isWeb) {
registerSingleton(IGenerateCommitMessageService, GenerateCommitMessageService, InstantiationType.Delayed)
} else {
class GenerateCommitMessageServiceWeb implements IGenerateCommitMessageService {
readonly _serviceBrand: undefined;
async generateCommitMessage() { }
abort() { }
}
registerSingleton(IGenerateCommitMessageService, GenerateCommitMessageServiceWeb, InstantiationType.Delayed)
}

View file

@ -0,0 +1,459 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Orcest. All rights reserved.
* Licensed under the MIT License. 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<typeof setInterval> | null = null;
private _popupTimeoutTimer: ReturnType<typeof setTimeout> | 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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
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}`,
});
}
}
});

View file

@ -11,9 +11,9 @@ import { IEditorContribution } from '../../../../editor/common/editorCommon.js';
import { Selection } from '../../../../editor/common/core/selection.js';
import { RunOnceScheduler } from '../../../../base/common/async.js';
import * as dom from '../../../../base/browser/dom.js';
import { mountVoidSelectionHelper } from './react/out/void-editor-widgets-tsx/index.js';
import { mountOrcideSelectionHelper } from './react/out/orcide-editor-widgets-tsx/index.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { IVoidSettingsService } from '../common/voidSettingsService.js';
import { IOrcideSettingsService } from '../common/orcideSettingsService.js';
import { EditorOption } from '../../../../editor/common/config/editorOptions.js';
import { getLengthOfTextPx } from './editCodeService.js';
@ -22,7 +22,7 @@ const minDistanceFromRightPx = 400;
const minLeftPx = 60;
export type VoidSelectionHelperProps = {
export type OrcideSelectionHelperProps = {
rerenderKey: number // alternates between 0 and 1
}
@ -43,7 +43,7 @@ export class SelectionHelperContribution extends Disposable implements IEditorCo
constructor(
private readonly _editor: ICodeEditor,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IVoidSettingsService private readonly _voidSettingsService: IVoidSettingsService
@IOrcideSettingsService private readonly _orcideSettingsService: IOrcideSettingsService
) {
super();
@ -63,13 +63,13 @@ export class SelectionHelperContribution extends Disposable implements IEditorCo
if (this._reactComponentDisposable) {
this._reactComponentDisposable.dispose();
}
const res = mountVoidSelectionHelper(content, accessor);
const res = mountOrcideSelectionHelper(content, accessor);
if (!res) return;
this._reactComponentDisposable = res;
this._rerender = res.rerender;
this._register(this._reactComponentDisposable);
this._register(res);
});
@ -242,11 +242,11 @@ export class SelectionHelperContribution extends Disposable implements IEditorCo
this._isVisible = true;
// rerender
const enabled = this._voidSettingsService.state.globalSettings.showInlineSuggestions
const enabled = this._orcideSettingsService.state.globalSettings.showInlineSuggestions
&& this._editor.hasTextFocus() // needed since VS Code counts unfocused selections as selections, which causes this to rerender when it shouldnt (bad ux)
if (enabled) {
this._rerender({ rerenderKey: this._rerenderKey } satisfies VoidSelectionHelperProps)
this._rerender({ rerenderKey: this._rerenderKey } satisfies OrcideSelectionHelperProps)
this._rerenderKey = (this._rerenderKey + 1) % 2;
// this._reactComponentRerender();
}

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
@ -23,33 +23,33 @@ import { URI } from '../../../../base/common/uri.js';
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
import { mountVoidSettings } from './react/out/void-settings-tsx/index.js'
import { mountOrcideSettings } from './react/out/orcide-settings-tsx/index.js'
import { Codicon } from '../../../../base/common/codicons.js';
import { toDisposable } from '../../../../base/common/lifecycle.js';
// refer to preferences.contribution.ts keybindings editor
class VoidSettingsInput extends EditorInput {
class OrcideSettingsInput extends EditorInput {
static readonly ID: string = 'workbench.input.void.settings';
static readonly ID: string = 'workbench.input.orcide.settings';
static readonly RESOURCE = URI.from({ // I think this scheme is invalid, it just shuts up TS
scheme: 'void', // Custom scheme for our editor (try Schemas.https)
scheme: 'orcide', // Custom scheme for our editor (try Schemas.https)
path: 'settings'
})
readonly resource = VoidSettingsInput.RESOURCE;
readonly resource = OrcideSettingsInput.RESOURCE;
constructor() {
super();
}
override get typeId(): string {
return VoidSettingsInput.ID;
return OrcideSettingsInput.ID;
}
override getName(): string {
return nls.localize('voidSettingsInputsName', 'Void\'s Settings');
return nls.localize('orcideSettingsInputsName', 'Orcide Settings');
}
override getIcon() {
@ -59,7 +59,7 @@ class VoidSettingsInput extends EditorInput {
}
class VoidSettingsPane extends EditorPane {
class OrcideSettingsPane extends EditorPane {
static readonly ID = 'workbench.test.myCustomPane';
// private _scrollbar: DomScrollableElement | undefined;
@ -71,7 +71,7 @@ class VoidSettingsPane extends EditorPane {
@IStorageService storageService: IStorageService,
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
super(VoidSettingsPane.ID, group, telemetryService, themeService, storageService);
super(OrcideSettingsPane.ID, group, telemetryService, themeService, storageService);
}
protected createEditor(parent: HTMLElement): void {
@ -90,7 +90,7 @@ class VoidSettingsPane extends EditorPane {
// Mount React into the scrollable content
this.instantiationService.invokeFunction(accessor => {
const disposeFn = mountVoidSettings(settingsElt, accessor)?.dispose;
const disposeFn = mountOrcideSettings(settingsElt, accessor)?.dispose;
this._register(toDisposable(() => disposeFn?.()))
// setTimeout(() => { // this is a complete hack and I don't really understand how scrollbar works here
@ -112,18 +112,18 @@ class VoidSettingsPane extends EditorPane {
// register Settings pane
Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(
EditorPaneDescriptor.create(VoidSettingsPane, VoidSettingsPane.ID, nls.localize('VoidSettingsPane', "Void\'s Settings Pane")),
[new SyncDescriptor(VoidSettingsInput)]
EditorPaneDescriptor.create(OrcideSettingsPane, OrcideSettingsPane.ID, nls.localize('OrcideSettingsPane', "Orcide Settings Pane")),
[new SyncDescriptor(OrcideSettingsInput)]
);
// register the gear on the top right
export const VOID_TOGGLE_SETTINGS_ACTION_ID = 'workbench.action.toggleVoidSettings'
export const ORCIDE_TOGGLE_SETTINGS_ACTION_ID = 'workbench.action.toggleOrcideSettings'
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_TOGGLE_SETTINGS_ACTION_ID,
title: nls.localize2('voidSettings', "Void: Toggle Settings"),
id: ORCIDE_TOGGLE_SETTINGS_ACTION_ID,
title: nls.localize2('orcideSettings', "Orcide: Toggle Settings"),
icon: Codicon.settingsGear,
menu: [
{
@ -146,7 +146,7 @@ registerAction2(class extends Action2 {
const instantiationService = accessor.get(IInstantiationService);
// if is open, close it
const openEditors = editorService.findEditors(VoidSettingsInput.RESOURCE); // should only have 0 or 1 elements...
const openEditors = editorService.findEditors(OrcideSettingsInput.RESOURCE); // should only have 0 or 1 elements...
if (openEditors.length !== 0) {
const openEditor = openEditors[0].editor
const isCurrentlyOpen = editorService.activeEditor?.resource?.fsPath === openEditor.resource?.fsPath
@ -159,7 +159,7 @@ registerAction2(class extends Action2 {
// else open it
const input = instantiationService.createInstance(VoidSettingsInput);
const input = instantiationService.createInstance(OrcideSettingsInput);
await editorGroupService.activeGroup.openEditor(input);
}
@ -167,12 +167,12 @@ registerAction2(class extends Action2 {
export const VOID_OPEN_SETTINGS_ACTION_ID = 'workbench.action.openVoidSettings'
export const ORCIDE_OPEN_SETTINGS_ACTION_ID = 'workbench.action.openOrcideSettings'
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_OPEN_SETTINGS_ACTION_ID,
title: nls.localize2('voidSettingsAction2', "Void: Open Settings"),
id: ORCIDE_OPEN_SETTINGS_ACTION_ID,
title: nls.localize2('orcideSettingsAction2', "Orcide: Open Settings"),
f1: true,
icon: Codicon.settingsGear,
});
@ -182,13 +182,13 @@ registerAction2(class extends Action2 {
const instantiationService = accessor.get(IInstantiationService);
// close all instances if found
const openEditors = editorService.findEditors(VoidSettingsInput.RESOURCE);
const openEditors = editorService.findEditors(OrcideSettingsInput.RESOURCE);
if (openEditors.length > 0) {
await editorService.closeEditors(openEditors);
}
// then, open one single editor
const input = instantiationService.createInstance(VoidSettingsInput);
const input = instantiationService.createInstance(OrcideSettingsInput);
await editorService.openEditor(input);
}
})
@ -201,8 +201,8 @@ registerAction2(class extends Action2 {
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '0_command',
command: {
id: VOID_TOGGLE_SETTINGS_ACTION_ID,
title: nls.localize('voidSettingsActionGear', "Void\'s Settings")
id: ORCIDE_TOGGLE_SETTINGS_ACTION_ID,
title: nls.localize('orcideSettingsActionGear', "Orcide Settings")
},
order: 1
});

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable } from '../../../../base/common/lifecycle.js';
@ -10,18 +10,18 @@ import { localize2 } from '../../../../nls.js';
import { Action2, registerAction2 } from '../../../../platform/actions/common/actions.js';
import { INotificationActions, INotificationHandle, INotificationService } from '../../../../platform/notification/common/notification.js';
import { IMetricsService } from '../common/metricsService.js';
import { IVoidUpdateService } from '../common/voidUpdateService.js';
import { IOrcideUpdateService } from '../common/orcideUpdateService.js';
import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
import * as dom from '../../../../base/browser/dom.js';
import { IUpdateService } from '../../../../platform/update/common/update.js';
import { VoidCheckUpdateRespose } from '../common/voidUpdateServiceTypes.js';
import { OrcideCheckUpdateResponse } from '../common/orcideUpdateServiceTypes.js';
import { IAction } from '../../../../base/common/actions.js';
const notifyUpdate = (res: VoidCheckUpdateRespose & { message: string }, notifService: INotificationService, updateService: IUpdateService): INotificationHandle => {
const message = res?.message || 'This is a very old version of Void, please download the latest version! [Void Editor](https://voideditor.com/download-beta)!'
const notifyUpdate = (res: OrcideCheckUpdateResponse & { message: string }, notifService: INotificationService, updateService: IUpdateService): INotificationHandle => {
const message = res?.message || 'This is a very old version of Orcide. Please download the latest version! [Orcide](https://orcest.ai/download-beta)!'
let actions: INotificationActions | undefined
@ -31,13 +31,13 @@ const notifyUpdate = (res: VoidCheckUpdateRespose & { message: string }, notifSe
if (res.action === 'reinstall') {
primary.push({
label: `Reinstall`,
id: 'void.updater.reinstall',
id: 'orcide.updater.reinstall',
enabled: true,
tooltip: '',
class: undefined,
run: () => {
const { window } = dom.getActiveWindow()
window.open('https://voideditor.com/download-beta')
window.open('https://orcest.ai/download-beta')
}
})
}
@ -45,7 +45,7 @@ const notifyUpdate = (res: VoidCheckUpdateRespose & { message: string }, notifSe
if (res.action === 'download') {
primary.push({
label: `Download`,
id: 'void.updater.download',
id: 'orcide.updater.download',
enabled: true,
tooltip: '',
class: undefined,
@ -59,7 +59,7 @@ const notifyUpdate = (res: VoidCheckUpdateRespose & { message: string }, notifSe
if (res.action === 'apply') {
primary.push({
label: `Apply`,
id: 'void.updater.apply',
id: 'orcide.updater.apply',
enabled: true,
tooltip: '',
class: undefined,
@ -72,7 +72,7 @@ const notifyUpdate = (res: VoidCheckUpdateRespose & { message: string }, notifSe
if (res.action === 'restart') {
primary.push({
label: `Restart`,
id: 'void.updater.restart',
id: 'orcide.updater.restart',
enabled: true,
tooltip: '',
class: undefined,
@ -83,21 +83,21 @@ const notifyUpdate = (res: VoidCheckUpdateRespose & { message: string }, notifSe
}
primary.push({
id: 'void.updater.site',
id: 'orcide.updater.site',
enabled: true,
label: `Void Site`,
label: `Orcide Site`,
tooltip: '',
class: undefined,
run: () => {
const { window } = dom.getActiveWindow()
window.open('https://voideditor.com/')
window.open('https://orcest.ai/')
}
})
actions = {
primary: primary,
secondary: [{
id: 'void.updater.close',
id: 'orcide.updater.close',
enabled: true,
label: `Keep current version`,
tooltip: '',
@ -127,7 +127,7 @@ const notifyUpdate = (res: VoidCheckUpdateRespose & { message: string }, notifSe
// })
}
const notifyErrChecking = (notifService: INotificationService): INotificationHandle => {
const message = `Void Error: There was an error checking for updates. If this persists, please get in touch or reinstall Void [here](https://voideditor.com/download-beta)!`
const message = `Orcide Error: There was an error checking for updates. If this persists, please get in touch or reinstall Orcide [here](https://orcest.ai/download-beta)!`
const notifController = notifService.notify({
severity: Severity.Info,
message: message,
@ -137,31 +137,31 @@ const notifyErrChecking = (notifService: INotificationService): INotificationHan
}
const performVoidCheck = async (
const performOrcideCheck = async (
explicit: boolean,
notifService: INotificationService,
voidUpdateService: IVoidUpdateService,
orcideUpdateService: IOrcideUpdateService,
metricsService: IMetricsService,
updateService: IUpdateService,
): Promise<INotificationHandle | null> => {
const metricsTag = explicit ? 'Manual' : 'Auto'
metricsService.capture(`Void Update ${metricsTag}: Checking...`, {})
const res = await voidUpdateService.check(explicit)
metricsService.capture(`Orcide Update ${metricsTag}: Checking...`, {})
const res = await orcideUpdateService.check(explicit)
if (!res) {
const notifController = notifyErrChecking(notifService);
metricsService.capture(`Void Update ${metricsTag}: Error`, { res })
metricsService.capture(`Orcide Update ${metricsTag}: Error`, { res })
return notifController
}
else {
if (res.message) {
const notifController = notifyUpdate(res, notifService, updateService)
metricsService.capture(`Void Update ${metricsTag}: Yes`, { res })
metricsService.capture(`Orcide Update ${metricsTag}: Yes`, { res })
return notifController
}
else {
metricsService.capture(`Void Update ${metricsTag}: No`, { res })
metricsService.capture(`Orcide Update ${metricsTag}: No`, { res })
return null
}
}
@ -176,19 +176,19 @@ registerAction2(class extends Action2 {
constructor() {
super({
f1: true,
id: 'void.voidCheckUpdate',
title: localize2('voidCheckUpdate', 'Void: Check for Updates'),
id: 'orcide.checkUpdate',
title: localize2('orcideCheckUpdate', 'Orcide: Check for Updates'),
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const voidUpdateService = accessor.get(IVoidUpdateService)
const orcideUpdateService = accessor.get(IOrcideUpdateService)
const notifService = accessor.get(INotificationService)
const metricsService = accessor.get(IMetricsService)
const updateService = accessor.get(IUpdateService)
const currNotifController = lastNotifController
const newController = await performVoidCheck(true, notifService, voidUpdateService, metricsService, updateService)
const newController = await performOrcideCheck(true, notifService, orcideUpdateService, metricsService, updateService)
if (newController) {
currNotifController?.close()
@ -198,10 +198,10 @@ registerAction2(class extends Action2 {
})
// on mount
class VoidUpdateWorkbenchContribution extends Disposable implements IWorkbenchContribution {
static readonly ID = 'workbench.contrib.void.voidUpdate'
class OrcideUpdateWorkbenchContribution extends Disposable implements IWorkbenchContribution {
static readonly ID = 'workbench.contrib.orcide.orcideUpdate'
constructor(
@IVoidUpdateService voidUpdateService: IVoidUpdateService,
@IOrcideUpdateService orcideUpdateService: IOrcideUpdateService,
@IMetricsService metricsService: IMetricsService,
@INotificationService notifService: INotificationService,
@IUpdateService updateService: IUpdateService,
@ -209,7 +209,7 @@ class VoidUpdateWorkbenchContribution extends Disposable implements IWorkbenchCo
super()
const autoCheck = () => {
performVoidCheck(false, notifService, voidUpdateService, metricsService, updateService)
performOrcideCheck(false, notifService, orcideUpdateService, metricsService, updateService)
}
// check once 5 seconds after mount
@ -225,4 +225,4 @@ class VoidUpdateWorkbenchContribution extends Disposable implements IWorkbenchCo
}
}
registerWorkbenchContribution2(VoidUpdateWorkbenchContribution.ID, VoidUpdateWorkbenchContribution, WorkbenchPhase.BlockRestore);
registerWorkbenchContribution2(OrcideUpdateWorkbenchContribution.ID, OrcideUpdateWorkbenchContribution, WorkbenchPhase.BlockRestore);

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { KeyCode, KeyMod } from '../../../../base/common/keyCodes.js';
@ -10,7 +10,7 @@ import { KeybindingWeight } from '../../../../platform/keybinding/common/keybind
import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';
import { IEditCodeService } from './editCodeServiceInterface.js';
import { roundRangeToLines } from './sidebarActions.js';
import { VOID_CTRL_K_ACTION_ID } from './actionIDs.js';
import { ORCIDE_CTRL_K_ACTION_ID } from './actionIDs.js';
import { localize2 } from '../../../../nls.js';
import { IMetricsService } from '../common/metricsService.js';
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
@ -36,12 +36,12 @@ registerAction2(class extends Action2 {
constructor(
) {
super({
id: VOID_CTRL_K_ACTION_ID,
id: ORCIDE_CTRL_K_ACTION_ID,
f1: true,
title: localize2('voidQuickEditAction', 'Void: Quick Edit'),
title: localize2('voidQuickEditAction', 'Orcide: Quick Edit'),
keybinding: {
primary: KeyMod.CtrlCmd | KeyCode.KeyK,
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
when: ContextKeyExpr.deserialize('editorFocus && !terminalFocus'),
}
});

View file

@ -1,10 +1,9 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { execSync } from 'child_process';
import { spawn } from 'cross-spawn'
import { execSync, spawn } from 'child_process';
// Added lines below
import fs from 'fs';
import path from 'path';
@ -33,7 +32,7 @@ This function finds `globalDesiredPath` given `localDesiredPath` and `currentPat
Diagram:
...basePath/
void/
orcide/
...currentPath/ (defined globally)
...localDesiredPath/ (defined locally)
@ -60,7 +59,7 @@ function findDesiredPathFromLocalPath(localDesiredPath, currentPath) {
function saveStylesFile() {
setTimeout(() => {
try {
const pathToCssFile = findDesiredPathFromLocalPath('./src/vs/workbench/contrib/void/browser/react/src2/styles.css', __dirname);
const pathToCssFile = findDesiredPathFromLocalPath('./src/vs/workbench/contrib/orcide/browser/react/src2/styles.css', __dirname);
if (pathToCssFile === undefined) {
console.error('[scope-tailwind] Error finding styles.css');
@ -87,7 +86,7 @@ if (isWatch) {
try {
console.log('🔨 Running initial scope-tailwind build to create src2 folder...');
execSync(
'npx scope-tailwind ./src -o src2/ -s void-scope -c styles.css -p "void-"',
'npx scope-tailwind ./src -o src2/ -s orcide-scope -c styles.css -p "orcide-"',
{ stdio: 'inherit' }
);
console.log('✅ src2/ created successfully.');
@ -103,7 +102,7 @@ if (isWatch) {
'--watch', 'src',
'--ext', 'ts,tsx,css',
'--exec',
'npx scope-tailwind ./src -o src2/ -s void-scope -c styles.css -p "void-"'
'npx scope-tailwind ./src -o src2/ -s orcide-scope -c styles.css -p "orcide-"'
]);
const tsupWatcher = spawn('npx', [
@ -145,7 +144,7 @@ if (isWatch) {
console.log('📦 Building...');
// Run scope-tailwind once
execSync('npx scope-tailwind ./src -o src2/ -s void-scope -c styles.css -p "void-"', { stdio: 'inherit' });
execSync('npx scope-tailwind ./src -o src2/ -s orcide-scope -c styles.css -p "orcide-"', { stdio: 'inherit' });
// Run tsup once
execSync('npx tsup', { stdio: 'inherit' });

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { diffLines, Change } from 'diff';

View file

@ -1,16 +1,16 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { useState, useEffect, useCallback, useRef, Fragment } from 'react'
import { useAccessor, useChatThreadsState, useChatThreadsStreamState, useCommandBarState, useCommandBarURIListener, useSettingsState } from '../util/services.js'
import { usePromise, useRefState } from '../util/helpers.js'
import { isFeatureNameDisabled } from '../../../../common/voidSettingsTypes.js'
import { isFeatureNameDisabled } from '../../../../common/orcideSettingsTypes.js'
import { URI } from '../../../../../../../base/common/uri.js'
import { FileSymlink, LucideIcon, RotateCw, Terminal } from 'lucide-react'
import { Check, X, Square, Copy, Play, } from 'lucide-react'
import { getBasename, ListableToolItem, voidOpenFileFn, ToolChildrenWrapper } from '../sidebar-tsx/SidebarChat.js'
import { getBasename, ListableToolItem, orcideOpenFileFn, ToolChildrenWrapper } from '../sidebar-tsx/SidebarChat.js'
import { PlacesType, VariantType } from 'react-tooltip'
enum CopyButtonText {
@ -33,12 +33,12 @@ export const IconShell1 = ({ onClick, Icon, disabled, className, ...props }: Ico
e.stopPropagation();
onClick?.(e);
}}
// border border-void-border-1 rounded
// border border-orcide-border-1 rounded
className={`
size-[18px]
p-[2px]
flex items-center justify-center
text-sm text-void-fg-3
text-sm text-orcide-fg-3
hover:brightness-110
disabled:opacity-50 disabled:cursor-not-allowed
${className}
@ -109,7 +109,7 @@ export const JumpToFileButton = ({ uri, ...props }: { uri: URI | 'current' } & R
<IconShell1
Icon={FileSymlink}
onClick={() => {
voidOpenFileFn(uri, accessor)
orcideOpenFileFn(uri, accessor)
}}
{...tooltipPropsForApplyBlock({ tooltipName: 'Go to file' })}
{...props}
@ -141,13 +141,13 @@ const getUriBeingApplied = (applyBoxId: string) => {
export const useApplyStreamState = ({ applyBoxId }: { applyBoxId: string }) => {
const accessor = useAccessor()
const voidCommandBarService = accessor.get('IVoidCommandBarService')
const orcideCommandBarService = accessor.get('IOrcideCommandBarService')
const getStreamState = useCallback(() => {
const uri = getUriBeingApplied(applyBoxId)
if (!uri) return 'idle-no-changes'
return voidCommandBarService.getStreamState(uri)
}, [voidCommandBarService, applyBoxId])
return orcideCommandBarService.getStreamState(uri)
}, [orcideCommandBarService, applyBoxId])
const [currStreamStateRef, setStreamState] = useRefState(getStreamState())
@ -173,15 +173,15 @@ export const useApplyStreamState = ({ applyBoxId }: { applyBoxId: string }) => {
type IndicatorColor = 'green' | 'orange' | 'dark' | 'yellow' | null
export const StatusIndicator = ({ indicatorColor, title, className, ...props }: { indicatorColor: IndicatorColor, title?: React.ReactNode, className?: string } & React.HTMLAttributes<HTMLDivElement>) => {
return (
<div className={`flex flex-row text-void-fg-3 text-xs items-center gap-1.5 ${className}`} {...props}>
<div className={`flex flex-row text-orcide-fg-3 text-xs items-center gap-1.5 ${className}`} {...props}>
{title && <span className='opacity-80'>{title}</span>}
<div
className={` size-1.5 rounded-full border
${indicatorColor === 'dark' ? 'bg-[rgba(0,0,0,0)] border-void-border-1' :
${indicatorColor === 'dark' ? 'bg-[rgba(0,0,0,0)] border-orcide-border-1' :
indicatorColor === 'orange' ? 'bg-orange-500 border-orange-500 shadow-[0_0_4px_0px_rgba(234,88,12,0.6)]' :
indicatorColor === 'green' ? 'bg-green-500 border-green-500 shadow-[0_0_4px_0px_rgba(22,163,74,0.6)]' :
indicatorColor === 'yellow' ? 'bg-yellow-500 border-yellow-500 shadow-[0_0_4px_0px_rgba(22,163,74,0.6)]' :
'bg-void-border-1 border-void-border-1'
'bg-orcide-border-1 border-orcide-border-1'
}
`}
/>
@ -190,7 +190,7 @@ export const StatusIndicator = ({ indicatorColor, title, className, ...props }:
};
const tooltipPropsForApplyBlock = ({ tooltipName, color = undefined, position = 'top', offset = undefined }: { tooltipName: string, color?: IndicatorColor, position?: PlacesType, offset?: number }) => ({
'data-tooltip-id': color === 'orange' ? `void-tooltip-orange` : color === 'green' ? 'void-tooltip-green' : 'void-tooltip',
'data-tooltip-id': color === 'orange' ? `orcide-tooltip-orange` : color === 'green' ? 'orcide-tooltip-green' : 'orcide-tooltip',
'data-tooltip-place': position as PlacesType,
'data-tooltip-content': `${tooltipName}`,
'data-tooltip-offset': offset,
@ -198,13 +198,13 @@ const tooltipPropsForApplyBlock = ({ tooltipName, color = undefined, position =
export const useEditToolStreamState = ({ applyBoxId, uri }: { applyBoxId: string, uri: URI }) => {
const accessor = useAccessor()
const voidCommandBarService = accessor.get('IVoidCommandBarService')
const [streamState, setStreamState] = useState(voidCommandBarService.getStreamState(uri))
const orcideCommandBarService = accessor.get('IOrcideCommandBarService')
const [streamState, setStreamState] = useState(orcideCommandBarService.getStreamState(uri))
// listen for stream updates on this box
useCommandBarURIListener(useCallback((uri_) => {
const shouldUpdate = uri.fsPath === uri_.fsPath
if (shouldUpdate) { setStreamState(voidCommandBarService.getStreamState(uri)) }
}, [voidCommandBarService, applyBoxId, uri]))
if (shouldUpdate) { setStreamState(orcideCommandBarService.getStreamState(uri)) }
}, [orcideCommandBarService, applyBoxId, uri]))
return { streamState, }
}
@ -351,14 +351,14 @@ const ApplyButtonsForEdit = ({
setApplying(newApplyingUri)
if (!applyDonePromise) {
notificationService.info(`Void Error: We couldn't run Apply here. ${uri === 'current' ? 'This Apply block wants to run on the current file, but you might not have a file open.' : `This Apply block wants to run on ${uri.fsPath}, but it might not exist.`}`)
notificationService.info(`Orcide Error: We couldn't run Apply here. ${uri === 'current' ? 'This Apply block wants to run on the current file, but you might not have a file open.' : `This Apply block wants to run on ${uri.fsPath}, but it might not exist.`}`)
}
// catch any errors by interrupting the stream
applyDonePromise?.catch(e => {
const uri = getUriBeingApplied(applyBoxId)
if (uri) editCodeService.interruptURIStreaming({ uri: uri })
notificationService.info(`Void Error: There was a problem running Apply: ${e}.`)
notificationService.info(`Orcide Error: There was a problem running Apply: ${e}.`)
})
metricsService.capture('Apply Code', { length: codeStr.length }) // capture the length only
@ -530,17 +530,17 @@ export const BlockCodeApplyWrapper = ({
name={<span className='not-italic'>{getBasename(uri.fsPath)}</span>}
isSmall={true}
showDot={false}
onClick={() => { voidOpenFileFn(uri, accessor) }}
onClick={() => { orcideOpenFileFn(uri, accessor) }}
/>
: <span>{language}</span>
return <div className='border border-void-border-3 rounded overflow-hidden bg-void-bg-3 my-1'>
return <div className='border border-orcide-border-3 rounded overflow-hidden bg-orcide-bg-3 my-1'>
{/* header */}
<div className=" select-none flex justify-between items-center py-1 px-2 border-b border-void-border-3 cursor-default">
<div className=" select-none flex justify-between items-center py-1 px-2 border-b border-orcide-border-3 cursor-default">
<div className="flex items-center">
<StatusIndicatorForApplyButton uri={uri} applyBoxId={applyBoxId} />
<span className="text-[13px] font-light text-void-fg-3">
<span className="text-[13px] font-light text-orcide-fg-3">
{name}
</span>
</div>

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import React, { JSX, useMemo, useState } from 'react'
@ -14,7 +14,7 @@ import { isAbsolute } from '../../../../../../../base/common/path.js'
import { separateOutFirstLine } from '../../../../common/helpers/util.js'
import { BlockCode } from '../util/inputs.js'
import { CodespanLocationLink } from '../../../../common/chatThreadServiceTypes.js'
import { getBasename, getRelative, voidOpenFileFn } from '../sidebar-tsx/SidebarChat.js'
import { getBasename, getRelative, orcideOpenFileFn } from '../sidebar-tsx/SidebarChat.js'
export type ChatMessageLocation = {
@ -94,10 +94,10 @@ const Codespan = ({ text, className, onClick, tooltip }: { text: string, classNa
// TODO compute this once for efficiency. we should use `labels.ts/shorten` to display duplicates properly
return <code
className={`font-mono font-medium rounded-sm bg-void-bg-1 px-1 ${className}`}
className={`font-mono font-medium rounded-sm bg-orcide-bg-1 px-1 ${className}`}
onClick={onClick}
{...tooltip ? {
'data-tooltip-id': 'void-tooltip',
'data-tooltip-id': 'orcide-tooltip',
'data-tooltip-content': tooltip,
'data-tooltip-place': 'top',
} : {}}
@ -150,11 +150,11 @@ const CodespanWithLink = ({ text, rawText, chatMessageLocation }: { text: string
const onClick = () => {
if (!link) return;
// Use the updated voidOpenFileFn to open the file and handle selection
// Use the updated orcideOpenFileFn to open the file and handle selection
if (link.selection)
voidOpenFileFn(link.uri, accessor, [link.selection.startLineNumber, link.selection.endLineNumber]);
orcideOpenFileFn(link.uri, accessor, [link.selection.startLineNumber, link.selection.endLineNumber]);
else
voidOpenFileFn(link.uri, accessor);
orcideOpenFileFn(link.uri, accessor);
}
return <Codespan
@ -375,13 +375,13 @@ const RenderToken = ({ token, inPTag, codeURI, chatMessageLocation, tokenIdx, ..
)
// return (
// <div>
// <table className={'min-w-full border border-void-bg-2'}>
// <table className={'min-w-full border border-orcide-bg-2'}>
// <thead>
// <tr className='bg-void-bg-1'>
// <tr className='bg-orcide-bg-1'>
// {t.header.map((cell: any, index: number) => (
// <th
// key={index}
// className='px-4 py-2 border border-void-bg-2 font-semibold'
// className='px-4 py-2 border border-orcide-bg-2 font-semibold'
// style={{ textAlign: t.align[index] || 'left' }}
// >
// {cell.raw}
@ -391,11 +391,11 @@ const RenderToken = ({ token, inPTag, codeURI, chatMessageLocation, tokenIdx, ..
// </thead>
// <tbody>
// {t.rows.map((row: any[], rowIndex: number) => (
// <tr key={rowIndex} className={rowIndex % 2 === 0 ? 'bg-white' : 'bg-void-bg-1'}>
// <tr key={rowIndex} className={rowIndex % 2 === 0 ? 'bg-white' : 'bg-orcide-bg-1'}>
// {row.map((cell: any, cellIndex: number) => (
// <td
// key={cellIndex}
// className={'px-4 py-2 border border-void-bg-2'}
// className={'px-4 py-2 border border-orcide-bg-2'}
// style={{ textAlign: t.align[cellIndex] || 'left' }}
// >
// {cell.raw}
@ -487,7 +487,7 @@ const RenderToken = ({ token, inPTag, codeURI, chatMessageLocation, tokenIdx, ..
onClick={() => { window.open(t.href) }}
href={t.href}
title={t.title ?? undefined}
className='underline cursor-pointer hover:brightness-90 transition-all duration-200 text-void-fg-2'
className='underline cursor-pointer hover:brightness-90 transition-all duration-200 text-orcide-fg-2'
>
{t.text}
</a>

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
@ -10,26 +10,26 @@ import '../styles.css'
import { useCallback, useEffect, useState, useRef } from 'react';
import { ScrollType } from '../../../../../../../editor/common/editorCommon.js';
import { acceptAllBg, acceptBorder, buttonFontSize, buttonTextColor, rejectAllBg, rejectBg, rejectBorder } from '../../../../common/helpers/colors.js';
import { VoidCommandBarProps } from '../../../voidCommandBarService.js';
import { OrcideCommandBarProps } from '../../../orcideCommandBarService.js';
import { Check, EllipsisVertical, Menu, MoveDown, MoveLeft, MoveRight, MoveUp, X } from 'lucide-react';
import {
VOID_GOTO_NEXT_DIFF_ACTION_ID,
VOID_GOTO_PREV_DIFF_ACTION_ID,
VOID_GOTO_NEXT_URI_ACTION_ID,
VOID_GOTO_PREV_URI_ACTION_ID,
VOID_ACCEPT_FILE_ACTION_ID,
VOID_REJECT_FILE_ACTION_ID,
VOID_ACCEPT_ALL_DIFFS_ACTION_ID,
VOID_REJECT_ALL_DIFFS_ACTION_ID
ORCIDE_GOTO_NEXT_DIFF_ACTION_ID,
ORCIDE_GOTO_PREV_DIFF_ACTION_ID,
ORCIDE_GOTO_NEXT_URI_ACTION_ID,
ORCIDE_GOTO_PREV_URI_ACTION_ID,
ORCIDE_ACCEPT_FILE_ACTION_ID,
ORCIDE_REJECT_FILE_ACTION_ID,
ORCIDE_ACCEPT_ALL_DIFFS_ACTION_ID,
ORCIDE_REJECT_ALL_DIFFS_ACTION_ID
} from '../../../actionIDs.js';
export const VoidCommandBarMain = ({ uri, editor }: VoidCommandBarProps) => {
export const OrcideCommandBarMain = ({ uri, editor }: OrcideCommandBarProps) => {
const isDark = useIsDark()
return <div
className={`@@void-scope ${isDark ? 'dark' : ''}`}
className={`@@orcide-scope ${isDark ? 'dark' : ''}`}
>
<VoidCommandBar uri={uri} editor={editor} />
<OrcideCommandBar uri={uri} editor={editor} />
</div>
}
@ -83,14 +83,14 @@ export const RejectAllButtonWrapper = ({ text, onClick, className, ...props }: {
export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
export const OrcideCommandBar = ({ uri, editor }: OrcideCommandBarProps) => {
const accessor = useAccessor()
const editCodeService = accessor.get('IEditCodeService')
const editorService = accessor.get('ICodeEditorService')
const metricsService = accessor.get('IMetricsService')
const commandService = accessor.get('ICommandService')
const commandBarService = accessor.get('IVoidCommandBarService')
const voidModelService = accessor.get('IVoidModelService')
const commandBarService = accessor.get('IOrcideCommandBarService')
const orcideModelService = accessor.get('IOrcideModelService')
const keybindingService = accessor.get('IKeybindingService')
const { stateOfURI: commandBarState, sortedURIs: sortedCommandBarURIs } = useCommandBarState()
const [showAcceptRejectAllButtons, setShowAcceptRejectAllButtons] = useState(false)
@ -171,14 +171,14 @@ export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
const _upKeybinding = keybindingService.lookupKeybinding(VOID_GOTO_PREV_DIFF_ACTION_ID);
const _downKeybinding = keybindingService.lookupKeybinding(VOID_GOTO_NEXT_DIFF_ACTION_ID);
const _leftKeybinding = keybindingService.lookupKeybinding(VOID_GOTO_PREV_URI_ACTION_ID);
const _rightKeybinding = keybindingService.lookupKeybinding(VOID_GOTO_NEXT_URI_ACTION_ID);
const _acceptFileKeybinding = keybindingService.lookupKeybinding(VOID_ACCEPT_FILE_ACTION_ID);
const _rejectFileKeybinding = keybindingService.lookupKeybinding(VOID_REJECT_FILE_ACTION_ID);
const _acceptAllKeybinding = keybindingService.lookupKeybinding(VOID_ACCEPT_ALL_DIFFS_ACTION_ID);
const _rejectAllKeybinding = keybindingService.lookupKeybinding(VOID_REJECT_ALL_DIFFS_ACTION_ID);
const _upKeybinding = keybindingService.lookupKeybinding(ORCIDE_GOTO_PREV_DIFF_ACTION_ID);
const _downKeybinding = keybindingService.lookupKeybinding(ORCIDE_GOTO_NEXT_DIFF_ACTION_ID);
const _leftKeybinding = keybindingService.lookupKeybinding(ORCIDE_GOTO_PREV_URI_ACTION_ID);
const _rightKeybinding = keybindingService.lookupKeybinding(ORCIDE_GOTO_NEXT_URI_ACTION_ID);
const _acceptFileKeybinding = keybindingService.lookupKeybinding(ORCIDE_ACCEPT_FILE_ACTION_ID);
const _rejectFileKeybinding = keybindingService.lookupKeybinding(ORCIDE_REJECT_FILE_ACTION_ID);
const _acceptAllKeybinding = keybindingService.lookupKeybinding(ORCIDE_ACCEPT_ALL_DIFFS_ACTION_ID);
const _rejectAllKeybinding = keybindingService.lookupKeybinding(ORCIDE_REJECT_ALL_DIFFS_ACTION_ID);
const upKeybindLabel = editCodeService.processRawKeybindingText(_upKeybinding?.getLabel() || '');
const downKeybindLabel = editCodeService.processRawKeybindingText(_downKeybinding?.getLabel() || '');
@ -196,7 +196,7 @@ export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
if (currFileIdx === null) {
return (
<div className="pointer-events-auto">
<div className="flex bg-void-bg-2 shadow-md border border-void-border-2 [&>*:first-child]:pl-3 [&>*:last-child]:pr-3 [&>*]:border-r [&>*]:border-void-border-2 [&>*:last-child]:border-r-0">
<div className="flex bg-orcide-bg-2 shadow-md border border-orcide-border-2 [&>*:first-child]:pl-3 [&>*:last-child]:pr-3 [&>*]:border-r [&>*]:border-orcide-border-2 [&>*:last-child]:border-r-0">
<div className="flex items-center px-3">
<span className="text-xs whitespace-nowrap">
{`${sortedCommandBarURIs.length} file${sortedCommandBarURIs.length === 1 ? '' : 's'} changed`}
@ -226,12 +226,12 @@ export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
{/* Accept All / Reject All buttons that appear when the vertical ellipsis is clicked */}
{showAcceptRejectAllButtons && showAcceptRejectAll && (
<div className="flex justify-end mb-1">
<div className="inline-flex bg-void-bg-2 rounded shadow-md border border-void-border-2 overflow-hidden">
<div className="flex items-center [&>*]:border-r [&>*]:border-void-border-2 [&>*:last-child]:border-r-0">
<div className="inline-flex bg-orcide-bg-2 rounded shadow-md border border-orcide-border-2 overflow-hidden">
<div className="flex items-center [&>*]:border-r [&>*]:border-orcide-border-2 [&>*:last-child]:border-r-0">
<AcceptAllButtonWrapper
// text={`Accept All${acceptAllKeybindLabel ? ` ${acceptAllKeybindLabel}` : ''}`}
text={`Accept All`}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-content={acceptAllKeybindLabel}
data-tooltip-delay-show={500}
onClick={onAcceptAll}
@ -239,7 +239,7 @@ export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
<RejectAllButtonWrapper
// text={`Reject All${rejectAllKeybindLabel ? ` ${rejectAllKeybindLabel}` : ''}`}
text={`Reject All`}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-content={rejectAllKeybindLabel}
data-tooltip-delay-show={500}
onClick={onRejectAll}
@ -249,7 +249,7 @@ export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
</div>
)}
<div className="flex items-center bg-void-bg-2 rounded shadow-md border border-void-border-2 [&>*:first-child]:pl-3 [&>*:last-child]:pr-3 [&>*]:px-3 [&>*]:border-r [&>*]:border-void-border-2 [&>*:last-child]:border-r-0">
<div className="flex items-center bg-orcide-bg-2 rounded shadow-md border border-orcide-border-2 [&>*:first-child]:pl-3 [&>*:last-child]:pr-3 [&>*]:px-3 [&>*]:border-r [&>*]:border-orcide-border-2 [&>*:last-child]:border-r-0">
{/* Diff Navigation Group */}
<div className="flex items-center py-0.5">
@ -263,7 +263,7 @@ export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
commandBarService.goToDiffIdx(prevDiffIdx);
}
}}
data-tooltip-id="void-tooltip"
data-tooltip-id="orcide-tooltip"
data-tooltip-content={`${upKeybindLabel ? `${upKeybindLabel}` : ''}`}
data-tooltip-delay-show={500}
>
@ -288,7 +288,7 @@ export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
commandBarService.goToDiffIdx(nextDiffIdx);
}
}}
data-tooltip-id="void-tooltip"
data-tooltip-id="orcide-tooltip"
data-tooltip-content={`${downKeybindLabel ? `${downKeybindLabel}` : ''}`}
data-tooltip-delay-show={500}
>
@ -310,7 +310,7 @@ export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
commandBarService.goToURIIdx(prevURIIdx);
}
}}
data-tooltip-id="void-tooltip"
data-tooltip-id="orcide-tooltip"
data-tooltip-content={`${leftKeybindLabel ? `${leftKeybindLabel}` : ''}`}
data-tooltip-delay-show={500}
>
@ -332,7 +332,7 @@ export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
commandBarService.goToURIIdx(nextURIIdx);
}
}}
data-tooltip-id="void-tooltip"
data-tooltip-id="orcide-tooltip"
data-tooltip-content={`${rightKeybindLabel ? `${rightKeybindLabel}` : ''}`}
data-tooltip-delay-show={500}
>
@ -347,7 +347,7 @@ export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
<AcceptAllButtonWrapper
// text={`Accept File${acceptFileKeybindLabel ? ` ${acceptFileKeybindLabel}` : ''}`}
text={`Accept File`}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-content={acceptFileKeybindLabel}
data-tooltip-delay-show={500}
onClick={onAcceptFile}
@ -355,7 +355,7 @@ export const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
<RejectAllButtonWrapper
// text={`Reject File${rejectFileKeybindLabel ? ` ${rejectFileKeybindLabel}` : ''}`}
text={`Reject File`}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-content={rejectFileKeybindLabel}
data-tooltip-delay-show={500}
onClick={onRejectFile}

View file

@ -1,51 +1,51 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { useAccessor, useActiveURI, useIsDark, useSettingsState } from '../util/services.js';
import '../styles.css'
import { VOID_CTRL_K_ACTION_ID, VOID_CTRL_L_ACTION_ID } from '../../../actionIDs.js';
import { ORCIDE_CTRL_K_ACTION_ID, ORCIDE_CTRL_L_ACTION_ID } from '../../../actionIDs.js';
import { Circle, MoreVertical } from 'lucide-react';
import { useEffect, useState } from 'react';
import { VoidSelectionHelperProps } from '../../../../../../contrib/void/browser/voidSelectionHelperWidget.js';
import { VOID_OPEN_SETTINGS_ACTION_ID } from '../../../voidSettingsPane.js';
import { OrcideSelectionHelperProps } from '../../../../../../contrib/orcide/browser/orcideSelectionHelperWidget.js';
import { ORCIDE_OPEN_SETTINGS_ACTION_ID } from '../../../orcideSettingsPane.js';
export const VoidSelectionHelperMain = (props: VoidSelectionHelperProps) => {
export const OrcideSelectionHelperMain = (props: OrcideSelectionHelperProps) => {
const isDark = useIsDark()
return <div
className={`@@void-scope ${isDark ? 'dark' : ''}`}
className={`@@orcide-scope ${isDark ? 'dark' : ''}`}
>
<VoidSelectionHelper {...props} />
<OrcideSelectionHelper {...props} />
</div>
}
const VoidSelectionHelper = ({ rerenderKey }: VoidSelectionHelperProps) => {
const OrcideSelectionHelper = ({ rerenderKey }: OrcideSelectionHelperProps) => {
const accessor = useAccessor()
const keybindingService = accessor.get('IKeybindingService')
const commandService = accessor.get('ICommandService')
const ctrlLKeybind = keybindingService.lookupKeybinding(VOID_CTRL_L_ACTION_ID)
const ctrlKKeybind = keybindingService.lookupKeybinding(VOID_CTRL_K_ACTION_ID)
const ctrlLKeybind = keybindingService.lookupKeybinding(ORCIDE_CTRL_L_ACTION_ID)
const ctrlKKeybind = keybindingService.lookupKeybinding(ORCIDE_CTRL_K_ACTION_ID)
const dividerHTML = <div className='w-[0.5px] bg-void-border-3'></div>
const dividerHTML = <div className='w-[0.5px] bg-orcide-border-3'></div>
const [reactRerenderCount, setReactRerenderKey] = useState(rerenderKey)
const [clickState, setClickState] = useState<'init' | 'clickedOption' | 'clickedMore'>('init')
useEffect(() => {
const disposable = commandService.onWillExecuteCommand(e => {
if (e.commandId === VOID_CTRL_L_ACTION_ID || e.commandId === VOID_CTRL_K_ACTION_ID) {
if (e.commandId === ORCIDE_CTRL_L_ACTION_ID || e.commandId === ORCIDE_CTRL_K_ACTION_ID) {
setClickState('clickedOption')
}
});
@ -79,7 +79,7 @@ const VoidSelectionHelper = ({ rerenderKey }: VoidSelectionHelperProps) => {
cursor-pointer
'
onClick={() => {
commandService.executeCommand(VOID_CTRL_L_ACTION_ID)
commandService.executeCommand(ORCIDE_CTRL_L_ACTION_ID)
setClickState('clickedOption');
}}
>
@ -99,7 +99,7 @@ const VoidSelectionHelper = ({ rerenderKey }: VoidSelectionHelperProps) => {
cursor-pointer
'
onClick={() => {
commandService.executeCommand(VOID_CTRL_K_ACTION_ID)
commandService.executeCommand(ORCIDE_CTRL_K_ACTION_ID)
setClickState('clickedOption');
}}
>
@ -133,7 +133,7 @@ const VoidSelectionHelper = ({ rerenderKey }: VoidSelectionHelperProps) => {
cursor-pointer
'
onClick={() => {
commandService.executeCommand(VOID_OPEN_SETTINGS_ACTION_ID);
commandService.executeCommand(ORCIDE_OPEN_SETTINGS_ACTION_ID);
setClickState('clickedOption');
}}
>
@ -159,7 +159,7 @@ const VoidSelectionHelper = ({ rerenderKey }: VoidSelectionHelperProps) => {
pointer-events-auto select-none
z-[1000]
rounded-sm shadow-md flex flex-nowrap text-nowrap
border border-void-border-3 bg-void-bg-2
border border-orcide-border-3 bg-orcide-bg-2
transition-all duration-200
'>
{clickState === 'init' ? defaultHTML

View file

@ -0,0 +1,11 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { mountFnGenerator } from '../util/mountFnGenerator.js'
import { OrcideCommandBar } from './OrcideCommandBar.js'
import { OrcideSelectionHelperMain } from './OrcideSelectionHelper.js'
export const mountOrcideCommandBar = mountFnGenerator(OrcideCommandBar)
export const mountOrcideSelectionHelper = mountFnGenerator(OrcideSelectionHelperMain)

View file

@ -1,52 +1,70 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { useEffect, useRef, 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 { displayInfoOfProviderName, ProviderName, providerNames, localProviderNames, featureNames, FeatureName, isFeatureNameDisabled } from '../../../../common/orcideSettingsTypes.js';
import { ChatMarkdownRender } from '../markdown/ChatMarkdownRender.js';
import { OllamaSetupInstructions, OneClickSwitchButton, SettingsForProvider, ModelDump } from '../void-settings-tsx/Settings.js';
import { OllamaSetupInstructions, OneClickSwitchButton, SettingsForProvider, ModelDump } from '../orcide-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
export const VoidOnboarding = () => {
export const OrcideOnboarding = () => {
const voidSettingsState = useSettingsState()
const isOnboardingComplete = voidSettingsState.globalSettings.isOnboardingComplete || OVERRIDE_VALUE
const settingsState = useSettingsState()
const accessor = useAccessor()
const orcideSettingsService = accessor.get('IOrcideSettingsService')
// Auto-complete onboarding - Orcide uses pre-configured models via SSO
// No API key setup page needed - models are pre-configured from environment
useEffect(() => {
if (!settingsState.globalSettings.isOnboardingComplete) {
// Auto-configure OrcestAI provider as ready (API key populated from environment/SSO)
orcideSettingsService.setSettingOfProvider('orcestAI', '_didFillInProviderSettings', true)
// Set default model selections to RainyModel
orcideSettingsService.setModelSelectionOfFeature('Chat', { providerName: 'orcestAI', modelName: 'rainymodel/chat' })
orcideSettingsService.setModelSelectionOfFeature('Ctrl+K', { providerName: 'orcestAI', modelName: 'rainymodel/code' })
orcideSettingsService.setModelSelectionOfFeature('Autocomplete', { providerName: 'orcestAI', modelName: 'rainymodel/code' })
orcideSettingsService.setModelSelectionOfFeature('Apply', { providerName: 'orcestAI', modelName: 'rainymodel/chat' })
orcideSettingsService.setModelSelectionOfFeature('SCM', { providerName: 'orcestAI', modelName: 'rainymodel/agent' })
}
}, [])
const isOnboardingComplete = settingsState.globalSettings.isOnboardingComplete || OVERRIDE_VALUE
const isDark = useIsDark()
return (
<div className={`@@void-scope ${isDark ? 'dark' : ''}`}>
<div className={`@@orcide-scope ${isDark ? 'dark' : ''}`}>
<div
className={`
bg-void-bg-3 fixed top-0 right-0 bottom-0 left-0 width-full z-[99999]
bg-orcide-bg-3 fixed top-0 right-0 bottom-0 left-0 width-full z-[99999]
transition-all duration-1000 ${isOnboardingComplete ? 'opacity-0 pointer-events-none' : 'opacity-100 pointer-events-auto'}
`}
style={{ height: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
>
<ErrorBoundary>
<VoidOnboardingContent />
<OrcideOnboardingContent />
</ErrorBoundary>
</div>
</div>
)
}
const VoidIcon = () => {
const OrcideIcon = () => {
const accessor = useAccessor()
const themeService = accessor.get('IThemeService')
const divRef = useRef<HTMLDivElement | null>(null)
useEffect(() => {
// void icon style
// orcide icon style
const updateTheme = () => {
const theme = themeService.getColorTheme().type
const isDark = theme === ColorScheme.DARK || theme === ColorScheme.HIGH_CONTRAST_DARK
@ -61,7 +79,7 @@ const VoidIcon = () => {
return () => d.dispose()
}, [])
return <div ref={divRef} className='@@void-void-icon' />
return <div ref={divRef} className='@@orcide-icon' />
}
const FADE_DURATION_MS = 2000
@ -151,7 +169,7 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP
return (<div className="flex flex-col md:flex-row w-full h-[80vh] gap-6 max-w-[900px] mx-auto relative">
{/* Left Column */}
<div className="md:w-1/4 w-full flex flex-col gap-6 p-6 border-none border-void-border-2 h-full overflow-y-auto">
<div className="md:w-1/4 w-full flex flex-col gap-6 p-6 border-none border-orcide-border-2 h-full overflow-y-auto">
{/* Tab Selector */}
<div className="flex md:flex-col gap-2">
{[...tabNames, 'Cloud/Other'].map(tab => (
@ -159,7 +177,7 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP
key={tab}
className={`py-2 px-4 rounded-md text-left ${currentTab === tab
? 'bg-[#0e70c0]/80 text-white font-medium shadow-sm'
: 'bg-void-bg-2 hover:bg-void-bg-2/80 text-void-fg-1'
: 'bg-orcide-bg-2 hover:bg-orcide-bg-2/80 text-orcide-fg-1'
} transition-all duration-200`}
onClick={() => {
setCurrentTab(tab as TabName);
@ -197,7 +215,7 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP
<div className="w-full max-w-xl mt-4 mb-10">
<div className="text-4xl font-light my-4 w-full">{currentTab}</div>
<div className="text-sm opacity-80 text-void-fg-3 my-4 w-full">{descriptionOfTab[currentTab]}</div>
<div className="text-sm opacity-80 text-orcide-fg-3 my-4 w-full">{descriptionOfTab[currentTab]}</div>
</div>
{providerNamesOfTab[currentTab].map((providerName) => (
@ -206,7 +224,7 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP
Add {displayInfoOfProviderName(providerName).title}
{providerName === 'gemini' && (
<span
data-tooltip-id="void-tooltip-provider-info"
data-tooltip-id="orcide-tooltip-provider-info"
data-tooltip-content="Gemini 2.5 Pro offers 25 free messages a day, and Gemini 2.5 Flash offers 500. We recommend using models down the line as you run out of free credits."
data-tooltip-place="right"
className="ml-1 text-xs align-top text-blue-400"
@ -214,7 +232,7 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP
)}
{providerName === 'openRouter' && (
<span
data-tooltip-id="void-tooltip-provider-info"
data-tooltip-id="orcide-tooltip-provider-info"
data-tooltip-content="OpenRouter offers 50 free messages a day, and 1000 if you deposit $10. Only applies to models labeled ':free'."
data-tooltip-place="right"
className="ml-1 text-xs align-top text-blue-400"
@ -230,13 +248,13 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP
))}
{(currentTab === 'Local' || currentTab === 'Cloud/Other') && (
<div className="w-full max-w-xl mt-8 bg-void-bg-2/50 rounded-lg p-6 border border-void-border-4">
<div className="w-full max-w-xl mt-8 bg-orcide-bg-2/50 rounded-lg p-6 border border-orcide-border-4">
<div className="flex items-center gap-2 mb-4">
<div className="text-xl font-medium">Models</div>
</div>
{currentTab === 'Local' && (
<div className="text-sm opacity-80 text-void-fg-3 my-4 w-full">Local models should be detected automatically. You can add custom models below.</div>
<div className="text-sm opacity-80 text-orcide-fg-3 my-4 w-full">Local models should be detected automatically. You can add custom models below.</div>
)}
{currentTab === 'Local' && <ModelDump filteredProviders={localProviderNames} />}
@ -275,7 +293,7 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP
// OnboardingPage
// title:
// div
// "Welcome to Void"
// "Welcome to Orcide"
// image
// content:<></>
// title
@ -285,7 +303,7 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP
// OnboardingPage
// title:
// div
// "How would you like to use Void?"
// "How would you like to use Orcide?"
// content:
// ModelQuestionContent
// |
@ -328,7 +346,7 @@ const NextButton = ({ onClick, ...props }: { onClick: () => void } & React.Butto
} rounded text-black duration-600 transition-all
`}
{...disabled && {
'data-tooltip-id': 'void-tooltip',
'data-tooltip-id': 'orcide-tooltip',
"data-tooltip-content": 'Please enter all required fields or choose another provider', // (double-click to proceed anyway, can come back in Settings)
"data-tooltip-place": 'top',
}}
@ -343,7 +361,7 @@ const PreviousButton = ({ onClick, ...props }: { onClick: () => void } & React.B
return (
<button
onClick={onClick}
className="px-6 py-2 rounded text-void-fg-3 opacity-80 hover:brightness-115 duration-600 transition-all"
className="px-6 py-2 rounded text-orcide-fg-3 opacity-80 hover:brightness-115 duration-600 transition-all"
{...props}
>
Back
@ -375,7 +393,7 @@ const OllamaDownloadOrRemoveModelButton = ({ modelName, isModelInstalled, sizeGb
href={`https://ollama.com/library/${modelName}`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center text-void-fg-2 hover:text-void-fg-1"
className="flex items-center justify-center text-orcide-fg-2 hover:text-orcide-fg-1"
>
<ExternalLink className="w-3.5 h-3.5" />
</a>
@ -467,14 +485,14 @@ const PrimaryActionButton = ({ children, className, ringSize, ...props }: { chil
type WantToUseOption = 'smart' | 'private' | 'cheap' | 'all'
const VoidOnboardingContent = () => {
const OrcideOnboardingContent = () => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const voidMetricsService = accessor.get('IMetricsService')
const orcideSettingsService = accessor.get('IOrcideSettingsService')
const orcideMetricsService = accessor.get('IMetricsService')
const voidSettingsState = useSettingsState()
const orcideSettingsState = useSettingsState()
const [pageIndex, setPageIndex] = useState(0)
@ -518,9 +536,9 @@ const VoidOnboardingContent = () => {
const selectedProviderName = getSelectedProvider();
const didFillInProviderSettings = selectedProviderName && voidSettingsState.settingsOfProvider[selectedProviderName]._didFillInProviderSettings
const isApiKeyLongEnoughIfApiKeyExists = selectedProviderName && voidSettingsState.settingsOfProvider[selectedProviderName].apiKey ? voidSettingsState.settingsOfProvider[selectedProviderName].apiKey.length > 15 : true
const isAtLeastOneModel = selectedProviderName && voidSettingsState.settingsOfProvider[selectedProviderName].models.length >= 1
const didFillInProviderSettings = selectedProviderName && orcideSettingsState.settingsOfProvider[selectedProviderName]._didFillInProviderSettings
const isApiKeyLongEnoughIfApiKeyExists = selectedProviderName && orcideSettingsState.settingsOfProvider[selectedProviderName].apiKey ? orcideSettingsState.settingsOfProvider[selectedProviderName].apiKey.length > 15 : true
const isAtLeastOneModel = selectedProviderName && orcideSettingsState.settingsOfProvider[selectedProviderName].models.length >= 1
const didFillInSelectedProviderSettings = !!(didFillInProviderSettings && isApiKeyLongEnoughIfApiKeyExists && isAtLeastOneModel)
@ -543,11 +561,11 @@ const VoidOnboardingContent = () => {
/>
<PrimaryActionButton
onClick={() => {
voidSettingsService.setGlobalSetting('isOnboardingComplete', true);
voidMetricsService.capture('Completed Onboarding', { selectedProviderName, wantToUseOption })
orcideSettingsService.setGlobalSetting('isOnboardingComplete', true);
orcideMetricsService.capture('Completed Onboarding', { selectedProviderName, wantToUseOption })
}}
ringSize={voidSettingsState.globalSettings.isOnboardingComplete ? 'screen' : undefined}
>Enter the Void</PrimaryActionButton>
ringSize={orcideSettingsState.globalSettings.isOnboardingComplete ? 'screen' : undefined}
>Enter Orcide</PrimaryActionButton>
</div>
</div>
@ -563,7 +581,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: "",
}
@ -586,23 +604,30 @@ const VoidOnboardingContent = () => {
// reset the page to page 0 if the user redos onboarding
useEffect(() => {
if (!voidSettingsState.globalSettings.isOnboardingComplete) {
if (!orcideSettingsState.globalSettings.isOnboardingComplete) {
setPageIndex(0)
}
}, [setPageIndex, voidSettingsState.globalSettings.isOnboardingComplete])
}, [setPageIndex, orcideSettingsState.globalSettings.isOnboardingComplete])
const contentOfIdx: { [pageIndex: number]: React.ReactNode } = {
0: <OnboardingPageShell
content={
<div className='flex flex-col items-center gap-8'>
<div className="text-5xl font-light text-center">Welcome to Void</div>
{/* Slice of Void image */}
<div className='max-w-md w-full h-[30vh] mx-auto flex items-center justify-center'>
{!isLinux && <VoidIcon />}
<div className="text-5xl font-light text-center">Welcome to Orcide</div>
<div className="text-lg text-orcide-fg-3 text-center max-w-md">
AI-powered Cloud IDE Part of the Orcest AI Ecosystem
</div>
{/* Orcide icon */}
<div className='max-w-md w-full h-[20vh] mx-auto flex items-center justify-center'>
{!isLinux && <OrcideIcon />}
</div>
<div className="text-sm text-orcide-fg-3 text-center max-w-md">
Your IDE is pre-configured with <strong>RainyModel</strong> as the default AI backend.
All models are available through your SSO login.
</div>
<FadeIn
delayMs={1000}
@ -618,19 +643,15 @@ const VoidOnboardingContent = () => {
}
/>,
1: <OnboardingPageShell hasMaxWidth={false}
content={
<AddProvidersPage pageIndex={pageIndex} setPageIndex={setPageIndex} />
}
/>,
2: <OnboardingPageShell
// Skip AddProvidersPage (API key setup) - models are pre-configured via environment
1: <OnboardingPageShell
content={
<div>
<div className="text-5xl font-light text-center">Settings and Themes</div>
<div className="mt-8 text-center flex flex-col items-center gap-4 w-full max-w-md mx-auto">
<h4 className="text-void-fg-3 mb-4">Transfer your settings from an existing editor?</h4>
<h4 className="text-orcide-fg-3 mb-4">Transfer your settings from an existing editor?</h4>
<OneClickSwitchButton className='w-full px-4 py-2' fromEditor="VS Code" />
<OneClickSwitchButton className='w-full px-4 py-2' fromEditor="Cursor" />
<OneClickSwitchButton className='w-full px-4 py-2' fromEditor="Windsurf" />

View file

@ -0,0 +1,9 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { mountFnGenerator } from '../util/mountFnGenerator.js'
import { OrcideOnboarding } from './OrcideOnboarding.js'
export const mountOrcideOnboarding = mountFnGenerator(OrcideOnboarding)

View file

@ -1,16 +1,16 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { FeatureName, featureNames, isFeatureNameDisabled, ModelSelection, modelSelectionsEqual, ProviderName, providerNames, SettingsOfProvider } from '../../../../../../../workbench/contrib/void/common/voidSettingsTypes.js'
import { FeatureName, featureNames, isFeatureNameDisabled, ModelSelection, modelSelectionsEqual, ProviderName, providerNames, SettingsOfProvider } from '../../../../../../../workbench/contrib/orcide/common/orcideSettingsTypes.js'
import { useSettingsState, useRefreshModelState, useAccessor } from '../util/services.js'
import { _VoidSelectBox, VoidCustomDropdownBox } from '../util/inputs.js'
import { _OrcideSelectBox, OrcideCustomDropdownBox } from '../util/inputs.js'
import { SelectBox } from '../../../../../../../base/browser/ui/selectBox/selectBox.js'
import { IconWarning } from '../sidebar-tsx/SidebarChat.js'
import { VOID_OPEN_SETTINGS_ACTION_ID, VOID_TOGGLE_SETTINGS_ACTION_ID } from '../../../voidSettingsPane.js'
import { modelFilterOfFeatureName, ModelOption } from '../../../../../../../workbench/contrib/void/common/voidSettingsService.js'
import { ORCIDE_OPEN_SETTINGS_ACTION_ID, ORCIDE_TOGGLE_SETTINGS_ACTION_ID } from '../../../orcideSettingsPane.js'
import { modelFilterOfFeatureName, ModelOption } from '../../../../../../../workbench/contrib/orcide/common/orcideSettingsService.js'
import { WarningBox } from './WarningBox.js'
import ErrorBoundary from '../sidebar-tsx/ErrorBoundary.js'
@ -24,16 +24,16 @@ const optionsEqual = (m1: ModelOption[], m2: ModelOption[]) => {
const ModelSelectBox = ({ options, featureName, className }: { options: ModelOption[], featureName: FeatureName, className: string }) => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const orcideSettingsService = accessor.get('IOrcideSettingsService')
const selection = voidSettingsService.state.modelSelectionOfFeature[featureName]
const selectedOption = selection ? voidSettingsService.state._modelOptions.find(v => modelSelectionsEqual(v.selection, selection))! : options[0]
const selection = orcideSettingsService.state.modelSelectionOfFeature[featureName]
const selectedOption = selection ? orcideSettingsService.state._modelOptions.find(v => modelSelectionsEqual(v.selection, selection))! : options[0]
const onChangeOption = useCallback((newOption: ModelOption) => {
voidSettingsService.setModelSelectionOfFeature(featureName, newOption.selection)
}, [voidSettingsService, featureName])
orcideSettingsService.setModelSelectionOfFeature(featureName, newOption.selection)
}, [orcideSettingsService, featureName])
return <VoidCustomDropdownBox
return <OrcideCustomDropdownBox
options={options}
selectedOption={selectedOption}
onChangeOption={onChangeOption}
@ -78,7 +78,7 @@ export const ModelDropdown = ({ featureName, className }: { featureName: Feature
const accessor = useAccessor()
const commandService = accessor.get('ICommandService')
const openSettings = () => { commandService.executeCommand(VOID_OPEN_SETTINGS_ACTION_ID); };
const openSettings = () => { commandService.executeCommand(ORCIDE_OPEN_SETTINGS_ACTION_ID); };
const { emptyMessage } = modelFilterOfFeatureName[featureName]

View file

@ -1,12 +1,12 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import React, { useCallback, useEffect, useMemo, useState, useRef } from 'react'; // Added useRef import just in case it was missed, though likely already present
import { ProviderName, SettingName, displayInfoOfSettingName, providerNames, VoidStatefulModelInfo, customSettingNamesOfProvider, RefreshableProviderName, refreshableProviderNames, displayInfoOfProviderName, nonlocalProviderNames, localProviderNames, GlobalSettingName, featureNames, displayInfoOfFeatureName, isProviderNameDisabled, FeatureName, hasDownloadButtonsOnModelsProviderNames, subTextMdOfProviderName } from '../../../../common/voidSettingsTypes.js'
import { ProviderName, SettingName, displayInfoOfSettingName, providerNames, OrcideStatefulModelInfo, customSettingNamesOfProvider, RefreshableProviderName, refreshableProviderNames, displayInfoOfProviderName, nonlocalProviderNames, localProviderNames, GlobalSettingName, featureNames, displayInfoOfFeatureName, isProviderNameDisabled, FeatureName, hasDownloadButtonsOnModelsProviderNames, subTextMdOfProviderName } from '../../../../common/orcideSettingsTypes.js'
import ErrorBoundary from '../sidebar-tsx/ErrorBoundary.js'
import { VoidButtonBgDarken, VoidCustomDropdownBox, VoidInputBox2, VoidSimpleInputBox, VoidSwitch } from '../util/inputs.js'
import { OrcideButtonBgDarken, OrcideCustomDropdownBox, OrcideInputBox2, OrcideSimpleInputBox, OrcideSwitch } from '../util/inputs.js'
import { useAccessor, useIsDark, useIsOptedOut, useRefreshModelListener, useRefreshModelState, useSettingsState } from '../util/services.js'
import { X, RefreshCw, Loader2, Check, Asterisk, Plus } from 'lucide-react'
import { URI } from '../../../../../../../base/common/uri.js'
@ -36,7 +36,7 @@ type Tab =
const ButtonLeftTextRightOption = ({ text, leftButton }: { text: string, leftButton?: React.ReactNode }) => {
return <div className='flex items-center text-void-fg-3 px-3 py-0.5 rounded-sm overflow-hidden gap-2'>
return <div className='flex items-center text-orcide-fg-3 px-3 py-0.5 rounded-sm overflow-hidden gap-2'>
{leftButton ? leftButton : null}
<span>
{text}
@ -184,7 +184,7 @@ const ConfirmButton = ({ children, onConfirm, className }: { children: React.Rea
}, [confirm]);
return (
<div ref={ref} className={`inline-block`}>
<VoidButtonBgDarken className={className} onClick={() => {
<OrcideButtonBgDarken className={className} onClick={() => {
if (!confirm) {
setConfirm(true);
} else {
@ -193,7 +193,7 @@ const ConfirmButton = ({ children, onConfirm, className }: { children: React.Rea
}
}}>
{confirm ? `Confirm Reset` : children}
</VoidButtonBgDarken>
</OrcideButtonBgDarken>
</div>
);
};
@ -220,7 +220,7 @@ const SimpleModelSettingsDialog = ({
const accessor = useAccessor()
const settingsState = useSettingsState()
const mouseDownInsideModal = useRef(false); // Ref to track mousedown origin
const settingsStateService = accessor.get('IVoidSettingsService')
const settingsStateService = accessor.get('IOrcideSettingsService')
// current overrides and defaults
const defaultModelCapabilities = getModelCapabilities(providerName, modelName, undefined);
@ -283,7 +283,7 @@ const SimpleModelSettingsDialog = ({
onClose();
};
const sourcecodeOverridesLink = `https://github.com/voideditor/void/blob/2e5ecb291d33afbe4565921664fb7e183189c1c5/src/vs/workbench/contrib/void/common/modelCapabilities.ts#L146-L172`
const sourcecodeOverridesLink = `https://github.com/orcest-ai/Orcide/blob/2e5ecb291d33afbe4565921664fb7e183189c1c5/src/vs/workbench/contrib/orcide/common/modelCapabilities.ts#L146-L172`
return (
<div // Backdrop
@ -300,7 +300,7 @@ const SimpleModelSettingsDialog = ({
>
{/* MODAL */}
<div
className="bg-void-bg-1 rounded-md p-4 max-w-xl w-full shadow-xl overflow-y-auto max-h-[90vh]"
className="bg-orcide-bg-1 rounded-md p-4 max-w-xl w-full shadow-xl overflow-y-auto max-h-[90vh]"
onClick={(e) => e.stopPropagation()} // Keep stopping propagation for normal clicks inside
onMouseDown={(e) => {
mouseDownInsideModal.current = true;
@ -313,36 +313,36 @@ const SimpleModelSettingsDialog = ({
</h3>
<button
onClick={onClose}
className="text-void-fg-3 hover:text-void-fg-1"
className="text-orcide-fg-3 hover:text-orcide-fg-1"
>
<X className="size-5" />
</button>
</div>
{/* Display model recognition status */}
<div className="text-sm text-void-fg-3 mb-4">
{type === 'default' ? `${modelName} comes packaged with Void, so you shouldn't need to change these settings.`
<div className="text-sm text-orcide-fg-3 mb-4">
{type === 'default' ? `${modelName} comes packaged with Orcide, so you shouldn't need to change these settings.`
: isUnrecognizedModel
? `Model not recognized by Void.`
: `Void recognizes ${modelName} ("${recognizedModelName}").`}
? `Model not recognized by Orcide.`
: `Orcide recognizes ${modelName} ("${recognizedModelName}").`}
</div>
{/* override toggle */}
<div className="flex items-center gap-2 mb-4">
<VoidSwitch size='xs' value={overrideEnabled} onChange={setOverrideEnabled} />
<span className="text-void-fg-3 text-sm">Override model defaults</span>
<OrcideSwitch size='xs' value={overrideEnabled} onChange={setOverrideEnabled} />
<span className="text-orcide-fg-3 text-sm">Override model defaults</span>
</div>
{/* Informational link */}
{overrideEnabled && <div className="text-sm text-void-fg-3 mb-4">
{overrideEnabled && <div className="text-sm text-orcide-fg-3 mb-4">
<ChatMarkdownRender string={`See the [sourcecode](${sourcecodeOverridesLink}) for a reference on how to set this JSON (advanced).`} chatMessageLocation={undefined} />
</div>}
<textarea
key={overrideEnabled + ''}
ref={textAreaRef}
className={`w-full min-h-[200px] p-2 rounded-sm border border-void-border-2 bg-void-bg-2 resize-none font-mono text-sm ${!overrideEnabled ? 'text-void-fg-3' : ''}`}
className={`w-full min-h-[200px] p-2 rounded-sm border border-orcide-border-2 bg-orcide-bg-2 resize-none font-mono text-sm ${!overrideEnabled ? 'text-orcide-fg-3' : ''}`}
defaultValue={overrideEnabled && currentOverrides ? JSON.stringify(currentOverrides, null, 2) : placeholder}
placeholder={placeholder}
readOnly={!overrideEnabled}
@ -353,15 +353,15 @@ const SimpleModelSettingsDialog = ({
<div className="flex justify-end gap-2 mt-4">
<VoidButtonBgDarken onClick={onClose} className="px-3 py-1">
<OrcideButtonBgDarken onClick={onClose} className="px-3 py-1">
Cancel
</VoidButtonBgDarken>
<VoidButtonBgDarken
</OrcideButtonBgDarken>
<OrcideButtonBgDarken
onClick={onSave}
className="px-3 py-1 bg-[#0e70c0] text-white"
>
Save
</VoidButtonBgDarken>
</OrcideButtonBgDarken>
</div>
</div>
</div>
@ -373,7 +373,7 @@ const SimpleModelSettingsDialog = ({
export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderName[] }) => {
const accessor = useAccessor()
const settingsStateService = accessor.get('IVoidSettingsService')
const settingsStateService = accessor.get('IOrcideSettingsService')
const settingsState = useSettingsState()
// State to track which model's settings dialog is open
@ -391,7 +391,7 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN
const [errorString, setErrorString] = useState('');
// a dump of all the enabled providers' models
const modelDump: (VoidStatefulModelInfo & { providerName: ProviderName, providerEnabled: boolean })[] = []
const modelDump: (OrcideStatefulModelInfo & { providerName: ProviderName, providerEnabled: boolean })[] = []
// Use either filtered providers or all providers
const providersToShow = filteredProviders || providerNames;
@ -454,9 +454,9 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN
const detailAboutModel = type === 'autodetected' ?
<Asterisk size={14} className="inline-block align-text-top brightness-115 stroke-[2] text-[#0e70c0]" data-tooltip-id='void-tooltip' data-tooltip-place='right' data-tooltip-content='Detected locally' />
<Asterisk size={14} className="inline-block align-text-top brightness-115 stroke-[2] text-[#0e70c0]" data-tooltip-id='orcide-tooltip' data-tooltip-place='right' data-tooltip-content='Detected locally' />
: type === 'custom' ?
<Asterisk size={14} className="inline-block align-text-top brightness-115 stroke-[2] text-[#0e70c0]" data-tooltip-id='void-tooltip' data-tooltip-place='right' data-tooltip-content='Custom model' />
<Asterisk size={14} className="inline-block align-text-top brightness-115 stroke-[2] text-[#0e70c0]" data-tooltip-id='orcide-tooltip' data-tooltip-place='right' data-tooltip-content='Custom model' />
: undefined
const hasOverrides = !!settingsState.overridesOfModel?.[providerName]?.[modelName]
@ -479,12 +479,12 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN
<div className="w-5 flex items-center justify-center">
<button
onClick={() => { setOpenSettingsModel({ modelName, providerName, type }) }}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='right'
data-tooltip-content='Advanced Settings'
className={`${hasOverrides ? '' : 'opacity-0 group-hover:opacity-100'} transition-opacity`}
>
<Plus size={12} className="text-void-fg-3 opacity-50" />
<Plus size={12} className="text-orcide-fg-3 opacity-50" />
</button>
</div>
)}
@ -494,13 +494,13 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN
{/* Switch */}
<VoidSwitch
<OrcideSwitch
value={value}
onChange={() => { settingsStateService.toggleModelHidden(providerName, modelName); }}
disabled={disabled}
size='sm'
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='right'
data-tooltip-content={tooltipName}
/>
@ -509,12 +509,12 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN
<div className={`w-5 flex items-center justify-center`}>
{type === 'default' || type === 'autodetected' ? null : <button
onClick={() => { settingsStateService.deleteModel(providerName, modelName); }}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='right'
data-tooltip-content='Delete'
className={`${hasOverrides ? '' : 'opacity-0 group-hover:opacity-100'} transition-opacity`}
>
<X size={12} className="text-void-fg-3 opacity-50" />
<X size={12} className="text-orcide-fg-3 opacity-50" />
</button>}
</div>
</div>
@ -532,21 +532,21 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN
{/* Provider dropdown */}
<ErrorBoundary>
<VoidCustomDropdownBox
<OrcideCustomDropdownBox
options={providersToShow}
selectedOption={userChosenProviderName}
onChangeOption={(pn) => setUserChosenProviderName(pn)}
getOptionDisplayName={(pn) => pn ? displayInfoOfProviderName(pn).title : 'Provider Name'}
getOptionDropdownName={(pn) => pn ? displayInfoOfProviderName(pn).title : 'Provider Name'}
getOptionsEqual={(a, b) => a === b}
className="max-w-32 mx-2 w-full resize-none bg-void-bg-1 text-void-fg-1 placeholder:text-void-fg-3 border border-void-border-2 focus:border-void-border-1 py-1 px-2 rounded"
className="max-w-32 mx-2 w-full resize-none bg-orcide-bg-1 text-orcide-fg-1 placeholder:text-orcide-fg-3 border border-orcide-border-2 focus:border-orcide-border-1 py-1 px-2 rounded"
arrowTouchesText={false}
/>
</ErrorBoundary>
{/* Model name input */}
<ErrorBoundary>
<VoidSimpleInputBox
<OrcideSimpleInputBox
value={modelName}
compact={true}
onChangeValue={setModelName}
@ -573,7 +573,7 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN
setModelName('');
setUserChosenProviderName(null);
}}
className='text-void-fg-4'
className='text-orcide-fg-4'
>
<X className='size-4' />
</button>
@ -587,7 +587,7 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN
</div>
) : (
<div
className="text-void-fg-4 flex flex-nowrap text-nowrap items-center hover:brightness-110 cursor-pointer mt-4"
className="text-orcide-fg-4 flex flex-nowrap text-nowrap items-center hover:brightness-110 cursor-pointer mt-4"
onClick={() => setIsAddModelOpen(true)}
>
<div className="flex items-center gap-1">
@ -615,7 +615,7 @@ const ProviderSetting = ({ providerName, settingName, subTextMd }: { providerNam
const { title: settingTitle, placeholder, isPasswordField } = displayInfoOfSettingName(providerName, settingName)
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const orcideSettingsService = accessor.get('IOrcideSettingsService')
const settingsState = useSettingsState()
const settingValue = settingsState.settingsOfProvider[providerName][settingName] as string // this should always be a string in this component
@ -626,12 +626,12 @@ const ProviderSetting = ({ providerName, settingName, subTextMd }: { providerNam
// Create a stable callback reference using useCallback with proper dependencies
const handleChangeValue = useCallback((newVal: string) => {
voidSettingsService.setSettingOfProvider(providerName, settingName, newVal)
}, [voidSettingsService, providerName, settingName]);
orcideSettingsService.setSettingOfProvider(providerName, settingName, newVal)
}, [orcideSettingsService, providerName, settingName]);
return <ErrorBoundary>
<div className='my-1'>
<VoidSimpleInputBox
<OrcideSimpleInputBox
value={settingValue}
onChangeValue={handleChangeValue}
placeholder={`${settingTitle} (${placeholder})`}
@ -646,14 +646,14 @@ const ProviderSetting = ({ providerName, settingName, subTextMd }: { providerNam
}
// const OldSettingsForProvider = ({ providerName, showProviderTitle }: { providerName: ProviderName, showProviderTitle: boolean }) => {
// const voidSettingsState = useSettingsState()
// const orcideSettingsState = useSettingsState()
// const needsModel = isProviderNameDisabled(providerName, voidSettingsState) === 'addModel'
// const needsModel = isProviderNameDisabled(providerName, orcideSettingsState) === 'addModel'
// // const accessor = useAccessor()
// // const voidSettingsService = accessor.get('IVoidSettingsService')
// // const orcideSettingsService = accessor.get('IOrcideSettingsService')
// // const { enabled } = voidSettingsState.settingsOfProvider[providerName]
// // const { enabled } = orcideSettingsState.settingsOfProvider[providerName]
// const settingNames = customSettingNamesOfProvider(providerName)
// const { title: providerTitle } = displayInfoOfProviderName(providerName)
@ -664,13 +664,13 @@ const ProviderSetting = ({ providerName, settingName, subTextMd }: { providerNam
// {showProviderTitle && <h3 className='text-xl truncate'>{providerTitle}</h3>}
// {/* enable provider switch */}
// {/* <VoidSwitch
// {/* <OrcideSwitch
// value={!!enabled}
// onChange={
// useCallback(() => {
// const enabledRef = voidSettingsService.state.settingsOfProvider[providerName].enabled
// voidSettingsService.setSettingOfProvider(providerName, 'enabled', !enabledRef)
// }, [voidSettingsService, providerName])}
// const enabledRef = orcideSettingsService.state.settingsOfProvider[providerName].enabled
// orcideSettingsService.setSettingOfProvider(providerName, 'enabled', !enabledRef)
// }, [orcideSettingsService, providerName])}
// size='sm+'
// /> */}
// </div>
@ -692,14 +692,14 @@ const ProviderSetting = ({ providerName, settingName, subTextMd }: { providerNam
export const SettingsForProvider = ({ providerName, showProviderTitle, showProviderSuggestions }: { providerName: ProviderName, showProviderTitle: boolean, showProviderSuggestions: boolean }) => {
const voidSettingsState = useSettingsState()
const orcideSettingsState = useSettingsState()
const needsModel = isProviderNameDisabled(providerName, voidSettingsState) === 'addModel'
const needsModel = isProviderNameDisabled(providerName, orcideSettingsState) === 'addModel'
// const accessor = useAccessor()
// const voidSettingsService = accessor.get('IVoidSettingsService')
// const orcideSettingsService = accessor.get('IOrcideSettingsService')
// const { enabled } = voidSettingsState.settingsOfProvider[providerName]
// const { enabled } = orcideSettingsState.settingsOfProvider[providerName]
const settingNames = customSettingNamesOfProvider(providerName)
const { title: providerTitle } = displayInfoOfProviderName(providerName)
@ -710,13 +710,13 @@ export const SettingsForProvider = ({ providerName, showProviderTitle, showProvi
{showProviderTitle && <h3 className='text-xl truncate'>{providerTitle}</h3>}
{/* enable provider switch */}
{/* <VoidSwitch
{/* <OrcideSwitch
value={!!enabled}
onChange={
useCallback(() => {
const enabledRef = voidSettingsService.state.settingsOfProvider[providerName].enabled
voidSettingsService.setSettingOfProvider(providerName, 'enabled', !enabledRef)
}, [voidSettingsService, providerName])}
const enabledRef = orcideSettingsService.state.settingsOfProvider[providerName].enabled
orcideSettingsService.setSettingOfProvider(providerName, 'enabled', !enabledRef)
}, [orcideSettingsService, providerName])}
size='sm+'
/> */}
</div>
@ -744,7 +744,7 @@ export const SettingsForProvider = ({ providerName, showProviderTitle, showProvi
}
export const VoidProviderSettings = ({ providerNames }: { providerNames: ProviderName[] }) => {
export const OrcideProviderSettings = ({ providerNames }: { providerNames: ProviderName[] }) => {
return <>
{providerNames.map(providerName =>
<SettingsForProvider key={providerName} providerName={providerName} showProviderTitle={true} showProviderSuggestions={true} />
@ -758,20 +758,20 @@ export const AutoDetectLocalModelsToggle = () => {
const settingName: GlobalSettingName = 'autoRefreshModels'
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const orcideSettingsService = accessor.get('IOrcideSettingsService')
const metricsService = accessor.get('IMetricsService')
const voidSettingsState = useSettingsState()
const orcideSettingsState = useSettingsState()
// right now this is just `enabled_autoRefreshModels`
const enabled = voidSettingsState.globalSettings[settingName]
const enabled = orcideSettingsState.globalSettings[settingName]
return <ButtonLeftTextRightOption
leftButton={<VoidSwitch
leftButton={<OrcideSwitch
size='xxs'
value={enabled}
onChange={(newVal) => {
voidSettingsService.setGlobalSetting(settingName, newVal)
orcideSettingsService.setGlobalSetting(settingName, newVal)
metricsService.capture('Click', { action: 'Autorefresh Toggle', settingName, enabled: newVal })
}}
/>}
@ -783,33 +783,33 @@ export const AutoDetectLocalModelsToggle = () => {
export const AIInstructionsBox = () => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const voidSettingsState = useSettingsState()
return <VoidInputBox2
const orcideSettingsService = accessor.get('IOrcideSettingsService')
const orcideSettingsState = useSettingsState()
return <OrcideInputBox2
className='min-h-[81px] p-3 rounded-sm'
initValue={voidSettingsState.globalSettings.aiInstructions}
initValue={orcideSettingsState.globalSettings.aiInstructions}
placeholder={`Do not change my indentation or delete my comments. When writing TS or JS, do not add ;'s. Write new code using Rust if possible. `}
multiline
onChangeText={(newText) => {
voidSettingsService.setGlobalSetting('aiInstructions', newText)
orcideSettingsService.setGlobalSetting('aiInstructions', newText)
}}
/>
}
const FastApplyMethodDropdown = () => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const orcideSettingsService = accessor.get('IOrcideSettingsService')
const options = useMemo(() => [true, false], [])
const onChangeOption = useCallback((newVal: boolean) => {
voidSettingsService.setGlobalSetting('enableFastApply', newVal)
}, [voidSettingsService])
orcideSettingsService.setGlobalSetting('enableFastApply', newVal)
}, [orcideSettingsService])
return <VoidCustomDropdownBox
className='text-xs text-void-fg-3 bg-void-bg-1 border border-void-border-1 rounded p-0.5 px-1'
return <OrcideCustomDropdownBox
className='text-xs text-orcide-fg-3 bg-orcide-bg-1 border border-orcide-border-1 rounded p-0.5 px-1'
options={options}
selectedOption={voidSettingsService.state.globalSettings.enableFastApply}
selectedOption={orcideSettingsService.state.globalSettings.enableFastApply}
onChangeOption={onChangeOption}
getOptionDisplayName={(val) => val ? 'Fast Apply' : 'Slow Apply'}
getOptionDropdownName={(val) => val ? 'Fast Apply' : 'Slow Apply'}
@ -821,27 +821,27 @@ const FastApplyMethodDropdown = () => {
export const OllamaSetupInstructions = ({ sayWeAutoDetect }: { sayWeAutoDetect?: boolean }) => {
return <div className='prose-p:my-0 prose-ol:list-decimal prose-p:py-0 prose-ol:my-0 prose-ol:py-0 prose-span:my-0 prose-span:py-0 text-void-fg-3 text-sm list-decimal select-text'>
return <div className='prose-p:my-0 prose-ol:list-decimal prose-p:py-0 prose-ol:my-0 prose-ol:py-0 prose-span:my-0 prose-span:py-0 text-orcide-fg-3 text-sm list-decimal select-text'>
<div className=''><ChatMarkdownRender string={`Ollama Setup Instructions`} chatMessageLocation={undefined} /></div>
<div className=' pl-6'><ChatMarkdownRender string={`1. Download [Ollama](https://ollama.com/download).`} chatMessageLocation={undefined} /></div>
<div className=' pl-6'><ChatMarkdownRender string={`2. Open your terminal.`} chatMessageLocation={undefined} /></div>
<div
className='pl-6 flex items-center w-fit'
data-tooltip-id='void-tooltip-ollama-settings'
data-tooltip-id='orcide-tooltip-ollama-settings'
>
<ChatMarkdownRender string={`3. Run \`ollama pull your_model\` to install a model.`} chatMessageLocation={undefined} />
</div>
{sayWeAutoDetect && <div className=' pl-6'><ChatMarkdownRender string={`Void automatically detects locally running models and enables them.`} chatMessageLocation={undefined} /></div>}
{sayWeAutoDetect && <div className=' pl-6'><ChatMarkdownRender string={`Orcide automatically detects locally running models and enables them.`} chatMessageLocation={undefined} /></div>}
</div>
}
const RedoOnboardingButton = ({ className }: { className?: string }) => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const orcideSettingsService = accessor.get('IOrcideSettingsService')
return <div
className={`text-void-fg-4 flex flex-nowrap text-nowrap items-center hover:brightness-110 cursor-pointer ${className}`}
onClick={() => { voidSettingsService.setGlobalSetting('isOnboardingComplete', false) }}
className={`text-orcide-fg-4 flex flex-nowrap text-nowrap items-center hover:brightness-110 cursor-pointer ${className}`}
onClick={() => { orcideSettingsService.setGlobalSetting('isOnboardingComplete', false) }}
>
See onboarding screen?
</div>
@ -856,25 +856,25 @@ const RedoOnboardingButton = ({ className }: { className?: string }) => {
export const ToolApprovalTypeSwitch = ({ approvalType, size, desc }: { approvalType: ToolApprovalType, size: "xxs" | "xs" | "sm" | "sm+" | "md", desc: string }) => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const voidSettingsState = useSettingsState()
const orcideSettingsService = accessor.get('IOrcideSettingsService')
const orcideSettingsState = useSettingsState()
const metricsService = accessor.get('IMetricsService')
const onToggleAutoApprove = useCallback((approvalType: ToolApprovalType, newValue: boolean) => {
voidSettingsService.setGlobalSetting('autoApprove', {
...voidSettingsService.state.globalSettings.autoApprove,
orcideSettingsService.setGlobalSetting('autoApprove', {
...orcideSettingsService.state.globalSettings.autoApprove,
[approvalType]: newValue
})
metricsService.capture('Tool Auto-Accept Toggle', { enabled: newValue })
}, [voidSettingsService, metricsService])
}, [orcideSettingsService, metricsService])
return <>
<VoidSwitch
<OrcideSwitch
size={size}
value={voidSettingsState.globalSettings.autoApprove[approvalType] ?? false}
value={orcideSettingsState.globalSettings.autoApprove[approvalType] ?? false}
onChange={(newVal) => onToggleAutoApprove(approvalType, newVal)}
/>
<span className="text-void-fg-3 text-xs">{desc}</span>
<span className="text-orcide-fg-3 text-xs">{desc}</span>
</>
}
@ -907,13 +907,13 @@ export const OneClickSwitchButton = ({ fromEditor = 'VS Code', className = '' }:
}
return <>
<VoidButtonBgDarken className={`max-w-48 p-4 ${className}`} disabled={transferState.type !== 'done'} onClick={onClick}>
<OrcideButtonBgDarken className={`max-w-48 p-4 ${className}`} disabled={transferState.type !== 'done'} onClick={onClick}>
{transferState.type === 'done' ? `Transfer from ${fromEditor}`
: transferState.type === 'loading' ? <span className='text-nowrap flex flex-nowrap'>Transferring<IconLoading /></span>
: transferState.type === 'justfinished' ? <AnimatedCheckmarkButton text='Settings Transferred' className='bg-none' />
: null
}
</VoidButtonBgDarken>
</OrcideButtonBgDarken>
{transferState.type === 'done' && transferState.error ? <WarningBox text={transferState.error} /> : null}
</>
}
@ -926,13 +926,13 @@ const MCPServerComponent = ({ name, server }: { name: string, server: MCPServer
const accessor = useAccessor();
const mcpService = accessor.get('IMCPService');
const voidSettings = useSettingsState()
const isOn = voidSettings.mcpUserStateOfName[name]?.isOn
const orcideSettings = useSettingsState()
const isOn = orcideSettings.mcpUserStateOfName[name]?.isOn
const removeUniquePrefix = (name: string) => name.split('_').slice(1).join('_')
return (
<div className="border border-void-border-2 bg-void-bg-1 py-3 px-4 rounded-sm my-2">
<div className="border border-orcide-border-2 bg-orcide-bg-1 py-3 px-4 rounded-sm my-2">
<div className="flex items-center justify-between">
{/* Left side - status and name */}
<div className="flex items-center gap-2">
@ -941,16 +941,16 @@ const MCPServerComponent = ({ name, server }: { name: string, server: MCPServer
${server.status === 'success' ? 'bg-green-500'
: server.status === 'error' ? 'bg-red-500'
: server.status === 'loading' ? 'bg-yellow-500'
: server.status === 'offline' ? 'bg-void-fg-3'
: server.status === 'offline' ? 'bg-orcide-fg-3'
: ''}
`}></div>
{/* Server name */}
<div className="text-sm font-medium text-void-fg-1">{name}</div>
<div className="text-sm font-medium text-orcide-fg-1">{name}</div>
</div>
{/* Right side - power toggle switch */}
<VoidSwitch
<OrcideSwitch
value={isOn ?? false}
size='xs'
disabled={server.status === 'error'}
@ -966,17 +966,17 @@ const MCPServerComponent = ({ name, server }: { name: string, server: MCPServer
(server.tools ?? []).map((tool: { name: string; description?: string }) => (
<span
key={tool.name}
className="px-2 py-0.5 bg-void-bg-2 text-void-fg-3 rounded-sm text-xs"
className="px-2 py-0.5 bg-orcide-bg-2 text-orcide-fg-3 rounded-sm text-xs"
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-content={tool.description || ''}
data-tooltip-class-name='void-max-w-[300px]'
data-tooltip-class-name='orcide-max-w-[300px]'
>
{removeUniquePrefix(tool.name)}
</span>
))
) : (
<span className="text-xs text-void-fg-3">No tools available</span>
<span className="text-xs text-orcide-fg-3">No tools available</span>
)}
</div>
</div>
@ -985,8 +985,8 @@ const MCPServerComponent = ({ name, server }: { name: string, server: MCPServer
{/* Command badge */}
{isOn && server.command && (
<div className="mt-3">
<div className="text-xs text-void-fg-3 mb-1">Command:</div>
<div className="px-2 py-1 bg-void-bg-2 text-xs font-mono overflow-x-auto whitespace-nowrap text-void-fg-2 rounded-sm">
<div className="text-xs text-orcide-fg-3 mb-1">Command:</div>
<div className="px-2 py-1 bg-orcide-bg-2 text-xs font-mono overflow-x-auto whitespace-nowrap text-orcide-fg-2 rounded-sm">
{server.command}
</div>
</div>
@ -1008,14 +1008,14 @@ const MCPServersList = () => {
let content: React.ReactNode
if (mcpServiceState.error) {
content = <div className="text-void-fg-3 text-sm mt-2">
content = <div className="text-orcide-fg-3 text-sm mt-2">
{mcpServiceState.error}
</div>
}
else {
const entries = Object.entries(mcpServiceState.mcpServerOfName)
if (entries.length === 0) {
content = <div className="text-void-fg-3 text-sm mt-2">
content = <div className="text-orcide-fg-3 text-sm mt-2">
No servers found
</div>
}
@ -1050,7 +1050,7 @@ export const Settings = () => {
const environmentService = accessor.get('IEnvironmentService')
const nativeHostService = accessor.get('INativeHostService')
const settingsState = useSettingsState()
const voidSettingsService = accessor.get('IVoidSettingsService')
const orcideSettingsService = accessor.get('IOrcideSettingsService')
const chatThreadsService = accessor.get('IChatThreadService')
const notificationService = accessor.get('INotificationService')
const mcpService = accessor.get('IMCPService')
@ -1064,12 +1064,12 @@ export const Settings = () => {
if (t === 'Chats') {
// Export chat threads
dataStr = JSON.stringify(chatThreadsService.state, null, 2)
downloadName = 'void-chats.json'
downloadName = 'orcide-chats.json'
}
else if (t === 'Settings') {
// Export user settings
dataStr = JSON.stringify(voidSettingsService.state, null, 2)
downloadName = 'void-settings.json'
dataStr = JSON.stringify(orcideSettingsService.state, null, 2)
downloadName = 'orcide-settings.json'
}
else {
dataStr = ''
@ -1107,7 +1107,7 @@ export const Settings = () => {
chatThreadsService.dangerousSetState(json as any)
}
else if (t === 'Settings') {
voidSettingsService.dangerousSetState(json as any)
orcideSettingsService.dangerousSetState(json as any)
}
notificationService.info(`${t} imported successfully!`)
@ -1123,7 +1123,7 @@ export const Settings = () => {
return (
<div className={`@@void-scope ${isDark ? 'dark' : ''}`} style={{ height: '100%', width: '100%', overflow: 'auto' }}>
<div className={`@@orcide-scope ${isDark ? 'dark' : ''}`} style={{ height: '100%', width: '100%', overflow: 'auto' }}>
<div className="flex flex-col md:flex-row w-full gap-6 max-w-[900px] mx-auto mb-32" style={{ minHeight: '80vh' }}>
{/* ────────────── SIDEBAR ────────────── */}
@ -1145,7 +1145,7 @@ export const Settings = () => {
py-2 px-4 rounded-md text-left transition-all duration-200
${selectedSection === tab
? 'bg-[#0e70c0]/80 text-white font-medium shadow-sm'
: 'bg-void-bg-2 hover:bg-void-bg-2/80 text-void-fg-1'}
: 'bg-orcide-bg-2 hover:bg-orcide-bg-2/80 text-orcide-fg-1'}
`}
>
{label}
@ -1161,7 +1161,7 @@ export const Settings = () => {
<div className='max-w-3xl'>
<h1 className='text-2xl w-full'>{`Void's Settings`}</h1>
<h1 className='text-2xl w-full'>{`Orcide's Settings`}</h1>
<div className='w-full h-[1px] my-2' />
@ -1189,13 +1189,13 @@ export const Settings = () => {
<div className={shouldShowTab('localProviders') ? `` : 'hidden'}>
<ErrorBoundary>
<h2 className={`text-3xl mb-2`}>Local Providers</h2>
<h3 className={`text-void-fg-3 mb-2`}>{`Void can access any model that you host locally. We automatically detect your local models by default.`}</h3>
<h3 className={`text-orcide-fg-3 mb-2`}>{`Orcide can access any model that you host locally. We automatically detect your local models by default.`}</h3>
<div className='opacity-80 mb-4'>
<OllamaSetupInstructions sayWeAutoDetect={true} />
</div>
<VoidProviderSettings providerNames={localProviderNames} />
<OrcideProviderSettings providerNames={localProviderNames} />
</ErrorBoundary>
</div>
@ -1203,9 +1203,9 @@ export const Settings = () => {
<div className={shouldShowTab('providers') ? `` : 'hidden'}>
<ErrorBoundary>
<h2 className={`text-3xl mb-2`}>Main Providers</h2>
<h3 className={`text-void-fg-3 mb-2`}>{`Void can access models from Anthropic, OpenAI, OpenRouter, and more.`}</h3>
<h3 className={`text-orcide-fg-3 mb-2`}>{`Orcide can access models from Anthropic, OpenAI, OpenRouter, and more.`}</h3>
<VoidProviderSettings providerNames={nonlocalProviderNames} />
<OrcideProviderSettings providerNames={nonlocalProviderNames} />
</ErrorBoundary>
</div>
@ -1219,15 +1219,15 @@ export const Settings = () => {
{/* FIM */}
<div>
<h4 className={`text-base`}>{displayInfoOfFeatureName('Autocomplete')}</h4>
<div className='text-sm text-void-fg-3 mt-1'>
<div className='text-sm text-orcide-fg-3 mt-1'>
<span>
Experimental.{' '}
</span>
<span
className='hover:brightness-110'
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-content='We recommend using the largest qwen2.5-coder model you can with Ollama (try qwen2.5-coder:3b).'
data-tooltip-class-name='void-max-w-[20px]'
data-tooltip-class-name='orcide-max-w-[20px]'
>
Only works with FIM models.*
</span>
@ -1237,19 +1237,19 @@ export const Settings = () => {
{/* Enable Switch */}
<ErrorBoundary>
<div className='flex items-center gap-x-2 my-2'>
<VoidSwitch
<OrcideSwitch
size='xs'
value={settingsState.globalSettings.enableAutocomplete}
onChange={(newVal) => voidSettingsService.setGlobalSetting('enableAutocomplete', newVal)}
onChange={(newVal) => orcideSettingsService.setGlobalSetting('enableAutocomplete', newVal)}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.enableAutocomplete ? 'Enabled' : 'Disabled'}</span>
<span className='text-orcide-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.enableAutocomplete ? 'Enabled' : 'Disabled'}</span>
</div>
</ErrorBoundary>
{/* Model Dropdown */}
<ErrorBoundary>
<div className={`my-2 ${!settingsState.globalSettings.enableAutocomplete ? 'hidden' : ''}`}>
<ModelDropdown featureName={'Autocomplete'} className='text-xs text-void-fg-3 bg-void-bg-1 border border-void-border-1 rounded p-0.5 px-1' />
<ModelDropdown featureName={'Autocomplete'} className='text-xs text-orcide-fg-3 bg-orcide-bg-1 border border-orcide-border-1 rounded p-0.5 px-1' />
</div>
</ErrorBoundary>
@ -1263,22 +1263,22 @@ export const Settings = () => {
<div className='w-full'>
<h4 className={`text-base`}>{displayInfoOfFeatureName('Apply')}</h4>
<div className='text-sm text-void-fg-3 mt-1'>Settings that control the behavior of the Apply button.</div>
<div className='text-sm text-orcide-fg-3 mt-1'>Settings that control the behavior of the Apply button.</div>
<div className='my-2'>
{/* Sync to Chat Switch */}
<div className='flex items-center gap-x-2 my-2'>
<VoidSwitch
<OrcideSwitch
size='xs'
value={settingsState.globalSettings.syncApplyToChat}
onChange={(newVal) => voidSettingsService.setGlobalSetting('syncApplyToChat', newVal)}
onChange={(newVal) => orcideSettingsService.setGlobalSetting('syncApplyToChat', newVal)}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.syncApplyToChat ? 'Same as Chat model' : 'Different model'}</span>
<span className='text-orcide-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.syncApplyToChat ? 'Same as Chat model' : 'Different model'}</span>
</div>
{/* Model Dropdown */}
<div className={`my-2 ${settingsState.globalSettings.syncApplyToChat ? 'hidden' : ''}`}>
<ModelDropdown featureName={'Apply'} className='text-xs text-void-fg-3 bg-void-bg-1 border border-void-border-1 rounded p-0.5 px-1' />
<ModelDropdown featureName={'Apply'} className='text-xs text-orcide-fg-3 bg-orcide-bg-1 border border-orcide-border-1 rounded p-0.5 px-1' />
</div>
</div>
@ -1299,7 +1299,7 @@ export const Settings = () => {
{/* Tools Section */}
<div>
<h4 className={`text-base`}>Tools</h4>
<div className='text-sm text-void-fg-3 mt-1'>{`Tools are functions that LLMs can call. Some tools require user approval.`}</div>
<div className='text-sm text-orcide-fg-3 mt-1'>{`Tools are functions that LLMs can call. Some tools require user approval.`}</div>
<div className='my-2'>
{/* Auto Accept Switch */}
@ -1316,24 +1316,24 @@ export const Settings = () => {
<ErrorBoundary>
<div className='flex items-center gap-x-2 my-2'>
<VoidSwitch
<OrcideSwitch
size='xs'
value={settingsState.globalSettings.includeToolLintErrors}
onChange={(newVal) => voidSettingsService.setGlobalSetting('includeToolLintErrors', newVal)}
onChange={(newVal) => orcideSettingsService.setGlobalSetting('includeToolLintErrors', newVal)}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.includeToolLintErrors ? 'Fix lint errors' : `Fix lint errors`}</span>
<span className='text-orcide-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.includeToolLintErrors ? 'Fix lint errors' : `Fix lint errors`}</span>
</div>
</ErrorBoundary>
{/* Auto Accept LLM Changes Switch */}
<ErrorBoundary>
<div className='flex items-center gap-x-2 my-2'>
<VoidSwitch
<OrcideSwitch
size='xs'
value={settingsState.globalSettings.autoAcceptLLMChanges}
onChange={(newVal) => voidSettingsService.setGlobalSetting('autoAcceptLLMChanges', newVal)}
onChange={(newVal) => orcideSettingsService.setGlobalSetting('autoAcceptLLMChanges', newVal)}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>Auto-accept LLM changes</span>
<span className='text-orcide-fg-3 text-xs pointer-events-none'>Auto-accept LLM changes</span>
</div>
</ErrorBoundary>
</div>
@ -1343,18 +1343,18 @@ export const Settings = () => {
<div className='w-full'>
<h4 className={`text-base`}>Editor</h4>
<div className='text-sm text-void-fg-3 mt-1'>{`Settings that control the visibility of Void suggestions in the code editor.`}</div>
<div className='text-sm text-orcide-fg-3 mt-1'>{`Settings that control the visibility of Orcide suggestions in the code editor.`}</div>
<div className='my-2'>
{/* Auto Accept Switch */}
<ErrorBoundary>
<div className='flex items-center gap-x-2 my-2'>
<VoidSwitch
<OrcideSwitch
size='xs'
value={settingsState.globalSettings.showInlineSuggestions}
onChange={(newVal) => voidSettingsService.setGlobalSetting('showInlineSuggestions', newVal)}
onChange={(newVal) => orcideSettingsService.setGlobalSetting('showInlineSuggestions', newVal)}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.showInlineSuggestions ? 'Show suggestions on select' : 'Show suggestions on select'}</span>
<span className='text-orcide-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.showInlineSuggestions ? 'Show suggestions on select' : 'Show suggestions on select'}</span>
</div>
</ErrorBoundary>
</div>
@ -1365,22 +1365,22 @@ export const Settings = () => {
<div className='w-full'>
<h4 className={`text-base`}>{displayInfoOfFeatureName('SCM')}</h4>
<div className='text-sm text-void-fg-3 mt-1'>Settings that control the behavior of the commit message generator.</div>
<div className='text-sm text-orcide-fg-3 mt-1'>Settings that control the behavior of the commit message generator.</div>
<div className='my-2'>
{/* Sync to Chat Switch */}
<div className='flex items-center gap-x-2 my-2'>
<VoidSwitch
<OrcideSwitch
size='xs'
value={settingsState.globalSettings.syncSCMToChat}
onChange={(newVal) => voidSettingsService.setGlobalSetting('syncSCMToChat', newVal)}
onChange={(newVal) => orcideSettingsService.setGlobalSetting('syncSCMToChat', newVal)}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.syncSCMToChat ? 'Same as Chat model' : 'Different model'}</span>
<span className='text-orcide-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.syncSCMToChat ? 'Same as Chat model' : 'Different model'}</span>
</div>
{/* Model Dropdown */}
<div className={`my-2 ${settingsState.globalSettings.syncSCMToChat ? 'hidden' : ''}`}>
<ModelDropdown featureName={'SCM'} className='text-xs text-void-fg-3 bg-void-bg-1 border border-void-border-1 rounded p-0.5 px-1' />
<ModelDropdown featureName={'SCM'} className='text-xs text-orcide-fg-3 bg-orcide-bg-1 border border-orcide-border-1 rounded p-0.5 px-1' />
</div>
</div>
@ -1396,7 +1396,7 @@ export const Settings = () => {
<div>
<ErrorBoundary>
<h2 className='text-3xl mb-2'>One-Click Switch</h2>
<h4 className='text-void-fg-3 mb-4'>{`Transfer your editor settings into Void.`}</h4>
<h4 className='text-orcide-fg-3 mb-4'>{`Transfer your editor settings into Orcide.`}</h4>
<div className='flex flex-col gap-2'>
<OneClickSwitchButton className='w-48' fromEditor="VS Code" />
@ -1409,18 +1409,18 @@ export const Settings = () => {
{/* Import/Export section */}
<div>
<h2 className='text-3xl mb-2'>Import/Export</h2>
<h4 className='text-void-fg-3 mb-4'>{`Transfer Void's settings and chats in and out of Void.`}</h4>
<h4 className='text-orcide-fg-3 mb-4'>{`Transfer Orcide's settings and chats in and out of Orcide.`}</h4>
<div className='flex flex-col gap-8'>
{/* Settings Subcategory */}
<div className='flex flex-col gap-2 max-w-48 w-full'>
<input key={2 * s} ref={fileInputSettingsRef} type='file' accept='.json' className='hidden' onChange={handleUpload('Settings')} />
<VoidButtonBgDarken className='px-4 py-1 w-full' onClick={() => { fileInputSettingsRef.current?.click() }}>
<OrcideButtonBgDarken className='px-4 py-1 w-full' onClick={() => { fileInputSettingsRef.current?.click() }}>
Import Settings
</VoidButtonBgDarken>
<VoidButtonBgDarken className='px-4 py-1 w-full' onClick={() => onDownload('Settings')}>
</OrcideButtonBgDarken>
<OrcideButtonBgDarken className='px-4 py-1 w-full' onClick={() => onDownload('Settings')}>
Export Settings
</VoidButtonBgDarken>
<ConfirmButton className='px-4 py-1 w-full' onConfirm={() => { voidSettingsService.resetState(); }}>
</OrcideButtonBgDarken>
<ConfirmButton className='px-4 py-1 w-full' onConfirm={() => { orcideSettingsService.resetState(); }}>
Reset Settings
</ConfirmButton>
</div>
@ -1428,12 +1428,12 @@ export const Settings = () => {
{/* Chats Subcategory */}
<div className='flex flex-col gap-2 max-w-48 w-full'>
<input key={2 * s + 1} ref={fileInputChatsRef} type='file' accept='.json' className='hidden' onChange={handleUpload('Chats')} />
<VoidButtonBgDarken className='px-4 py-1 w-full' onClick={() => { fileInputChatsRef.current?.click() }}>
<OrcideButtonBgDarken className='px-4 py-1 w-full' onClick={() => { fileInputChatsRef.current?.click() }}>
Import Chats
</VoidButtonBgDarken>
<VoidButtonBgDarken className='px-4 py-1 w-full' onClick={() => onDownload('Chats')}>
</OrcideButtonBgDarken>
<OrcideButtonBgDarken className='px-4 py-1 w-full' onClick={() => onDownload('Chats')}>
Export Chats
</VoidButtonBgDarken>
</OrcideButtonBgDarken>
<ConfirmButton className='px-4 py-1 w-full' onConfirm={() => { chatThreadsService.resetState(); }}>
Reset Chats
</ConfirmButton>
@ -1446,22 +1446,22 @@ export const Settings = () => {
{/* Built-in Settings section */}
<div>
<h2 className={`text-3xl mb-2`}>Built-in Settings</h2>
<h4 className={`text-void-fg-3 mb-4`}>{`IDE settings, keyboard settings, and theme customization.`}</h4>
<h4 className={`text-orcide-fg-3 mb-4`}>{`IDE settings, keyboard settings, and theme customization.`}</h4>
<ErrorBoundary>
<div className='flex flex-col gap-2 justify-center max-w-48 w-full'>
<VoidButtonBgDarken className='px-4 py-1' onClick={() => { commandService.executeCommand('workbench.action.openSettings') }}>
<OrcideButtonBgDarken className='px-4 py-1' onClick={() => { commandService.executeCommand('workbench.action.openSettings') }}>
General Settings
</VoidButtonBgDarken>
<VoidButtonBgDarken className='px-4 py-1' onClick={() => { commandService.executeCommand('workbench.action.openGlobalKeybindings') }}>
</OrcideButtonBgDarken>
<OrcideButtonBgDarken className='px-4 py-1' onClick={() => { commandService.executeCommand('workbench.action.openGlobalKeybindings') }}>
Keyboard Settings
</VoidButtonBgDarken>
<VoidButtonBgDarken className='px-4 py-1' onClick={() => { commandService.executeCommand('workbench.action.selectTheme') }}>
</OrcideButtonBgDarken>
<OrcideButtonBgDarken className='px-4 py-1' onClick={() => { commandService.executeCommand('workbench.action.selectTheme') }}>
Theme Settings
</VoidButtonBgDarken>
<VoidButtonBgDarken className='px-4 py-1' onClick={() => { nativeHostService.showItemInFolder(environmentService.logsHome.fsPath) }}>
</OrcideButtonBgDarken>
<OrcideButtonBgDarken className='px-4 py-1' onClick={() => { nativeHostService?.showItemInFolder(environmentService.logsHome.fsPath) }}>
Open Logs
</VoidButtonBgDarken>
</OrcideButtonBgDarken>
</div>
</ErrorBoundary>
</div>
@ -1470,13 +1470,13 @@ export const Settings = () => {
{/* Metrics section */}
<div className='max-w-[600px]'>
<h2 className={`text-3xl mb-2`}>Metrics</h2>
<h4 className={`text-void-fg-3 mb-4`}>Very basic anonymous usage tracking helps us keep Void running smoothly. You may opt out below. Regardless of this setting, Void never sees your code, messages, or API keys.</h4>
<h4 className={`text-orcide-fg-3 mb-4`}>Very basic anonymous usage tracking helps us keep Orcide running smoothly. You may opt out below. Regardless of this setting, Orcide never sees your code, messages, or API keys.</h4>
<div className='my-2'>
{/* Disable All Metrics Switch */}
<ErrorBoundary>
<div className='flex items-center gap-x-2 my-2'>
<VoidSwitch
<OrcideSwitch
size='xs'
value={isOptedOut}
onChange={(newVal) => {
@ -1484,7 +1484,7 @@ export const Settings = () => {
metricsService.capture(`Set metrics opt-out to ${newVal}`, {}) // this only fires if it's enabled, so it's fine to have here
}}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>{'Opt-out (requires restart)'}</span>
<span className='text-orcide-fg-3 text-xs pointer-events-none'>{'Opt-out (requires restart)'}</span>
</div>
</ErrorBoundary>
</div>
@ -1493,7 +1493,7 @@ export const Settings = () => {
{/* AI Instructions section */}
<div className='max-w-[600px]'>
<h2 className={`text-3xl mb-2`}>AI Instructions</h2>
<h4 className={`text-void-fg-3 mb-4`}>
<h4 className={`text-orcide-fg-3 mb-4`}>
<ChatMarkdownRender inPTag={true} string={`
System instructions to include with all AI requests.
Alternatively, place a \`.voidrules\` file in the root of your workspace.
@ -1506,20 +1506,20 @@ Alternatively, place a \`.voidrules\` file in the root of your workspace.
<div className='my-4'>
<ErrorBoundary>
<div className='flex items-center gap-x-2'>
<VoidSwitch
<OrcideSwitch
size='xs'
value={!!settingsState.globalSettings.disableSystemMessage}
onChange={(newValue) => {
voidSettingsService.setGlobalSetting('disableSystemMessage', newValue);
orcideSettingsService.setGlobalSetting('disableSystemMessage', newValue);
}}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>
<span className='text-orcide-fg-3 text-xs pointer-events-none'>
{'Disable system message'}
</span>
</div>
</ErrorBoundary>
<div className='text-void-fg-3 text-xs mt-1'>
{`When disabled, Void will not include anything in the system message except for content you specified above.`}
<div className='text-orcide-fg-3 text-xs mt-1'>
{`When disabled, Orcide will not include anything in the system message except for content you specified above.`}
</div>
</div>
</div>
@ -1532,15 +1532,15 @@ Alternatively, place a \`.voidrules\` file in the root of your workspace.
<div className={shouldShowTab('mcp') ? `` : 'hidden'}>
<ErrorBoundary>
<h2 className='text-3xl mb-2'>MCP</h2>
<h4 className={`text-void-fg-3 mb-4`}>
<h4 className={`text-orcide-fg-3 mb-4`}>
<ChatMarkdownRender inPTag={true} string={`
Use Model Context Protocol to provide Agent mode with more tools.
`} chatMessageLocation={undefined} />
</h4>
<div className='my-2'>
<VoidButtonBgDarken className='px-4 py-1 w-full max-w-48' onClick={async () => { await mcpService.revealMCPConfigFile() }}>
<OrcideButtonBgDarken className='px-4 py-1 w-full max-w-48' onClick={async () => { await mcpService.revealMCPConfigFile() }}>
Add MCP Server
</VoidButtonBgDarken>
</OrcideButtonBgDarken>
</div>
<ErrorBoundary>

View file

@ -5,7 +5,7 @@ export const WarningBox = ({ text, onClick, className }: { text: string; onClick
return <div
className={`
text-void-warning brightness-90 opacity-90 w-fit
text-orcide-warning brightness-90 opacity-90 w-fit
text-xs text-ellipsis
${onClick ? `hover:brightness-75 transition-all duration-200 cursor-pointer` : ''}
flex items-center flex-nowrap

View file

@ -1,11 +1,11 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { mountFnGenerator } from '../util/mountFnGenerator.js'
import { Settings } from './Settings.js'
export const mountVoidSettings = mountFnGenerator(Settings)
export const mountOrcideSettings = mountFnGenerator(Settings)

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import '../styles.css'
@ -11,41 +11,41 @@ import { useIsDark } from '../util/services.js';
/**
* Creates a configured global tooltip component with consistent styling
* To use:
* 1. Mount a Tooltip with some id eg id='void-tooltip'
* 2. Add data-tooltip-id="void-tooltip" and data-tooltip-content="Your tooltip text" to any element
* 1. Mount a Tooltip with some id eg id='orcide-tooltip'
* 2. Add data-tooltip-id="orcide-tooltip" and data-tooltip-content="Your tooltip text" to any element
*/
export const VoidTooltip = () => {
export const OrcideTooltip = () => {
const isDark = useIsDark()
return (
// use native colors so we don't have to worry about @@void-scope styles
// --void-bg-1: var(--vscode-input-background);
// --void-bg-1-alt: var(--vscode-badge-background);
// --void-bg-2: var(--vscode-sideBar-background);
// --void-bg-2-alt: color-mix(in srgb, var(--vscode-sideBar-background) 30%, var(--vscode-editor-background) 70%);
// --void-bg-3: var(--vscode-editor-background);
// use native colors so we don't have to worry about @@orcide-scope styles
// --orcide-bg-1: var(--vscode-input-background);
// --orcide-bg-1-alt: var(--vscode-badge-background);
// --orcide-bg-2: var(--vscode-sideBar-background);
// --orcide-bg-2-alt: color-mix(in srgb, var(--vscode-sideBar-background) 30%, var(--vscode-editor-background) 70%);
// --orcide-bg-3: var(--vscode-editor-background);
// --void-fg-0: color-mix(in srgb, var(--vscode-tab-activeForeground) 90%, black 10%);
// --void-fg-1: var(--vscode-editor-foreground);
// --void-fg-2: var(--vscode-input-foreground);
// --void-fg-3: var(--vscode-input-placeholderForeground);
// /* --void-fg-4: var(--vscode-tab-inactiveForeground); */
// --void-fg-4: var(--vscode-list-deemphasizedForeground);
// --orcide-fg-0: color-mix(in srgb, var(--vscode-tab-activeForeground) 90%, black 10%);
// --orcide-fg-1: var(--vscode-editor-foreground);
// --orcide-fg-2: var(--vscode-input-foreground);
// --orcide-fg-3: var(--vscode-input-placeholderForeground);
// /* --orcide-fg-4: var(--vscode-tab-inactiveForeground); */
// --orcide-fg-4: var(--vscode-list-deemphasizedForeground);
// --void-warning: var(--vscode-charts-yellow);
// --orcide-warning: var(--vscode-charts-yellow);
// --void-border-1: var(--vscode-commandCenter-activeBorder);
// --void-border-2: var(--vscode-commandCenter-border);
// --void-border-3: var(--vscode-commandCenter-inactiveBorder);
// --void-border-4: var(--vscode-editorGroup-border);
// --orcide-border-1: var(--vscode-commandCenter-activeBorder);
// --orcide-border-2: var(--vscode-commandCenter-border);
// --orcide-border-3: var(--vscode-commandCenter-inactiveBorder);
// --orcide-border-4: var(--vscode-editorGroup-border);
<>
<style>
{`
#void-tooltip, #void-tooltip-orange, #void-tooltip-green, #void-tooltip-ollama-settings, #void-tooltip-provider-info {
#orcide-tooltip, #orcide-tooltip-orange, #orcide-tooltip-green, #orcide-tooltip-ollama-settings, #orcide-tooltip-provider-info {
font-size: 12px;
padding: 0px 8px;
border-radius: 6px;
@ -54,22 +54,22 @@ export const VoidTooltip = () => {
word-wrap: break-word;
}
#void-tooltip {
#orcide-tooltip {
background-color: var(--vscode-editor-background);
color: var(--vscode-input-foreground);
}
#void-tooltip-orange {
#orcide-tooltip-orange {
background-color: #F6762A;
color: white;
}
#void-tooltip-green {
#orcide-tooltip-green {
background-color: #228B22;
color: white;
}
#void-tooltip-ollama-settings, #void-tooltip-provider-info {
#orcide-tooltip-ollama-settings, #orcide-tooltip-provider-info {
background-color: var(--vscode-editor-background);
color: var(--vscode-input-foreground);
}
@ -82,26 +82,26 @@ export const VoidTooltip = () => {
<Tooltip
id="void-tooltip"
id="orcide-tooltip"
// border='1px solid var(--vscode-editorGroup-border)'
border='1px solid rgba(100,100,100,.2)'
opacity={1}
delayShow={50}
/>
<Tooltip
id="void-tooltip-orange"
id="orcide-tooltip-orange"
border='1px solid rgba(200,200,200,.3)'
opacity={1}
delayShow={50}
/>
<Tooltip
id="void-tooltip-green"
id="orcide-tooltip-green"
border='1px solid rgba(200,200,200,.3)'
opacity={1}
delayShow={50}
/>
<Tooltip
id="void-tooltip-ollama-settings"
id="orcide-tooltip-ollama-settings"
border='1px solid rgba(100,100,100,.2)'
opacity={1}
openEvents={{ mouseover: true, click: true, focus: true }}
@ -127,7 +127,7 @@ export const VoidTooltip = () => {
</Tooltip>
<Tooltip
id="void-tooltip-provider-info"
id="orcide-tooltip-provider-info"
border='1px solid rgba(100,100,100,.2)'
opacity={1}
delayShow={50}

View file

@ -0,0 +1,9 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { mountFnGenerator } from '../util/mountFnGenerator.js'
import { OrcideTooltip } from './OrcideTooltip.js'
export const mountOrcideTooltip = mountFnGenerator(OrcideTooltip)

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import React, { useEffect, useState } from 'react'
@ -13,7 +13,7 @@ export const QuickEdit = (props: QuickEditPropsType) => {
const isDark = useIsDark()
return <div className={`@@void-scope ${isDark ? 'dark' : ''}`}>
return <div className={`@@orcide-scope ${isDark ? 'dark' : ''}`}>
<ErrorBoundary>
<QuickEditChat {...props} />
</ErrorBoundary>

View file

@ -1,16 +1,16 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useSettingsState, useAccessor, useCtrlKZoneStreamingState } from '../util/services.js';
import { TextAreaFns, VoidInputBox2 } from '../util/inputs.js';
import { TextAreaFns, OrcideInputBox2 } from '../util/inputs.js';
import { QuickEditPropsType } from '../../../quickEditActions.js';
import { ButtonStop, ButtonSubmit, IconX, VoidChatArea } from '../sidebar-tsx/SidebarChat.js';
import { VOID_CTRL_K_ACTION_ID } from '../../../actionIDs.js';
import { ORCIDE_CTRL_K_ACTION_ID } from '../../../actionIDs.js';
import { useRefState } from '../util/helpers.js';
import { isFeatureNameDisabled } from '../../../../../../../workbench/contrib/void/common/voidSettingsTypes.js';
import { isFeatureNameDisabled } from '../../../../../../../workbench/contrib/orcide/common/orcideSettingsTypes.js';
@ -57,7 +57,7 @@ export const QuickEditChat = ({
}, [diffareaid, setIsStreamingRef]))
const loadingIcon = <div
className="@@codicon @@codicon-loading @@codicon-modifier-spin @@codicon-no-default-spin text-void-fg-3"
className="@@codicon @@codicon-loading @@codicon-modifier-spin @@codicon-no-default-spin text-orcide-fg-3"
/>
const onSubmit = useCallback(async () => {
@ -91,7 +91,7 @@ export const QuickEditChat = ({
editCodeService.removeCtrlKZone({ diffareaid })
}, [editCodeService, diffareaid])
const keybindingString = accessor.get('IKeybindingService').lookupKeybinding(VOID_CTRL_K_ACTION_ID)?.getLabel()
const keybindingString = accessor.get('IKeybindingService').lookupKeybinding(ORCIDE_CTRL_K_ACTION_ID)?.getLabel()
const chatAreaRef = useRef<HTMLDivElement | null>(null)
return <div ref={sizerRef} style={{ maxWidth: 450 }} className={`py-2 w-full`}>
@ -106,7 +106,7 @@ export const QuickEditChat = ({
isDisabled={isDisabled}
onClickAnywhere={() => { textAreaRef.current?.focus() }}
>
<VoidInputBox2
<OrcideInputBox2
className='px-1'
initValue={initText}
ref={useCallback((r: HTMLTextAreaElement | null) => {

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { mountFnGenerator } from '../util/mountFnGenerator.js'

View file

@ -1,10 +1,10 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import React, { Component, ErrorInfo, ReactNode } from 'react';
import { WarningBox } from '../void-settings-tsx/WarningBox.js';
import { WarningBox } from '../orcide-settings-tsx/WarningBox.js';
interface Props {
children: ReactNode;

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import React, { useEffect, useState } from 'react';

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { useIsDark } from '../util/services.js';
@ -15,15 +15,15 @@ export const Sidebar = ({ className }: { className: string }) => {
const isDark = useIsDark()
return <div
className={`@@void-scope ${isDark ? 'dark' : ''}`}
className={`@@orcide-scope ${isDark ? 'dark' : ''}`}
style={{ width: '100%', height: '100%' }}
>
<div
// default background + text styles for sidebar
className={`
w-full h-full
bg-void-bg-2
text-void-fg-1
bg-orcide-bg-2
text-orcide-fg-1
`}
>

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import React, { ButtonHTMLAttributes, FormEvent, FormHTMLAttributes, Fragment, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
@ -13,14 +13,14 @@ import { ChatMarkdownRender, ChatMessageLocation, getApplyBoxId } from '../markd
import { URI } from '../../../../../../../base/common/uri.js';
import { IDisposable } from '../../../../../../../base/common/lifecycle.js';
import { ErrorDisplay } from './ErrorDisplay.js';
import { BlockCode, TextAreaFns, VoidCustomDropdownBox, VoidInputBox2, VoidSlider, VoidSwitch, VoidDiffEditor } from '../util/inputs.js';
import { ModelDropdown, } from '../void-settings-tsx/ModelDropdown.js';
import { BlockCode, TextAreaFns, OrcideCustomDropdownBox, OrcideInputBox2, OrcideSlider, OrcideSwitch, VoidDiffEditor } from '../util/inputs.js';
import { ModelDropdown, } from '../orcide-settings-tsx/ModelDropdown.js';
import { PastThreadsList } from './SidebarThreadSelector.js';
import { VOID_CTRL_L_ACTION_ID } from '../../../actionIDs.js';
import { VOID_OPEN_SETTINGS_ACTION_ID } from '../../../voidSettingsPane.js';
import { ChatMode, displayInfoOfProviderName, FeatureName, isFeatureNameDisabled } from '../../../../../../../workbench/contrib/void/common/voidSettingsTypes.js';
import { ORCIDE_CTRL_L_ACTION_ID } from '../../../actionIDs.js';
import { ORCIDE_OPEN_SETTINGS_ACTION_ID } from '../../../orcideSettingsPane.js';
import { ChatMode, displayInfoOfProviderName, FeatureName, isFeatureNameDisabled } from '../../../../../../../workbench/contrib/orcide/common/orcideSettingsTypes.js';
import { ICommandService } from '../../../../../../../platform/commands/common/commands.js';
import { WarningBox } from '../void-settings-tsx/WarningBox.js';
import { WarningBox } from '../orcide-settings-tsx/WarningBox.js';
import { getModelCapabilities, getIsReasoningEnabledState } from '../../../../common/modelCapabilities.js';
import { AlertTriangle, File, Ban, Check, ChevronRight, Dot, FileIcon, Pencil, Undo, Undo2, X, Flag, Copy as CopyIcon, Info, CirclePlus, Ellipsis, CircleEllipsis, Folder, ALargeSmall, TypeOutline, Text } from 'lucide-react';
import { ChatMessage, CheckpointEntry, StagingSelectionItem, ToolMessage } from '../../../../common/chatThreadServiceTypes.js';
@ -31,7 +31,7 @@ import { acceptAllBg, acceptBorder, buttonFontSize, buttonTextColor, rejectAllBg
import { builtinToolNames, isABuiltinToolName, MAX_FILE_CHARS_PAGE, MAX_TERMINAL_INACTIVE_TIME } from '../../../../common/prompt/prompts.js';
import { RawToolCallObj } from '../../../../common/sendLLMMessageTypes.js';
import ErrorBoundary from './ErrorBoundary.js';
import { ToolApprovalTypeSwitch } from '../void-settings-tsx/Settings.js';
import { ToolApprovalTypeSwitch } from '../orcide-settings-tsx/Settings.js';
import { persistentTerminalNameOfId } from '../../../terminalToolService.js';
import { removeMCPToolNamePrefix } from '../../../../common/mcpServiceTypes.js';
@ -153,11 +153,11 @@ export const IconLoading = ({ className = '' }: { className?: string }) => {
const ReasoningOptionSlider = ({ featureName }: { featureName: FeatureName }) => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const voidSettingsState = useSettingsState()
const orcideSettingsService = accessor.get('IOrcideSettingsService')
const orcideSettingsState = useSettingsState()
const modelSelection = voidSettingsState.modelSelectionOfFeature[featureName]
const overridesOfModel = voidSettingsState.overridesOfModel
const modelSelection = orcideSettingsState.modelSelectionOfFeature[featureName]
const overridesOfModel = orcideSettingsState.overridesOfModel
if (!modelSelection) return null
@ -165,18 +165,18 @@ const ReasoningOptionSlider = ({ featureName }: { featureName: FeatureName }) =>
const { reasoningCapabilities } = getModelCapabilities(providerName, modelName, overridesOfModel)
const { canTurnOffReasoning, reasoningSlider: reasoningBudgetSlider } = reasoningCapabilities || {}
const modelSelectionOptions = voidSettingsState.optionsOfModelSelection[featureName][providerName]?.[modelName]
const modelSelectionOptions = orcideSettingsState.optionsOfModelSelection[featureName][providerName]?.[modelName]
const isReasoningEnabled = getIsReasoningEnabledState(featureName, providerName, modelName, modelSelectionOptions, overridesOfModel)
if (canTurnOffReasoning && !reasoningBudgetSlider) { // if it's just a on/off toggle without a power slider
return <div className='flex items-center gap-x-2'>
<span className='text-void-fg-3 text-xs pointer-events-none inline-block w-10 pr-1'>Thinking</span>
<VoidSwitch
<span className='text-orcide-fg-3 text-xs pointer-events-none inline-block w-10 pr-1'>Thinking</span>
<OrcideSwitch
size='xxs'
value={isReasoningEnabled}
onChange={(newVal) => {
const isOff = canTurnOffReasoning && !newVal
voidSettingsService.setOptionsOfModelSelection(featureName, modelSelection.providerName, modelSelection.modelName, { reasoningEnabled: !isOff })
orcideSettingsService.setOptionsOfModelSelection(featureName, modelSelection.providerName, modelSelection.modelName, { reasoningEnabled: !isOff })
}}
/>
</div>
@ -190,12 +190,12 @@ const ReasoningOptionSlider = ({ featureName }: { featureName: FeatureName }) =>
const valueIfOff = min_ - stepSize
const min = canTurnOffReasoning ? valueIfOff : min_
const value = isReasoningEnabled ? voidSettingsState.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName]?.reasoningBudget ?? defaultVal
const value = isReasoningEnabled ? orcideSettingsState.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName]?.reasoningBudget ?? defaultVal
: valueIfOff
return <div className='flex items-center gap-x-2'>
<span className='text-void-fg-3 text-xs pointer-events-none inline-block w-10 pr-1'>Thinking</span>
<VoidSlider
<span className='text-orcide-fg-3 text-xs pointer-events-none inline-block w-10 pr-1'>Thinking</span>
<OrcideSlider
width={50}
size='xs'
min={min}
@ -204,10 +204,10 @@ const ReasoningOptionSlider = ({ featureName }: { featureName: FeatureName }) =>
value={value}
onChange={(newVal) => {
const isOff = canTurnOffReasoning && newVal === valueIfOff
voidSettingsService.setOptionsOfModelSelection(featureName, modelSelection.providerName, modelSelection.modelName, { reasoningEnabled: !isOff, reasoningBudget: newVal })
orcideSettingsService.setOptionsOfModelSelection(featureName, modelSelection.providerName, modelSelection.modelName, { reasoningEnabled: !isOff, reasoningBudget: newVal })
}}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>{isReasoningEnabled ? `${value} tokens` : 'Thinking disabled'}</span>
<span className='text-orcide-fg-3 text-xs pointer-events-none'>{isReasoningEnabled ? `${value} tokens` : 'Thinking disabled'}</span>
</div>
}
@ -218,15 +218,15 @@ const ReasoningOptionSlider = ({ featureName }: { featureName: FeatureName }) =>
const min = canTurnOffReasoning ? -1 : 0
const max = values.length - 1
const currentEffort = voidSettingsState.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName]?.reasoningEffort ?? defaultVal
const currentEffort = orcideSettingsState.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName]?.reasoningEffort ?? defaultVal
const valueIfOff = -1
const value = isReasoningEnabled && currentEffort ? values.indexOf(currentEffort) : valueIfOff
const currentEffortCapitalized = currentEffort.charAt(0).toUpperCase() + currentEffort.slice(1, Infinity)
return <div className='flex items-center gap-x-2'>
<span className='text-void-fg-3 text-xs pointer-events-none inline-block w-10 pr-1'>Thinking</span>
<VoidSlider
<span className='text-orcide-fg-3 text-xs pointer-events-none inline-block w-10 pr-1'>Thinking</span>
<OrcideSlider
width={30}
size='xs'
min={min}
@ -235,10 +235,10 @@ const ReasoningOptionSlider = ({ featureName }: { featureName: FeatureName }) =>
value={value}
onChange={(newVal) => {
const isOff = canTurnOffReasoning && newVal === valueIfOff
voidSettingsService.setOptionsOfModelSelection(featureName, modelSelection.providerName, modelSelection.modelName, { reasoningEnabled: !isOff, reasoningEffort: values[newVal] ?? undefined })
orcideSettingsService.setOptionsOfModelSelection(featureName, modelSelection.providerName, modelSelection.modelName, { reasoningEnabled: !isOff, reasoningEffort: values[newVal] ?? undefined })
}}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>{isReasoningEnabled ? `${currentEffortCapitalized}` : 'Thinking disabled'}</span>
<span className='text-orcide-fg-3 text-xs pointer-events-none'>{isReasoningEnabled ? `${currentEffortCapitalized}` : 'Thinking disabled'}</span>
</div>
}
@ -263,16 +263,16 @@ const detailOfChatMode = {
const ChatModeDropdown = ({ className }: { className: string }) => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const orcideSettingsService = accessor.get('IOrcideSettingsService')
const settingsState = useSettingsState()
const options: ChatMode[] = useMemo(() => ['normal', 'gather', 'agent'], [])
const onChangeOption = useCallback((newVal: ChatMode) => {
voidSettingsService.setGlobalSetting('chatMode', newVal)
}, [voidSettingsService])
orcideSettingsService.setGlobalSetting('chatMode', newVal)
}, [orcideSettingsService])
return <VoidCustomDropdownBox
return <OrcideCustomDropdownBox
className={className}
options={options}
selectedOption={settingsState.globalSettings.chatMode}
@ -344,9 +344,9 @@ export const VoidChatArea: React.FC<VoidChatAreaProps> = ({
gap-x-1
flex flex-col p-2 relative input text-left shrink-0
rounded-md
bg-void-bg-1
bg-orcide-bg-1
transition-all duration-200
border border-void-border-3 focus-within:border-void-border-1 hover:border-void-border-1
border border-orcide-border-3 focus-within:border-orcide-border-1 hover:border-orcide-border-1
max-h-[80vh] overflow-y-auto
${className}
`}
@ -373,7 +373,7 @@ export const VoidChatArea: React.FC<VoidChatAreaProps> = ({
<div className='absolute -top-1 -right-1 cursor-pointer z-1'>
<IconX
size={12}
className="stroke-[2] opacity-80 text-void-fg-3 hover:brightness-95"
className="stroke-[2] opacity-80 text-orcide-fg-3 hover:brightness-95"
onClick={onClose}
/>
</div>
@ -387,8 +387,8 @@ export const VoidChatArea: React.FC<VoidChatAreaProps> = ({
<ReasoningOptionSlider featureName={featureName} />
<div className='flex items-center flex-wrap gap-x-2 gap-y-1 text-nowrap '>
{featureName === 'Chat' && <ChatModeDropdown className='text-xs text-void-fg-3 bg-void-bg-1 border border-void-border-2 rounded py-0.5 px-1' />}
<ModelDropdown featureName={featureName} className='text-xs text-void-fg-3 bg-void-bg-1 rounded' />
{featureName === 'Chat' && <ChatModeDropdown className='text-xs text-orcide-fg-3 bg-orcide-bg-1 border border-orcide-border-2 rounded py-0.5 px-1' />}
<ModelDropdown featureName={featureName} className='text-xs text-orcide-fg-3 bg-orcide-bg-1 rounded' />
</div>
</div>
)}
@ -425,7 +425,7 @@ export const ButtonSubmit = ({ className, disabled, ...props }: ButtonProps & Re
${disabled ? 'bg-vscode-disabled-fg cursor-default' : 'bg-white cursor-pointer'}
${className}
`}
// data-tooltip-id='void-tooltip'
// data-tooltip-id='orcide-tooltip'
// data-tooltip-content={'Send'}
// data-tooltip-place='left'
{...props}
@ -536,7 +536,7 @@ export const getBasename = (pathStr: string, parts: number = 1) => {
// Open file utility function
export const voidOpenFileFn = (
export const orcideOpenFileFn = (
uri: URI,
accessor: ReturnType<typeof useAccessor>,
range?: [number, number]
@ -585,7 +585,7 @@ export const SelectedFiles = (
const accessor = useAccessor()
const commandService = accessor.get('ICommandService')
const modelReferenceService = accessor.get('IVoidModelService')
const modelReferenceService = accessor.get('IOrcideModelService')
@ -666,7 +666,7 @@ export const SelectedFiles = (
>
{/* tooltip for file path */}
<span className="truncate overflow-hidden text-ellipsis"
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-content={getRelative(selection.uri, accessor)}
data-tooltip-place='top'
data-tooltip-delay-show={3000}
@ -680,12 +680,12 @@ export const SelectedFiles = (
select-none
text-xs text-nowrap
border rounded-sm
${isThisSelectionProspective ? 'bg-void-bg-1 text-void-fg-3 opacity-80' : 'bg-void-bg-1 hover:brightness-95 text-void-fg-1'}
${isThisSelectionProspective ? 'bg-orcide-bg-1 text-orcide-fg-3 opacity-80' : 'bg-orcide-bg-1 hover:brightness-95 text-orcide-fg-1'}
${isThisSelectionProspective
? 'border-void-border-2'
: 'border-void-border-1'
? 'border-orcide-border-2'
: 'border-orcide-border-1'
}
hover:border-void-border-1
hover:border-orcide-border-1
transition-all duration-150
`}
onClick={() => {
@ -694,7 +694,7 @@ export const SelectedFiles = (
setSelections([...selections, selection])
}
else if (selection.type === 'File') { // open files
voidOpenFileFn(selection.uri, accessor);
orcideOpenFileFn(selection.uri, accessor);
const wasAddedAsCurrentFile = selection.state.wasAddedAsCurrentFile
if (wasAddedAsCurrentFile) {
@ -708,7 +708,7 @@ export const SelectedFiles = (
}
}
else if (selection.type === 'CodeSelection') {
voidOpenFileFn(selection.uri, accessor, selection.range);
orcideOpenFileFn(selection.uri, accessor, selection.range);
}
else if (selection.type === 'Folder') {
// TODO!!! reveal in tree
@ -723,7 +723,7 @@ export const SelectedFiles = (
}
{selection.type === 'File' && selection.state.wasAddedAsCurrentFile && messageIdx === undefined && currentURI?.fsPath === selection.uri.fsPath ?
<span className={`text-[8px] 'void-opacity-60 text-void-fg-4`}>
<span className={`text-[8px] 'orcide-opacity-60 text-orcide-fg-4`}>
{`(Current File)`}
</span>
: null
@ -807,12 +807,12 @@ const ToolHeaderWrapper = ({
const isDesc1Clickable = !!desc1OnClick
const desc1HTML = <span
className={`text-void-fg-4 text-xs italic truncate ml-2
className={`text-orcide-fg-4 text-xs italic truncate ml-2
${isDesc1Clickable ? 'cursor-pointer hover:brightness-125 transition-all duration-150' : ''}
`}
onClick={desc1OnClick}
{...desc1Info ? {
'data-tooltip-id': 'void-tooltip',
'data-tooltip-id': 'orcide-tooltip',
'data-tooltip-content': desc1Info,
'data-tooltip-place': 'top',
'data-tooltip-delay-show': 1000,
@ -820,7 +820,7 @@ const ToolHeaderWrapper = ({
>{desc1}</span>
return (<div className=''>
<div className={`w-full border border-void-border-3 rounded px-2 py-1 bg-void-bg-3 overflow-hidden ${className}`}>
<div className={`w-full border border-orcide-border-3 rounded px-2 py-1 bg-orcide-bg-3 overflow-hidden ${className}`}>
{/* header */}
<div className={`select-none flex items-center min-h-[24px]`}>
<div className={`flex items-center w-full gap-x-2 overflow-hidden justify-between ${isRejected ? 'line-through' : ''}`}>
@ -840,11 +840,11 @@ const ToolHeaderWrapper = ({
>
{isDropdown && (<ChevronRight
className={`
text-void-fg-3 mr-0.5 h-4 w-4 flex-shrink-0 transition-transform duration-100 ease-[cubic-bezier(0.4,0,0.2,1)]
text-orcide-fg-3 mr-0.5 h-4 w-4 flex-shrink-0 transition-transform duration-100 ease-[cubic-bezier(0.4,0,0.2,1)]
${isExpanded ? 'rotate-90' : ''}
`}
/>)}
<span className="text-void-fg-3 flex-shrink-0">{title}</span>
<span className="text-orcide-fg-3 flex-shrink-0">{title}</span>
{!isDesc1Clickable && desc1HTML}
</div>
@ -855,32 +855,32 @@ const ToolHeaderWrapper = ({
<div className="flex items-center gap-x-2 flex-shrink-0">
{info && <CircleEllipsis
className='ml-2 text-void-fg-4 opacity-60 flex-shrink-0'
className='ml-2 text-orcide-fg-4 opacity-60 flex-shrink-0'
size={14}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-content={info}
data-tooltip-place='top-end'
/>}
{isError && <AlertTriangle
className='text-void-warning opacity-90 flex-shrink-0'
className='text-orcide-warning opacity-90 flex-shrink-0'
size={14}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-content={'Error running tool'}
data-tooltip-place='top'
/>}
{isRejected && <Ban
className='text-void-fg-4 opacity-90 flex-shrink-0'
className='text-orcide-fg-4 opacity-90 flex-shrink-0'
size={14}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-content={'Canceled'}
data-tooltip-place='top'
/>}
{desc2 && <span className="text-void-fg-4 text-xs" onClick={desc2OnClick}>
{desc2 && <span className="text-orcide-fg-4 text-xs" onClick={desc2OnClick}>
{desc2}
</span>}
{numResults !== undefined && (
<span className="text-void-fg-4 text-xs ml-auto mr-1">
<span className="text-orcide-fg-4 text-xs ml-auto mr-1">
{`${numResults}${hasNextPage ? '+' : ''} result${numResults !== 1 ? 's' : ''}`}
</span>
)}
@ -890,9 +890,9 @@ const ToolHeaderWrapper = ({
{/* children */}
{<div
className={`overflow-hidden transition-all duration-200 ease-in-out ${isExpanded ? 'opacity-100 py-1' : 'max-h-0 opacity-0'}
text-void-fg-4 rounded-sm overflow-x-auto
text-orcide-fg-4 rounded-sm overflow-x-auto
`}
// bg-black bg-opacity-10 border border-void-border-4 border-opacity-50
// bg-black bg-opacity-10 border border-orcide-border-4 border-opacity-50
>
{children}
</div>}
@ -914,13 +914,13 @@ const EditTool = ({ toolMessage, threadId, messageIdx, content }: Parameters<Res
const icon = null
const { rawParams, params, name } = toolMessage
const desc1OnClick = () => voidOpenFileFn(params.uri, accessor)
const desc1OnClick = () => orcideOpenFileFn(params.uri, accessor)
const componentParams: ToolHeaderParams = { title, desc1, desc1OnClick, desc1Info, isError, icon, isRejected, }
const editToolType = toolMessage.name === 'edit_file' ? 'diff' : 'rewrite'
if (toolMessage.type === 'running_now' || toolMessage.type === 'tool_request') {
componentParams.children = <ToolChildrenWrapper className='bg-void-bg-3'>
componentParams.children = <ToolChildrenWrapper className='bg-orcide-bg-3'>
<EditToolChildren
uri={params.uri}
code={content}
@ -945,7 +945,7 @@ const EditTool = ({ toolMessage, threadId, messageIdx, content }: Parameters<Res
/>
// add children
componentParams.children = <ToolChildrenWrapper className='bg-void-bg-3'>
componentParams.children = <ToolChildrenWrapper className='bg-orcide-bg-3'>
<EditToolChildren
uri={params.uri}
code={content}
@ -996,16 +996,16 @@ const SimplifiedToolHeader = ({
>
{isDropdown && (
<ChevronRight
className={`text-void-fg-3 mr-0.5 h-4 w-4 flex-shrink-0 transition-transform duration-100 ease-[cubic-bezier(0.4,0,0.2,1)] ${isOpen ? 'rotate-90' : ''}`}
className={`text-orcide-fg-3 mr-0.5 h-4 w-4 flex-shrink-0 transition-transform duration-100 ease-[cubic-bezier(0.4,0,0.2,1)] ${isOpen ? 'rotate-90' : ''}`}
/>
)}
<div className="flex items-center w-full overflow-hidden">
<span className="text-void-fg-3">{title}</span>
<span className="text-orcide-fg-3">{title}</span>
</div>
</div>
{/* children */}
{<div
className={`overflow-hidden transition-all duration-200 ease-in-out ${isOpen ? 'opacity-100' : 'max-h-0 opacity-0'} text-void-fg-4`}
className={`overflow-hidden transition-all duration-200 ease-in-out ${isOpen ? 'opacity-100' : 'max-h-0 opacity-0'} text-orcide-fg-4`}
>
{children}
</div>}
@ -1149,7 +1149,7 @@ const UserMessageComponent = ({ chatMessage, messageIdx, isCheckpointGhost, curr
selections={stagingSelections}
setSelections={setStagingSelections}
>
<VoidInputBox2
<OrcideInputBox2
enableAtToMention
ref={setTextAreaRef}
className='min-h-[81px] max-h-[500px] px-0.5'
@ -1189,7 +1189,7 @@ const UserMessageComponent = ({ chatMessage, messageIdx, isCheckpointGhost, curr
className={`
text-left rounded-lg max-w-full
${mode === 'edit' ? ''
: mode === 'display' ? 'p-2 flex flex-col bg-void-bg-1 text-void-fg-1 overflow-x-auto cursor-pointer' : ''
: mode === 'display' ? 'p-2 flex flex-col bg-orcide-bg-1 text-orcide-fg-1 overflow-x-auto cursor-pointer' : ''
}
`}
onClick={() => { if (mode === 'display') { onOpenEdit() } }}
@ -1201,7 +1201,7 @@ const UserMessageComponent = ({ chatMessage, messageIdx, isCheckpointGhost, curr
<div
className="absolute -top-1 -right-1 translate-x-0 -translate-y-0 z-1"
// data-tooltip-id='void-tooltip'
// data-tooltip-id='orcide-tooltip'
// data-tooltip-content='Edit message'
// data-tooltip-place='left'
>
@ -1210,7 +1210,7 @@ const UserMessageComponent = ({ chatMessage, messageIdx, isCheckpointGhost, curr
className={`
cursor-pointer
p-[2px]
bg-void-bg-1 border border-void-border-1 rounded-md
bg-orcide-bg-1 border border-orcide-border-1 rounded-md
transition-opacity duration-200 ease-in-out
${isHovered || (isFocused && mode === 'edit') ? 'opacity-100' : 'opacity-0'}
`}
@ -1231,7 +1231,7 @@ const UserMessageComponent = ({ chatMessage, messageIdx, isCheckpointGhost, curr
const SmallProseWrapper = ({ children }: { children: React.ReactNode }) => {
return <div className='
text-void-fg-4
text-orcide-fg-4
prose
prose-sm
break-words
@ -1276,7 +1276,7 @@ marker:text-inherit
prose-blockquote:pl-2
prose-blockquote:my-2
prose-code:text-void-fg-3
prose-code:text-orcide-fg-3
prose-code:text-[12px]
prose-code:before:content-none
prose-code:after:content-none
@ -1293,7 +1293,7 @@ prose-table:text-[13px]
const ProseWrapper = ({ children }: { children: React.ReactNode }) => {
return <div className='
text-void-fg-2
text-orcide-fg-2
prose
prose-sm
break-words
@ -1574,8 +1574,8 @@ const ToolRequestAcceptRejectButtons = ({ toolName }: { toolName: ToolName }) =>
const accessor = useAccessor()
const chatThreadsService = accessor.get('IChatThreadService')
const metricsService = accessor.get('IMetricsService')
const voidSettingsService = accessor.get('IVoidSettingsService')
const voidSettingsState = useSettingsState()
const orcideSettingsService = accessor.get('IOrcideSettingsService')
const orcideSettingsState = useSettingsState()
const onAccept = useCallback(() => {
try { // this doesn't need to be wrapped in try/catch anymore
@ -1662,7 +1662,7 @@ export const ListableToolItem = ({ name, onClick, isSmall, className, showDot }:
onClick={onClick}
>
{showDot === false ? null : <div className="flex-shrink-0"><svg className="w-1 h-1 opacity-60 mr-1.5 fill-current" viewBox="0 0 100 40"><rect x="0" y="15" width="100" height="10" /></svg></div>}
<div className={`${isSmall ? 'italic text-void-fg-4 flex items-center' : ''}`}>{name}</div>
<div className={`${isSmall ? 'italic text-orcide-fg-4 flex items-center' : ''}`}>{name}</div>
</div>
}
@ -1684,7 +1684,7 @@ const EditToolChildren = ({ uri, code, type }: { uri: URI | undefined, code: str
const LintErrorChildren = ({ lintErrors }: { lintErrors: LintErrorItem[] }) => {
return <div className="text-xs text-void-fg-4 opacity-80 border-l-2 border-void-warning px-2 py-0.5 flex flex-col gap-0.5 overflow-x-auto whitespace-nowrap">
return <div className="text-xs text-orcide-fg-4 opacity-80 border-l-2 border-orcide-warning px-2 py-0.5 flex flex-col gap-0.5 overflow-x-auto whitespace-nowrap">
{lintErrors.map((error, i) => (
<div key={i}>Lines {error.startLineNumber}-{error.endLineNumber}: {error.message}</div>
))}
@ -1702,14 +1702,14 @@ const BottomChildren = ({ children, title }: { children: React.ReactNode, title:
style={{ background: 'none' }}
>
<ChevronRight
className={`mr-1 h-3 w-3 flex-shrink-0 transition-transform duration-100 text-void-fg-4 group-hover:text-void-fg-3 ${isOpen ? 'rotate-90' : ''}`}
className={`mr-1 h-3 w-3 flex-shrink-0 transition-transform duration-100 text-orcide-fg-4 group-hover:text-orcide-fg-3 ${isOpen ? 'rotate-90' : ''}`}
/>
<span className="font-medium text-void-fg-4 group-hover:text-void-fg-3 text-xs">{title}</span>
<span className="font-medium text-orcide-fg-4 group-hover:text-orcide-fg-3 text-xs">{title}</span>
</div>
<div
className={`overflow-hidden transition-all duration-200 ease-in-out ${isOpen ? 'opacity-100' : 'max-h-0 opacity-0'} text-xs pl-4`}
>
<div className="overflow-x-auto text-void-fg-4 opacity-90 border-l-2 border-void-warning px-2 py-0.5">
<div className="overflow-x-auto text-orcide-fg-4 opacity-90 border-l-2 border-orcide-warning px-2 py-0.5">
{children}
</div>
</div>
@ -1739,7 +1739,7 @@ const InvalidTool = ({ toolName, message, mcpServerName }: { toolName: ToolName,
const componentParams: ToolHeaderParams = { title, desc1, isError, icon }
componentParams.children = <ToolChildrenWrapper>
<CodeChildren className='bg-void-bg-3'>
<CodeChildren className='bg-orcide-bg-3'>
{message}
</CodeChildren>
</ToolChildrenWrapper>
@ -1944,7 +1944,7 @@ const builtinToolNameToComponent: { [T in BuiltinToolName]: { resultWrapper: Res
if (toolMessage.type === 'success') {
const { result } = toolMessage
componentParams.onClick = () => { voidOpenFileFn(params.uri, accessor, range) }
componentParams.onClick = () => { orcideOpenFileFn(params.uri, accessor, range) }
if (result.hasNextPage && params.pageNumber === 1) // first page
componentParams.desc2 = `(truncated after ${Math.round(MAX_FILE_CHARS_PAGE) / 1000}k)`
else if (params.pageNumber > 1) // subsequent pages
@ -2043,7 +2043,7 @@ const builtinToolNameToComponent: { [T in BuiltinToolName]: { resultWrapper: Res
name={`${child.name}${child.isDirectory ? '/' : ''}`}
className='w-full overflow-auto'
onClick={() => {
voidOpenFileFn(child.uri, accessor)
orcideOpenFileFn(child.uri, accessor)
// commandService.executeCommand('workbench.view.explorer'); // open in explorer folders view instead
// explorerService.select(child.uri, true);
}}
@ -2094,7 +2094,7 @@ const builtinToolNameToComponent: { [T in BuiltinToolName]: { resultWrapper: Res
{result.uris.map((uri, i) => (<ListableToolItem key={i}
name={getBasename(uri.fsPath)}
className='w-full overflow-auto'
onClick={() => { voidOpenFileFn(uri, accessor) }}
onClick={() => { orcideOpenFileFn(uri, accessor) }}
/>))}
{result.hasNextPage &&
<ListableToolItem name={'Results truncated.'} isSmall={true} className='w-full overflow-auto' />
@ -2149,7 +2149,7 @@ const builtinToolNameToComponent: { [T in BuiltinToolName]: { resultWrapper: Res
{result.uris.map((uri, i) => (<ListableToolItem key={i}
name={getBasename(uri.fsPath)}
className='w-full overflow-auto'
onClick={() => { voidOpenFileFn(uri, accessor) }}
onClick={() => { orcideOpenFileFn(uri, accessor) }}
/>))}
{result.hasNextPage &&
<ListableToolItem name={`Results truncated.`} isSmall={true} className='w-full overflow-auto' />
@ -2196,7 +2196,7 @@ const builtinToolNameToComponent: { [T in BuiltinToolName]: { resultWrapper: Res
componentParams.numResults = result.lines.length;
componentParams.children = result.lines.length === 0 ? undefined :
<ToolChildrenWrapper>
<CodeChildren className='bg-void-bg-3'>
<CodeChildren className='bg-orcide-bg-3'>
<pre className='font-mono whitespace-pre'>
{toolsService.stringOfResult['search_in_file'](params, result)}
</pre>
@ -2239,7 +2239,7 @@ const builtinToolNameToComponent: { [T in BuiltinToolName]: { resultWrapper: Res
if (toolMessage.type === 'success') {
const { result } = toolMessage
componentParams.onClick = () => { voidOpenFileFn(params.uri, accessor) }
componentParams.onClick = () => { orcideOpenFileFn(params.uri, accessor) }
if (result.lintErrors)
componentParams.children = <LintErrorChildren lintErrors={result.lintErrors} />
else
@ -2280,14 +2280,14 @@ const builtinToolNameToComponent: { [T in BuiltinToolName]: { resultWrapper: Res
if (toolMessage.type === 'success') {
const { result } = toolMessage
componentParams.onClick = () => { voidOpenFileFn(params.uri, accessor) }
componentParams.onClick = () => { orcideOpenFileFn(params.uri, accessor) }
}
else if (toolMessage.type === 'rejected') {
componentParams.onClick = () => { voidOpenFileFn(params.uri, accessor) }
componentParams.onClick = () => { orcideOpenFileFn(params.uri, accessor) }
}
else if (toolMessage.type === 'tool_error') {
const { result } = toolMessage
if (params) { componentParams.onClick = () => { voidOpenFileFn(params.uri, accessor) } }
if (params) { componentParams.onClick = () => { orcideOpenFileFn(params.uri, accessor) } }
componentParams.bottomChildren = <BottomChildren title='Error'>
<CodeChildren>
{result}
@ -2322,14 +2322,14 @@ const builtinToolNameToComponent: { [T in BuiltinToolName]: { resultWrapper: Res
if (toolMessage.type === 'success') {
const { result } = toolMessage
componentParams.onClick = () => { voidOpenFileFn(params.uri, accessor) }
componentParams.onClick = () => { orcideOpenFileFn(params.uri, accessor) }
}
else if (toolMessage.type === 'rejected') {
componentParams.onClick = () => { voidOpenFileFn(params.uri, accessor) }
componentParams.onClick = () => { orcideOpenFileFn(params.uri, accessor) }
}
else if (toolMessage.type === 'tool_error') {
const { result } = toolMessage
if (params) { componentParams.onClick = () => { voidOpenFileFn(params.uri, accessor) } }
if (params) { componentParams.onClick = () => { orcideOpenFileFn(params.uri, accessor) } }
componentParams.bottomChildren = <BottomChildren title='Error'>
<CodeChildren>
{result}
@ -2338,11 +2338,11 @@ const builtinToolNameToComponent: { [T in BuiltinToolName]: { resultWrapper: Res
}
else if (toolMessage.type === 'running_now') {
const { result } = toolMessage
componentParams.onClick = () => { voidOpenFileFn(params.uri, accessor) }
componentParams.onClick = () => { orcideOpenFileFn(params.uri, accessor) }
}
else if (toolMessage.type === 'tool_request') {
const { result } = toolMessage
componentParams.onClick = () => { voidOpenFileFn(params.uri, accessor) }
componentParams.onClick = () => { orcideOpenFileFn(params.uri, accessor) }
}
return <ToolHeaderWrapper {...componentParams} />
@ -2465,7 +2465,7 @@ const Checkpoint = ({ message, threadId, messageIdx, isCheckpointGhost, threadIs
<div
className={`
text-xs
text-void-fg-3
text-orcide-fg-3
select-none
${isCheckpointGhost ? 'opacity-50' : 'opacity-100'}
${isDisabled ? 'cursor-default' : 'cursor-pointer'}
@ -2481,7 +2481,7 @@ const Checkpoint = ({ message, threadId, messageIdx, isCheckpointGhost, threadIs
})
}}
{...isDisabled ? {
'data-tooltip-id': 'void-tooltip',
'data-tooltip-id': 'orcide-tooltip',
'data-tooltip-content': `Disabled ${isRunning ? 'when running' : 'because another thread is running'}`,
'data-tooltip-place': 'top',
} : {}}
@ -2594,7 +2594,7 @@ const CommandBarInChat = () => {
// <IconShell1
// Icon={CopyIcon}
// onClick={copyChatToClipboard}
// data-tooltip-id='void-tooltip'
// data-tooltip-id='orcide-tooltip'
// data-tooltip-place='top'
// data-tooltip-content='Copy chat JSON'
// />
@ -2672,7 +2672,7 @@ const CommandBarInChat = () => {
});
});
}}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='top'
data-tooltip-content='Reject all'
/>
@ -2691,7 +2691,7 @@ const CommandBarInChat = () => {
});
});
}}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='top'
data-tooltip-content='Accept all'
/>
@ -2717,18 +2717,18 @@ const CommandBarInChat = () => {
)
const fileNameHTML = <div
className="flex items-center gap-1.5 text-void-fg-3 hover:brightness-125 transition-all duration-200 cursor-pointer"
onClick={() => voidOpenFileFn(uri, accessor)}
className="flex items-center gap-1.5 text-orcide-fg-3 hover:brightness-125 transition-all duration-200 cursor-pointer"
onClick={() => orcideOpenFileFn(uri, accessor)}
>
{/* <FileIcon size={14} className="text-void-fg-3" /> */}
<span className="text-void-fg-3">{basename}</span>
{/* <FileIcon size={14} className="text-orcide-fg-3" /> */}
<span className="text-orcide-fg-3">{basename}</span>
</div>
const detailsContent = <div className='flex px-4'>
<span className="text-void-fg-3 opacity-80">{numDiffs} diff{numDiffs !== 1 ? 's' : ''}</span>
<span className="text-orcide-fg-3 opacity-80">{numDiffs} diff{numDiffs !== 1 ? 's' : ''}</span>
</div>
const acceptRejectButtons = <div
@ -2739,14 +2739,14 @@ const CommandBarInChat = () => {
>
{/* <JumpToFileButton
uri={uri}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='top'
data-tooltip-content='Go to file'
/> */}
<IconShell1 // RejectAllButtonWrapper
Icon={X}
onClick={() => { editCodeService.acceptOrRejectAllDiffAreas({ uri, removeCtrlKs: true, behavior: "reject", _addToHistory: true, }); }}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='top'
data-tooltip-content='Reject file'
@ -2754,7 +2754,7 @@ const CommandBarInChat = () => {
<IconShell1 // AcceptAllButtonWrapper
Icon={Check}
onClick={() => { editCodeService.acceptOrRejectAllDiffAreas({ uri, removeCtrlKs: true, behavior: "accept", _addToHistory: true, }); }}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='top'
data-tooltip-content='Accept file'
/>
@ -2805,8 +2805,8 @@ const CommandBarInChat = () => {
<div
className={`
select-none
flex w-full rounded-t-lg bg-void-bg-3
text-void-fg-3 text-xs text-nowrap
flex w-full rounded-t-lg bg-orcide-bg-3
text-orcide-fg-3 text-xs text-nowrap
overflow-hidden transition-all duration-200 ease-in-out
${isFileDetailsOpened ? 'max-h-24' : 'max-h-0'}
@ -2819,8 +2819,8 @@ const CommandBarInChat = () => {
<div
className={`
select-none
flex w-full rounded-t-lg bg-void-bg-3
text-void-fg-3 text-xs text-nowrap
flex w-full rounded-t-lg bg-orcide-bg-3
text-orcide-fg-3 text-xs text-nowrap
border-t border-l border-r border-zinc-300/10
px-2 py-1
@ -2859,7 +2859,7 @@ const EditToolSoFar = ({ toolCallSoFar, }: { toolCallSoFar: RawToolCallObj }) =>
<IconLoading />
</span>
const desc1OnClick = () => { uri && voidOpenFileFn(uri, accessor) }
const desc1OnClick = () => { uri && orcideOpenFileFn(uri, accessor) }
// If URI has not been specified
return <ToolHeaderWrapper
@ -2944,7 +2944,7 @@ export const SidebarChat = () => {
await chatThreadsService.abortRunning(threadId)
}
const keybindingString = accessor.get('IKeybindingService').lookupKeybinding(VOID_CTRL_L_ACTION_ID)?.getLabel()
const keybindingString = accessor.get('IKeybindingService').lookupKeybinding(ORCIDE_CTRL_L_ACTION_ID)?.getLabel()
const threadId = currentThread.id
const currCheckpointIdx = chatThreadsState.allThreads[threadId]?.state?.currCheckpointIdx ?? undefined // if not exist, treat like checkpoint is last message (infinity)
@ -3046,7 +3046,7 @@ export const SidebarChat = () => {
showDismiss={true}
/>
<WarningBox className='text-sm my-2 mx-4' onClick={() => { commandService.executeCommand(VOID_OPEN_SETTINGS_ACTION_ID) }} text='Open settings' />
<WarningBox className='text-sm my-2 mx-4' onClick={() => { commandService.executeCommand(ORCIDE_OPEN_SETTINGS_ACTION_ID) }} text='Open settings' />
</div>
}
</ScrollToBottomContainer>
@ -3075,7 +3075,7 @@ export const SidebarChat = () => {
setSelections={setSelections}
onClickAnywhere={() => { textAreaRef.current?.focus() }}
>
<VoidInputBox2
<OrcideInputBox2
enableAtToMention
className={`min-h-[81px] px-0.5 py-0.5`}
placeholder={`@ to mention, ${keybindingString ? `${keybindingString} to add a selection. ` : ''}Enter instructions...`}
@ -3093,7 +3093,7 @@ export const SidebarChat = () => {
const isLandingPage = previousMessages.length === 0
const initiallySuggestedPromptsHTML = <div className='flex flex-col gap-2 w-full text-nowrap text-void-fg-3 select-none'>
const initiallySuggestedPromptsHTML = <div className='flex flex-col gap-2 w-full text-nowrap text-orcide-fg-3 select-none'>
{[
'Summarize my codebase',
'How do types work in Rust?',
@ -3136,12 +3136,12 @@ export const SidebarChat = () => {
{Object.keys(chatThreadsState.allThreads).length > 1 ? // show if there are threads
<ErrorBoundary>
<div className='pt-8 mb-2 text-void-fg-3 text-root select-none pointer-events-none'>Previous Threads</div>
<div className='pt-8 mb-2 text-orcide-fg-3 text-root select-none pointer-events-none'>Previous Threads</div>
<PastThreadsList />
</ErrorBoundary>
:
<ErrorBoundary>
<div className='pt-8 mb-2 text-void-fg-3 text-root select-none pointer-events-none'>Suggestions</div>
<div className='pt-8 mb-2 text-orcide-fg-3 text-root select-none pointer-events-none'>Suggestions</div>
{initiallySuggestedPromptsHTML}
</ErrorBoundary>
}

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { useMemo, useState } from 'react';
@ -43,7 +43,7 @@ export const PastThreadsList = ({ className = '' }: { className?: string }) => {
const displayThreads = showAll ? sortedThreadIds : sortedThreadIds.slice(0, numInitialThreads);
return (
<div className={`flex flex-col mb-2 gap-2 w-full text-nowrap text-void-fg-3 select-none relative ${className}`}>
<div className={`flex flex-col mb-2 gap-2 w-full text-nowrap text-orcide-fg-3 select-none relative ${className}`}>
{displayThreads.length === 0 // this should never happen
? <></>
: displayThreads.map((threadId, i) => {
@ -67,7 +67,7 @@ export const PastThreadsList = ({ className = '' }: { className?: string }) => {
{hasMoreThreads && !showAll && (
<div
className="text-void-fg-3 opacity-80 hover:opacity-100 hover:brightness-115 cursor-pointer p-1 text-xs"
className="text-orcide-fg-3 opacity-80 hover:opacity-100 hover:brightness-115 cursor-pointer p-1 text-xs"
onClick={() => setShowAll(true)}
>
Show {sortedThreadIds.length - numInitialThreads} more...
@ -75,7 +75,7 @@ export const PastThreadsList = ({ className = '' }: { className?: string }) => {
)}
{hasMoreThreads && showAll && (
<div
className="text-void-fg-3 opacity-80 hover:opacity-100 hover:brightness-115 cursor-pointer p-1 text-xs"
className="text-orcide-fg-3 opacity-80 hover:opacity-100 hover:brightness-115 cursor-pointer p-1 text-xs"
onClick={() => setShowAll(false)}
>
Show less
@ -122,7 +122,7 @@ const DuplicateButton = ({ threadId }: { threadId: string }) => {
Icon={Copy}
className='size-[11px]'
onClick={() => { chatThreadsService.duplicateThread(threadId); }}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='top'
data-tooltip-content='Duplicate thread'
>
@ -144,7 +144,7 @@ const TrashButton = ({ threadId }: { threadId: string }) => {
Icon={X}
className='size-[11px]'
onClick={() => { setIsTrashPressed(false); }}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='top'
data-tooltip-content='Cancel'
/>
@ -152,7 +152,7 @@ const TrashButton = ({ threadId }: { threadId: string }) => {
Icon={Check}
className='size-[11px]'
onClick={() => { chatThreadsService.deleteThread(threadId); setIsTrashPressed(false); }}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='top'
data-tooltip-content='Confirm'
/>
@ -161,7 +161,7 @@ const TrashButton = ({ threadId }: { threadId: string }) => {
Icon={Trash2}
className='size-[11px]'
onClick={() => { setIsTrashPressed(true); }}
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-place='top'
data-tooltip-content='Delete thread'
/>
@ -204,7 +204,7 @@ const PastThreadElement = ({ pastThread, idx, hoveredIdx, setHoveredIdx, isRunni
// codeStr={async () => {
// return JSON.stringify(currentThread.messages, null, 2)
// }}
// toolTipName={`Copy As Void Chat`}
// toolTipName={`Copy As Orcide Chat`}
// />
let firstMsg = null;
@ -220,7 +220,7 @@ const PastThreadElement = ({ pastThread, idx, hoveredIdx, setHoveredIdx, isRunni
const numMessages = pastThread.messages.filter((msg) => msg.role === 'assistant' || msg.role === 'user').length;
const detailsHTML = <span
// data-tooltip-id='void-tooltip'
// data-tooltip-id='orcide-tooltip'
// data-tooltip-content={`Last modified ${formatTime(new Date(pastThread.lastModified))}`}
// data-tooltip-place='top'
>
@ -244,14 +244,14 @@ const PastThreadElement = ({ pastThread, idx, hoveredIdx, setHoveredIdx, isRunni
<div className="flex items-center justify-between gap-1">
<span className="flex items-center gap-2 min-w-0 overflow-hidden">
{/* spinner */}
{isRunning === 'LLM' || isRunning === 'tool' || isRunning === 'idle' ? <LoaderCircle className="animate-spin bg-void-stroke-1 flex-shrink-0 flex-grow-0" size={14} />
{isRunning === 'LLM' || isRunning === 'tool' || isRunning === 'idle' ? <LoaderCircle className="animate-spin bg-orcide-stroke-1 flex-shrink-0 flex-grow-0" size={14} />
:
isRunning === 'awaiting_user' ? <MessageCircleQuestion className="bg-void-stroke-1 flex-shrink-0 flex-grow-0" size={14} />
isRunning === 'awaiting_user' ? <MessageCircleQuestion className="bg-orcide-stroke-1 flex-shrink-0 flex-grow-0" size={14} />
:
null}
{/* name */}
<span className="truncate overflow-hidden text-ellipsis"
data-tooltip-id='void-tooltip'
data-tooltip-id='orcide-tooltip'
data-tooltip-content={numMessages + ' messages'}
data-tooltip-place='top'
>{firstMsg}</span>

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { mountFnGenerator } from '../util/mountFnGenerator.js'

View file

@ -8,29 +8,29 @@
@tailwind utilities;
& {
--void-bg-1: var(--vscode-input-background);
--void-bg-1-alt: var(--vscode-badge-background);
--void-bg-2: var(--vscode-sideBar-background);
--void-bg-2-alt: color-mix(in srgb, var(--vscode-editor-background) 30%, var(--vscode-sideBar-background) 70%);
--void-bg-2-hover: color-mix(in srgb, var(--vscode-editor-foreground) 2%, var(--vscode-sideBar-background) 98%);
--void-bg-3: var(--vscode-editor-background);
--orcide-bg-1: var(--vscode-input-background);
--orcide-bg-1-alt: var(--vscode-badge-background);
--orcide-bg-2: var(--vscode-sideBar-background);
--orcide-bg-2-alt: color-mix(in srgb, var(--vscode-editor-background) 30%, var(--vscode-sideBar-background) 70%);
--orcide-bg-2-hover: color-mix(in srgb, var(--vscode-editor-foreground) 2%, var(--vscode-sideBar-background) 98%);
--orcide-bg-3: var(--vscode-editor-background);
--void-fg-0: color-mix(in srgb, var(--vscode-tab-activeForeground) 90%, black 10%);
--void-fg-1: var(--vscode-editor-foreground);
--void-fg-2: var(--vscode-input-foreground);
--void-fg-3: var(--vscode-input-placeholderForeground);
/* --void-fg-4: var(--vscode-tab-inactiveForeground); */
--void-fg-4: var(--vscode-list-deemphasizedForeground);
--orcide-fg-0: color-mix(in srgb, var(--vscode-tab-activeForeground) 90%, black 10%);
--orcide-fg-1: var(--vscode-editor-foreground);
--orcide-fg-2: var(--vscode-input-foreground);
--orcide-fg-3: var(--vscode-input-placeholderForeground);
/* --orcide-fg-4: var(--vscode-tab-inactiveForeground); */
--orcide-fg-4: var(--vscode-list-deemphasizedForeground);
--void-warning: var(--vscode-charts-yellow);
--orcide-warning: var(--vscode-charts-yellow);
--void-border-1: var(--vscode-commandCenter-activeBorder);
--void-border-2: var(--vscode-commandCenter-border);
--void-border-3: var(--vscode-commandCenter-inactiveBorder);
--void-border-4: var(--vscode-editorGroup-border);
--orcide-border-1: var(--vscode-commandCenter-activeBorder);
--orcide-border-2: var(--vscode-commandCenter-border);
--orcide-border-3: var(--vscode-commandCenter-inactiveBorder);
--orcide-border-4: var(--vscode-editorGroup-border);
--void-ring-color: #007FD4;
--void-link-color: #007FD4;
--orcide-ring-color: #007FD4;
--orcide-link-color: #007FD4;
}
.select-child-restyle select {
@ -39,8 +39,8 @@
padding-right: 24px;
}
.void-force-child-placeholder-void-fg-1 ::placeholder {
color: var(--void-fg-3);
.orcide-force-child-placeholder-orcide-fg-1 ::placeholder {
color: var(--orcide-fg-3);
}
* {

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import React, { forwardRef, ForwardRefExoticComponent, MutableRefObject, RefAttributes, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';
@ -354,7 +354,7 @@ type InputBox2Props = {
onBlur?: (e: React.FocusEvent<HTMLTextAreaElement>) => void;
onChangeHeight?: (newHeight: number) => void;
}
export const VoidInputBox2 = forwardRef<HTMLTextAreaElement, InputBox2Props>(function X({ initValue, placeholder, multiline, enableAtToMention, fnsRef, className, onKeyDown, onFocus, onBlur, onChangeText }, ref) {
export const OrcideInputBox2 = forwardRef<HTMLTextAreaElement, InputBox2Props>(function X({ initValue, placeholder, multiline, enableAtToMention, fnsRef, className, onKeyDown, onFocus, onBlur, onChangeText }, ref) {
// mirrors whatever is in ref
@ -753,7 +753,7 @@ export const VoidInputBox2 = forwardRef<HTMLTextAreaElement, InputBox2Props>(fun
disabled={!isEnabled}
className={`w-full resize-none max-h-[500px] overflow-y-auto text-void-fg-1 placeholder:text-void-fg-3 ${className}`}
className={`w-full resize-none max-h-[500px] overflow-y-auto text-orcide-fg-1 placeholder:text-orcide-fg-3 ${className}`}
style={{
// defaultInputBoxStyles
background: asCssVariable(inputBackground),
@ -809,7 +809,7 @@ export const VoidInputBox2 = forwardRef<HTMLTextAreaElement, InputBox2Props>(fun
{isMenuOpen && (
<div
ref={refs.setFloating}
className="z-[100] border-void-border-3 bg-void-bg-2-alt border rounded shadow-lg flex flex-col overflow-hidden"
className="z-[100] border-orcide-border-3 bg-orcide-bg-2-alt border rounded shadow-lg flex flex-col overflow-hidden"
style={{
position: strategy,
top: y ?? 0,
@ -819,7 +819,7 @@ export const VoidInputBox2 = forwardRef<HTMLTextAreaElement, InputBox2Props>(fun
onWheel={(e) => e.stopPropagation()}
>
{/* Breadcrumbs Header */}
{isBreadcrumbsShowing && <div className="px-2 py-1 text-void-fg-1 bg-void-bg-2-alt border-b border-void-border-3 sticky top-0 bg-void-bg-1 z-10 select-none pointer-events-none">
{isBreadcrumbsShowing && <div className="px-2 py-1 text-orcide-fg-1 bg-orcide-bg-2-alt border-b border-orcide-border-3 sticky top-0 bg-orcide-bg-1 z-10 select-none pointer-events-none">
{optionText ?
<div className="flex items-center">
{/* {optionPath.map((path, index) => (
@ -839,7 +839,7 @@ export const VoidInputBox2 = forwardRef<HTMLTextAreaElement, InputBox2Props>(fun
<div className='max-h-[400px] w-full max-w-full overflow-y-auto overflow-x-auto'>
<div className="w-max min-w-full flex flex-col gap-0 text-nowrap flex-nowrap">
{options.length === 0 ?
<div className="text-void-fg-3 px-3 py-0.5">No results found</div>
<div className="text-orcide-fg-3 px-3 py-0.5">No results found</div>
: options.map((o, oIdx) => {
return (
@ -850,7 +850,7 @@ export const VoidInputBox2 = forwardRef<HTMLTextAreaElement, InputBox2Props>(fun
className={`
flex items-center gap-2
px-3 py-1 cursor-pointer
${oIdx === optionIdx ? 'bg-blue-500 text-white/80' : 'bg-void-bg-2-alt text-void-fg-1'}
${oIdx === optionIdx ? 'bg-blue-500 text-white/80' : 'bg-orcide-bg-2-alt text-orcide-fg-1'}
`}
onClick={() => { onSelectOption(); }}
onMouseMove={() => { setOptionIdx(oIdx) }}
@ -878,7 +878,7 @@ export const VoidInputBox2 = forwardRef<HTMLTextAreaElement, InputBox2Props>(fun
})
export const VoidSimpleInputBox = ({ value, onChangeValue, placeholder, className, disabled, passwordBlur, compact, ...inputProps }: {
export const OrcideSimpleInputBox = ({ value, onChangeValue, placeholder, className, disabled, passwordBlur, compact, ...inputProps }: {
value: string;
onChangeValue: (value: string) => void;
placeholder: string;
@ -925,7 +925,7 @@ export const VoidSimpleInputBox = ({ value, onChangeValue, placeholder, classNam
onChange={handleChange}
placeholder={placeholder}
disabled={disabled}
className={`w-full resize-none bg-void-bg-1 text-void-fg-1 placeholder:text-void-fg-3 border border-void-border-2 focus:border-void-border-1
className={`w-full resize-none bg-orcide-bg-1 text-orcide-fg-1 placeholder:text-orcide-fg-3 border border-orcide-border-2 focus:border-orcide-border-1
${compact ? 'py-1 px-2' : 'py-2 px-4 '}
rounded
${disabled ? 'opacity-50 cursor-not-allowed' : ''}
@ -942,7 +942,7 @@ export const VoidSimpleInputBox = ({ value, onChangeValue, placeholder, classNam
};
export const VoidInputBox = ({ onChangeText, onCreateInstance, inputBoxRef, placeholder, isPasswordField, multiline }: {
export const OrcideInputBox = ({ onChangeText, onCreateInstance, inputBoxRef, placeholder, isPasswordField, multiline }: {
onChangeText: (value: string) => void;
styles?: Partial<IInputBoxStyles>,
onCreateInstance?: (instance: InputBox) => void | IDisposable[];
@ -957,8 +957,8 @@ export const VoidInputBox = ({ onChangeText, onCreateInstance, inputBoxRef, plac
const contextViewProvider = accessor.get('IContextViewService')
return <WidgetComponent
className='
bg-void-bg-1
@@void-force-child-placeholder-void-fg-1
bg-orcide-bg-1
@@orcide-force-child-placeholder-orcide-fg-1
'
ctor={InputBox}
propsFn={useCallback((container) => [
@ -1004,7 +1004,7 @@ export const VoidInputBox = ({ onChangeText, onCreateInstance, inputBoxRef, plac
export const VoidSlider = ({
export const OrcideSlider = ({
value,
onChange,
size = 'md',
@ -1108,7 +1108,7 @@ export const VoidSlider = ({
size === 'xs' ? 'h-1' :
size === 'sm' ? 'h-1.5' :
size === 'sm+' ? 'h-2' : 'h-2.5'
} bg-void-bg-2 rounded-full cursor-pointer`}
} bg-orcide-bg-2 rounded-full cursor-pointer`}
onClick={handleTrackClick}
>
{/* Filled part of track */}
@ -1117,7 +1117,7 @@ export const VoidSlider = ({
size === 'xs' ? 'h-1' :
size === 'sm' ? 'h-1.5' :
size === 'sm+' ? 'h-2' : 'h-2.5'
} bg-void-fg-1 rounded-full`}
} bg-orcide-fg-1 rounded-full`}
style={{ width: `${percentage}%` }}
/>
</div>
@ -1130,8 +1130,8 @@ export const VoidSlider = ({
size === 'sm' ? 'h-3 w-3' :
size === 'sm+' ? 'h-3.5 w-3.5' : 'h-4 w-4'
}
bg-void-fg-1 rounded-full shadow-md ${disabled ? 'cursor-not-allowed' : 'cursor-grab active:cursor-grabbing'}
border border-void-fg-1`}
bg-orcide-fg-1 rounded-full shadow-md ${disabled ? 'cursor-not-allowed' : 'cursor-grab active:cursor-grabbing'}
border border-orcide-fg-1`}
style={{ left: `${percentage}%`, zIndex: 2 }} // Ensure thumb is above the invisible clickable area
onMouseDown={(e) => {
if (disabled) return;
@ -1165,7 +1165,7 @@ export const VoidSlider = ({
export const VoidSwitch = ({
export const OrcideSwitch = ({
value,
onChange,
size = 'md',
@ -1217,7 +1217,7 @@ export const VoidSwitch = ({
export const VoidCheckBox = ({ label, value, onClick, className }: { label: string, value: boolean, onClick: (checked: boolean) => void, className?: string }) => {
export const OrcideCheckBox = ({ label, value, onClick, className }: { label: string, value: boolean, onClick: (checked: boolean) => void, className?: string }) => {
const divRef = useRef<HTMLDivElement | null>(null)
const instanceRef = useRef<Checkbox | null>(null)
@ -1251,7 +1251,7 @@ export const VoidCheckBox = ({ label, value, onClick, className }: { label: stri
export const VoidCustomDropdownBox = <T extends NonNullable<any>>({
export const OrcideCustomDropdownBox = <T extends NonNullable<any>>({
options,
selectedOption,
onChangeOption,
@ -1416,7 +1416,7 @@ export const VoidCustomDropdownBox = <T extends NonNullable<any>>({
{isOpen && (
<div
ref={refs.setFloating}
className="z-[100] bg-void-bg-1 border-void-border-3 border rounded shadow-lg"
className="z-[100] bg-orcide-bg-1 border-orcide-border-3 border rounded shadow-lg"
style={{
position: strategy,
top: y ?? 0,
@ -1478,7 +1478,7 @@ export const VoidCustomDropdownBox = <T extends NonNullable<any>>({
export const _VoidSelectBox = <T,>({ onChangeSelection, onCreateInstance, selectBoxRef, options, className }: {
export const _OrcideSelectBox = <T,>({ onChangeSelection, onCreateInstance, selectBoxRef, options, className }: {
onChangeSelection: (value: T) => void;
onCreateInstance?: ((instance: SelectBox) => void | IDisposable[]);
selectBoxRef?: React.MutableRefObject<SelectBox | null>;
@ -1493,9 +1493,9 @@ export const _VoidSelectBox = <T,>({ onChangeSelection, onCreateInstance, select
return <WidgetComponent
className={`
@@select-child-restyle
@@[&_select]:!void-text-void-fg-3
@@[&_select]:!void-text-xs
!text-void-fg-3
@@[&_select]:!orcide-text-orcide-fg-3
@@[&_select]:!orcide-text-xs
!text-orcide-fg-3
${className ?? ''}
`}
ctor={SelectBox}
@ -1615,7 +1615,7 @@ export const BlockCode = ({ initValue, language, maxHeight, showScrollbars }: Bl
if (language) modelRef.current?.setLanguage(language)
}, [language])
return <div ref={divRef} className='relative z-0 px-2 py-1 bg-void-bg-3'>
return <div ref={divRef} className='relative z-0 px-2 py-1 bg-orcide-bg-3'>
<WidgetComponent
className='@@bg-editor-style-override' // text-sm
ctor={useCallback((container) => {
@ -1716,7 +1716,7 @@ export const BlockCode = ({ initValue, language, maxHeight, showScrollbars }: Bl
}
export const VoidButtonBgDarken = ({ children, disabled, onClick, className }: { children: React.ReactNode; disabled?: boolean; onClick: () => void; className?: string }) => {
export const OrcideButtonBgDarken = ({ children, disabled, onClick, className }: { children: React.ReactNode; disabled?: boolean; onClick: () => void; className?: string }) => {
return <button disabled={disabled}
className={`px-3 py-1 bg-black/10 dark:bg-white/10 rounded-sm overflow-hidden whitespace-nowrap flex items-center justify-center ${className || ''}`}
onClick={onClick}
@ -1793,7 +1793,7 @@ export const VoidButtonBgDarken = ({ children, disabled, onClick, className }: {
// export const VoidCheckBox = ({ onChangeChecked, initVal, label, checkboxRef, }: {
// export const OrcideCheckBox = ({ onChangeChecked, initVal, label, checkboxRef, }: {
// onChangeChecked: (checked: boolean) => void;
// initVal: boolean;
// checkboxRef: React.MutableRefObject<ObjectSettingCheckboxWidget | null>;
@ -1945,7 +1945,7 @@ const SingleDiffEditor = ({ block, lang }: { block: ExtractedSearchReplaceBlock,
}, [originalModel, modifiedModel, instantiationService]);
return (
<div className="w-full bg-void-bg-3 @@bg-editor-style-override" ref={divRef} />
<div className="w-full bg-orcide-bg-3 @@bg-editor-style-override" ref={divRef} />
);
};
@ -1975,7 +1975,7 @@ export const VoidDiffEditor = ({ uri, searchReplaceBlocks, language }: { uri?: a
// If no blocks, show empty state
if (blocks.length === 0) {
return <div className="w-full p-4 text-void-fg-4 text-sm">No changes found</div>;
return <div className="w-full p-4 text-orcide-fg-4 text-sm">No changes found</div>;
}
// Display all blocks
@ -1984,7 +1984,7 @@ export const VoidDiffEditor = ({ uri, searchReplaceBlocks, language }: { uri?: a
{blocks.map((block, index) => (
<div key={index} className="w-full">
{blocks.length > 1 && (
<div className="text-void-fg-4 text-xs mb-1 px-1">
<div className="text-orcide-fg-4 text-xs mb-1 px-1">
Change {index + 1} of {blocks.length}
</div>
)}

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import React, { useEffect, useState } from 'react';

View file

@ -1,14 +1,14 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import React, { useState, useEffect, useCallback } from 'react'
import { MCPUserState, RefreshableProviderName, SettingsOfProvider } from '../../../../../../../workbench/contrib/void/common/voidSettingsTypes.js'
import { MCPUserState, RefreshableProviderName, SettingsOfProvider } from '../../../../../../../workbench/contrib/orcide/common/orcideSettingsTypes.js'
import { DisposableStore, IDisposable } from '../../../../../../../base/common/lifecycle.js'
import { VoidSettingsState } from '../../../../../../../workbench/contrib/void/common/voidSettingsService.js'
import { OrcideSettingsState } from '../../../../../../../workbench/contrib/orcide/common/orcideSettingsService.js'
import { ColorScheme } from '../../../../../../../platform/theme/common/theme.js'
import { RefreshModelStateOfProvider } from '../../../../../../../workbench/contrib/void/common/refreshModelService.js'
import { RefreshModelStateOfProvider } from '../../../../../../../workbench/contrib/orcide/common/refreshModelService.js'
import { ServicesAccessor } from '../../../../../../../editor/browser/editorExtensions.js';
import { IExplorerService } from '../../../../../../../workbench/contrib/files/browser/files.js'
@ -19,9 +19,9 @@ import { IFileService } from '../../../../../../../platform/files/common/files.j
import { IHoverService } from '../../../../../../../platform/hover/browser/hover.js';
import { IThemeService } from '../../../../../../../platform/theme/common/themeService.js';
import { ILLMMessageService } from '../../../../common/sendLLMMessageService.js';
import { IRefreshModelService } from '../../../../../../../workbench/contrib/void/common/refreshModelService.js';
import { IVoidSettingsService } from '../../../../../../../workbench/contrib/void/common/voidSettingsService.js';
import { IExtensionTransferService } from '../../../../../../../workbench/contrib/void/browser/extensionTransferService.js'
import { IRefreshModelService } from '../../../../../../../workbench/contrib/orcide/common/refreshModelService.js';
import { IOrcideSettingsService } from '../../../../../../../workbench/contrib/orcide/common/orcideSettingsService.js';
import { IExtensionTransferService } from '../../../../../../../workbench/contrib/orcide/browser/extensionTransferService.js'
import { IInstantiationService } from '../../../../../../../platform/instantiation/common/instantiation.js'
import { ICodeEditorService } from '../../../../../../../editor/browser/services/codeEditorService.js'
@ -36,14 +36,14 @@ import { IKeybindingService } from '../../../../../../../platform/keybinding/com
import { IEnvironmentService } from '../../../../../../../platform/environment/common/environment.js'
import { IConfigurationService } from '../../../../../../../platform/configuration/common/configuration.js'
import { IPathService } from '../../../../../../../workbench/services/path/common/pathService.js'
import { IMetricsService } from '../../../../../../../workbench/contrib/void/common/metricsService.js'
import { IMetricsService } from '../../../../../../../workbench/contrib/orcide/common/metricsService.js'
import { URI } from '../../../../../../../base/common/uri.js'
import { IChatThreadService, ThreadsState, ThreadStreamState } from '../../../chatThreadService.js'
import { ITerminalToolService } from '../../../terminalToolService.js'
import { ILanguageService } from '../../../../../../../editor/common/languages/language.js'
import { IVoidModelService } from '../../../../common/voidModelService.js'
import { IOrcideModelService } from '../../../../common/orcideModelService.js'
import { IWorkspaceContextService } from '../../../../../../../platform/workspace/common/workspace.js'
import { IVoidCommandBarService } from '../../../voidCommandBarService.js'
import { IOrcideCommandBarService } from '../../../orcideCommandBarService.js'
import { INativeHostService } from '../../../../../../../platform/native/common/native.js';
import { IEditCodeService } from '../../../editCodeServiceInterface.js'
import { IToolsService } from '../../../toolsService.js'
@ -67,8 +67,8 @@ const chatThreadsStateListeners: Set<(s: ThreadsState) => void> = new Set()
let chatThreadsStreamState: ThreadStreamState
const chatThreadsStreamStateListeners: Set<(threadId: string) => void> = new Set()
let settingsState: VoidSettingsState
const settingsStateListeners: Set<(s: VoidSettingsState) => void> = new Set()
let settingsState: OrcideSettingsState
const settingsStateListeners: Set<(s: OrcideSettingsState) => void> = new Set()
let refreshModelState: RefreshModelStateOfProvider
const refreshModelStateListeners: Set<(s: RefreshModelStateOfProvider) => void> = new Set()
@ -94,16 +94,16 @@ export const _registerServices = (accessor: ServicesAccessor) => {
const stateServices = {
chatThreadsStateService: accessor.get(IChatThreadService),
settingsStateService: accessor.get(IVoidSettingsService),
settingsStateService: accessor.get(IOrcideSettingsService),
refreshModelService: accessor.get(IRefreshModelService),
themeService: accessor.get(IThemeService),
editCodeService: accessor.get(IEditCodeService),
voidCommandBarService: accessor.get(IVoidCommandBarService),
orcideCommandBarService: accessor.get(IOrcideCommandBarService),
modelService: accessor.get(IModelService),
mcpService: accessor.get(IMCPService),
}
const { settingsStateService, chatThreadsStateService, refreshModelService, themeService, editCodeService, voidCommandBarService, modelService, mcpService } = stateServices
const { settingsStateService, chatThreadsStateService, refreshModelService, themeService, editCodeService, orcideCommandBarService, modelService, mcpService } = stateServices
@ -159,13 +159,13 @@ export const _registerServices = (accessor: ServicesAccessor) => {
)
disposables.push(
voidCommandBarService.onDidChangeState(({ uri }) => {
orcideCommandBarService.onDidChangeState(({ uri }) => {
commandBarURIStateListeners.forEach(l => l(uri));
})
)
disposables.push(
voidCommandBarService.onDidChangeActiveURI(({ uri }) => {
orcideCommandBarService.onDidChangeActiveURI(({ uri }) => {
activeURIListeners.forEach(l => l(uri));
})
)
@ -193,7 +193,7 @@ const getReactAccessor = (accessor: ServicesAccessor) => {
IThemeService: accessor.get(IThemeService),
ILLMMessageService: accessor.get(ILLMMessageService),
IRefreshModelService: accessor.get(IRefreshModelService),
IVoidSettingsService: accessor.get(IVoidSettingsService),
IOrcideSettingsService: accessor.get(IOrcideSettingsService),
IEditCodeService: accessor.get(IEditCodeService),
IChatThreadService: accessor.get(IChatThreadService),
@ -216,11 +216,11 @@ const getReactAccessor = (accessor: ServicesAccessor) => {
IMetricsService: accessor.get(IMetricsService),
ITerminalToolService: accessor.get(ITerminalToolService),
ILanguageService: accessor.get(ILanguageService),
IVoidModelService: accessor.get(IVoidModelService),
IOrcideModelService: accessor.get(IOrcideModelService),
IWorkspaceContextService: accessor.get(IWorkspaceContextService),
IVoidCommandBarService: accessor.get(IVoidCommandBarService),
INativeHostService: accessor.get(INativeHostService),
IOrcideCommandBarService: accessor.get(IOrcideCommandBarService),
INativeHostService: (() => { try { return accessor.get(INativeHostService); } catch { return undefined; } })() as any,
IToolsService: accessor.get(IToolsService),
IConvertToLLMMessageService: accessor.get(IConvertToLLMMessageService),
ITerminalService: accessor.get(ITerminalService),
@ -246,7 +246,7 @@ const _registerAccessor = (accessor: ServicesAccessor) => {
// -- services --
export const useAccessor = () => {
if (!reactAccessor_) {
throw new Error(`⚠️ Void useAccessor was called before _registerServices!`)
throw new Error(`⚠️ Orcide useAccessor was called before _registerServices!`)
}
return { get: <S extends keyof ReactAccessor,>(service: S): ReactAccessor[S] => reactAccessor_![service] }
@ -363,7 +363,7 @@ export const useCommandBarURIListener = (listener: (uri: URI) => void) => {
};
export const useCommandBarState = () => {
const accessor = useAccessor()
const commandBarService = accessor.get('IVoidCommandBarService')
const commandBarService = accessor.get('IOrcideCommandBarService')
const [s, ss] = useState({ stateOfURI: commandBarService.stateOfURI, sortedURIs: commandBarService.sortedURIs });
const listener = useCallback(() => {
ss({ stateOfURI: commandBarService.stateOfURI, sortedURIs: commandBarService.sortedURIs });
@ -378,7 +378,7 @@ export const useCommandBarState = () => {
// roughly gets the active URI - this is used to get the history of recent URIs
export const useActiveURI = () => {
const accessor = useAccessor()
const commandBarService = accessor.get('IVoidCommandBarService')
const commandBarService = accessor.get('IOrcideCommandBarService')
const [s, ss] = useState(commandBarService.activeURI)
useEffect(() => {
const listener = () => { ss(commandBarService.activeURI) }

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
/** @type {import('tailwindcss').Config} */
@ -12,22 +12,22 @@ module.exports = {
typography: theme => ({
DEFAULT: {
css: {
'--tw-prose-body': 'var(--void-fg-1)',
'--tw-prose-headings': 'var(--void-fg-1)',
'--tw-prose-lead': 'var(--void-fg-2)',
'--tw-prose-links': 'var(--void-link-color)',
'--tw-prose-bold': 'var(--void-fg-1)',
'--tw-prose-counters': 'var(--void-fg-3)',
'--tw-prose-bullets': 'var(--void-fg-3)',
'--tw-prose-hr': 'var(--void-border-4)',
'--tw-prose-quotes': 'var(--void-fg-1)',
'--tw-prose-quote-borders': 'var(--void-border-2)',
'--tw-prose-captions': 'var(--void-fg-3)',
'--tw-prose-code': 'var(--void-fg-0)',
'--tw-prose-pre-code': 'var(--void-fg-0)',
'--tw-prose-pre-bg': 'var(--void-bg-1)',
'--tw-prose-th-borders': 'var(--void-border-4)',
'--tw-prose-td-borders': 'var(--void-border-4)',
'--tw-prose-body': 'var(--orcide-fg-1)',
'--tw-prose-headings': 'var(--orcide-fg-1)',
'--tw-prose-lead': 'var(--orcide-fg-2)',
'--tw-prose-links': 'var(--orcide-link-color)',
'--tw-prose-bold': 'var(--orcide-fg-1)',
'--tw-prose-counters': 'var(--orcide-fg-3)',
'--tw-prose-bullets': 'var(--orcide-fg-3)',
'--tw-prose-hr': 'var(--orcide-border-4)',
'--tw-prose-quotes': 'var(--orcide-fg-1)',
'--tw-prose-quote-borders': 'var(--orcide-border-2)',
'--tw-prose-captions': 'var(--orcide-fg-3)',
'--tw-prose-code': 'var(--orcide-fg-0)',
'--tw-prose-pre-code': 'var(--orcide-fg-0)',
'--tw-prose-pre-bg': 'var(--orcide-bg-1)',
'--tw-prose-th-borders': 'var(--orcide-border-4)',
'--tw-prose-td-borders': 'var(--orcide-border-4)',
},
},
}),
@ -49,30 +49,30 @@ module.exports = {
// common colors to use, ordered light to dark
colors: {
'void-bg-1': 'var(--void-bg-1)',
'void-bg-1-alt': 'var(--void-bg-1-alt)',
'void-bg-2': 'var(--void-bg-2)',
'void-bg-2-alt': 'var(--void-bg-2-alt)',
'void-bg-2-hover': 'var(--void-bg-2-hover)',
'void-bg-3': 'var(--void-bg-3)',
'orcide-bg-1': 'var(--orcide-bg-1)',
'orcide-bg-1-alt': 'var(--orcide-bg-1-alt)',
'orcide-bg-2': 'var(--orcide-bg-2)',
'orcide-bg-2-alt': 'var(--orcide-bg-2-alt)',
'orcide-bg-2-hover': 'var(--orcide-bg-2-hover)',
'orcide-bg-3': 'var(--orcide-bg-3)',
'void-fg-0': 'var(--void-fg-0)',
'void-fg-1': 'var(--void-fg-1)',
'void-fg-2': 'var(--void-fg-2)',
'void-fg-3': 'var(--void-fg-3)',
// 'void-fg-4': 'var(--vscode-tab-inactiveForeground)',
'void-fg-4': 'var(--void-fg-4)',
'orcide-fg-0': 'var(--orcide-fg-0)',
'orcide-fg-1': 'var(--orcide-fg-1)',
'orcide-fg-2': 'var(--orcide-fg-2)',
'orcide-fg-3': 'var(--orcide-fg-3)',
// 'orcide-fg-4': 'var(--vscode-tab-inactiveForeground)',
'orcide-fg-4': 'var(--orcide-fg-4)',
'void-warning': 'var(--void-warning)',
'orcide-warning': 'var(--orcide-warning)',
'void-border-1': 'var(--void-border-1)',
'void-border-2': 'var(--void-border-2)',
'void-border-3': 'var(--void-border-3)',
'void-border-4': 'var(--void-border-4)',
'orcide-border-1': 'var(--orcide-border-1)',
'orcide-border-2': 'var(--orcide-border-2)',
'orcide-border-3': 'var(--orcide-border-3)',
'orcide-border-4': 'var(--orcide-border-4)',
'void-ring-color': 'var(--void-ring-color)',
'void-link-color': 'var(--void-link-color)',
'orcide-ring-color': 'var(--orcide-ring-color)',
'orcide-link-color': 'var(--orcide-link-color)',
vscode: {
// see: https://code.visualstudio.com/api/extension-guides/webview#theming-webview-content
@ -194,6 +194,6 @@ module.exports = {
plugins: [
require('@tailwindcss/typography')
],
prefix: 'void-'
prefix: 'orcide-'
}

View file

@ -1,17 +1,17 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { defineConfig } from 'tsup'
export default defineConfig({
entry: [
'./src2/void-editor-widgets-tsx/index.tsx',
'./src2/orcide-editor-widgets-tsx/index.tsx',
'./src2/sidebar-tsx/index.tsx',
'./src2/void-settings-tsx/index.tsx',
'./src2/void-tooltip/index.tsx',
'./src2/void-onboarding/index.tsx',
'./src2/orcide-settings-tsx/index.tsx',
'./src2/orcide-tooltip/index.tsx',
'./src2/orcide-onboarding/index.tsx',
'./src2/quick-edit-tsx/index.tsx',
'./src2/diff/index.tsx',
],

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { KeyCode, KeyMod } from '../../../../base/common/keyCodes.js';
@ -14,11 +14,11 @@ import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextke
import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';
import { IRange } from '../../../../editor/common/core/range.js';
import { VOID_VIEW_CONTAINER_ID, VOID_VIEW_ID } from './sidebarPane.js';
import { ORCIDE_VIEW_CONTAINER_ID, ORCIDE_VIEW_ID } from './sidebarPane.js';
import { IMetricsService } from '../common/metricsService.js';
import { ICommandService } from '../../../../platform/commands/common/commands.js';
import { VOID_TOGGLE_SETTINGS_ACTION_ID } from './voidSettingsPane.js';
import { VOID_CTRL_L_ACTION_ID } from './actionIDs.js';
import { ORCIDE_TOGGLE_SETTINGS_ACTION_ID } from './orcideSettingsPane.js';
import { ORCIDE_CTRL_L_ACTION_ID } from './actionIDs.js';
import { localize2 } from '../../../../nls.js';
import { IChatThreadService } from './chatThreadService.js';
import { IViewsService } from '../../../services/views/common/viewsService.js';
@ -61,15 +61,15 @@ export const roundRangeToLines = (range: IRange | null | undefined, options: { e
const VOID_OPEN_SIDEBAR_ACTION_ID = 'void.sidebar.open'
const ORCIDE_OPEN_SIDEBAR_ACTION_ID = 'orcide.sidebar.open'
registerAction2(class extends Action2 {
constructor() {
super({ id: VOID_OPEN_SIDEBAR_ACTION_ID, title: localize2('voidOpenSidebar', 'Void: Open Sidebar'), f1: true });
super({ id: ORCIDE_OPEN_SIDEBAR_ACTION_ID, title: localize2('voidOpenSidebar', 'Orcide: Open Sidebar'), f1: true });
}
async run(accessor: ServicesAccessor): Promise<void> {
const viewsService = accessor.get(IViewsService)
const chatThreadsService = accessor.get(IChatThreadService)
viewsService.openViewContainer(VOID_VIEW_CONTAINER_ID)
viewsService.openViewContainer(ORCIDE_VIEW_CONTAINER_ID)
await chatThreadsService.focusCurrentChat()
}
})
@ -79,12 +79,12 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_CTRL_L_ACTION_ID,
id: ORCIDE_CTRL_L_ACTION_ID,
f1: true,
title: localize2('voidCmdL', 'Void: Add Selection to Chat'),
title: localize2('voidCmdL', 'Orcide: Add Selection to Chat'),
keybinding: {
primary: KeyMod.CtrlCmd | KeyCode.KeyL,
weight: KeybindingWeight.VoidExtension
weight: KeybindingWeight.OrcideExtension
}
});
}
@ -106,9 +106,9 @@ registerAction2(class extends Action2 {
const selectionRange = roundRangeToLines(editor?.getSelection(), { emptySelectionBehavior: 'null' })
// open panel
const wasAlreadyOpen = viewsService.isViewContainerVisible(VOID_VIEW_CONTAINER_ID)
const wasAlreadyOpen = viewsService.isViewContainerVisible(ORCIDE_VIEW_CONTAINER_ID)
if (!wasAlreadyOpen) {
await commandService.executeCommand(VOID_OPEN_SIDEBAR_ACTION_ID)
await commandService.executeCommand(ORCIDE_OPEN_SIDEBAR_ACTION_ID)
}
// Add selection to chat
@ -144,18 +144,18 @@ registerAction2(class extends Action2 {
// New chat keybind + menu button
const VOID_CMD_SHIFT_L_ACTION_ID = 'void.cmdShiftL'
const ORCIDE_CMD_SHIFT_L_ACTION_ID = 'orcide.cmdShiftL'
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_CMD_SHIFT_L_ACTION_ID,
id: ORCIDE_CMD_SHIFT_L_ACTION_ID,
title: 'New Chat',
keybinding: {
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyL,
weight: KeybindingWeight.VoidExtension,
weight: KeybindingWeight.OrcideExtension,
},
icon: { id: 'add' },
menu: [{ id: MenuId.ViewTitle, group: 'navigation', when: ContextKeyExpr.equals('view', VOID_VIEW_ID), }],
menu: [{ id: MenuId.ViewTitle, group: 'navigation', when: ContextKeyExpr.equals('view', ORCIDE_VIEW_ID), }],
});
}
async run(accessor: ServicesAccessor): Promise<void> {
@ -209,10 +209,10 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: 'void.historyAction',
id: 'orcide.historyAction',
title: 'View Past Chats',
icon: { id: 'history' },
menu: [{ id: MenuId.ViewTitle, group: 'navigation', when: ContextKeyExpr.equals('view', VOID_VIEW_ID), }]
menu: [{ id: MenuId.ViewTitle, group: 'navigation', when: ContextKeyExpr.equals('view', ORCIDE_VIEW_ID), }]
});
}
async run(accessor: ServicesAccessor): Promise<void> {
@ -229,7 +229,7 @@ registerAction2(class extends Action2 {
const commandService = accessor.get(ICommandService)
metricsService.capture('Chat Navigation', { type: 'History' })
commandService.executeCommand(VOID_CMD_SHIFT_L_ACTION_ID)
commandService.executeCommand(ORCIDE_CMD_SHIFT_L_ACTION_ID)
}
})
@ -239,15 +239,15 @@ registerAction2(class extends Action2 {
registerAction2(class extends Action2 {
constructor() {
super({
id: 'void.settingsAction',
title: `Void's Settings`,
id: 'orcide.settingsAction',
title: `Orcide Settings`,
icon: { id: 'settings-gear' },
menu: [{ id: MenuId.ViewTitle, group: 'navigation', when: ContextKeyExpr.equals('view', VOID_VIEW_ID), }]
menu: [{ id: MenuId.ViewTitle, group: 'navigation', when: ContextKeyExpr.equals('view', ORCIDE_VIEW_ID), }]
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const commandService = accessor.get(ICommandService)
commandService.executeCommand(VOID_TOGGLE_SETTINGS_ACTION_ID)
commandService.executeCommand(ORCIDE_TOGGLE_SETTINGS_ACTION_ID)
}
})

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Registry } from '../../../../platform/registry/common/platform.js';
@ -97,19 +97,19 @@ class SidebarViewPane extends ViewPane {
// ---------- Register viewpane inside the void container ----------
// const voidThemeIcon = Codicon.symbolObject;
// const voidViewIcon = registerIcon('void-view-icon', voidThemeIcon, localize('voidViewIcon', 'View icon of the Void chat view.'));
// const orcideThemeIcon = Codicon.symbolObject;
// const orcideViewIcon = registerIcon('orcide-view-icon', orcideThemeIcon, localize('orcideViewIcon', 'View icon of the Orcide chat view.'));
// called VIEWLET_ID in other places for some reason
export const VOID_VIEW_CONTAINER_ID = 'workbench.view.void'
export const VOID_VIEW_ID = VOID_VIEW_CONTAINER_ID
export const ORCIDE_VIEW_CONTAINER_ID = 'workbench.view.orcide'
export const ORCIDE_VIEW_ID = ORCIDE_VIEW_CONTAINER_ID
// Register view container
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
const container = viewContainerRegistry.registerViewContainer({
id: VOID_VIEW_CONTAINER_ID,
title: nls.localize2('voidContainer', 'Chat'), // this is used to say "Void" (Ctrl + L)
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [VOID_VIEW_CONTAINER_ID, {
id: ORCIDE_VIEW_CONTAINER_ID,
title: nls.localize2('orcideContainer', 'Chat'), // this is used to say "Orcide" (Ctrl + L)
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [ORCIDE_VIEW_CONTAINER_ID, {
mergeViewWithContainerWhenSingleView: true,
orientation: Orientation.HORIZONTAL,
}]),
@ -127,9 +127,9 @@ const container = viewContainerRegistry.registerViewContainer({
// Register search default location to the container (sidebar)
const viewsRegistry = Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry);
viewsRegistry.registerViews([{
id: VOID_VIEW_ID,
id: ORCIDE_VIEW_ID,
hideByDefault: false, // start open
// containerIcon: voidViewIcon,
// containerIcon: orcideViewIcon,
name: nls.localize2('voidChat', ''), // this says ... : CHAT
ctorDescriptor: new SyncDescriptor(SidebarViewPane),
canToggleVisibility: false,
@ -139,7 +139,7 @@ viewsRegistry.registerViews([{
// singleViewPaneContainerTitle: 'hi',
// openCommandActionDescriptor: {
// id: VOID_VIEW_CONTAINER_ID,
// id: ORCIDE_VIEW_CONTAINER_ID,
// keybindings: {
// primary: KeyMod.CtrlCmd | KeyCode.KeyL,
// },
@ -149,26 +149,26 @@ viewsRegistry.registerViews([{
// open sidebar
export const VOID_OPEN_SIDEBAR_ACTION_ID = 'void.openSidebar'
export const ORCIDE_OPEN_SIDEBAR_ACTION_ID = 'orcide.openSidebar'
registerAction2(class extends Action2 {
constructor() {
super({
id: VOID_OPEN_SIDEBAR_ACTION_ID,
title: 'Open Void Sidebar',
id: ORCIDE_OPEN_SIDEBAR_ACTION_ID,
title: 'Open Orcide Sidebar',
})
}
run(accessor: ServicesAccessor): void {
const viewsService = accessor.get(IViewsService)
viewsService.openViewContainer(VOID_VIEW_CONTAINER_ID);
viewsService.openViewContainer(ORCIDE_VIEW_CONTAINER_ID);
}
});
export class SidebarStartContribution implements IWorkbenchContribution {
static readonly ID = 'workbench.contrib.startupVoidSidebar';
static readonly ID = 'workbench.contrib.startupOrcideSidebar';
constructor(
@ICommandService private readonly commandService: ICommandService,
) {
this.commandService.executeCommand(VOID_OPEN_SIDEBAR_ACTION_ID)
this.commandService.executeCommand(ORCIDE_OPEN_SIDEBAR_ACTION_ID)
}
}
registerWorkbenchContribution2(SidebarStartContribution.ID, SidebarStartContribution, WorkbenchPhase.AfterRestored);

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable, IDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
@ -53,13 +53,13 @@ export const ITerminalToolService = createDecorator<ITerminalToolService>('Termi
export const persistentTerminalNameOfId = (id: string) => {
if (id === '1') return 'Void Agent'
return `Void Agent (${id})`
if (id === '1') return 'Orcide Agent'
return `Orcide Agent (${id})`
}
export const idOfPersistentTerminalName = (name: string) => {
if (name === 'Void Agent') return '1'
if (name === 'Orcide Agent') return '1'
const match = name.match(/Void Agent \((\d+)\)/)
const match = name.match(/Orcide Agent \((\d+)\)/)
if (!match) return null
if (Number.isInteger(match[1]) && Number(match[1]) >= 1) return match[1]
return null
@ -297,7 +297,7 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ
const cmdCap = await this._waitForCommandDetectionCapability(terminal)
// if (!cmdCap) throw new Error(`There was an error using the terminal: CommandDetection capability did not mount yet. Please try again in a few seconds or report this to the Void team.`)
// if (!cmdCap) throw new Error(`There was an error using the terminal: CommandDetection capability did not mount yet. Please try again in a few seconds or report this to the Orcide team.`)
// Prefer the structured command-detection capability when available

View file

@ -9,15 +9,15 @@ import { ISearchService } from '../../../services/search/common/search.js'
import { IEditCodeService } from './editCodeServiceInterface.js'
import { ITerminalToolService } from './terminalToolService.js'
import { LintErrorItem, BuiltinToolCallParams, BuiltinToolResultType, BuiltinToolName } from '../common/toolsServiceTypes.js'
import { IVoidModelService } from '../common/voidModelService.js'
import { IOrcideModelService } from '../common/orcideModelService.js'
import { EndOfLinePreference } from '../../../../editor/common/model.js'
import { IVoidCommandBarService } from './voidCommandBarService.js'
import { IOrcideCommandBarService } from './orcideCommandBarService.js'
import { computeDirectoryTree1Deep, IDirectoryStrService, stringifyDirectoryTree1Deep } from '../common/directoryStrService.js'
import { IMarkerService, MarkerSeverity } from '../../../../platform/markers/common/markers.js'
import { timeout } from '../../../../base/common/async.js'
import { RawToolParamsObj } from '../common/sendLLMMessageTypes.js'
import { MAX_CHILDREN_URIs_PAGE, MAX_FILE_CHARS_PAGE, MAX_TERMINAL_BG_COMMAND_TIME, MAX_TERMINAL_INACTIVE_TIME } from '../common/prompt/prompts.js'
import { IVoidSettingsService } from '../common/voidSettingsService.js'
import { IOrcideSettingsService } from '../common/orcideSettingsService.js'
import { generateUuid } from '../../../../base/common/uuid.js'
@ -146,13 +146,13 @@ export class ToolsService implements IToolsService {
@IWorkspaceContextService workspaceContextService: IWorkspaceContextService,
@ISearchService searchService: ISearchService,
@IInstantiationService instantiationService: IInstantiationService,
@IVoidModelService voidModelService: IVoidModelService,
@IOrcideModelService orcideModelService: IOrcideModelService,
@IEditCodeService editCodeService: IEditCodeService,
@ITerminalToolService private readonly terminalToolService: ITerminalToolService,
@IVoidCommandBarService private readonly commandBarService: IVoidCommandBarService,
@IOrcideCommandBarService private readonly commandBarService: IOrcideCommandBarService,
@IDirectoryStrService private readonly directoryStrService: IDirectoryStrService,
@IMarkerService private readonly markerService: IMarkerService,
@IVoidSettingsService private readonly voidSettingsService: IVoidSettingsService,
@IOrcideSettingsService private readonly orcideSettingsService: IOrcideSettingsService,
) {
const queryBuilder = instantiationService.createInstance(QueryBuilder);
@ -295,8 +295,8 @@ export class ToolsService implements IToolsService {
this.callTool = {
read_file: async ({ uri, startLine, endLine, pageNumber }) => {
await voidModelService.initializeModel(uri)
const { model } = await voidModelService.getModelSafe(uri)
await orcideModelService.initializeModel(uri)
const { model } = await orcideModelService.getModelSafe(uri)
if (model === null) { throw new Error(`No contents; File does not exist.`) }
let contents: string
@ -370,8 +370,8 @@ export class ToolsService implements IToolsService {
return { result: { queryStr, uris, hasNextPage } }
},
search_in_file: async ({ uri, query, isRegex }) => {
await voidModelService.initializeModel(uri);
const { model } = await voidModelService.getModelSafe(uri);
await orcideModelService.initializeModel(uri);
const { model } = await orcideModelService.getModelSafe(uri);
if (model === null) { throw new Error(`No contents; File does not exist.`); }
const contents = model.getValue(EndOfLinePreference.LF);
const contentOfLine = contents.split('\n');
@ -411,7 +411,7 @@ export class ToolsService implements IToolsService {
},
rewrite_file: async ({ uri, newContent }) => {
await voidModelService.initializeModel(uri)
await orcideModelService.initializeModel(uri)
if (this.commandBarService.getStreamState(uri) === 'streaming') {
throw new Error(`Another LLM is currently making changes to this file. Please stop streaming for now and ask the user to resume later.`)
}
@ -427,7 +427,7 @@ export class ToolsService implements IToolsService {
},
edit_file: async ({ uri, searchReplaceBlocks }) => {
await voidModelService.initializeModel(uri)
await orcideModelService.initializeModel(uri)
if (this.commandBarService.getStreamState(uri) === 'streaming') {
throw new Error(`Another LLM is currently making changes to this file. Please stop streaming for now and ask the user to resume later.`)
}
@ -492,7 +492,7 @@ export class ToolsService implements IToolsService {
return result.uris.map(uri => uri.fsPath).join('\n') + nextPageStr(result.hasNextPage)
},
search_in_file: (params, result) => {
const { model } = voidModelService.getModel(params.uri)
const { model } = orcideModelService.getModel(params.uri)
if (!model) return '<Error getting string of result>'
const lines = result.lines.map(n => {
const lineContent = model.getValueInRange({ startLineNumber: n, startColumn: 1, endLineNumber: n, endColumn: Number.MAX_SAFE_INTEGER }, EndOfLinePreference.LF)
@ -514,7 +514,7 @@ export class ToolsService implements IToolsService {
},
edit_file: (params, result) => {
const lintErrsString = (
this.voidSettingsService.state.globalSettings.includeToolLintErrors ?
this.orcideSettingsService.state.globalSettings.includeToolLintErrors ?
(result.lintErrors ? ` Lint errors found after change:\n${stringifyLintErrors(result.lintErrors)}.\nIf this is related to a change made while calling this tool, you might want to fix the error.`
: ` No lint errors found.`)
: '')
@ -523,7 +523,7 @@ export class ToolsService implements IToolsService {
},
rewrite_file: (params, result) => {
const lintErrsString = (
this.voidSettingsService.state.globalSettings.includeToolLintErrors ?
this.orcideSettingsService.state.globalSettings.includeToolLintErrors ?
(result.lintErrors ? ` Lint errors found after change:\n${stringifyLintErrors(result.lintErrors)}.\nIf this is related to a change made while calling this tool, you might want to fix the error.`
: ` No lint errors found.`)
: '')
@ -538,7 +538,7 @@ export class ToolsService implements IToolsService {
}
// normal command
if (resolveReason.type === 'timeout') {
return `${result_}\nTerminal command ran, but was automatically killed by Void after ${MAX_TERMINAL_INACTIVE_TIME}s of inactivity and did not finish successfully. To try with more time, open a persistent terminal and run the command there.`
return `${result_}\nTerminal command ran, but was automatically killed by Orcide after ${MAX_TERMINAL_INACTIVE_TIME}s of inactivity and did not finish successfully. To try with more time, open a persistent terminal and run the command there.`
}
throw new Error(`Unexpected internal error: Terminal command did not resolve with a valid reason.`)
},

View file

@ -1,13 +1,13 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Disposable, toDisposable } from '../../../../base/common/lifecycle.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js';
import { mountVoidTooltip } from './react/out/void-tooltip/index.js';
import { mountOrcideTooltip } from './react/out/orcide-tooltip/index.js';
import { h, getActiveWindow } from '../../../../base/browser/dom.js';
// Tooltip contribution that mounts the component at startup
@ -30,12 +30,12 @@ export class TooltipContribution extends Disposable implements IWorkbenchContrib
if (workbench) {
// Create a container element for the tooltip using h function
const tooltipContainer = h('div.void-tooltip-container').root;
const tooltipContainer = h('div.orcide-tooltip-container').root;
workbench.appendChild(tooltipContainer);
// Mount the React component
this.instantiationService.invokeFunction((accessor: ServicesAccessor) => {
const result = mountVoidTooltip(tooltipContainer, accessor);
const result = mountOrcideTooltip(tooltipContainer, accessor);
if (result && typeof result.dispose === 'function') {
this._register(toDisposable(result.dispose));
}

View file

@ -1,10 +1,10 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { URI } from '../../../../base/common/uri.js';
import { VoidFileSnapshot } from './editCodeServiceTypes.js';
import { OrcideFileSnapshot } from './editCodeServiceTypes.js';
import { AnthropicReasoning, RawToolParamsObj } from './sendLLMMessageTypes.js';
import { ToolCallParams, ToolName, ToolResult } from './toolsServiceTypes.js';
@ -38,10 +38,10 @@ export type DecorativeCanceledTool = {
export type CheckpointEntry = {
role: 'checkpoint';
type: 'user_edit' | 'tool_edit';
voidFileSnapshotOfURI: { [fsPath: string]: VoidFileSnapshot | undefined };
orcideFileSnapshotOfURI: { [fsPath: string]: OrcideFileSnapshot | undefined };
userModifications: {
voidFileSnapshotOfURI: { [fsPath: string]: VoidFileSnapshot | undefined };
orcideFileSnapshotOfURI: { [fsPath: string]: OrcideFileSnapshot | undefined };
};
}

View file

@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { URI } from '../../../../base/common/uri.js';
@ -31,7 +31,7 @@ export interface IDirectoryStrService {
getAllURIsInDirectory(uri: URI, opts: { maxResults: number }): Promise<URI[]>
}
export const IDirectoryStrService = createDecorator<IDirectoryStrService>('voidDirectoryStrService');
export const IDirectoryStrService = createDecorator<IDirectoryStrService>('orcideDirectoryStrService');

Some files were not shown because too many files have changed in this diff Show more