@adminforth/agent 1.14.1 → 1.16.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/agent/systemPrompt.ts +13 -2
- package/build.log +2 -2
- package/custom/ChatSurface.vue +1 -1
- package/custom/ConversationArea.vue +6 -1
- package/custom/composables/useAgentStore.ts +130 -4
- package/dist/agent/systemPrompt.js +7 -0
- package/dist/custom/ChatSurface.vue +1 -1
- package/dist/custom/ConversationArea.vue +6 -1
- package/dist/custom/composables/useAgentStore.ts +130 -4
- package/dist/index.js +29 -3
- package/index.ts +34 -2
- package/package.json +1 -1
- package/types.ts +20 -1
package/agent/systemPrompt.ts
CHANGED
|
@@ -35,10 +35,21 @@ export const DEFAULT_AGENT_SYSTEM_PROMPT = [
|
|
|
35
35
|
"If the confirmed plan has multiple steps, you may execute the whole confirmed plan without asking again between those steps.",
|
|
36
36
|
"If the plan changes, expands, or you want to do anything beyond the confirmed plan, ask for confirmation again.",
|
|
37
37
|
"Do not reuse an old confirmation for a new mutation plan.",
|
|
38
|
-
|
|
39
|
-
|
|
40
38
|
].join(" ");
|
|
41
39
|
|
|
40
|
+
export function appendCustomSystemPrompt(
|
|
41
|
+
systemPrompt: string,
|
|
42
|
+
customSystemPrompt?: string,
|
|
43
|
+
) {
|
|
44
|
+
const normalizedCustomSystemPrompt = customSystemPrompt?.trim();
|
|
45
|
+
|
|
46
|
+
if (!normalizedCustomSystemPrompt) {
|
|
47
|
+
return systemPrompt;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return `${systemPrompt}\n\n${normalizedCustomSystemPrompt}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
42
53
|
function formatResources(resources: AdminForthResource[]) {
|
|
43
54
|
return resources
|
|
44
55
|
.map((resource) => `- resourceId: ${resource.resourceId}\n label: ${resource.label}`)
|
package/build.log
CHANGED
|
@@ -31,5 +31,5 @@ custom/skills/fetch_data/SKILL.md
|
|
|
31
31
|
custom/skills/mutate_data/
|
|
32
32
|
custom/skills/mutate_data/SKILL.md
|
|
33
33
|
|
|
34
|
-
sent
|
|
35
|
-
total size is
|
|
34
|
+
sent 184,204 bytes received 436 bytes 369,280.00 bytes/sec
|
|
35
|
+
total size is 182,411 speedup is 0.99
|
package/custom/ChatSurface.vue
CHANGED
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
'min-h-12 w-full resize-none overflow-hidden border text-lightInputText dark:text-darkInputText rounded-md bg-transparent text-sm bg-gray-50 dark:bg-gray-700 dark:border-gray-600 focus:outline-none',
|
|
112
112
|
agentStore.availableModes.length > 1 ? 'p-4 pr-12 pb-12' : 'p-4 pr-12',
|
|
113
113
|
]"
|
|
114
|
-
placeholder="
|
|
114
|
+
:placeholder="agentStore.userMessagePlaceholder"
|
|
115
115
|
@keydown.enter.exact.prevent="sendMessage"
|
|
116
116
|
/>
|
|
117
117
|
<div
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
<script setup lang="ts">
|
|
75
75
|
import Message from './Message.vue';
|
|
76
76
|
import type { IMessage, IPart } from './types';
|
|
77
|
-
import { useTemplateRef, ref, defineAsyncComponent, onMounted, watch, computed } from 'vue';
|
|
77
|
+
import { useTemplateRef, ref, defineAsyncComponent, onMounted, onUnmounted, watch, computed } from 'vue';
|
|
78
78
|
import { IconArrowDownOutline } from '@iconify-prerendered/vue-flowbite';
|
|
79
79
|
import SessionsHistory from './SessionsHistory.vue';
|
|
80
80
|
import { useAgentStore } from './composables/useAgentStore';
|
|
@@ -98,6 +98,11 @@ function recalculateScroll() {
|
|
|
98
98
|
|
|
99
99
|
onMounted(async () => {
|
|
100
100
|
await import('@incremark/theme/styles.css')
|
|
101
|
+
await agentStore.fetchPlaceholderMessages()
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
onUnmounted(() => {
|
|
105
|
+
agentStore.stopPlaceholderAnimation();
|
|
101
106
|
});
|
|
102
107
|
|
|
103
108
|
watch(scrollContainer, () => {
|
|
@@ -12,6 +12,11 @@ type AgentMode = {
|
|
|
12
12
|
name: string;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
const DEFAULT_TEXTAREA_PLACEHOLDER = 'Type a message...';
|
|
16
|
+
const PLACEHOLDER_TYPING_DELAY_MS = 60;
|
|
17
|
+
const PLACEHOLDER_DELETING_DELAY_MS = 35;
|
|
18
|
+
const PLACEHOLDER_HOLD_DELAY_MS = 3000;
|
|
19
|
+
|
|
15
20
|
export const useAgentStore = defineStore('agent', () => {
|
|
16
21
|
const DEFAULT_CHAT_WIDTH = 600;
|
|
17
22
|
const MAX_WIDTH = 800;
|
|
@@ -25,8 +30,10 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
25
30
|
const adminforth = useAdminforth();
|
|
26
31
|
const isChatOpen = ref(false);
|
|
27
32
|
const isSessionHistoryOpen = ref(false);
|
|
28
|
-
const textInput = ref<
|
|
33
|
+
const textInput = ref<HTMLTextAreaElement | null>(null);
|
|
29
34
|
const userMessageInput = ref();
|
|
35
|
+
const userMessagePlaceholder = ref(DEFAULT_TEXTAREA_PLACEHOLDER);
|
|
36
|
+
const placeholderMessages = ref<string[]>([]);
|
|
30
37
|
const trimmedUserMessage = computed(() => userMessageInput.value ? userMessageInput.value.trim() : '');
|
|
31
38
|
const lastMessage = ref('');
|
|
32
39
|
const isTeleportedToBody = ref(false);
|
|
@@ -40,6 +47,9 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
40
47
|
const chatWidth = ref(DEFAULT_CHAT_WIDTH);
|
|
41
48
|
const availableModes = ref<AgentMode[]>([]);
|
|
42
49
|
const activeModeName = ref<string | null>(null);
|
|
50
|
+
const hasTypedMessageInPageSession = ref(false);
|
|
51
|
+
let placeholderAnimationTimer: ReturnType<typeof setTimeout> | null = null;
|
|
52
|
+
|
|
43
53
|
function setLocalStorageItem(key: string, value: string) {
|
|
44
54
|
window.localStorage.setItem(`${coreStore.config.brandName || 'adminforth'}-${key}`, value);
|
|
45
55
|
}
|
|
@@ -60,6 +70,16 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
60
70
|
setLocalStorageItem('lastSessionId', newVal);
|
|
61
71
|
}
|
|
62
72
|
})
|
|
73
|
+
watch(userMessageInput, (newVal: unknown) => {
|
|
74
|
+
if (hasTypedMessageInPageSession.value) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (typeof newVal === 'string' && newVal.trim() !== '') {
|
|
79
|
+
hasTypedMessageInPageSession.value = true;
|
|
80
|
+
stopPlaceholderAnimation();
|
|
81
|
+
}
|
|
82
|
+
})
|
|
63
83
|
onMounted(() => {
|
|
64
84
|
const chatWidthBeforeFullScreen = parseInt(getLocalStorageItem('chatWidthBeforeFullScreen') || '0', 10);
|
|
65
85
|
if (chatWidthBeforeFullScreen) {
|
|
@@ -130,14 +150,14 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
130
150
|
function setAvailableModes(modes: AgentMode[], defaultModeName?: string | null) {
|
|
131
151
|
availableModes.value = modes;
|
|
132
152
|
activeModeName.value =
|
|
133
|
-
modes.find((mode) => mode.name === activeModeName.value)?.name
|
|
153
|
+
modes.find((mode: AgentMode) => mode.name === activeModeName.value)?.name
|
|
134
154
|
?? defaultModeName
|
|
135
155
|
?? modes[0]?.name
|
|
136
156
|
?? null;
|
|
137
157
|
}
|
|
138
158
|
|
|
139
159
|
function setActiveMode(modeName: string) {
|
|
140
|
-
if (!availableModes.value.some((mode) => mode.name === modeName)) {
|
|
160
|
+
if (!availableModes.value.some((mode: AgentMode) => mode.name === modeName)) {
|
|
141
161
|
return;
|
|
142
162
|
}
|
|
143
163
|
|
|
@@ -179,6 +199,73 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
179
199
|
}
|
|
180
200
|
|
|
181
201
|
}
|
|
202
|
+
|
|
203
|
+
function clearPlaceholderAnimationTimer() {
|
|
204
|
+
if (placeholderAnimationTimer !== null) {
|
|
205
|
+
clearTimeout(placeholderAnimationTimer);
|
|
206
|
+
placeholderAnimationTimer = null;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function resetPlaceholder() {
|
|
211
|
+
clearPlaceholderAnimationTimer();
|
|
212
|
+
userMessagePlaceholder.value = DEFAULT_TEXTAREA_PLACEHOLDER;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function stopPlaceholderAnimation() {
|
|
216
|
+
resetPlaceholder();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function startPlaceholderAnimation(messages: string[]) {
|
|
220
|
+
clearPlaceholderAnimationTimer();
|
|
221
|
+
|
|
222
|
+
if (!messages.length) {
|
|
223
|
+
userMessagePlaceholder.value = DEFAULT_TEXTAREA_PLACEHOLDER;
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
let messageIndex = 0;
|
|
228
|
+
let visibleLength = 0;
|
|
229
|
+
let isDeleting = false;
|
|
230
|
+
|
|
231
|
+
const animate = () => {
|
|
232
|
+
const currentMessage = messages[messageIndex];
|
|
233
|
+
|
|
234
|
+
if (!currentMessage) {
|
|
235
|
+
resetPlaceholder();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (!isDeleting) {
|
|
240
|
+
visibleLength += 1;
|
|
241
|
+
userMessagePlaceholder.value = currentMessage.slice(0, visibleLength);
|
|
242
|
+
|
|
243
|
+
if (visibleLength >= currentMessage.length) {
|
|
244
|
+
isDeleting = true;
|
|
245
|
+
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_HOLD_DELAY_MS);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_TYPING_DELAY_MS);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
visibleLength -= 1;
|
|
254
|
+
userMessagePlaceholder.value = currentMessage.slice(0, Math.max(visibleLength, 0));
|
|
255
|
+
|
|
256
|
+
if (visibleLength <= 0) {
|
|
257
|
+
isDeleting = false;
|
|
258
|
+
messageIndex = (messageIndex + 1) % messages.length;
|
|
259
|
+
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_TYPING_DELAY_MS);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_DELETING_DELAY_MS);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
animate();
|
|
267
|
+
}
|
|
268
|
+
|
|
182
269
|
const isResponseInProgress = computed( () => {
|
|
183
270
|
return currentChat.value?.status === 'streaming';
|
|
184
271
|
});
|
|
@@ -234,10 +321,46 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
234
321
|
function setSessionHistoryOpen(isOpen: boolean) {
|
|
235
322
|
isSessionHistoryOpen.value = isOpen;
|
|
236
323
|
}
|
|
237
|
-
function regisrerTextInput(el:
|
|
324
|
+
function regisrerTextInput(el: HTMLTextAreaElement | null) {
|
|
238
325
|
textInput.value = el;
|
|
239
326
|
}
|
|
240
327
|
|
|
328
|
+
async function fetchPlaceholderMessages() {
|
|
329
|
+
if (hasTypedMessageInPageSession.value) {
|
|
330
|
+
stopPlaceholderAnimation();
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
const res = await callAdminForthApi({
|
|
336
|
+
method: 'POST',
|
|
337
|
+
path: '/agent/get-placeholder-messages',
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
if (res.error) {
|
|
341
|
+
console.error('Error fetching placeholder messages:', res.error);
|
|
342
|
+
placeholderMessages.value = [];
|
|
343
|
+
resetPlaceholder();
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
placeholderMessages.value = Array.isArray(res.messages)
|
|
348
|
+
? res.messages.filter((message: unknown): message is string => typeof message === 'string' && message.length > 0)
|
|
349
|
+
: [];
|
|
350
|
+
|
|
351
|
+
if (!placeholderMessages.value.length) {
|
|
352
|
+
resetPlaceholder();
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
startPlaceholderAnimation(placeholderMessages.value);
|
|
357
|
+
} catch (error) {
|
|
358
|
+
console.error('Error fetching placeholder messages', error);
|
|
359
|
+
placeholderMessages.value = [];
|
|
360
|
+
resetPlaceholder();
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
241
364
|
|
|
242
365
|
//create a pre-session, until user will type something, so we can save session
|
|
243
366
|
async function createPreSession() {
|
|
@@ -409,12 +532,15 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
409
532
|
createPreSession,
|
|
410
533
|
//____________________________________________
|
|
411
534
|
regisrerTextInput,
|
|
535
|
+
fetchPlaceholderMessages,
|
|
536
|
+
stopPlaceholderAnimation,
|
|
412
537
|
isChatOpen,
|
|
413
538
|
setIsChatOpen,
|
|
414
539
|
isSessionHistoryOpen,
|
|
415
540
|
setSessionHistoryOpen,
|
|
416
541
|
sendMessage,
|
|
417
542
|
userMessageInput,
|
|
543
|
+
userMessagePlaceholder,
|
|
418
544
|
chatMessages: computed(() => currentChat.value?.messages || []),
|
|
419
545
|
trimmedUserMessage,
|
|
420
546
|
isResponseInProgress,
|
|
@@ -35,6 +35,13 @@ export const DEFAULT_AGENT_SYSTEM_PROMPT = [
|
|
|
35
35
|
"If the plan changes, expands, or you want to do anything beyond the confirmed plan, ask for confirmation again.",
|
|
36
36
|
"Do not reuse an old confirmation for a new mutation plan.",
|
|
37
37
|
].join(" ");
|
|
38
|
+
export function appendCustomSystemPrompt(systemPrompt, customSystemPrompt) {
|
|
39
|
+
const normalizedCustomSystemPrompt = customSystemPrompt === null || customSystemPrompt === void 0 ? void 0 : customSystemPrompt.trim();
|
|
40
|
+
if (!normalizedCustomSystemPrompt) {
|
|
41
|
+
return systemPrompt;
|
|
42
|
+
}
|
|
43
|
+
return `${systemPrompt}\n\n${normalizedCustomSystemPrompt}`;
|
|
44
|
+
}
|
|
38
45
|
function formatResources(resources) {
|
|
39
46
|
return resources
|
|
40
47
|
.map((resource) => `- resourceId: ${resource.resourceId}\n label: ${resource.label}`)
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
'min-h-12 w-full resize-none overflow-hidden border text-lightInputText dark:text-darkInputText rounded-md bg-transparent text-sm bg-gray-50 dark:bg-gray-700 dark:border-gray-600 focus:outline-none',
|
|
112
112
|
agentStore.availableModes.length > 1 ? 'p-4 pr-12 pb-12' : 'p-4 pr-12',
|
|
113
113
|
]"
|
|
114
|
-
placeholder="
|
|
114
|
+
:placeholder="agentStore.userMessagePlaceholder"
|
|
115
115
|
@keydown.enter.exact.prevent="sendMessage"
|
|
116
116
|
/>
|
|
117
117
|
<div
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
<script setup lang="ts">
|
|
75
75
|
import Message from './Message.vue';
|
|
76
76
|
import type { IMessage, IPart } from './types';
|
|
77
|
-
import { useTemplateRef, ref, defineAsyncComponent, onMounted, watch, computed } from 'vue';
|
|
77
|
+
import { useTemplateRef, ref, defineAsyncComponent, onMounted, onUnmounted, watch, computed } from 'vue';
|
|
78
78
|
import { IconArrowDownOutline } from '@iconify-prerendered/vue-flowbite';
|
|
79
79
|
import SessionsHistory from './SessionsHistory.vue';
|
|
80
80
|
import { useAgentStore } from './composables/useAgentStore';
|
|
@@ -98,6 +98,11 @@ function recalculateScroll() {
|
|
|
98
98
|
|
|
99
99
|
onMounted(async () => {
|
|
100
100
|
await import('@incremark/theme/styles.css')
|
|
101
|
+
await agentStore.fetchPlaceholderMessages()
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
onUnmounted(() => {
|
|
105
|
+
agentStore.stopPlaceholderAnimation();
|
|
101
106
|
});
|
|
102
107
|
|
|
103
108
|
watch(scrollContainer, () => {
|
|
@@ -12,6 +12,11 @@ type AgentMode = {
|
|
|
12
12
|
name: string;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
const DEFAULT_TEXTAREA_PLACEHOLDER = 'Type a message...';
|
|
16
|
+
const PLACEHOLDER_TYPING_DELAY_MS = 60;
|
|
17
|
+
const PLACEHOLDER_DELETING_DELAY_MS = 35;
|
|
18
|
+
const PLACEHOLDER_HOLD_DELAY_MS = 3000;
|
|
19
|
+
|
|
15
20
|
export const useAgentStore = defineStore('agent', () => {
|
|
16
21
|
const DEFAULT_CHAT_WIDTH = 600;
|
|
17
22
|
const MAX_WIDTH = 800;
|
|
@@ -25,8 +30,10 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
25
30
|
const adminforth = useAdminforth();
|
|
26
31
|
const isChatOpen = ref(false);
|
|
27
32
|
const isSessionHistoryOpen = ref(false);
|
|
28
|
-
const textInput = ref<
|
|
33
|
+
const textInput = ref<HTMLTextAreaElement | null>(null);
|
|
29
34
|
const userMessageInput = ref();
|
|
35
|
+
const userMessagePlaceholder = ref(DEFAULT_TEXTAREA_PLACEHOLDER);
|
|
36
|
+
const placeholderMessages = ref<string[]>([]);
|
|
30
37
|
const trimmedUserMessage = computed(() => userMessageInput.value ? userMessageInput.value.trim() : '');
|
|
31
38
|
const lastMessage = ref('');
|
|
32
39
|
const isTeleportedToBody = ref(false);
|
|
@@ -40,6 +47,9 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
40
47
|
const chatWidth = ref(DEFAULT_CHAT_WIDTH);
|
|
41
48
|
const availableModes = ref<AgentMode[]>([]);
|
|
42
49
|
const activeModeName = ref<string | null>(null);
|
|
50
|
+
const hasTypedMessageInPageSession = ref(false);
|
|
51
|
+
let placeholderAnimationTimer: ReturnType<typeof setTimeout> | null = null;
|
|
52
|
+
|
|
43
53
|
function setLocalStorageItem(key: string, value: string) {
|
|
44
54
|
window.localStorage.setItem(`${coreStore.config.brandName || 'adminforth'}-${key}`, value);
|
|
45
55
|
}
|
|
@@ -60,6 +70,16 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
60
70
|
setLocalStorageItem('lastSessionId', newVal);
|
|
61
71
|
}
|
|
62
72
|
})
|
|
73
|
+
watch(userMessageInput, (newVal: unknown) => {
|
|
74
|
+
if (hasTypedMessageInPageSession.value) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (typeof newVal === 'string' && newVal.trim() !== '') {
|
|
79
|
+
hasTypedMessageInPageSession.value = true;
|
|
80
|
+
stopPlaceholderAnimation();
|
|
81
|
+
}
|
|
82
|
+
})
|
|
63
83
|
onMounted(() => {
|
|
64
84
|
const chatWidthBeforeFullScreen = parseInt(getLocalStorageItem('chatWidthBeforeFullScreen') || '0', 10);
|
|
65
85
|
if (chatWidthBeforeFullScreen) {
|
|
@@ -130,14 +150,14 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
130
150
|
function setAvailableModes(modes: AgentMode[], defaultModeName?: string | null) {
|
|
131
151
|
availableModes.value = modes;
|
|
132
152
|
activeModeName.value =
|
|
133
|
-
modes.find((mode) => mode.name === activeModeName.value)?.name
|
|
153
|
+
modes.find((mode: AgentMode) => mode.name === activeModeName.value)?.name
|
|
134
154
|
?? defaultModeName
|
|
135
155
|
?? modes[0]?.name
|
|
136
156
|
?? null;
|
|
137
157
|
}
|
|
138
158
|
|
|
139
159
|
function setActiveMode(modeName: string) {
|
|
140
|
-
if (!availableModes.value.some((mode) => mode.name === modeName)) {
|
|
160
|
+
if (!availableModes.value.some((mode: AgentMode) => mode.name === modeName)) {
|
|
141
161
|
return;
|
|
142
162
|
}
|
|
143
163
|
|
|
@@ -179,6 +199,73 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
179
199
|
}
|
|
180
200
|
|
|
181
201
|
}
|
|
202
|
+
|
|
203
|
+
function clearPlaceholderAnimationTimer() {
|
|
204
|
+
if (placeholderAnimationTimer !== null) {
|
|
205
|
+
clearTimeout(placeholderAnimationTimer);
|
|
206
|
+
placeholderAnimationTimer = null;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function resetPlaceholder() {
|
|
211
|
+
clearPlaceholderAnimationTimer();
|
|
212
|
+
userMessagePlaceholder.value = DEFAULT_TEXTAREA_PLACEHOLDER;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function stopPlaceholderAnimation() {
|
|
216
|
+
resetPlaceholder();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function startPlaceholderAnimation(messages: string[]) {
|
|
220
|
+
clearPlaceholderAnimationTimer();
|
|
221
|
+
|
|
222
|
+
if (!messages.length) {
|
|
223
|
+
userMessagePlaceholder.value = DEFAULT_TEXTAREA_PLACEHOLDER;
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
let messageIndex = 0;
|
|
228
|
+
let visibleLength = 0;
|
|
229
|
+
let isDeleting = false;
|
|
230
|
+
|
|
231
|
+
const animate = () => {
|
|
232
|
+
const currentMessage = messages[messageIndex];
|
|
233
|
+
|
|
234
|
+
if (!currentMessage) {
|
|
235
|
+
resetPlaceholder();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (!isDeleting) {
|
|
240
|
+
visibleLength += 1;
|
|
241
|
+
userMessagePlaceholder.value = currentMessage.slice(0, visibleLength);
|
|
242
|
+
|
|
243
|
+
if (visibleLength >= currentMessage.length) {
|
|
244
|
+
isDeleting = true;
|
|
245
|
+
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_HOLD_DELAY_MS);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_TYPING_DELAY_MS);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
visibleLength -= 1;
|
|
254
|
+
userMessagePlaceholder.value = currentMessage.slice(0, Math.max(visibleLength, 0));
|
|
255
|
+
|
|
256
|
+
if (visibleLength <= 0) {
|
|
257
|
+
isDeleting = false;
|
|
258
|
+
messageIndex = (messageIndex + 1) % messages.length;
|
|
259
|
+
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_TYPING_DELAY_MS);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_DELETING_DELAY_MS);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
animate();
|
|
267
|
+
}
|
|
268
|
+
|
|
182
269
|
const isResponseInProgress = computed( () => {
|
|
183
270
|
return currentChat.value?.status === 'streaming';
|
|
184
271
|
});
|
|
@@ -234,10 +321,46 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
234
321
|
function setSessionHistoryOpen(isOpen: boolean) {
|
|
235
322
|
isSessionHistoryOpen.value = isOpen;
|
|
236
323
|
}
|
|
237
|
-
function regisrerTextInput(el:
|
|
324
|
+
function regisrerTextInput(el: HTMLTextAreaElement | null) {
|
|
238
325
|
textInput.value = el;
|
|
239
326
|
}
|
|
240
327
|
|
|
328
|
+
async function fetchPlaceholderMessages() {
|
|
329
|
+
if (hasTypedMessageInPageSession.value) {
|
|
330
|
+
stopPlaceholderAnimation();
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
const res = await callAdminForthApi({
|
|
336
|
+
method: 'POST',
|
|
337
|
+
path: '/agent/get-placeholder-messages',
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
if (res.error) {
|
|
341
|
+
console.error('Error fetching placeholder messages:', res.error);
|
|
342
|
+
placeholderMessages.value = [];
|
|
343
|
+
resetPlaceholder();
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
placeholderMessages.value = Array.isArray(res.messages)
|
|
348
|
+
? res.messages.filter((message: unknown): message is string => typeof message === 'string' && message.length > 0)
|
|
349
|
+
: [];
|
|
350
|
+
|
|
351
|
+
if (!placeholderMessages.value.length) {
|
|
352
|
+
resetPlaceholder();
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
startPlaceholderAnimation(placeholderMessages.value);
|
|
357
|
+
} catch (error) {
|
|
358
|
+
console.error('Error fetching placeholder messages', error);
|
|
359
|
+
placeholderMessages.value = [];
|
|
360
|
+
resetPlaceholder();
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
241
364
|
|
|
242
365
|
//create a pre-session, until user will type something, so we can save session
|
|
243
366
|
async function createPreSession() {
|
|
@@ -409,12 +532,15 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
409
532
|
createPreSession,
|
|
410
533
|
//____________________________________________
|
|
411
534
|
regisrerTextInput,
|
|
535
|
+
fetchPlaceholderMessages,
|
|
536
|
+
stopPlaceholderAnimation,
|
|
412
537
|
isChatOpen,
|
|
413
538
|
setIsChatOpen,
|
|
414
539
|
isSessionHistoryOpen,
|
|
415
540
|
setSessionHistoryOpen,
|
|
416
541
|
sendMessage,
|
|
417
542
|
userMessageInput,
|
|
543
|
+
userMessagePlaceholder,
|
|
418
544
|
chatMessages: computed(() => currentChat.value?.messages || []),
|
|
419
545
|
trimmedUserMessage,
|
|
420
546
|
isResponseInProgress,
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import { HumanMessage, SystemMessage } from "langchain";
|
|
|
20
20
|
import { createAgentChatModel, callAgent } from "./agent/simpleAgent.js";
|
|
21
21
|
import { createSequenceDebugCollector } from "./agent/middleware/sequenceDebug.js";
|
|
22
22
|
import { prepareApiBasedTools as buildApiBasedTools, } from './apiBasedTools.js';
|
|
23
|
-
import { buildAgentSystemPrompt, DEFAULT_AGENT_SYSTEM_PROMPT, } from "./agent/systemPrompt.js";
|
|
23
|
+
import { appendCustomSystemPrompt, buildAgentSystemPrompt, DEFAULT_AGENT_SYSTEM_PROMPT, } from "./agent/systemPrompt.js";
|
|
24
24
|
import { ALWAYS_AVAILABLE_API_TOOL_NAMES } from "./agent/tools/index.js";
|
|
25
25
|
function isAggregateErrorLike(error) {
|
|
26
26
|
return typeof error === "object" && error !== null && Array.isArray(error.errors);
|
|
@@ -91,8 +91,8 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
91
91
|
constructor(options) {
|
|
92
92
|
super(options, import.meta.url);
|
|
93
93
|
this.apiBasedTools = {};
|
|
94
|
-
this.agentSystemPromptPromise = Promise.resolve(DEFAULT_AGENT_SYSTEM_PROMPT);
|
|
95
94
|
this.options = options;
|
|
95
|
+
this.agentSystemPromptPromise = Promise.resolve(appendCustomSystemPrompt(DEFAULT_AGENT_SYSTEM_PROMPT, this.options.systemPrompt));
|
|
96
96
|
this.shouldHaveSingleInstancePerWholeApp = () => false;
|
|
97
97
|
}
|
|
98
98
|
modifyResourceConfig(adminforth, resourceConfig) {
|
|
@@ -127,12 +127,38 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
127
127
|
assertRequiredApiTool(this.apiBasedTools, toolName);
|
|
128
128
|
}
|
|
129
129
|
assertRequiredApiTool(this.apiBasedTools, "update_record");
|
|
130
|
-
this.agentSystemPromptPromise = buildAgentSystemPrompt(adminforth)
|
|
130
|
+
this.agentSystemPromptPromise = buildAgentSystemPrompt(adminforth)
|
|
131
|
+
.then((systemPrompt) => appendCustomSystemPrompt(systemPrompt, this.options.systemPrompt));
|
|
131
132
|
}
|
|
132
133
|
instanceUniqueRepresentation(pluginOptions) {
|
|
133
134
|
return `single`;
|
|
134
135
|
}
|
|
135
136
|
setupEndpoints(server) {
|
|
137
|
+
server.endpoint({
|
|
138
|
+
method: 'POST',
|
|
139
|
+
path: `/agent/get-placeholder-messages`,
|
|
140
|
+
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, query, headers, cookies, adminUser, response, requestUrl }) {
|
|
141
|
+
if (!this.options.placeholderMessages) {
|
|
142
|
+
return {
|
|
143
|
+
messages: [],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
const messages = yield this.options.placeholderMessages({
|
|
147
|
+
adminUser,
|
|
148
|
+
httpExtra: {
|
|
149
|
+
body,
|
|
150
|
+
query,
|
|
151
|
+
headers,
|
|
152
|
+
cookies,
|
|
153
|
+
requestUrl,
|
|
154
|
+
response,
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
return {
|
|
158
|
+
messages,
|
|
159
|
+
};
|
|
160
|
+
})
|
|
161
|
+
});
|
|
136
162
|
server.endpoint({
|
|
137
163
|
method: 'POST',
|
|
138
164
|
path: `/agent/response`,
|
package/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from './apiBasedTools.js';
|
|
17
17
|
import type { ApiBasedTool } from './apiBasedTools.js';
|
|
18
18
|
import {
|
|
19
|
+
appendCustomSystemPrompt,
|
|
19
20
|
buildAgentSystemPrompt,
|
|
20
21
|
DEFAULT_AGENT_SYSTEM_PROMPT,
|
|
21
22
|
} from "./agent/systemPrompt.js";
|
|
@@ -67,7 +68,7 @@ function assertRequiredApiTool(
|
|
|
67
68
|
export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
68
69
|
options: PluginOptions;
|
|
69
70
|
apiBasedTools: Record<string, ApiBasedTool> = {};
|
|
70
|
-
agentSystemPromptPromise
|
|
71
|
+
agentSystemPromptPromise: Promise<string>;
|
|
71
72
|
|
|
72
73
|
private async createNewTurn(sessionId: string, prompt: string, response?: string) {
|
|
73
74
|
const turnId = randomUUID();
|
|
@@ -109,6 +110,9 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
109
110
|
constructor(options: PluginOptions) {
|
|
110
111
|
super(options, import.meta.url);
|
|
111
112
|
this.options = options;
|
|
113
|
+
this.agentSystemPromptPromise = Promise.resolve(
|
|
114
|
+
appendCustomSystemPrompt(DEFAULT_AGENT_SYSTEM_PROMPT, this.options.systemPrompt),
|
|
115
|
+
);
|
|
112
116
|
this.shouldHaveSingleInstancePerWholeApp = () => false;
|
|
113
117
|
}
|
|
114
118
|
|
|
@@ -139,7 +143,8 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
139
143
|
assertRequiredApiTool(this.apiBasedTools, toolName);
|
|
140
144
|
}
|
|
141
145
|
assertRequiredApiTool(this.apiBasedTools, "update_record");
|
|
142
|
-
this.agentSystemPromptPromise = buildAgentSystemPrompt(adminforth)
|
|
146
|
+
this.agentSystemPromptPromise = buildAgentSystemPrompt(adminforth)
|
|
147
|
+
.then((systemPrompt) => appendCustomSystemPrompt(systemPrompt, this.options.systemPrompt));
|
|
143
148
|
}
|
|
144
149
|
|
|
145
150
|
instanceUniqueRepresentation(pluginOptions: any) : string {
|
|
@@ -147,6 +152,33 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
setupEndpoints(server: IHttpServer) {
|
|
155
|
+
server.endpoint({
|
|
156
|
+
method: 'POST',
|
|
157
|
+
path: `/agent/get-placeholder-messages`,
|
|
158
|
+
handler: async ({ body, query, headers, cookies, adminUser, response, requestUrl }) => {
|
|
159
|
+
if (!this.options.placeholderMessages) {
|
|
160
|
+
return {
|
|
161
|
+
messages: [],
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const messages = await this.options.placeholderMessages({
|
|
166
|
+
adminUser,
|
|
167
|
+
httpExtra: {
|
|
168
|
+
body,
|
|
169
|
+
query,
|
|
170
|
+
headers,
|
|
171
|
+
cookies,
|
|
172
|
+
requestUrl,
|
|
173
|
+
response,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
messages,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
});
|
|
150
182
|
server.endpoint({
|
|
151
183
|
method: 'POST',
|
|
152
184
|
path: `/agent/response`,
|
package/package.json
CHANGED
package/types.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type PluginsCommonOptions,
|
|
3
|
+
type CompletionAdapter,
|
|
4
|
+
type AdminUser,
|
|
5
|
+
type HttpExtra,
|
|
6
|
+
} from "adminforth";
|
|
2
7
|
|
|
3
8
|
interface ISessionResource {
|
|
4
9
|
resourceId: string;
|
|
@@ -20,6 +25,15 @@ interface ITurnResource {
|
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
export interface PluginOptions extends PluginsCommonOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Optional placeholder examples to preload for the chat textarea.
|
|
30
|
+
* They are resolved once when the chat frontend loads.
|
|
31
|
+
*/
|
|
32
|
+
placeholderMessages?: ((input: {
|
|
33
|
+
adminUser: AdminUser;
|
|
34
|
+
httpExtra: HttpExtra;
|
|
35
|
+
}) => string[] | Promise<string[]>);
|
|
36
|
+
|
|
23
37
|
/**
|
|
24
38
|
* Modes for the plugin.
|
|
25
39
|
* Each mode can have its own configuration.
|
|
@@ -36,6 +50,11 @@ export interface PluginOptions extends PluginsCommonOptions {
|
|
|
36
50
|
*/
|
|
37
51
|
maxTokens?: number;
|
|
38
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Optional custom system prompt appended to the built-in agent system prompt.
|
|
55
|
+
*/
|
|
56
|
+
systemPrompt?: string;
|
|
57
|
+
|
|
39
58
|
/**
|
|
40
59
|
* Response generation level.
|
|
41
60
|
* Default is low
|