@liujitcn/kratos-admin-system 0.0.20 → 0.0.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/README.md +51 -50
- package/dist/package/declarations/src/api/system/base_language.d.ts +52 -0
- package/dist/package/declarations/src/api/system/base_translation.d.ts +10 -0
- package/dist/package/declarations/src/api/system/code_gen_i18n.d.ts +8 -0
- package/dist/package/declarations/src/api/system/ops_monitoring.d.ts +19 -0
- package/dist/package/declarations/src/api/system/ops_monitoring_sse.d.ts +12 -0
- package/dist/package/declarations/src/components/DynamicTranslationCell.vue.d.ts +16 -0
- package/dist/package/declarations/src/components/DynamicTranslationEditor.vue.d.ts +20 -0
- package/dist/package/declarations/src/components/dynamicTranslation.d.ts +38 -0
- package/dist/package/declarations/src/locales/generated.d.ts +6536 -0
- package/dist/package/declarations/src/rpc/base/v1/ai_session.d.ts +12 -2
- package/dist/package/declarations/src/rpc/base/v1/ai_tool.d.ts +9 -1
- package/dist/package/declarations/src/rpc/base/v1/config.d.ts +35 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/auth.d.ts +1 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +23 -2
- package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +9 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_job.d.ts +9 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/base_language.d.ts +119 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_menu.d.ts +6 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/base_migration.d.ts +6 -6
- package/dist/package/declarations/src/rpc/system/admin/v1/base_role.d.ts +13 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/base_translation.d.ts +75 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_user.d.ts +11 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/code_gen.d.ts +13 -11
- 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 +24 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/common.d.ts +13 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/ops_monitoring.d.ts +222 -0
- package/dist/package/declarations/src/views/base/language/index.vue.d.ts +3 -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/ops-monitoring/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 +135 -0
- package/dist/package/src/api/system/base_translation.ts +33 -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/api/system/ops_monitoring.ts +88 -0
- package/dist/package/src/api/system/ops_monitoring_sse.ts +49 -0
- package/dist/package/src/components/DynamicTranslationCell.vue +249 -0
- package/dist/package/src/components/DynamicTranslationEditor.vue +197 -0
- package/dist/package/src/components/dynamicTranslation.ts +66 -0
- package/dist/package/src/locales/README.md +30 -0
- package/dist/package/src/locales/en-US.json +933 -0
- package/dist/package/src/locales/es-ES.json +933 -0
- package/dist/package/src/locales/fr-FR.json +933 -0
- package/dist/package/src/locales/generated.ts +22 -0
- package/dist/package/src/locales/ja-JP.json +933 -0
- package/dist/package/src/locales/ko-KR.json +933 -0
- package/dist/package/src/locales/zh-CN.json +933 -0
- package/dist/package/src/locales/zh-TW.json +933 -0
- package/dist/package/src/module.ts +6 -2
- package/dist/package/src/rpc/base/v1/ai_session.ts +13 -2
- package/dist/package/src/rpc/base/v1/ai_tool.ts +10 -1
- package/dist/package/src/rpc/base/v1/config.ts +47 -0
- package/dist/package/src/rpc/system/admin/v1/auth.ts +1 -1
- package/dist/package/src/rpc/system/admin/v1/base_config.ts +24 -2
- package/dist/package/src/rpc/system/admin/v1/base_dict.ts +9 -0
- package/dist/package/src/rpc/system/admin/v1/base_job.ts +10 -1
- package/dist/package/src/rpc/system/admin/v1/base_language.ts +141 -0
- package/dist/package/src/rpc/system/admin/v1/base_menu.ts +6 -1
- package/dist/package/src/rpc/system/admin/v1/base_migration.ts +8 -8
- package/dist/package/src/rpc/system/admin/v1/base_role.ts +14 -1
- package/dist/package/src/rpc/system/admin/v1/base_translation.ts +90 -0
- package/dist/package/src/rpc/system/admin/v1/base_user.ts +12 -1
- package/dist/package/src/rpc/system/admin/v1/code_gen.ts +16 -12
- 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 +27 -1
- package/dist/package/src/rpc/system/admin/v1/common.ts +21 -0
- package/dist/package/src/rpc/system/admin/v1/ops_monitoring.ts +255 -0
- package/dist/package/src/views/ai/chat/components/AiMarkdown.vue +1 -6
- package/dist/package/src/views/ai/chat/components/ChatPanel.vue +75 -58
- 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 +58 -41
- package/dist/package/src/views/ai/chat/message.ts +29 -27
- package/dist/package/src/views/base/api/index.vue +121 -84
- package/dist/package/src/views/base/area/index.vue +81 -32
- package/dist/package/src/views/base/config/index.vue +300 -96
- package/dist/package/src/views/base/dept/index.vue +110 -62
- package/dist/package/src/views/base/dict/index.vue +145 -62
- package/dist/package/src/views/base/dict/item.vue +155 -64
- package/dist/package/src/views/base/job/index.vue +134 -82
- package/dist/package/src/views/base/job/log.vue +24 -25
- package/dist/package/src/views/base/language/index.vue +260 -0
- package/dist/package/src/views/base/log/index.vue +68 -46
- package/dist/package/src/views/base/menu/index.vue +344 -200
- package/dist/package/src/views/base/migration/index.vue +49 -29
- package/dist/package/src/views/base/post/index.vue +128 -60
- package/dist/package/src/views/base/role/index.vue +145 -79
- package/dist/package/src/views/base/tenant/index.vue +132 -64
- package/dist/package/src/views/base/user/components/dept-tree.vue +2 -1
- package/dist/package/src/views/base/user/index.vue +194 -116
- package/dist/package/src/views/profile/components/base.vue +45 -28
- package/dist/package/src/views/profile/components/password.vue +45 -30
- package/dist/package/src/views/profile/components/security.vue +90 -54
- 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 +32 -16
- 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 +116 -79
- 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 -59
- package/dist/package/src/views/tool/code-gen/proto/index.vue +110 -62
- package/dist/package/src/views/tool/code-gen/table/index.vue +201 -121
- package/dist/package/src/views/tool/ops-monitoring/index.vue +1175 -0
- package/dist/package/src/views/tool/project-doc/index.vue +17 -15
- package/package.json +6 -2
- package/dist/package/declarations/src/rpc/base/v1/enum.d.ts +0 -43
- package/dist/package/declarations/src/rpc/system/common/v1/enum.d.ts +0 -67
- package/dist/package/src/rpc/base/v1/enum.ts +0 -54
- package/dist/package/src/rpc/system/common/v1/enum.ts +0 -80
|
@@ -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.expand_sessions')"
|
|
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.recent_conversations") }}</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";
|
|
@@ -51,7 +57,8 @@ import { defAiToolService } from "@liujitcn/kratos-admin-system/api/base/ai_tool
|
|
|
51
57
|
import type { AiAction } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_message";
|
|
52
58
|
import type { AiSession } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_session";
|
|
53
59
|
import type { AiShortcut } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_tool";
|
|
54
|
-
import { AiMessageStatus
|
|
60
|
+
import { AiMessageStatus } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_session";
|
|
61
|
+
import { Terminal } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_tool";
|
|
55
62
|
import ChatPanel from "./components/ChatPanel.vue";
|
|
56
63
|
import SessionPanel from "./components/SessionPanel.vue";
|
|
57
64
|
import {
|
|
@@ -145,7 +152,7 @@ async function handleSessionAction(payload: { action: SessionAction; item: AiSes
|
|
|
145
152
|
await handleDeleteSession(payload.item);
|
|
146
153
|
} catch (error) {
|
|
147
154
|
if (error === "cancel" || error === "close") {
|
|
148
|
-
ElMessage.info("
|
|
155
|
+
ElMessage.info(t("system.ai.chat.message.action_canceled"));
|
|
149
156
|
}
|
|
150
157
|
}
|
|
151
158
|
}
|
|
@@ -156,7 +163,7 @@ async function handleCreateSession() {
|
|
|
156
163
|
if (!sessionID) return;
|
|
157
164
|
activeSessionID.value = sessionID;
|
|
158
165
|
messages.value[sessionID] = [];
|
|
159
|
-
ElMessage.success("
|
|
166
|
+
ElMessage.success(t("system.ai.chat.message.conversation_created"));
|
|
160
167
|
}
|
|
161
168
|
|
|
162
169
|
/** 提交用户输入并同步消息流。 */
|
|
@@ -169,7 +176,7 @@ async function handleFlowAction(action: AiAction, label?: string) {
|
|
|
169
176
|
const sessionID = activeSessionID.value;
|
|
170
177
|
if (!sessionID || isSessionSending(sessionID)) return;
|
|
171
178
|
await sendAiPayload({
|
|
172
|
-
text: label || "
|
|
179
|
+
text: label || t("system.ai.chat.action.continue"),
|
|
173
180
|
attachments: [],
|
|
174
181
|
action
|
|
175
182
|
});
|
|
@@ -220,7 +227,7 @@ async function runAiStreamTask(sessionID: string, payload: SubmitPayload) {
|
|
|
220
227
|
);
|
|
221
228
|
|
|
222
229
|
if (!response.body) {
|
|
223
|
-
throw new Error("
|
|
230
|
+
throw new Error(t("system.ai.chat.message.empty_stream"));
|
|
224
231
|
}
|
|
225
232
|
await readAiEventStream(
|
|
226
233
|
response.body,
|
|
@@ -230,14 +237,14 @@ async function runAiStreamTask(sessionID: string, payload: SubmitPayload) {
|
|
|
230
237
|
controller.signal
|
|
231
238
|
);
|
|
232
239
|
if (!task.finished && !controller.signal.aborted) {
|
|
233
|
-
throw new Error("
|
|
240
|
+
throw new Error(t("system.ai.chat.message.incomplete_stream"));
|
|
234
241
|
}
|
|
235
242
|
} catch (error) {
|
|
236
243
|
if (controller.signal.aborted) return;
|
|
237
244
|
messages.value[sessionID] = markThinkingMessageFailed(messages.value[sessionID] ?? [], {
|
|
238
245
|
sessionID
|
|
239
246
|
});
|
|
240
|
-
const message = error instanceof Error ? error.message : "
|
|
247
|
+
const message = error instanceof Error ? error.message : t("system.ai.chat.message.request_failed");
|
|
241
248
|
ElMessage.error(message);
|
|
242
249
|
} finally {
|
|
243
250
|
if (runningStreamTaskMap.get(sessionID) === task) {
|
|
@@ -299,10 +306,10 @@ async function handleEditMessage(payload: ChatMessageEditPayload) {
|
|
|
299
306
|
const currentMessages = messages.value[sessionID] ?? [];
|
|
300
307
|
messages.value[sessionID] = replacePendingMessages(currentMessages, normalizeMessageList(response.messages));
|
|
301
308
|
if (response.session) upsertSession(normalizeSession(response.session));
|
|
302
|
-
ElMessage.success("
|
|
309
|
+
ElMessage.success(t("system.ai.chat.message.updated_and_regenerated"));
|
|
303
310
|
} catch (error) {
|
|
304
311
|
await loadMessages(sessionID, { force: true });
|
|
305
|
-
const message = error instanceof Error ? error.message : "
|
|
312
|
+
const message = error instanceof Error ? error.message : t("system.ai.chat.message.update_failed");
|
|
306
313
|
ElMessage.error(message);
|
|
307
314
|
} finally {
|
|
308
315
|
setSessionSending(sessionID, false);
|
|
@@ -313,9 +320,9 @@ async function handleEditMessage(payload: ChatMessageEditPayload) {
|
|
|
313
320
|
async function handleCopyMessage(item: ChatMessageItem) {
|
|
314
321
|
try {
|
|
315
322
|
await navigator.clipboard.writeText(String(item.content ?? ""));
|
|
316
|
-
ElMessage.success("
|
|
323
|
+
ElMessage.success(t("system.ai.chat.message.message_copied"));
|
|
317
324
|
} catch {
|
|
318
|
-
ElMessage.error("
|
|
325
|
+
ElMessage.error(t("system.ai.chat.message.copy_unsupported"));
|
|
319
326
|
}
|
|
320
327
|
}
|
|
321
328
|
|
|
@@ -332,7 +339,7 @@ async function handleDeleteMessage(item: ChatMessageItem) {
|
|
|
332
339
|
if (item.role === "user") return !message.localOnly;
|
|
333
340
|
return resolveMessageBubbleKey(message) !== messageKey;
|
|
334
341
|
});
|
|
335
|
-
ElMessage.success("
|
|
342
|
+
ElMessage.success(t("system.ai.chat.message.message_deleted"));
|
|
336
343
|
return;
|
|
337
344
|
}
|
|
338
345
|
await defAiMessageService.DeleteAiMessage({
|
|
@@ -340,7 +347,7 @@ async function handleDeleteMessage(item: ChatMessageItem) {
|
|
|
340
347
|
message_id: String(item.id)
|
|
341
348
|
});
|
|
342
349
|
messages.value[sessionID] = (messages.value[sessionID] ?? []).filter(message => String(message.id) !== String(item.id));
|
|
343
|
-
ElMessage.success("
|
|
350
|
+
ElMessage.success(t("system.ai.chat.message.message_deleted"));
|
|
344
351
|
}
|
|
345
352
|
|
|
346
353
|
/** 重试失败的一轮消息,或重新生成助手输出。 */
|
|
@@ -353,19 +360,19 @@ async function handleRetryMessage(item: ChatMessageItem) {
|
|
|
353
360
|
if (item.localOnly) {
|
|
354
361
|
const payload = resolveLocalRetryPayload(item);
|
|
355
362
|
if (!payload) {
|
|
356
|
-
ElMessage.warning("
|
|
363
|
+
ElMessage.warning(t("system.ai.chat.message.local_retry_missing"));
|
|
357
364
|
return;
|
|
358
365
|
}
|
|
359
366
|
messages.value[sessionID] = (messages.value[sessionID] ?? []).filter(message => !message.localOnly);
|
|
360
367
|
if (await sendAiPayload(payload)) {
|
|
361
|
-
ElMessage.success("
|
|
368
|
+
ElMessage.success(t("system.ai.chat.message.resent"));
|
|
362
369
|
}
|
|
363
370
|
return;
|
|
364
371
|
}
|
|
365
372
|
setSessionSending(sessionID, true);
|
|
366
373
|
if (item.role === "user") {
|
|
367
|
-
if (item.status !== AiMessageStatus.
|
|
368
|
-
ElMessage.warning("
|
|
374
|
+
if (item.status !== AiMessageStatus.AI_MESSAGE_STATUS_FAILED) {
|
|
375
|
+
ElMessage.warning(t("system.ai.chat.message.retry_failed_only"));
|
|
369
376
|
return;
|
|
370
377
|
}
|
|
371
378
|
response = await defAiMessageService.RetryAiUserMessage({
|
|
@@ -382,10 +389,10 @@ async function handleRetryMessage(item: ChatMessageItem) {
|
|
|
382
389
|
const current = messages.value[sessionID] ?? [];
|
|
383
390
|
messages.value[sessionID] = replacePendingMessages(current, normalizeMessageList(response.messages));
|
|
384
391
|
if (response.session) upsertSession(normalizeSession(response.session));
|
|
385
|
-
ElMessage.success(item.role === "user" ? "
|
|
392
|
+
ElMessage.success(item.role === "user" ? t("system.ai.chat.message.resent") : t("system.ai.chat.message.regenerated"));
|
|
386
393
|
} catch (error) {
|
|
387
394
|
if (item.role !== "user") await loadMessages(sessionID, { force: true });
|
|
388
|
-
const message = error instanceof Error ? error.message : "
|
|
395
|
+
const message = error instanceof Error ? error.message : t("system.ai.chat.message.regenerate_failed");
|
|
389
396
|
ElMessage.error(message);
|
|
390
397
|
} finally {
|
|
391
398
|
if (!item.localOnly) {
|
|
@@ -433,14 +440,14 @@ async function handleBranchMessage(item: ChatMessageItem) {
|
|
|
433
440
|
upsertSession(branchSession);
|
|
434
441
|
messages.value[branchSession.id] = normalizeMessageList(response.messages);
|
|
435
442
|
activeSessionID.value = branchSession.id;
|
|
436
|
-
ElMessage.success("
|
|
443
|
+
ElMessage.success(t("system.ai.chat.message.branch_created"));
|
|
437
444
|
}
|
|
438
445
|
|
|
439
446
|
/** 朗读或停止朗读当前助手输出。 */
|
|
440
447
|
function handleSpeakMessage(item: ChatMessageItem) {
|
|
441
448
|
if (item.role === "user") return;
|
|
442
449
|
if (!window.speechSynthesis) {
|
|
443
|
-
ElMessage.warning("
|
|
450
|
+
ElMessage.warning(t("system.ai.chat.message.speech_unsupported"));
|
|
444
451
|
return;
|
|
445
452
|
}
|
|
446
453
|
const messageKey = resolveMessageBubbleKey(item);
|
|
@@ -450,7 +457,7 @@ function handleSpeakMessage(item: ChatMessageItem) {
|
|
|
450
457
|
}
|
|
451
458
|
stopSpeaking();
|
|
452
459
|
const utterance = new SpeechSynthesisUtterance(String(item.content ?? ""));
|
|
453
|
-
utterance.lang =
|
|
460
|
+
utterance.lang = getCurrentLocale();
|
|
454
461
|
utterance.onend = () => clearSpeakingState(messageKey);
|
|
455
462
|
utterance.onerror = () => clearSpeakingState(messageKey);
|
|
456
463
|
speakingMessageID = messageKey;
|
|
@@ -665,26 +672,34 @@ async function loadMessages(sessionID: string, options?: { force?: boolean }) {
|
|
|
665
672
|
|
|
666
673
|
/** 重命名当前会话。 */
|
|
667
674
|
async function handleRenameSession(item: AiSession) {
|
|
668
|
-
const { value } = await ElMessageBox.prompt(
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
+
const { value } = await ElMessageBox.prompt(
|
|
676
|
+
t("system.ai.chat.dialog.rename_description", { title: item.title }),
|
|
677
|
+
t("system.ai.chat.dialog.rename_title"),
|
|
678
|
+
{
|
|
679
|
+
confirmButtonText: t("common.action.confirm"),
|
|
680
|
+
cancelButtonText: t("common.action.cancel"),
|
|
681
|
+
inputValue: item.title,
|
|
682
|
+
inputPattern: /\S+/,
|
|
683
|
+
inputErrorMessage: t("system.ai.chat.placeholder.conversation_name")
|
|
684
|
+
}
|
|
685
|
+
);
|
|
675
686
|
|
|
676
687
|
const response = await defAiSessionService.UpdateAiSession({ id: item.id, title: value.trim() });
|
|
677
688
|
upsertSession(normalizeSession(response.session));
|
|
678
|
-
ElMessage.success("
|
|
689
|
+
ElMessage.success(t("system.ai.chat.message.conversation_renamed"));
|
|
679
690
|
}
|
|
680
691
|
|
|
681
692
|
/** 删除当前会话,并自动切换到剩余会话。 */
|
|
682
693
|
async function handleDeleteSession(item: AiSession) {
|
|
683
|
-
await ElMessageBox.confirm(
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
694
|
+
await ElMessageBox.confirm(
|
|
695
|
+
t("system.ai.chat.dialog.delete_description", { title: item.title }),
|
|
696
|
+
t("system.ai.chat.dialog.delete_title"),
|
|
697
|
+
{
|
|
698
|
+
confirmButtonText: t("system.ai.chat.action.confirm_delete_conversation"),
|
|
699
|
+
cancelButtonText: t("common.action.cancel"),
|
|
700
|
+
type: "warning"
|
|
701
|
+
}
|
|
702
|
+
);
|
|
688
703
|
|
|
689
704
|
await defAiSessionService.DeleteAiSession({ id: item.id });
|
|
690
705
|
cancelSessionStreamTask(item.id);
|
|
@@ -697,7 +712,7 @@ async function handleDeleteSession(item: AiSession) {
|
|
|
697
712
|
const nextSessionID = await ensureActiveSession();
|
|
698
713
|
if (nextSessionID) await loadMessages(nextSessionID);
|
|
699
714
|
|
|
700
|
-
ElMessage.success("
|
|
715
|
+
ElMessage.success(t("system.ai.chat.message.conversation_deleted"));
|
|
701
716
|
}
|
|
702
717
|
|
|
703
718
|
/** 保证当前存在可用会话;当列表为空时自动创建首个会话。 */
|
|
@@ -714,7 +729,7 @@ async function ensureActiveSession() {
|
|
|
714
729
|
/** 创建新的助手会话,并同步到本地列表。 */
|
|
715
730
|
async function createSession(options?: { title?: string }) {
|
|
716
731
|
const response = await defAiSessionService.CreateAiSession({
|
|
717
|
-
title: options?.title || "
|
|
732
|
+
title: options?.title || t("system.ai.chat.value.new_conversation"),
|
|
718
733
|
terminal: Terminal.TERMINAL_ADMIN
|
|
719
734
|
});
|
|
720
735
|
const normalizedSession = normalizeSession(response.session);
|
|
@@ -724,10 +739,12 @@ async function createSession(options?: { title?: string }) {
|
|
|
724
739
|
|
|
725
740
|
/** 使用当前消息内容生成一个易识别的分支会话标题。 */
|
|
726
741
|
function buildBranchSessionTitle(item: ChatMessageItem) {
|
|
727
|
-
const content = String(item.input_content?.content || item.content || "
|
|
742
|
+
const content = String(item.input_content?.content || item.content || t("system.ai.chat.value.new_conversation"))
|
|
728
743
|
.replace(/\s+/g, " ")
|
|
729
744
|
.trim();
|
|
730
|
-
return
|
|
745
|
+
return t("system.ai.chat.value.branch_title", {
|
|
746
|
+
title: content.slice(0, 18) || t("system.ai.chat.value.new_conversation")
|
|
747
|
+
});
|
|
731
748
|
}
|
|
732
749
|
|
|
733
750
|
/** 归一化快捷入口,保证空态展示稳定排序。 */
|
|
@@ -7,13 +7,15 @@ import {
|
|
|
7
7
|
type AiToken
|
|
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
|
-
import { AiMessageStatus
|
|
10
|
+
import { AiMessageStatus } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_session";
|
|
11
|
+
import { Terminal } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_tool";
|
|
12
|
+
import { t } from "@liujitcn/kratos-admin-core";
|
|
11
13
|
import type { AiStreamPayload, AIFlowBlock, ChatMessageItem, ReplySourceTag } from "./types";
|
|
12
14
|
|
|
13
15
|
const THINKING_MESSAGE_ID_PREFIX = "ai-thinking";
|
|
14
16
|
const LOCAL_USER_MESSAGE_ID_PREFIX = "ai-user-local";
|
|
15
17
|
const PENDING_STREAM_MESSAGE_ID = "pending";
|
|
16
|
-
const
|
|
18
|
+
const thinkingMessageContent = () => t("system.ai.chat.message.thinking");
|
|
17
19
|
|
|
18
20
|
/** 生成流式消息分组键,确保同一轮回复只更新当前占位气泡。 */
|
|
19
21
|
export function buildStreamMessageKey(sessionID: string, messageID: string) {
|
|
@@ -42,7 +44,7 @@ export function resolveTimestamp(timestamp?: { seconds?: number; nanos?: number
|
|
|
42
44
|
export function normalizeSession(session?: Partial<AiSession> | null): AiSession {
|
|
43
45
|
return {
|
|
44
46
|
id: String(session?.id ?? ""),
|
|
45
|
-
title: String(session?.title ?? "
|
|
47
|
+
title: String(session?.title ?? t("system.ai.chat.value.new_conversation")),
|
|
46
48
|
summary: String(session?.summary ?? ""),
|
|
47
49
|
updated_at: session?.updated_at,
|
|
48
50
|
terminal: Number(session?.terminal ?? Terminal.TERMINAL_ADMIN)
|
|
@@ -60,16 +62,16 @@ export function resolveReplySourceTag(
|
|
|
60
62
|
item: Pick<ChatMessageItem, "role" | "fallback" | "reply_source" | "model">
|
|
61
63
|
): ReplySourceTag | undefined {
|
|
62
64
|
if (item.role === "user") return undefined;
|
|
63
|
-
if (item.fallback) return { text: "
|
|
65
|
+
if (item.fallback) return { text: t("system.ai.chat.source.fallback"), tone: "warning" };
|
|
64
66
|
switch (String(item.reply_source ?? "")) {
|
|
65
67
|
case "network":
|
|
66
|
-
return { text: "
|
|
68
|
+
return { text: t("system.ai.chat.source.network"), tone: "success" };
|
|
67
69
|
case "llm":
|
|
68
|
-
return { text: "
|
|
70
|
+
return { text: t("system.ai.chat.source.model"), tone: "primary" };
|
|
69
71
|
case "fallback":
|
|
70
|
-
return { text: "
|
|
72
|
+
return { text: t("system.ai.chat.source.fallback"), tone: "warning" };
|
|
71
73
|
default:
|
|
72
|
-
return item.model ? { text: "
|
|
74
|
+
return item.model ? { text: t("system.ai.chat.source.model"), tone: "primary" } : undefined;
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
|
|
@@ -168,17 +170,17 @@ export function mapMessageItem(message: AiMessage, role: "user" | "ai"): ChatMes
|
|
|
168
170
|
step: role === "ai" ? outputContent.step : "",
|
|
169
171
|
blocksJson: role === "ai" ? outputContent.blocks_json : "",
|
|
170
172
|
blocks: role === "ai" ? markFlowBlocksDisabled(parseFlowBlocks(outputContent.blocks_json), String(message.id ?? "")) : [],
|
|
171
|
-
status: Number(message.status ?? AiMessageStatus.
|
|
173
|
+
status: Number(message.status ?? AiMessageStatus.AI_MESSAGE_STATUS_SUCCESS),
|
|
172
174
|
token: normalizeToken(message.token),
|
|
173
175
|
tools: Array.isArray(message.tools) ? message.tools : [],
|
|
174
176
|
variant: role === "user" ? "filled" : "borderless",
|
|
175
177
|
shape: "corner",
|
|
176
178
|
progressState:
|
|
177
|
-
message.status === AiMessageStatus.
|
|
179
|
+
message.status === AiMessageStatus.AI_MESSAGE_STATUS_GENERATING
|
|
178
180
|
? role === "user"
|
|
179
181
|
? "idle"
|
|
180
182
|
: "streaming"
|
|
181
|
-
: message.status === AiMessageStatus.
|
|
183
|
+
: message.status === AiMessageStatus.AI_MESSAGE_STATUS_FAILED
|
|
182
184
|
? "failed"
|
|
183
185
|
: "idle",
|
|
184
186
|
maxWidth: role === "user" ? "380px" : "100%"
|
|
@@ -209,7 +211,7 @@ export function createLocalUserMessage(payload: { text: string; attachments: AiA
|
|
|
209
211
|
seconds: Math.floor(now.getTime() / 1000),
|
|
210
212
|
nanos: (now.getTime() % 1000) * 1_000_000
|
|
211
213
|
},
|
|
212
|
-
status: AiMessageStatus.
|
|
214
|
+
status: AiMessageStatus.AI_MESSAGE_STATUS_GENERATING,
|
|
213
215
|
token: normalizeToken(),
|
|
214
216
|
tools: [],
|
|
215
217
|
first_token_ms: 0,
|
|
@@ -236,7 +238,7 @@ export function createThinkingMessage(options?: { sessionID?: string; messageID?
|
|
|
236
238
|
input_content: undefined,
|
|
237
239
|
output_content: {
|
|
238
240
|
kind: "text",
|
|
239
|
-
content:
|
|
241
|
+
content: thinkingMessageContent(),
|
|
240
242
|
reply_source: "",
|
|
241
243
|
model: "",
|
|
242
244
|
fallback: false,
|
|
@@ -250,7 +252,7 @@ export function createThinkingMessage(options?: { sessionID?: string; messageID?
|
|
|
250
252
|
seconds: Math.floor(now.getTime() / 1000),
|
|
251
253
|
nanos: (now.getTime() % 1000) * 1_000_000
|
|
252
254
|
},
|
|
253
|
-
status: AiMessageStatus.
|
|
255
|
+
status: AiMessageStatus.AI_MESSAGE_STATUS_GENERATING,
|
|
254
256
|
token: normalizeToken(),
|
|
255
257
|
tools: [],
|
|
256
258
|
first_token_ms: 0,
|
|
@@ -261,7 +263,7 @@ export function createThinkingMessage(options?: { sessionID?: string; messageID?
|
|
|
261
263
|
message.progressState = "streaming";
|
|
262
264
|
message.localOnly = true;
|
|
263
265
|
message.streamKey = streamKey;
|
|
264
|
-
message.replySourceTag = { text: "
|
|
266
|
+
message.replySourceTag = { text: t("system.ai.chat.status.thinking"), tone: "info" };
|
|
265
267
|
return message;
|
|
266
268
|
}
|
|
267
269
|
|
|
@@ -290,7 +292,7 @@ export function markAIMessageRegenerating(current: ChatMessageItem[], sessionID:
|
|
|
290
292
|
if (String(item.id) !== messageID || item.role === "user") return item;
|
|
291
293
|
return {
|
|
292
294
|
...item,
|
|
293
|
-
content:
|
|
295
|
+
content: thinkingMessageContent(),
|
|
294
296
|
fallback: false,
|
|
295
297
|
fallback_reason: "",
|
|
296
298
|
token: normalizeToken(),
|
|
@@ -298,8 +300,8 @@ export function markAIMessageRegenerating(current: ChatMessageItem[], sessionID:
|
|
|
298
300
|
first_token_ms: 0,
|
|
299
301
|
duration_ms: 0,
|
|
300
302
|
progressState: "streaming",
|
|
301
|
-
replySourceTag: { text: "
|
|
302
|
-
status: AiMessageStatus.
|
|
303
|
+
replySourceTag: { text: t("system.ai.chat.status.thinking"), tone: "info" },
|
|
304
|
+
status: AiMessageStatus.AI_MESSAGE_STATUS_GENERATING,
|
|
303
305
|
streamKey
|
|
304
306
|
};
|
|
305
307
|
});
|
|
@@ -354,16 +356,16 @@ export function markThinkingMessageFailed(current: ChatMessageItem[], options?:
|
|
|
354
356
|
return {
|
|
355
357
|
...item,
|
|
356
358
|
progressState: "failed",
|
|
357
|
-
status: AiMessageStatus.
|
|
359
|
+
status: AiMessageStatus.AI_MESSAGE_STATUS_FAILED
|
|
358
360
|
};
|
|
359
361
|
}
|
|
360
362
|
if (item.progressState !== "streaming") return item;
|
|
361
363
|
return {
|
|
362
364
|
...item,
|
|
363
365
|
progressState: "failed",
|
|
364
|
-
status: AiMessageStatus.
|
|
365
|
-
content: "
|
|
366
|
-
replySourceTag: { text: "
|
|
366
|
+
status: AiMessageStatus.AI_MESSAGE_STATUS_FAILED,
|
|
367
|
+
content: t("system.ai.chat.message.reply_failed"),
|
|
368
|
+
replySourceTag: { text: t("system.ai.chat.status.send_failed"), tone: "warning" }
|
|
367
369
|
};
|
|
368
370
|
});
|
|
369
371
|
}
|
|
@@ -379,13 +381,13 @@ export function appendStreamingDelta(current: ChatMessageItem[], payload: AiStre
|
|
|
379
381
|
const streamKey = buildStreamMessageKey(String(payload.session_id ?? ""), String(payload.message_id ?? ""));
|
|
380
382
|
return current.map<ChatMessageItem>(item => {
|
|
381
383
|
if (item.streamKey !== streamKey || (!item.localOnly && item.role === "user")) return item;
|
|
382
|
-
const baseContent = item.content ===
|
|
384
|
+
const baseContent = item.content === thinkingMessageContent() ? "" : item.content;
|
|
383
385
|
const nextContent = `${baseContent}${payload.delta ?? ""}`;
|
|
384
386
|
return {
|
|
385
387
|
...item,
|
|
386
388
|
content: nextContent || item.content,
|
|
387
389
|
progressState: "streaming",
|
|
388
|
-
replySourceTag: { text: "
|
|
390
|
+
replySourceTag: { text: t("system.ai.chat.status.answering"), tone: "info" }
|
|
389
391
|
};
|
|
390
392
|
});
|
|
391
393
|
}
|
|
@@ -400,9 +402,9 @@ export function markStreamingError(current: ChatMessageItem[], payload: AiStream
|
|
|
400
402
|
return {
|
|
401
403
|
...item,
|
|
402
404
|
progressState: "failed",
|
|
403
|
-
status: AiMessageStatus.
|
|
404
|
-
content: "
|
|
405
|
-
replySourceTag: { text: "
|
|
405
|
+
status: AiMessageStatus.AI_MESSAGE_STATUS_FAILED,
|
|
406
|
+
content: t("system.ai.chat.message.reply_failed"),
|
|
407
|
+
replySourceTag: { text: t("system.ai.chat.status.send_failed"), tone: "warning" }
|
|
406
408
|
};
|
|
407
409
|
});
|
|
408
410
|
}
|