@cat-factory/app 0.54.4 → 0.56.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/app.vue +14 -0
- package/app/components/auth/UserMenu.vue +1 -1
- package/app/components/board/AddTaskModal.vue +5 -4
- package/app/components/board/nodes/AgentChip.vue +2 -2
- package/app/components/board/nodes/BlockNode.vue +12 -8
- package/app/components/board/nodes/DraggableTask.vue +1 -1
- package/app/components/board/nodes/EpicNode.vue +1 -1
- package/app/components/board/nodes/ModuleFrame.vue +7 -4
- package/app/components/board/nodes/TaskCard.vue +2 -2
- package/app/components/board/nodes/TaskPipelineMini.vue +3 -3
- package/app/components/brainstorm/BrainstormWindow.vue +8 -7
- package/app/components/clarity/ClarityReviewWindow.vue +8 -7
- package/app/components/consensus/ConsensusSessionWindow.vue +2 -2
- package/app/components/documents/ContextDocumentPicker.vue +4 -4
- package/app/components/documents/SpawnPreviewModal.vue +4 -4
- package/app/components/focus/BlockFocusView.vue +11 -4
- package/app/components/fragments/FragmentLibraryManager.vue +5 -5
- package/app/components/gates/GateResultView.vue +3 -3
- package/app/components/github/GitHubPanel.vue +5 -2
- package/app/components/humanTest/HumanTestWindow.vue +1 -1
- package/app/components/kaizen/KaizenPanel.vue +5 -5
- package/app/components/kaizen/KaizenStepStatus.vue +2 -2
- package/app/components/layout/AccountDeploymentSettings.vue +31 -2
- package/app/components/layout/BoardSwitcher.vue +4 -4
- package/app/components/layout/CommandBar.vue +1 -1
- package/app/components/layout/IntegrationBackTitle.vue +2 -1
- package/app/components/layout/IntegrationsHub.vue +10 -4
- package/app/components/layout/LanguageSwitcher.vue +1 -1
- package/app/components/layout/NotificationsInbox.vue +1 -1
- package/app/components/layout/PersonalSetupModal.vue +5 -2
- package/app/components/layout/SideBar.vue +5 -3
- package/app/components/media/ArtifactLightbox.vue +5 -5
- package/app/components/media/ImageCompare.vue +6 -1
- package/app/components/observability/StepMetricsBar.vue +6 -2
- package/app/components/palettes/AgentPalette.vue +4 -4
- package/app/components/panels/AgentStepDetail.vue +12 -12
- package/app/components/panels/GenericStructuredResultView.vue +1 -1
- package/app/components/panels/InspectorPanel.vue +2 -2
- package/app/components/panels/ObservabilityPanel.vue +6 -6
- package/app/components/panels/StepMetadataCard.vue +1 -1
- package/app/components/panels/inspector/ContainerSummary.vue +2 -2
- package/app/components/panels/inspector/EpicChildren.vue +3 -3
- package/app/components/panels/inspector/RecurringScheduleSettings.vue +1 -1
- package/app/components/panels/inspector/ServiceFragments.vue +1 -1
- package/app/components/panels/inspector/ServiceTestConfig.vue +1 -1
- package/app/components/panels/inspector/TaskDependencies.vue +1 -1
- package/app/components/panels/inspector/TaskEstimateBadge.vue +1 -1
- package/app/components/panels/inspector/TaskExecution.vue +9 -9
- package/app/components/panels/inspector/TaskRunSettings.vue +2 -2
- package/app/components/panels/inspector/TaskStructure.vue +1 -1
- package/app/components/pipeline/IterationCapPrompt.vue +1 -0
- package/app/components/pipeline/PipelineBuilder.vue +8 -8
- package/app/components/pipeline/PipelineProgress.vue +4 -4
- package/app/components/providers/ApiKeysSection.vue +2 -2
- package/app/components/providers/PersonalSubscriptionSection.vue +2 -2
- package/app/components/providers/VendorCredentialsModal.vue +2 -2
- package/app/components/provisioning/ProvisioningLogsDrawer.vue +1 -1
- package/app/components/requirements/RequirementsReviewWindow.vue +9 -8
- package/app/components/sandbox/SandboxPanel.vue +17 -17
- package/app/components/settings/LocalModelEndpointsPanel.vue +1 -1
- package/app/components/settings/ModelConfigurationPanel.vue +4 -3
- package/app/components/settings/OpenRouterCatalogPanel.vue +3 -3
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +1 -1
- package/app/components/spec/ServiceSpecWindow.vue +3 -3
- package/app/components/tasks/ContextIssuePicker.vue +5 -5
- package/app/components/tasks/TaskContextIssues.vue +1 -1
- package/app/components/tasks/TaskImportModal.vue +1 -1
- package/app/components/testing/TestReportWindow.vue +5 -5
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +2 -2
- package/app/composables/usePipelineErrorToast.ts +37 -4
- package/app/pages/index.vue +1 -1
- package/app/stores/ui.ts +21 -0
- package/i18n/i18n.config.ts +9 -0
- package/i18n/locales/en.json +5 -0
- package/i18n/locales/es.json +5 -0
- package/i18n/locales/fr.json +5 -0
- package/i18n/locales/he.json +3390 -0
- package/i18n/locales/pl.json +5 -0
- package/i18n/locales/uk.json +5 -0
- package/nuxt.config.ts +1 -0
- package/package.json +2 -2
package/app/app.vue
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import AuthGate from '~/components/auth/AuthGate.vue'
|
|
3
|
+
|
|
4
|
+
// Drive the document's `lang`/`dir` from the active i18n locale. `useLocaleHead` derives
|
|
5
|
+
// these from the locale definitions in `nuxt.config.ts` (including the `dir: 'rtl'` flag on
|
|
6
|
+
// Hebrew), so switching to a RTL locale flips `<html dir="rtl" lang="he">` and the browser
|
|
7
|
+
// mirrors text alignment, flex/grid main-axis direction, and logical CSS properties. Wrapped
|
|
8
|
+
// in a getter so `useHead` tracks the reactive ref and re-applies on every locale change.
|
|
9
|
+
const localeHead = useLocaleHead()
|
|
10
|
+
useHead(() => ({
|
|
11
|
+
htmlAttrs: {
|
|
12
|
+
lang: localeHead.value.htmlAttrs?.lang,
|
|
13
|
+
// `useLocaleHead` types `dir` loosely as string; our locales only ever set ltr/rtl.
|
|
14
|
+
dir: localeHead.value.htmlAttrs?.dir as 'ltr' | 'rtl' | 'auto' | undefined,
|
|
15
|
+
},
|
|
16
|
+
}))
|
|
3
17
|
</script>
|
|
4
18
|
|
|
5
19
|
<template>
|
|
@@ -30,7 +30,7 @@ const items = computed<DropdownMenuItem[][]>(() => [
|
|
|
30
30
|
<UDropdownMenu v-if="auth.user" :items="items" :content="{ side: 'top', align: 'start' }">
|
|
31
31
|
<button
|
|
32
32
|
type="button"
|
|
33
|
-
class="flex w-full items-center gap-2 rounded-lg border border-slate-800 bg-slate-900/60 p-2 text-
|
|
33
|
+
class="flex w-full items-center gap-2 rounded-lg border border-slate-800 bg-slate-900/60 p-2 text-start transition hover:bg-slate-800/60"
|
|
34
34
|
>
|
|
35
35
|
<UAvatar
|
|
36
36
|
:src="auth.user.avatarUrl ?? undefined"
|
|
@@ -700,13 +700,13 @@ async function add() {
|
|
|
700
700
|
color="neutral"
|
|
701
701
|
variant="soft"
|
|
702
702
|
size="xs"
|
|
703
|
-
class="
|
|
703
|
+
class="ms-1 shrink-0"
|
|
704
704
|
>
|
|
705
705
|
{{ t('board.addTask.importsOnAdd') }}
|
|
706
706
|
</UBadge>
|
|
707
707
|
<button
|
|
708
708
|
type="button"
|
|
709
|
-
class="
|
|
709
|
+
class="ms-auto shrink-0 text-slate-400 hover:text-slate-200"
|
|
710
710
|
@click="removePending(item)"
|
|
711
711
|
>
|
|
712
712
|
<UIcon name="i-lucide-x" class="h-3.5 w-3.5" />
|
|
@@ -772,13 +772,13 @@ async function add() {
|
|
|
772
772
|
color="neutral"
|
|
773
773
|
variant="soft"
|
|
774
774
|
size="xs"
|
|
775
|
-
class="
|
|
775
|
+
class="ms-1 shrink-0"
|
|
776
776
|
>
|
|
777
777
|
{{ t('board.addTask.importsOnAdd') }}
|
|
778
778
|
</UBadge>
|
|
779
779
|
<button
|
|
780
780
|
type="button"
|
|
781
|
-
class="
|
|
781
|
+
class="ms-auto shrink-0 text-slate-400 hover:text-slate-200"
|
|
782
782
|
@click="removePending(item)"
|
|
783
783
|
>
|
|
784
784
|
<UIcon name="i-lucide-x" class="h-3.5 w-3.5" />
|
|
@@ -806,6 +806,7 @@ async function add() {
|
|
|
806
806
|
color="primary"
|
|
807
807
|
data-testid="add-task-submit"
|
|
808
808
|
:icon="isRecurring ? 'i-lucide-arrow-right' : 'i-lucide-plus'"
|
|
809
|
+
:ui="{ leadingIcon: 'rtl:-scale-x-100', trailingIcon: 'rtl:-scale-x-100' }"
|
|
809
810
|
:loading="saving"
|
|
810
811
|
:disabled="!canAdd"
|
|
811
812
|
@click="add"
|
|
@@ -37,13 +37,13 @@ const dim = computed(() => (props.size === 'sm' ? 'h-7 w-7' : 'h-9 w-9'))
|
|
|
37
37
|
<UIcon :name="archetype.icon" class="text-base" :style="{ color: archetype.color }" />
|
|
38
38
|
<span
|
|
39
39
|
v-if="step.state === 'working'"
|
|
40
|
-
class="absolute -bottom-1 -
|
|
40
|
+
class="absolute -bottom-1 -end-1 rounded-full bg-slate-900 p-0.5"
|
|
41
41
|
>
|
|
42
42
|
<UIcon :name="stateIcon.working!" class="h-3 w-3 animate-spin text-indigo-300" />
|
|
43
43
|
</span>
|
|
44
44
|
<span
|
|
45
45
|
v-else-if="stateIcon[step.state]"
|
|
46
|
-
class="absolute -bottom-1 -
|
|
46
|
+
class="absolute -bottom-1 -end-1 rounded-full bg-slate-900 p-0.5"
|
|
47
47
|
>
|
|
48
48
|
<UIcon
|
|
49
49
|
:name="stateIcon[step.state]!"
|
|
@@ -234,16 +234,16 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
234
234
|
<UIcon
|
|
235
235
|
v-if="bootstrapping"
|
|
236
236
|
name="i-lucide-loader-circle"
|
|
237
|
-
class="
|
|
237
|
+
class="ms-auto h-3.5 w-3.5 shrink-0 animate-spin text-amber-400"
|
|
238
238
|
:title="t('board.frame.bootstrapping')"
|
|
239
239
|
/>
|
|
240
240
|
<UIcon
|
|
241
241
|
v-else-if="runFailed"
|
|
242
242
|
name="i-lucide-alert-triangle"
|
|
243
|
-
class="
|
|
243
|
+
class="ms-auto h-3.5 w-3.5 shrink-0 text-rose-400"
|
|
244
244
|
:title="t('board.frame.runFailed')"
|
|
245
245
|
/>
|
|
246
|
-
<span v-else-if="hasTasks" class="
|
|
246
|
+
<span v-else-if="hasTasks" class="ms-auto shrink-0 text-[11px] text-slate-300">
|
|
247
247
|
{{ mergedTasks }}/{{ taskCount }}
|
|
248
248
|
</span>
|
|
249
249
|
</div>
|
|
@@ -263,7 +263,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
263
263
|
class="h-3.5 w-3.5 shrink-0 animate-spin text-amber-400"
|
|
264
264
|
/>
|
|
265
265
|
<span class="text-amber-300">{{ t('board.frame.bootstrapping') }}</span>
|
|
266
|
-
<span v-if="bootstrapSubtasks" class="
|
|
266
|
+
<span v-if="bootstrapSubtasks" class="ms-auto text-amber-200/80">
|
|
267
267
|
{{ bootstrapSubtasks.completed }}/{{ bootstrapSubtasks.total }}
|
|
268
268
|
</span>
|
|
269
269
|
</div>
|
|
@@ -321,7 +321,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
321
321
|
<span v-if="prTasks" class="text-emerald-400"
|
|
322
322
|
>· {{ t('board.frame.prCount', { count: prTasks }) }}</span
|
|
323
323
|
>
|
|
324
|
-
<UIcon name="i-lucide-chevron-down" class="
|
|
324
|
+
<UIcon name="i-lucide-chevron-down" class="ms-auto h-3 w-3" />
|
|
325
325
|
</button>
|
|
326
326
|
</div>
|
|
327
327
|
</div>
|
|
@@ -341,7 +341,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
341
341
|
class="h-4 w-4 shrink-0 animate-spin text-amber-400"
|
|
342
342
|
/>
|
|
343
343
|
<span class="text-amber-300">{{ t('board.frame.bootstrappingRepository') }}</span>
|
|
344
|
-
<span v-if="bootstrapSubtasks" class="
|
|
344
|
+
<span v-if="bootstrapSubtasks" class="ms-auto text-amber-200/80">
|
|
345
345
|
{{
|
|
346
346
|
t('board.frame.bootstrapStepsCount', {
|
|
347
347
|
completed: bootstrapSubtasks.completed,
|
|
@@ -392,7 +392,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
392
392
|
<div class="p-4">
|
|
393
393
|
<!-- frame header: the whole header (the title row AND the stats line below it)
|
|
394
394
|
is the drag handle for the expanded frame. `nopan` stops Vue Flow's pane
|
|
395
|
-
from panning on a
|
|
395
|
+
from panning on a start-drag that starts here (it pans via d3-zoom's
|
|
396
396
|
mousedown, which our pointerdown stopPropagation can't intercept), so the
|
|
397
397
|
grab drives the frame move. The action buttons on the right opt out via
|
|
398
398
|
`.nodrag` (onFrameHandle ignores them). `pb-3` provides the gap down to the
|
|
@@ -499,7 +499,11 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
499
499
|
|
|
500
500
|
<!-- resize handles (drag the borders to resize the service, Miro-style).
|
|
501
501
|
`nopan` (alongside `nodrag`) so the pane doesn't pan while resizing —
|
|
502
|
-
same reason as the header handle above.
|
|
502
|
+
same reason as the header handle above. These stay PHYSICAL
|
|
503
|
+
(`right-0`, not `end-0`): the resize math in useFrameResize grows the
|
|
504
|
+
right/bottom edge from an unmirrored clientX/clientY delta, so a
|
|
505
|
+
logical (RTL-flipped) grip would render on the opposite edge from the
|
|
506
|
+
one the drag actually moves. -->
|
|
503
507
|
<div
|
|
504
508
|
class="nodrag nopan absolute right-0 top-0 h-full w-2 cursor-ew-resize touch-none hover:bg-sky-400/20 pointer-coarse:w-4"
|
|
505
509
|
:title="t('board.frame.dragToResize')"
|
|
@@ -40,7 +40,7 @@ function onHandle(e: PointerEvent) {
|
|
|
40
40
|
pointerEvents: draggingId === taskId ? 'none' : undefined,
|
|
41
41
|
}"
|
|
42
42
|
>
|
|
43
|
-
<!-- drag handle (`nopan` so the pane doesn't pan on a
|
|
43
|
+
<!-- drag handle (`nopan` so the pane doesn't pan on a start-drag from here) -->
|
|
44
44
|
<div
|
|
45
45
|
class="nodrag nopan flex cursor-grab touch-none items-center justify-center rounded-t-lg border border-b-0 border-slate-700 bg-slate-800/80 py-px active:cursor-grabbing pointer-coarse:py-2"
|
|
46
46
|
:title="t('board.frame.dragTask')"
|
|
@@ -35,7 +35,7 @@ const selected = computed(() => ui.selectedBlockId === props.id)
|
|
|
35
35
|
<span class="text-[10px] font-semibold uppercase tracking-wide text-violet-300">{{
|
|
36
36
|
t('board.epic.label')
|
|
37
37
|
}}</span>
|
|
38
|
-
<span class="
|
|
38
|
+
<span class="ms-auto text-[10px] text-slate-400">{{ done }}/{{ total }}</span>
|
|
39
39
|
</div>
|
|
40
40
|
<div class="mt-1 truncate text-sm font-medium text-slate-100" :title="block.title">
|
|
41
41
|
{{ block.title }}
|
|
@@ -49,7 +49,7 @@ function onResize(e: PointerEvent, edge: 'e' | 's' | 'se') {
|
|
|
49
49
|
zIndex: draggingId === moduleId ? 50 : 5,
|
|
50
50
|
}"
|
|
51
51
|
>
|
|
52
|
-
<!-- module header / drag handle (`nopan` so a
|
|
52
|
+
<!-- module header / drag handle (`nopan` so a start-drag moves it, not the pane) -->
|
|
53
53
|
<div
|
|
54
54
|
class="nodrag nopan flex h-[30px] cursor-grab touch-none items-center gap-1 rounded-t-xl bg-violet-500/15 px-2 active:cursor-grabbing"
|
|
55
55
|
@pointerdown="onHandle"
|
|
@@ -61,10 +61,10 @@ function onResize(e: PointerEvent, edge: 'e' | 's' | 'se') {
|
|
|
61
61
|
:style="{ color: MODULE_META.color }"
|
|
62
62
|
/>
|
|
63
63
|
<span class="truncate text-[11px] font-semibold text-violet-100">{{ mod.title }}</span>
|
|
64
|
-
<span v-if="inflight" class="
|
|
64
|
+
<span v-if="inflight" class="ms-auto shrink-0 text-[9px] text-violet-300/70">
|
|
65
65
|
{{ t('board.frame.taskCount', { count: inflight }, inflight) }}
|
|
66
66
|
</span>
|
|
67
|
-
<span v-else-if="total" class="
|
|
67
|
+
<span v-else-if="total" class="ms-auto shrink-0 text-[9px] text-violet-300/70">
|
|
68
68
|
{{ t('board.frame.taskCount', { count: total }, total) }}
|
|
69
69
|
</span>
|
|
70
70
|
</div>
|
|
@@ -75,7 +75,10 @@ function onResize(e: PointerEvent, edge: 'e' | 's' | 'se') {
|
|
|
75
75
|
</div>
|
|
76
76
|
|
|
77
77
|
<!-- resize handles (drag the borders to resize the module, Miro-style).
|
|
78
|
-
`nopan` (with `nodrag`) so resizing doesn't pan the pane.
|
|
78
|
+
`nopan` (with `nodrag`) so resizing doesn't pan the pane. Kept PHYSICAL
|
|
79
|
+
(`right-0`, not `end-0`) for the same reason as the service-frame grips in
|
|
80
|
+
BlockNode: the resize delta is unmirrored, so a logical grip would sit on
|
|
81
|
+
the opposite edge from the one the drag moves. -->
|
|
79
82
|
<div
|
|
80
83
|
class="nodrag nopan absolute right-0 top-0 h-full w-2 cursor-ew-resize touch-none hover:bg-violet-400/20 pointer-coarse:w-4"
|
|
81
84
|
:title="t('board.frame.dragToResize')"
|
|
@@ -181,7 +181,7 @@ function selectTask() {
|
|
|
181
181
|
:data-block-id="task.id"
|
|
182
182
|
:data-status="task.status"
|
|
183
183
|
data-testid="task-card"
|
|
184
|
-
class="nodrag w-full cursor-pointer rounded-lg border bg-slate-950/70 p-2 text-
|
|
184
|
+
class="nodrag w-full cursor-pointer rounded-lg border bg-slate-950/70 p-2 text-start transition"
|
|
185
185
|
:class="[
|
|
186
186
|
selected ? 'border-white' : 'border-slate-700 hover:border-slate-500',
|
|
187
187
|
task.status === 'pr_ready' ? 'board-pulse-green' : attention ? 'board-pulse' : '',
|
|
@@ -204,7 +204,7 @@ function selectTask() {
|
|
|
204
204
|
"
|
|
205
205
|
/>
|
|
206
206
|
<span
|
|
207
|
-
class="
|
|
207
|
+
class="ms-auto truncate text-[9px] uppercase tracking-wide"
|
|
208
208
|
:class="
|
|
209
209
|
runFailed
|
|
210
210
|
? 'text-rose-400'
|
|
@@ -99,7 +99,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
99
99
|
/>
|
|
100
100
|
<span
|
|
101
101
|
v-if="s.subtasks && s.subtasks.total > 0"
|
|
102
|
-
class="
|
|
102
|
+
class="ms-auto shrink-0 font-mono text-[9px] tabular-nums text-slate-400"
|
|
103
103
|
>
|
|
104
104
|
{{ s.subtasks.completed }}/{{ s.subtasks.total }}
|
|
105
105
|
</span>
|
|
@@ -108,7 +108,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
108
108
|
:name="
|
|
109
109
|
isFailedStep(s.state, runFailed) ? FAILED_STEP_META.icon : STATE_META[s.state].icon
|
|
110
110
|
"
|
|
111
|
-
class="
|
|
111
|
+
class="ms-auto h-2.5 w-2.5 shrink-0"
|
|
112
112
|
:class="s.state === 'working' && !runFailed ? 'animate-spin' : ''"
|
|
113
113
|
:style="{
|
|
114
114
|
color: isFailedStep(s.state, runFailed)
|
|
@@ -162,7 +162,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
162
162
|
{{ agentKindMeta(companionByStep[i]!.kind).label }}
|
|
163
163
|
</span>
|
|
164
164
|
<span
|
|
165
|
-
class="
|
|
165
|
+
class="ms-auto shrink-0"
|
|
166
166
|
:class="COMPANION_STATE_META[companionByStep[i]!.state].text"
|
|
167
167
|
>
|
|
168
168
|
{{ COMPANION_STATE_META[companionByStep[i]!.state].label }}
|
|
@@ -275,7 +275,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
275
275
|
</h1>
|
|
276
276
|
<p v-if="block" class="truncate text-xs text-slate-500">{{ block.title }}</p>
|
|
277
277
|
</div>
|
|
278
|
-
<div class="
|
|
278
|
+
<div class="ms-auto flex items-center gap-1.5">
|
|
279
279
|
<UBadge v-if="session" color="neutral" variant="subtle" size="sm">
|
|
280
280
|
{{ t('brainstorm.iteration', { current: iteration, max: maxIterations }) }}
|
|
281
281
|
</UBadge>
|
|
@@ -376,7 +376,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
376
376
|
size="xs"
|
|
377
377
|
variant="soft"
|
|
378
378
|
:color="STATUS_COLOR[item.status]"
|
|
379
|
-
class="
|
|
379
|
+
class="ms-auto"
|
|
380
380
|
>
|
|
381
381
|
{{ t(STATUS_LABELS[item.status]) }}
|
|
382
382
|
</UBadge>
|
|
@@ -388,7 +388,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
388
388
|
<!-- recorded choice -->
|
|
389
389
|
<div
|
|
390
390
|
v-if="item.reply"
|
|
391
|
-
class="mt-2 rounded-md border-
|
|
391
|
+
class="mt-2 rounded-md border-s-2 border-slate-700 bg-slate-950/40 px-3 py-1.5 text-sm text-slate-300"
|
|
392
392
|
>
|
|
393
393
|
<span class="text-[10px] uppercase tracking-wide text-slate-500">
|
|
394
394
|
{{ t('brainstorm.yourChoice') }}
|
|
@@ -464,7 +464,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
464
464
|
<div v-for="s in outline.sections" :key="s.id" class="mb-2">
|
|
465
465
|
<button
|
|
466
466
|
v-if="s.title"
|
|
467
|
-
class="group flex w-full items-center gap-2 text-
|
|
467
|
+
class="group flex w-full items-center gap-2 text-start"
|
|
468
468
|
@click="toggle(s.id)"
|
|
469
469
|
>
|
|
470
470
|
<UIcon
|
|
@@ -480,7 +480,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
480
480
|
</button>
|
|
481
481
|
<div
|
|
482
482
|
v-show="!s.title || !collapsed[s.id]"
|
|
483
|
-
class="reader-prose mt-1
|
|
483
|
+
class="reader-prose mt-1 ps-5.5 text-[13px] leading-relaxed text-slate-300"
|
|
484
484
|
v-html="s.bodyHtml"
|
|
485
485
|
/>
|
|
486
486
|
</div>
|
|
@@ -489,7 +489,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
489
489
|
</div>
|
|
490
490
|
|
|
491
491
|
<!-- right action rail -->
|
|
492
|
-
<aside class="hidden w-72 shrink-0 flex-col border-
|
|
492
|
+
<aside class="hidden w-72 shrink-0 flex-col border-s border-slate-800 lg:flex">
|
|
493
493
|
<div class="flex flex-col gap-4 px-4 py-5">
|
|
494
494
|
<div v-if="session" class="space-y-2 text-xs text-slate-400">
|
|
495
495
|
<div class="flex items-center justify-between">
|
|
@@ -506,7 +506,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
506
506
|
</div>
|
|
507
507
|
<div v-if="session.model" class="flex items-center justify-between">
|
|
508
508
|
<span>{{ t('brainstorm.rail.model') }}</span>
|
|
509
|
-
<span class="truncate
|
|
509
|
+
<span class="truncate ps-2 text-slate-500">{{ session.model }}</span>
|
|
510
510
|
</div>
|
|
511
511
|
</div>
|
|
512
512
|
|
|
@@ -521,6 +521,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
521
521
|
size="sm"
|
|
522
522
|
block
|
|
523
523
|
icon="i-lucide-arrow-right"
|
|
524
|
+
:ui="{ leadingIcon: 'rtl:-scale-x-100', trailingIcon: 'rtl:-scale-x-100' }"
|
|
524
525
|
:loading="acting"
|
|
525
526
|
@click="proceed"
|
|
526
527
|
>
|
|
@@ -258,7 +258,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
258
258
|
<h1 class="truncate text-base font-semibold text-white">{{ t('clarity.title') }}</h1>
|
|
259
259
|
<p v-if="block" class="truncate text-xs text-slate-500">{{ block.title }}</p>
|
|
260
260
|
</div>
|
|
261
|
-
<div class="
|
|
261
|
+
<div class="ms-auto flex items-center gap-1.5">
|
|
262
262
|
<UBadge v-if="review" color="neutral" variant="subtle" size="sm">
|
|
263
263
|
{{ t('clarity.iteration', { current: iteration, max: maxIterations }) }}
|
|
264
264
|
</UBadge>
|
|
@@ -360,7 +360,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
360
360
|
size="xs"
|
|
361
361
|
variant="soft"
|
|
362
362
|
:color="STATUS_COLOR[item.status]"
|
|
363
|
-
class="
|
|
363
|
+
class="ms-auto"
|
|
364
364
|
>
|
|
365
365
|
{{ t(STATUS_LABELS[item.status]) }}
|
|
366
366
|
</UBadge>
|
|
@@ -372,7 +372,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
372
372
|
<!-- recorded answer -->
|
|
373
373
|
<div
|
|
374
374
|
v-if="item.reply"
|
|
375
|
-
class="mt-2 rounded-md border-
|
|
375
|
+
class="mt-2 rounded-md border-s-2 border-slate-700 bg-slate-950/40 px-3 py-1.5 text-sm text-slate-300"
|
|
376
376
|
>
|
|
377
377
|
<span class="text-[10px] uppercase tracking-wide text-slate-500">
|
|
378
378
|
{{ t('clarity.answerLabel') }}
|
|
@@ -449,7 +449,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
449
449
|
<div v-for="s in outline.sections" :key="s.id" class="mb-2">
|
|
450
450
|
<button
|
|
451
451
|
v-if="s.title"
|
|
452
|
-
class="group flex w-full items-center gap-2 text-
|
|
452
|
+
class="group flex w-full items-center gap-2 text-start"
|
|
453
453
|
@click="toggle(s.id)"
|
|
454
454
|
>
|
|
455
455
|
<UIcon
|
|
@@ -465,7 +465,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
465
465
|
</button>
|
|
466
466
|
<div
|
|
467
467
|
v-show="!s.title || !collapsed[s.id]"
|
|
468
|
-
class="reader-prose mt-1
|
|
468
|
+
class="reader-prose mt-1 ps-5.5 text-[13px] leading-relaxed text-slate-300"
|
|
469
469
|
v-html="s.bodyHtml"
|
|
470
470
|
/>
|
|
471
471
|
</div>
|
|
@@ -474,7 +474,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
474
474
|
</div>
|
|
475
475
|
|
|
476
476
|
<!-- right action rail -->
|
|
477
|
-
<aside class="hidden w-72 shrink-0 flex-col border-
|
|
477
|
+
<aside class="hidden w-72 shrink-0 flex-col border-s border-slate-800 lg:flex">
|
|
478
478
|
<div class="flex flex-col gap-4 px-4 py-5">
|
|
479
479
|
<div v-if="review" class="space-y-2 text-xs text-slate-400">
|
|
480
480
|
<div class="flex items-center justify-between">
|
|
@@ -491,7 +491,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
491
491
|
</div>
|
|
492
492
|
<div v-if="review.model" class="flex items-center justify-between">
|
|
493
493
|
<span>{{ t('clarity.rail.model') }}</span>
|
|
494
|
-
<span class="truncate
|
|
494
|
+
<span class="truncate ps-2 text-slate-500">{{ review.model }}</span>
|
|
495
495
|
</div>
|
|
496
496
|
</div>
|
|
497
497
|
|
|
@@ -506,6 +506,7 @@ async function resolveExceeded(choice: 'extra-round' | 'proceed' | 'stop-reset')
|
|
|
506
506
|
size="sm"
|
|
507
507
|
block
|
|
508
508
|
icon="i-lucide-arrow-right"
|
|
509
|
+
:ui="{ leadingIcon: 'rtl:-scale-x-100', trailingIcon: 'rtl:-scale-x-100' }"
|
|
509
510
|
:loading="acting"
|
|
510
511
|
@click="proceed"
|
|
511
512
|
>
|
|
@@ -195,7 +195,7 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
|
|
|
195
195
|
t('consensus.expert', { letter: String.fromCharCode(65 + i) })
|
|
196
196
|
}}</span>
|
|
197
197
|
<span class="text-slate-400"> · {{ p.role }}</span>
|
|
198
|
-
<span v-if="p.modelId" class="
|
|
198
|
+
<span v-if="p.modelId" class="ms-1 text-slate-500">({{ p.modelId }})</span>
|
|
199
199
|
</div>
|
|
200
200
|
</div>
|
|
201
201
|
</section>
|
|
@@ -219,7 +219,7 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
|
|
|
219
219
|
<span class="text-xs text-slate-500">{{ roleFor(c.participantId) }}</span>
|
|
220
220
|
<span
|
|
221
221
|
v-if="topScore(c)"
|
|
222
|
-
class="
|
|
222
|
+
class="ms-auto rounded bg-slate-800 px-1.5 py-0.5 text-xs text-slate-300"
|
|
223
223
|
>{{
|
|
224
224
|
t('consensus.topScore', {
|
|
225
225
|
label: topScore(c)!.label,
|
|
@@ -199,12 +199,12 @@ onMounted(() => {
|
|
|
199
199
|
v-for="d in importedRows"
|
|
200
200
|
:key="`imp:${d.externalId}`"
|
|
201
201
|
type="button"
|
|
202
|
-
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-
|
|
202
|
+
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-slate-300 hover:bg-slate-800/70"
|
|
203
203
|
@click="pickImported(d.externalId, d.title, d.excerpt)"
|
|
204
204
|
>
|
|
205
205
|
<UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-indigo-400" />
|
|
206
206
|
<span class="truncate">{{ d.title }}</span>
|
|
207
|
-
<UBadge color="neutral" variant="soft" size="xs" class="
|
|
207
|
+
<UBadge color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">{{
|
|
208
208
|
t('documents.picker.importedBadge')
|
|
209
209
|
}}</UBadge>
|
|
210
210
|
</button>
|
|
@@ -214,7 +214,7 @@ onMounted(() => {
|
|
|
214
214
|
v-for="r in searchRows"
|
|
215
215
|
:key="`hit:${r.externalId}`"
|
|
216
216
|
type="button"
|
|
217
|
-
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-
|
|
217
|
+
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-slate-300 hover:bg-slate-800/70"
|
|
218
218
|
@click="pickSearch(r)"
|
|
219
219
|
>
|
|
220
220
|
<UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-slate-400" />
|
|
@@ -225,7 +225,7 @@ onMounted(() => {
|
|
|
225
225
|
<button
|
|
226
226
|
v-if="refRow"
|
|
227
227
|
type="button"
|
|
228
|
-
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-
|
|
228
|
+
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-slate-300 hover:bg-slate-800/70"
|
|
229
229
|
@click="pickRef(refRow)"
|
|
230
230
|
>
|
|
231
231
|
<UIcon name="i-lucide-link" class="h-3.5 w-3.5 shrink-0 text-slate-400" />
|
|
@@ -115,7 +115,7 @@ async function spawn() {
|
|
|
115
115
|
{{ t('documents.spawn.buildingPlan') }}
|
|
116
116
|
</div>
|
|
117
117
|
|
|
118
|
-
<div v-else-if="plan" class="max-h-80 space-y-3 overflow-y-auto
|
|
118
|
+
<div v-else-if="plan" class="max-h-80 space-y-3 overflow-y-auto pe-1">
|
|
119
119
|
<div
|
|
120
120
|
v-for="(frame, fi) in plan.frames"
|
|
121
121
|
:key="fi"
|
|
@@ -127,7 +127,7 @@ async function spawn() {
|
|
|
127
127
|
<UBadge variant="subtle" size="sm" color="neutral">{{ frame.type }}</UBadge>
|
|
128
128
|
</div>
|
|
129
129
|
|
|
130
|
-
<ul v-if="frame.tasks.length" class="mt-2 space-y-1
|
|
130
|
+
<ul v-if="frame.tasks.length" class="mt-2 space-y-1 ps-6">
|
|
131
131
|
<li
|
|
132
132
|
v-for="(task, ti) in frame.tasks"
|
|
133
133
|
:key="`t-${ti}`"
|
|
@@ -138,12 +138,12 @@ async function spawn() {
|
|
|
138
138
|
</li>
|
|
139
139
|
</ul>
|
|
140
140
|
|
|
141
|
-
<div v-for="(mod, mi) in frame.modules" :key="`m-${mi}`" class="mt-2
|
|
141
|
+
<div v-for="(mod, mi) in frame.modules" :key="`m-${mi}`" class="mt-2 ps-4">
|
|
142
142
|
<div class="flex items-center gap-1.5 text-xs font-medium text-slate-200">
|
|
143
143
|
<UIcon name="i-lucide-folder" class="h-3.5 w-3.5 text-amber-400" />
|
|
144
144
|
{{ mod.name }}
|
|
145
145
|
</div>
|
|
146
|
-
<ul class="mt-1 space-y-1
|
|
146
|
+
<ul class="mt-1 space-y-1 ps-5">
|
|
147
147
|
<li
|
|
148
148
|
v-for="(task, ti) in mod.tasks"
|
|
149
149
|
:key="`mt-${ti}`"
|
|
@@ -60,10 +60,17 @@ function openApprovalFor(approvalId: string) {
|
|
|
60
60
|
>
|
|
61
61
|
<!-- header / breadcrumb -->
|
|
62
62
|
<header class="flex items-center gap-3 border-b border-slate-800 px-6 py-4">
|
|
63
|
-
<UButton
|
|
63
|
+
<UButton
|
|
64
|
+
icon="i-lucide-arrow-left"
|
|
65
|
+
:ui="{ leadingIcon: 'rtl:-scale-x-100', trailingIcon: 'rtl:-scale-x-100' }"
|
|
66
|
+
color="neutral"
|
|
67
|
+
variant="ghost"
|
|
68
|
+
size="sm"
|
|
69
|
+
@click="close"
|
|
70
|
+
>
|
|
64
71
|
{{ t('focus.board') }}
|
|
65
72
|
</UButton>
|
|
66
|
-
<UIcon name="i-lucide-chevron-right" class="h-4 w-4 text-slate-600" />
|
|
73
|
+
<UIcon name="i-lucide-chevron-right" class="h-4 w-4 text-slate-600 rtl:-scale-x-100" />
|
|
67
74
|
<div
|
|
68
75
|
class="flex h-9 w-9 items-center justify-center rounded-lg"
|
|
69
76
|
:style="{ backgroundColor: typeMeta.accent + '22' }"
|
|
@@ -76,10 +83,10 @@ function openApprovalFor(approvalId: string) {
|
|
|
76
83
|
{{ t('focus.typeSubtitle', { type: typeMeta.label }) }}
|
|
77
84
|
</div>
|
|
78
85
|
</div>
|
|
79
|
-
<UBadge :color="statusMeta.chip as any" variant="subtle" class="
|
|
86
|
+
<UBadge :color="statusMeta.chip as any" variant="subtle" class="ms-2">
|
|
80
87
|
{{ statusMeta.label }}
|
|
81
88
|
</UBadge>
|
|
82
|
-
<div class="
|
|
89
|
+
<div class="ms-auto flex items-center gap-2">
|
|
83
90
|
<UDropdownMenu :items="runMenu">
|
|
84
91
|
<UButton
|
|
85
92
|
color="primary"
|
|
@@ -284,7 +284,7 @@ async function unlinkSource(id: string) {
|
|
|
284
284
|
>
|
|
285
285
|
{{ t('fragments.catalog.live', { source: f.documentRef.source }) }}
|
|
286
286
|
</UBadge>
|
|
287
|
-
<span class="
|
|
287
|
+
<span class="ms-auto font-mono text-[11px] text-slate-500">{{ f.id }}</span>
|
|
288
288
|
</div>
|
|
289
289
|
<p class="mt-1 text-sm text-slate-400">{{ f.summary }}</p>
|
|
290
290
|
<div v-if="f.tags?.length" class="mt-1 flex flex-wrap gap-1">
|
|
@@ -316,7 +316,7 @@ async function unlinkSource(id: string) {
|
|
|
316
316
|
size="xs"
|
|
317
317
|
color="error"
|
|
318
318
|
variant="ghost"
|
|
319
|
-
class="
|
|
319
|
+
class="ms-auto"
|
|
320
320
|
@click="removeFragment(f.id)"
|
|
321
321
|
/>
|
|
322
322
|
</div>
|
|
@@ -380,7 +380,7 @@ async function unlinkSource(id: string) {
|
|
|
380
380
|
{{ t('fragments.documents.lastResolved', { date: d(new Date(f.resolvedAt), 'long') }) }}
|
|
381
381
|
</p>
|
|
382
382
|
</div>
|
|
383
|
-
<div class="
|
|
383
|
+
<div class="ms-auto flex gap-1">
|
|
384
384
|
<UButton
|
|
385
385
|
icon="i-lucide-refresh-cw"
|
|
386
386
|
size="xs"
|
|
@@ -465,7 +465,7 @@ async function unlinkSource(id: string) {
|
|
|
465
465
|
size="xs"
|
|
466
466
|
color="warning"
|
|
467
467
|
variant="subtle"
|
|
468
|
-
class="
|
|
468
|
+
class="ms-auto"
|
|
469
469
|
>
|
|
470
470
|
{{
|
|
471
471
|
t(
|
|
@@ -475,7 +475,7 @@ async function unlinkSource(id: string) {
|
|
|
475
475
|
)
|
|
476
476
|
}}
|
|
477
477
|
</UBadge>
|
|
478
|
-
<div class="
|
|
478
|
+
<div class="ms-auto flex gap-1">
|
|
479
479
|
<UButton
|
|
480
480
|
icon="i-lucide-search-check"
|
|
481
481
|
size="xs"
|
|
@@ -324,7 +324,7 @@ const conflictVerdict = computed(() => {
|
|
|
324
324
|
{{ c.name }}
|
|
325
325
|
<UIcon
|
|
326
326
|
name="i-lucide-external-link"
|
|
327
|
-
class="
|
|
327
|
+
class="ms-0.5 inline h-3 w-3 opacity-60 group-hover:opacity-100"
|
|
328
328
|
/>
|
|
329
329
|
</a>
|
|
330
330
|
<span v-else class="min-w-0 flex-1 truncate text-[13px] text-slate-200">{{
|
|
@@ -397,7 +397,7 @@ const conflictVerdict = computed(() => {
|
|
|
397
397
|
size="sm"
|
|
398
398
|
>{{ OUTCOME_LABELS[a.outcome] }}</UBadge
|
|
399
399
|
>
|
|
400
|
-
<span v-if="formatClock(a.at)" class="
|
|
400
|
+
<span v-if="formatClock(a.at)" class="ms-auto text-[11px] text-slate-500">{{
|
|
401
401
|
formatClock(a.at)
|
|
402
402
|
}}</span>
|
|
403
403
|
</div>
|
|
@@ -415,7 +415,7 @@ const conflictVerdict = computed(() => {
|
|
|
415
415
|
|
|
416
416
|
<!-- Sidebar: gate state -->
|
|
417
417
|
<aside
|
|
418
|
-
class="hidden w-60 shrink-0 flex-col gap-4 border-
|
|
418
|
+
class="hidden w-60 shrink-0 flex-col gap-4 border-s border-slate-800 bg-slate-900/50 px-4 py-4 lg:flex"
|
|
419
419
|
>
|
|
420
420
|
<div v-if="gate">
|
|
421
421
|
<h4 class="mb-2 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
@@ -361,7 +361,7 @@ async function merge(pr: GitHubPullRequest) {
|
|
|
361
361
|
v-for="r in github.availableRepos"
|
|
362
362
|
:key="r.githubId"
|
|
363
363
|
type="button"
|
|
364
|
-
class="flex w-full items-center gap-2 rounded px-2 py-1.5 text-
|
|
364
|
+
class="flex w-full items-center gap-2 rounded px-2 py-1.5 text-start transition hover:bg-slate-800/60"
|
|
365
365
|
@click="toggleSelected(r.githubId)"
|
|
366
366
|
>
|
|
367
367
|
<UIcon
|
|
@@ -400,7 +400,10 @@ async function merge(pr: GitHubPullRequest) {
|
|
|
400
400
|
class="rounded-md border border-slate-800 bg-slate-900/60"
|
|
401
401
|
>
|
|
402
402
|
<div class="flex items-center justify-between gap-2 px-3 py-2">
|
|
403
|
-
<button
|
|
403
|
+
<button
|
|
404
|
+
class="flex min-w-0 items-center gap-2 text-start"
|
|
405
|
+
@click="toggleRepo(repo)"
|
|
406
|
+
>
|
|
404
407
|
<UIcon
|
|
405
408
|
:name="
|
|
406
409
|
expandedRepo === repo.githubId
|
|
@@ -309,7 +309,7 @@ const canDestroy = computed(
|
|
|
309
309
|
: t('humanTest.history.pulledMain')
|
|
310
310
|
}}</span>
|
|
311
311
|
<span
|
|
312
|
-
class="
|
|
312
|
+
class="ms-1.5 rounded px-1 text-[10px] uppercase"
|
|
313
313
|
:class="
|
|
314
314
|
r.outcome === 'completed'
|
|
315
315
|
? 'bg-emerald-500/15 text-emerald-300'
|