@xcanwin/manyoyo 5.7.9 → 5.7.12
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/README.md +3 -2
- package/lib/plugin/playwright.js +20 -16
- package/lib/web/frontend/app.html +1 -0
- package/lib/web/frontend/app.js +28 -1
- package/lib/web/frontend/path-picker-utils.js +57 -0
- package/lib/web/server.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,10 +52,11 @@ AI Agent CLI 往往需要:
|
|
|
52
52
|
|
|
53
53
|
```bash
|
|
54
54
|
npm install -g @xcanwin/manyoyo
|
|
55
|
-
podman pull ubuntu:24.04
|
|
55
|
+
podman pull ubuntu:24.04 # 仅 Podman 需要
|
|
56
56
|
manyoyo build --iv 1.9.0-common
|
|
57
57
|
manyoyo init all
|
|
58
58
|
manyoyo run -r claude
|
|
59
|
+
manyoyo serve 127.0.0.1:3000 -U admin -P 123456 # Web UI 模式
|
|
59
60
|
```
|
|
60
61
|
|
|
61
62
|
系统要求:
|
|
@@ -122,7 +123,7 @@ manyoyo images
|
|
|
122
123
|
manyoyo run -n my-dev -x /bin/bash
|
|
123
124
|
manyoyo rm my-dev
|
|
124
125
|
|
|
125
|
-
# Web 模式
|
|
126
|
+
# Web UI 模式
|
|
126
127
|
manyoyo serve 127.0.0.1:3000
|
|
127
128
|
manyoyo serve 127.0.0.1:3000 -U admin -P 123456
|
|
128
129
|
manyoyo serve 127.0.0.1:3000 -U admin -P 123456 -d
|
package/lib/plugin/playwright.js
CHANGED
|
@@ -801,6 +801,25 @@ class PlaywrightPlugin {
|
|
|
801
801
|
launchOptions.args.push(...DISABLE_WEBRTC_LAUNCH_ARGS);
|
|
802
802
|
}
|
|
803
803
|
|
|
804
|
+
const contextOptions = {
|
|
805
|
+
userAgent: DEFAULT_FINGERPRINT_PROFILE.userAgent,
|
|
806
|
+
locale: DEFAULT_FINGERPRINT_PROFILE.locale,
|
|
807
|
+
timezoneId: DEFAULT_FINGERPRINT_PROFILE.timezoneId,
|
|
808
|
+
extraHTTPHeaders: {
|
|
809
|
+
'Accept-Language': DEFAULT_FINGERPRINT_PROFILE.acceptLanguage
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
if (sceneName !== 'mcp-host-headed') {
|
|
813
|
+
contextOptions.viewport = {
|
|
814
|
+
width: DEFAULT_FINGERPRINT_PROFILE.width,
|
|
815
|
+
height: DEFAULT_FINGERPRINT_PROFILE.height
|
|
816
|
+
};
|
|
817
|
+
contextOptions.screen = {
|
|
818
|
+
width: DEFAULT_FINGERPRINT_PROFILE.width,
|
|
819
|
+
height: DEFAULT_FINGERPRINT_PROFILE.height
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
|
|
804
823
|
return {
|
|
805
824
|
outputDir: '/tmp/.playwright-mcp',
|
|
806
825
|
server: {
|
|
@@ -818,22 +837,7 @@ class PlaywrightPlugin {
|
|
|
818
837
|
browserName: 'chromium',
|
|
819
838
|
initScript,
|
|
820
839
|
launchOptions,
|
|
821
|
-
contextOptions
|
|
822
|
-
userAgent: DEFAULT_FINGERPRINT_PROFILE.userAgent,
|
|
823
|
-
locale: DEFAULT_FINGERPRINT_PROFILE.locale,
|
|
824
|
-
timezoneId: DEFAULT_FINGERPRINT_PROFILE.timezoneId,
|
|
825
|
-
viewport: {
|
|
826
|
-
width: DEFAULT_FINGERPRINT_PROFILE.width,
|
|
827
|
-
height: DEFAULT_FINGERPRINT_PROFILE.height
|
|
828
|
-
},
|
|
829
|
-
screen: {
|
|
830
|
-
width: DEFAULT_FINGERPRINT_PROFILE.width,
|
|
831
|
-
height: DEFAULT_FINGERPRINT_PROFILE.height
|
|
832
|
-
},
|
|
833
|
-
extraHTTPHeaders: {
|
|
834
|
-
'Accept-Language': DEFAULT_FINGERPRINT_PROFILE.acceptLanguage
|
|
835
|
-
}
|
|
836
|
-
}
|
|
840
|
+
contextOptions
|
|
837
841
|
}
|
|
838
842
|
};
|
|
839
843
|
}
|
|
@@ -226,6 +226,7 @@
|
|
|
226
226
|
<script src="/app/vendor/xterm-addon-fit.js"></script>
|
|
227
227
|
<script src="/app/vendor/marked.min.js"></script>
|
|
228
228
|
<script src="/app/frontend/markdown-renderer.js"></script>
|
|
229
|
+
<script src="/app/frontend/path-picker-utils.js"></script>
|
|
229
230
|
<script src="/app/frontend/app.js"></script>
|
|
230
231
|
</body>
|
|
231
232
|
</html>
|
package/lib/web/frontend/app.js
CHANGED
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
sessionDetailError: '',
|
|
60
60
|
sessionDetailRequestId: 0,
|
|
61
61
|
createAgentPromptAuto: false,
|
|
62
|
+
createContainerPathBase: '',
|
|
62
63
|
createDefaults: null,
|
|
63
64
|
createRuns: {},
|
|
64
65
|
sessionNodeMap: new Map(),
|
|
@@ -77,6 +78,7 @@
|
|
|
77
78
|
tip: '',
|
|
78
79
|
currentPath: '',
|
|
79
80
|
basePath: '',
|
|
81
|
+
baseContainerPath: '',
|
|
80
82
|
entries: [],
|
|
81
83
|
error: ''
|
|
82
84
|
},
|
|
@@ -218,6 +220,9 @@
|
|
|
218
220
|
&& typeof window.ManyoyoMarkdown.render === 'function'
|
|
219
221
|
? window.ManyoyoMarkdown
|
|
220
222
|
: null;
|
|
223
|
+
const pathPickerUtils = window.ManyoyoPathPickerUtils && typeof window.ManyoyoPathPickerUtils === 'object'
|
|
224
|
+
? window.ManyoyoPathPickerUtils
|
|
225
|
+
: {};
|
|
221
226
|
|
|
222
227
|
function normalizeBooleanMap(source) {
|
|
223
228
|
const result = {};
|
|
@@ -647,10 +652,16 @@
|
|
|
647
652
|
}
|
|
648
653
|
|
|
649
654
|
function normalizeSlashPath(value) {
|
|
655
|
+
if (typeof pathPickerUtils.normalizeSlashPath === 'function') {
|
|
656
|
+
return pathPickerUtils.normalizeSlashPath(value);
|
|
657
|
+
}
|
|
650
658
|
return String(value || '').replace(/\\/g, '/');
|
|
651
659
|
}
|
|
652
660
|
|
|
653
661
|
function isChildPath(basePath, targetPath) {
|
|
662
|
+
if (typeof pathPickerUtils.isChildPath === 'function') {
|
|
663
|
+
return pathPickerUtils.isChildPath(basePath, targetPath);
|
|
664
|
+
}
|
|
654
665
|
const normalizedBase = normalizeSlashPath(basePath).replace(/\/+$/, '');
|
|
655
666
|
const normalizedTarget = normalizeSlashPath(targetPath).replace(/\/+$/, '');
|
|
656
667
|
if (!normalizedBase) {
|
|
@@ -660,6 +671,9 @@
|
|
|
660
671
|
}
|
|
661
672
|
|
|
662
673
|
function buildContainerPathFromHostSelection(baseHostPath, baseContainerPath, selectedHostPath) {
|
|
674
|
+
if (typeof pathPickerUtils.buildContainerPathFromHostSelection === 'function') {
|
|
675
|
+
return pathPickerUtils.buildContainerPathFromHostSelection(baseHostPath, baseContainerPath, selectedHostPath);
|
|
676
|
+
}
|
|
663
677
|
const normalizedBaseHost = normalizeSlashPath(baseHostPath).replace(/\/+$/, '');
|
|
664
678
|
const normalizedContainer = normalizeSlashPath(baseContainerPath).replace(/\/+$/, '') || '/workspace';
|
|
665
679
|
const normalizedSelected = normalizeSlashPath(selectedHostPath).replace(/\/+$/, '');
|
|
@@ -860,6 +874,7 @@
|
|
|
860
874
|
createContainerName.value = value.containerName || '';
|
|
861
875
|
createHostPath.value = value.hostPath || '';
|
|
862
876
|
createContainerPath.value = value.containerPath || '';
|
|
877
|
+
state.createContainerPathBase = String(value.containerPath || '').trim();
|
|
863
878
|
createImageName.value = value.imageName || '';
|
|
864
879
|
createImageVersion.value = value.imageVersion || '';
|
|
865
880
|
createContainerMode.value = value.containerMode || '';
|
|
@@ -2074,6 +2089,7 @@
|
|
|
2074
2089
|
state.directoryPicker.tip = '';
|
|
2075
2090
|
state.directoryPicker.currentPath = '';
|
|
2076
2091
|
state.directoryPicker.basePath = '';
|
|
2092
|
+
state.directoryPicker.baseContainerPath = '';
|
|
2077
2093
|
state.directoryPicker.parentPath = '';
|
|
2078
2094
|
state.directoryPicker.entries = [];
|
|
2079
2095
|
state.directoryPicker.error = '';
|
|
@@ -2089,11 +2105,12 @@
|
|
|
2089
2105
|
createHostPath.value = picker.currentPath;
|
|
2090
2106
|
if (!(createContainerPath.value || '').trim()) {
|
|
2091
2107
|
createContainerPath.value = '/workspace';
|
|
2108
|
+
state.createContainerPathBase = '/workspace';
|
|
2092
2109
|
}
|
|
2093
2110
|
} else if (picker.mode === 'container') {
|
|
2094
2111
|
const mapped = buildContainerPathFromHostSelection(
|
|
2095
2112
|
picker.basePath,
|
|
2096
|
-
|
|
2113
|
+
picker.baseContainerPath || '/workspace',
|
|
2097
2114
|
picker.currentPath
|
|
2098
2115
|
);
|
|
2099
2116
|
createContainerPath.value = mapped;
|
|
@@ -2120,12 +2137,16 @@
|
|
|
2120
2137
|
picker.title = '选择 containerPath 对应目录';
|
|
2121
2138
|
picker.tip = '从 hostPath 下选择子目录,结果会映射到容器路径。';
|
|
2122
2139
|
picker.basePath = baseHostPath;
|
|
2140
|
+
picker.baseContainerPath = typeof pathPickerUtils.resolveContainerPickerBase === 'function'
|
|
2141
|
+
? pathPickerUtils.resolveContainerPickerBase(state.createContainerPathBase, createContainerPath.value)
|
|
2142
|
+
: (String(state.createContainerPathBase || '').trim() || String(createContainerPath.value || '').trim() || '/workspace');
|
|
2123
2143
|
picker.currentPath = baseHostPath;
|
|
2124
2144
|
} else {
|
|
2125
2145
|
picker.mode = 'host';
|
|
2126
2146
|
picker.title = '选择 hostPath';
|
|
2127
2147
|
picker.tip = '浏览宿主机目录,选中后会回填 create 表单。';
|
|
2128
2148
|
picker.basePath = '';
|
|
2149
|
+
picker.baseContainerPath = '';
|
|
2129
2150
|
picker.currentPath = (createHostPath.value || '').trim() || '/';
|
|
2130
2151
|
}
|
|
2131
2152
|
renderDirectoryPicker();
|
|
@@ -3313,6 +3334,12 @@
|
|
|
3313
3334
|
});
|
|
3314
3335
|
}
|
|
3315
3336
|
|
|
3337
|
+
if (createContainerPath) {
|
|
3338
|
+
createContainerPath.addEventListener('input', function () {
|
|
3339
|
+
state.createContainerPathBase = String(createContainerPath.value || '').trim();
|
|
3340
|
+
});
|
|
3341
|
+
}
|
|
3342
|
+
|
|
3316
3343
|
if (createForm) {
|
|
3317
3344
|
createForm.addEventListener('submit', async function (event) {
|
|
3318
3345
|
event.preventDefault();
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
(function (root, factory) {
|
|
2
|
+
const api = factory();
|
|
3
|
+
if (typeof module === 'object' && module.exports) {
|
|
4
|
+
module.exports = api;
|
|
5
|
+
}
|
|
6
|
+
if (root && typeof root === 'object') {
|
|
7
|
+
root.ManyoyoPathPickerUtils = api;
|
|
8
|
+
}
|
|
9
|
+
}(typeof globalThis !== 'undefined' ? globalThis : this, function () {
|
|
10
|
+
function normalizeSlashPath(value) {
|
|
11
|
+
return String(value || '').replace(/\\/g, '/');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function isChildPath(basePath, targetPath) {
|
|
15
|
+
const normalizedBase = normalizeSlashPath(basePath).replace(/\/+$/, '');
|
|
16
|
+
const normalizedTarget = normalizeSlashPath(targetPath).replace(/\/+$/, '');
|
|
17
|
+
if (!normalizedBase) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return normalizedTarget === normalizedBase || normalizedTarget.startsWith(normalizedBase + '/');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function resolveContainerPickerBase(baseContainerPath, currentContainerPath) {
|
|
24
|
+
return String(baseContainerPath || '').trim()
|
|
25
|
+
|| String(currentContainerPath || '').trim()
|
|
26
|
+
|| '/workspace';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function buildContainerPathFromHostSelection(baseHostPath, baseContainerPath, selectedHostPath) {
|
|
30
|
+
const normalizedBaseHost = normalizeSlashPath(baseHostPath).replace(/\/+$/, '');
|
|
31
|
+
const normalizedContainer = normalizeSlashPath(baseContainerPath).replace(/\/+$/, '') || '/workspace';
|
|
32
|
+
const normalizedSelected = normalizeSlashPath(selectedHostPath).replace(/\/+$/, '');
|
|
33
|
+
if (!normalizedBaseHost || !isChildPath(normalizedBaseHost, normalizedSelected)) {
|
|
34
|
+
return normalizedContainer;
|
|
35
|
+
}
|
|
36
|
+
const relative = normalizedSelected === normalizedBaseHost
|
|
37
|
+
? ''
|
|
38
|
+
: normalizedSelected.slice(normalizedBaseHost.length + 1);
|
|
39
|
+
return relative ? `${normalizedContainer}/${relative}`.replace(/\/+/g, '/') : normalizedContainer;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function applyContainerPathSelection(baseHostPath, baseContainerPath, currentContainerPath, selectedHostPath) {
|
|
43
|
+
return buildContainerPathFromHostSelection(
|
|
44
|
+
baseHostPath,
|
|
45
|
+
resolveContainerPickerBase(baseContainerPath, currentContainerPath),
|
|
46
|
+
selectedHostPath
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
normalizeSlashPath,
|
|
52
|
+
isChildPath,
|
|
53
|
+
resolveContainerPickerBase,
|
|
54
|
+
buildContainerPathFromHostSelection,
|
|
55
|
+
applyContainerPathSelection
|
|
56
|
+
};
|
|
57
|
+
}));
|
package/lib/web/server.js
CHANGED
|
@@ -3542,7 +3542,7 @@ async function startWebServer(options) {
|
|
|
3542
3542
|
const appFrontendMatch = pathname.match(/^\/app\/frontend\/([A-Za-z0-9._-]+)$/);
|
|
3543
3543
|
if (req.method === 'GET' && appFrontendMatch) {
|
|
3544
3544
|
const assetName = appFrontendMatch[1];
|
|
3545
|
-
if (!(assetName === 'app.css' || assetName === 'app.js' || assetName === 'markdown.css' || assetName === 'markdown-renderer.js')) {
|
|
3545
|
+
if (!(assetName === 'app.css' || assetName === 'app.js' || assetName === 'markdown.css' || assetName === 'markdown-renderer.js' || assetName === 'path-picker-utils.js')) {
|
|
3546
3546
|
sendHtml(res, 404, '<h1>404 Not Found</h1>');
|
|
3547
3547
|
return;
|
|
3548
3548
|
}
|