Merge pull request #19 from orcest-ai/claude/rebrand-orcide-llm-qNsCI

feat: Complete Orcide rebrand with RainyModel default LLM, enterprise…
This commit is contained in:
Danial Samiei 2026-02-21 19:08:56 +03:30 committed by GitHub
commit 37504b8698
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
125 changed files with 3494 additions and 1613 deletions

View file

@ -1,6 +1,6 @@
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.

View file

@ -2,7 +2,7 @@
The Orcide codebase is not as intimidating as it seems!
Most of Orcide'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 Orcide's codebase works. If you want build instructions instead, see [Contributing](https://github.com/orcest-ai/Orcide/blob/main/HOW_TO_CONTRIBUTE.md).
@ -97,10 +97,10 @@ How Apply works:
### Writing Files Inner Workings
When Orcide wants to change your code, it just writes to a text model. This means all you need to know to write to a file is its URI - you don't have to load it, save it, etc. There are some annoying background URI/model things to think about to get this to work, but we handled them all in `voidModelService`.
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`.
### Orcide Settings Inner Workings
We have a service `voidSettingsService` that stores all your Orcide settings (providers, models, global Orcide settings, etc). Imagine this as an implicit dependency for any of the core Orcide services:
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">

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

@ -10,8 +10,8 @@
"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",

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/voidUpdateService.js';
import { MetricsMainService } from '../../workbench/contrib/orcide/electron-main/metricsMainService.js';
import { VoidMainUpdateService } from '../../workbench/contrib/orcide/electron-main/voidUpdateMainService.js';
import { LLMMessageChannel } from '../../workbench/contrib/orcide/electron-main/sendLLMMessageChannel.js';
import { VoidSCMService } from '../../workbench/contrib/orcide/electron-main/voidSCMMainService.js';
import { IOrcideSCMService } from '../../workbench/contrib/orcide/common/voidSCMTypes.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(VoidMainUpdateService, undefined, false));
services.set(IOrcideSCMService, new SyncDescriptor(VoidSCMService, 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

@ -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 { VOID_CTRL_K_ACTION_ID, VOID_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 */

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';
@ -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,15 +279,15 @@ 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/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',

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', 'Orcide: 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

@ -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,7 +62,7 @@ import './miscWokrbenchContrib.js'
import './fileService.js'
// register source control management
import './voidSCMService.js'
import './orcideSCMService.js'
// ---------- Orcide SSO & Profile services ----------
@ -74,8 +74,8 @@ import './orcideSSOBrowserService.js'
// llmMessage
import '../common/sendLLMMessageService.js'
// orcideSettings (previously voidSettings)
import '../common/voidSettingsService.js'
// orcideSettings (previously orcideSettings)
import '../common/orcideSettingsService.js'
// refreshModel
import '../common/refreshModelService.js'
@ -84,10 +84,10 @@ 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'
@ -97,3 +97,12 @@ 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

@ -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,14 +10,14 @@ import { generateUuid } from '../../../../base/common/uuid.js';
import { ILLMMessageService } from '../common/sendLLMMessageService.js';
import { ServiceSendLLMMessageParams, ServiceModelListParams, OllamaModelResponse, OpenaiCompatibleModelResponse } from '../common/sendLLMMessageTypes.js';
import { IVoidSettingsService } from '../common/voidSettingsService.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 { IVoidUpdateService } from '../common/voidUpdateService.js';
import { IGenerateCommitMessageService } from './voidSCMService.js';
import { ProviderName } from '../common/voidSettingsTypes.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>> = {
@ -34,7 +34,7 @@ class LLMMessageServiceWeb extends Disposable implements ILLMMessageService {
private readonly _abortControllers = new Map<string, AbortController>();
constructor(
@IVoidSettingsService private readonly voidSettingsService: IVoidSettingsService,
@IOrcideSettingsService private readonly orcideSettingsService: IOrcideSettingsService,
) {
super();
}
@ -43,7 +43,7 @@ class LLMMessageServiceWeb extends Disposable implements ILLMMessageService {
const { onError, modelSelection } = params;
if (modelSelection === null) {
onError({ message: 'Please add a provider in Void\'s Settings.', fullError: null });
onError({ message: 'Please add a provider in Orcide\'s Settings.', fullError: null });
return null;
}
@ -76,13 +76,13 @@ class LLMMessageServiceWeb extends Disposable implements ILLMMessageService {
if (params.messagesType !== 'chatMessages' || !modelSelection) return;
try {
const { settingsOfProvider } = this.voidSettingsService.state;
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 Void Settings.`,
message: `API key not set for ${modelSelection.providerName}. Please configure it in Orcide Settings.`,
fullError: null
});
return;
@ -274,9 +274,9 @@ class MetricsServiceWeb implements IMetricsService {
}
class VoidUpdateServiceWeb implements IVoidUpdateService {
class OrcideUpdateServiceWeb implements IOrcideUpdateService {
readonly _serviceBrand: undefined;
check: IVoidUpdateService['check'] = async () => null;
check: IOrcideUpdateService['check'] = async () => null;
}
@ -290,5 +290,5 @@ class GenerateCommitMessageServiceWeb implements IGenerateCommitMessageService {
registerSingleton(ILLMMessageService, LLMMessageServiceWeb, InstantiationType.Eager);
registerSingleton(IMCPService, MCPServiceWeb, InstantiationType.Eager);
registerSingleton(IMetricsService, MetricsServiceWeb, InstantiationType.Eager);
registerSingleton(IVoidUpdateService, VoidUpdateServiceWeb, 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,12 +9,12 @@ 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'
@ -47,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,
@ -61,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() {
@ -87,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 }
@ -160,7 +160,7 @@ class GenerateCommitMessageService extends Disposable implements IGenerateCommit
onAbort: () => {
reject(new CancellationError())
},
logging: { loggingName: 'VoidSCM - Commit Message' },
logging: { loggingName: 'OrcideSCM - Commit Message' },
})
})
}
@ -186,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,
@ -208,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,

