aws-runtime-bridge 1.2.0 → 1.2.1
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aws-client-agent-mcp.d.ts","sourceRoot":"","sources":["../../src/services/aws-client-agent-mcp.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"aws-client-agent-mcp.d.ts","sourceRoot":"","sources":["../../src/services/aws-client-agent-mcp.ts"],"names":[],"mappings":"AAwBA,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAuB7C,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,sCAAsC;IACrD,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,sCAAsC;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAaD,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;CAC3C;AAuBD,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAgLD,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,sCAA2C,GACnD,MAAM,GAAG,IAAI,CAoDf;AA2ED,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,sCAA2C,GACnD,kBAAkB,CAEpB;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,GAAE,sCAA2C,GACnD,kBAAkB,CAsBpB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,uBAAuB,GAC7B,kBAAkB,CAwBpB;AAED,wBAAgB,+BAA+B,IAAI,IAAI,CAgBtD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync, statSync, symlinkSync, writeFileSync, } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { getRuntimeHomeDir, port, schedulerBaseUrl } from "../config.js";
|
|
@@ -32,7 +32,10 @@ function getPackageRoot() {
|
|
|
32
32
|
return path.resolve(path.dirname(currentFile), "..", "..");
|
|
33
33
|
}
|
|
34
34
|
function getBundledEntryPath(packageRoot = getPackageRoot()) {
|
|
35
|
-
return path.join(packageRoot, "
|
|
35
|
+
return path.join(getBundledMcpRoot(packageRoot), "dist", "index.js");
|
|
36
|
+
}
|
|
37
|
+
function getBundledMcpRoot(packageRoot) {
|
|
38
|
+
return path.join(packageRoot, "package", "aws-client-agent-mcp");
|
|
36
39
|
}
|
|
37
40
|
function getReleasedMcpRoot() {
|
|
38
41
|
return path.join(getRuntimeHomeDir(), ".aws-bridge", "mcp");
|
|
@@ -56,7 +59,66 @@ function getBridgeVersion(packageRoot) {
|
|
|
56
59
|
return readPackageVersion(path.join(packageRoot, "package.json"));
|
|
57
60
|
}
|
|
58
61
|
function getBundledMcpVersion(packageRoot) {
|
|
59
|
-
return readPackageVersion(path.join(packageRoot, "package
|
|
62
|
+
return readPackageVersion(path.join(getBundledMcpRoot(packageRoot), "package.json"));
|
|
63
|
+
}
|
|
64
|
+
function copyIfExists(sourcePath, targetPath) {
|
|
65
|
+
if (!existsSync(sourcePath)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
copyFileOrDirectory(sourcePath, targetPath);
|
|
69
|
+
}
|
|
70
|
+
function copyFileOrDirectory(sourcePath, targetPath) {
|
|
71
|
+
const stat = statSync(sourcePath);
|
|
72
|
+
if (stat.isDirectory()) {
|
|
73
|
+
cpSync(sourcePath, targetPath, {
|
|
74
|
+
errorOnExist: false,
|
|
75
|
+
force: true,
|
|
76
|
+
recursive: true,
|
|
77
|
+
});
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
cpSync(sourcePath, targetPath, { errorOnExist: false, force: true });
|
|
81
|
+
}
|
|
82
|
+
function syncReleasedPackageMetadata(packageRoot, releasedRoot) {
|
|
83
|
+
const bundledMcpRoot = getBundledMcpRoot(packageRoot);
|
|
84
|
+
copyIfExists(path.join(bundledMcpRoot, "package.json"), path.join(releasedRoot, "package.json"));
|
|
85
|
+
copyIfExists(path.join(bundledMcpRoot, "README.md"), path.join(releasedRoot, "README.md"));
|
|
86
|
+
copyIfExists(path.join(bundledMcpRoot, "package-lock.json"), path.join(releasedRoot, "package-lock.json"));
|
|
87
|
+
}
|
|
88
|
+
function shouldReplaceNodeModulesLink(targetPath) {
|
|
89
|
+
if (!existsSync(targetPath)) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
const stat = lstatSync(targetPath);
|
|
93
|
+
return stat.isSymbolicLink() || stat.isDirectory();
|
|
94
|
+
}
|
|
95
|
+
function isExpectedNodeModulesLink(targetPath, sourcePath) {
|
|
96
|
+
if (!existsSync(targetPath)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
return realpathSync(targetPath) === realpathSync(sourcePath);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function ensureReleasedNodeModules(packageRoot, releasedRoot) {
|
|
107
|
+
const sourceNodeModules = path.join(packageRoot, "node_modules");
|
|
108
|
+
const releasedNodeModules = path.join(releasedRoot, "node_modules");
|
|
109
|
+
if (!existsSync(sourceNodeModules)) {
|
|
110
|
+
logger.warn(`[runtime-bridge] ${AWS_MCP_SERVER_NAME} MCP 未找到依赖目录,release 产物可能无法解析运行时依赖: ${sourceNodeModules}`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (isExpectedNodeModulesLink(releasedNodeModules, sourceNodeModules)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (!shouldReplaceNodeModulesLink(releasedNodeModules)) {
|
|
117
|
+
logger.warn(`[runtime-bridge] ${AWS_MCP_SERVER_NAME} MCP 依赖路径已存在但不是目录或链接,已保留: ${releasedNodeModules}`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
rmSync(releasedNodeModules, { recursive: true, force: true });
|
|
121
|
+
symlinkSync(sourceNodeModules, releasedNodeModules, process.platform === "win32" ? "junction" : "dir");
|
|
60
122
|
}
|
|
61
123
|
function listDistFiles(dirPath, rootPath = dirPath) {
|
|
62
124
|
return readdirSync(dirPath, { withFileTypes: true }).flatMap((entry) => {
|
|
@@ -128,6 +190,8 @@ export function releaseBundledAwsClientAgentMcp(options = {}) {
|
|
|
128
190
|
if (shouldRefreshReleasedMcp(releasedEntry, currentManifest, nextManifest)) {
|
|
129
191
|
rmSync(releasedDist, { recursive: true, force: true });
|
|
130
192
|
mkdirSync(releasedRoot, { recursive: true });
|
|
193
|
+
syncReleasedPackageMetadata(packageRoot, releasedRoot);
|
|
194
|
+
ensureReleasedNodeModules(packageRoot, releasedRoot);
|
|
131
195
|
cpSync(bundledDist, releasedDist, {
|
|
132
196
|
errorOnExist: false,
|
|
133
197
|
force: true,
|
|
@@ -140,6 +204,8 @@ export function releaseBundledAwsClientAgentMcp(options = {}) {
|
|
|
140
204
|
logger.info(`[runtime-bridge] ${AWS_MCP_SERVER_NAME} MCP 已更新到: ${releasedDist}`);
|
|
141
205
|
}
|
|
142
206
|
else {
|
|
207
|
+
syncReleasedPackageMetadata(packageRoot, releasedRoot);
|
|
208
|
+
ensureReleasedNodeModules(packageRoot, releasedRoot);
|
|
143
209
|
logger.info(`[runtime-bridge] ${AWS_MCP_SERVER_NAME} MCP 已是最新: ${releasedDist}`);
|
|
144
210
|
}
|
|
145
211
|
return releasedEntry;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readlinkSync, realpathSync, rmSync, writeFileSync, } from 'node:fs';
|
|
2
3
|
import os from 'node:os';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
@@ -13,7 +14,31 @@ function createBundledMcpPackage(version = '1.0.0') {
|
|
|
13
14
|
const bundledDist = path.join(packageRoot, 'package', 'aws-client-agent-mcp', 'dist');
|
|
14
15
|
mkdirSync(bundledDist, { recursive: true });
|
|
15
16
|
writeFileSync(path.join(packageRoot, 'package.json'), JSON.stringify({ name: 'aws-runtime-bridge', version: '9.9.9' }), 'utf-8');
|
|
16
|
-
writeFileSync(path.join(packageRoot, 'package', 'aws-client-agent-mcp', 'package.json'), JSON.stringify({
|
|
17
|
+
writeFileSync(path.join(packageRoot, 'package', 'aws-client-agent-mcp', 'package.json'), JSON.stringify({
|
|
18
|
+
name: 'aws-client-agent-mcp',
|
|
19
|
+
version,
|
|
20
|
+
type: 'module',
|
|
21
|
+
main: 'dist/index.js',
|
|
22
|
+
dependencies: {
|
|
23
|
+
'@modelcontextprotocol/sdk': '^1.27.1',
|
|
24
|
+
ws: '^8.14.2',
|
|
25
|
+
yaml: '^2.3.4',
|
|
26
|
+
},
|
|
27
|
+
}), 'utf-8');
|
|
28
|
+
writeFileSync(path.join(packageRoot, 'package', 'aws-client-agent-mcp', 'README.md'), '# aws-client-agent-mcp\n', 'utf-8');
|
|
29
|
+
mkdirSync(path.join(packageRoot, 'node_modules', '@modelcontextprotocol', 'sdk'), {
|
|
30
|
+
recursive: true,
|
|
31
|
+
});
|
|
32
|
+
writeFileSync(path.join(packageRoot, 'node_modules', '@modelcontextprotocol', 'sdk', 'package.json'), JSON.stringify({
|
|
33
|
+
name: '@modelcontextprotocol/sdk',
|
|
34
|
+
version: '1.27.1',
|
|
35
|
+
type: 'module',
|
|
36
|
+
main: 'index.js',
|
|
37
|
+
exports: './index.js',
|
|
38
|
+
}), 'utf-8');
|
|
39
|
+
writeFileSync(path.join(packageRoot, 'node_modules', '@modelcontextprotocol', 'sdk', 'index.js'), 'export const sdkMarker = "resolved-sdk";\n', 'utf-8');
|
|
40
|
+
mkdirSync(path.join(packageRoot, 'node_modules', 'ws'), { recursive: true });
|
|
41
|
+
mkdirSync(path.join(packageRoot, 'node_modules', 'yaml'), { recursive: true });
|
|
17
42
|
writeFileSync(path.join(bundledDist, 'index.js'), 'console.log("mcp v1");\n', 'utf-8');
|
|
18
43
|
return packageRoot;
|
|
19
44
|
}
|
|
@@ -56,8 +81,21 @@ describe('aws-client-agent-mcp service', () => {
|
|
|
56
81
|
});
|
|
57
82
|
const releasedIndex = path.join(releasedRoot, 'dist', 'index.js');
|
|
58
83
|
const manifestPath = path.join(releasedRoot, '.release.json');
|
|
84
|
+
const releasedPackageJson = path.join(releasedRoot, 'package.json');
|
|
85
|
+
const releasedNodeModules = path.join(releasedRoot, 'node_modules');
|
|
59
86
|
expect(firstRelease).toBe(releasedIndex);
|
|
60
87
|
expect(existsSync(releasedIndex)).toBe(true);
|
|
88
|
+
expect(JSON.parse(readFileSync(releasedPackageJson, 'utf-8'))).toMatchObject({
|
|
89
|
+
name: 'aws-client-agent-mcp',
|
|
90
|
+
version: '1.0.0',
|
|
91
|
+
dependencies: {
|
|
92
|
+
'@modelcontextprotocol/sdk': '^1.27.1',
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
expect(readFileSync(path.join(releasedRoot, 'README.md'), 'utf-8')).toBe('# aws-client-agent-mcp\n');
|
|
96
|
+
expect(lstatSync(releasedNodeModules).isSymbolicLink()).toBe(true);
|
|
97
|
+
expect(realpathSync(releasedNodeModules)).toBe(realpathSync(path.join(packageRoot, 'node_modules')));
|
|
98
|
+
expect(path.resolve(readlinkSync(releasedNodeModules))).toBe(path.join(packageRoot, 'node_modules'));
|
|
61
99
|
const firstManifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
62
100
|
expect(firstManifest).toMatchObject({
|
|
63
101
|
bridgeVersion: '9.9.9',
|
|
@@ -66,12 +104,15 @@ describe('aws-client-agent-mcp service', () => {
|
|
|
66
104
|
});
|
|
67
105
|
expect(firstManifest.distHash).toMatch(/^sha256:/);
|
|
68
106
|
writeFileSync(releasedIndex, 'console.log("local marker");\n', 'utf-8');
|
|
107
|
+
rmSync(releasedNodeModules, { recursive: true, force: true });
|
|
108
|
+
mkdirSync(releasedNodeModules, { recursive: true });
|
|
69
109
|
mod.releaseBundledAwsClientAgentMcp({
|
|
70
110
|
packageRoot,
|
|
71
111
|
releasedRoot,
|
|
72
112
|
now: () => '2026-05-05T00:00:00.000Z',
|
|
73
113
|
});
|
|
74
114
|
expect(readFileSync(releasedIndex, 'utf-8')).toBe('console.log("local marker");\n');
|
|
115
|
+
expect(realpathSync(releasedNodeModules)).toBe(realpathSync(path.join(packageRoot, 'node_modules')));
|
|
75
116
|
expect(JSON.parse(readFileSync(manifestPath, 'utf-8')).releasedAt).toBe('2026-05-04T00:00:00.000Z');
|
|
76
117
|
}
|
|
77
118
|
finally {
|
|
@@ -102,6 +143,32 @@ describe('aws-client-agent-mcp service', () => {
|
|
|
102
143
|
rmSync(releasedRoot, { recursive: true, force: true });
|
|
103
144
|
}
|
|
104
145
|
});
|
|
146
|
+
it('releases a runnable package root that resolves bundled mcp runtime dependencies', async () => {
|
|
147
|
+
process.env.AWS_CLIENT_AGENT_MCP_COMMAND = '';
|
|
148
|
+
const packageRoot = createBundledMcpPackage('1.0.0');
|
|
149
|
+
const releasedRoot = mkdtempSync(path.join(os.tmpdir(), 'aws-mcp-release-'));
|
|
150
|
+
try {
|
|
151
|
+
const bundledIndex = path.join(packageRoot, 'package', 'aws-client-agent-mcp', 'dist', 'index.js');
|
|
152
|
+
writeFileSync(bundledIndex, 'import { sdkMarker } from "@modelcontextprotocol/sdk";\nconsole.log(sdkMarker);\n', 'utf-8');
|
|
153
|
+
const mod = await import('./aws-client-agent-mcp.js');
|
|
154
|
+
const releasedEntry = mod.releaseBundledAwsClientAgentMcp({ packageRoot, releasedRoot });
|
|
155
|
+
expect(releasedEntry).toBe(path.join(releasedRoot, 'dist', 'index.js'));
|
|
156
|
+
if (!releasedEntry) {
|
|
157
|
+
throw new Error('Expected bundled MCP release entry to exist');
|
|
158
|
+
}
|
|
159
|
+
const result = spawnSync(process.execPath, [releasedEntry], {
|
|
160
|
+
cwd: releasedRoot,
|
|
161
|
+
encoding: 'utf-8',
|
|
162
|
+
});
|
|
163
|
+
expect(result.stderr).toBe('');
|
|
164
|
+
expect(result.status).toBe(0);
|
|
165
|
+
expect(result.stdout.trim()).toBe('resolved-sdk');
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
rmSync(packageRoot, { recursive: true, force: true });
|
|
169
|
+
rmSync(releasedRoot, { recursive: true, force: true });
|
|
170
|
+
}
|
|
171
|
+
});
|
|
105
172
|
it('releases bundled mcp into home directory when runtime dist is missing', async () => {
|
|
106
173
|
process.env.AWS_CLIENT_AGENT_MCP_COMMAND = '';
|
|
107
174
|
const mod = await import('./aws-client-agent-mcp.js');
|