@adminforth/agent 2.3.1 → 2.3.3
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/custom/ChatFooter.vue +5 -3
- package/dist/custom/composables/agentStore/useAgentChat.ts +14 -6
- package/dist/custom/composables/agentStore/useAgentSteerQueue.ts +1 -0
- package/dist/custom/composables/useAgentStore.ts +24 -7
- package/dist/custom/conversation_area/MessageRenderer.vue +18 -6
- package/dist/custom/conversation_area/TextRenderer.vue +2 -2
- package/package.json +1 -1
|
@@ -215,9 +215,11 @@ async function sendMessage() {
|
|
|
215
215
|
// While editing a message, the same send action commits the edit (regenerating
|
|
216
216
|
// from that turn) instead of starting/steering a turn.
|
|
217
217
|
if (agentStore.isEditingMessage) {
|
|
218
|
-
await agentStore.submitEditMessage();
|
|
219
|
-
|
|
220
|
-
|
|
218
|
+
const editSubmitted = await agentStore.submitEditMessage();
|
|
219
|
+
if (editSubmitted) {
|
|
220
|
+
autoResize();
|
|
221
|
+
props.conversationAreaRef?.handleSendMessage();
|
|
222
|
+
}
|
|
221
223
|
return;
|
|
222
224
|
}
|
|
223
225
|
// Routes to a steer (folded into the running turn) while generating, or a normal
|
|
@@ -100,12 +100,14 @@ export function createAgentChatManager({
|
|
|
100
100
|
}
|
|
101
101
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
102
102
|
const message = messages[i];
|
|
103
|
-
if (message.role === 'user'
|
|
103
|
+
if (message.role === 'user') {
|
|
104
104
|
messages.splice(i, 1, {
|
|
105
105
|
...message,
|
|
106
106
|
metadata: { ...(message.metadata ?? {}), turnId },
|
|
107
107
|
});
|
|
108
|
-
|
|
108
|
+
if (!message.metadata?.steer) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
109
111
|
}
|
|
110
112
|
}
|
|
111
113
|
}
|
|
@@ -310,11 +312,17 @@ export function createAgentChatManager({
|
|
|
310
312
|
if (!chat) {
|
|
311
313
|
return;
|
|
312
314
|
}
|
|
313
|
-
const currentMessage = chat.messages.find((m: any) => m.id === messageId);
|
|
314
|
-
if (!currentMessage || currentMessage.parts[0].text.trim() === text.trim()) {
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
315
|
await stopActiveTurnAndWaitForIdle();
|
|
316
|
+
// The edited text already folds in the turn's steer sub-messages, so drop those extra
|
|
317
|
+
// user messages first — otherwise they linger after the edit as duplicate bubbles.
|
|
318
|
+
const withoutTurnSteers = chat.messages.filter((message: any) =>
|
|
319
|
+
message.id === messageId
|
|
320
|
+
|| message.role !== 'user'
|
|
321
|
+
|| message.metadata?.turnId !== turnId
|
|
322
|
+
);
|
|
323
|
+
if (withoutTurnSteers.length !== chat.messages.length) {
|
|
324
|
+
chat.messages = withoutTurnSteers;
|
|
325
|
+
}
|
|
318
326
|
editingTurnId.value = turnId;
|
|
319
327
|
lastMessage.value = text;
|
|
320
328
|
try {
|
|
@@ -19,6 +19,7 @@ import { createAgentChatManager } from './agentStore/useAgentChat';
|
|
|
19
19
|
import { createAgentPlaceholderController } from './agentStore/useAgentPlaceholder';
|
|
20
20
|
import { createAgentSessionManager } from './agentStore/useAgentSessions';
|
|
21
21
|
import { createAgentSteerQueue } from './agentStore/useAgentSteerQueue';
|
|
22
|
+
import { STEER_PERSIST_PREFIX } from './agentStore/constants';
|
|
22
23
|
|
|
23
24
|
export const useAgentStore = defineStore('agent', () => {
|
|
24
25
|
const agentTransitions = useAgentTransitions();
|
|
@@ -465,6 +466,19 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
465
466
|
editingEnabled.value = enabled;
|
|
466
467
|
}
|
|
467
468
|
|
|
469
|
+
|
|
470
|
+
function getCompiledMessageTextWithSteeredParts(message: any): string {
|
|
471
|
+
const currentTurnUserMessages = currentChat.value?.messages.filter((msg: any) => msg.metadata?.turnId === message?.metadata?.turnId && msg.role === 'user');
|
|
472
|
+
let messageToCompile = '';
|
|
473
|
+
for(const msg of currentTurnUserMessages) {
|
|
474
|
+
const text = (msg.parts ?? [])
|
|
475
|
+
.filter((part: any) => part.type === 'text')
|
|
476
|
+
.map((part: any) => part.text ?? '')
|
|
477
|
+
.join('');
|
|
478
|
+
messageToCompile += text + ' ';
|
|
479
|
+
}
|
|
480
|
+
return messageToCompile.trim();
|
|
481
|
+
}
|
|
468
482
|
// Enter edit mode for a user message: stash the current input, then load the
|
|
469
483
|
// message's text into the textarea for the user to amend. Allowed mid-generation —
|
|
470
484
|
// committing the edit stops the running turn (see submitEditMessage).
|
|
@@ -480,10 +494,7 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
480
494
|
if (editingMessageId.value === null) {
|
|
481
495
|
savedUserInput.value = userMessageInput.value ?? '';
|
|
482
496
|
}
|
|
483
|
-
const text = (message
|
|
484
|
-
.filter((part: any) => part.type === 'text')
|
|
485
|
-
.map((part: any) => part.text ?? '')
|
|
486
|
-
.join('');
|
|
497
|
+
const text = getCompiledMessageTextWithSteeredParts(message);
|
|
487
498
|
editingMessageId.value = messageId;
|
|
488
499
|
editingMessageTurnId.value = turnId;
|
|
489
500
|
userMessageInput.value = text;
|
|
@@ -506,20 +517,25 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
506
517
|
nextTick(() => focusTextInput());
|
|
507
518
|
}
|
|
508
519
|
|
|
509
|
-
async function submitEditMessage() {
|
|
520
|
+
async function submitEditMessage(): Promise<boolean> {
|
|
510
521
|
if (editingMessageId.value === null) {
|
|
511
|
-
return;
|
|
522
|
+
return false;
|
|
512
523
|
}
|
|
513
524
|
const text = trimmedUserMessage.value;
|
|
514
525
|
if (!text) {
|
|
515
|
-
return;
|
|
526
|
+
return false;
|
|
516
527
|
}
|
|
517
528
|
const messageId = editingMessageId.value;
|
|
518
529
|
const turnId = editingMessageTurnId.value!;
|
|
519
530
|
steerBuffer.clear();
|
|
520
531
|
// Restore the stashed input and leave edit mode before the regeneration streams in.
|
|
521
532
|
exitEditMode();
|
|
533
|
+
const lastMessageText = getCompiledMessageTextWithSteeredParts(currentChat.value?.messages.find((m: any) => m.id === messageId));
|
|
534
|
+
if (lastMessageText.trim() === text.trim()) {
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
522
537
|
await sendEditMessage({ messageId, turnId, text });
|
|
538
|
+
return true;
|
|
523
539
|
}
|
|
524
540
|
|
|
525
541
|
function resolveInternalRoute(href: string): string | null {
|
|
@@ -612,6 +628,7 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
612
628
|
setEditingEnabled,
|
|
613
629
|
isEditingMessage,
|
|
614
630
|
editingMessageId,
|
|
631
|
+
editingMessageTurnId,
|
|
615
632
|
startEditMessage,
|
|
616
633
|
cancelEditMessage,
|
|
617
634
|
submitEditMessage,
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
</div>
|
|
42
42
|
</Transition>
|
|
43
43
|
<div
|
|
44
|
-
v-if="message.role === 'user' && message.metadata?.steer"
|
|
44
|
+
v-if="message.role === 'user' && message.metadata?.steer && !isBeingEditedTurn"
|
|
45
45
|
class="self-end mr-4 mb-0.5 text-xs italic text-gray-400 dark:text-gray-500"
|
|
46
46
|
>
|
|
47
47
|
{{ $t('Steering instruction') }}
|
|
@@ -55,10 +55,10 @@
|
|
|
55
55
|
:key="part.type"
|
|
56
56
|
>
|
|
57
57
|
<TextRenderer
|
|
58
|
-
v-if="part.type === 'text' && !checkIfMessageSystemMessage(part.text ?? '')"
|
|
59
|
-
:message="part.text"
|
|
58
|
+
v-if="part.type === 'text' && !checkIfMessageSystemMessage(part.text ?? '') && shouldBeShownWhileEditing"
|
|
59
|
+
:message="isBeingEditedMessage ? agentStore.userMessageInput : part.text"
|
|
60
60
|
:role="props.message.role"
|
|
61
|
-
:
|
|
61
|
+
:editMode="isBeingEditedMessage"
|
|
62
62
|
:state="part.state ?? (props.message.role === 'user' ? 'done' : undefined)"
|
|
63
63
|
/>
|
|
64
64
|
<ToolApprovalRenderer
|
|
@@ -105,15 +105,27 @@
|
|
|
105
105
|
const canEdit = computed(() =>
|
|
106
106
|
agentStore.editingEnabled
|
|
107
107
|
&& props.message.role === 'user'
|
|
108
|
-
&& !props.message.metadata?.steer
|
|
108
|
+
// && !props.message.metadata?.steer
|
|
109
109
|
&& Boolean(props.message.metadata?.turnId)
|
|
110
110
|
&& !agentStore.isEditingMessage
|
|
111
111
|
);
|
|
112
112
|
|
|
113
|
-
const
|
|
113
|
+
const isBeingEditedMessage = computed(() =>
|
|
114
114
|
Boolean(props.message.id) && props.message.id === agentStore.editingMessageId
|
|
115
115
|
);
|
|
116
116
|
|
|
117
|
+
const isBeingEditedTurn = computed(() =>
|
|
118
|
+
Boolean(agentStore.editingMessageTurnId && props.message?.metadata?.turnId === agentStore.editingMessageTurnId)
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const isUserMessage = computed(() => props.message.role === 'user');
|
|
122
|
+
|
|
123
|
+
// While editing, hide only the *other* user messages of the edited turn (its steer
|
|
124
|
+
// sub-messages); the edited message itself and all non-user parts stay visible.
|
|
125
|
+
const shouldBeShownWhileEditing = computed(() =>
|
|
126
|
+
!(isBeingEditedTurn.value && isUserMessage.value && !isBeingEditedMessage.value)
|
|
127
|
+
);
|
|
128
|
+
|
|
117
129
|
function checkIfMessageSystemMessage(message: IMessage): boolean {
|
|
118
130
|
const isReserved = Object.values(RESERVED_SYSTEM_MESSAGE_CONTENT).includes(message as RESERVED_SYSTEM_MESSAGE_CONTENT);
|
|
119
131
|
return isReserved;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
hasVegaLite ? 'w-full my-2' : 'm-2',
|
|
7
7
|
props.role === 'user' ? 'bg-lightListTableHeading dark:bg-darkListTableHeading self-end max-w-[80%] mr-4'
|
|
8
8
|
: 'border-none self-start max-w-full',
|
|
9
|
-
props.
|
|
9
|
+
props.editMode ? 'ring-2 ring-lightPrimary dark:ring-darkPrimary w-full max-w-[calc(100%-2rem)]' : ''
|
|
10
10
|
]"
|
|
11
11
|
>
|
|
12
12
|
<IncremarkContent
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
message: string | undefined,
|
|
37
37
|
state: string | undefined,
|
|
38
38
|
role: IMessage['role'],
|
|
39
|
-
|
|
39
|
+
editMode?: boolean
|
|
40
40
|
}>();
|
|
41
41
|
|
|
42
42
|
const emit = defineEmits(['toggle-thoughts']);
|