View file

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

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,7 +63,7 @@ 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;
@ -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', 'Orcide 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', "Orcide 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', "Orcide: 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', "Orcide: 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', "Orcide 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,17 +10,17 @@ 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 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,7 +31,7 @@ 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,
@ -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,7 +83,7 @@ const notifyUpdate = (res: VoidCheckUpdateRespose & { message: string }, notifSe
}
primary.push({
id: 'void.updater.site',
id: 'orcide.updater.site',
enabled: true,
label: `Orcide Site`,
tooltip: '',
@ -97,7 +97,7 @@ const notifyUpdate = (res: VoidCheckUpdateRespose & { message: string }, notifSe
actions = {
primary: primary,
secondary: [{
id: 'void.updater.close',
id: 'orcide.updater.close',
enabled: true,
label: `Keep current version`,
tooltip: '',
@ -137,10 +137,10 @@ 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> => {
@ -148,7 +148,7 @@ const performVoidCheck = async (
const metricsTag = explicit ? 'Manual' : 'Auto'
metricsService.capture(`Orcide Update ${metricsTag}: Checking...`, {})
const res = await voidUpdateService.check(explicit)
const res = await orcideUpdateService.check(explicit)
if (!res) {
const notifController = notifyErrChecking(notifService);
metricsService.capture(`Orcide Update ${metricsTag}: Error`, { res })
@ -176,19 +176,19 @@ registerAction2(class extends Action2 {
constructor() {
super({
f1: true,
id: 'void.voidCheckUpdate',
title: localize2('voidCheckUpdate', 'Orcide: 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,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 { execSync } from 'child_process';
@ -33,7 +33,7 @@ This function finds `globalDesiredPath` given `localDesiredPath` and `currentPat
Diagram:
...basePath/
void/
orcide/
...currentPath/ (defined globally)
...localDesiredPath/ (defined locally)
@ -60,7 +60,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 +87,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 +103,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 +145,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

@ -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,10 +561,10 @@ 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}
ringSize={orcideSettingsState.globalSettings.isOnboardingComplete ? 'screen' : undefined}
>Enter Orcide</PrimaryActionButton>
</div>
</div>
@ -586,10 +604,10 @@ 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 } = {
@ -597,12 +615,19 @@ const VoidOnboardingContent = () => {
content={
<div className='flex flex-col items-center gap-8'>
<div className="text-5xl font-light text-center">Welcome to Orcide</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-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

@ -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/orcest-ai/Orcide/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

@ -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,10 +216,10 @@ 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),
IOrcideCommandBarService: accessor.get(IOrcideCommandBarService),
INativeHostService: (() => { try { return accessor.get(INativeHostService); } catch { return undefined; } })() as any,
IToolsService: accessor.get(IToolsService),
IConvertToLLMMessageService: accessor.get(IConvertToLLMMessageService),
@ -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', 'Orcide: 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', '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',
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,
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');

View file

@ -1,10 +1,10 @@
import { URI } from '../../../../base/common/uri.js';
export type VoidDirectoryItem = {
export type OrcideDirectoryItem = {
uri: URI;
name: string;
isSymbolicLink: boolean;
children: VoidDirectoryItem[] | null;
children: OrcideDirectoryItem[] | null;
isDirectory: boolean;
isGitIgnoredDirectory: false | { numChildren: number }; // if directory is gitignored, we ignore children
}

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';
@ -112,7 +112,7 @@ export const diffAreaSnapshotKeys = [
export type DiffAreaSnapshotEntry<DiffAreaType extends DiffArea = DiffArea> = Pick<DiffAreaType, typeof diffAreaSnapshotKeys[number]>
export type VoidFileSnapshot = {
export type OrcideFileSnapshot = {
snapshottedDiffAreaOfId: Record<string, DiffAreaSnapshotEntry>;
entireFileCode: string;
}

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 { Color, RGBA } from '../../../../../base/common/color.js';
@ -32,9 +32,9 @@ const configOfBG = (color: Color) => {
return { dark: color, light: color, hcDark: color, hcLight: color, }
}
// gets converted to --vscode-void-greenBG, see void.css, asCssVariable
registerColor('void.greenBG', configOfBG(acceptBG), '', true);
registerColor('void.redBG', configOfBG(rejectBG), '', true);
registerColor('void.sweepBG', configOfBG(sweepBG), '', true);
registerColor('void.highlightBG', configOfBG(highlightBG), '', true);
registerColor('void.sweepIdxBG', configOfBG(sweepIdxBG), '', true);
// gets converted to --vscode-orcide-greenBG, see orcide.css, asCssVariable
registerColor('orcide.greenBG', configOfBG(acceptBG), '', true);
registerColor('orcide.redBG', configOfBG(rejectBG), '', true);
registerColor('orcide.sweepBG', configOfBG(sweepBG), '', true);
registerColor('orcide.highlightBG', configOfBG(highlightBG), '', true);
registerColor('orcide.sweepIdxBG', configOfBG(sweepIdxBG), '', 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 { DIVIDER, FINAL, ORIGINAL } from '../prompt/prompts.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 { URI } from '../../../../../base/common/uri.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 { isLinux, isMacintosh, isWindows } from '../../../../../base/common/platform.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 { URI } from '../../../../base/common/uri.js';
@ -18,8 +18,8 @@ import { IMainProcessService } from '../../../../platform/ipc/common/mainProcess
import { MCPServerOfName, MCPConfigFileJSON, MCPServer, MCPToolCallParams, RawMCPToolCall, MCPServerEventResponse } from './mcpServiceTypes.js';
import { Event, Emitter } from '../../../../base/common/event.js';
import { InternalToolInfo } from './prompt/prompts.js';
import { IVoidSettingsService } from './voidSettingsService.js';
import { MCPUserStateOfName } from './voidSettingsTypes.js';
import { IOrcideSettingsService } from './orcideSettingsService.js';
import { MCPUserStateOfName } from './orcideSettingsTypes.js';
type MCPServiceState = {
@ -82,10 +82,10 @@ class MCPService extends Disposable implements IMCPService {
@IProductService private readonly productService: IProductService,
@IEditorService private readonly editorService: IEditorService,
@IMainProcessService private readonly mainProcessService: IMainProcessService,
@IVoidSettingsService private readonly voidSettingsService: IVoidSettingsService,
@IOrcideSettingsService private readonly orcideSettingsService: IOrcideSettingsService,
) {
super();
this.channel = this.mainProcessService.getChannel('void-channel-mcp')
this.channel = this.mainProcessService.getChannel('orcide-channel-mcp')
const onEvent = (e: MCPServerEventResponse) => {
@ -102,7 +102,7 @@ class MCPService extends Disposable implements IMCPService {
private async _initialize() {
try {
await this.voidSettingsService.waitForInitState;
await this.orcideSettingsService.waitForInitState;
// Create .mcpConfig if it doesn't exist
const mcpConfigUri = await this._getMCPConfigFilePath();
@ -278,10 +278,10 @@ class MCPService extends Disposable implements IMCPService {
// set isOn to any new servers in the config
const addedUserStateOfName: MCPUserStateOfName = {}
for (const name of addedServerNames) { addedUserStateOfName[name] = { isOn: true } }
await this.voidSettingsService.addMCPUserStateOfNames(addedUserStateOfName);
await this.orcideSettingsService.addMCPUserStateOfNames(addedUserStateOfName);
// delete isOn for any servers that no longer show up in the config
await this.voidSettingsService.removeMCPUserStateOfNames(removedServerNames);
await this.orcideSettingsService.removeMCPUserStateOfNames(removedServerNames);
// set all servers to loading
for (const serverName in newConfigFileJSON.mcpServers) {
@ -294,7 +294,7 @@ class MCPService extends Disposable implements IMCPService {
addedServerNames,
removedServerNames,
updatedServerNames,
userStateOfName: this.voidSettingsService.state.mcpUserStateOfName,
userStateOfName: this.orcideSettingsService.state.mcpUserStateOfName,
})
}
@ -318,7 +318,7 @@ class MCPService extends Disposable implements IMCPService {
public async toggleServerIsOn(serverName: string, isOn: boolean): Promise<void> {
this._setMCPServerState(serverName, { status: 'loading', tools: [] })
await this.voidSettingsService.setMCPServerState(serverName, { isOn });
await this.orcideSettingsService.setMCPServerState(serverName, { isOn });
this.channel.call('toggleMCPServer', { serverName, isOn })
}

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 { createDecorator, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
@ -32,7 +32,7 @@ export class MetricsService implements IMetricsService {
@IMainProcessService mainProcessService: IMainProcessService // (only usable on client side)
) {
// creates an IPC proxy to use metricsMainService.ts
this.metricsService = ProxyChannel.toService<IMetricsService>(mainProcessService.getChannel('void-channel-metrics'));
this.metricsService = ProxyChannel.toService<IMetricsService>(mainProcessService.getChannel('orcide-channel-metrics'));
}
// call capture on the channel
@ -68,9 +68,9 @@ if (!isWeb) {
registerAction2(class extends Action2 {
constructor() {
super({
id: 'voidDebugInfo',
id: 'orcideDebugInfo',
f1: true,
title: localize2('voidMetricsDebug', 'Orcide: Log Debug Info'),
title: localize2('orcideMetricsDebug', 'Orcide: Log Debug Info'),
});
}
async run(accessor: ServicesAccessor): Promise<void> {

View file

@ -1,9 +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 { FeatureName, ModelSelectionOptions, OverridesOfModel, ProviderName } from './voidSettingsTypes.js';
import { FeatureName, ModelSelectionOptions, OverridesOfModel, ProviderName } from './orcideSettingsTypes.js';
@ -149,15 +149,10 @@ export const defaultModelsOfProvider = {
awsBedrock: [],
liteLLM: [],
orcestAI: [
'rainymodel-pro',
'rainymodel-standard',
'rainymodel-lite',
'gpt-4o',
'gpt-4o-mini',
'claude-3.5-sonnet',
'gemini-1.5-pro',
'llama-3.1-70b',
'mixtral-8x7b',
'rainymodel/auto',
'rainymodel/chat',
'rainymodel/code',
'rainymodel/agent',
],
@ -165,8 +160,8 @@ export const defaultModelsOfProvider = {
export type VoidStaticModelInfo = { // not stateful
// Void uses the information below to know how to handle each model.
export type OrcideStaticModelInfo = { // not stateful
// Orcide uses the information below to know how to handle each model.
// for some examples, see openAIModelOptions and anthropicModelOptions (below).
contextWindow: number; // input tokens
@ -222,7 +217,7 @@ export const modelOverrideKeys = [
] as const
export type ModelOverrides = Pick<
VoidStaticModelInfo,
OrcideStaticModelInfo,
(typeof modelOverrideKeys)[number]
>
@ -239,10 +234,10 @@ type ProviderReasoningIOSettings = {
| { nameOfFieldInDelta?: undefined, needsManualParse?: true, };
}
type VoidStaticProviderInfo = { // doesn't change (not stateful)
type OrcideStaticProviderInfo = { // doesn't change (not stateful)
providerReasoningIOSettings?: ProviderReasoningIOSettings; // input/output settings around thinking (allowed to be empty) - only applied if the model supports reasoning output
modelOptions: { [key: string]: VoidStaticModelInfo };
modelOptionsFallback: (modelName: string, fallbackKnownValues?: Partial<VoidStaticModelInfo>) => (VoidStaticModelInfo & { modelName: string, recognizedModelName: string }) | null;
modelOptions: { [key: string]: OrcideStaticModelInfo };
modelOptionsFallback: (modelName: string, fallbackKnownValues?: Partial<OrcideStaticModelInfo>) => (OrcideStaticModelInfo & { modelName: string, recognizedModelName: string }) | null;
}
@ -255,7 +250,7 @@ const defaultModelOptions = {
supportsSystemMessage: false,
supportsFIM: false,
reasoningCapabilities: false,
} as const satisfies VoidStaticModelInfo
} as const satisfies OrcideStaticModelInfo
// TODO!!! double check all context sizes below
// TODO!!! add openrouter common models
@ -391,18 +386,18 @@ const openSourceModelOptions_assumingOAICompat = {
reasoningCapabilities: false,
contextWindow: 1_000_000, reservedOutputTokenSpace: 32_000,
}
} as const satisfies { [s: string]: Partial<VoidStaticModelInfo> }
} as const satisfies { [s: string]: Partial<OrcideStaticModelInfo> }
// keep modelName, but use the fallback's defaults
const extensiveModelOptionsFallback: VoidStaticProviderInfo['modelOptionsFallback'] = (modelName, fallbackKnownValues) => {
const extensiveModelOptionsFallback: OrcideStaticProviderInfo['modelOptionsFallback'] = (modelName, fallbackKnownValues) => {
const lower = modelName.toLowerCase()
const toFallback = <T extends { [s: string]: Omit<VoidStaticModelInfo, 'cost' | 'downloadable'> },>(obj: T, recognizedModelName: string & keyof T)
: VoidStaticModelInfo & { modelName: string, recognizedModelName: string } => {
const toFallback = <T extends { [s: string]: Omit<OrcideStaticModelInfo, 'cost' | 'downloadable'> },>(obj: T, recognizedModelName: string & keyof T)
: OrcideStaticModelInfo & { modelName: string, recognizedModelName: string } => {
const opts = obj[recognizedModelName]
const supportsSystemMessage = opts.supportsSystemMessage === 'separated'
@ -573,9 +568,9 @@ const anthropicModelOptions = {
supportsSystemMessage: 'separated',
reasoningCapabilities: false,
}
} as const satisfies { [s: string]: VoidStaticModelInfo }
} as const satisfies { [s: string]: OrcideStaticModelInfo }
const anthropicSettings: VoidStaticProviderInfo = {
const anthropicSettings: OrcideStaticProviderInfo = {
providerReasoningIOSettings: {
input: {
includeInPayload: (reasoningInfo) => {
@ -706,7 +701,7 @@ const openAIModelOptions = { // https://platform.openai.com/docs/pricing
supportsSystemMessage: 'system-role', // ??
reasoningCapabilities: false,
},
} as const satisfies { [s: string]: VoidStaticModelInfo }
} as const satisfies { [s: string]: OrcideStaticModelInfo }
// https://platform.openai.com/docs/guides/reasoning?api-mode=chat
@ -719,7 +714,7 @@ const openAICompatIncludeInPayloadReasoning = (reasoningInfo: SendableReasoningI
}
const openAISettings: VoidStaticProviderInfo = {
const openAISettings: OrcideStaticProviderInfo = {
modelOptions: openAIModelOptions,
modelOptionsFallback: (modelName) => {
const lower = modelName.toLowerCase()
@ -790,9 +785,9 @@ const xAIModelOptions = {
specialToolFormat: 'openai-style',
reasoningCapabilities: { supportsReasoning: true, canTurnOffReasoning: false, canIOReasoning: false, reasoningSlider: { type: 'effort_slider', values: ['low', 'high'], default: 'low' } },
},
} as const satisfies { [s: string]: VoidStaticModelInfo }
} as const satisfies { [s: string]: OrcideStaticModelInfo }
const xAISettings: VoidStaticProviderInfo = {
const xAISettings: OrcideStaticProviderInfo = {
modelOptions: xAIModelOptions,
modelOptionsFallback: (modelName) => {
const lower = modelName.toLowerCase()
@ -921,9 +916,9 @@ const geminiModelOptions = { // https://ai.google.dev/gemini-api/docs/pricing
specialToolFormat: 'gemini-style',
reasoningCapabilities: false,
},
} as const satisfies { [s: string]: VoidStaticModelInfo }
} as const satisfies { [s: string]: OrcideStaticModelInfo }
const geminiSettings: VoidStaticProviderInfo = {
const geminiSettings: OrcideStaticProviderInfo = {
modelOptions: geminiModelOptions,
modelOptionsFallback: (modelName) => { return null },
}
@ -946,10 +941,10 @@ const deepseekModelOptions = {
cost: { cache_read: .14, input: .55, output: 2.19, },
downloadable: false,
},
} as const satisfies { [s: string]: VoidStaticModelInfo }
} as const satisfies { [s: string]: OrcideStaticModelInfo }
const deepseekSettings: VoidStaticProviderInfo = {
const deepseekSettings: OrcideStaticProviderInfo = {
modelOptions: deepseekModelOptions,
modelOptionsFallback: (modelName) => { return null },
providerReasoningIOSettings: {
@ -1036,9 +1031,9 @@ const mistralModelOptions = { // https://mistral.ai/products/la-plateforme#prici
supportsSystemMessage: 'system-role',
reasoningCapabilities: false,
},
} as const satisfies { [s: string]: VoidStaticModelInfo }
} as const satisfies { [s: string]: OrcideStaticModelInfo }
const mistralSettings: VoidStaticProviderInfo = {
const mistralSettings: OrcideStaticProviderInfo = {
modelOptions: mistralModelOptions,
modelOptionsFallback: (modelName) => { return null },
providerReasoningIOSettings: {
@ -1085,8 +1080,8 @@ const groqModelOptions = { // https://console.groq.com/docs/models, https://groq
supportsSystemMessage: 'system-role',
reasoningCapabilities: { supportsReasoning: true, canIOReasoning: true, canTurnOffReasoning: false, openSourceThinkTags: ['<think>', '</think>'] }, // we're using reasoning_format:parsed so really don't need to know openSourceThinkTags
},
} as const satisfies { [s: string]: VoidStaticModelInfo }
const groqSettings: VoidStaticProviderInfo = {
} as const satisfies { [s: string]: OrcideStaticModelInfo }
const groqSettings: OrcideStaticProviderInfo = {
modelOptions: groqModelOptions,
modelOptionsFallback: (modelName) => { return null },
providerReasoningIOSettings: {
@ -1107,8 +1102,8 @@ const groqSettings: VoidStaticProviderInfo = {
// ---------------- GOOGLE VERTEX ----------------
const googleVertexModelOptions = {
} as const satisfies Record<string, VoidStaticModelInfo>
const googleVertexSettings: VoidStaticProviderInfo = {
} as const satisfies Record<string, OrcideStaticModelInfo>
const googleVertexSettings: OrcideStaticProviderInfo = {
modelOptions: googleVertexModelOptions,
modelOptionsFallback: (modelName) => { return null },
providerReasoningIOSettings: {
@ -1118,8 +1113,8 @@ const googleVertexSettings: VoidStaticProviderInfo = {
// ---------------- MICROSOFT AZURE ----------------
const microsoftAzureModelOptions = {
} as const satisfies Record<string, VoidStaticModelInfo>
const microsoftAzureSettings: VoidStaticProviderInfo = {
} as const satisfies Record<string, OrcideStaticModelInfo>
const microsoftAzureSettings: OrcideStaticProviderInfo = {
modelOptions: microsoftAzureModelOptions,
modelOptionsFallback: (modelName) => { return null },
providerReasoningIOSettings: {
@ -1129,9 +1124,9 @@ const microsoftAzureSettings: VoidStaticProviderInfo = {
// ---------------- AWS BEDROCK ----------------
const awsBedrockModelOptions = {
} as const satisfies Record<string, VoidStaticModelInfo>
} as const satisfies Record<string, OrcideStaticModelInfo>
const awsBedrockSettings: VoidStaticProviderInfo = {
const awsBedrockSettings: OrcideStaticProviderInfo = {
modelOptions: awsBedrockModelOptions,
modelOptionsFallback: (modelName) => { return null },
providerReasoningIOSettings: {
@ -1215,12 +1210,12 @@ const ollamaModelOptions = {
reasoningCapabilities: false,
},
} as const satisfies Record<string, VoidStaticModelInfo>
} as const satisfies Record<string, OrcideStaticModelInfo>
export const ollamaRecommendedModels = ['qwen2.5-coder:1.5b', 'llama3.1', 'qwq', 'deepseek-r1', 'devstral:latest'] as const satisfies (keyof typeof ollamaModelOptions)[]
const vLLMSettings: VoidStaticProviderInfo = {
const vLLMSettings: OrcideStaticProviderInfo = {
modelOptionsFallback: (modelName) => extensiveModelOptionsFallback(modelName, { downloadable: { sizeGb: 'not-known' } }),
modelOptions: {},
providerReasoningIOSettings: {
@ -1230,7 +1225,7 @@ const vLLMSettings: VoidStaticProviderInfo = {
},
}
const lmStudioSettings: VoidStaticProviderInfo = {
const lmStudioSettings: OrcideStaticProviderInfo = {
modelOptionsFallback: (modelName) => extensiveModelOptionsFallback(modelName, { downloadable: { sizeGb: 'not-known' }, contextWindow: 4_096 }),
modelOptions: {},
providerReasoningIOSettings: {
@ -1239,7 +1234,7 @@ const lmStudioSettings: VoidStaticProviderInfo = {
},
}
const ollamaSettings: VoidStaticProviderInfo = {
const ollamaSettings: OrcideStaticProviderInfo = {
modelOptionsFallback: (modelName) => extensiveModelOptionsFallback(modelName, { downloadable: { sizeGb: 'not-known' } }),
modelOptions: ollamaModelOptions,
providerReasoningIOSettings: {
@ -1249,7 +1244,7 @@ const ollamaSettings: VoidStaticProviderInfo = {
},
}
const openaiCompatible: VoidStaticProviderInfo = {
const openaiCompatible: OrcideStaticProviderInfo = {
modelOptionsFallback: (modelName) => extensiveModelOptionsFallback(modelName),
modelOptions: {},
providerReasoningIOSettings: {
@ -1259,7 +1254,7 @@ const openaiCompatible: VoidStaticProviderInfo = {
},
}
const liteLLMSettings: VoidStaticProviderInfo = { // https://docs.litellm.ai/docs/reasoning_content
const liteLLMSettings: OrcideStaticProviderInfo = { // https://docs.litellm.ai/docs/reasoning_content
modelOptionsFallback: (modelName) => extensiveModelOptionsFallback(modelName, { downloadable: { sizeGb: 'not-known' } }),
modelOptions: {},
providerReasoningIOSettings: {
@ -1413,9 +1408,9 @@ const openRouterModelOptions_assumingOpenAICompat = {
cost: { input: 0.07, output: 0.16 },
downloadable: false,
}
} as const satisfies { [s: string]: VoidStaticModelInfo }
} as const satisfies { [s: string]: OrcideStaticModelInfo }
const openRouterSettings: VoidStaticProviderInfo = {
const openRouterSettings: OrcideStaticProviderInfo = {
modelOptions: openRouterModelOptions_assumingOpenAICompat,
modelOptionsFallback: (modelName) => {
const res = extensiveModelOptionsFallback(modelName)
@ -1487,9 +1482,9 @@ const orcestAIModelOptions = {
specialToolFormat: 'openai-style',
reasoningCapabilities: false,
},
} as const satisfies { [s: string]: VoidStaticModelInfo }
} as const satisfies { [s: string]: OrcideStaticModelInfo }
const orcestAISettings: VoidStaticProviderInfo = {
const orcestAISettings: OrcideStaticProviderInfo = {
modelOptions: orcestAIModelOptions,
modelOptionsFallback: (modelName) => {
// For non-RainyModel models served through the aggregator, use the extensive fallback
@ -1503,7 +1498,7 @@ const orcestAISettings: VoidStaticProviderInfo = {
// ---------------- model settings of everything above ----------------
const modelSettingsOfProvider: { [providerName in ProviderName]: VoidStaticProviderInfo } = {
const modelSettingsOfProvider: { [providerName in ProviderName]: OrcideStaticProviderInfo } = {
openAI: openAISettings,
anthropic: anthropicSettings,
xAI: xAISettings,
@ -1537,7 +1532,7 @@ export const getModelCapabilities = (
providerName: ProviderName,
modelName: string,
overridesOfModel: OverridesOfModel | undefined
): VoidStaticModelInfo & (
): OrcideStaticModelInfo & (
| { modelName: string; recognizedModelName: string; isUnrecognizedModel: false }
| { modelName: string; recognizedModelName?: undefined; isUnrecognizedModel: true }
) => {

View file

@ -0,0 +1,773 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Emitter, Event } from '../../../../base/common/event.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js';
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
import { generateUuid } from '../../../../base/common/uuid.js';
// ─── Enterprise & Cursor Ultra Features for Orcide ──────────────────────────────
const ORCIDE_ENTERPRISE_STORAGE_KEY = 'orcide.enterpriseState';
// ─── Types ──────────────────────────────────────────────────────────────────────
export type LicenseTier = 'free' | 'pro' | 'team' | 'enterprise';
export type LicenseInfo = {
tier: LicenseTier;
seats: number;
usedSeats: number;
expiresAt: number;
features: string[];
orgId?: string;
orgName?: string;
};
export type SeatAllocation = {
userId: string;
email: string;
name: string;
role: 'owner' | 'admin' | 'member';
allocatedAt: number;
lastActive: number;
};
export type AuditLogEntry = {
id: string;
timestamp: number;
userId: string;
userEmail: string;
action: string;
resource: string;
details?: Record<string, unknown>;
ipAddress?: string;
};
export type EnterprisePolicy = {
requireSSO: boolean;
allowPersonalAPIKeys: boolean;
allowedModels: string[];
maxTokensPerRequest: number;
maxRequestsPerDay: number;
dataRetentionDays: number;
allowExternalModels: boolean;
allowCodeExport: boolean;
enforceCodeReview: boolean;
requireMFA: boolean;
};
export type UsageMetrics = {
totalRequests: number;
totalTokensUsed: number;
requestsByModel: Record<string, number>;
requestsByUser: Record<string, number>;
averageLatencyMs: number;
errorRate: number;
period: 'daily' | 'weekly' | 'monthly';
startDate: number;
endDate: number;
};
// ─── Cursor Ultra Features ──────────────────────────────────────────────────────
export type BackgroundAgent = {
id: string;
name: string;
type: 'code-review' | 'test-generation' | 'documentation' | 'refactoring' | 'security-scan' | 'dependency-update';
status: 'idle' | 'running' | 'completed' | 'error';
config: Record<string, unknown>;
lastRunAt?: number;
lastResult?: string;
};
export type MultiFileEditSession = {
id: string;
files: string[];
description: string;
status: 'planning' | 'editing' | 'reviewing' | 'applied' | 'reverted';
changes: Array<{
filePath: string;
originalContent: string;
newContent: string;
applied: boolean;
}>;
createdAt: number;
};
export type ParallelCompletion = {
id: string;
prompt: string;
models: string[];
results: Array<{
model: string;
content: string;
latencyMs: number;
tokenCount: number;
}>;
selectedModel?: string;
status: 'pending' | 'completed' | 'partial';
};
export type UltraFeatures = {
backgroundAgents: BackgroundAgent[];
multiFileEditSessions: MultiFileEditSession[];
parallelCompletionEnabled: boolean;
predictiveEditingEnabled: boolean;
smartContextWindowEnabled: boolean;
bugDetectionEnabled: boolean;
};
// ─── Enterprise State ───────────────────────────────────────────────────────────
export type EnterpriseState = {
license: LicenseInfo;
seats: SeatAllocation[];
policy: EnterprisePolicy;
auditLog: AuditLogEntry[];
usageMetrics: UsageMetrics | null;
ultraFeatures: UltraFeatures;
};
// ─── Service Interface ──────────────────────────────────────────────────────────
export interface IOrcideEnterpriseService {
readonly _serviceBrand: undefined;
readonly state: EnterpriseState;
onDidChangeState: Event<void>;
onDidChangePolicy: Event<EnterprisePolicy>;
onDidBackgroundAgentComplete: Event<BackgroundAgent>;
// License management
getLicenseInfo(): LicenseInfo;
isFeatureAvailable(feature: string): boolean;
getTier(): LicenseTier;
// Seat management
allocateSeat(userId: string, email: string, name: string, role: SeatAllocation['role']): SeatAllocation;
deallocateSeat(userId: string): void;
getSeats(): SeatAllocation[];
getAvailableSeats(): number;
// Policy management
updatePolicy(policy: Partial<EnterprisePolicy>): void;
getPolicy(): EnterprisePolicy;
isActionAllowed(action: string, userId: string): boolean;
// Audit logging
logAction(userId: string, userEmail: string, action: string, resource: string, details?: Record<string, unknown>): void;
getAuditLog(filters?: { userId?: string; action?: string; from?: number; to?: number }): AuditLogEntry[];
exportAuditLog(format: 'json' | 'csv'): string;
// Usage metrics
getUsageMetrics(period?: UsageMetrics['period']): UsageMetrics | null;
trackUsage(model: string, userId: string, tokens: number, latencyMs: number): void;
// ─── Cursor Ultra Features ──────────────────────────────────────────────────
// Background agents
createBackgroundAgent(agent: Omit<BackgroundAgent, 'id' | 'status'>): BackgroundAgent;
runBackgroundAgent(agentId: string): Promise<string>;
stopBackgroundAgent(agentId: string): void;
getBackgroundAgents(): BackgroundAgent[];
// Multi-file editing
startMultiFileEdit(files: string[], description: string): Promise<MultiFileEditSession>;
applyMultiFileEdit(sessionId: string): Promise<void>;
revertMultiFileEdit(sessionId: string): Promise<void>;
getMultiFileEditSessions(): MultiFileEditSession[];
// Parallel completions
runParallelCompletion(prompt: string, models?: string[]): Promise<ParallelCompletion>;
selectCompletionResult(completionId: string, model: string): void;
// Predictive editing & smart context
togglePredictiveEditing(enabled: boolean): void;
toggleSmartContextWindow(enabled: boolean): void;
toggleBugDetection(enabled: boolean): void;
}
export const IOrcideEnterpriseService = createDecorator<IOrcideEnterpriseService>('orcideEnterpriseService');
// ─── Default State ──────────────────────────────────────────────────────────────
const RAINYMODEL_ENDPOINT = 'https://rm.orcest.ai/v1';
const defaultLicense: LicenseInfo = {
tier: 'team',
seats: 50,
usedSeats: 0,
expiresAt: Date.now() + (365 * 24 * 60 * 60 * 1000), // 1 year
features: [
'sso',
'team-management',
'collaboration',
'shared-workspaces',
'audit-log',
'usage-metrics',
'background-agents',
'multi-file-edit',
'parallel-completions',
'predictive-editing',
'smart-context-window',
'bug-detection',
'custom-models',
'priority-support',
'langchain-integration',
'git-pr-generation',
'deployment',
],
};
const defaultPolicy: EnterprisePolicy = {
requireSSO: true,
allowPersonalAPIKeys: false,
allowedModels: ['rainymodel/auto', 'rainymodel/chat', 'rainymodel/code', 'rainymodel/agent'],
maxTokensPerRequest: 8192,
maxRequestsPerDay: 10000,
dataRetentionDays: 90,
allowExternalModels: true,
allowCodeExport: true,
enforceCodeReview: false,
requireMFA: false,
};
const defaultUltraFeatures: UltraFeatures = {
backgroundAgents: [],
multiFileEditSessions: [],
parallelCompletionEnabled: true,
predictiveEditingEnabled: true,
smartContextWindowEnabled: true,
bugDetectionEnabled: true,
};
// ─── Service Implementation ─────────────────────────────────────────────────────
class OrcideEnterpriseService extends Disposable implements IOrcideEnterpriseService {
readonly _serviceBrand: undefined;
private _state: EnterpriseState;
private readonly _onDidChangeState = this._register(new Emitter<void>());
readonly onDidChangeState: Event<void> = this._onDidChangeState.event;
private readonly _onDidChangePolicy = this._register(new Emitter<EnterprisePolicy>());
readonly onDidChangePolicy: Event<EnterprisePolicy> = this._onDidChangePolicy.event;
private readonly _onDidBackgroundAgentComplete = this._register(new Emitter<BackgroundAgent>());
readonly onDidBackgroundAgentComplete: Event<BackgroundAgent> = this._onDidBackgroundAgentComplete.event;
get state(): EnterpriseState {
return this._state;
}
constructor(
@IStorageService private readonly _storageService: IStorageService,
) {
super();
this._state = {
license: { ...defaultLicense },
seats: [],
policy: { ...defaultPolicy },
auditLog: [],
usageMetrics: null,
ultraFeatures: { ...defaultUltraFeatures },
};
this._loadFromStorage();
}
private _loadFromStorage(): void {
const stored = this._storageService.get(ORCIDE_ENTERPRISE_STORAGE_KEY, StorageScope.APPLICATION);
if (stored) {
try {
const parsed = JSON.parse(stored);
this._state = {
...this._state,
...parsed,
license: { ...defaultLicense, ...(parsed.license ?? {}) },
policy: { ...defaultPolicy, ...(parsed.policy ?? {}) },
ultraFeatures: { ...defaultUltraFeatures, ...(parsed.ultraFeatures ?? {}) },
};
} catch { /* ignore */ }
}
this._onDidChangeState.fire();
}
private _saveState(): void {
const toStore = {
license: this._state.license,
seats: this._state.seats,
policy: this._state.policy,
ultraFeatures: {
parallelCompletionEnabled: this._state.ultraFeatures.parallelCompletionEnabled,
predictiveEditingEnabled: this._state.ultraFeatures.predictiveEditingEnabled,
smartContextWindowEnabled: this._state.ultraFeatures.smartContextWindowEnabled,
bugDetectionEnabled: this._state.ultraFeatures.bugDetectionEnabled,
},
};
this._storageService.store(ORCIDE_ENTERPRISE_STORAGE_KEY, JSON.stringify(toStore), StorageScope.APPLICATION, StorageTarget.USER);
}
// ── License Management ──────────────────────────────────────────────────────
getLicenseInfo(): LicenseInfo {
return this._state.license;
}
isFeatureAvailable(feature: string): boolean {
return this._state.license.features.includes(feature);
}
getTier(): LicenseTier {
return this._state.license.tier;
}
// ── Seat Management ─────────────────────────────────────────────────────────
allocateSeat(userId: string, email: string, name: string, role: SeatAllocation['role']): SeatAllocation {
const exists = this._state.seats.some(s => s.userId === userId);
if (exists) throw new Error(`Seat already allocated for user ${userId}`);
if (this._state.license.usedSeats >= this._state.license.seats) {
throw new Error('No available seats');
}
const seat: SeatAllocation = {
userId,
email,
name,
role,
allocatedAt: Date.now(),
lastActive: Date.now(),
};
this._state = {
...this._state,
seats: [...this._state.seats, seat],
license: {
...this._state.license,
usedSeats: this._state.license.usedSeats + 1,
},
};
this._saveState();
this._onDidChangeState.fire();
return seat;
}
deallocateSeat(userId: string): void {
const had = this._state.seats.some(s => s.userId === userId);
this._state = {
...this._state,
seats: this._state.seats.filter(s => s.userId !== userId),
license: {
...this._state.license,
usedSeats: had ? this._state.license.usedSeats - 1 : this._state.license.usedSeats,
},
};
this._saveState();
this._onDidChangeState.fire();
}
getSeats(): SeatAllocation[] {
return this._state.seats;
}
getAvailableSeats(): number {
return this._state.license.seats - this._state.license.usedSeats;
}
// ── Policy Management ───────────────────────────────────────────────────────
updatePolicy(policy: Partial<EnterprisePolicy>): void {
this._state = {
...this._state,
policy: { ...this._state.policy, ...policy },
};
this._saveState();
this._onDidChangePolicy.fire(this._state.policy);
this._onDidChangeState.fire();
}
getPolicy(): EnterprisePolicy {
return this._state.policy;
}
isActionAllowed(action: string, _userId: string): boolean {
switch (action) {
case 'use-personal-api-keys':
return this._state.policy.allowPersonalAPIKeys;
case 'use-external-models':
return this._state.policy.allowExternalModels;
case 'export-code':
return this._state.policy.allowCodeExport;
default:
return true;
}
}
// ── Audit Logging ───────────────────────────────────────────────────────────
logAction(userId: string, userEmail: string, action: string, resource: string, details?: Record<string, unknown>): void {
const entry: AuditLogEntry = {
id: generateUuid(),
timestamp: Date.now(),
userId,
userEmail,
action,
resource,
details,
};
this._state = {
...this._state,
auditLog: [...this._state.auditLog, entry],
};
// Keep only last 10000 entries in memory
if (this._state.auditLog.length > 10000) {
this._state.auditLog = this._state.auditLog.slice(-10000);
}
this._onDidChangeState.fire();
}
getAuditLog(filters?: { userId?: string; action?: string; from?: number; to?: number }): AuditLogEntry[] {
let log = this._state.auditLog;
if (filters) {
if (filters.userId) log = log.filter(e => e.userId === filters.userId);
if (filters.action) log = log.filter(e => e.action === filters.action);
if (filters.from) log = log.filter(e => e.timestamp >= filters.from!);
if (filters.to) log = log.filter(e => e.timestamp <= filters.to!);
}
return log;
}
exportAuditLog(format: 'json' | 'csv'): string {
if (format === 'json') {
return JSON.stringify(this._state.auditLog, null, 2);
}
const headers = 'id,timestamp,userId,userEmail,action,resource\n';
const rows = this._state.auditLog.map(e =>
`${e.id},${new Date(e.timestamp).toISOString()},${e.userId},${e.userEmail},${e.action},${e.resource}`
).join('\n');
return headers + rows;
}
// ── Usage Metrics ───────────────────────────────────────────────────────────
getUsageMetrics(_period?: UsageMetrics['period']): UsageMetrics | null {
return this._state.usageMetrics;
}
trackUsage(model: string, userId: string, tokens: number, latencyMs: number): void {
if (!this._state.usageMetrics) {
const now = Date.now();
this._state.usageMetrics = {
totalRequests: 0,
totalTokensUsed: 0,
requestsByModel: {},
requestsByUser: {},
averageLatencyMs: 0,
errorRate: 0,
period: 'daily',
startDate: now,
endDate: now + (24 * 60 * 60 * 1000),
};
}
const metrics = this._state.usageMetrics;
const totalReqs = metrics.totalRequests + 1;
metrics.averageLatencyMs = ((metrics.averageLatencyMs * metrics.totalRequests) + latencyMs) / totalReqs;
metrics.totalRequests = totalReqs;
metrics.totalTokensUsed += tokens;
metrics.requestsByModel[model] = (metrics.requestsByModel[model] ?? 0) + 1;
metrics.requestsByUser[userId] = (metrics.requestsByUser[userId] ?? 0) + 1;
this._state = { ...this._state, usageMetrics: { ...metrics } };
this._onDidChangeState.fire();
}
// ─── Cursor Ultra: Background Agents ────────────────────────────────────────
createBackgroundAgent(agent: Omit<BackgroundAgent, 'id' | 'status'>): BackgroundAgent {
const newAgent: BackgroundAgent = {
...agent,
id: generateUuid(),
status: 'idle',
};
this._state = {
...this._state,
ultraFeatures: {
...this._state.ultraFeatures,
backgroundAgents: [...this._state.ultraFeatures.backgroundAgents, newAgent],
},
};
this._onDidChangeState.fire();
return newAgent;
}
async runBackgroundAgent(agentId: string): Promise<string> {
const agents = this._state.ultraFeatures.backgroundAgents;
const idx = agents.findIndex(a => a.id === agentId);
if (idx === -1) throw new Error(`Background agent ${agentId} not found`);
const agent = agents[idx];
const updated = { ...agent, status: 'running' as const, lastRunAt: Date.now() };
this._updateAgent(idx, updated);
try {
const response = await fetch(`${RAINYMODEL_ENDPOINT}/chat/completions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'rainymodel/agent',
messages: [
{
role: 'system',
content: `You are a background ${agent.type} agent named "${agent.name}". Perform the requested task thoroughly.`,
},
{
role: 'user',
content: JSON.stringify(agent.config),
},
],
temperature: 0.3,
max_tokens: 4096,
}),
});
if (!response.ok) throw new Error(`Agent execution failed: ${response.status}`);
const data = await response.json();
const result = data.choices?.[0]?.message?.content ?? '';
const completed = { ...updated, status: 'completed' as const, lastResult: result };
this._updateAgent(idx, completed);
this._onDidBackgroundAgentComplete.fire(completed);
return result;
} catch (e) {
const errored = { ...updated, status: 'error' as const, lastResult: `Error: ${e}` };
this._updateAgent(idx, errored);
throw e;
}
}
stopBackgroundAgent(agentId: string): void {
const idx = this._state.ultraFeatures.backgroundAgents.findIndex(a => a.id === agentId);
if (idx === -1) return;
this._updateAgent(idx, {
...this._state.ultraFeatures.backgroundAgents[idx],
status: 'idle',
});
}
getBackgroundAgents(): BackgroundAgent[] {
return this._state.ultraFeatures.backgroundAgents;
}
private _updateAgent(idx: number, agent: BackgroundAgent): void {
const agents = [...this._state.ultraFeatures.backgroundAgents];
agents[idx] = agent;
this._state = {
...this._state,
ultraFeatures: { ...this._state.ultraFeatures, backgroundAgents: agents },
};
this._onDidChangeState.fire();
}
// ─── Cursor Ultra: Multi-File Editing ───────────────────────────────────────
async startMultiFileEdit(files: string[], description: string): Promise<MultiFileEditSession> {
const session: MultiFileEditSession = {
id: generateUuid(),
files,
description,
status: 'planning',
changes: [],
createdAt: Date.now(),
};
this._state = {
...this._state,
ultraFeatures: {
...this._state.ultraFeatures,
multiFileEditSessions: [...this._state.ultraFeatures.multiFileEditSessions, session],
},
};
this._onDidChangeState.fire();
// Use RainyModel to plan the edit
try {
const response = await fetch(`${RAINYMODEL_ENDPOINT}/chat/completions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'rainymodel/code',
messages: [
{
role: 'system',
content: 'You are a multi-file code editor. Plan changes across multiple files based on the description. Return a JSON array of {filePath, description} objects.',
},
{
role: 'user',
content: `Files: ${files.join(', ')}\n\nDescription: ${description}`,
},
],
temperature: 0.3,
max_tokens: 2048,
}),
});
if (response.ok) {
session.status = 'editing';
this._updateSession(session);
}
} catch {
// Planning failed, keep session in planning status
}
return session;
}
async applyMultiFileEdit(sessionId: string): Promise<void> {
const session = this._state.ultraFeatures.multiFileEditSessions.find(s => s.id === sessionId);
if (!session) throw new Error(`Session ${sessionId} not found`);
const updated = { ...session, status: 'applied' as const };
updated.changes = updated.changes.map(c => ({ ...c, applied: true }));
this._updateSession(updated);
}
async revertMultiFileEdit(sessionId: string): Promise<void> {
const session = this._state.ultraFeatures.multiFileEditSessions.find(s => s.id === sessionId);
if (!session) throw new Error(`Session ${sessionId} not found`);
const updated = { ...session, status: 'reverted' as const };
updated.changes = updated.changes.map(c => ({ ...c, applied: false }));
this._updateSession(updated);
}
getMultiFileEditSessions(): MultiFileEditSession[] {
return this._state.ultraFeatures.multiFileEditSessions;
}
private _updateSession(session: MultiFileEditSession): void {
const sessions = this._state.ultraFeatures.multiFileEditSessions.map(s =>
s.id === session.id ? session : s
);
this._state = {
...this._state,
ultraFeatures: { ...this._state.ultraFeatures, multiFileEditSessions: sessions },
};
this._onDidChangeState.fire();
}
// ─── Cursor Ultra: Parallel Completions ─────────────────────────────────────
async runParallelCompletion(prompt: string, models?: string[]): Promise<ParallelCompletion> {
const targetModels = models ?? ['rainymodel/chat', 'rainymodel/code', 'rainymodel/agent'];
const completion: ParallelCompletion = {
id: generateUuid(),
prompt,
models: targetModels,
results: [],
status: 'pending',
};
// Run completions in parallel across multiple models
const promises = targetModels.map(async (model) => {
const start = Date.now();
try {
const response = await fetch(`${RAINYMODEL_ENDPOINT}/chat/completions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model,
messages: [{ role: 'user', content: prompt }],
temperature: 0.7,
max_tokens: 2048,
}),
});
if (!response.ok) throw new Error(`${response.status}`);
const data = await response.json();
const content = data.choices?.[0]?.message?.content ?? '';
const tokenCount = data.usage?.total_tokens ?? 0;
return {
model,
content,
latencyMs: Date.now() - start,
tokenCount,
};
} catch {
return {
model,
content: '',
latencyMs: Date.now() - start,
tokenCount: 0,
};
}
});
const results = await Promise.allSettled(promises);
completion.results = results
.filter((r): r is PromiseFulfilledResult<ParallelCompletion['results'][0]> => r.status === 'fulfilled')
.map(r => r.value)
.filter(r => r.content.length > 0);
completion.status = completion.results.length === targetModels.length ? 'completed' : 'partial';
return completion;
}
selectCompletionResult(completionId: string, _model: string): void {
// Track which model the user preferred for future optimization
this.logAction('system', '', 'select-completion', completionId, { model: _model });
}
// ─── Cursor Ultra: Toggles ──────────────────────────────────────────────────
togglePredictiveEditing(enabled: boolean): void {
this._state = {
...this._state,
ultraFeatures: { ...this._state.ultraFeatures, predictiveEditingEnabled: enabled },
};
this._saveState();
this._onDidChangeState.fire();
}
toggleSmartContextWindow(enabled: boolean): void {
this._state = {
...this._state,
ultraFeatures: { ...this._state.ultraFeatures, smartContextWindowEnabled: enabled },
};
this._saveState();
this._onDidChangeState.fire();
}
toggleBugDetection(enabled: boolean): void {
this._state = {
...this._state,
ultraFeatures: { ...this._state.ultraFeatures, bugDetectionEnabled: enabled },
};
this._saveState();
this._onDidChangeState.fire();
}
}
// ─── Registration ───────────────────────────────────────────────────────────────
registerSingleton(IOrcideEnterpriseService, OrcideEnterpriseService, InstantiationType.Eager);

View file

@ -0,0 +1,755 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Emitter, Event } from '../../../../base/common/event.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js';
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
import { generateUuid } from '../../../../base/common/uuid.js';
// ─── Git & PR Integration for Orcide ─────────────────────────────────────────
const ORCIDE_GIT_STORAGE_KEY = 'orcide.gitIntegrationState';
export type GitProvider = 'github' | 'gitlab' | 'bitbucket' | 'gitea';
export type GitRemoteConfig = {
provider: GitProvider;
owner: string;
repo: string;
defaultBranch: string;
apiBaseUrl: string;
token?: string;
};
export type PullRequestDraft = {
title: string;
body: string;
sourceBranch: string;
targetBranch: string;
labels?: string[];
reviewers?: string[];
assignees?: string[];
isDraft: boolean;
};
export type PullRequest = {
id: string;
number: number;
title: string;
body: string;
state: 'open' | 'closed' | 'merged';
sourceBranch: string;
targetBranch: string;
author: string;
labels: string[];
reviewers: string[];
assignees: string[];
isDraft: boolean;
url: string;
createdAt: number;
updatedAt: number;
mergedAt?: number;
};
export type DeploymentTarget = {
id: string;
name: string;
type: 'render' | 'vercel' | 'netlify' | 'custom';
url: string;
branch: string;
autoDeployEnabled: boolean;
lastDeployedAt?: number;
lastDeployStatus?: 'success' | 'failed' | 'in_progress' | 'cancelled';
};
export type Deployment = {
id: string;
targetId: string;
commitSha: string;
branch: string;
status: 'queued' | 'building' | 'deploying' | 'success' | 'failed' | 'cancelled';
url?: string;
logs?: string;
startedAt: number;
completedAt?: number;
};
export type BranchInfo = {
name: string;
isDefault: boolean;
lastCommitSha: string;
lastCommitMessage: string;
lastCommitAuthor: string;
lastCommitDate: number;
aheadOfDefault: number;
behindDefault: number;
};
export type CommitInfo = {
sha: string;
message: string;
author: string;
authorEmail: string;
date: number;
files: string[];
};
export type GitServiceState = {
remote: GitRemoteConfig | null;
pullRequests: PullRequest[];
deploymentTargets: DeploymentTarget[];
deployments: Deployment[];
currentBranch: string | null;
branches: BranchInfo[];
isConnected: boolean;
};
// ─── Service Interface ──────────────────────────────────────────────────────────
export interface IOrcideGitService {
readonly _serviceBrand: undefined;
readonly state: GitServiceState;
onDidChangeState: Event<void>;
onDidCreatePR: Event<PullRequest>;
onDidDeploymentUpdate: Event<Deployment>;
// Remote configuration
configureRemote(config: GitRemoteConfig): void;
disconnectRemote(): void;
testRemoteConnection(): Promise<boolean>;
// Branch operations
getCurrentBranch(): string | null;
listBranches(): Promise<BranchInfo[]>;
createBranch(name: string, fromBranch?: string): Promise<BranchInfo>;
switchBranch(name: string): Promise<void>;
deleteBranch(name: string): Promise<void>;
// Commit operations
getRecentCommits(branch?: string, limit?: number): Promise<CommitInfo[]>;
generateCommitMessage(diff: string): Promise<string>;
// Pull Request operations
createPullRequest(draft: PullRequestDraft): Promise<PullRequest>;
updatePullRequest(prId: string, updates: Partial<PullRequestDraft>): Promise<PullRequest>;
mergePullRequest(prId: string, strategy?: 'merge' | 'squash' | 'rebase'): Promise<PullRequest>;
closePullRequest(prId: string): Promise<void>;
listPullRequests(state?: 'open' | 'closed' | 'all'): Promise<PullRequest[]>;
getPullRequest(prNumber: number): Promise<PullRequest | null>;
generatePRDescription(sourceBranch: string, targetBranch: string): Promise<string>;
// Deployment operations
addDeploymentTarget(target: Omit<DeploymentTarget, 'id'>): DeploymentTarget;
removeDeploymentTarget(targetId: string): void;
triggerDeployment(targetId: string, branch?: string): Promise<Deployment>;
getDeploymentStatus(deploymentId: string): Promise<Deployment>;
listDeployments(targetId?: string): Deployment[];
cancelDeployment(deploymentId: string): Promise<void>;
}
export const IOrcideGitService = createDecorator<IOrcideGitService>('orcideGitService');
// ─── Orcest API Endpoints ───────────────────────────────────────────────────────
const ORCEST_GIT_API = 'https://api.orcest.ai/v1/git';
const RAINYMODEL_ENDPOINT = 'https://rm.orcest.ai/v1';
// ─── Service Implementation ─────────────────────────────────────────────────────
class OrcideGitService extends Disposable implements IOrcideGitService {
readonly _serviceBrand: undefined;
private _state: GitServiceState;
private readonly _onDidChangeState = this._register(new Emitter<void>());
readonly onDidChangeState: Event<void> = this._onDidChangeState.event;
private readonly _onDidCreatePR = this._register(new Emitter<PullRequest>());
readonly onDidCreatePR: Event<PullRequest> = this._onDidCreatePR.event;
private readonly _onDidDeploymentUpdate = this._register(new Emitter<Deployment>());
readonly onDidDeploymentUpdate: Event<Deployment> = this._onDidDeploymentUpdate.event;
get state(): GitServiceState {
return this._state;
}
constructor(
@IStorageService private readonly _storageService: IStorageService,
) {
super();
this._state = {
remote: null,
pullRequests: [],
deploymentTargets: [],
deployments: [],
currentBranch: null,
branches: [],
isConnected: false,
};
this._loadFromStorage();
}
private _loadFromStorage(): void {
const stored = this._storageService.get(ORCIDE_GIT_STORAGE_KEY, StorageScope.APPLICATION);
if (stored) {
try {
const parsed = JSON.parse(stored);
this._state = { ...this._state, ...parsed };
} catch { /* ignore */ }
}
this._onDidChangeState.fire();
}
private _saveState(): void {
const toStore = {
remote: this._state.remote,
deploymentTargets: this._state.deploymentTargets,
};
this._storageService.store(ORCIDE_GIT_STORAGE_KEY, JSON.stringify(toStore), StorageScope.APPLICATION, StorageTarget.USER);
}
// ── Remote Configuration ────────────────────────────────────────────────────
configureRemote(config: GitRemoteConfig): void {
this._state = { ...this._state, remote: config };
this._saveState();
this._onDidChangeState.fire();
}
disconnectRemote(): void {
this._state = {
...this._state,
remote: null,
pullRequests: [],
branches: [],
currentBranch: null,
isConnected: false,
};
this._saveState();
this._onDidChangeState.fire();
}
async testRemoteConnection(): Promise<boolean> {
if (!this._state.remote) return false;
try {
const { provider, apiBaseUrl, owner, repo, token } = this._state.remote;
let url: string;
switch (provider) {
case 'github':
url = `${apiBaseUrl || 'https://api.github.com'}/repos/${owner}/${repo}`;
break;
case 'gitlab':
url = `${apiBaseUrl || 'https://gitlab.com/api/v4'}/projects/${encodeURIComponent(`${owner}/${repo}`)}`;
break;
case 'bitbucket':
url = `${apiBaseUrl || 'https://api.bitbucket.org/2.0'}/repositories/${owner}/${repo}`;
break;
case 'gitea':
url = `${apiBaseUrl}/repos/${owner}/${repo}`;
break;
}
const headers: Record<string, string> = { 'Accept': 'application/json' };
if (token) {
headers['Authorization'] = provider === 'gitlab' ? `Bearer ${token}` : `token ${token}`;
}
const response = await fetch(url, { headers });
const connected = response.ok;
this._state = { ...this._state, isConnected: connected };
this._onDidChangeState.fire();
return connected;
} catch {
this._state = { ...this._state, isConnected: false };
this._onDidChangeState.fire();
return false;
}
}
// ── Branch Operations ───────────────────────────────────────────────────────
getCurrentBranch(): string | null {
return this._state.currentBranch;
}
async listBranches(): Promise<BranchInfo[]> {
if (!this._state.remote) throw new Error('No remote configured');
const { provider, apiBaseUrl, owner, repo, token } = this._state.remote;
const headers: Record<string, string> = { 'Accept': 'application/json' };
if (token) {
headers['Authorization'] = provider === 'gitlab' ? `Bearer ${token}` : `token ${token}`;
}
let url: string;
switch (provider) {
case 'github':
url = `${apiBaseUrl || 'https://api.github.com'}/repos/${owner}/${repo}/branches`;
break;
case 'gitlab':
url = `${apiBaseUrl || 'https://gitlab.com/api/v4'}/projects/${encodeURIComponent(`${owner}/${repo}`)}/repository/branches`;
break;
default:
url = `${apiBaseUrl}/repos/${owner}/${repo}/branches`;
}
const response = await fetch(url, { headers });
if (!response.ok) throw new Error(`Failed to list branches: ${response.status}`);
const data = await response.json();
const branches: BranchInfo[] = (data as Array<Record<string, unknown>>).map((b: Record<string, unknown>) => ({
name: (b.name as string) ?? '',
isDefault: b.name === this._state.remote?.defaultBranch,
lastCommitSha: ((b.commit as Record<string, unknown>)?.sha as string) ?? '',
lastCommitMessage: (((b.commit as Record<string, unknown>)?.commit as Record<string, unknown>)?.message as string) ?? '',
lastCommitAuthor: ((((b.commit as Record<string, unknown>)?.commit as Record<string, unknown>)?.author as Record<string, unknown>)?.name as string) ?? '',
lastCommitDate: Date.now(),
aheadOfDefault: 0,
behindDefault: 0,
}));
this._state = { ...this._state, branches };
this._onDidChangeState.fire();
return branches;
}
async createBranch(name: string, _fromBranch?: string): Promise<BranchInfo> {
const branch: BranchInfo = {
name,
isDefault: false,
lastCommitSha: '',
lastCommitMessage: '',
lastCommitAuthor: '',
lastCommitDate: Date.now(),
aheadOfDefault: 0,
behindDefault: 0,
};
this._state = {
...this._state,
branches: [...this._state.branches, branch],
currentBranch: name,
};
this._onDidChangeState.fire();
return branch;
}
async switchBranch(name: string): Promise<void> {
this._state = { ...this._state, currentBranch: name };
this._onDidChangeState.fire();
}
async deleteBranch(name: string): Promise<void> {
this._state = {
...this._state,
branches: this._state.branches.filter(b => b.name !== name),
};
this._onDidChangeState.fire();
}
// ── Commit Operations ───────────────────────────────────────────────────────
async getRecentCommits(branch?: string, limit?: number): Promise<CommitInfo[]> {
if (!this._state.remote) throw new Error('No remote configured');
const { provider, apiBaseUrl, owner, repo, token } = this._state.remote;
const headers: Record<string, string> = { 'Accept': 'application/json' };
if (token) {
headers['Authorization'] = provider === 'gitlab' ? `Bearer ${token}` : `token ${token}`;
}
const branchName = branch ?? this._state.remote.defaultBranch;
const perPage = limit ?? 20;
let url: string;
switch (provider) {
case 'github':
url = `${apiBaseUrl || 'https://api.github.com'}/repos/${owner}/${repo}/commits?sha=${branchName}&per_page=${perPage}`;
break;
default:
url = `${apiBaseUrl}/repos/${owner}/${repo}/commits?sha=${branchName}&limit=${perPage}`;
}
const response = await fetch(url, { headers });
if (!response.ok) throw new Error(`Failed to get commits: ${response.status}`);
const data = await response.json();
return (data as Array<Record<string, unknown>>).map((c: Record<string, unknown>) => ({
sha: (c.sha as string) ?? '',
message: (((c.commit as Record<string, unknown>)?.message as string) ?? ''),
author: ((((c.commit as Record<string, unknown>)?.author as Record<string, unknown>)?.name as string) ?? ''),
authorEmail: ((((c.commit as Record<string, unknown>)?.author as Record<string, unknown>)?.email as string) ?? ''),
date: Date.now(),
files: [],
}));
}
async generateCommitMessage(diff: string): Promise<string> {
try {
const response = await fetch(`${RAINYMODEL_ENDPOINT}/chat/completions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'rainymodel/code',
messages: [
{
role: 'system',
content: 'You are a helpful assistant that generates concise, descriptive git commit messages. Follow conventional commit format (feat, fix, refactor, docs, chore, etc). Output only the commit message, nothing else.',
},
{
role: 'user',
content: `Generate a commit message for the following diff:\n\n${diff}`,
},
],
temperature: 0.3,
max_tokens: 200,
}),
});
if (!response.ok) throw new Error(`Failed to generate commit message: ${response.status}`);
const data = await response.json();
return data.choices?.[0]?.message?.content?.trim() ?? 'chore: update code';
} catch {
return 'chore: update code';
}
}
// ── Pull Request Operations ─────────────────────────────────────────────────
async createPullRequest(draft: PullRequestDraft): Promise<PullRequest> {
if (!this._state.remote) throw new Error('No remote configured');
const { provider, apiBaseUrl, owner, repo, token } = this._state.remote;
const headers: Record<string, string> = {
'Accept': 'application/json',
'Content-Type': 'application/json',
};
if (token) {
headers['Authorization'] = provider === 'gitlab' ? `Bearer ${token}` : `token ${token}`;
}
let url: string;
let body: Record<string, unknown>;
switch (provider) {
case 'github':
url = `${apiBaseUrl || 'https://api.github.com'}/repos/${owner}/${repo}/pulls`;
body = {
title: draft.title,
body: draft.body,
head: draft.sourceBranch,
base: draft.targetBranch,
draft: draft.isDraft,
};
break;
case 'gitlab':
url = `${apiBaseUrl || 'https://gitlab.com/api/v4'}/projects/${encodeURIComponent(`${owner}/${repo}`)}/merge_requests`;
body = {
title: draft.title,
description: draft.body,
source_branch: draft.sourceBranch,
target_branch: draft.targetBranch,
};
break;
default:
url = `${apiBaseUrl}/repos/${owner}/${repo}/pulls`;
body = {
title: draft.title,
body: draft.body,
head: draft.sourceBranch,
base: draft.targetBranch,
};
}
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify(body),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Failed to create PR: ${response.status} - ${errorText}`);
}
const data = await response.json() as Record<string, unknown>;
const now = Date.now();
const pr: PullRequest = {
id: generateUuid(),
number: (data.number as number) ?? (data.iid as number) ?? 0,
title: draft.title,
body: draft.body,
state: 'open',
sourceBranch: draft.sourceBranch,
targetBranch: draft.targetBranch,
author: '',
labels: draft.labels ?? [],
reviewers: draft.reviewers ?? [],
assignees: draft.assignees ?? [],
isDraft: draft.isDraft,
url: (data.html_url as string) ?? (data.web_url as string) ?? '',
createdAt: now,
updatedAt: now,
};
this._state = {
...this._state,
pullRequests: [...this._state.pullRequests, pr],
};
this._onDidCreatePR.fire(pr);
this._onDidChangeState.fire();
return pr;
}
async updatePullRequest(prId: string, updates: Partial<PullRequestDraft>): Promise<PullRequest> {
const prIndex = this._state.pullRequests.findIndex(p => p.id === prId);
if (prIndex === -1) throw new Error(`PR ${prId} not found`);
const existing = this._state.pullRequests[prIndex];
const updated: PullRequest = {
...existing,
title: updates.title ?? existing.title,
body: updates.body ?? existing.body,
labels: updates.labels ?? existing.labels,
reviewers: updates.reviewers ?? existing.reviewers,
assignees: updates.assignees ?? existing.assignees,
isDraft: updates.isDraft ?? existing.isDraft,
updatedAt: Date.now(),
};
const pullRequests = [...this._state.pullRequests];
pullRequests[prIndex] = updated;
this._state = { ...this._state, pullRequests };
this._onDidChangeState.fire();
return updated;
}
async mergePullRequest(prId: string, _strategy?: 'merge' | 'squash' | 'rebase'): Promise<PullRequest> {
const prIndex = this._state.pullRequests.findIndex(p => p.id === prId);
if (prIndex === -1) throw new Error(`PR ${prId} not found`);
const existing = this._state.pullRequests[prIndex];
if (!this._state.remote) throw new Error('No remote configured');
const { provider, apiBaseUrl, owner, repo, token } = this._state.remote;
const headers: Record<string, string> = {
'Accept': 'application/json',
'Content-Type': 'application/json',
};
if (token) {
headers['Authorization'] = provider === 'gitlab' ? `Bearer ${token}` : `token ${token}`;
}
let url: string;
switch (provider) {
case 'github':
url = `${apiBaseUrl || 'https://api.github.com'}/repos/${owner}/${repo}/pulls/${existing.number}/merge`;
break;
case 'gitlab':
url = `${apiBaseUrl || 'https://gitlab.com/api/v4'}/projects/${encodeURIComponent(`${owner}/${repo}`)}/merge_requests/${existing.number}/merge`;
break;
default:
url = `${apiBaseUrl}/repos/${owner}/${repo}/pulls/${existing.number}/merge`;
}
const response = await fetch(url, {
method: 'PUT',
headers,
body: JSON.stringify({ merge_method: _strategy ?? 'merge' }),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Failed to merge PR: ${response.status} - ${errorText}`);
}
const merged: PullRequest = {
...existing,
state: 'merged',
mergedAt: Date.now(),
updatedAt: Date.now(),
};
const pullRequests = [...this._state.pullRequests];
pullRequests[prIndex] = merged;
this._state = { ...this._state, pullRequests };
this._onDidChangeState.fire();
return merged;
}
async closePullRequest(prId: string): Promise<void> {
const prIndex = this._state.pullRequests.findIndex(p => p.id === prId);
if (prIndex === -1) throw new Error(`PR ${prId} not found`);
const pullRequests = [...this._state.pullRequests];
pullRequests[prIndex] = {
...pullRequests[prIndex],
state: 'closed',
updatedAt: Date.now(),
};
this._state = { ...this._state, pullRequests };
this._onDidChangeState.fire();
}
async listPullRequests(state?: 'open' | 'closed' | 'all'): Promise<PullRequest[]> {
if (state === 'all') return this._state.pullRequests;
if (state) return this._state.pullRequests.filter(p => p.state === state);
return this._state.pullRequests.filter(p => p.state === 'open');
}
async getPullRequest(prNumber: number): Promise<PullRequest | null> {
return this._state.pullRequests.find(p => p.number === prNumber) ?? null;
}
async generatePRDescription(sourceBranch: string, targetBranch: string): Promise<string> {
try {
const commits = await this.getRecentCommits(sourceBranch, 10);
const commitSummary = commits.map(c => `- ${c.message}`).join('\n');
const response = await fetch(`${RAINYMODEL_ENDPOINT}/chat/completions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'rainymodel/code',
messages: [
{
role: 'system',
content: 'You are a helpful assistant that generates clear, comprehensive pull request descriptions. Include a summary section and a changes section. Use markdown formatting.',
},
{
role: 'user',
content: `Generate a PR description for merging ${sourceBranch} into ${targetBranch}.\n\nRecent commits:\n${commitSummary}`,
},
],
temperature: 0.5,
max_tokens: 1000,
}),
});
if (!response.ok) throw new Error(`Failed: ${response.status}`);
const data = await response.json();
return data.choices?.[0]?.message?.content ?? '';
} catch {
return `## Pull Request\n\nMerging \`${sourceBranch}\` into \`${targetBranch}\``;
}
}
// ── Deployment Operations ───────────────────────────────────────────────────
addDeploymentTarget(target: Omit<DeploymentTarget, 'id'>): DeploymentTarget {
const newTarget: DeploymentTarget = {
...target,
id: generateUuid(),
};
this._state = {
...this._state,
deploymentTargets: [...this._state.deploymentTargets, newTarget],
};
this._saveState();
this._onDidChangeState.fire();
return newTarget;
}
removeDeploymentTarget(targetId: string): void {
this._state = {
...this._state,
deploymentTargets: this._state.deploymentTargets.filter(t => t.id !== targetId),
};
this._saveState();
this._onDidChangeState.fire();
}
async triggerDeployment(targetId: string, branch?: string): Promise<Deployment> {
const target = this._state.deploymentTargets.find(t => t.id === targetId);
if (!target) throw new Error(`Deployment target ${targetId} not found`);
const deployment: Deployment = {
id: generateUuid(),
targetId,
commitSha: '',
branch: branch ?? target.branch,
status: 'queued',
startedAt: Date.now(),
};
this._state = {
...this._state,
deployments: [...this._state.deployments, deployment],
};
this._onDidDeploymentUpdate.fire(deployment);
this._onDidChangeState.fire();
// Trigger deployment via Orcest API
try {
const response = await fetch(`${ORCEST_GIT_API}/deploy`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
targetType: target.type,
targetUrl: target.url,
branch: deployment.branch,
targetName: target.name,
}),
});
if (response.ok) {
const data = await response.json();
const updated: Deployment = {
...deployment,
status: 'building',
commitSha: (data as Record<string, string>).commitSha ?? '',
url: (data as Record<string, string>).deployUrl,
};
this._updateDeployment(updated);
return updated;
}
} catch {
// Deployment trigger failed, mark as failed
const failed: Deployment = { ...deployment, status: 'failed', completedAt: Date.now() };
this._updateDeployment(failed);
return failed;
}
return deployment;
}
async getDeploymentStatus(deploymentId: string): Promise<Deployment> {
const deployment = this._state.deployments.find(d => d.id === deploymentId);
if (!deployment) throw new Error(`Deployment ${deploymentId} not found`);
return deployment;
}
listDeployments(targetId?: string): Deployment[] {
if (targetId) return this._state.deployments.filter(d => d.targetId === targetId);
return this._state.deployments;
}
async cancelDeployment(deploymentId: string): Promise<void> {
const deployment = this._state.deployments.find(d => d.id === deploymentId);
if (!deployment) throw new Error(`Deployment ${deploymentId} not found`);
this._updateDeployment({
...deployment,
status: 'cancelled',
completedAt: Date.now(),
});
}
private _updateDeployment(updated: Deployment): void {
const deployments = this._state.deployments.map(d =>
d.id === updated.id ? updated : d
);
this._state = { ...this._state, deployments };
this._onDidDeploymentUpdate.fire(updated);
this._onDidChangeState.fire();
}
}
// ─── Registration ───────────────────────────────────────────────────────────────
registerSingleton(IOrcideGitService, OrcideGitService, InstantiationType.Eager);

