@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.
- 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/fragments/FragmentLibraryManager.vue +410 -283
- package/app/components/github/GitHubRepoSearchSelect.vue +118 -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 +15 -4
- package/i18n/locales/es.json +12 -4
- package/i18n/locales/fr.json +12 -4
- package/i18n/locales/he.json +12 -4
- package/i18n/locales/ja.json +12 -4
- package/i18n/locales/pl.json +12 -4
- package/i18n/locales/tr.json +12 -4
- package/i18n/locales/uk.json +12 -4
- package/package.json +2 -2
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// A reusable server-side GitHub repository picker: the same searchable combobox the
|
|
3
|
+
// add-service modal uses, extracted so any window that needs to pick a repo the App
|
|
4
|
+
// can access gets identical behaviour (type ≥ MIN_SEARCH_LEN chars → the backend
|
|
5
|
+
// filters `owner/name`, nothing is prefetched). Exposes the selected repo's numeric
|
|
6
|
+
// id via `v-model`, and emits the full `GitHubAvailableRepo` (owner/name/flags) via
|
|
7
|
+
// `update:repo` for callers that need more than the id.
|
|
8
|
+
import { refDebounced } from '@vueuse/core'
|
|
9
|
+
import type { GitHubAvailableRepo } from '~/types/domain'
|
|
10
|
+
|
|
11
|
+
const props = defineProps<{
|
|
12
|
+
/** Selected repo GitHub numeric id, via v-model. */
|
|
13
|
+
modelValue?: number
|
|
14
|
+
}>()
|
|
15
|
+
const emit = defineEmits<{
|
|
16
|
+
'update:modelValue': [number | undefined]
|
|
17
|
+
'update:repo': [GitHubAvailableRepo | undefined]
|
|
18
|
+
}>()
|
|
19
|
+
|
|
20
|
+
const { t } = useI18n()
|
|
21
|
+
const github = useGitHubStore()
|
|
22
|
+
|
|
23
|
+
// A wide App install (or a PAT) can expose hundreds of repos — too many to prefetch and
|
|
24
|
+
// filter client-side — so the picker searches SERVER-SIDE once the user types at least
|
|
25
|
+
// MIN_SEARCH_LEN characters (debounced). Below the gate the list stays empty.
|
|
26
|
+
const MIN_SEARCH_LEN = 3
|
|
27
|
+
const repoSearch = ref('')
|
|
28
|
+
const repoSearchDebounced = refDebounced(repoSearch, 250)
|
|
29
|
+
const repoQueryRaw = computed(() => repoSearchDebounced.value.trim())
|
|
30
|
+
const belowMinChars = computed(() => repoQueryRaw.value.length < MIN_SEARCH_LEN)
|
|
31
|
+
|
|
32
|
+
// The picked repo, captured when selected — the loaded list is volatile (a later search
|
|
33
|
+
// replaces it), so the selection can't be derived from `availableRepos` after the fact.
|
|
34
|
+
const selectedRepo = ref<GitHubAvailableRepo | undefined>(undefined)
|
|
35
|
+
|
|
36
|
+
function toRepoItem(r: GitHubAvailableRepo) {
|
|
37
|
+
const suffix = r.private ? t('github.addService.repoLabel.private') : ''
|
|
38
|
+
return { label: `${r.owner}/${r.name}${suffix}`, value: r.githubId }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const repoItems = computed(() => github.availableRepos.map(toRepoItem))
|
|
42
|
+
const queryMatches = computed(() => (belowMinChars.value ? [] : repoItems.value))
|
|
43
|
+
|
|
44
|
+
// Items fed to the combobox: the matches plus the current selection kept present, so the
|
|
45
|
+
// menu still renders the selected repo's label after a later search replaces the list.
|
|
46
|
+
const repoMenuItems = computed(() => {
|
|
47
|
+
const matches = queryMatches.value
|
|
48
|
+
if (props.modelValue === undefined) return matches
|
|
49
|
+
if (matches.some((r) => r.value === props.modelValue)) return matches
|
|
50
|
+
return selectedRepo.value ? [toRepoItem(selectedRepo.value), ...matches] : matches
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
// Fetch matches server-side as the debounced query changes; below the gate clear the list.
|
|
54
|
+
watch(repoQueryRaw, (q) => {
|
|
55
|
+
void github.loadAvailableRepos(q.length >= MIN_SEARCH_LEN ? q : '')
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const selectedId = computed({
|
|
59
|
+
get: () => props.modelValue,
|
|
60
|
+
set: (v: number | undefined) => emit('update:modelValue', v),
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// On selection, capture the picked repo (from the still-current loaded list) and surface it.
|
|
64
|
+
watch(
|
|
65
|
+
() => props.modelValue,
|
|
66
|
+
(id) => {
|
|
67
|
+
if (id === undefined) {
|
|
68
|
+
selectedRepo.value = undefined
|
|
69
|
+
emit('update:repo', undefined)
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
const found = github.availableRepos.find((r) => r.githubId === id)
|
|
73
|
+
if (found) {
|
|
74
|
+
selectedRepo.value = found
|
|
75
|
+
emit('update:repo', found)
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
function clear() {
|
|
81
|
+
emit('update:modelValue', undefined)
|
|
82
|
+
emit('update:repo', undefined)
|
|
83
|
+
repoSearch.value = ''
|
|
84
|
+
}
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<template>
|
|
88
|
+
<UInputMenu
|
|
89
|
+
v-model="selectedId"
|
|
90
|
+
v-model:search-term="repoSearch"
|
|
91
|
+
:items="repoMenuItems"
|
|
92
|
+
:ignore-filter="true"
|
|
93
|
+
value-key="value"
|
|
94
|
+
:loading="github.loadingAvailable"
|
|
95
|
+
icon="i-lucide-search"
|
|
96
|
+
:placeholder="t('github.addService.searchPlaceholder')"
|
|
97
|
+
class="w-full"
|
|
98
|
+
>
|
|
99
|
+
<template v-if="selectedId !== undefined" #trailing>
|
|
100
|
+
<UButton
|
|
101
|
+
color="neutral"
|
|
102
|
+
variant="link"
|
|
103
|
+
size="sm"
|
|
104
|
+
icon="i-lucide-x"
|
|
105
|
+
:aria-label="t('github.addService.clearSelection')"
|
|
106
|
+
@click.stop="clear"
|
|
107
|
+
/>
|
|
108
|
+
</template>
|
|
109
|
+
<template #empty>
|
|
110
|
+
<span v-if="belowMinChars">
|
|
111
|
+
{{ t('github.addService.searchMinChars', { min: MIN_SEARCH_LEN }, MIN_SEARCH_LEN) }}
|
|
112
|
+
</span>
|
|
113
|
+
<span v-else-if="!github.loadingAvailable">
|
|
114
|
+
{{ t('github.addService.noMatches', { query: repoQueryRaw }) }}
|
|
115
|
+
</span>
|
|
116
|
+
</template>
|
|
117
|
+
</UInputMenu>
|
|
118
|
+
</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",
|
|
@@ -3717,7 +3723,8 @@
|
|
|
3717
3723
|
"connectFirst": "Connect a document source (Confluence, Notion or GitHub) under Integrations first.",
|
|
3718
3724
|
"refPlaceholder": "Page id or URL (e.g. a Confluence/Notion page or GitHub file URL)",
|
|
3719
3725
|
"tagsPlaceholder": "Tags, comma-separated (optional)",
|
|
3720
|
-
"link": "Link as living fragment"
|
|
3726
|
+
"link": "Link as living fragment",
|
|
3727
|
+
"githubBrowseHint": "Browse the repo and pick the file to link."
|
|
3721
3728
|
},
|
|
3722
3729
|
"sources": {
|
|
3723
3730
|
"metaSynced": "synced · ref {ref}",
|
|
@@ -3729,7 +3736,10 @@
|
|
|
3729
3736
|
"repoPlaceholder": "repo",
|
|
3730
3737
|
"dirPlaceholder": "dir path (e.g. guidelines)",
|
|
3731
3738
|
"refPlaceholder": "ref (default HEAD)",
|
|
3732
|
-
"link": "Link & sync"
|
|
3739
|
+
"link": "Link & sync",
|
|
3740
|
+
"browseHint": "Browse the repo and pick the directory of Markdown guidelines (or link the whole repo).",
|
|
3741
|
+
"selectedDir": "Directory:",
|
|
3742
|
+
"wholeRepo": "Whole repository (root)."
|
|
3733
3743
|
},
|
|
3734
3744
|
"toast": {
|
|
3735
3745
|
"added": "Fragment added",
|
|
@@ -3753,7 +3763,8 @@
|
|
|
3753
3763
|
"confirmRemove": {
|
|
3754
3764
|
"title": "Delete this fragment?",
|
|
3755
3765
|
"body": "\"{name}\" will be removed. This can't be undone."
|
|
3756
|
-
}
|
|
3766
|
+
},
|
|
3767
|
+
"unavailable": "The prompt-fragment library isn't enabled for this deployment."
|
|
3757
3768
|
},
|
|
3758
3769
|
"sandbox": {
|
|
3759
3770
|
"title": "Sandbox: prompt and model testing",
|
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",
|
|
@@ -3585,7 +3588,8 @@
|
|
|
3585
3588
|
"connectFirst": "Conecta primero una fuente de documentos (Confluence, Notion o GitHub) en Integraciones.",
|
|
3586
3589
|
"refPlaceholder": "Id o URL de página (p. ej., una página de Confluence/Notion o la URL de un archivo de GitHub)",
|
|
3587
3590
|
"tagsPlaceholder": "Etiquetas, separadas por comas (opcional)",
|
|
3588
|
-
"link": "Vincular como fragmento vivo"
|
|
3591
|
+
"link": "Vincular como fragmento vivo",
|
|
3592
|
+
"githubBrowseHint": "Explora el repositorio y elige el archivo a enlazar."
|
|
3589
3593
|
},
|
|
3590
3594
|
"sources": {
|
|
3591
3595
|
"metaSynced": "sincronizado · ref {ref}",
|
|
@@ -3597,7 +3601,10 @@
|
|
|
3597
3601
|
"repoPlaceholder": "repositorio",
|
|
3598
3602
|
"dirPlaceholder": "ruta del directorio (p. ej., guidelines)",
|
|
3599
3603
|
"refPlaceholder": "ref (HEAD por defecto)",
|
|
3600
|
-
"link": "Vincular y sincronizar"
|
|
3604
|
+
"link": "Vincular y sincronizar",
|
|
3605
|
+
"browseHint": "Explora el repositorio y elige el directorio de guías Markdown (o enlaza todo el repositorio).",
|
|
3606
|
+
"selectedDir": "Directorio:",
|
|
3607
|
+
"wholeRepo": "Repositorio completo (raíz)."
|
|
3601
3608
|
},
|
|
3602
3609
|
"toast": {
|
|
3603
3610
|
"added": "Fragmento añadido",
|
|
@@ -3621,7 +3628,8 @@
|
|
|
3621
3628
|
"confirmRemove": {
|
|
3622
3629
|
"title": "¿Eliminar este fragmento?",
|
|
3623
3630
|
"body": "Se eliminará \"{name}\". Esta acción no se puede deshacer."
|
|
3624
|
-
}
|
|
3631
|
+
},
|
|
3632
|
+
"unavailable": "La biblioteca de fragmentos de prompt no está habilitada en esta implementación."
|
|
3625
3633
|
},
|
|
3626
3634
|
"sandbox": {
|
|
3627
3635
|
"title": "Sandbox: pruebas de prompts y modelos",
|
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",
|
|
@@ -3585,7 +3588,8 @@
|
|
|
3585
3588
|
"connectFirst": "Connectez d'abord une source de documents (Confluence, Notion ou GitHub) dans Intégrations.",
|
|
3586
3589
|
"refPlaceholder": "Id ou URL de page (par ex. une page Confluence/Notion ou l'URL d'un fichier GitHub)",
|
|
3587
3590
|
"tagsPlaceholder": "Étiquettes, séparées par des virgules (facultatif)",
|
|
3588
|
-
"link": "Lier comme fragment vivant"
|
|
3591
|
+
"link": "Lier comme fragment vivant",
|
|
3592
|
+
"githubBrowseHint": "Parcourez le dépôt et choisissez le fichier à lier."
|
|
3589
3593
|
},
|
|
3590
3594
|
"sources": {
|
|
3591
3595
|
"metaSynced": "synchronisé · ref {ref}",
|
|
@@ -3597,7 +3601,10 @@
|
|
|
3597
3601
|
"repoPlaceholder": "dépôt",
|
|
3598
3602
|
"dirPlaceholder": "chemin du répertoire (par ex. guidelines)",
|
|
3599
3603
|
"refPlaceholder": "ref (HEAD par défaut)",
|
|
3600
|
-
"link": "Lier et synchroniser"
|
|
3604
|
+
"link": "Lier et synchroniser",
|
|
3605
|
+
"browseHint": "Parcourez le dépôt et choisissez le répertoire de consignes Markdown (ou liez tout le dépôt).",
|
|
3606
|
+
"selectedDir": "Répertoire :",
|
|
3607
|
+
"wholeRepo": "Dépôt entier (racine)."
|
|
3601
3608
|
},
|
|
3602
3609
|
"toast": {
|
|
3603
3610
|
"added": "Fragment ajouté",
|
|
@@ -3621,7 +3628,8 @@
|
|
|
3621
3628
|
"confirmRemove": {
|
|
3622
3629
|
"title": "Supprimer ce fragment ?",
|
|
3623
3630
|
"body": "\"{name}\" sera supprimé. Cette action est irréversible."
|
|
3624
|
-
}
|
|
3631
|
+
},
|
|
3632
|
+
"unavailable": "La bibliothèque de fragments de prompt n'est pas activée pour ce déploiement."
|
|
3625
3633
|
},
|
|
3626
3634
|
"sandbox": {
|
|
3627
3635
|
"title": "Bac à sable : test de prompts et de modèles",
|
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": "עצור",
|
|
@@ -3596,7 +3599,8 @@
|
|
|
3596
3599
|
"connectFirst": "חבר תחילה מקור מסמכים (Confluence, Notion או GitHub) תחת אינטגרציות.",
|
|
3597
3600
|
"refPlaceholder": "מזהה עמוד או כתובת (למשל עמוד Confluence/Notion או כתובת קובץ GitHub)",
|
|
3598
3601
|
"tagsPlaceholder": "תגיות, מופרדות בפסיקים (אופציונלי)",
|
|
3599
|
-
"link": "קשר כמקטע חי"
|
|
3602
|
+
"link": "קשר כמקטע חי",
|
|
3603
|
+
"githubBrowseHint": "עיין במאגר ובחר את הקובץ לקישור."
|
|
3600
3604
|
},
|
|
3601
3605
|
"sources": {
|
|
3602
3606
|
"metaSynced": "סונכרן · ref {ref}",
|
|
@@ -3608,7 +3612,10 @@
|
|
|
3608
3612
|
"repoPlaceholder": "מאגר",
|
|
3609
3613
|
"dirPlaceholder": "נתיב תיקייה (למשל guidelines)",
|
|
3610
3614
|
"refPlaceholder": "ref (ברירת מחדל HEAD)",
|
|
3611
|
-
"link": "קשר וסנכרן"
|
|
3615
|
+
"link": "קשר וסנכרן",
|
|
3616
|
+
"browseHint": "עיין במאגר ובחר את תיקיית הנחיות ה-Markdown (או קשר את המאגר כולו).",
|
|
3617
|
+
"selectedDir": "תיקייה:",
|
|
3618
|
+
"wholeRepo": "המאגר כולו (השורש)."
|
|
3612
3619
|
},
|
|
3613
3620
|
"toast": {
|
|
3614
3621
|
"added": "המקטע נוסף",
|
|
@@ -3632,7 +3639,8 @@
|
|
|
3632
3639
|
"confirmRemove": {
|
|
3633
3640
|
"title": "למחוק את המקטע הזה?",
|
|
3634
3641
|
"body": "\"{name}\" יימחק. לא ניתן לבטל פעולה זו."
|
|
3635
|
-
}
|
|
3642
|
+
},
|
|
3643
|
+
"unavailable": "ספריית מקטעי הפרומפט אינה מופעלת בפריסה זו."
|
|
3636
3644
|
},
|
|
3637
3645
|
"sandbox": {
|
|
3638
3646
|
"title": "Sandbox: בדיקת פרומפטים ומודלים",
|
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": "停止",
|
|
@@ -3598,7 +3601,8 @@
|
|
|
3598
3601
|
"connectFirst": "まず Integrations でドキュメントソース (Confluence、Notion または GitHub) を接続してください。",
|
|
3599
3602
|
"refPlaceholder": "ページ id または URL (例: Confluence/Notion ページや GitHub ファイル URL)",
|
|
3600
3603
|
"tagsPlaceholder": "タグ、カンマ区切り (任意)",
|
|
3601
|
-
"link": "リビングフラグメントとしてリンク"
|
|
3604
|
+
"link": "リビングフラグメントとしてリンク",
|
|
3605
|
+
"githubBrowseHint": "リポジトリを参照してリンクするファイルを選択します。"
|
|
3602
3606
|
},
|
|
3603
3607
|
"sources": {
|
|
3604
3608
|
"metaSynced": "同期済み · ref {ref}",
|
|
@@ -3610,7 +3614,10 @@
|
|
|
3610
3614
|
"repoPlaceholder": "repo",
|
|
3611
3615
|
"dirPlaceholder": "ディレクトリパス (例: guidelines)",
|
|
3612
3616
|
"refPlaceholder": "ref (デフォルト HEAD)",
|
|
3613
|
-
"link": "リンクして同期"
|
|
3617
|
+
"link": "リンクして同期",
|
|
3618
|
+
"browseHint": "リポジトリを参照して Markdown ガイドラインのディレクトリを選択します(またはリポジトリ全体をリンク)。",
|
|
3619
|
+
"selectedDir": "ディレクトリ:",
|
|
3620
|
+
"wholeRepo": "リポジトリ全体(ルート)。"
|
|
3614
3621
|
},
|
|
3615
3622
|
"toast": {
|
|
3616
3623
|
"added": "フラグメントを追加しました",
|
|
@@ -3634,7 +3641,8 @@
|
|
|
3634
3641
|
"confirmRemove": {
|
|
3635
3642
|
"title": "このフラグメントを削除しますか?",
|
|
3636
3643
|
"body": "「{name}」が削除されます。 この操作は取り消せません。"
|
|
3637
|
-
}
|
|
3644
|
+
},
|
|
3645
|
+
"unavailable": "このデプロイではプロンプトフラグメントライブラリが有効になっていません。"
|
|
3638
3646
|
},
|
|
3639
3647
|
"sandbox": {
|
|
3640
3648
|
"title": "Sandbox: プロンプトとモデルのテスト",
|
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",
|
|
@@ -3585,7 +3588,8 @@
|
|
|
3585
3588
|
"connectFirst": "Najpierw połącz źródło dokumentów (Confluence, Notion lub GitHub) w sekcji Integracje.",
|
|
3586
3589
|
"refPlaceholder": "Id lub URL strony (np. strona Confluence/Notion lub URL pliku GitHub)",
|
|
3587
3590
|
"tagsPlaceholder": "Tagi, oddzielone przecinkami (opcjonalnie)",
|
|
3588
|
-
"link": "Połącz jako żywy fragment"
|
|
3591
|
+
"link": "Połącz jako żywy fragment",
|
|
3592
|
+
"githubBrowseHint": "Przeglądaj repozytorium i wybierz plik do połączenia."
|
|
3589
3593
|
},
|
|
3590
3594
|
"sources": {
|
|
3591
3595
|
"metaSynced": "zsynchronizowano · ref {ref}",
|
|
@@ -3597,7 +3601,10 @@
|
|
|
3597
3601
|
"repoPlaceholder": "repozytorium",
|
|
3598
3602
|
"dirPlaceholder": "ścieżka katalogu (np. guidelines)",
|
|
3599
3603
|
"refPlaceholder": "ref (domyślnie HEAD)",
|
|
3600
|
-
"link": "Połącz i synchronizuj"
|
|
3604
|
+
"link": "Połącz i synchronizuj",
|
|
3605
|
+
"browseHint": "Przeglądaj repozytorium i wybierz katalog wytycznych Markdown (lub połącz całe repozytorium).",
|
|
3606
|
+
"selectedDir": "Katalog:",
|
|
3607
|
+
"wholeRepo": "Całe repozytorium (katalog główny)."
|
|
3601
3608
|
},
|
|
3602
3609
|
"toast": {
|
|
3603
3610
|
"added": "Dodano fragment",
|
|
@@ -3621,7 +3628,8 @@
|
|
|
3621
3628
|
"confirmRemove": {
|
|
3622
3629
|
"title": "Usunąć ten fragment?",
|
|
3623
3630
|
"body": "\"{name}\" zostanie usunięty. Tej operacji nie można cofnąć."
|
|
3624
|
-
}
|
|
3631
|
+
},
|
|
3632
|
+
"unavailable": "Biblioteka fragmentów promptów nie jest włączona w tym wdrożeniu."
|
|
3625
3633
|
},
|
|
3626
3634
|
"sandbox": {
|
|
3627
3635
|
"title": "Piaskownica: testowanie promptów i modeli",
|