-
Notifications
You must be signed in to change notification settings - Fork 55
馃尡 feat: Create an Explicit Default Workspace #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| import { createHash, randomBytes } from 'node:crypto'; | ||
| import { chmod, mkdir, open, readFile, rename, rm } from 'node:fs/promises'; | ||
| import { chmod, lstat, mkdir, open, readFile, rename, rm } from 'node:fs/promises'; | ||
| import { homedir } from 'node:os'; | ||
| import { dirname, join } from 'node:path'; | ||
|
|
||
|
|
@@ -27,12 +27,60 @@ function isPairedIdentity(value: unknown): value is PairedBridgeWorkerIdentity { | |
|
|
||
| export function defaultBridgeIdentityPath(workerId: string): string { | ||
| const readableName = workerId.replace(/[^A-Za-z0-9._-]/g, '_'); | ||
| const fileName = readableName === workerId | ||
| ? readableName | ||
| : `${readableName}-${createHash('sha256').update(workerId).digest('hex').slice(0, 16)}`; | ||
| const fileName = | ||
| readableName === workerId | ||
| ? readableName | ||
| : `${readableName}-${createHash('sha256') | ||
| .update(workerId) | ||
| .digest('hex') | ||
| .slice(0, 16)}`; | ||
| return join(homedir(), '.config', 'librechat', 'code', `${fileName}.json`); | ||
| } | ||
|
|
||
| function workspaceStorageName(value: string): string { | ||
| return `id-${createHash('sha256').update(value).digest('hex')}`; | ||
| } | ||
|
|
||
| export interface DefaultWorkspacePathOptions { | ||
| codeApiUrl: string; | ||
| securityIdentity: string; | ||
| workerId: string; | ||
| workspaceId: string; | ||
| homeDirectory?: string; | ||
| } | ||
|
|
||
| export function defaultWorkspacePath({ | ||
| codeApiUrl, | ||
| securityIdentity, | ||
| workerId, | ||
| workspaceId, | ||
| homeDirectory = homedir(), | ||
| }: DefaultWorkspacePathOptions): string { | ||
| const deploymentIdentity = `${codeApiUrl.replace(/\/+$/, '')}\0${securityIdentity}`; | ||
| return join( | ||
| homeDirectory, | ||
| '.local', | ||
| 'share', | ||
| 'librechat', | ||
| 'code', | ||
| 'workspaces', | ||
| workspaceStorageName(deploymentIdentity), | ||
| workspaceStorageName(workerId), | ||
| workspaceStorageName(workspaceId), | ||
|
Comment on lines
+68
to
+69
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the same host account re-pairs a worker ID for another tenant, this path remains identical because it includes only the public worker and workspace IDs. Useful? React with 馃憤聽/ 馃憥.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 38d0d50. Default paths now include a deployment/security-identity namespace derived from the normalized Code API URL plus the paired public key (or static credential), ahead of the worker/workspace digests. Credential refresh within one pairing remains stable; re-pairing or changing deployments produces an isolated path. Tests cover both identity and deployment changes. |
||
| ); | ||
| } | ||
|
|
||
| export async function ensurePrivateWorkspaceDirectory( | ||
| path: string, | ||
| ): Promise<void> { | ||
| await mkdir(path, { recursive: true, mode: 0o700 }); | ||
| const metadata = await lstat(path); | ||
| if (!metadata.isDirectory() || metadata.isSymbolicLink()) { | ||
| throw new BridgeProtocolError('Default workspace path must be a directory'); | ||
| } | ||
| await chmod(path, 0o700); | ||
| } | ||
|
|
||
| export async function saveBridgeIdentity( | ||
| path: string, | ||
| identity: PairedBridgeWorkerIdentity, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
LIBRECHAT_CODE_WORKER_DIRcontains incidental leading or trailing whitespace,nonEmptynow verifies the trimmed value but returns the original string, soLocalWorkspaceTools.createcallsrealpathon a different path and rejects registration. The parent implementation trimmed this environment variable, so this commit regresses previously valid configurations such asLIBRECHAT_CODE_WORKER_DIR=' /srv/project '; return the normalized value for environment input while retaining the intended empty-value handling.Useful? React with 馃憤聽/ 馃憥.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 47d4832. Environment-provided worker directories are trimmed before empty-value normalization, preserving the prior behavior; CLI-provided paths retain their literal spelling. Added a CLI regression test with leading/trailing environment whitespace.