arkaos 3.47.0 → 3.49.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.47.0
1
+ 3.49.0
@@ -63,6 +63,16 @@ function applyArchetype(arch: Archetype) {
63
63
  mode.value = 'description'
64
64
  }
65
65
 
66
+ // PR94b v3.48.0 — auto-apply archetype from query string (deep link
67
+ // from the /personas/archetypes catalog).
68
+ const route = useRoute()
69
+ watch(archetypes, (list) => {
70
+ const slug = String(route.query.archetype ?? '')
71
+ if (!slug || list.length === 0) return
72
+ const match = list.find((a) => a.id === slug)
73
+ if (match) applyArchetype(match)
74
+ }, { immediate: true })
75
+
66
76
  // ─── Step 2 state ────────────────────────────────────────────────────────
67
77
  const ingestJobs = ref<Array<{
68
78
  source: string
@@ -0,0 +1,110 @@
1
+ <script setup lang="ts">
2
+ // PR94c v3.49.0 — minimal side-by-side line diff.
3
+ //
4
+ // Uses LCS (longest common subsequence) on lines to mark equal / added /
5
+ // removed rows. Empty inputs render an italic "—" placeholder. Diff is
6
+ // pure client-side — no deps.
7
+
8
+ const props = defineProps<{
9
+ left: string
10
+ right: string
11
+ leftLabel?: string
12
+ rightLabel?: string
13
+ }>()
14
+
15
+ interface DiffRow {
16
+ kind: 'eq' | 'add' | 'del'
17
+ left: string
18
+ right: string
19
+ }
20
+
21
+ function lineDiff(a: string, b: string): DiffRow[] {
22
+ const left = (a ?? '').split(/\r?\n/)
23
+ const right = (b ?? '').split(/\r?\n/)
24
+ const m = left.length
25
+ const n = right.length
26
+ // Build LCS table.
27
+ const dp: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0))
28
+ for (let i = m - 1; i >= 0; i -= 1) {
29
+ for (let j = n - 1; j >= 0; j -= 1) {
30
+ if (left[i] === right[j]) dp[i][j] = dp[i + 1][j + 1] + 1
31
+ else dp[i][j] = Math.max(dp[i + 1][j], dp[i][j + 1])
32
+ }
33
+ }
34
+ // Walk back, emitting rows.
35
+ const rows: DiffRow[] = []
36
+ let i = 0
37
+ let j = 0
38
+ while (i < m && j < n) {
39
+ if (left[i] === right[j]) {
40
+ rows.push({ kind: 'eq', left: left[i], right: right[j] })
41
+ i += 1
42
+ j += 1
43
+ } else if (dp[i + 1][j] >= dp[i][j + 1]) {
44
+ rows.push({ kind: 'del', left: left[i], right: '' })
45
+ i += 1
46
+ } else {
47
+ rows.push({ kind: 'add', left: '', right: right[j] })
48
+ j += 1
49
+ }
50
+ }
51
+ while (i < m) {
52
+ rows.push({ kind: 'del', left: left[i], right: '' })
53
+ i += 1
54
+ }
55
+ while (j < n) {
56
+ rows.push({ kind: 'add', left: '', right: right[j] })
57
+ j += 1
58
+ }
59
+ return rows
60
+ }
61
+
62
+ const rows = computed(() => lineDiff(props.left || '', props.right || ''))
63
+
64
+ const summary = computed(() => {
65
+ const adds = rows.value.filter((r) => r.kind === 'add').length
66
+ const dels = rows.value.filter((r) => r.kind === 'del').length
67
+ return { adds, dels }
68
+ })
69
+ </script>
70
+
71
+ <template>
72
+ <div class="rounded-lg border border-default overflow-hidden">
73
+ <div class="px-3 py-2 border-b border-default bg-elevated/30 flex items-center justify-between gap-3 text-xs">
74
+ <div class="flex items-center gap-3">
75
+ <span class="font-mono">{{ leftLabel ?? 'left' }}</span>
76
+ <UIcon name="i-lucide-arrow-right" class="size-3 text-muted" />
77
+ <span class="font-mono">{{ rightLabel ?? 'right' }}</span>
78
+ </div>
79
+ <div class="flex items-center gap-2 font-mono text-muted">
80
+ <span v-if="summary.adds > 0" class="text-emerald-500">+{{ summary.adds }}</span>
81
+ <span v-if="summary.dels > 0" class="text-rose-500">-{{ summary.dels }}</span>
82
+ <span v-if="summary.adds === 0 && summary.dels === 0">identical</span>
83
+ </div>
84
+ </div>
85
+ <div class="grid grid-cols-2 text-xs font-mono overflow-x-auto">
86
+ <div>
87
+ <div
88
+ v-for="(row, idx) in rows"
89
+ :key="`l-${idx}`"
90
+ :class="[
91
+ 'px-3 py-1 whitespace-pre-wrap break-words border-b border-default/50 min-h-[1.5rem]',
92
+ row.kind === 'del' ? 'bg-rose-500/10 text-rose-600 dark:text-rose-400' : '',
93
+ row.kind === 'add' ? 'bg-muted/10' : '',
94
+ ]"
95
+ >{{ row.left || '·' }}</div>
96
+ </div>
97
+ <div class="border-l border-default">
98
+ <div
99
+ v-for="(row, idx) in rows"
100
+ :key="`r-${idx}`"
101
+ :class="[
102
+ 'px-3 py-1 whitespace-pre-wrap break-words border-b border-default/50 min-h-[1.5rem]',
103
+ row.kind === 'add' ? 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400' : '',
104
+ row.kind === 'del' ? 'bg-muted/10' : '',
105
+ ]"
106
+ >{{ row.right || '·' }}</div>
107
+ </div>
108
+ </div>
109
+ </div>
110
+ </template>
@@ -40,6 +40,8 @@ interface AgentDetail {
40
40
  preferred_format?: string
41
41
  language?: string
42
42
  }
