@cat-factory/app 0.75.0 → 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.
- package/app/components/board/AgentFailureCard.vue +8 -9
- package/app/components/board/AgentFailureHistory.vue +60 -0
- package/app/components/board/FailureDetail.vue +27 -0
- package/app/components/panels/inspector/ServiceFragments.vue +7 -4
- package/app/components/panels/inspector/TaskExecution.vue +8 -0
- package/app/components/panels/inspector/TaskStructure.vue +10 -4
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +6 -5
- package/app/stores/agentRuns.ts +10 -0
- package/app/stores/fragmentLibrary.ts +4 -0
- package/app/stores/fragments.ts +30 -7
- package/app/stores/workspace.ts +5 -0
- package/i18n/locales/en.json +7 -1
- package/i18n/locales/es.json +4 -1
- package/i18n/locales/fr.json +4 -1
- package/i18n/locales/he.json +4 -1
- package/i18n/locales/ja.json +4 -1
- package/i18n/locales/pl.json +4 -1
- package/i18n/locales/tr.json +4 -1
- package/i18n/locales/uk.json +4 -1
- package/package.json +2 -2
|
@@ -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
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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>
|
|
@@ -4,7 +4,8 @@ import type { Block } from '~/types/domain'
|
|
|
4
4
|
// Service-level best-practice fragments (frame blocks). These are the programming
|
|
5
5
|
// standards/guidelines for the whole service; at run time their bodies are folded
|
|
6
6
|
// into the prompt of every `code-aware` agent on tasks under this service. Drawn from
|
|
7
|
-
// the
|
|
7
|
+
// the board's merged fragment catalog (built-in ∪ registered ∪ account ∪ workspace,
|
|
8
|
+
// via the fragments store; static pool when the library is off), grouped by category.
|
|
8
9
|
const props = defineProps<{ block: Block }>()
|
|
9
10
|
|
|
10
11
|
const board = useBoardStore()
|
|
@@ -17,10 +18,12 @@ onMounted(() => fragments.ensureLoaded())
|
|
|
17
18
|
|
|
18
19
|
type MenuItem = { label: string; icon?: string; onSelect: () => void }
|
|
19
20
|
|
|
21
|
+
// An id the catalog no longer resolves (removed/suppressed after selection) still
|
|
22
|
+
// renders — labelled by its raw id — so it stays visible and removable.
|
|
20
23
|
const selectedFragments = computed(() =>
|
|
21
|
-
(props.block.serviceFragmentIds ?? [])
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
(props.block.serviceFragmentIds ?? []).map(
|
|
25
|
+
(id) => fragments.getFragment(id) ?? { id, title: id, summary: '' },
|
|
26
|
+
),
|
|
24
27
|
)
|
|
25
28
|
|
|
26
29
|
// A trailing group that jumps from "attach a fragment" to authoring/editing the
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
containerPhaseLabel,
|
|
9
9
|
} from '~/utils/pipelineRender'
|
|
10
10
|
import AgentFailureCard from '~/components/board/AgentFailureCard.vue'
|
|
11
|
+
import AgentFailureHistory from '~/components/board/AgentFailureHistory.vue'
|
|
11
12
|
import EmptyState from '~/components/common/EmptyState.vue'
|
|
12
13
|
|
|
13
14
|
const props = defineProps<{ block: Block }>()
|
|
@@ -57,6 +58,10 @@ const failedRun = computed(() => {
|
|
|
57
58
|
return run && run.status === 'failed' ? run : null
|
|
58
59
|
})
|
|
59
60
|
|
|
61
|
+
// Failures from prior attempts, preserved across retries — shown regardless of the run's
|
|
62
|
+
// CURRENT status, so the error trail stays viewable after a restart clears the top banner.
|
|
63
|
+
const failureHistory = computed(() => agentRuns.byBlock[props.block.id]?.failureHistory ?? [])
|
|
64
|
+
|
|
60
65
|
const pr = computed(() => props.block.pullRequest)
|
|
61
66
|
/** A PR is merged once the block is `done`; otherwise it is open awaiting merge. */
|
|
62
67
|
const prMerged = computed(() => props.block.status === 'done')
|
|
@@ -413,6 +418,9 @@ async function mergePr() {
|
|
|
413
418
|
<!-- failed run: shared failure banner + retry -->
|
|
414
419
|
<AgentFailureCard v-if="failedRun" :run="failedRun" />
|
|
415
420
|
|
|
421
|
+
<!-- error trail of prior attempts (survives a retry/restart that cleared the banner) -->
|
|
422
|
+
<AgentFailureHistory :failures="failureHistory" />
|
|
423
|
+
|
|
416
424
|
<!-- Open PR: link straight to it on GitHub -->
|
|
417
425
|
<div v-if="pr" class="space-y-2">
|
|
418
426
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
@@ -9,14 +9,20 @@ const ui = useUiStore()
|
|
|
9
9
|
const accounts = useAccountsStore()
|
|
10
10
|
const { t } = useI18n()
|
|
11
11
|
|
|
12
|
+
// The catalog is per-board and invalidated on a workspace switch, so (re)load it when the
|
|
13
|
+
// task inspector mounts — mirrors ServiceFragments; ensureLoaded is a no-op while current.
|
|
14
|
+
onMounted(() => fragments.ensureLoaded())
|
|
15
|
+
|
|
12
16
|
type MenuItem = { label: string; icon?: string; onSelect: () => void }
|
|
13
17
|
|
|
14
18
|
// ---- best-practice prompt fragments ----------------------------------------
|
|
15
|
-
// Selected fragments
|
|
19
|
+
// Selected fragments, resolved against the catalog. An id the catalog no longer
|
|
20
|
+
// resolves (removed/suppressed after selection) still renders — labelled by its
|
|
21
|
+
// raw id — so it stays visible and removable.
|
|
16
22
|
const selectedFragments = computed(() =>
|
|
17
|
-
(props.block.fragmentIds ?? [])
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
(props.block.fragmentIds ?? []).map(
|
|
24
|
+
(id) => fragments.getFragment(id) ?? { id, title: id, summary: '' },
|
|
25
|
+
),
|
|
20
26
|
)
|
|
21
27
|
|
|
22
28
|
// A trailing group that jumps from "attach a fragment" to authoring/editing the
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
// Workspace settings: the default best-practice fragments NEW services inherit. The
|
|
3
|
-
// selection is drawn from the
|
|
4
|
-
//
|
|
3
|
+
// selection is drawn from the board's merged fragment catalog (built-in ∪ registered ∪
|
|
4
|
+
// account ∪ workspace via the fragments store; the static GET /prompt-fragments pool
|
|
5
|
+
// when the library is off). Changing it does not retroactively change existing
|
|
5
6
|
// services — each owns its selection from creation. Persisted via the
|
|
6
7
|
// serviceFragmentDefaults store (the backend replaces the whole list on each change).
|
|
7
8
|
import { onMounted, ref } from 'vue'
|
|
@@ -17,10 +18,10 @@ const busy = ref(false)
|
|
|
17
18
|
// The tab renders when Workspace settings opens; load the fragment pool then.
|
|
18
19
|
onMounted(() => void fragments.ensureLoaded())
|
|
19
20
|
|
|
21
|
+
// An id the catalog no longer resolves still renders (labelled by its raw id) so it
|
|
22
|
+
// stays visible and removable from the default set.
|
|
20
23
|
const selected = computed(() =>
|
|
21
|
-
defaults.fragmentIds
|
|
22
|
-
.map((id) => fragments.getFragment(id))
|
|
23
|
-
.filter((f): f is NonNullable<typeof f> => !!f),
|
|
24
|
+
defaults.fragmentIds.map((id) => fragments.getFragment(id) ?? { id, title: id, summary: '' }),
|
|
24
25
|
)
|
|
25
26
|
|
|
26
27
|
// Pool fragments not already in the default set, grouped by category.
|
package/app/stores/agentRuns.ts
CHANGED
|
@@ -26,6 +26,13 @@ export interface AgentRunSummary {
|
|
|
26
26
|
runId: string
|
|
27
27
|
/** Structured failure when `status` is `failed`; null otherwise. */
|
|
28
28
|
failure: AgentFailure | null
|
|
29
|
+
/**
|
|
30
|
+
* Failures from the run's PRIOR attempts, oldest→newest — the error trail preserved
|
|
31
|
+
* across retries/restarts. Stays populated after a restart (when `status` is no longer
|
|
32
|
+
* `failed` and the top banner is gone), so the "previous errors" history remains
|
|
33
|
+
* viewable. Empty for a bootstrap run or a run that never failed-then-retried.
|
|
34
|
+
*/
|
|
35
|
+
failureHistory: AgentFailure[]
|
|
29
36
|
/** Latest subtask counts for a live progress bar (null until reported). */
|
|
30
37
|
subtasks: StepSubtasks | null
|
|
31
38
|
}
|
|
@@ -138,6 +145,7 @@ export const useAgentRunsStore = defineStore('agentRuns', () => {
|
|
|
138
145
|
status: e.status,
|
|
139
146
|
runId: e.id,
|
|
140
147
|
failure: e.failure ?? null,
|
|
148
|
+
failureHistory: e.failureHistory ?? [],
|
|
141
149
|
subtasks: e.steps[e.currentStep]?.subtasks ?? null,
|
|
142
150
|
}
|
|
143
151
|
}
|
|
@@ -150,6 +158,8 @@ export const useAgentRunsStore = defineStore('agentRuns', () => {
|
|
|
150
158
|
status: job.status,
|
|
151
159
|
runId: job.id,
|
|
152
160
|
failure: job.failure,
|
|
161
|
+
// Bootstrap runs keep no prior-attempt trail (retry mints a fresh row).
|
|
162
|
+
failureHistory: [],
|
|
153
163
|
subtasks: job.subtasks,
|
|
154
164
|
}
|
|
155
165
|
}
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
UpdatePromptFragmentInput,
|
|
12
12
|
} from '~/types/domain'
|
|
13
13
|
import { useWorkspaceStore } from '~/stores/workspace'
|
|
14
|
+
import { useFragmentsStore } from '~/stores/fragments'
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Prompt-fragment library state (ADR 0006), scoped to a single owner — a board
|
|
@@ -83,6 +84,9 @@ function fragmentLibrarySetup(kind: FragmentOwnerKind, resolveOwnerId: () => str
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
async function refreshResolved() {
|
|
87
|
+
// Every library mutation lands here: drop the picker catalog's cache so the
|
|
88
|
+
// per-service / per-block pickers see the edit on their next open.
|
|
89
|
+
useFragmentsStore().invalidate()
|
|
86
90
|
if (!hasResolved) return
|
|
87
91
|
resolved.value = await api.getResolvedFragments(requireOwnerId())
|
|
88
92
|
}
|
package/app/stores/fragments.ts
CHANGED
|
@@ -1,24 +1,47 @@
|
|
|
1
1
|
import { defineStore } from 'pinia'
|
|
2
2
|
import { ref, computed } from 'vue'
|
|
3
3
|
import type { BlockType, PromptFragment } from '~/types/domain'
|
|
4
|
+
import { useWorkspaceStore } from '~/stores/workspace'
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* The best-practice prompt fragment catalog
|
|
7
|
-
* the
|
|
8
|
-
*
|
|
7
|
+
* The best-practice prompt fragment catalog backing the per-service and per-block
|
|
8
|
+
* pickers. When the fragment library is configured it loads the MERGED tenant
|
|
9
|
+
* catalog for the active board (`GET /workspaces/:id/prompt-fragments/resolved` —
|
|
10
|
+
* built-in ∪ account ∪ workspace, override-by-id, tombstones applied), so managed,
|
|
11
|
+
* repo-sourced and document-backed fragments are selectable exactly like the
|
|
12
|
+
* built-ins and a suppressed built-in disappears from the picker. When the library
|
|
13
|
+
* is off (the resolved endpoint 503s) it falls back to the workspace-independent
|
|
14
|
+
* static pool (`GET /prompt-fragments`). Cached per board; re-fetched on a board
|
|
15
|
+
* switch or after `invalidate()` (a library edit).
|
|
9
16
|
*/
|
|
10
17
|
export const useFragmentsStore = defineStore('fragments', () => {
|
|
11
18
|
const api = useApi()
|
|
12
19
|
const fragments = ref<PromptFragment[]>([])
|
|
13
20
|
const loaded = ref(false)
|
|
21
|
+
/** The board the catalog was loaded for (null = never; '' = static pool, no board). */
|
|
22
|
+
const loadedFor = ref<string | null>(null)
|
|
14
23
|
|
|
15
|
-
/** Fetch the catalog
|
|
24
|
+
/** Fetch the catalog for the active board; a no-op while it is current. */
|
|
16
25
|
async function ensureLoaded() {
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
const wsId = useWorkspaceStore().workspaceId ?? ''
|
|
27
|
+
if (loaded.value && loadedFor.value === wsId) return
|
|
28
|
+
// Prefer the merged tenant catalog; only a FAILURE (a 503 when the library is
|
|
29
|
+
// unconfigured, or any other error) degrades to the static universal pool — mapped to
|
|
30
|
+
// null by the catch. A successful-but-empty resolved catalog is left empty on purpose:
|
|
31
|
+
// it means every fragment is suppressed at some tier, and falling back to the static
|
|
32
|
+
// pool would resurrect the very built-ins the tenant tombstoned.
|
|
33
|
+
const resolved = wsId ? await api.getResolvedFragments(wsId).catch(() => null) : null
|
|
34
|
+
fragments.value = resolved ?? (await api.getPromptFragments())
|
|
35
|
+
loadedFor.value = wsId
|
|
19
36
|
loaded.value = true
|
|
20
37
|
}
|
|
21
38
|
|
|
39
|
+
/** Drop the cache so the next `ensureLoaded()` re-fetches (after a library edit). */
|
|
40
|
+
function invalidate() {
|
|
41
|
+
loaded.value = false
|
|
42
|
+
loadedFor.value = null
|
|
43
|
+
}
|
|
44
|
+
|
|
22
45
|
const byId = computed(() => {
|
|
23
46
|
const map = new Map<string, PromptFragment>()
|
|
24
47
|
for (const f of fragments.value) map.set(f.id, f)
|
|
@@ -36,5 +59,5 @@ export const useFragmentsStore = defineStore('fragments', () => {
|
|
|
36
59
|
)
|
|
37
60
|
}
|
|
38
61
|
|
|
39
|
-
return { fragments, loaded, ensureLoaded, byId, getFragment, forBlockType }
|
|
62
|
+
return { fragments, loaded, ensureLoaded, invalidate, byId, getFragment, forBlockType }
|
|
40
63
|
})
|
package/app/stores/workspace.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { useClarityStore } from '~/stores/clarity'
|
|
|
21
21
|
import { useBrainstormStore } from '~/stores/brainstorm'
|
|
22
22
|
import { useConsensusStore } from '~/stores/consensus'
|
|
23
23
|
import { useGitHubStore } from '~/stores/github'
|
|
24
|
+
import { useFragmentsStore } from '~/stores/fragments'
|
|
24
25
|
import { useProviderConnectionsStore } from '~/stores/providerConnections'
|
|
25
26
|
|
|
26
27
|
/**
|
|
@@ -81,6 +82,10 @@ export const useWorkspaceStore = defineStore(
|
|
|
81
82
|
useBrainstormStore().reset()
|
|
82
83
|
useConsensusStore().reset()
|
|
83
84
|
useGitHubStore().reset()
|
|
85
|
+
// The fragment picker catalog is per-board (the merged tenant catalog), so drop
|
|
86
|
+
// it too — the next inspector open re-fetches it for the switched-to board rather
|
|
87
|
+
// than showing the previous board's (or a raw-id placeholder for) fragments.
|
|
88
|
+
useFragmentsStore().invalidate()
|
|
84
89
|
}
|
|
85
90
|
workspaceId.value = snapshot.workspace.id
|
|
86
91
|
spend.value = snapshot.spend ?? null
|
package/i18n/locales/en.json
CHANGED
|
@@ -225,7 +225,13 @@
|
|
|
225
225
|
"retryBootstrap": "Retry bootstrap",
|
|
226
226
|
"retryRun": "Retry run",
|
|
227
227
|
"showDetail": "Show detail",
|
|
228
|
-
"retrying": "Retrying…"
|
|
228
|
+
"retrying": "Retrying…",
|
|
229
|
+
"history": {
|
|
230
|
+
"previousErrors": "{count} previous error | {count} previous errors",
|
|
231
|
+
"@previousErrors": {
|
|
232
|
+
"description": "Count-based tally of a run's earlier failed attempts, rendered as e.g. '3 previous errors' (count is always >= 1). Provide ALL plural forms your language needs (English has 2; Polish/Ukrainian need 3 - one/few/many - via the custom pluralRules in i18n.config.ts)."
|
|
233
|
+
}
|
|
234
|
+
}
|
|
229
235
|
},
|
|
230
236
|
"stop": {
|
|
231
237
|
"label": "Stop",
|
package/i18n/locales/es.json
CHANGED
|
@@ -204,7 +204,10 @@
|
|
|
204
204
|
"retryBootstrap": "Reintentar arranque",
|
|
205
205
|
"retryRun": "Reintentar ejecución",
|
|
206
206
|
"showDetail": "Mostrar detalle",
|
|
207
|
-
"retrying": "Reintentando…"
|
|
207
|
+
"retrying": "Reintentando…",
|
|
208
|
+
"history": {
|
|
209
|
+
"previousErrors": "{count} error anterior | {count} errores anteriores"
|
|
210
|
+
}
|
|
208
211
|
},
|
|
209
212
|
"stop": {
|
|
210
213
|
"label": "Detener",
|
package/i18n/locales/fr.json
CHANGED
|
@@ -204,7 +204,10 @@
|
|
|
204
204
|
"retryBootstrap": "Relancer l’initialisation",
|
|
205
205
|
"retryRun": "Relancer l’exécution",
|
|
206
206
|
"showDetail": "Afficher le détail",
|
|
207
|
-
"retrying": "Nouvelle tentative…"
|
|
207
|
+
"retrying": "Nouvelle tentative…",
|
|
208
|
+
"history": {
|
|
209
|
+
"previousErrors": "{count} erreur précédente | {count} erreurs précédentes"
|
|
210
|
+
}
|
|
208
211
|
},
|
|
209
212
|
"stop": {
|
|
210
213
|
"label": "Arrêter",
|
package/i18n/locales/he.json
CHANGED
|
@@ -204,7 +204,10 @@
|
|
|
204
204
|
"retryBootstrap": "נסה שוב לאתחל",
|
|
205
205
|
"retryRun": "נסה שוב להריץ",
|
|
206
206
|
"showDetail": "הצג פרטים",
|
|
207
|
-
"retrying": "מנסה שוב…"
|
|
207
|
+
"retrying": "מנסה שוב…",
|
|
208
|
+
"history": {
|
|
209
|
+
"previousErrors": "שגיאה קודמת {count} | {count} שגיאות קודמות"
|
|
210
|
+
}
|
|
208
211
|
},
|
|
209
212
|
"stop": {
|
|
210
213
|
"label": "עצור",
|
package/i18n/locales/ja.json
CHANGED
|
@@ -204,7 +204,10 @@
|
|
|
204
204
|
"retryBootstrap": "ブートストラップを再試行",
|
|
205
205
|
"retryRun": "実行を再試行",
|
|
206
206
|
"showDetail": "詳細を表示",
|
|
207
|
-
"retrying": "再試行中…"
|
|
207
|
+
"retrying": "再試行中…",
|
|
208
|
+
"history": {
|
|
209
|
+
"previousErrors": "以前のエラー {count} 件 | 以前のエラー {count} 件"
|
|
210
|
+
}
|
|
208
211
|
},
|
|
209
212
|
"stop": {
|
|
210
213
|
"label": "停止",
|
package/i18n/locales/pl.json
CHANGED
|
@@ -204,7 +204,10 @@
|
|
|
204
204
|
"retryBootstrap": "Ponów inicjalizację",
|
|
205
205
|
"retryRun": "Ponów uruchomienie",
|
|
206
206
|
"showDetail": "Pokaż szczegóły",
|
|
207
|
-
"retrying": "Ponawianie…"
|
|
207
|
+
"retrying": "Ponawianie…",
|
|
208
|
+
"history": {
|
|
209
|
+
"previousErrors": "{count} poprzedni błąd | {count} poprzednie błędy | {count} poprzednich błędów"
|
|
210
|
+
}
|
|
208
211
|
},
|
|
209
212
|
"stop": {
|
|
210
213
|
"label": "Zatrzymaj",
|
package/i18n/locales/tr.json
CHANGED
|
@@ -204,7 +204,10 @@
|
|
|
204
204
|
"retryBootstrap": "Bootstrap'ı yeniden dene",
|
|
205
205
|
"retryRun": "Çalıştırmayı yeniden dene",
|
|
206
206
|
"showDetail": "Ayrıntıyı göster",
|
|
207
|
-
"retrying": "Yeniden deneniyor…"
|
|
207
|
+
"retrying": "Yeniden deneniyor…",
|
|
208
|
+
"history": {
|
|
209
|
+
"previousErrors": "{count} önceki hata | {count} önceki hata"
|
|
210
|
+
}
|
|
208
211
|
},
|
|
209
212
|
"stop": {
|
|
210
213
|
"label": "Durdur",
|
package/i18n/locales/uk.json
CHANGED
|
@@ -204,7 +204,10 @@
|
|
|
204
204
|
"retryBootstrap": "Повторити ініціалізацію",
|
|
205
205
|
"retryRun": "Повторити запуск",
|
|
206
206
|
"showDetail": "Показати деталі",
|
|
207
|
-
"retrying": "Повторення…"
|
|
207
|
+
"retrying": "Повторення…",
|
|
208
|
+
"history": {
|
|
209
|
+
"previousErrors": "{count} попередня помилка | {count} попередні помилки | {count} попередніх помилок"
|
|
210
|
+
}
|
|
208
211
|
},
|
|
209
212
|
"stop": {
|
|
210
213
|
"label": "Зупинити",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.75.
|
|
3
|
+
"version": "0.75.2",
|
|
4
4
|
"description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"valibot": "^1.4.2",
|
|
35
35
|
"vue": "^3.5.39",
|
|
36
36
|
"wretch": "^3.0.9",
|
|
37
|
-
"@cat-factory/contracts": "0.81.
|
|
37
|
+
"@cat-factory/contracts": "0.81.3"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@toad-contracts/testing": "0.3.2",
|