agentgui 1.0.9 → 1.0.11
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/acp-launcher.js +150 -205
- package/database.js +145 -96
- package/package.json +3 -3
- package/server.js +1 -1
- package/static/app.js +114 -53
- package/static/index.html +37 -36
- package/static/styles.css +27 -39
- package/install.sh +0 -147
- package/static/rippleui.css +0 -208
package/static/index.html
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>GMGUI - Chat with CLI Agents</title>
|
|
7
|
-
<
|
|
7
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
8
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/rippleui@1.12.1/dist/css/styles.css" />
|
|
8
9
|
<link rel="stylesheet" href="styles.css">
|
|
9
10
|
</head>
|
|
10
11
|
<body>
|
|
@@ -93,12 +94,12 @@
|
|
|
93
94
|
|
|
94
95
|
<div class="setting-group">
|
|
95
96
|
<label for="connectTimeout">Connection Timeout (seconds)</label>
|
|
96
|
-
<input type="number" id="connectTimeout" value="30" class="input" />
|
|
97
|
+
<input type="number" id="connectTimeout" value="30" class="gm-input" />
|
|
97
98
|
</div>
|
|
98
99
|
|
|
99
100
|
<div class="setting-group">
|
|
100
101
|
<label for="screenshotFormat">Screenshot Format</label>
|
|
101
|
-
<select id="screenshotFormat" class="input">
|
|
102
|
+
<select id="screenshotFormat" class="gm-input">
|
|
102
103
|
<option value="png">PNG</option>
|
|
103
104
|
<option value="jpg">JPEG</option>
|
|
104
105
|
</select>
|
|
@@ -108,13 +109,13 @@
|
|
|
108
109
|
</div>
|
|
109
110
|
|
|
110
111
|
<!-- Modal for new chat options -->
|
|
111
|
-
<div id="newChatModal" class="modal">
|
|
112
|
-
<div class="modal-content" style="max-width: 400px;">
|
|
113
|
-
<div class="modal-header">
|
|
112
|
+
<div id="newChatModal" class="gm-modal">
|
|
113
|
+
<div class="gm-modal-content" style="max-width: 400px;">
|
|
114
|
+
<div class="gm-modal-header">
|
|
114
115
|
<h3>New Chat</h3>
|
|
115
|
-
<button onclick="closeNewChatModal()" class="btn-close">×</button>
|
|
116
|
+
<button onclick="closeNewChatModal()" class="gm-btn-close">×</button>
|
|
116
117
|
</div>
|
|
117
|
-
<div class="modal-body" style="gap: 1rem; flex-direction: column; padding: 2rem;">
|
|
118
|
+
<div class="gm-modal-body" style="gap: 1rem; flex-direction: column; padding: 2rem;">
|
|
118
119
|
<button class="chat-option-btn" onclick="createChatInWorkspace()">
|
|
119
120
|
<span class="chat-option-icon">💬</span>
|
|
120
121
|
<div class="chat-option-content">
|
|
@@ -141,65 +142,65 @@
|
|
|
141
142
|
</div>
|
|
142
143
|
|
|
143
144
|
<!-- Modal for folder browser -->
|
|
144
|
-
<div id="folderBrowserModal" class="modal">
|
|
145
|
-
<div class="modal-content" style="max-width: 600px; height: 500px;">
|
|
146
|
-
<div class="modal-header">
|
|
145
|
+
<div id="folderBrowserModal" class="gm-modal">
|
|
146
|
+
<div class="gm-modal-content" style="max-width: 600px; height: 500px;">
|
|
147
|
+
<div class="gm-modal-header">
|
|
147
148
|
<h3>Select a Folder</h3>
|
|
148
|
-
<button class="btn-close" onclick="closeFolderBrowser()">×</button>
|
|
149
|
+
<button class="gm-btn-close" onclick="closeFolderBrowser()">×</button>
|
|
149
150
|
</div>
|
|
150
|
-
<div class="modal-body" style="flex-direction: column; gap: 0; padding: 0;">
|
|
151
|
+
<div class="gm-modal-body" style="flex-direction: column; gap: 0; padding: 0;">
|
|
151
152
|
<div style="padding: 1rem 1.5rem; border-bottom: 1px solid var(--border-color); display: flex; gap: 0.5rem; align-items: center;">
|
|
152
|
-
<input type="text" id="folderPath" class="input" placeholder="/home or ~" style="flex: 1; margin: 0;" />
|
|
153
|
-
<button onclick="browseFolders()" class="btn btn-primary" style="margin: 0;">Browse</button>
|
|
153
|
+
<input type="text" id="folderPath" class="gm-input" placeholder="/home or ~" style="flex: 1; margin: 0;" />
|
|
154
|
+
<button onclick="browseFolders()" class="gm-btn gm-btn-primary" style="margin: 0;">Browse</button>
|
|
154
155
|
</div>
|
|
155
156
|
<div id="folderBrowserList" style="flex: 1; overflow-y: auto; padding: 0; border: none;"></div>
|
|
156
157
|
</div>
|
|
157
|
-
<div class="modal-footer">
|
|
158
|
-
<button onclick="confirmFolderSelection()" class="btn btn-primary">Select</button>
|
|
159
|
-
<button onclick="closeFolderBrowser()" class="btn btn-secondary">Cancel</button>
|
|
158
|
+
<div class="gm-modal-footer">
|
|
159
|
+
<button onclick="confirmFolderSelection()" class="gm-btn gm-btn-primary">Select</button>
|
|
160
|
+
<button onclick="closeFolderBrowser()" class="gm-btn gm-btn-secondary">Cancel</button>
|
|
160
161
|
</div>
|
|
161
162
|
</div>
|
|
162
163
|
</div>
|
|
163
164
|
|
|
164
165
|
<!-- Modal for delete confirmation -->
|
|
165
|
-
<div id="deleteConfirmModal" class="modal">
|
|
166
|
-
<div class="modal-content" style="max-width: 400px;">
|
|
167
|
-
<div class="modal-header">
|
|
166
|
+
<div id="deleteConfirmModal" class="gm-modal">
|
|
167
|
+
<div class="gm-modal-content" style="max-width: 400px;">
|
|
168
|
+
<div class="gm-modal-header">
|
|
168
169
|
<h3>Delete Chat</h3>
|
|
169
|
-
<button class="btn-close" onclick="app.closeDeleteConfirmDialog()">×</button>
|
|
170
|
+
<button class="gm-btn-close" onclick="app.closeDeleteConfirmDialog()">×</button>
|
|
170
171
|
</div>
|
|
171
|
-
<div class="modal-body" style="flex-direction: column; gap: 1rem; text-align: center;">
|
|
172
|
+
<div class="gm-modal-body" style="flex-direction: column; gap: 1rem; text-align: center;">
|
|
172
173
|
<p style="margin: 0; color: var(--text-primary);">Are you sure you want to delete this chat?</p>
|
|
173
174
|
<p style="margin: 0; font-size: 0.875rem; color: var(--text-tertiary);">This action cannot be undone.</p>
|
|
174
175
|
</div>
|
|
175
|
-
<div class="modal-footer">
|
|
176
|
-
<button class="btn-confirm btn btn-danger">Delete</button>
|
|
177
|
-
<button class="btn-cancel btn btn-secondary">Cancel</button>
|
|
176
|
+
<div class="gm-modal-footer">
|
|
177
|
+
<button class="gm-btn-confirm gm-btn gm-btn-danger">Delete</button>
|
|
178
|
+
<button class="gm-btn-cancel gm-btn gm-btn-secondary">Cancel</button>
|
|
178
179
|
</div>
|
|
179
180
|
</div>
|
|
180
181
|
</div>
|
|
181
182
|
|
|
182
183
|
<!-- Modal for screenshot preview -->
|
|
183
|
-
<div id="screenshotModal" class="modal">
|
|
184
|
-
<div class="modal-content">
|
|
185
|
-
<div class="modal-header">
|
|
184
|
+
<div id="screenshotModal" class="gm-modal">
|
|
185
|
+
<div class="gm-modal-content">
|
|
186
|
+
<div class="gm-modal-header">
|
|
186
187
|
<h3>Screenshot Captured</h3>
|
|
187
|
-
<button onclick="closeScreenshotModal()" class="btn-close">×</button>
|
|
188
|
+
<button onclick="closeScreenshotModal()" class="gm-btn-close">×</button>
|
|
188
189
|
</div>
|
|
189
|
-
<div class="modal-body">
|
|
190
|
+
<div class="gm-modal-body">
|
|
190
191
|
<img id="screenshotImage" src="" alt="Screenshot" style="max-width: 100%; max-height: 60vh; border-radius: 0.5rem;" />
|
|
191
192
|
</div>
|
|
192
|
-
<div class="modal-footer">
|
|
193
|
-
<button onclick="sendScreenshot()" class="btn btn-success">Send to Agent</button>
|
|
194
|
-
<button onclick="downloadScreenshot()" class="btn btn-secondary">Download</button>
|
|
195
|
-
<button onclick="closeScreenshotModal()" class="btn btn-secondary">Close</button>
|
|
193
|
+
<div class="gm-modal-footer">
|
|
194
|
+
<button onclick="sendScreenshot()" class="gm-btn gm-btn-success">Send to Agent</button>
|
|
195
|
+
<button onclick="downloadScreenshot()" class="gm-btn gm-btn-secondary">Download</button>
|
|
196
|
+
<button onclick="closeScreenshotModal()" class="gm-btn gm-btn-secondary">Close</button>
|
|
196
197
|
</div>
|
|
197
198
|
</div>
|
|
198
199
|
</div>
|
|
199
200
|
|
|
200
201
|
<!-- Loading overlay -->
|
|
201
202
|
<div id="loadingOverlay" class="loading-overlay">
|
|
202
|
-
<div class="spinner"></div>
|
|
203
|
+
<div class="gm-spinner"></div>
|
|
203
204
|
</div>
|
|
204
205
|
|
|
205
206
|
<script src="theme.js"></script>
|
package/static/styles.css
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
margin: 0;
|
|
3
|
-
padding: 0;
|
|
1
|
+
*, *::before, *::after {
|
|
4
2
|
box-sizing: border-box;
|
|
5
3
|
}
|
|
6
4
|
|
|
@@ -594,7 +592,7 @@ html, body {
|
|
|
594
592
|
cursor: pointer;
|
|
595
593
|
}
|
|
596
594
|
|
|
597
|
-
.input {
|
|
595
|
+
.gm-input {
|
|
598
596
|
width: 100%;
|
|
599
597
|
padding: 0.75rem;
|
|
600
598
|
border: 1px solid var(--border-color);
|
|
@@ -607,7 +605,7 @@ html, body {
|
|
|
607
605
|
margin-top: 0.5rem;
|
|
608
606
|
}
|
|
609
607
|
|
|
610
|
-
.input:focus {
|
|
608
|
+
.gm-input:focus {
|
|
611
609
|
outline: none;
|
|
612
610
|
border-color: var(--color-primary);
|
|
613
611
|
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
|
|
@@ -619,6 +617,7 @@ html, body {
|
|
|
619
617
|
flex-wrap: wrap;
|
|
620
618
|
gap: 1rem;
|
|
621
619
|
animation: slideUp 0.2s ease;
|
|
620
|
+
width: 100%;
|
|
622
621
|
}
|
|
623
622
|
|
|
624
623
|
.message-bubble {
|
|
@@ -627,6 +626,7 @@ html, body {
|
|
|
627
626
|
padding: 0.75rem 1rem;
|
|
628
627
|
border-radius: 0.5rem;
|
|
629
628
|
word-wrap: break-word;
|
|
629
|
+
white-space: pre-wrap;
|
|
630
630
|
}
|
|
631
631
|
|
|
632
632
|
.message.user .message-bubble {
|
|
@@ -819,9 +819,9 @@ html, body {
|
|
|
819
819
|
flex: 0 1 100%;
|
|
820
820
|
border: 1px solid var(--border-color);
|
|
821
821
|
border-radius: 0.5rem;
|
|
822
|
-
overflow:
|
|
822
|
+
overflow: visible;
|
|
823
823
|
background: var(--bg-secondary);
|
|
824
|
-
max-width:
|
|
824
|
+
max-width: 100%;
|
|
825
825
|
}
|
|
826
826
|
|
|
827
827
|
.html-header {
|
|
@@ -835,22 +835,10 @@ html, body {
|
|
|
835
835
|
|
|
836
836
|
.html-content {
|
|
837
837
|
padding: 0.75rem;
|
|
838
|
-
font-size: 0.9rem;
|
|
839
|
-
color: var(--text-primary);
|
|
840
838
|
overflow-x: auto;
|
|
841
839
|
}
|
|
842
840
|
|
|
843
|
-
.html-content > * {
|
|
844
|
-
margin: 0.5rem 0;
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
.html-content > *:first-child {
|
|
848
|
-
margin-top: 0;
|
|
849
|
-
}
|
|
850
841
|
|
|
851
|
-
.html-content > *:last-child {
|
|
852
|
-
margin-bottom: 0;
|
|
853
|
-
}
|
|
854
842
|
|
|
855
843
|
.image-block {
|
|
856
844
|
flex: 0 1 100%;
|
|
@@ -938,7 +926,7 @@ html, body {
|
|
|
938
926
|
}
|
|
939
927
|
|
|
940
928
|
/* Modal */
|
|
941
|
-
.modal {
|
|
929
|
+
.gm-modal {
|
|
942
930
|
display: none;
|
|
943
931
|
position: fixed;
|
|
944
932
|
inset: 0;
|
|
@@ -971,11 +959,11 @@ html, body {
|
|
|
971
959
|
}
|
|
972
960
|
}
|
|
973
961
|
|
|
974
|
-
.modal.active {
|
|
962
|
+
.gm-modal.active {
|
|
975
963
|
display: flex;
|
|
976
964
|
}
|
|
977
965
|
|
|
978
|
-
.modal-content {
|
|
966
|
+
.gm-modal-content {
|
|
979
967
|
background: var(--bg-primary);
|
|
980
968
|
border-radius: 0.75rem;
|
|
981
969
|
box-shadow: var(--shadow-xl);
|
|
@@ -988,7 +976,7 @@ html, body {
|
|
|
988
976
|
transition: var(--transition-smooth);
|
|
989
977
|
}
|
|
990
978
|
|
|
991
|
-
.modal-header {
|
|
979
|
+
.gm-modal-header {
|
|
992
980
|
padding: 1.5rem;
|
|
993
981
|
border-bottom: 1px solid var(--border-color);
|
|
994
982
|
display: flex;
|
|
@@ -996,12 +984,12 @@ html, body {
|
|
|
996
984
|
align-items: center;
|
|
997
985
|
}
|
|
998
986
|
|
|
999
|
-
.modal-header h3 {
|
|
987
|
+
.gm-modal-header h3 {
|
|
1000
988
|
margin: 0;
|
|
1001
989
|
color: var(--text-primary);
|
|
1002
990
|
}
|
|
1003
991
|
|
|
1004
|
-
.modal-body {
|
|
992
|
+
.gm-modal-body {
|
|
1005
993
|
padding: 1.5rem;
|
|
1006
994
|
overflow-y: auto;
|
|
1007
995
|
flex: 1;
|
|
@@ -1010,7 +998,7 @@ html, body {
|
|
|
1010
998
|
justify-content: center;
|
|
1011
999
|
}
|
|
1012
1000
|
|
|
1013
|
-
.modal-footer {
|
|
1001
|
+
.gm-modal-footer {
|
|
1014
1002
|
padding: 1rem 1.5rem;
|
|
1015
1003
|
border-top: 1px solid var(--border-color);
|
|
1016
1004
|
display: flex;
|
|
@@ -1069,7 +1057,7 @@ html, body {
|
|
|
1069
1057
|
color: var(--text-tertiary);
|
|
1070
1058
|
}
|
|
1071
1059
|
|
|
1072
|
-
.btn {
|
|
1060
|
+
.gm-btn {
|
|
1073
1061
|
padding: 0.625rem 1rem;
|
|
1074
1062
|
border: none;
|
|
1075
1063
|
border-radius: 0.5rem;
|
|
@@ -1083,47 +1071,47 @@ html, body {
|
|
|
1083
1071
|
white-space: nowrap;
|
|
1084
1072
|
}
|
|
1085
1073
|
|
|
1086
|
-
.btn-primary {
|
|
1074
|
+
.gm-btn-primary {
|
|
1087
1075
|
background: var(--color-primary);
|
|
1088
1076
|
color: white;
|
|
1089
1077
|
}
|
|
1090
1078
|
|
|
1091
|
-
.btn-primary:hover {
|
|
1079
|
+
.gm-btn-primary:hover {
|
|
1092
1080
|
background: var(--color-primary-light);
|
|
1093
1081
|
transform: translateY(-1px);
|
|
1094
1082
|
}
|
|
1095
1083
|
|
|
1096
|
-
.btn-success {
|
|
1084
|
+
.gm-btn-success {
|
|
1097
1085
|
background: var(--color-success);
|
|
1098
1086
|
color: white;
|
|
1099
1087
|
}
|
|
1100
1088
|
|
|
1101
|
-
.btn-success:hover {
|
|
1089
|
+
.gm-btn-success:hover {
|
|
1102
1090
|
background: #059669;
|
|
1103
1091
|
transform: translateY(-1px);
|
|
1104
1092
|
}
|
|
1105
1093
|
|
|
1106
|
-
.btn-secondary {
|
|
1094
|
+
.gm-btn-secondary {
|
|
1107
1095
|
background: var(--bg-tertiary);
|
|
1108
1096
|
color: var(--text-primary);
|
|
1109
1097
|
border: 1px solid var(--border-color);
|
|
1110
1098
|
}
|
|
1111
1099
|
|
|
1112
|
-
.btn-secondary:hover {
|
|
1100
|
+
.gm-btn-secondary:hover {
|
|
1113
1101
|
background: var(--border-color);
|
|
1114
1102
|
}
|
|
1115
1103
|
|
|
1116
|
-
.btn-danger {
|
|
1104
|
+
.gm-btn-danger {
|
|
1117
1105
|
background: var(--color-danger);
|
|
1118
1106
|
color: white;
|
|
1119
1107
|
}
|
|
1120
1108
|
|
|
1121
|
-
.btn-danger:hover {
|
|
1109
|
+
.gm-btn-danger:hover {
|
|
1122
1110
|
background: #dc2626;
|
|
1123
1111
|
transform: translateY(-1px);
|
|
1124
1112
|
}
|
|
1125
1113
|
|
|
1126
|
-
.btn-close {
|
|
1114
|
+
.gm-btn-close {
|
|
1127
1115
|
background: none;
|
|
1128
1116
|
border: none;
|
|
1129
1117
|
font-size: 2rem;
|
|
@@ -1138,7 +1126,7 @@ html, body {
|
|
|
1138
1126
|
transition: var(--transition-fast);
|
|
1139
1127
|
}
|
|
1140
1128
|
|
|
1141
|
-
.btn-close:hover {
|
|
1129
|
+
.gm-btn-close:hover {
|
|
1142
1130
|
color: var(--text-primary);
|
|
1143
1131
|
}
|
|
1144
1132
|
|
|
@@ -1157,7 +1145,7 @@ html, body {
|
|
|
1157
1145
|
display: flex;
|
|
1158
1146
|
}
|
|
1159
1147
|
|
|
1160
|
-
.spinner {
|
|
1148
|
+
.gm-spinner {
|
|
1161
1149
|
width: 48px;
|
|
1162
1150
|
height: 48px;
|
|
1163
1151
|
border: 4px solid rgba(255, 255, 255, 0.3);
|
|
@@ -1420,7 +1408,7 @@ html, body {
|
|
|
1420
1408
|
.sidebar,
|
|
1421
1409
|
.chat-input-section,
|
|
1422
1410
|
.chat-footer,
|
|
1423
|
-
.modal,
|
|
1411
|
+
.gm-modal,
|
|
1424
1412
|
.loading-overlay {
|
|
1425
1413
|
display: none;
|
|
1426
1414
|
}
|
package/install.sh
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
# GMGUI Installation Script
|
|
5
|
-
# Robust, error-handled installation with proper cleanup
|
|
6
|
-
|
|
7
|
-
# Enable error handling and cleanup
|
|
8
|
-
TMPDIR=""
|
|
9
|
-
EXIT_CODE=0
|
|
10
|
-
|
|
11
|
-
cleanup() {
|
|
12
|
-
local code=$?
|
|
13
|
-
if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then
|
|
14
|
-
rm -rf "$TMPDIR" 2>/dev/null || true
|
|
15
|
-
fi
|
|
16
|
-
if [ $code -ne 0 ] && [ $code -ne 130 ]; then
|
|
17
|
-
echo "Error: Installation failed. Check messages above." >&2
|
|
18
|
-
fi
|
|
19
|
-
exit $code
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
# Handle interrupts gracefully
|
|
23
|
-
handle_interrupt() {
|
|
24
|
-
echo ""
|
|
25
|
-
echo "Installation interrupted. Cleaning up..." >&2
|
|
26
|
-
exit 130
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
trap cleanup EXIT
|
|
30
|
-
trap handle_interrupt SIGINT SIGTERM
|
|
31
|
-
|
|
32
|
-
# Detect runtime (prefer bun, fall back to node)
|
|
33
|
-
RUNTIME=""
|
|
34
|
-
if command -v bun &> /dev/null; then
|
|
35
|
-
RUNTIME=bun
|
|
36
|
-
elif command -v node &> /dev/null; then
|
|
37
|
-
RUNTIME=node
|
|
38
|
-
else
|
|
39
|
-
echo "Error: Neither bun nor node is installed." >&2
|
|
40
|
-
echo "Install one with:" >&2
|
|
41
|
-
echo " • Bun (recommended, 3-4x faster):" >&2
|
|
42
|
-
echo " curl -fsSL https://bun.sh/install | bash" >&2
|
|
43
|
-
echo " • Node.js:" >&2
|
|
44
|
-
echo " curl https://nodejs.org/en/download/" >&2
|
|
45
|
-
exit 1
|
|
46
|
-
fi
|
|
47
|
-
|
|
48
|
-
# Verify curl or wget is available
|
|
49
|
-
if ! command -v curl &> /dev/null && ! command -v wget &> /dev/null; then
|
|
50
|
-
echo "Error: Neither curl nor wget found. Install one to download gmgui." >&2
|
|
51
|
-
exit 1
|
|
52
|
-
fi
|
|
53
|
-
|
|
54
|
-
# Create temp directory with secure permissions
|
|
55
|
-
TMPDIR=$(mktemp -d) || {
|
|
56
|
-
echo "Error: Could not create temporary directory." >&2
|
|
57
|
-
exit 1
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
# Verify we have write access to temp directory
|
|
61
|
-
if ! [ -w "$TMPDIR" ]; then
|
|
62
|
-
echo "Error: No write permission to temporary directory." >&2
|
|
63
|
-
exit 1
|
|
64
|
-
fi
|
|
65
|
-
|
|
66
|
-
# Check disk space (need at least 200MB)
|
|
67
|
-
AVAILABLE_KB=$(df "$TMPDIR" 2>/dev/null | tail -1 | awk '{print $4}' || echo 0)
|
|
68
|
-
if [ "$AVAILABLE_KB" -lt 200000 ]; then
|
|
69
|
-
echo "Warning: Low disk space. At least 200MB recommended." >&2
|
|
70
|
-
fi
|
|
71
|
-
|
|
72
|
-
echo "Downloading gmgui from GitHub..."
|
|
73
|
-
cd "$TMPDIR"
|
|
74
|
-
|
|
75
|
-
# Use git if available, otherwise use curl/wget to download tarball
|
|
76
|
-
if command -v git &> /dev/null; then
|
|
77
|
-
# Git clone with error handling
|
|
78
|
-
if ! git clone --depth=1 https://github.com/AnEntrypoint/gmgui.git . 2>&1 | grep -v "^Cloning"; then
|
|
79
|
-
echo "Warning: Git clone failed, trying tarball download..." >&2
|
|
80
|
-
# Fallback to tarball
|
|
81
|
-
if command -v curl &> /dev/null; then
|
|
82
|
-
curl -fsSL https://github.com/AnEntrypoint/gmgui/archive/refs/heads/main.tar.gz | tar xz --strip-components=1 || {
|
|
83
|
-
echo "Error: Could not download gmgui from GitHub." >&2
|
|
84
|
-
exit 1
|
|
85
|
-
}
|
|
86
|
-
else
|
|
87
|
-
wget -qO- https://github.com/AnEntrypoint/gmgui/archive/refs/heads/main.tar.gz | tar xz --strip-components=1 || {
|
|
88
|
-
echo "Error: Could not download gmgui from GitHub." >&2
|
|
89
|
-
exit 1
|
|
90
|
-
}
|
|
91
|
-
fi
|
|
92
|
-
fi
|
|
93
|
-
else
|
|
94
|
-
echo "Downloading tarball (git not available)..."
|
|
95
|
-
# Download tarball with curl or wget
|
|
96
|
-
if command -v curl &> /dev/null; then
|
|
97
|
-
curl -fsSL https://github.com/AnEntrypoint/gmgui/archive/refs/heads/main.tar.gz | tar xz --strip-components=1 || {
|
|
98
|
-
echo "Error: Could not download gmgui from GitHub." >&2
|
|
99
|
-
exit 1
|
|
100
|
-
}
|
|
101
|
-
else
|
|
102
|
-
wget -qO- https://github.com/AnEntrypoint/gmgui/archive/refs/heads/main.tar.gz | tar xz --strip-components=1 || {
|
|
103
|
-
echo "Error: Could not download gmgui from GitHub." >&2
|
|
104
|
-
exit 1
|
|
105
|
-
}
|
|
106
|
-
fi
|
|
107
|
-
fi
|
|
108
|
-
|
|
109
|
-
# Verify essential files were downloaded
|
|
110
|
-
if [ ! -f server.js ] || [ ! -f package.json ]; then
|
|
111
|
-
echo "Error: Downloaded files appear corrupted. Missing server.js or package.json." >&2
|
|
112
|
-
exit 1
|
|
113
|
-
fi
|
|
114
|
-
|
|
115
|
-
echo "Installing dependencies with $RUNTIME..."
|
|
116
|
-
if [ "$RUNTIME" = "bun" ]; then
|
|
117
|
-
if ! bun install --frozen-lockfile 2>&1 | grep -E "added|removed|found|vulnerabilities" | tail -1; then
|
|
118
|
-
# Warn but don't fail if grep doesn't match
|
|
119
|
-
bun install --frozen-lockfile 2>&1 | tail -3
|
|
120
|
-
fi
|
|
121
|
-
else
|
|
122
|
-
if ! npm install 2>&1 | grep -E "added|removed|found|vulnerabilities" | tail -1; then
|
|
123
|
-
# Warn but don't fail if grep doesn't match
|
|
124
|
-
npm install 2>&1 | tail -3
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
|
-
# For Node.js, install better-sqlite3 if not already present
|
|
128
|
-
echo "Installing better-sqlite3 for Node.js..."
|
|
129
|
-
if ! npm install better-sqlite3 2>&1 | grep -E "added|removed|found|vulnerabilities" | tail -1; then
|
|
130
|
-
# Warn but don't fail - may already be installed
|
|
131
|
-
echo "Note: better-sqlite3 installation completed." >&2
|
|
132
|
-
fi
|
|
133
|
-
fi
|
|
134
|
-
|
|
135
|
-
echo ""
|
|
136
|
-
echo "✓ Installation complete!"
|
|
137
|
-
echo ""
|
|
138
|
-
echo "Starting gmgui server on http://localhost:3000"
|
|
139
|
-
echo "Press Ctrl+C to stop"
|
|
140
|
-
echo ""
|
|
141
|
-
|
|
142
|
-
# Start server with proper error handling
|
|
143
|
-
if [ "$RUNTIME" = "bun" ]; then
|
|
144
|
-
exec bun run server.js
|
|
145
|
-
else
|
|
146
|
-
exec node server.js
|
|
147
|
-
fi
|