@xcanwin/manyoyo 5.8.11 → 5.9.0
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/lib/web/frontend/app.css +182 -1
- package/lib/web/frontend/app.html +4 -0
- package/lib/web/frontend/app.js +34 -0
- package/lib/web/frontend/codemirror-entry.js +98 -0
- package/lib/web/frontend/codemirror.bundle.js +31648 -0
- package/lib/web/frontend/file-browser.js +406 -0
- package/lib/web/server.js +230 -1
- package/package.json +15 -1
package/lib/web/frontend/app.css
CHANGED
|
@@ -1140,6 +1140,177 @@ body.mobile-actions-open .header-actions {
|
|
|
1140
1140
|
background: #131923;
|
|
1141
1141
|
}
|
|
1142
1142
|
|
|
1143
|
+
.files-pane {
|
|
1144
|
+
min-height: 0;
|
|
1145
|
+
border: 1px solid var(--line);
|
|
1146
|
+
border-radius: 14px;
|
|
1147
|
+
overflow: hidden;
|
|
1148
|
+
background:
|
|
1149
|
+
linear-gradient(180deg, rgba(255, 255, 255, 0.88) 0%, rgba(252, 246, 236, 0.88) 100%);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
.files-browser {
|
|
1153
|
+
height: 100%;
|
|
1154
|
+
min-height: 0;
|
|
1155
|
+
display: grid;
|
|
1156
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
.files-toolbar {
|
|
1160
|
+
display: flex;
|
|
1161
|
+
align-items: center;
|
|
1162
|
+
gap: 8px;
|
|
1163
|
+
padding: 12px 14px;
|
|
1164
|
+
border-bottom: 1px solid var(--line);
|
|
1165
|
+
background: rgba(255, 251, 244, 0.96);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
.files-toolbar-path {
|
|
1169
|
+
flex: 1;
|
|
1170
|
+
min-width: 0;
|
|
1171
|
+
padding: 8px 10px;
|
|
1172
|
+
border: 1px solid rgba(181, 146, 99, 0.35);
|
|
1173
|
+
border-radius: 10px;
|
|
1174
|
+
background: #fffdf9;
|
|
1175
|
+
color: var(--text);
|
|
1176
|
+
font-family: var(--font-mono);
|
|
1177
|
+
font-size: 12px;
|
|
1178
|
+
line-height: 1.5;
|
|
1179
|
+
word-break: break-all;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
.files-toolbar-status {
|
|
1183
|
+
color: var(--muted);
|
|
1184
|
+
font-size: 12px;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
.files-layout {
|
|
1188
|
+
min-height: 0;
|
|
1189
|
+
display: grid;
|
|
1190
|
+
grid-template-columns: minmax(240px, 320px) minmax(0, 1fr);
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
.files-sidebar {
|
|
1194
|
+
min-height: 0;
|
|
1195
|
+
border-right: 1px solid var(--line);
|
|
1196
|
+
background: rgba(255, 251, 244, 0.84);
|
|
1197
|
+
overflow: auto;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
.files-list {
|
|
1201
|
+
display: flex;
|
|
1202
|
+
flex-direction: column;
|
|
1203
|
+
gap: 6px;
|
|
1204
|
+
padding: 12px;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
.files-entry {
|
|
1208
|
+
width: 100%;
|
|
1209
|
+
display: flex;
|
|
1210
|
+
align-items: center;
|
|
1211
|
+
justify-content: space-between;
|
|
1212
|
+
gap: 10px;
|
|
1213
|
+
padding: 10px 12px;
|
|
1214
|
+
border: 1px solid rgba(181, 146, 99, 0.28);
|
|
1215
|
+
border-radius: 12px;
|
|
1216
|
+
background: rgba(255, 255, 255, 0.92);
|
|
1217
|
+
color: var(--text);
|
|
1218
|
+
text-align: left;
|
|
1219
|
+
cursor: pointer;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
.files-entry.is-active {
|
|
1223
|
+
border-color: rgba(120, 78, 27, 0.45);
|
|
1224
|
+
background: rgba(255, 244, 224, 0.9);
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
.files-entry-name {
|
|
1228
|
+
min-width: 0;
|
|
1229
|
+
display: flex;
|
|
1230
|
+
flex-direction: column;
|
|
1231
|
+
gap: 0;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
.files-entry-title {
|
|
1235
|
+
font-size: 13px;
|
|
1236
|
+
font-weight: 600;
|
|
1237
|
+
word-break: break-word;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
.files-entry-meta {
|
|
1241
|
+
color: var(--muted);
|
|
1242
|
+
font-size: 11px;
|
|
1243
|
+
white-space: nowrap;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
.files-preview {
|
|
1247
|
+
min-height: 0;
|
|
1248
|
+
display: grid;
|
|
1249
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
.files-preview-head {
|
|
1253
|
+
display: flex;
|
|
1254
|
+
flex-direction: column;
|
|
1255
|
+
gap: 6px;
|
|
1256
|
+
padding: 12px 14px;
|
|
1257
|
+
border-bottom: 1px solid var(--line);
|
|
1258
|
+
background: rgba(255, 251, 244, 0.96);
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
.files-preview-title {
|
|
1262
|
+
font-family: var(--font-display);
|
|
1263
|
+
font-size: 15px;
|
|
1264
|
+
font-weight: 700;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
.files-preview-meta {
|
|
1268
|
+
color: var(--muted);
|
|
1269
|
+
font-size: 12px;
|
|
1270
|
+
word-break: break-all;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
.files-preview-body {
|
|
1274
|
+
min-height: 0;
|
|
1275
|
+
overflow: auto;
|
|
1276
|
+
padding: 14px;
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
.files-empty,
|
|
1280
|
+
.files-note {
|
|
1281
|
+
padding: 18px;
|
|
1282
|
+
border: 1px dashed rgba(181, 146, 99, 0.45);
|
|
1283
|
+
border-radius: 12px;
|
|
1284
|
+
background: rgba(255, 255, 255, 0.7);
|
|
1285
|
+
color: var(--muted);
|
|
1286
|
+
line-height: 1.6;
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
.files-pre {
|
|
1290
|
+
margin: 0;
|
|
1291
|
+
white-space: pre-wrap;
|
|
1292
|
+
word-break: break-word;
|
|
1293
|
+
font-family: var(--font-mono);
|
|
1294
|
+
font-size: 12px;
|
|
1295
|
+
line-height: 1.6;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
.files-editor-host {
|
|
1299
|
+
min-height: 100%;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
.files-editor-host .cm-editor {
|
|
1303
|
+
height: 100%;
|
|
1304
|
+
border: 1px solid rgba(181, 146, 99, 0.32);
|
|
1305
|
+
border-radius: 12px;
|
|
1306
|
+
overflow: hidden;
|
|
1307
|
+
background: rgba(255, 255, 255, 0.94);
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
.files-editor-host .cm-scroller {
|
|
1311
|
+
font-family: var(--font-mono);
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1143
1314
|
.inspector-pane {
|
|
1144
1315
|
overflow-y: auto;
|
|
1145
1316
|
padding: 0;
|
|
@@ -1939,7 +2110,7 @@ details.trace-card > .trace-card-summary {
|
|
|
1939
2110
|
|
|
1940
2111
|
.workbench-tabs {
|
|
1941
2112
|
display: grid;
|
|
1942
|
-
grid-template-columns: repeat(
|
|
2113
|
+
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
1943
2114
|
gap: 6px;
|
|
1944
2115
|
}
|
|
1945
2116
|
|
|
@@ -1953,6 +2124,16 @@ details.trace-card > .trace-card-summary {
|
|
|
1953
2124
|
align-items: flex-start;
|
|
1954
2125
|
}
|
|
1955
2126
|
|
|
2127
|
+
.files-layout {
|
|
2128
|
+
grid-template-columns: minmax(0, 1fr);
|
|
2129
|
+
grid-template-rows: minmax(180px, 38%) minmax(0, 1fr);
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
.files-sidebar {
|
|
2133
|
+
border-right: 0;
|
|
2134
|
+
border-bottom: 1px solid var(--line);
|
|
2135
|
+
}
|
|
2136
|
+
|
|
1956
2137
|
.composer-toolbar-meta {
|
|
1957
2138
|
width: 100%;
|
|
1958
2139
|
justify-content: space-between;
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
<div class="workbench-tabs" id="workbenchTabs" aria-label="工作台视图">
|
|
69
69
|
<button type="button" id="viewActivityBtn" class="secondary is-active">活动</button>
|
|
70
70
|
<button type="button" id="viewTerminalBtn" class="secondary">终端</button>
|
|
71
|
+
<button type="button" id="viewFilesBtn" class="secondary">文件</button>
|
|
71
72
|
<button type="button" id="viewDetailBtn" class="secondary">详情</button>
|
|
72
73
|
<button type="button" id="viewConfigBtn" class="secondary">配置</button>
|
|
73
74
|
<button type="button" id="viewCheckBtn" class="secondary">检查</button>
|
|
@@ -90,6 +91,7 @@
|
|
|
90
91
|
</div>
|
|
91
92
|
<div id="terminalScreen" aria-label="终端输出区域"></div>
|
|
92
93
|
</section>
|
|
94
|
+
<section id="filesPanel" class="workspace-pane files-pane" hidden></section>
|
|
93
95
|
<section id="detailPanel" class="workspace-pane inspector-pane" hidden>
|
|
94
96
|
<div id="detailSummary" class="inspector-stack"></div>
|
|
95
97
|
</section>
|
|
@@ -297,6 +299,8 @@
|
|
|
297
299
|
<script src="/app/vendor/xterm-addon-fit.js"></script>
|
|
298
300
|
<script src="/app/vendor/marked.min.js"></script>
|
|
299
301
|
<script src="/app/frontend/markdown-renderer.js"></script>
|
|
302
|
+
<script src="/app/frontend/codemirror.bundle.js"></script>
|
|
303
|
+
<script src="/app/frontend/file-browser.js"></script>
|
|
300
304
|
<script src="/app/frontend/app.js"></script>
|
|
301
305
|
</body>
|
|
302
306
|
</html>
|
package/lib/web/frontend/app.js
CHANGED
|
@@ -118,6 +118,7 @@
|
|
|
118
118
|
const headerActions = document.getElementById('headerActions');
|
|
119
119
|
const viewActivityBtn = document.getElementById('viewActivityBtn');
|
|
120
120
|
const viewTerminalBtn = document.getElementById('viewTerminalBtn');
|
|
121
|
+
const viewFilesBtn = document.getElementById('viewFilesBtn');
|
|
121
122
|
const viewDetailBtn = document.getElementById('viewDetailBtn');
|
|
122
123
|
const viewConfigBtn = document.getElementById('viewConfigBtn');
|
|
123
124
|
const viewCheckBtn = document.getElementById('viewCheckBtn');
|
|
@@ -174,6 +175,7 @@
|
|
|
174
175
|
const activityModelChip = document.getElementById('activityModelChip');
|
|
175
176
|
const messagesNode = document.getElementById('messages');
|
|
176
177
|
const terminalPanel = document.getElementById('terminalPanel');
|
|
178
|
+
const filesPanel = document.getElementById('filesPanel');
|
|
177
179
|
const detailPanel = document.getElementById('detailPanel');
|
|
178
180
|
const configPanel = document.getElementById('configPanel');
|
|
179
181
|
const checkPanel = document.getElementById('checkPanel');
|
|
@@ -248,6 +250,7 @@
|
|
|
248
250
|
&& typeof window.ManyoyoMarkdown.render === 'function'
|
|
249
251
|
? window.ManyoyoMarkdown
|
|
250
252
|
: null;
|
|
253
|
+
let fileBrowser = null;
|
|
251
254
|
function normalizeBooleanMap(source) {
|
|
252
255
|
const result = {};
|
|
253
256
|
if (!source || typeof source !== 'object' || Array.isArray(source)) {
|
|
@@ -1723,6 +1726,7 @@
|
|
|
1723
1726
|
const VIEW_LABELS = {
|
|
1724
1727
|
activity: '活动',
|
|
1725
1728
|
terminal: '终端',
|
|
1729
|
+
files: '文件',
|
|
1726
1730
|
detail: '详情',
|
|
1727
1731
|
config: '配置',
|
|
1728
1732
|
check: '检查'
|
|
@@ -2001,6 +2005,7 @@
|
|
|
2001
2005
|
|
|
2002
2006
|
const activityTab = state.activeTab === 'activity';
|
|
2003
2007
|
const terminalTab = state.activeTab === 'terminal';
|
|
2008
|
+
const filesTab = state.activeTab === 'files';
|
|
2004
2009
|
const detailTab = state.activeTab === 'detail';
|
|
2005
2010
|
const configTab = state.activeTab === 'config';
|
|
2006
2011
|
const checkTab = state.activeTab === 'check';
|
|
@@ -2011,6 +2016,7 @@
|
|
|
2011
2016
|
document.body.classList.toggle('command-mode', commandMode);
|
|
2012
2017
|
document.body.classList.toggle('agent-mode', agentMode);
|
|
2013
2018
|
document.body.classList.toggle('terminal-mode', terminalTab);
|
|
2019
|
+
document.body.classList.toggle('files-tab', filesTab);
|
|
2014
2020
|
document.body.classList.toggle('detail-tab', detailTab);
|
|
2015
2021
|
document.body.classList.toggle('config-tab', configTab);
|
|
2016
2022
|
document.body.classList.toggle('check-tab', checkTab);
|
|
@@ -2036,6 +2042,7 @@
|
|
|
2036
2042
|
}
|
|
2037
2043
|
if (viewActivityBtn) viewActivityBtn.classList.toggle('is-active', activityTab);
|
|
2038
2044
|
if (viewTerminalBtn) viewTerminalBtn.classList.toggle('is-active', terminalTab);
|
|
2045
|
+
if (viewFilesBtn) viewFilesBtn.classList.toggle('is-active', filesTab);
|
|
2039
2046
|
if (viewDetailBtn) viewDetailBtn.classList.toggle('is-active', detailTab);
|
|
2040
2047
|
if (viewConfigBtn) viewConfigBtn.classList.toggle('is-active', configTab);
|
|
2041
2048
|
if (viewCheckBtn) viewCheckBtn.classList.toggle('is-active', checkTab);
|
|
@@ -2045,6 +2052,9 @@
|
|
|
2045
2052
|
if (terminalPanel) {
|
|
2046
2053
|
terminalPanel.hidden = !terminalTab;
|
|
2047
2054
|
}
|
|
2055
|
+
if (filesPanel) {
|
|
2056
|
+
filesPanel.hidden = !filesTab;
|
|
2057
|
+
}
|
|
2048
2058
|
if (detailPanel) {
|
|
2049
2059
|
detailPanel.hidden = !detailTab;
|
|
2050
2060
|
}
|
|
@@ -2057,6 +2067,14 @@
|
|
|
2057
2067
|
if (terminalTab && state.terminal.terminalReady) {
|
|
2058
2068
|
scheduleTerminalFit(false);
|
|
2059
2069
|
}
|
|
2070
|
+
if (fileBrowser) {
|
|
2071
|
+
fileBrowser.sync({
|
|
2072
|
+
visible: filesTab,
|
|
2073
|
+
session: getActiveSession(),
|
|
2074
|
+
detail: state.sessionDetail,
|
|
2075
|
+
historyOnly: isActiveSessionHistoryOnly()
|
|
2076
|
+
});
|
|
2077
|
+
}
|
|
2060
2078
|
|
|
2061
2079
|
const activeAgentRunning = isAgentRunActiveForSession(state.active);
|
|
2062
2080
|
const busy = state.loadingSessions || state.loadingMessages || state.sending;
|
|
@@ -3949,6 +3967,12 @@
|
|
|
3949
3967
|
});
|
|
3950
3968
|
}
|
|
3951
3969
|
|
|
3970
|
+
if (viewFilesBtn) {
|
|
3971
|
+
viewFilesBtn.addEventListener('click', function () {
|
|
3972
|
+
setActiveTab('files');
|
|
3973
|
+
});
|
|
3974
|
+
}
|
|
3975
|
+
|
|
3952
3976
|
if (viewDetailBtn) {
|
|
3953
3977
|
viewDetailBtn.addEventListener('click', function () {
|
|
3954
3978
|
setActiveTab('detail');
|
|
@@ -4210,6 +4234,16 @@
|
|
|
4210
4234
|
});
|
|
4211
4235
|
}
|
|
4212
4236
|
|
|
4237
|
+
if (window.ManyoyoFileBrowser && typeof window.ManyoyoFileBrowser.create === 'function') {
|
|
4238
|
+
fileBrowser = window.ManyoyoFileBrowser.create({
|
|
4239
|
+
root: filesPanel,
|
|
4240
|
+
api,
|
|
4241
|
+
onError: function (message) {
|
|
4242
|
+
alert(message);
|
|
4243
|
+
}
|
|
4244
|
+
});
|
|
4245
|
+
}
|
|
4246
|
+
|
|
4213
4247
|
window.addEventListener('beforeunload', function () {
|
|
4214
4248
|
disconnectTerminal('', true);
|
|
4215
4249
|
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { basicSetup } from 'codemirror';
|
|
2
|
+
import { Compartment, EditorState } from '@codemirror/state';
|
|
3
|
+
import { EditorView } from '@codemirror/view';
|
|
4
|
+
import { css } from '@codemirror/lang-css';
|
|
5
|
+
import { html } from '@codemirror/lang-html';
|
|
6
|
+
import { javascript } from '@codemirror/lang-javascript';
|
|
7
|
+
import { json } from '@codemirror/lang-json';
|
|
8
|
+
import { markdown } from '@codemirror/lang-markdown';
|
|
9
|
+
import { python } from '@codemirror/lang-python';
|
|
10
|
+
import { yaml } from '@codemirror/lang-yaml';
|
|
11
|
+
|
|
12
|
+
function resolveLanguageExtension(language) {
|
|
13
|
+
switch (String(language || '').trim()) {
|
|
14
|
+
case 'css':
|
|
15
|
+
return css();
|
|
16
|
+
case 'html':
|
|
17
|
+
return html();
|
|
18
|
+
case 'javascript':
|
|
19
|
+
return javascript({ jsx: true, typescript: true });
|
|
20
|
+
case 'json':
|
|
21
|
+
return json();
|
|
22
|
+
case 'markdown':
|
|
23
|
+
return markdown();
|
|
24
|
+
case 'python':
|
|
25
|
+
return python();
|
|
26
|
+
case 'yaml':
|
|
27
|
+
return yaml();
|
|
28
|
+
default:
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function createEditor(parent, options = {}) {
|
|
34
|
+
const target = parent;
|
|
35
|
+
const initialDoc = String(options.doc || '');
|
|
36
|
+
const initialLanguage = String(options.language || 'text').trim();
|
|
37
|
+
const initialReadOnly = options.readOnly !== false;
|
|
38
|
+
const languageCompartment = new Compartment();
|
|
39
|
+
const readOnlyCompartment = new Compartment();
|
|
40
|
+
const view = new EditorView({
|
|
41
|
+
parent: target,
|
|
42
|
+
state: EditorState.create({
|
|
43
|
+
doc: initialDoc,
|
|
44
|
+
extensions: [
|
|
45
|
+
basicSetup,
|
|
46
|
+
EditorView.lineWrapping,
|
|
47
|
+
readOnlyCompartment.of([
|
|
48
|
+
EditorState.readOnly.of(initialReadOnly),
|
|
49
|
+
EditorView.editable.of(!initialReadOnly)
|
|
50
|
+
]),
|
|
51
|
+
languageCompartment.of(resolveLanguageExtension(initialLanguage)),
|
|
52
|
+
EditorView.theme({
|
|
53
|
+
'&': {
|
|
54
|
+
height: '100%',
|
|
55
|
+
fontSize: '12px'
|
|
56
|
+
},
|
|
57
|
+
'.cm-scroller': {
|
|
58
|
+
overflow: 'auto'
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
]
|
|
62
|
+
})
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
setValue(nextValue) {
|
|
67
|
+
const text = String(nextValue == null ? '' : nextValue);
|
|
68
|
+
view.dispatch({
|
|
69
|
+
changes: {
|
|
70
|
+
from: 0,
|
|
71
|
+
to: view.state.doc.length,
|
|
72
|
+
insert: text
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
setLanguage(nextLanguage) {
|
|
77
|
+
view.dispatch({
|
|
78
|
+
effects: languageCompartment.reconfigure(resolveLanguageExtension(nextLanguage))
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
setReadOnly(readOnly) {
|
|
82
|
+
const value = readOnly !== false;
|
|
83
|
+
view.dispatch({
|
|
84
|
+
effects: readOnlyCompartment.reconfigure([
|
|
85
|
+
EditorState.readOnly.of(value),
|
|
86
|
+
EditorView.editable.of(!value)
|
|
87
|
+
])
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
destroy() {
|
|
91
|
+
view.destroy();
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
window.ManyoyoCodeEditor = {
|
|
97
|
+
create: createEditor
|
|
98
|
+
};
|