@cat-factory/app 0.9.0 → 0.10.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/AddTaskModal.vue +209 -21
- package/app/components/board/nodes/BlockNode.vue +2 -2
- package/app/components/focus/BlockFocusView.vue +2 -2
- package/app/components/layout/CommandBar.vue +7 -33
- package/app/components/layout/IntegrationsHub.vue +230 -0
- package/app/components/layout/SideBar.vue +8 -170
- package/app/components/panels/GenericStructuredResultView.vue +131 -0
- package/app/components/panels/InspectorPanel.vue +6 -2
- package/app/components/panels/StepResultViewHost.vue +4 -0
- package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +148 -0
- package/app/components/settings/IssueTrackerWritebackPanel.vue +45 -57
- package/app/components/settings/MergeThresholdsPanel.vue +189 -226
- package/app/components/settings/ObservabilityConnectionPanel.vue +151 -0
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +46 -61
- package/app/components/settings/WorkspaceSettingsPanel.vue +136 -63
- package/app/composables/api/releaseHealth.ts +11 -10
- package/app/pages/index.vue +4 -8
- package/app/stores/agents.ts +27 -2
- package/app/stores/releaseHealth.ts +48 -12
- package/app/stores/ui.ts +34 -42
- package/app/stores/workspace.ts +4 -0
- package/app/types/domain.ts +33 -1
- package/app/types/execution.ts +6 -0
- package/app/types/releaseHealth.ts +19 -11
- package/app/utils/catalog.spec.ts +10 -0
- package/app/utils/catalog.ts +20 -6
- package/package.json +2 -2
- package/app/components/board/ContextPicker.vue +0 -367
- package/app/components/settings/DatadogPanel.vue +0 -213
package/app/stores/ui.ts
CHANGED
|
@@ -64,18 +64,22 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
64
64
|
// Command bar (⌘K) — searchable launcher for every navbar action.
|
|
65
65
|
const commandBarOpen = ref(false)
|
|
66
66
|
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
//
|
|
67
|
+
// Integrations hub: a single modal listing every external system the workspace
|
|
68
|
+
// can enable/link (GitHub, Slack, document + task sources, Datadog, LLM vendors,
|
|
69
|
+
// local runners, OpenRouter). Replaces the per-integration navbar buttons; each
|
|
70
|
+
// row inside it opens that integration's own panel via the handlers below.
|
|
71
|
+
const integrationsOpen = ref(false)
|
|
72
|
+
|
|
73
|
+
// Workspace-settings modal: a single tabbed window gathering the workspace-wide
|
|
74
|
+
// config (workspace / merge thresholds / issue writeback / service best practices).
|
|
75
|
+
// `workspaceSettingsTab` lets other surfaces deep-link straight to a tab.
|
|
71
76
|
const workspaceSettingsOpen = ref(false)
|
|
72
|
-
const
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
|
|
77
|
+
const workspaceSettingsTab = ref('workspace')
|
|
78
|
+
// Observability integration: the post-release-health connection panel (Datadog
|
|
79
|
+
// today, pluggable). NB: distinct from `observabilityInstanceId` below, which is the
|
|
80
|
+
// LLM per-call observability panel.
|
|
81
|
+
const observabilityConnectionOpen = ref(false)
|
|
76
82
|
const modelConfigOpen = ref(false)
|
|
77
|
-
// Workspace-settings panel: the default service-fragment selection new services inherit.
|
|
78
|
-
const serviceFragmentDefaultsOpen = ref(false)
|
|
79
83
|
// LLM-vendor subscription credentials (the token pool powering the Claude Code
|
|
80
84
|
// / Codex harnesses).
|
|
81
85
|
const vendorCredentialsOpen = ref(false)
|
|
@@ -280,29 +284,27 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
280
284
|
function toggleCommandBar() {
|
|
281
285
|
commandBarOpen.value = !commandBarOpen.value
|
|
282
286
|
}
|
|
283
|
-
function
|
|
284
|
-
|
|
287
|
+
function openIntegrations() {
|
|
288
|
+
integrationsOpen.value = true
|
|
285
289
|
}
|
|
286
|
-
function
|
|
287
|
-
|
|
290
|
+
function closeIntegrations() {
|
|
291
|
+
integrationsOpen.value = false
|
|
288
292
|
}
|
|
289
|
-
function openWorkspaceSettings() {
|
|
293
|
+
function openWorkspaceSettings(tab = 'workspace') {
|
|
294
|
+
workspaceSettingsTab.value = tab
|
|
290
295
|
workspaceSettingsOpen.value = true
|
|
291
296
|
}
|
|
292
297
|
function closeWorkspaceSettings() {
|
|
293
298
|
workspaceSettingsOpen.value = false
|
|
294
299
|
}
|
|
295
|
-
function
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
function closeIssueWriteback() {
|
|
299
|
-
issueWritebackOpen.value = false
|
|
300
|
+
function setWorkspaceSettingsTab(tab: string) {
|
|
301
|
+
workspaceSettingsTab.value = tab
|
|
300
302
|
}
|
|
301
|
-
function
|
|
302
|
-
|
|
303
|
+
function openObservabilityConnection() {
|
|
304
|
+
observabilityConnectionOpen.value = true
|
|
303
305
|
}
|
|
304
|
-
function
|
|
305
|
-
|
|
306
|
+
function closeObservabilityConnection() {
|
|
307
|
+
observabilityConnectionOpen.value = false
|
|
306
308
|
}
|
|
307
309
|
function openModelConfig() {
|
|
308
310
|
modelConfigOpen.value = true
|
|
@@ -310,12 +312,6 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
310
312
|
function closeModelConfig() {
|
|
311
313
|
modelConfigOpen.value = false
|
|
312
314
|
}
|
|
313
|
-
function openServiceFragmentDefaults() {
|
|
314
|
-
serviceFragmentDefaultsOpen.value = true
|
|
315
|
-
}
|
|
316
|
-
function closeServiceFragmentDefaults() {
|
|
317
|
-
serviceFragmentDefaultsOpen.value = false
|
|
318
|
-
}
|
|
319
315
|
function openVendorCredentials() {
|
|
320
316
|
vendorCredentialsOpen.value = true
|
|
321
317
|
}
|
|
@@ -376,12 +372,11 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
376
372
|
slackOpen,
|
|
377
373
|
fragmentLibraryOpen,
|
|
378
374
|
commandBarOpen,
|
|
379
|
-
|
|
380
|
-
issueWritebackOpen,
|
|
375
|
+
integrationsOpen,
|
|
381
376
|
workspaceSettingsOpen,
|
|
382
|
-
|
|
377
|
+
workspaceSettingsTab,
|
|
378
|
+
observabilityConnectionOpen,
|
|
383
379
|
modelConfigOpen,
|
|
384
|
-
serviceFragmentDefaultsOpen,
|
|
385
380
|
vendorCredentialsOpen,
|
|
386
381
|
localModelsOpen,
|
|
387
382
|
openRouterOpen,
|
|
@@ -428,18 +423,15 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
428
423
|
openCommandBar,
|
|
429
424
|
closeCommandBar,
|
|
430
425
|
toggleCommandBar,
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
openIssueWriteback,
|
|
434
|
-
closeIssueWriteback,
|
|
426
|
+
openIntegrations,
|
|
427
|
+
closeIntegrations,
|
|
435
428
|
openWorkspaceSettings,
|
|
436
429
|
closeWorkspaceSettings,
|
|
437
|
-
|
|
438
|
-
|
|
430
|
+
setWorkspaceSettingsTab,
|
|
431
|
+
openObservabilityConnection,
|
|
432
|
+
closeObservabilityConnection,
|
|
439
433
|
openModelConfig,
|
|
440
434
|
closeModelConfig,
|
|
441
|
-
openServiceFragmentDefaults,
|
|
442
|
-
closeServiceFragmentDefaults,
|
|
443
435
|
openVendorCredentials,
|
|
444
436
|
closeVendorCredentials,
|
|
445
437
|
openLocalModels,
|
package/app/stores/workspace.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { useModelPresetsStore } from '~/stores/modelPresets'
|
|
|
14
14
|
import { useServiceFragmentDefaultsStore } from '~/stores/serviceFragmentDefaults'
|
|
15
15
|
import { useRecurringPipelinesStore } from '~/stores/recurringPipelines'
|
|
16
16
|
import { useServicesStore } from '~/stores/services'
|
|
17
|
+
import { useAgentsStore } from '~/stores/agents'
|
|
17
18
|
import { useTrackerStore } from '~/stores/tracker'
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -76,6 +77,9 @@ export const useWorkspaceStore = defineStore(
|
|
|
76
77
|
useRecurringPipelinesStore().hydrate(snapshot.recurringPipelines ?? [])
|
|
77
78
|
useTrackerStore().hydrate(snapshot.trackerSettings)
|
|
78
79
|
useServicesStore().hydrate(snapshot.mounts ?? [], snapshot.serviceCatalog ?? [])
|
|
80
|
+
// Merge the deployment's registered custom agent kinds into the palette catalog so a
|
|
81
|
+
// proprietary kind renders as a first-class block + result view (idempotent on reload).
|
|
82
|
+
useAgentsStore().registerCustomKinds(snapshot.customAgentKinds ?? [])
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
/** Resolve accounts + boards, then open the right board for the active account. */
|
package/app/types/domain.ts
CHANGED
|
@@ -35,7 +35,13 @@ export type BlockStatus =
|
|
|
35
35
|
| 'pr_ready' // pipeline finished — a PR is open and awaiting merge
|
|
36
36
|
| 'done' // PR merged, implementation complete
|
|
37
37
|
|
|
38
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* Kind of architecture building block (drives icon + accent). `external` and
|
|
40
|
+
* `environment` are no longer user-creatable, but the backend still emits them
|
|
41
|
+
* (the seed's third-party `external` service, and the environments integration's
|
|
42
|
+
* `environment` blocks), so they remain part of the union for display parity with
|
|
43
|
+
* the contracts `blockTypeSchema`.
|
|
44
|
+
*/
|
|
39
45
|
export type BlockType =
|
|
40
46
|
| 'frontend'
|
|
41
47
|
| 'service'
|
|
@@ -294,6 +300,26 @@ export interface AgentArchetype {
|
|
|
294
300
|
resultView?: string
|
|
295
301
|
}
|
|
296
302
|
|
|
303
|
+
/**
|
|
304
|
+
* A registered CUSTOM agent kind carried in the workspace snapshot: its id + display
|
|
305
|
+
* metadata + whether it runs in a container. The SPA merges these into its palette
|
|
306
|
+
* catalog (`registerCustomKinds`) so a deployment's proprietary kind becomes a
|
|
307
|
+
* first-class palette block + result view. Mirrors `CustomAgentKind` in
|
|
308
|
+
* `@cat-factory/contracts`.
|
|
309
|
+
*/
|
|
310
|
+
export interface CustomAgentKind {
|
|
311
|
+
kind: AgentKind
|
|
312
|
+
presentation: {
|
|
313
|
+
label: string
|
|
314
|
+
icon: string
|
|
315
|
+
color: string
|
|
316
|
+
description: string
|
|
317
|
+
category?: AgentCategory
|
|
318
|
+
resultView?: string
|
|
319
|
+
}
|
|
320
|
+
container: boolean
|
|
321
|
+
}
|
|
322
|
+
|
|
297
323
|
/** A reusable, linear sequence of agents. */
|
|
298
324
|
export interface Pipeline {
|
|
299
325
|
id: string
|
|
@@ -409,6 +435,12 @@ export interface WorkspaceSnapshot {
|
|
|
409
435
|
serviceCatalog?: Service[]
|
|
410
436
|
/** The workspace's runtime settings (human-wait escalation threshold + task limit). */
|
|
411
437
|
settings?: WorkspaceSettings
|
|
438
|
+
/**
|
|
439
|
+
* Registered custom agent kinds (kind + presentation + container flag) a deployment
|
|
440
|
+
* mixed in. The SPA merges these into its palette catalog so a proprietary kind becomes
|
|
441
|
+
* a first-class palette block + result view. Absent when none are registered.
|
|
442
|
+
*/
|
|
443
|
+
customAgentKinds?: CustomAgentKind[]
|
|
412
444
|
}
|
|
413
445
|
|
|
414
446
|
/** How the per-service running-task limit is bucketed. Mirrors `@cat-factory/contracts`. */
|
package/app/types/execution.ts
CHANGED
|
@@ -300,6 +300,12 @@ export interface PipelineStep {
|
|
|
300
300
|
consensus?: ConsensusStepConfig | null
|
|
301
301
|
/** text the agent produced for this step (when LLM execution is enabled). */
|
|
302
302
|
output?: string
|
|
303
|
+
/**
|
|
304
|
+
* Structured JSON a registered CUSTOM kind's agent step returned (the generic
|
|
305
|
+
* manifest-driven `agent` dispatch). Rendered by the `generic-structured` result view.
|
|
306
|
+
* Absent for built-in / prose kinds.
|
|
307
|
+
*/
|
|
308
|
+
custom?: unknown
|
|
303
309
|
/** identifier of the model that produced `output`, for transparency. */
|
|
304
310
|
model?: string
|
|
305
311
|
/** prompt-fragment library ids folded into this step (manual ∪ selector pick). */
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
//
|
|
2
|
-
// (release.ts). Per-workspace
|
|
3
|
-
// the per-block monitor/SLO mappings the post-release-health gate reads.
|
|
1
|
+
// Post-release-health (observability) settings shapes, mirroring `@cat-factory/contracts`
|
|
2
|
+
// (release.ts). Per-workspace observability connection (provider + credentials, write-only,
|
|
3
|
+
// never read back) and the per-block monitor/SLO mappings the post-release-health gate reads.
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
export
|
|
5
|
+
/** Observability vendors a workspace can connect (extensible; Datadog today). */
|
|
6
|
+
export type ObservabilityProviderKind = 'datadog'
|
|
7
|
+
|
|
8
|
+
/** What `GET /observability/connection` returns — never the secret keys. */
|
|
9
|
+
export interface ObservabilityConnectionView {
|
|
7
10
|
connected: boolean
|
|
8
|
-
|
|
11
|
+
provider: ObservabilityProviderKind | null
|
|
12
|
+
/** Non-secret display fields, e.g. `{ site }` for Datadog. */
|
|
13
|
+
summary: Record<string, string> | null
|
|
9
14
|
}
|
|
10
15
|
|
|
11
|
-
/** Set/replace the workspace's
|
|
12
|
-
export interface
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
/** Set/replace the workspace's observability connection. */
|
|
17
|
+
export interface UpsertObservabilityConnectionInput {
|
|
18
|
+
provider: ObservabilityProviderKind
|
|
19
|
+
credentials: {
|
|
20
|
+
site: string
|
|
21
|
+
apiKey: string
|
|
22
|
+
appKey: string
|
|
23
|
+
}
|
|
16
24
|
}
|
|
17
25
|
|
|
18
26
|
/** A block's monitor/SLO mapping for the post-release-health gate. */
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
STATUS_META,
|
|
8
8
|
SYSTEM_AGENT_META,
|
|
9
9
|
agentKindMeta,
|
|
10
|
+
blockTypeMeta,
|
|
10
11
|
uid,
|
|
11
12
|
} from '~/utils/catalog'
|
|
12
13
|
|
|
@@ -37,6 +38,7 @@ const BLOCK_TYPES: BlockType[] = [
|
|
|
37
38
|
'queue',
|
|
38
39
|
'integration',
|
|
39
40
|
'external',
|
|
41
|
+
'environment',
|
|
40
42
|
]
|
|
41
43
|
const BLOCK_STATUSES: BlockStatus[] = [
|
|
42
44
|
'planned',
|
|
@@ -94,6 +96,14 @@ describe('catalog', () => {
|
|
|
94
96
|
}
|
|
95
97
|
})
|
|
96
98
|
|
|
99
|
+
it('blockTypeMeta returns a usable fallback for an unknown block type', () => {
|
|
100
|
+
expect(blockTypeMeta('totally-made-up' as BlockType)).toMatchObject({
|
|
101
|
+
label: expect.any(String),
|
|
102
|
+
icon: expect.any(String),
|
|
103
|
+
accent: expect.any(String),
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
|
|
97
107
|
it('provides metadata for every block status', () => {
|
|
98
108
|
for (const s of BLOCK_STATUSES) {
|
|
99
109
|
expect(STATUS_META[s]).toMatchObject({
|
package/app/utils/catalog.ts
CHANGED
|
@@ -384,8 +384,10 @@ export function agentKindMeta(kind: string): AgentArchetype {
|
|
|
384
384
|
)
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
+
type BlockTypeMeta = { label: string; icon: string; accent: string }
|
|
388
|
+
|
|
387
389
|
/** Visual metadata for each architecture block type. */
|
|
388
|
-
export const BLOCK_TYPE_META: Record<BlockType,
|
|
390
|
+
export const BLOCK_TYPE_META: Record<BlockType, BlockTypeMeta> = {
|
|
389
391
|
frontend: { label: 'Frontend', icon: 'i-lucide-monitor', accent: '#60a5fa' },
|
|
390
392
|
service: { label: 'Service', icon: 'i-lucide-server', accent: '#a78bfa' },
|
|
391
393
|
api: { label: 'API', icon: 'i-lucide-route', accent: '#22d3ee' },
|
|
@@ -396,12 +398,24 @@ export const BLOCK_TYPE_META: Record<BlockType, { label: string; icon: string; a
|
|
|
396
398
|
icon: 'i-lucide-workflow',
|
|
397
399
|
accent: '#fb923c',
|
|
398
400
|
},
|
|
401
|
+
// Not user-creatable, but still emitted by the backend (the seeded third-party
|
|
402
|
+
// service and the environments integration), so they need display metadata.
|
|
399
403
|
external: { label: 'External', icon: 'i-lucide-globe', accent: '#94a3b8' },
|
|
400
|
-
environment: {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
404
|
+
environment: { label: 'Environment', icon: 'i-lucide-box', accent: '#2dd4bf' },
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const FALLBACK_BLOCK_TYPE_META: BlockTypeMeta = {
|
|
408
|
+
label: 'Block',
|
|
409
|
+
icon: 'i-lucide-box',
|
|
410
|
+
accent: '#94a3b8',
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Visual metadata for a block type, with a safe fallback for any unknown/legacy
|
|
415
|
+
* type so the board never crashes on a type the backend introduces ahead of the SPA.
|
|
416
|
+
*/
|
|
417
|
+
export function blockTypeMeta(type: BlockType): BlockTypeMeta {
|
|
418
|
+
return BLOCK_TYPE_META[type] ?? FALLBACK_BLOCK_TYPE_META
|
|
405
419
|
}
|
|
406
420
|
|
|
407
421
|
/** Color + iconography for each block status. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/markdown-it": "^14.1.2",
|
|
35
|
-
"happy-dom": "^
|
|
35
|
+
"happy-dom": "^20.10.6",
|
|
36
36
|
"nuxt": "^4.4.8",
|
|
37
37
|
"typescript": "^6.0.3",
|
|
38
38
|
"vitest": "^4.1.9",
|