@cat-factory/app 0.309.0 → 0.310.1
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/README.md +11 -2
- package/app/components/assistant/AssistantModal.vue +5 -4
- package/app/components/auth/BackendMisconfiguredScreen.vue +4 -3
- package/app/components/auth/LoginScreen.vue +40 -26
- package/app/components/auth/ResetPasswordScreen.vue +9 -4
- package/app/components/auth/UserMenu.vue +4 -3
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +34 -23
- package/app/components/binaryOutput/StoredAssetView.vue +8 -6
- package/app/components/board/AddTaskModal.vue +16 -15
- package/app/components/board/AgentFailureCard.vue +12 -9
- package/app/components/board/AgentFailureHistory.vue +18 -9
- package/app/components/board/CreateInitiativeModal.vue +5 -4
- package/app/components/board/FailureDetail.vue +22 -12
- package/app/components/board/ReviewFrictionDialog.vue +4 -3
- package/app/components/board/nodes/BlockNode.vue +17 -15
- package/app/components/board/nodes/DecisionBadge.vue +4 -3
- package/app/components/board/nodes/FrameSwimlanes.vue +4 -3
- package/app/components/board/nodes/TaskCard.vue +12 -7
- package/app/components/board/nodes/TaskPipelineMini.vue +9 -7
- package/app/components/bootstrap/AdoptionReviewModal.vue +30 -21
- package/app/components/bootstrap/BootstrapModal.vue +3 -3
- package/app/components/brainstorm/BrainstormWindow.vue +5 -3
- package/app/components/bugFishing/BugFishingWindow.vue +49 -27
- package/app/components/clarity/ClarityReviewWindow.vue +5 -3
- package/app/components/common/CopyButton.vue +12 -11
- package/app/components/common/IconButton.vue +34 -9
- package/app/components/context/ContextAttachmentFields.vue +23 -12
- package/app/components/documents/ContextDocumentPicker.vue +12 -9
- package/app/components/documents/DocumentImportModal.vue +4 -3
- package/app/components/documents/DocumentOriginLink.vue +12 -9
- package/app/components/documents/DocumentSyncState.vue +3 -3
- package/app/components/documents/RepoContextDocPicker.vue +4 -3
- package/app/components/environments/EnvironmentStatusPanel.vue +4 -3
- package/app/components/followUp/FollowUpWindow.vue +9 -6
- package/app/components/forkDecision/ForkDecisionWindow.vue +71 -80
- package/app/components/foundational/FoundationalServiceCatalogList.vue +3 -2
- package/app/components/foundational/FoundationalServiceRegistry.vue +7 -6
- package/app/components/foundational/FoundationalServiceSources.vue +7 -6
- package/app/components/fragments/FragmentLibraryManager.vue +5 -4
- package/app/components/fragments/FragmentSelector.vue +12 -9
- package/app/components/gates/GateFailingCheckList.vue +4 -3
- package/app/components/gates/GateResultView.vue +17 -12
- package/app/components/github/AddServiceFromRepoModal.vue +11 -7
- package/app/components/github/GitHubOnboarding.vue +7 -2
- package/app/components/github/GitHubPanel.vue +9 -6
- package/app/components/github/RepoTreeBrowser.vue +15 -12
- package/app/components/humanTest/HumanTestWindow.vue +13 -9
- package/app/components/initiative/InitiativePlanReview.vue +28 -18
- package/app/components/initiative/InitiativeTrackerWindow.vue +171 -124
- package/app/components/judge/JudgeResultView.vue +5 -3
- package/app/components/kaizen/KaizenPanel.vue +67 -53
- package/app/components/layout/AccountTeamSettings.vue +9 -9
- package/app/components/layout/AppearanceSwitcher.vue +4 -3
- package/app/components/layout/BoardSwitcher.vue +10 -8
- package/app/components/layout/BoardToolbar.vue +5 -4
- package/app/components/layout/CommandBar.vue +4 -3
- package/app/components/layout/DefaultTestEnvBanner.vue +4 -3
- package/app/components/layout/IntegrationsHub.vue +8 -6
- package/app/components/layout/LanguageSwitcher.vue +4 -3
- package/app/components/layout/ModelProvidersHub.vue +4 -3
- package/app/components/layout/NotificationsInbox.vue +40 -30
- package/app/components/layout/PersonalSetupModal.vue +4 -3
- package/app/components/layout/RolePrompt.vue +4 -3
- package/app/components/layout/SideBar.vue +4 -3
- package/app/components/layout/TranslationWarningBanner.vue +4 -3
- package/app/components/layout/UiModeSwitcher.vue +8 -6
- package/app/components/layout/UiRoleSwitcher.vue +8 -6
- package/app/components/layout/WorkspaceMembersSettings.vue +2 -2
- package/app/components/media/ArtifactLightbox.vue +69 -39
- package/app/components/media/ImageCompare.vue +69 -74
- package/app/components/observability/OutcomeFilterChips.vue +5 -4
- package/app/components/observability/RunFailureSummary.vue +8 -6
- package/app/components/observability/StepModelActivity.vue +5 -3
- package/app/components/observability/ToolCallList.vue +4 -2
- package/app/components/outcome/OutcomeSummaryWindow.vue +5 -4
- package/app/components/palettes/AgentPalette.vue +18 -14
- package/app/components/panels/AgentStepDetail.vue +30 -19
- package/app/components/panels/ObservabilityPanel.vue +149 -114
- package/app/components/panels/OperatorDashboardPanel.vue +99 -91
- package/app/components/panels/ReportsPanel.vue +64 -61
- package/app/components/panels/ResultWindowShell.vue +148 -134
- package/app/components/panels/StepContainerStatus.vue +9 -9
- package/app/components/panels/StepDelegatedStatus.vue +11 -9
- package/app/components/panels/StepRestartControl.vue +3 -2
- package/app/components/panels/inspector/EpicChildren.vue +4 -3
- package/app/components/panels/inspector/FrontendConfig.vue +3 -2
- package/app/components/panels/inspector/InspectorSection.vue +22 -17
- package/app/components/panels/inspector/ServiceConnections.vue +3 -2
- package/app/components/panels/inspector/ServiceTestConfig.vue +5 -4
- package/app/components/panels/inspector/TaskExecution.vue +5 -4
- package/app/components/panels/inspector/TaskRunSettings.vue +10 -6
- package/app/components/pipeline/EstimateThresholdFields.vue +13 -10
- package/app/components/pipeline/GateConfigFields.vue +14 -18
- package/app/components/pipeline/PipelineBuilder.vue +90 -77
- package/app/components/pipeline/PipelinePicker.vue +8 -6
- package/app/components/pipeline/PipelineProgress.vue +26 -21
- package/app/components/prReview/PrReviewWindow.vue +46 -25
- package/app/components/providers/ApiKeysSection.vue +4 -3
- package/app/components/ralph/RalphLoopResultView.vue +4 -3
- package/app/components/requirements/RequirementsReviewWindow.vue +10 -6
- package/app/components/riskPolicy/RiskPolicyPicker.vue +8 -6
- package/app/components/sandbox/SandboxPanel.vue +73 -54
- package/app/components/settings/CloudflareHandlerSection.vue +33 -30
- package/app/components/settings/ConsensusGroupsSection.vue +40 -30
- package/app/components/settings/InfraHandlersConfigurator.vue +16 -13
- package/app/components/settings/InfrastructureBackendPicker.vue +17 -17
- package/app/components/settings/IssueTrackerPanel.vue +21 -6
- package/app/components/settings/LocalModelEndpointsPanel.vue +3 -2
- package/app/components/settings/ModelConfigurationPanel.vue +9 -8
- package/app/components/settings/OpenRouterCatalogPanel.vue +4 -3
- package/app/components/settings/ProviderPreferenceEditor.vue +5 -6
- package/app/components/settings/RiskPolicyEditorRow.vue +3 -2
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +10 -8
- package/app/components/skills/ReviewSkillQueue.vue +4 -3
- package/app/components/skills/SkillLibraryManager.vue +7 -6
- package/app/components/slack/SlackPanel.vue +9 -5
- package/app/components/spec/ServiceSpecWindow.vue +4 -3
- package/app/components/tasks/ContextIssuePicker.vue +12 -9
- package/app/components/tasks/TaskContextIssues.vue +4 -3
- package/app/components/testing/TestReportWindow.vue +14 -8
- package/app/components/theme/ThemeImportModal.vue +2 -2
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +62 -35
- package/i18n/locales/de.json +7 -3
- package/i18n/locales/en.json +7 -3
- package/i18n/locales/es.json +7 -3
- package/i18n/locales/fr.json +7 -3
- package/i18n/locales/he.json +7 -3
- package/i18n/locales/it.json +7 -3
- package/i18n/locales/ja.json +7 -3
- package/i18n/locales/pl.json +7 -3
- package/i18n/locales/tr.json +7 -3
- package/i18n/locales/uk.json +7 -3
- package/package.json +2 -2
|
@@ -237,40 +237,43 @@ async function remove() {
|
|
|
237
237
|
</p>
|
|
238
238
|
</div>
|
|
239
239
|
|
|
240
|
-
<
|
|
241
|
-
<
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
240
|
+
<UCollapsible class="rounded-md border border-muted/70 p-2">
|
|
241
|
+
<template #default="{ open }">
|
|
242
|
+
<UButton
|
|
243
|
+
variant="link"
|
|
244
|
+
color="neutral"
|
|
245
|
+
size="xs"
|
|
246
|
+
:icon="open ? 'i-lucide-chevron-down' : 'i-lucide-chevron-right'"
|
|
247
|
+
:label="t('settings.infrastructure.cloudflare.advanced')"
|
|
248
|
+
:ui="{ base: 'w-full justify-start gap-1 p-0 text-2xs text-muted' }"
|
|
249
|
+
/>
|
|
250
|
+
</template>
|
|
251
|
+
<template #content>
|
|
252
|
+
<div class="mt-2 space-y-2">
|
|
249
253
|
<!-- The placeholder is a FORMAT EXAMPLE containing vue-i18n metacharacters, so it
|
|
250
254
|
stays inline rather than becoming a catalog key. -->
|
|
251
|
-
<
|
|
252
|
-
|
|
255
|
+
<UFormField size="xs" :label="t('settings.infrastructure.cloudflare.workerTemplate')">
|
|
256
|
+
<UInput
|
|
257
|
+
v-model="workerNameTemplate"
|
|
258
|
+
size="xs"
|
|
259
|
+
placeholder="cat-factory-pr-{{pullNumber}}"
|
|
260
|
+
/>
|
|
261
|
+
</UFormField>
|
|
262
|
+
<UFormField
|
|
253
263
|
size="xs"
|
|
254
|
-
|
|
255
|
-
|
|
264
|
+
:label="t('settings.infrastructure.cloudflare.environmentTemplate')"
|
|
265
|
+
>
|
|
266
|
+
<UInput v-model="environmentNameTemplate" size="xs" placeholder="pr-{{pullNumber}}" />
|
|
267
|
+
</UFormField>
|
|
268
|
+
<p class="text-2xs text-dimmed">
|
|
269
|
+
{{ t('settings.infrastructure.cloudflare.templateHint') }}
|
|
270
|
+
</p>
|
|
271
|
+
<UFormField size="xs" :label="t('settings.infrastructure.cloudflare.apiBaseUrl')">
|
|
272
|
+
<UInput v-model="apiBaseUrl" size="xs" placeholder="https://api.github.com" />
|
|
273
|
+
</UFormField>
|
|
256
274
|
</div>
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
t('settings.infrastructure.cloudflare.environmentTemplate')
|
|
260
|
-
}}</label>
|
|
261
|
-
<UInput v-model="environmentNameTemplate" size="xs" placeholder="pr-{{pullNumber}}" />
|
|
262
|
-
</div>
|
|
263
|
-
<p class="text-2xs text-dimmed">
|
|
264
|
-
{{ t('settings.infrastructure.cloudflare.templateHint') }}
|
|
265
|
-
</p>
|
|
266
|
-
<div class="space-y-1">
|
|
267
|
-
<label class="text-2xs text-muted">{{
|
|
268
|
-
t('settings.infrastructure.cloudflare.apiBaseUrl')
|
|
269
|
-
}}</label>
|
|
270
|
-
<UInput v-model="apiBaseUrl" size="xs" placeholder="https://api.github.com" />
|
|
271
|
-
</div>
|
|
272
|
-
</div>
|
|
273
|
-
</details>
|
|
275
|
+
</template>
|
|
276
|
+
</UCollapsible>
|
|
274
277
|
|
|
275
278
|
<div class="flex items-center gap-2">
|
|
276
279
|
<UButton size="xs" :disabled="!canSave || busy" @click="save">
|
|
@@ -14,6 +14,7 @@ import type { ConsensusGroup, ConsensusStrategy } from '~/types/consensus'
|
|
|
14
14
|
import { isSelectable } from '~/stores/models'
|
|
15
15
|
import { uid } from '~/utils/catalog'
|
|
16
16
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
17
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
17
18
|
|
|
18
19
|
const { t } = useI18n()
|
|
19
20
|
const groups = useConsensusGroupsStore()
|
|
@@ -116,6 +117,17 @@ const selectableModelIds = computed(() => {
|
|
|
116
117
|
.map((m) => ({ id: m.id, label: m.label }))
|
|
117
118
|
})
|
|
118
119
|
|
|
120
|
+
// "Inherit the step's model" is a NAMED sentinel in the picker, never an empty string and never
|
|
121
|
+
// `undefined`: a Select reserves both for "nothing selected", so an item carrying one either
|
|
122
|
+
// throws (empty string) or renders the placeholder over its own label (undefined). One item list
|
|
123
|
+
// serves both pickers; each binding below maps the sentinel to what its field holds on the wire,
|
|
124
|
+
// which is `undefined` for a participant and an empty string for the synthesizer.
|
|
125
|
+
const STEP_MODEL = '__step__'
|
|
126
|
+
const modelItems = computed(() => [
|
|
127
|
+
{ label: t('settings.consensusGroups.editor.stepModel'), value: STEP_MODEL },
|
|
128
|
+
...selectableModelIds.value.map((m) => ({ label: m.label, value: m.id })),
|
|
129
|
+
])
|
|
130
|
+
|
|
119
131
|
/**
|
|
120
132
|
* A threshold field's value as the contract wants it, or undefined when the author left it blank.
|
|
121
133
|
*
|
|
@@ -246,21 +258,21 @@ async function remove(group: ConsensusGroup) {
|
|
|
246
258
|
<span class="truncate text-sm font-semibold text-app-100">{{ g.name }}</span>
|
|
247
259
|
<UBadge color="neutral" variant="subtle" size="xs">{{ barLabel(g) }}</UBadge>
|
|
248
260
|
<div class="ms-auto flex items-center gap-1">
|
|
249
|
-
<
|
|
261
|
+
<IconButton
|
|
250
262
|
size="xs"
|
|
251
263
|
variant="ghost"
|
|
252
264
|
color="neutral"
|
|
253
265
|
icon="i-lucide-pencil"
|
|
254
|
-
:
|
|
266
|
+
:label="t('settings.consensusGroups.list.editTitle')"
|
|
255
267
|
@click="startEdit(g)"
|
|
256
268
|
/>
|
|
257
|
-
<
|
|
269
|
+
<IconButton
|
|
258
270
|
size="xs"
|
|
259
271
|
variant="ghost"
|
|
260
272
|
color="error"
|
|
261
273
|
icon="i-lucide-trash-2"
|
|
262
274
|
:loading="busy"
|
|
263
|
-
:
|
|
275
|
+
:label="t('settings.consensusGroups.list.deleteTitle')"
|
|
264
276
|
@click="remove(g)"
|
|
265
277
|
/>
|
|
266
278
|
</div>
|
|
@@ -302,12 +314,7 @@ async function remove(group: ConsensusGroup) {
|
|
|
302
314
|
<SectionLabel as="label" class="mb-1 block">
|
|
303
315
|
{{ t('settings.consensusGroups.editor.strategyLabel') }}
|
|
304
316
|
</SectionLabel>
|
|
305
|
-
<
|
|
306
|
-
v-model="editor.strategy"
|
|
307
|
-
class="w-full rounded-sm border border-muted bg-default px-2 py-1.5 text-sm text-app-100"
|
|
308
|
-
>
|
|
309
|
-
<option v-for="s in STRATEGIES" :key="s.value" :value="s.value">{{ s.label }}</option>
|
|
310
|
-
</select>
|
|
317
|
+
<USelect v-model="editor.strategy" :items="STRATEGIES" size="sm" class="w-full" />
|
|
311
318
|
</div>
|
|
312
319
|
</div>
|
|
313
320
|
|
|
@@ -358,20 +365,20 @@ async function remove(group: ConsensusGroup) {
|
|
|
358
365
|
class="min-w-40 flex-1"
|
|
359
366
|
:placeholder="t('settings.consensusGroups.editor.framingPlaceholder')"
|
|
360
367
|
/>
|
|
361
|
-
<
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
<
|
|
368
|
+
<USelect
|
|
369
|
+
:model-value="p.modelId || STEP_MODEL"
|
|
370
|
+
:items="modelItems"
|
|
371
|
+
size="xs"
|
|
372
|
+
class="w-44"
|
|
373
|
+
@update:model-value="p.modelId = $event === STEP_MODEL ? undefined : String($event)"
|
|
374
|
+
/>
|
|
375
|
+
<IconButton
|
|
369
376
|
icon="i-lucide-x"
|
|
370
377
|
color="error"
|
|
371
378
|
variant="ghost"
|
|
372
379
|
size="xs"
|
|
373
380
|
:disabled="editor.participants.length <= 2"
|
|
374
|
-
:
|
|
381
|
+
:label="t('pipeline.builder.removeParticipant')"
|
|
375
382
|
@click="removeParticipant(index)"
|
|
376
383
|
/>
|
|
377
384
|
</div>
|
|
@@ -382,13 +389,15 @@ async function remove(group: ConsensusGroup) {
|
|
|
382
389
|
<SectionLabel as="label" class="mb-1 block">
|
|
383
390
|
{{ t('settings.consensusGroups.editor.synthesizerLabel') }}
|
|
384
391
|
</SectionLabel>
|
|
385
|
-
<
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
+
<USelect
|
|
393
|
+
:model-value="editor.synthesizerModelId || STEP_MODEL"
|
|
394
|
+
:items="modelItems"
|
|
395
|
+
size="sm"
|
|
396
|
+
class="w-full"
|
|
397
|
+
@update:model-value="
|
|
398
|
+
editor.synthesizerModelId = $event === STEP_MODEL ? '' : String($event)
|
|
399
|
+
"
|
|
400
|
+
/>
|
|
392
401
|
</div>
|
|
393
402
|
<div v-if="editor.strategy === 'debate'">
|
|
394
403
|
<SectionLabel as="label" class="mb-1 block">
|
|
@@ -400,10 +409,11 @@ async function remove(group: ConsensusGroup) {
|
|
|
400
409
|
|
|
401
410
|
<!-- the estimate bar -->
|
|
402
411
|
<div class="space-y-2 rounded-lg border border-default bg-app-950/40 p-3">
|
|
403
|
-
<
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
412
|
+
<UCheckbox
|
|
413
|
+
v-model="editor.gated"
|
|
414
|
+
size="xs"
|
|
415
|
+
:label="t('settings.consensusGroups.editor.gatedLabel')"
|
|
416
|
+
/>
|
|
407
417
|
<p class="text-2xs text-dimmed">
|
|
408
418
|
{{ t('settings.consensusGroups.editor.gatedHint') }}
|
|
409
419
|
</p>
|
|
@@ -514,21 +514,24 @@ function toastRemoved() {
|
|
|
514
514
|
|
|
515
515
|
<!-- Local mode: a personal override for THIS machine, layered over the workspace handler. -->
|
|
516
516
|
<div v-if="userOverridesOn" class="border-t border-default pt-2">
|
|
517
|
-
<
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
class="
|
|
517
|
+
<UButton
|
|
518
|
+
color="neutral"
|
|
519
|
+
variant="link"
|
|
520
|
+
class="group w-full p-0"
|
|
521
|
+
:aria-expanded="showKubeOverride"
|
|
521
522
|
@click="showKubeOverride = !showKubeOverride"
|
|
522
523
|
>
|
|
523
|
-
<
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
524
|
+
<SectionLabel as="span" class="flex w-full items-center gap-1.5 group-hover:text-default">
|
|
525
|
+
<UIcon
|
|
526
|
+
:name="showKubeOverride ? 'i-lucide-chevron-down' : 'i-lucide-chevron-right'"
|
|
527
|
+
class="h-3.5 w-3.5"
|
|
528
|
+
/>
|
|
529
|
+
{{ t('settings.infrastructure.handler.personalOverride') }}
|
|
530
|
+
<UBadge v-if="kubeUserHandler" color="primary" variant="subtle" size="sm">
|
|
531
|
+
{{ t('settings.infrastructure.handler.overrideActive') }}
|
|
532
|
+
</UBadge>
|
|
533
|
+
</SectionLabel>
|
|
534
|
+
</UButton>
|
|
532
535
|
<div v-if="showKubeOverride" class="mt-2 space-y-2">
|
|
533
536
|
<p class="text-2xs text-dimmed">
|
|
534
537
|
{{ t('settings.infrastructure.handler.personalOverrideHint') }}
|
|
@@ -199,6 +199,16 @@ const items = computed<PickerItem[]>(() => {
|
|
|
199
199
|
return out
|
|
200
200
|
})
|
|
201
201
|
|
|
202
|
+
// The same list in the shape URadioGroup reads. `desc` is optional on a PickerItem and an empty
|
|
203
|
+
// string renders an empty description line, so it is dropped rather than passed through blank.
|
|
204
|
+
const backendItems = computed(() =>
|
|
205
|
+
items.value.map((item) => ({
|
|
206
|
+
value: item.id,
|
|
207
|
+
label: item.label,
|
|
208
|
+
...(item.desc ? { description: item.desc } : {}),
|
|
209
|
+
})),
|
|
210
|
+
)
|
|
211
|
+
|
|
202
212
|
// The active-line label: prefer the registered connection's concrete kind over the generic
|
|
203
213
|
// "delegated" label so "Active: Kubernetes cluster" reads truthfully.
|
|
204
214
|
const activeLabel = computed(() => {
|
|
@@ -275,23 +285,13 @@ const labelKey = computed(() =>
|
|
|
275
285
|
{{ t('settings.infrastructure.active', { backend: activeLabel }) }}
|
|
276
286
|
</p>
|
|
277
287
|
|
|
278
|
-
<
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
:disabled="saving"
|
|
286
|
-
:data-testid="`${axis}-backend-${item.id}`"
|
|
287
|
-
@change="select(item.id)"
|
|
288
|
-
/>
|
|
289
|
-
<span class="min-w-0">
|
|
290
|
-
<span class="text-sm text-default">{{ item.label }}</span>
|
|
291
|
-
<span v-if="item.desc" class="block text-2xs text-muted">{{ item.desc }}</span>
|
|
292
|
-
</span>
|
|
293
|
-
</label>
|
|
294
|
-
</div>
|
|
288
|
+
<URadioGroup
|
|
289
|
+
:model-value="selected"
|
|
290
|
+
:items="backendItems"
|
|
291
|
+
:disabled="saving"
|
|
292
|
+
:data-testid="`${axis}-backend-options`"
|
|
293
|
+
@update:model-value="select(String($event))"
|
|
294
|
+
/>
|
|
295
295
|
|
|
296
296
|
<p v-if="showRegisterHint" class="text-2xs text-app-warning-300/80">
|
|
297
297
|
{{ t('settings.infrastructure.registerHint') }}
|
|
@@ -272,18 +272,28 @@ async function checkSetup(source: TaskSourceKind) {
|
|
|
272
272
|
<p v-if="trackerKind === 'github' && !githubAvailable" class="text-2xs text-app-warning-400">
|
|
273
273
|
<i18n-t keypath="settings.issueTracker.filing.githubHint" tag="span" scope="global">
|
|
274
274
|
<template #link>
|
|
275
|
-
<
|
|
275
|
+
<UButton
|
|
276
|
+
color="neutral"
|
|
277
|
+
variant="link"
|
|
278
|
+
class="p-0 text-2xs underline"
|
|
279
|
+
@click="ui.openGitHub()"
|
|
280
|
+
>
|
|
276
281
|
{{ t('settings.issueTracker.filing.githubHintLink') }}
|
|
277
|
-
</
|
|
282
|
+
</UButton>
|
|
278
283
|
</template>
|
|
279
284
|
</i18n-t>
|
|
280
285
|
</p>
|
|
281
286
|
<p v-else-if="trackerKind === 'jira' && !jiraConnected" class="text-2xs text-app-warning-400">
|
|
282
287
|
<i18n-t keypath="settings.issueTracker.filing.jiraHint" tag="span" scope="global">
|
|
283
288
|
<template #link>
|
|
284
|
-
<
|
|
289
|
+
<UButton
|
|
290
|
+
color="neutral"
|
|
291
|
+
variant="link"
|
|
292
|
+
class="p-0 text-2xs underline"
|
|
293
|
+
@click="ui.openTaskConnect('jira')"
|
|
294
|
+
>
|
|
285
295
|
{{ t('settings.issueTracker.filing.connectLink') }}
|
|
286
|
-
</
|
|
296
|
+
</UButton>
|
|
287
297
|
</template>
|
|
288
298
|
</i18n-t>
|
|
289
299
|
</p>
|
|
@@ -293,9 +303,14 @@ async function checkSetup(source: TaskSourceKind) {
|
|
|
293
303
|
>
|
|
294
304
|
<i18n-t keypath="settings.issueTracker.filing.linearHint" tag="span" scope="global">
|
|
295
305
|
<template #link>
|
|
296
|
-
<
|
|
306
|
+
<UButton
|
|
307
|
+
color="neutral"
|
|
308
|
+
variant="link"
|
|
309
|
+
class="p-0 text-2xs underline"
|
|
310
|
+
@click="ui.openTaskConnect('linear')"
|
|
311
|
+
>
|
|
297
312
|
{{ t('settings.issueTracker.filing.connectLink') }}
|
|
298
|
-
</
|
|
313
|
+
</UButton>
|
|
299
314
|
</template>
|
|
300
315
|
</i18n-t>
|
|
301
316
|
</p>
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
|
|
19
19
|
import SecretInput from '~/components/common/SecretInput.vue'
|
|
20
20
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
21
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
21
22
|
|
|
22
23
|
const { t } = useI18n()
|
|
23
24
|
const ui = useUiStore()
|
|
@@ -331,13 +332,13 @@ async function remove(p: LocalRunner) {
|
|
|
331
332
|
</div>
|
|
332
333
|
</div>
|
|
333
334
|
<div class="flex items-center gap-1">
|
|
334
|
-
<
|
|
335
|
+
<IconButton
|
|
335
336
|
icon="i-lucide-pencil"
|
|
336
337
|
color="neutral"
|
|
337
338
|
variant="ghost"
|
|
338
339
|
size="xs"
|
|
339
340
|
:disabled="busy"
|
|
340
|
-
:
|
|
341
|
+
:label="t('settings.localModelEndpoints.edit')"
|
|
341
342
|
@click="selectRunner(e.provider)"
|
|
342
343
|
/>
|
|
343
344
|
<UButton
|
|
@@ -23,6 +23,7 @@ import ConsensusGroupsSection from '~/components/settings/ConsensusGroupsSection
|
|
|
23
23
|
import ProviderPreferenceEditor from '~/components/settings/ProviderPreferenceEditor.vue'
|
|
24
24
|
import { showOverrideField } from '~/utils/uiMode'
|
|
25
25
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
26
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
26
27
|
|
|
27
28
|
const { t } = useI18n()
|
|
28
29
|
const ui = useUiStore()
|
|
@@ -331,13 +332,13 @@ async function save() {
|
|
|
331
332
|
>
|
|
332
333
|
{{ t('settings.modelConfiguration.back') }}
|
|
333
334
|
</UButton>
|
|
334
|
-
<
|
|
335
|
+
<IconButton
|
|
335
336
|
icon="i-lucide-x"
|
|
336
337
|
color="neutral"
|
|
337
338
|
variant="ghost"
|
|
338
339
|
size="sm"
|
|
339
340
|
:class="editor ? '' : 'ms-auto'"
|
|
340
|
-
:
|
|
341
|
+
:label="t('settings.modelConfiguration.closeEsc')"
|
|
341
342
|
@click="
|
|
342
343
|
() => {
|
|
343
344
|
open = false
|
|
@@ -391,32 +392,32 @@ async function save() {
|
|
|
391
392
|
{{ t('settings.modelConfiguration.list.default') }}
|
|
392
393
|
</UBadge>
|
|
393
394
|
<div class="ms-auto flex items-center gap-1">
|
|
394
|
-
<
|
|
395
|
+
<IconButton
|
|
395
396
|
v-if="!p.isDefault"
|
|
396
397
|
size="xs"
|
|
397
398
|
variant="ghost"
|
|
398
399
|
color="neutral"
|
|
399
400
|
icon="i-lucide-star"
|
|
400
401
|
:loading="busy"
|
|
401
|
-
:
|
|
402
|
+
:label="t('settings.modelConfiguration.list.setDefaultTitle')"
|
|
402
403
|
@click="setDefault(p)"
|
|
403
404
|
/>
|
|
404
|
-
<
|
|
405
|
+
<IconButton
|
|
405
406
|
size="xs"
|
|
406
407
|
variant="ghost"
|
|
407
408
|
color="neutral"
|
|
408
409
|
icon="i-lucide-pencil"
|
|
409
|
-
:
|
|
410
|
+
:label="t('settings.modelConfiguration.list.editTitle')"
|
|
410
411
|
@click="startEdit(p)"
|
|
411
412
|
/>
|
|
412
|
-
<
|
|
413
|
+
<IconButton
|
|
413
414
|
size="xs"
|
|
414
415
|
variant="ghost"
|
|
415
416
|
color="error"
|
|
416
417
|
icon="i-lucide-trash-2"
|
|
417
418
|
:disabled="p.isDefault"
|
|
418
419
|
:loading="busy"
|
|
419
|
-
:
|
|
420
|
+
:label="
|
|
420
421
|
p.isDefault
|
|
421
422
|
? t('settings.modelConfiguration.list.deleteDisabledTitle')
|
|
422
423
|
: t('settings.modelConfiguration.list.deleteTitle')
|
|
@@ -247,12 +247,13 @@ function manageKeys() {
|
|
|
247
247
|
<li>
|
|
248
248
|
<i18n-t keypath="settings.openRouterCatalog.step1" tag="span" scope="global">
|
|
249
249
|
<template #link>
|
|
250
|
-
<
|
|
251
|
-
|
|
250
|
+
<ULink
|
|
251
|
+
raw
|
|
252
|
+
to="https://openrouter.ai/keys"
|
|
252
253
|
target="_blank"
|
|
253
254
|
rel="noopener noreferrer"
|
|
254
255
|
class="text-primary underline"
|
|
255
|
-
>{{ t('settings.openRouterCatalog.step1Link') }}</
|
|
256
|
+
>{{ t('settings.openRouterCatalog.step1Link') }}</ULink
|
|
256
257
|
>
|
|
257
258
|
</template>
|
|
258
259
|
</i18n-t>
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
subscriptionOverridesOrder,
|
|
28
28
|
} from '~/components/settings/ProviderPreferenceEditor.logic'
|
|
29
29
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
30
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
30
31
|
|
|
31
32
|
const props = defineProps<{
|
|
32
33
|
/** The preset's stored order; empty/absent ⇒ the deployment's default order. */
|
|
@@ -154,24 +155,22 @@ function reset() {
|
|
|
154
155
|
<p class="truncate text-2xs text-dimmed">{{ t(ROUTE_HINTS[flavor]) }}</p>
|
|
155
156
|
</div>
|
|
156
157
|
<div class="flex shrink-0 items-center gap-1">
|
|
157
|
-
<
|
|
158
|
+
<IconButton
|
|
158
159
|
size="xs"
|
|
159
160
|
variant="ghost"
|
|
160
161
|
color="neutral"
|
|
161
162
|
icon="i-lucide-chevron-up"
|
|
162
163
|
:disabled="index === 0"
|
|
163
|
-
:
|
|
164
|
-
:aria-label="t('settings.modelConfiguration.routeOrder.moveUp')"
|
|
164
|
+
:label="t('settings.modelConfiguration.routeOrder.moveUp')"
|
|
165
165
|
@click="move(index, -1)"
|
|
166
166
|
/>
|
|
167
|
-
<
|
|
167
|
+
<IconButton
|
|
168
168
|
size="xs"
|
|
169
169
|
variant="ghost"
|
|
170
170
|
color="neutral"
|
|
171
171
|
icon="i-lucide-chevron-down"
|
|
172
172
|
:disabled="index === order.length - 1"
|
|
173
|
-
:
|
|
174
|
-
:aria-label="t('settings.modelConfiguration.routeOrder.moveDown')"
|
|
173
|
+
:label="t('settings.modelConfiguration.routeOrder.moveDown')"
|
|
175
174
|
@click="move(index, 1)"
|
|
176
175
|
/>
|
|
177
176
|
</div>
|
|
@@ -24,6 +24,7 @@ import { RISK_POLICY_AXES, RISK_POLICY_CEILING_FIELD } from '~/utils/riskPolicy'
|
|
|
24
24
|
import MergeClassRulesEditor from '~/components/settings/MergeClassRulesEditor.vue'
|
|
25
25
|
import MergeRolePolicyEditor from '~/components/settings/MergeRolePolicyEditor.vue'
|
|
26
26
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
27
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
27
28
|
|
|
28
29
|
const props = defineProps<{
|
|
29
30
|
policy: RiskPolicyLibraryEntry
|
|
@@ -144,13 +145,13 @@ const deleteBlocked = computed(
|
|
|
144
145
|
{{ t('settings.riskPolicy.makeDefault') }}
|
|
145
146
|
</UButton>
|
|
146
147
|
</template>
|
|
147
|
-
<
|
|
148
|
+
<IconButton
|
|
148
149
|
color="error"
|
|
149
150
|
variant="ghost"
|
|
150
151
|
size="xs"
|
|
151
152
|
icon="i-lucide-trash-2"
|
|
152
153
|
:disabled="deleteBlocked || busy?.startsWith(policy.id)"
|
|
153
|
-
:
|
|
154
|
+
:label="deleteBlockedReason"
|
|
154
155
|
@click="emit('remove')"
|
|
155
156
|
/>
|
|
156
157
|
</div>
|
|
@@ -99,20 +99,22 @@ function remove(id: string) {
|
|
|
99
99
|
<span class="text-dimmed">
|
|
100
100
|
{{ t('settings.serviceFragmentDefaults.footer.question') }}
|
|
101
101
|
</span>
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
<UButton
|
|
103
|
+
color="primary"
|
|
104
|
+
variant="link"
|
|
105
|
+
class="p-0 text-2xs font-medium text-primary hover:underline"
|
|
105
106
|
@click="ui.openFragmentLibrary()"
|
|
106
107
|
>
|
|
107
108
|
{{ t('settings.serviceFragmentDefaults.footer.manageBoard') }}
|
|
108
|
-
</
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
</UButton>
|
|
110
|
+
<UButton
|
|
111
|
+
color="primary"
|
|
112
|
+
variant="link"
|
|
113
|
+
class="p-0 text-2xs font-medium text-primary hover:underline"
|
|
112
114
|
@click="ui.openAccountSettings('fragments')"
|
|
113
115
|
>
|
|
114
116
|
{{ t('settings.serviceFragmentDefaults.footer.manageAccount') }}
|
|
115
|
-
</
|
|
117
|
+
</UButton>
|
|
116
118
|
</div>
|
|
117
119
|
</div>
|
|
118
120
|
</template>
|
|
@@ -84,10 +84,11 @@ function toggle(id: string) {
|
|
|
84
84
|
>
|
|
85
85
|
<div class="min-h-0 flex-1 overflow-y-auto p-1">
|
|
86
86
|
<template v-if="offered.length">
|
|
87
|
-
<
|
|
87
|
+
<UButton
|
|
88
|
+
color="neutral"
|
|
89
|
+
variant="ghost"
|
|
88
90
|
v-for="s in offered"
|
|
89
91
|
:key="s.id"
|
|
90
|
-
type="button"
|
|
91
92
|
class="flex w-full items-start gap-2 rounded-sm px-2 py-1.5 text-start text-sm hover:bg-elevated/60 disabled:cursor-not-allowed disabled:opacity-40"
|
|
92
93
|
:class="selectedSet.has(s.id) ? 'text-app-100' : 'text-toned'"
|
|
93
94
|
:disabled="atCap && !selectedSet.has(s.id)"
|
|
@@ -106,7 +107,7 @@ function toggle(id: string) {
|
|
|
106
107
|
{{ s.description }}
|
|
107
108
|
</span>
|
|
108
109
|
</span>
|
|
109
|
-
</
|
|
110
|
+
</UButton>
|
|
110
111
|
</template>
|
|
111
112
|
<p v-else class="px-2 py-3 text-xs text-dimmed">
|
|
112
113
|
{{ t('skills.reviewQueue.pickerEmpty') }}
|
|
@@ -12,6 +12,7 @@ import { useSkillLibrary } from '~/stores/skillLibrary'
|
|
|
12
12
|
import { SKILL_GROUP_LABEL_KEYS } from '~/utils/skills'
|
|
13
13
|
import GitHubRepoSearchSelect from '~/components/github/GitHubRepoSearchSelect.vue'
|
|
14
14
|
import RepoTreeBrowser from '~/components/github/RepoTreeBrowser.vue'
|
|
15
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
15
16
|
|
|
16
17
|
const props = defineProps<{ accountId: string }>()
|
|
17
18
|
|
|
@@ -234,29 +235,29 @@ async function unlinkSource(id: string) {
|
|
|
234
235
|
{{ t('skills.sources.changes') }}
|
|
235
236
|
</UBadge>
|
|
236
237
|
<div class="ms-auto flex gap-1">
|
|
237
|
-
<
|
|
238
|
+
<IconButton
|
|
238
239
|
icon="i-lucide-search-check"
|
|
239
240
|
size="xs"
|
|
240
241
|
variant="ghost"
|
|
241
242
|
:loading="rowBusy(`check:${s.id}`)"
|
|
242
|
-
:
|
|
243
|
+
:label="t('skills.sources.check')"
|
|
243
244
|
@click="checkSource(s.id)"
|
|
244
245
|
/>
|
|
245
|
-
<
|
|
246
|
+
<IconButton
|
|
246
247
|
icon="i-lucide-refresh-cw"
|
|
247
248
|
size="xs"
|
|
248
249
|
variant="ghost"
|
|
249
250
|
:loading="rowBusy(`sync:${s.id}`)"
|
|
250
|
-
:
|
|
251
|
+
:label="t('skills.sources.sync')"
|
|
251
252
|
@click="syncSource(s.id)"
|
|
252
253
|
/>
|
|
253
|
-
<
|
|
254
|
+
<IconButton
|
|
254
255
|
icon="i-lucide-unplug"
|
|
255
256
|
size="xs"
|
|
256
257
|
color="error"
|
|
257
258
|
variant="ghost"
|
|
258
259
|
:loading="rowBusy(`unlink:${s.id}`)"
|
|
259
|
-
:
|
|
260
|
+
:label="t('skills.sources.unlink')"
|
|
260
261
|
@click="unlinkSource(s.id)"
|
|
261
262
|
/>
|
|
262
263
|
</div>
|