arkaos 3.62.0 → 3.64.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/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.64.0
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// PR98b v3.64.0 — quick list of starred agents/personas in the sidebar.
|
|
3
|
+
//
|
|
4
|
+
// Shows up to 4 agents + 4 personas. Each row links to its detail.
|
|
5
|
+
// Hides itself when the operator has zero favourites.
|
|
6
|
+
|
|
7
|
+
const favs = useFavorites()
|
|
8
|
+
const { fetchApi } = useApi()
|
|
9
|
+
|
|
10
|
+
await favs.load()
|
|
11
|
+
const { data: agentsData } = fetchApi<{ agents: Array<{ id: string, name: string }> }>(
|
|
12
|
+
'/api/agents',
|
|
13
|
+
)
|
|
14
|
+
const { data: personasData } = fetchApi<{ personas: Array<{ id: string, name: string }> }>(
|
|
15
|
+
'/api/personas',
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
interface FavRow { id: string, name: string }
|
|
19
|
+
|
|
20
|
+
const starredAgents = computed<FavRow[]>(() => {
|
|
21
|
+
const all = agentsData.value?.agents ?? []
|
|
22
|
+
return favs.state.value.agents
|
|
23
|
+
.map((id) => all.find((a) => a.id === id))
|
|
24
|
+
.filter((a): a is FavRow => Boolean(a))
|
|
25
|
+
.slice(0, 4)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const starredPersonas = computed<FavRow[]>(() => {
|
|
29
|
+
const all = personasData.value?.personas ?? []
|
|
30
|
+
return favs.state.value.personas
|
|
31
|
+
.map((id) => all.find((p) => p.id === id))
|
|
32
|
+
.filter((p): p is FavRow => Boolean(p))
|
|
33
|
+
.slice(0, 4)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const hasAny = computed(
|
|
37
|
+
() => starredAgents.value.length > 0 || starredPersonas.value.length > 0,
|
|
38
|
+
)
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<div
|
|
43
|
+
v-if="hasAny"
|
|
44
|
+
class="rounded-lg border border-default bg-elevated/20 p-2 mx-2 mb-2 text-xs"
|
|
45
|
+
aria-label="Starred agents and personas"
|
|
46
|
+
>
|
|
47
|
+
<div class="flex items-center gap-1.5 mb-1.5">
|
|
48
|
+
<UIcon name="i-lucide-star" class="size-3 text-amber-500" />
|
|
49
|
+
<span class="font-semibold uppercase tracking-wide text-muted text-[10px]">
|
|
50
|
+
Favorites
|
|
51
|
+
</span>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div v-if="starredAgents.length > 0" class="space-y-0.5 mb-1.5">
|
|
55
|
+
<NuxtLink
|
|
56
|
+
v-for="a in starredAgents"
|
|
57
|
+
:key="`a-${a.id}`"
|
|
58
|
+
:to="`/agents/${a.id}`"
|
|
59
|
+
class="flex items-center gap-1.5 rounded px-1.5 py-1 hover:bg-elevated/40 transition-colors"
|
|
60
|
+
>
|
|
61
|
+
<UIcon name="i-lucide-user" class="size-3 text-primary shrink-0" />
|
|
62
|
+
<span class="truncate">{{ a.name }}</span>
|
|
63
|
+
</NuxtLink>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<div v-if="starredPersonas.length > 0" class="space-y-0.5">
|
|
67
|
+
<NuxtLink
|
|
68
|
+
v-for="p in starredPersonas"
|
|
69
|
+
:key="`p-${p.id}`"
|
|
70
|
+
:to="`/personas/${p.id}`"
|
|
71
|
+
class="flex items-center gap-1.5 rounded px-1.5 py-1 hover:bg-elevated/40 transition-colors"
|
|
72
|
+
>
|
|
73
|
+
<UIcon name="i-lucide-user-plus" class="size-3 text-emerald-500 shrink-0" />
|
|
74
|
+
<span class="truncate">{{ p.name }}</span>
|
|
75
|
+
</NuxtLink>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</template>
|
|
@@ -156,8 +156,11 @@ const links = [[{
|
|
|
156
156
|
popover
|
|
157
157
|
/>
|
|
158
158
|
|
|
159
|
+
<!-- PR98b v3.64.0 — favorites quick list -->
|
|
160
|
+
<SidebarFavoritesWidget v-if="!collapsed" class="mt-auto" />
|
|
161
|
+
|
|
159
162
|
<!-- PR87d v3.22.0 — quick stats widget above the bottom nav. -->
|
|
160
|
-
<SidebarStatsWidget v-if="!collapsed"
|
|
163
|
+
<SidebarStatsWidget v-if="!collapsed" />
|
|
161
164
|
|
|
162
165
|
<UNavigationMenu
|
|
163
166
|
:collapsed="collapsed"
|
|
@@ -226,6 +226,59 @@ function csvToList(value: string): string[] {
|
|
|
226
226
|
type SuggestField = 'mental_models' | 'frameworks' | 'expertise_domains' | 'communication_avoid' | 'key_quotes'
|
|
227
227
|
const suggestingField = ref<SuggestField | null>(null)
|
|
228
228
|
|
|
229
|
+
// PR98a v3.63.0 — inline edit for name + title.
|
|
230
|
+
type InlineField = 'name' | 'title'
|
|
231
|
+
const inlineField = ref<InlineField | null>(null)
|
|
232
|
+
const inlineDraft = ref('')
|
|
233
|
+
const inlineSaving = ref(false)
|
|
234
|
+
|
|
235
|
+
function startInline(field: InlineField, current: string | undefined) {
|
|
236
|
+
inlineField.value = field
|
|
237
|
+
inlineDraft.value = current ?? ''
|
|
238
|
+
}
|
|
239
|
+
function cancelInline() {
|
|
240
|
+
inlineField.value = null
|
|
241
|
+
inlineDraft.value = ''
|
|
242
|
+
}
|
|
243
|
+
async function commitInline(field: InlineField) {
|
|
244
|
+
if (!detail.value || inlineField.value !== field) return
|
|
245
|
+
const next = inlineDraft.value.trim()
|
|
246
|
+
const current = (field === 'name' ? detail.value.name : detail.value.title) ?? ''
|
|
247
|
+
if (next === current) {
|
|
248
|
+
cancelInline()
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
if (field === 'name' && !next) {
|
|
252
|
+
// Names can't be empty — persona schema requires it.
|
|
253
|
+
cancelInline()
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
inlineSaving.value = true
|
|
257
|
+
try {
|
|
258
|
+
const res = await $fetch<{ updated?: boolean, error?: string }>(
|
|
259
|
+
`${apiBase}/api/personas/${personaId}`,
|
|
260
|
+
{ method: 'PUT', body: { [field]: next } },
|
|
261
|
+
)
|
|
262
|
+
if (res.error) throw new Error(res.error)
|
|
263
|
+
toast.add({
|
|
264
|
+
title: field === 'name' ? 'Name updated' : 'Title updated',
|
|
265
|
+
description: next || '(empty)',
|
|
266
|
+
color: 'success',
|
|
267
|
+
icon: 'i-lucide-check',
|
|
268
|
+
})
|
|
269
|
+
await refresh()
|
|
270
|
+
} catch (err) {
|
|
271
|
+
toast.add({
|
|
272
|
+
title: 'Save failed',
|
|
273
|
+
description: err instanceof Error ? err.message : 'unknown error',
|
|
274
|
+
color: 'error',
|
|
275
|
+
})
|
|
276
|
+
} finally {
|
|
277
|
+
inlineSaving.value = false
|
|
278
|
+
inlineField.value = null
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
229
282
|
// PR97b v3.60.0 — weekly usage timeline (when did agents clone from here).
|
|
230
283
|
interface UsageWeek { week_start: string, count: number }
|
|
231
284
|
const { data: usageTimelineData } = fetchApi<{
|
|
@@ -552,11 +605,58 @@ const vocabOptions = [
|
|
|
552
605
|
<div class="flex-1 min-w-0 space-y-2">
|
|
553
606
|
<div class="flex items-start justify-between gap-3 flex-wrap">
|
|
554
607
|
<div class="min-w-0">
|
|
608
|
+
<!-- PR98a v3.63.0 — inline edit name + title -->
|
|
555
609
|
<h1 class="text-3xl md:text-4xl font-bold tracking-tight text-highlighted">
|
|
556
|
-
|
|
610
|
+
<UInput
|
|
611
|
+
v-if="inlineField === 'name'"
|
|
612
|
+
v-model="inlineDraft"
|
|
613
|
+
autofocus
|
|
614
|
+
size="lg"
|
|
615
|
+
class="font-bold"
|
|
616
|
+
:loading="inlineSaving"
|
|
617
|
+
@keydown.enter="commitInline('name')"
|
|
618
|
+
@keydown.escape="cancelInline"
|
|
619
|
+
@blur="commitInline('name')"
|
|
620
|
+
/>
|
|
621
|
+
<button
|
|
622
|
+
v-else
|
|
623
|
+
type="button"
|
|
624
|
+
class="hover:text-primary transition-colors"
|
|
625
|
+
title="Click to edit name"
|
|
626
|
+
@click="startInline('name', detail.name)"
|
|
627
|
+
>
|
|
628
|
+
{{ detail.name }}
|
|
629
|
+
</button>
|
|
557
630
|
</h1>
|
|
558
|
-
<p
|
|
559
|
-
|
|
631
|
+
<p class="text-base md:text-lg text-muted mt-0.5">
|
|
632
|
+
<UInput
|
|
633
|
+
v-if="inlineField === 'title'"
|
|
634
|
+
v-model="inlineDraft"
|
|
635
|
+
autofocus
|
|
636
|
+
size="md"
|
|
637
|
+
:loading="inlineSaving"
|
|
638
|
+
@keydown.enter="commitInline('title')"
|
|
639
|
+
@keydown.escape="cancelInline"
|
|
640
|
+
@blur="commitInline('title')"
|
|
641
|
+
/>
|
|
642
|
+
<button
|
|
643
|
+
v-else-if="detail.title"
|
|
644
|
+
type="button"
|
|
645
|
+
class="hover:text-primary transition-colors text-left"
|
|
646
|
+
title="Click to edit title"
|
|
647
|
+
@click="startInline('title', detail.title)"
|
|
648
|
+
>
|
|
649
|
+
{{ detail.title }}
|
|
650
|
+
</button>
|
|
651
|
+
<button
|
|
652
|
+
v-else
|
|
653
|
+
type="button"
|
|
654
|
+
class="hover:text-primary transition-colors text-left italic text-muted/60"
|
|
655
|
+
title="Click to add title"
|
|
656
|
+
@click="startInline('title', '')"
|
|
657
|
+
>
|
|
658
|
+
+ Add title
|
|
659
|
+
</button>
|
|
560
660
|
</p>
|
|
561
661
|
</div>
|
|
562
662
|
<div class="flex items-center gap-2">
|
package/package.json
CHANGED