agentgui 1.0.199 → 1.0.200
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/package.json +1 -1
- package/server.js +141 -0
- package/static/index.html +7 -2
- package/static/js/agent-auth.js +113 -79
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -180,6 +180,120 @@ function discoverAgents() {
|
|
|
180
180
|
|
|
181
181
|
const discoveredAgents = discoverAgents();
|
|
182
182
|
|
|
183
|
+
const PROVIDER_CONFIGS = {
|
|
184
|
+
'anthropic': {
|
|
185
|
+
name: 'Anthropic', configPaths: [
|
|
186
|
+
path.join(os.homedir(), '.claude.json'),
|
|
187
|
+
path.join(os.homedir(), '.config', 'claude', 'settings.json'),
|
|
188
|
+
path.join(os.homedir(), '.anthropic.json')
|
|
189
|
+
],
|
|
190
|
+
configFormat: (apiKey, model) => ({ api_key: apiKey, default_model: model })
|
|
191
|
+
},
|
|
192
|
+
'openai': {
|
|
193
|
+
name: 'OpenAI', configPaths: [
|
|
194
|
+
path.join(os.homedir(), '.openai.json'),
|
|
195
|
+
path.join(os.homedir(), '.config', 'openai', 'api-key')
|
|
196
|
+
],
|
|
197
|
+
configFormat: (apiKey, model) => ({ apiKey, defaultModel: model })
|
|
198
|
+
},
|
|
199
|
+
'google': {
|
|
200
|
+
name: 'Google Gemini', configPaths: [
|
|
201
|
+
path.join(os.homedir(), '.gemini.json'),
|
|
202
|
+
path.join(os.homedir(), '.config', 'gemini', 'credentials.json')
|
|
203
|
+
],
|
|
204
|
+
configFormat: (apiKey, model) => ({ api_key: apiKey, default_model: model })
|
|
205
|
+
},
|
|
206
|
+
'openrouter': {
|
|
207
|
+
name: 'OpenRouter', configPaths: [
|
|
208
|
+
path.join(os.homedir(), '.openrouter.json'),
|
|
209
|
+
path.join(os.homedir(), '.config', 'openrouter', 'config.json')
|
|
210
|
+
],
|
|
211
|
+
configFormat: (apiKey, model) => ({ api_key: apiKey, default_model: model })
|
|
212
|
+
},
|
|
213
|
+
'github': {
|
|
214
|
+
name: 'GitHub Models', configPaths: [
|
|
215
|
+
path.join(os.homedir(), '.github.json'),
|
|
216
|
+
path.join(os.homedir(), '.config', 'github-copilot.json')
|
|
217
|
+
],
|
|
218
|
+
configFormat: (apiKey, model) => ({ github_token: apiKey, default_model: model })
|
|
219
|
+
},
|
|
220
|
+
'azure': {
|
|
221
|
+
name: 'Azure OpenAI', configPaths: [
|
|
222
|
+
path.join(os.homedir(), '.azure.json'),
|
|
223
|
+
path.join(os.homedir(), '.config', 'azure-openai', 'config.json')
|
|
224
|
+
],
|
|
225
|
+
configFormat: (apiKey, model) => ({ api_key: apiKey, endpoint: '', default_model: model })
|
|
226
|
+
},
|
|
227
|
+
'anthropic-claude-code': {
|
|
228
|
+
name: 'Claude Code Max', configPaths: [
|
|
229
|
+
path.join(os.homedir(), '.claude', 'max.json'),
|
|
230
|
+
path.join(os.homedir(), '.config', 'claude-code', 'max.json')
|
|
231
|
+
],
|
|
232
|
+
configFormat: (apiKey, model) => ({ api_key: apiKey, plan: 'max', default_model: model })
|
|
233
|
+
},
|
|
234
|
+
'opencode': {
|
|
235
|
+
name: 'OpenCode', configPaths: [
|
|
236
|
+
path.join(os.homedir(), '.opencode', 'config.json'),
|
|
237
|
+
path.join(os.homedir(), '.config', 'opencode', 'config.json')
|
|
238
|
+
],
|
|
239
|
+
configFormat: (apiKey, model) => ({ api_key: apiKey, default_model: model, providers: ['anthropic', 'openai', 'google'] })
|
|
240
|
+
},
|
|
241
|
+
'proxypilot': {
|
|
242
|
+
name: 'ProxyPilot', configPaths: [
|
|
243
|
+
path.join(os.homedir(), '.proxypilot', 'config.json'),
|
|
244
|
+
path.join(os.homedir(), '.config', 'proxypilot', 'config.json')
|
|
245
|
+
],
|
|
246
|
+
configFormat: (apiKey, model) => ({ api_key: apiKey, default_model: model })
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
function maskKey(key) {
|
|
251
|
+
if (!key || key.length < 8) return '****';
|
|
252
|
+
return '****' + key.slice(-4);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function getProviderConfigs() {
|
|
256
|
+
const configs = {};
|
|
257
|
+
for (const [providerId, config] of Object.entries(PROVIDER_CONFIGS)) {
|
|
258
|
+
for (const configPath of config.configPaths) {
|
|
259
|
+
try {
|
|
260
|
+
if (fs.existsSync(configPath)) {
|
|
261
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
262
|
+
const parsed = JSON.parse(content);
|
|
263
|
+
const rawKey = parsed.api_key || parsed.apiKey || parsed.github_token || '';
|
|
264
|
+
configs[providerId] = {
|
|
265
|
+
name: config.name,
|
|
266
|
+
apiKey: maskKey(rawKey),
|
|
267
|
+
hasKey: !!rawKey,
|
|
268
|
+
defaultModel: parsed.default_model || parsed.defaultModel || '',
|
|
269
|
+
path: configPath
|
|
270
|
+
};
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
} catch (_) {}
|
|
274
|
+
}
|
|
275
|
+
if (!configs[providerId]) {
|
|
276
|
+
configs[providerId] = { name: config.name, apiKey: '', hasKey: false, defaultModel: '', path: '' };
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return configs;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function saveProviderConfig(providerId, apiKey, defaultModel) {
|
|
283
|
+
const config = PROVIDER_CONFIGS[providerId];
|
|
284
|
+
if (!config) throw new Error('Unknown provider: ' + providerId);
|
|
285
|
+
const configPath = config.configPaths[0];
|
|
286
|
+
const configDir = path.dirname(configPath);
|
|
287
|
+
if (!fs.existsSync(configDir)) fs.mkdirSync(configDir, { recursive: true });
|
|
288
|
+
let existing = {};
|
|
289
|
+
try {
|
|
290
|
+
if (fs.existsSync(configPath)) existing = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
291
|
+
} catch (_) {}
|
|
292
|
+
const merged = { ...existing, ...config.configFormat(apiKey, defaultModel) };
|
|
293
|
+
fs.writeFileSync(configPath, JSON.stringify(merged, null, 2), { mode: 0o600 });
|
|
294
|
+
return configPath;
|
|
295
|
+
}
|
|
296
|
+
|
|
183
297
|
function parseBody(req) {
|
|
184
298
|
return new Promise((resolve, reject) => {
|
|
185
299
|
let body = '';
|
|
@@ -755,6 +869,33 @@ const server = http.createServer(async (req, res) => {
|
|
|
755
869
|
return;
|
|
756
870
|
}
|
|
757
871
|
|
|
872
|
+
if (pathOnly === '/api/auth/configs' && req.method === 'GET') {
|
|
873
|
+
const configs = getProviderConfigs();
|
|
874
|
+
sendJSON(req, res, 200, configs);
|
|
875
|
+
return;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
if (pathOnly === '/api/auth/save-config' && req.method === 'POST') {
|
|
879
|
+
try {
|
|
880
|
+
const body = await parseBody(req);
|
|
881
|
+
const { providerId, apiKey, defaultModel } = body || {};
|
|
882
|
+
if (typeof providerId !== 'string' || !providerId.length || providerId.length > 100) {
|
|
883
|
+
sendJSON(req, res, 400, { error: 'Invalid providerId' }); return;
|
|
884
|
+
}
|
|
885
|
+
if (typeof apiKey !== 'string' || !apiKey.length || apiKey.length > 10000) {
|
|
886
|
+
sendJSON(req, res, 400, { error: 'Invalid apiKey' }); return;
|
|
887
|
+
}
|
|
888
|
+
if (defaultModel !== undefined && (typeof defaultModel !== 'string' || defaultModel.length > 200)) {
|
|
889
|
+
sendJSON(req, res, 400, { error: 'Invalid defaultModel' }); return;
|
|
890
|
+
}
|
|
891
|
+
const configPath = saveProviderConfig(providerId, apiKey, defaultModel || '');
|
|
892
|
+
sendJSON(req, res, 200, { success: true, path: configPath });
|
|
893
|
+
} catch (err) {
|
|
894
|
+
sendJSON(req, res, 400, { error: err.message });
|
|
895
|
+
}
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
|
|
758
899
|
if (pathOnly === '/api/import/claude-code' && req.method === 'GET') {
|
|
759
900
|
const result = queries.importClaudeCodeConversations();
|
|
760
901
|
sendJSON(req, res, 200, { imported: result });
|
package/static/index.html
CHANGED
|
@@ -452,7 +452,7 @@
|
|
|
452
452
|
transition: background-color 0.15s, color 0.15s;
|
|
453
453
|
}
|
|
454
454
|
.header-icon-btn:hover { background-color: var(--color-bg-primary); color: var(--color-text-primary); }
|
|
455
|
-
.header-icon-btn svg { width:
|
|
455
|
+
.header-icon-btn svg { width: 20px; height: 20px; }
|
|
456
456
|
#scriptStartBtn { color: var(--color-success); }
|
|
457
457
|
#scriptStartBtn:hover { background-color: rgba(16,185,129,0.1); color: var(--color-success); }
|
|
458
458
|
.script-dev-btn { color: var(--color-info); }
|
|
@@ -466,7 +466,7 @@
|
|
|
466
466
|
.agent-auth-btn:hover { background-color: var(--color-bg-primary); }
|
|
467
467
|
.agent-auth-dropdown {
|
|
468
468
|
position: absolute; top: 100%; right: 0; z-index: 100;
|
|
469
|
-
min-width:
|
|
469
|
+
min-width: 260px; padding: 0.25rem 0;
|
|
470
470
|
background: var(--color-bg-secondary); border: 1px solid var(--color-border);
|
|
471
471
|
border-radius: 0.5rem; box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
472
472
|
display: none;
|
|
@@ -485,6 +485,11 @@
|
|
|
485
485
|
.agent-auth-dot.ok { background: var(--color-success); }
|
|
486
486
|
.agent-auth-dot.missing { background: var(--color-warning); }
|
|
487
487
|
.agent-auth-dot.unknown { background: var(--color-text-secondary); }
|
|
488
|
+
.agent-auth-section-header {
|
|
489
|
+
padding: 0.375rem 0.75rem; font-size: 0.6875rem; font-weight: 600;
|
|
490
|
+
text-transform: uppercase; letter-spacing: 0.05em;
|
|
491
|
+
color: var(--color-text-secondary); user-select: none;
|
|
492
|
+
}
|
|
488
493
|
|
|
489
494
|
.terminal-container {
|
|
490
495
|
flex: 1; display: flex; flex-direction: column; overflow: hidden; background: #1e1e1e;
|
package/static/js/agent-auth.js
CHANGED
|
@@ -2,103 +2,154 @@
|
|
|
2
2
|
var BASE = window.__BASE_URL || '';
|
|
3
3
|
var btn = document.getElementById('agentAuthBtn');
|
|
4
4
|
var dropdown = document.getElementById('agentAuthDropdown');
|
|
5
|
-
var agents = [];
|
|
6
|
-
var authRunning = false;
|
|
5
|
+
var agents = [], providers = {}, authRunning = false, editingProvider = null;
|
|
7
6
|
var AUTH_CONV_ID = '__agent_auth__';
|
|
8
7
|
|
|
9
8
|
function init() {
|
|
10
9
|
if (!btn || !dropdown) return;
|
|
10
|
+
btn.style.display = 'flex';
|
|
11
11
|
btn.addEventListener('click', toggleDropdown);
|
|
12
12
|
document.addEventListener('click', function(e) {
|
|
13
|
-
if (!btn.contains(e.target)) closeDropdown();
|
|
13
|
+
if (!btn.contains(e.target) && !dropdown.contains(e.target)) closeDropdown();
|
|
14
14
|
});
|
|
15
|
-
window.addEventListener('conversation-selected', function() {
|
|
15
|
+
window.addEventListener('conversation-selected', function() { refresh(); });
|
|
16
16
|
window.addEventListener('ws-message', onWsMessage);
|
|
17
|
-
|
|
17
|
+
refresh();
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
function refresh() { fetchAuthStatus(); fetchProviderConfigs(); }
|
|
21
|
+
|
|
20
22
|
function fetchAuthStatus() {
|
|
21
|
-
fetch(BASE + '/api/agents/auth-status')
|
|
22
|
-
.then(function(
|
|
23
|
-
.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
fetch(BASE + '/api/agents/auth-status').then(function(r) { return r.json(); })
|
|
24
|
+
.then(function(data) { agents = data.agents || []; updateButton(); renderDropdown(); })
|
|
25
|
+
.catch(function() {});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function fetchProviderConfigs() {
|
|
29
|
+
fetch(BASE + '/api/auth/configs').then(function(r) { return r.json(); })
|
|
30
|
+
.then(function(data) { providers = data || {}; updateButton(); renderDropdown(); })
|
|
28
31
|
.catch(function() {});
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
function updateButton() {
|
|
32
|
-
if (agents.length === 0) { btn.style.display = 'none'; return; }
|
|
33
35
|
btn.style.display = 'flex';
|
|
34
|
-
var
|
|
35
|
-
var
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
var agentOk = agents.length === 0 || agents.every(function(a) { return a.authenticated; });
|
|
37
|
+
var pkeys = Object.keys(providers);
|
|
38
|
+
var provOk = pkeys.length === 0 || pkeys.some(function(k) { return providers[k].hasKey; });
|
|
39
|
+
var anyWarn = agents.some(function(a) { return !a.authenticated; }) ||
|
|
40
|
+
pkeys.some(function(k) { return !providers[k].hasKey; });
|
|
41
|
+
btn.classList.toggle('auth-ok', agentOk && provOk && (agents.length > 0 || pkeys.length > 0));
|
|
42
|
+
btn.classList.toggle('auth-warn', anyWarn);
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
function renderDropdown() {
|
|
41
46
|
dropdown.innerHTML = '';
|
|
42
|
-
agents.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
'
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
if (agents.length > 0) {
|
|
48
|
+
appendHeader('Agent CLI Auth');
|
|
49
|
+
agents.forEach(function(agent) {
|
|
50
|
+
var dotClass = agent.authenticated ? 'ok' : (agent.detail === 'unknown' ? 'unknown' : 'missing');
|
|
51
|
+
var item = makeItem(dotClass, agent.name, agent.detail);
|
|
52
|
+
item.addEventListener('click', function(e) { e.stopPropagation(); closeDropdown(); triggerAuth(agent.id); });
|
|
53
|
+
dropdown.appendChild(item);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
var pkeys = Object.keys(providers);
|
|
57
|
+
if (pkeys.length > 0) {
|
|
58
|
+
if (agents.length > 0) appendSep();
|
|
59
|
+
appendHeader('Provider Keys');
|
|
60
|
+
pkeys.forEach(function(pid) {
|
|
61
|
+
var p = providers[pid];
|
|
62
|
+
var item = makeItem(p.hasKey ? 'ok' : 'missing', p.name || pid, p.hasKey ? p.apiKey : 'not set');
|
|
63
|
+
item.style.flexWrap = 'wrap';
|
|
64
|
+
item.addEventListener('click', function(e) { e.stopPropagation(); toggleEdit(pid); });
|
|
65
|
+
dropdown.appendChild(item);
|
|
66
|
+
if (editingProvider === pid) dropdown.appendChild(makeEditForm(pid));
|
|
53
67
|
});
|
|
54
|
-
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function appendHeader(text) {
|
|
72
|
+
var h = document.createElement('div');
|
|
73
|
+
h.className = 'agent-auth-section-header';
|
|
74
|
+
h.textContent = text;
|
|
75
|
+
dropdown.appendChild(h);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function appendSep() {
|
|
79
|
+
var s = document.createElement('div');
|
|
80
|
+
s.style.cssText = 'height:1px;background:var(--color-border);margin:0.25rem 0;';
|
|
81
|
+
dropdown.appendChild(s);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function makeItem(dotClass, name, detail) {
|
|
85
|
+
var el = document.createElement('button');
|
|
86
|
+
el.className = 'agent-auth-item';
|
|
87
|
+
el.innerHTML = '<span class="agent-auth-dot ' + dotClass + '"></span><span>' + esc(name) +
|
|
88
|
+
'</span><span style="margin-left:auto;font-size:0.7rem;color:var(--color-text-secondary)">' + esc(detail) + '</span>';
|
|
89
|
+
return el;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function makeEditForm(pid) {
|
|
93
|
+
var form = document.createElement('div');
|
|
94
|
+
form.style.cssText = 'width:100%;padding:0.375rem 0.75rem;display:flex;gap:0.375rem;';
|
|
95
|
+
var input = document.createElement('input');
|
|
96
|
+
input.type = 'password'; input.placeholder = 'API key';
|
|
97
|
+
input.style.cssText = 'flex:1;min-width:0;padding:0.25rem 0.5rem;font-size:0.75rem;border:1px solid var(--color-border);border-radius:0.25rem;background:var(--color-bg-primary);color:var(--color-text-primary);outline:none;';
|
|
98
|
+
input.addEventListener('click', function(e) { e.stopPropagation(); });
|
|
99
|
+
var saveBtn = document.createElement('button');
|
|
100
|
+
saveBtn.textContent = 'Save';
|
|
101
|
+
saveBtn.style.cssText = 'padding:0.25rem 0.5rem;font-size:0.7rem;font-weight:600;background:var(--color-primary);color:white;border:none;border-radius:0.25rem;cursor:pointer;flex-shrink:0;';
|
|
102
|
+
saveBtn.addEventListener('click', function(e) {
|
|
103
|
+
e.stopPropagation();
|
|
104
|
+
var key = input.value.trim();
|
|
105
|
+
if (!key) return;
|
|
106
|
+
saveBtn.disabled = true; saveBtn.textContent = '...';
|
|
107
|
+
saveProviderKey(pid, key);
|
|
55
108
|
});
|
|
109
|
+
form.appendChild(input); form.appendChild(saveBtn);
|
|
110
|
+
setTimeout(function() { input.focus(); }, 50);
|
|
111
|
+
return form;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function toggleEdit(pid) { editingProvider = editingProvider === pid ? null : pid; renderDropdown(); }
|
|
115
|
+
|
|
116
|
+
function saveProviderKey(providerId, apiKey) {
|
|
117
|
+
fetch(BASE + '/api/auth/save-config', {
|
|
118
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
119
|
+
body: JSON.stringify({ providerId: providerId, apiKey: apiKey, defaultModel: '' })
|
|
120
|
+
}).then(function(r) { return r.json(); }).then(function(data) {
|
|
121
|
+
if (data.success) { editingProvider = null; fetchProviderConfigs(); }
|
|
122
|
+
}).catch(function() { editingProvider = null; renderDropdown(); });
|
|
56
123
|
}
|
|
57
124
|
|
|
58
125
|
function toggleDropdown(e) {
|
|
59
126
|
e.stopPropagation();
|
|
127
|
+
if (!dropdown.classList.contains('open')) { editingProvider = null; refresh(); }
|
|
60
128
|
dropdown.classList.toggle('open');
|
|
61
129
|
}
|
|
62
130
|
|
|
63
|
-
function closeDropdown() {
|
|
64
|
-
dropdown.classList.remove('open');
|
|
65
|
-
}
|
|
131
|
+
function closeDropdown() { dropdown.classList.remove('open'); editingProvider = null; }
|
|
66
132
|
|
|
67
133
|
function triggerAuth(agentId) {
|
|
68
134
|
if (authRunning) return;
|
|
69
135
|
fetch(BASE + '/api/agents/' + agentId + '/auth', {
|
|
70
|
-
method: 'POST',
|
|
71
|
-
|
|
72
|
-
body: '{}'
|
|
73
|
-
})
|
|
74
|
-
.then(function(r) { return r.json(); })
|
|
75
|
-
.then(function(data) {
|
|
136
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}'
|
|
137
|
+
}).then(function(r) { return r.json(); }).then(function(data) {
|
|
76
138
|
if (data.ok) {
|
|
77
|
-
authRunning = true;
|
|
78
|
-
showTerminalTab();
|
|
79
|
-
switchToTerminalView();
|
|
139
|
+
authRunning = true; showTerminalTab(); switchToTerminalView();
|
|
80
140
|
var term = getTerminal();
|
|
81
|
-
if (term) {
|
|
82
|
-
term.clear();
|
|
83
|
-
term.writeln('\x1b[36m[authenticating ' + agentId + ']\x1b[0m\r\n');
|
|
84
|
-
}
|
|
141
|
+
if (term) { term.clear(); term.writeln('\x1b[36m[authenticating ' + agentId + ']\x1b[0m\r\n'); }
|
|
85
142
|
}
|
|
86
|
-
})
|
|
87
|
-
.catch(function() {});
|
|
143
|
+
}).catch(function() {});
|
|
88
144
|
}
|
|
89
145
|
|
|
90
146
|
function onWsMessage(e) {
|
|
91
147
|
var data = e.detail;
|
|
92
148
|
if (!data || data.conversationId !== AUTH_CONV_ID) return;
|
|
93
149
|
if (data.type === 'script_started') {
|
|
94
|
-
authRunning = true;
|
|
95
|
-
showTerminalTab();
|
|
96
|
-
switchToTerminalView();
|
|
150
|
+
authRunning = true; showTerminalTab(); switchToTerminalView();
|
|
97
151
|
var term = getTerminal();
|
|
98
|
-
if (term) {
|
|
99
|
-
term.clear();
|
|
100
|
-
term.writeln('\x1b[36m[authenticating ' + (data.agentId || '') + ']\x1b[0m\r\n');
|
|
101
|
-
}
|
|
152
|
+
if (term) { term.clear(); term.writeln('\x1b[36m[authenticating ' + (data.agentId || '') + ']\x1b[0m\r\n'); }
|
|
102
153
|
} else if (data.type === 'script_output') {
|
|
103
154
|
showTerminalTab();
|
|
104
155
|
var term = getTerminal();
|
|
@@ -108,37 +159,20 @@
|
|
|
108
159
|
var term = getTerminal();
|
|
109
160
|
var msg = data.error ? data.error : ('exited with code ' + (data.code || 0));
|
|
110
161
|
if (term) term.writeln('\r\n\x1b[90m[auth ' + msg + ']\x1b[0m');
|
|
111
|
-
setTimeout(
|
|
162
|
+
setTimeout(refresh, 1000);
|
|
112
163
|
}
|
|
113
164
|
}
|
|
114
165
|
|
|
115
|
-
function showTerminalTab() {
|
|
116
|
-
var tabBtn = document.getElementById('terminalTabBtn');
|
|
117
|
-
if (tabBtn) tabBtn.style.display = '';
|
|
118
|
-
}
|
|
119
|
-
|
|
166
|
+
function showTerminalTab() { var t = document.getElementById('terminalTabBtn'); if (t) t.style.display = ''; }
|
|
120
167
|
function switchToTerminalView() {
|
|
121
168
|
var bar = document.getElementById('viewToggleBar');
|
|
122
169
|
if (!bar) return;
|
|
123
|
-
var
|
|
124
|
-
if (termBtn) termBtn.click();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function getTerminal() {
|
|
128
|
-
return window.scriptRunner ? window.scriptRunner.getTerminal() : null;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function escapeHtml(s) {
|
|
132
|
-
var d = document.createElement('div');
|
|
133
|
-
d.textContent = s;
|
|
134
|
-
return d.innerHTML;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (document.readyState === 'loading') {
|
|
138
|
-
document.addEventListener('DOMContentLoaded', init);
|
|
139
|
-
} else {
|
|
140
|
-
init();
|
|
170
|
+
var t = bar.querySelector('[data-view="terminal"]'); if (t) t.click();
|
|
141
171
|
}
|
|
172
|
+
function getTerminal() { return window.scriptRunner ? window.scriptRunner.getTerminal() : null; }
|
|
173
|
+
function esc(s) { var d = document.createElement('div'); d.textContent = s; return d.innerHTML; }
|
|
142
174
|
|
|
143
|
-
|
|
175
|
+
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
|
|
176
|
+
else init();
|
|
177
|
+
window.agentAuth = { refresh: refresh };
|
|
144
178
|
})();
|