@cat-factory/app 0.242.2 → 0.244.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/board/RecurringPipelineModal.vue +12 -3
- package/app/components/panels/StepToolServers.logic.spec.ts +108 -1
- package/app/components/panels/StepToolServers.logic.ts +150 -2
- package/app/components/panels/StepToolServers.vue +89 -6
- package/app/components/settings/IssueTrackerPanel.vue +32 -205
- package/app/components/settings/TaskSourceCard.vue +143 -0
- package/app/stores/tasks.spec.ts +3 -0
- package/app/types/toolServers.ts +2 -0
- package/i18n/locales/de.json +19 -14
- package/i18n/locales/en.json +19 -14
- package/i18n/locales/es.json +19 -14
- package/i18n/locales/fr.json +19 -14
- package/i18n/locales/he.json +19 -14
- package/i18n/locales/it.json +19 -14
- package/i18n/locales/ja.json +19 -14
- package/i18n/locales/pl.json +19 -14
- package/i18n/locales/tr.json +19 -14
- package/i18n/locales/uk.json +19 -14
- package/package.json +2 -2
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
// directly; linking is the source toggle), so both are shown explicitly to undo
|
|
16
16
|
// the common confusion that "I have the GitHub App, why is nothing surfaced?".
|
|
17
17
|
import { computed, onMounted, ref, watch } from 'vue'
|
|
18
|
-
import type {
|
|
18
|
+
import type { TaskSourceKind, TaskSourceState, TrackerKind } from '~/types/domain'
|
|
19
|
+
import TaskSourceCard from '~/components/settings/TaskSourceCard.vue'
|
|
19
20
|
|
|
20
21
|
const { t } = useI18n()
|
|
21
22
|
const tracker = useTrackerStore()
|
|
@@ -50,15 +51,12 @@ onMounted(() => {
|
|
|
50
51
|
// (no deep traversal) catches every change.
|
|
51
52
|
watch(() => tracker.settings, hydrate)
|
|
52
53
|
|
|
53
|
-
// Per-source live state (available = usable now; enabled = offered to the workspace).
|
|
54
|
-
const github = computed(() => tasks.descriptorFor('github'))
|
|
55
|
-
const jira = computed(() => tasks.descriptorFor('jira'))
|
|
56
|
-
const linear = computed(() => tasks.descriptorFor('linear'))
|
|
57
|
-
|
|
58
54
|
// A tracker can only file where it can authenticate: GitHub rides the installed
|
|
59
55
|
// App, Jira/Linear need a connection. Selecting an unusable tracker is allowed (it
|
|
60
|
-
// just won't file until set up), but we surface the gap inline.
|
|
61
|
-
|
|
56
|
+
// just won't file until set up), but we surface the gap inline. (The FILING picker is a
|
|
57
|
+
// closed list of the three trackers the `tracker` step can file into, unlike the LINKING
|
|
58
|
+
// list below, which is whatever the deployment registered.)
|
|
59
|
+
const githubAvailable = computed(() => tasks.descriptorFor('github')?.available ?? false)
|
|
62
60
|
const jiraConnected = computed(() => tasks.isConnected('jira'))
|
|
63
61
|
const linearConnected = computed(() => tasks.isConnected('linear'))
|
|
64
62
|
|
|
@@ -135,6 +133,18 @@ async function save() {
|
|
|
135
133
|
// --- linking sources (per-source toggle, saved immediately) -------------------
|
|
136
134
|
const togglingSource = ref<TaskSourceKind | null>(null)
|
|
137
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Open whatever a source needs before it can be offered. A VCS-backed source (GitHub Issues,
|
|
138
|
+
* GitLab Issues) is missing its workspace VCS connection, which is set up on the VCS integration
|
|
139
|
+
* surface and NOT here: that one panel serves both providers, so a GitLab deployment lands on
|
|
140
|
+
* its PAT form and a GitHub one on the App install. Everything else is missing its own
|
|
141
|
+
* credentials, which is this source's connect form.
|
|
142
|
+
*/
|
|
143
|
+
function openRemedy(source: TaskSourceState) {
|
|
144
|
+
if (source.ridesVcsProvider) ui.openGitHub()
|
|
145
|
+
else ui.openTaskConnect(source.source)
|
|
146
|
+
}
|
|
147
|
+
|
|
138
148
|
async function toggleSource(source: TaskSourceKind, enabled: boolean) {
|
|
139
149
|
togglingSource.value = source
|
|
140
150
|
try {
|
|
@@ -187,20 +197,6 @@ async function checkSetup(source: TaskSourceKind) {
|
|
|
187
197
|
})
|
|
188
198
|
}
|
|
189
199
|
}
|
|
190
|
-
|
|
191
|
-
// Status → presentation for a setup-check verdict.
|
|
192
|
-
const STATUS_UI: Record<
|
|
193
|
-
TaskSourceDiagnosticStatus,
|
|
194
|
-
{ color: 'success' | 'warning' | 'error' | 'neutral'; icon: string }
|
|
195
|
-
> = {
|
|
196
|
-
ready: { color: 'success', icon: 'i-lucide-circle-check' },
|
|
197
|
-
not_installed: { color: 'warning', icon: 'i-lucide-download' },
|
|
198
|
-
not_connected: { color: 'warning', icon: 'i-lucide-plug' },
|
|
199
|
-
auth_failed: { color: 'error', icon: 'i-lucide-key-round' },
|
|
200
|
-
forbidden: { color: 'error', icon: 'i-lucide-shield-x' },
|
|
201
|
-
unreachable: { color: 'error', icon: 'i-lucide-wifi-off' },
|
|
202
|
-
error: { color: 'error', icon: 'i-lucide-triangle-alert' },
|
|
203
|
-
}
|
|
204
200
|
</script>
|
|
205
201
|
|
|
206
202
|
<template>
|
|
@@ -370,190 +366,21 @@ const STATUS_UI: Record<
|
|
|
370
366
|
</p>
|
|
371
367
|
</div>
|
|
372
368
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
githubAvailable
|
|
385
|
-
? t('settings.issueTracker.linking.github.available')
|
|
386
|
-
: t('settings.issueTracker.linking.github.unavailable')
|
|
387
|
-
}}
|
|
388
|
-
</div>
|
|
389
|
-
</div>
|
|
390
|
-
</div>
|
|
391
|
-
<div class="flex shrink-0 items-center gap-2">
|
|
392
|
-
<UButton
|
|
393
|
-
size="xs"
|
|
394
|
-
color="neutral"
|
|
395
|
-
variant="ghost"
|
|
396
|
-
icon="i-lucide-stethoscope"
|
|
397
|
-
:loading="tasks.checking === 'github'"
|
|
398
|
-
@click="checkSetup('github')"
|
|
399
|
-
>
|
|
400
|
-
{{ t('settings.issueTracker.linking.checkSetup') }}
|
|
401
|
-
</UButton>
|
|
402
|
-
<USwitch
|
|
403
|
-
v-if="githubAvailable"
|
|
404
|
-
:model-value="github?.enabled ?? false"
|
|
405
|
-
:loading="togglingSource === 'github'"
|
|
406
|
-
@update:model-value="(v: boolean) => toggleSource('github', v)"
|
|
407
|
-
/>
|
|
408
|
-
<UButton
|
|
409
|
-
v-else
|
|
410
|
-
size="xs"
|
|
411
|
-
color="neutral"
|
|
412
|
-
variant="soft"
|
|
413
|
-
icon="i-lucide-github"
|
|
414
|
-
@click="ui.openGitHub()"
|
|
415
|
-
>
|
|
416
|
-
{{ t('settings.issueTracker.linking.install') }}
|
|
417
|
-
</UButton>
|
|
418
|
-
</div>
|
|
419
|
-
</div>
|
|
420
|
-
<UAlert
|
|
421
|
-
v-if="tasks.diagnostics.github"
|
|
422
|
-
class="mt-2.5"
|
|
423
|
-
:color="STATUS_UI[tasks.diagnostics.github.status].color"
|
|
424
|
-
variant="subtle"
|
|
425
|
-
:icon="STATUS_UI[tasks.diagnostics.github.status].icon"
|
|
426
|
-
:description="
|
|
427
|
-
tasks.diagnostics.github.message +
|
|
428
|
-
(tasks.diagnostics.github.detail ? ` ${tasks.diagnostics.github.detail}` : '')
|
|
429
|
-
"
|
|
430
|
-
:ui="{ description: 'text-[11px]' }"
|
|
431
|
-
/>
|
|
432
|
-
</div>
|
|
433
|
-
|
|
434
|
-
<!-- Jira source -->
|
|
435
|
-
<div class="rounded-lg border border-slate-800 bg-slate-800/40 px-3 py-2.5">
|
|
436
|
-
<div class="flex items-center justify-between gap-2">
|
|
437
|
-
<div class="flex min-w-0 items-center gap-2.5">
|
|
438
|
-
<UIcon name="i-lucide-trello" class="h-5 w-5 shrink-0 text-slate-300" />
|
|
439
|
-
<div class="min-w-0">
|
|
440
|
-
<div class="text-sm font-medium text-slate-200">
|
|
441
|
-
{{ t('settings.issueTracker.vendor.jira') }}
|
|
442
|
-
</div>
|
|
443
|
-
<div class="text-[11px] text-slate-500">
|
|
444
|
-
{{
|
|
445
|
-
jiraConnected
|
|
446
|
-
? t('settings.issueTracker.linking.connected')
|
|
447
|
-
: t('settings.issueTracker.linking.jira.connectHint')
|
|
448
|
-
}}
|
|
449
|
-
</div>
|
|
450
|
-
</div>
|
|
451
|
-
</div>
|
|
452
|
-
<div class="flex shrink-0 items-center gap-2">
|
|
453
|
-
<UButton
|
|
454
|
-
v-if="jiraConnected"
|
|
455
|
-
size="xs"
|
|
456
|
-
color="neutral"
|
|
457
|
-
variant="ghost"
|
|
458
|
-
icon="i-lucide-stethoscope"
|
|
459
|
-
:loading="tasks.checking === 'jira'"
|
|
460
|
-
@click="checkSetup('jira')"
|
|
461
|
-
>
|
|
462
|
-
{{ t('settings.issueTracker.linking.checkSetup') }}
|
|
463
|
-
</UButton>
|
|
464
|
-
<USwitch
|
|
465
|
-
v-if="jira?.available"
|
|
466
|
-
:model-value="jira?.enabled ?? false"
|
|
467
|
-
:loading="togglingSource === 'jira'"
|
|
468
|
-
@update:model-value="(v: boolean) => toggleSource('jira', v)"
|
|
469
|
-
/>
|
|
470
|
-
<UButton
|
|
471
|
-
v-else
|
|
472
|
-
size="xs"
|
|
473
|
-
color="neutral"
|
|
474
|
-
variant="soft"
|
|
475
|
-
icon="i-lucide-plug"
|
|
476
|
-
@click="ui.openTaskConnect('jira')"
|
|
477
|
-
>
|
|
478
|
-
{{ t('settings.issueTracker.linking.connect') }}
|
|
479
|
-
</UButton>
|
|
480
|
-
</div>
|
|
481
|
-
</div>
|
|
482
|
-
<UAlert
|
|
483
|
-
v-if="tasks.diagnostics.jira"
|
|
484
|
-
class="mt-2.5"
|
|
485
|
-
:color="STATUS_UI[tasks.diagnostics.jira.status].color"
|
|
486
|
-
variant="subtle"
|
|
487
|
-
:icon="STATUS_UI[tasks.diagnostics.jira.status].icon"
|
|
488
|
-
:description="
|
|
489
|
-
tasks.diagnostics.jira.message +
|
|
490
|
-
(tasks.diagnostics.jira.detail ? ` ${tasks.diagnostics.jira.detail}` : '')
|
|
491
|
-
"
|
|
492
|
-
:ui="{ description: 'text-[11px]' }"
|
|
493
|
-
/>
|
|
494
|
-
</div>
|
|
369
|
+
<TaskSourceCard
|
|
370
|
+
v-for="source in tasks.sources"
|
|
371
|
+
:key="source.source"
|
|
372
|
+
:state="source"
|
|
373
|
+
:diagnostic="tasks.diagnostics[source.source] ?? null"
|
|
374
|
+
:checking="tasks.checking === source.source"
|
|
375
|
+
:toggling="togglingSource === source.source"
|
|
376
|
+
@check="checkSetup(source.source)"
|
|
377
|
+
@toggle="(enabled: boolean) => toggleSource(source.source, enabled)"
|
|
378
|
+
@remedy="openRemedy(source)"
|
|
379
|
+
/>
|
|
495
380
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
<div class="flex min-w-0 items-center gap-2.5">
|
|
500
|
-
<UIcon name="i-lucide-square-kanban" class="h-5 w-5 shrink-0 text-slate-300" />
|
|
501
|
-
<div class="min-w-0">
|
|
502
|
-
<div class="text-sm font-medium text-slate-200">
|
|
503
|
-
{{ t('settings.issueTracker.vendor.linear') }}
|
|
504
|
-
</div>
|
|
505
|
-
<div class="text-[11px] text-slate-500">
|
|
506
|
-
{{
|
|
507
|
-
linearConnected
|
|
508
|
-
? t('settings.issueTracker.linking.connected')
|
|
509
|
-
: t('settings.issueTracker.linking.linear.connectHint')
|
|
510
|
-
}}
|
|
511
|
-
</div>
|
|
512
|
-
</div>
|
|
513
|
-
</div>
|
|
514
|
-
<div class="flex shrink-0 items-center gap-2">
|
|
515
|
-
<UButton
|
|
516
|
-
v-if="linearConnected"
|
|
517
|
-
size="xs"
|
|
518
|
-
color="neutral"
|
|
519
|
-
variant="ghost"
|
|
520
|
-
icon="i-lucide-stethoscope"
|
|
521
|
-
:loading="tasks.checking === 'linear'"
|
|
522
|
-
@click="checkSetup('linear')"
|
|
523
|
-
>
|
|
524
|
-
{{ t('settings.issueTracker.linking.checkSetup') }}
|
|
525
|
-
</UButton>
|
|
526
|
-
<USwitch
|
|
527
|
-
v-if="linear?.available"
|
|
528
|
-
:model-value="linear?.enabled ?? false"
|
|
529
|
-
:loading="togglingSource === 'linear'"
|
|
530
|
-
@update:model-value="(v: boolean) => toggleSource('linear', v)"
|
|
531
|
-
/>
|
|
532
|
-
<UButton
|
|
533
|
-
v-else
|
|
534
|
-
size="xs"
|
|
535
|
-
color="neutral"
|
|
536
|
-
variant="soft"
|
|
537
|
-
icon="i-lucide-plug"
|
|
538
|
-
@click="ui.openTaskConnect('linear')"
|
|
539
|
-
>
|
|
540
|
-
{{ t('settings.issueTracker.linking.connect') }}
|
|
541
|
-
</UButton>
|
|
542
|
-
</div>
|
|
543
|
-
</div>
|
|
544
|
-
<UAlert
|
|
545
|
-
v-if="tasks.diagnostics.linear"
|
|
546
|
-
class="mt-2.5"
|
|
547
|
-
:color="STATUS_UI[tasks.diagnostics.linear.status].color"
|
|
548
|
-
variant="subtle"
|
|
549
|
-
:icon="STATUS_UI[tasks.diagnostics.linear.status].icon"
|
|
550
|
-
:description="
|
|
551
|
-
tasks.diagnostics.linear.message +
|
|
552
|
-
(tasks.diagnostics.linear.detail ? ` ${tasks.diagnostics.linear.detail}` : '')
|
|
553
|
-
"
|
|
554
|
-
:ui="{ description: 'text-[11px]' }"
|
|
555
|
-
/>
|
|
556
|
-
</div>
|
|
381
|
+
<p v-if="tasks.sources.length === 0" class="text-[11px] text-slate-500">
|
|
382
|
+
{{ t('settings.issueTracker.linking.none') }}
|
|
383
|
+
</p>
|
|
557
384
|
</section>
|
|
558
385
|
|
|
559
386
|
<!-- 3. Writeback ---------------------------------------------------------->
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// One connected-source row of the issue-tracker settings panel: what the source is, whether the
|
|
3
|
+
// workspace can use it, the live setup check, and the on/off toggle.
|
|
4
|
+
//
|
|
5
|
+
// It renders from the source's own STATE (the descriptor the backend registry serves plus the
|
|
6
|
+
// workspace's live availability), so a source is a row here the moment its provider is
|
|
7
|
+
// registered. That is the whole reason this component exists: the panel used to hold one
|
|
8
|
+
// hard-coded card per built-in, which meant a newly shipped source had no setup check and no
|
|
9
|
+
// toggle until someone remembered to paste a fourth copy, and a deployment-registered source
|
|
10
|
+
// never got one at all.
|
|
11
|
+
//
|
|
12
|
+
// The single thing that still varies per source is the REMEDY for an unavailable one, and it
|
|
13
|
+
// varies along an axis the state names: `ridesVcsProvider` says the source authenticates through
|
|
14
|
+
// the workspace's VCS connection (so the fix lives on the VCS integration surface, and the copy
|
|
15
|
+
// names that provider), while a null one carries its own credentials (so the fix is this
|
|
16
|
+
// source's own connect form). Both are emitted as one `remedy` event; where it navigates is the
|
|
17
|
+
// panel's business.
|
|
18
|
+
import { computed } from 'vue'
|
|
19
|
+
import type { TaskSourceDiagnosticStatus, TaskSourceState } from '~/types/domain'
|
|
20
|
+
import { VCS_PROVIDER_LABELS } from '~/utils/vcs'
|
|
21
|
+
|
|
22
|
+
const props = defineProps<{
|
|
23
|
+
state: TaskSourceState
|
|
24
|
+
/** The last live setup-check verdict for this source, if one has been run. */
|
|
25
|
+
diagnostic?: {
|
|
26
|
+
status: TaskSourceDiagnosticStatus
|
|
27
|
+
message: string
|
|
28
|
+
detail?: string | null
|
|
29
|
+
} | null
|
|
30
|
+
/** A setup check is in flight for this source. */
|
|
31
|
+
checking?: boolean
|
|
32
|
+
/** The enable/disable toggle is in flight for this source. */
|
|
33
|
+
toggling?: boolean
|
|
34
|
+
}>()
|
|
35
|
+
|
|
36
|
+
const emit = defineEmits<{
|
|
37
|
+
check: []
|
|
38
|
+
toggle: [enabled: boolean]
|
|
39
|
+
remedy: []
|
|
40
|
+
}>()
|
|
41
|
+
|
|
42
|
+
const { t } = useI18n()
|
|
43
|
+
|
|
44
|
+
/** The brand name of the VCS connection this source rides, or null when it carries credentials. */
|
|
45
|
+
const vcsLabel = computed(() =>
|
|
46
|
+
props.state.ridesVcsProvider ? VCS_PROVIDER_LABELS[props.state.ridesVcsProvider] : null,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The one-line explanation under the source name: what makes it usable, or what is missing.
|
|
51
|
+
* Four cases rather than two, because "rides a connection you already have" and "connected with
|
|
52
|
+
* its own credentials" are different facts, and so are the two ways of fixing an unavailable one.
|
|
53
|
+
*/
|
|
54
|
+
const subtitle = computed(() => {
|
|
55
|
+
const provider = vcsLabel.value
|
|
56
|
+
if (provider) {
|
|
57
|
+
return props.state.available
|
|
58
|
+
? t('settings.issueTracker.linking.state.ridesConnected', { provider })
|
|
59
|
+
: t('settings.issueTracker.linking.state.ridesMissing', { provider })
|
|
60
|
+
}
|
|
61
|
+
return props.state.available
|
|
62
|
+
? t('settings.issueTracker.linking.connected')
|
|
63
|
+
: t('settings.issueTracker.linking.state.notConnected')
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
/** The label of the button that leads to whatever is missing. */
|
|
67
|
+
const remedyLabel = computed(() =>
|
|
68
|
+
vcsLabel.value
|
|
69
|
+
? t('settings.issueTracker.linking.connectProvider', { provider: vcsLabel.value })
|
|
70
|
+
: t('settings.issueTracker.linking.connect'),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
// Status → presentation for a setup-check verdict. Exhaustive over the status vocabulary, so a
|
|
74
|
+
// new verdict fails the typecheck here rather than rendering with no icon.
|
|
75
|
+
const STATUS_UI: Record<
|
|
76
|
+
TaskSourceDiagnosticStatus,
|
|
77
|
+
{ color: 'success' | 'warning' | 'error' | 'neutral'; icon: string }
|
|
78
|
+
> = {
|
|
79
|
+
ready: { color: 'success', icon: 'i-lucide-circle-check' },
|
|
80
|
+
not_installed: { color: 'warning', icon: 'i-lucide-download' },
|
|
81
|
+
not_connected: { color: 'warning', icon: 'i-lucide-plug' },
|
|
82
|
+
auth_failed: { color: 'error', icon: 'i-lucide-key-round' },
|
|
83
|
+
forbidden: { color: 'error', icon: 'i-lucide-shield-x' },
|
|
84
|
+
unreachable: { color: 'error', icon: 'i-lucide-wifi-off' },
|
|
85
|
+
error: { color: 'error', icon: 'i-lucide-triangle-alert' },
|
|
86
|
+
}
|
|
87
|
+
</script>
|
|
88
|
+
|
|
89
|
+
<template>
|
|
90
|
+
<div class="rounded-lg border border-slate-800 bg-slate-800/40 px-3 py-2.5">
|
|
91
|
+
<div class="flex items-center justify-between gap-2">
|
|
92
|
+
<div class="flex min-w-0 items-center gap-2.5">
|
|
93
|
+
<UIcon :name="state.icon" class="h-5 w-5 shrink-0 text-slate-300" />
|
|
94
|
+
<div class="min-w-0">
|
|
95
|
+
<div class="text-sm font-medium text-slate-200">{{ state.label }}</div>
|
|
96
|
+
<div class="text-[11px] text-slate-500">{{ subtitle }}</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="flex shrink-0 items-center gap-2">
|
|
100
|
+
<!-- Offered whatever the state: the check is precisely the "why is this not working"
|
|
101
|
+
affordance, and its verdict distinguishes a missing connection from a broken one. -->
|
|
102
|
+
<UButton
|
|
103
|
+
size="xs"
|
|
104
|
+
color="neutral"
|
|
105
|
+
variant="ghost"
|
|
106
|
+
icon="i-lucide-stethoscope"
|
|
107
|
+
:loading="checking"
|
|
108
|
+
:data-testid="`task-source-check-${state.source}`"
|
|
109
|
+
@click="emit('check')"
|
|
110
|
+
>
|
|
111
|
+
{{ t('settings.issueTracker.linking.checkSetup') }}
|
|
112
|
+
</UButton>
|
|
113
|
+
<USwitch
|
|
114
|
+
v-if="state.available"
|
|
115
|
+
:model-value="state.enabled"
|
|
116
|
+
:loading="toggling"
|
|
117
|
+
:data-testid="`task-source-toggle-${state.source}`"
|
|
118
|
+
@update:model-value="(v: boolean) => emit('toggle', v)"
|
|
119
|
+
/>
|
|
120
|
+
<UButton
|
|
121
|
+
v-else
|
|
122
|
+
size="xs"
|
|
123
|
+
color="neutral"
|
|
124
|
+
variant="soft"
|
|
125
|
+
:icon="state.icon"
|
|
126
|
+
:data-testid="`task-source-remedy-${state.source}`"
|
|
127
|
+
@click="emit('remedy')"
|
|
128
|
+
>
|
|
129
|
+
{{ remedyLabel }}
|
|
130
|
+
</UButton>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
<UAlert
|
|
134
|
+
v-if="diagnostic"
|
|
135
|
+
class="mt-2.5"
|
|
136
|
+
:color="STATUS_UI[diagnostic.status].color"
|
|
137
|
+
variant="subtle"
|
|
138
|
+
:icon="STATUS_UI[diagnostic.status].icon"
|
|
139
|
+
:description="diagnostic.message + (diagnostic.detail ? ` ${diagnostic.detail}` : '')"
|
|
140
|
+
:ui="{ description: 'text-[11px]' }"
|
|
141
|
+
/>
|
|
142
|
+
</div>
|
|
143
|
+
</template>
|
package/app/stores/tasks.spec.ts
CHANGED
|
@@ -32,6 +32,9 @@ const jiraDescriptor: TaskSourceState = {
|
|
|
32
32
|
refPlaceholder: 'PROJ-123',
|
|
33
33
|
available: true,
|
|
34
34
|
enabled: true,
|
|
35
|
+
supportsIntake: true,
|
|
36
|
+
// Jira carries its own credentials, so it rides no VCS connection.
|
|
37
|
+
ridesVcsProvider: null,
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
const jiraConnection: TaskConnection = { source: 'jira', label: 'acme', connectedAt: 0 }
|
package/app/types/toolServers.ts
CHANGED
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
// member added on one side only renders as a blank chip rather than failing to compile.
|
|
7
7
|
|
|
8
8
|
export type {
|
|
9
|
+
ObservedToolServer,
|
|
9
10
|
StepToolServers,
|
|
10
11
|
ToolServerUnavailableReason,
|
|
11
12
|
ToolServerAllowedToolsCheck,
|
|
12
13
|
ToolServerCredential,
|
|
13
14
|
ToolServerNotProbeableReason,
|
|
15
|
+
ToolServerObservedStatus,
|
|
14
16
|
ToolServerOAuthGrant,
|
|
15
17
|
ToolServerOAuthStatus,
|
|
16
18
|
ToolServerProbeResult,
|
package/i18n/locales/de.json
CHANGED
|
@@ -377,27 +377,21 @@
|
|
|
377
377
|
"linearTeamSearchPlaceholder": "Teams suchen…"
|
|
378
378
|
},
|
|
379
379
|
"vendor": {
|
|
380
|
-
"github": "GitHub Issues"
|
|
381
|
-
"jira": "Jira",
|
|
382
|
-
"linear": "Linear"
|
|
380
|
+
"github": "GitHub Issues"
|
|
383
381
|
},
|
|
384
382
|
"linking": {
|
|
385
383
|
"heading": "Issues als Kontext verknüpfen",
|
|
386
384
|
"description": "Wenn eine Quelle angeboten wird, kannst du ihre Issues importieren und an eine Aufgabe anhängen, sodass Agenten die Issue-Beschreibung und Kommentare während der Umsetzung sehen. Dies ist unabhängig vom Ablage-Tracker oben.",
|
|
387
|
-
"github": {
|
|
388
|
-
"available": "Nutzt deine installierte GitHub-App — keine Zugangsdaten nötig.",
|
|
389
|
-
"unavailable": "Installiere die GitHub-App (Integrationen → GitHub), um diese Quelle anzubieten."
|
|
390
|
-
},
|
|
391
385
|
"checkSetup": "Einrichtung prüfen",
|
|
392
|
-
"install": "Installieren",
|
|
393
386
|
"connected": "Verbunden.",
|
|
394
|
-
"
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
"
|
|
387
|
+
"connect": "Verbinden",
|
|
388
|
+
"state": {
|
|
389
|
+
"ridesConnected": "Nutzt die {provider}-Verbindung dieses Workspace und braucht daher keine eigenen Zugangsdaten.",
|
|
390
|
+
"ridesMissing": "Verbinde {provider} unter Integrationen, um diese Quelle anzubieten.",
|
|
391
|
+
"notConnected": "Noch nicht verbunden."
|
|
399
392
|
},
|
|
400
|
-
"
|
|
393
|
+
"connectProvider": "{provider} verbinden",
|
|
394
|
+
"none": "In diesem Deployment sind keine Aufgabenquellen konfiguriert."
|
|
401
395
|
},
|
|
402
396
|
"writeback": {
|
|
403
397
|
"heading": "Rückschreiben",
|
|
@@ -2007,6 +2001,16 @@
|
|
|
2007
2001
|
"oauthNotConnected": "Verbinden Sie dieses Board im Infrastruktur-Fenster damit. Ein Deployment ohne ENCRYPTION_KEY hat keinen Ort für eine Berechtigung, das muss ein Betreiber also zuerst setzen.",
|
|
2008
2002
|
"oauthTokenFailed": "Verbinden Sie es im Infrastruktur-Fenster neu, oder warten Sie die Störung des Anbieters ab.",
|
|
2009
2003
|
"overBudget": "Kürzen Sie, was der Agent deklariert, damit ein Lauf alles mitführen kann."
|
|
2004
|
+
},
|
|
2005
|
+
"observed": {
|
|
2006
|
+
"ready": "gestartet",
|
|
2007
|
+
"readyTools": "{count} Tools",
|
|
2008
|
+
"readyNoTools": "gestartet, keine Tools",
|
|
2009
|
+
"failed": "Start fehlgeschlagen",
|
|
2010
|
+
"needsAuth": "Autorisierung erforderlich",
|
|
2011
|
+
"unknown": "Zustand ungeklärt",
|
|
2012
|
+
"notLoaded": "nie geladen",
|
|
2013
|
+
"unattributed": "Die Agenten-CLI meldete einen Server, den dieser Schritt nicht eingebunden hat: {id}."
|
|
2010
2014
|
}
|
|
2011
2015
|
},
|
|
2012
2016
|
"adherence": {
|
|
@@ -2914,6 +2918,7 @@
|
|
|
2914
2918
|
"intake": "Issue-Aufnahme",
|
|
2915
2919
|
"intakeHint": "Jeder Lauf wählt ein passendes offenes Issue aus dem Tracker und bearbeitet es von Anfang bis Ende.",
|
|
2916
2920
|
"intakeNoSources": "Verbinden Sie zuerst eine Task-Quelle, um Issues daraus zu ziehen.",
|
|
2921
|
+
"intakeNoIntakeSources": "Eine Task-Quelle ist verbunden, aber keine der verbundenen Quellen kann bereits eine geplante Issue-Suche ausführen.",
|
|
2917
2922
|
"intakeGithubRepo": "Repository",
|
|
2918
2923
|
"intakeBoardId": "Board-ID",
|
|
2919
2924
|
"intakeBoardIdHelp": "Das Board, Projekt oder die Warteschlange, auf die dieser Tracker die Aufnahme eingrenzt. Das Format gibt der Tracker vor.",
|
package/i18n/locales/en.json
CHANGED
|
@@ -384,6 +384,7 @@
|
|
|
384
384
|
"intake": "Issue intake",
|
|
385
385
|
"intakeHint": "Each run picks one matching open issue from the tracker and works it end to end.",
|
|
386
386
|
"intakeNoSources": "Connect a task source first to pull issues from it.",
|
|
387
|
+
"intakeNoIntakeSources": "A task source is connected, but none of the connected sources can run a scheduled issue search yet.",
|
|
387
388
|
"intakeGithubRepo": "Repository",
|
|
388
389
|
"intakeBoardId": "Board id",
|
|
389
390
|
"intakeBoardIdHelp": "The board, project or queue this tracker scopes intake to. Its format is defined by the tracker.",
|
|
@@ -1534,6 +1535,16 @@
|
|
|
1534
1535
|
"oauthNotConnected": "Connect this board to it from the Infrastructure window. A deployment with no ENCRYPTION_KEY has nowhere to keep a grant, so an operator has to set that first.",
|
|
1535
1536
|
"oauthTokenFailed": "Reconnect it from the Infrastructure window, or wait out the vendor's outage.",
|
|
1536
1537
|
"overBudget": "Trim what the agent declares, so one run can carry all of it."
|
|
1538
|
+
},
|
|
1539
|
+
"observed": {
|
|
1540
|
+
"ready": "started",
|
|
1541
|
+
"readyTools": "{count} tools",
|
|
1542
|
+
"readyNoTools": "started, no tools",
|
|
1543
|
+
"failed": "failed to start",
|
|
1544
|
+
"needsAuth": "needs authorization",
|
|
1545
|
+
"unknown": "state unresolved",
|
|
1546
|
+
"notLoaded": "never loaded",
|
|
1547
|
+
"unattributed": "The agent CLI reported a server this step did not wire: {id}."
|
|
1537
1548
|
}
|
|
1538
1549
|
},
|
|
1539
1550
|
"adherence": {
|
|
@@ -3010,27 +3021,21 @@
|
|
|
3010
3021
|
"linearTeamSearchPlaceholder": "Search teams…"
|
|
3011
3022
|
},
|
|
3012
3023
|
"vendor": {
|
|
3013
|
-
"github": "GitHub Issues"
|
|
3014
|
-
"jira": "Jira",
|
|
3015
|
-
"linear": "Linear"
|
|
3024
|
+
"github": "GitHub Issues"
|
|
3016
3025
|
},
|
|
3017
3026
|
"linking": {
|
|
3018
3027
|
"heading": "Link issues as context",
|
|
3019
3028
|
"description": "When a source is offered you can import its issues and attach them to a task, so agents see the issue description and comments while implementing. This is independent of the filing tracker above.",
|
|
3020
|
-
"github": {
|
|
3021
|
-
"available": "Rides your installed GitHub App — no credentials needed.",
|
|
3022
|
-
"unavailable": "Install the GitHub App (Integrations → GitHub) to offer this source."
|
|
3023
|
-
},
|
|
3024
3029
|
"checkSetup": "Check setup",
|
|
3025
|
-
"install": "Install",
|
|
3026
3030
|
"connected": "Connected.",
|
|
3027
|
-
"
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
"
|
|
3031
|
+
"connect": "Connect",
|
|
3032
|
+
"state": {
|
|
3033
|
+
"ridesConnected": "Rides this workspace's {provider} connection, so it needs no credentials of its own.",
|
|
3034
|
+
"ridesMissing": "Connect {provider} under Integrations to offer this source.",
|
|
3035
|
+
"notConnected": "Not connected yet."
|
|
3032
3036
|
},
|
|
3033
|
-
"
|
|
3037
|
+
"connectProvider": "Connect {provider}",
|
|
3038
|
+
"none": "This deployment has no task sources configured."
|
|
3034
3039
|
},
|
|
3035
3040
|
"writeback": {
|
|
3036
3041
|
"heading": "Writeback",
|
package/i18n/locales/es.json
CHANGED
|
@@ -345,6 +345,7 @@
|
|
|
345
345
|
"intake": "Admisión de incidencias",
|
|
346
346
|
"intakeHint": "Cada ejecución toma una incidencia abierta que coincide del rastreador y la resuelve de principio a fin.",
|
|
347
347
|
"intakeNoSources": "Primero conecta una fuente de tareas para extraer incidencias de ella.",
|
|
348
|
+
"intakeNoIntakeSources": "Hay una fuente de tareas conectada, pero ninguna de las fuentes conectadas puede ejecutar todavía una búsqueda programada de incidencias.",
|
|
348
349
|
"intakeGithubRepo": "Repositorio",
|
|
349
350
|
"intakeBoardId": "ID del tablero",
|
|
350
351
|
"intakeBoardIdHelp": "El tablero, proyecto o cola al que este rastreador limita la admisión. El formato lo define el rastreador.",
|
|
@@ -1443,6 +1444,16 @@
|
|
|
1443
1444
|
"oauthNotConnected": "Conecta este tablero con él desde la ventana de Infraestructura. Un despliegue sin ENCRYPTION_KEY no tiene dónde guardar una concesión, así que un operador debe configurarla primero.",
|
|
1444
1445
|
"oauthTokenFailed": "Vuelve a conectarlo desde la ventana de Infraestructura, o espera a que pase la caída del proveedor.",
|
|
1445
1446
|
"overBudget": "Recorta lo que declara el agente, para que una ejecución pueda llevarlo todo."
|
|
1447
|
+
},
|
|
1448
|
+
"observed": {
|
|
1449
|
+
"ready": "iniciado",
|
|
1450
|
+
"readyTools": "{count} herramientas",
|
|
1451
|
+
"readyNoTools": "iniciado, sin herramientas",
|
|
1452
|
+
"failed": "no arrancó",
|
|
1453
|
+
"needsAuth": "requiere autorización",
|
|
1454
|
+
"unknown": "estado sin determinar",
|
|
1455
|
+
"notLoaded": "nunca se cargó",
|
|
1456
|
+
"unattributed": "La CLI del agente informó de un servidor que este paso no conectó: {id}."
|
|
1446
1457
|
}
|
|
1447
1458
|
},
|
|
1448
1459
|
"adherence": {
|
|
@@ -2759,27 +2770,21 @@
|
|
|
2759
2770
|
"linearTeamSearchPlaceholder": "Buscar equipos…"
|
|
2760
2771
|
},
|
|
2761
2772
|
"vendor": {
|
|
2762
|
-
"github": "GitHub Issues"
|
|
2763
|
-
"jira": "Jira",
|
|
2764
|
-
"linear": "Linear"
|
|
2773
|
+
"github": "GitHub Issues"
|
|
2765
2774
|
},
|
|
2766
2775
|
"linking": {
|
|
2767
2776
|
"heading": "Vincular incidencias como contexto",
|
|
2768
2777
|
"description": "Cuando se ofrece una fuente, puedes importar sus incidencias y adjuntarlas a una tarea, para que los agentes vean la descripción de la incidencia y los comentarios mientras implementan. Esto es independiente del gestor de registro de arriba.",
|
|
2769
|
-
"github": {
|
|
2770
|
-
"available": "Usa tu GitHub App instalada: no se necesitan credenciales.",
|
|
2771
|
-
"unavailable": "Instala la GitHub App (Integraciones → GitHub) para ofrecer esta fuente."
|
|
2772
|
-
},
|
|
2773
2778
|
"checkSetup": "Comprobar configuración",
|
|
2774
|
-
"install": "Instalar",
|
|
2775
2779
|
"connected": "Conectado.",
|
|
2776
|
-
"
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
"
|
|
2780
|
+
"connect": "Conectar",
|
|
2781
|
+
"state": {
|
|
2782
|
+
"ridesConnected": "Usa la conexión de {provider} de este espacio de trabajo, así que no necesita credenciales propias.",
|
|
2783
|
+
"ridesMissing": "Conecta {provider} en Integraciones para ofrecer esta fuente.",
|
|
2784
|
+
"notConnected": "Aún sin conectar."
|
|
2781
2785
|
},
|
|
2782
|
-
"
|
|
2786
|
+
"connectProvider": "Conectar {provider}",
|
|
2787
|
+
"none": "Este despliegue no tiene fuentes de tareas configuradas."
|
|
2783
2788
|
},
|
|
2784
2789
|
"writeback": {
|
|
2785
2790
|
"heading": "Escritura de vuelta",
|