@liujitcn/kratos-uni-app-system 0.0.65 → 0.0.66
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 +24 -4
- package/dist/module.mjs +24 -4
- package/package.json +2 -2
- package/src/api/base/v1/ai_knowledge.ts +25 -0
- 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 +52 -0
- package/src/views/pagesMember/ai/components/KnowledgePicker.vue +181 -0
- package/src/views/pagesMember/ai/index.vue +20 -1
package/dist/index.mjs
CHANGED
|
@@ -372,7 +372,12 @@ var zh_CN_default = {
|
|
|
372
372
|
"system.ai.model.load_failed": "\u52A0\u8F7D\u4F9B\u5E94\u5546\u548C\u6A21\u578B\u5931\u8D25",
|
|
373
373
|
"system.ai.model.title": "\u9009\u62E9\u6A21\u578B",
|
|
374
374
|
"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"
|
|
375
|
+
"system.ai.model.empty": "\u6682\u65E0\u53EF\u9009\u6A21\u578B",
|
|
376
|
+
"system.ai.knowledge.title": "\u77E5\u8BC6\u5E93",
|
|
377
|
+
"system.ai.knowledge.selected_count": "\u5DF2\u9009 {count} \u4E2A\u77E5\u8BC6\u5E93",
|
|
378
|
+
"system.ai.knowledge.doc_count": "{count} \u7BC7\u6587\u6863",
|
|
379
|
+
"system.ai.knowledge.select_hint": "\u52FE\u9009\u8981\u6CE8\u5165\u4E0A\u4E0B\u6587\u7684\u77E5\u8BC6\u5E93",
|
|
380
|
+
"system.ai.knowledge.empty": "\u6682\u65E0\u77E5\u8BC6\u5E93"
|
|
376
381
|
};
|
|
377
382
|
|
|
378
383
|
// src/locales/en-US.json
|
|
@@ -494,7 +499,12 @@ var en_US_default = {
|
|
|
494
499
|
"system.ai.model.load_failed": "Failed to load providers and models",
|
|
495
500
|
"system.ai.model.title": "Select Model",
|
|
496
501
|
"system.ai.model.provider_model_count": "{providers} providers \xB7 {models} models",
|
|
497
|
-
"system.ai.model.empty": "No models available"
|
|
502
|
+
"system.ai.model.empty": "No models available",
|
|
503
|
+
"system.ai.knowledge.title": "Knowledge Base",
|
|
504
|
+
"system.ai.knowledge.selected_count": "{count} knowledge base(s) selected",
|
|
505
|
+
"system.ai.knowledge.doc_count": "{count} doc(s)",
|
|
506
|
+
"system.ai.knowledge.select_hint": "Select knowledge bases to inject into context",
|
|
507
|
+
"system.ai.knowledge.empty": "No knowledge base available"
|
|
498
508
|
};
|
|
499
509
|
|
|
500
510
|
// src/locales/ja-JP.json
|
|
@@ -616,7 +626,12 @@ var ja_JP_default = {
|
|
|
616
626
|
"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
627
|
"system.ai.model.title": "\u30E2\u30C7\u30EB\u3092\u9078\u629E",
|
|
618
628
|
"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"
|
|
629
|
+
"system.ai.model.empty": "\u9078\u629E\u53EF\u80FD\u306A\u30E2\u30C7\u30EB\u304C\u3042\u308A\u307E\u305B\u3093",
|
|
630
|
+
"system.ai.knowledge.title": "\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9",
|
|
631
|
+
"system.ai.knowledge.selected_count": "{count} \u4EF6\u306E\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9\u3092\u9078\u629E\u4E2D",
|
|
632
|
+
"system.ai.knowledge.doc_count": "{count} \u4EF6\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8",
|
|
633
|
+
"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",
|
|
634
|
+
"system.ai.knowledge.empty": "\u5229\u7528\u53EF\u80FD\u306A\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093"
|
|
620
635
|
};
|
|
621
636
|
|
|
622
637
|
// src/locales/zh-TW.json
|
|
@@ -738,7 +753,12 @@ var zh_TW_default = {
|
|
|
738
753
|
"system.ai.model.load_failed": "\u8F09\u5165\u4F9B\u61C9\u5546\u8207\u6A21\u578B\u5931\u6557",
|
|
739
754
|
"system.ai.model.title": "\u9078\u64C7\u6A21\u578B",
|
|
740
755
|
"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"
|
|
756
|
+
"system.ai.model.empty": "\u66AB\u7121\u53EF\u9078\u6A21\u578B",
|
|
757
|
+
"system.ai.knowledge.title": "\u77E5\u8B58\u5EAB",
|
|
758
|
+
"system.ai.knowledge.selected_count": "\u5DF2\u9078 {count} \u500B\u77E5\u8B58\u5EAB",
|
|
759
|
+
"system.ai.knowledge.doc_count": "{count} \u7BC7\u6587\u4EF6",
|
|
760
|
+
"system.ai.knowledge.select_hint": "\u52FE\u9078\u8981\u6CE8\u5165\u4E0A\u4E0B\u6587\u7684\u77E5\u8B58\u5EAB",
|
|
761
|
+
"system.ai.knowledge.empty": "\u66AB\u7121\u77E5\u8B58\u5EAB"
|
|
742
762
|
};
|
|
743
763
|
|
|
744
764
|
// 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.66",
|
|
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.66"
|
|
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()
|
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>
|
|
@@ -72,6 +100,22 @@ function handleModelSelect(providerId: number, modelName: string) {
|
|
|
72
100
|
<text class="composer-model-chip__label">{{ selectedModelDisplayName || modelPlaceholder }}</text>
|
|
73
101
|
<uni-icons type="down" size="12" color="#8a8f99" />
|
|
74
102
|
</view>
|
|
103
|
+
<view
|
|
104
|
+
class="composer-model-chip"
|
|
105
|
+
:class="{
|
|
106
|
+
'is-disabled': sending || !knowledgeOptions.length,
|
|
107
|
+
'is-selected': knowledgeIds.length > 0,
|
|
108
|
+
}"
|
|
109
|
+
@tap="openKnowledgePicker"
|
|
110
|
+
>
|
|
111
|
+
<text class="composer-model-chip__spark">📚</text>
|
|
112
|
+
<text class="composer-model-chip__label">{{
|
|
113
|
+
knowledgeIds.length > 0
|
|
114
|
+
? t('system.ai.knowledge.selected_count', { count: knowledgeIds.length })
|
|
115
|
+
: t('system.ai.knowledge.title')
|
|
116
|
+
}}</text>
|
|
117
|
+
<uni-icons type="down" size="12" color="#8a8f99" />
|
|
118
|
+
</view>
|
|
75
119
|
<view class="composer-main">
|
|
76
120
|
<button class="attach-button" hover-class="none" @tap="emit('attach')">
|
|
77
121
|
<uni-icons type="plusempty" size="30" color="#111" />
|
|
@@ -124,6 +168,14 @@ function handleModelSelect(providerId: number, modelName: string) {
|
|
|
124
168
|
@select="handleModelSelect"
|
|
125
169
|
@close="showModelPicker = false"
|
|
126
170
|
/>
|
|
171
|
+
|
|
172
|
+
<KnowledgePicker
|
|
173
|
+
v-if="showKnowledgePicker"
|
|
174
|
+
:options="knowledgeOptions"
|
|
175
|
+
:selected-ids="knowledgeIds"
|
|
176
|
+
@toggle="handleKnowledgeToggle"
|
|
177
|
+
@close="showKnowledgePicker = false"
|
|
178
|
+
/>
|
|
127
179
|
</view>
|
|
128
180
|
</template>
|
|
129
181
|
|
|
@@ -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
|
}
|
|
@@ -1332,6 +1348,8 @@ function showError(error: unknown, fallback: string) {
|
|
|
1332
1348
|
:model-providers="modelProviders"
|
|
1333
1349
|
:provider-id="selectedProviderId"
|
|
1334
1350
|
:model-name="selectedModelName"
|
|
1351
|
+
:knowledge-options="knowledgeOptions"
|
|
1352
|
+
:knowledge-ids="selectedKnowledgeIds"
|
|
1335
1353
|
:model-placeholder="t('system.ai.model.model_placeholder')"
|
|
1336
1354
|
:placeholder="composerPlaceholder"
|
|
1337
1355
|
:bottom="composerBottom"
|
|
@@ -1342,6 +1360,7 @@ function showError(error: unknown, fallback: string) {
|
|
|
1342
1360
|
@record="handleToggleRecord"
|
|
1343
1361
|
@send="handleSend"
|
|
1344
1362
|
@model-change="handleModelChange"
|
|
1363
|
+
@knowledge-change="handleKnowledgeChange"
|
|
1345
1364
|
@remove-attachment="removeSelectedAttachment"
|
|
1346
1365
|
/>
|
|
1347
1366
|
|