@pellux/goodvibes-tui 0.19.26 → 0.19.28
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 +10 -0
- package/README.md +1 -1
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +2 -2
- package/src/cli/bundle-command.ts +3 -2
- package/src/cli/entrypoint.ts +2 -2
- package/src/cli/help.ts +1 -1
- package/src/cli/status.ts +9 -9
- package/src/cli/tui-startup.ts +4 -4
- package/src/input/handler-interactions.ts +14 -1
- package/src/input/handler-onboarding.ts +18 -82
- package/src/input/handler.ts +1 -1
- package/src/input/onboarding/handler-onboarding-routes.ts +31 -15
- package/src/input/onboarding/onboarding-wizard-apply.ts +0 -17
- package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -2
- package/src/input/onboarding/onboarding-wizard-rules.ts +18 -5
- package/src/input/onboarding/onboarding-wizard-state.ts +8 -2
- package/src/input/onboarding/onboarding-wizard-steps.ts +118 -59
- package/src/input/onboarding/onboarding-wizard-types.ts +5 -0
- package/src/input/onboarding/onboarding-wizard.ts +70 -5
- package/src/main.ts +2 -1
- package/src/renderer/onboarding/onboarding-wizard.ts +115 -48
- package/src/runtime/onboarding/apply.ts +9 -82
- package/src/runtime/onboarding/markers.ts +41 -55
- package/src/runtime/onboarding/state.ts +6 -6
- package/src/runtime/onboarding/types.ts +20 -26
- package/src/runtime/onboarding/verify.ts +2 -64
- package/src/version.ts +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { NETWORK_MODE_OPTIONS, REASONING_OPTIONS, HITL_MODE_OPTIONS, GUIDANCE_MODE_OPTIONS, PERMISSION_MODE_OPTIONS, SECRET_POLICY_OPTIONS } from './onboarding-wizard-constants.ts';
|
|
2
|
-
import { EXTERNAL_SURFACE_SPECS } from './onboarding-wizard-external-surfaces.ts';
|
|
2
|
+
import { EXTERNAL_SURFACE_SPECS, type ExternalSurfaceSpec } from './onboarding-wizard-external-surfaces.ts';
|
|
3
3
|
import { countSelected, modelSelectionLabel, normalizeText } from './onboarding-wizard-helpers.ts';
|
|
4
4
|
import type { OnboardingWizardController } from './onboarding-wizard.ts';
|
|
5
|
-
import type { OnboardingWizardAcknowledgementFieldDefinition, OnboardingWizardChecklistFieldDefinition, OnboardingWizardFieldDefinition, OnboardingWizardModelPickerFieldDefinition, OnboardingWizardRadioFieldDefinition, OnboardingWizardStepDefinition } from './onboarding-wizard-types.ts';
|
|
5
|
+
import type { OnboardingWizardAcknowledgementFieldDefinition, OnboardingWizardChecklistFieldDefinition, OnboardingWizardExternalSurfaceStepId, OnboardingWizardFieldDefinition, OnboardingWizardModelPickerFieldDefinition, OnboardingWizardRadioFieldDefinition, OnboardingWizardStepDefinition } from './onboarding-wizard-types.ts';
|
|
6
6
|
|
|
7
7
|
export function buildOnboardingWizardSteps(controller: OnboardingWizardController): readonly OnboardingWizardStepDefinition[] {
|
|
8
8
|
if (controller.hydrationPending || controller.hydrationError !== null) return [buildLoadingStep(controller)];
|
|
@@ -24,6 +24,9 @@ export function buildOnboardingWizardSteps(controller: OnboardingWizardControlle
|
|
|
24
24
|
|
|
25
25
|
if (wantsExternalServices) {
|
|
26
26
|
steps.push(buildExternalServicesStep(controller));
|
|
27
|
+
for (const surface of getSelectedExternalSurfaceSpecs(controller)) {
|
|
28
|
+
steps.push(buildExternalSurfaceStep(controller, surface));
|
|
29
|
+
}
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
steps.push(buildProviderAccessStep(controller));
|
|
@@ -98,9 +101,9 @@ export function buildCapabilitiesStep(controller: OnboardingWizardController): O
|
|
|
98
101
|
|
|
99
102
|
return {
|
|
100
103
|
id: 'capabilities',
|
|
101
|
-
title: '
|
|
104
|
+
title: 'Choose GoodVibes capabilities',
|
|
102
105
|
shortLabel: 'Capabilities',
|
|
103
|
-
description: '
|
|
106
|
+
description: 'Select one or more capabilities. Local TUI Only means no browser, daemon, listener, or network setup; any other choice turns on service mode and autostart.',
|
|
104
107
|
summaryTitle: 'Selected capabilities',
|
|
105
108
|
summaryLines: [
|
|
106
109
|
`${selectedCount}/${capabilities.length} option(s) selected`,
|
|
@@ -269,7 +272,6 @@ export function buildExternalServicesStep(controller: OnboardingWizardController
|
|
|
269
272
|
const fields: OnboardingWizardFieldDefinition[] = [];
|
|
270
273
|
|
|
271
274
|
for (const surface of EXTERNAL_SURFACE_SPECS) {
|
|
272
|
-
const enabled = controller.getBooleanFieldValue(surface.enabledFieldId, surface.defaultEnabled(controller.runtimeSnapshot));
|
|
273
275
|
fields.push({
|
|
274
276
|
kind: 'checklist',
|
|
275
277
|
id: surface.enabledFieldId,
|
|
@@ -277,54 +279,114 @@ export function buildExternalServicesStep(controller: OnboardingWizardController
|
|
|
277
279
|
hint: surface.hint,
|
|
278
280
|
defaultValue: surface.defaultEnabled(controller.runtimeSnapshot),
|
|
279
281
|
});
|
|
282
|
+
}
|
|
280
283
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
284
|
+
fields.push(
|
|
285
|
+
{
|
|
286
|
+
kind: 'action',
|
|
287
|
+
id: 'external-services.select-all',
|
|
288
|
+
action: 'select-all-external-surfaces',
|
|
289
|
+
label: 'Select all external surfaces',
|
|
290
|
+
hint: 'Enable every supported external surface so each one gets a setup screen.',
|
|
291
|
+
defaultValue: 'Action',
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
kind: 'action',
|
|
295
|
+
id: 'external-services.clear',
|
|
296
|
+
action: 'clear-external-surfaces',
|
|
297
|
+
label: 'Clear all external surfaces',
|
|
298
|
+
hint: 'Disable all external surfaces. The HTTP listener can still be enabled separately by webhook/event capabilities.',
|
|
299
|
+
defaultValue: 'Action',
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
kind: 'radio',
|
|
303
|
+
id: 'external-services.secret-policy',
|
|
304
|
+
label: 'Secret storage policy',
|
|
305
|
+
hint: 'Choose how selected surface secrets should be stored. Secret values are never shown in the wizard.',
|
|
306
|
+
options: SECRET_POLICY_OPTIONS,
|
|
307
|
+
defaultValue: controller.runtimeSnapshot?.runtimeDefaults.secretStoragePolicy ?? 'preferred_secure',
|
|
308
|
+
},
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
id: 'external-services',
|
|
313
|
+
title: 'Choose external surfaces',
|
|
314
|
+
shortLabel: 'Services',
|
|
315
|
+
description: 'Select the apps and integration surfaces GoodVibes should prepare. Setup fields are not shown here; each selected surface opens as its own screen.',
|
|
316
|
+
summaryTitle: 'External surfaces',
|
|
317
|
+
summaryLines: [
|
|
318
|
+
`${enabledCount} external surface(s) selected`,
|
|
319
|
+
`Secret policy: ${controller.getStringFieldValue('external-services.secret-policy', controller.runtimeSnapshot?.runtimeDefaults.secretStoragePolicy ?? 'preferred_secure')}`,
|
|
320
|
+
enabledCount > 0 ? 'Selected surfaces appear as separate setup screens.' : 'No external surfaces selected.',
|
|
321
|
+
],
|
|
322
|
+
fields,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function getSelectedExternalSurfaceSpecs(controller: OnboardingWizardController): readonly ExternalSurfaceSpec[] {
|
|
327
|
+
return EXTERNAL_SURFACE_SPECS.filter((surface) => (
|
|
328
|
+
controller.getBooleanFieldValue(surface.enabledFieldId, surface.defaultEnabled(controller.runtimeSnapshot))
|
|
329
|
+
));
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function buildExternalSurfaceStep(
|
|
333
|
+
controller: OnboardingWizardController,
|
|
334
|
+
surface: ExternalSurfaceSpec,
|
|
335
|
+
): OnboardingWizardStepDefinition {
|
|
336
|
+
let requiredCount = 0;
|
|
337
|
+
let requiredCompleteCount = 0;
|
|
338
|
+
const setupFields = surface.fields.map((setupField): OnboardingWizardFieldDefinition => {
|
|
339
|
+
const required = controller.isRequiredExternalSetupField(setupField.id);
|
|
340
|
+
if (required) {
|
|
341
|
+
requiredCount += 1;
|
|
342
|
+
if (normalizeText(setupField.defaultValue(controller.runtimeSnapshot)).length > 0
|
|
343
|
+
|| normalizeText(controller.getStringFieldValue(setupField.id, '')).length > 0) {
|
|
344
|
+
requiredCompleteCount += 1;
|
|
293
345
|
}
|
|
346
|
+
}
|
|
294
347
|
|
|
295
|
-
|
|
296
|
-
|
|
348
|
+
const hint = required
|
|
349
|
+
? `${setupField.hint} Required because ${surface.label} is selected.`
|
|
350
|
+
: setupField.hint;
|
|
351
|
+
|
|
352
|
+
if (setupField.kind === 'radio') {
|
|
353
|
+
return {
|
|
354
|
+
kind: 'radio',
|
|
297
355
|
id: setupField.id,
|
|
298
356
|
label: setupField.label,
|
|
299
|
-
hint
|
|
300
|
-
|
|
357
|
+
hint,
|
|
358
|
+
options: setupField.options ?? [],
|
|
301
359
|
defaultValue: setupField.defaultValue(controller.runtimeSnapshot),
|
|
302
|
-
|
|
303
|
-
});
|
|
360
|
+
};
|
|
304
361
|
}
|
|
305
|
-
}
|
|
306
362
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
363
|
+
return {
|
|
364
|
+
kind: setupField.kind,
|
|
365
|
+
id: setupField.id,
|
|
366
|
+
label: setupField.label,
|
|
367
|
+
hint,
|
|
368
|
+
placeholder: setupField.placeholder,
|
|
369
|
+
defaultValue: setupField.defaultValue(controller.runtimeSnapshot),
|
|
370
|
+
required,
|
|
371
|
+
};
|
|
314
372
|
});
|
|
373
|
+
const title = `${surface.label.replace(/ surface$/i, '')} setup`;
|
|
374
|
+
const requiredSummary = requiredCount === 0
|
|
375
|
+
? 'Required setup: none'
|
|
376
|
+
: `Required setup: ${requiredCompleteCount}/${requiredCount}`;
|
|
315
377
|
|
|
316
378
|
return {
|
|
317
|
-
id:
|
|
318
|
-
title
|
|
319
|
-
shortLabel: '
|
|
320
|
-
description:
|
|
321
|
-
summaryTitle:
|
|
379
|
+
id: `external-surface:${surface.id}` as OnboardingWizardExternalSurfaceStepId,
|
|
380
|
+
title,
|
|
381
|
+
shortLabel: surface.label.replace(/ surface$/i, ''),
|
|
382
|
+
description: `Configure ${surface.label}. This screen only appears because that surface is selected on the previous screen.`,
|
|
383
|
+
summaryTitle: `${surface.label} setup`,
|
|
322
384
|
summaryLines: [
|
|
323
|
-
|
|
385
|
+
requiredSummary,
|
|
324
386
|
`Secret policy: ${controller.getStringFieldValue('external-services.secret-policy', controller.runtimeSnapshot?.runtimeDefaults.secretStoragePolicy ?? 'preferred_secure')}`,
|
|
325
|
-
'
|
|
387
|
+
'Leave optional fields blank to keep defaults or existing values.',
|
|
326
388
|
],
|
|
327
|
-
fields,
|
|
389
|
+
fields: setupFields,
|
|
328
390
|
};
|
|
329
391
|
}
|
|
330
392
|
|
|
@@ -510,7 +572,7 @@ export function buildAccountsStep(controller: OnboardingWizardController): Onboa
|
|
|
510
572
|
const needsAuthBootstrap = controller.requiresAuthBootstrap();
|
|
511
573
|
const needsExistingAuthAcknowledgement = controller.hasServerCapabilitiesSelected()
|
|
512
574
|
&& !needsAuthBootstrap
|
|
513
|
-
&& controller.
|
|
575
|
+
&& controller.hasLocalAuthUser();
|
|
514
576
|
const fields: OnboardingWizardFieldDefinition[] = [];
|
|
515
577
|
|
|
516
578
|
if (needsAuthBootstrap) {
|
|
@@ -563,13 +625,17 @@ export function buildAccountsStep(controller: OnboardingWizardController): Onboa
|
|
|
563
625
|
{
|
|
564
626
|
kind: 'status',
|
|
565
627
|
id: 'accounts.bootstrap',
|
|
566
|
-
label: '
|
|
628
|
+
label: 'Local auth readiness',
|
|
567
629
|
hint: needsAuthBootstrap
|
|
568
630
|
? 'The wizard will create local auth before applying network-accessible settings.'
|
|
569
|
-
:
|
|
631
|
+
: controller.hasAdminAuthUser()
|
|
632
|
+
? 'An existing local auth admin user was detected and will be kept.'
|
|
633
|
+
: controller.hasLocalAuthUser()
|
|
634
|
+
? 'Existing local auth users were detected and will be kept.'
|
|
635
|
+
: 'No server-backed capability is selected, so local auth is not required.',
|
|
570
636
|
defaultValue: needsAuthBootstrap
|
|
571
637
|
? controller.hasBootstrapCredentialPresent() ? 'Bootstrap replacement required' : 'Local admin required'
|
|
572
|
-
:
|
|
638
|
+
: controller.hasAdminAuthUser() ? 'Admin detected' : controller.hasLocalAuthUser() ? 'Local auth detected' : 'Not required',
|
|
573
639
|
},
|
|
574
640
|
{
|
|
575
641
|
kind: 'status',
|
|
@@ -586,7 +652,7 @@ export function buildAccountsStep(controller: OnboardingWizardController): Onboa
|
|
|
586
652
|
shortLabel: 'Accounts',
|
|
587
653
|
description: needsAuthBootstrap
|
|
588
654
|
? 'Create wizard-owned local auth before any LAN, browser, service, or listener settings are applied.'
|
|
589
|
-
: '
|
|
655
|
+
: 'Review existing subscription and local auth state. Existing local auth is kept unless you change it elsewhere.',
|
|
590
656
|
summaryTitle: 'Stored account state',
|
|
591
657
|
summaryLines: [
|
|
592
658
|
`Subscriptions: ${controller.runtimeSnapshot?.subscriptions.active.length ?? 0} active / ${controller.runtimeSnapshot?.subscriptions.pending.length ?? 0} pending`,
|
|
@@ -595,7 +661,7 @@ export function buildAccountsStep(controller: OnboardingWizardController): Onboa
|
|
|
595
661
|
? controller.hasBootstrapCredentialPresent()
|
|
596
662
|
? 'Bootstrap credentials will be replaced before network settings are applied'
|
|
597
663
|
: 'Local admin will be created before network settings are applied'
|
|
598
|
-
:
|
|
664
|
+
: controller.hasLocalAuthUser() ? 'Existing local auth will be kept' : 'Local auth is not required for this setup',
|
|
599
665
|
],
|
|
600
666
|
fields,
|
|
601
667
|
};
|
|
@@ -604,7 +670,7 @@ export function buildAccountsStep(controller: OnboardingWizardController): Onboa
|
|
|
604
670
|
export function buildReviewStep(controller: OnboardingWizardController): OnboardingWizardStepDefinition {
|
|
605
671
|
return {
|
|
606
672
|
id: 'review',
|
|
607
|
-
title: 'Review and
|
|
673
|
+
title: 'Review and apply',
|
|
608
674
|
shortLabel: 'Review',
|
|
609
675
|
description: 'Review the selected settings and apply them directly from the wizard.',
|
|
610
676
|
summaryTitle: 'Review posture',
|
|
@@ -616,25 +682,18 @@ export function buildReviewStep(controller: OnboardingWizardController): Onboard
|
|
|
616
682
|
],
|
|
617
683
|
fields: [
|
|
618
684
|
{
|
|
619
|
-
kind: '
|
|
620
|
-
id: 'review.
|
|
621
|
-
label: '
|
|
622
|
-
hint: '
|
|
623
|
-
defaultValue:
|
|
624
|
-
},
|
|
625
|
-
{
|
|
626
|
-
kind: 'checklist',
|
|
627
|
-
id: 'review.user-marker',
|
|
628
|
-
label: 'Write user completion marker',
|
|
629
|
-
hint: 'User scope keeps the shell-level completion marker available outside this workspace.',
|
|
630
|
-
defaultValue: controller.defaultReviewUserMarker(),
|
|
685
|
+
kind: 'status',
|
|
686
|
+
id: 'review.global-marker',
|
|
687
|
+
label: 'Global onboarding check',
|
|
688
|
+
hint: 'Opening this wizard marks onboarding as shown for this user account, so new projects do not reopen it automatically.',
|
|
689
|
+
defaultValue: 'Already marked as shown',
|
|
631
690
|
},
|
|
632
691
|
{
|
|
633
692
|
kind: 'action',
|
|
634
693
|
id: 'review.apply',
|
|
635
694
|
action: 'apply',
|
|
636
695
|
label: 'Apply settings and verify',
|
|
637
|
-
hint: 'Persist the wizard settings
|
|
696
|
+
hint: 'Persist the wizard settings and verify the resulting runtime state. The global onboarding check was already recorded when the wizard opened.',
|
|
638
697
|
defaultValue: 'Ready',
|
|
639
698
|
},
|
|
640
699
|
],
|
|
@@ -16,12 +16,15 @@ import type { ConfigKey } from '../../config/index.ts';
|
|
|
16
16
|
|
|
17
17
|
export type OnboardingWizardMode = OnboardingMode;
|
|
18
18
|
|
|
19
|
+
export type OnboardingWizardExternalSurfaceStepId = `external-surface:${string}`;
|
|
20
|
+
|
|
19
21
|
export type OnboardingWizardStepId =
|
|
20
22
|
| 'loading'
|
|
21
23
|
| 'capabilities'
|
|
22
24
|
| 'network'
|
|
23
25
|
| 'access'
|
|
24
26
|
| 'external-services'
|
|
27
|
+
| OnboardingWizardExternalSurfaceStepId
|
|
25
28
|
| 'provider-access'
|
|
26
29
|
| 'default-model'
|
|
27
30
|
| 'experience'
|
|
@@ -41,6 +44,8 @@ export type OnboardingWizardAction =
|
|
|
41
44
|
| 'apply'
|
|
42
45
|
| 'select-all-capabilities'
|
|
43
46
|
| 'clear-capabilities'
|
|
47
|
+
| 'select-all-external-surfaces'
|
|
48
|
+
| 'clear-external-surfaces'
|
|
44
49
|
| 'start-openai-subscription'
|
|
45
50
|
| 'finish-openai-subscription';
|
|
46
51
|
|
|
@@ -4,11 +4,39 @@ import { STEP_ORDER } from './onboarding-wizard-constants.ts';
|
|
|
4
4
|
import { buildOnboardingApplyRequest } from './onboarding-wizard-apply.ts';
|
|
5
5
|
import { buildOnboardingWizardSteps } from './onboarding-wizard-steps.ts';
|
|
6
6
|
import { buildDefaultDerivedState, clamp, cloneSelection, getRuntimeDerivedState, maskValue, modelSelectionLabel, normalizeText } from './onboarding-wizard-helpers.ts';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
clearExternalSurfaces as clearExternalSurfacesForController,
|
|
9
|
+
getBooleanFieldValue as getBooleanFieldValueForController,
|
|
10
|
+
getDefaultAdminUsername as getDefaultAdminUsernameForController,
|
|
11
|
+
getNumberFieldValue as getNumberFieldValueForController,
|
|
12
|
+
getPortFieldValue as getPortFieldValueForController,
|
|
13
|
+
getSelectedSecretMedium as getSelectedSecretMediumForController,
|
|
14
|
+
getSharedIpDefault as getSharedIpDefaultForController,
|
|
15
|
+
getSharedIpHostDefault as getSharedIpHostDefaultForController,
|
|
16
|
+
getStringFieldValue as getStringFieldValueForController,
|
|
17
|
+
hasAdminAuthUser as hasAdminAuthUserForController,
|
|
18
|
+
hasBootstrapCredentialPresent as hasBootstrapCredentialPresentForController,
|
|
19
|
+
hasLocalAuthUser as hasLocalAuthUserForController,
|
|
20
|
+
hasSelectedInboundExternalSurface as hasSelectedInboundExternalSurfaceForController,
|
|
21
|
+
hasServerCapabilitiesSelected as hasServerCapabilitiesSelectedForController,
|
|
22
|
+
isCapabilitySelected as isCapabilitySelectedForController,
|
|
23
|
+
isRequiredExternalSetupField as isRequiredExternalSetupFieldForController,
|
|
24
|
+
parseIntegerFieldValue as parseIntegerFieldValueForController,
|
|
25
|
+
requiresAuthBootstrap as requiresAuthBootstrapForController,
|
|
26
|
+
selectAllExternalSurfaces as selectAllExternalSurfacesForController,
|
|
27
|
+
selectAllServerCapabilities as selectAllServerCapabilitiesForController,
|
|
28
|
+
selectLocalTuiOnly as selectLocalTuiOnlyForController,
|
|
29
|
+
setCapabilityValue as setCapabilityValueForController,
|
|
30
|
+
shouldEnableBrowserSurface as shouldEnableBrowserSurfaceForController,
|
|
31
|
+
shouldEnableHttpListener as shouldEnableHttpListenerForController,
|
|
32
|
+
shouldExposeControlPlaneNetwork as shouldExposeControlPlaneNetworkForController,
|
|
33
|
+
shouldExposeHttpListenerNetworkFields as shouldExposeHttpListenerNetworkFieldsForController,
|
|
34
|
+
toggleCapability as toggleCapabilityForController,
|
|
35
|
+
} from './onboarding-wizard-rules.ts';
|
|
8
36
|
import { ensureSelectionVisible as ensureSelectionVisibleForController, getBlockingFieldLabels as getBlockingFieldLabelsForController, getCapabilitySelectionState as getCapabilitySelectionStateForController, getCompletedFieldCount as getCompletedFieldCountForController, getCompletedToggleCount as getCompletedToggleCountForController, getCurrentCapabilities as getCurrentCapabilitiesForController, getFieldById as getFieldByIdForController, getFieldValidationError as getFieldValidationErrorForController, getStepFieldCount as getStepFieldCountForController, getToggleFieldCount as getToggleFieldCountForController, hasExistingAccessState as hasExistingAccessStateForController, isFieldDirty as isFieldDirtyForController, isFieldDirtyByDefinition as isFieldDirtyByDefinitionForController, isFieldSatisfied as isFieldSatisfiedForController, isStepDirty as isStepDirtyForController, recalculateDirtyState as recalculateDirtyStateForController, reconcileStateWithCurrentDefinitions as reconcileStateWithCurrentDefinitionsForController, reconcileStepCursor as reconcileStepCursorForController, resetValuesFromCurrentDefinitions as resetValuesFromCurrentDefinitionsForController } from './onboarding-wizard-state.ts';
|
|
9
37
|
import type { MutableModelSelectionMap, OnboardingWizardAction, OnboardingWizardFieldDefinition, OnboardingWizardFieldWindow, OnboardingWizardMode, OnboardingWizardModelSelection, OnboardingWizardRuntimeHydration, OnboardingWizardSnapshot, OnboardingWizardStepDefinition, OnboardingWizardStepId } from './onboarding-wizard-types.ts';
|
|
10
38
|
|
|
11
|
-
export type { OnboardingWizardAcknowledgementFieldDefinition, OnboardingWizardAction, OnboardingWizardActionFieldDefinition, OnboardingWizardChecklistFieldDefinition, OnboardingWizardFieldDefinition, OnboardingWizardFieldKind, OnboardingWizardFieldWindow, OnboardingWizardMaskedFieldDefinition, OnboardingWizardMode, OnboardingWizardModelPickerFieldDefinition, OnboardingWizardModelSelection, OnboardingWizardRadioFieldDefinition, OnboardingWizardRadioOption, OnboardingWizardRuntimeHydration, OnboardingWizardSnapshot, OnboardingWizardStatusFieldDefinition, OnboardingWizardStepDefinition, OnboardingWizardStepId, OnboardingWizardTextFieldDefinition } from './onboarding-wizard-types.ts';
|
|
39
|
+
export type { OnboardingWizardAcknowledgementFieldDefinition, OnboardingWizardAction, OnboardingWizardActionFieldDefinition, OnboardingWizardChecklistFieldDefinition, OnboardingWizardExternalSurfaceStepId, OnboardingWizardFieldDefinition, OnboardingWizardFieldKind, OnboardingWizardFieldWindow, OnboardingWizardMaskedFieldDefinition, OnboardingWizardMode, OnboardingWizardModelPickerFieldDefinition, OnboardingWizardModelSelection, OnboardingWizardRadioFieldDefinition, OnboardingWizardRadioOption, OnboardingWizardRuntimeHydration, OnboardingWizardSnapshot, OnboardingWizardStatusFieldDefinition, OnboardingWizardStepDefinition, OnboardingWizardStepId, OnboardingWizardTextFieldDefinition } from './onboarding-wizard-types.ts';
|
|
12
40
|
export { getOnboardingWizardBodyRows, getOnboardingWizardVisibleFieldCount } from './onboarding-wizard-helpers.ts';
|
|
13
41
|
|
|
14
42
|
export class OnboardingWizardController {
|
|
@@ -40,7 +68,9 @@ export class OnboardingWizardController {
|
|
|
40
68
|
public runtimeDerived: OnboardingStepDerivationState = buildDefaultDerivedState();
|
|
41
69
|
|
|
42
70
|
public get steps(): readonly OnboardingWizardStepDefinition[] {
|
|
43
|
-
|
|
71
|
+
const steps = buildOnboardingWizardSteps(this);
|
|
72
|
+
this.ensureNavigationStateLength(steps.length);
|
|
73
|
+
return steps;
|
|
44
74
|
}
|
|
45
75
|
|
|
46
76
|
public get currentStep(): OnboardingWizardStepDefinition {
|
|
@@ -59,6 +89,11 @@ export class OnboardingWizardController {
|
|
|
59
89
|
this.resetValuesFromCurrentDefinitions();
|
|
60
90
|
}
|
|
61
91
|
|
|
92
|
+
private ensureNavigationStateLength(stepCount: number): void {
|
|
93
|
+
while (this.scrollOffsets.length < stepCount) this.scrollOffsets.push(0);
|
|
94
|
+
while (this.selectedFieldIndices.length < stepCount) this.selectedFieldIndices.push(0);
|
|
95
|
+
}
|
|
96
|
+
|
|
62
97
|
public open(mode: OnboardingWizardMode = 'new'): void {
|
|
63
98
|
this.mode = mode;
|
|
64
99
|
this.active = true;
|
|
@@ -159,7 +194,9 @@ export class OnboardingWizardController {
|
|
|
159
194
|
this.dirtyStepIds.clear();
|
|
160
195
|
for (const stepId of snapshot.dirtyStepIds) this.dirtyStepIds.add(stepId);
|
|
161
196
|
|
|
162
|
-
|
|
197
|
+
const navigationLength = Math.max(this.steps.length, snapshot.scrollOffsets.length, this.scrollOffsets.length);
|
|
198
|
+
this.ensureNavigationStateLength(navigationLength);
|
|
199
|
+
for (let index = 0; index < navigationLength; index += 1) {
|
|
163
200
|
this.scrollOffsets[index] = snapshot.scrollOffsets[index] ?? 0;
|
|
164
201
|
this.selectedFieldIndices[index] = snapshot.selectedFieldIndices[index] ?? 0;
|
|
165
202
|
}
|
|
@@ -372,6 +409,22 @@ export class OnboardingWizardController {
|
|
|
372
409
|
return;
|
|
373
410
|
}
|
|
374
411
|
|
|
412
|
+
if (field.action === 'select-all-external-surfaces') {
|
|
413
|
+
this.selectAllExternalSurfaces();
|
|
414
|
+
this.pendingAction = null;
|
|
415
|
+
this.pendingModelPickerTarget = null;
|
|
416
|
+
this.recalculateDirtyState();
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (field.action === 'clear-external-surfaces') {
|
|
421
|
+
this.clearExternalSurfaces();
|
|
422
|
+
this.pendingAction = null;
|
|
423
|
+
this.pendingModelPickerTarget = null;
|
|
424
|
+
this.recalculateDirtyState();
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
|
|
375
428
|
this.pendingAction = field.action;
|
|
376
429
|
this.pendingModelPickerTarget = null;
|
|
377
430
|
return;
|
|
@@ -391,6 +444,14 @@ export class OnboardingWizardController {
|
|
|
391
444
|
this.editBuffer = this.textState.get(field.id) ?? field.defaultValue;
|
|
392
445
|
}
|
|
393
446
|
|
|
447
|
+
public beginSelectedTextInput(initialText: string): boolean {
|
|
448
|
+
const field = this.getSelectedField();
|
|
449
|
+
if (!field || (field.kind !== 'text' && field.kind !== 'masked')) return false;
|
|
450
|
+
this.beginEdit(field.id);
|
|
451
|
+
this.editBuffer = initialText;
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
|
|
394
455
|
public commitEdit(): void {
|
|
395
456
|
const fieldId = this.editingFieldId;
|
|
396
457
|
if (fieldId === null) return;
|
|
@@ -498,11 +559,13 @@ export class OnboardingWizardController {
|
|
|
498
559
|
|
|
499
560
|
if (field.kind === 'text') {
|
|
500
561
|
const value = normalizeText(this.getFieldValue(field) as string);
|
|
562
|
+
if (value.length === 0 && (field.required === true || this.isRequiredExternalSetupField(field.id))) return 'Missing';
|
|
501
563
|
return value.length > 0 ? value : field.placeholder;
|
|
502
564
|
}
|
|
503
565
|
|
|
504
566
|
if (field.kind === 'masked') {
|
|
505
567
|
const value = normalizeText(this.getFieldValue(field) as string);
|
|
568
|
+
if (value.length === 0 && (field.required === true || this.isRequiredExternalSetupField(field.id))) return 'Missing';
|
|
506
569
|
return value.length > 0 ? maskValue(value) : field.placeholder;
|
|
507
570
|
}
|
|
508
571
|
|
|
@@ -548,10 +611,11 @@ export class OnboardingWizardController {
|
|
|
548
611
|
return getSharedIpHostDefaultForController(this, enabled);
|
|
549
612
|
}
|
|
550
613
|
|
|
551
|
-
public defaultReviewUserMarker(): boolean { return defaultReviewUserMarkerForController(this); }
|
|
552
614
|
public toggleCapability(capabilityId: OnboardingStep1CapabilityId): void { toggleCapabilityForController(this, capabilityId); }
|
|
553
615
|
public selectAllServerCapabilities(): void { selectAllServerCapabilitiesForController(this); }
|
|
554
616
|
public selectLocalTuiOnly(): void { selectLocalTuiOnlyForController(this); }
|
|
617
|
+
public selectAllExternalSurfaces(): void { selectAllExternalSurfacesForController(this); }
|
|
618
|
+
public clearExternalSurfaces(): void { clearExternalSurfacesForController(this); }
|
|
555
619
|
public setCapabilityValue(capabilityId: OnboardingStep1CapabilityId, selected: boolean): void { setCapabilityValueForController(this, capabilityId, selected); }
|
|
556
620
|
public isCapabilitySelected(capabilityId: OnboardingStep1CapabilityId): boolean { return isCapabilitySelectedForController(this, capabilityId); }
|
|
557
621
|
public hasServerCapabilitiesSelected(): boolean { return hasServerCapabilitiesSelectedForController(this); }
|
|
@@ -564,6 +628,7 @@ export class OnboardingWizardController {
|
|
|
564
628
|
public shouldExposeControlPlaneNetwork(): boolean { return shouldExposeControlPlaneNetworkForController(this); }
|
|
565
629
|
public requiresAuthBootstrap(): boolean { return requiresAuthBootstrapForController(this); }
|
|
566
630
|
public hasAdminAuthUser(): boolean { return hasAdminAuthUserForController(this); }
|
|
631
|
+
public hasLocalAuthUser(): boolean { return hasLocalAuthUserForController(this); }
|
|
567
632
|
public hasBootstrapCredentialPresent(): boolean { return hasBootstrapCredentialPresentForController(this); }
|
|
568
633
|
public getDefaultAdminUsername(): string { return getDefaultAdminUsernameForController(this); }
|
|
569
634
|
public getBooleanFieldValue(fieldId: string, fallback: boolean): boolean { return getBooleanFieldValueForController(this, fieldId, fallback); }
|
package/src/main.ts
CHANGED
|
@@ -258,7 +258,8 @@ async function main() {
|
|
|
258
258
|
stdout.removeListener('resize', resizeHandler);
|
|
259
259
|
process.removeListener('SIGINT', sigintHandler);
|
|
260
260
|
process.removeListener('unhandledRejection', unhandledRejectionHandler);
|
|
261
|
-
|
|
261
|
+
const exitScreen = cli.flags.noAltScreen ? CLEAR_SCREEN : CLEAR_SCREEN + ALT_SCREEN_EXIT;
|
|
262
|
+
stdout.write(PASTE_DISABLE + KEYBOARD_EXT_DISABLE + MOUSE_DISABLE + CURSOR_SHOW + exitScreen);
|
|
262
263
|
stdin.setRawMode(false);
|
|
263
264
|
process.exit(0);
|
|
264
265
|
};
|