@cat-factory/app 0.123.1 → 0.125.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/app/components/layout/AccountSkillSettings.vue +21 -0
- package/app/components/panels/OperatorDashboardPanel.vue +41 -4
- package/app/components/pipeline/PipelineBuilder.vue +48 -0
- package/app/components/settings/AccountSettingsPanel.vue +15 -0
- package/app/components/skills/SkillLibraryManager.vue +337 -0
- package/app/composables/api/context.ts +2 -0
- package/app/composables/api/skills.ts +48 -0
- package/app/composables/useApi.ts +4 -1
- package/app/stores/pipelines.ts +19 -0
- package/app/stores/skillLibrary.ts +153 -0
- package/app/stores/skills.spec.ts +60 -0
- package/app/stores/skills.ts +22 -0
- package/app/stores/workspace.ts +4 -0
- package/app/types/domain.ts +1 -0
- package/app/types/skills.ts +18 -0
- package/i18n/locales/de.json +58 -2
- package/i18n/locales/en.json +58 -2
- package/i18n/locales/es.json +58 -2
- package/i18n/locales/fr.json +58 -2
- package/i18n/locales/he.json +58 -2
- package/i18n/locales/it.json +58 -2
- package/i18n/locales/ja.json +58 -2
- package/i18n/locales/pl.json +58 -2
- package/i18n/locales/tr.json +58 -2
- package/i18n/locales/uk.json +58 -2
- package/package.json +2 -2
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import type {
|
|
4
|
+
AccountSkill,
|
|
5
|
+
LinkSkillSourceInput,
|
|
6
|
+
SkillSource,
|
|
7
|
+
SkillSyncResult,
|
|
8
|
+
} from '~/types/domain'
|
|
9
|
+
import { useSingleFlightProbe } from '~/composables/useSingleFlightProbe'
|
|
10
|
+
import { useSkillsStore } from '~/stores/skills'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The repo-sourced Claude Skills library for one account (docs/initiatives/repo-skills.md),
|
|
14
|
+
* used by the account-settings management surface. Holds the account's synced skill catalog
|
|
15
|
+
* (full detail) and its linked repo sources, and drives link / sync / status / unlink. Skills
|
|
16
|
+
* are a single account tier (no workspace tier), so — unlike the fragment library — there is no
|
|
17
|
+
* owner-kind axis; the store is keyed purely by account id.
|
|
18
|
+
*
|
|
19
|
+
* `available` mirrors the backend's opt-in gate: a 503 from the catalog probe means the feature
|
|
20
|
+
* is off and the UI hides its panel. `sourcesAvailable` is the finer gate — the catalog read
|
|
21
|
+
* works, but linking/syncing repo sources needs the GitHub integration, whose absence 503s only
|
|
22
|
+
* the `skill-sources/*` routes.
|
|
23
|
+
*
|
|
24
|
+
* After any mutation that changes the catalog, the updated summaries are pushed into the
|
|
25
|
+
* snapshot-hydrated {@link useSkillsStore} so the pipeline builder's picker reflects the change
|
|
26
|
+
* immediately, without a full board refresh.
|
|
27
|
+
*/
|
|
28
|
+
function skillLibrarySetup(resolveAccountId: () => string | null) {
|
|
29
|
+
const api = useApi()
|
|
30
|
+
|
|
31
|
+
/** null = not probed yet; true/false = library on/off (the catalog read). */
|
|
32
|
+
const available = ref<boolean | null>(null)
|
|
33
|
+
/** false when the GitHub integration is off (catalog works; source linking/syncing does not). */
|
|
34
|
+
const sourcesAvailable = ref(true)
|
|
35
|
+
/** The account's synced skills (full detail — instructions + resource manifest). */
|
|
36
|
+
const catalog = ref<AccountSkill[]>([])
|
|
37
|
+
/** Linked repo sources of skill folders. */
|
|
38
|
+
const sources = ref<SkillSource[]>([])
|
|
39
|
+
/** Per-source "changes available" flag from the last status check. */
|
|
40
|
+
const sourceChanges = ref<Record<string, boolean>>({})
|
|
41
|
+
const loading = ref(false)
|
|
42
|
+
|
|
43
|
+
function requireAccountId(): string {
|
|
44
|
+
const id = resolveAccountId()
|
|
45
|
+
if (!id) throw new Error('No skill-library account')
|
|
46
|
+
return id
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Mirror the full catalog into the snapshot picker store as lightweight summaries. */
|
|
50
|
+
function syncPicker() {
|
|
51
|
+
useSkillsStore().hydrate(
|
|
52
|
+
catalog.value.map((s) => ({ id: s.id, name: s.name, description: s.description })),
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Probe the feature + load this account's catalog and sources. */
|
|
57
|
+
async function runProbe() {
|
|
58
|
+
const id = resolveAccountId()
|
|
59
|
+
if (!id) return
|
|
60
|
+
try {
|
|
61
|
+
catalog.value = await api.listAccountSkills(id)
|
|
62
|
+
available.value = true
|
|
63
|
+
syncPicker()
|
|
64
|
+
} catch {
|
|
65
|
+
available.value = false
|
|
66
|
+
catalog.value = []
|
|
67
|
+
sources.value = []
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
// Sources need the GitHub integration; a 503 here just hides the linking UI (the catalog
|
|
71
|
+
// read above already succeeded, so the feature itself is on).
|
|
72
|
+
try {
|
|
73
|
+
sources.value = await api.listSkillSources(id)
|
|
74
|
+
sourcesAvailable.value = true
|
|
75
|
+
} catch {
|
|
76
|
+
sources.value = []
|
|
77
|
+
sourcesAvailable.value = false
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Single-flight the probe keyed on the account id, so the panel-open fan-out loads once.
|
|
81
|
+
const { probe, ensureProbed } = useSingleFlightProbe(runProbe, () => resolveAccountId())
|
|
82
|
+
|
|
83
|
+
async function reloadCatalog() {
|
|
84
|
+
catalog.value = await api.listAccountSkills(requireAccountId())
|
|
85
|
+
syncPicker()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function reloadSources() {
|
|
89
|
+
sources.value = await api.listSkillSources(requireAccountId())
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function linkSource(input: LinkSkillSourceInput): Promise<SkillSource> {
|
|
93
|
+
const source = await api.linkSkillSource(requireAccountId(), input)
|
|
94
|
+
sources.value = [source, ...sources.value]
|
|
95
|
+
// Auto-sync the freshly-linked source so its skills land in the catalog immediately.
|
|
96
|
+
await syncSourceRaw(source.id)
|
|
97
|
+
return source
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function unlinkSource(sourceId: string) {
|
|
101
|
+
await api.unlinkSkillSource(requireAccountId(), sourceId)
|
|
102
|
+
sources.value = sources.value.filter((s) => s.id !== sourceId)
|
|
103
|
+
delete sourceChanges.value[sourceId]
|
|
104
|
+
await reloadCatalog()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** The bare sync used both by the row action and the auto-sync after link. */
|
|
108
|
+
async function syncSourceRaw(sourceId: string): Promise<SkillSyncResult> {
|
|
109
|
+
const result = await api.syncSkillSource(requireAccountId(), sourceId)
|
|
110
|
+
delete sourceChanges.value[sourceId]
|
|
111
|
+
await Promise.all([reloadSources(), reloadCatalog()])
|
|
112
|
+
return result
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function syncSource(sourceId: string): Promise<SkillSyncResult> {
|
|
116
|
+
loading.value = true
|
|
117
|
+
try {
|
|
118
|
+
return await syncSourceRaw(sourceId)
|
|
119
|
+
} finally {
|
|
120
|
+
loading.value = false
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Lightweight commit-version "check for changes" for a source; caches the flag. */
|
|
125
|
+
async function checkSource(sourceId: string) {
|
|
126
|
+
const status = await api.skillSourceStatus(requireAccountId(), sourceId)
|
|
127
|
+
sourceChanges.value = { ...sourceChanges.value, [sourceId]: status.changed }
|
|
128
|
+
return status
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
available,
|
|
133
|
+
sourcesAvailable,
|
|
134
|
+
catalog,
|
|
135
|
+
sources,
|
|
136
|
+
sourceChanges,
|
|
137
|
+
loading,
|
|
138
|
+
probe,
|
|
139
|
+
ensureProbed,
|
|
140
|
+
linkSource,
|
|
141
|
+
unlinkSource,
|
|
142
|
+
syncSource,
|
|
143
|
+
checkSource,
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* An account-keyed skill-library store (one isolated instance per account), used by the
|
|
149
|
+
* account-settings Skills tab.
|
|
150
|
+
*/
|
|
151
|
+
export function useSkillLibrary(accountId: string) {
|
|
152
|
+
return defineStore(`skillLibrary:${accountId}`, () => skillLibrarySetup(() => accountId))()
|
|
153
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { useSkillsStore } from '~/stores/skills'
|
|
3
|
+
import { usePipelinesStore } from '~/stores/pipelines'
|
|
4
|
+
import type { SkillSummary } from '~/types/domain'
|
|
5
|
+
|
|
6
|
+
const summary = (id: string, name = id): SkillSummary => ({ id, name, description: `${name} desc` })
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The skill picker spans two stores: the snapshot-hydrated `useSkillsStore` (the catalog the
|
|
10
|
+
* builder's `USelect` binds against) and the per-step `skillId` helpers on `usePipelinesStore`.
|
|
11
|
+
* These pin the behaviours the builder relies on (docs/initiatives/repo-skills.md slice 3).
|
|
12
|
+
*/
|
|
13
|
+
describe('skills picker store — snapshot-hydrated catalog', () => {
|
|
14
|
+
it('hydrate is a straight replace (a later hydrate does not merge with the earlier one)', () => {
|
|
15
|
+
const skills = useSkillsStore()
|
|
16
|
+
expect(skills.catalog).toEqual([])
|
|
17
|
+
|
|
18
|
+
skills.hydrate([summary('sk_a'), summary('sk_b')])
|
|
19
|
+
expect(skills.catalog.map((s) => s.id)).toEqual(['sk_a', 'sk_b'])
|
|
20
|
+
|
|
21
|
+
// A resync (or a board switch) replaces the whole list — no stale ids linger.
|
|
22
|
+
skills.hydrate([summary('sk_c')])
|
|
23
|
+
expect(skills.catalog.map((s) => s.id)).toEqual(['sk_c'])
|
|
24
|
+
|
|
25
|
+
// An empty hydrate (feature off / account with no skills) clears it.
|
|
26
|
+
skills.hydrate([])
|
|
27
|
+
expect(skills.catalog).toEqual([])
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
describe('pipelines store — per-step skill picker helpers', () => {
|
|
32
|
+
it('sets, reads and clears a draft skill step’s skillId', () => {
|
|
33
|
+
const pipelines = usePipelinesStore()
|
|
34
|
+
pipelines.addToDraft('skill')
|
|
35
|
+
expect(pipelines.draftSkillId(0)).toBeUndefined()
|
|
36
|
+
|
|
37
|
+
pipelines.setDraftSkillId(0, 'sk_1')
|
|
38
|
+
expect(pipelines.draftSkillId(0)).toBe('sk_1')
|
|
39
|
+
expect(pipelines.draftStepOptions[0]).toEqual({ skillId: 'sk_1' })
|
|
40
|
+
|
|
41
|
+
// Clearing drops the field and, with the bag now empty, normalizes the entry back to null.
|
|
42
|
+
pipelines.setDraftSkillId(0, undefined)
|
|
43
|
+
expect(pipelines.draftSkillId(0)).toBeUndefined()
|
|
44
|
+
expect(pipelines.draftStepOptions[0]).toBeNull()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('merges into the options bag rather than clobbering other per-step options', () => {
|
|
48
|
+
const pipelines = usePipelinesStore()
|
|
49
|
+
pipelines.addToDraft('skill')
|
|
50
|
+
// Seed a co-existing option (as a requirements-review opt-out would).
|
|
51
|
+
pipelines.draftStepOptions[0] = { autoRecommend: false }
|
|
52
|
+
|
|
53
|
+
pipelines.setDraftSkillId(0, 'sk_1')
|
|
54
|
+
expect(pipelines.draftStepOptions[0]).toEqual({ autoRecommend: false, skillId: 'sk_1' })
|
|
55
|
+
|
|
56
|
+
// Clearing only the skill leaves the other option (bag not empty ⇒ entry survives).
|
|
57
|
+
pipelines.setDraftSkillId(0, undefined)
|
|
58
|
+
expect(pipelines.draftStepOptions[0]).toEqual({ autoRecommend: false })
|
|
59
|
+
})
|
|
60
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import type { SkillSummary } from '~/types/domain'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The account's repo-sourced Claude Skills catalog (docs/initiatives/repo-skills.md slice 3),
|
|
7
|
+
* hydrated from the workspace snapshot as lightweight `{ id, name, description }` summaries.
|
|
8
|
+
* Drives the pipeline builder's per-step skill picker: a `skill` step binds its
|
|
9
|
+
* `stepOptions.skillId` to one of these. Skills live in ONE tier (the account, shared across its
|
|
10
|
+
* workspaces), so a snapshot hydrate is a straight replace — no per-board reset needed. The
|
|
11
|
+
* account-settings management surface owns the full catalog + sources; it pushes its updated
|
|
12
|
+
* summaries back here after a sync so the picker stays in step without a board reload.
|
|
13
|
+
*/
|
|
14
|
+
export const useSkillsStore = defineStore('skills', () => {
|
|
15
|
+
const catalog = ref<SkillSummary[]>([])
|
|
16
|
+
|
|
17
|
+
function hydrate(list: SkillSummary[]) {
|
|
18
|
+
catalog.value = list
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return { catalog, hydrate }
|
|
22
|
+
})
|
package/app/stores/workspace.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { useRecurringPipelinesStore } from '~/stores/recurringPipelines'
|
|
|
24
24
|
import { useInitiativesStore } from '~/stores/initiative'
|
|
25
25
|
import { useServicesStore } from '~/stores/services'
|
|
26
26
|
import { useAgentsStore } from '~/stores/agents'
|
|
27
|
+
import { useSkillsStore } from '~/stores/skills'
|
|
27
28
|
import { useTrackerStore } from '~/stores/tracker'
|
|
28
29
|
import { useRequirementsStore } from '~/stores/requirements'
|
|
29
30
|
import { useClarityStore } from '~/stores/clarity'
|
|
@@ -151,6 +152,9 @@ export const useWorkspaceStore = defineStore(
|
|
|
151
152
|
// Merge the deployment's registered custom agent kinds into the palette catalog so a
|
|
152
153
|
// proprietary kind renders as a first-class block + result view (idempotent on reload).
|
|
153
154
|
useAgentsStore().registerCustomKinds(snapshot.customAgentKinds ?? [])
|
|
155
|
+
// The account's repo-sourced Claude Skills catalog (shared across its workspaces), so the
|
|
156
|
+
// pipeline builder's per-step skill picker has its options. A straight replace.
|
|
157
|
+
useSkillsStore().hydrate(snapshot.skills ?? [])
|
|
154
158
|
// Seed the connect form's backend-kind selectors (built-in + any custom backend a
|
|
155
159
|
// deployment registered), so a programmatically-registered env/runner backend is a
|
|
156
160
|
// first-class connect option instead of a hardcoded manifest/kubernetes list.
|
package/app/types/domain.ts
CHANGED
|
@@ -133,6 +133,7 @@ export interface AuthUser {
|
|
|
133
133
|
export type * from './execution'
|
|
134
134
|
export type * from './models'
|
|
135
135
|
export type * from './fragments'
|
|
136
|
+
export type * from './skills'
|
|
136
137
|
export type * from './documents'
|
|
137
138
|
export type * from './tasks'
|
|
138
139
|
export type * from './bootstrap'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Repo-sourced Claude Skills library (docs/initiatives/repo-skills.md). Mirrors
|
|
3
|
+
// the `@cat-factory/contracts` skill-library schemas: the account skill catalog
|
|
4
|
+
// (shared across the account's workspaces), the repo sources that feed it, and the
|
|
5
|
+
// lightweight per-skill summary carried in the workspace snapshot for the picker.
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
//
|
|
8
|
+
// All wire shapes are sourced from @cat-factory/contracts (single source of truth).
|
|
9
|
+
|
|
10
|
+
export type {
|
|
11
|
+
SkillResource,
|
|
12
|
+
AccountSkill,
|
|
13
|
+
SkillSource,
|
|
14
|
+
SkillSummary,
|
|
15
|
+
LinkSkillSourceInput,
|
|
16
|
+
SkillSyncResult,
|
|
17
|
+
SkillSourceStatus,
|
|
18
|
+
} from '@cat-factory/contracts'
|
package/i18n/locales/de.json
CHANGED
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
"noAccount": "Kein Konto ausgewählt.",
|
|
51
51
|
"tabs": {
|
|
52
52
|
"team": "Team & Zugriff",
|
|
53
|
-
"fragments": "Kontextfragmente"
|
|
53
|
+
"fragments": "Kontextfragmente",
|
|
54
|
+
"skills": "Skills"
|
|
54
55
|
}
|
|
55
56
|
},
|
|
56
57
|
"infrastructure": {
|
|
@@ -1963,6 +1964,9 @@
|
|
|
1963
1964
|
"label": "Vorlagen & Beispiele"
|
|
1964
1965
|
}
|
|
1965
1966
|
}
|
|
1967
|
+
},
|
|
1968
|
+
"accountSkills": {
|
|
1969
|
+
"intro": "Verknüpfe Repositorys, in denen dein Team Claude Skills erstellt (ein SKILL.md-Ordner plus Ressourcendateien). Synchronisierte Skills landen im Katalog dieses Kontos, der von allen Boards geteilt wird, und der Skill-Schritt einer Pipeline führt einen davon für eine Aufgabe aus."
|
|
1966
1970
|
}
|
|
1967
1971
|
},
|
|
1968
1972
|
"board": {
|
|
@@ -2797,6 +2801,9 @@
|
|
|
2797
2801
|
"avg": "Durchschnitt",
|
|
2798
2802
|
"min": "Min.",
|
|
2799
2803
|
"max": "Max.",
|
|
2804
|
+
"p50": "p50",
|
|
2805
|
+
"p90": "p90",
|
|
2806
|
+
"p99": "p99",
|
|
2800
2807
|
"empty": "Keine abgeschlossenen Läufe in diesem Zeitraum."
|
|
2801
2808
|
},
|
|
2802
2809
|
"live": {
|
|
@@ -3117,7 +3124,11 @@
|
|
|
3117
3124
|
"cloned": "\"{name}\" geklont — bearbeite jetzt \"{copy}\"",
|
|
3118
3125
|
"cloneFailed": "Pipeline konnte nicht geklont werden",
|
|
3119
3126
|
"updateFailed": "Pipeline konnte nicht aktualisiert werden"
|
|
3120
|
-
}
|
|
3127
|
+
},
|
|
3128
|
+
"skillPlaceholder": "Skill auswählen",
|
|
3129
|
+
"skillNoneAvailable": "Keine Skills verfügbar. Verknüpfe eine Skill-Quelle in den Kontoeinstellungen.",
|
|
3130
|
+
"skillMissing": "Dieser Skill ist nicht mehr im Katalog; wähle einen anderen.",
|
|
3131
|
+
"skillNeedsPick": "Ein Skill-Schritt braucht einen ausgewählten Skill, bevor du speichern kannst."
|
|
3121
3132
|
},
|
|
3122
3133
|
"progress": {
|
|
3123
3134
|
"status": {
|
|
@@ -4881,5 +4892,50 @@
|
|
|
4881
4892
|
"count": "{attempts} von {max}",
|
|
4882
4893
|
"footer": "Die Schleife wird wiederholt, bis der Validierungsbefehl erfolgreich ist oder das Iterationsbudget aufgebraucht ist."
|
|
4883
4894
|
}
|
|
4895
|
+
},
|
|
4896
|
+
"skills": {
|
|
4897
|
+
"unavailable": "Die Claude-Skills-Bibliothek ist für diese Bereitstellung nicht aktiviert.",
|
|
4898
|
+
"catalog": {
|
|
4899
|
+
"title": "Synchronisierte Skills",
|
|
4900
|
+
"empty": "Noch keine Skills synchronisiert. Verknüpfe unten eine Repo-Quelle, um ihre Skill-Ordner zu importieren.",
|
|
4901
|
+
"resources": "{count} Ressourcen",
|
|
4902
|
+
"pinned": "fixiert auf {commit}"
|
|
4903
|
+
},
|
|
4904
|
+
"sources": {
|
|
4905
|
+
"title": "Repo-Quellen",
|
|
4906
|
+
"empty": "Keine verknüpften Skill-Quellen. Verknüpfe unten ein Repo-Verzeichnis mit Skill-Ordnern.",
|
|
4907
|
+
"linkTitle": "Skill-Quelle verknüpfen",
|
|
4908
|
+
"link": "Verknüpfen & synchronisieren",
|
|
4909
|
+
"metaSynced": "synchronisiert {date} · Ref {ref}",
|
|
4910
|
+
"metaNever": "nie synchronisiert · Ref {ref}",
|
|
4911
|
+
"changes": "Änderungen",
|
|
4912
|
+
"check": "Auf Änderungen prüfen",
|
|
4913
|
+
"sync": "Neu synchronisieren",
|
|
4914
|
+
"unlink": "Trennen",
|
|
4915
|
+
"browseHint": "Durchsuche das Repository und wähle das Verzeichnis mit den Skill-Ordnern (oder verknüpfe das ganze Repo).",
|
|
4916
|
+
"selectedDir": "Verzeichnis:",
|
|
4917
|
+
"wholeRepo": "Gesamtes Repository (Wurzel).",
|
|
4918
|
+
"ownerPlaceholder": "Eigentümer",
|
|
4919
|
+
"repoPlaceholder": "Repo",
|
|
4920
|
+
"dirPlaceholder": "Verzeichnispfad (z. B. .claude/skills)",
|
|
4921
|
+
"refPlaceholder": "Ref (Standard HEAD)",
|
|
4922
|
+
"githubRequired": "Zum Verknüpfen einer Skill-Quelle ist die GitHub-Integration erforderlich. Verbinde sie zuerst auf einem Board."
|
|
4923
|
+
},
|
|
4924
|
+
"confirmUnlinkSource": {
|
|
4925
|
+
"title": "Diese Quelle trennen?",
|
|
4926
|
+
"body": "\"{repo}\" und die davon synchronisierten Skills werden entfernt. Du kannst sie später erneut verknüpfen.",
|
|
4927
|
+
"confirm": "Trennen"
|
|
4928
|
+
},
|
|
4929
|
+
"toast": {
|
|
4930
|
+
"sourceLinked": "Quelle verknüpft & synchronisiert",
|
|
4931
|
+
"linkSourceFailed": "Quelle konnte nicht verknüpft werden",
|
|
4932
|
+
"synced": "Synchronisiert: {updated} aktualisiert, {removed} entfernt",
|
|
4933
|
+
"syncFailed": "Quelle konnte nicht synchronisiert werden",
|
|
4934
|
+
"changesAvailable": "Änderungen verfügbar",
|
|
4935
|
+
"upToDate": "Aktuell",
|
|
4936
|
+
"checkSourceFailed": "Quelle konnte nicht geprüft werden",
|
|
4937
|
+
"sourceUnlinked": "Quelle getrennt",
|
|
4938
|
+
"unlinkSourceFailed": "Quelle konnte nicht getrennt werden"
|
|
4939
|
+
}
|
|
4884
4940
|
}
|
|
4885
4941
|
}
|
package/i18n/locales/en.json
CHANGED
|
@@ -1416,6 +1416,9 @@
|
|
|
1416
1416
|
"avg": "Average",
|
|
1417
1417
|
"min": "Min",
|
|
1418
1418
|
"max": "Max",
|
|
1419
|
+
"p50": "p50",
|
|
1420
|
+
"p90": "p90",
|
|
1421
|
+
"p99": "p99",
|
|
1419
1422
|
"empty": "No completed runs in this window."
|
|
1420
1423
|
},
|
|
1421
1424
|
"live": {
|
|
@@ -1935,6 +1938,9 @@
|
|
|
1935
1938
|
"label": "Templates & examples"
|
|
1936
1939
|
}
|
|
1937
1940
|
}
|
|
1941
|
+
},
|
|
1942
|
+
"accountSkills": {
|
|
1943
|
+
"intro": "Link repos where your team authors Claude Skills (a SKILL.md folder plus resource files). Synced skills join this account's catalog, shared by every board, and a pipeline's Skill step runs one against a task."
|
|
1938
1944
|
}
|
|
1939
1945
|
},
|
|
1940
1946
|
"settings": {
|
|
@@ -1988,7 +1994,8 @@
|
|
|
1988
1994
|
"noAccount": "No account selected.",
|
|
1989
1995
|
"tabs": {
|
|
1990
1996
|
"team": "Team & access",
|
|
1991
|
-
"fragments": "Context fragments"
|
|
1997
|
+
"fragments": "Context fragments",
|
|
1998
|
+
"skills": "Skills"
|
|
1992
1999
|
}
|
|
1993
2000
|
},
|
|
1994
2001
|
"infrastructure": {
|
|
@@ -3473,7 +3480,11 @@
|
|
|
3473
3480
|
"cloned": "Cloned \"{name}\" — now editing \"{copy}\"",
|
|
3474
3481
|
"cloneFailed": "Could not clone pipeline",
|
|
3475
3482
|
"updateFailed": "Could not update pipeline"
|
|
3476
|
-
}
|
|
3483
|
+
},
|
|
3484
|
+
"skillPlaceholder": "Select a skill",
|
|
3485
|
+
"skillNoneAvailable": "No skills available. Link a skill source in account settings.",
|
|
3486
|
+
"skillMissing": "This skill is no longer in the catalog; pick another.",
|
|
3487
|
+
"skillNeedsPick": "A Skill step needs a skill selected before you can save."
|
|
3477
3488
|
},
|
|
3478
3489
|
"progress": {
|
|
3479
3490
|
"status": {
|
|
@@ -5007,5 +5018,50 @@
|
|
|
5007
5018
|
"count": "{attempts} of {max}",
|
|
5008
5019
|
"footer": "The loop retries until the validation command passes or the iteration budget is spent."
|
|
5009
5020
|
}
|
|
5021
|
+
},
|
|
5022
|
+
"skills": {
|
|
5023
|
+
"unavailable": "The Claude Skills library isn't enabled for this deployment.",
|
|
5024
|
+
"catalog": {
|
|
5025
|
+
"title": "Synced skills",
|
|
5026
|
+
"empty": "No skills synced yet. Link a repo source below to import its skill folders.",
|
|
5027
|
+
"resources": "{count} resources",
|
|
5028
|
+
"pinned": "pinned {commit}"
|
|
5029
|
+
},
|
|
5030
|
+
"sources": {
|
|
5031
|
+
"title": "Repo sources",
|
|
5032
|
+
"empty": "No linked skill sources. Link a repo directory of skill folders below.",
|
|
5033
|
+
"linkTitle": "Link a skill source",
|
|
5034
|
+
"link": "Link & sync",
|
|
5035
|
+
"metaSynced": "synced {date} · ref {ref}",
|
|
5036
|
+
"metaNever": "never synced · ref {ref}",
|
|
5037
|
+
"changes": "Changes",
|
|
5038
|
+
"check": "Check for changes",
|
|
5039
|
+
"sync": "Resync",
|
|
5040
|
+
"unlink": "Unlink",
|
|
5041
|
+
"browseHint": "Browse the repo and pick the directory of skill folders (or link the whole repo).",
|
|
5042
|
+
"selectedDir": "Directory:",
|
|
5043
|
+
"wholeRepo": "Whole repository (root).",
|
|
5044
|
+
"ownerPlaceholder": "owner",
|
|
5045
|
+
"repoPlaceholder": "repo",
|
|
5046
|
+
"dirPlaceholder": "dir path (e.g. .claude/skills)",
|
|
5047
|
+
"refPlaceholder": "ref (default HEAD)",
|
|
5048
|
+
"githubRequired": "Linking a skill source requires the GitHub integration. Connect it on a board first."
|
|
5049
|
+
},
|
|
5050
|
+
"confirmUnlinkSource": {
|
|
5051
|
+
"title": "Unlink this source?",
|
|
5052
|
+
"body": "\"{repo}\" and the skills it synced will be removed. You can re-link it later.",
|
|
5053
|
+
"confirm": "Unlink"
|
|
5054
|
+
},
|
|
5055
|
+
"toast": {
|
|
5056
|
+
"sourceLinked": "Source linked & synced",
|
|
5057
|
+
"linkSourceFailed": "Could not link source",
|
|
5058
|
+
"synced": "Synced: {updated} updated, {removed} removed",
|
|
5059
|
+
"syncFailed": "Could not sync source",
|
|
5060
|
+
"changesAvailable": "Changes available",
|
|
5061
|
+
"upToDate": "Up to date",
|
|
5062
|
+
"checkSourceFailed": "Could not check source",
|
|
5063
|
+
"sourceUnlinked": "Source unlinked",
|
|
5064
|
+
"unlinkSourceFailed": "Could not unlink source"
|
|
5065
|
+
}
|
|
5010
5066
|
}
|
|
5011
5067
|
}
|
package/i18n/locales/es.json
CHANGED
|
@@ -1359,6 +1359,9 @@
|
|
|
1359
1359
|
"avg": "Media",
|
|
1360
1360
|
"min": "Mín.",
|
|
1361
1361
|
"max": "Máx.",
|
|
1362
|
+
"p50": "p50",
|
|
1363
|
+
"p90": "p90",
|
|
1364
|
+
"p99": "p99",
|
|
1362
1365
|
"empty": "No hay ejecuciones completadas en este periodo."
|
|
1363
1366
|
},
|
|
1364
1367
|
"live": {
|
|
@@ -1875,6 +1878,9 @@
|
|
|
1875
1878
|
"deselect": "Deseleccionar / cerrar el inspector",
|
|
1876
1879
|
"deleteBlock": "Eliminar el bloque seleccionado",
|
|
1877
1880
|
"help": "Mostrar esta ayuda"
|
|
1881
|
+
},
|
|
1882
|
+
"accountSkills": {
|
|
1883
|
+
"intro": "Vincula repositorios donde tu equipo crea Claude Skills (una carpeta SKILL.md más archivos de recursos). Las habilidades sincronizadas se añaden al catálogo de esta cuenta, compartido por todos los tableros, y el paso Skill de una tubería ejecuta una sobre una tarea."
|
|
1878
1884
|
}
|
|
1879
1885
|
},
|
|
1880
1886
|
"settings": {
|
|
@@ -1928,7 +1934,8 @@
|
|
|
1928
1934
|
"noAccount": "Ninguna cuenta seleccionada.",
|
|
1929
1935
|
"tabs": {
|
|
1930
1936
|
"team": "Equipo y acceso",
|
|
1931
|
-
"fragments": "Fragmentos de contexto"
|
|
1937
|
+
"fragments": "Fragmentos de contexto",
|
|
1938
|
+
"skills": "Habilidades"
|
|
1932
1939
|
}
|
|
1933
1940
|
},
|
|
1934
1941
|
"providerConnection": {
|
|
@@ -3377,7 +3384,11 @@
|
|
|
3377
3384
|
"confirmDeletePipeline": {
|
|
3378
3385
|
"title": "¿Eliminar este pipeline?",
|
|
3379
3386
|
"body": "Se eliminará \"{name}\". Esta acción no se puede deshacer."
|
|
3380
|
-
}
|
|
3387
|
+
},
|
|
3388
|
+
"skillPlaceholder": "Selecciona una habilidad",
|
|
3389
|
+
"skillNoneAvailable": "No hay habilidades disponibles. Vincula una fuente de habilidades en la configuración de la cuenta.",
|
|
3390
|
+
"skillMissing": "Esta habilidad ya no está en el catálogo; elige otra.",
|
|
3391
|
+
"skillNeedsPick": "Un paso Skill necesita una habilidad seleccionada antes de poder guardar."
|
|
3381
3392
|
},
|
|
3382
3393
|
"progress": {
|
|
3383
3394
|
"status": {
|
|
@@ -4869,5 +4880,50 @@
|
|
|
4869
4880
|
"count": "{attempts} de {max}",
|
|
4870
4881
|
"footer": "El bucle se repite hasta que el comando de validación pasa o se agota el presupuesto de iteraciones."
|
|
4871
4882
|
}
|
|
4883
|
+
},
|
|
4884
|
+
"skills": {
|
|
4885
|
+
"unavailable": "La biblioteca de Claude Skills no está habilitada en este despliegue.",
|
|
4886
|
+
"catalog": {
|
|
4887
|
+
"title": "Habilidades sincronizadas",
|
|
4888
|
+
"empty": "Aún no hay habilidades sincronizadas. Vincula una fuente de repositorio abajo para importar sus carpetas de habilidades.",
|
|
4889
|
+
"resources": "{count} recursos",
|
|
4890
|
+
"pinned": "fijada en {commit}"
|
|
4891
|
+
},
|
|
4892
|
+
"sources": {
|
|
4893
|
+
"title": "Fuentes de repositorio",
|
|
4894
|
+
"empty": "No hay fuentes de habilidades vinculadas. Vincula abajo un directorio de repositorio con carpetas de habilidades.",
|
|
4895
|
+
"linkTitle": "Vincular una fuente de habilidades",
|
|
4896
|
+
"link": "Vincular y sincronizar",
|
|
4897
|
+
"metaSynced": "sincronizada {date} · ref {ref}",
|
|
4898
|
+
"metaNever": "nunca sincronizada · ref {ref}",
|
|
4899
|
+
"changes": "Cambios",
|
|
4900
|
+
"check": "Buscar cambios",
|
|
4901
|
+
"sync": "Resincronizar",
|
|
4902
|
+
"unlink": "Desvincular",
|
|
4903
|
+
"browseHint": "Explora el repositorio y elige el directorio de carpetas de habilidades (o vincula todo el repo).",
|
|
4904
|
+
"selectedDir": "Directorio:",
|
|
4905
|
+
"wholeRepo": "Repositorio completo (raíz).",
|
|
4906
|
+
"ownerPlaceholder": "propietario",
|
|
4907
|
+
"repoPlaceholder": "repo",
|
|
4908
|
+
"dirPlaceholder": "ruta del directorio (p. ej. .claude/skills)",
|
|
4909
|
+
"refPlaceholder": "ref (por defecto HEAD)",
|
|
4910
|
+
"githubRequired": "Vincular una fuente de habilidades requiere la integración de GitHub. Conéctala primero en un tablero."
|
|
4911
|
+
},
|
|
4912
|
+
"confirmUnlinkSource": {
|
|
4913
|
+
"title": "¿Desvincular esta fuente?",
|
|
4914
|
+
"body": "\"{repo}\" y las habilidades que sincronizó se eliminarán. Puedes volver a vincularla más tarde.",
|
|
4915
|
+
"confirm": "Desvincular"
|
|
4916
|
+
},
|
|
4917
|
+
"toast": {
|
|
4918
|
+
"sourceLinked": "Fuente vinculada y sincronizada",
|
|
4919
|
+
"linkSourceFailed": "No se pudo vincular la fuente",
|
|
4920
|
+
"synced": "Sincronizado: {updated} actualizadas, {removed} eliminadas",
|
|
4921
|
+
"syncFailed": "No se pudo sincronizar la fuente",
|
|
4922
|
+
"changesAvailable": "Cambios disponibles",
|
|
4923
|
+
"upToDate": "Actualizado",
|
|
4924
|
+
"checkSourceFailed": "No se pudo comprobar la fuente",
|
|
4925
|
+
"sourceUnlinked": "Fuente desvinculada",
|
|
4926
|
+
"unlinkSourceFailed": "No se pudo desvincular la fuente"
|
|
4927
|
+
}
|
|
4872
4928
|
}
|
|
4873
4929
|
}
|
package/i18n/locales/fr.json
CHANGED
|
@@ -1359,6 +1359,9 @@
|
|
|
1359
1359
|
"avg": "Moyenne",
|
|
1360
1360
|
"min": "Min.",
|
|
1361
1361
|
"max": "Max.",
|
|
1362
|
+
"p50": "p50",
|
|
1363
|
+
"p90": "p90",
|
|
1364
|
+
"p99": "p99",
|
|
1362
1365
|
"empty": "Aucune exécution terminée sur cette période."
|
|
1363
1366
|
},
|
|
1364
1367
|
"live": {
|
|
@@ -1875,6 +1878,9 @@
|
|
|
1875
1878
|
"deselect": "Désélectionner / fermer l'inspecteur",
|
|
1876
1879
|
"deleteBlock": "Supprimer le bloc sélectionné",
|
|
1877
1880
|
"help": "Afficher cet aide-mémoire"
|
|
1881
|
+
},
|
|
1882
|
+
"accountSkills": {
|
|
1883
|
+
"intro": "Reliez les dépôts où votre équipe crée des Claude Skills (un dossier SKILL.md plus des fichiers de ressources). Les compétences synchronisées rejoignent le catalogue de ce compte, partagé par tous les tableaux, et l'étape Skill d'un pipeline en exécute une sur une tâche."
|
|
1878
1884
|
}
|
|
1879
1885
|
},
|
|
1880
1886
|
"settings": {
|
|
@@ -1928,7 +1934,8 @@
|
|
|
1928
1934
|
"noAccount": "Aucun compte sélectionné.",
|
|
1929
1935
|
"tabs": {
|
|
1930
1936
|
"team": "Équipe et accès",
|
|
1931
|
-
"fragments": "Fragments de contexte"
|
|
1937
|
+
"fragments": "Fragments de contexte",
|
|
1938
|
+
"skills": "Compétences"
|
|
1932
1939
|
}
|
|
1933
1940
|
},
|
|
1934
1941
|
"providerConnection": {
|
|
@@ -3377,7 +3384,11 @@
|
|
|
3377
3384
|
"confirmDeletePipeline": {
|
|
3378
3385
|
"title": "Supprimer ce pipeline ?",
|
|
3379
3386
|
"body": "\"{name}\" sera supprimé. Cette action est irréversible."
|
|
3380
|
-
}
|
|
3387
|
+
},
|
|
3388
|
+
"skillPlaceholder": "Sélectionner une compétence",
|
|
3389
|
+
"skillNoneAvailable": "Aucune compétence disponible. Reliez une source de compétences dans les paramètres du compte.",
|
|
3390
|
+
"skillMissing": "Cette compétence n'est plus dans le catalogue ; choisissez-en une autre.",
|
|
3391
|
+
"skillNeedsPick": "Une étape Skill a besoin d'une compétence sélectionnée avant de pouvoir enregistrer."
|
|
3381
3392
|
},
|
|
3382
3393
|
"progress": {
|
|
3383
3394
|
"status": {
|
|
@@ -4869,5 +4880,50 @@
|
|
|
4869
4880
|
"count": "{attempts} sur {max}",
|
|
4870
4881
|
"footer": "La boucle réessaie jusqu'à ce que la commande de validation réussisse ou que le budget d'itérations soit épuisé."
|
|
4871
4882
|
}
|
|
4883
|
+
},
|
|
4884
|
+
"skills": {
|
|
4885
|
+
"unavailable": "La bibliothèque Claude Skills n'est pas activée pour ce déploiement.",
|
|
4886
|
+
"catalog": {
|
|
4887
|
+
"title": "Compétences synchronisées",
|
|
4888
|
+
"empty": "Aucune compétence synchronisée pour l'instant. Reliez une source de dépôt ci-dessous pour importer ses dossiers de compétences.",
|
|
4889
|
+
"resources": "{count} ressources",
|
|
4890
|
+
"pinned": "épinglée sur {commit}"
|
|
4891
|
+
},
|
|
4892
|
+
"sources": {
|
|
4893
|
+
"title": "Sources de dépôt",
|
|
4894
|
+
"empty": "Aucune source de compétences reliée. Reliez ci-dessous un répertoire de dépôt contenant des dossiers de compétences.",
|
|
4895
|
+
"linkTitle": "Relier une source de compétences",
|
|
4896
|
+
"link": "Relier et synchroniser",
|
|
4897
|
+
"metaSynced": "synchronisée {date} · réf {ref}",
|
|
4898
|
+
"metaNever": "jamais synchronisée · réf {ref}",
|
|
4899
|
+
"changes": "Modifications",
|
|
4900
|
+
"check": "Vérifier les modifications",
|
|
4901
|
+
"sync": "Resynchroniser",
|
|
4902
|
+
"unlink": "Dissocier",
|
|
4903
|
+
"browseHint": "Parcourez le dépôt et choisissez le répertoire des dossiers de compétences (ou reliez tout le dépôt).",
|
|
4904
|
+
"selectedDir": "Répertoire :",
|
|
4905
|
+
"wholeRepo": "Dépôt entier (racine).",
|
|
4906
|
+
"ownerPlaceholder": "propriétaire",
|
|
4907
|
+
"repoPlaceholder": "dépôt",
|
|
4908
|
+
"dirPlaceholder": "chemin du répertoire (p. ex. .claude/skills)",
|
|
4909
|
+
"refPlaceholder": "réf (HEAD par défaut)",
|
|
4910
|
+
"githubRequired": "Relier une source de compétences nécessite l'intégration GitHub. Connectez-la d'abord sur un tableau."
|
|
4911
|
+
},
|
|
4912
|
+
"confirmUnlinkSource": {
|
|
4913
|
+
"title": "Dissocier cette source ?",
|
|
4914
|
+
"body": "\"{repo}\" et les compétences qu'elle a synchronisées seront supprimées. Vous pourrez la relier de nouveau plus tard.",
|
|
4915
|
+
"confirm": "Dissocier"
|
|
4916
|
+
},
|
|
4917
|
+
"toast": {
|
|
4918
|
+
"sourceLinked": "Source reliée et synchronisée",
|
|
4919
|
+
"linkSourceFailed": "Impossible de relier la source",
|
|
4920
|
+
"synced": "Synchronisé : {updated} mises à jour, {removed} supprimées",
|
|
4921
|
+
"syncFailed": "Impossible de synchroniser la source",
|
|
4922
|
+
"changesAvailable": "Modifications disponibles",
|
|
4923
|
+
"upToDate": "À jour",
|
|
4924
|
+
"checkSourceFailed": "Impossible de vérifier la source",
|
|
4925
|
+
"sourceUnlinked": "Source dissociée",
|
|
4926
|
+
"unlinkSourceFailed": "Impossible de dissocier la source"
|
|
4927
|
+
}
|
|
4872
4928
|
}
|
|
4873
4929
|
}
|