@cat-factory/app 0.121.0 → 0.121.2
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/composables/useUpsertList.spec.ts +13 -0
- package/app/stores/accounts.ts +9 -9
- package/app/stores/agentRuns.spec.ts +54 -1
- package/app/stores/agentRuns.ts +10 -19
- package/app/stores/bootstrap.ts +9 -5
- package/app/stores/github.ts +15 -8
- package/app/stores/pipelines.ts +12 -10
- package/app/stores/releaseHealth.ts +8 -5
- package/app/stores/sharedStacks.ts +3 -8
- package/app/stores/ui/modals.ts +810 -0
- package/app/stores/ui/navigation.ts +63 -0
- package/app/stores/ui/resultViews.ts +246 -0
- package/app/stores/ui.spec.ts +30 -0
- package/app/stores/ui.ts +19 -1072
- package/package.json +1 -1
package/app/stores/ui.ts
CHANGED
|
@@ -1,1082 +1,29 @@
|
|
|
1
1
|
import { defineStore } from 'pinia'
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { zoomToLod } from '~/composables/useSemanticZoom'
|
|
6
|
-
import { useExecutionStore } from '~/stores/execution'
|
|
7
|
-
import { agentKindMeta } from '~/utils/catalog'
|
|
2
|
+
import { createUiNavigation } from '~/stores/ui/navigation'
|
|
3
|
+
import { createUiResultViews } from '~/stores/ui/resultViews'
|
|
4
|
+
import { createUiModals } from '~/stores/ui/modals'
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
export interface AddTaskPrefill {
|
|
11
|
-
title?: string
|
|
12
|
-
description?: string
|
|
13
|
-
/** Context items staged on the new task (e.g. the source issue), linked once created. */
|
|
14
|
-
context?: PendingContext[]
|
|
15
|
-
}
|
|
6
|
+
export type { AddTaskPrefill, K3sSetupPrefill } from '~/stores/ui/modals'
|
|
16
7
|
|
|
17
8
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
9
|
+
* Transient UI state: selection, panels, zoom level.
|
|
10
|
+
*
|
|
11
|
+
* The concerns are split into cohesive, independently-testable slices under `stores/ui/`
|
|
12
|
+
* (refactoring candidate #4 — the store had grown to 40+ unrelated concerns in one 800-line
|
|
13
|
+
* file): board `navigation` (selection / focus / zoom / LOD), the step `resultViews` overlay
|
|
14
|
+
* seam (`dispatchStepView` / `ui.resultView` + the observability + Kaizen panels), and the
|
|
15
|
+
* `modals` slice (every modal / panel open-close flag, hub markers, deep-link params, and the
|
|
16
|
+
* startup + AI-onboarding advisories). This store composes them behind ONE unchanged public
|
|
17
|
+
* surface, so every existing `useUiStore()` consumer is untouched — the split is internal.
|
|
21
18
|
*/
|
|
22
|
-
export interface K3sSetupPrefill {
|
|
23
|
-
label: string
|
|
24
|
-
apiServerUrl: string
|
|
25
|
-
namespaceTemplate: string
|
|
26
|
-
hostTemplate: string
|
|
27
|
-
// Absent when the link omitted the param, so the form keeps its engine default rather than
|
|
28
|
-
// forcing verification back on (which would break a self-signed local cluster).
|
|
29
|
-
insecureSkipTlsVerify?: boolean
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Transient UI state: selection, panels, zoom level. */
|
|
33
19
|
export const useUiStore = defineStore('ui', () => {
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
// Pipeline-health startup advisory: lists invalid pipelines (delete / reseed) + built-ins
|
|
38
|
-
// with a newer catalog version (reseed). `pipelineHealthSeen` gates auto-open to once per
|
|
39
|
-
// session so it does not re-pop on every snapshot re-hydration.
|
|
40
|
-
const pipelineHealthOpen = ref(false)
|
|
41
|
-
const pipelineHealthSeen = ref(false)
|
|
42
|
-
// Merge-preset health startup advisory: lists built-ins with a newer catalog version (reseed)
|
|
43
|
-
// and new built-in presets the workspace can add. `riskPolicyHealthSeen` gates auto-open to
|
|
44
|
-
// once per session so it does not re-pop on every snapshot re-hydration (mirrors pipelines).
|
|
45
|
-
const riskPolicyHealthOpen = ref(false)
|
|
46
|
-
const riskPolicyHealthSeen = ref(false)
|
|
47
|
-
// Model-preset health startup advisory: lists built-ins with a newer catalog version (reseed)
|
|
48
|
-
// and new built-in presets the workspace can add. `modelPresetHealthSeen` gates auto-open to
|
|
49
|
-
// once per session so it does not re-pop on every snapshot re-hydration (mirrors pipelines).
|
|
50
|
-
const modelPresetHealthOpen = ref(false)
|
|
51
|
-
const modelPresetHealthSeen = ref(false)
|
|
52
|
-
const decisionContext = ref<{ instanceId: string; decisionId: string } | null>(null)
|
|
53
|
-
|
|
54
|
-
// Document-source integration modals, keyed by source. `documentImport` and
|
|
55
|
-
// `spawnPreview` carry an optional target frame, so structure spawned from a
|
|
56
|
-
// frame's inspector lands inside that frame rather than creating new top-level
|
|
57
|
-
// frames. `documentConnect` carries the source whose connect form to show;
|
|
58
|
-
// `documentImport`'s source may be null to let the modal pick a connected one.
|
|
59
|
-
const documentConnect = ref<{ source: DocumentSourceKind } | null>(null)
|
|
60
|
-
const documentImport = ref<{
|
|
61
|
-
source: DocumentSourceKind | null
|
|
62
|
-
targetFrameId: string | null
|
|
63
|
-
} | null>(null)
|
|
64
|
-
// The workspace+DocKind template / exemplar management modal (WS1). A single boolean —
|
|
65
|
-
// it manages every kind's links in one place.
|
|
66
|
-
const documentTemplates = ref(false)
|
|
67
|
-
const spawnPreview = ref<{
|
|
68
|
-
source: DocumentSourceKind
|
|
69
|
-
externalId: string
|
|
70
|
-
targetFrameId: string | null
|
|
71
|
-
} | null>(null)
|
|
72
|
-
|
|
73
|
-
// Task-source integration modals, keyed by source. `taskConnect` carries the
|
|
74
|
-
// source whose connect form to show; `taskImport`'s source may be null to let
|
|
75
|
-
// the modal pick a connected one (there is no spawn target — issues are linked
|
|
76
|
-
// to a block for context, not expanded into structure).
|
|
77
|
-
const taskConnect = ref<{ source: TaskSourceKind } | null>(null)
|
|
78
|
-
// `containerId` (a service frame) scopes the modal: it preselects that frame as
|
|
79
|
-
// the create-in target AND scopes the issue search to the frame's linked repo.
|
|
80
|
-
// Null → the unscoped "import an issue" surface (workspace-wide search).
|
|
81
|
-
const taskImport = ref<{ source: TaskSourceKind | null; containerId: string | null } | null>(null)
|
|
82
|
-
|
|
83
|
-
// Add-task modal: the container (service frame or module) a new task is being
|
|
84
|
-
// added to, or null when closed. The user types the title + description; nothing
|
|
85
|
-
// is launched until they explicitly start the created task.
|
|
86
|
-
const addTaskContainerId = ref<string | null>(null)
|
|
87
|
-
// Optional values to seed the add-task form with when it is opened from another
|
|
88
|
-
// surface (e.g. "create task from issue" prefills the title + stages the issue as
|
|
89
|
-
// linked context). The user still confirms pipeline / preset before adding.
|
|
90
|
-
const addTaskPrefill = ref<AddTaskPrefill | null>(null)
|
|
91
|
-
|
|
92
|
-
// Add-recurring-pipeline modal: the service frame a new recurring pipeline is
|
|
93
|
-
// being added to, or null when closed (mirrors the add-task flow — a button on
|
|
94
|
-
// the frame opens it, scoped to that frame).
|
|
95
|
-
const addRecurringFrameId = ref<string | null>(null)
|
|
96
|
-
|
|
97
|
-
// Create-initiative modal: the service frame a new initiative is being created
|
|
98
|
-
// under, or null when closed (mirrors the add-task flow).
|
|
99
|
-
const createInitiativeFrameId = ref<string | null>(null)
|
|
100
|
-
|
|
101
|
-
// Repo-bootstrap modal (manage reference architectures + launch a bootstrap).
|
|
102
|
-
const bootstrapOpen = ref(false)
|
|
103
|
-
|
|
104
|
-
// "Add a service from an existing GitHub repo" modal (no bootstrap run).
|
|
105
|
-
const addServiceOpen = ref(false)
|
|
106
|
-
|
|
107
|
-
// GitHub integration panel (connection management + repo/PR/issue browsing).
|
|
108
|
-
const githubOpen = ref(false)
|
|
109
|
-
|
|
110
|
-
// Slack integration panel (connect the account's Slack + per-workspace routing).
|
|
111
|
-
const slackOpen = ref(false)
|
|
112
|
-
|
|
113
|
-
// Prompt-fragment library panel (manage the board's best-practice catalog +
|
|
114
|
-
// linked guideline repos; ADR 0006).
|
|
115
|
-
const fragmentLibraryOpen = ref(false)
|
|
116
|
-
|
|
117
|
-
// Command bar (⌘K) — searchable launcher for every navbar action.
|
|
118
|
-
const commandBarOpen = ref(false)
|
|
119
|
-
|
|
120
|
-
// Keyboard-shortcuts cheatsheet (?) — a modal listing every global shortcut.
|
|
121
|
-
const shortcutsHelpOpen = ref(false)
|
|
122
|
-
|
|
123
|
-
// Mobile navigation drawer: on compact (< lg) viewports the SideBar is an
|
|
124
|
-
// off-canvas drawer toggled by a hamburger; on lg+ it is a static aside and this
|
|
125
|
-
// flag is ignored. Closed on any nav action so the board is revealed immediately.
|
|
126
|
-
const mobileNavOpen = ref(false)
|
|
127
|
-
|
|
128
|
-
// Integrations hub: a single modal listing every external system the workspace
|
|
129
|
-
// can enable/link (GitHub, Slack, document + task sources, Datadog, LLM vendors,
|
|
130
|
-
// local runners, OpenRouter). Replaces the per-integration navbar buttons; each
|
|
131
|
-
// row inside it opens that integration's own panel via the handlers below.
|
|
132
|
-
const integrationsOpen = ref(false)
|
|
133
|
-
// True while an integration's own panel is showing AND it was reached from the hub
|
|
134
|
-
// (not the command bar, sidebar, a banner or an inspector link). Drives the "Back to
|
|
135
|
-
// Integrations" control those panels render: it only offers a return path when there
|
|
136
|
-
// is one. Every direct `open*` below resets it; `openFromIntegrations` sets it.
|
|
137
|
-
const cameFromIntegrations = ref(false)
|
|
138
|
-
|
|
139
|
-
// Personal "My setup" hub: a user-scoped sibling of the Integrations hub, listing the
|
|
140
|
-
// signed-in user's own connections (GitHub PAT, local runners, personal subscriptions)
|
|
141
|
-
// separated out of the workspace-scoped Integrations hub. `cameFromPersonal` is the
|
|
142
|
-
// symmetric came-from marker, so a panel reached from here renders a "Back to My setup"
|
|
143
|
-
// control instead of "Back to Integrations".
|
|
144
|
-
const personalSetupOpen = ref(false)
|
|
145
|
-
const cameFromPersonal = ref(false)
|
|
146
|
-
|
|
147
|
-
// Workspace-settings modal: a single tabbed window gathering the workspace-wide
|
|
148
|
-
// config (workspace / merge thresholds / issue writeback / service best practices).
|
|
149
|
-
// `workspaceSettingsTab` lets other surfaces deep-link straight to a tab.
|
|
150
|
-
const workspaceSettingsOpen = ref(false)
|
|
151
|
-
const workspaceSettingsTab = ref('workspace')
|
|
152
|
-
// Account-settings modal: a single tabbed window for the per-account configuration —
|
|
153
|
-
// the team panel (members + roles + invitations + email sender + account API keys,
|
|
154
|
-
// `AccountTeamSettings`) and the account-tier prompt-fragment library. Account-scoped
|
|
155
|
-
// (distinct from workspace settings). `accountSettingsTab` lets other surfaces deep-link
|
|
156
|
-
// straight to a tab.
|
|
157
|
-
const accountSettingsOpen = ref(false)
|
|
158
|
-
const accountSettingsTab = ref('team')
|
|
159
|
-
// A one-shot deep-link anchor: when a surface opens account settings AND wants to land on a
|
|
160
|
-
// specific section within the (long) tab body, it sets this to that section's id. The owning
|
|
161
|
-
// panel scrolls the matching element into view once, then calls `clearAccountSettingsScrollTarget`
|
|
162
|
-
// so a later plain open doesn't re-scroll. Null when no section was requested.
|
|
163
|
-
const accountSettingsScrollTarget = ref<string | null>(null)
|
|
164
|
-
// Observability integration: the post-release-health connection panel (Datadog
|
|
165
|
-
// today, pluggable). NB: distinct from `observabilityInstanceId` below, which is the
|
|
166
|
-
// LLM per-call observability panel.
|
|
167
|
-
const observabilityConnectionOpen = ref(false)
|
|
168
|
-
// Private package registries: the workspace's npm/GitHub-Packages entries agent
|
|
169
|
-
// containers install with. Opened from the Integrations hub.
|
|
170
|
-
const packageRegistriesOpen = ref(false)
|
|
171
|
-
// API access tokens: the workspace's inbound public-API keys external systems present to
|
|
172
|
-
// the `/api/v1` surface. Opened from the Integrations hub.
|
|
173
|
-
const apiTokensOpen = ref(false)
|
|
174
|
-
// The single tabbed Infrastructure window — a TOP-LEVEL navbar destination (no longer
|
|
175
|
-
// reached via the Integrations hub). Two topical tabs: "Agent containers" (the execution
|
|
176
|
-
// backend + self-hosted runner pool, plus the local-mode warm pool/checkout) and "Test
|
|
177
|
-
// environments" (the ephemeral-environment provider). `infrastructureOpen` is the modal
|
|
178
|
-
// flag; `infrastructureTab` selects the tab. `openInfrastructure()` is the navbar entry;
|
|
179
|
-
// `openProviderConnection(kind)` remains for deep-links (a banner's "Configure…" button).
|
|
180
|
-
const infrastructureOpen = ref(false)
|
|
181
|
-
const infrastructureTab = ref<'environment' | 'runner-pool'>('runner-pool')
|
|
182
|
-
// Non-secret prefill captured from the `cat-factory k3s` CLI deep-link (see
|
|
183
|
-
// `consumeK3sSetupDeepLink`). When set, the Test-environments tab's kube engine form seeds the
|
|
184
|
-
// `local-k3s` connection from it; the ServiceAccount token is deliberately NOT in the link (a
|
|
185
|
-
// secret in a URL leaks into history/logs), so the user still pastes it before Test → Save.
|
|
186
|
-
const k3sSetupPrefill = ref<K3sSetupPrefill | null>(null)
|
|
187
|
-
// Environment setup wizard (shared-stacks slice 7): the guided detect → review → preflight →
|
|
188
|
-
// trial → save flow for a service frame's `docker-compose` provisioning. `environmentWizardOpen`
|
|
189
|
-
// is the modal flag; `environmentWizardFrameId` preselects the service frame the flow targets
|
|
190
|
-
// (set when launched from a frame's inspector nudge; null ⇒ the wizard's pick step chooses one).
|
|
191
|
-
const environmentWizardOpen = ref(false)
|
|
192
|
-
const environmentWizardFrameId = ref<string | null>(null)
|
|
193
|
-
const modelConfigOpen = ref(false)
|
|
194
|
-
// LLM-vendor subscription credentials (the token pool powering the Claude Code
|
|
195
|
-
// / Codex harnesses). `vendorCredentialsTab` lets a caller deep-link to one tab —
|
|
196
|
-
// the user-scoped "My subscriptions" entry opens straight onto the `personal` tab.
|
|
197
|
-
const vendorCredentialsOpen = ref(false)
|
|
198
|
-
const vendorCredentialsTab = ref('pool')
|
|
199
|
-
// Per-user settings panel: the signed-in user's own-machine local model runners.
|
|
200
|
-
const localModelsOpen = ref(false)
|
|
201
|
-
// The Sandbox (parallel prompt/model testing) surface — an opt-in, on-demand window.
|
|
202
|
-
const sandboxOpen = ref(false)
|
|
203
|
-
const userSecretsOpen = ref(false)
|
|
204
|
-
// Per-workspace settings panel: the OpenRouter dynamic catalog (browse/enable gateway models).
|
|
205
|
-
const openRouterOpen = ref(false)
|
|
206
|
-
|
|
207
|
-
// AI-onboarding surfaces (driven by `useAiReadiness`). `aiProviderSetupOpen` is the
|
|
208
|
-
// "no usable AI source" dialog; `aiPresetMismatchOpen` is the "default preset points at
|
|
209
|
-
// unavailable models" dialog. The `*Dismissed` flags are per-session: they suppress the
|
|
210
|
-
// auto-open (and let the banner be dismissed) without permanently hiding the prompt — it
|
|
211
|
-
// re-evaluates on the next load. Both clear themselves once the underlying gap is closed.
|
|
212
|
-
const aiProviderSetupOpen = ref(false)
|
|
213
|
-
const aiPresetMismatchOpen = ref(false)
|
|
214
|
-
const aiSetupDismissed = ref(false)
|
|
215
|
-
const aiPresetDismissed = ref(false)
|
|
216
|
-
|
|
217
|
-
// Infra-setup banner: per-SESSION dismissals, one flag per area, cleared on workspace switch
|
|
218
|
-
// exactly like the AI-onboarding flags (a dismissal in one workspace must not suppress the
|
|
219
|
-
// independent prompt for another). The PERMANENT "don't notify me again" dismissal is per-USER
|
|
220
|
-
// and persists in localStorage from the banner component; this only covers "hide for now".
|
|
221
|
-
const infraSetupSessionDismissed = ref<InfraSetupArea[]>([])
|
|
222
|
-
function dismissInfraSetupForSession(area: InfraSetupArea) {
|
|
223
|
-
if (!infraSetupSessionDismissed.value.includes(area))
|
|
224
|
-
infraSetupSessionDismissed.value = [...infraSetupSessionDismissed.value, area]
|
|
225
|
-
}
|
|
226
|
-
function resetInfraSetupDismissals() {
|
|
227
|
-
infraSetupSessionDismissed.value = []
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Dedicated result-view overlay: a step whose agent kind declares a bespoke
|
|
231
|
-
// visualization (via the archetype's `resultView`) opens here instead of the generic
|
|
232
|
-
// prose step-detail panel. `view` is the registry id (e.g. 'requirements-review');
|
|
233
|
-
// `blockId` is always set; `instanceId`/`stepIndex` are present on the pipeline path and
|
|
234
|
-
// null for an off-path open (e.g. the inspector's pre-start requirements review).
|
|
235
|
-
const resultView = ref<{
|
|
236
|
-
view: string
|
|
237
|
-
blockId: string
|
|
238
|
-
instanceId: string | null
|
|
239
|
-
stepIndex: number | null
|
|
240
|
-
// The brainstorm dialogue stage, set only when `view === 'brainstorm'` (its two agent
|
|
241
|
-
// kinds share one window). Derived from the step's agent kind on the pipeline path, or
|
|
242
|
-
// passed explicitly on an off-path open.
|
|
243
|
-
stage?: 'requirements' | 'architecture'
|
|
244
|
-
} | null>(null)
|
|
245
|
-
|
|
246
|
-
// Agent step-detail overlay: which pipeline step (a run instance + step index)
|
|
247
|
-
// a human is inspecting, or null when closed. The overlay resolves the step
|
|
248
|
-
// from the execution store so it stays live; it shows the step's metadata
|
|
249
|
-
// (model, state, progress, subtasks, …) and — when the agent produced prose —
|
|
250
|
-
// a reader for it (ToC + collapsible sections).
|
|
251
|
-
const stepDetail = ref<{ instanceId: string; stepIndex: number } | null>(null)
|
|
252
|
-
|
|
253
|
-
// LLM observability panel: which run (execution instance) a human is inspecting
|
|
254
|
-
// the per-call model activity for, or null when closed. The panel loads the full
|
|
255
|
-
// per-call detail from the observability store on open.
|
|
256
|
-
const observabilityInstanceId = ref<string | null>(null)
|
|
257
|
-
|
|
258
|
-
// The Kaizen screen (grading history + verified-combo library), a full-panel overlay
|
|
259
|
-
// opened from the sidebar. Distinct from the per-run grading status shown in run details.
|
|
260
|
-
const kaizenScreenOpen = ref(false)
|
|
261
|
-
|
|
262
|
-
/** Current canvas zoom (driven by Vue Flow viewport). */
|
|
263
|
-
const zoom = ref(1)
|
|
264
|
-
|
|
265
|
-
const lod = computed<LodLevel>(() => zoomToLod(zoom.value))
|
|
266
|
-
|
|
267
|
-
/** Frames the user has manually expanded to reveal their tasks. */
|
|
268
|
-
const expandedFrames = ref<Set<string>>(new Set())
|
|
269
|
-
|
|
270
|
-
function toggleFrame(id: string) {
|
|
271
|
-
const next = new Set(expandedFrames.value)
|
|
272
|
-
if (next.has(id)) next.delete(id)
|
|
273
|
-
else next.add(id)
|
|
274
|
-
expandedFrames.value = next
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function expandFrame(id: string) {
|
|
278
|
-
if (expandedFrames.value.has(id)) return
|
|
279
|
-
expandedFrames.value = new Set(expandedFrames.value).add(id)
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/** Services are always expanded to their task canvas, at every zoom level, so the
|
|
283
|
-
* board layout is fixed: panning never changes it and zooming has no expand/collapse
|
|
284
|
-
* transition to snap on. (`expandedFrames`/`toggleFrame` are retained for callers but
|
|
285
|
-
* no longer gate rendering.) */
|
|
286
|
-
function isFrameExpanded(_id: string) {
|
|
287
|
-
return true
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
function select(id: string | null) {
|
|
291
|
-
selectedBlockId.value = id
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
function focus(id: string | null) {
|
|
295
|
-
focusBlockId.value = id
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
function openBuilder() {
|
|
299
|
-
builderOpen.value = true
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/** Auto-open the pipeline-health advisory once per session (no-op after it's been shown). */
|
|
303
|
-
function maybeOpenPipelineHealth() {
|
|
304
|
-
if (pipelineHealthSeen.value) return
|
|
305
|
-
pipelineHealthSeen.value = true
|
|
306
|
-
pipelineHealthOpen.value = true
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function openPipelineHealth() {
|
|
310
|
-
pipelineHealthSeen.value = true
|
|
311
|
-
pipelineHealthOpen.value = true
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
function closePipelineHealth() {
|
|
315
|
-
pipelineHealthOpen.value = false
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/** Auto-open the merge-preset health advisory once per session (no-op after it's been shown). */
|
|
319
|
-
function maybeOpenRiskPolicyHealth() {
|
|
320
|
-
if (riskPolicyHealthSeen.value) return
|
|
321
|
-
riskPolicyHealthSeen.value = true
|
|
322
|
-
riskPolicyHealthOpen.value = true
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
function openRiskPolicyHealth() {
|
|
326
|
-
riskPolicyHealthSeen.value = true
|
|
327
|
-
riskPolicyHealthOpen.value = true
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
function closeRiskPolicyHealth() {
|
|
331
|
-
riskPolicyHealthOpen.value = false
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/** Auto-open the model-preset health advisory once per session (no-op after it's been shown). */
|
|
335
|
-
function maybeOpenModelPresetHealth() {
|
|
336
|
-
if (modelPresetHealthSeen.value) return
|
|
337
|
-
modelPresetHealthSeen.value = true
|
|
338
|
-
modelPresetHealthOpen.value = true
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
function openModelPresetHealth() {
|
|
342
|
-
modelPresetHealthSeen.value = true
|
|
343
|
-
modelPresetHealthOpen.value = true
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
function closeModelPresetHealth() {
|
|
347
|
-
modelPresetHealthOpen.value = false
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
function openDecision(instanceId: string, decisionId: string) {
|
|
351
|
-
decisionContext.value = { instanceId, decisionId }
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
function closeDecision() {
|
|
355
|
-
decisionContext.value = null
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
* Open a pending approval gate in the conclusions reader (approval mode). Resolves
|
|
360
|
-
* the step index from the gate id so every board/inspector entry point can keep
|
|
361
|
-
* passing the approval id it already has.
|
|
362
|
-
*/
|
|
363
|
-
function openApprovalDetail(instanceId: string, approvalId: string) {
|
|
364
|
-
const execution = useExecutionStore()
|
|
365
|
-
const instance = execution.getInstance(instanceId)
|
|
366
|
-
const idx = instance?.steps.findIndex((s) => s.approval?.id === approvalId) ?? -1
|
|
367
|
-
if (idx >= 0) dispatchStepView(instanceId, idx)
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Open a pipeline step: route it to its agent kind's DEDICATED result window when the
|
|
372
|
-
* archetype declares one (the universal `resultView` seam), else the generic prose
|
|
373
|
-
* step-detail panel. This is the single dispatch every board/inspector entry point uses,
|
|
374
|
-
* so adding a bespoke window for a new agent is just declaring `resultView` + registering
|
|
375
|
-
* a component — no caller changes.
|
|
376
|
-
*/
|
|
377
|
-
function dispatchStepView(instanceId: string, stepIndex: number) {
|
|
378
|
-
const execution = useExecutionStore()
|
|
379
|
-
const instance = execution.getInstance(instanceId)
|
|
380
|
-
const step = instance?.steps[stepIndex]
|
|
381
|
-
// A step that actually ran the consensus mechanism opens the dedicated Consensus
|
|
382
|
-
// Session window, regardless of its kind's normal result view — consensus is an
|
|
383
|
-
// execution MODE on a kind, not a kind, so it can't be a static archetype `resultView`.
|
|
384
|
-
const view = step?.consensus?.enabled
|
|
385
|
-
? 'consensus-session'
|
|
386
|
-
: step
|
|
387
|
-
? agentKindMeta(step.agentKind).resultView
|
|
388
|
-
: undefined
|
|
389
|
-
if (view && instance) {
|
|
390
|
-
// The brainstorm window is shared by both stages; carry which one from the step's kind.
|
|
391
|
-
const stage =
|
|
392
|
-
view === 'brainstorm'
|
|
393
|
-
? step?.agentKind === 'architecture-brainstorm'
|
|
394
|
-
? 'architecture'
|
|
395
|
-
: 'requirements'
|
|
396
|
-
: undefined
|
|
397
|
-
resultView.value = {
|
|
398
|
-
view,
|
|
399
|
-
blockId: instance.blockId,
|
|
400
|
-
instanceId,
|
|
401
|
-
stepIndex,
|
|
402
|
-
...(stage ? { stage } : {}),
|
|
403
|
-
}
|
|
404
|
-
return
|
|
405
|
-
}
|
|
406
|
-
stepDetail.value = { instanceId, stepIndex }
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
function openDocumentConnect(source: DocumentSourceKind) {
|
|
410
|
-
resetHubReturn()
|
|
411
|
-
documentConnect.value = { source }
|
|
412
|
-
}
|
|
413
|
-
function closeDocumentConnect() {
|
|
414
|
-
documentConnect.value = null
|
|
415
|
-
}
|
|
416
|
-
function openDocumentImport(
|
|
417
|
-
targetFrameId: string | null = null,
|
|
418
|
-
source: DocumentSourceKind | null = null,
|
|
419
|
-
) {
|
|
420
|
-
resetHubReturn()
|
|
421
|
-
documentImport.value = { source, targetFrameId }
|
|
422
|
-
}
|
|
423
|
-
function closeDocumentImport() {
|
|
424
|
-
documentImport.value = null
|
|
425
|
-
}
|
|
426
|
-
function openDocumentTemplates() {
|
|
427
|
-
resetHubReturn()
|
|
428
|
-
documentTemplates.value = true
|
|
429
|
-
}
|
|
430
|
-
function closeDocumentTemplates() {
|
|
431
|
-
documentTemplates.value = false
|
|
432
|
-
}
|
|
433
|
-
function openSpawnPreview(
|
|
434
|
-
source: DocumentSourceKind,
|
|
435
|
-
externalId: string,
|
|
436
|
-
targetFrameId: string | null = null,
|
|
437
|
-
) {
|
|
438
|
-
spawnPreview.value = { source, externalId, targetFrameId }
|
|
439
|
-
}
|
|
440
|
-
function closeSpawnPreview() {
|
|
441
|
-
spawnPreview.value = null
|
|
442
|
-
}
|
|
443
|
-
function openTaskConnect(source: TaskSourceKind) {
|
|
444
|
-
resetHubReturn()
|
|
445
|
-
taskConnect.value = { source }
|
|
446
|
-
}
|
|
447
|
-
function closeTaskConnect() {
|
|
448
|
-
taskConnect.value = null
|
|
449
|
-
}
|
|
450
|
-
function openTaskImport(source: TaskSourceKind | null = null, containerId: string | null = null) {
|
|
451
|
-
resetHubReturn()
|
|
452
|
-
taskImport.value = { source, containerId }
|
|
453
|
-
}
|
|
454
|
-
function closeTaskImport() {
|
|
455
|
-
taskImport.value = null
|
|
456
|
-
}
|
|
457
|
-
function openAddTask(containerId: string, prefill: AddTaskPrefill | null = null) {
|
|
458
|
-
addTaskPrefill.value = prefill
|
|
459
|
-
addTaskContainerId.value = containerId
|
|
460
|
-
}
|
|
461
|
-
function closeAddTask() {
|
|
462
|
-
addTaskContainerId.value = null
|
|
463
|
-
addTaskPrefill.value = null
|
|
464
|
-
}
|
|
465
|
-
function openAddRecurring(frameId: string) {
|
|
466
|
-
addRecurringFrameId.value = frameId
|
|
467
|
-
}
|
|
468
|
-
function closeAddRecurring() {
|
|
469
|
-
addRecurringFrameId.value = null
|
|
470
|
-
}
|
|
471
|
-
function openCreateInitiative(frameId: string) {
|
|
472
|
-
createInitiativeFrameId.value = frameId
|
|
473
|
-
}
|
|
474
|
-
function closeCreateInitiative() {
|
|
475
|
-
createInitiativeFrameId.value = null
|
|
476
|
-
}
|
|
477
|
-
function openBootstrap() {
|
|
478
|
-
bootstrapOpen.value = true
|
|
479
|
-
}
|
|
480
|
-
function closeBootstrap() {
|
|
481
|
-
bootstrapOpen.value = false
|
|
482
|
-
}
|
|
483
|
-
function openAddService() {
|
|
484
|
-
addServiceOpen.value = true
|
|
485
|
-
}
|
|
486
|
-
function closeAddService() {
|
|
487
|
-
addServiceOpen.value = false
|
|
488
|
-
}
|
|
489
|
-
function openGitHub() {
|
|
490
|
-
resetHubReturn()
|
|
491
|
-
githubOpen.value = true
|
|
492
|
-
}
|
|
493
|
-
function closeGitHub() {
|
|
494
|
-
githubOpen.value = false
|
|
495
|
-
}
|
|
496
|
-
function openSlack() {
|
|
497
|
-
resetHubReturn()
|
|
498
|
-
slackOpen.value = true
|
|
499
|
-
}
|
|
500
|
-
function closeSlack() {
|
|
501
|
-
slackOpen.value = false
|
|
502
|
-
}
|
|
503
|
-
function openFragmentLibrary() {
|
|
504
|
-
fragmentLibraryOpen.value = true
|
|
505
|
-
}
|
|
506
|
-
function closeFragmentLibrary() {
|
|
507
|
-
fragmentLibraryOpen.value = false
|
|
508
|
-
}
|
|
509
|
-
function openCommandBar() {
|
|
510
|
-
commandBarOpen.value = true
|
|
511
|
-
}
|
|
512
|
-
function closeCommandBar() {
|
|
513
|
-
commandBarOpen.value = false
|
|
514
|
-
}
|
|
515
|
-
function toggleCommandBar() {
|
|
516
|
-
commandBarOpen.value = !commandBarOpen.value
|
|
517
|
-
}
|
|
518
|
-
function openShortcutsHelp() {
|
|
519
|
-
shortcutsHelpOpen.value = true
|
|
520
|
-
}
|
|
521
|
-
function closeShortcutsHelp() {
|
|
522
|
-
shortcutsHelpOpen.value = false
|
|
523
|
-
}
|
|
524
|
-
function toggleShortcutsHelp() {
|
|
525
|
-
shortcutsHelpOpen.value = !shortcutsHelpOpen.value
|
|
526
|
-
}
|
|
527
|
-
function openMobileNav() {
|
|
528
|
-
mobileNavOpen.value = true
|
|
529
|
-
}
|
|
530
|
-
function closeMobileNav() {
|
|
531
|
-
mobileNavOpen.value = false
|
|
532
|
-
}
|
|
533
|
-
function toggleMobileNav() {
|
|
534
|
-
mobileNavOpen.value = !mobileNavOpen.value
|
|
535
|
-
}
|
|
536
|
-
// Clear BOTH hub came-from markers. Every direct `open*` below calls this so that a
|
|
537
|
-
// panel opened outside the hubs never grows a dead Back control, and so switching from
|
|
538
|
-
// one hub's panel to the other's clears the stale marker.
|
|
539
|
-
function resetHubReturn() {
|
|
540
|
-
cameFromIntegrations.value = false
|
|
541
|
-
cameFromPersonal.value = false
|
|
542
|
-
}
|
|
543
|
-
function openIntegrations() {
|
|
544
|
-
// Reaching the hub itself (fresh, or via a panel's Back control) clears the
|
|
545
|
-
// came-from markers — we're at the hub, not inside a hub-spawned panel.
|
|
546
|
-
resetHubReturn()
|
|
547
|
-
integrationsOpen.value = true
|
|
548
|
-
}
|
|
549
|
-
function closeIntegrations() {
|
|
550
|
-
integrationsOpen.value = false
|
|
551
|
-
}
|
|
552
|
-
function openPersonalSetup() {
|
|
553
|
-
resetHubReturn()
|
|
554
|
-
personalSetupOpen.value = true
|
|
555
|
-
}
|
|
556
|
-
function closePersonalSetup() {
|
|
557
|
-
personalSetupOpen.value = false
|
|
558
|
-
}
|
|
559
|
-
// Open a user-scoped panel FROM the My-setup hub: run its open handler (which resets the
|
|
560
|
-
// markers), then mark that we came from My setup and dismiss it, so the panel's
|
|
561
|
-
// IntegrationBackTitle returns here rather than to the workspace Integrations hub.
|
|
562
|
-
function openFromPersonal(open: () => void) {
|
|
563
|
-
open()
|
|
564
|
-
cameFromPersonal.value = true
|
|
565
|
-
personalSetupOpen.value = false
|
|
566
|
-
}
|
|
567
|
-
// Open an integration's own panel FROM the hub: run its open handler (which resets
|
|
568
|
-
// `cameFromIntegrations`), then mark that we came from the hub and dismiss it. The
|
|
569
|
-
// panel reads `cameFromIntegrations` to show its Back control.
|
|
570
|
-
function openFromIntegrations(open: () => void) {
|
|
571
|
-
open()
|
|
572
|
-
cameFromIntegrations.value = true
|
|
573
|
-
integrationsOpen.value = false
|
|
574
|
-
}
|
|
575
|
-
function openWorkspaceSettings(tab = 'workspace') {
|
|
576
|
-
resetHubReturn()
|
|
577
|
-
workspaceSettingsTab.value = tab
|
|
578
|
-
workspaceSettingsOpen.value = true
|
|
579
|
-
}
|
|
580
|
-
function closeWorkspaceSettings() {
|
|
581
|
-
workspaceSettingsOpen.value = false
|
|
582
|
-
}
|
|
583
|
-
function setWorkspaceSettingsTab(tab: string) {
|
|
584
|
-
workspaceSettingsTab.value = tab
|
|
585
|
-
}
|
|
586
|
-
function openAccountSettings(tab = 'team') {
|
|
587
|
-
resetHubReturn()
|
|
588
|
-
accountSettingsTab.value = tab
|
|
589
|
-
accountSettingsOpen.value = true
|
|
590
|
-
}
|
|
591
|
-
// Deep-link to the content (binary-artifact) storage configuration, which lives near the
|
|
592
|
-
// bottom of the account settings' team tab (`AccountDeploymentSettings`). Used by the
|
|
593
|
-
// pipeline-start error prompt when a storage-reliant agent (the UI Tester) has no storage
|
|
594
|
-
// configured. Sets a scroll anchor so the panel brings the storage section into view rather
|
|
595
|
-
// than dropping the user at the top of the long team tab to hunt for it.
|
|
596
|
-
function openContentStorageSettings() {
|
|
597
|
-
accountSettingsScrollTarget.value = 'content-storage'
|
|
598
|
-
openAccountSettings('team')
|
|
599
|
-
}
|
|
600
|
-
function clearAccountSettingsScrollTarget() {
|
|
601
|
-
accountSettingsScrollTarget.value = null
|
|
602
|
-
}
|
|
603
|
-
function closeAccountSettings() {
|
|
604
|
-
accountSettingsOpen.value = false
|
|
605
|
-
accountSettingsScrollTarget.value = null
|
|
606
|
-
}
|
|
607
|
-
function setAccountSettingsTab(tab: string) {
|
|
608
|
-
accountSettingsTab.value = tab
|
|
609
|
-
}
|
|
610
|
-
function openObservabilityConnection() {
|
|
611
|
-
resetHubReturn()
|
|
612
|
-
observabilityConnectionOpen.value = true
|
|
613
|
-
}
|
|
614
|
-
function closeObservabilityConnection() {
|
|
615
|
-
observabilityConnectionOpen.value = false
|
|
616
|
-
}
|
|
617
|
-
function openPackageRegistries() {
|
|
618
|
-
resetHubReturn()
|
|
619
|
-
packageRegistriesOpen.value = true
|
|
620
|
-
}
|
|
621
|
-
function closePackageRegistries() {
|
|
622
|
-
packageRegistriesOpen.value = false
|
|
623
|
-
}
|
|
624
|
-
function openApiTokens() {
|
|
625
|
-
resetHubReturn()
|
|
626
|
-
apiTokensOpen.value = true
|
|
627
|
-
}
|
|
628
|
-
function closeApiTokens() {
|
|
629
|
-
apiTokensOpen.value = false
|
|
630
|
-
}
|
|
631
|
-
// Top-level navbar entry into the Infrastructure window. No hub-return marker (it isn't
|
|
632
|
-
// reached from the Integrations hub), so the window shows no "Back to Integrations" control.
|
|
633
|
-
function openInfrastructure(tab: 'environment' | 'runner-pool' = 'runner-pool') {
|
|
634
|
-
resetHubReturn()
|
|
635
|
-
infrastructureTab.value = tab
|
|
636
|
-
infrastructureOpen.value = true
|
|
637
|
-
}
|
|
638
|
-
function openProviderConnection(kind: 'environment' | 'runner-pool') {
|
|
639
|
-
resetHubReturn()
|
|
640
|
-
infrastructureTab.value = kind
|
|
641
|
-
infrastructureOpen.value = true
|
|
642
|
-
}
|
|
643
|
-
function closeProviderConnection() {
|
|
644
|
-
infrastructureOpen.value = false
|
|
645
|
-
// Drop any consumed CLI prefill so re-opening the window normally doesn't re-seed the form.
|
|
646
|
-
k3sSetupPrefill.value = null
|
|
647
|
-
}
|
|
648
|
-
// Capture a `cat-factory k3s` deep-link (`?infraSetup=local-k3s&…`) on app load: stash the
|
|
649
|
-
// non-secret connection values, open the Infrastructure window on the Test-environments tab so
|
|
650
|
-
// the kube engine form seeds from them, then strip the params from the URL (mirrors the
|
|
651
|
-
// `?invite=` handling in the auth store) so a reload doesn't re-trigger and the link isn't left
|
|
652
|
-
// in history. No-op when the query param is absent.
|
|
653
|
-
function consumeK3sSetupDeepLink() {
|
|
654
|
-
if (typeof window === 'undefined') return
|
|
655
|
-
const params = new URLSearchParams(window.location.search)
|
|
656
|
-
if (params.get('infraSetup') !== 'local-k3s') return
|
|
657
|
-
k3sSetupPrefill.value = {
|
|
658
|
-
label: params.get('label') ?? 'Local k3s',
|
|
659
|
-
apiServerUrl: params.get('apiServerUrl') ?? '',
|
|
660
|
-
namespaceTemplate: params.get('namespaceTemplate') ?? '',
|
|
661
|
-
hostTemplate: params.get('hostTemplate') ?? '',
|
|
662
|
-
// Only carry the flag the link actually set — a missing param leaves the form's engine
|
|
663
|
-
// default (skip-TLS on for a local self-signed cluster) untouched.
|
|
664
|
-
insecureSkipTlsVerify: params.has('insecureSkipTlsVerify')
|
|
665
|
-
? params.get('insecureSkipTlsVerify') === '1'
|
|
666
|
-
: undefined,
|
|
667
|
-
}
|
|
668
|
-
resetHubReturn()
|
|
669
|
-
infrastructureTab.value = 'environment'
|
|
670
|
-
infrastructureOpen.value = true
|
|
671
|
-
for (const key of [
|
|
672
|
-
'infraSetup',
|
|
673
|
-
'label',
|
|
674
|
-
'apiServerUrl',
|
|
675
|
-
'namespaceTemplate',
|
|
676
|
-
'hostTemplate',
|
|
677
|
-
'insecureSkipTlsVerify',
|
|
678
|
-
]) {
|
|
679
|
-
params.delete(key)
|
|
680
|
-
}
|
|
681
|
-
const qs = params.toString()
|
|
682
|
-
history.replaceState(null, '', window.location.pathname + (qs ? `?${qs}` : ''))
|
|
683
|
-
}
|
|
684
|
-
// Launch the environment setup wizard, optionally preselecting the service frame it targets
|
|
685
|
-
// (the inspector nudge passes the frame; the navbar entry opens it with the pick step active).
|
|
686
|
-
function openEnvironmentSetup(frameId: string | null = null) {
|
|
687
|
-
resetHubReturn()
|
|
688
|
-
environmentWizardFrameId.value = frameId
|
|
689
|
-
environmentWizardOpen.value = true
|
|
690
|
-
}
|
|
691
|
-
function closeEnvironmentSetup() {
|
|
692
|
-
environmentWizardOpen.value = false
|
|
693
|
-
environmentWizardFrameId.value = null
|
|
694
|
-
}
|
|
695
|
-
function openModelConfig() {
|
|
696
|
-
modelConfigOpen.value = true
|
|
697
|
-
}
|
|
698
|
-
function closeModelConfig() {
|
|
699
|
-
modelConfigOpen.value = false
|
|
700
|
-
}
|
|
701
|
-
function openVendorCredentials(tab = 'pool') {
|
|
702
|
-
resetHubReturn()
|
|
703
|
-
vendorCredentialsTab.value = tab
|
|
704
|
-
vendorCredentialsOpen.value = true
|
|
705
|
-
}
|
|
706
|
-
function setVendorCredentialsTab(tab: string) {
|
|
707
|
-
vendorCredentialsTab.value = tab
|
|
708
|
-
}
|
|
709
|
-
function closeVendorCredentials() {
|
|
710
|
-
vendorCredentialsOpen.value = false
|
|
711
|
-
}
|
|
712
|
-
function openLocalModels() {
|
|
713
|
-
resetHubReturn()
|
|
714
|
-
localModelsOpen.value = true
|
|
715
|
-
}
|
|
716
|
-
function closeLocalModels() {
|
|
717
|
-
localModelsOpen.value = false
|
|
718
|
-
}
|
|
719
|
-
function openSandbox() {
|
|
720
|
-
sandboxOpen.value = true
|
|
721
|
-
}
|
|
722
|
-
function closeSandbox() {
|
|
723
|
-
sandboxOpen.value = false
|
|
724
|
-
}
|
|
725
|
-
function openUserSecrets() {
|
|
726
|
-
resetHubReturn()
|
|
727
|
-
userSecretsOpen.value = true
|
|
728
|
-
}
|
|
729
|
-
function closeUserSecrets() {
|
|
730
|
-
userSecretsOpen.value = false
|
|
731
|
-
}
|
|
732
|
-
function openOpenRouter() {
|
|
733
|
-
resetHubReturn()
|
|
734
|
-
openRouterOpen.value = true
|
|
735
|
-
}
|
|
736
|
-
function closeOpenRouter() {
|
|
737
|
-
openRouterOpen.value = false
|
|
738
|
-
}
|
|
739
|
-
function openAiProviderSetup() {
|
|
740
|
-
aiProviderSetupOpen.value = true
|
|
741
|
-
}
|
|
742
|
-
function closeAiProviderSetup() {
|
|
743
|
-
aiProviderSetupOpen.value = false
|
|
744
|
-
}
|
|
745
|
-
function openAiPresetMismatch() {
|
|
746
|
-
aiPresetMismatchOpen.value = true
|
|
747
|
-
}
|
|
748
|
-
function closeAiPresetMismatch() {
|
|
749
|
-
aiPresetMismatchOpen.value = false
|
|
750
|
-
}
|
|
751
|
-
// Banner dismissal is distinct from closing the dialog: closing the dialog leaves the
|
|
752
|
-
// banner so the user can reopen it; dismissing the banner hides the whole prompt for
|
|
753
|
-
// the session (it re-evaluates on the next load).
|
|
754
|
-
function dismissAiSetup() {
|
|
755
|
-
aiProviderSetupOpen.value = false
|
|
756
|
-
aiSetupDismissed.value = true
|
|
757
|
-
}
|
|
758
|
-
function dismissAiPresetMismatch() {
|
|
759
|
-
aiPresetMismatchOpen.value = false
|
|
760
|
-
aiPresetDismissed.value = true
|
|
761
|
-
}
|
|
762
|
-
// Clear the per-session AI-onboarding state (open dialogs + dismissed flags). Called on
|
|
763
|
-
// workspace switch: dismissals are per-session-per-workspace, so a prompt dismissed in one
|
|
764
|
-
// workspace must not suppress the (independent) prompt for another workspace that also
|
|
765
|
-
// lacks a usable AI source / has a broken default preset.
|
|
766
|
-
function resetAiOnboarding() {
|
|
767
|
-
aiProviderSetupOpen.value = false
|
|
768
|
-
aiPresetMismatchOpen.value = false
|
|
769
|
-
aiSetupDismissed.value = false
|
|
770
|
-
aiPresetDismissed.value = false
|
|
771
|
-
}
|
|
772
|
-
function openRequirementReview(blockId: string) {
|
|
773
|
-
resultView.value = { view: 'requirements-review', blockId, instanceId: null, stepIndex: null }
|
|
774
|
-
}
|
|
775
|
-
function openClarityReview(blockId: string) {
|
|
776
|
-
resultView.value = { view: 'clarity-review', blockId, instanceId: null, stepIndex: null }
|
|
777
|
-
}
|
|
778
|
-
function openBrainstorm(blockId: string, stage: 'requirements' | 'architecture') {
|
|
779
|
-
resultView.value = { view: 'brainstorm', blockId, instanceId: null, stepIndex: null, stage }
|
|
780
|
-
}
|
|
781
|
-
// Open the service-spec window for a service frame (the inspector's "View Requirements").
|
|
782
|
-
function openServiceSpec(blockId: string) {
|
|
783
|
-
resultView.value = { view: 'service-spec', blockId, instanceId: null, stepIndex: null }
|
|
784
|
-
}
|
|
785
|
-
// Open the initiative tracker window for an initiative block (board card / inspector).
|
|
786
|
-
function openInitiativeTracker(blockId: string) {
|
|
787
|
-
resultView.value = { view: 'initiative-tracker', blockId, instanceId: null, stepIndex: null }
|
|
788
|
-
}
|
|
789
|
-
// Open the interactive-planning Q&A window for an initiative block (inspector / card,
|
|
790
|
-
// when the interviewer has parked the planning run with pending questions).
|
|
791
|
-
function openInitiativePlanning(blockId: string) {
|
|
792
|
-
resultView.value = { view: 'initiative-planning', blockId, instanceId: null, stepIndex: null }
|
|
793
|
-
}
|
|
794
|
-
// Open the Follow-up companion window for a run's Coder step (the blinking chip + the
|
|
795
|
-
// `followup_pending` notification). Resolves the Coder step index from the run when not
|
|
796
|
-
// given, so callers that only know the run can still open it.
|
|
797
|
-
function openFollowUps(instanceId: string, stepIndex: number | null = null) {
|
|
798
|
-
const execution = useExecutionStore()
|
|
799
|
-
const instance = execution.getInstance(instanceId)
|
|
800
|
-
if (!instance) return
|
|
801
|
-
// A pipeline may carry more than one follow-up-enabled Coder step, so don't blindly pick
|
|
802
|
-
// the first when no index is given: prefer the step that still has undecided items (the
|
|
803
|
-
// one the run is parked on), else the current step, else the first enabled one.
|
|
804
|
-
const resolveIdx = () => {
|
|
805
|
-
const pending = instance.steps.findIndex(
|
|
806
|
-
(s) => s.followUps?.enabled && s.followUps.items.some((i) => i.status === 'pending'),
|
|
807
|
-
)
|
|
808
|
-
if (pending >= 0) return pending
|
|
809
|
-
const current = instance.steps[instance.currentStep]
|
|
810
|
-
if (current?.followUps?.enabled) return instance.currentStep
|
|
811
|
-
return instance.steps.findIndex((s) => s.followUps?.enabled)
|
|
812
|
-
}
|
|
813
|
-
const idx = stepIndex ?? resolveIdx()
|
|
814
|
-
if (idx < 0) return
|
|
815
|
-
resultView.value = {
|
|
816
|
-
view: 'follow-ups',
|
|
817
|
-
blockId: instance.blockId,
|
|
818
|
-
instanceId,
|
|
819
|
-
stepIndex: idx,
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
// Open the implementation-fork decision window for a run's coder step (from the inspector /
|
|
823
|
-
// pipeline chip / `fork_decision_pending` notification). Resolves the coder step index from
|
|
824
|
-
// the run when not given, preferring the step parked awaiting a choice.
|
|
825
|
-
function openForkDecision(instanceId: string, stepIndex: number | null = null) {
|
|
826
|
-
const execution = useExecutionStore()
|
|
827
|
-
const instance = execution.getInstance(instanceId)
|
|
828
|
-
if (!instance) return
|
|
829
|
-
const resolveIdx = () => {
|
|
830
|
-
const awaiting = instance.steps.findIndex(
|
|
831
|
-
(s) => s.agentKind === 'coder' && s.forkDecision?.status === 'awaiting_choice',
|
|
832
|
-
)
|
|
833
|
-
if (awaiting >= 0) return awaiting
|
|
834
|
-
const current = instance.steps[instance.currentStep]
|
|
835
|
-
if (current?.agentKind === 'coder' && current.forkDecision) return instance.currentStep
|
|
836
|
-
return instance.steps.findIndex((s) => s.agentKind === 'coder' && s.forkDecision)
|
|
837
|
-
}
|
|
838
|
-
const idx = stepIndex ?? resolveIdx()
|
|
839
|
-
if (idx < 0) return
|
|
840
|
-
resultView.value = {
|
|
841
|
-
view: 'fork-decision',
|
|
842
|
-
blockId: instance.blockId,
|
|
843
|
-
instanceId,
|
|
844
|
-
stepIndex: idx,
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
// Open the PR deep-review window for a run's `pr-reviewer` step (from the `pr_review_ready`
|
|
848
|
-
// notification / the step). Resolves the step index from the run when not given, preferring
|
|
849
|
-
// the step parked awaiting a finding selection.
|
|
850
|
-
function openPrReview(instanceId: string, stepIndex: number | null = null) {
|
|
851
|
-
const execution = useExecutionStore()
|
|
852
|
-
const instance = execution.getInstance(instanceId)
|
|
853
|
-
if (!instance) return
|
|
854
|
-
const resolveIdx = () => {
|
|
855
|
-
const awaiting = instance.steps.findIndex(
|
|
856
|
-
(s) => s.agentKind === 'pr-reviewer' && s.prReview?.status === 'awaiting_selection',
|
|
857
|
-
)
|
|
858
|
-
if (awaiting >= 0) return awaiting
|
|
859
|
-
const current = instance.steps[instance.currentStep]
|
|
860
|
-
if (current?.agentKind === 'pr-reviewer' && current.prReview) return instance.currentStep
|
|
861
|
-
return instance.steps.findIndex((s) => s.agentKind === 'pr-reviewer' && s.prReview)
|
|
862
|
-
}
|
|
863
|
-
const idx = stepIndex ?? resolveIdx()
|
|
864
|
-
if (idx < 0) return
|
|
865
|
-
resultView.value = {
|
|
866
|
-
view: 'pr-review',
|
|
867
|
-
blockId: instance.blockId,
|
|
868
|
-
instanceId,
|
|
869
|
-
stepIndex: idx,
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
function closeResultView() {
|
|
873
|
-
resultView.value = null
|
|
874
|
-
}
|
|
875
|
-
// Kept name for the requirements window's close handler.
|
|
876
|
-
const closeRequirementReview = closeResultView
|
|
877
|
-
function openStepDetail(instanceId: string, stepIndex: number) {
|
|
878
|
-
dispatchStepView(instanceId, stepIndex)
|
|
879
|
-
}
|
|
880
|
-
function closeStepDetail() {
|
|
881
|
-
stepDetail.value = null
|
|
882
|
-
}
|
|
883
|
-
function openObservability(instanceId: string) {
|
|
884
|
-
observabilityInstanceId.value = instanceId
|
|
885
|
-
}
|
|
886
|
-
function closeObservability() {
|
|
887
|
-
observabilityInstanceId.value = null
|
|
888
|
-
}
|
|
889
|
-
function openKaizen() {
|
|
890
|
-
kaizenScreenOpen.value = true
|
|
891
|
-
}
|
|
892
|
-
function closeKaizen() {
|
|
893
|
-
kaizenScreenOpen.value = false
|
|
894
|
-
}
|
|
20
|
+
const navigation = createUiNavigation()
|
|
21
|
+
const resultViews = createUiResultViews()
|
|
22
|
+
const modals = createUiModals()
|
|
895
23
|
|
|
896
24
|
return {
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
pipelineHealthOpen,
|
|
901
|
-
pipelineHealthSeen,
|
|
902
|
-
riskPolicyHealthOpen,
|
|
903
|
-
riskPolicyHealthSeen,
|
|
904
|
-
modelPresetHealthOpen,
|
|
905
|
-
modelPresetHealthSeen,
|
|
906
|
-
decisionContext,
|
|
907
|
-
documentConnect,
|
|
908
|
-
documentImport,
|
|
909
|
-
documentTemplates,
|
|
910
|
-
spawnPreview,
|
|
911
|
-
taskConnect,
|
|
912
|
-
taskImport,
|
|
913
|
-
addTaskContainerId,
|
|
914
|
-
addTaskPrefill,
|
|
915
|
-
addRecurringFrameId,
|
|
916
|
-
createInitiativeFrameId,
|
|
917
|
-
bootstrapOpen,
|
|
918
|
-
addServiceOpen,
|
|
919
|
-
githubOpen,
|
|
920
|
-
slackOpen,
|
|
921
|
-
fragmentLibraryOpen,
|
|
922
|
-
commandBarOpen,
|
|
923
|
-
shortcutsHelpOpen,
|
|
924
|
-
mobileNavOpen,
|
|
925
|
-
integrationsOpen,
|
|
926
|
-
cameFromIntegrations,
|
|
927
|
-
personalSetupOpen,
|
|
928
|
-
cameFromPersonal,
|
|
929
|
-
workspaceSettingsOpen,
|
|
930
|
-
workspaceSettingsTab,
|
|
931
|
-
accountSettingsOpen,
|
|
932
|
-
accountSettingsTab,
|
|
933
|
-
accountSettingsScrollTarget,
|
|
934
|
-
observabilityConnectionOpen,
|
|
935
|
-
packageRegistriesOpen,
|
|
936
|
-
apiTokensOpen,
|
|
937
|
-
infrastructureOpen,
|
|
938
|
-
infrastructureTab,
|
|
939
|
-
openInfrastructure,
|
|
940
|
-
modelConfigOpen,
|
|
941
|
-
vendorCredentialsOpen,
|
|
942
|
-
vendorCredentialsTab,
|
|
943
|
-
localModelsOpen,
|
|
944
|
-
sandboxOpen,
|
|
945
|
-
userSecretsOpen,
|
|
946
|
-
openRouterOpen,
|
|
947
|
-
aiProviderSetupOpen,
|
|
948
|
-
aiPresetMismatchOpen,
|
|
949
|
-
aiSetupDismissed,
|
|
950
|
-
aiPresetDismissed,
|
|
951
|
-
infraSetupSessionDismissed,
|
|
952
|
-
dismissInfraSetupForSession,
|
|
953
|
-
resetInfraSetupDismissals,
|
|
954
|
-
resultView,
|
|
955
|
-
closeResultView,
|
|
956
|
-
stepDetail,
|
|
957
|
-
observabilityInstanceId,
|
|
958
|
-
kaizenScreenOpen,
|
|
959
|
-
zoom,
|
|
960
|
-
lod,
|
|
961
|
-
expandedFrames,
|
|
962
|
-
toggleFrame,
|
|
963
|
-
expandFrame,
|
|
964
|
-
isFrameExpanded,
|
|
965
|
-
select,
|
|
966
|
-
focus,
|
|
967
|
-
openBuilder,
|
|
968
|
-
maybeOpenPipelineHealth,
|
|
969
|
-
openPipelineHealth,
|
|
970
|
-
closePipelineHealth,
|
|
971
|
-
maybeOpenRiskPolicyHealth,
|
|
972
|
-
openRiskPolicyHealth,
|
|
973
|
-
closeRiskPolicyHealth,
|
|
974
|
-
maybeOpenModelPresetHealth,
|
|
975
|
-
openModelPresetHealth,
|
|
976
|
-
closeModelPresetHealth,
|
|
977
|
-
openDecision,
|
|
978
|
-
closeDecision,
|
|
979
|
-
openApprovalDetail,
|
|
980
|
-
openDocumentConnect,
|
|
981
|
-
closeDocumentConnect,
|
|
982
|
-
openDocumentImport,
|
|
983
|
-
closeDocumentImport,
|
|
984
|
-
openDocumentTemplates,
|
|
985
|
-
closeDocumentTemplates,
|
|
986
|
-
openSpawnPreview,
|
|
987
|
-
closeSpawnPreview,
|
|
988
|
-
openTaskConnect,
|
|
989
|
-
closeTaskConnect,
|
|
990
|
-
openTaskImport,
|
|
991
|
-
closeTaskImport,
|
|
992
|
-
openAddTask,
|
|
993
|
-
closeAddTask,
|
|
994
|
-
openAddRecurring,
|
|
995
|
-
closeAddRecurring,
|
|
996
|
-
openCreateInitiative,
|
|
997
|
-
closeCreateInitiative,
|
|
998
|
-
openBootstrap,
|
|
999
|
-
closeBootstrap,
|
|
1000
|
-
openAddService,
|
|
1001
|
-
closeAddService,
|
|
1002
|
-
openGitHub,
|
|
1003
|
-
closeGitHub,
|
|
1004
|
-
openSlack,
|
|
1005
|
-
closeSlack,
|
|
1006
|
-
openFragmentLibrary,
|
|
1007
|
-
closeFragmentLibrary,
|
|
1008
|
-
openCommandBar,
|
|
1009
|
-
closeCommandBar,
|
|
1010
|
-
toggleCommandBar,
|
|
1011
|
-
openShortcutsHelp,
|
|
1012
|
-
closeShortcutsHelp,
|
|
1013
|
-
toggleShortcutsHelp,
|
|
1014
|
-
openMobileNav,
|
|
1015
|
-
closeMobileNav,
|
|
1016
|
-
toggleMobileNav,
|
|
1017
|
-
openIntegrations,
|
|
1018
|
-
closeIntegrations,
|
|
1019
|
-
openFromIntegrations,
|
|
1020
|
-
openPersonalSetup,
|
|
1021
|
-
closePersonalSetup,
|
|
1022
|
-
openFromPersonal,
|
|
1023
|
-
openWorkspaceSettings,
|
|
1024
|
-
closeWorkspaceSettings,
|
|
1025
|
-
setWorkspaceSettingsTab,
|
|
1026
|
-
openAccountSettings,
|
|
1027
|
-
openContentStorageSettings,
|
|
1028
|
-
clearAccountSettingsScrollTarget,
|
|
1029
|
-
closeAccountSettings,
|
|
1030
|
-
setAccountSettingsTab,
|
|
1031
|
-
openObservabilityConnection,
|
|
1032
|
-
closeObservabilityConnection,
|
|
1033
|
-
openPackageRegistries,
|
|
1034
|
-
closePackageRegistries,
|
|
1035
|
-
openApiTokens,
|
|
1036
|
-
closeApiTokens,
|
|
1037
|
-
openProviderConnection,
|
|
1038
|
-
closeProviderConnection,
|
|
1039
|
-
k3sSetupPrefill,
|
|
1040
|
-
consumeK3sSetupDeepLink,
|
|
1041
|
-
environmentWizardOpen,
|
|
1042
|
-
environmentWizardFrameId,
|
|
1043
|
-
openEnvironmentSetup,
|
|
1044
|
-
closeEnvironmentSetup,
|
|
1045
|
-
openModelConfig,
|
|
1046
|
-
closeModelConfig,
|
|
1047
|
-
openVendorCredentials,
|
|
1048
|
-
setVendorCredentialsTab,
|
|
1049
|
-
closeVendorCredentials,
|
|
1050
|
-
openLocalModels,
|
|
1051
|
-
closeLocalModels,
|
|
1052
|
-
openSandbox,
|
|
1053
|
-
closeSandbox,
|
|
1054
|
-
openUserSecrets,
|
|
1055
|
-
closeUserSecrets,
|
|
1056
|
-
openOpenRouter,
|
|
1057
|
-
closeOpenRouter,
|
|
1058
|
-
openAiProviderSetup,
|
|
1059
|
-
closeAiProviderSetup,
|
|
1060
|
-
openAiPresetMismatch,
|
|
1061
|
-
closeAiPresetMismatch,
|
|
1062
|
-
dismissAiSetup,
|
|
1063
|
-
dismissAiPresetMismatch,
|
|
1064
|
-
resetAiOnboarding,
|
|
1065
|
-
openRequirementReview,
|
|
1066
|
-
openClarityReview,
|
|
1067
|
-
openBrainstorm,
|
|
1068
|
-
openServiceSpec,
|
|
1069
|
-
openInitiativeTracker,
|
|
1070
|
-
openInitiativePlanning,
|
|
1071
|
-
openFollowUps,
|
|
1072
|
-
openForkDecision,
|
|
1073
|
-
openPrReview,
|
|
1074
|
-
closeRequirementReview,
|
|
1075
|
-
openStepDetail,
|
|
1076
|
-
closeStepDetail,
|
|
1077
|
-
openObservability,
|
|
1078
|
-
closeObservability,
|
|
1079
|
-
openKaizen,
|
|
1080
|
-
closeKaizen,
|
|
25
|
+
...navigation,
|
|
26
|
+
...resultViews,
|
|
27
|
+
...modals,
|
|
1081
28
|
}
|
|
1082
29
|
})
|