loadtoagent 1.3.1 → 1.3.3
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.ko.md +11 -9
- package/docs/PROVIDER-CONTRACTS.md +8 -6
- package/main.js +25 -3
- package/package.json +1 -1
- package/preload.js +7 -2
- package/renderer/app-dashboard.js +18 -12
- package/renderer/app-graph-view.js +1 -1
- package/renderer/app-management.js +91 -45
- package/renderer/app-run-modal.js +1 -1
- package/renderer/app.js +1 -1
- package/renderer/i18n-messages.js +212 -199
- package/renderer/index.html +28 -27
- package/renderer/styles-agent-map.css +10 -10
- package/renderer/styles-cards.css +19 -19
- package/renderer/styles-collaboration.css +23 -23
- package/renderer/styles-components.css +36 -36
- package/renderer/styles-management.css +23 -14
- package/renderer/styles-onboarding.css +8 -8
- package/renderer/styles-overlays.css +5 -5
- package/renderer/styles-product.css +24 -24
- package/renderer/styles-quality.css +4 -4
- package/renderer/styles-readability.css +179 -1
- package/renderer/styles-responsive-runtime.css +5 -5
- package/renderer/styles-responsive-workflows.css +2 -2
- package/renderer/styles-run-composer.css +23 -23
- package/renderer/styles-runtime-overview.css +22 -22
- package/renderer/styles-settings.css +21 -21
- package/renderer/styles-terminal.css +66 -66
- package/renderer/styles-tmux.css +49 -49
- package/renderer/styles-workflows.css +48 -48
- package/renderer/styles.css +7 -7
- package/renderer/terminal-events.js +34 -11
- package/renderer/terminal-workbench.js +52 -21
- package/renderer/terminal.js +9 -1
- package/src/contracts.js +5 -5
- package/src/ipc/registerTerminalIpc.js +6 -14
- package/src/sessionIntelligence.js +18 -4
- package/src/terminalHost.js +100 -26
- package/src/terminalHostDaemon.js +1 -0
- package/src/terminalManager.js +61 -4
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
border-radius: 999px;
|
|
110
110
|
color: #09140f;
|
|
111
111
|
background: #63dba0;
|
|
112
|
-
font-size:
|
|
112
|
+
font-size: 12px;
|
|
113
113
|
font-variant-numeric: tabular-nums;
|
|
114
114
|
}
|
|
115
115
|
|
|
@@ -213,7 +213,7 @@
|
|
|
213
213
|
.agent-node-top .provider-mark {
|
|
214
214
|
width: 40px;
|
|
215
215
|
height: 40px;
|
|
216
|
-
font-size:
|
|
216
|
+
font-size: 12px;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
.agent-identity {
|
|
@@ -237,11 +237,11 @@
|
|
|
237
237
|
white-space: nowrap;
|
|
238
238
|
margin-top: 4px;
|
|
239
239
|
color: #7c899c;
|
|
240
|
-
font-size:
|
|
240
|
+
font-size: 12px;
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
.agent-node .status-pill {
|
|
244
|
-
font-size:
|
|
244
|
+
font-size: 12px;
|
|
245
245
|
padding: 5px 8px;
|
|
246
246
|
}
|
|
247
247
|
|
|
@@ -249,7 +249,7 @@
|
|
|
249
249
|
display: block;
|
|
250
250
|
margin-top: 17px;
|
|
251
251
|
color: var(--provider);
|
|
252
|
-
font-size:
|
|
252
|
+
font-size: 12px;
|
|
253
253
|
font-weight: 750;
|
|
254
254
|
letter-spacing: .13em;
|
|
255
255
|
}
|
|
@@ -290,13 +290,13 @@
|
|
|
290
290
|
border-radius: 6px;
|
|
291
291
|
background: rgba(76,227,154,.1);
|
|
292
292
|
color: #67e9a6;
|
|
293
|
-
font-size:
|
|
293
|
+
font-size: 12px;
|
|
294
294
|
font-style: normal;
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
.agent-current b {
|
|
298
298
|
color: #76e8ac;
|
|
299
|
-
font-size:
|
|
299
|
+
font-size: 12px;
|
|
300
300
|
}
|
|
301
301
|
|
|
302
302
|
.agent-current>strong {
|
|
@@ -325,7 +325,7 @@
|
|
|
325
325
|
.agent-node-metrics small {
|
|
326
326
|
display: block;
|
|
327
327
|
color: #6f7c8f;
|
|
328
|
-
font-size:
|
|
328
|
+
font-size: 12px;
|
|
329
329
|
}
|
|
330
330
|
|
|
331
331
|
.agent-node-metrics b {
|
|
@@ -359,7 +359,7 @@
|
|
|
359
359
|
border-top: 1px solid #192230;
|
|
360
360
|
background: rgba(5,8,13,.5);
|
|
361
361
|
color: #748195;
|
|
362
|
-
font-size:
|
|
362
|
+
font-size: 12px;
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
.agent-node-footer button {
|
|
@@ -369,7 +369,7 @@
|
|
|
369
369
|
border-radius: 7px;
|
|
370
370
|
background: transparent;
|
|
371
371
|
color: #aab7c7;
|
|
372
|
-
font-size:
|
|
372
|
+
font-size: 12px;
|
|
373
373
|
cursor: pointer;
|
|
374
374
|
}
|
|
375
375
|
|
|
@@ -428,7 +428,7 @@
|
|
|
428
428
|
.agent-flow-lane-head .provider-mark {
|
|
429
429
|
width: 32px;
|
|
430
430
|
height: 32px;
|
|
431
|
-
font-size:
|
|
431
|
+
font-size: 12px;
|
|
432
432
|
}
|
|
433
433
|
|
|
434
434
|
.agent-flow-lane-head>span:nth-child(2) {
|
|
@@ -540,7 +540,7 @@
|
|
|
540
540
|
white-space: nowrap;
|
|
541
541
|
margin-top: 3px;
|
|
542
542
|
color: #667587;
|
|
543
|
-
font-size:
|
|
543
|
+
font-size: 12px;
|
|
544
544
|
}
|
|
545
545
|
|
|
546
546
|
.agent-flow-lane-head em {
|
|
@@ -550,7 +550,7 @@
|
|
|
550
550
|
color: #65dba9;
|
|
551
551
|
font-style: normal;
|
|
552
552
|
font-weight: 750;
|
|
553
|
-
font-size:
|
|
553
|
+
font-size: 12px;
|
|
554
554
|
}
|
|
555
555
|
|
|
556
556
|
.agent-flow-copy small {
|
|
@@ -562,7 +562,7 @@
|
|
|
562
562
|
color: var(--provider);
|
|
563
563
|
font-weight: 700;
|
|
564
564
|
letter-spacing: .05em;
|
|
565
|
-
font-size:
|
|
565
|
+
font-size: 12px;
|
|
566
566
|
}
|
|
567
567
|
|
|
568
568
|
.agent-flow-copy b {
|
|
@@ -583,7 +583,7 @@
|
|
|
583
583
|
margin-top: 4px;
|
|
584
584
|
color: #5f6f82;
|
|
585
585
|
font-style: normal;
|
|
586
|
-
font-size:
|
|
586
|
+
font-size: 12px;
|
|
587
587
|
}
|
|
588
588
|
|
|
589
589
|
.agent-flow-provider small {
|
|
@@ -592,7 +592,7 @@
|
|
|
592
592
|
color: #718092;
|
|
593
593
|
text-overflow: ellipsis;
|
|
594
594
|
white-space: nowrap;
|
|
595
|
-
font-size:
|
|
595
|
+
font-size: 12px;
|
|
596
596
|
}
|
|
597
597
|
|
|
598
598
|
.agent-flow-provider i {
|
|
@@ -605,7 +605,7 @@
|
|
|
605
605
|
font-weight: 800;
|
|
606
606
|
width: 27px;
|
|
607
607
|
height: 23px;
|
|
608
|
-
font-size:
|
|
608
|
+
font-size: 12px;
|
|
609
609
|
}
|
|
610
610
|
|
|
611
611
|
.agent-flow-more {
|
|
@@ -616,7 +616,7 @@
|
|
|
616
616
|
color: #7894a1;
|
|
617
617
|
cursor: pointer;
|
|
618
618
|
height: 40px;
|
|
619
|
-
font-size:
|
|
619
|
+
font-size: 12px;
|
|
620
620
|
}
|
|
621
621
|
|
|
622
622
|
.agent-relation-block>header b {
|
|
@@ -626,7 +626,7 @@
|
|
|
626
626
|
|
|
627
627
|
.agent-relation-block>header span {
|
|
628
628
|
color: #657587;
|
|
629
|
-
font-size:
|
|
629
|
+
font-size: 12px;
|
|
630
630
|
}
|
|
631
631
|
|
|
632
632
|
.agent-relation-empty {
|
|
@@ -636,7 +636,7 @@
|
|
|
636
636
|
padding: 14px;
|
|
637
637
|
color: #596a7d;
|
|
638
638
|
text-align: center;
|
|
639
|
-
font-size:
|
|
639
|
+
font-size: 12px;
|
|
640
640
|
}
|
|
641
641
|
|
|
642
642
|
.agent-relation-block .agent-flow-copy b {
|
|
@@ -644,7 +644,7 @@
|
|
|
644
644
|
}
|
|
645
645
|
|
|
646
646
|
.agent-relation-block .agent-flow-copy em {
|
|
647
|
-
font-size:
|
|
647
|
+
font-size: 12px;
|
|
648
648
|
}
|
|
649
649
|
|
|
650
650
|
.workflow-origin-icon {
|
|
@@ -739,7 +739,7 @@
|
|
|
739
739
|
background: color-mix(in srgb,var(--command-accent) 10%,#111c22);
|
|
740
740
|
color: var(--command-accent);
|
|
741
741
|
font-family: "Cascadia Code",Consolas,monospace;
|
|
742
|
-
font-size:
|
|
742
|
+
font-size: 12px;
|
|
743
743
|
font-weight: 800;
|
|
744
744
|
}
|
|
745
745
|
|
|
@@ -758,7 +758,7 @@
|
|
|
758
758
|
white-space: nowrap;
|
|
759
759
|
margin-top: 4px;
|
|
760
760
|
color: #7f918f;
|
|
761
|
-
font-size:
|
|
761
|
+
font-size: 12px;
|
|
762
762
|
}
|
|
763
763
|
|
|
764
764
|
.agent-command-panel header>i {
|
|
@@ -822,7 +822,7 @@
|
|
|
822
822
|
|
|
823
823
|
.agent-command-target>span {
|
|
824
824
|
color: #849493;
|
|
825
|
-
font-size:
|
|
825
|
+
font-size: 12px;
|
|
826
826
|
}
|
|
827
827
|
|
|
828
828
|
.agent-command-target select {
|
|
@@ -833,7 +833,7 @@
|
|
|
833
833
|
border-radius: 8px;
|
|
834
834
|
background: #0b1518;
|
|
835
835
|
color: #b8ccc8;
|
|
836
|
-
font-size:
|
|
836
|
+
font-size: 12px;
|
|
837
837
|
outline: none;
|
|
838
838
|
}
|
|
839
839
|
|
|
@@ -853,7 +853,7 @@
|
|
|
853
853
|
border-radius: 10px;
|
|
854
854
|
background: #071013;
|
|
855
855
|
color: #dbe9e6;
|
|
856
|
-
font-size:
|
|
856
|
+
font-size: 12px;
|
|
857
857
|
line-height: 1.5;
|
|
858
858
|
outline: none;
|
|
859
859
|
transition: border-color var(--motion-fast) ease,box-shadow var(--motion-medium) ease;
|
|
@@ -884,7 +884,7 @@
|
|
|
884
884
|
min-width: 0;
|
|
885
885
|
margin-right: auto;
|
|
886
886
|
color: #647672;
|
|
887
|
-
font-size:
|
|
887
|
+
font-size: 12px;
|
|
888
888
|
line-height: 1.4;
|
|
889
889
|
}
|
|
890
890
|
|
|
@@ -895,7 +895,7 @@
|
|
|
895
895
|
border-radius: 8px;
|
|
896
896
|
background: #111d1f;
|
|
897
897
|
color: #9cc9bd;
|
|
898
|
-
font-size:
|
|
898
|
+
font-size: 12px;
|
|
899
899
|
font-weight: 650;
|
|
900
900
|
cursor: pointer;
|
|
901
901
|
transition: transform var(--motion-fast) var(--motion-ease),border-color var(--motion-fast) ease,background-color var(--motion-fast) ease,color var(--motion-fast) ease;
|
|
@@ -931,7 +931,7 @@
|
|
|
931
931
|
display: block;
|
|
932
932
|
margin-top: 5px;
|
|
933
933
|
color: #6f9f91;
|
|
934
|
-
font-size:
|
|
934
|
+
font-size: 12px;
|
|
935
935
|
letter-spacing: .01em;
|
|
936
936
|
}
|
|
937
937
|
|
|
@@ -942,7 +942,7 @@
|
|
|
942
942
|
text-overflow: ellipsis;
|
|
943
943
|
white-space: nowrap;
|
|
944
944
|
color: #71879a;
|
|
945
|
-
font-size:
|
|
945
|
+
font-size: 12px;
|
|
946
946
|
}
|
|
947
947
|
|
|
948
948
|
.agent-flow-copy .agent-flow-outcome {
|
|
@@ -954,14 +954,14 @@
|
|
|
954
954
|
padding-top: 5px;
|
|
955
955
|
border-top: 1px solid rgba(92,132,145,.12);
|
|
956
956
|
color: #9fb1bf;
|
|
957
|
-
font-size:
|
|
957
|
+
font-size: 12px;
|
|
958
958
|
}
|
|
959
959
|
|
|
960
960
|
.agent-flow-copy .agent-flow-outcome b {
|
|
961
961
|
display: inline;
|
|
962
962
|
margin-right: 6px;
|
|
963
963
|
color: #67dfb0;
|
|
964
|
-
font-size:
|
|
964
|
+
font-size: 12px;
|
|
965
965
|
}
|
|
966
966
|
|
|
967
967
|
.agent-flow-copy .agent-flow-outcome.done b {
|
|
@@ -990,7 +990,7 @@
|
|
|
990
990
|
.child-session .agent-flow-kicker small {
|
|
991
991
|
margin: 0;
|
|
992
992
|
color: var(--provider);
|
|
993
|
-
font-size:
|
|
993
|
+
font-size: 12px;
|
|
994
994
|
font-weight: 800;
|
|
995
995
|
letter-spacing: .08em;
|
|
996
996
|
}
|
|
@@ -998,7 +998,7 @@
|
|
|
998
998
|
.child-session .agent-flow-kicker time {
|
|
999
999
|
flex: 0 0 auto;
|
|
1000
1000
|
color: #60727e;
|
|
1001
|
-
font-size:
|
|
1001
|
+
font-size: 12px;
|
|
1002
1002
|
}
|
|
1003
1003
|
|
|
1004
1004
|
.child-session .agent-flow-agent {
|
|
@@ -1018,7 +1018,7 @@
|
|
|
1018
1018
|
border-radius: 5px;
|
|
1019
1019
|
background: color-mix(in srgb,var(--provider) 13%,#17212b);
|
|
1020
1020
|
color: var(--provider);
|
|
1021
|
-
font-size:
|
|
1021
|
+
font-size: 12px;
|
|
1022
1022
|
font-style: normal;
|
|
1023
1023
|
font-weight: 850;
|
|
1024
1024
|
}
|
|
@@ -1026,7 +1026,7 @@
|
|
|
1026
1026
|
.child-session .agent-flow-agent strong {
|
|
1027
1027
|
flex: 0 0 auto;
|
|
1028
1028
|
color: #b9c7cf;
|
|
1029
|
-
font-size:
|
|
1029
|
+
font-size: 12px;
|
|
1030
1030
|
}
|
|
1031
1031
|
|
|
1032
1032
|
.child-session .agent-flow-agent small {
|
|
@@ -1034,7 +1034,7 @@
|
|
|
1034
1034
|
margin: 0;
|
|
1035
1035
|
overflow: hidden;
|
|
1036
1036
|
color: #627581;
|
|
1037
|
-
font-size:
|
|
1037
|
+
font-size: 12px;
|
|
1038
1038
|
font-weight: 500;
|
|
1039
1039
|
letter-spacing: 0;
|
|
1040
1040
|
text-overflow: ellipsis;
|
|
@@ -1052,7 +1052,7 @@
|
|
|
1052
1052
|
.child-session .agent-flow-assignment small {
|
|
1053
1053
|
margin: 0 0 4px;
|
|
1054
1054
|
color: #6e8791;
|
|
1055
|
-
font-size:
|
|
1055
|
+
font-size: 12px;
|
|
1056
1056
|
letter-spacing: .04em;
|
|
1057
1057
|
}
|
|
1058
1058
|
|
|
@@ -1060,7 +1060,7 @@
|
|
|
1060
1060
|
display: -webkit-box;
|
|
1061
1061
|
overflow: hidden;
|
|
1062
1062
|
color: #aebdc5;
|
|
1063
|
-
font-size:
|
|
1063
|
+
font-size: 12px;
|
|
1064
1064
|
font-weight: 520;
|
|
1065
1065
|
line-height: 1.45;
|
|
1066
1066
|
white-space: normal;
|
|
@@ -1079,7 +1079,7 @@
|
|
|
1079
1079
|
border-radius: 8px;
|
|
1080
1080
|
background: rgba(109,174,204,.055);
|
|
1081
1081
|
color: #c1d0d8;
|
|
1082
|
-
font-size:
|
|
1082
|
+
font-size: 12px;
|
|
1083
1083
|
white-space: normal;
|
|
1084
1084
|
}
|
|
1085
1085
|
|
|
@@ -1088,7 +1088,7 @@
|
|
|
1088
1088
|
flex: 0 0 auto;
|
|
1089
1089
|
margin: 0;
|
|
1090
1090
|
color: #79dfb6;
|
|
1091
|
-
font-size:
|
|
1091
|
+
font-size: 12px;
|
|
1092
1092
|
}
|
|
1093
1093
|
|
|
1094
1094
|
.child-session .agent-flow-outcome.done b {
|
|
@@ -1102,7 +1102,7 @@
|
|
|
1102
1102
|
.child-session .agent-flow-provider .status-pill {
|
|
1103
1103
|
margin: 0;
|
|
1104
1104
|
padding: 4px 6px;
|
|
1105
|
-
font-size:
|
|
1105
|
+
font-size: 12px;
|
|
1106
1106
|
letter-spacing: 0;
|
|
1107
1107
|
text-transform: none;
|
|
1108
1108
|
}
|
|
@@ -1130,7 +1130,7 @@
|
|
|
1130
1130
|
display: block;
|
|
1131
1131
|
overflow: hidden;
|
|
1132
1132
|
color: #7b9099;
|
|
1133
|
-
font-size:
|
|
1133
|
+
font-size: 12px;
|
|
1134
1134
|
text-overflow: ellipsis;
|
|
1135
1135
|
white-space: nowrap;
|
|
1136
1136
|
}
|
|
@@ -1146,7 +1146,7 @@
|
|
|
1146
1146
|
.workflow-metric-grid em {
|
|
1147
1147
|
margin-left: 3px;
|
|
1148
1148
|
color: #73918d;
|
|
1149
|
-
font-size:
|
|
1149
|
+
font-size: 12px;
|
|
1150
1150
|
font-style: normal;
|
|
1151
1151
|
}
|
|
1152
1152
|
|
|
@@ -1181,7 +1181,7 @@
|
|
|
1181
1181
|
.child-session .agent-flow-provider em {
|
|
1182
1182
|
max-width: 76px;
|
|
1183
1183
|
color: #607884;
|
|
1184
|
-
font-size:
|
|
1184
|
+
font-size: 12px;
|
|
1185
1185
|
font-style: normal;
|
|
1186
1186
|
line-height: 1.3;
|
|
1187
1187
|
text-align: right;
|
|
@@ -1191,7 +1191,7 @@
|
|
|
1191
1191
|
display: block;
|
|
1192
1192
|
margin-top: 9px;
|
|
1193
1193
|
color: #6f9f9a;
|
|
1194
|
-
font-size:
|
|
1194
|
+
font-size: 12px;
|
|
1195
1195
|
font-weight: 750;
|
|
1196
1196
|
text-align: right;
|
|
1197
1197
|
}
|
|
@@ -1224,7 +1224,7 @@
|
|
|
1224
1224
|
.agent-flow-provider .execution-mode-badge {
|
|
1225
1225
|
margin-bottom: 2px;
|
|
1226
1226
|
padding: 3px 5px;
|
|
1227
|
-
font-size:
|
|
1227
|
+
font-size: 12px;
|
|
1228
1228
|
}
|
|
1229
1229
|
|
|
1230
1230
|
.agent-node-top .execution-mode-badge {
|
|
@@ -1241,7 +1241,7 @@
|
|
|
1241
1241
|
gap: 6px;
|
|
1242
1242
|
margin-top: 7px;
|
|
1243
1243
|
color: #728695;
|
|
1244
|
-
font-size:
|
|
1244
|
+
font-size: 12px;
|
|
1245
1245
|
line-height: 1.4;
|
|
1246
1246
|
}
|
|
1247
1247
|
|
package/renderer/styles.css
CHANGED
|
@@ -162,13 +162,13 @@ body[data-current-view="settings"] .sidebar>.workspace-section {
|
|
|
162
162
|
color: #657187;
|
|
163
163
|
font-weight: 700;
|
|
164
164
|
letter-spacing: .18em;
|
|
165
|
-
font-size:
|
|
165
|
+
font-size: 12px;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
.nav-group-label {
|
|
169
169
|
margin: 18px 10px 6px;
|
|
170
170
|
color: #718096;
|
|
171
|
-
font-size:
|
|
171
|
+
font-size: 12px;
|
|
172
172
|
font-weight: 700;
|
|
173
173
|
letter-spacing: .08em;
|
|
174
174
|
}
|
|
@@ -195,7 +195,7 @@ body {
|
|
|
195
195
|
background: #101923;
|
|
196
196
|
color: #7f929d;
|
|
197
197
|
font-family: "Geist Mono","Cascadia Code",Consolas,monospace;
|
|
198
|
-
font-size:
|
|
198
|
+
font-size: 12px;
|
|
199
199
|
font-weight: 700;
|
|
200
200
|
letter-spacing: .02em;
|
|
201
201
|
white-space: nowrap;
|
|
@@ -242,7 +242,7 @@ html {
|
|
|
242
242
|
font-weight: 760;
|
|
243
243
|
letter-spacing: .17em;
|
|
244
244
|
color: #8d9bad;
|
|
245
|
-
font-size:
|
|
245
|
+
font-size: 12px;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
.nav-item b {
|
|
@@ -252,20 +252,20 @@ html {
|
|
|
252
252
|
border-radius: 10px;
|
|
253
253
|
background: #1c2431;
|
|
254
254
|
color: #aeb9c7;
|
|
255
|
-
font-size:
|
|
255
|
+
font-size: 12px;
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
.sidebar-footer strong {
|
|
259
259
|
display: block;
|
|
260
260
|
color: #aeb9c7;
|
|
261
|
-
font-size:
|
|
261
|
+
font-size: 12px;
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
.sidebar-footer small {
|
|
265
265
|
display: block;
|
|
266
266
|
margin-top: 3px;
|
|
267
267
|
color: #8795a6;
|
|
268
|
-
font-size:
|
|
268
|
+
font-size: 12px;
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
.app-shell {
|
|
@@ -9,6 +9,7 @@ window.LoadToAgentTerminalEvents = function bindTerminalEvents(context) {
|
|
|
9
9
|
refreshSessions, renderHistoryPanel, fitEntry, attachTmux, currentTmux, manageTmux,
|
|
10
10
|
closeTmuxModal, errorMessage, notice, reorderSession, moveSessionByOffset,
|
|
11
11
|
setTerminalFontSize, toggleTerminalFocusMode,
|
|
12
|
+
isAiTerminalSession,
|
|
12
13
|
} = context;
|
|
13
14
|
|
|
14
15
|
const runBusy = async (button, action) => {
|
|
@@ -283,17 +284,13 @@ window.LoadToAgentTerminalEvents = function bindTerminalEvents(context) {
|
|
|
283
284
|
});
|
|
284
285
|
renderAll();
|
|
285
286
|
});
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
294
|
-
if (session.status === 'running' && !window.confirm(t('terminal.session.confirm_end', { title: session.title }))) return;
|
|
295
|
-
await runBusy(event.currentTarget, async () => {
|
|
296
|
-
const closed = await guarded(() => window.loadtoagent.terminalClose(session.id), t('terminal.session.ended'), `terminal-close:${session.id}`);
|
|
287
|
+
const endTerminalSession = async (button, session) => {
|
|
288
|
+
if (!session) return;
|
|
289
|
+
const confirmation = isAiTerminalSession(session) ? 'terminal.session.confirm_end_ai' : 'terminal.session.confirm_end';
|
|
290
|
+
if (session.type !== 'tmux' && session.status === 'running' && !window.confirm(t(confirmation, { title: session.title }))) return;
|
|
291
|
+
await runBusy(button, async () => {
|
|
292
|
+
const message = session.type === 'tmux' ? t('terminal.tmux.detached_input') : t('terminal.session.ended');
|
|
293
|
+
const closed = await guarded(() => window.loadtoagent.terminalClose(session.id), message, `terminal-close:${session.id}`);
|
|
297
294
|
if (!closed) return;
|
|
298
295
|
const entry = state.terminals.get(session.id);
|
|
299
296
|
if (entry) {
|
|
@@ -310,7 +307,29 @@ window.LoadToAgentTerminalEvents = function bindTerminalEvents(context) {
|
|
|
310
307
|
await refreshSessions();
|
|
311
308
|
});
|
|
312
309
|
renderAll();
|
|
310
|
+
};
|
|
311
|
+
$('#terminalCloseBtn').addEventListener('click', async event => {
|
|
312
|
+
const session = currentSession();
|
|
313
|
+
if (!session) {
|
|
314
|
+
state.selectedTmux = null;
|
|
315
|
+
renderAll();
|
|
316
|
+
await showSelection();
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (isAiTerminalSession(session)) {
|
|
320
|
+
state.captureGeneration += 1;
|
|
321
|
+
state.selectedId = null;
|
|
322
|
+
state.boundAgent = null;
|
|
323
|
+
state.boundTargetId = '';
|
|
324
|
+
renderAll();
|
|
325
|
+
renderHistoryPanel();
|
|
326
|
+
await showSelection();
|
|
327
|
+
notice(t('terminal.view_closed_ai_kept'), 'success');
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
await endTerminalSession(event.currentTarget, session);
|
|
313
331
|
});
|
|
332
|
+
$('#terminalEndSessionBtn').addEventListener('click', event => endTerminalSession(event.currentTarget, currentSession()));
|
|
314
333
|
$('#terminalHistoryToggle').addEventListener('click', () => {
|
|
315
334
|
state.historyCollapsed = !state.historyCollapsed;
|
|
316
335
|
renderHistoryPanel();
|
|
@@ -415,5 +434,9 @@ window.LoadToAgentTerminalEvents = function bindTerminalEvents(context) {
|
|
|
415
434
|
});
|
|
416
435
|
window.loadtoagent.onTerminalState(payload => refreshSessions(payload));
|
|
417
436
|
window.loadtoagent.onTerminalError(payload => notice(payload && payload.message || t('terminal.error.input_failed'), 'error'));
|
|
437
|
+
window.loadtoagent.onTerminalConnection?.(payload => {
|
|
438
|
+
const tone = payload?.state === 'failed' ? 'error' : payload?.state === 'connected' ? 'success' : 'info';
|
|
439
|
+
notice(payload?.message || t('terminal.error.input_failed'), tone);
|
|
440
|
+
});
|
|
418
441
|
}
|
|
419
442
|
};
|
|
@@ -19,7 +19,10 @@ window.LoadToAgentTerminalWorkbench = function createModule(context) {
|
|
|
19
19
|
const fit = new window.FitAddon.FitAddon();
|
|
20
20
|
terminal.loadAddon(fit);
|
|
21
21
|
terminal.open(host);
|
|
22
|
-
const entry = {
|
|
22
|
+
const entry = {
|
|
23
|
+
terminal, fit, host, readOnly, userScrollRevision: 0, outputWritePending: 0,
|
|
24
|
+
writeQueue: Promise.resolve(), pendingResize: null, resizePromise: null,
|
|
25
|
+
};
|
|
23
26
|
const syncScrollState = viewportY => {
|
|
24
27
|
const normalizedViewport = Number(viewportY) || 0;
|
|
25
28
|
const baseY = Number(terminal.buffer.active.baseY) || 0;
|
|
@@ -43,27 +46,33 @@ window.LoadToAgentTerminalWorkbench = function createModule(context) {
|
|
|
43
46
|
if (['PageUp', 'PageDown', 'Home', 'End', 'ArrowUp', 'ArrowDown'].includes(event.key)) rememberUserScroll();
|
|
44
47
|
}, true);
|
|
45
48
|
terminal.onData(data => {
|
|
46
|
-
if (state.selectedId
|
|
49
|
+
if (state.selectedId !== key) return;
|
|
50
|
+
entry.writeQueue = entry.writeQueue
|
|
51
|
+
.then(() => window.loadtoagent.terminalWrite(key, data))
|
|
52
|
+
.catch(error => notice(errorMessage(error), 'error'));
|
|
47
53
|
});
|
|
48
54
|
terminal.onResize(size => {
|
|
49
|
-
|
|
55
|
+
entry.pendingResize = { cols: size.cols, rows: size.rows };
|
|
56
|
+
if (entry.resizePromise) return;
|
|
57
|
+
entry.resizePromise = (async () => {
|
|
58
|
+
while (entry.pendingResize) {
|
|
59
|
+
const pending = entry.pendingResize;
|
|
60
|
+
entry.pendingResize = null;
|
|
61
|
+
await window.loadtoagent.terminalResize(key, pending.cols, pending.rows);
|
|
62
|
+
}
|
|
63
|
+
})().catch(error => {
|
|
50
64
|
window.LoadToAgentRendererUtils.reportRecoverableError('terminal-resize', error);
|
|
51
|
-
});
|
|
65
|
+
}).finally(() => { entry.resizePromise = null; });
|
|
52
66
|
});
|
|
53
67
|
}
|
|
54
68
|
return entry;
|
|
55
69
|
}
|
|
56
70
|
|
|
57
|
-
function fitEntry(entry,
|
|
71
|
+
function fitEntry(entry, _sessionId = '') {
|
|
58
72
|
if (!entry || entry.host.classList.contains('hidden')) return;
|
|
59
73
|
requestAnimationFrame(() => {
|
|
60
74
|
try {
|
|
61
75
|
entry.fit.fit();
|
|
62
|
-
if (sessionId) {
|
|
63
|
-
Promise.resolve(window.loadtoagent.terminalResize(sessionId, entry.terminal.cols, entry.terminal.rows)).catch(error => {
|
|
64
|
-
window.LoadToAgentRendererUtils.reportRecoverableError('terminal-fit-resize', error);
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
76
|
} catch (error) {
|
|
68
77
|
window.LoadToAgentRendererUtils.reportRecoverableError('terminal-fit', error);
|
|
69
78
|
}
|
|
@@ -95,15 +104,25 @@ window.LoadToAgentTerminalWorkbench = function createModule(context) {
|
|
|
95
104
|
function linkedAgentSession(session) {
|
|
96
105
|
if (!session) return null;
|
|
97
106
|
if (state.boundTargetId === session.id && state.boundAgent) return state.boundAgent;
|
|
107
|
+
const agents = Array.isArray(state.snapshot?.sessions) ? state.snapshot.sessions : [];
|
|
98
108
|
const bridgeId = String(session.bridgeId || '');
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
109
|
+
const bridged = bridgeId ? agents.find(item => item.id === bridgeId) : null;
|
|
110
|
+
if (bridged) return bridged;
|
|
111
|
+
const terminalPid = Number(session.pid || 0);
|
|
112
|
+
return agents.find(agent => (Array.isArray(agent.runtimePresence) ? agent.runtimePresence : []).some(item => (
|
|
113
|
+
item.terminalId === session.id
|
|
114
|
+
|| (terminalPid > 0 && Number(item.pid || 0) === terminalPid)
|
|
115
|
+
|| (terminalPid > 0 && Number(item.parentPid || 0) === terminalPid)
|
|
116
|
+
))) || null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function isAiTerminalSession(session) {
|
|
120
|
+
return Boolean(session && (session.type === 'agent' || linkedAgentSession(session)));
|
|
102
121
|
}
|
|
103
122
|
|
|
104
123
|
function terminalPresentation(session) {
|
|
105
124
|
const agent = linkedAgentSession(session);
|
|
106
|
-
if (agent?.attention?.required || agent?.status === 'waiting') return { tone: 'attention', label: t('
|
|
125
|
+
if (agent?.attention?.required || agent?.status === 'waiting') return { tone: 'attention', label: t('ui.waiting_for_review') };
|
|
107
126
|
if (agent?.status === 'failed' || session?.status === 'failed') return { tone: 'failed', label: t('terminal.status.failed') };
|
|
108
127
|
if (agent?.status === 'completed') return { tone: 'completed', label: t('ui.completed') };
|
|
109
128
|
if (agent && ['running', 'starting'].includes(agent.status)) return { tone: 'running', label: t('ui.working') };
|
|
@@ -136,7 +155,10 @@ window.LoadToAgentTerminalWorkbench = function createModule(context) {
|
|
|
136
155
|
state.selectedId,
|
|
137
156
|
general.map(session => {
|
|
138
157
|
const presentation = terminalPresentation(session);
|
|
139
|
-
return [
|
|
158
|
+
return [
|
|
159
|
+
session.id, session.title, session.type, session.status, session.pid, session.cwd, session.background,
|
|
160
|
+
session.recoveredAfterHostRestart, session.recoverySkippedReason, presentation.tone, presentation.label,
|
|
161
|
+
];
|
|
140
162
|
}),
|
|
141
163
|
]);
|
|
142
164
|
if (renderKey === state.sessionRenderKey) return;
|
|
@@ -157,7 +179,7 @@ window.LoadToAgentTerminalWorkbench = function createModule(context) {
|
|
|
157
179
|
aria-describedby="terminalReorderHelp"
|
|
158
180
|
title="${esc(session.cwd || window.LoadToAgentI18n.t('terminal.reorder_hint'))}">
|
|
159
181
|
<span class="terminal-session-icon">${esc(terminalTypeMark(session))}</span>
|
|
160
|
-
<span><b>${esc(session.title)}</b><small>${esc(terminalTypeLabel(session))}${session.background ? ` · ${t('terminal.background_kept')}` : ''}</small><em>${esc(session.cwd || session.distro || `PID ${session.pid || '--'}`)}</em><span class="sr-only">${index + 1}/${general.length}</span></span>
|
|
182
|
+
<span><b>${esc(session.title)}</b><small>${esc(terminalTypeLabel(session))}${session.background ? ` · ${t('terminal.background_kept')}` : ''}${session.recoveredAfterHostRestart ? ` · ${t('terminal.recovered_after_host_restart')}` : ''}</small><em>${esc(session.cwd || session.distro || `PID ${session.pid || '--'}`)}</em><span class="sr-only">${index + 1}/${general.length}</span></span>
|
|
161
183
|
<span class="terminal-session-status" data-status="${esc(presentation.tone)}"><i></i>${esc(presentation.label)}</span>
|
|
162
184
|
</button>
|
|
163
185
|
<span class="terminal-reorder-actions" aria-label="${esc(window.LoadToAgentI18n.t('terminal.reorder_group', { title: session.title }))}">
|
|
@@ -192,12 +214,20 @@ window.LoadToAgentTerminalWorkbench = function createModule(context) {
|
|
|
192
214
|
const session = currentSession();
|
|
193
215
|
const remote = currentTmux();
|
|
194
216
|
const bound = visibleBoundAgent();
|
|
217
|
+
const aiTerminal = isAiTerminalSession(session);
|
|
195
218
|
const hasTarget = Boolean(session || remote);
|
|
196
219
|
const canInput = Boolean((remote && !remote.pane.dead) || (session && session.status === 'running'));
|
|
197
220
|
const closeButton = $('#terminalCloseBtn');
|
|
198
221
|
closeButton.disabled = !hasTarget;
|
|
199
|
-
closeButton.textContent = remote && !session
|
|
200
|
-
|
|
222
|
+
closeButton.textContent = remote && !session
|
|
223
|
+
? t('terminal.clear_selection')
|
|
224
|
+
: session?.type === 'tmux'
|
|
225
|
+
? t('terminal.detach_tmux_input')
|
|
226
|
+
: aiTerminal ? t('terminal.close_view') : t('ui.end_session');
|
|
227
|
+
closeButton.classList.toggle('terminal-danger-button', Boolean(session && !aiTerminal && session.type !== 'tmux'));
|
|
228
|
+
const endSessionButton = $('#terminalEndSessionBtn');
|
|
229
|
+
endSessionButton.classList.toggle('hidden', !aiTerminal);
|
|
230
|
+
endSessionButton.disabled = !aiTerminal;
|
|
201
231
|
$('#terminalRestartBtn').classList.toggle('hidden', !session || session.status === 'running' || session.type === 'agent');
|
|
202
232
|
$('#terminalRestartBtn').disabled = !session || session.status === 'running';
|
|
203
233
|
$('#terminalCommandInput').disabled = !canInput;
|
|
@@ -215,7 +245,7 @@ window.LoadToAgentTerminalWorkbench = function createModule(context) {
|
|
|
215
245
|
const presentation = terminalPresentation(session);
|
|
216
246
|
setConnectionState(presentation.label, presentation.tone);
|
|
217
247
|
$('#terminalTargetIcon').textContent = terminalTypeMark(session);
|
|
218
|
-
$('#terminalTargetMeta').innerHTML = `<b>${esc(session.title)}</b><span>${bound ? `● ${t('terminal.bound_ai_session')} · ` : ''}${esc(session.type.toUpperCase())} · PID ${session.pid || '--'} · ${esc(session.cwd || session.distro || '')}</span>`;
|
|
248
|
+
$('#terminalTargetMeta').innerHTML = `<b>${esc(session.title)}</b><span>${bound ? `● ${t('terminal.bound_ai_session')} · ` : ''}${session.recoveredAfterHostRestart ? `${t('terminal.recovered_after_host_restart')} · ` : ''}${esc(session.type.toUpperCase())} · PID ${session.pid || '--'} · ${esc(session.cwd || session.distro || '')}</span>`;
|
|
219
249
|
$('#terminalConsoleCaption').textContent = `${terminalTypeLabel(session)} · PID ${session.pid || '--'}`;
|
|
220
250
|
$('#terminalConsoleState').textContent = presentation.tone === 'attention' || presentation.tone === 'completed'
|
|
221
251
|
? presentation.label
|
|
@@ -334,8 +364,9 @@ window.LoadToAgentTerminalWorkbench = function createModule(context) {
|
|
|
334
364
|
const nextSessions = payload && Array.isArray(payload.sessions) ? payload.sessions : await window.loadtoagent.terminalList();
|
|
335
365
|
state.sessions = Array.isArray(nextSessions) ? nextSessions : [];
|
|
336
366
|
const activeIds = new Set(state.sessions.map(session => session.id));
|
|
367
|
+
const rehydratedIds = new Set(payload?.change === 'reconnected' ? activeIds : []);
|
|
337
368
|
for (const [id, entry] of state.terminals) {
|
|
338
|
-
if (activeIds.has(id)) continue;
|
|
369
|
+
if (activeIds.has(id) && !rehydratedIds.has(id)) continue;
|
|
339
370
|
entry.terminal.dispose();
|
|
340
371
|
entry.host.remove();
|
|
341
372
|
state.terminals.delete(id);
|
|
@@ -558,5 +589,5 @@ window.LoadToAgentTerminalWorkbench = function createModule(context) {
|
|
|
558
589
|
}
|
|
559
590
|
}
|
|
560
591
|
|
|
561
|
-
return { createXtermHost, fitEntry, ensureSessionTerminal, ensureRemoteTerminal, hideScreens, renderSessions, renderTmuxResources, renderTarget, showSelection, selectSession, selectTmux, selectTmuxById, renderAll, refreshSessions, createTerminal, captureRemote, startCapture, stopCapture, sendCommand, sendSignal, openTmuxModal, closeTmuxModal, refreshSnapshot, attachTmux, manageTmux };
|
|
592
|
+
return { createXtermHost, fitEntry, ensureSessionTerminal, ensureRemoteTerminal, hideScreens, linkedAgentSession, isAiTerminalSession, renderSessions, renderTmuxResources, renderTarget, showSelection, selectSession, selectTmux, selectTmuxById, renderAll, refreshSessions, createTerminal, captureRemote, startCapture, stopCapture, sendCommand, sendSignal, openTmuxModal, closeTmuxModal, refreshSnapshot, attachTmux, manageTmux };
|
|
562
593
|
};
|