@cat-factory/app 0.66.0 → 0.68.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/panels/inspector/ServiceTestConfig.vue +142 -9
- package/app/components/settings/CustomManifestTypeEditor.vue +38 -2
- package/app/components/testing/TestReportWindow.vue +37 -0
- package/app/composables/api/infraHandlers.ts +6 -0
- package/app/stores/infraConfig.ts +12 -0
- package/i18n/locales/en.json +18 -0
- package/i18n/locales/es.json +19 -1
- package/i18n/locales/fr.json +19 -1
- package/i18n/locales/he.json +19 -1
- package/i18n/locales/ja.json +19 -1
- package/i18n/locales/pl.json +19 -1
- package/i18n/locales/tr.json +19 -1
- package/i18n/locales/uk.json +19 -1
- package/package.json +2 -2
|
@@ -37,6 +37,7 @@ const accounts = useAccountsStore()
|
|
|
37
37
|
const github = useGitHubStore()
|
|
38
38
|
const services = useServicesStore()
|
|
39
39
|
const infra = useInfraConfigStore()
|
|
40
|
+
const agentRuns = useAgentRunsStore()
|
|
40
41
|
const { t } = useI18n()
|
|
41
42
|
|
|
42
43
|
// The custom-manifest-type catalog feeds the `custom` picker. Cheap + shared (coalesced).
|
|
@@ -83,6 +84,12 @@ watch(
|
|
|
83
84
|
)
|
|
84
85
|
const customManifestId = computed(() => props.block.provisioning?.manifestId ?? '')
|
|
85
86
|
const customManifestPath = computed(() => props.block.provisioning?.manifestPath ?? '')
|
|
87
|
+
// The catalog entry for the pinned custom type — supplies its default manifest path (prefill +
|
|
88
|
+
// detection seed) and whether it can generate/fix (a `fixerPrompt` is declared).
|
|
89
|
+
const selectedCustomType = computed(() =>
|
|
90
|
+
infra.customTypes.find((c) => c.manifestId === customManifestId.value),
|
|
91
|
+
)
|
|
92
|
+
const manifestFixerAvailable = computed(() => !!selectedCustomType.value?.fixerPrompt)
|
|
86
93
|
|
|
87
94
|
const PROVISION_TYPES = computed<{ value: ProvisionType; label: string }[]>(() => [
|
|
88
95
|
{ value: 'infraless', label: t('inspector.testConfig.provisionTypes.infraless') },
|
|
@@ -158,14 +165,82 @@ function setKubeRenderer(value: KubernetesRenderer) {
|
|
|
158
165
|
commitManifestSource()
|
|
159
166
|
}
|
|
160
167
|
|
|
168
|
+
// Root a service-relative default under the service subtree, normalizing `.`/`..`/empty segments
|
|
169
|
+
// (mirrors the backend `joinPath`). A stored `manifestPath` is always REPO-root-relative — the
|
|
170
|
+
// same form auto-detection produces — so prefill and generate agree with detect.
|
|
171
|
+
function rootUnderDirectory(directory: string | null | undefined, path: string): string {
|
|
172
|
+
const segs: string[] = []
|
|
173
|
+
for (const part of [directory ?? '', path]) {
|
|
174
|
+
for (const seg of part.split('/')) {
|
|
175
|
+
if (!seg || seg === '.') continue
|
|
176
|
+
if (seg === '..') segs.pop()
|
|
177
|
+
else segs.push(seg)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return segs.join('/')
|
|
181
|
+
}
|
|
182
|
+
|
|
161
183
|
function setCustomManifestId(value: string) {
|
|
162
|
-
|
|
184
|
+
// Prefill the manifest path with the selected type's default, rooted under the service subtree
|
|
185
|
+
// (repo-root-relative, editable afterwards) so a monorepo service targets the right location
|
|
186
|
+
// even without running Detect. Leave the existing path untouched when the type declares no default.
|
|
187
|
+
const type = infra.customTypes.find((c) => c.manifestId === value)
|
|
188
|
+
const rooted = type?.defaultManifestPath
|
|
189
|
+
? rootUnderDirectory(repoContext.value?.directory, type.defaultManifestPath)
|
|
190
|
+
: ''
|
|
191
|
+
patchProvisioning({
|
|
192
|
+
type: 'custom',
|
|
193
|
+
manifestId: value || undefined,
|
|
194
|
+
...(rooted ? { manifestPath: rooted } : {}),
|
|
195
|
+
})
|
|
163
196
|
}
|
|
164
197
|
|
|
165
198
|
function setCustomManifestPath(value: string) {
|
|
166
199
|
patchProvisioning({ type: 'custom', manifestPath: value.trim() || undefined })
|
|
167
200
|
}
|
|
168
201
|
|
|
202
|
+
// Generate (or fix) the custom manifest via the fixer coding agent (async repair run). Shown only
|
|
203
|
+
// when the selected type declares a `fixerPrompt`. The dispatched run is tracked live below by id.
|
|
204
|
+
const generating = ref(false)
|
|
205
|
+
const manifestRepairError = ref(false)
|
|
206
|
+
const manifestRepairJobId = ref<string | null>(null)
|
|
207
|
+
const manifestRepairJob = computed(() =>
|
|
208
|
+
manifestRepairJobId.value ? agentRuns.envConfigRepairById(manifestRepairJobId.value) : undefined,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
async function generateOrFixManifest() {
|
|
212
|
+
const ctx = repoContext.value
|
|
213
|
+
const type = selectedCustomType.value
|
|
214
|
+
if (!ctx || !type?.fixerPrompt) return
|
|
215
|
+
const repo = github.repoFor(ctx.githubId)
|
|
216
|
+
// `manifestPath` is already repo-root-relative (prefill/detect root it); the fallback default
|
|
217
|
+
// still needs rooting for the rare case where nothing was prefilled yet.
|
|
218
|
+
const path =
|
|
219
|
+
customManifestPath.value.trim() ||
|
|
220
|
+
(type.defaultManifestPath ? rootUnderDirectory(ctx.directory, type.defaultManifestPath) : '')
|
|
221
|
+
if (!repo || !path) {
|
|
222
|
+
manifestRepairError.value = true
|
|
223
|
+
return
|
|
224
|
+
}
|
|
225
|
+
generating.value = true
|
|
226
|
+
manifestRepairError.value = false
|
|
227
|
+
manifestRepairJobId.value = null
|
|
228
|
+
try {
|
|
229
|
+
const res = await infra.repairCustomManifest({
|
|
230
|
+
manifestId: type.manifestId,
|
|
231
|
+
owner: repo.owner,
|
|
232
|
+
repo: repo.name,
|
|
233
|
+
manifestPath: path,
|
|
234
|
+
})
|
|
235
|
+
manifestRepairJobId.value = res.repairJobId ?? null
|
|
236
|
+
if (!res.usedAgent) manifestRepairError.value = true
|
|
237
|
+
} catch {
|
|
238
|
+
manifestRepairError.value = true
|
|
239
|
+
} finally {
|
|
240
|
+
generating.value = false
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
169
244
|
// The provisioning hints (cloud provider + instance size) are advisory inputs to the
|
|
170
245
|
// ephemeral-environment provisioner, not commonly tuned — keep them collapsed by default.
|
|
171
246
|
const showProvisioning = ref(false)
|
|
@@ -239,19 +314,27 @@ async function detectFromRepo() {
|
|
|
239
314
|
owner: repo.owner,
|
|
240
315
|
repo: repo.name,
|
|
241
316
|
...(ctx.directory ? { directory: ctx.directory } : {}),
|
|
242
|
-
// Prioritize the option matching the currently-selected tab (kubernetes
|
|
243
|
-
//
|
|
317
|
+
// Prioritize the option matching the currently-selected tab (kubernetes / docker-compose /
|
|
318
|
+
// custom); the detector falls back to the other when the preferred isn't found.
|
|
244
319
|
prefer: provisionType.value,
|
|
320
|
+
// `custom`: the selected type seeds the path search from its default; the current path is
|
|
321
|
+
// kept when it already resolves.
|
|
322
|
+
...(provisionType.value === 'custom' && customManifestId.value
|
|
323
|
+
? {
|
|
324
|
+
manifestId: customManifestId.value,
|
|
325
|
+
...(customManifestPath.value ? { currentManifestPath: customManifestPath.value } : {}),
|
|
326
|
+
}
|
|
327
|
+
: {}),
|
|
245
328
|
})
|
|
246
329
|
detectResult.value = rec
|
|
247
330
|
// Pre-select the recommended compose service so the picker opens on a real choice.
|
|
248
331
|
pickedComposeService.value =
|
|
249
332
|
rec.composeServiceCandidates?.find((c) => c.recommended)?.service ?? null
|
|
250
|
-
//
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
if (rec.detected) {
|
|
333
|
+
// Prefill when the detector inferred something. A non-custom `detected: false` recommendation
|
|
334
|
+
// is `infraless`; applying it would WIPE the service's existing provisioning (updateBlock
|
|
335
|
+
// persists immediately) — so we skip it. A `custom` recommendation is non-destructive (it just
|
|
336
|
+
// carries the resolved/default manifest path), so we apply it even when the file wasn't found.
|
|
337
|
+
if (rec.detected || rec.provisioning.type === 'custom') {
|
|
255
338
|
board.updateBlock(props.block.id, { provisioning: rec.provisioning })
|
|
256
339
|
if (rec.provisioning.type === 'kubernetes') seedKubeSource(rec.provisioning.manifestSource)
|
|
257
340
|
}
|
|
@@ -369,7 +452,10 @@ function setSize(value: InstanceSize) {
|
|
|
369
452
|
</p>
|
|
370
453
|
|
|
371
454
|
<template v-if="detectResult && !detecting">
|
|
372
|
-
<p
|
|
455
|
+
<p
|
|
456
|
+
v-if="!detectResult.detected && detectResult.provisioning.type !== 'custom'"
|
|
457
|
+
class="text-[11px] text-amber-300/80"
|
|
458
|
+
>
|
|
373
459
|
{{ t('inspector.testConfig.detect.none') }}
|
|
374
460
|
</p>
|
|
375
461
|
<template v-else>
|
|
@@ -659,6 +745,53 @@ function setSize(value: InstanceSize) {
|
|
|
659
745
|
(e: KeyboardEvent) => setCustomManifestPath((e.target as HTMLInputElement).value)
|
|
660
746
|
"
|
|
661
747
|
/>
|
|
748
|
+
<p class="text-[11px] leading-snug text-slate-500">
|
|
749
|
+
{{ t('inspector.testConfig.customManifestPathHint') }}
|
|
750
|
+
</p>
|
|
751
|
+
</div>
|
|
752
|
+
|
|
753
|
+
<!-- Generate (when missing) or fix (when invalid) the manifest via the fixer agent. Only
|
|
754
|
+
shown when the selected type declares a fixer prompt. -->
|
|
755
|
+
<div
|
|
756
|
+
v-if="manifestFixerAvailable && repoContext"
|
|
757
|
+
class="space-y-1.5 rounded border border-slate-800 bg-slate-900/40 p-2"
|
|
758
|
+
>
|
|
759
|
+
<div class="flex items-center justify-between gap-2">
|
|
760
|
+
<span class="text-[11px] text-slate-400">{{
|
|
761
|
+
t('inspector.testConfig.generateManifest.title')
|
|
762
|
+
}}</span>
|
|
763
|
+
<UButton
|
|
764
|
+
size="xs"
|
|
765
|
+
variant="soft"
|
|
766
|
+
color="primary"
|
|
767
|
+
icon="i-lucide-file-cog"
|
|
768
|
+
:loading="generating"
|
|
769
|
+
:disabled="!customManifestPath && !selectedCustomType?.defaultManifestPath"
|
|
770
|
+
@click="generateOrFixManifest"
|
|
771
|
+
>
|
|
772
|
+
{{ t('inspector.testConfig.generateManifest.button') }}
|
|
773
|
+
</UButton>
|
|
774
|
+
</div>
|
|
775
|
+
<p class="text-[11px] leading-snug text-slate-500">
|
|
776
|
+
{{ t('inspector.testConfig.generateManifest.hint') }}
|
|
777
|
+
</p>
|
|
778
|
+
<p v-if="manifestRepairError" class="text-[11px] text-rose-300/80">
|
|
779
|
+
{{ t('inspector.testConfig.generateManifest.error') }}
|
|
780
|
+
</p>
|
|
781
|
+
<p
|
|
782
|
+
v-else-if="manifestRepairJob"
|
|
783
|
+
class="text-[11px]"
|
|
784
|
+
:class="{
|
|
785
|
+
'text-sky-300/80': manifestRepairJob.status === 'running',
|
|
786
|
+
'text-emerald-300/80': manifestRepairJob.status === 'succeeded',
|
|
787
|
+
'text-rose-300/80': manifestRepairJob.status === 'failed',
|
|
788
|
+
}"
|
|
789
|
+
>
|
|
790
|
+
{{ t(`inspector.testConfig.generateManifest.status.${manifestRepairJob.status}`) }}
|
|
791
|
+
</p>
|
|
792
|
+
<p v-else-if="manifestRepairJobId" class="text-[11px] text-sky-300/80">
|
|
793
|
+
{{ t('inspector.testConfig.generateManifest.dispatched') }}
|
|
794
|
+
</p>
|
|
662
795
|
</div>
|
|
663
796
|
</div>
|
|
664
797
|
|
|
@@ -12,7 +12,14 @@ const infra = useInfraConfigStore()
|
|
|
12
12
|
const toast = useToast()
|
|
13
13
|
|
|
14
14
|
// A draft for the add/edit form. `manifestId` is locked on edit (it's the PK).
|
|
15
|
-
const draft = reactive({
|
|
15
|
+
const draft = reactive({
|
|
16
|
+
manifestId: '',
|
|
17
|
+
label: '',
|
|
18
|
+
acceptsInputHint: '',
|
|
19
|
+
description: '',
|
|
20
|
+
defaultManifestPath: '',
|
|
21
|
+
fixerPrompt: '',
|
|
22
|
+
})
|
|
16
23
|
const editing = ref(false)
|
|
17
24
|
const busy = ref(false)
|
|
18
25
|
|
|
@@ -22,7 +29,14 @@ const canSave = computed(
|
|
|
22
29
|
)
|
|
23
30
|
|
|
24
31
|
function startAdd() {
|
|
25
|
-
Object.assign(draft, {
|
|
32
|
+
Object.assign(draft, {
|
|
33
|
+
manifestId: '',
|
|
34
|
+
label: '',
|
|
35
|
+
acceptsInputHint: '',
|
|
36
|
+
description: '',
|
|
37
|
+
defaultManifestPath: '',
|
|
38
|
+
fixerPrompt: '',
|
|
39
|
+
})
|
|
26
40
|
editing.value = false
|
|
27
41
|
}
|
|
28
42
|
|
|
@@ -32,6 +46,8 @@ function startEdit(type: CustomManifestType) {
|
|
|
32
46
|
label: type.label,
|
|
33
47
|
acceptsInputHint: type.acceptsInputHint ?? '',
|
|
34
48
|
description: type.description ?? '',
|
|
49
|
+
defaultManifestPath: type.defaultManifestPath ?? '',
|
|
50
|
+
fixerPrompt: type.fixerPrompt ?? '',
|
|
35
51
|
})
|
|
36
52
|
editing.value = true
|
|
37
53
|
}
|
|
@@ -44,6 +60,10 @@ async function save() {
|
|
|
44
60
|
label: draft.label.trim(),
|
|
45
61
|
...(draft.acceptsInputHint.trim() ? { acceptsInputHint: draft.acceptsInputHint.trim() } : {}),
|
|
46
62
|
...(draft.description.trim() ? { description: draft.description.trim() } : {}),
|
|
63
|
+
...(draft.defaultManifestPath.trim()
|
|
64
|
+
? { defaultManifestPath: draft.defaultManifestPath.trim() }
|
|
65
|
+
: {}),
|
|
66
|
+
...(draft.fixerPrompt.trim() ? { fixerPrompt: draft.fixerPrompt.trim() } : {}),
|
|
47
67
|
})
|
|
48
68
|
startAdd()
|
|
49
69
|
} catch (e) {
|
|
@@ -158,6 +178,22 @@ async function remove(type: CustomManifestType) {
|
|
|
158
178
|
<UFormField :label="t('settings.infrastructure.customType.description')">
|
|
159
179
|
<UTextarea v-model="draft.description" :rows="2" />
|
|
160
180
|
</UFormField>
|
|
181
|
+
<UFormField
|
|
182
|
+
:label="t('settings.infrastructure.customType.defaultManifestPath')"
|
|
183
|
+
:help="t('settings.infrastructure.customType.defaultManifestPathHelp')"
|
|
184
|
+
>
|
|
185
|
+
<UInput
|
|
186
|
+
v-model="draft.defaultManifestPath"
|
|
187
|
+
class="font-mono"
|
|
188
|
+
placeholder="deploy/preview.yaml"
|
|
189
|
+
/>
|
|
190
|
+
</UFormField>
|
|
191
|
+
<UFormField
|
|
192
|
+
:label="t('settings.infrastructure.customType.fixerPrompt')"
|
|
193
|
+
:help="t('settings.infrastructure.customType.fixerPromptHelp')"
|
|
194
|
+
>
|
|
195
|
+
<UTextarea v-model="draft.fixerPrompt" :rows="3" />
|
|
196
|
+
</UFormField>
|
|
161
197
|
<div class="flex justify-end gap-2">
|
|
162
198
|
<UButton v-if="editing" color="neutral" variant="ghost" size="sm" @click="startAdd">
|
|
163
199
|
{{ t('common.cancel') }}
|
|
@@ -66,6 +66,30 @@ const infraSetup = computed(() => testState.value?.infraSetup ?? null)
|
|
|
66
66
|
// The captured stand-up logs are shown on demand (they can be long).
|
|
67
67
|
const showInfraSetupLogs = ref(false)
|
|
68
68
|
|
|
69
|
+
// Once ALL of a tester's infrastructure is up (its container is running, the ephemeral
|
|
70
|
+
// environment (when it tests against one) is ready, and any in-container dependency stand-up
|
|
71
|
+
// succeeded) the agent can actually begin exercising the change. Surface an explicit line
|
|
72
|
+
// saying so, so a run's details don't jump silently from "provisioning" straight into a blank
|
|
73
|
+
// "working" state. This only fills the gap BEFORE the first working signal, so it is scoped
|
|
74
|
+
// to a still-running step that hasn't produced a report yet: a finished step (state 'done'),
|
|
75
|
+
// a failed run, or one that already has a report is past "starting", so the banner clears.
|
|
76
|
+
// (The backend keeps the raw container status at 'up' after the step ends; 'destroyed' is a
|
|
77
|
+
// display-only derivation in StepContainerStatus, so gating on the step state is what stops
|
|
78
|
+
// the banner lingering.) Requires the container to actually report 'up' (a not-yet-created
|
|
79
|
+
// container is not "up"), and requires the tester to genuinely depend on a test environment
|
|
80
|
+
// (an ephemeral env or an in-container stand-up); an infraless tester has nothing to announce.
|
|
81
|
+
const infraReady = computed(() => {
|
|
82
|
+
const s = step.value
|
|
83
|
+
if (!s || runFailed.value || s.state === 'done' || report.value) return false
|
|
84
|
+
if (s.container?.status !== 'up') return false
|
|
85
|
+
const env = stepEnvironment.value
|
|
86
|
+
const infra = infraSetup.value
|
|
87
|
+
if (!env && !infra) return false
|
|
88
|
+
const envReady = !env || env.status === 'ready'
|
|
89
|
+
const standupReady = !infra || infra.started
|
|
90
|
+
return envReady && standupReady
|
|
91
|
+
})
|
|
92
|
+
|
|
69
93
|
const screenshots = computed<TestScreenshot[]>(() => report.value?.screenshots ?? [])
|
|
70
94
|
// Resolve each capture into an object URL for the gallery + lightbox. The shared cache
|
|
71
95
|
// dedupes, so the lightbox reuses what the thumbnails fetched. (The reference design is not
|
|
@@ -424,6 +448,19 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
424
448
|
</template>
|
|
425
449
|
</div>
|
|
426
450
|
|
|
451
|
+
<!-- Explicit confirmation that every piece of the tester's infrastructure is up
|
|
452
|
+
(container running, the ephemeral environment ready, any in-container
|
|
453
|
+
dependency stand-up done) and the agent is now starting its work — so the
|
|
454
|
+
details don't jump silently from "provisioning" into a blank working state. -->
|
|
455
|
+
<div
|
|
456
|
+
v-if="infraReady"
|
|
457
|
+
data-testid="tester-env-ready"
|
|
458
|
+
class="flex items-center gap-2 rounded-lg border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-[13px] text-emerald-200"
|
|
459
|
+
>
|
|
460
|
+
<UIcon name="i-lucide-rocket" class="h-4 w-4 shrink-0 text-emerald-400" />
|
|
461
|
+
<span>{{ t('testing.readyBanner') }}</span>
|
|
462
|
+
</div>
|
|
463
|
+
|
|
427
464
|
<div v-if="executionId">
|
|
428
465
|
<UButton
|
|
429
466
|
:icon="showProvisioning ? 'i-lucide-chevron-up' : 'i-lucide-scroll-text'"
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
registerEnvironmentHandlerContract,
|
|
6
6
|
removeCustomManifestTypeContract,
|
|
7
7
|
removeEnvironmentUserHandlerContract,
|
|
8
|
+
repairCustomManifestContract,
|
|
8
9
|
testEnvironmentHandlerContract,
|
|
9
10
|
unregisterEnvironmentHandlerContract,
|
|
10
11
|
upsertCustomManifestTypeContract,
|
|
@@ -14,6 +15,7 @@ import type {
|
|
|
14
15
|
DetectServiceProvisioningInput,
|
|
15
16
|
ProvisionType,
|
|
16
17
|
RegisterEnvironmentHandlerInput,
|
|
18
|
+
RepairCustomManifestInput,
|
|
17
19
|
TestEnvironmentHandlerInput,
|
|
18
20
|
UpsertCustomManifestTypeInput,
|
|
19
21
|
UpsertEnvironmentUserHandlerBody,
|
|
@@ -45,6 +47,10 @@ export function infraHandlersApi({ send, ws }: ApiContext) {
|
|
|
45
47
|
detectServiceProvisioning: (workspaceId: string, body: DetectServiceProvisioningInput) =>
|
|
46
48
|
send(detectServiceProvisioningContract, { pathPrefix: ws(workspaceId), body }),
|
|
47
49
|
|
|
50
|
+
// Generate/fix a service's custom manifest via the fixer coding agent (async repair run).
|
|
51
|
+
repairCustomManifest: (workspaceId: string, body: RepairCustomManifestInput) =>
|
|
52
|
+
send(repairCustomManifestContract, { pathPrefix: ws(workspaceId), body }),
|
|
53
|
+
|
|
48
54
|
// `manifestId` (for a `custom` handler) rides as a query param; absent ⇒ the bare handler.
|
|
49
55
|
unregisterEnvironmentHandler: (
|
|
50
56
|
workspaceId: string,
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
EnvironmentHandlerView,
|
|
7
7
|
ProvisionType,
|
|
8
8
|
RegisterEnvironmentHandlerInput,
|
|
9
|
+
RepairCustomManifestInput,
|
|
9
10
|
TestEnvironmentHandlerInput,
|
|
10
11
|
UpsertCustomManifestTypeInput,
|
|
11
12
|
UpsertEnvironmentUserHandlerBody,
|
|
@@ -112,6 +113,16 @@ export const useInfraConfigStore = defineStore('infraConfig', () => {
|
|
|
112
113
|
return api.detectServiceProvisioning(ws.requireId(), input)
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Generate (or fix) a service's custom manifest via the fixer coding agent. Dispatches a
|
|
118
|
+
* durable async repair run and returns immediately with `usedAgent`/`repairJobId`; the run is
|
|
119
|
+
* tracked via the workspace stream like the provider-config repair. Nothing persisted here.
|
|
120
|
+
*/
|
|
121
|
+
async function repairCustomManifest(input: RepairCustomManifestInput) {
|
|
122
|
+
const ws = useWorkspaceStore()
|
|
123
|
+
return api.repairCustomManifest(ws.requireId(), input)
|
|
124
|
+
}
|
|
125
|
+
|
|
115
126
|
async function unregisterHandler(type: ProvisionType, manifestId?: string | null) {
|
|
116
127
|
const ws = useWorkspaceStore()
|
|
117
128
|
await api.unregisterEnvironmentHandler(ws.requireId(), type, manifestId ?? undefined)
|
|
@@ -181,6 +192,7 @@ export const useInfraConfigStore = defineStore('infraConfig', () => {
|
|
|
181
192
|
registerHandler,
|
|
182
193
|
testHandler,
|
|
183
194
|
detectProvisioning,
|
|
195
|
+
repairCustomManifest,
|
|
184
196
|
unregisterHandler,
|
|
185
197
|
upsertCustomType,
|
|
186
198
|
removeCustomType,
|
package/i18n/locales/en.json
CHANGED
|
@@ -476,6 +476,19 @@
|
|
|
476
476
|
"customNoTypes": "No custom manifest types are defined yet. Add one in the Infrastructure window.",
|
|
477
477
|
"customManifestIdHint": "The custom type this service produces, matched to a remote-custom handler the workspace configures.",
|
|
478
478
|
"customManifestPath": "Manifest path (optional)",
|
|
479
|
+
"customManifestPathHint": "Prefilled from the type's default when you select it. Use Detect to locate an existing manifest in the repo.",
|
|
480
|
+
"generateManifest": {
|
|
481
|
+
"title": "Manifest file",
|
|
482
|
+
"button": "Generate / fix",
|
|
483
|
+
"hint": "Runs a coding agent to create the manifest at this path (or fix it if it exists but is invalid) and push it to the branch.",
|
|
484
|
+
"error": "Could not start the manifest generation run.",
|
|
485
|
+
"dispatched": "A manifest generation run was started.",
|
|
486
|
+
"status": {
|
|
487
|
+
"running": "Generating the manifest…",
|
|
488
|
+
"succeeded": "Manifest generated and pushed.",
|
|
489
|
+
"failed": "The manifest generation run failed. Retry it from the Infrastructure window."
|
|
490
|
+
}
|
|
491
|
+
},
|
|
479
492
|
"detect": {
|
|
480
493
|
"title": "Auto-detect",
|
|
481
494
|
"button": "Detect from repo",
|
|
@@ -1404,6 +1417,10 @@
|
|
|
1404
1417
|
"acceptsInputHint": "Input hint (optional)",
|
|
1405
1418
|
"acceptsInputHintHelp": "Describes the input shape the provider expects.",
|
|
1406
1419
|
"description": "Description (optional)",
|
|
1420
|
+
"defaultManifestPath": "Default manifest path (optional)",
|
|
1421
|
+
"defaultManifestPathHelp": "Prefilled on a service that pins this type, and the seed for path auto-detection. A complete path (deploy/preview.yaml) or a bare filename.",
|
|
1422
|
+
"fixerPrompt": "Fixer prompt (optional)",
|
|
1423
|
+
"fixerPromptHelp": "Coding-agent instructions to generate or fix the manifest. When set, a service shows a Generate / fix button.",
|
|
1407
1424
|
"add": "Add type",
|
|
1408
1425
|
"saveFailed": "Could not save the custom type",
|
|
1409
1426
|
"removeFailed": "Could not remove the custom type"
|
|
@@ -3163,6 +3180,7 @@
|
|
|
3163
3180
|
"showLogs": "Show stand-up logs",
|
|
3164
3181
|
"hideLogs": "Hide stand-up logs"
|
|
3165
3182
|
},
|
|
3183
|
+
"readyBanner": "Test environment is up. The tester is starting its work.",
|
|
3166
3184
|
"footer": "Scenarios are the areas the Tester chose to exercise (its spec acceptance scenarios). Outcomes and concerns are grouped under them by name.",
|
|
3167
3185
|
"@screenshotAlt": {
|
|
3168
3186
|
"description": "Alt text for a captured screenshot thumbnail; {view} is the screen/view name. The literal word 'screenshot' should be localized."
|
package/i18n/locales/es.json
CHANGED
|
@@ -454,6 +454,19 @@
|
|
|
454
454
|
"namespace": "Los manifiestos fijan el espacio de nombres \"{namespace}\"; se recomienda respetarlo en el gestor del espacio de trabajo.",
|
|
455
455
|
"confidenceHigh": "Detectado",
|
|
456
456
|
"confidenceLow": "Sugerencia"
|
|
457
|
+
},
|
|
458
|
+
"customManifestPathHint": "Se rellena con el valor predeterminado del tipo al seleccionarlo. Usa Detectar para localizar un manifiesto existente en el repositorio.",
|
|
459
|
+
"generateManifest": {
|
|
460
|
+
"title": "Archivo de manifiesto",
|
|
461
|
+
"button": "Generar / corregir",
|
|
462
|
+
"hint": "Ejecuta un agente de código para crear el manifiesto en esta ruta (o corregirlo si existe pero no es válido) y subirlo a la rama.",
|
|
463
|
+
"error": "No se pudo iniciar la generación del manifiesto.",
|
|
464
|
+
"dispatched": "Se inició una ejecución de generación del manifiesto.",
|
|
465
|
+
"status": {
|
|
466
|
+
"running": "Generando el manifiesto…",
|
|
467
|
+
"succeeded": "Manifiesto generado y subido.",
|
|
468
|
+
"failed": "La generación del manifiesto falló. Vuelve a intentarlo desde la ventana de Infraestructura."
|
|
469
|
+
}
|
|
457
470
|
}
|
|
458
471
|
},
|
|
459
472
|
"agentConfig": {
|
|
@@ -1815,7 +1828,11 @@
|
|
|
1815
1828
|
"description": "Descripción (opcional)",
|
|
1816
1829
|
"add": "Añadir tipo",
|
|
1817
1830
|
"saveFailed": "No se pudo guardar el tipo personalizado",
|
|
1818
|
-
"removeFailed": "No se pudo eliminar el tipo personalizado"
|
|
1831
|
+
"removeFailed": "No se pudo eliminar el tipo personalizado",
|
|
1832
|
+
"defaultManifestPath": "Ruta de manifiesto predeterminada (opcional)",
|
|
1833
|
+
"defaultManifestPathHelp": "Se rellena en un servicio que fije este tipo, y es la base para la detección automática de la ruta. Una ruta completa (deploy/preview.yaml) o solo un nombre de archivo.",
|
|
1834
|
+
"fixerPrompt": "Prompt de corrección (opcional)",
|
|
1835
|
+
"fixerPromptHelp": "Instrucciones para el agente de código para generar o corregir el manifiesto. Cuando se define, el servicio muestra un botón Generar / corregir."
|
|
1819
1836
|
},
|
|
1820
1837
|
"handler": {
|
|
1821
1838
|
"intro": "Configura cómo se gestiona cada tipo de aprovisionamiento que declara un servicio: el motor y la conexión. Los manifiestos o la ruta de compose de un servicio (el qué/dónde) se definen en el servicio.",
|
|
@@ -3035,6 +3052,7 @@
|
|
|
3035
3052
|
"blocking": "({count} bloqueante) | ({count} bloqueantes)"
|
|
3036
3053
|
},
|
|
3037
3054
|
"environment": "Entorno",
|
|
3055
|
+
"readyBanner": "El entorno de pruebas está listo. El Tester está comenzando su trabajo.",
|
|
3038
3056
|
"footer": "Los escenarios son las áreas que el Tester decidió ejercitar (sus escenarios de aceptación de la especificación). Los resultados y las incidencias se agrupan bajo ellos por nombre.",
|
|
3039
3057
|
"infrastructure": "Infraestructura",
|
|
3040
3058
|
"standup": {
|
package/i18n/locales/fr.json
CHANGED
|
@@ -454,6 +454,19 @@
|
|
|
454
454
|
"namespace": "Les manifestes fixent l'espace de noms « {namespace} » ; il est recommandé de le respecter sur le gestionnaire de l'espace de travail.",
|
|
455
455
|
"confidenceHigh": "Détecté",
|
|
456
456
|
"confidenceLow": "Suggestion"
|
|
457
|
+
},
|
|
458
|
+
"customManifestPathHint": "Prérempli avec la valeur par défaut du type lors de sa sélection. Utilisez Détecter pour localiser un manifeste existant dans le dépôt.",
|
|
459
|
+
"generateManifest": {
|
|
460
|
+
"title": "Fichier de manifeste",
|
|
461
|
+
"button": "Générer / corriger",
|
|
462
|
+
"hint": "Lance un agent de code pour créer le manifeste à ce chemin (ou le corriger s'il existe mais n'est pas valide) et le pousser sur la branche.",
|
|
463
|
+
"error": "Impossible de démarrer la génération du manifeste.",
|
|
464
|
+
"dispatched": "Une exécution de génération du manifeste a démarré.",
|
|
465
|
+
"status": {
|
|
466
|
+
"running": "Génération du manifeste…",
|
|
467
|
+
"succeeded": "Manifeste généré et poussé.",
|
|
468
|
+
"failed": "La génération du manifeste a échoué. Réessayez depuis la fenêtre Infrastructure."
|
|
469
|
+
}
|
|
457
470
|
}
|
|
458
471
|
},
|
|
459
472
|
"agentConfig": {
|
|
@@ -1815,7 +1828,11 @@
|
|
|
1815
1828
|
"description": "Description (facultatif)",
|
|
1816
1829
|
"add": "Ajouter le type",
|
|
1817
1830
|
"saveFailed": "Impossible d'enregistrer le type personnalisé",
|
|
1818
|
-
"removeFailed": "Impossible de supprimer le type personnalisé"
|
|
1831
|
+
"removeFailed": "Impossible de supprimer le type personnalisé",
|
|
1832
|
+
"defaultManifestPath": "Chemin de manifeste par défaut (facultatif)",
|
|
1833
|
+
"defaultManifestPathHelp": "Prérempli sur un service qui épingle ce type, et base de la détection automatique du chemin. Un chemin complet (deploy/preview.yaml) ou un simple nom de fichier.",
|
|
1834
|
+
"fixerPrompt": "Prompt de correction (facultatif)",
|
|
1835
|
+
"fixerPromptHelp": "Instructions pour l'agent de code afin de générer ou corriger le manifeste. Lorsqu'il est défini, le service affiche un bouton Générer / corriger."
|
|
1819
1836
|
},
|
|
1820
1837
|
"handler": {
|
|
1821
1838
|
"intro": "Configurez la manière dont chaque type de provisionnement déclaré par un service est géré: le moteur et la connexion. Les manifestes ou le chemin compose d'un service (le quoi/où) se définissent sur le service.",
|
|
@@ -3035,6 +3052,7 @@
|
|
|
3035
3052
|
"blocking": "({count} bloquante) | ({count} bloquantes)"
|
|
3036
3053
|
},
|
|
3037
3054
|
"environment": "Environnement",
|
|
3055
|
+
"readyBanner": "L'environnement de test est prêt. Le Testeur commence son travail.",
|
|
3038
3056
|
"footer": "Les scénarios sont les domaines que le Testeur a choisi d'éprouver (ses scénarios d'acceptation de la spécification). Les résultats et les réserves y sont regroupés par nom.",
|
|
3039
3057
|
"infrastructure": "Infrastructure",
|
|
3040
3058
|
"standup": {
|
package/i18n/locales/he.json
CHANGED
|
@@ -454,6 +454,19 @@
|
|
|
454
454
|
"namespace": "המניפסטים מקבעים את מרחב השמות \"{namespace}\"; מומלץ לכבד אותו במטפל של המרחב.",
|
|
455
455
|
"confidenceHigh": "זוהה",
|
|
456
456
|
"confidenceLow": "הצעה"
|
|
457
|
+
},
|
|
458
|
+
"customManifestPathHint": "מתמלא מברירת המחדל של הסוג בעת הבחירה. השתמש ב'זיהוי' כדי לאתר מניפסט קיים במאגר.",
|
|
459
|
+
"generateManifest": {
|
|
460
|
+
"title": "קובץ מניפסט",
|
|
461
|
+
"button": "צור / תקן",
|
|
462
|
+
"hint": "מריץ סוכן קוד ליצירת המניפסט בנתיב זה (או לתיקונו אם קיים אך אינו תקין) ולדחיפתו לענף.",
|
|
463
|
+
"error": "לא ניתן להתחיל את הפקת המניפסט.",
|
|
464
|
+
"dispatched": "הפקת מניפסט הופעלה.",
|
|
465
|
+
"status": {
|
|
466
|
+
"running": "מפיק את המניפסט…",
|
|
467
|
+
"succeeded": "המניפסט נוצר ונדחף.",
|
|
468
|
+
"failed": "הפקת המניפסט נכשלה. נסה שוב מחלון התשתית."
|
|
469
|
+
}
|
|
457
470
|
}
|
|
458
471
|
},
|
|
459
472
|
"agentConfig": {
|
|
@@ -1364,7 +1377,11 @@
|
|
|
1364
1377
|
"description": "תיאור (אופציונלי)",
|
|
1365
1378
|
"add": "הוסף סוג",
|
|
1366
1379
|
"saveFailed": "לא ניתן לשמור את הסוג המותאם",
|
|
1367
|
-
"removeFailed": "לא ניתן להסיר את הסוג המותאם"
|
|
1380
|
+
"removeFailed": "לא ניתן להסיר את הסוג המותאם",
|
|
1381
|
+
"defaultManifestPath": "נתיב מניפסט ברירת מחדל (אופציונלי)",
|
|
1382
|
+
"defaultManifestPathHelp": "מתמלא בשירות שמצמיד סוג זה, ומשמש בסיס לזיהוי אוטומטי של הנתיב. נתיב מלא (deploy/preview.yaml) או שם קובץ בלבד.",
|
|
1383
|
+
"fixerPrompt": "הנחיית תיקון (אופציונלי)",
|
|
1384
|
+
"fixerPromptHelp": "הוראות לסוכן הקוד ליצירה או תיקון של המניפסט. כאשר מוגדר, השירות מציג כפתור צור / תקן."
|
|
1368
1385
|
},
|
|
1369
1386
|
"handler": {
|
|
1370
1387
|
"intro": "הגדר כיצד מטופל כל סוג אספקה שהשירות מצהיר עליו: המנוע והחיבור. המניפסטים או נתיב ה-compose של שירות (מה/היכן) מוגדרים על השירות.",
|
|
@@ -3054,6 +3071,7 @@
|
|
|
3054
3071
|
"showLogs": "הצג יומני הקמה",
|
|
3055
3072
|
"hideLogs": "הסתר יומני הקמה"
|
|
3056
3073
|
},
|
|
3074
|
+
"readyBanner": "סביבת הבדיקה פעילה. הבודק מתחיל בעבודתו.",
|
|
3057
3075
|
"footer": "תרחישים הם התחומים שהבודק בחר לבחון (תרחישי קבלת המפרט שלו). תוצאות וחששות מקובצים תחתם לפי שם."
|
|
3058
3076
|
},
|
|
3059
3077
|
"visualConfirm": {
|
package/i18n/locales/ja.json
CHANGED
|
@@ -454,6 +454,19 @@
|
|
|
454
454
|
"namespace": "マニフェストは名前空間「{namespace}」を固定しています。ワークスペースのハンドラーでそれを尊重することを推奨します。",
|
|
455
455
|
"confidenceHigh": "検出",
|
|
456
456
|
"confidenceLow": "提案"
|
|
457
|
+
},
|
|
458
|
+
"customManifestPathHint": "タイプを選択すると既定値が自動入力されます。リポジトリ内の既存のマニフェストを探すには「検出」を使用してください。",
|
|
459
|
+
"generateManifest": {
|
|
460
|
+
"title": "マニフェストファイル",
|
|
461
|
+
"button": "生成 / 修正",
|
|
462
|
+
"hint": "コーディングエージェントを実行して、このパスにマニフェストを作成(存在するが無効な場合は修正)し、ブランチにプッシュします。",
|
|
463
|
+
"error": "マニフェスト生成の実行を開始できませんでした。",
|
|
464
|
+
"dispatched": "マニフェスト生成の実行を開始しました。",
|
|
465
|
+
"status": {
|
|
466
|
+
"running": "マニフェストを生成しています…",
|
|
467
|
+
"succeeded": "マニフェストを生成してプッシュしました。",
|
|
468
|
+
"failed": "マニフェスト生成の実行に失敗しました。インフラウィンドウから再試行してください。"
|
|
469
|
+
}
|
|
457
470
|
}
|
|
458
471
|
},
|
|
459
472
|
"agentConfig": {
|
|
@@ -1366,7 +1379,11 @@
|
|
|
1366
1379
|
"description": "説明(任意)",
|
|
1367
1380
|
"add": "タイプを追加",
|
|
1368
1381
|
"saveFailed": "カスタムタイプを保存できませんでした",
|
|
1369
|
-
"removeFailed": "カスタムタイプを削除できませんでした"
|
|
1382
|
+
"removeFailed": "カスタムタイプを削除できませんでした",
|
|
1383
|
+
"defaultManifestPath": "既定のマニフェストパス(任意)",
|
|
1384
|
+
"defaultManifestPathHelp": "このタイプを固定するサービスに自動入力され、パス自動検出の起点になります。完全なパス(deploy/preview.yaml)またはファイル名のみ。",
|
|
1385
|
+
"fixerPrompt": "修正プロンプト(任意)",
|
|
1386
|
+
"fixerPromptHelp": "マニフェストを生成または修正するためのコーディングエージェントへの指示。設定すると、サービスに「生成 / 修正」ボタンが表示されます。"
|
|
1370
1387
|
},
|
|
1371
1388
|
"handler": {
|
|
1372
1389
|
"intro": "サービスが宣言する各プロビジョニングタイプの処理方法(エンジンと接続)を構成します。サービスのマニフェストや compose パス(何を/どこで)はサービス側で設定します。",
|
|
@@ -3056,6 +3073,7 @@
|
|
|
3056
3073
|
"showLogs": "スタンドアップログを表示",
|
|
3057
3074
|
"hideLogs": "スタンドアップログを非表示"
|
|
3058
3075
|
},
|
|
3076
|
+
"readyBanner": "テスト環境が起動しました。テスターが作業を開始します。",
|
|
3059
3077
|
"footer": "シナリオはTesterが検証対象に選んだ領域(スペックの受け入れシナリオ)です。結果と懸念は名前ごとにその下にグループ化されます。"
|
|
3060
3078
|
},
|
|
3061
3079
|
"visualConfirm": {
|
package/i18n/locales/pl.json
CHANGED
|
@@ -454,6 +454,19 @@
|
|
|
454
454
|
"namespace": "Manifesty ustalają przestrzeń nazw \"{namespace}\"; zaleca się jej przestrzeganie w handlerze przestrzeni roboczej.",
|
|
455
455
|
"confidenceHigh": "Wykryto",
|
|
456
456
|
"confidenceLow": "Sugestia"
|
|
457
|
+
},
|
|
458
|
+
"customManifestPathHint": "Wypełniane wartością domyślną typu po jego wybraniu. Użyj Wykryj, aby znaleźć istniejący manifest w repozytorium.",
|
|
459
|
+
"generateManifest": {
|
|
460
|
+
"title": "Plik manifestu",
|
|
461
|
+
"button": "Generuj / napraw",
|
|
462
|
+
"hint": "Uruchamia agenta kodu, aby utworzyć manifest w tej ścieżce (lub naprawić go, jeśli istnieje, ale jest nieprawidłowy) i wypchnąć go do gałęzi.",
|
|
463
|
+
"error": "Nie udało się rozpocząć generowania manifestu.",
|
|
464
|
+
"dispatched": "Rozpoczęto generowanie manifestu.",
|
|
465
|
+
"status": {
|
|
466
|
+
"running": "Generowanie manifestu…",
|
|
467
|
+
"succeeded": "Manifest wygenerowany i wypchnięty.",
|
|
468
|
+
"failed": "Generowanie manifestu nie powiodło się. Spróbuj ponownie w oknie Infrastruktura."
|
|
469
|
+
}
|
|
457
470
|
}
|
|
458
471
|
},
|
|
459
472
|
"agentConfig": {
|
|
@@ -1815,7 +1828,11 @@
|
|
|
1815
1828
|
"description": "Opis (opcjonalnie)",
|
|
1816
1829
|
"add": "Dodaj typ",
|
|
1817
1830
|
"saveFailed": "Nie udało się zapisać niestandardowego typu",
|
|
1818
|
-
"removeFailed": "Nie udało się usunąć niestandardowego typu"
|
|
1831
|
+
"removeFailed": "Nie udało się usunąć niestandardowego typu",
|
|
1832
|
+
"defaultManifestPath": "Domyślna ścieżka manifestu (opcjonalnie)",
|
|
1833
|
+
"defaultManifestPathHelp": "Wypełniane dla usługi, która przypina ten typ, oraz podstawa automatycznego wykrywania ścieżki. Pełna ścieżka (deploy/preview.yaml) lub sama nazwa pliku.",
|
|
1834
|
+
"fixerPrompt": "Prompt naprawczy (opcjonalnie)",
|
|
1835
|
+
"fixerPromptHelp": "Instrukcje dla agenta kodu do wygenerowania lub naprawy manifestu. Gdy ustawione, usługa pokazuje przycisk Generuj / napraw."
|
|
1819
1836
|
},
|
|
1820
1837
|
"handler": {
|
|
1821
1838
|
"intro": "Skonfiguruj, jak obsługiwany jest każdy typ provisioningu zadeklarowany przez usługę: silnik i połączenie. Manifesty lub ścieżka compose usługi (co/gdzie) są ustawiane na usłudze.",
|
|
@@ -3035,6 +3052,7 @@
|
|
|
3035
3052
|
"blocking": "({count} blokujące) | ({count} blokujące) | ({count} blokujących)"
|
|
3036
3053
|
},
|
|
3037
3054
|
"environment": "Środowisko",
|
|
3055
|
+
"readyBanner": "Środowisko testowe jest gotowe. Tester rozpoczyna pracę.",
|
|
3038
3056
|
"footer": "Scenariusze to obszary, które Tester postanowił sprawdzić (jego scenariusze akceptacyjne ze specyfikacji). Wyniki i zastrzeżenia są pod nimi grupowane według nazwy.",
|
|
3039
3057
|
"infrastructure": "Infrastruktura",
|
|
3040
3058
|
"standup": {
|
package/i18n/locales/tr.json
CHANGED
|
@@ -454,6 +454,19 @@
|
|
|
454
454
|
"namespace": "Manifestler \"{namespace}\" ad alanını sabitliyor; çalışma alanı işleyicisinde buna uymanız önerilir.",
|
|
455
455
|
"confidenceHigh": "Algılandı",
|
|
456
456
|
"confidenceLow": "Öneri"
|
|
457
|
+
},
|
|
458
|
+
"customManifestPathHint": "Türü seçtiğinizde varsayılan değeriyle doldurulur. Depodaki mevcut bir manifesti bulmak için Algıla'yı kullanın.",
|
|
459
|
+
"generateManifest": {
|
|
460
|
+
"title": "Manifest dosyası",
|
|
461
|
+
"button": "Oluştur / düzelt",
|
|
462
|
+
"hint": "Bu yolda manifesti oluşturmak (veya varsa ancak geçersizse düzeltmek) ve dala göndermek için bir kod aracısı çalıştırır.",
|
|
463
|
+
"error": "Manifest oluşturma çalışması başlatılamadı.",
|
|
464
|
+
"dispatched": "Bir manifest oluşturma çalışması başlatıldı.",
|
|
465
|
+
"status": {
|
|
466
|
+
"running": "Manifest oluşturuluyor…",
|
|
467
|
+
"succeeded": "Manifest oluşturuldu ve gönderildi.",
|
|
468
|
+
"failed": "Manifest oluşturma çalışması başarısız oldu. Altyapı penceresinden yeniden deneyin."
|
|
469
|
+
}
|
|
457
470
|
}
|
|
458
471
|
},
|
|
459
472
|
"agentConfig": {
|
|
@@ -1366,7 +1379,11 @@
|
|
|
1366
1379
|
"description": "Açıklama (isteğe bağlı)",
|
|
1367
1380
|
"add": "Tür ekle",
|
|
1368
1381
|
"saveFailed": "Özel tür kaydedilemedi",
|
|
1369
|
-
"removeFailed": "Özel tür kaldırılamadı"
|
|
1382
|
+
"removeFailed": "Özel tür kaldırılamadı",
|
|
1383
|
+
"defaultManifestPath": "Varsayılan manifest yolu (isteğe bağlı)",
|
|
1384
|
+
"defaultManifestPathHelp": "Bu türü sabitleyen bir hizmette önceden doldurulur ve yol otomatik algılamanın temelidir. Tam bir yol (deploy/preview.yaml) veya yalnızca bir dosya adı.",
|
|
1385
|
+
"fixerPrompt": "Düzeltme istemi (isteğe bağlı)",
|
|
1386
|
+
"fixerPromptHelp": "Manifesti oluşturmak veya düzeltmek için kod aracısı talimatları. Ayarlandığında hizmette bir Oluştur / düzelt düğmesi gösterilir."
|
|
1370
1387
|
},
|
|
1371
1388
|
"handler": {
|
|
1372
1389
|
"intro": "Bir servisin bildirdiği her sağlama türünün nasıl ele alınacağını yapılandırın: motor ve bağlantı. Bir servisin manifestleri veya compose yolu (ne/nerede) serviste ayarlanır.",
|
|
@@ -3056,6 +3073,7 @@
|
|
|
3056
3073
|
"showLogs": "Başlatma günlüklerini göster",
|
|
3057
3074
|
"hideLogs": "Başlatma günlüklerini gizle"
|
|
3058
3075
|
},
|
|
3076
|
+
"readyBanner": "Test ortamı hazır. Test aracı çalışmaya başlıyor.",
|
|
3059
3077
|
"footer": "Senaryolar, Tester'ın test etmek için seçtiği alanlardır (spesifikasyon kabul senaryoları). Sonuçlar ve endişeler ada göre bunların altında gruplanır."
|
|
3060
3078
|
},
|
|
3061
3079
|
"visualConfirm": {
|
package/i18n/locales/uk.json
CHANGED
|
@@ -454,6 +454,19 @@
|
|
|
454
454
|
"namespace": "Маніфести фіксують простір імен \"{namespace}\"; рекомендуємо дотримуватися його в обробнику робочого простору.",
|
|
455
455
|
"confidenceHigh": "Виявлено",
|
|
456
456
|
"confidenceLow": "Пропозиція"
|
|
457
|
+
},
|
|
458
|
+
"customManifestPathHint": "Заповнюється значенням типу за замовчуванням під час вибору. Скористайтеся «Виявити», щоб знайти наявний маніфест у репозиторії.",
|
|
459
|
+
"generateManifest": {
|
|
460
|
+
"title": "Файл маніфесту",
|
|
461
|
+
"button": "Згенерувати / виправити",
|
|
462
|
+
"hint": "Запускає агента коду, щоб створити маніфест за цим шляхом (або виправити його, якщо він існує, але недійсний) і надіслати до гілки.",
|
|
463
|
+
"error": "Не вдалося розпочати генерування маніфесту.",
|
|
464
|
+
"dispatched": "Розпочато генерування маніфесту.",
|
|
465
|
+
"status": {
|
|
466
|
+
"running": "Генерування маніфесту…",
|
|
467
|
+
"succeeded": "Маніфест згенеровано та надіслано.",
|
|
468
|
+
"failed": "Генерування маніфесту не вдалося. Повторіть спробу у вікні «Інфраструктура»."
|
|
469
|
+
}
|
|
457
470
|
}
|
|
458
471
|
},
|
|
459
472
|
"agentConfig": {
|
|
@@ -1815,7 +1828,11 @@
|
|
|
1815
1828
|
"description": "Опис (необов'язково)",
|
|
1816
1829
|
"add": "Додати тип",
|
|
1817
1830
|
"saveFailed": "Не вдалося зберегти власний тип",
|
|
1818
|
-
"removeFailed": "Не вдалося видалити власний тип"
|
|
1831
|
+
"removeFailed": "Не вдалося видалити власний тип",
|
|
1832
|
+
"defaultManifestPath": "Типовий шлях маніфесту (необов’язково)",
|
|
1833
|
+
"defaultManifestPathHelp": "Заповнюється для сервісу, який закріплює цей тип, і є основою для автоматичного визначення шляху. Повний шлях (deploy/preview.yaml) або лише ім’я файлу.",
|
|
1834
|
+
"fixerPrompt": "Промпт для виправлення (необов’язково)",
|
|
1835
|
+
"fixerPromptHelp": "Інструкції для агента коду щодо генерування або виправлення маніфесту. Якщо задано, сервіс показує кнопку «Згенерувати / виправити»."
|
|
1819
1836
|
},
|
|
1820
1837
|
"handler": {
|
|
1821
1838
|
"intro": "Налаштуйте, як обробляється кожен тип провіженінгу, оголошений службою: рушій і з'єднання. Маніфести або шлях compose служби (що/де) задаються на службі.",
|
|
@@ -3035,6 +3052,7 @@
|
|
|
3035
3052
|
"blocking": "({count} блокувальне) | ({count} блокувальні) | ({count} блокувальних)"
|
|
3036
3053
|
},
|
|
3037
3054
|
"environment": "Середовище",
|
|
3055
|
+
"readyBanner": "Тестове середовище готове. Тестувальник починає роботу.",
|
|
3038
3056
|
"footer": "Сценарії — це області, які Тестувальник вирішив перевірити (його сценарії приймання зі специфікації). Результати та зауваження групуються під ними за назвою.",
|
|
3039
3057
|
"infrastructure": "Інфраструктура",
|
|
3040
3058
|
"standup": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.68.0",
|
|
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.
|
|
37
|
+
"@cat-factory/contracts": "0.73.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@toad-contracts/testing": "0.3.2",
|