@ultrst-armada/kloks 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/.krusbl-release-attestation.json +3 -3
  2. package/package.json +1 -1
  3. package/packages/backend/dist/{BaseStorageAdapter-tosOoSUg.d.ts → BaseStorageAdapter-EUCSvJse.d.ts} +7 -1
  4. package/packages/backend/dist/auth/index.d.ts +51 -13
  5. package/packages/backend/dist/auth/index.js +6 -2
  6. package/packages/backend/dist/{chunk-BI5RDDB4.js → chunk-3IUA66RS.js} +9 -2
  7. package/packages/backend/dist/{chunk-KSZ67VZJ.js → chunk-5RXXC6GE.js} +3 -3
  8. package/packages/backend/dist/{chunk-Y3X3H2XX.js → chunk-BPFZCDS4.js} +12 -12
  9. package/packages/backend/dist/{chunk-6QTNNZSE.js → chunk-BTMIK44G.js} +136 -71
  10. package/packages/backend/dist/{chunk-MPYASJ5A.js → chunk-HT2SEDHD.js} +1 -1
  11. package/packages/backend/dist/chunk-KKRWZDMN.js +237 -0
  12. package/packages/backend/dist/chunk-M4GSR46Y.js +205 -0
  13. package/packages/backend/dist/chunk-RBQ4CW3T.js +136 -0
  14. package/packages/backend/dist/{chunk-J2J24JVC.js → chunk-SHZAQTIT.js} +31 -204
  15. package/packages/backend/dist/{chunk-N4Z57FVR.js → chunk-XHADDA75.js} +9 -3
  16. package/packages/backend/dist/index.d.ts +5 -5
  17. package/packages/backend/dist/index.js +65 -50
  18. package/packages/backend/dist/krnl-services.js +7 -6
  19. package/packages/backend/dist/services/index.js +3 -2
  20. package/packages/backend/dist/srkl/index.d.ts +7 -1
  21. package/packages/backend/dist/srkl/index.js +3 -3
  22. package/packages/backend/dist/storage/index.d.ts +35 -3
  23. package/packages/backend/dist/storage/index.js +21 -10
  24. package/packages/backend/dist/workspace/index.d.ts +27 -33
  25. package/packages/backend/dist/workspace/index.js +2 -1
  26. package/packages/client/dist/index.d.ts +34 -1
  27. package/packages/client/dist/index.js +116 -0
  28. package/packages/backend/dist/chunk-LS3HWJBX.js +0 -0
  29. package/packages/backend/dist/chunk-ZDH4XI7W.js +0 -140
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schema": 1,
3
3
  "packageName": "@ultrst-armada/kloks",
4
- "version": "1.7.0",
5
- "sourceCommit": "b794ff2065167edac2d5c817897b5244e9136952",
4
+ "version": "1.8.0",
5
+ "sourceCommit": "d364f4fd5a705bea93c4fb0a93ff9740c1050f49",
6
6
  "releaseWorkflow": "npm Release",
7
- "workflowRunId": "40036485979"
7
+ "workflowRunId": "40208606705"
8
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultrst-armada/kloks",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -1,7 +1,7 @@
1
1
  import { SkipoBase } from '@ultrst-armada/kloks/functions';
2
2
 
3
3
  type StorageMode = 'local' | 'local_hosted' | 'remote';
