@adminforth/agent 2.10.0 → 3.0.1
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 +47 -82
- package/dist/custom/ChatHeader.vue +59 -63
- package/dist/custom/ChatSurface.vue +12 -19
- package/dist/custom/EditActionButtons.vue +12 -8
- package/dist/custom/SessionsHistory.vue +90 -28
- package/dist/custom/SteerQueue.vue +15 -9
- package/dist/custom/composables/agentStore/useAgentSessions.ts +21 -0
- package/dist/custom/composables/useAgentStore.ts +2 -0
- package/dist/custom/conversation_area/ConversationArea.vue +21 -21
- package/dist/custom/conversation_area/MessageRenderer.vue +18 -17
- package/dist/custom/conversation_area/ProcessingTimeline.vue +11 -11
- package/dist/custom/conversation_area/ReasoningRenderer.vue +5 -6
- package/dist/custom/conversation_area/SystemMessageRenderer.vue +4 -4
- package/dist/custom/conversation_area/TextRenderer.vue +65 -27
- package/dist/custom/conversation_area/ToolApprovalRenderer.vue +34 -42
- package/dist/custom/conversation_area/ToolRenderer.vue +14 -14
- package/dist/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +22 -61
- package/dist/custom/speech_recognition_frontend/MicrophoneButon.vue +6 -4
- package/dist/transport/http/sessionEndpoints.js +34 -0
- package/package.json +3 -3
- package/dist/custom/SteerDebugPanel.vue +0 -45
|
@@ -1,29 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
-
class="mx-4 my-2 max-w-[min(34rem,calc(100%-2rem))] z-20 rounded-
|
|
3
|
+
class="af-agent-approval mx-4 my-2 max-w-[min(34rem,calc(100%-2rem))] z-20 rounded-lg border p-3.5"
|
|
4
4
|
:class="isAwaitingDecision
|
|
5
|
-
? 'border-
|
|
6
|
-
: 'border-
|
|
5
|
+
? 'border-lightWarningBorder bg-lightWarningSoft dark:border-darkWarningBorder dark:bg-darkWarningSoft'
|
|
6
|
+
: 'border-lightCardBorder bg-lightCardBackground dark:border-darkCardBorder dark:bg-darkCardBackground'"
|
|
7
7
|
>
|
|
8
8
|
<div class="flex items-start gap-2.5">
|
|
9
|
-
<
|
|
10
|
-
class="
|
|
11
|
-
:class="isAwaitingDecision
|
|
12
|
-
|
|
13
|
-
: 'bg-gray-200 text-gray-600 dark:bg-gray-700 dark:text-gray-300'"
|
|
14
|
-
>
|
|
15
|
-
<IconShieldExclamation class="h-4 w-4" />
|
|
16
|
-
</span>
|
|
9
|
+
<IconShieldAlert
|
|
10
|
+
class="mt-0.5 h-4 w-4 shrink-0"
|
|
11
|
+
:class="isAwaitingDecision ? 'text-lightWarning dark:text-darkWarning' : 'text-lightInputIconColor dark:text-darkInputIconColor'"
|
|
12
|
+
/>
|
|
17
13
|
<div class="min-w-0 flex-1">
|
|
18
|
-
<h3 class="text-sm font-semibold leading-5 text-
|
|
19
|
-
<p class="text-[0.8125rem] leading-5 text-
|
|
14
|
+
<h3 class="text-sm font-semibold leading-5 text-lightCardTitle dark:text-darkCardTitle">{{ $t('Approval needed') }}</h3>
|
|
15
|
+
<p class="text-[0.8125rem] leading-5 text-lightCardDescription dark:text-darkCardDescription">
|
|
20
16
|
{{ $t('Review what the agent is about to do before continuing.') }}
|
|
21
17
|
</p>
|
|
22
18
|
</div>
|
|
23
19
|
</div>
|
|
24
20
|
<ul
|
|
25
|
-
class="mt-3 divide-y rounded-
|
|
26
|
-
divide-
|
|
21
|
+
class="mt-3 divide-y rounded-default border text-[0.8125rem] leading-5
|
|
22
|
+
divide-lightCardBorder border-lightCardBorder bg-lightCardBackground text-lightTableText
|
|
23
|
+
dark:divide-darkCardBorder dark:border-darkCardBorder dark:bg-darkCardBackground dark:text-darkTableText"
|
|
27
24
|
>
|
|
28
25
|
<li
|
|
29
26
|
v-for="(approval, approvalIndex) in data.approvals"
|
|
@@ -36,19 +33,19 @@
|
|
|
36
33
|
class="mt-2 grid grid-cols-[minmax(0,auto)_minmax(0,1fr)] gap-x-4 gap-y-1.5"
|
|
37
34
|
>
|
|
38
35
|
<template v-for="(field, fieldIndex) in approval.fields" :key="fieldIndex">
|
|
39
|
-
<dt class="text-
|
|
36
|
+
<dt class="text-lightInputIconColor dark:text-darkInputIconColor [overflow-wrap:anywhere]">{{ field.label }}</dt>
|
|
40
37
|
<dd class="flex min-w-0 flex-wrap items-center gap-1.5">
|
|
41
38
|
<template v-if="field.from !== undefined && field.from !== field.to">
|
|
42
39
|
<span
|
|
43
40
|
class="min-w-0 rounded px-1.5 line-through [overflow-wrap:anywhere]
|
|
44
|
-
bg-
|
|
41
|
+
bg-lightDangerSoft text-lightDanger decoration-lightDanger/50 dark:bg-darkDangerSoft dark:text-darkDanger dark:decoration-darkDanger/50"
|
|
45
42
|
>
|
|
46
43
|
{{ field.from }}
|
|
47
44
|
</span>
|
|
48
|
-
<IconArrowRight class="h-3.5 w-3.5 shrink-0 text-
|
|
45
|
+
<IconArrowRight class="h-3.5 w-3.5 shrink-0 text-lightInputIconColor dark:text-darkInputIconColor" />
|
|
49
46
|
<span
|
|
50
47
|
class="min-w-0 rounded px-1.5 font-medium [overflow-wrap:anywhere]
|
|
51
|
-
bg-
|
|
48
|
+
bg-lightSuccessSoft text-lightSuccess dark:bg-darkSuccessSoft dark:text-darkSuccess"
|
|
52
49
|
>
|
|
53
50
|
{{ field.to }}
|
|
54
51
|
</span>
|
|
@@ -61,39 +58,28 @@
|
|
|
61
58
|
</ul>
|
|
62
59
|
<div class="mt-3 flex flex-wrap gap-2">
|
|
63
60
|
<template v-if="data.status === 'pending'">
|
|
64
|
-
<button
|
|
65
|
-
type="button"
|
|
66
|
-
class="inline-flex h-8 items-center gap-1.5 rounded-lg px-3 text-[0.8125rem] font-medium transition-opacity duration-150
|
|
67
|
-
bg-lightPrimary text-lightPrimaryContrast hover:opacity-90 dark:bg-darkPrimary dark:text-darkPrimaryContrast"
|
|
68
|
-
@click="submit('approve')"
|
|
69
|
-
>
|
|
61
|
+
<Button size="sm" type="button" @click="submit('approve')">
|
|
70
62
|
<IconCheck class="h-4 w-4" />
|
|
71
63
|
{{ $t('Approve') }}
|
|
72
|
-
</
|
|
73
|
-
<button
|
|
74
|
-
type="button"
|
|
75
|
-
class="inline-flex h-8 items-center rounded-lg border px-3 text-[0.8125rem] font-medium transition-colors duration-150
|
|
76
|
-
border-gray-300 bg-white text-gray-700 hover:bg-gray-50
|
|
77
|
-
dark:border-gray-600 dark:bg-transparent dark:text-gray-200 dark:hover:bg-gray-700/50"
|
|
78
|
-
@click="submit('reject')"
|
|
79
|
-
>
|
|
64
|
+
</Button>
|
|
65
|
+
<Button variant="secondary" size="sm" type="button" @click="submit('reject')">
|
|
80
66
|
{{ $t('Reject') }}
|
|
81
|
-
</
|
|
67
|
+
</Button>
|
|
82
68
|
</template>
|
|
83
69
|
<span
|
|
84
70
|
v-else
|
|
85
|
-
class="inline-flex h-
|
|
86
|
-
|
|
71
|
+
class="inline-flex h-6 items-center gap-1.5 rounded-full border px-2 text-xs font-medium"
|
|
72
|
+
:class="STATUS_BADGE_CLASSES[data.status]"
|
|
87
73
|
>
|
|
88
|
-
<Spinner v-if="data.status === 'processing'" class="h-
|
|
89
|
-
<IconCheck v-else-if="data.status === 'approved'" class="h-
|
|
90
|
-
<
|
|
74
|
+
<Spinner v-if="data.status === 'processing'" class="h-3.5 w-3.5" />
|
|
75
|
+
<IconCheck v-else-if="data.status === 'approved'" class="h-3.5 w-3.5" />
|
|
76
|
+
<IconX v-else class="h-3.5 w-3.5" />
|
|
91
77
|
{{ data.status === 'processing' ? $t('Processing') : data.status === 'approved' ? $t('Approved') : $t('Rejected') }}
|
|
92
78
|
</span>
|
|
93
79
|
</div>
|
|
94
80
|
<p
|
|
95
81
|
v-if="data.error"
|
|
96
|
-
class="mt-3 text-sm leading-5 text-
|
|
82
|
+
class="mt-3 text-sm leading-5 text-lightDanger dark:text-darkDanger"
|
|
97
83
|
>
|
|
98
84
|
{{ data.error }}
|
|
99
85
|
</p>
|
|
@@ -104,13 +90,19 @@
|
|
|
104
90
|
import { computed } from 'vue';
|
|
105
91
|
import type { IPartData } from '../types';
|
|
106
92
|
import { useAgentStore } from '../composables/useAgentStore';
|
|
107
|
-
import { Spinner } from '@/afcl';
|
|
108
|
-
import { IconArrowRight, IconCheck,
|
|
93
|
+
import { Button, Spinner } from '@/afcl';
|
|
94
|
+
import { IconArrowRight, IconCheck, IconShieldAlert, IconX } from '@iconify-prerendered/vue-lucide';
|
|
109
95
|
|
|
110
96
|
const props = defineProps<{
|
|
111
97
|
data: IPartData;
|
|
112
98
|
}>();
|
|
113
99
|
|
|
100
|
+
const STATUS_BADGE_CLASSES: Record<string, string> = {
|
|
101
|
+
processing: 'border-transparent bg-lightSecondaryDarken text-lightInputIconColor dark:bg-darkSecondaryLighten dark:text-darkInputIconColor',
|
|
102
|
+
approved: 'border-lightSuccessBorder bg-lightSuccessSoft text-lightSuccess dark:border-darkSuccessBorder dark:bg-darkSuccessSoft dark:text-darkSuccess',
|
|
103
|
+
rejected: 'border-lightDangerBorder bg-lightDangerSoft text-lightDanger dark:border-darkDangerBorder dark:bg-darkDangerSoft dark:text-darkDanger',
|
|
104
|
+
};
|
|
105
|
+
|
|
114
106
|
const agentStore = useAgentStore();
|
|
115
107
|
|
|
116
108
|
const isAwaitingDecision = computed(() => props.data.status === 'pending' || props.data.status === 'processing');
|
|
@@ -8,19 +8,19 @@
|
|
|
8
8
|
>
|
|
9
9
|
<span class="flex items-center justify-center w-4 h-4 shrink-0 rounded-full" :class="statusClasses">
|
|
10
10
|
<Spinner v-if="isRunning" class="w-3 h-3" />
|
|
11
|
-
<
|
|
12
|
-
<
|
|
11
|
+
<IconX v-else-if="props.data.toolInfo.error" class="w-3 h-3" />
|
|
12
|
+
<IconCheck v-else class="w-3 h-3" />
|
|
13
13
|
</span>
|
|
14
|
-
<span class="max-w-[55%] shrink-0 truncate font-mono text-xs text-
|
|
14
|
+
<span class="max-w-[55%] shrink-0 truncate font-mono text-xs text-lightInputText dark:text-darkInputText">
|
|
15
15
|
{{ props.data.toolInfo.toolName }}
|
|
16
16
|
</span>
|
|
17
|
-
<span class="flex-1 min-w-0 truncate text-
|
|
17
|
+
<span class="flex-1 min-w-0 truncate text-lightInputIconColor dark:text-darkInputIconColor" :title="props.data.toolInfo.toolInfo">
|
|
18
18
|
{{ props.data.toolInfo.toolInfo }}
|
|
19
19
|
</span>
|
|
20
|
-
<span v-if="durationLabel" class="shrink-0 tabular-nums text-
|
|
20
|
+
<span v-if="durationLabel" class="shrink-0 tabular-nums text-lightInputIconColor dark:text-darkInputIconColor">{{ durationLabel }}</span>
|
|
21
21
|
<IconChevronDown
|
|
22
22
|
v-if="hasToolSections"
|
|
23
|
-
class="w-3.5 h-3.5 shrink-0 text-
|
|
23
|
+
class="w-3.5 h-3.5 shrink-0 text-lightInputIconColor transition-transform duration-200 dark:text-darkInputIconColor"
|
|
24
24
|
:class="isInputOutputExpanded ? 'rotate-180' : 'rotate-0'"
|
|
25
25
|
/>
|
|
26
26
|
</button>
|
|
@@ -29,14 +29,14 @@
|
|
|
29
29
|
<section
|
|
30
30
|
v-for="section in toolSections"
|
|
31
31
|
:key="section.label"
|
|
32
|
-
class="overflow-hidden rounded-
|
|
32
|
+
class="overflow-hidden rounded-default border border-lightCardBorder bg-lightCardBackground dark:border-darkCardBorder dark:bg-darkCardBackground"
|
|
33
33
|
>
|
|
34
|
-
<header class="border-b border-
|
|
34
|
+
<header class="border-b border-lightCardBorder px-2.5 py-1.5 text-xs font-medium text-lightInputIconColor dark:border-darkCardBorder dark:text-darkInputIconColor">
|
|
35
35
|
{{ section.label }}
|
|
36
36
|
</header>
|
|
37
|
-
<div class="select-all grid grid-cols-[auto,1fr] gap-x-3 gap-y-0.5 px-2.5 py-2 font-mono text-xs leading-5 text-
|
|
37
|
+
<div class="select-all grid grid-cols-[auto,1fr] gap-x-3 gap-y-0.5 px-2.5 py-2 font-mono text-xs leading-5 text-lightTableText dark:text-darkTableText">
|
|
38
38
|
<template v-for="line in section.lines" :key="`${section.label}-${line.number}`">
|
|
39
|
-
<span class="text-[0.7rem] text-
|
|
39
|
+
<span class="text-[0.7rem] text-lightInputPlaceholderText dark:text-darkInputPlaceholderText select-none">{{ line.number }}</span>
|
|
40
40
|
<span class="whitespace-pre-wrap break-words">{{ line.content || ' ' }}</span>
|
|
41
41
|
</template>
|
|
42
42
|
</div>
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
import { computed, ref } from 'vue';
|
|
51
51
|
import { type IFormattedToolCallPart } from '../types';
|
|
52
52
|
import { Spinner } from '@/afcl';
|
|
53
|
-
import {
|
|
53
|
+
import { IconCheck, IconChevronDown, IconX } from '@iconify-prerendered/vue-lucide';
|
|
54
54
|
|
|
55
55
|
const props = defineProps<{
|
|
56
56
|
data: IFormattedToolCallPart
|
|
@@ -73,11 +73,11 @@
|
|
|
73
73
|
});
|
|
74
74
|
const statusClasses = computed(() => {
|
|
75
75
|
if (isRunning.value) {
|
|
76
|
-
return 'text-
|
|
76
|
+
return 'text-lightInputIconColor dark:text-darkInputIconColor';
|
|
77
77
|
}
|
|
78
78
|
return props.data.toolInfo.error
|
|
79
|
-
? 'bg-
|
|
80
|
-
: 'bg-
|
|
79
|
+
? 'bg-lightDangerSoft text-lightDanger dark:bg-darkDangerSoft dark:text-darkDanger'
|
|
80
|
+
: 'bg-lightSuccessSoft text-lightSuccess dark:bg-darkSuccessSoft dark:text-darkSuccess';
|
|
81
81
|
});
|
|
82
82
|
const toolSections = computed<IToolSection[]>(() => {
|
|
83
83
|
const sections = [
|
|
@@ -205,6 +205,9 @@ async function renderHighlight() {
|
|
|
205
205
|
const result = await embed(vegaContainer.value, spec, {
|
|
206
206
|
actions: false,
|
|
207
207
|
renderer: 'svg',
|
|
208
|
+
// the chart sits on the surface of the code block, so it takes the theme of the page
|
|
209
|
+
theme: codeTheme.value === 'dark' ? 'dark' : undefined,
|
|
210
|
+
config: { background: 'transparent' },
|
|
208
211
|
});
|
|
209
212
|
|
|
210
213
|
if (requestId !== renderRequestId) {
|
|
@@ -259,70 +262,36 @@ function clearVega() {
|
|
|
259
262
|
|
|
260
263
|
<style scoped>
|
|
261
264
|
.incremark-shiki-code {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
--incremark-code-toolbar-text: #475569;
|
|
265
|
-
--incremark-code-copy-bg: rgba(226, 232, 240, 0.9);
|
|
266
|
-
--incremark-code-copy-text: #0f172a;
|
|
267
|
-
border: 1px solid var(--incremark-code-border);
|
|
268
|
-
border-radius: 16px;
|
|
265
|
+
@apply border border-lightCardBorder bg-lightCardBackground dark:border-darkCardBorder dark:bg-darkCardBackground;
|
|
266
|
+
border-radius: 8px;
|
|
269
267
|
overflow: hidden;
|
|
270
268
|
width: 100%;
|
|
271
|
-
|
|
272
|
-
linear-gradient(180deg, rgba(255, 255, 255, 0.94), rgba(248, 250, 252, 0.96));
|
|
273
|
-
box-shadow: 0 14px 30px -24px rgba(15, 23, 42, 0.45);
|
|
274
|
-
margin: 16px 0 ;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
.dark .incremark-shiki-code {
|
|
278
|
-
--incremark-code-border: rgba(100, 116, 139, 0.38);
|
|
279
|
-
--incremark-code-toolbar-bg: rgba(15, 23, 42, 0.88);
|
|
280
|
-
--incremark-code-toolbar-text: #cbd5e1;
|
|
281
|
-
--incremark-code-copy-bg: rgba(30, 41, 59, 0.88);
|
|
282
|
-
--incremark-code-copy-text: #e2e8f0;
|
|
283
|
-
background:
|
|
284
|
-
linear-gradient(180deg, rgba(2, 6, 23, 0.96), rgba(15, 23, 42, 0.98));
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
.incremark-shiki-code[data-stream-state='pending'],
|
|
288
|
-
.incremark-shiki-code[data-stream-state='stable'] {
|
|
289
|
-
box-shadow: 0 10px 24px -24px rgba(15, 23, 42, 0.8);
|
|
269
|
+
margin: 0 0 8px;
|
|
290
270
|
}
|
|
291
271
|
|
|
292
272
|
.incremark-shiki-toolbar {
|
|
273
|
+
@apply border-b border-lightCardBorder bg-lightCardBackgroundHover dark:border-darkCardBorder dark:bg-darkCardBackgroundHover;
|
|
293
274
|
display: flex;
|
|
294
275
|
align-items: center;
|
|
295
276
|
justify-content: space-between;
|
|
296
277
|
gap: 12px;
|
|
297
|
-
padding:
|
|
298
|
-
border-bottom: 1px solid var(--incremark-code-border);
|
|
299
|
-
background: var(--incremark-code-toolbar-bg);
|
|
300
|
-
backdrop-filter: blur(10px);
|
|
278
|
+
padding: 4px 4px 4px 12px;
|
|
301
279
|
}
|
|
302
280
|
|
|
303
281
|
.incremark-shiki-language {
|
|
304
|
-
font-
|
|
305
|
-
font-weight: 600;
|
|
306
|
-
letter-spacing: 0.12em;
|
|
307
|
-
text-transform: uppercase;
|
|
308
|
-
color: var(--incremark-code-toolbar-text);
|
|
282
|
+
@apply text-xs font-medium text-lightInputIconColor dark:text-darkInputIconColor;
|
|
309
283
|
}
|
|
310
284
|
|
|
311
285
|
.incremark-shiki-copy {
|
|
312
|
-
|
|
313
|
-
border-radius: 999px;
|
|
314
|
-
padding: 6px 10px;
|
|
315
|
-
font-size: 11px;
|
|
316
|
-
font-weight: 600;
|
|
317
|
-
letter-spacing: 0.04em;
|
|
318
|
-
background: var(--incremark-code-copy-bg);
|
|
319
|
-
color: var(--incremark-code-copy-text);
|
|
320
|
-
cursor: pointer;
|
|
321
|
-
transition: transform 0.16s ease, opacity 0.16s ease, background-color 0.16s ease;
|
|
286
|
+
@apply h-6 rounded-default px-2 text-xs font-medium transition-colors text-lightInputIconColor dark:text-darkInputIconColor;
|
|
322
287
|
}
|
|
323
288
|
|
|
324
289
|
.incremark-shiki-copy:hover:not(:disabled) {
|
|
325
|
-
|
|
290
|
+
@apply bg-lightSecondaryDarken text-lightInputText dark:bg-darkSecondaryLighten dark:text-darkInputText;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.incremark-shiki-copy:focus-visible {
|
|
294
|
+
@apply outline-none ring-[3px] ring-lightFocusRing dark:ring-darkFocusRing;
|
|
326
295
|
}
|
|
327
296
|
|
|
328
297
|
.incremark-shiki-copy:disabled {
|
|
@@ -331,13 +300,7 @@ function clearVega() {
|
|
|
331
300
|
}
|
|
332
301
|
|
|
333
302
|
.incremark-shiki-copy.is-copied {
|
|
334
|
-
|
|
335
|
-
color: #059669;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
.dark .incremark-shiki-copy.is-copied {
|
|
339
|
-
background: rgba(16, 185, 129, 0.24);
|
|
340
|
-
color: #6ee7b7;
|
|
303
|
+
@apply text-lightSuccess dark:text-darkSuccess;
|
|
341
304
|
}
|
|
342
305
|
|
|
343
306
|
.incremark-shiki-body {
|
|
@@ -345,13 +308,13 @@ function clearVega() {
|
|
|
345
308
|
}
|
|
346
309
|
|
|
347
310
|
.incremark-vega {
|
|
348
|
-
padding:
|
|
311
|
+
padding: 12px;
|
|
349
312
|
width: 100%;
|
|
350
313
|
}
|
|
351
314
|
|
|
352
315
|
.incremark-shiki-fallback {
|
|
353
316
|
margin: 0;
|
|
354
|
-
padding:
|
|
317
|
+
padding: 12px;
|
|
355
318
|
overflow-x: auto;
|
|
356
319
|
background: transparent;
|
|
357
320
|
color: inherit;
|
|
@@ -359,7 +322,7 @@ function clearVega() {
|
|
|
359
322
|
|
|
360
323
|
.incremark-shiki-fallback code {
|
|
361
324
|
display: block;
|
|
362
|
-
font-family: '
|
|
325
|
+
font-family: theme('fontFamily.mono');
|
|
363
326
|
font-size: 13px;
|
|
364
327
|
line-height: 1.65;
|
|
365
328
|
white-space: pre;
|
|
@@ -367,7 +330,7 @@ function clearVega() {
|
|
|
367
330
|
|
|
368
331
|
:deep(.incremark-shiki-html pre.shiki) {
|
|
369
332
|
margin: 0;
|
|
370
|
-
padding:
|
|
333
|
+
padding: 12px;
|
|
371
334
|
overflow-x: auto;
|
|
372
335
|
background: transparent !important;
|
|
373
336
|
font-size: 13px;
|
|
@@ -376,7 +339,7 @@ function clearVega() {
|
|
|
376
339
|
|
|
377
340
|
:deep(.incremark-shiki-html code) {
|
|
378
341
|
display: block;
|
|
379
|
-
font-family: '
|
|
342
|
+
font-family: theme('fontFamily.mono');
|
|
380
343
|
}
|
|
381
344
|
|
|
382
345
|
:deep(.incremark-shiki-html .line) {
|
|
@@ -387,7 +350,5 @@ function clearVega() {
|
|
|
387
350
|
width: 100%;
|
|
388
351
|
}
|
|
389
352
|
|
|
390
|
-
|
|
391
|
-
padding: 0;
|
|
392
|
-
}
|
|
353
|
+
|
|
393
354
|
</style>
|
|
@@ -6,12 +6,14 @@
|
|
|
6
6
|
<!-- One button for the whole voice flow: the icon shows the state, the label what a click does -->
|
|
7
7
|
<button
|
|
8
8
|
type="button"
|
|
9
|
-
class="flex h-
|
|
9
|
+
class="flex h-[2.125rem] shrink-0 items-center justify-center rounded-full transition-colors duration-150
|
|
10
|
+
focus:outline-none focus-visible:ring-[3px] focus-visible:ring-lightFocusRing dark:focus-visible:ring-darkFocusRing"
|
|
10
11
|
:class="isAudioChatMode
|
|
11
12
|
? `w-40 gap-2 px-3 text-sm font-medium
|
|
12
|
-
bg-lightPrimary/10 text-
|
|
13
|
-
dark:bg-darkPrimary/20 dark:text-
|
|
14
|
-
:
|
|
13
|
+
bg-lightPrimary/10 text-lightInputText hover:bg-lightPrimary/15
|
|
14
|
+
dark:bg-darkPrimary/20 dark:text-darkInputText dark:hover:bg-darkPrimary/30`
|
|
15
|
+
: `w-[2.125rem] text-lightInputIconColor hover:bg-lightSecondaryDarken hover:text-lightInputText
|
|
16
|
+
dark:text-darkInputIconColor dark:hover:bg-darkSecondaryLighten dark:hover:text-darkInputText`"
|
|
15
17
|
:title="$t(buttonTitle)"
|
|
16
18
|
:aria-label="$t(buttonTitle)"
|
|
17
19
|
@click="isGenerating ? stopCurrentGeneration() : toggleChatMode()"
|
|
@@ -28,6 +28,10 @@ const sessionIdBodySchema = z.object({
|
|
|
28
28
|
const createSessionBodySchema = z.object({
|
|
29
29
|
triggerMessage: z.string().optional(),
|
|
30
30
|
}).strict();
|
|
31
|
+
const renameSessionBodySchema = z.object({
|
|
32
|
+
sessionId: z.string(),
|
|
33
|
+
title: z.string().trim().min(1).max(100),
|
|
34
|
+
}).strict();
|
|
31
35
|
export function setupSessionEndpoints(ctx, server) {
|
|
32
36
|
server.endpoint({
|
|
33
37
|
method: 'POST',
|
|
@@ -175,6 +179,36 @@ export function setupSessionEndpoints(ctx, server) {
|
|
|
175
179
|
};
|
|
176
180
|
})
|
|
177
181
|
});
|
|
182
|
+
server.endpoint({
|
|
183
|
+
method: 'POST',
|
|
184
|
+
path: `/agent/rename-session`,
|
|
185
|
+
agent: {
|
|
186
|
+
hiddenFromAgents: true,
|
|
187
|
+
},
|
|
188
|
+
request_schema: renameSessionBodySchema,
|
|
189
|
+
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
190
|
+
const data = body;
|
|
191
|
+
const session = yield ctx.adminforth.resource(ctx.options.sessionResource.resourceId).get([Filters.EQ(ctx.options.sessionResource.idField, data.sessionId)]);
|
|
192
|
+
if (!session) {
|
|
193
|
+
response.setStatus(404, 'Session not found');
|
|
194
|
+
return {
|
|
195
|
+
error: 'Session not found'
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
if (session[ctx.options.sessionResource.askerIdField] !== adminUser.pk) {
|
|
199
|
+
response.setStatus(403, 'Unauthorized');
|
|
200
|
+
return {
|
|
201
|
+
error: 'Unauthorized'
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
yield ctx.adminforth.resource(ctx.options.sessionResource.resourceId).update(data.sessionId, {
|
|
205
|
+
[ctx.options.sessionResource.titleField]: data.title,
|
|
206
|
+
});
|
|
207
|
+
return {
|
|
208
|
+
title: data.title,
|
|
209
|
+
};
|
|
210
|
+
})
|
|
211
|
+
});
|
|
178
212
|
server.endpoint({
|
|
179
213
|
method: 'POST',
|
|
180
214
|
path: `/agent/add-system-message-to-turns`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminforth/agent",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/jest": "^30.0.0",
|
|
38
38
|
"@types/node": "latest",
|
|
39
|
-
"adminforth": "^
|
|
39
|
+
"adminforth": "^4.1.0",
|
|
40
40
|
"jest": "^30.3.0",
|
|
41
41
|
"semantic-release": "^24.2.1",
|
|
42
42
|
"semantic-release-slack-bot": "^4.0.2",
|
|
@@ -80,6 +80,6 @@
|
|
|
80
80
|
}
|
|
81
81
|
],
|
|
82
82
|
"peerDependencies": {
|
|
83
|
-
"adminforth": "^
|
|
83
|
+
"adminforth": "^4.1.0"
|
|
84
84
|
}
|
|
85
85
|
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
TEMPORARY debug helper: enqueues a test steer message into the buffer WITHOUT sending
|
|
3
|
-
or steering it, so the SteerQueue enter/leave animation can be exercised without a live
|
|
4
|
-
generating turn. Remove before shipping.
|
|
5
|
-
-->
|
|
6
|
-
<template>
|
|
7
|
-
<div
|
|
8
|
-
class="fixed bottom-[400px] left-4 z-[9999] flex items-center gap-2 rounded-lg border border-dashed border-amber-400 bg-amber-50/95 px-2.5 py-2 shadow-lg backdrop-blur dark:border-amber-500 dark:bg-amber-950/95"
|
|
9
|
-
>
|
|
10
|
-
<span class="text-[10px] font-bold uppercase tracking-wider text-amber-600 dark:text-amber-400">
|
|
11
|
-
Steer debug
|
|
12
|
-
</span>
|
|
13
|
-
<input
|
|
14
|
-
v-model="debugText"
|
|
15
|
-
type="text"
|
|
16
|
-
placeholder="Test steer text…"
|
|
17
|
-
class="w-44 rounded-md border border-amber-300 bg-white px-2 py-1 text-xs text-gray-800 focus:outline-none focus:ring-1 focus:ring-amber-400 dark:border-amber-600 dark:bg-gray-800 dark:text-gray-100"
|
|
18
|
-
@keydown.enter.prevent="addTestSteer"
|
|
19
|
-
/>
|
|
20
|
-
<button
|
|
21
|
-
type="button"
|
|
22
|
-
class="rounded-md bg-amber-500 px-2.5 py-1 text-xs font-semibold text-white transition-colors hover:bg-amber-600 active:bg-amber-700"
|
|
23
|
-
@click="addTestSteer"
|
|
24
|
-
>
|
|
25
|
-
Add steer
|
|
26
|
-
</button>
|
|
27
|
-
</div>
|
|
28
|
-
</template>
|
|
29
|
-
|
|
30
|
-
<script setup lang="ts">
|
|
31
|
-
import { ref } from 'vue';
|
|
32
|
-
import { useAgentStore } from './composables/useAgentStore';
|
|
33
|
-
|
|
34
|
-
const agentStore = useAgentStore();
|
|
35
|
-
const debugText = ref('');
|
|
36
|
-
let counter = 0;
|
|
37
|
-
|
|
38
|
-
function addTestSteer() {
|
|
39
|
-
counter += 1;
|
|
40
|
-
const text = debugText.value.trim() || `Test steer #${counter}`;
|
|
41
|
-
// enqueue() only pushes onto the client-side buffer — no /agent/steer, no send.
|
|
42
|
-
agentStore.enqueueSteerMessage(text);
|
|
43
|
-
debugText.value = '';
|
|
44
|
-
}
|
|
45
|
-
</script>
|