@xcanwin/manyoyo 4.0.2 → 4.0.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 +0 -15
- package/lib/web/frontend/app.css +146 -4
- package/lib/web/frontend/app.html +18 -0
- package/lib/web/frontend/app.js +499 -31
- package/lib/web/frontend/login.css +2 -3
- package/lib/web/server.js +324 -6
- package/package.json +5 -2
package/bin/manyoyo.js
CHANGED
|
@@ -483,29 +483,14 @@ function collectClaudeInitData(homeDir) {
|
|
|
483
483
|
|
|
484
484
|
const claudeDir = path.join(homeDir, '.claude');
|
|
485
485
|
const claudeSettingsPath = path.join(claudeDir, 'settings.json');
|
|
486
|
-
const claudeJsonPath = path.join(homeDir, '.claude.json');
|
|
487
486
|
const settingsJson = readJsonFileSafely(claudeSettingsPath, 'Claude settings');
|
|
488
|
-
const claudeJson = readJsonFileSafely(claudeJsonPath, 'Claude config');
|
|
489
487
|
|
|
490
488
|
keys.forEach(key => setInitValue(values, key, process.env[key]));
|
|
491
489
|
|
|
492
|
-
if (claudeJson && claudeJson.env && typeof claudeJson.env === 'object') {
|
|
493
|
-
keys.forEach(key => setInitValue(values, key, claudeJson.env[key]));
|
|
494
|
-
}
|
|
495
490
|
if (settingsJson && settingsJson.env && typeof settingsJson.env === 'object') {
|
|
496
491
|
keys.forEach(key => setInitValue(values, key, settingsJson.env[key]));
|
|
497
492
|
}
|
|
498
493
|
|
|
499
|
-
if (fs.existsSync(claudeDir)) {
|
|
500
|
-
volumes.push(`${claudeDir}:/root/.claude`);
|
|
501
|
-
}
|
|
502
|
-
if (fs.existsSync(claudeJsonPath)) {
|
|
503
|
-
volumes.push(`${claudeJsonPath}:/root/.claude.json`);
|
|
504
|
-
}
|
|
505
|
-
if (!fs.existsSync(claudeDir) && !fs.existsSync(claudeJsonPath)) {
|
|
506
|
-
notes.push('未检测到 Claude 本地配置(~/.claude 或 ~/.claude.json),已生成占位模板。');
|
|
507
|
-
}
|
|
508
|
-
|
|
509
494
|
return { keys, values, notes, volumes: dedupeList(volumes) };
|
|
510
495
|
}
|
|
511
496
|
|
package/lib/web/frontend/app.css
CHANGED
|
@@ -63,7 +63,7 @@ body::before {
|
|
|
63
63
|
left: -120px;
|
|
64
64
|
top: -150px;
|
|
65
65
|
background: radial-gradient(circle at 30% 30%, rgba(96, 190, 143, 0.28) 0%, rgba(96, 190, 143, 0) 72%);
|
|
66
|
-
animation:
|
|
66
|
+
animation: none;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
body::after {
|
|
@@ -72,7 +72,7 @@ body::after {
|
|
|
72
72
|
right: -80px;
|
|
73
73
|
bottom: -120px;
|
|
74
74
|
background: radial-gradient(circle at 55% 45%, rgba(33, 130, 86, 0.22) 0%, rgba(33, 130, 86, 0) 70%);
|
|
75
|
-
animation:
|
|
75
|
+
animation: none;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
.app {
|
|
@@ -90,7 +90,6 @@ body::after {
|
|
|
90
90
|
border-radius: 12px;
|
|
91
91
|
border: 1px solid var(--line);
|
|
92
92
|
background: var(--panel);
|
|
93
|
-
backdrop-filter: blur(9px);
|
|
94
93
|
box-shadow: var(--shadow-soft);
|
|
95
94
|
}
|
|
96
95
|
|
|
@@ -362,7 +361,7 @@ button.danger:hover {
|
|
|
362
361
|
min-height: 0;
|
|
363
362
|
padding: 12px 14px 10px;
|
|
364
363
|
display: grid;
|
|
365
|
-
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
364
|
+
grid-template-rows: auto auto minmax(0, 1fr) auto;
|
|
366
365
|
gap: 0;
|
|
367
366
|
animation: panelIn 380ms ease 80ms both;
|
|
368
367
|
}
|
|
@@ -416,6 +415,53 @@ button.danger:hover {
|
|
|
416
415
|
flex-wrap: wrap;
|
|
417
416
|
}
|
|
418
417
|
|
|
418
|
+
.mode-switch {
|
|
419
|
+
display: flex;
|
|
420
|
+
justify-content: space-between;
|
|
421
|
+
align-items: center;
|
|
422
|
+
gap: 10px;
|
|
423
|
+
margin: 8px 8px 2px;
|
|
424
|
+
min-height: 34px;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.mode-switch-left {
|
|
428
|
+
display: inline-flex;
|
|
429
|
+
align-items: center;
|
|
430
|
+
gap: 8px;
|
|
431
|
+
min-width: 0;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.mode-switch button {
|
|
435
|
+
min-width: 98px;
|
|
436
|
+
color: var(--text);
|
|
437
|
+
background: #eef4f0;
|
|
438
|
+
border-color: var(--line);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.mode-switch button.is-active {
|
|
442
|
+
color: #ffffff;
|
|
443
|
+
background: var(--accent);
|
|
444
|
+
border-color: var(--accent-strong);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
body.command-mode #modeCommandBtn,
|
|
448
|
+
body.terminal-mode #modeTerminalBtn {
|
|
449
|
+
color: #ffffff;
|
|
450
|
+
background: var(--accent);
|
|
451
|
+
border-color: var(--accent-strong);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.mode-terminal-controls {
|
|
455
|
+
display: none;
|
|
456
|
+
align-items: center;
|
|
457
|
+
gap: 8px;
|
|
458
|
+
min-width: 0;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
body.terminal-mode .mode-terminal-controls {
|
|
462
|
+
display: inline-flex;
|
|
463
|
+
}
|
|
464
|
+
|
|
419
465
|
#messages {
|
|
420
466
|
min-height: 0;
|
|
421
467
|
overflow-y: auto;
|
|
@@ -426,6 +472,71 @@ button.danger:hover {
|
|
|
426
472
|
scroll-behavior: smooth;
|
|
427
473
|
}
|
|
428
474
|
|
|
475
|
+
#terminalPanel {
|
|
476
|
+
min-height: 0;
|
|
477
|
+
display: none;
|
|
478
|
+
flex-direction: column;
|
|
479
|
+
gap: 8px;
|
|
480
|
+
padding: 6px 8px 8px;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
.terminal-status {
|
|
484
|
+
display: inline-block;
|
|
485
|
+
color: var(--muted);
|
|
486
|
+
font-size: 12px;
|
|
487
|
+
white-space: nowrap;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
#terminalScreen {
|
|
491
|
+
flex: 1;
|
|
492
|
+
min-height: 0;
|
|
493
|
+
height: 100%;
|
|
494
|
+
border-radius: 10px;
|
|
495
|
+
border: 1px solid #2a3d34;
|
|
496
|
+
box-shadow: inset 0 0 0 1px rgba(123, 161, 146, 0.12);
|
|
497
|
+
overflow: hidden;
|
|
498
|
+
background: radial-gradient(circle at 10% 8%, #1a2832 0%, #0c131a 64%);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
#terminalScreen .xterm {
|
|
502
|
+
width: 100%;
|
|
503
|
+
height: 100%;
|
|
504
|
+
padding: 8px 6px;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
#terminalScreen .xterm-screen {
|
|
508
|
+
width: 100%;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
.terminal-foot {
|
|
512
|
+
color: #556961;
|
|
513
|
+
font-size: 12px;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
body.command-mode #messages {
|
|
517
|
+
display: flex;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
body.command-mode #terminalPanel {
|
|
521
|
+
display: none;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
body.command-mode .composer {
|
|
525
|
+
display: block;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
body.terminal-mode #messages {
|
|
529
|
+
display: none;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
body.terminal-mode #terminalPanel {
|
|
533
|
+
display: flex;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
body.terminal-mode .composer {
|
|
537
|
+
display: none;
|
|
538
|
+
}
|
|
539
|
+
|
|
429
540
|
.msg {
|
|
430
541
|
max-width: min(900px, 92%);
|
|
431
542
|
width: fit-content;
|
|
@@ -652,6 +763,10 @@ button.danger:hover {
|
|
|
652
763
|
max-height: none;
|
|
653
764
|
}
|
|
654
765
|
|
|
766
|
+
#terminalPanel {
|
|
767
|
+
min-height: 0;
|
|
768
|
+
}
|
|
769
|
+
|
|
655
770
|
.composer {
|
|
656
771
|
position: sticky;
|
|
657
772
|
bottom: 0;
|
|
@@ -740,6 +855,33 @@ button.danger:hover {
|
|
|
740
855
|
grid-template-columns: 1fr auto;
|
|
741
856
|
}
|
|
742
857
|
|
|
858
|
+
.mode-switch {
|
|
859
|
+
margin: 8px 10px 2px;
|
|
860
|
+
overflow-x: auto;
|
|
861
|
+
padding-bottom: 2px;
|
|
862
|
+
gap: 8px;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
.mode-switch-left {
|
|
866
|
+
flex: 0 0 auto;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
.mode-switch button {
|
|
870
|
+
min-width: 90px;
|
|
871
|
+
flex: 0 0 auto;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
.mode-terminal-controls {
|
|
875
|
+
flex: 0 0 auto;
|
|
876
|
+
gap: 6px;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
.terminal-status {
|
|
880
|
+
max-width: 5.2em;
|
|
881
|
+
overflow: hidden;
|
|
882
|
+
text-overflow: ellipsis;
|
|
883
|
+
}
|
|
884
|
+
|
|
743
885
|
#commandInput {
|
|
744
886
|
min-height: 68px;
|
|
745
887
|
max-height: 160px;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
/>
|
|
9
9
|
<title>MANYOYO Web</title>
|
|
10
10
|
<link rel="stylesheet" href="/app/frontend/app.css" />
|
|
11
|
+
<link rel="stylesheet" href="/app/vendor/xterm.css" />
|
|
11
12
|
</head>
|
|
12
13
|
<body>
|
|
13
14
|
<div class="app">
|
|
@@ -62,7 +63,22 @@
|
|
|
62
63
|
<button type="button" id="removeAllBtn" class="danger">删除对话</button>
|
|
63
64
|
</div>
|
|
64
65
|
</header>
|
|
66
|
+
<section class="mode-switch" id="modeSwitch">
|
|
67
|
+
<div class="mode-switch-left">
|
|
68
|
+
<button type="button" id="modeCommandBtn" class="secondary is-active">命令模式</button>
|
|
69
|
+
<button type="button" id="modeTerminalBtn" class="secondary">交互终端</button>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="mode-terminal-controls">
|
|
72
|
+
<button type="button" id="terminalConnectBtn">连接终端</button>
|
|
73
|
+
<button type="button" id="terminalDisconnectBtn" class="secondary">断开终端</button>
|
|
74
|
+
<span id="terminalStatus" class="terminal-status">未连接</span>
|
|
75
|
+
</div>
|
|
76
|
+
</section>
|
|
65
77
|
<section id="messages"></section>
|
|
78
|
+
<section id="terminalPanel" hidden>
|
|
79
|
+
<div id="terminalScreen" aria-label="终端输出区域"></div>
|
|
80
|
+
<div class="terminal-foot">点击终端后可直接输入;适用于 codex / claude 等交互式 agent。</div>
|
|
81
|
+
</section>
|
|
66
82
|
<form class="composer" id="composer">
|
|
67
83
|
<div class="composer-inner">
|
|
68
84
|
<textarea id="commandInput" placeholder="输入容器命令,例如: ls -la"></textarea>
|
|
@@ -77,6 +93,8 @@
|
|
|
77
93
|
<div id="sidebarBackdrop" class="sidebar-backdrop" hidden></div>
|
|
78
94
|
</div>
|
|
79
95
|
|
|
96
|
+
<script src="/app/vendor/xterm.js"></script>
|
|
97
|
+
<script src="/app/vendor/xterm-addon-fit.js"></script>
|
|
80
98
|
<script src="/app/frontend/app.js"></script>
|
|
81
99
|
</body>
|
|
82
100
|
</html>
|