codeharbor 0.1.21 → 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/.env.example +4 -0
- package/README.md +13 -5
- package/dist/cli.js +641 -142
- 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,169 +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"
|
|
371
|
-
<input id="global-cli-audio-
|
|
379
|
+
<span class="field-label" data-i18n="global.audioMaxRetries">\u97F3\u9891\u8F6C\u5199\u6700\u5927\u91CD\u8BD5\u6B21\u6570</span>
|
|
380
|
+
<input id="global-cli-audio-max-retries" type="number" min="0" max="10" />
|
|
381
|
+
</label>
|
|
382
|
+
<label class="field">
|
|
383
|
+
<span class="field-label" data-i18n="global.audioRetryDelay">\u97F3\u9891\u8F6C\u5199\u91CD\u8BD5\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09</span>
|
|
384
|
+
<input id="global-cli-audio-retry-delay" type="number" min="0" />
|
|
372
385
|
</label>
|
|
373
386
|
<label class="field">
|
|
374
|
-
<span class="field-label"
|
|
387
|
+
<span class="field-label" data-i18n="global.audioMaxBytes">\u97F3\u9891\u6700\u5927\u5B57\u8282\u6570</span>
|
|
388
|
+
<input id="global-cli-audio-max-bytes" type="number" min="1" />
|
|
389
|
+
</label>
|
|
390
|
+
<label class="field">
|
|
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" />
|
|
393
|
+
</label>
|
|
394
|
+
<label class="field">
|
|
395
|
+
<span class="field-label" data-i18n="global.audioLocalTimeout">\u672C\u5730 Whisper \u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09</span>
|
|
375
396
|
<input id="global-cli-audio-local-timeout" type="number" min="1" />
|
|
376
397
|
</label>
|
|
377
|
-
<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>
|
|
378
399
|
<label class="field">
|
|
379
|
-
<span class="field-label"
|
|
400
|
+
<span class="field-label" data-i18n="global.agentRounds">\u5DE5\u4F5C\u6D41\u81EA\u52A8\u4FEE\u590D\u8F6E\u6B21</span>
|
|
380
401
|
<input id="global-agent-repair-rounds" type="number" min="0" max="10" />
|
|
381
402
|
</label>
|
|
382
403
|
</div>
|
|
383
404
|
<div class="actions">
|
|
384
|
-
<button id="global-save-btn" type="button"
|
|
385
|
-
<button id="global-reload-btn" type="button" class="secondary"
|
|
386
|
-
<button id="global-restart-main-btn" type="button" class="secondary"
|
|
387
|
-
<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>
|
|
388
409
|
</div>
|
|
389
|
-
<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>
|
|
390
411
|
</section>
|
|
391
412
|
|
|
392
413
|
<section class="panel" data-view="settings-rooms" hidden>
|
|
393
|
-
<h2 class="panel-title"
|
|
414
|
+
<h2 class="panel-title" data-i18n="rooms.title">\u623F\u95F4\u914D\u7F6E</h2>
|
|
394
415
|
<div class="grid">
|
|
395
416
|
<label class="field">
|
|
396
|
-
<span class="field-label"
|
|
397
|
-
<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" />
|
|
398
419
|
</label>
|
|
399
420
|
<label class="field">
|
|
400
|
-
<span class="field-label"
|
|
401
|
-
<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" />
|
|
402
423
|
</label>
|
|
403
424
|
<label class="field full">
|
|
404
|
-
<span class="field-label"
|
|
425
|
+
<span class="field-label" data-i18n="rooms.workdir">\u5DE5\u4F5C\u76EE\u5F55</span>
|
|
405
426
|
<input id="room-workdir" type="text" />
|
|
406
427
|
</label>
|
|
407
|
-
<label class="checkbox"><input id="room-enabled" type="checkbox" /><span
|
|
408
|
-
<label class="checkbox"><input id="room-mention" type="checkbox" /><span
|
|
409
|
-
<label class="checkbox"><input id="room-reply" type="checkbox" /><span
|
|
410
|
-
<label class="checkbox"><input id="room-window" type="checkbox" /><span
|
|
411
|
-
<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>
|
|
412
433
|
</div>
|
|
413
434
|
<div class="actions">
|
|
414
|
-
<button id="room-load-btn" type="button" class="secondary"
|
|
415
|
-
<button id="room-save-btn" type="button"
|
|
416
|
-
<button id="room-delete-btn" type="button" class="danger"
|
|
417
|
-
<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>
|
|
418
439
|
</div>
|
|
419
440
|
<div class="table-wrap">
|
|
420
441
|
<table>
|
|
421
442
|
<thead>
|
|
422
443
|
<tr>
|
|
423
|
-
<th
|
|
424
|
-
<th
|
|
425
|
-
<th
|
|
426
|
-
<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>
|
|
427
448
|
</tr>
|
|
428
449
|
</thead>
|
|
429
450
|
<tbody id="room-list-body"></tbody>
|
|
@@ -432,17 +453,17 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
432
453
|
</section>
|
|
433
454
|
|
|
434
455
|
<section class="panel" data-view="health" hidden>
|
|
435
|
-
<h2 class="panel-title"
|
|
456
|
+
<h2 class="panel-title" data-i18n="health.title">\u5065\u5EB7\u68C0\u67E5</h2>
|
|
436
457
|
<div class="actions">
|
|
437
|
-
<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>
|
|
438
459
|
</div>
|
|
439
460
|
<div class="table-wrap">
|
|
440
461
|
<table>
|
|
441
462
|
<thead>
|
|
442
463
|
<tr>
|
|
443
|
-
<th
|
|
444
|
-
<th
|
|
445
|
-
<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>
|
|
446
467
|
</tr>
|
|
447
468
|
</thead>
|
|
448
469
|
<tbody id="health-body"></tbody>
|
|
@@ -451,23 +472,23 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
451
472
|
</section>
|
|
452
473
|
|
|
453
474
|
<section class="panel" data-view="audit" hidden>
|
|
454
|
-
<h2 class="panel-title"
|
|
475
|
+
<h2 class="panel-title" data-i18n="audit.title">\u914D\u7F6E\u5BA1\u8BA1</h2>
|
|
455
476
|
<div class="actions">
|
|
456
477
|
<label class="field" style="max-width: 120px;">
|
|
457
|
-
<span class="field-label"
|
|
478
|
+
<span class="field-label" data-i18n="audit.limit">\u6761\u6570</span>
|
|
458
479
|
<input id="audit-limit" type="number" min="1" max="200" value="30" />
|
|
459
480
|
</label>
|
|
460
|
-
<button id="audit-refresh-btn" type="button"
|
|
481
|
+
<button id="audit-refresh-btn" type="button" data-i18n="audit.refresh">\u5237\u65B0\u5BA1\u8BA1</button>
|
|
461
482
|
</div>
|
|
462
483
|
<div class="table-wrap">
|
|
463
484
|
<table>
|
|
464
485
|
<thead>
|
|
465
486
|
<tr>
|
|
466
|
-
<th>ID</th>
|
|
467
|
-
<th
|
|
468
|
-
<th
|
|
469
|
-
<th
|
|
470
|
-
<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>
|
|
471
492
|
</tr>
|
|
472
493
|
</thead>
|
|
473
494
|
<tbody id="audit-body"></tbody>
|
|
@@ -494,6 +515,264 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
494
515
|
};
|
|
495
516
|
var storageTokenKey = "codeharbor.admin.token";
|
|
496
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
|
+
}
|
|
497
776
|
var loaded = {
|
|
498
777
|
"settings-global": false,
|
|
499
778
|
"settings-rooms": false,
|
|
@@ -503,6 +782,7 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
503
782
|
|
|
504
783
|
var tokenInput = document.getElementById("auth-token");
|
|
505
784
|
var actorInput = document.getElementById("auth-actor");
|
|
785
|
+
var langSelect = document.getElementById("lang-select");
|
|
506
786
|
var noticeNode = document.getElementById("notice");
|
|
507
787
|
var authRoleNode = document.getElementById("auth-role");
|
|
508
788
|
var roomListBody = document.getElementById("room-list-body");
|
|
@@ -511,11 +791,19 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
511
791
|
|
|
512
792
|
tokenInput.value = localStorage.getItem(storageTokenKey) || "";
|
|
513
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
|
+
});
|
|
514
802
|
|
|
515
803
|
document.getElementById("auth-save-btn").addEventListener("click", function () {
|
|
516
804
|
localStorage.setItem(storageTokenKey, tokenInput.value.trim());
|
|
517
805
|
localStorage.setItem(storageActorKey, actorInput.value.trim());
|
|
518
|
-
showNotice("ok", "
|
|
806
|
+
showNotice("ok", t("notice.authSaved"));
|
|
519
807
|
void refreshAuthStatus();
|
|
520
808
|
});
|
|
521
809
|
|
|
@@ -524,7 +812,7 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
524
812
|
actorInput.value = "";
|
|
525
813
|
localStorage.removeItem(storageTokenKey);
|
|
526
814
|
localStorage.removeItem(storageActorKey);
|
|
527
|
-
showNotice("warn", "
|
|
815
|
+
showNotice("warn", t("notice.authCleared"));
|
|
528
816
|
void refreshAuthStatus();
|
|
529
817
|
});
|
|
530
818
|
|
|
@@ -550,6 +838,8 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
550
838
|
} else {
|
|
551
839
|
handleRoute();
|
|
552
840
|
}
|
|
841
|
+
applyLanguage();
|
|
842
|
+
showNotice("ok", t("notice.ready"));
|
|
553
843
|
void refreshAuthStatus();
|
|
554
844
|
|
|
555
845
|
function getCurrentView() {
|
|
@@ -636,6 +926,42 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
636
926
|
return document.getElementById(inputId).value.trim();
|
|
637
927
|
}
|
|
638
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
|
+
|
|
639
965
|
function showNotice(type, message) {
|
|
640
966
|
noticeNode.className = "notice " + type;
|
|
641
967
|
noticeNode.textContent = message;
|
|
@@ -646,21 +972,25 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
646
972
|
var response = await apiRequest("/api/admin/auth/status", "GET");
|
|
647
973
|
var data = response.data || {};
|
|
648
974
|
if (!data.role) {
|
|
649
|
-
authRoleNode.textContent = "
|
|
975
|
+
authRoleNode.textContent = t("auth.permission.unauth");
|
|
650
976
|
return;
|
|
651
977
|
}
|
|
652
978
|
|
|
653
979
|
var role = String(data.role).toUpperCase();
|
|
654
980
|
var source = data.source ? " (" + String(data.source) + ")" : "";
|
|
655
|
-
var actor = data.actor ? "
|
|
656
|
-
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
|
+
});
|
|
657
987
|
} catch (error) {
|
|
658
988
|
var message = error && error.message ? String(error.message) : "";
|
|
659
989
|
if (/Unauthorized/i.test(message)) {
|
|
660
|
-
authRoleNode.textContent = "
|
|
990
|
+
authRoleNode.textContent = t("auth.permission.unauth");
|
|
661
991
|
return;
|
|
662
992
|
}
|
|
663
|
-
authRoleNode.textContent = "
|
|
993
|
+
authRoleNode.textContent = t("auth.permission.unknown");
|
|
664
994
|
}
|
|
665
995
|
}
|
|
666
996
|
|
|
@@ -712,6 +1042,11 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
712
1042
|
document.getElementById("global-cli-audio-model").value = cliCompat.audioTranscribeModel || "gpt-4o-mini-transcribe";
|
|
713
1043
|
document.getElementById("global-cli-audio-timeout").value = String(cliCompat.audioTranscribeTimeoutMs || 120000);
|
|
714
1044
|
document.getElementById("global-cli-audio-max-chars").value = String(cliCompat.audioTranscribeMaxChars || 6000);
|
|
1045
|
+
document.getElementById("global-cli-audio-max-retries").value = String(
|
|
1046
|
+
typeof cliCompat.audioTranscribeMaxRetries === "number" ? cliCompat.audioTranscribeMaxRetries : 1
|
|
1047
|
+
);
|
|
1048
|
+
document.getElementById("global-cli-audio-retry-delay").value = String(cliCompat.audioTranscribeRetryDelayMs || 800);
|
|
1049
|
+
document.getElementById("global-cli-audio-max-bytes").value = String(cliCompat.audioTranscribeMaxBytes || 26214400);
|
|
715
1050
|
document.getElementById("global-cli-audio-local-command").value = cliCompat.audioLocalWhisperCommand || "";
|
|
716
1051
|
document.getElementById("global-cli-audio-local-timeout").value = String(cliCompat.audioLocalWhisperTimeoutMs || 180000);
|
|
717
1052
|
document.getElementById("global-agent-enabled").checked = Boolean(agentWorkflow.enabled);
|
|
@@ -719,9 +1054,9 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
719
1054
|
typeof agentWorkflow.autoRepairMaxRounds === "number" ? agentWorkflow.autoRepairMaxRounds : 1
|
|
720
1055
|
);
|
|
721
1056
|
|
|
722
|
-
showNotice("ok", "
|
|
1057
|
+
showNotice("ok", t("notice.globalLoaded"));
|
|
723
1058
|
} catch (error) {
|
|
724
|
-
showNotice("error", "
|
|
1059
|
+
showNotice("error", t("notice.globalLoadFailed", { error: error.message }));
|
|
725
1060
|
}
|
|
726
1061
|
}
|
|
727
1062
|
|
|
@@ -760,6 +1095,9 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
760
1095
|
audioTranscribeModel: asText("global-cli-audio-model") || "gpt-4o-mini-transcribe",
|
|
761
1096
|
audioTranscribeTimeoutMs: asNumber("global-cli-audio-timeout", 120000),
|
|
762
1097
|
audioTranscribeMaxChars: asNumber("global-cli-audio-max-chars", 6000),
|
|
1098
|
+
audioTranscribeMaxRetries: asNumber("global-cli-audio-max-retries", 1),
|
|
1099
|
+
audioTranscribeRetryDelayMs: asNumber("global-cli-audio-retry-delay", 800),
|
|
1100
|
+
audioTranscribeMaxBytes: asNumber("global-cli-audio-max-bytes", 26214400),
|
|
763
1101
|
audioLocalWhisperCommand: asText("global-cli-audio-local-command"),
|
|
764
1102
|
audioLocalWhisperTimeoutMs: asNumber("global-cli-audio-local-timeout", 180000)
|
|
765
1103
|
},
|
|
@@ -770,10 +1108,10 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
770
1108
|
};
|
|
771
1109
|
var response = await apiRequest("/api/admin/config/global", "PUT", body);
|
|
772
1110
|
var keys = Array.isArray(response.updatedKeys) ? response.updatedKeys.join(", ") : "global config";
|
|
773
|
-
showNotice("warn", "
|
|
1111
|
+
showNotice("warn", t("notice.globalSaved", { keys: keys }));
|
|
774
1112
|
await loadAudit();
|
|
775
1113
|
} catch (error) {
|
|
776
|
-
showNotice("error", "
|
|
1114
|
+
showNotice("error", t("notice.globalSaveFailed", { error: error.message }));
|
|
777
1115
|
}
|
|
778
1116
|
}
|
|
779
1117
|
|
|
@@ -783,10 +1121,10 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
783
1121
|
withAdmin: Boolean(withAdmin)
|
|
784
1122
|
});
|
|
785
1123
|
var restarted = Array.isArray(response.restarted) ? response.restarted.join(", ") : "codeharbor";
|
|
786
|
-
var suffix = withAdmin ? "
|
|
787
|
-
showNotice("warn", "
|
|
1124
|
+
var suffix = withAdmin ? t("notice.restartSuffixAll") : "";
|
|
1125
|
+
showNotice("warn", t("notice.restartRequested", { services: restarted, suffix: suffix }));
|
|
788
1126
|
} catch (error) {
|
|
789
|
-
showNotice("error", "
|
|
1127
|
+
showNotice("error", t("notice.restartFailed", { error: error.message }));
|
|
790
1128
|
}
|
|
791
1129
|
}
|
|
792
1130
|
|
|
@@ -796,7 +1134,7 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
796
1134
|
var items = Array.isArray(response.data) ? response.data : [];
|
|
797
1135
|
roomListBody.innerHTML = "";
|
|
798
1136
|
if (items.length === 0) {
|
|
799
|
-
renderEmptyRow(roomListBody, 4, "
|
|
1137
|
+
renderEmptyRow(roomListBody, 4, t("notice.roomsEmpty"));
|
|
800
1138
|
return;
|
|
801
1139
|
}
|
|
802
1140
|
for (var i = 0; i < items.length; i += 1) {
|
|
@@ -808,10 +1146,10 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
808
1146
|
appendCell(row, item.updatedAt ? new Date(item.updatedAt).toISOString() : "-");
|
|
809
1147
|
roomListBody.appendChild(row);
|
|
810
1148
|
}
|
|
811
|
-
showNotice("ok", "
|
|
1149
|
+
showNotice("ok", t("notice.roomsLoaded", { count: items.length }));
|
|
812
1150
|
} catch (error) {
|
|
813
|
-
showNotice("error", "
|
|
814
|
-
renderEmptyRow(roomListBody, 4, "
|
|
1151
|
+
showNotice("error", t("notice.roomsLoadFailed", { error: error.message }));
|
|
1152
|
+
renderEmptyRow(roomListBody, 4, t("table.loadFailed"));
|
|
815
1153
|
}
|
|
816
1154
|
}
|
|
817
1155
|
|
|
@@ -824,15 +1162,15 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
824
1162
|
async function loadRoom() {
|
|
825
1163
|
var roomId = asText("room-id");
|
|
826
1164
|
if (!roomId) {
|
|
827
|
-
showNotice("warn", "
|
|
1165
|
+
showNotice("warn", t("notice.roomIdRequired"));
|
|
828
1166
|
return;
|
|
829
1167
|
}
|
|
830
1168
|
try {
|
|
831
1169
|
var response = await apiRequest("/api/admin/config/rooms/" + encodeURIComponent(roomId), "GET");
|
|
832
1170
|
fillRoomForm(response.data || {});
|
|
833
|
-
showNotice("ok", "
|
|
1171
|
+
showNotice("ok", t("notice.roomLoaded", { roomId: roomId }));
|
|
834
1172
|
} catch (error) {
|
|
835
|
-
showNotice("error", "
|
|
1173
|
+
showNotice("error", t("notice.roomLoadFailed", { error: error.message }));
|
|
836
1174
|
}
|
|
837
1175
|
}
|
|
838
1176
|
|
|
@@ -848,7 +1186,7 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
848
1186
|
async function saveRoom() {
|
|
849
1187
|
var roomId = asText("room-id");
|
|
850
1188
|
if (!roomId) {
|
|
851
|
-
showNotice("warn", "
|
|
1189
|
+
showNotice("warn", t("notice.roomIdRequired"));
|
|
852
1190
|
return;
|
|
853
1191
|
}
|
|
854
1192
|
try {
|
|
@@ -862,30 +1200,30 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
862
1200
|
summary: asText("room-summary")
|
|
863
1201
|
};
|
|
864
1202
|
await apiRequest("/api/admin/config/rooms/" + encodeURIComponent(roomId), "PUT", body);
|
|
865
|
-
showNotice("ok", "
|
|
1203
|
+
showNotice("ok", t("notice.roomSaved", { roomId: roomId }));
|
|
866
1204
|
await refreshRoomList();
|
|
867
1205
|
await loadAudit();
|
|
868
1206
|
} catch (error) {
|
|
869
|
-
showNotice("error", "
|
|
1207
|
+
showNotice("error", t("notice.roomSaveFailed", { error: error.message }));
|
|
870
1208
|
}
|
|
871
1209
|
}
|
|
872
1210
|
|
|
873
1211
|
async function deleteRoom() {
|
|
874
1212
|
var roomId = asText("room-id");
|
|
875
1213
|
if (!roomId) {
|
|
876
|
-
showNotice("warn", "
|
|
1214
|
+
showNotice("warn", t("notice.roomIdRequired"));
|
|
877
1215
|
return;
|
|
878
1216
|
}
|
|
879
|
-
if (!window.confirm("
|
|
1217
|
+
if (!window.confirm(t("confirm.roomDelete", { roomId: roomId }))) {
|
|
880
1218
|
return;
|
|
881
1219
|
}
|
|
882
1220
|
try {
|
|
883
1221
|
await apiRequest("/api/admin/config/rooms/" + encodeURIComponent(roomId), "DELETE");
|
|
884
|
-
showNotice("ok", "
|
|
1222
|
+
showNotice("ok", t("notice.roomDeleted", { roomId: roomId }));
|
|
885
1223
|
await refreshRoomList();
|
|
886
1224
|
await loadAudit();
|
|
887
1225
|
} catch (error) {
|
|
888
|
-
showNotice("error", "
|
|
1226
|
+
showNotice("error", t("notice.roomDeleteFailed", { error: error.message }));
|
|
889
1227
|
}
|
|
890
1228
|
}
|
|
891
1229
|
|
|
@@ -897,24 +1235,30 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
897
1235
|
var codex = response.codex || {};
|
|
898
1236
|
var matrix = response.matrix || {};
|
|
899
1237
|
|
|
900
|
-
appendHealthRow("Codex", Boolean(codex.ok), codex.ok ? (codex.version || "ok") : (codex.error || "failed"));
|
|
901
1238
|
appendHealthRow(
|
|
902
|
-
"
|
|
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"),
|
|
903
1245
|
Boolean(matrix.ok),
|
|
904
|
-
matrix.ok
|
|
1246
|
+
matrix.ok
|
|
1247
|
+
? "HTTP " + matrix.status + " " + JSON.stringify(matrix.versions || [])
|
|
1248
|
+
: (matrix.error || t("health.status.fail"))
|
|
905
1249
|
);
|
|
906
|
-
appendHealthRow("
|
|
907
|
-
showNotice("ok", "
|
|
1250
|
+
appendHealthRow(t("health.component.overall"), Boolean(response.ok), response.timestamp || "");
|
|
1251
|
+
showNotice("ok", t("notice.healthDone"));
|
|
908
1252
|
} catch (error) {
|
|
909
|
-
showNotice("error", "
|
|
910
|
-
renderEmptyRow(healthBody, 3, "
|
|
1253
|
+
showNotice("error", t("notice.healthFailed", { error: error.message }));
|
|
1254
|
+
renderEmptyRow(healthBody, 3, t("notice.healthEmptyFailed"));
|
|
911
1255
|
}
|
|
912
1256
|
}
|
|
913
1257
|
|
|
914
1258
|
function appendHealthRow(component, ok, detail) {
|
|
915
1259
|
var row = document.createElement("tr");
|
|
916
1260
|
appendCell(row, component);
|
|
917
|
-
appendCell(row, ok ? "
|
|
1261
|
+
appendCell(row, ok ? t("health.status.ok") : t("health.status.fail"));
|
|
918
1262
|
appendCell(row, detail);
|
|
919
1263
|
healthBody.appendChild(row);
|
|
920
1264
|
}
|
|
@@ -932,7 +1276,7 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
932
1276
|
var items = Array.isArray(response.data) ? response.data : [];
|
|
933
1277
|
auditBody.innerHTML = "";
|
|
934
1278
|
if (items.length === 0) {
|
|
935
|
-
renderEmptyRow(auditBody, 5, "
|
|
1279
|
+
renderEmptyRow(auditBody, 5, t("notice.auditEmpty"));
|
|
936
1280
|
return;
|
|
937
1281
|
}
|
|
938
1282
|
for (var i = 0; i < items.length; i += 1) {
|
|
@@ -949,10 +1293,10 @@ var ADMIN_CONSOLE_HTML = `<!doctype html>
|
|
|
949
1293
|
row.appendChild(payloadCell);
|
|
950
1294
|
auditBody.appendChild(row);
|
|
951
1295
|
}
|
|
952
|
-
showNotice("ok", "
|
|
1296
|
+
showNotice("ok", t("notice.auditLoaded", { count: items.length }));
|
|
953
1297
|
} catch (error) {
|
|
954
|
-
showNotice("error", "
|
|
955
|
-
renderEmptyRow(auditBody, 5, "
|
|
1298
|
+
showNotice("error", t("notice.auditLoadFailed", { error: error.message }));
|
|
1299
|
+
renderEmptyRow(auditBody, 5, t("table.loadFailed"));
|
|
956
1300
|
}
|
|
957
1301
|
}
|
|
958
1302
|
|
|
@@ -2037,6 +2381,37 @@ var AdminServer = class {
|
|
|
2037
2381
|
envUpdates.CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_CHARS = String(value);
|
|
2038
2382
|
updatedKeys.push("cliCompat.audioTranscribeMaxChars");
|
|
2039
2383
|
}
|
|
2384
|
+
if ("audioTranscribeMaxRetries" in compat) {
|
|
2385
|
+
const value = normalizePositiveInt(
|
|
2386
|
+
compat.audioTranscribeMaxRetries,
|
|
2387
|
+
this.config.cliCompat.audioTranscribeMaxRetries,
|
|
2388
|
+
0,
|
|
2389
|
+
10
|
|
2390
|
+
);
|
|
2391
|
+
this.config.cliCompat.audioTranscribeMaxRetries = value;
|
|
2392
|
+
envUpdates.CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_RETRIES = String(value);
|
|
2393
|
+
updatedKeys.push("cliCompat.audioTranscribeMaxRetries");
|
|
2394
|
+
}
|
|
2395
|
+
if ("audioTranscribeRetryDelayMs" in compat) {
|
|
2396
|
+
const value = normalizeNonNegativeInt(
|
|
2397
|
+
compat.audioTranscribeRetryDelayMs,
|
|
2398
|
+
this.config.cliCompat.audioTranscribeRetryDelayMs
|
|
2399
|
+
);
|
|
2400
|
+
this.config.cliCompat.audioTranscribeRetryDelayMs = value;
|
|
2401
|
+
envUpdates.CLI_COMPAT_AUDIO_TRANSCRIBE_RETRY_DELAY_MS = String(value);
|
|
2402
|
+
updatedKeys.push("cliCompat.audioTranscribeRetryDelayMs");
|
|
2403
|
+
}
|
|
2404
|
+
if ("audioTranscribeMaxBytes" in compat) {
|
|
2405
|
+
const value = normalizePositiveInt(
|
|
2406
|
+
compat.audioTranscribeMaxBytes,
|
|
2407
|
+
this.config.cliCompat.audioTranscribeMaxBytes,
|
|
2408
|
+
1,
|
|
2409
|
+
Number.MAX_SAFE_INTEGER
|
|
2410
|
+
);
|
|
2411
|
+
this.config.cliCompat.audioTranscribeMaxBytes = value;
|
|
2412
|
+
envUpdates.CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_BYTES = String(value);
|
|
2413
|
+
updatedKeys.push("cliCompat.audioTranscribeMaxBytes");
|
|
2414
|
+
}
|
|
2040
2415
|
if ("audioLocalWhisperCommand" in compat) {
|
|
2041
2416
|
const value = normalizeString(
|
|
2042
2417
|
compat.audioLocalWhisperCommand,
|
|
@@ -3753,12 +4128,15 @@ var import_promises3 = __toESM(require("fs/promises"));
|
|
|
3753
4128
|
var import_node_path8 = __toESM(require("path"));
|
|
3754
4129
|
var import_node_util3 = require("util");
|
|
3755
4130
|
var execAsync = (0, import_node_util3.promisify)(import_node_child_process5.exec);
|
|
4131
|
+
var RETRYABLE_OPENAI_STATUS = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
3756
4132
|
var AudioTranscriber = class {
|
|
3757
4133
|
enabled;
|
|
3758
4134
|
apiKey;
|
|
3759
4135
|
model;
|
|
3760
4136
|
timeoutMs;
|
|
3761
4137
|
maxChars;
|
|
4138
|
+
maxRetries;
|
|
4139
|
+
retryDelayMs;
|
|
3762
4140
|
localWhisperCommand;
|
|
3763
4141
|
localWhisperTimeoutMs;
|
|
3764
4142
|
constructor(options) {
|
|
@@ -3767,6 +4145,8 @@ var AudioTranscriber = class {
|
|
|
3767
4145
|
this.model = options.model;
|
|
3768
4146
|
this.timeoutMs = options.timeoutMs;
|
|
3769
4147
|
this.maxChars = options.maxChars;
|
|
4148
|
+
this.maxRetries = options.maxRetries;
|
|
4149
|
+
this.retryDelayMs = options.retryDelayMs;
|
|
3770
4150
|
this.localWhisperCommand = options.localWhisperCommand;
|
|
3771
4151
|
this.localWhisperTimeoutMs = options.localWhisperTimeoutMs;
|
|
3772
4152
|
}
|
|
@@ -3808,7 +4188,7 @@ var AudioTranscriber = class {
|
|
|
3808
4188
|
let localError = null;
|
|
3809
4189
|
if (hasLocalWhisper) {
|
|
3810
4190
|
try {
|
|
3811
|
-
const localText = await this.
|
|
4191
|
+
const localText = await this.transcribeOneWithLocalWhisperWithRetry(attachment);
|
|
3812
4192
|
if (localText) {
|
|
3813
4193
|
return localText;
|
|
3814
4194
|
}
|
|
@@ -3818,7 +4198,7 @@ var AudioTranscriber = class {
|
|
|
3818
4198
|
}
|
|
3819
4199
|
if (hasOpenAi) {
|
|
3820
4200
|
try {
|
|
3821
|
-
return await this.
|
|
4201
|
+
return await this.transcribeOneWithOpenAiWithRetry(attachment);
|
|
3822
4202
|
} catch (error) {
|
|
3823
4203
|
if (!localError) {
|
|
3824
4204
|
throw error;
|
|
@@ -3834,6 +4214,34 @@ var AudioTranscriber = class {
|
|
|
3834
4214
|
}
|
|
3835
4215
|
return "";
|
|
3836
4216
|
}
|
|
4217
|
+
async transcribeOneWithOpenAiWithRetry(attachment) {
|
|
4218
|
+
let attempt = 0;
|
|
4219
|
+
while (true) {
|
|
4220
|
+
try {
|
|
4221
|
+
return await this.transcribeOneWithOpenAi(attachment);
|
|
4222
|
+
} catch (error) {
|
|
4223
|
+
if (!isRetryableOpenAiError(error) || attempt >= this.maxRetries) {
|
|
4224
|
+
throw error;
|
|
4225
|
+
}
|
|
4226
|
+
attempt += 1;
|
|
4227
|
+
await sleep2(this.retryDelayMs * attempt);
|
|
4228
|
+
}
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
async transcribeOneWithLocalWhisperWithRetry(attachment) {
|
|
4232
|
+
let attempt = 0;
|
|
4233
|
+
while (true) {
|
|
4234
|
+
try {
|
|
4235
|
+
return await this.transcribeOneWithLocalWhisper(attachment);
|
|
4236
|
+
} catch (error) {
|
|
4237
|
+
if (attempt >= this.maxRetries) {
|
|
4238
|
+
throw error;
|
|
4239
|
+
}
|
|
4240
|
+
attempt += 1;
|
|
4241
|
+
await sleep2(this.retryDelayMs * attempt);
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4244
|
+
}
|
|
3837
4245
|
async transcribeOneWithOpenAi(attachment) {
|
|
3838
4246
|
if (!this.apiKey) {
|
|
3839
4247
|
return "";
|
|
@@ -3866,7 +4274,7 @@ var AudioTranscriber = class {
|
|
|
3866
4274
|
const payload = await response.json().catch(() => ({}));
|
|
3867
4275
|
if (!response.ok) {
|
|
3868
4276
|
const message = typeof payload?.error?.message === "string" ? payload.error.message : `HTTP ${response.status} ${response.statusText}`;
|
|
3869
|
-
throw new
|
|
4277
|
+
throw new OpenAiTranscriptionHttpError(response.status, `Audio transcription failed for ${attachment.name}: ${message}`);
|
|
3870
4278
|
}
|
|
3871
4279
|
const text = typeof payload.text === "string" ? payload.text.trim() : "";
|
|
3872
4280
|
return this.normalizeTranscriptText(text);
|
|
@@ -3911,12 +4319,38 @@ function buildLocalWhisperCommand(template, inputPath) {
|
|
|
3911
4319
|
function shellEscape(value) {
|
|
3912
4320
|
return `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
3913
4321
|
}
|
|
4322
|
+
function isRetryableOpenAiError(error) {
|
|
4323
|
+
if (error instanceof OpenAiTranscriptionHttpError) {
|
|
4324
|
+
return RETRYABLE_OPENAI_STATUS.has(error.status);
|
|
4325
|
+
}
|
|
4326
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
4327
|
+
return true;
|
|
4328
|
+
}
|
|
4329
|
+
return true;
|
|
4330
|
+
}
|
|
4331
|
+
async function sleep2(delayMs) {
|
|
4332
|
+
if (delayMs <= 0) {
|
|
4333
|
+
return;
|
|
4334
|
+
}
|
|
4335
|
+
await new Promise((resolve) => {
|
|
4336
|
+
const timer = setTimeout(resolve, delayMs);
|
|
4337
|
+
timer.unref?.();
|
|
4338
|
+
});
|
|
4339
|
+
}
|
|
3914
4340
|
function formatError3(error) {
|
|
3915
4341
|
if (error instanceof Error) {
|
|
3916
4342
|
return error.message;
|
|
3917
4343
|
}
|
|
3918
4344
|
return String(error);
|
|
3919
4345
|
}
|
|
4346
|
+
var OpenAiTranscriptionHttpError = class extends Error {
|
|
4347
|
+
status;
|
|
4348
|
+
constructor(status, message) {
|
|
4349
|
+
super(message);
|
|
4350
|
+
this.name = "OpenAiTranscriptionHttpError";
|
|
4351
|
+
this.status = status;
|
|
4352
|
+
}
|
|
4353
|
+
};
|
|
3920
4354
|
|
|
3921
4355
|
// src/compat/cli-compat-recorder.ts
|
|
3922
4356
|
var import_node_fs6 = __toESM(require("fs"));
|
|
@@ -4814,6 +5248,9 @@ var Orchestrator = class {
|
|
|
4814
5248
|
audioTranscribeModel: "gpt-4o-mini-transcribe",
|
|
4815
5249
|
audioTranscribeTimeoutMs: 12e4,
|
|
4816
5250
|
audioTranscribeMaxChars: 6e3,
|
|
5251
|
+
audioTranscribeMaxRetries: 1,
|
|
5252
|
+
audioTranscribeRetryDelayMs: 800,
|
|
5253
|
+
audioTranscribeMaxBytes: 26214400,
|
|
4817
5254
|
audioLocalWhisperCommand: null,
|
|
4818
5255
|
audioLocalWhisperTimeoutMs: 18e4,
|
|
4819
5256
|
recordPath: null
|
|
@@ -4825,6 +5262,8 @@ var Orchestrator = class {
|
|
|
4825
5262
|
model: this.cliCompat.audioTranscribeModel,
|
|
4826
5263
|
timeoutMs: this.cliCompat.audioTranscribeTimeoutMs,
|
|
4827
5264
|
maxChars: this.cliCompat.audioTranscribeMaxChars,
|
|
5265
|
+
maxRetries: this.cliCompat.audioTranscribeMaxRetries,
|
|
5266
|
+
retryDelayMs: this.cliCompat.audioTranscribeRetryDelayMs,
|
|
4828
5267
|
localWhisperCommand: this.cliCompat.audioLocalWhisperCommand,
|
|
4829
5268
|
localWhisperTimeoutMs: this.cliCompat.audioLocalWhisperTimeoutMs
|
|
4830
5269
|
});
|
|
@@ -5661,35 +6100,73 @@ var Orchestrator = class {
|
|
|
5661
6100
|
if (!this.audioTranscriber.isEnabled()) {
|
|
5662
6101
|
return [];
|
|
5663
6102
|
}
|
|
5664
|
-
const
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
}));
|
|
5669
|
-
if (audioAttachments.length === 0) {
|
|
6103
|
+
const rawAudioAttachments = message.attachments.filter(
|
|
6104
|
+
(attachment) => attachment.kind === "audio" && Boolean(attachment.localPath)
|
|
6105
|
+
);
|
|
6106
|
+
if (rawAudioAttachments.length === 0) {
|
|
5670
6107
|
return [];
|
|
5671
6108
|
}
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
6109
|
+
const maxBytes = this.cliCompat.audioTranscribeMaxBytes;
|
|
6110
|
+
const audioAttachments = [];
|
|
6111
|
+
let skippedTooLarge = 0;
|
|
6112
|
+
for (const attachment of rawAudioAttachments) {
|
|
6113
|
+
const localPath = attachment.localPath;
|
|
6114
|
+
const sizeBytes = await this.resolveAudioAttachmentSizeBytes(attachment.sizeBytes, localPath);
|
|
6115
|
+
if (sizeBytes !== null && sizeBytes > maxBytes) {
|
|
6116
|
+
skippedTooLarge += 1;
|
|
6117
|
+
this.logger.warn("Skip audio transcription for oversized attachment", {
|
|
5676
6118
|
requestId,
|
|
5677
6119
|
sessionKey,
|
|
5678
|
-
|
|
5679
|
-
|
|
6120
|
+
name: attachment.name,
|
|
6121
|
+
sizeBytes,
|
|
6122
|
+
maxBytes
|
|
5680
6123
|
});
|
|
6124
|
+
continue;
|
|
5681
6125
|
}
|
|
6126
|
+
audioAttachments.push({
|
|
6127
|
+
name: attachment.name,
|
|
6128
|
+
mimeType: attachment.mimeType,
|
|
6129
|
+
localPath
|
|
6130
|
+
});
|
|
6131
|
+
}
|
|
6132
|
+
if (audioAttachments.length === 0) {
|
|
6133
|
+
return [];
|
|
6134
|
+
}
|
|
6135
|
+
const startedAt = Date.now();
|
|
6136
|
+
try {
|
|
6137
|
+
const transcripts = await this.audioTranscriber.transcribeMany(audioAttachments);
|
|
6138
|
+
this.logger.info("Audio transcription completed", {
|
|
6139
|
+
requestId,
|
|
6140
|
+
sessionKey,
|
|
6141
|
+
attachmentCount: audioAttachments.length,
|
|
6142
|
+
transcriptCount: transcripts.length,
|
|
6143
|
+
skippedTooLarge,
|
|
6144
|
+
durationMs: Date.now() - startedAt
|
|
6145
|
+
});
|
|
5682
6146
|
return transcripts;
|
|
5683
6147
|
} catch (error) {
|
|
5684
6148
|
this.logger.warn("Audio transcription failed, continuing without transcripts", {
|
|
5685
6149
|
requestId,
|
|
5686
6150
|
sessionKey,
|
|
5687
6151
|
attachmentCount: audioAttachments.length,
|
|
6152
|
+
skippedTooLarge,
|
|
6153
|
+
durationMs: Date.now() - startedAt,
|
|
5688
6154
|
error: formatError4(error)
|
|
5689
6155
|
});
|
|
5690
6156
|
return [];
|
|
5691
6157
|
}
|
|
5692
6158
|
}
|
|
6159
|
+
async resolveAudioAttachmentSizeBytes(sizeBytes, localPath) {
|
|
6160
|
+
if (sizeBytes !== null) {
|
|
6161
|
+
return sizeBytes;
|
|
6162
|
+
}
|
|
6163
|
+
try {
|
|
6164
|
+
const stats = await import_promises5.default.stat(localPath);
|
|
6165
|
+
return stats.size;
|
|
6166
|
+
} catch {
|
|
6167
|
+
return null;
|
|
6168
|
+
}
|
|
6169
|
+
}
|
|
5693
6170
|
buildExecutionPrompt(prompt, message, audioTranscripts) {
|
|
5694
6171
|
if (message.attachments.length === 0 && audioTranscripts.length === 0) {
|
|
5695
6172
|
return prompt;
|
|
@@ -6590,6 +7067,9 @@ var configSchema = import_zod.z.object({
|
|
|
6590
7067
|
CLI_COMPAT_AUDIO_TRANSCRIBE_MODEL: import_zod.z.string().default("gpt-4o-mini-transcribe"),
|
|
6591
7068
|
CLI_COMPAT_AUDIO_TRANSCRIBE_TIMEOUT_MS: import_zod.z.string().default("120000").transform((v) => Number.parseInt(v, 10)).pipe(import_zod.z.number().int().positive()),
|
|
6592
7069
|
CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_CHARS: import_zod.z.string().default("6000").transform((v) => Number.parseInt(v, 10)).pipe(import_zod.z.number().int().positive()),
|
|
7070
|
+
CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_RETRIES: import_zod.z.string().default("1").transform((v) => Number.parseInt(v, 10)).pipe(import_zod.z.number().int().min(0).max(10)),
|
|
7071
|
+
CLI_COMPAT_AUDIO_TRANSCRIBE_RETRY_DELAY_MS: import_zod.z.string().default("800").transform((v) => Number.parseInt(v, 10)).pipe(import_zod.z.number().int().nonnegative()),
|
|
7072
|
+
CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_BYTES: import_zod.z.string().default("26214400").transform((v) => Number.parseInt(v, 10)).pipe(import_zod.z.number().int().positive()),
|
|
6593
7073
|
CLI_COMPAT_AUDIO_LOCAL_WHISPER_COMMAND: import_zod.z.string().default(""),
|
|
6594
7074
|
CLI_COMPAT_AUDIO_LOCAL_WHISPER_TIMEOUT_MS: import_zod.z.string().default("180000").transform((v) => Number.parseInt(v, 10)).pipe(import_zod.z.number().int().positive()),
|
|
6595
7075
|
CLI_COMPAT_RECORD_PATH: import_zod.z.string().default(""),
|
|
@@ -6656,6 +7136,9 @@ var configSchema = import_zod.z.object({
|
|
|
6656
7136
|
audioTranscribeModel: v.CLI_COMPAT_AUDIO_TRANSCRIBE_MODEL.trim() || "gpt-4o-mini-transcribe",
|
|
6657
7137
|
audioTranscribeTimeoutMs: v.CLI_COMPAT_AUDIO_TRANSCRIBE_TIMEOUT_MS,
|
|
6658
7138
|
audioTranscribeMaxChars: v.CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_CHARS,
|
|
7139
|
+
audioTranscribeMaxRetries: v.CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_RETRIES,
|
|
7140
|
+
audioTranscribeRetryDelayMs: v.CLI_COMPAT_AUDIO_TRANSCRIBE_RETRY_DELAY_MS,
|
|
7141
|
+
audioTranscribeMaxBytes: v.CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_BYTES,
|
|
6659
7142
|
audioLocalWhisperCommand: v.CLI_COMPAT_AUDIO_LOCAL_WHISPER_COMMAND.trim() ? v.CLI_COMPAT_AUDIO_LOCAL_WHISPER_COMMAND.trim() : null,
|
|
6660
7143
|
audioLocalWhisperTimeoutMs: v.CLI_COMPAT_AUDIO_LOCAL_WHISPER_TIMEOUT_MS,
|
|
6661
7144
|
recordPath: v.CLI_COMPAT_RECORD_PATH.trim() ? import_node_path12.default.resolve(v.CLI_COMPAT_RECORD_PATH) : null
|
|
@@ -6903,6 +7386,9 @@ var CONFIG_SNAPSHOT_ENV_KEYS = [
|
|
|
6903
7386
|
"CLI_COMPAT_AUDIO_TRANSCRIBE_MODEL",
|
|
6904
7387
|
"CLI_COMPAT_AUDIO_TRANSCRIBE_TIMEOUT_MS",
|
|
6905
7388
|
"CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_CHARS",
|
|
7389
|
+
"CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_RETRIES",
|
|
7390
|
+
"CLI_COMPAT_AUDIO_TRANSCRIBE_RETRY_DELAY_MS",
|
|
7391
|
+
"CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_BYTES",
|
|
6906
7392
|
"CLI_COMPAT_AUDIO_LOCAL_WHISPER_COMMAND",
|
|
6907
7393
|
"CLI_COMPAT_AUDIO_LOCAL_WHISPER_TIMEOUT_MS",
|
|
6908
7394
|
"CLI_COMPAT_RECORD_PATH",
|
|
@@ -6979,6 +7465,16 @@ var envSnapshotSchema = import_zod2.z.object({
|
|
|
6979
7465
|
CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_CHARS: integerStringSchema("CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_CHARS", 1).default(
|
|
6980
7466
|
"6000"
|
|
6981
7467
|
),
|
|
7468
|
+
CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_RETRIES: integerStringSchema("CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_RETRIES", 0, 10).default(
|
|
7469
|
+
"1"
|
|
7470
|
+
),
|
|
7471
|
+
CLI_COMPAT_AUDIO_TRANSCRIBE_RETRY_DELAY_MS: integerStringSchema(
|
|
7472
|
+
"CLI_COMPAT_AUDIO_TRANSCRIBE_RETRY_DELAY_MS",
|
|
7473
|
+
0
|
|
7474
|
+
).default("800"),
|
|
7475
|
+
CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_BYTES: integerStringSchema("CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_BYTES", 1).default(
|
|
7476
|
+
"26214400"
|
|
7477
|
+
),
|
|
6982
7478
|
CLI_COMPAT_AUDIO_LOCAL_WHISPER_COMMAND: import_zod2.z.string().default(""),
|
|
6983
7479
|
CLI_COMPAT_AUDIO_LOCAL_WHISPER_TIMEOUT_MS: integerStringSchema(
|
|
6984
7480
|
"CLI_COMPAT_AUDIO_LOCAL_WHISPER_TIMEOUT_MS",
|
|
@@ -7178,6 +7674,9 @@ function buildSnapshotEnv(config) {
|
|
|
7178
7674
|
CLI_COMPAT_AUDIO_TRANSCRIBE_MODEL: config.cliCompat.audioTranscribeModel,
|
|
7179
7675
|
CLI_COMPAT_AUDIO_TRANSCRIBE_TIMEOUT_MS: String(config.cliCompat.audioTranscribeTimeoutMs),
|
|
7180
7676
|
CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_CHARS: String(config.cliCompat.audioTranscribeMaxChars),
|
|
7677
|
+
CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_RETRIES: String(config.cliCompat.audioTranscribeMaxRetries),
|
|
7678
|
+
CLI_COMPAT_AUDIO_TRANSCRIBE_RETRY_DELAY_MS: String(config.cliCompat.audioTranscribeRetryDelayMs),
|
|
7679
|
+
CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_BYTES: String(config.cliCompat.audioTranscribeMaxBytes),
|
|
7181
7680
|
CLI_COMPAT_AUDIO_LOCAL_WHISPER_COMMAND: config.cliCompat.audioLocalWhisperCommand ?? "",
|
|
7182
7681
|
CLI_COMPAT_AUDIO_LOCAL_WHISPER_TIMEOUT_MS: String(config.cliCompat.audioLocalWhisperTimeoutMs),
|
|
7183
7682
|
CLI_COMPAT_RECORD_PATH: config.cliCompat.recordPath ?? "",
|