arkaos 3.56.0 → 3.57.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.57.0
|
|
@@ -283,15 +283,28 @@ function onCloned(agentId: string) {
|
|
|
283
283
|
}
|
|
284
284
|
|
|
285
285
|
// PR88a v3.23.0 — Compare with linked agent.
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
286
|
+
// PR96c v3.57.0 — also compare with another persona.
|
|
287
|
+
const { data: otherPersonasData } = fetchApi<{ personas: Array<{ id: string, name: string }> }>(
|
|
288
|
+
'/api/personas',
|
|
289
|
+
)
|
|
290
|
+
const compareWithOptions = computed(() => {
|
|
291
|
+
const agentOpts = linkedAgentIds.value.map((aid) => ({
|
|
292
|
+
label: `Compare with agent ${aid}`,
|
|
293
|
+
icon: 'i-lucide-user',
|
|
290
294
|
onSelect: () => navigateTo(
|
|
291
295
|
`/personas/compare-with-agent?persona=${personaId}&agent=${aid}`,
|
|
292
296
|
),
|
|
293
|
-
}))
|
|
294
|
-
)
|
|
297
|
+
}))
|
|
298
|
+
const personaOpts = (otherPersonasData.value?.personas ?? [])
|
|
299
|
+
.filter((p) => p.id !== personaId)
|
|
300
|
+
.slice(0, 30)
|
|
301
|
+
.map((p) => ({
|
|
302
|
+
label: `Compare with persona ${p.name}`,
|
|
303
|
+
icon: 'i-lucide-user-plus',
|
|
304
|
+
onSelect: () => navigateTo(`/personas/compare?a=${personaId}&b=${p.id}`),
|
|
305
|
+
}))
|
|
306
|
+
return [...agentOpts, ...personaOpts]
|
|
307
|
+
})
|
|
295
308
|
|
|
296
309
|
// PR84c v3.9.0 — Auto-fill empty lists in one go.
|
|
297
310
|
const autofilling = ref(false)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// PR96c v3.57.0 — Compare two personas side-by-side.
|
|
3
|
+
//
|
|
4
|
+
// Driven by `?a=p1&b=p2`. Mirrors the agents/compare layout but
|
|
5
|
+
// adapts to the persona schema (flat mental_models, no department).
|
|
6
|
+
|
|
7
|
+
const route = useRoute()
|
|
8
|
+
const { fetchApi } = useApi()
|
|
9
|
+
|
|
10
|
+
const ids = computed<string[]>(() => {
|
|
11
|
+
const raw = [route.query.a, route.query.b]
|
|
12
|
+
return raw.map((v) => String(v ?? '').trim()).filter(Boolean).slice(0, 2)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
interface PersonaDetail {
|
|
16
|
+
id: string
|
|
17
|
+
name?: string
|
|
18
|
+
title?: string
|
|
19
|
+
source?: string
|
|
20
|
+
tagline?: string
|
|
21
|
+
mbti?: string
|
|
22
|
+
disc?: { primary?: string, secondary?: string }
|
|
23
|
+
enneagram?: { type?: number, wing?: number }
|
|
24
|
+
big_five?: {
|
|
25
|
+
openness?: number
|
|
26
|
+
conscientiousness?: number
|
|
27
|
+
extraversion?: number
|
|
28
|
+
agreeableness?: number
|
|
29
|
+
neuroticism?: number
|
|
30
|
+
}
|
|
31
|
+
mental_models?: string[]
|
|
32
|
+
expertise_domains?: string[]
|
|
33
|
+
frameworks?: string[]
|
|
34
|
+
key_quotes?: string[]
|
|
35
|
+
communication?: { tone?: string, vocabulary_level?: string, avoid?: string[] }
|
|
36
|
+
bio_md?: string
|
|
37
|
+
error?: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const { data: a, status: aStatus } = fetchApi<PersonaDetail>(
|
|
41
|
+
() => ids.value[0] ? `/api/personas/${ids.value[0]}` : '',
|
|
42
|
+
)
|
|
43
|
+
const { data: b, status: bStatus } = fetchApi<PersonaDetail>(
|
|
44
|
+
() => ids.value[1] ? `/api/personas/${ids.value[1]}` : '',
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
const loading = computed(() => aStatus.value === 'pending' || bStatus.value === 'pending')
|
|
48
|
+
const errorMsg = computed(() => {
|
|
49
|
+
if (ids.value.length < 2) return 'Pass two persona ids via ?a=p1&b=p2'
|
|
50
|
+
if (a.value?.error) return `Left: ${a.value.error}`
|
|
51
|
+
if (b.value?.error) return `Right: ${b.value.error}`
|
|
52
|
+
return null
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
function diffClass(left: unknown, right: unknown): string {
|
|
56
|
+
return left !== right ? 'bg-yellow-500/10 border-yellow-500/30' : ''
|
|
57
|
+
}
|
|
58
|
+
function listDiffClass(left: unknown[] | undefined, right: unknown[] | undefined): string {
|
|
59
|
+
const x = JSON.stringify([...(left ?? [])].sort())
|
|
60
|
+
const y = JSON.stringify([...(right ?? [])].sort())
|
|
61
|
+
return x !== y ? 'bg-yellow-500/10 border-yellow-500/30' : ''
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const bigFiveKeys = ['openness', 'conscientiousness', 'extraversion', 'agreeableness', 'neuroticism'] as const
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<template>
|
|
68
|
+
<UDashboardPanel id="personas-compare">
|
|
69
|
+
<template #header>
|
|
70
|
+
<UDashboardNavbar title="Compare personas">
|
|
71
|
+
<template #leading>
|
|
72
|
+
<UButton icon="i-lucide-arrow-left" variant="ghost" size="sm" to="/personas" aria-label="Back" />
|
|
73
|
+
</template>
|
|
74
|
+
<template #trailing>
|
|
75
|
+
<UBadge label="2-way" variant="subtle" size="sm" />
|
|
76
|
+
</template>
|
|
77
|
+
</UDashboardNavbar>
|
|
78
|
+
</template>
|
|
79
|
+
|
|
80
|
+
<template #body>
|
|
81
|
+
<div v-if="errorMsg" class="p-6 text-center text-sm text-error">
|
|
82
|
+
{{ errorMsg }}
|
|
83
|
+
</div>
|
|
84
|
+
<div v-else-if="loading" class="p-6 text-center text-sm text-muted">
|
|
85
|
+
<UIcon name="i-lucide-loader-2" class="size-4 animate-spin inline" /> Loading…
|
|
86
|
+
</div>
|
|
87
|
+
<div v-else-if="a && b" class="space-y-4 max-w-6xl">
|
|
88
|
+
<section class="grid grid-cols-2 gap-3">
|
|
89
|
+
<NuxtLink :to="`/personas/${a.id}`" class="rounded-lg border border-default p-4 hover:border-primary/40">
|
|
90
|
+
<p class="text-xs text-muted uppercase tracking-wide">Left</p>
|
|
91
|
+
<h2 class="text-xl font-bold">{{ a.name }}</h2>
|
|
92
|
+
<p class="text-sm text-muted">{{ a.title || '—' }}</p>
|
|
93
|
+
</NuxtLink>
|
|
94
|
+
<NuxtLink :to="`/personas/${b.id}`" class="rounded-lg border border-default p-4 hover:border-primary/40">
|
|
95
|
+
<p class="text-xs text-muted uppercase tracking-wide">Right</p>
|
|
96
|
+
<h2 class="text-xl font-bold">{{ b.name }}</h2>
|
|
97
|
+
<p class="text-sm text-muted">{{ b.title || '—' }}</p>
|
|
98
|
+
</NuxtLink>
|
|
99
|
+
</section>
|
|
100
|
+
|
|
101
|
+
<h3 class="text-sm font-semibold uppercase tracking-wide text-muted pt-2">Behavioural DNA</h3>
|
|
102
|
+
<div class="grid grid-cols-2 gap-3">
|
|
103
|
+
<div :class="['rounded-lg border p-3', diffClass(a.mbti, b.mbti)]">
|
|
104
|
+
<p class="text-xs text-muted">MBTI</p>
|
|
105
|
+
<p class="text-lg font-mono font-bold">{{ a.mbti ?? '—' }}</p>
|
|
106
|
+
</div>
|
|
107
|
+
<div :class="['rounded-lg border p-3', diffClass(a.mbti, b.mbti)]">
|
|
108
|
+
<p class="text-xs text-muted">MBTI</p>
|
|
109
|
+
<p class="text-lg font-mono font-bold">{{ b.mbti ?? '—' }}</p>
|
|
110
|
+
</div>
|
|
111
|
+
<div :class="['rounded-lg border p-3', diffClass(`${a.disc?.primary}/${a.disc?.secondary}`, `${b.disc?.primary}/${b.disc?.secondary}`)]">
|
|
112
|
+
<p class="text-xs text-muted">DISC</p>
|
|
113
|
+
<p class="text-lg font-mono font-bold">{{ a.disc?.primary ?? '?' }}/{{ a.disc?.secondary ?? '?' }}</p>
|
|
114
|
+
</div>
|
|
115
|
+
<div :class="['rounded-lg border p-3', diffClass(`${a.disc?.primary}/${a.disc?.secondary}`, `${b.disc?.primary}/${b.disc?.secondary}`)]">
|
|
116
|
+
<p class="text-xs text-muted">DISC</p>
|
|
117
|
+
<p class="text-lg font-mono font-bold">{{ b.disc?.primary ?? '?' }}/{{ b.disc?.secondary ?? '?' }}</p>
|
|
118
|
+
</div>
|
|
119
|
+
<div :class="['rounded-lg border p-3', diffClass(`${a.enneagram?.type}w${a.enneagram?.wing}`, `${b.enneagram?.type}w${b.enneagram?.wing}`)]">
|
|
120
|
+
<p class="text-xs text-muted">Enneagram</p>
|
|
121
|
+
<p class="text-lg font-mono font-bold">{{ a.enneagram?.type ?? '?' }}w{{ a.enneagram?.wing ?? '?' }}</p>
|
|
122
|
+
</div>
|
|
123
|
+
<div :class="['rounded-lg border p-3', diffClass(`${a.enneagram?.type}w${a.enneagram?.wing}`, `${b.enneagram?.type}w${b.enneagram?.wing}`)]">
|
|
124
|
+
<p class="text-xs text-muted">Enneagram</p>
|
|
125
|
+
<p class="text-lg font-mono font-bold">{{ b.enneagram?.type ?? '?' }}w{{ b.enneagram?.wing ?? '?' }}</p>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<h3 class="text-sm font-semibold uppercase tracking-wide text-muted pt-2">Big Five (OCEAN)</h3>
|
|
130
|
+
<div class="space-y-1">
|
|
131
|
+
<div v-for="k in bigFiveKeys" :key="k" class="grid grid-cols-2 gap-3">
|
|
132
|
+
<div :class="['rounded-lg border p-2 flex items-center gap-3', diffClass(a.big_five?.[k], b.big_five?.[k])]">
|
|
133
|
+
<span class="text-xs text-muted w-36 shrink-0 capitalize">{{ k }}</span>
|
|
134
|
+
<span class="font-mono text-sm">{{ a.big_five?.[k] ?? '—' }}</span>
|
|
135
|
+
</div>
|
|
136
|
+
<div :class="['rounded-lg border p-2 flex items-center gap-3', diffClass(a.big_five?.[k], b.big_five?.[k])]">
|
|
137
|
+
<span class="text-xs text-muted w-36 shrink-0 capitalize">{{ k }}</span>
|
|
138
|
+
<span class="font-mono text-sm">{{ b.big_five?.[k] ?? '—' }}</span>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<h3 class="text-sm font-semibold uppercase tracking-wide text-muted pt-2">Expertise domains</h3>
|
|
144
|
+
<div class="grid grid-cols-2 gap-3">
|
|
145
|
+
<div :class="['rounded-lg border p-3', listDiffClass(a.expertise_domains, b.expertise_domains)]">
|
|
146
|
+
<ul class="list-disc list-inside text-sm space-y-1">
|
|
147
|
+
<li v-for="d in a.expertise_domains" :key="d">{{ d }}</li>
|
|
148
|
+
<li v-if="!a.expertise_domains?.length" class="list-none text-muted italic">none</li>
|
|
149
|
+
</ul>
|
|
150
|
+
</div>
|
|
151
|
+
<div :class="['rounded-lg border p-3', listDiffClass(a.expertise_domains, b.expertise_domains)]">
|
|
152
|
+
<ul class="list-disc list-inside text-sm space-y-1">
|
|
153
|
+
<li v-for="d in b.expertise_domains" :key="d">{{ d }}</li>
|
|
154
|
+
<li v-if="!b.expertise_domains?.length" class="list-none text-muted italic">none</li>
|
|
155
|
+
</ul>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
|
|
159
|
+
<h3 class="text-sm font-semibold uppercase tracking-wide text-muted pt-2">Mental models</h3>
|
|
160
|
+
<div class="grid grid-cols-2 gap-3">
|
|
161
|
+
<div :class="['rounded-lg border p-3', listDiffClass(a.mental_models, b.mental_models)]">
|
|
162
|
+
<ul class="list-disc list-inside text-sm space-y-1">
|
|
163
|
+
<li v-for="m in a.mental_models" :key="m">{{ m }}</li>
|
|
164
|
+
<li v-if="!a.mental_models?.length" class="list-none text-muted italic">none</li>
|
|
165
|
+
</ul>
|
|
166
|
+
</div>
|
|
167
|
+
<div :class="['rounded-lg border p-3', listDiffClass(a.mental_models, b.mental_models)]">
|
|
168
|
+
<ul class="list-disc list-inside text-sm space-y-1">
|
|
169
|
+
<li v-for="m in b.mental_models" :key="m">{{ m }}</li>
|
|
170
|
+
<li v-if="!b.mental_models?.length" class="list-none text-muted italic">none</li>
|
|
171
|
+
</ul>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
<h3 class="text-sm font-semibold uppercase tracking-wide text-muted pt-2">Frameworks</h3>
|
|
176
|
+
<div class="grid grid-cols-2 gap-3">
|
|
177
|
+
<div :class="['rounded-lg border p-3', listDiffClass(a.frameworks, b.frameworks)]">
|
|
178
|
+
<ul class="list-disc list-inside text-sm space-y-1">
|
|
179
|
+
<li v-for="f in a.frameworks" :key="f">{{ f }}</li>
|
|
180
|
+
<li v-if="!a.frameworks?.length" class="list-none text-muted italic">none</li>
|
|
181
|
+
</ul>
|
|
182
|
+
</div>
|
|
183
|
+
<div :class="['rounded-lg border p-3', listDiffClass(a.frameworks, b.frameworks)]">
|
|
184
|
+
<ul class="list-disc list-inside text-sm space-y-1">
|
|
185
|
+
<li v-for="f in b.frameworks" :key="f">{{ f }}</li>
|
|
186
|
+
<li v-if="!b.frameworks?.length" class="list-none text-muted italic">none</li>
|
|
187
|
+
</ul>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
|
|
191
|
+
<h3 class="text-sm font-semibold uppercase tracking-wide text-muted pt-2">Bio (Markdown)</h3>
|
|
192
|
+
<TextDiff
|
|
193
|
+
:left="a.bio_md || ''"
|
|
194
|
+
:right="b.bio_md || ''"
|
|
195
|
+
:left-label="a.name || a.id"
|
|
196
|
+
:right-label="b.name || b.id"
|
|
197
|
+
/>
|
|
198
|
+
|
|
199
|
+
<h3 class="text-sm font-semibold uppercase tracking-wide text-muted pt-2">Communication tone</h3>
|
|
200
|
+
<TextDiff
|
|
201
|
+
:left="a.communication?.tone || ''"
|
|
202
|
+
:right="b.communication?.tone || ''"
|
|
203
|
+
:left-label="a.name || a.id"
|
|
204
|
+
:right-label="b.name || b.id"
|
|
205
|
+
/>
|
|
206
|
+
|
|
207
|
+
<p class="text-xs text-muted pt-4 italic">
|
|
208
|
+
Yellow tint = different. Red removed, green added.
|
|
209
|
+
</p>
|
|
210
|
+
</div>
|
|
211
|
+
</template>
|
|
212
|
+
</UDashboardPanel>
|
|
213
|
+
</template>
|
package/package.json
CHANGED