@pellux/goodvibes-tui 0.20.3 → 0.21.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/CHANGELOG.md +27 -0
- package/README.md +23 -2
- package/docs/foundation-artifacts/operator-contract.json +78 -1
- package/package.json +3 -2
- package/src/audio/spoken-turn-controller.ts +31 -1
- package/src/audio/spoken-turn-wiring.ts +26 -4
- package/src/cli/bundle-command.ts +1 -1
- package/src/cli/completions/generate.ts +662 -0
- package/src/cli/config-overrides.ts +68 -0
- package/src/cli/help.ts +4 -2
- package/src/cli/management-commands.ts +1 -1
- package/src/cli/management.ts +1 -8
- package/src/cli/parser.ts +14 -18
- package/src/cli/service-command.ts +1 -1
- package/src/cli/surface-command.ts +1 -1
- package/src/cli/tui-startup.ts +72 -10
- package/src/cli/types.ts +12 -3
- package/src/cli-flags.ts +1 -0
- package/src/config/atomic-write.ts +70 -0
- package/src/config/read-versioned.ts +115 -0
- package/src/core/conversation-rendering.ts +49 -15
- package/src/core/conversation.ts +101 -16
- package/src/core/format-user-error.ts +192 -0
- package/src/core/stream-event-wiring.ts +144 -0
- package/src/core/stream-stall-watchdog.ts +103 -0
- package/src/core/system-message-router.ts +5 -1
- package/src/export/cost-utils.ts +71 -0
- package/src/export/gist-uploader.ts +136 -0
- package/src/input/command-registry.ts +31 -1
- package/src/input/commands/control-room-runtime.ts +5 -5
- package/src/input/commands/experience-runtime.ts +5 -4
- package/src/input/commands/knowledge.ts +1 -1
- package/src/input/commands/local-auth-runtime.ts +27 -5
- package/src/input/commands/local-setup.ts +4 -6
- package/src/input/commands/memory-product-runtime.ts +8 -6
- package/src/input/commands/operator-panel-runtime.ts +1 -1
- package/src/input/commands/operator-runtime.ts +3 -10
- package/src/input/commands/{integration-runtime.ts → plugin-runtime.ts} +1 -1
- package/src/input/commands/recall-review.ts +26 -2
- package/src/input/commands/services-runtime.ts +2 -2
- package/src/input/commands/session-workflow.ts +3 -3
- package/src/input/commands/share-runtime.ts +99 -12
- package/src/input/commands/tts-runtime.ts +30 -4
- package/src/input/commands.ts +2 -2
- package/src/input/delete-key-policy.ts +46 -0
- package/src/input/feed-context-factory.ts +2 -0
- package/src/input/handler-feed.ts +3 -0
- package/src/input/handler-interactions.ts +2 -15
- package/src/input/handler-modal-routes.ts +91 -12
- package/src/input/handler-modal-token-routes.ts +3 -0
- package/src/input/handler-onboarding-cloudflare.ts +1 -1
- package/src/input/handler-onboarding.ts +55 -69
- package/src/input/handler-types.ts +163 -0
- package/src/input/handler.ts +5 -2
- package/src/input/input-history.ts +76 -6
- package/src/input/model-picker-filter.ts +265 -0
- package/src/input/model-picker-items.ts +208 -0
- package/src/input/model-picker.ts +92 -325
- package/src/input/onboarding/handler-onboarding-routes.ts +7 -2
- package/src/input/onboarding/onboarding-verification-helpers.ts +76 -0
- package/src/input/onboarding/onboarding-wizard-apply.ts +4 -4
- package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +2 -2
- package/src/input/onboarding/onboarding-wizard-cloudflare.ts +8 -8
- package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +2 -29
- package/src/input/onboarding/onboarding-wizard-rules.ts +28 -28
- package/src/input/onboarding/onboarding-wizard-state.ts +20 -20
- package/src/input/onboarding/onboarding-wizard-steps.ts +18 -25
- package/src/input/onboarding/onboarding-wizard-types.ts +145 -3
- package/src/input/onboarding/onboarding-wizard.ts +3 -3
- package/src/input/settings-modal-data.ts +304 -0
- package/src/input/settings-modal-mutations.ts +154 -0
- package/src/input/settings-modal.ts +182 -220
- package/src/main.ts +57 -57
- package/src/panels/builtin/agent.ts +4 -1
- package/src/panels/builtin/development.ts +4 -1
- package/src/panels/confirm-state.ts +27 -12
- package/src/panels/cost-tracker-panel.ts +23 -67
- package/src/panels/eval-panel.ts +10 -9
- package/src/panels/knowledge-panel.ts +3 -5
- package/src/panels/local-auth-panel.ts +124 -4
- package/src/panels/project-planning-panel.ts +42 -4
- package/src/panels/search-focus.ts +11 -5
- package/src/panels/subscription-panel.ts +33 -25
- package/src/panels/types.ts +28 -1
- package/src/panels/wrfc-panel.ts +224 -41
- package/src/renderer/agent-detail-modal.ts +11 -10
- package/src/renderer/code-block.ts +10 -2
- package/src/renderer/compositor.ts +18 -4
- package/src/renderer/context-inspector.ts +1 -5
- package/src/renderer/diff.ts +94 -21
- package/src/renderer/markdown.ts +29 -13
- package/src/renderer/settings-modal-helpers.ts +1 -1
- package/src/renderer/settings-modal.ts +77 -8
- package/src/renderer/syntax-highlighter.ts +10 -3
- package/src/renderer/term-caps.ts +318 -0
- package/src/renderer/theme.ts +158 -0
- package/src/renderer/tool-call.ts +12 -2
- package/src/renderer/ui-factory.ts +50 -6
- package/src/runtime/bootstrap-command-context.ts +1 -0
- package/src/runtime/bootstrap-command-parts.ts +14 -0
- package/src/runtime/bootstrap-core.ts +121 -13
- package/src/runtime/bootstrap.ts +2 -0
- package/src/runtime/onboarding/apply.ts +4 -6
- package/src/runtime/onboarding/index.ts +1 -0
- package/src/runtime/onboarding/markers.ts +42 -49
- package/src/runtime/onboarding/progress.ts +148 -0
- package/src/runtime/onboarding/state.ts +133 -55
- package/src/runtime/onboarding/types.ts +20 -0
- package/src/runtime/services.ts +21 -0
- package/src/runtime/wrfc-persistence.ts +237 -0
- package/src/shell/blocking-input.ts +20 -5
- package/src/tools/wrfc-agent-guard.ts +64 -3
- package/src/utils/format-elapsed.ts +30 -0
- package/src/utils/terminal-width.ts +45 -0
- package/src/version.ts +1 -1
- package/src/work-plans/work-plan-store.ts +4 -6
- package/src/planning/project-planning-coordinator.ts +0 -543
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
type CloudflareProvisionRequest,
|
|
9
9
|
} from '../../runtime/cloudflare-control-plane.ts';
|
|
10
10
|
import { buildGoodVibesSecretRef, normalizeText } from './onboarding-wizard-helpers.ts';
|
|
11
|
-
import type {
|
|
11
|
+
import type { OnboardingWizardControllerLike } from './onboarding-wizard-types.ts';
|
|
12
12
|
import type { OnboardingWizardRadioOption } from './onboarding-wizard-types.ts';
|
|
13
13
|
|
|
14
14
|
export const CLOUDFLARE_SETUP_SOURCE_OPTIONS: readonly OnboardingWizardRadioOption[] = [
|
|
@@ -90,7 +90,7 @@ export function cloudflareComponentLabel(component: CloudflareComponent): string
|
|
|
90
90
|
return CLOUDFLARE_COMPONENT_LABELS[component];
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
export function isCloudflareConfigured(controller:
|
|
93
|
+
export function isCloudflareConfigured(controller: OnboardingWizardControllerLike): boolean {
|
|
94
94
|
const config = controller.runtimeSnapshot?.config.cloudflare;
|
|
95
95
|
if (!config) return false;
|
|
96
96
|
return config.enabled
|
|
@@ -100,11 +100,11 @@ export function isCloudflareConfigured(controller: OnboardingWizardController):
|
|
|
100
100
|
|| normalizeText(config.workerName).length > 0;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
export function shouldShowCloudflareStep(controller:
|
|
103
|
+
export function shouldShowCloudflareStep(controller: OnboardingWizardControllerLike): boolean {
|
|
104
104
|
return controller.isCapabilitySelected('cloudflare-batch') || isCloudflareConfigured(controller);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
export function getCloudflareSetupSource(controller:
|
|
107
|
+
export function getCloudflareSetupSource(controller: OnboardingWizardControllerLike): CloudflareSetupSource {
|
|
108
108
|
const configuredTokenRef = controller.runtimeSnapshot?.config.cloudflare.apiTokenRef ?? '';
|
|
109
109
|
const defaultValue = configuredTokenRef.startsWith('goodvibes://secrets/env/') ? 'operational-env' : 'save-only';
|
|
110
110
|
const value = controller.getStringFieldValue('cloudflare.setup-source', defaultValue);
|
|
@@ -120,7 +120,7 @@ export function getCloudflareSetupSource(controller: OnboardingWizardController)
|
|
|
120
120
|
return 'save-only';
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
export function getCloudflareComponentSelection(controller:
|
|
123
|
+
export function getCloudflareComponentSelection(controller: OnboardingWizardControllerLike): Record<CloudflareComponent, boolean> {
|
|
124
124
|
const selected: Record<CloudflareComponent, boolean> = { ...DEFAULT_CLOUDFLARE_COMPONENT_SELECTION };
|
|
125
125
|
const configured = controller.runtimeSnapshot?.config.cloudflare;
|
|
126
126
|
for (const component of CLOUDFLARE_COMPONENT_IDS) {
|
|
@@ -132,11 +132,11 @@ export function getCloudflareComponentSelection(controller: OnboardingWizardCont
|
|
|
132
132
|
return selected;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
export function getSelectedCloudflareComponents(controller:
|
|
135
|
+
export function getSelectedCloudflareComponents(controller: OnboardingWizardControllerLike): CloudflareComponentSelection {
|
|
136
136
|
return getCloudflareComponentSelection(controller);
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
export function getCloudflareBatchMode(controller:
|
|
139
|
+
export function getCloudflareBatchMode(controller: OnboardingWizardControllerLike): CloudflareBatchMode {
|
|
140
140
|
const value = controller.getStringFieldValue('cloudflare.batch-mode', controller.runtimeSnapshot?.config.batch.mode ?? 'off');
|
|
141
141
|
return value === 'explicit' || value === 'eligible-by-default' ? value : 'off';
|
|
142
142
|
}
|
|
@@ -146,7 +146,7 @@ export function buildCloudflareApiTokenRef(envName: string): string {
|
|
|
146
146
|
return `goodvibes://secrets/env/${encodeURIComponent(normalized)}`;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
export function buildCloudflareProvisionRequest(controller:
|
|
149
|
+
export function buildCloudflareProvisionRequest(controller: OnboardingWizardControllerLike, options: {
|
|
150
150
|
readonly includeTransientSecrets?: boolean;
|
|
151
151
|
} = {}): CloudflareProvisionRequest {
|
|
152
152
|
const components = getCloudflareComponentSelection(controller);
|
|
@@ -8,36 +8,9 @@ import { DEFAULT_CONFIG, type ConfigKey } from '../../config/index.ts';
|
|
|
8
8
|
import type { OnboardingSnapshotState } from '../../runtime/onboarding/index.ts';
|
|
9
9
|
import { TELEGRAM_MODE_OPTIONS, WHATSAPP_PROVIDER_OPTIONS } from './onboarding-wizard-constants.ts';
|
|
10
10
|
import { HOME_ASSISTANT_SURFACE_SPEC, WEBHOOK_SURFACE_SPEC } from './onboarding-wizard-external-surface-extra-specs.ts';
|
|
11
|
-
import type { OnboardingWizardRadioOption } from './onboarding-wizard-types.ts';
|
|
11
|
+
import type { ExternalSurfaceSetupFieldSpec, ExternalSurfaceSpec, OnboardingWizardRadioOption } from './onboarding-wizard-types.ts';
|
|
12
12
|
|
|
13
|
-
export
|
|
14
|
-
readonly id: string;
|
|
15
|
-
readonly configKey: ConfigKey;
|
|
16
|
-
readonly kind: 'text' | 'masked' | 'radio';
|
|
17
|
-
readonly valueType?: 'string' | 'number';
|
|
18
|
-
readonly label: string;
|
|
19
|
-
readonly hint: string;
|
|
20
|
-
readonly placeholder: string;
|
|
21
|
-
readonly options?: readonly OnboardingWizardRadioOption[];
|
|
22
|
-
readonly defaultNumber?: number;
|
|
23
|
-
readonly min?: number;
|
|
24
|
-
readonly max?: number;
|
|
25
|
-
readonly defaultValue: (snapshot: OnboardingSnapshotState | null) => string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface ExternalSurfaceSpec {
|
|
29
|
-
readonly id: string;
|
|
30
|
-
readonly enabledFieldId: string;
|
|
31
|
-
readonly enabledConfigKey: ConfigKey;
|
|
32
|
-
readonly label: string;
|
|
33
|
-
readonly hint: string;
|
|
34
|
-
/**
|
|
35
|
-
* Existing SDK config key. In onboarding this maps to the per-surface
|
|
36
|
-
* auto-start choice, not to whether setup fields are shown.
|
|
37
|
-
*/
|
|
38
|
-
readonly defaultEnabled: (snapshot: OnboardingSnapshotState | null) => boolean;
|
|
39
|
-
readonly fields: readonly ExternalSurfaceSetupFieldSpec[];
|
|
40
|
-
}
|
|
13
|
+
export type { ExternalSurfaceSetupFieldSpec, ExternalSurfaceSpec };
|
|
41
14
|
|
|
42
15
|
function normalizeConfigValue(value: unknown): string {
|
|
43
16
|
if (value === null || value === undefined) return '';
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
isExternalSurfaceSelectedByDefault,
|
|
8
8
|
} from './onboarding-wizard-external-surfaces.ts';
|
|
9
9
|
import { getExternalSurfaceSpecByFieldId, normalizeText, uniqueNonEmpty } from './onboarding-wizard-helpers.ts';
|
|
10
|
-
import type {
|
|
10
|
+
import type { OnboardingWizardControllerLike } from './onboarding-wizard-types.ts';
|
|
11
11
|
|
|
12
12
|
export function getSharedIpDefault(
|
|
13
|
-
controller:
|
|
13
|
+
controller: OnboardingWizardControllerLike,
|
|
14
14
|
enabled: { readonly controlPlane: boolean; readonly httpListener: boolean; readonly web: boolean },
|
|
15
15
|
): boolean {
|
|
16
16
|
if (!controller.runtimeSnapshot) return true;
|
|
@@ -23,7 +23,7 @@ export function getSharedIpDefault(
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export function getSharedIpHostDefault(
|
|
26
|
-
controller:
|
|
26
|
+
controller: OnboardingWizardControllerLike,
|
|
27
27
|
enabled: { readonly controlPlane: boolean; readonly httpListener: boolean; readonly web: boolean },
|
|
28
28
|
): string {
|
|
29
29
|
if (!controller.runtimeSnapshot) return '0.0.0.0';
|
|
@@ -35,7 +35,7 @@ export function getSharedIpHostDefault(
|
|
|
35
35
|
return hosts[0] ?? '0.0.0.0';
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
export function toggleCapability(controller:
|
|
38
|
+
export function toggleCapability(controller: OnboardingWizardControllerLike, capabilityId: OnboardingStep1CapabilityId): void {
|
|
39
39
|
if (capabilityId === 'local-tui-only') {
|
|
40
40
|
for (const capability of controller.getCurrentCapabilities()) {
|
|
41
41
|
controller.toggleState.set(`capabilities.${capability.id}`, capability.id === 'local-tui-only');
|
|
@@ -58,31 +58,31 @@ export function toggleCapability(controller: OnboardingWizardController, capabil
|
|
|
58
58
|
if (!anyServerCapability) controller.toggleState.set('capabilities.local-tui-only', true);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
export function selectAllServerCapabilities(controller:
|
|
61
|
+
export function selectAllServerCapabilities(controller: OnboardingWizardControllerLike): void {
|
|
62
62
|
for (const capability of controller.getCurrentCapabilities()) {
|
|
63
63
|
controller.toggleState.set(`capabilities.${capability.id}`, capability.id !== 'local-tui-only');
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
export function selectLocalTuiOnly(controller:
|
|
67
|
+
export function selectLocalTuiOnly(controller: OnboardingWizardControllerLike): void {
|
|
68
68
|
for (const capability of controller.getCurrentCapabilities()) {
|
|
69
69
|
controller.toggleState.set(`capabilities.${capability.id}`, capability.id === 'local-tui-only');
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
export function selectAllExternalSurfaces(controller:
|
|
73
|
+
export function selectAllExternalSurfaces(controller: OnboardingWizardControllerLike): void {
|
|
74
74
|
for (const surface of EXTERNAL_SURFACE_SPECS) {
|
|
75
75
|
controller.toggleState.set(surface.enabledFieldId, true);
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
export function clearExternalSurfaces(controller:
|
|
79
|
+
export function clearExternalSurfaces(controller: OnboardingWizardControllerLike): void {
|
|
80
80
|
for (const surface of EXTERNAL_SURFACE_SPECS) {
|
|
81
81
|
controller.toggleState.set(surface.enabledFieldId, false);
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
export function setCapabilityValue(controller:
|
|
85
|
+
export function setCapabilityValue(controller: OnboardingWizardControllerLike, capabilityId: OnboardingStep1CapabilityId, selected: boolean): void {
|
|
86
86
|
if (capabilityId === 'local-tui-only') {
|
|
87
87
|
if (selected) {
|
|
88
88
|
for (const capability of controller.getCurrentCapabilities()) {
|
|
@@ -112,20 +112,20 @@ export function setCapabilityValue(controller: OnboardingWizardController, capab
|
|
|
112
112
|
if (!anyServerCapability) controller.toggleState.set('capabilities.local-tui-only', true);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
export function isCapabilitySelected(controller:
|
|
115
|
+
export function isCapabilitySelected(controller: OnboardingWizardControllerLike, capabilityId: OnboardingStep1CapabilityId): boolean {
|
|
116
116
|
return controller.getCapabilitySelectionState().some((capability) => capability.id === capabilityId && capability.selected);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
export function hasServerCapabilitiesSelected(controller:
|
|
119
|
+
export function hasServerCapabilitiesSelected(controller: OnboardingWizardControllerLike): boolean {
|
|
120
120
|
return controller.getCapabilitySelectionState().some((capability) => capability.id !== 'local-tui-only' && capability.selected);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
export function shouldEnableBrowserSurface(controller:
|
|
123
|
+
export function shouldEnableBrowserSurface(controller: OnboardingWizardControllerLike): boolean {
|
|
124
124
|
return controller.hasServerCapabilitiesSelected()
|
|
125
125
|
&& (controller.isCapabilitySelected('browser-access') || controller.isCapabilitySelected('network-access'));
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
export function hasSelectedInboundExternalSurface(controller:
|
|
128
|
+
export function hasSelectedInboundExternalSurface(controller: OnboardingWizardControllerLike): boolean {
|
|
129
129
|
if (!controller.isCapabilitySelected('external-integrations')) return false;
|
|
130
130
|
return EXTERNAL_SURFACE_SPECS.some((surface) => (
|
|
131
131
|
INBOUND_EXTERNAL_SURFACE_IDS.has(surface.id)
|
|
@@ -140,7 +140,7 @@ export function hasSelectedInboundExternalSurface(controller: OnboardingWizardCo
|
|
|
140
140
|
));
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
export function isRequiredExternalSetupField(controller:
|
|
143
|
+
export function isRequiredExternalSetupField(controller: OnboardingWizardControllerLike, fieldId: string): boolean {
|
|
144
144
|
if (!REQUIRED_EXTERNAL_SETUP_FIELD_IDS.has(fieldId)) return false;
|
|
145
145
|
const surface = getExternalSurfaceSpecByFieldId(fieldId);
|
|
146
146
|
if (!surface) return false;
|
|
@@ -163,7 +163,7 @@ export function isRequiredExternalSetupField(controller: OnboardingWizardControl
|
|
|
163
163
|
return true;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
export function getSelectedSecretMedium(controller:
|
|
166
|
+
export function getSelectedSecretMedium(controller: OnboardingWizardControllerLike): 'secure' | 'plaintext' {
|
|
167
167
|
const policy = controller.getStringFieldValue(
|
|
168
168
|
'external-services.secret-policy',
|
|
169
169
|
controller.runtimeSnapshot?.runtimeDefaults.secretStoragePolicy ?? 'preferred_secure',
|
|
@@ -174,12 +174,12 @@ export function getSelectedSecretMedium(controller: OnboardingWizardController):
|
|
|
174
174
|
return 'plaintext';
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
export function shouldEnableHttpListener(controller:
|
|
177
|
+
export function shouldEnableHttpListener(controller: OnboardingWizardControllerLike): boolean {
|
|
178
178
|
return controller.hasServerCapabilitiesSelected()
|
|
179
179
|
&& (controller.isCapabilitySelected('webhook-events') || controller.hasSelectedInboundExternalSurface());
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
export function shouldExposeHttpListenerNetworkFields(controller:
|
|
182
|
+
export function shouldExposeHttpListenerNetworkFields(controller: OnboardingWizardControllerLike): boolean {
|
|
183
183
|
return controller.hasServerCapabilitiesSelected()
|
|
184
184
|
&& (
|
|
185
185
|
controller.isCapabilitySelected('webhook-events')
|
|
@@ -188,31 +188,31 @@ export function shouldExposeHttpListenerNetworkFields(controller: OnboardingWiza
|
|
|
188
188
|
);
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
export function shouldExposeControlPlaneNetwork(controller:
|
|
191
|
+
export function shouldExposeControlPlaneNetwork(controller: OnboardingWizardControllerLike): boolean {
|
|
192
192
|
return controller.hasServerCapabilitiesSelected()
|
|
193
193
|
&& (controller.isCapabilitySelected('browser-access') || controller.isCapabilitySelected('network-access'));
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
export function requiresAuthBootstrap(controller:
|
|
196
|
+
export function requiresAuthBootstrap(controller: OnboardingWizardControllerLike): boolean {
|
|
197
197
|
return controller.hasServerCapabilitiesSelected()
|
|
198
198
|
&& (!controller.hasLocalAuthUser() || controller.hasBootstrapCredentialPresent());
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
export function hasAdminAuthUser(controller:
|
|
201
|
+
export function hasAdminAuthUser(controller: OnboardingWizardControllerLike): boolean {
|
|
202
202
|
return (controller.runtimeSnapshot?.auth.snapshot.users ?? [])
|
|
203
203
|
.some((user) => user.roles.includes('admin'));
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
export function hasLocalAuthUser(controller:
|
|
206
|
+
export function hasLocalAuthUser(controller: OnboardingWizardControllerLike): boolean {
|
|
207
207
|
return (controller.runtimeSnapshot?.auth.snapshot.userCount ?? 0) > 0
|
|
208
208
|
|| (controller.runtimeSnapshot?.auth.snapshot.users ?? []).length > 0;
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
export function hasBootstrapCredentialPresent(controller:
|
|
211
|
+
export function hasBootstrapCredentialPresent(controller: OnboardingWizardControllerLike): boolean {
|
|
212
212
|
return controller.runtimeSnapshot?.auth.snapshot.bootstrapCredentialPresent === true;
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
-
export function getDefaultAdminUsername(controller:
|
|
215
|
+
export function getDefaultAdminUsername(controller: OnboardingWizardControllerLike): string {
|
|
216
216
|
const users = controller.runtimeSnapshot?.auth.snapshot.users ?? [];
|
|
217
217
|
if (controller.hasBootstrapCredentialPresent()) {
|
|
218
218
|
const existingAdmin = users.find((user) => user.roles.includes('admin'));
|
|
@@ -225,29 +225,29 @@ export function getDefaultAdminUsername(controller: OnboardingWizardController):
|
|
|
225
225
|
return candidate ?? `goodvibes-admin-${users.length + 1}`;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
-
export function getBooleanFieldValue(controller:
|
|
228
|
+
export function getBooleanFieldValue(controller: OnboardingWizardControllerLike, fieldId: string, fallback: boolean): boolean {
|
|
229
229
|
return controller.toggleState.get(fieldId) ?? fallback;
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
export function getStringFieldValue(controller:
|
|
232
|
+
export function getStringFieldValue(controller: OnboardingWizardControllerLike, fieldId: string, fallback: string): string {
|
|
233
233
|
const value = controller.textState.get(fieldId) ?? controller.radioState.get(fieldId);
|
|
234
234
|
return normalizeText(value ?? fallback);
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
export function parseIntegerFieldValue(controller:
|
|
237
|
+
export function parseIntegerFieldValue(controller: OnboardingWizardControllerLike, fieldId: string, fallback: number): number | null {
|
|
238
238
|
const raw = controller.getStringFieldValue(fieldId, String(fallback));
|
|
239
239
|
if (!/^-?\d+$/.test(raw)) return null;
|
|
240
240
|
const parsed = Number.parseInt(raw, 10);
|
|
241
241
|
return Number.isInteger(parsed) ? parsed : null;
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
export function getPortFieldValue(controller:
|
|
244
|
+
export function getPortFieldValue(controller: OnboardingWizardControllerLike, fieldId: string, fallback: number): number {
|
|
245
245
|
const parsed = controller.parseIntegerFieldValue(fieldId, fallback);
|
|
246
246
|
if (parsed === null || parsed < 1 || parsed > 65535) return fallback;
|
|
247
247
|
return parsed;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
export function getNumberFieldValue(controller:
|
|
250
|
+
export function getNumberFieldValue(controller: OnboardingWizardControllerLike, fieldId: string, fallback: number, min?: number, max?: number): number {
|
|
251
251
|
const parsed = controller.parseIntegerFieldValue(fieldId, fallback);
|
|
252
252
|
if (parsed === null) return fallback;
|
|
253
253
|
if (min !== undefined && parsed < min) return fallback;
|
|
@@ -2,16 +2,16 @@ import type { ModelPickerTarget } from '../model-picker.ts';
|
|
|
2
2
|
import type { OnboardingStep1CapabilityItem } from '../../runtime/onboarding/index.ts';
|
|
3
3
|
import { DEFAULT_CAPABILITIES, NETWORK_HOST_FIELD_IDS } from './onboarding-wizard-constants.ts';
|
|
4
4
|
import { areSelectionsEqual, clamp, cloneSelection, getExternalSurfaceSetupFieldSpec, isMalformedGoodVibesSecretReferenceValue, isValidHostValue, normalizeText } from './onboarding-wizard-helpers.ts';
|
|
5
|
-
import type {
|
|
5
|
+
import type { OnboardingWizardControllerLike } from './onboarding-wizard-types.ts';
|
|
6
6
|
import type { OnboardingWizardFieldDefinition, OnboardingWizardModelSelection, OnboardingWizardStepDefinition } from './onboarding-wizard-types.ts';
|
|
7
7
|
|
|
8
|
-
export function getToggleFieldCount(controller:
|
|
8
|
+
export function getToggleFieldCount(controller: OnboardingWizardControllerLike, stepIndex: number): number {
|
|
9
9
|
const step = controller.steps[stepIndex];
|
|
10
10
|
if (!step) return 0;
|
|
11
11
|
return step.fields.filter((field) => field.kind === 'checklist' || field.kind === 'acknowledgement').length;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export function getCompletedToggleCount(controller:
|
|
14
|
+
export function getCompletedToggleCount(controller: OnboardingWizardControllerLike, stepIndex: number): number {
|
|
15
15
|
const step = controller.steps[stepIndex];
|
|
16
16
|
if (!step) return 0;
|
|
17
17
|
|
|
@@ -21,27 +21,27 @@ export function getCompletedToggleCount(controller: OnboardingWizardController,
|
|
|
21
21
|
)).length;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export function getStepFieldCount(controller:
|
|
24
|
+
export function getStepFieldCount(controller: OnboardingWizardControllerLike, stepIndex: number): number {
|
|
25
25
|
return controller.steps[stepIndex]?.fields.length ?? 0;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export function getCompletedFieldCount(controller:
|
|
28
|
+
export function getCompletedFieldCount(controller: OnboardingWizardControllerLike, stepIndex: number): number {
|
|
29
29
|
const step = controller.steps[stepIndex];
|
|
30
30
|
if (!step) return 0;
|
|
31
31
|
return step.fields.filter((field) => controller.isFieldSatisfied(field)).length;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export function isStepDirty(controller:
|
|
34
|
+
export function isStepDirty(controller: OnboardingWizardControllerLike, stepIndex: number): boolean {
|
|
35
35
|
const stepId = controller.steps[stepIndex]?.id;
|
|
36
36
|
return stepId ? controller.dirtyStepIds.has(stepId) : false;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
export function isFieldDirty(controller:
|
|
39
|
+
export function isFieldDirty(controller: OnboardingWizardControllerLike, fieldId: string): boolean {
|
|
40
40
|
const field = controller.getFieldById(fieldId);
|
|
41
41
|
return field ? controller.isFieldDirtyByDefinition(field) : false;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export function getBlockingFieldLabels(controller:
|
|
44
|
+
export function getBlockingFieldLabels(controller: OnboardingWizardControllerLike): readonly string[] {
|
|
45
45
|
const labels: string[] = [];
|
|
46
46
|
if (controller.hydrationPending) {
|
|
47
47
|
labels.push('Loading: Current runtime settings are still being collected.');
|
|
@@ -65,7 +65,7 @@ export function getBlockingFieldLabels(controller: OnboardingWizardController):
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
export function getFieldValidationError(
|
|
68
|
-
controller:
|
|
68
|
+
controller: OnboardingWizardControllerLike,
|
|
69
69
|
step: OnboardingWizardStepDefinition,
|
|
70
70
|
field: OnboardingWizardFieldDefinition,
|
|
71
71
|
): string | null {
|
|
@@ -127,7 +127,7 @@ export function getFieldValidationError(
|
|
|
127
127
|
return null;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
export function getFieldById(controller:
|
|
130
|
+
export function getFieldById(controller: OnboardingWizardControllerLike, fieldId: string): OnboardingWizardFieldDefinition | null {
|
|
131
131
|
for (const step of controller.steps) {
|
|
132
132
|
const field = step.fields.find((entry) => entry.id === fieldId);
|
|
133
133
|
if (field) return field;
|
|
@@ -135,7 +135,7 @@ export function getFieldById(controller: OnboardingWizardController, fieldId: st
|
|
|
135
135
|
return null;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
export function ensureSelectionVisible(controller:
|
|
138
|
+
export function ensureSelectionVisible(controller: OnboardingWizardControllerLike, visibleFields: number): void {
|
|
139
139
|
const total = controller.currentStep.fields.length;
|
|
140
140
|
if (total === 0) {
|
|
141
141
|
controller.scrollOffsets[controller.stepIndex] = 0;
|
|
@@ -154,7 +154,7 @@ export function ensureSelectionVisible(controller: OnboardingWizardController, v
|
|
|
154
154
|
controller.scrollOffsets[controller.stepIndex] = clamp(nextOffset, 0, maxStart);
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
export function reconcileStepCursor(controller:
|
|
157
|
+
export function reconcileStepCursor(controller: OnboardingWizardControllerLike, stepIndex: number): void {
|
|
158
158
|
const total = controller.steps[stepIndex]?.fields.length ?? 0;
|
|
159
159
|
if (total === 0) {
|
|
160
160
|
controller.scrollOffsets[stepIndex] = 0;
|
|
@@ -166,7 +166,7 @@ export function reconcileStepCursor(controller: OnboardingWizardController, step
|
|
|
166
166
|
controller.scrollOffsets[stepIndex] = clamp(controller.scrollOffsets[stepIndex] ?? 0, 0, total - 1);
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
export function resetValuesFromCurrentDefinitions(controller:
|
|
169
|
+
export function resetValuesFromCurrentDefinitions(controller: OnboardingWizardControllerLike): void {
|
|
170
170
|
controller.toggleState.clear();
|
|
171
171
|
controller.baselineToggleState.clear();
|
|
172
172
|
controller.radioState.clear();
|
|
@@ -213,7 +213,7 @@ export function resetValuesFromCurrentDefinitions(controller: OnboardingWizardCo
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
export function reconcileStateWithCurrentDefinitions(controller:
|
|
216
|
+
export function reconcileStateWithCurrentDefinitions(controller: OnboardingWizardControllerLike): void {
|
|
217
217
|
const nextToggleKeys = new Set<string>();
|
|
218
218
|
const nextRadioKeys = new Set<string>();
|
|
219
219
|
const nextTextKeys = new Set<string>();
|
|
@@ -282,7 +282,7 @@ export function reconcileStateWithCurrentDefinitions(controller: OnboardingWizar
|
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
export function recalculateDirtyState(controller:
|
|
285
|
+
export function recalculateDirtyState(controller: OnboardingWizardControllerLike): void {
|
|
286
286
|
controller.reconcileStateWithCurrentDefinitions();
|
|
287
287
|
controller.dirtyStepIds.clear();
|
|
288
288
|
|
|
@@ -293,7 +293,7 @@ export function recalculateDirtyState(controller: OnboardingWizardController): v
|
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
-
export function isFieldDirtyByDefinition(controller:
|
|
296
|
+
export function isFieldDirtyByDefinition(controller: OnboardingWizardControllerLike, field: OnboardingWizardFieldDefinition): boolean {
|
|
297
297
|
if (field.kind === 'checklist' || field.kind === 'acknowledgement') {
|
|
298
298
|
return (controller.toggleState.get(field.id) ?? field.defaultValue)
|
|
299
299
|
!== (controller.baselineToggleState.get(field.id) ?? field.defaultValue);
|
|
@@ -317,7 +317,7 @@ export function isFieldDirtyByDefinition(controller: OnboardingWizardController,
|
|
|
317
317
|
);
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
export function isFieldSatisfied(controller:
|
|
320
|
+
export function isFieldSatisfied(controller: OnboardingWizardControllerLike, field: OnboardingWizardFieldDefinition): boolean {
|
|
321
321
|
if (field.kind === 'checklist') {
|
|
322
322
|
return true;
|
|
323
323
|
}
|
|
@@ -341,20 +341,20 @@ export function isFieldSatisfied(controller: OnboardingWizardController, field:
|
|
|
341
341
|
return selection.providerId.length > 0 || selection.modelId.length > 0;
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
-
export function getCurrentCapabilities(controller:
|
|
344
|
+
export function getCurrentCapabilities(controller: OnboardingWizardControllerLike): readonly OnboardingStep1CapabilityItem[] {
|
|
345
345
|
return controller.runtimeDerived.step1Capabilities.length > 0
|
|
346
346
|
? controller.runtimeDerived.step1Capabilities
|
|
347
347
|
: DEFAULT_CAPABILITIES;
|
|
348
348
|
}
|
|
349
349
|
|
|
350
|
-
export function getCapabilitySelectionState(controller:
|
|
350
|
+
export function getCapabilitySelectionState(controller: OnboardingWizardControllerLike): readonly OnboardingStep1CapabilityItem[] {
|
|
351
351
|
return controller.getCurrentCapabilities().map((capability) => ({
|
|
352
352
|
...capability,
|
|
353
353
|
selected: controller.toggleState.get(`capabilities.${capability.id}`) ?? capability.selected,
|
|
354
354
|
}));
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
-
export function hasExistingAccessState(controller:
|
|
357
|
+
export function hasExistingAccessState(controller: OnboardingWizardControllerLike): boolean {
|
|
358
358
|
const auth = controller.runtimeSnapshot?.auth.snapshot;
|
|
359
359
|
return controller.mode !== 'new'
|
|
360
360
|
|| (controller.runtimeSnapshot?.subscriptions.active.length ?? 0) > 0
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
type ExternalSurfaceSpec,
|
|
10
10
|
} from './onboarding-wizard-external-surfaces.ts';
|
|
11
11
|
import { countSelected, modelSelectionLabel, normalizeText } from './onboarding-wizard-helpers.ts';
|
|
12
|
-
import type {
|
|
12
|
+
import type { OnboardingWizardControllerLike } from './onboarding-wizard-types.ts';
|
|
13
13
|
import type { OnboardingWizardAcknowledgementFieldDefinition, OnboardingWizardActionFieldDefinition, OnboardingWizardChecklistFieldDefinition, OnboardingWizardExternalSurfaceStepId, OnboardingWizardFieldDefinition, OnboardingWizardModelPickerFieldDefinition, OnboardingWizardRadioFieldDefinition, OnboardingWizardRadioOption, OnboardingWizardStepDefinition } from './onboarding-wizard-types.ts';
|
|
14
14
|
|
|
15
|
-
export function buildOnboardingWizardSteps(controller:
|
|
15
|
+
export function buildOnboardingWizardSteps(controller: OnboardingWizardControllerLike): readonly OnboardingWizardStepDefinition[] {
|
|
16
16
|
if (controller.hydrationPending || controller.hydrationError !== null) return [buildLoadingStep(controller)];
|
|
17
17
|
|
|
18
18
|
const capabilities = controller.getCapabilitySelectionState();
|
|
@@ -48,8 +48,8 @@ function buildApplyAndContinueAction(step: OnboardingWizardStepDefinition): Onbo
|
|
|
48
48
|
kind: 'action',
|
|
49
49
|
id: `${step.id}.apply-and-continue`,
|
|
50
50
|
action: 'apply-and-continue',
|
|
51
|
-
label: '
|
|
52
|
-
hint: '
|
|
51
|
+
label: 'Next section',
|
|
52
|
+
hint: 'Selections are kept in this wizard session and persisted on the final Review apply.',
|
|
53
53
|
defaultValue: 'Apply & next',
|
|
54
54
|
spacerBeforeRows: 2,
|
|
55
55
|
};
|
|
@@ -66,7 +66,7 @@ function addApplyAndContinueAction(step: OnboardingWizardStepDefinition): Onboar
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
export function buildLoadingStep(controller:
|
|
69
|
+
export function buildLoadingStep(controller: OnboardingWizardControllerLike): OnboardingWizardStepDefinition {
|
|
70
70
|
const failed = controller.hydrationError !== null;
|
|
71
71
|
return {
|
|
72
72
|
id: 'loading',
|
|
@@ -98,7 +98,7 @@ export function buildLoadingStep(controller: OnboardingWizardController): Onboar
|
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
export function buildCapabilitiesStep(controller:
|
|
101
|
+
export function buildCapabilitiesStep(controller: OnboardingWizardControllerLike): OnboardingWizardStepDefinition {
|
|
102
102
|
const capabilities = controller.getCapabilitySelectionState();
|
|
103
103
|
const selectedCount = countSelected(capabilities);
|
|
104
104
|
const fields: OnboardingWizardFieldDefinition[] = [
|
|
@@ -145,7 +145,7 @@ export function buildCapabilitiesStep(controller: OnboardingWizardController): O
|
|
|
145
145
|
};
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
export function buildProvidersStep(controller:
|
|
148
|
+
export function buildProvidersStep(controller: OnboardingWizardControllerLike): OnboardingWizardStepDefinition {
|
|
149
149
|
const providerAck = controller.runtimeDerived.reopenEditAcknowledgements.providers;
|
|
150
150
|
const activeSubscriptions = controller.runtimeSnapshot?.subscriptions.active ?? [];
|
|
151
151
|
const pendingSubscriptions = controller.runtimeSnapshot?.subscriptions.pending ?? [];
|
|
@@ -250,11 +250,11 @@ export function buildProvidersStep(controller: OnboardingWizardController): Onbo
|
|
|
250
250
|
};
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
-
export function buildProviderAccessStep(controller:
|
|
253
|
+
export function buildProviderAccessStep(controller: OnboardingWizardControllerLike): OnboardingWizardStepDefinition {
|
|
254
254
|
return buildProvidersStep(controller);
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
export function buildDefaultModelStep(controller:
|
|
257
|
+
export function buildDefaultModelStep(controller: OnboardingWizardControllerLike): OnboardingWizardStepDefinition {
|
|
258
258
|
const routing = controller.runtimeSnapshot?.providerRouting;
|
|
259
259
|
const primarySelectionField: OnboardingWizardModelPickerFieldDefinition = {
|
|
260
260
|
kind: 'modelPicker',
|
|
@@ -294,7 +294,7 @@ export function buildDefaultModelStep(controller: OnboardingWizardController): O
|
|
|
294
294
|
};
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
-
export function buildExternalServicesStep(controller:
|
|
297
|
+
export function buildExternalServicesStep(controller: OnboardingWizardControllerLike): OnboardingWizardStepDefinition {
|
|
298
298
|
const selectedCount = EXTERNAL_SURFACE_SPECS
|
|
299
299
|
.filter((surface) => controller.getBooleanFieldValue(
|
|
300
300
|
surface.enabledFieldId,
|
|
@@ -355,7 +355,7 @@ export function buildExternalServicesStep(controller: OnboardingWizardController
|
|
|
355
355
|
};
|
|
356
356
|
}
|
|
357
357
|
|
|
358
|
-
function getSelectedExternalSurfaceSpecs(controller:
|
|
358
|
+
function getSelectedExternalSurfaceSpecs(controller: OnboardingWizardControllerLike): readonly ExternalSurfaceSpec[] {
|
|
359
359
|
return EXTERNAL_SURFACE_SPECS.filter((surface) => (
|
|
360
360
|
controller.getBooleanFieldValue(
|
|
361
361
|
surface.enabledFieldId,
|
|
@@ -378,7 +378,7 @@ const SURFACE_AUTO_START_OPTIONS: readonly OnboardingWizardRadioOption[] = [
|
|
|
378
378
|
];
|
|
379
379
|
|
|
380
380
|
function buildExternalSurfaceStep(
|
|
381
|
-
controller:
|
|
381
|
+
controller: OnboardingWizardControllerLike,
|
|
382
382
|
surface: ExternalSurfaceSpec,
|
|
383
383
|
): OnboardingWizardStepDefinition {
|
|
384
384
|
let setupCount = 0;
|
|
@@ -461,7 +461,7 @@ function buildExternalSurfaceStep(
|
|
|
461
461
|
};
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
-
export function buildAccessStep(controller:
|
|
464
|
+
export function buildAccessStep(controller: OnboardingWizardControllerLike): OnboardingWizardStepDefinition {
|
|
465
465
|
const step = buildAccountsStep(controller);
|
|
466
466
|
return {
|
|
467
467
|
...step,
|
|
@@ -471,7 +471,7 @@ export function buildAccessStep(controller: OnboardingWizardController): Onboard
|
|
|
471
471
|
};
|
|
472
472
|
}
|
|
473
473
|
|
|
474
|
-
export function buildExperienceStep(controller:
|
|
474
|
+
export function buildExperienceStep(controller: OnboardingWizardControllerLike): OnboardingWizardStepDefinition {
|
|
475
475
|
return {
|
|
476
476
|
id: 'experience',
|
|
477
477
|
title: 'Shell experience',
|
|
@@ -512,7 +512,7 @@ export function buildExperienceStep(controller: OnboardingWizardController): Onb
|
|
|
512
512
|
};
|
|
513
513
|
}
|
|
514
514
|
|
|
515
|
-
export function buildNetworkStep(controller:
|
|
515
|
+
export function buildNetworkStep(controller: OnboardingWizardControllerLike): OnboardingWizardStepDefinition {
|
|
516
516
|
const bindSettings = controller.runtimeSnapshot?.bindSettings;
|
|
517
517
|
const browserEnabled = controller.shouldEnableBrowserSurface();
|
|
518
518
|
const listenerEnabled = controller.shouldExposeHttpListenerNetworkFields();
|
|
@@ -636,7 +636,7 @@ export function buildNetworkStep(controller: OnboardingWizardController): Onboar
|
|
|
636
636
|
};
|
|
637
637
|
}
|
|
638
638
|
|
|
639
|
-
export function buildAccountsStep(controller:
|
|
639
|
+
export function buildAccountsStep(controller: OnboardingWizardControllerLike): OnboardingWizardStepDefinition {
|
|
640
640
|
const subscriptionsAck = controller.runtimeDerived.reopenEditAcknowledgements.subscriptions;
|
|
641
641
|
const authAck = controller.runtimeDerived.reopenEditAcknowledgements.auth;
|
|
642
642
|
const auth = controller.runtimeSnapshot?.auth.snapshot;
|
|
@@ -740,7 +740,7 @@ export function buildAccountsStep(controller: OnboardingWizardController): Onboa
|
|
|
740
740
|
};
|
|
741
741
|
}
|
|
742
742
|
|
|
743
|
-
export function buildReviewStep(controller:
|
|
743
|
+
export function buildReviewStep(controller: OnboardingWizardControllerLike): OnboardingWizardStepDefinition {
|
|
744
744
|
const feedback = controller.applyFeedback;
|
|
745
745
|
const feedbackFields: OnboardingWizardFieldDefinition[] = feedback
|
|
746
746
|
? [
|
|
@@ -778,19 +778,12 @@ export function buildReviewStep(controller: OnboardingWizardController): Onboard
|
|
|
778
778
|
],
|
|
779
779
|
fields: [
|
|
780
780
|
...feedbackFields,
|
|
781
|
-
{
|
|
782
|
-
kind: 'status',
|
|
783
|
-
id: 'review.global-marker',
|
|
784
|
-
label: 'Global onboarding check',
|
|
785
|
-
hint: 'Opening this wizard marks onboarding as shown for this user account, so new projects do not reopen it automatically.',
|
|
786
|
-
defaultValue: 'Already marked as shown',
|
|
787
|
-
},
|
|
788
781
|
{
|
|
789
782
|
kind: 'action',
|
|
790
783
|
id: 'review.apply',
|
|
791
784
|
action: 'apply',
|
|
792
785
|
label: 'Apply settings and verify',
|
|
793
|
-
hint: 'Persist the wizard settings and verify the resulting runtime state. The global onboarding check
|
|
786
|
+
hint: 'Persist the wizard settings and verify the resulting runtime state. The global onboarding check marker is recorded when apply succeeds.',
|
|
794
787
|
defaultValue: 'Ready',
|
|
795
788
|
},
|
|
796
789
|
],
|