aws-runtime-bridge 1.3.9 → 1.5.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 (37) hide show
  1. package/README.md +9 -4
  2. package/dist/adapter/OpencodeSdkAdapter.d.ts +13 -1
  3. package/dist/adapter/OpencodeSdkAdapter.d.ts.map +1 -1
  4. package/dist/adapter/OpencodeSdkAdapter.js +56 -4
  5. package/dist/adapter/OpencodeSdkAdapter.test.js +57 -1
  6. package/dist/config.d.ts +14 -1
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +103 -4
  9. package/dist/config.test.d.ts +2 -0
  10. package/dist/config.test.d.ts.map +1 -0
  11. package/dist/config.test.js +95 -0
  12. package/dist/routes/file-browser.d.ts +10 -0
  13. package/dist/routes/file-browser.d.ts.map +1 -1
  14. package/dist/routes/file-browser.js +206 -4
  15. package/dist/routes/file-browser.test.js +22 -0
  16. package/dist/routes/instance.d.ts +15 -0
  17. package/dist/routes/instance.d.ts.map +1 -1
  18. package/dist/routes/instance.js +25 -2
  19. package/dist/routes/instance.test.js +19 -0
  20. package/dist/services/aws-client-agent-mcp.test.js +1 -0
  21. package/dist/services/runtime-binding.d.ts.map +1 -1
  22. package/dist/services/runtime-binding.js +10 -3
  23. package/dist/services/runtime-binding.test.js +13 -1
  24. package/dist/services/session-output.d.ts +12 -0
  25. package/dist/services/session-output.d.ts.map +1 -1
  26. package/dist/services/session-output.js +15 -0
  27. package/dist/services/workspace-files.d.ts +72 -0
  28. package/dist/services/workspace-files.d.ts.map +1 -1
  29. package/dist/services/workspace-files.js +519 -21
  30. package/dist/services/workspace-files.test.js +387 -11
  31. package/dist/services/workspace-watch.d.ts +21 -0
  32. package/dist/services/workspace-watch.d.ts.map +1 -0
  33. package/dist/services/workspace-watch.js +123 -0
  34. package/dist/services/workspace-watch.test.d.ts +2 -0
  35. package/dist/services/workspace-watch.test.d.ts.map +1 -0
  36. package/dist/services/workspace-watch.test.js +38 -0
  37. package/package.json +8 -1
@@ -3,15 +3,79 @@
3
3
  *
4
4
  * 提供文件系统浏览功能
5
5
  */
6
- import { Router } from 'express';
6
+ import os from 'node:os';
7
+ import { createReadStream, promises as fs } from 'node:fs';
7
8
  import path from 'node:path';
8
- import { promises as fs } from 'node:fs';
9
- import { validateToken } from '../middleware/auth.js';
9
+ import { Router } from 'express';
10
+ import multer from 'multer';
10
11
  import { allowHostFileBrowser } from '../config.js';
12
+ import { validateToken } from '../middleware/auth.js';
11
13
  import { createLogger } from '../utils/logger.js';
12
- import { createWorkspaceEntry, deleteWorkspaceEntry, listWorkspaceDirectory, readWorkspaceFile, renameWorkspaceEntry, writeWorkspaceFile, } from '../services/workspace-files.js';
14
+ import { createWorkspaceEntry, deleteWorkspaceEntry, extractWorkspaceArchive, listWorkspaceDirectory, previewWorkspaceDocument, readWorkspaceFile, renameWorkspaceEntry, resolveWorkspaceDownloadTarget, streamWorkspaceDirectoryZip, uploadWorkspaceFiles, writeWorkspaceFile, } from '../services/workspace-files.js';
15
+ import { unwatchWorkspaceFile, watchWorkspaceFile } from '../services/workspace-watch.js';
13
16
  const log = createLogger('file-browser');
14
17
  export const fileBrowserRouter = Router();
