@zhongqian97-code/ecode 0.5.18 → 0.5.19
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/dist/index.js +133 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5244,6 +5244,135 @@ function createAuthHook(token) {
|
|
|
5244
5244
|
};
|
|
5245
5245
|
}
|
|
5246
5246
|
|
|
5247
|
+
// src/web/admin-html.ts
|
|
5248
|
+
function generateAdminHtml(version2) {
|
|
5249
|
+
return `<!DOCTYPE html>
|
|
5250
|
+
<html lang="zh">
|
|
5251
|
+
<head>
|
|
5252
|
+
<meta charset="UTF-8">
|
|
5253
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
5254
|
+
<title>ecode web admin</title>
|
|
5255
|
+
<style>
|
|
5256
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
5257
|
+
body {
|
|
5258
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, monospace;
|
|
5259
|
+
background: #0d1117; color: #c9d1d9; min-height: 100vh; padding: 24px;
|
|
5260
|
+
}
|
|
5261
|
+
header {
|
|
5262
|
+
display: flex; align-items: center; gap: 12px;
|
|
5263
|
+
padding-bottom: 16px; border-bottom: 1px solid #21262d; margin-bottom: 24px;
|
|
5264
|
+
}
|
|
5265
|
+
header h1 { font-size: 18px; font-weight: 600; color: #e6edf3; }
|
|
5266
|
+
header .version { font-size: 12px; color: #8b949e; background: #21262d;
|
|
5267
|
+
padding: 2px 8px; border-radius: 20px; }
|
|
5268
|
+
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px; }
|
|
5269
|
+
.card {
|
|
5270
|
+
background: #161b22; border: 1px solid #21262d; border-radius: 8px; padding: 16px;
|
|
5271
|
+
}
|
|
5272
|
+
.card h2 { font-size: 13px; font-weight: 600; color: #8b949e;
|
|
5273
|
+
text-transform: uppercase; letter-spacing: .05em; margin-bottom: 12px; }
|
|
5274
|
+
.stat { display: flex; justify-content: space-between; align-items: center;
|
|
5275
|
+
padding: 6px 0; border-bottom: 1px solid #21262d; font-size: 13px; }
|
|
5276
|
+
.stat:last-child { border-bottom: none; }
|
|
5277
|
+
.stat .label { color: #8b949e; }
|
|
5278
|
+
.stat .value { color: #e6edf3; font-weight: 500; }
|
|
5279
|
+
.badge { display: inline-block; padding: 2px 8px; border-radius: 20px;
|
|
5280
|
+
font-size: 11px; font-weight: 600; }
|
|
5281
|
+
.badge.ok { background: #1a4731; color: #3fb950; }
|
|
5282
|
+
.badge.err { background: #4d1f24; color: #f85149; }
|
|
5283
|
+
.session-item {
|
|
5284
|
+
padding: 8px 0; border-bottom: 1px solid #21262d; font-size: 13px;
|
|
5285
|
+
}
|
|
5286
|
+
.session-item:last-child { border-bottom: none; }
|
|
5287
|
+
.session-id { color: #79c0ff; font-family: monospace; font-size: 12px; }
|
|
5288
|
+
.session-title { color: #e6edf3; margin-top: 2px; }
|
|
5289
|
+
.empty { color: #8b949e; font-size: 13px; font-style: italic; }
|
|
5290
|
+
.error { color: #f85149; font-size: 13px; }
|
|
5291
|
+
.loading { color: #8b949e; font-size: 13px; font-style: italic; }
|
|
5292
|
+
.api-row { font-size: 12px; font-family: monospace; padding: 4px 0;
|
|
5293
|
+
border-bottom: 1px solid #21262d; display: flex; gap: 8px; }
|
|
5294
|
+
.api-row:last-child { border-bottom: none; }
|
|
5295
|
+
.method { color: #79c0ff; min-width: 50px; }
|
|
5296
|
+
.path { color: #e6edf3; }
|
|
5297
|
+
</style>
|
|
5298
|
+
</head>
|
|
5299
|
+
<body>
|
|
5300
|
+
<header>
|
|
5301
|
+
<h1>\u26A1 ecode web admin</h1>
|
|
5302
|
+
<span class="version">v${version2}</span>
|
|
5303
|
+
</header>
|
|
5304
|
+
|
|
5305
|
+
<div class="grid">
|
|
5306
|
+
<div class="card">
|
|
5307
|
+
<h2>\u670D\u52A1\u72B6\u6001</h2>
|
|
5308
|
+
<div id="status-content"><span class="loading">\u52A0\u8F7D\u4E2D\u2026</span></div>
|
|
5309
|
+
</div>
|
|
5310
|
+
|
|
5311
|
+
<div class="card">
|
|
5312
|
+
<h2>\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD</h2>
|
|
5313
|
+
<div id="sessions-content"><span class="loading">\u52A0\u8F7D\u4E2D\u2026</span></div>
|
|
5314
|
+
</div>
|
|
5315
|
+
|
|
5316
|
+
<div class="card">
|
|
5317
|
+
<h2>API \u7AEF\u70B9</h2>
|
|
5318
|
+
<div class="api-row"><span class="method">GET</span><span class="path">/api/status</span></div>
|
|
5319
|
+
<div class="api-row"><span class="method">GET</span><span class="path">/api/sessions</span></div>
|
|
5320
|
+
<div class="api-row"><span class="method">GET</span><span class="path">/api/config</span></div>
|
|
5321
|
+
<div class="api-row"><span class="method">GET</span><span class="path">/api/automation/jobs</span></div>
|
|
5322
|
+
<div class="api-row"><span class="method">POST</span><span class="path">/api/chat/sessions</span></div>
|
|
5323
|
+
<div class="api-row"><span class="method">WS</span><span class="path">/api/ws/sessions/:id</span></div>
|
|
5324
|
+
</div>
|
|
5325
|
+
</div>
|
|
5326
|
+
|
|
5327
|
+
<script>
|
|
5328
|
+
const token = new URLSearchParams(location.search).get('token') || '';
|
|
5329
|
+
|
|
5330
|
+
async function apiFetch(path) {
|
|
5331
|
+
const sep = path.includes('?') ? '&' : '?';
|
|
5332
|
+
const r = await fetch(path + sep + 'token=' + encodeURIComponent(token));
|
|
5333
|
+
if (!r.ok) throw new Error(r.status + ' ' + r.statusText);
|
|
5334
|
+
return r.json();
|
|
5335
|
+
}
|
|
5336
|
+
|
|
5337
|
+
function setHtml(id, html) {
|
|
5338
|
+
document.getElementById(id).innerHTML = html;
|
|
5339
|
+
}
|
|
5340
|
+
|
|
5341
|
+
// \u72B6\u6001\u5361
|
|
5342
|
+
apiFetch('/api/status').then(d => {
|
|
5343
|
+
const rows = [
|
|
5344
|
+
['\u72B6\u6001', '<span class="badge ok">\u8FD0\u884C\u4E2D</span>'],
|
|
5345
|
+
['\u7248\u672C', d.version ?? '-'],
|
|
5346
|
+
['\u6D3B\u8DC3\u4F1A\u8BDD', d.activeSessions ?? 0],
|
|
5347
|
+
];
|
|
5348
|
+
setHtml('status-content',
|
|
5349
|
+
rows.map(([l,v]) =>
|
|
5350
|
+
'<div class="stat"><span class="label">' + l + '</span><span class="value">' + v + '</span></div>'
|
|
5351
|
+
).join('')
|
|
5352
|
+
);
|
|
5353
|
+
}).catch(e => setHtml('status-content', '<span class="error">' + e.message + '</span>'));
|
|
5354
|
+
|
|
5355
|
+
// \u4F1A\u8BDD\u5217\u8868
|
|
5356
|
+
apiFetch('/api/sessions').then(d => {
|
|
5357
|
+
const sessions = d.sessions ?? d.data ?? d ?? [];
|
|
5358
|
+
if (!sessions.length) {
|
|
5359
|
+
setHtml('sessions-content', '<span class="empty">\u6682\u65E0\u4F1A\u8BDD</span>');
|
|
5360
|
+
return;
|
|
5361
|
+
}
|
|
5362
|
+
setHtml('sessions-content',
|
|
5363
|
+
sessions.slice(0, 10).map(s =>
|
|
5364
|
+
'<div class="session-item">' +
|
|
5365
|
+
'<div class="session-id">' + s.id + '</div>' +
|
|
5366
|
+
'<div class="session-title">' + (s.title || '(\u65E0\u6807\u9898)') + '</div>' +
|
|
5367
|
+
'</div>'
|
|
5368
|
+
).join('')
|
|
5369
|
+
);
|
|
5370
|
+
}).catch(e => setHtml('sessions-content', '<span class="error">' + e.message + '</span>'));
|
|
5371
|
+
</script>
|
|
5372
|
+
</body>
|
|
5373
|
+
</html>`;
|
|
5374
|
+
}
|
|
5375
|
+
|
|
5247
5376
|
// src/web/routes/status.ts
|
|
5248
5377
|
async function statusRoutes(app, opts) {
|
|
5249
5378
|
app.get(
|
|
@@ -5551,6 +5680,10 @@ async function buildServer(opts) {
|
|
|
5551
5680
|
authHook(request, reply, done);
|
|
5552
5681
|
});
|
|
5553
5682
|
app.get("/health", async () => ({ ok: true }));
|
|
5683
|
+
const adminHtml = generateAdminHtml(opts.version);
|
|
5684
|
+
app.get("/", async (_req, reply) => {
|
|
5685
|
+
return reply.type("text/html").send(adminHtml);
|
|
5686
|
+
});
|
|
5554
5687
|
await app.register(statusRoutes, {
|
|
5555
5688
|
config: opts.config,
|
|
5556
5689
|
manager: opts.manager,
|