@cat-factory/app 0.74.3 → 0.75.2

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.
@@ -5,6 +5,7 @@
5
5
  // inspector, task panel) gets identical behaviour from one place. Replaces the
6
6
  // three hand-rolled bootstrap banners that used to duplicate this logic.
7
7
  import type { AgentRunSummary } from '~/stores/agentRuns'
8
+ import FailureDetail from '~/components/board/FailureDetail.vue'
8
9
 
9
10
  const props = withDefaults(
10
11
  defineProps<{ run: AgentRunSummary; variant?: 'compact' | 'expanded' }>(),
@@ -82,15 +83,13 @@ async function retry() {
82
83
  {{ failure.hint }}
83
84
  </p>
84
85
 
85
- <details v-if="!compact && failure?.detail && failure.detail !== failure.message" class="mt-1">
86
- <summary class="cursor-pointer text-[10px] text-rose-400/60 hover:text-rose-300">
87
- {{ t('board.failure.showDetail') }}
88
- </summary>
89
- <pre
90
- class="mt-1 max-h-32 overflow-auto whitespace-pre-wrap rounded bg-rose-950/60 p-1.5 text-[10px] text-rose-200/80"
91
- >{{ failure.detail }}</pre
92
- >
93
- </details>
86
+ <FailureDetail
87
+ v-if="!compact && failure"
88
+ :detail="failure.detail"
89
+ :message="failure.message"
90
+ summary-class="text-[10px] text-rose-400/60 hover:text-rose-300"
91
+ pre-class="bg-rose-950/60 text-[10px] text-rose-200/80"
92
+ />
94
93
 
95
94
  <button
96
95
  type="button"
@@ -0,0 +1,60 @@
1
+ <script setup lang="ts">
2
+ // The error trail of a run's PRIOR attempts, preserved across retries/restarts. This is
3
+ // deliberately SEPARATE from the top failure banner (`AgentFailureCard`, keyed on the
4
+ // current `status === 'failed'`): when a failed task is retried it restarts and the top
5
+ // banner disappears, but this collapsed history stays available so every previous error
6
+ // remains viewable. Renders nothing when there is no trail.
7
+ import type { AgentFailure } from '~/types/domain'
8
+ import FailureDetail from '~/components/board/FailureDetail.vue'
9
+
10
+ const props = defineProps<{ failures: AgentFailure[] }>()
11
+
12
+ const { t, d } = useI18n()
13
+
14
+ // Newest attempt first — the most recent failure is the most relevant to look at.
15
+ const ordered = computed(() => [...props.failures].reverse())
16
+ </script>
17
+
18
+ <template>
19
+ <details
20
+ v-if="failures.length"
21
+ class="nodrag rounded-lg border border-slate-700/60 bg-slate-900/40 px-3 py-2"
22
+ data-testid="agent-failure-history"
23
+ >
24
+ <summary
25
+ class="flex cursor-pointer items-center gap-1.5 text-[11px] text-slate-400 hover:text-slate-200"
26
+ >
27
+ <UIcon name="i-lucide-history" class="h-3.5 w-3.5 shrink-0" />
28
+ {{ t('board.failure.history.previousErrors', { count: failures.length }, failures.length) }}
29
+ </summary>
30
+
31
+ <ol class="mt-2 space-y-2">
32
+ <li
33
+ v-for="failure in ordered"
34
+ :key="failure.occurredAt"
35
+ class="rounded-md border border-slate-800/80 bg-slate-950/50 px-2.5 py-2"
36
+ data-testid="agent-failure-history-entry"
37
+ >
38
+ <div class="flex items-center gap-1.5 text-[10px] text-slate-500">
39
+ <UIcon name="i-lucide-alert-triangle" class="h-3 w-3 shrink-0 text-rose-400/70" />
40
+ <time>{{ d(new Date(failure.occurredAt), 'long') }}</time>
41
+ </div>
42
+
43
+ <p class="mt-1 text-[11px] leading-snug text-slate-300" :title="failure.message">
44
+ {{ failure.message }}
45
+ </p>
46
+
47
+ <p v-if="failure.hint" class="mt-1 text-[10px] leading-snug text-slate-500">
48
+ {{ failure.hint }}
49
+ </p>
50
+
51
+ <FailureDetail
52
+ :detail="failure.detail"
53
+ :message="failure.message"
54
+ summary-class="text-[10px] text-slate-500 hover:text-slate-300"
55
+ pre-class="bg-slate-950/80 text-[10px] text-slate-400"
56
+ />
57
+ </li>
58
+ </ol>
59
+ </details>
60
+ </template>
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ // Shared collapsible "Show detail" disclosure for a failure's extended `detail`, used by
3
+ // both the failure banner (`AgentFailureCard`) and the prior-errors history
4
+ // (`AgentFailureHistory`). Renders nothing when there is no detail or it merely repeats the
5
+ // message. Tone (summary/pre classes) is passed by the host so it blends into each surface
6
+ // (rose banner vs slate history) while the guard + the `showDetail` key + the whitespace-
7
+ // preserving `<pre>` structure live in one place.
8
+ defineProps<{
9
+ detail: string | null
10
+ message: string
11
+ summaryClass: string
12
+ preClass: string
13
+ }>()
14
+
15
+ const { t } = useI18n()
16
+ </script>
17
+
18
+ <template>
19
+ <details v-if="detail && detail !== message" class="mt-1">
20
+ <summary class="cursor-pointer" :class="summaryClass">
21
+ {{ t('board.failure.showDetail') }}
22
+ </summary>
23
+ <pre class="mt-1 max-h-32 overflow-auto whitespace-pre-wrap rounded p-1.5" :class="preClass">{{
24
+ detail
25
+ }}</pre>
26
+ </details>
27
+ </template>