@xcanwin/manyoyo 5.7.11 → 5.7.13

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.
@@ -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>
@@ -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
- (createContainerPath.value || '').trim() || '/workspace',
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
@@ -158,17 +158,57 @@ function normalizeWebAgentSessionRecord(agentId, rawAgent) {
158
158
  };
159
159
  }
160
160
 
161
+ function resolveEffectiveAgentPromptCommand(template, applied) {
162
+ const normalizedTemplate = normalizeAgentPromptCommandTemplate(template, 'agentPromptCommand');
163
+ if (!normalizedTemplate) {
164
+ return '';
165
+ }
166
+
167
+ const program = resolveAgentProgram(normalizedTemplate);
168
+ const defaultCommand = applied && typeof applied === 'object'
169
+ ? String(applied.defaultCommand || '').trim()
170
+ : '';
171
+ if (!program || !defaultCommand) {
172
+ return normalizedTemplate;
173
+ }
174
+
175
+ const defaultProgram = resolveAgentProgram(defaultCommand);
176
+ if (!defaultProgram || defaultProgram !== program) {
177
+ return normalizedTemplate;
178
+ }
179
+
180
+ const genericTemplate = normalizeAgentPromptCommandTemplate(
181
+ resolveAgentPromptCommandTemplate(program),
182
+ 'agentPromptCommand'
183
+ );
184
+ if (normalizedTemplate !== genericTemplate) {
185
+ return normalizedTemplate;
186
+ }
187
+
188
+ const inferredTemplate = normalizeAgentPromptCommandTemplate(
189
+ resolveAgentPromptCommandTemplate(defaultCommand),
190
+ 'agentPromptCommand'
191
+ );
192
+ if (!inferredTemplate || inferredTemplate === genericTemplate) {
193
+ return normalizedTemplate;
194
+ }
195
+
196
+ return inferredTemplate;
197
+ }
198
+
161
199
  function normalizeWebHistoryRecord(containerName, rawData) {
162
200
  const data = rawData && typeof rawData === 'object' && !Array.isArray(rawData) ? rawData : {};
201
+ const applied = data.applied && typeof data.applied === 'object' && !Array.isArray(data.applied)
202
+ ? data.applied
203
+ : null;
163
204
  const history = {
164
205
  containerName,
165
206
  updatedAt: typeof data.updatedAt === 'string' ? data.updatedAt : null,
166
- agentPromptCommand: typeof data.agentPromptCommand === 'string'
167
- ? data.agentPromptCommand
168
- : '',
169
- applied: data.applied && typeof data.applied === 'object' && !Array.isArray(data.applied)
170
- ? data.applied
171
- : null,
207
+ agentPromptCommand: resolveEffectiveAgentPromptCommand(
208
+ typeof data.agentPromptCommand === 'string' ? data.agentPromptCommand : '',
209
+ applied
210
+ ),
211
+ applied,
172
212
  agents: {}
173
213
  };
174
214
 
@@ -3542,7 +3582,7 @@ async function startWebServer(options) {
3542
3582
  const appFrontendMatch = pathname.match(/^\/app\/frontend\/([A-Za-z0-9._-]+)$/);
3543
3583
  if (req.method === 'GET' && appFrontendMatch) {
3544
3584
  const assetName = appFrontendMatch[1];
3545
- if (!(assetName === 'app.css' || assetName === 'app.js' || assetName === 'markdown.css' || assetName === 'markdown-renderer.js')) {
3585
+ if (!(assetName === 'app.css' || assetName === 'app.js' || assetName === 'markdown.css' || assetName === 'markdown-renderer.js' || assetName === 'path-picker-utils.js')) {
3546
3586
  sendHtml(res, 404, '<h1>404 Not Found</h1>');
3547
3587
  return;
3548
3588
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcanwin/manyoyo",
3
- "version": "5.7.11",
3
+ "version": "5.7.13",
4
4
  "imageVersion": "1.9.0-common",
5
5
  "playwrightCliVersion": "0.1.1",
6
6
  "description": "AI Agent CLI Security Sandbox for Docker and Podman",