@xcanwin/manyoyo 5.11.10 → 5.11.11

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.
@@ -31,7 +31,9 @@ function createPlugin(pluginName, options = {}) {
31
31
  stdout: options.stdout,
32
32
  stderr: options.stderr,
33
33
  globalConfig: cfg.globalPluginConfig,
34
- runConfig: cfg.runPluginConfig
34
+ runConfig: cfg.runPluginConfig,
35
+ rootGlobalConfig: asObject(options.globalConfig),
36
+ rootRunConfig: asObject(options.runConfig)
35
37
  });
36
38
  }
37
39
 
@@ -312,6 +312,8 @@ class PlaywrightPlugin {
312
312
  this.stderr = options.stderr || process.stderr;
313
313
  this.globalConfig = asObject(options.globalConfig);
314
314
  this.runConfig = asObject(options.runConfig);
315
+ this.rootGlobalConfig = asObject(options.rootGlobalConfig);
316
+ this.rootRunConfig = asObject(options.rootRunConfig);
315
317
  this.config = this.resolveConfig();
316
318
  }
317
319
 
@@ -421,7 +423,7 @@ class PlaywrightPlugin {
421
423
  if (sceneName !== 'cli-host-headed') {
422
424
  return;
423
425
  }
424
- if (this.config.cliSessionScene === sceneName) {
426
+ if (this.cliHostContainerAttachConfigReady()) {
425
427
  return;
426
428
  }
427
429
  this.writeStdout('[tip] 如果希望容器内 manyoyo run 自动附着到当前 CLI 宿主场景,请在 ~/.manyoyo/manyoyo.json 中设置:');
@@ -473,20 +475,17 @@ class PlaywrightPlugin {
473
475
  return false;
474
476
  }
475
477
 
476
- remindDevHostCliSessionScene() {
477
- this.writeStdout(`[tip] 已尝试用 Chrome 打开 ${this.remoteDebuggingPageUrl()},请在页面中确认 remote debugging 相关勾选项已启用。`);
478
- this.writeStdout('[tip] 如果希望容器内 manyoyo run 自动附着到宿主机正在运行的 Chrome,请在 ~/.manyoyo/manyoyo.json 中设置:');
479
- this.writeStdout('{');
480
- this.writeStdout(' "volumes": [');
481
- this.writeStdout(' "~/.manyoyo/.cache/ms-playwright:/root/.cache/ms-playwright",');
482
- this.writeStdout(' "~/Library/Application Support/Google/Chrome/DevToolsActivePort:/root/Library/Application Support/Google/Chrome/DevToolsActivePort"');
483
- this.writeStdout(' ],');
484
- this.writeStdout(' "plugins": {');
485
- this.writeStdout(' "playwright": {');
486
- this.writeStdout(' "cliSessionScene": "dev-host-headed"');
487
- this.writeStdout(' }');
488
- this.writeStdout(' }');
489
- this.writeStdout('}');
478
+ writeDevHostUsage(configPath) {
479
+ this.writeStdout('');
480
+ this.writeStdout('若用容器 Agent 操作宿主机浏览器,在宿主机执行:');
481
+ ['claude', 'codex', 'gemini'].forEach(runName => {
482
+ this.writeStdout(`my run -r ${runName}`);
483
+ });
484
+ this.writeStdout('');
485
+ this.writeStdout('若用宿主机 Agent 操作宿主机浏览器,在宿主机执行:');
486
+ ['claude', 'codex', 'gemini'].forEach(command => {
487
+ this.writeStdout(this.devHostAttachCommand(configPath, command));
488
+ });
490
489
  }
491
490
 
492
491
  randomAlnum(length = 16) {
@@ -594,6 +593,109 @@ class PlaywrightPlugin {
594
593
  fs.rmSync(this.sceneCliAttachConfigPath(sceneName), { force: true });
595
594
  }
596
595
 
596
+ buildDevHostAttachConfig(endpoint, cdpHost) {
597
+ return {
598
+ outputDir: '/tmp/.playwright-cli',
599
+ browser: {
600
+ cdpEndpoint: `ws://${cdpHost}:${endpoint.port}${endpoint.wsPath}`,
601
+ cdpHeaders: {
602
+ Host: `127.0.0.1:${endpoint.port}`
603
+ },
604
+ cdpTimeout: this.config.devtoolsCdpTimeout
605
+ }
606
+ };
607
+ }
608
+
609
+ writeDevHostAttachConfig(sceneName, endpoint) {
610
+ fs.mkdirSync(this.config.configDir, { recursive: true });
611
+ const filePath = this.sceneConfigPath(sceneName);
612
+ fs.writeFileSync(filePath, `${JSON.stringify(this.buildDevHostAttachConfig(endpoint, '127.0.0.1'), null, 4)}\n`, 'utf8');
613
+ return filePath;
614
+ }
615
+
616
+ removeDevHostAttachConfig(sceneName) {
617
+ fs.rmSync(this.sceneConfigPath(sceneName), { force: true });
618
+ }
619
+
620
+ userDisplayPath(filePath) {
621
+ const normalizedPath = path.resolve(filePath);
622
+ const normalizedHome = path.resolve(this.config.homeDir);
623
+ if (normalizedPath === normalizedHome) {
624
+ return '~';
625
+ }
626
+ if (normalizedPath.startsWith(`${normalizedHome}${path.sep}`)) {
627
+ return `~${normalizedPath.slice(normalizedHome.length)}`;
628
+ }
629
+ return filePath;
630
+ }
631
+
632
+ shellValue(value) {
633
+ const text = String(value);
634
+ if (/^[A-Za-z0-9_@%+=:,./~-]+$/.test(text)) {
635
+ return text;
636
+ }
637
+ return `'${text.replace(/'/g, "'\\''")}'`;
638
+ }
639
+
640
+ devHostAttachEnvEntries(configPath) {
641
+ return [
642
+ `PLAYWRIGHT_MCP_CONFIG=${this.shellValue(this.userDisplayPath(configPath))}`
643
+ ];
644
+ }
645
+
646
+ devHostAttachCommand(configPath, command) {
647
+ return `${this.devHostAttachEnvEntries(configPath).join(' ')} ${command}`;
648
+ }
649
+
650
+ expandHomePath(value) {
651
+ const text = String(value || '').trim();
652
+ if (text === '~') {
653
+ return this.config.homeDir;
654
+ }
655
+ if (text.startsWith('~/')) {
656
+ return path.join(this.config.homeDir, text.slice(2));
657
+ }
658
+ return text;
659
+ }
660
+
661
+ parseVolumeEntry(value) {
662
+ const parts = String(value || '').split(':');
663
+ if (parts.length < 2) {
664
+ return null;
665
+ }
666
+ return {
667
+ hostPath: path.resolve(this.expandHomePath(parts[0])),
668
+ containerPath: parts[1]
669
+ };
670
+ }
671
+
672
+ mergedRootVolumes() {
673
+ return [
674
+ ...asStringArray(this.rootGlobalConfig.volumes, []),
675
+ ...asStringArray(this.rootRunConfig.volumes, []),
676
+ ...asStringArray(this.globalConfig.volumes, []),
677
+ ...asStringArray(this.runConfig.volumes, [])
678
+ ];
679
+ }
680
+
681
+ hasRootVolume(required) {
682
+ const parsedRequired = this.parseVolumeEntry(required);
683
+ if (!parsedRequired) {
684
+ return false;
685
+ }
686
+ return this.mergedRootVolumes().some(item => {
687
+ const parsed = this.parseVolumeEntry(item);
688
+ return parsed
689
+ && parsed.hostPath === parsedRequired.hostPath
690
+ && parsed.containerPath === parsedRequired.containerPath;
691
+ });
692
+ }
693
+
694
+ cliHostContainerAttachConfigReady() {
695
+ return this.config.cliSessionScene === 'cli-host-headed'
696
+ && this.hasRootVolume('~/.manyoyo/.cache/ms-playwright:/root/.cache/ms-playwright');
697
+ }
698
+
597
699
  devtoolsActivePortCandidates() {
598
700
  const homeDir = this.config.homeDir;
599
701
  const configured = this.config.devtoolsActivePortPath;
@@ -1168,24 +1270,13 @@ class PlaywrightPlugin {
1168
1270
  const endpoint = this.readDevToolsActivePort();
1169
1271
  const normalizedDockerCmd = String(dockerCmd || '').trim().toLowerCase();
1170
1272
  const connectHost = normalizedDockerCmd === 'podman' ? 'host.containers.internal' : 'host.docker.internal';
1171
- const cdpEndpoint = `ws://${connectHost}:${endpoint.port}${endpoint.wsPath}`;
1172
1273
  const hostConfigPath = this.sceneCliAttachConfigPath(sceneName);
1173
1274
  const containerConfigPath = `/tmp/manyoyo-playwright/${sceneName}.cli-attach.json`;
1174
1275
 
1175
- this.writeSceneCliAttachConfig(sceneName, {
1176
- outputDir: '/tmp/.playwright-cli',
1177
- browser: {
1178
- cdpEndpoint,
1179
- cdpHeaders: {
1180
- Host: `127.0.0.1:${endpoint.port}`
1181
- },
1182
- cdpTimeout: this.config.devtoolsCdpTimeout
1183
- }
1184
- });
1276
+ this.writeSceneCliAttachConfig(sceneName, this.buildDevHostAttachConfig(endpoint, connectHost));
1185
1277
 
1186
1278
  const envEntries = [
1187
- `PLAYWRIGHT_MCP_CONFIG=${containerConfigPath}`,
1188
- 'PW_CHROMIUM_ATTACH_TO_OTHER=1'
1279
+ `PLAYWRIGHT_MCP_CONFIG=${containerConfigPath}`
1189
1280
  ];
1190
1281
  const extraArgs = normalizedDockerCmd === 'docker'
1191
1282
  ? ['--add-host', 'host.docker.internal:host-gateway']
@@ -1506,12 +1597,13 @@ class PlaywrightPlugin {
1506
1597
  if (!(await this.portReady(endpoint.port))) {
1507
1598
  throw new Error(`DevToolsActivePort 指向 127.0.0.1:${endpoint.port},但该端口不可连接;请确认 Chrome remote debugging 已启用,或重新打开 Chrome 后再试。`);
1508
1599
  }
1600
+ const cfgPath = this.writeDevHostAttachConfig(sceneName, endpoint);
1509
1601
  this.writeStdout(`[up] ${sceneName} ready via DevToolsActivePort (${endpoint.filePath}, 127.0.0.1:${endpoint.port})`);
1510
- this.remindDevHostCliSessionScene();
1602
+ this.writeStdout(`[tip] 已尝试打开 ${this.remoteDebuggingPageUrl()},请确认 remote debugging 已启用。`);
1603
+ this.writeDevHostUsage(cfgPath);
1511
1604
  return 0;
1512
1605
  } catch (error) {
1513
1606
  this.writeStderr(`[up] ${sceneName} failed: ${error.message || String(error)}`);
1514
- this.remindDevHostCliSessionScene();
1515
1607
  return 1;
1516
1608
  }
1517
1609
  }
@@ -1559,6 +1651,7 @@ class PlaywrightPlugin {
1559
1651
  stopDevHost(sceneName) {
1560
1652
  this.removeSceneEndpoint(sceneName);
1561
1653
  this.removeSceneCliAttachConfig(sceneName);
1654
+ this.removeDevHostAttachConfig(sceneName);
1562
1655
  this.writeStdout(`[down] ${sceneName} no managed process`);
1563
1656
  return 0;
1564
1657
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcanwin/manyoyo",
3
- "version": "5.11.10",
3
+ "version": "5.11.11",
4
4
  "imageVersion": "1.9.1-common",
5
5
  "playwrightCliVersion": "0.1.14",
6
6
  "description": "AI Agent CLI Security Sandbox for Docker and Podman",