43
+ // PR94c v3.49.0 — diffable free-text field
44
+ bio_md?: string
43
45
  }
44
46
 
45
47
  const { data: a, status: aStatus } = fetchApi<AgentDetail>(
@@ -216,8 +218,26 @@ const bigFiveKeys = ['openness', 'conscientiousness', 'extraversion', 'agreeable
216
218
  </div>
217
219
  </div>
218
220
 
221
+ <!-- PR94c v3.49.0 — text diff blocks for the free-text fields -->
222
+ <h3 class="text-sm font-semibold uppercase tracking-wide text-muted pt-2">Bio (Markdown)</h3>
223
+ <TextDiff
224
+ :left="a.bio_md || ''"
225
+ :right="b.bio_md || ''"
226
+ :left-label="a.name || a.id"
227
+ :right-label="b.name || b.id"
228
+ />
229
+
230
+ <h3 class="text-sm font-semibold uppercase tracking-wide text-muted pt-2">Communication tone</h3>
231
+ <TextDiff
232
+ :left="a.communication?.tone || ''"
233
+ :right="b.communication?.tone || ''"
234
+ :left-label="a.name || a.id"
235
+ :right-label="b.name || b.id"
236
+ />
237
+
219
238
  <p class="text-xs text-muted pt-4 italic">
220
- Cells with a yellow tint differ between the two agents.
239
+ Cells with a yellow tint differ between the two agents. Red lines were
240
+ removed; green lines were added.
221
241
  </p>
222
242
  </div>
223
243
  </template>
@@ -0,0 +1,106 @@
1
+ <script setup lang="ts">
2
+ // PR94b v3.48.0 — Browseable catalog of persona archetypes.
3
+ //
4
+ // Reads /api/personas/archetypes (PR93b) and renders each as a card.
5
+ // "Create from this" deep-links to /personas/new?archetype=<id> where
6
+ // the wizard auto-selects description mode and pre-fills.
7
+
8
+ interface Archetype {
9
+ id: string
10
+ name: string
11
+ title: string
12
+ tagline: string
13
+ mbti: string
14
+ disc: { primary: string, secondary: string }
15
+ enneagram: { type: number, wing: number }
16
+ description: string
17
+ }
18
+
19
+ const { fetchApi } = useApi()
20
+ const { data, status, error, refresh } = await fetchApi<{
21
+ archetypes: Archetype[]
22
+ total: number
23
+ }>('/api/personas/archetypes')
24
+
25
+ const archetypes = computed<Archetype[]>(() => data.value?.archetypes ?? [])
26
+
27
+ function discColor(letter: string): 'error' | 'warning' | 'success' | 'primary' | 'neutral' {
28
+ const m: Record<string, 'error' | 'warning' | 'success' | 'primary' | 'neutral'> = {
29
+ D: 'error', I: 'warning', S: 'success', C: 'primary',
30
+ }
31
+ return m[letter] ?? 'neutral'
32
+ }
33
+ </script>
34
+
35
+ <template>
36
+ <UDashboardPanel id="archetypes">
37
+ <template #header>
38
+ <UDashboardNavbar title="Persona archetypes">
39
+ <template #leading>
40
+ <UButton icon="i-lucide-arrow-left" variant="ghost" size="sm" to="/personas" aria-label="Back" />
41
+ </template>
42
+ <template #trailing>
43
+ <UBadge v-if="data?.total" :label="String(data.total)" variant="subtle" />
44
+ </template>
45
+ </UDashboardNavbar>
46
+ </template>
47
+
48
+ <template #body>
49
+ <DashboardState
50
+ :status="status"
51
+ :error="error"
52
+ :empty="!archetypes.length"
53
+ empty-title="No archetypes available"
54
+ empty-icon="i-lucide-sparkles"
55
+ loading-label="Loading archetypes"
56
+ :on-retry="() => refresh()"
57
+ >
58
+ <p class="text-sm text-muted mb-6 max-w-2xl">
59
+ Curated starter profiles. Each one ships a description, behavioural DNA
60
+ defaults, and a recommended communication style. Use them as a base
61
+ when you don't have indexed content yet — the wizard pre-fills the
62
+ description and you tweak from there.
63
+ </p>
64
+
65
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
66
+ <div
67
+ v-for="arch in archetypes"
68
+ :key="arch.id"
69
+ class="rounded-xl border border-default p-5 flex flex-col gap-3 hover:border-primary/40 transition-colors"
70
+ >
71
+ <div>
72
+ <h3 class="text-lg font-bold">{{ arch.name }}</h3>
73
+ <p class="text-xs text-muted">{{ arch.title }}</p>
74
+ </div>
75
+ <p class="text-sm italic text-muted">"{{ arch.tagline }}"</p>
76
+ <div class="flex flex-wrap gap-1.5">
77
+ <UBadge :label="arch.mbti" variant="subtle" size="xs" />
78
+ <UBadge
79
+ :label="`DISC: ${arch.disc.primary}/${arch.disc.secondary}`"
80
+ :color="discColor(arch.disc.primary)"
81
+ variant="subtle"
82
+ size="xs"
83
+ />
84
+ <UBadge
85
+ :label="`E${arch.enneagram.type}w${arch.enneagram.wing}`"
86
+ variant="outline"
87
+ size="xs"
88
+ />
89
+ </div>
90
+ <p class="text-sm text-muted line-clamp-3">{{ arch.description }}</p>
91
+ <div class="pt-2 mt-auto">
92
+ <UButton
93
+ label="Create from this"
94
+ icon="i-lucide-sparkles"
95
+ color="primary"
96
+ size="sm"
97
+ block
98
+ :to="`/personas/new?archetype=${arch.id}`"
99
+ />
100
+ </div>
101
+ </div>
102
+ </div>
103
+ </DashboardState>
104
+ </template>
105
+ </UDashboardPanel>
106
+ </template>
@@ -29,6 +29,7 @@ interface PersonaDetail {
29
29
  expertise_domains?: string[]
30
30
  frameworks?: string[]
31
31
  communication?: { tone?: string, vocabulary_level?: string, avoid?: string[] }
32
+ bio_md?: string // PR94c v3.49.0
32
33
  }
33
34
 
34
35
  interface AgentDetail {
@@ -43,6 +44,7 @@ interface AgentDetail {
43
44
  mental_models?: { primary?: string[], secondary?: string[] }
44
45
  expertise?: { domains?: string[], frameworks?: string[] }
45
46
  communication?: { tone?: string, vocabulary_level?: string, avoid?: string[] }
47
+ bio_md?: string // PR94c v3.49.0
46
48
  }
47
49
 
48
50
  const { data: persona, status: pStatus } = fetchApi<PersonaDetail>(
@@ -209,8 +211,26 @@ const bigFiveKeys = ['openness', 'conscientiousness', 'extraversion', 'agreeable
209
211
  </div>
210
212
  </div>
211
213
 
214
+ <!-- PR94c v3.49.0 — free-text diff blocks -->
215
+ <h3 class="text-sm font-semibold uppercase tracking-wide text-muted pt-2">Bio (Markdown)</h3>
216
+ <TextDiff
217
+ :left="persona.bio_md || ''"
218
+ :right="agent.bio_md || ''"
219
+ :left-label="persona.name || persona.id"
220
+ :right-label="agent.name || agent.id"
221
+ />
222
+
223
+ <h3 class="text-sm font-semibold uppercase tracking-wide text-muted pt-2">Communication tone</h3>
224
+ <TextDiff
225
+ :left="persona.communication?.tone || ''"
226
+ :right="agent.communication?.tone || ''"
227
+ :left-label="persona.name || persona.id"
228
+ :right-label="agent.name || agent.id"
229
+ />
230
+
212
231
  <p class="text-xs text-muted pt-4 italic">
213
- Cells with a yellow tint differ between persona and agent.
232
+ Cells with a yellow tint differ between persona and agent. Red lines
233
+ were removed; green lines were added.
214
234
  </p>
215
235
  </div>
216
236
  </template>
@@ -423,6 +423,13 @@ async function undoTrashIds(ids: string[]) {
423
423
  />
424
424
  </template>
425
425
  <template #right>
426
+ <UButton
427
+ label="Archetypes"
428
+ icon="i-lucide-sparkles"
429
+ variant="ghost"
430
+ size="sm"
431
+ to="/personas/archetypes"
432
+ />
426
433
  <UButton
427
434
  label="Export ZIP"
428
435
  icon="i-lucide-archive"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkaos",
3
- "version": "3.47.0",
3
+ "version": "3.49.0",
4
4
  "description": "The Operating System for AI Agent Teams",
5
5
  "type": "module",
6
6
  "bin": {
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "arkaos-core"
3
- version = "3.47.0"
3
+ version = "3.49.0"
4
4
  description = "Core engine for ArkaOS — The Operating System for AI Agent Teams"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}