@xcanwin/manyoyo 5.4.4 → 5.4.6
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.
- package/bin/manyoyo.js +19 -8
- package/lib/global-config.js +88 -0
- package/lib/plugin/playwright.js +16 -19
- package/manyoyo.example.json +5 -5
- package/package.json +1 -1
package/bin/manyoyo.js
CHANGED
|
@@ -8,9 +8,9 @@ const crypto = require('crypto');
|
|
|
8
8
|
const net = require('net');
|
|
9
9
|
const readline = require('readline');
|
|
10
10
|
const { Command } = require('commander');
|
|
11
|
-
const JSON5 = require('json5');
|
|
12
11
|
const { startWebServer } = require('../lib/web/server');
|
|
13
12
|
const { buildContainerRunArgs, buildContainerRunCommand } = require('../lib/container-run');
|
|
13
|
+
const { getManyoyoConfigPath, readManyoyoConfig, syncGlobalImageVersion } = require('../lib/global-config');
|
|
14
14
|
const { initAgentConfigs } = require('../lib/init-config');
|
|
15
15
|
const { buildImage } = require('../lib/image-build');
|
|
16
16
|
const { resolveAgentResumeArg, buildAgentResumeCommand } = require('../lib/agent-resume');
|
|
@@ -309,19 +309,29 @@ function installServeProcessDiagnostics(logger) {
|
|
|
309
309
|
* @returns {Config} 配置对象
|
|
310
310
|
*/
|
|
311
311
|
function loadConfig() {
|
|
312
|
-
const
|
|
313
|
-
if (
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
return config;
|
|
317
|
-
} catch (e) {
|
|
318
|
-
console.error(`${YELLOW}⚠️ 配置文件格式错误: ${configPath}${NC}`);
|
|
312
|
+
const result = readManyoyoConfig();
|
|
313
|
+
if (result.exists) {
|
|
314
|
+
if (result.parseError) {
|
|
315
|
+
console.error(`${YELLOW}⚠️ 配置文件格式错误: ${result.path}${NC}`);
|
|
319
316
|
return {};
|
|
320
317
|
}
|
|
318
|
+
return result.config;
|
|
321
319
|
}
|
|
322
320
|
return {};
|
|
323
321
|
}
|
|
324
322
|
|
|
323
|
+
function syncBuiltImageVersionToGlobalConfig(imageVersion) {
|
|
324
|
+
const syncResult = syncGlobalImageVersion(imageVersion);
|
|
325
|
+
if (syncResult.updated) {
|
|
326
|
+
console.log(`${GREEN}✅ 已同步 ${path.basename(getManyoyoConfigPath())} 的 imageVersion: ${imageVersion}${NC}`);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (syncResult.reason === 'unchanged') {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
console.log(`${YELLOW}⚠️ 镜像构建成功,但未更新 imageVersion: ${syncResult.path}${NC}`);
|
|
333
|
+
}
|
|
334
|
+
|
|
325
335
|
function loadRunConfig(name, config) {
|
|
326
336
|
const runName = String(name || '').trim();
|
|
327
337
|
if (!runName) {
|
|
@@ -1971,6 +1981,7 @@ async function main() {
|
|
|
1971
1981
|
pruneDanglingImages,
|
|
1972
1982
|
colors: { RED, GREEN, YELLOW, BLUE, CYAN, NC }
|
|
1973
1983
|
});
|
|
1984
|
+
syncBuiltImageVersionToGlobalConfig(runtime.imageVersion);
|
|
1974
1985
|
process.exit(0);
|
|
1975
1986
|
}
|
|
1976
1987
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const JSON5 = require('json5');
|
|
7
|
+
|
|
8
|
+
function getManyoyoConfigPath(homeDir = os.homedir()) {
|
|
9
|
+
return path.join(homeDir, '.manyoyo', 'manyoyo.json');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function readManyoyoConfig(homeDir = os.homedir()) {
|
|
13
|
+
const configPath = getManyoyoConfigPath(homeDir);
|
|
14
|
+
if (!fs.existsSync(configPath)) {
|
|
15
|
+
return {
|
|
16
|
+
path: configPath,
|
|
17
|
+
exists: false,
|
|
18
|
+
config: {}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const config = JSON5.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
24
|
+
return {
|
|
25
|
+
path: configPath,
|
|
26
|
+
exists: true,
|
|
27
|
+
config
|
|
28
|
+
};
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return {
|
|
31
|
+
path: configPath,
|
|
32
|
+
exists: true,
|
|
33
|
+
config: {},
|
|
34
|
+
parseError: error
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function syncGlobalImageVersion(imageVersion, options = {}) {
|
|
40
|
+
const homeDir = options.homeDir || os.homedir();
|
|
41
|
+
const result = readManyoyoConfig(homeDir);
|
|
42
|
+
const configPath = result.path;
|
|
43
|
+
|
|
44
|
+
if (result.parseError) {
|
|
45
|
+
return {
|
|
46
|
+
updated: false,
|
|
47
|
+
path: configPath,
|
|
48
|
+
reason: 'parse-error'
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const currentConfig = result.config;
|
|
53
|
+
if (typeof currentConfig !== 'object' || currentConfig === null || Array.isArray(currentConfig)) {
|
|
54
|
+
return {
|
|
55
|
+
updated: false,
|
|
56
|
+
path: configPath,
|
|
57
|
+
reason: 'invalid-root'
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (currentConfig.imageVersion === imageVersion) {
|
|
62
|
+
return {
|
|
63
|
+
updated: false,
|
|
64
|
+
path: configPath,
|
|
65
|
+
reason: 'unchanged'
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const nextConfig = {
|
|
70
|
+
...currentConfig,
|
|
71
|
+
imageVersion
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
75
|
+
fs.writeFileSync(configPath, `${JSON.stringify(nextConfig, null, 4)}\n`);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
updated: true,
|
|
79
|
+
path: configPath,
|
|
80
|
+
reason: result.exists ? 'updated' : 'created'
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = {
|
|
85
|
+
getManyoyoConfigPath,
|
|
86
|
+
readManyoyoConfig,
|
|
87
|
+
syncGlobalImageVersion
|
|
88
|
+
};
|
package/lib/plugin/playwright.js
CHANGED
|
@@ -25,7 +25,7 @@ const SCENE_DEFS = {
|
|
|
25
25
|
composeFile: 'compose-headless.yaml',
|
|
26
26
|
projectName: 'my-playwright-mcp-cont-headless',
|
|
27
27
|
containerName: 'my-playwright-mcp-cont-headless',
|
|
28
|
-
portKey: '
|
|
28
|
+
portKey: 'mcpContHeadless',
|
|
29
29
|
headless: true,
|
|
30
30
|
listenHost: '0.0.0.0'
|
|
31
31
|
},
|
|
@@ -36,7 +36,7 @@ const SCENE_DEFS = {
|
|
|
36
36
|
composeFile: 'compose-headed.yaml',
|
|
37
37
|
projectName: 'my-playwright-mcp-cont-headed',
|
|
38
38
|
containerName: 'my-playwright-mcp-cont-headed',
|
|
39
|
-
portKey: '
|
|
39
|
+
portKey: 'mcpContHeaded',
|
|
40
40
|
headless: false,
|
|
41
41
|
listenHost: '0.0.0.0'
|
|
42
42
|
},
|
|
@@ -44,7 +44,7 @@ const SCENE_DEFS = {
|
|
|
44
44
|
type: 'host',
|
|
45
45
|
engine: 'mcp',
|
|
46
46
|
configFile: 'mcp-host-headless.json',
|
|
47
|
-
portKey: '
|
|
47
|
+
portKey: 'mcpHostHeadless',
|
|
48
48
|
headless: true,
|
|
49
49
|
listenHost: '127.0.0.1'
|
|
50
50
|
},
|
|
@@ -52,7 +52,7 @@ const SCENE_DEFS = {
|
|
|
52
52
|
type: 'host',
|
|
53
53
|
engine: 'mcp',
|
|
54
54
|
configFile: 'mcp-host-headed.json',
|
|
55
|
-
portKey: '
|
|
55
|
+
portKey: 'mcpHostHeaded',
|
|
56
56
|
headless: false,
|
|
57
57
|
listenHost: '127.0.0.1'
|
|
58
58
|
},
|
|
@@ -293,7 +293,6 @@ class PlaywrightPlugin {
|
|
|
293
293
|
runtime: 'mixed',
|
|
294
294
|
enabledScenes: [...SCENE_ORDER],
|
|
295
295
|
cliSessionScene: 'cli-host-headless',
|
|
296
|
-
hostListen: '127.0.0.1',
|
|
297
296
|
mcpDefaultHost: 'host.docker.internal',
|
|
298
297
|
dockerTag: process.env.PLAYWRIGHT_MCP_DOCKER_TAG || 'latest',
|
|
299
298
|
containerRuntime: '',
|
|
@@ -306,13 +305,13 @@ class PlaywrightPlugin {
|
|
|
306
305
|
disableWebRTC: false,
|
|
307
306
|
composeDir: path.join(__dirname, 'playwright-assets'),
|
|
308
307
|
ports: {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
308
|
+
mcpContHeadless: 8931,
|
|
309
|
+
mcpContHeaded: 8932,
|
|
310
|
+
mcpHostHeadless: 8933,
|
|
311
|
+
mcpHostHeaded: 8934,
|
|
313
312
|
cliHostHeadless: 8935,
|
|
314
313
|
cliHostHeaded: 8936,
|
|
315
|
-
|
|
314
|
+
mcpContHeadedNoVnc: 6080
|
|
316
315
|
}
|
|
317
316
|
};
|
|
318
317
|
|
|
@@ -481,15 +480,15 @@ class PlaywrightPlugin {
|
|
|
481
480
|
fs.writeFileSync(this.sceneCliAttachConfigPath(sceneName), `${JSON.stringify(payload, null, 4)}\n`, 'utf8');
|
|
482
481
|
}
|
|
483
482
|
|
|
483
|
+
removeSceneCliAttachConfig(sceneName) {
|
|
484
|
+
fs.rmSync(this.sceneCliAttachConfigPath(sceneName), { force: true });
|
|
485
|
+
}
|
|
486
|
+
|
|
484
487
|
sceneInitScriptPath(sceneName) {
|
|
485
488
|
const configFile = path.basename(this.sceneConfigPath(sceneName), '.json');
|
|
486
489
|
return path.join(this.config.configDir, `${configFile}.init.js`);
|
|
487
490
|
}
|
|
488
491
|
|
|
489
|
-
legacySceneInitScriptPath(sceneName) {
|
|
490
|
-
return path.join(this.config.configDir, `${sceneName}.init.js`);
|
|
491
|
-
}
|
|
492
|
-
|
|
493
492
|
buildInitScriptContent() {
|
|
494
493
|
const lines = [
|
|
495
494
|
"'use strict';",
|
|
@@ -540,10 +539,6 @@ class PlaywrightPlugin {
|
|
|
540
539
|
const filePath = this.sceneInitScriptPath(sceneName);
|
|
541
540
|
const content = this.buildInitScriptContent();
|
|
542
541
|
fs.writeFileSync(filePath, content, 'utf8');
|
|
543
|
-
const legacyFilePath = this.legacySceneInitScriptPath(sceneName);
|
|
544
|
-
if (legacyFilePath !== filePath) {
|
|
545
|
-
fs.rmSync(legacyFilePath, { force: true });
|
|
546
|
-
}
|
|
547
542
|
return filePath;
|
|
548
543
|
}
|
|
549
544
|
|
|
@@ -900,7 +895,7 @@ class PlaywrightPlugin {
|
|
|
900
895
|
PLAYWRIGHT_MCP_CONFIG_PATH: cfgPath,
|
|
901
896
|
PLAYWRIGHT_MCP_CONTAINER_NAME: def.containerName,
|
|
902
897
|
PLAYWRIGHT_MCP_IMAGE: this.config.headedImage,
|
|
903
|
-
PLAYWRIGHT_MCP_NOVNC_PORT: String(this.config.ports.
|
|
898
|
+
PLAYWRIGHT_MCP_NOVNC_PORT: String(this.config.ports.mcpContHeadedNoVnc)
|
|
904
899
|
};
|
|
905
900
|
|
|
906
901
|
if (sceneName === 'mcp-cont-headed') {
|
|
@@ -1221,6 +1216,7 @@ class PlaywrightPlugin {
|
|
|
1221
1216
|
const logFile = this.sceneLogFile(sceneName);
|
|
1222
1217
|
const port = this.scenePort(sceneName);
|
|
1223
1218
|
this.removeSceneEndpoint(sceneName);
|
|
1219
|
+
this.removeSceneCliAttachConfig(sceneName);
|
|
1224
1220
|
|
|
1225
1221
|
let managedPids = this.hostScenePids(sceneName);
|
|
1226
1222
|
if (managedPids.length > 0 && (await this.portReady(port))) {
|
|
@@ -1285,6 +1281,7 @@ class PlaywrightPlugin {
|
|
|
1285
1281
|
const port = this.scenePort(sceneName);
|
|
1286
1282
|
const managedPids = this.hostScenePids(sceneName);
|
|
1287
1283
|
this.removeSceneEndpoint(sceneName);
|
|
1284
|
+
this.removeSceneCliAttachConfig(sceneName);
|
|
1288
1285
|
|
|
1289
1286
|
for (const pid of managedPids) {
|
|
1290
1287
|
try {
|
package/manyoyo.example.json
CHANGED
|
@@ -64,13 +64,13 @@
|
|
|
64
64
|
// 是否禁用 WebRTC(默认 false)
|
|
65
65
|
"disableWebRTC": false,
|
|
66
66
|
"ports": {
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
67
|
+
"mcpContHeadless": 8931,
|
|
68
|
+
"mcpContHeaded": 8932,
|
|
69
|
+
"mcpHostHeadless": 8933,
|
|
70
|
+
"mcpHostHeaded": 8934,
|
|
71
71
|
"cliHostHeadless": 8935,
|
|
72
72
|
"cliHostHeaded": 8936,
|
|
73
|
-
"
|
|
73
|
+
"mcpContHeadedNoVnc": 6080
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
},
|