4
- type StorageProviderType = 'local_fs' | 's3' | 'backblaze_b2' | 'b2' | 'cloudflare_r2' | 'r2' | 'supabase' | 'firebase' | 'google_drive';
4
+ type StorageProviderType = 'local_fs' | 'backblaze_b2' | 'b2' | 'supabase' | 'firebase' | 'google_drive';
5
5
  interface StorageConfig {
6
6
  provider: StorageProviderType;
7
7
  mode?: StorageMode;
@@ -19,6 +19,12 @@ interface StorageConfig {
19
19
  keyId?: string;
20
20
  applicationKey?: string;
21
21
  accountId?: string;
22
+ googleClientId?: string;
23
+ googleRedirectUri?: string;
24
+ googleAccessToken?: string;
25
+ googleAccessTokenExpiresAt?: number;
26
+ googleRefreshToken?: string;
27
+ googleRootFolderId?: string;
22
28
  }
23
29
  interface FileInfo {
24
30
  path: string;
@@ -26,31 +26,69 @@ declare class AdminGuard extends SkipoBase {
26
26
  static verifyUser(authHeaderOrToken: string | null | undefined, provider: BaseAccountProvider): Promise<AuthSession>;
27
27
  }
28
28
 
29
- /**
30
- * @file UnifiedAuthCore.ts
31
- * @description Strict Universal Authentication against "ultrst-users" and "ultrst-credentials".
32
- * Zero offline dummy fallbacks. Runs across Node.js, Vercel, and Cloudflare Workers (< 200 lines).
33
- */
34
- interface SystemUser {
29
+ interface CanonicalAuthUser {
35
30
  id: string;
36
31
  email: string;
37
- username: string;
38
32
  name: string;
33
+ username?: string;
34
+ role?: string;
35
+ status?: string;
36
+ appProfiles?: Record<string, unknown>;
37
+ emailVerified?: boolean;
38
+ }
39
+ interface CanonicalAuthSession {
40
+ session: Record<string, unknown>;
41
+ user: CanonicalAuthUser;
42
+ }
43
+ interface CanonicalAuthClientOptions {
44
+ baseUrl: string;
45
+ fetcher?: typeof fetch;
46
+ credentials?: RequestCredentials;
47
+ }
48
+ interface AuthResult {
49
+ success: boolean;
50
+ status: number;
51
+ user?: CanonicalAuthUser;
52
+ session?: Record<string, unknown>;
53
+ error?: string;
54
+ redirectUrl?: string;
55
+ }
56
+ declare class CanonicalAuthClient {
57
+ private readonly baseUrl;
58
+ private readonly fetcher;
59
+ private readonly credentials;
60
+ constructor(options: CanonicalAuthClientOptions);
61
+ private request;
62
+ signInEmail(email: string, password: string): Promise<AuthResult>;
63
+ signUpEmail(email: string, password: string, name: string): Promise<AuthResult>;
64
+ signInGoogle(callbackURL: string): Promise<AuthResult>;
65
+ requestGoogleDriveAccess(callbackURL?: string): Promise<AuthResult>;
66
+ getSession(cookie?: string): Promise<CanonicalAuthSession | null>;
67
+ signOut(): Promise<boolean>;
68
+ }
69
+ declare function createCanonicalAuthClient(baseUrl: string, fetcher?: typeof fetch): CanonicalAuthClient;
70
+
71
+ interface SystemUser extends CanonicalAuthUser {
72
+ username: string;
39
73
  role: string;
40
74
  status: string;
41
- appProfiles?: Record<string, any>;
75
+ appProfiles?: Record<string, unknown>;
76
+ }
77
+ interface AuthEnvironment {
78
+ SRKL_AUTH_BASE_URL?: string;
79
+ [key: string]: unknown;
42
80
  }
43
- declare function loginSystemUser(email: string, rawPass: string, isAdmin: boolean, queryDb: (sql: string, params?: unknown[]) => Promise<{
81
+ declare function loginSystemUser(email: string, rawPass: string, isAdmin: boolean, _queryDb: (sql: string, params?: unknown[]) => Promise<{
44
82
  rows: any[];
45
- }>): Promise<{
83
+ }>, env?: AuthEnvironment): Promise<{
46
84
  success: boolean;
47
85
  status: number;
48
86
  token?: string;
49
87
  user?: SystemUser;
50
88
  error?: string;
51
89
  }>;
52
- declare function resolveUserFromToken(tokenOrUserId: string, queryDb: (sql: string, params?: unknown[]) => Promise<{
90
+ declare function resolveUserFromToken(tokenOrUserId: string, _queryDb: (sql: string, params?: unknown[]) => Promise<{
53
91
  rows: any[];
54
- }>): Promise<SystemUser | null>;
92
+ }>, env?: AuthEnvironment): Promise<SystemUser | null>;
55
93
 
56
- export { AdminGuard, AuthSession, BaseAccountProvider, CreateUserData, LocalAccountProvider, PasswordHasher, type SystemUser, User, loginSystemUser, resolveUserFromToken };
94
+ export { AdminGuard, type AuthEnvironment, type AuthResult, AuthSession, BaseAccountProvider, CanonicalAuthClient, type CanonicalAuthClientOptions, type CanonicalAuthSession, type CanonicalAuthUser, CreateUserData, LocalAccountProvider, PasswordHasher, type SystemUser, User, createCanonicalAuthClient, loginSystemUser, resolveUserFromToken };
@@ -3,20 +3,24 @@ import {
3
3
  BaseAccountProvider,
4
4
  LocalAccountProvider,
5
5
  PasswordHasher
6
- } from "../chunk-MPYASJ5A.js";
6
+ } from "../chunk-HT2SEDHD.js";
7
7
  import {
8
+ CanonicalAuthClient,
8
9
  RateLimiter,
9
10
  SessionManager,
11
+ createCanonicalAuthClient,
10
12
  loginSystemUser,
11
13
  resolveUserFromToken
12
- } from "../chunk-ZDH4XI7W.js";
14
+ } from "../chunk-M4GSR46Y.js";
13
15
  export {
14
16
  AdminGuard,
15
17
  BaseAccountProvider,
18
+ CanonicalAuthClient,
16
19
  LocalAccountProvider,
17
20
  PasswordHasher,
18
21
  RateLimiter,
19
22
  SessionManager,
23
+ createCanonicalAuthClient,
20
24
  loginSystemUser,
21
25
  resolveUserFromToken
22
26
  };
@@ -121,9 +121,10 @@ var SrklClient = class {
121
121
  const creds = account.credentials || {};
122
122
  const sId = (account.serviceId || "").toLowerCase();
123
123
  const isB2 = sId.includes("backblaze") || sId === "b2";
124
+ const isGoogle = sId.includes("google_drive") || sId.includes("googledrive") || sId === "google";
124
125
  return {
125
126
  id: `conn-srkl-${account.id}`,
126
- provider: isB2 ? "backblaze_b2" : "aws_s3",
127
+ provider: isB2 ? "backblaze_b2" : isGoogle ? "google_drive" : "aws_s3",
127
128
  label: `SRKL: ${account.name || (isB2 ? "Backblaze" : "S3")}`,
128
129
  role: "redundant_clone",
129
130
  enabled: true,
@@ -137,7 +138,13 @@ var SrklClient = class {
137
138
  s3SecretAccessKey: creds.secretAccessKey || creds.applicationKey || creds.s3SecretAccessKey,
138
139
  s3BucketName: creds.bucketName || creds.s3BucketName,
139
140
  s3Region: creds.region || creds.s3Region,
140
- s3Endpoint: creds.endpoint || creds.s3Endpoint
141
+ s3Endpoint: creds.endpoint || creds.s3Endpoint,
142
+ googleEmail: creds.email || account.credentials?.email || account.name,
143
+ googleRootFolderId: creds.rootFolderId,
144
+ googleRootFolderName: creds.rootFolderName,
145
+ googleAccessToken: creds.accessToken,
146
+ googleAccessTokenExpiresAt: creds.accessTokenExpiresAt,
147
+ googleRefreshToken: creds.refreshToken
141
148
  };
142
149
  }
143
150
  };
@@ -1,9 +1,9 @@
1
- import {
2
- StorageAdapterFactory
3
- } from "./chunk-J2J24JVC.js";
4
1
  import {
5
2
  findUserWorkspace
6
3
  } from "./chunk-6K75XXFD.js";
4
+ import {
5
+ StorageAdapterFactory
6
+ } from "./chunk-SHZAQTIT.js";
7
7
 
8
8
  // src/services/workspaceGraphService.ts
9
9
  function slugify(name) {
@@ -1,16 +1,10 @@
1
- import {
2
- workspaceGraphService
3
- } from "./chunk-KSZ67VZJ.js";
4
1
  import {
5
2
  getSrklAccounts,
6
3
  srklListBackblazeBuckets
7
- } from "./chunk-N4Z57FVR.js";
8
- import {
9
- StorageAdapterFactory
10
- } from "./chunk-J2J24JVC.js";
4
+ } from "./chunk-XHADDA75.js";
11
5
  import {
12
- b2ListBuckets
13
- } from "./chunk-4QEMALXF.js";
6
+ workspaceGraphService
7
+ } from "./chunk-5RXXC6GE.js";
14
8
  import {
15
9
  formatCanonicalWorkspaceFolderName,
16
10
  sanitizeWorkspaceName
@@ -25,12 +19,18 @@ import {
25
19
  import {
26
20
  queryUnifiedDb
27
21
  } from "./chunk-VAFCR2MS.js";
22
+ import {
23
+ b2ListBuckets
24
+ } from "./chunk-4QEMALXF.js";
25
+ import {
26
+ StorageAdapterFactory
27
+ } from "./chunk-SHZAQTIT.js";
28
28
  import {
29
29
  RateLimiter,
30
30
  SessionManager,
31
31
  loginSystemUser,
32
32
  resolveUserFromToken
33
- } from "./chunk-ZDH4XI7W.js";
33
+ } from "./chunk-M4GSR46Y.js";
34
34
  import {
35
35
  createService,
36
36
  createServiceDefinition
@@ -56,12 +56,12 @@ var AuthServiceDefinition = createServiceDefinition({
56
56
  login: {
57
57
  id: "AuthService.login",
58
58
  name: "login",
59
- handler: async (input) => loginSystemUser(input.email, input.password, Boolean(input.isAdmin), (sql, params) => queryUnifiedDb(sql, params, input.env))
59
+ handler: async (input) => loginSystemUser(input.email, input.password, Boolean(input.isAdmin), (sql, params) => queryUnifiedDb(sql, params, input.env), input.env)
60
60
  },
61
61
  resolveUser: {
62
62
  id: "AuthService.resolveUser",
63
63
  name: "resolveUser",
64
- handler: async (input) => resolveUserFromToken(input.tokenOrUserId, (sql, params) => queryUnifiedDb(sql, params, input.env))
64
+ handler: async (input) => resolveUserFromToken(input.tokenOrUserId, (sql, params) => queryUnifiedDb(sql, params, input.env), input.env)
65
65
  },
66
66
  checkRateLimit: {
67
67
  id: "AuthService.checkRateLimit",
@@ -1,13 +1,9 @@
1
1
  import {
2
2
  createWorkspace,
3
3
  deleteWorkspace,
4
- deleteWorkspaceFile,
5
4
  findUserWorkspace,
6
5
  getWorkspaces,
7
- listWorkspaceFiles,
8
- readWorkspaceFile,
9
- updateWorkspace,
10
- writeWorkspaceFile
6
+ updateWorkspace
11
7
  } from "./chunk-6K75XXFD.js";
12
8
  import {
13
9
  b2DownloadFile,
@@ -15,6 +11,9 @@ import {
15
11
  b2UploadFile,
16
12
  queryUnifiedDb
17
13
  } from "./chunk-VAFCR2MS.js";
14
+ import {
15
+ GoogleDriveAdapter
16
+ } from "./chunk-KKRWZDMN.js";
18
17
 
19
18
  // src/workspace/WorkspaceFS.ts
20
19
  import { SkipoBase } from "@ultrst-armada/kloks/functions";
@@ -135,58 +134,6 @@ var WorkspaceCloneSyncEngine = class extends SkipoBase3 {
135
134
  }
136
135
  };
137
136
 
138
- // src/workspace/RemoteWorkspaceService.ts
139
- var RemoteWorkspaceService = class {
140
- type = "remote";
141
- async findWorkspace(workspaceId, env) {
142
- return await findUserWorkspace(workspaceId, env);
143
- }
144
- async listWorkspaces(userId, env) {
145
- return await getWorkspaces(userId, env);
146
- }
147
- async createWorkspace(userId, data, env) {
148
- return await createWorkspace(userId, data, env);
149
- }
150
- async updateWorkspace(userId, params, env) {
151
- return await updateWorkspace(userId, params, env);
152
- }
153
- async deleteWorkspace(userId, workspaceId, env) {
154
- return await deleteWorkspace(userId, workspaceId, env);
155
- }
156
- async readFile(workspaceId, filePath, env) {
157
- const { workspace, connection } = await this.findWorkspace(workspaceId, env);
158
- if (!workspace) throw new Error(`Workspace "${workspaceId}" not found.`);
159
- const data = await readWorkspaceFile(workspace, connection, filePath);
160
- if (!data) throw new Error(`File "${filePath}" not found in workspace "${workspaceId}".`);
161
- return data;
162
- }
163
- async writeFile(workspaceId, filePath, content, env) {
164
- const { workspace, connection } = await this.findWorkspace(workspaceId, env);
165
- if (!workspace) throw new Error(`Workspace "${workspaceId}" not found.`);
166
- await writeWorkspaceFile(workspace, connection, filePath, content);
167
- const size = typeof content === "string" ? new TextEncoder().encode(content).length : content.byteLength;
168
- return { success: true, path: filePath, sizeBytes: size };
169
- }
170
- async deleteFile(workspaceId, filePath, env) {
171
- const { workspace, connection } = await this.findWorkspace(workspaceId, env);
172
- if (!workspace) throw new Error(`Workspace "${workspaceId}" not found.`);
173
- const deleted = await deleteWorkspaceFile(workspace, connection, filePath);
174
- return { success: deleted };
175
- }
176
- async listFiles(workspaceId, subfolder = "", env) {
177
- const { workspace, connection } = await this.findWorkspace(workspaceId, env);
178
- if (!workspace) throw new Error(`Workspace "${workspaceId}" not found.`);
179
- const files = await listWorkspaceFiles(workspace, connection, subfolder);
180
- return files.map((f) => ({
181
- path: f.fileName,
182
- name: f.fileName.split("/").pop() || f.fileName,
183
- sizeBytes: f.sizeBytes,
184
- updatedAt: f.uploadTimestamp
185
- }));
186
- }
187
- };
188
- var remoteWorkspaceService = new RemoteWorkspaceService();
189
-
190
137
  // src/workspace/WorkingWorkspaceService.ts
191
138
  import fs2 from "fs";
192
139
  import path2 from "path";
@@ -245,8 +192,10 @@ function setWorkingWorkspaceConfig(cfg) {
245
192
  }
246
193
  return updated;
247
194
  }
248
- function getWorkingWorkspaceDir() {
249
- const dir = getWorkingWorkspaceConfig().workingDirectory;
195
+ function getWorkingWorkspaceDir(workspaceId = "default") {
196
+ const root = getWorkingWorkspaceConfig().workingDirectory;
197
+ const safeId = workspaceId.replace(/[^a-zA-Z0-9._-]/g, "_");
198
+ const dir = path.join(root, safeId);
250
199
  if (!fs.existsSync(dir)) {
251
200
  fs.mkdirSync(dir, { recursive: true });
252
201
  }
@@ -331,7 +280,7 @@ async function syncWorkspace(workspaceId) {
331
280
  }
332
281
  const { workspace, user, connection } = match;
333
282
  const folderKey = getWorkspaceFolderKey(workspace, user);
334
- const workingDir = getWorkingWorkspaceDir();
283
+ const workingDir = getWorkingWorkspaceDir(workspaceId);
335
284
  const isB2 = workspace.storageProvider === "backblaze_b2" || workspace.storageConfig?.type === "b2";
336
285
  const syncedFiles = [];
337
286
  let uploadedCount = 0;
@@ -428,6 +377,86 @@ async function syncWorkspace(workspaceId) {
428
377
  };
429
378
  }
430
379
  }
380
+ const isGoogleDrive = workspace.storageProvider === "google_drive" || workspace.storageConfig?.type === "google_drive";
381
+ if (isGoogleDrive) {
382
+ const creds = workspace.storageConfig || connection?.credentials || connection || {};
383
+ const rootFolderId = creds.googleRootFolderId || creds.rootFolderId || workspace.googleRootFolderId;
384
+ const adapter = new GoogleDriveAdapter({
385
+ provider: "google_drive",
386
+ googleAccessToken: creds.googleAccessToken || creds.accessToken,
387
+ googleAccessTokenExpiresAt: creds.googleAccessTokenExpiresAt,
388
+ googleRefreshToken: creds.googleRefreshToken || creds.refreshToken,
389
+ googleClientId: creds.googleClientId || process.env.GOOGLE_CLIENT_ID,
390
+ googleRootFolderId: rootFolderId
391
+ });
392
+ try {
393
+ const remoteFiles = await adapter.list("");
394
+ const remoteMap = /* @__PURE__ */ new Map();
395
+ for (const rf of remoteFiles) {
396
+ if (rf.path) remoteMap.set(rf.path, { size: rf.size, timestamp: rf.modifiedAt });
397
+ }
398
+ const localFiles = await collectLocalFiles(workingDir);
399
+ const localMap = /* @__PURE__ */ new Map();
400
+ for (const lf of localFiles) {
401
+ localMap.set(lf.relPath, lf);
402
+ }
403
+ for (const [relPath, rInfo] of remoteMap.entries()) {
404
+ const lFile = localMap.get(relPath);
405
+ const shouldDownload = !lFile || rInfo.timestamp > lFile.mtimeMs + 2e3;
406
+ if (shouldDownload) {
407
+ const buf = await adapter.read(relPath);
408
+ const destPath = path.join(workingDir, relPath);
409
+ await fs.promises.mkdir(path.dirname(destPath), { recursive: true });
410
+ await fs.promises.writeFile(destPath, buf);
411
+ try {
412
+ const fileTime = new Date(rInfo.timestamp);
413
+ await fs.promises.utimes(destPath, fileTime, fileTime);
414
+ } catch {
415
+ }
416
+ syncedFiles.push({ fileName: relPath, action: "DOWNLOADED", sizeBytes: buf.byteLength });
417
+ downloadedCount++;
418
+ }
419
+ }
420
+ for (const [relPath, lFile] of localMap.entries()) {
421
+ const rInfo = remoteMap.get(relPath);
422
+ const shouldUpload = !rInfo || lFile.mtimeMs > rInfo.timestamp + 2e3;
423
+ if (shouldUpload) {
424
+ const content = await fs.promises.readFile(lFile.fullPath);
425
+ await adapter.write(relPath, new Uint8Array(content));
426
+ syncedFiles.push({ fileName: relPath, action: "UPLOADED", sizeBytes: lFile.sizeBytes });
427
+ uploadedCount++;
428
+ } else if (!syncedFiles.some((f) => f.fileName === relPath)) {
429
+ syncedFiles.push({ fileName: relPath, action: "UP_TO_DATE", sizeBytes: lFile.sizeBytes });
430
+ }
431
+ }
432
+ return {
433
+ success: true,
434
+ workspaceId,
435
+ folderKey,
436
+ workingDir,
437
+ persistenceType: "google_drive",
438
+ targetLocation: `GoogleDrive://${rootFolderId || "root"}`,
439
+ syncedFiles,
440
+ uploadedCount,
441
+ downloadedCount,
442
+ syncedAt: nowIso
443
+ };
444
+ } catch (err) {
445
+ return {
446
+ success: false,
447
+ workspaceId,
448
+ folderKey,
449
+ workingDir,
450
+ persistenceType: "google_drive",
451
+ targetLocation: `GoogleDrive://${rootFolderId || "root"}`,
452
+ syncedFiles,
453
+ uploadedCount,
454
+ downloadedCount,
455
+ syncedAt: nowIso,
456
+ error: err.message || "Google Drive sync failed."
457
+ };
458
+ }
459
+ }
431
460
  const vaultDir = path.resolve(process.cwd(), folderKey);
432
461
  await fs.promises.mkdir(vaultDir, { recursive: true });
433
462
  try {
@@ -505,8 +534,8 @@ var WorkingWorkspaceService = class {
505
534
  }
506
535
  workingDirResolver;
507
536
  type = "working";
508
- getWorkingDir() {
509
- return this.workingDirResolver ? this.workingDirResolver() : getWorkingWorkspaceDir();
537
+ getWorkingDir(workspaceId) {
538
+ return this.workingDirResolver ? this.workingDirResolver(workspaceId) : getWorkingWorkspaceDir(workspaceId);
510
539
  }
511
540
  async findWorkspace(workspaceId, env) {
512
541
  return await findUserWorkspace(workspaceId, env);
@@ -516,7 +545,7 @@ var WorkingWorkspaceService = class {
516
545
  }
517
546
  async createWorkspace(userId, data, env) {
518
547
  const res = await createWorkspace(userId, data, env);
519
- const dir = this.getWorkingDir();
548
+ const dir = this.getWorkingDir(res.workspace?.id || data?.id || "default");
520
549
  try {
521
550
  await fs2.promises.mkdir(dir, { recursive: true });
522
551
  } catch {
@@ -531,12 +560,12 @@ var WorkingWorkspaceService = class {
531
560
  }
532
561
  async readFile(_workspaceId, filePath) {
533
562
  const cleanRel = filePath.replace(/^\/+/, "");
534
- const fullPath = path2.resolve(this.getWorkingDir(), cleanRel);
563
+ const fullPath = path2.resolve(this.getWorkingDir(_workspaceId), cleanRel);
535
564
  return await fs2.promises.readFile(fullPath);
536
565
  }
537
566
  async writeFile(_workspaceId, filePath, content) {
538
567
  const cleanRel = filePath.replace(/^\/+/, "");
539
- const fullPath = path2.resolve(this.getWorkingDir(), cleanRel);
568
+ const fullPath = path2.resolve(this.getWorkingDir(_workspaceId), cleanRel);
540
569
  await fs2.promises.mkdir(path2.dirname(fullPath), { recursive: true });
541
570
  const buffer = typeof content === "string" ? Buffer.from(content) : Buffer.from(content.buffer, content.byteOffset, content.byteLength);
542
571
  await fs2.promises.writeFile(fullPath, buffer);
@@ -544,7 +573,7 @@ var WorkingWorkspaceService = class {
544
573
  }
545
574
  async deleteFile(_workspaceId, filePath) {
546
575
  const cleanRel = filePath.replace(/^\/+/, "");
547
- const fullPath = path2.resolve(this.getWorkingDir(), cleanRel);
576
+ const fullPath = path2.resolve(this.getWorkingDir(_workspaceId), cleanRel);
548
577
  try {
549
578
  await fs2.promises.unlink(fullPath);
550
579
  return { success: true };
@@ -553,7 +582,7 @@ var WorkingWorkspaceService = class {
553
582
  }
554
583
  }
555
584
  async listFiles(_workspaceId, subfolder = "") {
556
- const baseDir = path2.resolve(this.getWorkingDir(), subfolder.replace(/^\/+/, ""));
585
+ const baseDir = path2.resolve(this.getWorkingDir(_workspaceId), subfolder.replace(/^\/+/, ""));
557
586
  if (!fs2.existsSync(baseDir)) return [];
558
587
  const entries = await fs2.promises.readdir(baseDir, { withFileTypes: true });
559
588
  return entries.map((e) => {
@@ -567,7 +596,7 @@ var WorkingWorkspaceService = class {
567
596
  } catch {
568
597
  }
569
598
  return {
570
- path: path2.relative(this.getWorkingDir(), full),
599
+ path: path2.relative(this.getWorkingDir(_workspaceId), full),
571
600
  name: e.name,
572
601
  isFolder: e.isDirectory(),
573
602
  sizeBytes,
@@ -581,12 +610,46 @@ var WorkingWorkspaceService = class {
581
610
  };
582
611
  var workingWorkspaceService = new WorkingWorkspaceService();
583
612
 
613
+ // src/workspace/RemoteWorkspaceService.ts
614
+ var RemoteWorkspaceService = class {
615
+ type = "working";
616
+ findWorkspace(id, env) {
617
+ return workingWorkspaceService.findWorkspace(id, env);
618
+ }
619
+ listWorkspaces(userId, env) {
620
+ return workingWorkspaceService.listWorkspaces(userId, env);
621
+ }
622
+ createWorkspace(userId, data, env) {
623
+ return workingWorkspaceService.createWorkspace(userId, data, env);
624
+ }
625
+ updateWorkspace(userId, params, env) {
626
+ return workingWorkspaceService.updateWorkspace(userId, params, env);
627
+ }
628
+ deleteWorkspace(userId, id, env) {
629
+ return workingWorkspaceService.deleteWorkspace(userId, id, env);
630
+ }
631
+ readFile(id, path3, env) {
632
+ return workingWorkspaceService.readFile(id, path3);
633
+ }
634
+ writeFile(id, path3, content, env) {
635
+ return workingWorkspaceService.writeFile(id, path3, content);
636
+ }
637
+ deleteFile(id, path3, env) {
638
+ return workingWorkspaceService.deleteFile(id, path3);
639
+ }
640
+ listFiles(id, subfolder, env) {
641
+ return workingWorkspaceService.listFiles(id, subfolder);
642
+ }
643
+ sync(id, options, env) {
644
+ return workingWorkspaceService.sync(id, options);
645
+ }
646
+ };
647
+ var remoteWorkspaceService = workingWorkspaceService;
648
+
584
649
  export {
585
650
  WorkspaceFS,
586
651
  SyncEngine,
587
652
  WorkspaceCloneSyncEngine,
588
- RemoteWorkspaceService,
589
- remoteWorkspaceService,
590
653
  getDefaultWorkingWorkspaceDir,
591
654
  getWorkingWorkspaceConfig,
592
655
  setWorkingWorkspaceConfig,
@@ -595,5 +658,7 @@ export {
595
658
  getWorkspaceFolderKey,
596
659
  syncWorkspace,
597
660
  WorkingWorkspaceService,
598
- workingWorkspaceService
661
+ workingWorkspaceService,
662
+ RemoteWorkspaceService,
663
+ remoteWorkspaceService
599
664
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  RateLimiter,
3
3
  SessionManager
4
- } from "./chunk-ZDH4XI7W.js";
4
+ } from "./chunk-M4GSR46Y.js";
5
5
 
6
6
  // src/auth/PasswordHasher.ts
7
7
  var bcrypt = null;