@budibase/frontend-core 3.24.2 → 3.24.4
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/package.json +2 -2
- package/src/api/agents.ts +37 -5
- package/src/api/chatApps.ts +2 -1
- package/src/api/configs.ts +11 -0
- package/src/api/index.ts +4 -0
- package/src/api/ragConfigs.ts +44 -0
- package/src/api/types.ts +4 -0
- package/src/api/vectorDbs.ts +44 -0
- package/src/components/Chatbox/index.svelte +89 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "3.24.
|
|
3
|
+
"version": "3.24.4",
|
|
4
4
|
"description": "Budibase frontend core libraries used in builder and client",
|
|
5
5
|
"author": "Budibase",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -18,5 +18,5 @@
|
|
|
18
18
|
"shortid": "2.2.15",
|
|
19
19
|
"socket.io-client": "^4.7.5"
|
|
20
20
|
},
|
|
21
|
-
"gitHead": "
|
|
21
|
+
"gitHead": "6d1812ff9a22270318eaf1f61f4e9af51bbac383"
|
|
22
22
|
}
|
package/src/api/agents.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AgentFileUploadResponse,
|
|
2
3
|
CreateAgentRequest,
|
|
3
4
|
CreateAgentResponse,
|
|
5
|
+
FetchAgentFilesResponse,
|
|
4
6
|
FetchAgentsResponse,
|
|
5
7
|
ToolMetadata,
|
|
6
8
|
UpdateAgentRequest,
|
|
@@ -15,9 +17,26 @@ export interface AgentEndpoints {
|
|
|
15
17
|
createAgent: (agent: CreateAgentRequest) => Promise<CreateAgentResponse>
|
|
16
18
|
updateAgent: (agent: UpdateAgentRequest) => Promise<UpdateAgentResponse>
|
|
17
19
|
deleteAgent: (agentId: string) => Promise<{ deleted: true }>
|
|
20
|
+
fetchAgentFiles: (agentId: string) => Promise<FetchAgentFilesResponse>
|
|
21
|
+
uploadAgentFile: (
|
|
22
|
+
agentId: string,
|
|
23
|
+
file: File
|
|
24
|
+
) => Promise<AgentFileUploadResponse>
|
|
25
|
+
deleteAgentFile: (
|
|
26
|
+
agentId: string,
|
|
27
|
+
fileId: string
|
|
28
|
+
) => Promise<{ deleted: true }>
|
|
18
29
|
}
|
|
19
30
|
|
|
20
31
|
export const buildAgentEndpoints = (API: BaseAPIClient): AgentEndpoints => ({
|
|
32
|
+
fetchTools: async (aiconfigId?: string) => {
|
|
33
|
+
const query = aiconfigId
|
|
34
|
+
? `?aiconfigId=${encodeURIComponent(aiconfigId)}`
|
|
35
|
+
: ""
|
|
36
|
+
return await API.get({
|
|
37
|
+
url: `/api/agent/tools${query}`,
|
|
38
|
+
})
|
|
39
|
+
},
|
|
21
40
|
fetchAgents: async () => {
|
|
22
41
|
return await API.get({
|
|
23
42
|
url: "/api/agent",
|
|
@@ -44,12 +63,25 @@ export const buildAgentEndpoints = (API: BaseAPIClient): AgentEndpoints => ({
|
|
|
44
63
|
})
|
|
45
64
|
},
|
|
46
65
|
|
|
47
|
-
|
|
48
|
-
const query = aiconfigId
|
|
49
|
-
? `?aiconfigId=${encodeURIComponent(aiconfigId)}`
|
|
50
|
-
: ""
|
|
66
|
+
fetchAgentFiles: async (agentId: string) => {
|
|
51
67
|
return await API.get({
|
|
52
|
-
url: `/api/agent
|
|
68
|
+
url: `/api/agent/${agentId}/files`,
|
|
69
|
+
})
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
uploadAgentFile: async (agentId: string, file: File) => {
|
|
73
|
+
const formData = new FormData()
|
|
74
|
+
formData.append("file", file)
|
|
75
|
+
return await API.post<FormData, AgentFileUploadResponse>({
|
|
76
|
+
url: `/api/agent/${agentId}/files`,
|
|
77
|
+
body: formData,
|
|
78
|
+
json: false,
|
|
79
|
+
})
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
deleteAgentFile: async (agentId: string, fileId: string) => {
|
|
83
|
+
return await API.delete({
|
|
84
|
+
url: `/api/agent/${agentId}/files/${fileId}`,
|
|
53
85
|
})
|
|
54
86
|
},
|
|
55
87
|
})
|
package/src/api/chatApps.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
ChatApp,
|
|
7
7
|
FetchAgentHistoryResponse,
|
|
8
8
|
UpdateChatAppRequest,
|
|
9
|
+
AgentMessageMetadata,
|
|
9
10
|
} from "@budibase/types"
|
|
10
11
|
import { Header } from "@budibase/shared-core"
|
|
11
12
|
import { BaseAPIClient } from "./types"
|
|
@@ -16,7 +17,7 @@ export interface ChatAppEndpoints {
|
|
|
16
17
|
streamChatConversation: (
|
|
17
18
|
chat: ChatConversationRequest,
|
|
18
19
|
workspaceId: string
|
|
19
|
-
) => Promise<AsyncIterable<UIMessage
|
|
20
|
+
) => Promise<AsyncIterable<UIMessage<AgentMessageMetadata>>>
|
|
20
21
|
deleteChatConversation: (
|
|
21
22
|
chatConversationId: string,
|
|
22
23
|
chatAppId: string
|
package/src/api/configs.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
FindConfigResponse,
|
|
7
7
|
GetPublicOIDCConfigResponse,
|
|
8
8
|
GetPublicSettingsResponse,
|
|
9
|
+
GetPublicTranslationsResponse,
|
|
9
10
|
OIDCLogosConfig,
|
|
10
11
|
SaveConfigRequest,
|
|
11
12
|
SaveConfigResponse,
|
|
@@ -17,6 +18,9 @@ export interface ConfigEndpoints {
|
|
|
17
18
|
getConfig: (type: ConfigType) => Promise<FindConfigResponse>
|
|
18
19
|
getTenantConfig: (tentantId: string) => Promise<GetPublicSettingsResponse>
|
|
19
20
|
getOIDCConfigs: (tenantId: string) => Promise<GetPublicOIDCConfigResponse>
|
|
21
|
+
getPublicTranslations: (
|
|
22
|
+
tenantId?: string
|
|
23
|
+
) => Promise<GetPublicTranslationsResponse>
|
|
20
24
|
getOIDCLogos: () => Promise<Config<OIDCLogosConfig>>
|
|
21
25
|
saveConfig: (config: SaveConfigRequest) => Promise<SaveConfigResponse>
|
|
22
26
|
deleteConfig: (id: string, rev: string) => Promise<DeleteConfigResponse>
|
|
@@ -79,6 +83,13 @@ export const buildConfigEndpoints = (API: BaseAPIClient): ConfigEndpoints => ({
|
|
|
79
83
|
})
|
|
80
84
|
},
|
|
81
85
|
|
|
86
|
+
getPublicTranslations: async tenantId => {
|
|
87
|
+
const query = tenantId ? `?tenantId=${tenantId}` : ""
|
|
88
|
+
return await API.get({
|
|
89
|
+
url: `/api/global/configs/public/translations${query}`,
|
|
90
|
+
})
|
|
91
|
+
},
|
|
92
|
+
|
|
82
93
|
/**
|
|
83
94
|
* Gets the checklist for a specific tenant.
|
|
84
95
|
* @param tenantId the tenant ID to get the checklist for
|
package/src/api/index.ts
CHANGED
|
@@ -56,6 +56,8 @@ import { buildDeploymentEndpoints } from "./deploy"
|
|
|
56
56
|
import { buildWorkspaceFavouriteEndpoints } from "./workspaceFavourites"
|
|
57
57
|
import { buildRecaptchaEndpoints } from "./recaptcha"
|
|
58
58
|
import { buildAIConfigEndpoints } from "./aiConfig"
|
|
59
|
+
import { buildRagConfigEndpoints } from "./ragConfigs"
|
|
60
|
+
import { buildVectorDbEndpoints } from "./vectorDbs"
|
|
59
61
|
|
|
60
62
|
export type { APIClient } from "./types"
|
|
61
63
|
|
|
@@ -326,5 +328,7 @@ export const createAPIClient = (config: APIClientConfig = {}): APIClient => {
|
|
|
326
328
|
resource: buildResourceEndpoints(API),
|
|
327
329
|
recaptcha: buildRecaptchaEndpoints(API),
|
|
328
330
|
aiConfig: buildAIConfigEndpoints(API),
|
|
331
|
+
ragConfig: buildRagConfigEndpoints(API),
|
|
332
|
+
vectorDb: buildVectorDbEndpoints(API),
|
|
329
333
|
}
|
|
330
334
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CreateRagConfigRequest,
|
|
3
|
+
RagConfig,
|
|
4
|
+
RagConfigListResponse,
|
|
5
|
+
UpdateRagConfigRequest,
|
|
6
|
+
} from "@budibase/types"
|
|
7
|
+
import { BaseAPIClient } from "./types"
|
|
8
|
+
|
|
9
|
+
export interface RagConfigEndpoints {
|
|
10
|
+
fetch: () => Promise<RagConfigListResponse>
|
|
11
|
+
create: (config: CreateRagConfigRequest) => Promise<RagConfig>
|
|
12
|
+
update: (config: UpdateRagConfigRequest) => Promise<RagConfig>
|
|
13
|
+
delete: (id: string) => Promise<{ deleted: true }>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const buildRagConfigEndpoints = (
|
|
17
|
+
API: BaseAPIClient
|
|
18
|
+
): RagConfigEndpoints => ({
|
|
19
|
+
fetch: async () => {
|
|
20
|
+
return await API.get({
|
|
21
|
+
url: "/api/ragconfig",
|
|
22
|
+
})
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
create: async config => {
|
|
26
|
+
return await API.post({
|
|
27
|
+
url: "/api/ragconfig",
|
|
28
|
+
body: config,
|
|
29
|
+
})
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
update: async config => {
|
|
33
|
+
return await API.put({
|
|
34
|
+
url: "/api/ragconfig",
|
|
35
|
+
body: config,
|
|
36
|
+
})
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
delete: async id => {
|
|
40
|
+
return await API.delete({
|
|
41
|
+
url: `/api/ragconfig/${id}`,
|
|
42
|
+
})
|
|
43
|
+
},
|
|
44
|
+
})
|
package/src/api/types.ts
CHANGED
|
@@ -43,6 +43,8 @@ import { DeploymentEndpoints } from "./deploy"
|
|
|
43
43
|
import { WorkspaceFavouriteEndpoints } from "./workspaceFavourites"
|
|
44
44
|
import { RecaptchaEndpoints } from "./recaptcha"
|
|
45
45
|
import { AIConfigEndpoints } from "./aiConfig"
|
|
46
|
+
import { RagConfigEndpoints } from "./ragConfigs"
|
|
47
|
+
import { VectorDbEndpoints } from "./vectorDbs"
|
|
46
48
|
|
|
47
49
|
export enum HTTPMethod {
|
|
48
50
|
POST = "POST",
|
|
@@ -157,4 +159,6 @@ export type APIClient = BaseAPIClient &
|
|
|
157
159
|
deployment: DeploymentEndpoints
|
|
158
160
|
recaptcha: RecaptchaEndpoints
|
|
159
161
|
aiConfig: AIConfigEndpoints
|
|
162
|
+
ragConfig: RagConfigEndpoints
|
|
163
|
+
vectorDb: VectorDbEndpoints
|
|
160
164
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CreateVectorDbRequest,
|
|
3
|
+
UpdateVectorDbRequest,
|
|
4
|
+
VectorDb,
|
|
5
|
+
VectorDbListResponse,
|
|
6
|
+
} from "@budibase/types"
|
|
7
|
+
import { BaseAPIClient } from "./types"
|
|
8
|
+
|
|
9
|
+
export interface VectorDbEndpoints {
|
|
10
|
+
fetch: () => Promise<VectorDbListResponse>
|
|
11
|
+
create: (config: CreateVectorDbRequest) => Promise<VectorDb>
|
|
12
|
+
update: (config: UpdateVectorDbRequest) => Promise<VectorDb>
|
|
13
|
+
delete: (id: string) => Promise<{ deleted: true }>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const buildVectorDbEndpoints = (
|
|
17
|
+
API: BaseAPIClient
|
|
18
|
+
): VectorDbEndpoints => ({
|
|
19
|
+
fetch: async () => {
|
|
20
|
+
return await API.get({
|
|
21
|
+
url: "/api/vectordb",
|
|
22
|
+
})
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
create: async config => {
|
|
26
|
+
return await API.post({
|
|
27
|
+
url: "/api/vectordb",
|
|
28
|
+
body: config,
|
|
29
|
+
})
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
update: async config => {
|
|
33
|
+
return await API.put({
|
|
34
|
+
url: "/api/vectordb",
|
|
35
|
+
body: config,
|
|
36
|
+
})
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
delete: async id => {
|
|
40
|
+
return await API.delete({
|
|
41
|
+
url: `/api/vectordb/${id}`,
|
|
42
|
+
})
|
|
43
|
+
},
|
|
44
|
+
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { MarkdownViewer, notifications } from "@budibase/bbui"
|
|
3
3
|
import type {
|
|
4
|
+
AgentMessageMetadata,
|
|
4
5
|
ChatConversation,
|
|
5
6
|
ChatConversationRequest,
|
|
6
7
|
} from "@budibase/types"
|
|
@@ -11,8 +12,8 @@
|
|
|
11
12
|
import { onMount } from "svelte"
|
|
12
13
|
import { createEventDispatcher } from "svelte"
|
|
13
14
|
import { createAPIClient } from "@budibase/frontend-core"
|
|
14
|
-
import type { UIMessage } from "ai"
|
|
15
15
|
import { v4 as uuidv4 } from "uuid"
|
|
16
|
+
import type { UIMessage } from "ai"
|
|
16
17
|
|
|
17
18
|
export let workspaceId: string
|
|
18
19
|
export let API = createAPIClient({
|
|
@@ -114,7 +115,7 @@
|
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
const userMessage: UIMessage = {
|
|
118
|
+
const userMessage: UIMessage<AgentMessageMetadata> = {
|
|
118
119
|
id: uuidv4(),
|
|
119
120
|
role: "user",
|
|
120
121
|
parts: [{ type: "text", text: inputValue }],
|
|
@@ -138,10 +139,35 @@
|
|
|
138
139
|
workspaceId
|
|
139
140
|
)
|
|
140
141
|
|
|
141
|
-
let streamedMessages
|
|
142
|
+
let streamedMessages = [...updatedChat.messages]
|
|
142
143
|
|
|
143
144
|
for await (const message of messageStream) {
|
|
144
|
-
|
|
145
|
+
if (message?.id) {
|
|
146
|
+
const existingIndex = streamedMessages.findIndex(
|
|
147
|
+
existing => existing.id === message.id
|
|
148
|
+
)
|
|
149
|
+
if (existingIndex !== -1) {
|
|
150
|
+
streamedMessages = streamedMessages.map((existing, index) =>
|
|
151
|
+
index === existingIndex ? message : existing
|
|
152
|
+
)
|
|
153
|
+
} else {
|
|
154
|
+
streamedMessages = [...streamedMessages, message]
|
|
155
|
+
}
|
|
156
|
+
} else if (message?.role === "assistant") {
|
|
157
|
+
const lastIndex = [...streamedMessages]
|
|
158
|
+
.reverse()
|
|
159
|
+
.findIndex(existing => existing.role === "assistant")
|
|
160
|
+
if (lastIndex !== -1) {
|
|
161
|
+
const targetIndex = streamedMessages.length - 1 - lastIndex
|
|
162
|
+
streamedMessages = streamedMessages.map((existing, index) =>
|
|
163
|
+
index === targetIndex ? message : existing
|
|
164
|
+
)
|
|
165
|
+
} else {
|
|
166
|
+
streamedMessages = [...streamedMessages, message]
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
streamedMessages = [...streamedMessages, message]
|
|
170
|
+
}
|
|
145
171
|
chat = {
|
|
146
172
|
...updatedChat,
|
|
147
173
|
messages: streamedMessages,
|
|
@@ -285,6 +311,27 @@
|
|
|
285
311
|
</div>
|
|
286
312
|
{/if}
|
|
287
313
|
{/each}
|
|
314
|
+
{#if message.metadata?.ragSources?.length}
|
|
315
|
+
<div class="sources">
|
|
316
|
+
<div class="sources-title">Sources</div>
|
|
317
|
+
<ul>
|
|
318
|
+
{#each message.metadata.ragSources as source (source.sourceId)}
|
|
319
|
+
<li class="source-item">
|
|
320
|
+
<span class="source-name"
|
|
321
|
+
>{source.filename || source.sourceId}</span
|
|
322
|
+
>
|
|
323
|
+
{#if source.chunkCount > 0}
|
|
324
|
+
<span class="source-count"
|
|
325
|
+
>({source.chunkCount} chunk{source.chunkCount === 1
|
|
326
|
+
? ""
|
|
327
|
+
: "s"})</span
|
|
328
|
+
>
|
|
329
|
+
{/if}
|
|
330
|
+
</li>
|
|
331
|
+
{/each}
|
|
332
|
+
</ul>
|
|
333
|
+
</div>
|
|
334
|
+
{/if}
|
|
288
335
|
</div>
|
|
289
336
|
{/if}
|
|
290
337
|
{/each}
|
|
@@ -480,4 +527,42 @@
|
|
|
480
527
|
color: var(--spectrum-global-color-gray-800);
|
|
481
528
|
font-style: italic;
|
|
482
529
|
}
|
|
530
|
+
|
|
531
|
+
.sources {
|
|
532
|
+
margin-top: var(--spacing-m);
|
|
533
|
+
padding-top: var(--spacing-s);
|
|
534
|
+
border-top: 1px solid var(--grey-3);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
.sources-title {
|
|
538
|
+
font-size: 13px;
|
|
539
|
+
text-transform: uppercase;
|
|
540
|
+
letter-spacing: 0.08em;
|
|
541
|
+
color: var(--spectrum-global-color-gray-600);
|
|
542
|
+
margin-bottom: var(--spacing-xs);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
.sources ul {
|
|
546
|
+
list-style: none;
|
|
547
|
+
padding: 0;
|
|
548
|
+
margin: 0;
|
|
549
|
+
display: flex;
|
|
550
|
+
flex-direction: column;
|
|
551
|
+
gap: 4px;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
.source-item {
|
|
555
|
+
display: flex;
|
|
556
|
+
gap: 8px;
|
|
557
|
+
font-size: 14px;
|
|
558
|
+
color: var(--spectrum-global-color-gray-900);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.source-name {
|
|
562
|
+
font-weight: 500;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.source-count {
|
|
566
|
+
color: var(--spectrum-global-color-gray-600);
|
|
567
|
+
}
|
|
483
568
|
</style>
|