@liujitcn/kratos-uni-app-system 0.0.65 → 0.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +28 -4
- package/dist/module.mjs +24 -4
- package/package.json +2 -2
- package/src/api/base/v1/ai_knowledge.ts +25 -0
- package/src/api/base/v1/notification.ts +3 -0
- package/src/locales/README.md +1 -1
- package/src/locales/en-US.json +6 -1
- package/src/locales/ja-JP.json +6 -1
- package/src/locales/zh-CN.json +6 -1
- package/src/locales/zh-TW.json +6 -1
- package/src/rpc/base/v1/ai_knowledge.ts +33 -0
- package/src/rpc/base/v1/ai_message.ts +2 -0
- package/src/views/pagesMember/ai/components/Composer.vue +55 -1
- package/src/views/pagesMember/ai/components/KnowledgePicker.vue +181 -0
- package/src/views/pagesMember/ai/index.vue +23 -2
package/dist/index.mjs
CHANGED
|
@@ -21,6 +21,10 @@ var NotificationServiceImpl = class {
|
|
|
21
21
|
const data = Object.fromEntries(
|
|
22
22
|
Object.entries(request).filter(([, value]) => value !== void 0)
|
|
23
23
|
);
|
|
24
|
+
if (data.page_num === void 0)
|
|
25
|
+
data.page_num = 1;
|
|
26
|
+
if (data.page_size === void 0)
|
|
27
|
+
data.page_size = 20;
|
|
24
28
|
const response = await http({
|
|
25
29
|
url: NOTIFICATION_URL,
|
|
26
30
|
method: "GET",
|
|
@@ -372,7 +376,12 @@ var zh_CN_default = {
|
|
|
372
376
|
"system.ai.model.load_failed": "\u52A0\u8F7D\u4F9B\u5E94\u5546\u548C\u6A21\u578B\u5931\u8D25",
|
|
373
377
|
"system.ai.model.title": "\u9009\u62E9\u6A21\u578B",
|
|
374
378
|
"system.ai.model.provider_model_count": "{providers} \u4E2A\u4F9B\u5E94\u5546 \xB7 {models} \u4E2A\u6A21\u578B",
|
|
375
|
-
"system.ai.model.empty": "\u6682\u65E0\u53EF\u9009\u6A21\u578B"
|
|
379
|
+
"system.ai.model.empty": "\u6682\u65E0\u53EF\u9009\u6A21\u578B",
|
|
380
|
+
"system.ai.knowledge.title": "\u77E5\u8BC6\u5E93",
|
|
381
|
+
"system.ai.knowledge.selected_count": "\u5DF2\u9009 {count} \u4E2A\u77E5\u8BC6\u5E93",
|
|
382
|
+
"system.ai.knowledge.doc_count": "{count} \u7BC7\u6587\u6863",
|
|
383
|
+
"system.ai.knowledge.select_hint": "\u52FE\u9009\u8981\u6CE8\u5165\u4E0A\u4E0B\u6587\u7684\u77E5\u8BC6\u5E93",
|
|
384
|
+
"system.ai.knowledge.empty": "\u6682\u65E0\u77E5\u8BC6\u5E93"
|
|
376
385
|
};
|
|
377
386
|
|
|
378
387
|
// src/locales/en-US.json
|
|
@@ -494,7 +503,12 @@ var en_US_default = {
|
|
|
494
503
|
"system.ai.model.load_failed": "Failed to load providers and models",
|
|
495
504
|
"system.ai.model.title": "Select Model",
|
|
496
505
|
"system.ai.model.provider_model_count": "{providers} providers \xB7 {models} models",
|
|
497
|
-
"system.ai.model.empty": "No models available"
|
|
506
|
+
"system.ai.model.empty": "No models available",
|
|
507
|
+
"system.ai.knowledge.title": "Knowledge Base",
|
|
508
|
+
"system.ai.knowledge.selected_count": "{count} knowledge base(s) selected",
|
|
509
|
+
"system.ai.knowledge.doc_count": "{count} doc(s)",
|
|
510
|
+
"system.ai.knowledge.select_hint": "Select knowledge bases to inject into context",
|
|
511
|
+
"system.ai.knowledge.empty": "No knowledge base available"
|
|
498
512
|
};
|
|
499
513
|
|
|
500
514
|
// src/locales/ja-JP.json
|
|
@@ -616,7 +630,12 @@ var ja_JP_default = {
|
|
|
616
630
|
"system.ai.model.load_failed": "\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3068\u30E2\u30C7\u30EB\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093\u3067\u3057\u305F",
|
|
617
631
|
"system.ai.model.title": "\u30E2\u30C7\u30EB\u3092\u9078\u629E",
|
|
618
632
|
"system.ai.model.provider_model_count": "{providers} \u30D7\u30ED\u30D0\u30A4\u30C0\u30FC \xB7 {models} \u30E2\u30C7\u30EB",
|
|
619
|
-
"system.ai.model.empty": "\u9078\u629E\u53EF\u80FD\u306A\u30E2\u30C7\u30EB\u304C\u3042\u308A\u307E\u305B\u3093"
|
|
633
|
+
"system.ai.model.empty": "\u9078\u629E\u53EF\u80FD\u306A\u30E2\u30C7\u30EB\u304C\u3042\u308A\u307E\u305B\u3093",
|
|
634
|
+
"system.ai.knowledge.title": "\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9",
|
|
635
|
+
"system.ai.knowledge.selected_count": "{count} \u4EF6\u306E\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9\u3092\u9078\u629E\u4E2D",
|
|
636
|
+
"system.ai.knowledge.doc_count": "{count} \u4EF6\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8",
|
|
637
|
+
"system.ai.knowledge.select_hint": "\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u306B\u6CE8\u5165\u3059\u308B\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9\u3092\u9078\u629E",
|
|
638
|
+
"system.ai.knowledge.empty": "\u5229\u7528\u53EF\u80FD\u306A\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093"
|
|
620
639
|
};
|
|
621
640
|
|
|
622
641
|
// src/locales/zh-TW.json
|
|
@@ -738,7 +757,12 @@ var zh_TW_default = {
|
|
|
738
757
|
"system.ai.model.load_failed": "\u8F09\u5165\u4F9B\u61C9\u5546\u8207\u6A21\u578B\u5931\u6557",
|
|
739
758
|
"system.ai.model.title": "\u9078\u64C7\u6A21\u578B",
|
|
740
759
|
"system.ai.model.provider_model_count": "{providers} \u500B\u4F9B\u61C9\u5546 \xB7 {models} \u500B\u6A21\u578B",
|
|
741
|
-
"system.ai.model.empty": "\u66AB\u7121\u53EF\u9078\u6A21\u578B"
|
|
760
|
+
"system.ai.model.empty": "\u66AB\u7121\u53EF\u9078\u6A21\u578B",
|
|
761
|
+
"system.ai.knowledge.title": "\u77E5\u8B58\u5EAB",
|
|
762
|
+
"system.ai.knowledge.selected_count": "\u5DF2\u9078 {count} \u500B\u77E5\u8B58\u5EAB",
|
|
763
|
+
"system.ai.knowledge.doc_count": "{count} \u7BC7\u6587\u4EF6",
|
|
764
|
+
"system.ai.knowledge.select_hint": "\u52FE\u9078\u8981\u6CE8\u5165\u4E0A\u4E0B\u6587\u7684\u77E5\u8B58\u5EAB",
|
|
765
|
+
"system.ai.knowledge.empty": "\u66AB\u7121\u77E5\u8B58\u5EAB"
|
|
742
766
|
};
|
|
743
767
|
|
|
744
768
|
// src/locales/generated.ts
|
package/dist/module.mjs
CHANGED
|
@@ -152,7 +152,12 @@ var zh_CN_default = {
|
|
|
152
152
|
"system.ai.model.load_failed": "\u52A0\u8F7D\u4F9B\u5E94\u5546\u548C\u6A21\u578B\u5931\u8D25",
|
|
153
153
|
"system.ai.model.title": "\u9009\u62E9\u6A21\u578B",
|
|
154
154
|
"system.ai.model.provider_model_count": "{providers} \u4E2A\u4F9B\u5E94\u5546 \xB7 {models} \u4E2A\u6A21\u578B",
|
|
155
|
-
"system.ai.model.empty": "\u6682\u65E0\u53EF\u9009\u6A21\u578B"
|
|
155
|
+
"system.ai.model.empty": "\u6682\u65E0\u53EF\u9009\u6A21\u578B",
|
|
156
|
+
"system.ai.knowledge.title": "\u77E5\u8BC6\u5E93",
|
|
157
|
+
"system.ai.knowledge.selected_count": "\u5DF2\u9009 {count} \u4E2A\u77E5\u8BC6\u5E93",
|
|
158
|
+
"system.ai.knowledge.doc_count": "{count} \u7BC7\u6587\u6863",
|
|
159
|
+
"system.ai.knowledge.select_hint": "\u52FE\u9009\u8981\u6CE8\u5165\u4E0A\u4E0B\u6587\u7684\u77E5\u8BC6\u5E93",
|
|
160
|
+
"system.ai.knowledge.empty": "\u6682\u65E0\u77E5\u8BC6\u5E93"
|
|
156
161
|
};
|
|
157
162
|
|
|
158
163
|
// src/locales/en-US.json
|
|
@@ -274,7 +279,12 @@ var en_US_default = {
|
|
|
274
279
|
"system.ai.model.load_failed": "Failed to load providers and models",
|
|
275
280
|
"system.ai.model.title": "Select Model",
|
|
276
281
|
"system.ai.model.provider_model_count": "{providers} providers \xB7 {models} models",
|
|
277
|
-
"system.ai.model.empty": "No models available"
|
|
282
|
+
"system.ai.model.empty": "No models available",
|
|
283
|
+
"system.ai.knowledge.title": "Knowledge Base",
|
|
284
|
+
"system.ai.knowledge.selected_count": "{count} knowledge base(s) selected",
|
|
285
|
+
"system.ai.knowledge.doc_count": "{count} doc(s)",
|
|
286
|
+
"system.ai.knowledge.select_hint": "Select knowledge bases to inject into context",
|
|
287
|
+
"system.ai.knowledge.empty": "No knowledge base available"
|
|
278
288
|
};
|
|
279
289
|
|
|
280
290
|
// src/locales/ja-JP.json
|
|
@@ -396,7 +406,12 @@ var ja_JP_default = {
|
|
|
396
406
|
"system.ai.model.load_failed": "\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3068\u30E2\u30C7\u30EB\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093\u3067\u3057\u305F",
|
|
397
407
|
"system.ai.model.title": "\u30E2\u30C7\u30EB\u3092\u9078\u629E",
|
|
398
408
|
"system.ai.model.provider_model_count": "{providers} \u30D7\u30ED\u30D0\u30A4\u30C0\u30FC \xB7 {models} \u30E2\u30C7\u30EB",
|
|
399
|
-
"system.ai.model.empty": "\u9078\u629E\u53EF\u80FD\u306A\u30E2\u30C7\u30EB\u304C\u3042\u308A\u307E\u305B\u3093"
|
|
409
|
+
"system.ai.model.empty": "\u9078\u629E\u53EF\u80FD\u306A\u30E2\u30C7\u30EB\u304C\u3042\u308A\u307E\u305B\u3093",
|
|
410
|
+
"system.ai.knowledge.title": "\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9",
|
|
411
|
+
"system.ai.knowledge.selected_count": "{count} \u4EF6\u306E\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9\u3092\u9078\u629E\u4E2D",
|
|
412
|
+
"system.ai.knowledge.doc_count": "{count} \u4EF6\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8",
|
|
413
|
+
"system.ai.knowledge.select_hint": "\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u306B\u6CE8\u5165\u3059\u308B\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9\u3092\u9078\u629E",
|
|
414
|
+
"system.ai.knowledge.empty": "\u5229\u7528\u53EF\u80FD\u306A\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093"
|
|
400
415
|
};
|
|
401
416
|
|
|
402
417
|
// src/locales/zh-TW.json
|
|
@@ -518,7 +533,12 @@ var zh_TW_default = {
|
|
|
518
533
|
"system.ai.model.load_failed": "\u8F09\u5165\u4F9B\u61C9\u5546\u8207\u6A21\u578B\u5931\u6557",
|
|
519
534
|
"system.ai.model.title": "\u9078\u64C7\u6A21\u578B",
|
|
520
535
|
"system.ai.model.provider_model_count": "{providers} \u500B\u4F9B\u61C9\u5546 \xB7 {models} \u500B\u6A21\u578B",
|
|
521
|
-
"system.ai.model.empty": "\u66AB\u7121\u53EF\u9078\u6A21\u578B"
|
|
536
|
+
"system.ai.model.empty": "\u66AB\u7121\u53EF\u9078\u6A21\u578B",
|
|
537
|
+
"system.ai.knowledge.title": "\u77E5\u8B58\u5EAB",
|
|
538
|
+
"system.ai.knowledge.selected_count": "\u5DF2\u9078 {count} \u500B\u77E5\u8B58\u5EAB",
|
|
539
|
+
"system.ai.knowledge.doc_count": "{count} \u7BC7\u6587\u4EF6",
|
|
540
|
+
"system.ai.knowledge.select_hint": "\u52FE\u9078\u8981\u6CE8\u5165\u4E0A\u4E0B\u6587\u7684\u77E5\u8B58\u5EAB",
|
|
541
|
+
"system.ai.knowledge.empty": "\u66AB\u7121\u77E5\u8B58\u5EAB"
|
|
522
542
|
};
|
|
523
543
|
|
|
524
544
|
// src/locales/generated.ts
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git@github.com:liujitcn/kratos-admin.git"
|
|
9
9
|
},
|
|
10
|
-
"version": "0.0.
|
|
10
|
+
"version": "0.0.67",
|
|
11
11
|
"type": "module",
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@dcloudio/uni-app": "3.0.0-5010520260709002",
|
|
36
36
|
"@dcloudio/uni-ui": "^1.4.28",
|
|
37
37
|
"vue": "^3.4.21",
|
|
38
|
-
"@liujitcn/kratos-uni-app-core": "^0.0.
|
|
38
|
+
"@liujitcn/kratos-uni-app-core": "^0.0.67"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"esbuild": "^0.20.2",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { http } from '@liujitcn/kratos-uni-app-core/utils/http'
|
|
2
|
+
import type {
|
|
3
|
+
AiKnowledgeService,
|
|
4
|
+
ListAiKnowledgeOptionsRequest,
|
|
5
|
+
ListAiKnowledgeOptionsResponse,
|
|
6
|
+
} from '../../../rpc/base/v1/ai_knowledge'
|
|
7
|
+
|
|
8
|
+
const AI_KNOWLEDGE_OPTIONS_URL = '/v1/base/ai/knowledge/options'
|
|
9
|
+
|
|
10
|
+
/** AI知识库选项服务。 */
|
|
11
|
+
export class AiKnowledgeServiceImpl implements AiKnowledgeService {
|
|
12
|
+
/** 查询可用的AI知识库选项。 */
|
|
13
|
+
ListAiKnowledgeOptions(
|
|
14
|
+
request: ListAiKnowledgeOptionsRequest,
|
|
15
|
+
): Promise<ListAiKnowledgeOptionsResponse> {
|
|
16
|
+
return http<ListAiKnowledgeOptionsResponse>({
|
|
17
|
+
url: AI_KNOWLEDGE_OPTIONS_URL,
|
|
18
|
+
method: 'GET',
|
|
19
|
+
authMode: 'required',
|
|
20
|
+
data: request,
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const defAiKnowledgeService = new AiKnowledgeServiceImpl()
|
|
@@ -27,6 +27,9 @@ export class NotificationServiceImpl implements NotificationService {
|
|
|
27
27
|
const data = Object.fromEntries(
|
|
28
28
|
Object.entries(request).filter(([, value]) => value !== undefined),
|
|
29
29
|
)
|
|
30
|
+
// 后端 buf.validate 要求 page_num>=1;游标模式下该值不参与查询,补默认值保证校验通过。
|
|
31
|
+
if (data.page_num === undefined) data.page_num = 1
|
|
32
|
+
if (data.page_size === undefined) data.page_size = 20
|
|
30
33
|
const response = await http<Partial<PageNotificationResponse>>({
|
|
31
34
|
url: NOTIFICATION_URL,
|
|
32
35
|
method: 'GET',
|
package/src/locales/README.md
CHANGED
package/src/locales/en-US.json
CHANGED
|
@@ -116,5 +116,10 @@
|
|
|
116
116
|
"system.ai.model.load_failed": "Failed to load providers and models",
|
|
117
117
|
"system.ai.model.title": "Select Model",
|
|
118
118
|
"system.ai.model.provider_model_count": "{providers} providers · {models} models",
|
|
119
|
-
"system.ai.model.empty": "No models available"
|
|
119
|
+
"system.ai.model.empty": "No models available",
|
|
120
|
+
"system.ai.knowledge.title": "Knowledge Base",
|
|
121
|
+
"system.ai.knowledge.selected_count": "{count} knowledge base(s) selected",
|
|
122
|
+
"system.ai.knowledge.doc_count": "{count} doc(s)",
|
|
123
|
+
"system.ai.knowledge.select_hint": "Select knowledge bases to inject into context",
|
|
124
|
+
"system.ai.knowledge.empty": "No knowledge base available"
|
|
120
125
|
}
|
package/src/locales/ja-JP.json
CHANGED
|
@@ -116,5 +116,10 @@
|
|
|
116
116
|
"system.ai.model.load_failed": "プロバイダーとモデルを読み込めませんでした",
|
|
117
117
|
"system.ai.model.title": "モデルを選択",
|
|
118
118
|
"system.ai.model.provider_model_count": "{providers} プロバイダー · {models} モデル",
|
|
119
|
-
"system.ai.model.empty": "選択可能なモデルがありません"
|
|
119
|
+
"system.ai.model.empty": "選択可能なモデルがありません",
|
|
120
|
+
"system.ai.knowledge.title": "ナレッジベース",
|
|
121
|
+
"system.ai.knowledge.selected_count": "{count} 件のナレッジベースを選択中",
|
|
122
|
+
"system.ai.knowledge.doc_count": "{count} 件のドキュメント",
|
|
123
|
+
"system.ai.knowledge.select_hint": "コンテキストに注入するナレッジベースを選択",
|
|
124
|
+
"system.ai.knowledge.empty": "利用可能なナレッジベースがありません"
|
|
120
125
|
}
|
package/src/locales/zh-CN.json
CHANGED
|
@@ -116,5 +116,10 @@
|
|
|
116
116
|
"system.ai.model.load_failed": "加载供应商和模型失败",
|
|
117
117
|
"system.ai.model.title": "选择模型",
|
|
118
118
|
"system.ai.model.provider_model_count": "{providers} 个供应商 · {models} 个模型",
|
|
119
|
-
"system.ai.model.empty": "暂无可选模型"
|
|
119
|
+
"system.ai.model.empty": "暂无可选模型",
|
|
120
|
+
"system.ai.knowledge.title": "知识库",
|
|
121
|
+
"system.ai.knowledge.selected_count": "已选 {count} 个知识库",
|
|
122
|
+
"system.ai.knowledge.doc_count": "{count} 篇文档",
|
|
123
|
+
"system.ai.knowledge.select_hint": "勾选要注入上下文的知识库",
|
|
124
|
+
"system.ai.knowledge.empty": "暂无知识库"
|
|
120
125
|
}
|
package/src/locales/zh-TW.json
CHANGED
|
@@ -116,5 +116,10 @@
|
|
|
116
116
|
"system.ai.model.load_failed": "載入供應商與模型失敗",
|
|
117
117
|
"system.ai.model.title": "選擇模型",
|
|
118
118
|
"system.ai.model.provider_model_count": "{providers} 個供應商 · {models} 個模型",
|
|
119
|
-
"system.ai.model.empty": "暫無可選模型"
|
|
119
|
+
"system.ai.model.empty": "暫無可選模型",
|
|
120
|
+
"system.ai.knowledge.title": "知識庫",
|
|
121
|
+
"system.ai.knowledge.selected_count": "已選 {count} 個知識庫",
|
|
122
|
+
"system.ai.knowledge.doc_count": "{count} 篇文件",
|
|
123
|
+
"system.ai.knowledge.select_hint": "勾選要注入上下文的知識庫",
|
|
124
|
+
"system.ai.knowledge.empty": "暫無知識庫"
|
|
120
125
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
|
2
|
+
// versions:
|
|
3
|
+
// protoc-gen-ts_proto v2.11.8
|
|
4
|
+
// protoc unknown
|
|
5
|
+
// source: base/v1/ai_knowledge.proto
|
|
6
|
+
|
|
7
|
+
/* eslint-disable */
|
|
8
|
+
|
|
9
|
+
/** AI知识库选项查询请求。 */
|
|
10
|
+
export interface ListAiKnowledgeOptionsRequest {
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** AI知识库选项查询响应。 */
|
|
14
|
+
export interface ListAiKnowledgeOptionsResponse {
|
|
15
|
+
/** 知识库选项列表 */
|
|
16
|
+
options: AiKnowledgeOption[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** AI知识库选项。 */
|
|
20
|
+
export interface AiKnowledgeOption {
|
|
21
|
+
/** 知识库ID */
|
|
22
|
+
id: number;
|
|
23
|
+
/** 知识库名称 */
|
|
24
|
+
name: string;
|
|
25
|
+
/** 已就绪文档数,不含处理失败 */
|
|
26
|
+
doc_count: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** AI 知识库选项查询服务。 */
|
|
30
|
+
export interface AiKnowledgeService {
|
|
31
|
+
/** 查询可用的AI知识库选项。 */
|
|
32
|
+
ListAiKnowledgeOptions(request: ListAiKnowledgeOptionsRequest): Promise<ListAiKnowledgeOptionsResponse>;
|
|
33
|
+
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, ref } from 'vue'
|
|
3
|
+
import { useI18n } from '@liujitcn/kratos-uni-app-core'
|
|
3
4
|
import type { AiAttachment } from '../../../../rpc/base/v1/ai_session'
|
|
4
5
|
import type { AiProviderModelOption } from '../../../../rpc/base/v1/ai_provider'
|
|
6
|
+
import type { AiKnowledgeOption } from '../../../../rpc/base/v1/ai_knowledge'
|
|
5
7
|
import { fallbackModelDisplayName } from '../modelDisplay'
|
|
6
8
|
import ModelPicker from './ModelPicker.vue'
|
|
9
|
+
import KnowledgePicker from './KnowledgePicker.vue'
|
|
10
|
+
|
|
11
|
+
const { t } = useI18n()
|
|
7
12
|
|
|
8
13
|
type InputEventValue = {
|
|
9
14
|
detail: {
|
|
@@ -19,6 +24,10 @@ const props = defineProps<{
|
|
|
19
24
|
/** 当前选中的供应商编号和模型名称。 */
|
|
20
25
|
providerId: number
|
|
21
26
|
modelName: string
|
|
27
|
+
/** 当前可供选择的知识库。 */
|
|
28
|
+
knowledgeOptions: AiKnowledgeOption[]
|
|
29
|
+
/** 当前选择的知识库编号列表。 */
|
|
30
|
+
knowledgeIds: number[]
|
|
22
31
|
modelPlaceholder: string
|
|
23
32
|
placeholder: string
|
|
24
33
|
bottom: string
|
|
@@ -34,9 +43,11 @@ const emit = defineEmits<{
|
|
|
34
43
|
send: []
|
|
35
44
|
'remove-attachment': [attachment: AiAttachment]
|
|
36
45
|
'model-change': [providerId: number, modelName: string]
|
|
46
|
+
'knowledge-change': [knowledgeIds: number[]]
|
|
37
47
|
}>()
|
|
38
48
|
|
|
39
49
|
const showModelPicker = ref(false)
|
|
50
|
+
const showKnowledgePicker = ref(false)
|
|
40
51
|
|
|
41
52
|
const selectedModelDisplayName = computed(() => {
|
|
42
53
|
const provider = props.modelProviders.find((item) => item.provider_id === props.providerId)
|
|
@@ -59,6 +70,23 @@ function handleModelSelect(providerId: number, modelName: string) {
|
|
|
59
70
|
showModelPicker.value = false
|
|
60
71
|
emit('model-change', providerId, modelName)
|
|
61
72
|
}
|
|
73
|
+
|
|
74
|
+
function openKnowledgePicker() {
|
|
75
|
+
if (props.sending || !props.knowledgeOptions.length) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
showKnowledgePicker.value = true
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function handleKnowledgeToggle(knowledgeId: number) {
|
|
82
|
+
const current = new Set(props.knowledgeIds)
|
|
83
|
+
if (current.has(knowledgeId)) {
|
|
84
|
+
current.delete(knowledgeId)
|
|
85
|
+
} else {
|
|
86
|
+
current.add(knowledgeId)
|
|
87
|
+
}
|
|
88
|
+
emit('knowledge-change', [...current])
|
|
89
|
+
}
|
|
62
90
|
</script>
|
|
63
91
|
|
|
64
92
|
<template>
|
|
@@ -69,7 +97,25 @@ function handleModelSelect(providerId: number, modelName: string) {
|
|
|
69
97
|
@tap="openModelPicker"
|
|
70
98
|
>
|
|
71
99
|
<text class="composer-model-chip__spark">✦</text>
|
|
72
|
-
<text class="composer-model-chip__label">{{
|
|
100
|
+
<text class="composer-model-chip__label">{{
|
|
101
|
+
selectedModelDisplayName || modelPlaceholder
|
|
102
|
+
}}</text>
|
|
103
|
+
<uni-icons type="down" size="12" color="#8a8f99" />
|
|
104
|
+
</view>
|
|
105
|
+
<view
|
|
106
|
+
class="composer-model-chip"
|
|
107
|
+
:class="{
|
|
108
|
+
'is-disabled': sending || !knowledgeOptions.length,
|
|
109
|
+
'is-selected': knowledgeIds.length > 0,
|
|
110
|
+
}"
|
|
111
|
+
@tap="openKnowledgePicker"
|
|
112
|
+
>
|
|
113
|
+
<text class="composer-model-chip__spark">📚</text>
|
|
114
|
+
<text class="composer-model-chip__label">{{
|
|
115
|
+
knowledgeIds.length > 0
|
|
116
|
+
? t('system.ai.knowledge.selected_count', { count: knowledgeIds.length })
|
|
117
|
+
: t('system.ai.knowledge.title')
|
|
118
|
+
}}</text>
|
|
73
119
|
<uni-icons type="down" size="12" color="#8a8f99" />
|
|
74
120
|
</view>
|
|
75
121
|
<view class="composer-main">
|
|
@@ -124,6 +170,14 @@ function handleModelSelect(providerId: number, modelName: string) {
|
|
|
124
170
|
@select="handleModelSelect"
|
|
125
171
|
@close="showModelPicker = false"
|
|
126
172
|
/>
|
|
173
|
+
|
|
174
|
+
<KnowledgePicker
|
|
175
|
+
v-if="showKnowledgePicker"
|
|
176
|
+
:options="knowledgeOptions"
|
|
177
|
+
:selected-ids="knowledgeIds"
|
|
178
|
+
@toggle="handleKnowledgeToggle"
|
|
179
|
+
@close="showKnowledgePicker = false"
|
|
180
|
+
/>
|
|
127
181
|
</view>
|
|
128
182
|
</template>
|
|
129
183
|
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useI18n } from '@liujitcn/kratos-uni-app-core'
|
|
4
|
+
import type { AiKnowledgeOption } from '../../../../rpc/base/v1/ai_knowledge'
|
|
5
|
+
|
|
6
|
+
const props = defineProps<{
|
|
7
|
+
options: AiKnowledgeOption[]
|
|
8
|
+
selectedIds: number[]
|
|
9
|
+
}>()
|
|
10
|
+
|
|
11
|
+
const emit = defineEmits<{
|
|
12
|
+
toggle: [knowledgeId: number]
|
|
13
|
+
close: []
|
|
14
|
+
}>()
|
|
15
|
+
|
|
16
|
+
const { t } = useI18n()
|
|
17
|
+
|
|
18
|
+
const selectedCount = computed(() => props.selectedIds.length)
|
|
19
|
+
|
|
20
|
+
function isSelected(knowledgeId: number) {
|
|
21
|
+
return props.selectedIds.includes(knowledgeId)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function handleToggle(knowledgeId: number) {
|
|
25
|
+
emit('toggle', knowledgeId)
|
|
26
|
+
}
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<template>
|
|
30
|
+
<view class="knowledge-picker">
|
|
31
|
+
<view class="knowledge-picker__mask" @tap="emit('close')" />
|
|
32
|
+
<view class="knowledge-picker__sheet">
|
|
33
|
+
<view class="knowledge-picker__handle" />
|
|
34
|
+
<view class="knowledge-picker__head">
|
|
35
|
+
<text class="knowledge-picker__title">{{ t('system.ai.knowledge.title') }}</text>
|
|
36
|
+
<text class="knowledge-picker__count">{{
|
|
37
|
+
t('system.ai.knowledge.selected_count', { count: selectedCount })
|
|
38
|
+
}}</text>
|
|
39
|
+
<button class="knowledge-picker__close" hover-class="none" @tap="emit('close')">✕</button>
|
|
40
|
+
</view>
|
|
41
|
+
<text class="knowledge-picker__hint">{{ t('system.ai.knowledge.select_hint') }}</text>
|
|
42
|
+
<scroll-view class="knowledge-picker__body" scroll-y :show-scrollbar="true">
|
|
43
|
+
<view
|
|
44
|
+
v-for="option in options"
|
|
45
|
+
:key="option.id"
|
|
46
|
+
class="knowledge-picker__row"
|
|
47
|
+
:class="{ 'is-selected': isSelected(option.id) }"
|
|
48
|
+
@tap="handleToggle(option.id)"
|
|
49
|
+
>
|
|
50
|
+
<view class="knowledge-picker__row-main">
|
|
51
|
+
<text class="knowledge-picker__row-name">{{ option.name }}</text>
|
|
52
|
+
<text v-if="option.doc_count" class="knowledge-picker__row-meta">{{
|
|
53
|
+
t('system.ai.knowledge.doc_count', { count: option.doc_count })
|
|
54
|
+
}}</text>
|
|
55
|
+
</view>
|
|
56
|
+
<view class="knowledge-picker__check" :class="{ 'is-checked': isSelected(option.id) }">
|
|
57
|
+
<text v-if="isSelected(option.id)">✓</text>
|
|
58
|
+
</view>
|
|
59
|
+
</view>
|
|
60
|
+
</scroll-view>
|
|
61
|
+
</view>
|
|
62
|
+
</view>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<style lang="scss" scoped>
|
|
66
|
+
.knowledge-picker {
|
|
67
|
+
position: fixed;
|
|
68
|
+
inset: 0;
|
|
69
|
+
z-index: 1000;
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: flex-end;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.knowledge-picker__mask {
|
|
75
|
+
position: absolute;
|
|
76
|
+
inset: 0;
|
|
77
|
+
background: rgba(0, 0, 0, 0.45);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.knowledge-picker__sheet {
|
|
81
|
+
position: relative;
|
|
82
|
+
display: flex;
|
|
83
|
+
flex-direction: column;
|
|
84
|
+
width: 100%;
|
|
85
|
+
max-height: 62vh;
|
|
86
|
+
padding: 10px 20px calc(20px + env(safe-area-inset-bottom));
|
|
87
|
+
background: #fff;
|
|
88
|
+
border-radius: 20px 20px 0 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.knowledge-picker__handle {
|
|
92
|
+
width: 36px;
|
|
93
|
+
height: 4px;
|
|
94
|
+
margin: 0 auto 10px;
|
|
95
|
+
background: #e5e6eb;
|
|
96
|
+
border-radius: 2px;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.knowledge-picker__head {
|
|
100
|
+
display: flex;
|
|
101
|
+
align-items: center;
|
|
102
|
+
gap: 10px;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.knowledge-picker__title {
|
|
106
|
+
font-size: 17px;
|
|
107
|
+
font-weight: 600;
|
|
108
|
+
color: #111;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.knowledge-picker__count {
|
|
112
|
+
flex: 1;
|
|
113
|
+
font-size: 12px;
|
|
114
|
+
color: #8a8f99;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.knowledge-picker__close {
|
|
118
|
+
padding: 0;
|
|
119
|
+
font-size: 16px;
|
|
120
|
+
line-height: 1;
|
|
121
|
+
color: #8a8f99;
|
|
122
|
+
background: transparent;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.knowledge-picker__close::after {
|
|
126
|
+
border: none;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.knowledge-picker__hint {
|
|
130
|
+
margin-top: 6px;
|
|
131
|
+
font-size: 12px;
|
|
132
|
+
color: #8a8f99;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.knowledge-picker__body {
|
|
136
|
+
margin-top: 10px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.knowledge-picker__row {
|
|
140
|
+
display: flex;
|
|
141
|
+
align-items: center;
|
|
142
|
+
justify-content: space-between;
|
|
143
|
+
gap: 12px;
|
|
144
|
+
padding: 12px 4px;
|
|
145
|
+
border-bottom: 1px solid #f2f3f5;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.knowledge-picker__row-main {
|
|
149
|
+
display: flex;
|
|
150
|
+
flex-direction: column;
|
|
151
|
+
gap: 2px;
|
|
152
|
+
min-width: 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.knowledge-picker__row-name {
|
|
156
|
+
font-size: 15px;
|
|
157
|
+
color: #111;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.knowledge-picker__row-meta {
|
|
161
|
+
font-size: 12px;
|
|
162
|
+
color: #8a8f99;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.knowledge-picker__check {
|
|
166
|
+
display: flex;
|
|
167
|
+
align-items: center;
|
|
168
|
+
justify-content: center;
|
|
169
|
+
width: 22px;
|
|
170
|
+
height: 22px;
|
|
171
|
+
border: 1px solid #d0d2d6;
|
|
172
|
+
border-radius: 50%;
|
|
173
|
+
font-size: 13px;
|
|
174
|
+
color: #fff;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.knowledge-picker__check.is-checked {
|
|
178
|
+
background: #00a96b;
|
|
179
|
+
border-color: #00a96b;
|
|
180
|
+
}
|
|
181
|
+
</style>
|
|
@@ -8,9 +8,11 @@ import {
|
|
|
8
8
|
import { defAiSessionService } from '../../../api/base/v1/ai_session'
|
|
9
9
|
import { defAiToolService } from '../../../api/base/v1/ai_tool'
|
|
10
10
|
import { defAiModelService } from '../../../api/base/v1/ai_provider'
|
|
11
|
+
import { defAiKnowledgeService } from '../../../api/base/v1/ai_knowledge'
|
|
11
12
|
import type { AiMessage } from '../../../rpc/base/v1/ai_session'
|
|
12
13
|
import type { AiAttachment, AiSession } from '../../../rpc/base/v1/ai_session'
|
|
13
14
|
import type { AiProviderModelOption } from '../../../rpc/base/v1/ai_provider'
|
|
15
|
+
import type { AiKnowledgeOption } from '../../../rpc/base/v1/ai_knowledge'
|
|
14
16
|
import type { AiShortcut, AiToolCall } from '../../../rpc/base/v1/ai_tool'
|
|
15
17
|
import { AiMessageStatus } from '../../../rpc/base/v1/ai_session'
|
|
16
18
|
import { Terminal } from '../../../rpc/base/v1/ai_tool'
|
|
@@ -100,6 +102,8 @@ const selectedAttachments = ref<AiAttachment[]>([])
|
|
|
100
102
|
const modelProviders = ref<AiProviderModelOption[]>([])
|
|
101
103
|
const selectedProviderId = ref(0)
|
|
102
104
|
const selectedModelName = ref('')
|
|
105
|
+
const knowledgeOptions = ref<AiKnowledgeOption[]>([])
|
|
106
|
+
const selectedKnowledgeIds = ref<number[]>([])
|
|
103
107
|
const runningStreamTaskMap = new Map<string, StreamTask>()
|
|
104
108
|
const pendingDeltaMap = new Map<string, AiStreamPayload>()
|
|
105
109
|
let pendingDeltaTimer = 0
|
|
@@ -472,11 +476,16 @@ async function loadAiShortcuts() {
|
|
|
472
476
|
}
|
|
473
477
|
loadingShortcuts.value = true
|
|
474
478
|
try {
|
|
475
|
-
const [response, providerResponse] = await Promise.all([
|
|
479
|
+
const [response, providerResponse, knowledgeResponse] = await Promise.all([
|
|
476
480
|
defAiToolService.ListAiShortcut({ terminal: AI_TERMINAL }),
|
|
477
481
|
defAiModelService.ListAiProviderModelOptions({}),
|
|
482
|
+
defAiKnowledgeService.ListAiKnowledgeOptions({}),
|
|
478
483
|
])
|
|
479
484
|
modelProviders.value = providerResponse.providers ?? []
|
|
485
|
+
knowledgeOptions.value = knowledgeResponse.options ?? []
|
|
486
|
+
selectedKnowledgeIds.value = selectedKnowledgeIds.value.filter((id) =>
|
|
487
|
+
knowledgeOptions.value.some((option) => option.id === id),
|
|
488
|
+
)
|
|
480
489
|
applyModelSelection()
|
|
481
490
|
const shortcuts = normalizeStarterShortcuts(response.shortcuts).filter((item) => !item.action)
|
|
482
491
|
if (shortcuts.length) {
|
|
@@ -487,6 +496,7 @@ async function loadAiShortcuts() {
|
|
|
487
496
|
modelProviders.value = []
|
|
488
497
|
selectedProviderId.value = 0
|
|
489
498
|
selectedModelName.value = ''
|
|
499
|
+
knowledgeOptions.value = []
|
|
490
500
|
showError(error, t('system.ai.load_shortcuts_failed'))
|
|
491
501
|
} finally {
|
|
492
502
|
loadingShortcuts.value = false
|
|
@@ -520,6 +530,11 @@ function handleModelChange(providerId: number, modelName: string) {
|
|
|
520
530
|
saveModelSelection({ provider_id: providerId, model_name: modelName })
|
|
521
531
|
}
|
|
522
532
|
|
|
533
|
+
/** 更新当前聊天检索注入的知识库选择。 */
|
|
534
|
+
function handleKnowledgeChange(knowledgeIds: number[]) {
|
|
535
|
+
selectedKnowledgeIds.value = knowledgeIds
|
|
536
|
+
}
|
|
537
|
+
|
|
523
538
|
async function sendAiPayload(payload: { text: string; attachments: AiAttachment[] }) {
|
|
524
539
|
const sessionID = await ensureActiveSession()
|
|
525
540
|
if (!sessionID || isSessionSending(sessionID)) {
|
|
@@ -550,6 +565,7 @@ async function runAiTask(
|
|
|
550
565
|
content: payload.text,
|
|
551
566
|
provider_id: selectedProviderId.value,
|
|
552
567
|
model_name: selectedModelName.value,
|
|
568
|
+
knowledge_base_ids: selectedKnowledgeIds.value,
|
|
553
569
|
attachments: payload.attachments,
|
|
554
570
|
action: undefined,
|
|
555
571
|
}
|
|
@@ -1293,7 +1309,9 @@ function showError(error: unknown, fallback: string) {
|
|
|
1293
1309
|
>
|
|
1294
1310
|
<view v-if="item.role === 'ai' && item.model" class="reply-meta">
|
|
1295
1311
|
<text class="reply-tag">{{ t('system.ai.model_reply') }}</text>
|
|
1296
|
-
<text class="reply-model">{{
|
|
1312
|
+
<text class="reply-model">{{
|
|
1313
|
+
resolveModelDisplayName(modelProviders, item.model)
|
|
1314
|
+
}}</text>
|
|
1297
1315
|
</view>
|
|
1298
1316
|
<view class="bubble-content">{{ item.content }}</view>
|
|
1299
1317
|
<view v-if="item.attachments.length" class="attachment-list">
|
|
@@ -1332,6 +1350,8 @@ function showError(error: unknown, fallback: string) {
|
|
|
1332
1350
|
:model-providers="modelProviders"
|
|
1333
1351
|
:provider-id="selectedProviderId"
|
|
1334
1352
|
:model-name="selectedModelName"
|
|
1353
|
+
:knowledge-options="knowledgeOptions"
|
|
1354
|
+
:knowledge-ids="selectedKnowledgeIds"
|
|
1335
1355
|
:model-placeholder="t('system.ai.model.model_placeholder')"
|
|
1336
1356
|
:placeholder="composerPlaceholder"
|
|
1337
1357
|
:bottom="composerBottom"
|
|
@@ -1342,6 +1362,7 @@ function showError(error: unknown, fallback: string) {
|
|
|
1342
1362
|
@record="handleToggleRecord"
|
|
1343
1363
|
@send="handleSend"
|
|
1344
1364
|
@model-change="handleModelChange"
|
|
1365
|
+
@knowledge-change="handleKnowledgeChange"
|
|
1345
1366
|
@remove-attachment="removeSelectedAttachment"
|
|
1346
1367
|
/>
|
|
1347
1368
|
|