18
+ export const WORKSPACE_UPLOAD_FILE_LIMIT = 2000;
19
+ const upload = multer({
20
+ dest: path.join(os.tmpdir(), 'agentswork-runtime-bridge-uploads'),
21
+ limits: {
22
+ files: WORKSPACE_UPLOAD_FILE_LIMIT,
23
+ fileSize: 512 * 1024 * 1024
24
+ }
25
+ });
26
+ function toBoolean(value) {
27
+ return value === true || value === 'true' || value === '1';
28
+ }
29
+ function contentDispositionFileName(fileName) {
30
+ const fallbackName = fileName
31
+ .replace(/[\\"\r\n]/g, '_')
32
+ .replace(/[^\x20-\x7E]/g, '_');
33
+ return `attachment; filename="${fallbackName}"; filename*=UTF-8''${encodeURIComponent(fileName)}`;
34
+ }
35
+ async function cleanupUploadedFiles(files = []) {
36
+ await Promise.all(files.map((file) => fs.rm(file.path, { force: true }).catch(() => undefined)));
37
+ }
38
+ export function createWorkspaceUploadLimitResponse(error) {
39
+ return {
40
+ status: 400,
41
+ body: {
42
+ error: error.code === 'LIMIT_FILE_COUNT'
43
+ ? `一次最多上传 ${WORKSPACE_UPLOAD_FILE_LIMIT} 个文件,请拆分文件夹后重试。`
44
+ : error.message,
45
+ code: error.code
46
+ }
47
+ };
48
+ }
49
+ export function parseWorkspaceUploadRelativePaths(body) {
50
+ const relativePathsJson = body.relativePathsJson;
51
+ if (typeof relativePathsJson === 'string' && relativePathsJson.trim()) {
52
+ const parsed = JSON.parse(relativePathsJson);
53
+ if (!Array.isArray(parsed)) {
54
+ throw new Error('relativePathsJson must be an array');
55
+ }
56
+ return parsed.map((relativePath) => String(relativePath || ''));
57
+ }
58
+ const relativePaths = body.relativePaths;
59
+ return Array.isArray(relativePaths)
60
+ ? relativePaths.map((relativePath) => String(relativePath || ''))
61
+ : typeof relativePaths === 'string'
62
+ ? [relativePaths]
63
+ : [];
64
+ }
65
+ function workspaceUploadMiddleware(req, res, next) {
66
+ upload.array('files')(req, res, (error) => {
67
+ if (!error) {
68
+ next();
69
+ return;
70
+ }
71
+ if (error instanceof multer.MulterError) {
72
+ const response = createWorkspaceUploadLimitResponse(error);
73
+ res.status(response.status).json(response.body);
74
+ return;
75
+ }
76
+ next(error);
77
+ });
78
+ }
15
79
  async function listHostDirectories(requestPath = '') {
16
80
  const platform = process.platform;
17
81
  const isWindows = platform === 'win32';
@@ -155,6 +219,61 @@ fileBrowserRouter.post('/workspace/read', validateToken, async (req, res) => {
155
219
  res.status(400).json({ error: err.message });
156
220
  }
157
221
  });
222
+ /**
223
+ * 预览工作区文档内容。
224
+ * POST /api/file-browser/workspace/preview
225
+ */
226
+ fileBrowserRouter.post('/workspace/preview', validateToken, async (req, res) => {
227
+ try {
228
+ const { workspacePath, filePath } = req.body || {};
229
+ const result = await previewWorkspaceDocument({
230
+ workspacePath: String(workspacePath || ''),
231
+ filePath: String(filePath || '')
232
+ });
233
+ res.json(result);
234
+ }
235
+ catch (error) {
236
+ const err = error;
237
+ log.error('failed to preview workspace document:', err);
238
+ res.status(400).json({ error: err.message });
239
+ }
240
+ });
241
+ /**
242
+ * 监听工作区文件变化,用于文档预览自动刷新。
243
+ * POST /api/file-browser/workspace/watch
244
+ */
245
+ fileBrowserRouter.post('/workspace/watch', validateToken, async (req, res) => {
246
+ try {
247
+ const { workspacePath, filePath } = req.body || {};
248
+ res.json(await watchWorkspaceFile({
249
+ workspacePath: String(workspacePath || ''),
250
+ filePath: String(filePath || '')
251
+ }));
252
+ }
253
+ catch (error) {
254
+ const err = error;
255
+ log.error('failed to watch workspace file:', err);
256
+ res.status(400).json({ error: err.message });
257
+ }
258
+ });
259
+ /**
260
+ * 取消监听工作区文件变化。
261
+ * POST /api/file-browser/workspace/unwatch
262
+ */
263
+ fileBrowserRouter.post('/workspace/unwatch', validateToken, async (req, res) => {
264
+ try {
265
+ const { workspacePath, filePath } = req.body || {};
266
+ res.json(await unwatchWorkspaceFile({
267
+ workspacePath: String(workspacePath || ''),
268
+ filePath: String(filePath || '')
269
+ }));
270
+ }
271
+ catch (error) {
272
+ const err = error;
273
+ log.error('failed to unwatch workspace file:', err);
274
+ res.status(400).json({ error: err.message });
275
+ }
276
+ });
158
277
  /**
159
278
  * 保存工作区文件内容
160
279
  * POST /api/file-browser/workspace/write
@@ -235,3 +354,86 @@ fileBrowserRouter.post('/workspace/delete', validateToken, async (req, res) => {
235
354
  res.status(400).json({ error: err.message });
236
355
  }
237
356
  });
357
+ /**
358
+ * 上传文件到工作区指定目录,可选自动解压常见压缩包。
359
+ * POST /api/file-browser/workspace/upload
360
+ */
361
+ fileBrowserRouter.post('/workspace/upload', validateToken, workspaceUploadMiddleware, async (req, res) => {
362
+ const files = (req.files || []);
363
+ try {
364
+ const { workspacePath, path: requestPath = '', extractArchives } = req.body || {};
365
+ const relativePaths = parseWorkspaceUploadRelativePaths(req.body || {});
366
+ const result = await uploadWorkspaceFiles({
367
+ workspacePath: String(workspacePath || ''),
368
+ targetPath: String(requestPath || ''),
369
+ extractArchives: toBoolean(extractArchives),
370
+ files: files.map((file, index) => ({
371
+ originalname: file.originalname,
372
+ relativePath: relativePaths[index],
373
+ path: file.path,
374
+ size: file.size
375
+ }))
376
+ });
377
+ res.json(result);
378
+ }
379
+ catch (error) {
380
+ const err = error;
381
+ log.error('failed to upload workspace files:', err);
382
+ res.status(400).json({ error: err.message });
383
+ }
384
+ finally {
385
+ await cleanupUploadedFiles(files);
386
+ }
387
+ });
388
+ /**
389
+ * 下载工作区文件或目录;目录会实时打包为 zip。
390
+ * POST /api/file-browser/workspace/download
391
+ */
392
+ fileBrowserRouter.post('/workspace/download', validateToken, async (req, res) => {
393
+ try {
394
+ const { workspacePath, targetPath } = req.body || {};
395
+ const target = await resolveWorkspaceDownloadTarget({
396
+ workspacePath: String(workspacePath || ''),
397
+ targetPath: String(targetPath || '')
398
+ });
399
+ res.setHeader('Content-Type', target.contentType);
400
+ res.setHeader('Content-Disposition', contentDispositionFileName(target.fileName));
401
+ res.setHeader('X-Workspace-Path', encodeURIComponent(target.workspacePath));
402
+ res.setHeader('X-Workspace-Target-Path', encodeURIComponent(target.targetPath));
403
+ if (target.isDirectory) {
404
+ await streamWorkspaceDirectoryZip(target.resolvedTargetPath, res);
405
+ return;
406
+ }
407
+ createReadStream(target.resolvedTargetPath).pipe(res);
408
+ }
409
+ catch (error) {
410
+ const err = error;
411
+ log.error('failed to download workspace entry:', err);
412
+ if (!res.headersSent) {
413
+ res.status(400).json({ error: err.message });
414
+ }
415
+ else {
416
+ res.destroy(err);
417
+ }
418
+ }
419
+ });
420
+ /**
421
+ * 解压工作区内的压缩包到指定目录。
422
+ * POST /api/file-browser/workspace/extract
423
+ */
424
+ fileBrowserRouter.post('/workspace/extract', validateToken, async (req, res) => {
425
+ try {
426
+ const { workspacePath, archivePath, outputPath = '' } = req.body || {};
427
+ const result = await extractWorkspaceArchive({
428
+ workspacePath: String(workspacePath || ''),
429
+ archivePath: String(archivePath || ''),
430
+ outputPath: String(outputPath || '')
431
+ });
432
+ res.json(result);
433
+ }
434
+ catch (error) {
435
+ const err = error;
436
+ log.error('failed to extract workspace archive:', err);
437
+ res.status(400).json({ error: err.message });
438
+ }
439
+ });
@@ -2,6 +2,8 @@
2
2
  * File Browser 路由单元测试
3
3
  */
4
4
  import { describe, it, expect } from 'vitest';
5
+ import multer from 'multer';
6
+ import { createWorkspaceUploadLimitResponse, parseWorkspaceUploadRelativePaths, WORKSPACE_UPLOAD_FILE_LIMIT } from './file-browser.js';
5
7
  describe('file-browser route validation', () => {
6
8
  it('returns root drives on Windows when path is empty', () => {
7
9
  const getRootForWindows = () => {
@@ -85,4 +87,24 @@ describe('file-browser response building', () => {
85
87
  expect(directories).toEqual(['src']);
86
88
  expect(files).toEqual(['package.json']);
87
89
  });
90
+ it('returns JSON guidance when folder upload exceeds file count limit', () => {
91
+ const response = createWorkspaceUploadLimitResponse(new multer.MulterError('LIMIT_FILE_COUNT'));
92
+ expect(response.status).toBe(400);
93
+ expect(response.body).toEqual({
94
+ error: `一次最多上传 ${WORKSPACE_UPLOAD_FILE_LIMIT} 个文件,请拆分文件夹后重试。`,
95
+ code: 'LIMIT_FILE_COUNT'
96
+ });
97
+ });
98
+ it('parses relative paths from a JSON manifest to preserve folder hierarchy', () => {
99
+ const relativePaths = parseWorkspaceUploadRelativePaths({
100
+ relativePathsJson: JSON.stringify(['a/b/c.txt', 'a/d/e.txt'])
101
+ });
102
+ expect(relativePaths).toEqual(['a/b/c.txt', 'a/d/e.txt']);
103
+ });
104
+ it('keeps backward compatibility with repeated relativePaths fields', () => {
105
+ const relativePaths = parseWorkspaceUploadRelativePaths({
106
+ relativePaths: ['a/b/c.txt', 'a/d/e.txt']
107
+ });
108
+ expect(relativePaths).toEqual(['a/b/c.txt', 'a/d/e.txt']);
109
+ });
88
110
  });
@@ -18,9 +18,24 @@ export interface SchedulerPingFailureResponse {
18
18
  schedulerBaseUrl: string;
19
19
  hint: string;
20
20
  }
21
+ interface AmbiguousSchedulerBaseUrlResponse {
22
+ ok: false;
23
+ error: "ambiguous_scheduler_base_url";
24
+ failureStage: "scheduler_ping";
25
+ runtimeBridge: "healthy";
26
+ schedulerBaseUrl: string;
27
+ autoRegisterTargetUrls: string[];
28
+ hint: string;
29
+ }
21
30
  /**
22
31
  * 构建调度中心 ping 失败响应。
23
32
  * 主流程:保留底层错误与 scheduler 地址,同时明确 bridge 本身已连通、失败点在 bridge 回连调度中心。
24
33
  */
25
34
  export declare function buildSchedulerPingFailureResponse(error: Error, configuredSchedulerBaseUrl: string): SchedulerPingFailureResponse;
35
+ /**
36
+ * Build the response for ambiguous scheduler targets.
37
+ * Main flow: never silently pick the first target; require an explicit scheduler URL or future scheduler identity routing.
38
+ */
39
+ export declare function buildAmbiguousSchedulerBaseUrlResponse(targetUrls: string[]): AmbiguousSchedulerBaseUrlResponse;
40
+ export {};
26
41
  //# sourceMappingURL=instance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/routes/instance.ts"],"names":[],"mappings":"AA6BA,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAC/D,IAAI,CAEN;AAED,eAAO,MAAM,cAAc,4CAAW,CAAC;AAyBvC,wBAAgB,4BAA4B,CAAC,gBAAgB,EAAE,MAAM,GAAG;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE;QACJ,EAAE,EAAE,OAAO,CAAC;QACZ,aAAa,CAAC,EAAE,SAAS,CAAC;QAC1B,oBAAoB,EAAE,OAAO,CAAC;QAC9B,qBAAqB,EAAE,OAAO,CAAC;QAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAqCA;AAED,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,SAAS,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,KAAK,EACZ,0BAA0B,EAAE,MAAM,GACjC,4BAA4B,CAiB9B"}
1
+ {"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/routes/instance.ts"],"names":[],"mappings":"AA6BA,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAC/D,IAAI,CAEN;AAED,eAAO,MAAM,cAAc,4CAAW,CAAC;AAyBvC,wBAAgB,4BAA4B,CAAC,gBAAgB,EAAE,MAAM,GAAG;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE;QACJ,EAAE,EAAE,OAAO,CAAC;QACZ,aAAa,CAAC,EAAE,SAAS,CAAC;QAC1B,oBAAoB,EAAE,OAAO,CAAC;QAC9B,qBAAqB,EAAE,OAAO,CAAC;QAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAqCA;AAED,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,SAAS,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,iCAAiC;IACzC,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,8BAA8B,CAAC;IACtC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,SAAS,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,KAAK,EACZ,0BAA0B,EAAE,MAAM,GACjC,4BAA4B,CAiB9B;AAED;;;GAGG;AACH,wBAAgB,sCAAsC,CACpD,UAAU,EAAE,MAAM,EAAE,GACnB,iCAAiC,CAUnC"}
@@ -2,7 +2,7 @@ import { Router } from "express";
2
2
  import axios from "axios";
3
3
  import { createHash, timingSafeEqual } from "node:crypto";
4
4
  import { validateToken } from "../middleware/auth.js";
5
- import { schedulerBaseUrl } from "../config.js";
5
+ import { resolveSchedulerBaseUrl } from "../config.js";
6
6
  import { getRuntimeAccessToken } from "../services/runtime-binding.js";
7
7
  import { loadInstanceState, saveInstanceState, } from "../services/instance-state.js";
8
8
  import { initInstance } from "../services/instance-init-service.js";
@@ -91,6 +91,21 @@ export function buildSchedulerPingFailureResponse(error, configuredSchedulerBase
91
91
  : "aws-runtime-bridge 已连通,但它回连调度中心失败。请确认 AWS_RUNTIME_SCHEDULER_BASE_URL 指向的调度中心地址可从 bridge 机器访问,并且运行时访问令牌仍有效。",
92
92
  };
93
93
  }
94
+ /**
95
+ * Build the response for ambiguous scheduler targets.
96
+ * Main flow: never silently pick the first target; require an explicit scheduler URL or future scheduler identity routing.
97
+ */
98
+ export function buildAmbiguousSchedulerBaseUrlResponse(targetUrls) {
99
+ return {
100
+ ok: false,
101
+ error: "ambiguous_scheduler_base_url",
102
+ failureStage: "scheduler_ping",
103
+ runtimeBridge: "healthy",
104
+ schedulerBaseUrl: "",
105
+ autoRegisterTargetUrls: targetUrls,
106
+ hint: "Multiple autoRegisterTargets.serverUrl values were found, so bridge cannot safely infer which scheduler /runtime/ping should call back. Set AWS_RUNTIME_SCHEDULER_BASE_URL explicitly, or use future schedulerId/token-bound multi-scheduler routing.",
107
+ };
108
+ }
94
109
  instanceRouter.get("/healthz", (_req, res) => {
95
110
  res.json({
96
111
  ok: true,
@@ -103,8 +118,16 @@ instanceRouter.get("/connection-check", (req, res) => {
103
118
  res.status(result.status).json(result.body);
104
119
  });
105
120
  instanceRouter.get("/ping", validateToken, async (_req, res) => {
121
+ const schedulerBaseUrlResolution = resolveSchedulerBaseUrl();
122
+ if (schedulerBaseUrlResolution.source === "ambiguous-auto-register-targets") {
123
+ res
124
+ .status(400)
125
+ .json(buildAmbiguousSchedulerBaseUrlResponse(schedulerBaseUrlResolution.ambiguousTargetUrls));
126
+ return;
127
+ }
128
+ const schedulerBaseUrl = schedulerBaseUrlResolution.url;
106
129
  try {
107
- const runtimeAccessToken = getRuntimeAccessToken(undefined, schedulerBaseUrl) || getRuntimeAccessToken();
130
+ const runtimeAccessToken = getRuntimeAccessToken(undefined, schedulerBaseUrl);
108
131
  if (!runtimeAccessToken) {
109
132
  res.status(401).json({ ok: false, error: "runtime_access_token_required" });
110
133
  return;
@@ -119,4 +119,23 @@ describe('instance route validation', () => {
119
119
  expect(response.runtimeBridge).toBe('healthy');
120
120
  expect(response.hint).toContain('运行时访问令牌仍有效');
121
121
  });
122
+ it('explains ambiguous auto-register scheduler targets without picking the first one', async () => {
123
+ const { buildAmbiguousSchedulerBaseUrlResponse } = await import('./instance.js');
124
+ const response = buildAmbiguousSchedulerBaseUrlResponse([
125
+ 'http://scheduler-a.local:7380',
126
+ 'http://scheduler-b.local:7380',
127
+ ]);
128
+ expect(response).toEqual({
129
+ ok: false,
130
+ error: 'ambiguous_scheduler_base_url',
131
+ failureStage: 'scheduler_ping',
132
+ runtimeBridge: 'healthy',
133
+ schedulerBaseUrl: '',
134
+ autoRegisterTargetUrls: [
135
+ 'http://scheduler-a.local:7380',
136
+ 'http://scheduler-b.local:7380',
137
+ ],
138
+ hint: expect.stringContaining('AWS_RUNTIME_SCHEDULER_BASE_URL'),
139
+ });
140
+ });
122
141
  });
@@ -199,6 +199,7 @@ describe('aws-client-agent-mcp service', () => {
199
199
  process.env.AWS_CLIENT_AGENT_MCP_COMMAND = 'aws-client-agent-mcp';
200
200
  process.env.CUSTOM_SECRET = 'should-not-leak';
201
201
  process.env.AWS_RUNTIME_HOME_DIR = mkdtempSync(path.join(os.tmpdir(), 'aws-mcp-config-'));
202
+ process.env.AWS_TEST_HOME = process.env.AWS_RUNTIME_HOME_DIR;
202
203
  process.env.AWS_RUNTIME_SCHEDULER_BASE_URL = '';
203
204
  process.env.AWS_SERVER_URL = '';
204
205
  process.env.AWS_MCP_HTTP_URL = '';
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-binding.d.ts","sourceRoot":"","sources":["../../src/services/runtime-binding.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA2DF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAqB5E;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAiCD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,MAAM,CAYR;AAsCD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAWT;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,MAAM,GAAG,SAAS,CAUpB;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,OAAO,CAeT;AAcD,wBAAgB,kBAAkB,IAAI,mBAAmB,CAgBxD;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CAClD,mBAAmB,EACnB,WAAW,GAAG,aAAa,CAC5B,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAWtB;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAG3C;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAcnE;AAED,wBAAgB,qBAAqB,CACnC,MAAM,CAAC,EAAE,OAAO,EAChB,aAAa,CAAC,EAAE,OAAO,GACtB,MAAM,GAAG,SAAS,CAepB;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAEjE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,mBAAmB,CAwCtB;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAkB1C"}
1
+ {"version":3,"file":"runtime-binding.d.ts","sourceRoot":"","sources":["../../src/services/runtime-binding.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA2DF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAqB5E;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAiCD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,MAAM,CAYR;AAsCD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAWT;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,MAAM,GAAG,SAAS,CAUpB;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,OAAO,CAeT;AAcD,wBAAgB,kBAAkB,IAAI,mBAAmB,CAgBxD;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CAClD,mBAAmB,EACnB,WAAW,GAAG,aAAa,CAC5B,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAWtB;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAG3C;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAcnE;AAED,wBAAgB,qBAAqB,CACnC,MAAM,CAAC,EAAE,OAAO,EAChB,aAAa,CAAC,EAAE,OAAO,GACtB,MAAM,GAAG,SAAS,CAyBpB;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAEjE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,mBAAmB,CAwCtB;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAkB1C"}
@@ -254,13 +254,20 @@ export function getRuntimeAccessToken(userId, serverBaseUrl) {
254
254
  if (scopedToken) {
255
255
  return scopedToken;
256
256
  }
257
- if (serverBaseUrl) {
258
- return undefined;
259
- }
260
257
  const state = loadRuntimeBinding();
261
258
  if (state.status !== "paired") {
262
259
  return undefined;
263
260
  }
261
+ if (serverBaseUrl) {
262
+ const requestedSchedulerBaseUrl = normalizeSchedulerBaseUrl(serverBaseUrl);
263
+ const boundSchedulerBaseUrl = normalizeSchedulerBaseUrl(state.schedulerBaseUrl);
264
+ if (requestedSchedulerBaseUrl &&
265
+ boundSchedulerBaseUrl &&
266
+ requestedSchedulerBaseUrl === boundSchedulerBaseUrl) {
267
+ return normalizeToken(state.accessToken) || undefined;
268
+ }
269
+ return undefined;
270
+ }
264
271
  return normalizeToken(state.accessToken) || undefined;
265
272
  }
266
273
  export function validateRuntimePairingCode(code) {
@@ -2,7 +2,7 @@ import { mkdirSync, mkdtempSync, rmSync } from "node:fs";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { afterEach, describe, expect, it } from "vitest";
5
- import { buildRuntimeTokenKey, clearScopedRuntimeAccessToken, getScopedRuntimeAccessToken, normalizeSchedulerBaseUrl, saveScopedRuntimeAccessToken, } from "./runtime-binding.js";
5
+ import { buildRuntimeTokenKey, clearScopedRuntimeAccessToken, getRuntimeAccessToken, getScopedRuntimeAccessToken, normalizeSchedulerBaseUrl, saveScopedRuntimeAccessToken, } from "./runtime-binding.js";
6
6
  const originalEnv = { ...process.env };
7
7
  const tempRoots = [];
8
8
  function useRuntimeHome() {
@@ -28,6 +28,18 @@ describe('runtime binding scheduler URL normalization', () => {
28
28
  expect(normalizeSchedulerBaseUrl('ws://127.0.0.1:8080/ws/agent')).toBe('http://127.0.0.1:8080');
29
29
  expect(normalizeSchedulerBaseUrl('wss://example.com/ws/agent')).toBe('https://example.com');
30
30
  });
31
+ it("returns paired binding token only when requested scheduler URL matches", async () => {
32
+ useRuntimeHome();
33
+ const { saveRuntimeBinding } = await import("./runtime-binding.js");
34
+ saveRuntimeBinding({
35
+ accessToken: "paired-runtime-token-123456",
36
+ instanceId: "bridge-1",
37
+ userId: "user-a",
38
+ schedulerBaseUrl: "http://scheduler.local:7380",
39
+ });
40
+ expect(getRuntimeAccessToken(undefined, "http://scheduler.local:7380/api")).toBe("paired-runtime-token-123456");
41
+ expect(getRuntimeAccessToken(undefined, "http://scheduler.local:8080")).toBeUndefined();
42
+ });
31
43
  it("scopes runtime tokens by user and full scheduler origin", () => {
32
44
  useRuntimeHome();
33
45
  const key7380 = saveScopedRuntimeAccessToken({
@@ -41,6 +41,18 @@ export declare function sendOutput(agentId: string, output: string, sessionId: s
41
41
  * @param questions - 结构化问题列表
42
42
  */
43
43
  export declare function sendQuestionRequest(agentId: string, sessionId: string, questions: unknown[]): Promise<void>;
44
+ export interface RuntimeFileChangedPayload {
45
+ bridgeBaseUrl?: string;
46
+ workspacePath: string;
47
+ filePath: string;
48
+ eventType: string;
49
+ size?: number;
50
+ mtimeMs?: number;
51
+ }
52
+ /**
53
+ * 发送工作区文件变更事件到调度器,由调度器通过 WebSocket 通知前端刷新预览。
54
+ */
55
+ export declare function sendFileChanged(payload: RuntimeFileChangedPayload): Promise<void>;
44
56
  /**
45
57
  * 调度输出刷新
46
58
  *
@@ -1 +1 @@
1
- {"version":3,"file":"session-output.d.ts","sourceRoot":"","sources":["../../src/services/session-output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAO3C,aAAa;AACb,eAAO,MAAM,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAa,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,EACjF,KAAK,CAAC,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACpD,OAAO,CAAC,IAAI,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAyBnC;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAAE,GACnB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAa3D;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCzE"}
1
+ {"version":3,"file":"session-output.d.ts","sourceRoot":"","sources":["../../src/services/session-output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAO3C,aAAa;AACb,eAAO,MAAM,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAa,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,EACjF,KAAK,CAAC,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACpD,OAAO,CAAC,IAAI,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAyBnC;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAAE,GACnB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAcvF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAa3D;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCzE"}
@@ -81,6 +81,21 @@ export async function sendQuestionRequest(agentId, sessionId, questions) {
81
81
  // ignore transient callback failures
82
82
  }
83
83
  }
84
+ /**
85
+ * 发送工作区文件变更事件到调度器,由调度器通过 WebSocket 通知前端刷新预览。
86
+ */
87
+ export async function sendFileChanged(payload) {
88
+ try {
89
+ const headers = runtimeAuthHeaders();
90
+ if (!headers) {
91
+ return;
92
+ }
93
+ await axios.post(`${schedulerBaseUrl}/api/runtime/callback/file-changed`, payload, { headers });
94
+ }
95
+ catch {
96
+ // ignore transient callback failures
97
+ }
98
+ }
84
99
  /**
85
100
  * 调度输出刷新
86
101
  *
@@ -6,6 +6,7 @@ export interface WorkspaceFileItem {
6
6
  name: string;
7
7
  path: string;
8
8
  isDirectory: boolean;
9
+ size?: number;
9
10
  }
10
11
  export interface ListWorkspaceDirectoryResult {
11
12
  currentPath: string;
@@ -17,6 +18,36 @@ export interface ReadWorkspaceFileResult {
17
18
  filePath: string;
18
19
  content: string;
19
20
  }
21
+ export interface WorkspaceDocumentPreviewResult {
22
+ workspacePath: string;
23
+ filePath: string;
24
+ kind: 'html' | 'unsupported';
25
+ content: string;
26
+ message?: string;
27
+ size: number;
28
+ mtimeMs: number;
29
+ }
30
+ export interface WorkspaceDownloadTarget {
31
+ workspacePath: string;
32
+ targetPath: string;
33
+ resolvedTargetPath: string;
34
+ fileName: string;
35
+ contentType: string;
36
+ isDirectory: boolean;
37
+ }
38
+ export interface WorkspaceUploadFile {
39
+ originalname: string;
40
+ relativePath?: string;
41
+ path: string;
42
+ size: number;
43
+ }
44
+ export interface WorkspaceArchiveExtractResult {
45
+ ok: true;
46
+ workspacePath: string;
47
+ archivePath: string;
48
+ targetPath: string;
49
+ extractedEntries: number;
50
+ }
20
51
  interface WorkspacePathParams {
21
52
  workspacePath: string;
22
53
  targetPath?: string;
@@ -39,6 +70,17 @@ interface RenameWorkspaceEntryParams extends WorkspacePathParams {
39
70
  interface DeleteWorkspaceEntryParams extends WorkspacePathParams {
40
71
  targetPath: string;
41
72
  }
73
+ interface UploadWorkspaceFilesParams extends WorkspacePathParams {
74
+ files: WorkspaceUploadFile[];
75
+ extractArchives?: boolean;
76
+ }
77
+ interface DownloadWorkspaceEntryParams extends WorkspacePathParams {
78
+ targetPath: string;
79
+ }
80
+ interface ExtractWorkspaceArchiveParams extends WorkspacePathParams {
81
+ archivePath: string;
82
+ outputPath?: string;
83
+ }
42
84
  /**
43
85
  * 列出工作区目录内容。
44
86
  */
@@ -47,6 +89,10 @@ export declare function listWorkspaceDirectory(params: WorkspacePathParams): Pro
47
89
  * 读取工作区中的文本文件。
48
90
  */
49
91
  export declare function readWorkspaceFile(params: WorkspaceFileParams): Promise<ReadWorkspaceFileResult>;
92
+ /**
93
+ * 返回工作区内 Word 文档的预览元数据;docx 由前端下载原文件后渲染,旧版 doc 明确提示不支持。
94
+ */
95
+ export declare function previewWorkspaceDocument(params: WorkspaceFileParams): Promise<WorkspaceDocumentPreviewResult>;
50
96
  /**
51
97
  * 将文本内容保存到工作区文件中。
52
98
  */
@@ -81,5 +127,31 @@ export declare function deleteWorkspaceEntry(params: DeleteWorkspaceEntryParams)
81
127
  workspacePath: string;
82
128
  targetPath: string;
83
129
  }>;
130
+ /**
131
+ * 上传文件到工作区指定目录,并可在上传后自动解压常见归档。
132
+ */
133
+ export declare function uploadWorkspaceFiles(params: UploadWorkspaceFilesParams): Promise<{
134
+ ok: true;
135
+ workspacePath: string;
136
+ targetPath: string;
137
+ files: Array<{
138
+ fileName: string;
139
+ targetPath: string;
140
+ size: number;
141
+ extracted?: WorkspaceArchiveExtractResult;
142
+ }>;
143
+ }>;
144
+ /**
145
+ * 解析工作区下载目标;目录由路由层打包为 zip,文件直接流式下载。
146
+ */
147
+ export declare function resolveWorkspaceDownloadTarget(params: DownloadWorkspaceEntryParams): Promise<WorkspaceDownloadTarget>;
148
+ /**
149
+ * 将目录内容以 zip 格式写入输出流,避免在磁盘生成临时包。
150
+ */
151
+ export declare function streamWorkspaceDirectoryZip(directoryPath: string, output: NodeJS.WritableStream): Promise<void>;
152
+ /**
153
+ * 解压工作区中的归档文件到指定目录,支持 zip、tar、tar.gz/tgz 与单文件 gz。
154
+ */
155
+ export declare function extractWorkspaceArchive(params: ExtractWorkspaceArchiveParams): Promise<WorkspaceArchiveExtractResult>;
84
156
  export {};
85
157
  //# sourceMappingURL=workspace-files.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-files.d.ts","sourceRoot":"","sources":["../../src/services/workspace-files.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,4BAA4B;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,mBAAmB;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,mBAAmB;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,wBAAyB,SAAQ,mBAAmB;IAC5D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,0BAA2B,SAAQ,mBAAmB;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,0BAA2B,SAAQ,mBAAmB;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,0BAA2B,SAAQ,mBAAmB;IAC9D,UAAU,EAAE,MAAM,CAAC;CACpB;AA+FD;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAoB/G;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAerG;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAWzI;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAC,CAiCxF;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAkCtF;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAelE"}
1
+ {"version":3,"file":"workspace-files.d.ts","sourceRoot":"","sources":["../../src/services/workspace-files.ts"],"names":[],"mappings":"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"}