codeharbor 0.1.22 → 0.1.23
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/cli.js +454 -130
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -42,11 +42,11 @@ var import_node_util2 = require("util");
|
|
|
42
42
|
|
|
43
43
|
// src/admin-console-html.ts
|
|
44
44
|
var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
45
|
-
<html lang="
|
|
45
|
+
<html lang="zh-CN">
|
|
46
46
|
<head>
|
|
47
47
|
<meta charset="utf-8" />
|
|
48
48
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
49
|
-
<title>CodeHarbor Admin Console</title>
|
|
49
|
+
<title>CodeHarbor \u7BA1\u7406\u540E\u53F0 / Admin Console</title>
|
|
50
50
|
<style>
|
|
51
51
|
:root {
|
|
52
52
|
--bg-start: #0f172a;
|
|
@@ -129,13 +129,15 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
129
129
|
color: var(--muted);
|
|
130
130
|
}
|
|
131
131
|
input,
|
|
132
|
+
select,
|
|
132
133
|
button,
|
|
133
134
|
textarea {
|
|
134
135
|
font: inherit;
|
|
135
136
|
}
|
|
136
137
|
input[type="text"],
|
|
137
138
|
input[type="password"],
|
|
138
|
-
input[type="number"]
|
|
139
|
+
input[type="number"],
|
|
140
|
+
select {
|
|
139
141
|
border: 1px solid var(--panel-border);
|
|
140
142
|
background: #0f172acc;
|
|
141
143
|
color: var(--text);
|
|
@@ -261,181 +263,188 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
261
263
|
<body>
|
|
262
264
|
<main class="shell">
|
|
263
265
|
<section class="header">
|
|
264
|
-
<h1 class="title">CodeHarbor
|
|
265
|
-
<p class="subtitle"
|
|
266
|
+
<h1 class="title" data-i18n="header.title">CodeHarbor \u7BA1\u7406\u540E\u53F0</h1>
|
|
267
|
+
<p class="subtitle" data-i18n="header.subtitle">\u7BA1\u7406\u5168\u5C40\u914D\u7F6E\u3001\u623F\u95F4\u7B56\u7565\u3001\u5065\u5EB7\u68C0\u67E5\u4E0E\u914D\u7F6E\u5BA1\u8BA1\u8BB0\u5F55\u3002</p>
|
|
266
268
|
<nav class="tabs">
|
|
267
|
-
<a class="tab" data-page="settings-global" href="#/settings/global"
|
|
268
|
-
<a class="tab" data-page="settings-rooms" href="#/settings/rooms"
|
|
269
|
-
<a class="tab" data-page="health" href="#/health"
|
|
270
|
-
<a class="tab" data-page="audit" href="#/audit"
|
|
269
|
+
<a class="tab" data-page="settings-global" href="#/settings/global" data-i18n="tab.global">\u5168\u5C40</a>
|
|
270
|
+
<a class="tab" data-page="settings-rooms" href="#/settings/rooms" data-i18n="tab.rooms">\u623F\u95F4</a>
|
|
271
|
+
<a class="tab" data-page="health" href="#/health" data-i18n="tab.health">\u5065\u5EB7</a>
|
|
272
|
+
<a class="tab" data-page="audit" href="#/audit" data-i18n="tab.audit">\u5BA1\u8BA1</a>
|
|
271
273
|
</nav>
|
|
272
274
|
<div class="auth-row">
|
|
273
275
|
<label class="field">
|
|
274
|
-
<span class="field-label"
|
|
275
|
-
<input id="auth-token" type="password" placeholder="ADMIN_TOKEN" />
|
|
276
|
+
<span class="field-label" data-i18n="auth.token.label">\u7BA1\u7406\u5458\u4EE4\u724C\uFF08\u53EF\u9009\uFF09</span>
|
|
277
|
+
<input id="auth-token" type="password" placeholder="ADMIN_TOKEN" data-i18n-placeholder="auth.token.placeholder" />
|
|
276
278
|
</label>
|
|
277
279
|
<label class="field">
|
|
278
|
-
<span class="field-label"
|
|
279
|
-
<input id="auth-actor" type="text" placeholder="
|
|
280
|
+
<span class="field-label" data-i18n="auth.actor.label">\u64CD\u4F5C\u8005\uFF08\u7528\u4E8E\u5BA1\u8BA1\u65E5\u5FD7\uFF09</span>
|
|
281
|
+
<input id="auth-actor" type="text" placeholder="\u4F60\u7684\u540D\u5B57" data-i18n-placeholder="auth.actor.placeholder" />
|
|
280
282
|
</label>
|
|
281
|
-
<
|
|
282
|
-
|
|
283
|
+
<label class="field">
|
|
284
|
+
<span class="field-label" data-i18n="auth.language.label">\u754C\u9762\u8BED\u8A00</span>
|
|
285
|
+
<select id="lang-select">
|
|
286
|
+
<option value="zh">\u4E2D\u6587</option>
|
|
287
|
+
<option value="en">English</option>
|
|
288
|
+
</select>
|
|
289
|
+
</label>
|
|
290
|
+
<button id="auth-save-btn" type="button" class="secondary" data-i18n="auth.save">\u4FDD\u5B58\u8BA4\u8BC1</button>
|
|
291
|
+
<button id="auth-clear-btn" type="button" class="secondary" data-i18n="auth.clear">\u6E05\u9664\u8BA4\u8BC1</button>
|
|
283
292
|
</div>
|
|
284
|
-
<div id="notice" class="notice"
|
|
285
|
-
<p id="auth-role" class="muted"
|
|
293
|
+
<div id="notice" class="notice" data-i18n="notice.ready">\u5C31\u7EEA\u3002</div>
|
|
294
|
+
<p id="auth-role" class="muted" data-i18n="auth.permission.unknown">\u6743\u9650\uFF1A\u672A\u77E5</p>
|
|
286
295
|
</section>
|
|
287
296
|
|
|
288
297
|
<section class="panel" data-view="settings-global">
|
|
289
|
-
<h2 class="panel-title"
|
|
298
|
+
<h2 class="panel-title" data-i18n="global.title">\u5168\u5C40\u914D\u7F6E</h2>
|
|
290
299
|
<div class="grid">
|
|
291
300
|
<label class="field">
|
|
292
|
-
<span class="field-label"
|
|
301
|
+
<span class="field-label" data-i18n="global.commandPrefix">\u547D\u4EE4\u524D\u7F00</span>
|
|
293
302
|
<input id="global-matrix-prefix" type="text" />
|
|
294
303
|
</label>
|
|
295
304
|
<label class="field">
|
|
296
|
-
<span class="field-label"
|
|
305
|
+
<span class="field-label" data-i18n="global.defaultWorkdir">\u9ED8\u8BA4\u5DE5\u4F5C\u76EE\u5F55</span>
|
|
297
306
|
<input id="global-workdir" type="text" />
|
|
298
307
|
</label>
|
|
299
308
|
<label class="field">
|
|
300
|
-
<span class="field-label"
|
|
309
|
+
<span class="field-label" data-i18n="global.progressInterval">\u8FDB\u5EA6\u66F4\u65B0\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09</span>
|
|
301
310
|
<input id="global-progress-interval" type="number" min="1" />
|
|
302
311
|
</label>
|
|
303
312
|
<label class="field">
|
|
304
|
-
<span class="field-label"
|
|
313
|
+
<span class="field-label" data-i18n="global.typingTimeout">\u8F93\u5165\u72B6\u6001\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09</span>
|
|
305
314
|
<input id="global-typing-timeout" type="number" min="1" />
|
|
306
315
|
</label>
|
|
307
316
|
<label class="field">
|
|
308
|
-
<span class="field-label"
|
|
317
|
+
<span class="field-label" data-i18n="global.sessionWindow">\u4F1A\u8BDD\u6D3B\u8DC3\u7A97\u53E3\uFF08\u5206\u949F\uFF09</span>
|
|
309
318
|
<input id="global-active-window" type="number" min="1" />
|
|
310
319
|
</label>
|
|
311
320
|
<label class="checkbox">
|
|
312
321
|
<input id="global-progress-enabled" type="checkbox" />
|
|
313
|
-
<span
|
|
322
|
+
<span data-i18n="global.progressEnabled">\u542F\u7528\u8FDB\u5EA6\u66F4\u65B0</span>
|
|
314
323
|
</label>
|
|
315
324
|
|
|
316
325
|
<label class="field">
|
|
317
|
-
<span class="field-label"
|
|
326
|
+
<span class="field-label" data-i18n="global.rateWindow">\u9650\u6D41\u7A97\u53E3\uFF08\u6BEB\u79D2\uFF09</span>
|
|
318
327
|
<input id="global-rate-window" type="number" min="1" />
|
|
319
328
|
</label>
|
|
320
329
|
<label class="field">
|
|
321
|
-
<span class="field-label"
|
|
330
|
+
<span class="field-label" data-i18n="global.rateUser">\u5355\u7528\u6237\u7A97\u53E3\u6700\u5927\u8BF7\u6C42\u6570</span>
|
|
322
331
|
<input id="global-rate-user" type="number" min="0" />
|
|
323
332
|
</label>
|
|
324
333
|
<label class="field">
|
|
325
|
-
<span class="field-label"
|
|
334
|
+
<span class="field-label" data-i18n="global.rateRoom">\u5355\u623F\u95F4\u7A97\u53E3\u6700\u5927\u8BF7\u6C42\u6570</span>
|
|
326
335
|
<input id="global-rate-room" type="number" min="0" />
|
|
327
336
|
</label>
|
|
328
337
|
<label class="field">
|
|
329
|
-
<span class="field-label"
|
|
338
|
+
<span class="field-label" data-i18n="global.concurrentGlobal">\u5168\u5C40\u6700\u5927\u5E76\u53D1</span>
|
|
330
339
|
<input id="global-concurrency-global" type="number" min="0" />
|
|
331
340
|
</label>
|
|
332
341
|
<label class="field">
|
|
333
|
-
<span class="field-label"
|
|
342
|
+
<span class="field-label" data-i18n="global.concurrentUser">\u5355\u7528\u6237\u6700\u5927\u5E76\u53D1</span>
|
|
334
343
|
<input id="global-concurrency-user" type="number" min="0" />
|
|
335
344
|
</label>
|
|
336
345
|
<label class="field">
|
|
337
|
-
<span class="field-label"
|
|
346
|
+
<span class="field-label" data-i18n="global.concurrentRoom">\u5355\u623F\u95F4\u6700\u5927\u5E76\u53D1</span>
|
|
338
347
|
<input id="global-concurrency-room" type="number" min="0" />
|
|
339
348
|
</label>
|
|
340
349
|
|
|
341
|
-
<label class="checkbox"><input id="global-direct-mode" type="checkbox" /><span
|
|
342
|
-
<label class="checkbox"><input id="global-trigger-mention" type="checkbox" /><span
|
|
343
|
-
<label class="checkbox"><input id="global-trigger-reply" type="checkbox" /><span
|
|
344
|
-
<label class="checkbox"><input id="global-trigger-window" type="checkbox" /><span
|
|
345
|
-
<label class="checkbox"><input id="global-trigger-prefix" type="checkbox" /><span
|
|
350
|
+
<label class="checkbox"><input id="global-direct-mode" type="checkbox" /><span data-i18n="global.groupDirect">\u7FA4\u804A\u76F4\u901A\u6A21\u5F0F\uFF08\u65E0\u9700\u89E6\u53D1\uFF09</span></label>
|
|
351
|
+
<label class="checkbox"><input id="global-trigger-mention" type="checkbox" /><span data-i18n="global.triggerMention">\u89E6\u53D1\uFF1A\u63D0\u53CA\u673A\u5668\u4EBA</span></label>
|
|
352
|
+
<label class="checkbox"><input id="global-trigger-reply" type="checkbox" /><span data-i18n="global.triggerReply">\u89E6\u53D1\uFF1A\u56DE\u590D\u673A\u5668\u4EBA</span></label>
|
|
353
|
+
<label class="checkbox"><input id="global-trigger-window" type="checkbox" /><span data-i18n="global.triggerWindow">\u89E6\u53D1\uFF1A\u6D3B\u8DC3\u7A97\u53E3</span></label>
|
|
354
|
+
<label class="checkbox"><input id="global-trigger-prefix" type="checkbox" /><span data-i18n="global.triggerPrefix">\u89E6\u53D1\uFF1A\u547D\u4EE4\u524D\u7F00</span></label>
|
|
346
355
|
|
|
347
|
-
<label class="checkbox"><input id="global-cli-enabled" type="checkbox" /><span>CLI
|
|
348
|
-
<label class="checkbox"><input id="global-cli-pass" type="checkbox" /><span>CLI
|
|
349
|
-
<label class="checkbox"><input id="global-cli-whitespace" type="checkbox" /><span
|
|
350
|
-
<label class="checkbox"><input id="global-cli-disable-split" type="checkbox" /><span
|
|
356
|
+
<label class="checkbox"><input id="global-cli-enabled" type="checkbox" /><span data-i18n="global.cliEnabled">CLI \u517C\u5BB9\u6A21\u5F0F</span></label>
|
|
357
|
+
<label class="checkbox"><input id="global-cli-pass" type="checkbox" /><span data-i18n="global.cliPass">CLI \u900F\u4F20\u4E8B\u4EF6</span></label>
|
|
358
|
+
<label class="checkbox"><input id="global-cli-whitespace" type="checkbox" /><span data-i18n="global.cliWhitespace">\u4FDD\u7559\u7A7A\u767D\u7B26</span></label>
|
|
359
|
+
<label class="checkbox"><input id="global-cli-disable-split" type="checkbox" /><span data-i18n="global.cliDisableSplit">\u7981\u7528\u56DE\u590D\u5206\u7247</span></label>
|
|
351
360
|
<label class="field">
|
|
352
|
-
<span class="field-label">CLI
|
|
361
|
+
<span class="field-label" data-i18n="global.cliThrottle">CLI \u8FDB\u5EA6\u8282\u6D41\uFF08\u6BEB\u79D2\uFF09</span>
|
|
353
362
|
<input id="global-cli-throttle" type="number" min="0" />
|
|
354
363
|
</label>
|
|
355
|
-
<label class="checkbox"><input id="global-cli-fetch-media" type="checkbox" /><span
|
|
356
|
-
<label class="checkbox"><input id="global-cli-transcribe-audio" type="checkbox" /><span
|
|
364
|
+
<label class="checkbox"><input id="global-cli-fetch-media" type="checkbox" /><span data-i18n="global.cliFetchMedia">\u4E0B\u8F7D\u5A92\u4F53\u9644\u4EF6</span></label>
|
|
365
|
+
<label class="checkbox"><input id="global-cli-transcribe-audio" type="checkbox" /><span data-i18n="global.cliTranscribeAudio">\u8F6C\u5199\u97F3\u9891\u9644\u4EF6</span></label>
|
|
357
366
|
<label class="field">
|
|
358
|
-
<span class="field-label"
|
|
367
|
+
<span class="field-label" data-i18n="global.audioModel">\u97F3\u9891\u8F6C\u5199\u6A21\u578B</span>
|
|
359
368
|
<input id="global-cli-audio-model" type="text" />
|
|
360
369
|
</label>
|
|
361
370
|
<label class="field">
|
|
362
|
-
<span class="field-label"
|
|
371
|
+
<span class="field-label" data-i18n="global.audioTimeout">\u97F3\u9891\u8F6C\u5199\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09</span>
|
|
363
372
|
<input id="global-cli-audio-timeout" type="number" min="1" />
|
|
364
373
|
</label>
|
|
365
374
|
<label class="field">
|
|
366
|
-
<span class="field-label"
|
|
375
|
+
<span class="field-label" data-i18n="global.audioMaxChars">\u97F3\u9891\u8F6C\u5199\u6700\u5927\u5B57\u7B26\u6570</span>
|
|
367
376
|
<input id="global-cli-audio-max-chars" type="number" min="1" />
|
|
368
377
|
</label>
|
|
369
378
|
<label class="field">
|
|
370
|
-
<span class="field-label"
|
|
379
|
+
<span class="field-label" data-i18n="global.audioMaxRetries">\u97F3\u9891\u8F6C\u5199\u6700\u5927\u91CD\u8BD5\u6B21\u6570</span>
|
|
371
380
|
<input id="global-cli-audio-max-retries" type="number" min="0" max="10" />
|
|
372
381
|
</label>
|
|
373
382
|
<label class="field">
|
|
374
|
-
<span class="field-label"
|
|
383
|
+
<span class="field-label" data-i18n="global.audioRetryDelay">\u97F3\u9891\u8F6C\u5199\u91CD\u8BD5\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09</span>
|
|
375
384
|
<input id="global-cli-audio-retry-delay" type="number" min="0" />
|
|
376
385
|
</label>
|
|
377
386
|
<label class="field">
|
|
378
|
-
<span class="field-label"
|
|
387
|
+
<span class="field-label" data-i18n="global.audioMaxBytes">\u97F3\u9891\u6700\u5927\u5B57\u8282\u6570</span>
|
|
379
388
|
<input id="global-cli-audio-max-bytes" type="number" min="1" />
|
|
380
389
|
</label>
|
|
381
390
|
<label class="field">
|
|
382
|
-
<span class="field-label"
|
|
383
|
-
<input id="global-cli-audio-local-command" type="text" placeholder='python3 /opt/whisper/transcribe.py --input {input}' />
|
|
391
|
+
<span class="field-label" data-i18n="global.audioLocalCommand">\u672C\u5730 Whisper \u547D\u4EE4</span>
|
|
392
|
+
<input id="global-cli-audio-local-command" type="text" placeholder='python3 /opt/whisper/transcribe.py --input {input}' data-i18n-placeholder="global.audioLocalCommandPlaceholder" />
|
|
384
393
|
</label>
|
|
385
394
|
<label class="field">
|
|
386
|
-
<span class="field-label"
|
|
395
|
+
<span class="field-label" data-i18n="global.audioLocalTimeout">\u672C\u5730 Whisper \u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09</span>
|
|
387
396
|
<input id="global-cli-audio-local-timeout" type="number" min="1" />
|
|
388
397
|
</label>
|
|
389
|
-
<label class="checkbox"><input id="global-agent-enabled" type="checkbox" /><span
|
|
398
|
+
<label class="checkbox"><input id="global-agent-enabled" type="checkbox" /><span data-i18n="global.agentEnabled">\u542F\u7528\u591A\u667A\u80FD\u4F53\u5DE5\u4F5C\u6D41</span></label>
|
|
390
399
|
<label class="field">
|
|
391
|
-
<span class="field-label"
|
|
400
|
+
<span class="field-label" data-i18n="global.agentRounds">\u5DE5\u4F5C\u6D41\u81EA\u52A8\u4FEE\u590D\u8F6E\u6B21</span>
|
|
392
401
|
<input id="global-agent-repair-rounds" type="number" min="0" max="10" />
|
|
393
402
|
</label>
|
|
394
403
|
</div>
|
|
395
404
|
<div class="actions">
|
|
396
|
-
<button id="global-save-btn" type="button"
|
|
397
|
-
<button id="global-reload-btn" type="button" class="secondary"
|
|
398
|
-
<button id="global-restart-main-btn" type="button" class="secondary"
|
|
399
|
-
<button id="global-restart-all-btn" type="button" class="secondary"
|
|
405
|
+
<button id="global-save-btn" type="button" data-i18n="global.save">\u4FDD\u5B58\u5168\u5C40\u914D\u7F6E</button>
|
|
406
|
+
<button id="global-reload-btn" type="button" class="secondary" data-i18n="global.reload">\u91CD\u65B0\u52A0\u8F7D</button>
|
|
407
|
+
<button id="global-restart-main-btn" type="button" class="secondary" data-i18n="global.restartMain">\u91CD\u542F\u4E3B\u670D\u52A1</button>
|
|
408
|
+
<button id="global-restart-all-btn" type="button" class="secondary" data-i18n="global.restartAll">\u91CD\u542F\u4E3B\u670D\u52A1+\u7BA1\u7406\u540E\u53F0</button>
|
|
400
409
|
</div>
|
|
401
|
-
<p class="muted"
|
|
410
|
+
<p class="muted" data-i18n="global.restartHint">\u4FDD\u5B58\u5168\u5C40\u914D\u7F6E\u4F1A\u66F4\u65B0 .env\uFF0C\u5E76\u9700\u8981\u91CD\u542F\u540E\u5B8C\u5168\u751F\u6548\u3002</p>
|
|
402
411
|
</section>
|
|
403
412
|
|
|
404
413
|
<section class="panel" data-view="settings-rooms" hidden>
|
|
405
|
-
<h2 class="panel-title"
|
|
414
|
+
<h2 class="panel-title" data-i18n="rooms.title">\u623F\u95F4\u914D\u7F6E</h2>
|
|
406
415
|
<div class="grid">
|
|
407
416
|
<label class="field">
|
|
408
|
-
<span class="field-label"
|
|
409
|
-
<input id="room-id" type="text" placeholder="!room:example.com" />
|
|
417
|
+
<span class="field-label" data-i18n="rooms.roomId">\u623F\u95F4 ID</span>
|
|
418
|
+
<input id="room-id" type="text" placeholder="!room:example.com" data-i18n-placeholder="rooms.roomIdPlaceholder" />
|
|
410
419
|
</label>
|
|
411
420
|
<label class="field">
|
|
412
|
-
<span class="field-label"
|
|
413
|
-
<input id="room-summary" type="text" placeholder="
|
|
421
|
+
<span class="field-label" data-i18n="rooms.summary">\u5BA1\u8BA1\u6458\u8981\uFF08\u53EF\u9009\uFF09</span>
|
|
422
|
+
<input id="room-summary" type="text" placeholder="\u7ED1\u5B9A\u623F\u95F4\u5230\u9879\u76EE A" data-i18n-placeholder="rooms.summaryPlaceholder" />
|
|
414
423
|
</label>
|
|
415
424
|
<label class="field full">
|
|
416
|
-
<span class="field-label"
|
|
425
|
+
<span class="field-label" data-i18n="rooms.workdir">\u5DE5\u4F5C\u76EE\u5F55</span>
|
|
417
426
|
<input id="room-workdir" type="text" />
|
|
418
427
|
</label>
|
|
419
|
-
<label class="checkbox"><input id="room-enabled" type="checkbox" /><span
|
|
420
|
-
<label class="checkbox"><input id="room-mention" type="checkbox" /><span
|
|
421
|
-
<label class="checkbox"><input id="room-reply" type="checkbox" /><span
|
|
422
|
-
<label class="checkbox"><input id="room-window" type="checkbox" /><span
|
|
423
|
-
<label class="checkbox"><input id="room-prefix" type="checkbox" /><span
|
|
428
|
+
<label class="checkbox"><input id="room-enabled" type="checkbox" /><span data-i18n="rooms.enabled">\u542F\u7528</span></label>
|
|
429
|
+
<label class="checkbox"><input id="room-mention" type="checkbox" /><span data-i18n="rooms.allowMention">\u5141\u8BB8\u63D0\u53CA\u89E6\u53D1</span></label>
|
|
430
|
+
<label class="checkbox"><input id="room-reply" type="checkbox" /><span data-i18n="rooms.allowReply">\u5141\u8BB8\u56DE\u590D\u89E6\u53D1</span></label>
|
|
431
|
+
<label class="checkbox"><input id="room-window" type="checkbox" /><span data-i18n="rooms.allowWindow">\u5141\u8BB8\u6D3B\u8DC3\u7A97\u53E3\u89E6\u53D1</span></label>
|
|
432
|
+
<label class="checkbox"><input id="room-prefix" type="checkbox" /><span data-i18n="rooms.allowPrefix">\u5141\u8BB8\u524D\u7F00\u89E6\u53D1</span></label>
|
|
424
433
|
</div>
|
|
425
434
|
<div class="actions">
|
|
426
|
-
<button id="room-load-btn" type="button" class="secondary"
|
|
427
|
-
<button id="room-save-btn" type="button"
|
|
428
|
-
<button id="room-delete-btn" type="button" class="danger"
|
|
429
|
-
<button id="room-refresh-btn" type="button" class="secondary"
|
|
435
|
+
<button id="room-load-btn" type="button" class="secondary" data-i18n="rooms.load">\u52A0\u8F7D\u623F\u95F4</button>
|
|
436
|
+
<button id="room-save-btn" type="button" data-i18n="rooms.save">\u4FDD\u5B58\u623F\u95F4</button>
|
|
437
|
+
<button id="room-delete-btn" type="button" class="danger" data-i18n="rooms.delete">\u5220\u9664\u623F\u95F4</button>
|
|
438
|
+
<button id="room-refresh-btn" type="button" class="secondary" data-i18n="rooms.refresh">\u5237\u65B0\u5217\u8868</button>
|
|
430
439
|
</div>
|
|
431
440
|
<div class="table-wrap">
|
|
432
441
|
<table>
|
|
433
442
|
<thead>
|
|
434
443
|
<tr>
|
|
435
|
-
<th
|
|
436
|
-
<th
|
|
437
|
-
<th
|
|
438
|
-
<th
|
|
444
|
+
<th data-i18n="rooms.table.roomId">\u623F\u95F4 ID</th>
|
|
445
|
+
<th data-i18n="rooms.table.enabled">\u542F\u7528</th>
|
|
446
|
+
<th data-i18n="rooms.table.workdir">\u5DE5\u4F5C\u76EE\u5F55</th>
|
|
447
|
+
<th data-i18n="rooms.table.updatedAt">\u66F4\u65B0\u65F6\u95F4</th>
|
|
439
448
|
</tr>
|
|
440
449
|
</thead>
|
|
441
450
|
<tbody id="room-list-body"></tbody>
|
|
@@ -444,17 +453,17 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
444
453
|
</section>
|
|
445
454
|
|
|
446
455
|
<section class="panel" data-view="health" hidden>
|
|
447
|
-
<h2 class="panel-title"
|
|
456
|
+
<h2 class="panel-title" data-i18n="health.title">\u5065\u5EB7\u68C0\u67E5</h2>
|
|
448
457
|
<div class="actions">
|
|
449
|
-
<button id="health-refresh-btn" type="button"
|
|
458
|
+
<button id="health-refresh-btn" type="button" data-i18n="health.run">\u6267\u884C\u5065\u5EB7\u68C0\u67E5</button>
|
|
450
459
|
</div>
|
|
451
460
|
<div class="table-wrap">
|
|
452
461
|
<table>
|
|
453
462
|
<thead>
|
|
454
463
|
<tr>
|
|
455
|
-
<th
|
|
456
|
-
<th
|
|
457
|
-
<th
|
|
464
|
+
<th data-i18n="health.table.component">\u7EC4\u4EF6</th>
|
|
465
|
+
<th data-i18n="health.table.status">\u72B6\u6001</th>
|
|
466
|
+
<th data-i18n="health.table.details">\u8BE6\u60C5</th>
|
|
458
467
|
</tr>
|
|
459
468
|
</thead>
|
|
460
469
|
<tbody id="health-body"></tbody>
|
|
@@ -463,23 +472,23 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
463
472
|
</section>
|
|
464
473
|
|
|
465
474
|
<section class="panel" data-view="audit" hidden>
|
|
466
|
-
<h2 class="panel-title"
|
|
475
|
+
<h2 class="panel-title" data-i18n="audit.title">\u914D\u7F6E\u5BA1\u8BA1</h2>
|
|
467
476
|
<div class="actions">
|
|
468
477
|
<label class="field" style="max-width: 120px;">
|
|
469
|
-
<span class="field-label"
|
|
478
|
+
<span class="field-label" data-i18n="audit.limit">\u6761\u6570</span>
|
|
470
479
|
<input id="audit-limit" type="number" min="1" max="200" value="30" />
|
|
471
480
|
</label>
|
|
472
|
-
<button id="audit-refresh-btn" type="button"
|
|
481
|
+
<button id="audit-refresh-btn" type="button" data-i18n="audit.refresh">\u5237\u65B0\u5BA1\u8BA1</button>
|
|
473
482
|
</div>
|
|
474
483
|
<div class="table-wrap">
|
|
475
484
|
<table>
|
|
476
485
|
<thead>
|
|
477
486
|
<tr>
|
|
478
|
-
<th>ID</th>
|
|
479
|
-
<th
|
|
480
|
-
<th
|
|
481
|
-
<th
|
|
482
|
-
<th
|
|
487
|
+
<th data-i18n="audit.table.id">ID</th>
|
|
488
|
+
<th data-i18n="audit.table.time">\u65F6\u95F4</th>
|
|
489
|
+
<th data-i18n="audit.table.actor">\u64CD\u4F5C\u8005</th>
|
|
490
|
+
<th data-i18n="audit.table.summary">\u6458\u8981</th>
|
|
491
|
+
<th data-i18n="audit.table.payload">\u8F7D\u8377</th>
|
|
483
492
|
</tr>
|
|
484
493
|
</thead>
|
|
485
494
|
<tbody id="audit-body"></tbody>
|
|
@@ -506,6 +515,264 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
506
515
|
};
|
|
507
516
|
var storageTokenKey = "codeharbor.admin.token";
|
|
508
517
|
var storageActorKey = "codeharbor.admin.actor";
|
|
518
|
+
var storageLangKey = "codeharbor.admin.lang";
|
|
519
|
+
var defaultLang = "zh";
|
|
520
|
+
var i18n = {
|
|
521
|
+
zh: {
|
|
522
|
+
"header.title": "CodeHarbor \u7BA1\u7406\u540E\u53F0",
|
|
523
|
+
"header.subtitle": "\u7BA1\u7406\u5168\u5C40\u914D\u7F6E\u3001\u623F\u95F4\u7B56\u7565\u3001\u5065\u5EB7\u68C0\u67E5\u4E0E\u914D\u7F6E\u5BA1\u8BA1\u8BB0\u5F55\u3002",
|
|
524
|
+
"tab.global": "\u5168\u5C40",
|
|
525
|
+
"tab.rooms": "\u623F\u95F4",
|
|
526
|
+
"tab.health": "\u5065\u5EB7",
|
|
527
|
+
"tab.audit": "\u5BA1\u8BA1",
|
|
528
|
+
"auth.token.label": "\u7BA1\u7406\u5458\u4EE4\u724C\uFF08\u53EF\u9009\uFF09",
|
|
529
|
+
"auth.token.placeholder": "ADMIN_TOKEN",
|
|
530
|
+
"auth.actor.label": "\u64CD\u4F5C\u8005\uFF08\u7528\u4E8E\u5BA1\u8BA1\u65E5\u5FD7\uFF09",
|
|
531
|
+
"auth.actor.placeholder": "\u4F60\u7684\u540D\u5B57",
|
|
532
|
+
"auth.language.label": "\u754C\u9762\u8BED\u8A00",
|
|
533
|
+
"auth.save": "\u4FDD\u5B58\u8BA4\u8BC1",
|
|
534
|
+
"auth.clear": "\u6E05\u9664\u8BA4\u8BC1",
|
|
535
|
+
"auth.permission.unknown": "\u6743\u9650\uFF1A\u672A\u77E5",
|
|
536
|
+
"auth.permission.unauth": "\u6743\u9650\uFF1A\u672A\u8BA4\u8BC1",
|
|
537
|
+
"auth.permission.prefix": "\u6743\u9650\uFF1A{role}{source}{actor}",
|
|
538
|
+
"auth.permission.actorSuffix": "\uFF08\u7528\u6237\uFF1A{actor}\uFF09",
|
|
539
|
+
"notice.ready": "\u5C31\u7EEA\u3002",
|
|
540
|
+
"notice.authSaved": "\u8BA4\u8BC1\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\u5230 localStorage\u3002",
|
|
541
|
+
"notice.authCleared": "\u8BA4\u8BC1\u8BBE\u7F6E\u5DF2\u6E05\u9664\u3002",
|
|
542
|
+
"global.title": "\u5168\u5C40\u914D\u7F6E",
|
|
543
|
+
"global.commandPrefix": "\u547D\u4EE4\u524D\u7F00",
|
|
544
|
+
"global.defaultWorkdir": "\u9ED8\u8BA4\u5DE5\u4F5C\u76EE\u5F55",
|
|
545
|
+
"global.progressInterval": "\u8FDB\u5EA6\u66F4\u65B0\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09",
|
|
546
|
+
"global.typingTimeout": "\u8F93\u5165\u72B6\u6001\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",
|
|
547
|
+
"global.sessionWindow": "\u4F1A\u8BDD\u6D3B\u8DC3\u7A97\u53E3\uFF08\u5206\u949F\uFF09",
|
|
548
|
+
"global.progressEnabled": "\u542F\u7528\u8FDB\u5EA6\u66F4\u65B0",
|
|
549
|
+
"global.rateWindow": "\u9650\u6D41\u7A97\u53E3\uFF08\u6BEB\u79D2\uFF09",
|
|
550
|
+
"global.rateUser": "\u5355\u7528\u6237\u7A97\u53E3\u6700\u5927\u8BF7\u6C42\u6570",
|
|
551
|
+
"global.rateRoom": "\u5355\u623F\u95F4\u7A97\u53E3\u6700\u5927\u8BF7\u6C42\u6570",
|
|
552
|
+
"global.concurrentGlobal": "\u5168\u5C40\u6700\u5927\u5E76\u53D1",
|
|
553
|
+
"global.concurrentUser": "\u5355\u7528\u6237\u6700\u5927\u5E76\u53D1",
|
|
554
|
+
"global.concurrentRoom": "\u5355\u623F\u95F4\u6700\u5927\u5E76\u53D1",
|
|
555
|
+
"global.groupDirect": "\u7FA4\u804A\u76F4\u901A\u6A21\u5F0F\uFF08\u65E0\u9700\u89E6\u53D1\uFF09",
|
|
556
|
+
"global.triggerMention": "\u89E6\u53D1\uFF1A\u63D0\u53CA\u673A\u5668\u4EBA",
|
|
557
|
+
"global.triggerReply": "\u89E6\u53D1\uFF1A\u56DE\u590D\u673A\u5668\u4EBA",
|
|
558
|
+
"global.triggerWindow": "\u89E6\u53D1\uFF1A\u6D3B\u8DC3\u7A97\u53E3",
|
|
559
|
+
"global.triggerPrefix": "\u89E6\u53D1\uFF1A\u547D\u4EE4\u524D\u7F00",
|
|
560
|
+
"global.cliEnabled": "CLI \u517C\u5BB9\u6A21\u5F0F",
|
|
561
|
+
"global.cliPass": "CLI \u900F\u4F20\u4E8B\u4EF6",
|
|
562
|
+
"global.cliWhitespace": "\u4FDD\u7559\u7A7A\u767D\u7B26",
|
|
563
|
+
"global.cliDisableSplit": "\u7981\u7528\u56DE\u590D\u5206\u7247",
|
|
564
|
+
"global.cliThrottle": "CLI \u8FDB\u5EA6\u8282\u6D41\uFF08\u6BEB\u79D2\uFF09",
|
|
565
|
+
"global.cliFetchMedia": "\u4E0B\u8F7D\u5A92\u4F53\u9644\u4EF6",
|
|
566
|
+
"global.cliTranscribeAudio": "\u8F6C\u5199\u97F3\u9891\u9644\u4EF6",
|
|
567
|
+
"global.audioModel": "\u97F3\u9891\u8F6C\u5199\u6A21\u578B",
|
|
568
|
+
"global.audioTimeout": "\u97F3\u9891\u8F6C\u5199\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",
|
|
569
|
+
"global.audioMaxChars": "\u97F3\u9891\u8F6C\u5199\u6700\u5927\u5B57\u7B26\u6570",
|
|
570
|
+
"global.audioMaxRetries": "\u97F3\u9891\u8F6C\u5199\u6700\u5927\u91CD\u8BD5\u6B21\u6570",
|
|
571
|
+
"global.audioRetryDelay": "\u97F3\u9891\u8F6C\u5199\u91CD\u8BD5\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09",
|
|
572
|
+
"global.audioMaxBytes": "\u97F3\u9891\u6700\u5927\u5B57\u8282\u6570",
|
|
573
|
+
"global.audioLocalCommand": "\u672C\u5730 Whisper \u547D\u4EE4",
|
|
574
|
+
"global.audioLocalCommandPlaceholder": "python3 /opt/whisper/transcribe.py --input {input}",
|
|
575
|
+
"global.audioLocalTimeout": "\u672C\u5730 Whisper \u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",
|
|
576
|
+
"global.agentEnabled": "\u542F\u7528\u591A\u667A\u80FD\u4F53\u5DE5\u4F5C\u6D41",
|
|
577
|
+
"global.agentRounds": "\u5DE5\u4F5C\u6D41\u81EA\u52A8\u4FEE\u590D\u8F6E\u6B21",
|
|
578
|
+
"global.save": "\u4FDD\u5B58\u5168\u5C40\u914D\u7F6E",
|
|
579
|
+
"global.reload": "\u91CD\u65B0\u52A0\u8F7D",
|
|
580
|
+
"global.restartMain": "\u91CD\u542F\u4E3B\u670D\u52A1",
|
|
581
|
+
"global.restartAll": "\u91CD\u542F\u4E3B\u670D\u52A1+\u7BA1\u7406\u540E\u53F0",
|
|
582
|
+
"global.restartHint": "\u4FDD\u5B58\u5168\u5C40\u914D\u7F6E\u4F1A\u66F4\u65B0 .env\uFF0C\u5E76\u9700\u8981\u91CD\u542F\u540E\u5B8C\u5168\u751F\u6548\u3002",
|
|
583
|
+
"notice.globalLoaded": "\u5168\u5C40\u914D\u7F6E\u5DF2\u52A0\u8F7D\u3002",
|
|
584
|
+
"notice.globalLoadFailed": "\u52A0\u8F7D\u5168\u5C40\u914D\u7F6E\u5931\u8D25\uFF1A{error}",
|
|
585
|
+
"notice.globalSaved": "\u4FDD\u5B58\u6210\u529F\uFF1A{keys}\u3002\u9700\u8981\u91CD\u542F\u540E\u751F\u6548\u3002",
|
|
586
|
+
"notice.globalSaveFailed": "\u4FDD\u5B58\u5168\u5C40\u914D\u7F6E\u5931\u8D25\uFF1A{error}",
|
|
587
|
+
"notice.restartRequested": "\u5DF2\u8BF7\u6C42\u91CD\u542F\uFF1A{services}\u3002{suffix}",
|
|
588
|
+
"notice.restartFailed": "\u91CD\u542F\u670D\u52A1\u5931\u8D25\uFF1A{error}",
|
|
589
|
+
"notice.restartSuffixAll": "\u7BA1\u7406\u540E\u53F0\u9875\u9762\u53EF\u80FD\u5728\u91CD\u542F\u671F\u95F4\u77ED\u6682\u65AD\u8FDE\u3002",
|
|
590
|
+
"rooms.title": "\u623F\u95F4\u914D\u7F6E",
|
|
591
|
+
"rooms.roomId": "\u623F\u95F4 ID",
|
|
592
|
+
"rooms.roomIdPlaceholder": "!room:example.com",
|
|
593
|
+
"rooms.summary": "\u5BA1\u8BA1\u6458\u8981\uFF08\u53EF\u9009\uFF09",
|
|
594
|
+
"rooms.summaryPlaceholder": "\u7ED1\u5B9A\u623F\u95F4\u5230\u9879\u76EE A",
|
|
595
|
+
"rooms.workdir": "\u5DE5\u4F5C\u76EE\u5F55",
|
|
596
|
+
"rooms.enabled": "\u542F\u7528",
|
|
597
|
+
"rooms.allowMention": "\u5141\u8BB8\u63D0\u53CA\u89E6\u53D1",
|
|
598
|
+
"rooms.allowReply": "\u5141\u8BB8\u56DE\u590D\u89E6\u53D1",
|
|
599
|
+
"rooms.allowWindow": "\u5141\u8BB8\u6D3B\u8DC3\u7A97\u53E3\u89E6\u53D1",
|
|
600
|
+
"rooms.allowPrefix": "\u5141\u8BB8\u524D\u7F00\u89E6\u53D1",
|
|
601
|
+
"rooms.load": "\u52A0\u8F7D\u623F\u95F4",
|
|
602
|
+
"rooms.save": "\u4FDD\u5B58\u623F\u95F4",
|
|
603
|
+
"rooms.delete": "\u5220\u9664\u623F\u95F4",
|
|
604
|
+
"rooms.refresh": "\u5237\u65B0\u5217\u8868",
|
|
605
|
+
"rooms.table.roomId": "\u623F\u95F4 ID",
|
|
606
|
+
"rooms.table.enabled": "\u542F\u7528",
|
|
607
|
+
"rooms.table.workdir": "\u5DE5\u4F5C\u76EE\u5F55",
|
|
608
|
+
"rooms.table.updatedAt": "\u66F4\u65B0\u65F6\u95F4",
|
|
609
|
+
"notice.roomsEmpty": "\u6682\u65E0\u623F\u95F4\u914D\u7F6E\u3002",
|
|
610
|
+
"notice.roomsLoaded": "\u5DF2\u52A0\u8F7D {count} \u6761\u623F\u95F4\u914D\u7F6E\u3002",
|
|
611
|
+
"notice.roomsLoadFailed": "\u52A0\u8F7D\u623F\u95F4\u5217\u8868\u5931\u8D25\uFF1A{error}",
|
|
612
|
+
"notice.roomIdRequired": "\u623F\u95F4 ID \u4E0D\u80FD\u4E3A\u7A7A\u3002",
|
|
613
|
+
"notice.roomLoaded": "\u623F\u95F4\u914D\u7F6E\u5DF2\u52A0\u8F7D\uFF1A{roomId}\u3002",
|
|
614
|
+
"notice.roomLoadFailed": "\u52A0\u8F7D\u623F\u95F4\u914D\u7F6E\u5931\u8D25\uFF1A{error}",
|
|
615
|
+
"notice.roomSaved": "\u623F\u95F4\u914D\u7F6E\u5DF2\u4FDD\u5B58\uFF1A{roomId}\u3002",
|
|
616
|
+
"notice.roomSaveFailed": "\u4FDD\u5B58\u623F\u95F4\u914D\u7F6E\u5931\u8D25\uFF1A{error}",
|
|
617
|
+
"notice.roomDeleted": "\u623F\u95F4\u914D\u7F6E\u5DF2\u5220\u9664\uFF1A{roomId}\u3002",
|
|
618
|
+
"notice.roomDeleteFailed": "\u5220\u9664\u623F\u95F4\u914D\u7F6E\u5931\u8D25\uFF1A{error}",
|
|
619
|
+
"confirm.roomDelete": "\u786E\u8BA4\u5220\u9664\u623F\u95F4\u914D\u7F6E\uFF1A{roomId}\uFF1F",
|
|
620
|
+
"health.title": "\u5065\u5EB7\u68C0\u67E5",
|
|
621
|
+
"health.run": "\u6267\u884C\u5065\u5EB7\u68C0\u67E5",
|
|
622
|
+
"health.table.component": "\u7EC4\u4EF6",
|
|
623
|
+
"health.table.status": "\u72B6\u6001",
|
|
624
|
+
"health.table.details": "\u8BE6\u60C5",
|
|
625
|
+
"health.component.codex": "Codex",
|
|
626
|
+
"health.component.matrix": "Matrix",
|
|
627
|
+
"health.component.overall": "\u6574\u4F53",
|
|
628
|
+
"health.status.ok": "\u6B63\u5E38",
|
|
629
|
+
"health.status.fail": "\u5931\u8D25",
|
|
630
|
+
"notice.healthDone": "\u5065\u5EB7\u68C0\u67E5\u5B8C\u6210\u3002",
|
|
631
|
+
"notice.healthFailed": "\u5065\u5EB7\u68C0\u67E5\u5931\u8D25\uFF1A{error}",
|
|
632
|
+
"notice.healthEmptyFailed": "\u5065\u5EB7\u68C0\u67E5\u6267\u884C\u5931\u8D25\u3002",
|
|
633
|
+
"audit.title": "\u914D\u7F6E\u5BA1\u8BA1",
|
|
634
|
+
"audit.limit": "\u6761\u6570",
|
|
635
|
+
"audit.refresh": "\u5237\u65B0\u5BA1\u8BA1",
|
|
636
|
+
"audit.table.id": "ID",
|
|
637
|
+
"audit.table.time": "\u65F6\u95F4",
|
|
638
|
+
"audit.table.actor": "\u64CD\u4F5C\u8005",
|
|
639
|
+
"audit.table.summary": "\u6458\u8981",
|
|
640
|
+
"audit.table.payload": "\u8F7D\u8377",
|
|
641
|
+
"notice.auditEmpty": "\u6682\u65E0\u5BA1\u8BA1\u8BB0\u5F55\u3002",
|
|
642
|
+
"notice.auditLoaded": "\u5BA1\u8BA1\u8BB0\u5F55\u5DF2\u52A0\u8F7D\uFF1A{count} \u6761\u3002",
|
|
643
|
+
"notice.auditLoadFailed": "\u52A0\u8F7D\u5BA1\u8BA1\u8BB0\u5F55\u5931\u8D25\uFF1A{error}",
|
|
644
|
+
"table.loadFailed": "\u52A0\u8F7D\u5931\u8D25\u3002"
|
|
645
|
+
},
|
|
646
|
+
en: {
|
|
647
|
+
"header.title": "CodeHarbor Admin Console",
|
|
648
|
+
"header.subtitle": "Manage global settings, room policies, health checks, and config audit records.",
|
|
649
|
+
"tab.global": "Global",
|
|
650
|
+
"tab.rooms": "Rooms",
|
|
651
|
+
"tab.health": "Health",
|
|
652
|
+
"tab.audit": "Audit",
|
|
653
|
+
"auth.token.label": "Admin Token (optional)",
|
|
654
|
+
"auth.token.placeholder": "ADMIN_TOKEN",
|
|
655
|
+
"auth.actor.label": "Actor (for audit logs)",
|
|
656
|
+
"auth.actor.placeholder": "your-name",
|
|
657
|
+
"auth.language.label": "Language",
|
|
658
|
+
"auth.save": "Save Auth",
|
|
659
|
+
"auth.clear": "Clear Auth",
|
|
660
|
+
"auth.permission.unknown": "Permission: unknown",
|
|
661
|
+
"auth.permission.unauth": "Permission: unauthenticated",
|
|
662
|
+
"auth.permission.prefix": "Permission: {role}{source}{actor}",
|
|
663
|
+
"auth.permission.actorSuffix": " as {actor}",
|
|
664
|
+
"notice.ready": "Ready.",
|
|
665
|
+
"notice.authSaved": "Auth settings saved to localStorage.",
|
|
666
|
+
"notice.authCleared": "Auth settings cleared.",
|
|
667
|
+
"global.title": "Global Config",
|
|
668
|
+
"global.commandPrefix": "Command Prefix",
|
|
669
|
+
"global.defaultWorkdir": "Default Workdir",
|
|
670
|
+
"global.progressInterval": "Progress Interval (ms)",
|
|
671
|
+
"global.typingTimeout": "Typing Timeout (ms)",
|
|
672
|
+
"global.sessionWindow": "Session Active Window (minutes)",
|
|
673
|
+
"global.progressEnabled": "Enable progress updates",
|
|
674
|
+
"global.rateWindow": "Rate Window (ms)",
|
|
675
|
+
"global.rateUser": "Rate Max Requests / User",
|
|
676
|
+
"global.rateRoom": "Rate Max Requests / Room",
|
|
677
|
+
"global.concurrentGlobal": "Max Concurrent Global",
|
|
678
|
+
"global.concurrentUser": "Max Concurrent / User",
|
|
679
|
+
"global.concurrentRoom": "Max Concurrent / Room",
|
|
680
|
+
"global.groupDirect": "Group direct mode (no trigger required)",
|
|
681
|
+
"global.triggerMention": "Trigger: mention",
|
|
682
|
+
"global.triggerReply": "Trigger: reply",
|
|
683
|
+
"global.triggerWindow": "Trigger: active window",
|
|
684
|
+
"global.triggerPrefix": "Trigger: prefix",
|
|
685
|
+
"global.cliEnabled": "CLI compat mode",
|
|
686
|
+
"global.cliPass": "CLI passthrough events",
|
|
687
|
+
"global.cliWhitespace": "Preserve whitespace",
|
|
688
|
+
"global.cliDisableSplit": "Disable reply split",
|
|
689
|
+
"global.cliThrottle": "CLI progress throttle (ms)",
|
|
690
|
+
"global.cliFetchMedia": "Fetch media attachments",
|
|
691
|
+
"global.cliTranscribeAudio": "Transcribe audio attachments",
|
|
692
|
+
"global.audioModel": "Audio transcribe model",
|
|
693
|
+
"global.audioTimeout": "Audio transcribe timeout (ms)",
|
|
694
|
+
"global.audioMaxChars": "Audio transcript max chars",
|
|
695
|
+
"global.audioMaxRetries": "Audio transcribe max retries",
|
|
696
|
+
"global.audioRetryDelay": "Audio transcribe retry delay (ms)",
|
|
697
|
+
"global.audioMaxBytes": "Audio max bytes",
|
|
698
|
+
"global.audioLocalCommand": "Local whisper command",
|
|
699
|
+
"global.audioLocalCommandPlaceholder": "python3 /opt/whisper/transcribe.py --input {input}",
|
|
700
|
+
"global.audioLocalTimeout": "Local whisper timeout (ms)",
|
|
701
|
+
"global.agentEnabled": "Enable multi-agent workflow",
|
|
702
|
+
"global.agentRounds": "Workflow auto-repair rounds",
|
|
703
|
+
"global.save": "Save Global Config",
|
|
704
|
+
"global.reload": "Reload",
|
|
705
|
+
"global.restartMain": "Restart Main Service",
|
|
706
|
+
"global.restartAll": "Restart Main + Admin",
|
|
707
|
+
"global.restartHint": "Saving global config updates .env and requires restart to fully take effect.",
|
|
708
|
+
"notice.globalLoaded": "Global config loaded.",
|
|
709
|
+
"notice.globalLoadFailed": "Failed to load global config: {error}",
|
|
710
|
+
"notice.globalSaved": "Saved: {keys}. Restart is required.",
|
|
711
|
+
"notice.globalSaveFailed": "Failed to save global config: {error}",
|
|
712
|
+
"notice.restartRequested": "Restart requested: {services}. {suffix}",
|
|
713
|
+
"notice.restartFailed": "Failed to restart service(s): {error}",
|
|
714
|
+
"notice.restartSuffixAll": "Admin page may reconnect during restart.",
|
|
715
|
+
"rooms.title": "Room Config",
|
|
716
|
+
"rooms.roomId": "Room ID",
|
|
717
|
+
"rooms.roomIdPlaceholder": "!room:example.com",
|
|
718
|
+
"rooms.summary": "Audit Summary (optional)",
|
|
719
|
+
"rooms.summaryPlaceholder": "bind room to project A",
|
|
720
|
+
"rooms.workdir": "Workdir",
|
|
721
|
+
"rooms.enabled": "Enabled",
|
|
722
|
+
"rooms.allowMention": "Allow mention trigger",
|
|
723
|
+
"rooms.allowReply": "Allow reply trigger",
|
|
724
|
+
"rooms.allowWindow": "Allow active-window trigger",
|
|
725
|
+
"rooms.allowPrefix": "Allow prefix trigger",
|
|
726
|
+
"rooms.load": "Load Room",
|
|
727
|
+
"rooms.save": "Save Room",
|
|
728
|
+
"rooms.delete": "Delete Room",
|
|
729
|
+
"rooms.refresh": "Refresh List",
|
|
730
|
+
"rooms.table.roomId": "Room ID",
|
|
731
|
+
"rooms.table.enabled": "Enabled",
|
|
732
|
+
"rooms.table.workdir": "Workdir",
|
|
733
|
+
"rooms.table.updatedAt": "Updated At",
|
|
734
|
+
"notice.roomsEmpty": "No room settings.",
|
|
735
|
+
"notice.roomsLoaded": "Loaded {count} room setting(s).",
|
|
736
|
+
"notice.roomsLoadFailed": "Failed to load room list: {error}",
|
|
737
|
+
"notice.roomIdRequired": "Room ID is required.",
|
|
738
|
+
"notice.roomLoaded": "Room config loaded for {roomId}.",
|
|
739
|
+
"notice.roomLoadFailed": "Failed to load room config: {error}",
|
|
740
|
+
"notice.roomSaved": "Room config saved for {roomId}.",
|
|
741
|
+
"notice.roomSaveFailed": "Failed to save room config: {error}",
|
|
742
|
+
"notice.roomDeleted": "Room config deleted for {roomId}.",
|
|
743
|
+
"notice.roomDeleteFailed": "Failed to delete room config: {error}",
|
|
744
|
+
"confirm.roomDelete": "Delete room config for {roomId}?",
|
|
745
|
+
"health.title": "Health Check",
|
|
746
|
+
"health.run": "Run Health Check",
|
|
747
|
+
"health.table.component": "Component",
|
|
748
|
+
"health.table.status": "Status",
|
|
749
|
+
"health.table.details": "Details",
|
|
750
|
+
"health.component.codex": "Codex",
|
|
751
|
+
"health.component.matrix": "Matrix",
|
|
752
|
+
"health.component.overall": "Overall",
|
|
753
|
+
"health.status.ok": "OK",
|
|
754
|
+
"health.status.fail": "FAIL",
|
|
755
|
+
"notice.healthDone": "Health check completed.",
|
|
756
|
+
"notice.healthFailed": "Health check failed: {error}",
|
|
757
|
+
"notice.healthEmptyFailed": "Failed to run health check.",
|
|
758
|
+
"audit.title": "Config Audit",
|
|
759
|
+
"audit.limit": "Limit",
|
|
760
|
+
"audit.refresh": "Refresh Audit",
|
|
761
|
+
"audit.table.id": "ID",
|
|
762
|
+
"audit.table.time": "Time",
|
|
763
|
+
"audit.table.actor": "Actor",
|
|
764
|
+
"audit.table.summary": "Summary",
|
|
765
|
+
"audit.table.payload": "Payload",
|
|
766
|
+
"notice.auditEmpty": "No audit records.",
|
|
767
|
+
"notice.auditLoaded": "Audit loaded: {count} record(s).",
|
|
768
|
+
"notice.auditLoadFailed": "Failed to load audit: {error}",
|
|
769
|
+
"table.loadFailed": "Failed to load."
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
var currentLang = localStorage.getItem(storageLangKey);
|
|
773
|
+
if (currentLang !== "en" && currentLang !== "zh") {
|
|
774
|
+
currentLang = defaultLang;
|
|
775
|
+
}
|
|
509
776
|
var loaded = {
|
|
510
777
|
"settings-global": false,
|
|
511
778
|
"settings-rooms": false,
|
|
@@ -515,6 +782,7 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
515
782
|
|
|
516
783
|
var tokenInput = document.getElementById("auth-token");
|
|
517
784
|
var actorInput = document.getElementById("auth-actor");
|
|
785
|
+
var langSelect = document.getElementById("lang-select");
|
|
518
786
|
var noticeNode = document.getElementById("notice");
|
|
519
787
|
var authRoleNode = document.getElementById("auth-role");
|
|
520
788
|
var roomListBody = document.getElementById("room-list-body");
|
|
@@ -523,11 +791,19 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
523
791
|
|
|
524
792
|
tokenInput.value = localStorage.getItem(storageTokenKey) || "";
|
|
525
793
|
actorInput.value = localStorage.getItem(storageActorKey) || "";
|
|
794
|
+
langSelect.value = currentLang;
|
|
795
|
+
|
|
796
|
+
langSelect.addEventListener("change", function () {
|
|
797
|
+
currentLang = langSelect.value === "en" ? "en" : "zh";
|
|
798
|
+
localStorage.setItem(storageLangKey, currentLang);
|
|
799
|
+
applyLanguage();
|
|
800
|
+
void refreshAuthStatus();
|
|
801
|
+
});
|
|
526
802
|
|
|
527
803
|
document.getElementById("auth-save-btn").addEventListener("click", function () {
|
|
528
804
|
localStorage.setItem(storageTokenKey, tokenInput.value.trim());
|
|
529
805
|
localStorage.setItem(storageActorKey, actorInput.value.trim());
|
|
530
|
-
showNotice("ok", "
|
|
806
|
+
showNotice("ok", t("notice.authSaved"));
|
|
531
807
|
void refreshAuthStatus();
|
|
532
808
|
});
|
|
533
809
|
|
|
@@ -536,7 +812,7 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
536
812
|
actorInput.value = "";
|
|
537
813
|
localStorage.removeItem(storageTokenKey);
|
|
538
814
|
localStorage.removeItem(storageActorKey);
|
|
539
|
-
showNotice("warn", "
|
|
815
|
+
showNotice("warn", t("notice.authCleared"));
|
|
540
816
|
void refreshAuthStatus();
|
|
541
817
|
});
|
|
542
818
|
|
|
@@ -562,6 +838,8 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
562
838
|
} else {
|
|
563
839
|
handleRoute();
|
|
564
840
|
}
|
|
841
|
+
applyLanguage();
|
|
842
|
+
showNotice("ok", t("notice.ready"));
|
|
565
843
|
void refreshAuthStatus();
|
|
566
844
|
|
|
567
845
|
function getCurrentView() {
|
|
@@ -648,6 +926,42 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
648
926
|
return document.getElementById(inputId).value.trim();
|
|
649
927
|
}
|
|
650
928
|
|
|
929
|
+
function t(key, vars) {
|
|
930
|
+
var dict = i18n[currentLang] || i18n[defaultLang];
|
|
931
|
+
var template = dict[key] || key;
|
|
932
|
+
if (!vars) {
|
|
933
|
+
return template;
|
|
934
|
+
}
|
|
935
|
+
return template.replace(/{([a-zA-Z0-9_]+)}/g, function (_all, name) {
|
|
936
|
+
return vars[name] === undefined || vars[name] === null ? "" : String(vars[name]);
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
function applyLanguage() {
|
|
941
|
+
var nodes = document.querySelectorAll("[data-i18n]");
|
|
942
|
+
for (var i = 0; i < nodes.length; i += 1) {
|
|
943
|
+
var node = nodes[i];
|
|
944
|
+
var key = node.getAttribute("data-i18n");
|
|
945
|
+
if (!key) {
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
node.textContent = t(key);
|
|
949
|
+
}
|
|
950
|
+
var placeholderNodes = document.querySelectorAll("[data-i18n-placeholder]");
|
|
951
|
+
for (var j = 0; j < placeholderNodes.length; j += 1) {
|
|
952
|
+
var input = placeholderNodes[j];
|
|
953
|
+
var placeholderKey = input.getAttribute("data-i18n-placeholder");
|
|
954
|
+
if (!placeholderKey) {
|
|
955
|
+
continue;
|
|
956
|
+
}
|
|
957
|
+
input.setAttribute("placeholder", t(placeholderKey));
|
|
958
|
+
}
|
|
959
|
+
document.documentElement.lang = currentLang === "en" ? "en" : "zh-CN";
|
|
960
|
+
if (langSelect.value !== currentLang) {
|
|
961
|
+
langSelect.value = currentLang;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
651
965
|
function showNotice(type, message) {
|
|
652
966
|
noticeNode.className = "notice " + type;
|
|
653
967
|
noticeNode.textContent = message;
|
|
@@ -658,21 +972,25 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
658
972
|
var response = await apiRequest("/api/admin/auth/status", "GET");
|
|
659
973
|
var data = response.data || {};
|
|
660
974
|
if (!data.role) {
|
|
661
|
-
authRoleNode.textContent = "
|
|
975
|
+
authRoleNode.textContent = t("auth.permission.unauth");
|
|
662
976
|
return;
|
|
663
977
|
}
|
|
664
978
|
|
|
665
979
|
var role = String(data.role).toUpperCase();
|
|
666
980
|
var source = data.source ? " (" + String(data.source) + ")" : "";
|
|
667
|
-
var actor = data.actor ? "
|
|
668
|
-
authRoleNode.textContent = "
|
|
981
|
+
var actor = data.actor ? t("auth.permission.actorSuffix", { actor: String(data.actor) }) : "";
|
|
982
|
+
authRoleNode.textContent = t("auth.permission.prefix", {
|
|
983
|
+
role: role,
|
|
984
|
+
source: source,
|
|
985
|
+
actor: actor
|
|
986
|
+
});
|
|
669
987
|
} catch (error) {
|
|
670
988
|
var message = error && error.message ? String(error.message) : "";
|
|
671
989
|
if (/Unauthorized/i.test(message)) {
|
|
672
|
-
authRoleNode.textContent = "
|
|
990
|
+
authRoleNode.textContent = t("auth.permission.unauth");
|
|
673
991
|
return;
|
|
674
992
|
}
|
|
675
|
-
authRoleNode.textContent = "
|
|
993
|
+
authRoleNode.textContent = t("auth.permission.unknown");
|
|
676
994
|
}
|
|
677
995
|
}
|
|
678
996
|
|
|
@@ -736,9 +1054,9 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
736
1054
|
typeof agentWorkflow.autoRepairMaxRounds === "number" ? agentWorkflow.autoRepairMaxRounds : 1
|
|
737
1055
|
);
|
|
738
1056
|
|
|
739
|
-
showNotice("ok", "
|
|
1057
|
+
showNotice("ok", t("notice.globalLoaded"));
|
|
740
1058
|
} catch (error) {
|
|
741
|
-
showNotice("error", "
|
|
1059
|
+
showNotice("error", t("notice.globalLoadFailed", { error: error.message }));
|
|
742
1060
|
}
|
|
743
1061
|
}
|
|
744
1062
|
|
|
@@ -790,10 +1108,10 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
790
1108
|
};
|
|
791
1109
|
var response = await apiRequest("/api/admin/config/global", "PUT", body);
|
|
792
1110
|
var keys = Array.isArray(response.updatedKeys) ? response.updatedKeys.join(", ") : "global config";
|
|
793
|
-
showNotice("warn", "
|
|
1111
|
+
showNotice("warn", t("notice.globalSaved", { keys: keys }));
|
|
794
1112
|
await loadAudit();
|
|
795
1113
|
} catch (error) {
|
|
796
|
-
showNotice("error", "
|
|
1114
|
+
showNotice("error", t("notice.globalSaveFailed", { error: error.message }));
|
|
797
1115
|
}
|
|
798
1116
|
}
|
|
799
1117
|
|
|
@@ -803,10 +1121,10 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
803
1121
|
withAdmin: Boolean(withAdmin)
|
|
804
1122
|
});
|
|
805
1123
|
var restarted = Array.isArray(response.restarted) ? response.restarted.join(", ") : "codeharbor";
|
|
806
|
-
var suffix = withAdmin ? "
|
|
807
|
-
showNotice("warn", "
|
|
1124
|
+
var suffix = withAdmin ? t("notice.restartSuffixAll") : "";
|
|
1125
|
+
showNotice("warn", t("notice.restartRequested", { services: restarted, suffix: suffix }));
|
|
808
1126
|
} catch (error) {
|
|
809
|
-
showNotice("error", "
|
|
1127
|
+
showNotice("error", t("notice.restartFailed", { error: error.message }));
|
|
810
1128
|
}
|
|
811
1129
|
}
|
|
812
1130
|
|
|
@@ -816,7 +1134,7 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
816
1134
|
var items = Array.isArray(response.data) ? response.data : [];
|
|
817
1135
|
roomListBody.innerHTML = "";
|
|
818
1136
|
if (items.length === 0) {
|
|
819
|
-
renderEmptyRow(roomListBody, 4, "
|
|
1137
|
+
renderEmptyRow(roomListBody, 4, t("notice.roomsEmpty"));
|
|
820
1138
|
return;
|
|
821
1139
|
}
|
|
822
1140
|
for (var i = 0; i < items.length; i += 1) {
|
|
@@ -828,10 +1146,10 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
828
1146
|
appendCell(row, item.updatedAt ? new Date(item.updatedAt).toISOString() : "-");
|
|
829
1147
|
roomListBody.appendChild(row);
|
|
830
1148
|
}
|
|
831
|
-
showNotice("ok", "
|
|
1149
|
+
showNotice("ok", t("notice.roomsLoaded", { count: items.length }));
|
|
832
1150
|
} catch (error) {
|
|
833
|
-
showNotice("error", "
|
|
834
|
-
renderEmptyRow(roomListBody, 4, "
|
|
1151
|
+
showNotice("error", t("notice.roomsLoadFailed", { error: error.message }));
|
|
1152
|
+
renderEmptyRow(roomListBody, 4, t("table.loadFailed"));
|
|
835
1153
|
}
|
|
836
1154
|
}
|
|
837
1155
|
|
|
@@ -844,15 +1162,15 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
844
1162
|
async function loadRoom() {
|
|
845
1163
|
var roomId = asText("room-id");
|
|
846
1164
|
if (!roomId) {
|
|
847
|
-
showNotice("warn", "
|
|
1165
|
+
showNotice("warn", t("notice.roomIdRequired"));
|
|
848
1166
|
return;
|
|
849
1167
|
}
|
|
850
1168
|
try {
|
|
851
1169
|
var response = await apiRequest("/api/admin/config/rooms/" + encodeURIComponent(roomId), "GET");
|
|
852
1170
|
fillRoomForm(response.data || {});
|
|
853
|
-
showNotice("ok", "
|
|
1171
|
+
showNotice("ok", t("notice.roomLoaded", { roomId: roomId }));
|
|
854
1172
|
} catch (error) {
|
|
855
|
-
showNotice("error", "
|
|
1173
|
+
showNotice("error", t("notice.roomLoadFailed", { error: error.message }));
|
|
856
1174
|
}
|
|
857
1175
|
}
|
|
858
1176
|
|
|
@@ -868,7 +1186,7 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
868
1186
|
async function saveRoom() {
|
|
869
1187
|
var roomId = asText("room-id");
|
|
870
1188
|
if (!roomId) {
|
|
871
|
-
showNotice("warn", "
|
|
1189
|
+
showNotice("warn", t("notice.roomIdRequired"));
|
|
872
1190
|
return;
|
|
873
1191
|
}
|
|
874
1192
|
try {
|
|
@@ -882,30 +1200,30 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
882
1200
|
summary: asText("room-summary")
|
|
883
1201
|
};
|
|
884
1202
|
await apiRequest("/api/admin/config/rooms/" + encodeURIComponent(roomId), "PUT", body);
|
|
885
|
-
showNotice("ok", "
|
|
1203
|
+
showNotice("ok", t("notice.roomSaved", { roomId: roomId }));
|
|
886
1204
|
await refreshRoomList();
|
|
887
1205
|
await loadAudit();
|
|
888
1206
|
} catch (error) {
|
|
889
|
-
showNotice("error", "
|
|
1207
|
+
showNotice("error", t("notice.roomSaveFailed", { error: error.message }));
|
|
890
1208
|
}
|
|
891
1209
|
}
|
|
892
1210
|
|
|
893
1211
|
async function deleteRoom() {
|
|
894
1212
|
var roomId = asText("room-id");
|
|
895
1213
|
if (!roomId) {
|
|
896
|
-
showNotice("warn", "
|
|
1214
|
+
showNotice("warn", t("notice.roomIdRequired"));
|
|
897
1215
|
return;
|
|
898
1216
|
}
|
|
899
|
-
if (!window.confirm("
|
|
1217
|
+
if (!window.confirm(t("confirm.roomDelete", { roomId: roomId }))) {
|
|
900
1218
|
return;
|
|
901
1219
|
}
|
|
902
1220
|
try {
|
|
903
1221
|
await apiRequest("/api/admin/config/rooms/" + encodeURIComponent(roomId), "DELETE");
|
|
904
|
-
showNotice("ok", "
|
|
1222
|
+
showNotice("ok", t("notice.roomDeleted", { roomId: roomId }));
|
|
905
1223
|
await refreshRoomList();
|
|
906
1224
|
await loadAudit();
|
|
907
1225
|
} catch (error) {
|
|
908
|
-
showNotice("error", "
|
|
1226
|
+
showNotice("error", t("notice.roomDeleteFailed", { error: error.message }));
|
|
909
1227
|
}
|
|
910
1228
|
}
|
|
911
1229
|
|
|
@@ -917,24 +1235,30 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
917
1235
|
var codex = response.codex || {};
|
|
918
1236
|
var matrix = response.matrix || {};
|
|
919
1237
|
|
|
920
|
-
appendHealthRow("Codex", Boolean(codex.ok), codex.ok ? (codex.version || "ok") : (codex.error || "failed"));
|
|
921
1238
|
appendHealthRow(
|
|
922
|
-
"
|
|
1239
|
+
t("health.component.codex"),
|
|
1240
|
+
Boolean(codex.ok),
|
|
1241
|
+
codex.ok ? (codex.version || t("health.status.ok")) : (codex.error || t("health.status.fail"))
|
|
1242
|
+
);
|
|
1243
|
+
appendHealthRow(
|
|
1244
|
+
t("health.component.matrix"),
|
|
923
1245
|
Boolean(matrix.ok),
|
|
924
|
-
matrix.ok
|
|
1246
|
+
matrix.ok
|
|
1247
|
+
? "HTTP " + matrix.status + " " + JSON.stringify(matrix.versions || [])
|
|
1248
|
+
: (matrix.error || t("health.status.fail"))
|
|
925
1249
|
);
|
|
926
|
-
appendHealthRow("
|
|
927
|
-
showNotice("ok", "
|
|
1250
|
+
appendHealthRow(t("health.component.overall"), Boolean(response.ok), response.timestamp || "");
|
|
1251
|
+
showNotice("ok", t("notice.healthDone"));
|
|
928
1252
|
} catch (error) {
|
|
929
|
-
showNotice("error", "
|
|
930
|
-
renderEmptyRow(healthBody, 3, "
|
|
1253
|
+
showNotice("error", t("notice.healthFailed", { error: error.message }));
|
|
1254
|
+
renderEmptyRow(healthBody, 3, t("notice.healthEmptyFailed"));
|
|
931
1255
|
}
|
|
932
1256
|
}
|
|
933
1257
|
|
|
934
1258
|
function appendHealthRow(component, ok, detail) {
|
|
935
1259
|
var row = document.createElement("tr");
|
|
936
1260
|
appendCell(row, component);
|
|
937
|
-
appendCell(row, ok ? "
|
|
1261
|
+
appendCell(row, ok ? t("health.status.ok") : t("health.status.fail"));
|
|
938
1262
|
appendCell(row, detail);
|
|
939
1263
|
healthBody.appendChild(row);
|
|
940
1264
|
}
|
|
@@ -952,7 +1276,7 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
952
1276
|
var items = Array.isArray(response.data) ? response.data : [];
|
|
953
1277
|
auditBody.innerHTML = "";
|
|
954
1278
|
if (items.length === 0) {
|
|
955
|
-
renderEmptyRow(auditBody, 5, "
|
|
1279
|
+
renderEmptyRow(auditBody, 5, t("notice.auditEmpty"));
|
|
956
1280
|
return;
|
|
957
1281
|
}
|
|
958
1282
|
for (var i = 0; i < items.length; i += 1) {
|
|
@@ -969,10 +1293,10 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
969
1293
|
row.appendChild(payloadCell);
|
|
970
1294
|
auditBody.appendChild(row);
|
|
971
1295
|
}
|
|
972
|
-
showNotice("ok", "
|
|
1296
|
+
showNotice("ok", t("notice.auditLoaded", { count: items.length }));
|
|
973
1297
|
} catch (error) {
|
|
974
|
-
showNotice("error", "
|
|
975
|
-
renderEmptyRow(auditBody, 5, "
|
|
1298
|
+
showNotice("error", t("notice.auditLoadFailed", { error: error.message }));
|
|
1299
|
+
renderEmptyRow(auditBody, 5, t("table.loadFailed"));
|
|
976
1300
|
}
|
|
977
1301
|
}
|
|
978
1302
|
|