View file

@ -0,0 +1,359 @@
/*--------------------------------------------------------------------------------------
* Copyright 2025 Orcest AI. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { Emitter, Event } from '../../../../base/common/event.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js';
// ─── LangChain Integration for Orcest Ecosystem ──────────────────────────────
export type LangChainConfig = {
enabled: boolean;
rainyModelEndpoint: string;
ollamaFreeApiEndpoint: string;
maestristEndpoint: string;
laminoEndpoint: string;
defaultChainType: 'conversational' | 'retrieval_qa' | 'agent' | 'sequential';
memoryType: 'buffer' | 'summary' | 'conversation_buffer_window';
maxTokens: number;
temperature: number;
verbose: boolean;
};
export type LangChainTool = {
name: string;
description: string;
endpoint: string;
type: 'api' | 'function' | 'retriever';
enabled: boolean;
};
export type LangChainAgent = {
id: string;
name: string;
description: string;
model: string;
tools: string[];
systemPrompt: string;
status: 'active' | 'paused' | 'error';
};
export type LangChainState = {
config: LangChainConfig;
availableTools: LangChainTool[];
activeAgents: LangChainAgent[];
isConnected: boolean;
};
export interface IOrcideLangChainService {
readonly _serviceBrand: undefined;
readonly state: LangChainState;
onDidChangeState: Event<void>;
// Configuration
updateConfig(config: Partial<LangChainConfig>): void;
resetConfig(): void;
// Tools
registerTool(tool: Omit<LangChainTool, 'enabled'>): void;
removeTool(name: string): void;
enableTool(name: string): void;
disableTool(name: string): void;
getAvailableTools(): LangChainTool[];
// Agent management
createAgent(agent: Omit<LangChainAgent, 'id' | 'status'>): LangChainAgent;
removeAgent(agentId: string): void;
pauseAgent(agentId: string): void;
resumeAgent(agentId: string): void;
getActiveAgents(): LangChainAgent[];
// Chain execution
executeChain(input: string, chainType?: LangChainConfig['defaultChainType']): Promise<string>;
executeAgentChain(agentId: string, input: string): Promise<string>;
// Connection
testConnection(): Promise<boolean>;
}
export const IOrcideLangChainService = createDecorator<IOrcideLangChainService>('orcideLangChainService');
const defaultLangChainConfig: LangChainConfig = {
enabled: true,
rainyModelEndpoint: 'https://rm.orcest.ai/v1',
ollamaFreeApiEndpoint: 'https://ollamafreeapi.orcest.ai',
maestristEndpoint: 'https://agent.orcest.ai',
laminoEndpoint: 'https://llm.orcest.ai',
defaultChainType: 'agent',
memoryType: 'conversation_buffer_window',
maxTokens: 4096,
temperature: 0.7,
verbose: false,
};
const defaultOrcestTools: LangChainTool[] = [
{
name: 'rainymodel-chat',
description: 'Chat with RainyModel (auto-routing across free, internal, and premium providers)',
endpoint: 'https://rm.orcest.ai/v1/chat/completions',
type: 'api',
enabled: true,
},
{
name: 'rainymodel-code',
description: 'Code generation and completion via RainyModel code-specialized models',
endpoint: 'https://rm.orcest.ai/v1/chat/completions',
type: 'api',
enabled: true,
},
{
name: 'maestrist-agent',
description: 'AI software development agent for complex coding tasks',
endpoint: 'https://agent.orcest.ai/v1/agent',
type: 'api',
enabled: true,
},
{
name: 'lamino-workspace',
description: 'LLM workspace for collaborative AI conversations',
endpoint: 'https://llm.orcest.ai/v1/chat',
type: 'api',
enabled: true,
},
{
name: 'ollamafreeapi',
description: 'Free access to 65+ open-source LLMs via distributed Ollama network',
endpoint: 'https://ollamafreeapi.orcest.ai/api/chat',
type: 'api',
enabled: true,
},
{
name: 'file-reader',
description: 'Read and analyze files from the current workspace',
endpoint: 'local://file-reader',
type: 'function',
enabled: true,
},
{
name: 'code-search',
description: 'Search across the codebase for relevant code snippets',
endpoint: 'local://code-search',
type: 'retriever',
enabled: true,
},
];
class OrcideLangChainService extends Disposable implements IOrcideLangChainService {
readonly _serviceBrand: undefined;
private _state: LangChainState;
private readonly _onDidChangeState = this._register(new Emitter<void>());
readonly onDidChangeState: Event<void> = this._onDidChangeState.event;
get state(): LangChainState {
return this._state;
}
constructor() {
super();
this._state = {
config: { ...defaultLangChainConfig },
availableTools: [...defaultOrcestTools],
activeAgents: [],
isConnected: false,
};
this._checkConnection();
}
private async _checkConnection(): Promise<void> {
try {
const response = await fetch(`${this._state.config.rainyModelEndpoint.replace('/v1', '')}/health`);
this._state = { ...this._state, isConnected: response.ok };
} catch {
this._state = { ...this._state, isConnected: false };
}
this._onDidChangeState.fire();
}
// Configuration
updateConfig(config: Partial<LangChainConfig>): void {
this._state = {
...this._state,
config: { ...this._state.config, ...config },
};
this._onDidChangeState.fire();
}
resetConfig(): void {
this._state = {
...this._state,
config: { ...defaultLangChainConfig },
};
this._onDidChangeState.fire();
}
// Tools
registerTool(tool: Omit<LangChainTool, 'enabled'>): void {
const exists = this._state.availableTools.some(t => t.name === tool.name);
if (exists) return;
this._state = {
...this._state,
availableTools: [...this._state.availableTools, { ...tool, enabled: true }],
};
this._onDidChangeState.fire();
}
removeTool(name: string): void {
this._state = {
...this._state,
availableTools: this._state.availableTools.filter(t => t.name !== name),
};
this._onDidChangeState.fire();
}
enableTool(name: string): void {
this._state = {
...this._state,
availableTools: this._state.availableTools.map(t =>
t.name === name ? { ...t, enabled: true } : t
),
};
this._onDidChangeState.fire();
}
disableTool(name: string): void {
this._state = {
...this._state,
availableTools: this._state.availableTools.map(t =>
t.name === name ? { ...t, enabled: false } : t
),
};
this._onDidChangeState.fire();
}
getAvailableTools(): LangChainTool[] {
return this._state.availableTools;
}
// Agent management
createAgent(agent: Omit<LangChainAgent, 'id' | 'status'>): LangChainAgent {
const newAgent: LangChainAgent = {
...agent,
id: `agent-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
status: 'active',
};
this._state = {
...this._state,
activeAgents: [...this._state.activeAgents, newAgent],
};
this._onDidChangeState.fire();
return newAgent;
}
removeAgent(agentId: string): void {
this._state = {
...this._state,
activeAgents: this._state.activeAgents.filter(a => a.id !== agentId),
};
this._onDidChangeState.fire();
}
pauseAgent(agentId: string): void {
this._state = {
...this._state,
activeAgents: this._state.activeAgents.map(a =>
a.id === agentId ? { ...a, status: 'paused' as const } : a
),
};
this._onDidChangeState.fire();
}
resumeAgent(agentId: string): void {
this._state = {
...this._state,
activeAgents: this._state.activeAgents.map(a =>
a.id === agentId ? { ...a, status: 'active' as const } : a
),
};
this._onDidChangeState.fire();
}
getActiveAgents(): LangChainAgent[] {
return this._state.activeAgents.filter(a => a.status === 'active');
}
// Chain execution
async executeChain(input: string, chainType?: LangChainConfig['defaultChainType']): Promise<string> {
const model = chainType === 'agent' ? 'rainymodel/agent' : 'rainymodel/chat';
try {
const response = await fetch(`${this._state.config.rainyModelEndpoint}/chat/completions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model,
messages: [{ role: 'user', content: input }],
temperature: this._state.config.temperature,
max_tokens: this._state.config.maxTokens,
}),
});
if (!response.ok) throw new Error(`Chain execution failed: ${response.status}`);
const data = await response.json();
return data.choices?.[0]?.message?.content ?? '';
} catch (e) {
throw new Error(`LangChain execution error: ${e}`);
}
}
async executeAgentChain(agentId: string, input: string): Promise<string> {
const agent = this._state.activeAgents.find(a => a.id === agentId);
if (!agent) throw new Error(`Agent ${agentId} not found`);
if (agent.status !== 'active') throw new Error(`Agent ${agentId} is not active`);
const enabledTools = this._state.availableTools
.filter(t => t.enabled && agent.tools.includes(t.name))
.map(t => ({ type: 'function' as const, function: { name: t.name, description: t.description } }));
try {
const response = await fetch(`${this._state.config.rainyModelEndpoint}/chat/completions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: agent.model,
messages: [
{ role: 'system', content: agent.systemPrompt },
{ role: 'user', content: input },
],
tools: enabledTools.length > 0 ? enabledTools : undefined,
temperature: this._state.config.temperature,
max_tokens: this._state.config.maxTokens,
}),
});
if (!response.ok) throw new Error(`Agent chain failed: ${response.status}`);
const data = await response.json();
return data.choices?.[0]?.message?.content ?? '';
} catch (e) {
this._state = {
...this._state,
activeAgents: this._state.activeAgents.map(a =>
a.id === agentId ? { ...a, status: 'error' as const } : a
),
};
this._onDidChangeState.fire();
throw new Error(`Agent execution error: ${e}`);
}
}
// Connection test
async testConnection(): Promise<boolean> {
await this._checkConnection();
return this._state.isConnected;
}
}
registerSingleton(IOrcideLangChainService, OrcideLangChainService, InstantiationType.Eager);

View file

@ -6,26 +6,26 @@ import { registerSingleton, InstantiationType } from '../../../../platform/insta
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
import { ITextFileService } from '../../../services/textfile/common/textfiles.js';
type VoidModelType = {
type OrcideModelType = {
model: ITextModel | null;
editorModel: IResolvedTextEditorModel | null;
};
export interface IVoidModelService {
export interface IOrcideModelService {
readonly _serviceBrand: undefined;
initializeModel(uri: URI): Promise<void>;
getModel(uri: URI): VoidModelType;
getModelFromFsPath(fsPath: string): VoidModelType;
getModelSafe(uri: URI): Promise<VoidModelType>;
getModel(uri: URI): OrcideModelType;
getModelFromFsPath(fsPath: string): OrcideModelType;
getModelSafe(uri: URI): Promise<OrcideModelType>;
saveModel(uri: URI): Promise<void>;
}
export const IVoidModelService = createDecorator<IVoidModelService>('voidVoidModelService');
export const IOrcideModelService = createDecorator<IOrcideModelService>('orcideModelService');
class VoidModelService extends Disposable implements IVoidModelService {
class OrcideModelService extends Disposable implements IOrcideModelService {
_serviceBrand: undefined;
static readonly ID = 'voidVoidModelService';
static readonly ID = 'orcideModelService';
private readonly _modelRefOfURI: Record<string, IReference<IResolvedTextEditorModel>> = {};
constructor(
@ -53,7 +53,7 @@ class VoidModelService extends Disposable implements IVoidModelService {
}
};
getModelFromFsPath = (fsPath: string): VoidModelType => {
getModelFromFsPath = (fsPath: string): OrcideModelType => {
const editorModelRef = this._modelRefOfURI[fsPath];
if (!editorModelRef) {
return { model: null, editorModel: null };
@ -73,7 +73,7 @@ class VoidModelService extends Disposable implements IVoidModelService {
}
getModelSafe = async (uri: URI): Promise<VoidModelType> => {
getModelSafe = async (uri: URI): Promise<OrcideModelType> => {
if (!(uri.fsPath in this._modelRefOfURI)) await this.initializeModel(uri);
return this.getModel(uri);
@ -87,4 +87,4 @@ class VoidModelService extends Disposable implements IVoidModelService {
}
}
registerSingleton(IVoidModelService, VoidModelService, InstantiationType.Eager);
registerSingleton(IOrcideModelService, OrcideModelService, InstantiationType.Eager);

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 { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
export interface IVoidSCMService {
export interface IOrcideSCMService {
readonly _serviceBrand: undefined;
/**
* Get git diff --stat
@ -33,4 +33,4 @@ export interface IVoidSCMService {
gitLog(path: string): Promise<string>
}
export const IVoidSCMService = createDecorator<IVoidSCMService>('voidSCMService')
export const IOrcideSCMService = createDecorator<IOrcideSCMService>('orcideSCMService')

View file

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

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