@cat-factory/app 0.145.0 → 0.146.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/TaskDependencyEdges.vue +37 -73
- package/app/components/brainstorm/BrainstormWindow.vue +2 -7
- package/app/components/clarity/ClarityReviewWindow.vue +2 -2
- package/app/components/consensus/ConsensusSessionWindow.vue +2 -2
- package/app/components/docs/DocInterviewWindow.vue +1 -1
- package/app/components/environments/EnvSetupStepper.vue +70 -0
- package/app/components/environments/EnvironmentSetupWizard.vue +9 -59
- package/app/components/forkDecision/ForkDecisionWindow.vue +1 -1
- package/app/components/initiative/InitiativePlanningWindow.vue +1 -1
- package/app/components/initiative/InitiativeTrackerWindow.vue +1 -1
- package/app/components/prReview/PrReviewWindow.vue +2 -2
- package/app/components/requirements/RequirementsReviewWindow.vue +2 -2
- package/app/components/spec/ServiceSpecWindow.vue +2 -2
- package/app/composables/useResultView.ts +26 -3
- package/app/modular/journeys/environmentSetup.logic.spec.ts +46 -15
- package/app/modular/journeys/environmentSetup.logic.ts +102 -35
- package/app/modular/journeys/environmentSetup.ts +17 -68
- package/app/stores/pipelines.ts +50 -19
- package/app/stores/ui/modals.ts +599 -532
- package/i18n/locales/de.json +1 -0
- package/i18n/locales/en.json +1 -0
- package/i18n/locales/es.json +1 -0
- package/i18n/locales/fr.json +1 -0
- package/i18n/locales/he.json +1 -0
- package/i18n/locales/it.json +1 -0
- package/i18n/locales/ja.json +1 -0
- package/i18n/locales/pl.json +1 -0
- package/i18n/locales/tr.json +1 -0
- package/i18n/locales/uk.json +1 -0
- package/package.json +4 -4
package/app/stores/ui/modals.ts
CHANGED
|
@@ -25,34 +25,110 @@ export interface K3sSetupPrefill {
|
|
|
25
25
|
insecureSkipTlsVerify?: boolean
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/** Clears both hub came-from markers; injected into the slices whose `open*` handlers reset them. */
|
|
29
|
+
type ResetHubReturn = () => void
|
|
30
|
+
|
|
28
31
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* …), their deep-link params, and the hub came-from markers. Split out of the navigation +
|
|
33
|
-
* result-view state per refactoring candidate #4 so the god-object's modal churn is contained to
|
|
34
|
-
* one place. Composed into {@link useUiStore} with the same public names, so consumers are
|
|
35
|
-
* unchanged.
|
|
32
|
+
* Startup health advisories (pipeline / merge-preset / model-preset). Each lists built-ins with a
|
|
33
|
+
* newer catalog version (reseed) + new built-ins the workspace can add; the `*Seen` flag gates
|
|
34
|
+
* auto-open to once per session so it does not re-pop on every snapshot re-hydration.
|
|
36
35
|
*/
|
|
37
|
-
|
|
38
|
-
const builderOpen = ref(false)
|
|
39
|
-
// Pipeline-health startup advisory: lists invalid pipelines (delete / reseed) + built-ins
|
|
40
|
-
// with a newer catalog version (reseed). `pipelineHealthSeen` gates auto-open to once per
|
|
41
|
-
// session so it does not re-pop on every snapshot re-hydration.
|
|
36
|
+
function createHealthAdvisoryModals() {
|
|
42
37
|
const pipelineHealthOpen = ref(false)
|
|
43
38
|
const pipelineHealthSeen = ref(false)
|
|
44
|
-
// Merge-preset health startup advisory: lists built-ins with a newer catalog version (reseed)
|
|
45
|
-
// and new built-in presets the workspace can add. `riskPolicyHealthSeen` gates auto-open to
|
|
46
|
-
// once per session so it does not re-pop on every snapshot re-hydration (mirrors pipelines).
|
|
47
39
|
const riskPolicyHealthOpen = ref(false)
|
|
48
40
|
const riskPolicyHealthSeen = ref(false)
|
|
49
|
-
// Model-preset health startup advisory: lists built-ins with a newer catalog version (reseed)
|
|
50
|
-
// and new built-in presets the workspace can add. `modelPresetHealthSeen` gates auto-open to
|
|
51
|
-
// once per session so it does not re-pop on every snapshot re-hydration (mirrors pipelines).
|
|
52
41
|
const modelPresetHealthOpen = ref(false)
|
|
53
42
|
const modelPresetHealthSeen = ref(false)
|
|
43
|
+
|
|
44
|
+
/** Auto-open the pipeline-health advisory once per session (no-op after it's been shown). */
|
|
45
|
+
function maybeOpenPipelineHealth() {
|
|
46
|
+
if (pipelineHealthSeen.value) return
|
|
47
|
+
pipelineHealthSeen.value = true
|
|
48
|
+
pipelineHealthOpen.value = true
|
|
49
|
+
}
|
|
50
|
+
function openPipelineHealth() {
|
|
51
|
+
pipelineHealthSeen.value = true
|
|
52
|
+
pipelineHealthOpen.value = true
|
|
53
|
+
}
|
|
54
|
+
function closePipelineHealth() {
|
|
55
|
+
pipelineHealthOpen.value = false
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Auto-open the merge-preset health advisory once per session (no-op after it's been shown). */
|
|
59
|
+
function maybeOpenRiskPolicyHealth() {
|
|
60
|
+
if (riskPolicyHealthSeen.value) return
|
|
61
|
+
riskPolicyHealthSeen.value = true
|
|
62
|
+
riskPolicyHealthOpen.value = true
|
|
63
|
+
}
|
|
64
|
+
function openRiskPolicyHealth() {
|
|
65
|
+
riskPolicyHealthSeen.value = true
|
|
66
|
+
riskPolicyHealthOpen.value = true
|
|
67
|
+
}
|
|
68
|
+
function closeRiskPolicyHealth() {
|
|
69
|
+
riskPolicyHealthOpen.value = false
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Auto-open the model-preset health advisory once per session (no-op after it's been shown). */
|
|
73
|
+
function maybeOpenModelPresetHealth() {
|
|
74
|
+
if (modelPresetHealthSeen.value) return
|
|
75
|
+
modelPresetHealthSeen.value = true
|
|
76
|
+
modelPresetHealthOpen.value = true
|
|
77
|
+
}
|
|
78
|
+
function openModelPresetHealth() {
|
|
79
|
+
modelPresetHealthSeen.value = true
|
|
80
|
+
modelPresetHealthOpen.value = true
|
|
81
|
+
}
|
|
82
|
+
function closeModelPresetHealth() {
|
|
83
|
+
modelPresetHealthOpen.value = false
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
pipelineHealthOpen,
|
|
88
|
+
pipelineHealthSeen,
|
|
89
|
+
riskPolicyHealthOpen,
|
|
90
|
+
riskPolicyHealthSeen,
|
|
91
|
+
modelPresetHealthOpen,
|
|
92
|
+
modelPresetHealthSeen,
|
|
93
|
+
maybeOpenPipelineHealth,
|
|
94
|
+
openPipelineHealth,
|
|
95
|
+
closePipelineHealth,
|
|
96
|
+
maybeOpenRiskPolicyHealth,
|
|
97
|
+
openRiskPolicyHealth,
|
|
98
|
+
closeRiskPolicyHealth,
|
|
99
|
+
maybeOpenModelPresetHealth,
|
|
100
|
+
openModelPresetHealth,
|
|
101
|
+
closeModelPresetHealth,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Small standalone surfaces with no hub relationship: the pipeline builder and the
|
|
107
|
+
* decision-wait window.
|
|
108
|
+
*/
|
|
109
|
+
function createMiscModals() {
|
|
110
|
+
const builderOpen = ref(false)
|
|
54
111
|
const decisionContext = ref<{ instanceId: string; decisionId: string } | null>(null)
|
|
55
112
|
|
|
113
|
+
function openBuilder() {
|
|
114
|
+
builderOpen.value = true
|
|
115
|
+
}
|
|
116
|
+
function openDecision(instanceId: string, decisionId: string) {
|
|
117
|
+
decisionContext.value = { instanceId, decisionId }
|
|
118
|
+
}
|
|
119
|
+
function closeDecision() {
|
|
120
|
+
decisionContext.value = null
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return { builderOpen, decisionContext, openBuilder, openDecision, closeDecision }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Document- and task-source integration modals (keyed by source), plus the add-task /
|
|
128
|
+
* add-recurring / create-initiative surfaces. The `open*` connect/import handlers reset the hub
|
|
129
|
+
* came-from markers (they can be reached from the Integrations hub).
|
|
130
|
+
*/
|
|
131
|
+
function createDocumentTaskModals(resetHubReturn: ResetHubReturn) {
|
|
56
132
|
// Document-source integration modals, keyed by source. `documentImport` and
|
|
57
133
|
// `spawnPreview` carry an optional target frame, so structure spawned from a
|
|
58
134
|
// frame's inspector lands inside that frame rather than creating new top-level
|
|
@@ -100,280 +176,248 @@ export function createUiModals() {
|
|
|
100
176
|
// under, or null when closed (mirrors the add-task flow).
|
|
101
177
|
const createInitiativeFrameId = ref<string | null>(null)
|
|
102
178
|
|
|
179
|
+
function openDocumentConnect(source: DocumentSourceKind) {
|
|
180
|
+
resetHubReturn()
|
|
181
|
+
documentConnect.value = { source }
|
|
182
|
+
}
|
|
183
|
+
function closeDocumentConnect() {
|
|
184
|
+
documentConnect.value = null
|
|
185
|
+
}
|
|
186
|
+
function openDocumentImport(
|
|
187
|
+
targetFrameId: string | null = null,
|
|
188
|
+
source: DocumentSourceKind | null = null,
|
|
189
|
+
) {
|
|
190
|
+
resetHubReturn()
|
|
191
|
+
documentImport.value = { source, targetFrameId }
|
|
192
|
+
}
|
|
193
|
+
function closeDocumentImport() {
|
|
194
|
+
documentImport.value = null
|
|
195
|
+
}
|
|
196
|
+
function openDocumentTemplates() {
|
|
197
|
+
resetHubReturn()
|
|
198
|
+
documentTemplates.value = true
|
|
199
|
+
}
|
|
200
|
+
function closeDocumentTemplates() {
|
|
201
|
+
documentTemplates.value = false
|
|
202
|
+
}
|
|
203
|
+
function openSpawnPreview(
|
|
204
|
+
source: DocumentSourceKind,
|
|
205
|
+
externalId: string,
|
|
206
|
+
targetFrameId: string | null = null,
|
|
207
|
+
) {
|
|
208
|
+
spawnPreview.value = { source, externalId, targetFrameId }
|
|
209
|
+
}
|
|
210
|
+
function closeSpawnPreview() {
|
|
211
|
+
spawnPreview.value = null
|
|
212
|
+
}
|
|
213
|
+
function openTaskConnect(source: TaskSourceKind) {
|
|
214
|
+
resetHubReturn()
|
|
215
|
+
taskConnect.value = { source }
|
|
216
|
+
}
|
|
217
|
+
function closeTaskConnect() {
|
|
218
|
+
taskConnect.value = null
|
|
219
|
+
}
|
|
220
|
+
function openTaskImport(source: TaskSourceKind | null = null, containerId: string | null = null) {
|
|
221
|
+
resetHubReturn()
|
|
222
|
+
taskImport.value = { source, containerId }
|
|
223
|
+
}
|
|
224
|
+
function closeTaskImport() {
|
|
225
|
+
taskImport.value = null
|
|
226
|
+
}
|
|
227
|
+
function openAddTask(containerId: string, prefill: AddTaskPrefill | null = null) {
|
|
228
|
+
addTaskPrefill.value = prefill
|
|
229
|
+
addTaskContainerId.value = containerId
|
|
230
|
+
}
|
|
231
|
+
function closeAddTask() {
|
|
232
|
+
addTaskContainerId.value = null
|
|
233
|
+
addTaskPrefill.value = null
|
|
234
|
+
}
|
|
235
|
+
function openAddRecurring(frameId: string) {
|
|
236
|
+
addRecurringFrameId.value = frameId
|
|
237
|
+
}
|
|
238
|
+
function closeAddRecurring() {
|
|
239
|
+
addRecurringFrameId.value = null
|
|
240
|
+
}
|
|
241
|
+
function openCreateInitiative(frameId: string) {
|
|
242
|
+
createInitiativeFrameId.value = frameId
|
|
243
|
+
}
|
|
244
|
+
function closeCreateInitiative() {
|
|
245
|
+
createInitiativeFrameId.value = null
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
documentConnect,
|
|
250
|
+
documentImport,
|
|
251
|
+
documentTemplates,
|
|
252
|
+
spawnPreview,
|
|
253
|
+
taskConnect,
|
|
254
|
+
taskImport,
|
|
255
|
+
addTaskContainerId,
|
|
256
|
+
addTaskPrefill,
|
|
257
|
+
addRecurringFrameId,
|
|
258
|
+
createInitiativeFrameId,
|
|
259
|
+
openDocumentConnect,
|
|
260
|
+
closeDocumentConnect,
|
|
261
|
+
openDocumentImport,
|
|
262
|
+
closeDocumentImport,
|
|
263
|
+
openDocumentTemplates,
|
|
264
|
+
closeDocumentTemplates,
|
|
265
|
+
openSpawnPreview,
|
|
266
|
+
closeSpawnPreview,
|
|
267
|
+
openTaskConnect,
|
|
268
|
+
closeTaskConnect,
|
|
269
|
+
openTaskImport,
|
|
270
|
+
closeTaskImport,
|
|
271
|
+
openAddTask,
|
|
272
|
+
closeAddTask,
|
|
273
|
+
openAddRecurring,
|
|
274
|
+
closeAddRecurring,
|
|
275
|
+
openCreateInitiative,
|
|
276
|
+
closeCreateInitiative,
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Global overlays with no hub-return relationship: repo bootstrap, add-service, the fragment
|
|
282
|
+
* library, the command bar (⌘K), the shortcuts cheatsheet, the mobile nav drawer, and the
|
|
283
|
+
* Sandbox. None reset the hub came-from markers (they aren't reached from the Integrations hub).
|
|
284
|
+
*/
|
|
285
|
+
function createOverlayModals() {
|
|
103
286
|
// Repo-bootstrap modal (manage reference architectures + launch a bootstrap).
|
|
104
287
|
const bootstrapOpen = ref(false)
|
|
105
|
-
|
|
106
288
|
// "Add a service from an existing GitHub repo" modal (no bootstrap run).
|
|
107
289
|
const addServiceOpen = ref(false)
|
|
108
|
-
|
|
109
|
-
// GitHub integration panel (connection management + repo/PR/issue browsing).
|
|
110
|
-
const githubOpen = ref(false)
|
|
111
|
-
|
|
112
|
-
// Slack integration panel (connect the account's Slack + per-workspace routing).
|
|
113
|
-
const slackOpen = ref(false)
|
|
114
|
-
|
|
115
290
|
// Prompt-fragment library panel (manage the board's best-practice catalog +
|
|
116
291
|
// linked guideline repos; ADR 0006).
|
|
117
292
|
const fragmentLibraryOpen = ref(false)
|
|
118
|
-
|
|
119
293
|
// Command bar (⌘K) — searchable launcher for every navbar action.
|
|
120
294
|
const commandBarOpen = ref(false)
|
|
121
|
-
|
|
122
295
|
// Keyboard-shortcuts cheatsheet (?) — a modal listing every global shortcut.
|
|
123
296
|
const shortcutsHelpOpen = ref(false)
|
|
124
|
-
|
|
125
297
|
// Mobile navigation drawer: on compact (< lg) viewports the SideBar is an
|
|
126
298
|
// off-canvas drawer toggled by a hamburger; on lg+ it is a static aside and this
|
|
127
299
|
// flag is ignored. Closed on any nav action so the board is revealed immediately.
|
|
128
300
|
const mobileNavOpen = ref(false)
|
|
301
|
+
// The Sandbox (parallel prompt/model testing) surface — an opt-in, on-demand window.
|
|
302
|
+
const sandboxOpen = ref(false)
|
|
129
303
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
// local runners, OpenRouter). Replaces the per-integration navbar buttons; each
|
|
133
|
-
// row inside it opens that integration's own panel via the handlers below.
|
|
134
|
-
const integrationsOpen = ref(false)
|
|
135
|
-
// True while an integration's own panel is showing AND it was reached from the hub
|
|
136
|
-
// (not the command bar, sidebar, a banner or an inspector link). Drives the "Back to
|
|
137
|
-
// Integrations" control those panels render: it only offers a return path when there
|
|
138
|
-
// is one. Every direct `open*` below resets it; `openFromIntegrations` sets it.
|
|
139
|
-
const cameFromIntegrations = ref(false)
|
|
140
|
-
|
|
141
|
-
// Personal "My setup" hub: a user-scoped sibling of the Integrations hub, listing the
|
|
142
|
-
// signed-in user's own connections (GitHub PAT, local runners, personal subscriptions)
|
|
143
|
-
// separated out of the workspace-scoped Integrations hub. `cameFromPersonal` is the
|
|
144
|
-
// symmetric came-from marker, so a panel reached from here renders a "Back to My setup"
|
|
145
|
-
// control instead of "Back to Integrations".
|
|
146
|
-
const personalSetupOpen = ref(false)
|
|
147
|
-
const cameFromPersonal = ref(false)
|
|
148
|
-
|
|
149
|
-
// Workspace-settings modal: a single tabbed window gathering the workspace-wide
|
|
150
|
-
// config (workspace / merge thresholds / issue writeback / service best practices).
|
|
151
|
-
// `workspaceSettingsTab` lets other surfaces deep-link straight to a tab.
|
|
152
|
-
const workspaceSettingsOpen = ref(false)
|
|
153
|
-
const workspaceSettingsTab = ref('workspace')
|
|
154
|
-
// Account-settings modal: a single tabbed window for the per-account configuration —
|
|
155
|
-
// the team panel (members + roles + invitations + email sender + account API keys,
|
|
156
|
-
// `AccountTeamSettings`) and the account-tier prompt-fragment library. Account-scoped
|
|
157
|
-
// (distinct from workspace settings). `accountSettingsTab` lets other surfaces deep-link
|
|
158
|
-
// straight to a tab.
|
|
159
|
-
const accountSettingsOpen = ref(false)
|
|
160
|
-
const accountSettingsTab = ref('team')
|
|
161
|
-
// A one-shot deep-link anchor: when a surface opens account settings AND wants to land on a
|
|
162
|
-
// specific section within the (long) tab body, it sets this to that section's id. The owning
|
|
163
|
-
// panel scrolls the matching element into view once, then calls `clearAccountSettingsScrollTarget`
|
|
164
|
-
// so a later plain open doesn't re-scroll. Null when no section was requested.
|
|
165
|
-
const accountSettingsScrollTarget = ref<string | null>(null)
|
|
166
|
-
// Observability integration: the post-release-health connection panel (Datadog
|
|
167
|
-
// today, pluggable). NB: distinct from `observabilityInstanceId`, which is the
|
|
168
|
-
// LLM per-call observability panel (see the result-views slice).
|
|
169
|
-
const observabilityConnectionOpen = ref(false)
|
|
170
|
-
// Platform-operator observability: the deployment-level dashboard (aggregate run health of
|
|
171
|
-
// the account — outcomes, failure taxonomy, live depth, durations). Admin-gated. Distinct
|
|
172
|
-
// from `observabilityConnectionOpen` (the Datadog connection) AND `observabilityInstanceId`
|
|
173
|
-
// (the per-run LLM call panel).
|
|
174
|
-
const operatorDashboardOpen = ref(false)
|
|
175
|
-
// Private package registries: the workspace's npm/GitHub-Packages entries agent
|
|
176
|
-
// containers install with. Opened from the Integrations hub.
|
|
177
|
-
const packageRegistriesOpen = ref(false)
|
|
178
|
-
// API access tokens: the workspace's inbound public-API keys external systems present to
|
|
179
|
-
// the `/api/v1` surface. Opened from the Integrations hub.
|
|
180
|
-
const apiTokensOpen = ref(false)
|
|
181
|
-
// The single tabbed Infrastructure window — a TOP-LEVEL navbar destination (no longer
|
|
182
|
-
// reached via the Integrations hub). Two topical tabs: "Agent containers" (the execution
|
|
183
|
-
// backend + self-hosted runner pool, plus the local-mode warm pool/checkout) and "Test
|
|
184
|
-
// environments" (the ephemeral-environment provider). `infrastructureOpen` is the modal
|
|
185
|
-
// flag; `infrastructureTab` selects the tab. `openInfrastructure()` is the navbar entry;
|
|
186
|
-
// `openProviderConnection(kind)` remains for deep-links (a banner's "Configure…" button).
|
|
187
|
-
const infrastructureOpen = ref(false)
|
|
188
|
-
const infrastructureTab = ref<'environment' | 'runner-pool'>('runner-pool')
|
|
189
|
-
// Non-secret prefill captured from the `cat-factory k3s` CLI deep-link (see
|
|
190
|
-
// `consumeK3sSetupDeepLink`). When set, the Test-environments tab's kube engine form seeds the
|
|
191
|
-
// `local-k3s` connection from it; the ServiceAccount token is deliberately NOT in the link (a
|
|
192
|
-
// secret in a URL leaks into history/logs), so the user still pastes it before Test → Save.
|
|
193
|
-
const k3sSetupPrefill = ref<K3sSetupPrefill | null>(null)
|
|
194
|
-
// Environment setup wizard (shared-stacks slice 7): the guided detect → review → preflight →
|
|
195
|
-
// trial → save flow for a service frame's `docker-compose` provisioning. `environmentWizardOpen`
|
|
196
|
-
// is the modal flag; `environmentWizardFrameId` preselects the service frame the flow targets
|
|
197
|
-
// (set when launched from a frame's inspector nudge; null ⇒ the wizard's pick step chooses one).
|
|
198
|
-
const environmentWizardOpen = ref(false)
|
|
199
|
-
const environmentWizardFrameId = ref<string | null>(null)
|
|
200
|
-
const modelConfigOpen = ref(false)
|
|
201
|
-
// LLM-vendor subscription credentials (the token pool powering the Claude Code
|
|
202
|
-
// / Codex harnesses). `vendorCredentialsTab` lets a caller deep-link to one tab —
|
|
203
|
-
// the user-scoped "My subscriptions" entry opens straight onto the `personal` tab.
|
|
204
|
-
const vendorCredentialsOpen = ref(false)
|
|
205
|
-
const vendorCredentialsTab = ref('pool')
|
|
206
|
-
// Per-user settings panel: the signed-in user's own-machine local model runners.
|
|
207
|
-
const localModelsOpen = ref(false)
|
|
208
|
-
// The Sandbox (parallel prompt/model testing) surface — an opt-in, on-demand window.
|
|
209
|
-
const sandboxOpen = ref(false)
|
|
210
|
-
const userSecretsOpen = ref(false)
|
|
211
|
-
// Per-workspace settings panel: the OpenRouter dynamic catalog (browse/enable gateway models).
|
|
212
|
-
const openRouterOpen = ref(false)
|
|
213
|
-
|
|
214
|
-
// AI-onboarding surfaces (driven by `useAiReadiness`). `aiProviderSetupOpen` is the
|
|
215
|
-
// "no usable AI source" dialog; `aiPresetMismatchOpen` is the "default preset points at
|
|
216
|
-
// unavailable models" dialog. The `*Dismissed` flags are per-session: they suppress the
|
|
217
|
-
// auto-open (and let the banner be dismissed) without permanently hiding the prompt — it
|
|
218
|
-
// re-evaluates on the next load. Both clear themselves once the underlying gap is closed.
|
|
219
|
-
const aiProviderSetupOpen = ref(false)
|
|
220
|
-
const aiPresetMismatchOpen = ref(false)
|
|
221
|
-
const aiSetupDismissed = ref(false)
|
|
222
|
-
const aiPresetDismissed = ref(false)
|
|
223
|
-
|
|
224
|
-
// Infra-setup banner: per-SESSION dismissals, one flag per area, cleared on workspace switch
|
|
225
|
-
// exactly like the AI-onboarding flags (a dismissal in one workspace must not suppress the
|
|
226
|
-
// independent prompt for another). The PERMANENT "don't notify me again" dismissal is per-USER
|
|
227
|
-
// and persists in localStorage from the banner component; this only covers "hide for now".
|
|
228
|
-
const infraSetupSessionDismissed = ref<InfraSetupArea[]>([])
|
|
229
|
-
function dismissInfraSetupForSession(area: InfraSetupArea) {
|
|
230
|
-
if (!infraSetupSessionDismissed.value.includes(area))
|
|
231
|
-
infraSetupSessionDismissed.value = [...infraSetupSessionDismissed.value, area]
|
|
232
|
-
}
|
|
233
|
-
function resetInfraSetupDismissals() {
|
|
234
|
-
infraSetupSessionDismissed.value = []
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function openBuilder() {
|
|
238
|
-
builderOpen.value = true
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/** Auto-open the pipeline-health advisory once per session (no-op after it's been shown). */
|
|
242
|
-
function maybeOpenPipelineHealth() {
|
|
243
|
-
if (pipelineHealthSeen.value) return
|
|
244
|
-
pipelineHealthSeen.value = true
|
|
245
|
-
pipelineHealthOpen.value = true
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
function openPipelineHealth() {
|
|
249
|
-
pipelineHealthSeen.value = true
|
|
250
|
-
pipelineHealthOpen.value = true
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function closePipelineHealth() {
|
|
254
|
-
pipelineHealthOpen.value = false
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/** Auto-open the merge-preset health advisory once per session (no-op after it's been shown). */
|
|
258
|
-
function maybeOpenRiskPolicyHealth() {
|
|
259
|
-
if (riskPolicyHealthSeen.value) return
|
|
260
|
-
riskPolicyHealthSeen.value = true
|
|
261
|
-
riskPolicyHealthOpen.value = true
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function openRiskPolicyHealth() {
|
|
265
|
-
riskPolicyHealthSeen.value = true
|
|
266
|
-
riskPolicyHealthOpen.value = true
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
function closeRiskPolicyHealth() {
|
|
270
|
-
riskPolicyHealthOpen.value = false
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/** Auto-open the model-preset health advisory once per session (no-op after it's been shown). */
|
|
274
|
-
function maybeOpenModelPresetHealth() {
|
|
275
|
-
if (modelPresetHealthSeen.value) return
|
|
276
|
-
modelPresetHealthSeen.value = true
|
|
277
|
-
modelPresetHealthOpen.value = true
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function openModelPresetHealth() {
|
|
281
|
-
modelPresetHealthSeen.value = true
|
|
282
|
-
modelPresetHealthOpen.value = true
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
function closeModelPresetHealth() {
|
|
286
|
-
modelPresetHealthOpen.value = false
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function openDecision(instanceId: string, decisionId: string) {
|
|
290
|
-
decisionContext.value = { instanceId, decisionId }
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
function closeDecision() {
|
|
294
|
-
decisionContext.value = null
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function openDocumentConnect(source: DocumentSourceKind) {
|
|
298
|
-
resetHubReturn()
|
|
299
|
-
documentConnect.value = { source }
|
|
300
|
-
}
|
|
301
|
-
function closeDocumentConnect() {
|
|
302
|
-
documentConnect.value = null
|
|
303
|
-
}
|
|
304
|
-
function openDocumentImport(
|
|
305
|
-
targetFrameId: string | null = null,
|
|
306
|
-
source: DocumentSourceKind | null = null,
|
|
307
|
-
) {
|
|
308
|
-
resetHubReturn()
|
|
309
|
-
documentImport.value = { source, targetFrameId }
|
|
310
|
-
}
|
|
311
|
-
function closeDocumentImport() {
|
|
312
|
-
documentImport.value = null
|
|
313
|
-
}
|
|
314
|
-
function openDocumentTemplates() {
|
|
315
|
-
resetHubReturn()
|
|
316
|
-
documentTemplates.value = true
|
|
304
|
+
function openBootstrap() {
|
|
305
|
+
bootstrapOpen.value = true
|
|
317
306
|
}
|
|
318
|
-
function
|
|
319
|
-
|
|
307
|
+
function closeBootstrap() {
|
|
308
|
+
bootstrapOpen.value = false
|
|
320
309
|
}
|
|
321
|
-
function
|
|
322
|
-
|
|
323
|
-
externalId: string,
|
|
324
|
-
targetFrameId: string | null = null,
|
|
325
|
-
) {
|
|
326
|
-
spawnPreview.value = { source, externalId, targetFrameId }
|
|
310
|
+
function openAddService() {
|
|
311
|
+
addServiceOpen.value = true
|
|
327
312
|
}
|
|
328
|
-
function
|
|
329
|
-
|
|
313
|
+
function closeAddService() {
|
|
314
|
+
addServiceOpen.value = false
|
|
330
315
|
}
|
|
331
|
-
function
|
|
332
|
-
|
|
333
|
-
taskConnect.value = { source }
|
|
316
|
+
function openFragmentLibrary() {
|
|
317
|
+
fragmentLibraryOpen.value = true
|
|
334
318
|
}
|
|
335
|
-
function
|
|
336
|
-
|
|
319
|
+
function closeFragmentLibrary() {
|
|
320
|
+
fragmentLibraryOpen.value = false
|
|
337
321
|
}
|
|
338
|
-
function
|
|
339
|
-
|
|
340
|
-
taskImport.value = { source, containerId }
|
|
322
|
+
function openCommandBar() {
|
|
323
|
+
commandBarOpen.value = true
|
|
341
324
|
}
|
|
342
|
-
function
|
|
343
|
-
|
|
325
|
+
function closeCommandBar() {
|
|
326
|
+
commandBarOpen.value = false
|
|
344
327
|
}
|
|
345
|
-
function
|
|
346
|
-
|
|
347
|
-
addTaskContainerId.value = containerId
|
|
328
|
+
function toggleCommandBar() {
|
|
329
|
+
commandBarOpen.value = !commandBarOpen.value
|
|
348
330
|
}
|
|
349
|
-
function
|
|
350
|
-
|
|
351
|
-
addTaskPrefill.value = null
|
|
331
|
+
function openShortcutsHelp() {
|
|
332
|
+
shortcutsHelpOpen.value = true
|
|
352
333
|
}
|
|
353
|
-
function
|
|
354
|
-
|
|
334
|
+
function closeShortcutsHelp() {
|
|
335
|
+
shortcutsHelpOpen.value = false
|
|
355
336
|
}
|
|
356
|
-
function
|
|
357
|
-
|
|
337
|
+
function toggleShortcutsHelp() {
|
|
338
|
+
shortcutsHelpOpen.value = !shortcutsHelpOpen.value
|
|
358
339
|
}
|
|
359
|
-
function
|
|
360
|
-
|
|
340
|
+
function openMobileNav() {
|
|
341
|
+
mobileNavOpen.value = true
|
|
361
342
|
}
|
|
362
|
-
function
|
|
363
|
-
|
|
343
|
+
function closeMobileNav() {
|
|
344
|
+
mobileNavOpen.value = false
|
|
364
345
|
}
|
|
365
|
-
function
|
|
366
|
-
|
|
346
|
+
function toggleMobileNav() {
|
|
347
|
+
mobileNavOpen.value = !mobileNavOpen.value
|
|
367
348
|
}
|
|
368
|
-
function
|
|
369
|
-
|
|
349
|
+
function openSandbox() {
|
|
350
|
+
sandboxOpen.value = true
|
|
370
351
|
}
|
|
371
|
-
function
|
|
372
|
-
|
|
352
|
+
function closeSandbox() {
|
|
353
|
+
sandboxOpen.value = false
|
|
373
354
|
}
|
|
374
|
-
|
|
375
|
-
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
bootstrapOpen,
|
|
358
|
+
addServiceOpen,
|
|
359
|
+
fragmentLibraryOpen,
|
|
360
|
+
commandBarOpen,
|
|
361
|
+
shortcutsHelpOpen,
|
|
362
|
+
mobileNavOpen,
|
|
363
|
+
sandboxOpen,
|
|
364
|
+
openBootstrap,
|
|
365
|
+
closeBootstrap,
|
|
366
|
+
openAddService,
|
|
367
|
+
closeAddService,
|
|
368
|
+
openFragmentLibrary,
|
|
369
|
+
closeFragmentLibrary,
|
|
370
|
+
openCommandBar,
|
|
371
|
+
closeCommandBar,
|
|
372
|
+
toggleCommandBar,
|
|
373
|
+
openShortcutsHelp,
|
|
374
|
+
closeShortcutsHelp,
|
|
375
|
+
toggleShortcutsHelp,
|
|
376
|
+
openMobileNav,
|
|
377
|
+
closeMobileNav,
|
|
378
|
+
toggleMobileNav,
|
|
379
|
+
openSandbox,
|
|
380
|
+
closeSandbox,
|
|
376
381
|
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* The workspace-scoped integration panels: GitHub, Slack, observability, the operator dashboard,
|
|
386
|
+
* package registries, API tokens, model config, vendor credentials, local models, user secrets and
|
|
387
|
+
* OpenRouter. Every `open*` that a hub can route to resets the hub came-from markers.
|
|
388
|
+
*/
|
|
389
|
+
function createIntegrationPanelModals(resetHubReturn: ResetHubReturn) {
|
|
390
|
+
// GitHub integration panel (connection management + repo/PR/issue browsing).
|
|
391
|
+
const githubOpen = ref(false)
|
|
392
|
+
// Slack integration panel (connect the account's Slack + per-workspace routing).
|
|
393
|
+
const slackOpen = ref(false)
|
|
394
|
+
// Observability integration: the post-release-health connection panel (Datadog
|
|
395
|
+
// today, pluggable). NB: distinct from `observabilityInstanceId`, which is the
|
|
396
|
+
// LLM per-call observability panel (see the result-views slice).
|
|
397
|
+
const observabilityConnectionOpen = ref(false)
|
|
398
|
+
// Platform-operator observability: the deployment-level dashboard (aggregate run health of
|
|
399
|
+
// the account — outcomes, failure taxonomy, live depth, durations). Admin-gated. Distinct
|
|
400
|
+
// from `observabilityConnectionOpen` (the Datadog connection) AND `observabilityInstanceId`
|
|
401
|
+
// (the per-run LLM call panel).
|
|
402
|
+
const operatorDashboardOpen = ref(false)
|
|
403
|
+
// Private package registries: the workspace's npm/GitHub-Packages entries agent
|
|
404
|
+
// containers install with. Opened from the Integrations hub.
|
|
405
|
+
const packageRegistriesOpen = ref(false)
|
|
406
|
+
// API access tokens: the workspace's inbound public-API keys external systems present to
|
|
407
|
+
// the `/api/v1` surface. Opened from the Integrations hub.
|
|
408
|
+
const apiTokensOpen = ref(false)
|
|
409
|
+
const modelConfigOpen = ref(false)
|
|
410
|
+
// LLM-vendor subscription credentials (the token pool powering the Claude Code
|
|
411
|
+
// / Codex harnesses). `vendorCredentialsTab` lets a caller deep-link to one tab —
|
|
412
|
+
// the user-scoped "My subscriptions" entry opens straight onto the `personal` tab.
|
|
413
|
+
const vendorCredentialsOpen = ref(false)
|
|
414
|
+
const vendorCredentialsTab = ref('pool')
|
|
415
|
+
// Per-user settings panel: the signed-in user's own-machine local model runners.
|
|
416
|
+
const localModelsOpen = ref(false)
|
|
417
|
+
const userSecretsOpen = ref(false)
|
|
418
|
+
// Per-workspace settings panel: the OpenRouter dynamic catalog (browse/enable gateway models).
|
|
419
|
+
const openRouterOpen = ref(false)
|
|
420
|
+
|
|
377
421
|
function openGitHub() {
|
|
378
422
|
resetHubReturn()
|
|
379
423
|
githubOpen.value = true
|
|
@@ -388,78 +432,136 @@ export function createUiModals() {
|
|
|
388
432
|
function closeSlack() {
|
|
389
433
|
slackOpen.value = false
|
|
390
434
|
}
|
|
391
|
-
function
|
|
392
|
-
|
|
435
|
+
function openObservabilityConnection() {
|
|
436
|
+
resetHubReturn()
|
|
437
|
+
observabilityConnectionOpen.value = true
|
|
438
|
+
}
|
|
439
|
+
function closeObservabilityConnection() {
|
|
440
|
+
observabilityConnectionOpen.value = false
|
|
441
|
+
}
|
|
442
|
+
function openOperatorDashboard() {
|
|
443
|
+
resetHubReturn()
|
|
444
|
+
operatorDashboardOpen.value = true
|
|
445
|
+
}
|
|
446
|
+
function closeOperatorDashboard() {
|
|
447
|
+
operatorDashboardOpen.value = false
|
|
393
448
|
}
|
|
394
|
-
function
|
|
395
|
-
|
|
449
|
+
function openPackageRegistries() {
|
|
450
|
+
resetHubReturn()
|
|
451
|
+
packageRegistriesOpen.value = true
|
|
396
452
|
}
|
|
397
|
-
function
|
|
398
|
-
|
|
453
|
+
function closePackageRegistries() {
|
|
454
|
+
packageRegistriesOpen.value = false
|
|
399
455
|
}
|
|
400
|
-
function
|
|
401
|
-
|
|
456
|
+
function openApiTokens() {
|
|
457
|
+
resetHubReturn()
|
|
458
|
+
apiTokensOpen.value = true
|
|
402
459
|
}
|
|
403
|
-
function
|
|
404
|
-
|
|
460
|
+
function closeApiTokens() {
|
|
461
|
+
apiTokensOpen.value = false
|
|
405
462
|
}
|
|
406
|
-
function
|
|
407
|
-
|
|
463
|
+
function openModelConfig() {
|
|
464
|
+
modelConfigOpen.value = true
|
|
408
465
|
}
|
|
409
|
-
function
|
|
410
|
-
|
|
466
|
+
function closeModelConfig() {
|
|
467
|
+
modelConfigOpen.value = false
|
|
411
468
|
}
|
|
412
|
-
function
|
|
413
|
-
|
|
469
|
+
function openVendorCredentials(tab = 'pool') {
|
|
470
|
+
resetHubReturn()
|
|
471
|
+
vendorCredentialsTab.value = tab
|
|
472
|
+
vendorCredentialsOpen.value = true
|
|
414
473
|
}
|
|
415
|
-
function
|
|
416
|
-
|
|
474
|
+
function setVendorCredentialsTab(tab: string) {
|
|
475
|
+
vendorCredentialsTab.value = tab
|
|
417
476
|
}
|
|
418
|
-
function
|
|
419
|
-
|
|
477
|
+
function closeVendorCredentials() {
|
|
478
|
+
vendorCredentialsOpen.value = false
|
|
420
479
|
}
|
|
421
|
-
function
|
|
422
|
-
|
|
480
|
+
function openLocalModels() {
|
|
481
|
+
resetHubReturn()
|
|
482
|
+
localModelsOpen.value = true
|
|
423
483
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
// one hub's panel to the other's clears the stale marker.
|
|
427
|
-
function resetHubReturn() {
|
|
428
|
-
cameFromIntegrations.value = false
|
|
429
|
-
cameFromPersonal.value = false
|
|
484
|
+
function closeLocalModels() {
|
|
485
|
+
localModelsOpen.value = false
|
|
430
486
|
}
|
|
431
|
-
function
|
|
432
|
-
// Reaching the hub itself (fresh, or via a panel's Back control) clears the
|
|
433
|
-
// came-from markers — we're at the hub, not inside a hub-spawned panel.
|
|
487
|
+
function openUserSecrets() {
|
|
434
488
|
resetHubReturn()
|
|
435
|
-
|
|
489
|
+
userSecretsOpen.value = true
|
|
436
490
|
}
|
|
437
|
-
function
|
|
438
|
-
|
|
491
|
+
function closeUserSecrets() {
|
|
492
|
+
userSecretsOpen.value = false
|
|
439
493
|
}
|
|
440
|
-
function
|
|
494
|
+
function openOpenRouter() {
|
|
441
495
|
resetHubReturn()
|
|
442
|
-
|
|
443
|
-
}
|
|
444
|
-
function closePersonalSetup() {
|
|
445
|
-
personalSetupOpen.value = false
|
|
496
|
+
openRouterOpen.value = true
|
|
446
497
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
// IntegrationBackTitle returns here rather than to the workspace Integrations hub.
|
|
450
|
-
function openFromPersonal(open: () => void) {
|
|
451
|
-
open()
|
|
452
|
-
cameFromPersonal.value = true
|
|
453
|
-
personalSetupOpen.value = false
|
|
498
|
+
function closeOpenRouter() {
|
|
499
|
+
openRouterOpen.value = false
|
|
454
500
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
501
|
+
|
|
502
|
+
return {
|
|
503
|
+
githubOpen,
|
|
504
|
+
slackOpen,
|
|
505
|
+
observabilityConnectionOpen,
|
|
506
|
+
operatorDashboardOpen,
|
|
507
|
+
packageRegistriesOpen,
|
|
508
|
+
apiTokensOpen,
|
|
509
|
+
modelConfigOpen,
|
|
510
|
+
vendorCredentialsOpen,
|
|
511
|
+
vendorCredentialsTab,
|
|
512
|
+
localModelsOpen,
|
|
513
|
+
userSecretsOpen,
|
|
514
|
+
openRouterOpen,
|
|
515
|
+
openGitHub,
|
|
516
|
+
closeGitHub,
|
|
517
|
+
openSlack,
|
|
518
|
+
closeSlack,
|
|
519
|
+
openObservabilityConnection,
|
|
520
|
+
closeObservabilityConnection,
|
|
521
|
+
openOperatorDashboard,
|
|
522
|
+
closeOperatorDashboard,
|
|
523
|
+
openPackageRegistries,
|
|
524
|
+
closePackageRegistries,
|
|
525
|
+
openApiTokens,
|
|
526
|
+
closeApiTokens,
|
|
527
|
+
openModelConfig,
|
|
528
|
+
closeModelConfig,
|
|
529
|
+
openVendorCredentials,
|
|
530
|
+
setVendorCredentialsTab,
|
|
531
|
+
closeVendorCredentials,
|
|
532
|
+
openLocalModels,
|
|
533
|
+
closeLocalModels,
|
|
534
|
+
openUserSecrets,
|
|
535
|
+
closeUserSecrets,
|
|
536
|
+
openOpenRouter,
|
|
537
|
+
closeOpenRouter,
|
|
462
538
|
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Workspace- and account-settings modals (single tabbed windows). `*Tab` lets a caller deep-link
|
|
543
|
+
* straight to a tab; `accountSettingsScrollTarget` is a one-shot deep-link anchor into a section
|
|
544
|
+
* within the (long) account-settings body.
|
|
545
|
+
*/
|
|
546
|
+
function createSettingsModals(resetHubReturn: ResetHubReturn) {
|
|
547
|
+
// Workspace-settings modal: a single tabbed window gathering the workspace-wide
|
|
548
|
+
// config (workspace / merge thresholds / issue writeback / service best practices).
|
|
549
|
+
// `workspaceSettingsTab` lets other surfaces deep-link straight to a tab.
|
|
550
|
+
const workspaceSettingsOpen = ref(false)
|
|
551
|
+
const workspaceSettingsTab = ref('workspace')
|
|
552
|
+
// Account-settings modal: a single tabbed window for the per-account configuration —
|
|
553
|
+
// the team panel (members + roles + invitations + email sender + account API keys,
|
|
554
|
+
// `AccountTeamSettings`) and the account-tier prompt-fragment library. Account-scoped
|
|
555
|
+
// (distinct from workspace settings). `accountSettingsTab` lets other surfaces deep-link
|
|
556
|
+
// straight to a tab.
|
|
557
|
+
const accountSettingsOpen = ref(false)
|
|
558
|
+
const accountSettingsTab = ref('team')
|
|
559
|
+
// A one-shot deep-link anchor: when a surface opens account settings AND wants to land on a
|
|
560
|
+
// specific section within the (long) tab body, it sets this to that section's id. The owning
|
|
561
|
+
// panel scrolls the matching element into view once, then calls `clearAccountSettingsScrollTarget`
|
|
562
|
+
// so a later plain open doesn't re-scroll. Null when no section was requested.
|
|
563
|
+
const accountSettingsScrollTarget = ref<string | null>(null)
|
|
564
|
+
|
|
463
565
|
function openWorkspaceSettings(tab = 'workspace') {
|
|
464
566
|
resetHubReturn()
|
|
465
567
|
workspaceSettingsTab.value = tab
|
|
@@ -495,34 +597,49 @@ export function createUiModals() {
|
|
|
495
597
|
function setAccountSettingsTab(tab: string) {
|
|
496
598
|
accountSettingsTab.value = tab
|
|
497
599
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
resetHubReturn()
|
|
514
|
-
packageRegistriesOpen.value = true
|
|
515
|
-
}
|
|
516
|
-
function closePackageRegistries() {
|
|
517
|
-
packageRegistriesOpen.value = false
|
|
518
|
-
}
|
|
519
|
-
function openApiTokens() {
|
|
520
|
-
resetHubReturn()
|
|
521
|
-
apiTokensOpen.value = true
|
|
522
|
-
}
|
|
523
|
-
function closeApiTokens() {
|
|
524
|
-
apiTokensOpen.value = false
|
|
600
|
+
|
|
601
|
+
return {
|
|
602
|
+
workspaceSettingsOpen,
|
|
603
|
+
workspaceSettingsTab,
|
|
604
|
+
accountSettingsOpen,
|
|
605
|
+
accountSettingsTab,
|
|
606
|
+
accountSettingsScrollTarget,
|
|
607
|
+
openWorkspaceSettings,
|
|
608
|
+
closeWorkspaceSettings,
|
|
609
|
+
setWorkspaceSettingsTab,
|
|
610
|
+
openAccountSettings,
|
|
611
|
+
openContentStorageSettings,
|
|
612
|
+
clearAccountSettingsScrollTarget,
|
|
613
|
+
closeAccountSettings,
|
|
614
|
+
setAccountSettingsTab,
|
|
525
615
|
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* The Infrastructure window (agent containers + test environments) and the environment setup
|
|
620
|
+
* wizard, plus the `cat-factory k3s` CLI deep-link capture that seeds the kube engine form.
|
|
621
|
+
*/
|
|
622
|
+
function createInfraModals(resetHubReturn: ResetHubReturn) {
|
|
623
|
+
// The single tabbed Infrastructure window — a TOP-LEVEL navbar destination (no longer
|
|
624
|
+
// reached via the Integrations hub). Two topical tabs: "Agent containers" (the execution
|
|
625
|
+
// backend + self-hosted runner pool, plus the local-mode warm pool/checkout) and "Test
|
|
626
|
+
// environments" (the ephemeral-environment provider). `infrastructureOpen` is the modal
|
|
627
|
+
// flag; `infrastructureTab` selects the tab. `openInfrastructure()` is the navbar entry;
|
|
628
|
+
// `openProviderConnection(kind)` remains for deep-links (a banner's "Configure…" button).
|
|
629
|
+
const infrastructureOpen = ref(false)
|
|
630
|
+
const infrastructureTab = ref<'environment' | 'runner-pool'>('runner-pool')
|
|
631
|
+
// Non-secret prefill captured from the `cat-factory k3s` CLI deep-link (see
|
|
632
|
+
// `consumeK3sSetupDeepLink`). When set, the Test-environments tab's kube engine form seeds the
|
|
633
|
+
// `local-k3s` connection from it; the ServiceAccount token is deliberately NOT in the link (a
|
|
634
|
+
// secret in a URL leaks into history/logs), so the user still pastes it before Test → Save.
|
|
635
|
+
const k3sSetupPrefill = ref<K3sSetupPrefill | null>(null)
|
|
636
|
+
// Environment setup wizard (shared-stacks slice 7): the guided detect → review → preflight →
|
|
637
|
+
// trial → save flow for a service frame's `docker-compose` provisioning. `environmentWizardOpen`
|
|
638
|
+
// is the modal flag; `environmentWizardFrameId` preselects the service frame the flow targets
|
|
639
|
+
// (set when launched from a frame's inspector nudge; null ⇒ the wizard's pick step chooses one).
|
|
640
|
+
const environmentWizardOpen = ref(false)
|
|
641
|
+
const environmentWizardFrameId = ref<string | null>(null)
|
|
642
|
+
|
|
526
643
|
// Top-level navbar entry into the Infrastructure window. No hub-return marker (it isn't
|
|
527
644
|
// reached from the Integrations hub), so the window shows no "Back to Integrations" control.
|
|
528
645
|
function openInfrastructure(tab: 'environment' | 'runner-pool' = 'runner-pool') {
|
|
@@ -572,65 +689,64 @@ export function createUiModals() {
|
|
|
572
689
|
'insecureSkipTlsVerify',
|
|
573
690
|
]) {
|
|
574
691
|
params.delete(key)
|
|
575
|
-
}
|
|
576
|
-
const qs = params.toString()
|
|
577
|
-
history.replaceState(null, '', window.location.pathname + (qs ? `?${qs}` : ''))
|
|
578
|
-
}
|
|
579
|
-
// Launch the environment setup wizard, optionally preselecting the service frame it targets
|
|
580
|
-
// (the inspector nudge passes the frame; the navbar entry opens it with the pick step active).
|
|
581
|
-
function openEnvironmentSetup(frameId: string | null = null) {
|
|
582
|
-
resetHubReturn()
|
|
583
|
-
environmentWizardFrameId.value = frameId
|
|
584
|
-
environmentWizardOpen.value = true
|
|
585
|
-
}
|
|
586
|
-
function closeEnvironmentSetup() {
|
|
587
|
-
environmentWizardOpen.value = false
|
|
588
|
-
environmentWizardFrameId.value = null
|
|
589
|
-
}
|
|
590
|
-
function openModelConfig() {
|
|
591
|
-
modelConfigOpen.value = true
|
|
592
|
-
}
|
|
593
|
-
function closeModelConfig() {
|
|
594
|
-
modelConfigOpen.value = false
|
|
595
|
-
}
|
|
596
|
-
function openVendorCredentials(tab = 'pool') {
|
|
597
|
-
resetHubReturn()
|
|
598
|
-
vendorCredentialsTab.value = tab
|
|
599
|
-
vendorCredentialsOpen.value = true
|
|
600
|
-
}
|
|
601
|
-
function setVendorCredentialsTab(tab: string) {
|
|
602
|
-
vendorCredentialsTab.value = tab
|
|
603
|
-
}
|
|
604
|
-
function closeVendorCredentials() {
|
|
605
|
-
vendorCredentialsOpen.value = false
|
|
606
|
-
}
|
|
607
|
-
function openLocalModels() {
|
|
608
|
-
resetHubReturn()
|
|
609
|
-
localModelsOpen.value = true
|
|
610
|
-
}
|
|
611
|
-
function closeLocalModels() {
|
|
612
|
-
localModelsOpen.value = false
|
|
613
|
-
}
|
|
614
|
-
function openSandbox() {
|
|
615
|
-
sandboxOpen.value = true
|
|
616
|
-
}
|
|
617
|
-
function closeSandbox() {
|
|
618
|
-
sandboxOpen.value = false
|
|
692
|
+
}
|
|
693
|
+
const qs = params.toString()
|
|
694
|
+
history.replaceState(null, '', window.location.pathname + (qs ? `?${qs}` : ''))
|
|
619
695
|
}
|
|
620
|
-
|
|
696
|
+
// Launch the environment setup wizard, optionally preselecting the service frame it targets
|
|
697
|
+
// (the inspector nudge passes the frame; the navbar entry opens it with the pick step active).
|
|
698
|
+
function openEnvironmentSetup(frameId: string | null = null) {
|
|
621
699
|
resetHubReturn()
|
|
622
|
-
|
|
700
|
+
environmentWizardFrameId.value = frameId
|
|
701
|
+
environmentWizardOpen.value = true
|
|
623
702
|
}
|
|
624
|
-
function
|
|
625
|
-
|
|
703
|
+
function closeEnvironmentSetup() {
|
|
704
|
+
environmentWizardOpen.value = false
|
|
705
|
+
environmentWizardFrameId.value = null
|
|
626
706
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
707
|
+
|
|
708
|
+
return {
|
|
709
|
+
infrastructureOpen,
|
|
710
|
+
infrastructureTab,
|
|
711
|
+
openInfrastructure,
|
|
712
|
+
k3sSetupPrefill,
|
|
713
|
+
consumeK3sSetupDeepLink,
|
|
714
|
+
environmentWizardOpen,
|
|
715
|
+
environmentWizardFrameId,
|
|
716
|
+
openProviderConnection,
|
|
717
|
+
closeProviderConnection,
|
|
718
|
+
openEnvironmentSetup,
|
|
719
|
+
closeEnvironmentSetup,
|
|
630
720
|
}
|
|
631
|
-
|
|
632
|
-
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* AI-onboarding surfaces (driven by `useAiReadiness`) + the infra-setup banner's per-session
|
|
725
|
+
* dismissals. The `*Dismissed` flags are per-session: they suppress the auto-open (and let the
|
|
726
|
+
* banner be dismissed) without permanently hiding the prompt — it re-evaluates on the next load.
|
|
727
|
+
*/
|
|
728
|
+
function createAiOnboardingModals() {
|
|
729
|
+
// `aiProviderSetupOpen` is the "no usable AI source" dialog; `aiPresetMismatchOpen` is the
|
|
730
|
+
// "default preset points at unavailable models" dialog. Both clear themselves once the
|
|
731
|
+
// underlying gap is closed.
|
|
732
|
+
const aiProviderSetupOpen = ref(false)
|
|
733
|
+
const aiPresetMismatchOpen = ref(false)
|
|
734
|
+
const aiSetupDismissed = ref(false)
|
|
735
|
+
const aiPresetDismissed = ref(false)
|
|
736
|
+
|
|
737
|
+
// Infra-setup banner: per-SESSION dismissals, one flag per area, cleared on workspace switch
|
|
738
|
+
// exactly like the AI-onboarding flags (a dismissal in one workspace must not suppress the
|
|
739
|
+
// independent prompt for another). The PERMANENT "don't notify me again" dismissal is per-USER
|
|
740
|
+
// and persists in localStorage from the banner component; this only covers "hide for now".
|
|
741
|
+
const infraSetupSessionDismissed = ref<InfraSetupArea[]>([])
|
|
742
|
+
function dismissInfraSetupForSession(area: InfraSetupArea) {
|
|
743
|
+
if (!infraSetupSessionDismissed.value.includes(area))
|
|
744
|
+
infraSetupSessionDismissed.value = [...infraSetupSessionDismissed.value, area]
|
|
745
|
+
}
|
|
746
|
+
function resetInfraSetupDismissals() {
|
|
747
|
+
infraSetupSessionDismissed.value = []
|
|
633
748
|
}
|
|
749
|
+
|
|
634
750
|
function openAiProviderSetup() {
|
|
635
751
|
aiProviderSetupOpen.value = true
|
|
636
752
|
}
|
|
@@ -666,55 +782,6 @@ export function createUiModals() {
|
|
|
666
782
|
}
|
|
667
783
|
|
|
668
784
|
return {
|
|
669
|
-
builderOpen,
|
|
670
|
-
pipelineHealthOpen,
|
|
671
|
-
pipelineHealthSeen,
|
|
672
|
-
riskPolicyHealthOpen,
|
|
673
|
-
riskPolicyHealthSeen,
|
|
674
|
-
modelPresetHealthOpen,
|
|
675
|
-
modelPresetHealthSeen,
|
|
676
|
-
decisionContext,
|
|
677
|
-
documentConnect,
|
|
678
|
-
documentImport,
|
|
679
|
-
documentTemplates,
|
|
680
|
-
spawnPreview,
|
|
681
|
-
taskConnect,
|
|
682
|
-
taskImport,
|
|
683
|
-
addTaskContainerId,
|
|
684
|
-
addTaskPrefill,
|
|
685
|
-
addRecurringFrameId,
|
|
686
|
-
createInitiativeFrameId,
|
|
687
|
-
bootstrapOpen,
|
|
688
|
-
addServiceOpen,
|
|
689
|
-
githubOpen,
|
|
690
|
-
slackOpen,
|
|
691
|
-
fragmentLibraryOpen,
|
|
692
|
-
commandBarOpen,
|
|
693
|
-
shortcutsHelpOpen,
|
|
694
|
-
mobileNavOpen,
|
|
695
|
-
integrationsOpen,
|
|
696
|
-
cameFromIntegrations,
|
|
697
|
-
personalSetupOpen,
|
|
698
|
-
cameFromPersonal,
|
|
699
|
-
workspaceSettingsOpen,
|
|
700
|
-
workspaceSettingsTab,
|
|
701
|
-
accountSettingsOpen,
|
|
702
|
-
accountSettingsTab,
|
|
703
|
-
accountSettingsScrollTarget,
|
|
704
|
-
observabilityConnectionOpen,
|
|
705
|
-
operatorDashboardOpen,
|
|
706
|
-
packageRegistriesOpen,
|
|
707
|
-
apiTokensOpen,
|
|
708
|
-
infrastructureOpen,
|
|
709
|
-
infrastructureTab,
|
|
710
|
-
openInfrastructure,
|
|
711
|
-
modelConfigOpen,
|
|
712
|
-
vendorCredentialsOpen,
|
|
713
|
-
vendorCredentialsTab,
|
|
714
|
-
localModelsOpen,
|
|
715
|
-
sandboxOpen,
|
|
716
|
-
userSecretsOpen,
|
|
717
|
-
openRouterOpen,
|
|
718
785
|
aiProviderSetupOpen,
|
|
719
786
|
aiPresetMismatchOpen,
|
|
720
787
|
aiSetupDismissed,
|
|
@@ -722,98 +789,6 @@ export function createUiModals() {
|
|
|
722
789
|
infraSetupSessionDismissed,
|
|
723
790
|
dismissInfraSetupForSession,
|
|
724
791
|
resetInfraSetupDismissals,
|
|
725
|
-
k3sSetupPrefill,
|
|
726
|
-
consumeK3sSetupDeepLink,
|
|
727
|
-
environmentWizardOpen,
|
|
728
|
-
environmentWizardFrameId,
|
|
729
|
-
openBuilder,
|
|
730
|
-
maybeOpenPipelineHealth,
|
|
731
|
-
openPipelineHealth,
|
|
732
|
-
closePipelineHealth,
|
|
733
|
-
maybeOpenRiskPolicyHealth,
|
|
734
|
-
openRiskPolicyHealth,
|
|
735
|
-
closeRiskPolicyHealth,
|
|
736
|
-
maybeOpenModelPresetHealth,
|
|
737
|
-
openModelPresetHealth,
|
|
738
|
-
closeModelPresetHealth,
|
|
739
|
-
openDecision,
|
|
740
|
-
closeDecision,
|
|
741
|
-
openDocumentConnect,
|
|
742
|
-
closeDocumentConnect,
|
|
743
|
-
openDocumentImport,
|
|
744
|
-
closeDocumentImport,
|
|
745
|
-
openDocumentTemplates,
|
|
746
|
-
closeDocumentTemplates,
|
|
747
|
-
openSpawnPreview,
|
|
748
|
-
closeSpawnPreview,
|
|
749
|
-
openTaskConnect,
|
|
750
|
-
closeTaskConnect,
|
|
751
|
-
openTaskImport,
|
|
752
|
-
closeTaskImport,
|
|
753
|
-
openAddTask,
|
|
754
|
-
closeAddTask,
|
|
755
|
-
openAddRecurring,
|
|
756
|
-
closeAddRecurring,
|
|
757
|
-
openCreateInitiative,
|
|
758
|
-
closeCreateInitiative,
|
|
759
|
-
openBootstrap,
|
|
760
|
-
closeBootstrap,
|
|
761
|
-
openAddService,
|
|
762
|
-
closeAddService,
|
|
763
|
-
openGitHub,
|
|
764
|
-
closeGitHub,
|
|
765
|
-
openSlack,
|
|
766
|
-
closeSlack,
|
|
767
|
-
openFragmentLibrary,
|
|
768
|
-
closeFragmentLibrary,
|
|
769
|
-
openCommandBar,
|
|
770
|
-
closeCommandBar,
|
|
771
|
-
toggleCommandBar,
|
|
772
|
-
openShortcutsHelp,
|
|
773
|
-
closeShortcutsHelp,
|
|
774
|
-
toggleShortcutsHelp,
|
|
775
|
-
openMobileNav,
|
|
776
|
-
closeMobileNav,
|
|
777
|
-
toggleMobileNav,
|
|
778
|
-
openIntegrations,
|
|
779
|
-
closeIntegrations,
|
|
780
|
-
openFromIntegrations,
|
|
781
|
-
openPersonalSetup,
|
|
782
|
-
closePersonalSetup,
|
|
783
|
-
openFromPersonal,
|
|
784
|
-
openWorkspaceSettings,
|
|
785
|
-
closeWorkspaceSettings,
|
|
786
|
-
setWorkspaceSettingsTab,
|
|
787
|
-
openAccountSettings,
|
|
788
|
-
openContentStorageSettings,
|
|
789
|
-
clearAccountSettingsScrollTarget,
|
|
790
|
-
closeAccountSettings,
|
|
791
|
-
setAccountSettingsTab,
|
|
792
|
-
openObservabilityConnection,
|
|
793
|
-
closeObservabilityConnection,
|
|
794
|
-
openOperatorDashboard,
|
|
795
|
-
closeOperatorDashboard,
|
|
796
|
-
openPackageRegistries,
|
|
797
|
-
closePackageRegistries,
|
|
798
|
-
openApiTokens,
|
|
799
|
-
closeApiTokens,
|
|
800
|
-
openProviderConnection,
|
|
801
|
-
closeProviderConnection,
|
|
802
|
-
openEnvironmentSetup,
|
|
803
|
-
closeEnvironmentSetup,
|
|
804
|
-
openModelConfig,
|
|
805
|
-
closeModelConfig,
|
|
806
|
-
openVendorCredentials,
|
|
807
|
-
setVendorCredentialsTab,
|
|
808
|
-
closeVendorCredentials,
|
|
809
|
-
openLocalModels,
|
|
810
|
-
closeLocalModels,
|
|
811
|
-
openSandbox,
|
|
812
|
-
closeSandbox,
|
|
813
|
-
openUserSecrets,
|
|
814
|
-
closeUserSecrets,
|
|
815
|
-
openOpenRouter,
|
|
816
|
-
closeOpenRouter,
|
|
817
792
|
openAiProviderSetup,
|
|
818
793
|
closeAiProviderSetup,
|
|
819
794
|
openAiPresetMismatch,
|
|
@@ -823,3 +798,95 @@ export function createUiModals() {
|
|
|
823
798
|
resetAiOnboarding,
|
|
824
799
|
}
|
|
825
800
|
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* The modal / panel slice of the UI store: every open-close flag for the dozens of modals,
|
|
804
|
+
* panels and hubs (document + task import, bootstrap, integrations, workspace/account settings,
|
|
805
|
+
* infrastructure, vendor credentials, the startup health advisories, the AI-onboarding surfaces,
|
|
806
|
+
* …), their deep-link params, and the hub came-from markers. Split out of the navigation +
|
|
807
|
+
* result-view state per refactoring candidate #4 so the god-object's modal churn is contained to
|
|
808
|
+
* one place. Composed into {@link useUiStore} with the same public names, so consumers are
|
|
809
|
+
* unchanged. The state itself is grouped into cohesive sub-slices (health advisories, document +
|
|
810
|
+
* task sources, integration panels, settings, infrastructure, AI onboarding), composed here behind
|
|
811
|
+
* the shared hub came-from markers.
|
|
812
|
+
*/
|
|
813
|
+
export function createUiModals() {
|
|
814
|
+
// Integrations / My-setup hub came-from markers — the one piece of state SHARED across slices
|
|
815
|
+
// (many `open*` handlers reset it), so it lives here and `resetHubReturn` is threaded into the
|
|
816
|
+
// slices that need it. `cameFromIntegrations` is true while an integration's own panel is showing
|
|
817
|
+
// AND it was reached from the Integrations hub; `cameFromPersonal` is the My-setup analogue.
|
|
818
|
+
const cameFromIntegrations = ref(false)
|
|
819
|
+
const cameFromPersonal = ref(false)
|
|
820
|
+
const integrationsOpen = ref(false)
|
|
821
|
+
const personalSetupOpen = ref(false)
|
|
822
|
+
|
|
823
|
+
// Clear BOTH hub came-from markers. Every direct `open*` in the slices calls this so that a
|
|
824
|
+
// panel opened outside the hubs never grows a dead Back control, and so switching from one
|
|
825
|
+
// hub's panel to the other's clears the stale marker.
|
|
826
|
+
function resetHubReturn() {
|
|
827
|
+
cameFromIntegrations.value = false
|
|
828
|
+
cameFromPersonal.value = false
|
|
829
|
+
}
|
|
830
|
+
function openIntegrations() {
|
|
831
|
+
// Reaching the hub itself (fresh, or via a panel's Back control) clears the
|
|
832
|
+
// came-from markers — we're at the hub, not inside a hub-spawned panel.
|
|
833
|
+
resetHubReturn()
|
|
834
|
+
integrationsOpen.value = true
|
|
835
|
+
}
|
|
836
|
+
function closeIntegrations() {
|
|
837
|
+
integrationsOpen.value = false
|
|
838
|
+
}
|
|
839
|
+
function openPersonalSetup() {
|
|
840
|
+
resetHubReturn()
|
|
841
|
+
personalSetupOpen.value = true
|
|
842
|
+
}
|
|
843
|
+
function closePersonalSetup() {
|
|
844
|
+
personalSetupOpen.value = false
|
|
845
|
+
}
|
|
846
|
+
// Open a user-scoped panel FROM the My-setup hub: run its open handler (which resets the
|
|
847
|
+
// markers), then mark that we came from My setup and dismiss it, so the panel's
|
|
848
|
+
// IntegrationBackTitle returns here rather than to the workspace Integrations hub.
|
|
849
|
+
function openFromPersonal(open: () => void) {
|
|
850
|
+
open()
|
|
851
|
+
cameFromPersonal.value = true
|
|
852
|
+
personalSetupOpen.value = false
|
|
853
|
+
}
|
|
854
|
+
// Open an integration's own panel FROM the hub: run its open handler (which resets
|
|
855
|
+
// `cameFromIntegrations`), then mark that we came from the hub and dismiss it. The
|
|
856
|
+
// panel reads `cameFromIntegrations` to show its Back control.
|
|
857
|
+
function openFromIntegrations(open: () => void) {
|
|
858
|
+
open()
|
|
859
|
+
cameFromIntegrations.value = true
|
|
860
|
+
integrationsOpen.value = false
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
const health = createHealthAdvisoryModals()
|
|
864
|
+
const misc = createMiscModals()
|
|
865
|
+
const documentsTasks = createDocumentTaskModals(resetHubReturn)
|
|
866
|
+
const overlays = createOverlayModals()
|
|
867
|
+
const panels = createIntegrationPanelModals(resetHubReturn)
|
|
868
|
+
const settings = createSettingsModals(resetHubReturn)
|
|
869
|
+
const infra = createInfraModals(resetHubReturn)
|
|
870
|
+
const ai = createAiOnboardingModals()
|
|
871
|
+
|
|
872
|
+
return {
|
|
873
|
+
integrationsOpen,
|
|
874
|
+
cameFromIntegrations,
|
|
875
|
+
personalSetupOpen,
|
|
876
|
+
cameFromPersonal,
|
|
877
|
+
openIntegrations,
|
|
878
|
+
closeIntegrations,
|
|
879
|
+
openFromIntegrations,
|
|
880
|
+
openPersonalSetup,
|
|
881
|
+
closePersonalSetup,
|
|
882
|
+
openFromPersonal,
|
|
883
|
+
...health,
|
|
884
|
+
...misc,
|
|
885
|
+
...documentsTasks,
|
|
886
|
+
...overlays,
|
|
887
|
+
...panels,
|
|
888
|
+
...settings,
|
|
889
|
+
...infra,
|
|
890
|
+
...ai,
|
|
891
|
+
}
|
|
892
|
+
}
|