@cat-factory/app 0.6.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/LICENSE +21 -0
- package/README.md +88 -0
- package/app/app.config.ts +8 -0
- package/app/app.vue +11 -0
- package/app/assets/css/main.css +100 -0
- package/app/components/auth/AuthGate.vue +24 -0
- package/app/components/auth/LoginScreen.vue +143 -0
- package/app/components/auth/UserMenu.vue +39 -0
- package/app/components/board/AddTaskModal.vue +444 -0
- package/app/components/board/AgentFailureCard.vue +97 -0
- package/app/components/board/AgentStopButton.vue +61 -0
- package/app/components/board/BoardCanvas.vue +183 -0
- package/app/components/board/ContextPicker.vue +367 -0
- package/app/components/board/RecurringPipelineModal.vue +219 -0
- package/app/components/board/TaskDependencyEdges.vue +132 -0
- package/app/components/board/nodes/AgentChip.vue +59 -0
- package/app/components/board/nodes/BlockNode.vue +433 -0
- package/app/components/board/nodes/DecisionBadge.vue +27 -0
- package/app/components/board/nodes/DraggableTask.vue +48 -0
- package/app/components/board/nodes/ModuleFrame.vue +97 -0
- package/app/components/board/nodes/TaskCard.vue +359 -0
- package/app/components/board/nodes/TaskPipelineMini.vue +159 -0
- package/app/components/bootstrap/BootstrapModal.vue +665 -0
- package/app/components/clarity/ClarityReviewWindow.vue +611 -0
- package/app/components/consensus/ConsensusSessionWindow.vue +210 -0
- package/app/components/documents/DocumentImportModal.vue +161 -0
- package/app/components/documents/DocumentSourceConnectModal.vue +127 -0
- package/app/components/documents/SpawnPreviewModal.vue +161 -0
- package/app/components/documents/TaskContextDocs.vue +83 -0
- package/app/components/focus/BlockFocusView.vue +171 -0
- package/app/components/fragments/FragmentLibraryPanel.vue +340 -0
- package/app/components/gates/GateResultView.vue +282 -0
- package/app/components/github/AddServiceFromRepoModal.vue +354 -0
- package/app/components/github/GitHubConnect.vue +183 -0
- package/app/components/github/GitHubOnboarding.vue +45 -0
- package/app/components/github/GitHubPanel.vue +584 -0
- package/app/components/github/RepoTreeBrowser.vue +171 -0
- package/app/components/layout/AccountTeamSettings.vue +237 -0
- package/app/components/layout/BoardSwitcher.vue +280 -0
- package/app/components/layout/BoardToolbar.vue +156 -0
- package/app/components/layout/CommandBar.vue +336 -0
- package/app/components/layout/GitHubPatBanner.vue +73 -0
- package/app/components/layout/NotificationsInbox.vue +175 -0
- package/app/components/layout/SideBar.vue +314 -0
- package/app/components/layout/SpendWarningBanner.vue +107 -0
- package/app/components/observability/StepMetricsBar.vue +102 -0
- package/app/components/palettes/AgentPalette.vue +86 -0
- package/app/components/panels/AgentStepDetail.vue +737 -0
- package/app/components/panels/DecisionModal.vue +71 -0
- package/app/components/panels/InspectorPanel.vue +465 -0
- package/app/components/panels/ObservabilityPanel.vue +351 -0
- package/app/components/panels/StepMetadataCard.vue +253 -0
- package/app/components/panels/StepRestartControl.vue +90 -0
- package/app/components/panels/StepResultViewHost.vue +40 -0
- package/app/components/panels/StepTestReport.vue +84 -0
- package/app/components/panels/inspector/ContainerSummary.vue +74 -0
- package/app/components/panels/inspector/RecurringScheduleSettings.vue +178 -0
- package/app/components/panels/inspector/ServiceFragments.vue +82 -0
- package/app/components/panels/inspector/ServiceTestConfig.vue +198 -0
- package/app/components/panels/inspector/TaskAgentConfig.vue +81 -0
- package/app/components/panels/inspector/TaskDependencies.vue +70 -0
- package/app/components/panels/inspector/TaskEstimateBadge.vue +56 -0
- package/app/components/panels/inspector/TaskExecution.vue +364 -0
- package/app/components/panels/inspector/TaskRunSettings.vue +187 -0
- package/app/components/panels/inspector/TaskStructure.vue +96 -0
- package/app/components/pipeline/AgentKindIcon.vue +30 -0
- package/app/components/pipeline/IterationCapPrompt.vue +70 -0
- package/app/components/pipeline/PipelineBuilder.vue +817 -0
- package/app/components/pipeline/PipelineProgress.vue +484 -0
- package/app/components/providers/ApiKeysSection.vue +273 -0
- package/app/components/providers/PersonalCredentialModal.vue +128 -0
- package/app/components/providers/PersonalSubscriptionSection.vue +225 -0
- package/app/components/providers/VendorCredentialsModal.vue +197 -0
- package/app/components/recurring/RecurrenceEditor.vue +124 -0
- package/app/components/requirements/RequirementsReviewWindow.vue +620 -0
- package/app/components/settings/DatadogPanel.vue +213 -0
- package/app/components/settings/LocalModelEndpointsPanel.vue +286 -0
- package/app/components/settings/MergeThresholdsPanel.vue +378 -0
- package/app/components/settings/ModelDefaultsPanel.vue +250 -0
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +124 -0
- package/app/components/settings/WorkspaceSettingsPanel.vue +142 -0
- package/app/components/slack/SlackPanel.vue +299 -0
- package/app/components/tasks/TaskContextIssues.vue +88 -0
- package/app/components/tasks/TaskImportModal.vue +207 -0
- package/app/components/tasks/TaskSourceConnectModal.vue +133 -0
- package/app/components/testing/TestReportWindow.vue +404 -0
- package/app/composables/api/accounts.ts +81 -0
- package/app/composables/api/auth.ts +45 -0
- package/app/composables/api/board.ts +101 -0
- package/app/composables/api/bootstrap.ts +62 -0
- package/app/composables/api/context.ts +25 -0
- package/app/composables/api/documents.ts +74 -0
- package/app/composables/api/execution.ts +127 -0
- package/app/composables/api/fragments.ts +71 -0
- package/app/composables/api/github.ts +131 -0
- package/app/composables/api/models.ts +127 -0
- package/app/composables/api/notifications.ts +23 -0
- package/app/composables/api/presets.ts +29 -0
- package/app/composables/api/recurring.ts +68 -0
- package/app/composables/api/releaseHealth.ts +43 -0
- package/app/composables/api/reviews.ts +146 -0
- package/app/composables/api/slack.ts +54 -0
- package/app/composables/api/tasks.ts +72 -0
- package/app/composables/api/workspaces.ts +36 -0
- package/app/composables/useApi.ts +89 -0
- package/app/composables/useBlockDrag.ts +90 -0
- package/app/composables/useBlockQueries.ts +154 -0
- package/app/composables/useBoardFlow.ts +11 -0
- package/app/composables/useContextLinking.ts +65 -0
- package/app/composables/useDepLabels.ts +26 -0
- package/app/composables/useFrameResize.ts +54 -0
- package/app/composables/useResultView.ts +48 -0
- package/app/composables/useReviewStage.ts +40 -0
- package/app/composables/useSemanticZoom.ts +31 -0
- package/app/composables/useStepApproval.ts +233 -0
- package/app/composables/useStepProse.ts +78 -0
- package/app/composables/useStepTimer.ts +63 -0
- package/app/composables/useTaskExpansion.ts +92 -0
- package/app/composables/useWorkspaceStream.ts +155 -0
- package/app/docs/architecture.md +31 -0
- package/app/pages/index.vue +141 -0
- package/app/stores/accounts.ts +152 -0
- package/app/stores/agentConfig.ts +35 -0
- package/app/stores/agentRuns.ts +122 -0
- package/app/stores/agents.ts +40 -0
- package/app/stores/apiKeys.ts +108 -0
- package/app/stores/auth.ts +166 -0
- package/app/stores/board.spec.ts +205 -0
- package/app/stores/board.ts +286 -0
- package/app/stores/bootstrap.ts +97 -0
- package/app/stores/clarity.ts +196 -0
- package/app/stores/consensus.ts +60 -0
- package/app/stores/documents.ts +176 -0
- package/app/stores/execution.ts +273 -0
- package/app/stores/fragmentLibrary.ts +147 -0
- package/app/stores/fragments.ts +40 -0
- package/app/stores/github.ts +305 -0
- package/app/stores/localModels.ts +51 -0
- package/app/stores/mergePresets.ts +58 -0
- package/app/stores/modelDefaults.ts +76 -0
- package/app/stores/models.ts +134 -0
- package/app/stores/notifications.ts +70 -0
- package/app/stores/observability.ts +144 -0
- package/app/stores/personalSubscriptions.ts +215 -0
- package/app/stores/pipelines.ts +327 -0
- package/app/stores/recurringPipelines.ts +112 -0
- package/app/stores/releaseHealth.ts +75 -0
- package/app/stores/requirements.spec.ts +94 -0
- package/app/stores/requirements.ts +208 -0
- package/app/stores/serviceFragmentDefaults.ts +29 -0
- package/app/stores/services.ts +87 -0
- package/app/stores/slack.ts +142 -0
- package/app/stores/taskExpansion.ts +36 -0
- package/app/stores/tasks.spec.ts +71 -0
- package/app/stores/tasks.ts +176 -0
- package/app/stores/tracker.ts +27 -0
- package/app/stores/ui.ts +434 -0
- package/app/stores/vendorCredentials.ts +54 -0
- package/app/stores/workspace.ts +215 -0
- package/app/stores/workspaceSettings.ts +36 -0
- package/app/types/accounts.ts +77 -0
- package/app/types/bootstrap.ts +83 -0
- package/app/types/clarity.ts +59 -0
- package/app/types/consensus.ts +91 -0
- package/app/types/documents.ts +104 -0
- package/app/types/domain.ts +495 -0
- package/app/types/execution.ts +383 -0
- package/app/types/fragments.ts +72 -0
- package/app/types/github.ts +173 -0
- package/app/types/localModels.ts +73 -0
- package/app/types/merge.ts +71 -0
- package/app/types/models.ts +157 -0
- package/app/types/notifications.ts +74 -0
- package/app/types/recurring.ts +69 -0
- package/app/types/releaseHealth.ts +31 -0
- package/app/types/requirements.ts +61 -0
- package/app/types/services.ts +27 -0
- package/app/types/slack.ts +57 -0
- package/app/types/tasks.ts +82 -0
- package/app/types/tracker.ts +18 -0
- package/app/utils/agentOutput.spec.ts +128 -0
- package/app/utils/agentOutput.ts +173 -0
- package/app/utils/catalog.spec.ts +112 -0
- package/app/utils/catalog.ts +455 -0
- package/app/utils/dnd.ts +29 -0
- package/app/utils/observability.ts +52 -0
- package/app/utils/pipelineRender.ts +151 -0
- package/nuxt.config.ts +55 -0
- package/package.json +45 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import type { StepMetrics } from '~/types/execution'
|
|
4
|
+
import {
|
|
5
|
+
formatMs,
|
|
6
|
+
formatTokens,
|
|
7
|
+
headroomColor,
|
|
8
|
+
headroomRatio,
|
|
9
|
+
pct,
|
|
10
|
+
transportRatio,
|
|
11
|
+
} from '~/utils/observability'
|
|
12
|
+
|
|
13
|
+
// Compact, at-a-glance LLM rollup for one pipeline step: token usage, an
|
|
14
|
+
// output-limit headroom bar (how close the step ran to truncation), a
|
|
15
|
+
// transport-vs-execution latency split, and error/warning badges. Rendered inline
|
|
16
|
+
// on the step surfaces (step detail, pipeline timeline). A no-op when there are no
|
|
17
|
+
// recorded calls. Clicking anywhere emits `inspect` so a parent can open the
|
|
18
|
+
// drill-down panel.
|
|
19
|
+
const props = defineProps<{ metrics: StepMetrics; clickable?: boolean }>()
|
|
20
|
+
defineEmits<{ inspect: [] }>()
|
|
21
|
+
|
|
22
|
+
const m = computed(() => props.metrics)
|
|
23
|
+
const headroom = computed(() => headroomRatio(m.value))
|
|
24
|
+
const transport = computed(() => transportRatio(m.value))
|
|
25
|
+
const headroomTone = computed(() => headroomColor(headroom.value, m.value.truncatedCalls > 0))
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<template>
|
|
29
|
+
<div
|
|
30
|
+
v-if="m.calls > 0"
|
|
31
|
+
class="rounded-lg border border-slate-800 bg-slate-900/40 p-2.5 text-[12px]"
|
|
32
|
+
:class="
|
|
33
|
+
clickable ? 'cursor-pointer transition hover:border-slate-700 hover:bg-slate-900/70' : ''
|
|
34
|
+
"
|
|
35
|
+
:role="clickable ? 'button' : undefined"
|
|
36
|
+
@click="clickable ? $emit('inspect') : undefined"
|
|
37
|
+
>
|
|
38
|
+
<!-- header line: call count + tokens + warning/error badges -->
|
|
39
|
+
<div class="flex items-center gap-2">
|
|
40
|
+
<UIcon name="i-lucide-activity" class="h-3.5 w-3.5 shrink-0 text-slate-500" />
|
|
41
|
+
<span class="text-slate-300"> {{ m.calls }} {{ m.calls === 1 ? 'call' : 'calls' }} </span>
|
|
42
|
+
<span class="text-slate-500">·</span>
|
|
43
|
+
<span class="tabular-nums text-slate-400" title="Prompt / completion tokens">
|
|
44
|
+
{{ formatTokens(m.promptTokens) }}↑ {{ formatTokens(m.completionTokens) }}↓
|
|
45
|
+
</span>
|
|
46
|
+
<div class="ml-auto flex items-center gap-1">
|
|
47
|
+
<UBadge v-if="m.errors > 0" color="error" variant="subtle" size="sm">
|
|
48
|
+
{{ m.errors }} error{{ m.errors === 1 ? '' : 's' }}
|
|
49
|
+
</UBadge>
|
|
50
|
+
<UBadge v-if="m.warnings > 0" color="warning" variant="subtle" size="sm">
|
|
51
|
+
{{ m.warnings }} warning{{ m.warnings === 1 ? '' : 's' }}
|
|
52
|
+
</UBadge>
|
|
53
|
+
<UIcon v-if="clickable" name="i-lucide-chevron-right" class="h-3.5 w-3.5 text-slate-600" />
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<!-- output-limit headroom -->
|
|
58
|
+
<div v-if="headroom !== null" class="mt-2">
|
|
59
|
+
<div class="flex items-center justify-between text-[11px]">
|
|
60
|
+
<span class="text-slate-500">Output limit</span>
|
|
61
|
+
<span class="tabular-nums" :class="headroomTone">
|
|
62
|
+
{{ formatTokens(m.peakCompletionTokens) }} /
|
|
63
|
+
{{ formatTokens(m.maxOutputTokens ?? 0) }} ({{ pct(headroom) }}%)
|
|
64
|
+
</span>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="mt-1 h-1 overflow-hidden rounded-full bg-slate-700/60">
|
|
67
|
+
<div
|
|
68
|
+
class="h-full rounded-full transition-all duration-500"
|
|
69
|
+
:class="
|
|
70
|
+
m.truncatedCalls > 0 || headroom >= 0.98
|
|
71
|
+
? 'bg-rose-400'
|
|
72
|
+
: headroom >= 0.8
|
|
73
|
+
? 'bg-amber-400'
|
|
74
|
+
: 'bg-emerald-400'
|
|
75
|
+
"
|
|
76
|
+
:style="{ width: `${Math.max(2, pct(headroom))}%` }"
|
|
77
|
+
/>
|
|
78
|
+
</div>
|
|
79
|
+
<p v-if="m.truncatedCalls > 0" class="mt-1 text-[11px] text-rose-400">
|
|
80
|
+
{{ m.truncatedCalls }} call{{ m.truncatedCalls === 1 ? '' : 's' }} truncated at the limit
|
|
81
|
+
</p>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<!-- transport overhead vs model execution -->
|
|
85
|
+
<div v-if="transport !== null" class="mt-2">
|
|
86
|
+
<div class="flex items-center justify-between text-[11px]">
|
|
87
|
+
<span class="text-slate-500">Transport vs execution</span>
|
|
88
|
+
<span class="tabular-nums text-slate-400">
|
|
89
|
+
{{ formatMs(m.overheadMs) }} / {{ formatMs(m.upstreamMs) }}
|
|
90
|
+
</span>
|
|
91
|
+
</div>
|
|
92
|
+
<div class="mt-1 flex h-1 overflow-hidden rounded-full bg-slate-700/60">
|
|
93
|
+
<div
|
|
94
|
+
class="h-full bg-sky-400/80"
|
|
95
|
+
:style="{ width: `${pct(transport)}%` }"
|
|
96
|
+
title="Transport / proxy overhead"
|
|
97
|
+
/>
|
|
98
|
+
<div class="h-full bg-indigo-400/80 flex-1" title="Model execution" />
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</template>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useLocalStorage } from '@vueuse/core'
|
|
4
|
+
import type { AgentKind } from '~/types/domain'
|
|
5
|
+
import { AGENT_CATEGORIES, OBSERVABILITY_GATE_ARCHETYPE } from '~/utils/catalog'
|
|
6
|
+
|
|
7
|
+
const agents = useAgentsStore()
|
|
8
|
+
const releaseHealth = useReleaseHealthStore()
|
|
9
|
+
defineEmits<{ (e: 'add', kind: AgentKind): void }>()
|
|
10
|
+
|
|
11
|
+
// The post-release-health gate is only meaningful — and only accepted by the backend —
|
|
12
|
+
// with an observability integration connected, so it appears in the palette ONLY then.
|
|
13
|
+
const palette = computed(() =>
|
|
14
|
+
releaseHealth.connection.connected
|
|
15
|
+
? [...agents.archetypes, OBSERVABILITY_GATE_ARCHETYPE]
|
|
16
|
+
: agents.archetypes,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
// Group the palette into the ordered catalog categories, plus a trailing "Custom" bucket
|
|
20
|
+
// for runtime-added agents that carry no category. Empty groups are dropped.
|
|
21
|
+
const groups = computed(() => {
|
|
22
|
+
const ordered = AGENT_CATEGORIES.map((cat) => ({
|
|
23
|
+
id: cat.id as string,
|
|
24
|
+
label: cat.label,
|
|
25
|
+
agents: palette.value.filter((a) => a.category === cat.id),
|
|
26
|
+
}))
|
|
27
|
+
const custom = palette.value.filter((a) => !a.category)
|
|
28
|
+
if (custom.length) ordered.push({ id: 'custom', label: 'Custom agents', agents: custom })
|
|
29
|
+
return ordered.filter((g) => g.agents.length)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
// Persist which category sections are collapsed across builder opens.
|
|
33
|
+
const collapsed = useLocalStorage<string[]>('cf.pipelineBuilder.collapsedAgentCategories', [])
|
|
34
|
+
function isCollapsed(id: string) {
|
|
35
|
+
return collapsed.value.includes(id)
|
|
36
|
+
}
|
|
37
|
+
function toggle(id: string) {
|
|
38
|
+
collapsed.value = isCollapsed(id)
|
|
39
|
+
? collapsed.value.filter((c) => c !== id)
|
|
40
|
+
: [...collapsed.value, id]
|
|
41
|
+
}
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<template>
|
|
45
|
+
<div class="space-y-2">
|
|
46
|
+
<p class="px-1 text-[11px] text-slate-500">Click an agent to append it to the pipeline.</p>
|
|
47
|
+
<div class="space-y-2">
|
|
48
|
+
<section v-for="g in groups" :key="g.id">
|
|
49
|
+
<button
|
|
50
|
+
type="button"
|
|
51
|
+
class="flex w-full items-center gap-1.5 rounded px-1 py-1 text-left text-[11px] font-semibold uppercase tracking-wide text-slate-400 transition hover:text-slate-200"
|
|
52
|
+
@click="toggle(g.id)"
|
|
53
|
+
>
|
|
54
|
+
<UIcon
|
|
55
|
+
:name="isCollapsed(g.id) ? 'i-lucide-chevron-right' : 'i-lucide-chevron-down'"
|
|
56
|
+
class="h-3.5 w-3.5 shrink-0"
|
|
57
|
+
/>
|
|
58
|
+
<span>{{ g.label }}</span>
|
|
59
|
+
<span class="ml-auto text-slate-600">{{ g.agents.length }}</span>
|
|
60
|
+
</button>
|
|
61
|
+
<div v-if="!isCollapsed(g.id)" class="mt-1 space-y-1.5">
|
|
62
|
+
<button
|
|
63
|
+
v-for="a in g.agents"
|
|
64
|
+
:key="a.kind"
|
|
65
|
+
type="button"
|
|
66
|
+
class="flex w-full items-center gap-2.5 rounded-lg border border-slate-700 bg-slate-800/60 p-2 text-left transition hover:border-slate-500 hover:bg-slate-800"
|
|
67
|
+
:title="a.description"
|
|
68
|
+
@click="$emit('add', a.kind)"
|
|
69
|
+
>
|
|
70
|
+
<div
|
|
71
|
+
class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg"
|
|
72
|
+
:style="{ backgroundColor: a.color + '22' }"
|
|
73
|
+
>
|
|
74
|
+
<UIcon :name="a.icon" class="h-4 w-4" :style="{ color: a.color }" />
|
|
75
|
+
</div>
|
|
76
|
+
<div class="min-w-0">
|
|
77
|
+
<div class="text-xs font-semibold text-slate-100">{{ a.label }}</div>
|
|
78
|
+
<div class="truncate text-[10px] text-slate-400">{{ a.description }}</div>
|
|
79
|
+
</div>
|
|
80
|
+
<UIcon name="i-lucide-plus" class="ml-auto h-4 w-4 shrink-0 text-slate-500" />
|
|
81
|
+
</button>
|
|
82
|
+
</div>
|
|
83
|
+
</section>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</template>
|