@budibase/frontend-core 3.41.2 → 3.42.0
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "v3.42.0",
|
|
4
4
|
"description": "Budibase frontend core libraries used in builder and client",
|
|
5
5
|
"author": "Budibase",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -23,5 +23,5 @@
|
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"vitest": "^4.1.0"
|
|
25
25
|
},
|
|
26
|
-
"gitHead": "
|
|
26
|
+
"gitHead": "180c04c6852aa7acf0402d53dc909eab764d0251"
|
|
27
27
|
}
|
package/src/api/chatApps.ts
CHANGED
|
@@ -55,6 +55,14 @@ export interface ChatAppEndpoints {
|
|
|
55
55
|
>
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
const getBrowserTimezone = () => {
|
|
59
|
+
try {
|
|
60
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
61
|
+
} catch {
|
|
62
|
+
return undefined
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
58
66
|
const throwOnErrorChunk = () =>
|
|
59
67
|
new TransformStream<UIMessageChunk, UIMessageChunk>({
|
|
60
68
|
transform(chunk, controller) {
|
|
@@ -82,7 +90,10 @@ export const buildChatAppEndpoints = (
|
|
|
82
90
|
throw new Error("chatAppId is required to stream a chat conversation")
|
|
83
91
|
}
|
|
84
92
|
|
|
85
|
-
const body: ChatAgentRequest =
|
|
93
|
+
const body: ChatAgentRequest = {
|
|
94
|
+
...chat,
|
|
95
|
+
timezone: chat.timezone ?? getBrowserTimezone(),
|
|
96
|
+
}
|
|
86
97
|
const conversationId = chat._id || "new"
|
|
87
98
|
|
|
88
99
|
const response = await fetch(
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
import ReasoningStatus from "./ReasoningStatus.svelte"
|
|
24
24
|
import ContextUsage from "./ContextUsage.svelte"
|
|
25
25
|
import EscalationCard from "./EscalationCard.svelte"
|
|
26
|
+
import { navigatePromptHistory } from "./promptHistory"
|
|
26
27
|
import {
|
|
27
28
|
DefaultChatTransport,
|
|
28
29
|
isTextUIPart,
|
|
@@ -59,6 +60,8 @@
|
|
|
59
60
|
isAgentPreviewChat?: boolean
|
|
60
61
|
readOnly?: boolean
|
|
61
62
|
readOnlyReason?: "disabled" | "deleted" | "offline"
|
|
63
|
+
promptHistory?: string[]
|
|
64
|
+
onpromptsubmitted?: (prompt: string) => void
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
let {
|
|
@@ -75,6 +78,8 @@
|
|
|
75
78
|
isAgentPreviewChat = false,
|
|
76
79
|
readOnly = false,
|
|
77
80
|
readOnlyReason,
|
|
81
|
+
promptHistory = [],
|
|
82
|
+
onpromptsubmitted,
|
|
78
83
|
}: Props = $props()
|
|
79
84
|
|
|
80
85
|
// Per-escalation in-flight flag + the message relayed from resolve, so the
|
|
@@ -133,6 +138,7 @@
|
|
|
133
138
|
let expandedTools = $state<Record<string, boolean>>({})
|
|
134
139
|
let reasoningTextByMessageId = $state<Record<string, string>>({})
|
|
135
140
|
let inputValue = $state("")
|
|
141
|
+
let promptHistoryIndex = $state<number | undefined>()
|
|
136
142
|
let lastInitialPrompt = $state("")
|
|
137
143
|
let isPreparingResponse = $state(false)
|
|
138
144
|
const resetPendingResponse = () => {
|
|
@@ -560,6 +566,23 @@
|
|
|
560
566
|
return
|
|
561
567
|
}
|
|
562
568
|
|
|
569
|
+
if (isAgentPreviewChat) {
|
|
570
|
+
const navigationState = navigatePromptHistory({
|
|
571
|
+
key: event.key,
|
|
572
|
+
history: promptHistory,
|
|
573
|
+
inputValue,
|
|
574
|
+
index: promptHistoryIndex,
|
|
575
|
+
})
|
|
576
|
+
if (navigationState) {
|
|
577
|
+
event.preventDefault()
|
|
578
|
+
inputValue = navigationState.inputValue
|
|
579
|
+
promptHistoryIndex = navigationState.index
|
|
580
|
+
await tick()
|
|
581
|
+
textareaElement?.setSelectionRange(inputValue.length, inputValue.length)
|
|
582
|
+
return
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
563
586
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
564
587
|
event.preventDefault()
|
|
565
588
|
await sendMessage()
|
|
@@ -634,6 +657,8 @@
|
|
|
634
657
|
}
|
|
635
658
|
|
|
636
659
|
inputValue = ""
|
|
660
|
+
promptHistoryIndex = undefined
|
|
661
|
+
onpromptsubmitted?.(text)
|
|
637
662
|
chatInstance.sendMessage({ text })
|
|
638
663
|
isPreparingResponse = false
|
|
639
664
|
}
|
|
@@ -955,6 +980,7 @@
|
|
|
955
980
|
bind:this={textareaElement}
|
|
956
981
|
class="input spectrum-Textfield-input"
|
|
957
982
|
onkeydown={handleKeyDown}
|
|
983
|
+
oninput={() => (promptHistoryIndex = undefined)}
|
|
958
984
|
placeholder="Ask..."
|
|
959
985
|
disabled={isRequestPending}
|
|
960
986
|
></textarea>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest"
|
|
2
|
+
import { navigatePromptHistory } from "./promptHistory"
|
|
3
|
+
|
|
4
|
+
describe("navigatePromptHistory", () => {
|
|
5
|
+
const history = ["first", "second", "third"]
|
|
6
|
+
|
|
7
|
+
it("starts at the newest prompt from an empty input", () => {
|
|
8
|
+
expect(
|
|
9
|
+
navigatePromptHistory({
|
|
10
|
+
key: "ArrowUp",
|
|
11
|
+
history,
|
|
12
|
+
inputValue: "",
|
|
13
|
+
index: undefined,
|
|
14
|
+
})
|
|
15
|
+
).toEqual({ inputValue: "third", index: 2 })
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it("navigates backwards and stops at the oldest prompt", () => {
|
|
19
|
+
expect(
|
|
20
|
+
navigatePromptHistory({
|
|
21
|
+
key: "ArrowUp",
|
|
22
|
+
history,
|
|
23
|
+
inputValue: "second",
|
|
24
|
+
index: 1,
|
|
25
|
+
})
|
|
26
|
+
).toEqual({ inputValue: "first", index: 0 })
|
|
27
|
+
expect(
|
|
28
|
+
navigatePromptHistory({
|
|
29
|
+
key: "ArrowUp",
|
|
30
|
+
history,
|
|
31
|
+
inputValue: "first",
|
|
32
|
+
index: 0,
|
|
33
|
+
})
|
|
34
|
+
).toEqual({ inputValue: "first", index: 0 })
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it("navigates forwards and clears after the newest prompt", () => {
|
|
38
|
+
expect(
|
|
39
|
+
navigatePromptHistory({
|
|
40
|
+
key: "ArrowDown",
|
|
41
|
+
history,
|
|
42
|
+
inputValue: "first",
|
|
43
|
+
index: 0,
|
|
44
|
+
})
|
|
45
|
+
).toEqual({ inputValue: "second", index: 1 })
|
|
46
|
+
expect(
|
|
47
|
+
navigatePromptHistory({
|
|
48
|
+
key: "ArrowDown",
|
|
49
|
+
history,
|
|
50
|
+
inputValue: "third",
|
|
51
|
+
index: 2,
|
|
52
|
+
})
|
|
53
|
+
).toEqual({ inputValue: "", index: undefined })
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it("leaves arrow keys alone until navigation starts", () => {
|
|
57
|
+
expect(
|
|
58
|
+
navigatePromptHistory({
|
|
59
|
+
key: "ArrowUp",
|
|
60
|
+
history,
|
|
61
|
+
inputValue: "draft",
|
|
62
|
+
index: undefined,
|
|
63
|
+
})
|
|
64
|
+
).toBeUndefined()
|
|
65
|
+
expect(
|
|
66
|
+
navigatePromptHistory({
|
|
67
|
+
key: "ArrowDown",
|
|
68
|
+
history,
|
|
69
|
+
inputValue: "",
|
|
70
|
+
index: undefined,
|
|
71
|
+
})
|
|
72
|
+
).toBeUndefined()
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it("leaves Enter handling to the chat input", () => {
|
|
76
|
+
expect(
|
|
77
|
+
navigatePromptHistory({
|
|
78
|
+
key: "Enter",
|
|
79
|
+
history,
|
|
80
|
+
inputValue: "draft",
|
|
81
|
+
index: undefined,
|
|
82
|
+
})
|
|
83
|
+
).toBeUndefined()
|
|
84
|
+
})
|
|
85
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface PromptHistoryNavigationState {
|
|
2
|
+
inputValue: string
|
|
3
|
+
index: number | undefined
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
interface NavigatePromptHistoryOptions extends PromptHistoryNavigationState {
|
|
7
|
+
key: string
|
|
8
|
+
history: string[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const navigatePromptHistory = ({
|
|
12
|
+
key,
|
|
13
|
+
history,
|
|
14
|
+
inputValue,
|
|
15
|
+
index,
|
|
16
|
+
}: NavigatePromptHistoryOptions): PromptHistoryNavigationState | undefined => {
|
|
17
|
+
if (key !== "ArrowUp" && key !== "ArrowDown") {
|
|
18
|
+
return undefined
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (index === undefined) {
|
|
22
|
+
if (key !== "ArrowUp" || inputValue !== "" || history.length === 0) {
|
|
23
|
+
return undefined
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const nextIndex = history.length - 1
|
|
27
|
+
return { inputValue: history[nextIndex], index: nextIndex }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (key === "ArrowUp") {
|
|
31
|
+
const nextIndex = Math.max(0, index - 1)
|
|
32
|
+
return { inputValue: history[nextIndex], index: nextIndex }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (index >= history.length - 1) {
|
|
36
|
+
return { inputValue: "", index: undefined }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const nextIndex = index + 1
|
|
40
|
+
return { inputValue: history[nextIndex], index: nextIndex }
|
|
41
|
+
}
|
package/src/styles.d.ts
ADDED
package/tsconfig.json
CHANGED
|
@@ -6,8 +6,13 @@
|
|
|
6
6
|
"module": "preserve",
|
|
7
7
|
"moduleResolution": "bundler",
|
|
8
8
|
"outDir": "./dist",
|
|
9
|
+
"rootDir": "..",
|
|
9
10
|
"skipLibCheck": true,
|
|
10
|
-
"allowJs": true
|
|
11
|
+
"allowJs": true,
|
|
12
|
+
"paths": {
|
|
13
|
+
"@budibase/*": ["../*/src"],
|
|
14
|
+
"@/*": ["../bbui/src/*"]
|
|
15
|
+
}
|
|
11
16
|
},
|
|
12
17
|
"include": ["src/**/*"],
|
|
13
18
|
"exclude": ["node_modules", "dist"]
|