@liujitcn/kratos-admin-system 0.0.20 → 0.0.21
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/README.md +51 -50
- package/dist/package/declarations/src/api/system/base_language.d.ts +51 -0
- package/dist/package/declarations/src/api/system/base_translation.d.ts +7 -0
- package/dist/package/declarations/src/api/system/code_gen_i18n.d.ts +8 -0
- package/dist/package/declarations/src/components/DynamicTranslationCell.vue.d.ts +39 -0
- package/dist/package/declarations/src/components/DynamicTranslationEditor.vue.d.ts +23 -0
- package/dist/package/declarations/src/components/dynamicTranslation.d.ts +44 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +5 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +79 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_language.d.ts +114 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_menu.d.ts +40 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_translation.d.ts +102 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/code_gen.d.ts +2 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_column.d.ts +7 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_table.d.ts +13 -0
- package/dist/package/declarations/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue.d.ts +23 -0
- package/dist/package/declarations/src/views/tool/code-gen/config.d.ts +7 -7
- package/dist/package/declarations/src/views/tool/language/index.vue.d.ts +3 -0
- package/dist/package/src/api/base/ai_message.ts +7 -12
- package/dist/package/src/api/base/sse.ts +3 -1
- package/dist/package/src/api/system/base_language.ts +137 -0
- package/dist/package/src/api/system/base_translation.ts +22 -0
- package/dist/package/src/api/system/code_gen_column.ts +17 -3
- package/dist/package/src/api/system/code_gen_i18n.ts +18 -0
- package/dist/package/src/api/system/code_gen_table.ts +12 -4
- package/dist/package/src/components/DynamicTranslationCell.vue +176 -0
- package/dist/package/src/components/DynamicTranslationEditor.vue +166 -0
- package/dist/package/src/components/dynamicTranslation.ts +86 -0
- package/dist/package/src/locales/README.md +28 -0
- package/dist/package/src/locales/en-US.json +929 -0
- package/dist/package/src/locales/es-ES.json +928 -0
- package/dist/package/src/locales/fr-FR.json +928 -0
- package/dist/package/src/locales/ja-JP.json +929 -0
- package/dist/package/src/locales/ko-KR.json +928 -0
- package/dist/package/src/locales/zh-CN.json +929 -0
- package/dist/package/src/locales/zh-TW.json +928 -0
- package/dist/package/src/module.ts +19 -1
- package/dist/package/src/rpc/system/admin/v1/base_config.ts +5 -0
- package/dist/package/src/rpc/system/admin/v1/base_dict.ts +81 -0
- package/dist/package/src/rpc/system/admin/v1/base_language.ts +135 -0
- package/dist/package/src/rpc/system/admin/v1/base_menu.ts +41 -0
- package/dist/package/src/rpc/system/admin/v1/base_translation.ts +117 -0
- package/dist/package/src/rpc/system/admin/v1/code_gen.ts +5 -1
- package/dist/package/src/rpc/system/admin/v1/code_gen_column.ts +8 -0
- package/dist/package/src/rpc/system/admin/v1/code_gen_table.ts +15 -0
- package/dist/package/src/views/ai/chat/components/AiMarkdown.vue +1 -6
- package/dist/package/src/views/ai/chat/components/ChatPanel.vue +70 -53
- package/dist/package/src/views/ai/chat/components/SessionPanel.vue +20 -9
- package/dist/package/src/views/ai/chat/components/XSender.vue +36 -23
- package/dist/package/src/views/ai/chat/index.vue +55 -39
- package/dist/package/src/views/ai/chat/message.ts +18 -17
- package/dist/package/src/views/base/api/index.vue +121 -83
- package/dist/package/src/views/base/area/index.vue +81 -31
- package/dist/package/src/views/base/config/index.vue +272 -78
- package/dist/package/src/views/base/dept/index.vue +110 -61
- package/dist/package/src/views/base/dict/index.vue +137 -58
- package/dist/package/src/views/base/dict/item.vue +147 -61
- package/dist/package/src/views/base/job/index.vue +134 -81
- package/dist/package/src/views/base/job/log.vue +21 -22
- package/dist/package/src/views/base/log/index.vue +68 -46
- package/dist/package/src/views/base/menu/index.vue +257 -156
- package/dist/package/src/views/base/migration/index.vue +49 -29
- package/dist/package/src/views/base/post/index.vue +128 -59
- package/dist/package/src/views/base/role/index.vue +145 -78
- package/dist/package/src/views/base/tenant/index.vue +132 -63
- package/dist/package/src/views/base/user/components/dept-tree.vue +2 -1
- package/dist/package/src/views/base/user/index.vue +192 -112
- package/dist/package/src/views/profile/components/base.vue +44 -27
- package/dist/package/src/views/profile/components/password.vue +43 -27
- package/dist/package/src/views/profile/components/security.vue +89 -53
- package/dist/package/src/views/profile/index.vue +10 -9
- package/dist/package/src/views/tool/api-doc/index.vue +6 -2
- package/dist/package/src/views/tool/code-gen/code-preview/index.vue +30 -14
- package/dist/package/src/views/tool/code-gen/columns/index.vue +382 -273
- package/dist/package/src/views/tool/code-gen/columns/option-copy.ts +1 -6
- package/dist/package/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue +118 -0
- package/dist/package/src/views/tool/code-gen/components/CodeGenProgressDialog.vue +65 -36
- package/dist/package/src/views/tool/code-gen/components/CodePreviewPane.vue +8 -5
- package/dist/package/src/views/tool/code-gen/config.ts +114 -77
- package/dist/package/src/views/tool/code-gen/preview/data.ts +19 -17
- package/dist/package/src/views/tool/code-gen/preview/index.vue +96 -58
- package/dist/package/src/views/tool/code-gen/proto/index.vue +110 -62
- package/dist/package/src/views/tool/code-gen/table/index.vue +197 -117
- package/dist/package/src/views/tool/language/index.vue +256 -0
- package/dist/package/src/views/tool/project-doc/index.vue +17 -15
- package/package.json +6 -2
|
@@ -11,10 +11,15 @@
|
|
|
11
11
|
@toggle-collapse="toggleSessionPanel"
|
|
12
12
|
/>
|
|
13
13
|
<div v-else class="agent-session-collapsed">
|
|
14
|
-
<button
|
|
14
|
+
<button
|
|
15
|
+
class="agent-session-collapsed__toggle"
|
|
16
|
+
type="button"
|
|
17
|
+
:aria-label="t('system.ai.chat.action.expandSessions')"
|
|
18
|
+
@click="toggleSessionPanel"
|
|
19
|
+
>
|
|
15
20
|
<el-icon><DArrowRight /></el-icon>
|
|
16
21
|
</button>
|
|
17
|
-
<span class="agent-session-collapsed__label"
|
|
22
|
+
<span class="agent-session-collapsed__label">{{ t("system.ai.chat.title.recentConversations") }}</span>
|
|
18
23
|
</div>
|
|
19
24
|
<ChatPanel
|
|
20
25
|
:active-session="activeSession"
|
|
@@ -44,6 +49,7 @@ import "vue-element-plus-x/styles/index.css";
|
|
|
44
49
|
import { computed, onBeforeUnmount, onMounted, ref } from "vue";
|
|
45
50
|
import { DArrowRight } from "@element-plus/icons-vue";
|
|
46
51
|
import { ElMessage, ElMessageBox } from "element-plus";
|
|
52
|
+
import { getCurrentLocale, t } from "@liujitcn/kratos-admin-core";
|
|
47
53
|
import { getAdminAiExtension } from "@liujitcn/kratos-admin-system";
|
|
48
54
|
import { defAiMessageService } from "@liujitcn/kratos-admin-system/api/base/ai_message";
|
|
49
55
|
import { defAiSessionService } from "@liujitcn/kratos-admin-system/api/base/ai_session";
|
|
@@ -145,7 +151,7 @@ async function handleSessionAction(payload: { action: SessionAction; item: AiSes
|
|
|
145
151
|
await handleDeleteSession(payload.item);
|
|
146
152
|
} catch (error) {
|
|
147
153
|
if (error === "cancel" || error === "close") {
|
|
148
|
-
ElMessage.info("
|
|
154
|
+
ElMessage.info(t("system.ai.chat.message.actionCanceled"));
|
|
149
155
|
}
|
|
150
156
|
}
|
|
151
157
|
}
|
|
@@ -156,7 +162,7 @@ async function handleCreateSession() {
|
|
|
156
162
|
if (!sessionID) return;
|
|
157
163
|
activeSessionID.value = sessionID;
|
|
158
164
|
messages.value[sessionID] = [];
|
|
159
|
-
ElMessage.success("
|
|
165
|
+
ElMessage.success(t("system.ai.chat.message.conversationCreated"));
|
|
160
166
|
}
|
|
161
167
|
|
|
162
168
|
/** 提交用户输入并同步消息流。 */
|
|
@@ -169,7 +175,7 @@ async function handleFlowAction(action: AiAction, label?: string) {
|
|
|
169
175
|
const sessionID = activeSessionID.value;
|
|
170
176
|
if (!sessionID || isSessionSending(sessionID)) return;
|
|
171
177
|
await sendAiPayload({
|
|
172
|
-
text: label || "
|
|
178
|
+
text: label || t("system.ai.chat.action.continue"),
|
|
173
179
|
attachments: [],
|
|
174
180
|
action
|
|
175
181
|
});
|
|
@@ -220,7 +226,7 @@ async function runAiStreamTask(sessionID: string, payload: SubmitPayload) {
|
|
|
220
226
|
);
|
|
221
227
|
|
|
222
228
|
if (!response.body) {
|
|
223
|
-
throw new Error("
|
|
229
|
+
throw new Error(t("system.ai.chat.message.emptyStream"));
|
|
224
230
|
}
|
|
225
231
|
await readAiEventStream(
|
|
226
232
|
response.body,
|
|
@@ -230,14 +236,14 @@ async function runAiStreamTask(sessionID: string, payload: SubmitPayload) {
|
|
|
230
236
|
controller.signal
|
|
231
237
|
);
|
|
232
238
|
if (!task.finished && !controller.signal.aborted) {
|
|
233
|
-
throw new Error("
|
|
239
|
+
throw new Error(t("system.ai.chat.message.incompleteStream"));
|
|
234
240
|
}
|
|
235
241
|
} catch (error) {
|
|
236
242
|
if (controller.signal.aborted) return;
|
|
237
243
|
messages.value[sessionID] = markThinkingMessageFailed(messages.value[sessionID] ?? [], {
|
|
238
244
|
sessionID
|
|
239
245
|
});
|
|
240
|
-
const message = error instanceof Error ? error.message : "
|
|
246
|
+
const message = error instanceof Error ? error.message : t("system.ai.chat.message.requestFailed");
|
|
241
247
|
ElMessage.error(message);
|
|
242
248
|
} finally {
|
|
243
249
|
if (runningStreamTaskMap.get(sessionID) === task) {
|
|
@@ -299,10 +305,10 @@ async function handleEditMessage(payload: ChatMessageEditPayload) {
|
|
|
299
305
|
const currentMessages = messages.value[sessionID] ?? [];
|
|
300
306
|
messages.value[sessionID] = replacePendingMessages(currentMessages, normalizeMessageList(response.messages));
|
|
301
307
|
if (response.session) upsertSession(normalizeSession(response.session));
|
|
302
|
-
ElMessage.success("
|
|
308
|
+
ElMessage.success(t("system.ai.chat.message.updatedAndRegenerated"));
|
|
303
309
|
} catch (error) {
|
|
304
310
|
await loadMessages(sessionID, { force: true });
|
|
305
|
-
const message = error instanceof Error ? error.message : "
|
|
311
|
+
const message = error instanceof Error ? error.message : t("system.ai.chat.message.updateFailed");
|
|
306
312
|
ElMessage.error(message);
|
|
307
313
|
} finally {
|
|
308
314
|
setSessionSending(sessionID, false);
|
|
@@ -313,9 +319,9 @@ async function handleEditMessage(payload: ChatMessageEditPayload) {
|
|
|
313
319
|
async function handleCopyMessage(item: ChatMessageItem) {
|
|
314
320
|
try {
|
|
315
321
|
await navigator.clipboard.writeText(String(item.content ?? ""));
|
|
316
|
-
ElMessage.success("
|
|
322
|
+
ElMessage.success(t("system.ai.chat.message.messageCopied"));
|
|
317
323
|
} catch {
|
|
318
|
-
ElMessage.error("
|
|
324
|
+
ElMessage.error(t("system.ai.chat.message.copyUnsupported"));
|
|
319
325
|
}
|
|
320
326
|
}
|
|
321
327
|
|
|
@@ -332,7 +338,7 @@ async function handleDeleteMessage(item: ChatMessageItem) {
|
|
|
332
338
|
if (item.role === "user") return !message.localOnly;
|
|
333
339
|
return resolveMessageBubbleKey(message) !== messageKey;
|
|
334
340
|
});
|
|
335
|
-
ElMessage.success("
|
|
341
|
+
ElMessage.success(t("system.ai.chat.message.messageDeleted"));
|
|
336
342
|
return;
|
|
337
343
|
}
|
|
338
344
|
await defAiMessageService.DeleteAiMessage({
|
|
@@ -340,7 +346,7 @@ async function handleDeleteMessage(item: ChatMessageItem) {
|
|
|
340
346
|
message_id: String(item.id)
|
|
341
347
|
});
|
|
342
348
|
messages.value[sessionID] = (messages.value[sessionID] ?? []).filter(message => String(message.id) !== String(item.id));
|
|
343
|
-
ElMessage.success("
|
|
349
|
+
ElMessage.success(t("system.ai.chat.message.messageDeleted"));
|
|
344
350
|
}
|
|
345
351
|
|
|
346
352
|
/** 重试失败的一轮消息,或重新生成助手输出。 */
|
|
@@ -353,19 +359,19 @@ async function handleRetryMessage(item: ChatMessageItem) {
|
|
|
353
359
|
if (item.localOnly) {
|
|
354
360
|
const payload = resolveLocalRetryPayload(item);
|
|
355
361
|
if (!payload) {
|
|
356
|
-
ElMessage.warning("
|
|
362
|
+
ElMessage.warning(t("system.ai.chat.message.localRetryMissing"));
|
|
357
363
|
return;
|
|
358
364
|
}
|
|
359
365
|
messages.value[sessionID] = (messages.value[sessionID] ?? []).filter(message => !message.localOnly);
|
|
360
366
|
if (await sendAiPayload(payload)) {
|
|
361
|
-
ElMessage.success("
|
|
367
|
+
ElMessage.success(t("system.ai.chat.message.resent"));
|
|
362
368
|
}
|
|
363
369
|
return;
|
|
364
370
|
}
|
|
365
371
|
setSessionSending(sessionID, true);
|
|
366
372
|
if (item.role === "user") {
|
|
367
373
|
if (item.status !== AiMessageStatus.FAILED_AMS) {
|
|
368
|
-
ElMessage.warning("
|
|
374
|
+
ElMessage.warning(t("system.ai.chat.message.retryFailedOnly"));
|
|
369
375
|
return;
|
|
370
376
|
}
|
|
371
377
|
response = await defAiMessageService.RetryAiUserMessage({
|
|
@@ -382,10 +388,10 @@ async function handleRetryMessage(item: ChatMessageItem) {
|
|
|
382
388
|
const current = messages.value[sessionID] ?? [];
|
|
383
389
|
messages.value[sessionID] = replacePendingMessages(current, normalizeMessageList(response.messages));
|
|
384
390
|
if (response.session) upsertSession(normalizeSession(response.session));
|
|
385
|
-
ElMessage.success(item.role === "user" ? "
|
|
391
|
+
ElMessage.success(item.role === "user" ? t("system.ai.chat.message.resent") : t("system.ai.chat.message.regenerated"));
|
|
386
392
|
} catch (error) {
|
|
387
393
|
if (item.role !== "user") await loadMessages(sessionID, { force: true });
|
|
388
|
-
const message = error instanceof Error ? error.message : "
|
|
394
|
+
const message = error instanceof Error ? error.message : t("system.ai.chat.message.regenerateFailed");
|
|
389
395
|
ElMessage.error(message);
|
|
390
396
|
} finally {
|
|
391
397
|
if (!item.localOnly) {
|
|
@@ -433,14 +439,14 @@ async function handleBranchMessage(item: ChatMessageItem) {
|
|
|
433
439
|
upsertSession(branchSession);
|
|
434
440
|
messages.value[branchSession.id] = normalizeMessageList(response.messages);
|
|
435
441
|
activeSessionID.value = branchSession.id;
|
|
436
|
-
ElMessage.success("
|
|
442
|
+
ElMessage.success(t("system.ai.chat.message.branchCreated"));
|
|
437
443
|
}
|
|
438
444
|
|
|
439
445
|
/** 朗读或停止朗读当前助手输出。 */
|
|
440
446
|
function handleSpeakMessage(item: ChatMessageItem) {
|
|
441
447
|
if (item.role === "user") return;
|
|
442
448
|
if (!window.speechSynthesis) {
|
|
443
|
-
ElMessage.warning("
|
|
449
|
+
ElMessage.warning(t("system.ai.chat.message.speechUnsupported"));
|
|
444
450
|
return;
|
|
445
451
|
}
|
|
446
452
|
const messageKey = resolveMessageBubbleKey(item);
|
|
@@ -450,7 +456,7 @@ function handleSpeakMessage(item: ChatMessageItem) {
|
|
|
450
456
|
}
|
|
451
457
|
stopSpeaking();
|
|
452
458
|
const utterance = new SpeechSynthesisUtterance(String(item.content ?? ""));
|
|
453
|
-
utterance.lang =
|
|
459
|
+
utterance.lang = getCurrentLocale();
|
|
454
460
|
utterance.onend = () => clearSpeakingState(messageKey);
|
|
455
461
|
utterance.onerror = () => clearSpeakingState(messageKey);
|
|
456
462
|
speakingMessageID = messageKey;
|
|
@@ -665,26 +671,34 @@ async function loadMessages(sessionID: string, options?: { force?: boolean }) {
|
|
|
665
671
|
|
|
666
672
|
/** 重命名当前会话。 */
|
|
667
673
|
async function handleRenameSession(item: AiSession) {
|
|
668
|
-
const { value } = await ElMessageBox.prompt(
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
674
|
+
const { value } = await ElMessageBox.prompt(
|
|
675
|
+
t("system.ai.chat.dialog.renameDescription", { title: item.title }),
|
|
676
|
+
t("system.ai.chat.dialog.renameTitle"),
|
|
677
|
+
{
|
|
678
|
+
confirmButtonText: t("common.action.confirm"),
|
|
679
|
+
cancelButtonText: t("common.action.cancel"),
|
|
680
|
+
inputValue: item.title,
|
|
681
|
+
inputPattern: /\S+/,
|
|
682
|
+
inputErrorMessage: t("system.ai.chat.placeholder.conversationName")
|
|
683
|
+
}
|
|
684
|
+
);
|
|
675
685
|
|
|
676
686
|
const response = await defAiSessionService.UpdateAiSession({ id: item.id, title: value.trim() });
|
|
677
687
|
upsertSession(normalizeSession(response.session));
|
|
678
|
-
ElMessage.success("
|
|
688
|
+
ElMessage.success(t("system.ai.chat.message.conversationRenamed"));
|
|
679
689
|
}
|
|
680
690
|
|
|
681
691
|
/** 删除当前会话,并自动切换到剩余会话。 */
|
|
682
692
|
async function handleDeleteSession(item: AiSession) {
|
|
683
|
-
await ElMessageBox.confirm(
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
693
|
+
await ElMessageBox.confirm(
|
|
694
|
+
t("system.ai.chat.dialog.deleteDescription", { title: item.title }),
|
|
695
|
+
t("system.ai.chat.dialog.deleteTitle"),
|
|
696
|
+
{
|
|
697
|
+
confirmButtonText: t("system.ai.chat.action.confirmDeleteConversation"),
|
|
698
|
+
cancelButtonText: t("common.action.cancel"),
|
|
699
|
+
type: "warning"
|
|
700
|
+
}
|
|
701
|
+
);
|
|
688
702
|
|
|
689
703
|
await defAiSessionService.DeleteAiSession({ id: item.id });
|
|
690
704
|
cancelSessionStreamTask(item.id);
|
|
@@ -697,7 +711,7 @@ async function handleDeleteSession(item: AiSession) {
|
|
|
697
711
|
const nextSessionID = await ensureActiveSession();
|
|
698
712
|
if (nextSessionID) await loadMessages(nextSessionID);
|
|
699
713
|
|
|
700
|
-
ElMessage.success("
|
|
714
|
+
ElMessage.success(t("system.ai.chat.message.conversationDeleted"));
|
|
701
715
|
}
|
|
702
716
|
|
|
703
717
|
/** 保证当前存在可用会话;当列表为空时自动创建首个会话。 */
|
|
@@ -714,7 +728,7 @@ async function ensureActiveSession() {
|
|
|
714
728
|
/** 创建新的助手会话,并同步到本地列表。 */
|
|
715
729
|
async function createSession(options?: { title?: string }) {
|
|
716
730
|
const response = await defAiSessionService.CreateAiSession({
|
|
717
|
-
title: options?.title || "
|
|
731
|
+
title: options?.title || t("system.ai.chat.value.newConversation"),
|
|
718
732
|
terminal: Terminal.TERMINAL_ADMIN
|
|
719
733
|
});
|
|
720
734
|
const normalizedSession = normalizeSession(response.session);
|
|
@@ -724,10 +738,12 @@ async function createSession(options?: { title?: string }) {
|
|
|
724
738
|
|
|
725
739
|
/** 使用当前消息内容生成一个易识别的分支会话标题。 */
|
|
726
740
|
function buildBranchSessionTitle(item: ChatMessageItem) {
|
|
727
|
-
const content = String(item.input_content?.content || item.content || "
|
|
741
|
+
const content = String(item.input_content?.content || item.content || t("system.ai.chat.value.newConversation"))
|
|
728
742
|
.replace(/\s+/g, " ")
|
|
729
743
|
.trim();
|
|
730
|
-
return
|
|
744
|
+
return t("system.ai.chat.value.branchTitle", {
|
|
745
|
+
title: content.slice(0, 18) || t("system.ai.chat.value.newConversation")
|
|
746
|
+
});
|
|
731
747
|
}
|
|
732
748
|
|
|
733
749
|
/** 归一化快捷入口,保证空态展示稳定排序。 */
|
|
@@ -8,12 +8,13 @@ import {
|
|
|
8
8
|
} from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_session";
|
|
9
9
|
import type { AiAction } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_message";
|
|
10
10
|
import { AiMessageStatus, Terminal } from "@liujitcn/kratos-admin-system/rpc/base/v1/enum";
|
|
11
|
+
import { t } from "@liujitcn/kratos-admin-core";
|
|
11
12
|
import type { AiStreamPayload, AIFlowBlock, ChatMessageItem, ReplySourceTag } from "./types";
|
|
12
13
|
|
|
13
14
|
const THINKING_MESSAGE_ID_PREFIX = "ai-thinking";
|
|
14
15
|
const LOCAL_USER_MESSAGE_ID_PREFIX = "ai-user-local";
|
|
15
16
|
const PENDING_STREAM_MESSAGE_ID = "pending";
|
|
16
|
-
const
|
|
17
|
+
const thinkingMessageContent = () => t("system.ai.chat.message.thinking");
|
|
17
18
|
|
|
18
19
|
/** 生成流式消息分组键,确保同一轮回复只更新当前占位气泡。 */
|
|
19
20
|
export function buildStreamMessageKey(sessionID: string, messageID: string) {
|
|
@@ -42,7 +43,7 @@ export function resolveTimestamp(timestamp?: { seconds?: number; nanos?: number
|
|
|
42
43
|
export function normalizeSession(session?: Partial<AiSession> | null): AiSession {
|
|
43
44
|
return {
|
|
44
45
|
id: String(session?.id ?? ""),
|
|
45
|
-
title: String(session?.title ?? "
|
|
46
|
+
title: String(session?.title ?? t("system.ai.chat.value.newConversation")),
|
|
46
47
|
summary: String(session?.summary ?? ""),
|
|
47
48
|
updated_at: session?.updated_at,
|
|
48
49
|
terminal: Number(session?.terminal ?? Terminal.TERMINAL_ADMIN)
|
|
@@ -60,16 +61,16 @@ export function resolveReplySourceTag(
|
|
|
60
61
|
item: Pick<ChatMessageItem, "role" | "fallback" | "reply_source" | "model">
|
|
61
62
|
): ReplySourceTag | undefined {
|
|
62
63
|
if (item.role === "user") return undefined;
|
|
63
|
-
if (item.fallback) return { text: "
|
|
64
|
+
if (item.fallback) return { text: t("system.ai.chat.source.fallback"), tone: "warning" };
|
|
64
65
|
switch (String(item.reply_source ?? "")) {
|
|
65
66
|
case "network":
|
|
66
|
-
return { text: "
|
|
67
|
+
return { text: t("system.ai.chat.source.network"), tone: "success" };
|
|
67
68
|
case "llm":
|
|
68
|
-
return { text: "
|
|
69
|
+
return { text: t("system.ai.chat.source.model"), tone: "primary" };
|
|
69
70
|
case "fallback":
|
|
70
|
-
return { text: "
|
|
71
|
+
return { text: t("system.ai.chat.source.fallback"), tone: "warning" };
|
|
71
72
|
default:
|
|
72
|
-
return item.model ? { text: "
|
|
73
|
+
return item.model ? { text: t("system.ai.chat.source.model"), tone: "primary" } : undefined;
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -236,7 +237,7 @@ export function createThinkingMessage(options?: { sessionID?: string; messageID?
|
|
|
236
237
|
input_content: undefined,
|
|
237
238
|
output_content: {
|
|
238
239
|
kind: "text",
|
|
239
|
-
content:
|
|
240
|
+
content: thinkingMessageContent(),
|
|
240
241
|
reply_source: "",
|
|
241
242
|
model: "",
|
|
242
243
|
fallback: false,
|
|
@@ -261,7 +262,7 @@ export function createThinkingMessage(options?: { sessionID?: string; messageID?
|
|
|
261
262
|
message.progressState = "streaming";
|
|
262
263
|
message.localOnly = true;
|
|
263
264
|
message.streamKey = streamKey;
|
|
264
|
-
message.replySourceTag = { text: "
|
|
265
|
+
message.replySourceTag = { text: t("system.ai.chat.status.thinking"), tone: "info" };
|
|
265
266
|
return message;
|
|
266
267
|
}
|
|
267
268
|
|
|
@@ -290,7 +291,7 @@ export function markAIMessageRegenerating(current: ChatMessageItem[], sessionID:
|
|
|
290
291
|
if (String(item.id) !== messageID || item.role === "user") return item;
|
|
291
292
|
return {
|
|
292
293
|
...item,
|
|
293
|
-
content:
|
|
294
|
+
content: thinkingMessageContent(),
|
|
294
295
|
fallback: false,
|
|
295
296
|
fallback_reason: "",
|
|
296
297
|
token: normalizeToken(),
|
|
@@ -298,7 +299,7 @@ export function markAIMessageRegenerating(current: ChatMessageItem[], sessionID:
|
|
|
298
299
|
first_token_ms: 0,
|
|
299
300
|
duration_ms: 0,
|
|
300
301
|
progressState: "streaming",
|
|
301
|
-
replySourceTag: { text: "
|
|
302
|
+
replySourceTag: { text: t("system.ai.chat.status.thinking"), tone: "info" },
|
|
302
303
|
status: AiMessageStatus.GENERATING_AMS,
|
|
303
304
|
streamKey
|
|
304
305
|
};
|
|
@@ -362,8 +363,8 @@ export function markThinkingMessageFailed(current: ChatMessageItem[], options?:
|
|
|
362
363
|
...item,
|
|
363
364
|
progressState: "failed",
|
|
364
365
|
status: AiMessageStatus.FAILED_AMS,
|
|
365
|
-
content: "
|
|
366
|
-
replySourceTag: { text: "
|
|
366
|
+
content: t("system.ai.chat.message.replyFailed"),
|
|
367
|
+
replySourceTag: { text: t("system.ai.chat.status.sendFailed"), tone: "warning" }
|
|
367
368
|
};
|
|
368
369
|
});
|
|
369
370
|
}
|
|
@@ -379,13 +380,13 @@ export function appendStreamingDelta(current: ChatMessageItem[], payload: AiStre
|
|
|
379
380
|
const streamKey = buildStreamMessageKey(String(payload.session_id ?? ""), String(payload.message_id ?? ""));
|
|
380
381
|
return current.map<ChatMessageItem>(item => {
|
|
381
382
|
if (item.streamKey !== streamKey || (!item.localOnly && item.role === "user")) return item;
|
|
382
|
-
const baseContent = item.content ===
|
|
383
|
+
const baseContent = item.content === thinkingMessageContent() ? "" : item.content;
|
|
383
384
|
const nextContent = `${baseContent}${payload.delta ?? ""}`;
|
|
384
385
|
return {
|
|
385
386
|
...item,
|
|
386
387
|
content: nextContent || item.content,
|
|
387
388
|
progressState: "streaming",
|
|
388
|
-
replySourceTag: { text: "
|
|
389
|
+
replySourceTag: { text: t("system.ai.chat.status.answering"), tone: "info" }
|
|
389
390
|
};
|
|
390
391
|
});
|
|
391
392
|
}
|
|
@@ -401,8 +402,8 @@ export function markStreamingError(current: ChatMessageItem[], payload: AiStream
|
|
|
401
402
|
...item,
|
|
402
403
|
progressState: "failed",
|
|
403
404
|
status: AiMessageStatus.FAILED_AMS,
|
|
404
|
-
content: "
|
|
405
|
-
replySourceTag: { text: "
|
|
405
|
+
content: t("system.ai.chat.message.replyFailed"),
|
|
406
|
+
replySourceTag: { text: t("system.ai.chat.status.sendFailed"), tone: "warning" }
|
|
406
407
|
};
|
|
407
408
|
});
|
|
408
409
|
}
|