@pellux/goodvibes-agent 0.1.55 → 0.1.57
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/.goodvibes/GOODVIBES.md +1 -1
- package/CHANGELOG.md +19 -8
- package/README.md +10 -3
- package/docs/README.md +1 -1
- package/docs/getting-started.md +10 -3
- package/docs/release-and-publishing.md +12 -3
- package/package.json +1 -3
- package/scripts/check-bun.sh +5 -1
- package/src/agent/routine-schedule-args.ts +219 -0
- package/src/agent/routine-schedule-format.ts +173 -0
- package/src/agent/routine-schedule-promotion.ts +3 -811
- package/src/agent/routine-schedule-receipts.ts +502 -0
- package/src/cli/agent-knowledge-command.ts +6 -6
- package/src/cli/help.ts +3 -25
- package/src/cli/package-verification.ts +23 -16
- package/src/cli/redaction.ts +4 -1
- package/src/cli/routines-command.ts +10 -6
- package/src/cli/service-posture.ts +47 -280
- package/src/cli/status.ts +0 -1
- package/src/config/secret-config.ts +0 -2
- package/src/input/agent-workspace-categories.ts +219 -0
- package/src/input/agent-workspace-editors.ts +143 -0
- package/src/input/agent-workspace-snapshot.ts +265 -0
- package/src/input/agent-workspace-types.ts +142 -0
- package/src/input/agent-workspace.ts +22 -766
- package/src/input/commands/agent-runtime-profile-runtime.ts +1 -1
- package/src/input/commands/delegation-runtime.ts +1 -1
- package/src/input/commands/experience-runtime.ts +3 -4
- package/src/input/commands/guidance-runtime.ts +1 -2
- package/src/input/commands/health-runtime.ts +3 -65
- package/src/input/commands/knowledge.ts +7 -7
- package/src/input/commands/local-setup-review.ts +0 -61
- package/src/input/commands/local-setup-transfer.ts +0 -3
- package/src/input/commands/local-setup.ts +2 -15
- package/src/input/commands/planning-runtime.ts +4 -1
- package/src/input/commands/platform-access-runtime.ts +1 -10
- package/src/input/commands/platform-services-runtime.ts +0 -1
- package/src/input/commands/recall-query.ts +1 -1
- package/src/input/commands/routines-runtime.ts +10 -6
- package/src/input/commands/schedule-runtime.ts +10 -6
- package/src/input/commands/session-workflow.ts +1 -1
- package/src/input/commands/tasks-runtime.ts +1 -14
- package/src/input/commands.ts +0 -4
- package/src/input/handler-onboarding.ts +10 -120
- package/src/input/onboarding/onboarding-wizard-apply.ts +5 -196
- package/src/input/onboarding/onboarding-wizard-constants.ts +8 -119
- package/src/input/onboarding/onboarding-wizard-helpers.ts +2 -53
- package/src/input/onboarding/onboarding-wizard-rules.ts +2 -236
- package/src/input/onboarding/onboarding-wizard-state.ts +1 -69
- package/src/input/onboarding/onboarding-wizard-steps.ts +584 -737
- package/src/input/onboarding/onboarding-wizard-types.ts +8 -26
- package/src/input/onboarding/onboarding-wizard.ts +4 -109
- package/src/input/settings-modal-agent-policy.ts +10 -0
- package/src/input/settings-modal-types.ts +2 -4
- package/src/input/settings-modal.ts +3 -1
- package/src/input/submission-router.ts +0 -1
- package/src/panels/approval-panel.ts +1 -2
- package/src/panels/builtin/operations.ts +1 -2
- package/src/panels/knowledge-panel.ts +2 -2
- package/src/panels/project-planning-panel.ts +4 -1
- package/src/panels/provider-health-domains.ts +0 -22
- package/src/panels/provider-health-panel.ts +1 -5
- package/src/panels/session-browser-panel.ts +0 -5
- package/src/panels/tasks-panel.ts +2 -64
- package/src/renderer/agent-workspace.ts +1 -1
- package/src/renderer/help-overlay.ts +1 -2
- package/src/renderer/semantic-diff.ts +1 -1
- package/src/renderer/settings-modal-helpers.ts +0 -16
- package/src/renderer/settings-modal.ts +3 -5
- package/src/runtime/bootstrap-hook-bridge.ts +0 -3
- package/src/runtime/bootstrap-shell.ts +2 -1
- package/src/runtime/bootstrap.ts +1 -1
- package/src/runtime/index.ts +0 -1
- package/src/runtime/onboarding/derivation.ts +1 -28
- package/src/runtime/onboarding/snapshot.ts +0 -1
- package/src/runtime/onboarding/types.ts +1 -4
- package/src/runtime/services.ts +4 -23
- package/src/runtime/ui-read-models.ts +4 -3
- package/src/shell/service-settings-sync.ts +15 -244
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/wrfc-agent-guard.ts +3 -3
- package/src/verification/live-verifier.ts +11 -5
- package/src/verification/verification-ledger.ts +3 -6
- package/src/version.ts +1 -1
- package/src/input/commands/agent-externalized-tui.ts +0 -73
- package/src/input/commands/cloudflare-runtime.ts +0 -385
- package/src/input/handler-onboarding-cloudflare.ts +0 -322
- package/src/input/onboarding/onboarding-runtime-status.ts +0 -87
- package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +0 -494
- package/src/input/onboarding/onboarding-wizard-cloudflare.ts +0 -199
- package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +0 -130
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +0 -762
- package/src/runtime/cloudflare-control-plane.ts +0 -350
- package/src/runtime/sandbox-public-gaps.ts +0 -358
|
@@ -1,171 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { INBOUND_EXTERNAL_SURFACE_IDS, REQUIRED_EXTERNAL_SETUP_FIELD_IDS } from './onboarding-wizard-constants.ts';
|
|
3
|
-
import {
|
|
4
|
-
EXTERNAL_SURFACE_SPECS,
|
|
5
|
-
getExternalSurfaceAutoStartDefaultValue,
|
|
6
|
-
getExternalSurfaceAutoStartFieldId,
|
|
7
|
-
isExternalSurfaceSelectedByDefault,
|
|
8
|
-
} from './onboarding-wizard-external-surfaces.ts';
|
|
9
|
-
import { getExternalSurfaceSpecByFieldId, normalizeText, uniqueNonEmpty } from './onboarding-wizard-helpers.ts';
|
|
1
|
+
import { normalizeText } from './onboarding-wizard-helpers.ts';
|
|
10
2
|
import type { OnboardingWizardController } from './onboarding-wizard.ts';
|
|
11
3
|
|
|
12
|
-
export function getSharedIpDefault(
|
|
13
|
-
controller: OnboardingWizardController,
|
|
14
|
-
enabled: { readonly controlPlane: boolean; readonly httpListener: boolean; readonly web: boolean },
|
|
15
|
-
): boolean {
|
|
16
|
-
if (!controller.runtimeSnapshot) return true;
|
|
17
|
-
const hosts = uniqueNonEmpty([
|
|
18
|
-
enabled.controlPlane ? controller.runtimeSnapshot.bindSettings.controlPlane.host : '',
|
|
19
|
-
enabled.httpListener ? controller.runtimeSnapshot.bindSettings.httpListener.host : '',
|
|
20
|
-
enabled.web ? controller.runtimeSnapshot.bindSettings.web.host : '',
|
|
21
|
-
]);
|
|
22
|
-
return hosts.length <= 1;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function getSharedIpHostDefault(
|
|
26
|
-
controller: OnboardingWizardController,
|
|
27
|
-
enabled: { readonly controlPlane: boolean; readonly httpListener: boolean; readonly web: boolean },
|
|
28
|
-
): string {
|
|
29
|
-
if (!controller.runtimeSnapshot) return '0.0.0.0';
|
|
30
|
-
const hosts = uniqueNonEmpty([
|
|
31
|
-
enabled.controlPlane ? controller.runtimeSnapshot.bindSettings.controlPlane.host : '',
|
|
32
|
-
enabled.httpListener ? controller.runtimeSnapshot.bindSettings.httpListener.host : '',
|
|
33
|
-
enabled.web ? controller.runtimeSnapshot.bindSettings.web.host : '',
|
|
34
|
-
]);
|
|
35
|
-
return hosts[0] ?? '0.0.0.0';
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function toggleCapability(controller: OnboardingWizardController, capabilityId: OnboardingStep1CapabilityId): void {
|
|
39
|
-
if (capabilityId === 'local-tui-only') {
|
|
40
|
-
for (const capability of controller.getCurrentCapabilities()) {
|
|
41
|
-
controller.toggleState.set(`capabilities.${capability.id}`, capability.id === 'local-tui-only');
|
|
42
|
-
}
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const fieldId = `capabilities.${capabilityId}`;
|
|
47
|
-
const nextValue = !(controller.toggleState.get(fieldId) ?? false);
|
|
48
|
-
controller.toggleState.set(fieldId, nextValue);
|
|
49
|
-
if (nextValue) {
|
|
50
|
-
controller.toggleState.set('capabilities.local-tui-only', false);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const anyServerCapability = controller.getCurrentCapabilities().some((capability) => (
|
|
55
|
-
capability.id !== 'local-tui-only'
|
|
56
|
-
&& (controller.toggleState.get(`capabilities.${capability.id}`) ?? false)
|
|
57
|
-
));
|
|
58
|
-
if (!anyServerCapability) controller.toggleState.set('capabilities.local-tui-only', true);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function selectAllServerCapabilities(controller: OnboardingWizardController): void {
|
|
62
|
-
for (const capability of controller.getCurrentCapabilities()) {
|
|
63
|
-
controller.toggleState.set(`capabilities.${capability.id}`, capability.id !== 'local-tui-only');
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function selectLocalTuiOnly(controller: OnboardingWizardController): void {
|
|
68
|
-
for (const capability of controller.getCurrentCapabilities()) {
|
|
69
|
-
controller.toggleState.set(`capabilities.${capability.id}`, capability.id === 'local-tui-only');
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function selectAllExternalSurfaces(controller: OnboardingWizardController): void {
|
|
74
|
-
for (const surface of EXTERNAL_SURFACE_SPECS) {
|
|
75
|
-
controller.toggleState.set(surface.enabledFieldId, true);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function clearExternalSurfaces(controller: OnboardingWizardController): void {
|
|
80
|
-
for (const surface of EXTERNAL_SURFACE_SPECS) {
|
|
81
|
-
controller.toggleState.set(surface.enabledFieldId, false);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function setCapabilityValue(controller: OnboardingWizardController, capabilityId: OnboardingStep1CapabilityId, selected: boolean): void {
|
|
86
|
-
if (capabilityId === 'local-tui-only') {
|
|
87
|
-
if (selected) {
|
|
88
|
-
for (const capability of controller.getCurrentCapabilities()) {
|
|
89
|
-
controller.toggleState.set(`capabilities.${capability.id}`, capability.id === 'local-tui-only');
|
|
90
|
-
}
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const anyServerCapability = controller.getCurrentCapabilities().some((capability) => (
|
|
95
|
-
capability.id !== 'local-tui-only'
|
|
96
|
-
&& (controller.toggleState.get(`capabilities.${capability.id}`) ?? false)
|
|
97
|
-
));
|
|
98
|
-
controller.toggleState.set('capabilities.local-tui-only', !anyServerCapability);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
controller.toggleState.set(`capabilities.${capabilityId}`, selected);
|
|
103
|
-
if (selected) {
|
|
104
|
-
controller.toggleState.set('capabilities.local-tui-only', false);
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const anyServerCapability = controller.getCurrentCapabilities().some((capability) => (
|
|
109
|
-
capability.id !== 'local-tui-only'
|
|
110
|
-
&& (controller.toggleState.get(`capabilities.${capability.id}`) ?? false)
|
|
111
|
-
));
|
|
112
|
-
if (!anyServerCapability) controller.toggleState.set('capabilities.local-tui-only', true);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export function isCapabilitySelected(controller: OnboardingWizardController, capabilityId: OnboardingStep1CapabilityId): boolean {
|
|
116
|
-
return controller.getCapabilitySelectionState().some((capability) => capability.id === capabilityId && capability.selected);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function hasServerCapabilitiesSelected(controller: OnboardingWizardController): boolean {
|
|
120
|
-
return controller.getCapabilitySelectionState().some((capability) => capability.id !== 'local-tui-only' && capability.selected);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export function shouldEnableBrowserSurface(controller: OnboardingWizardController): boolean {
|
|
124
|
-
return controller.hasServerCapabilitiesSelected()
|
|
125
|
-
&& (controller.isCapabilitySelected('browser-access') || controller.isCapabilitySelected('network-access'));
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function hasSelectedInboundExternalSurface(controller: OnboardingWizardController): boolean {
|
|
129
|
-
if (!controller.isCapabilitySelected('external-integrations')) return false;
|
|
130
|
-
return EXTERNAL_SURFACE_SPECS.some((surface) => (
|
|
131
|
-
INBOUND_EXTERNAL_SURFACE_IDS.has(surface.id)
|
|
132
|
-
&& controller.getBooleanFieldValue(
|
|
133
|
-
surface.enabledFieldId,
|
|
134
|
-
isExternalSurfaceSelectedByDefault(surface, controller.runtimeSnapshot),
|
|
135
|
-
)
|
|
136
|
-
&& controller.getStringFieldValue(
|
|
137
|
-
getExternalSurfaceAutoStartFieldId(surface),
|
|
138
|
-
getExternalSurfaceAutoStartDefaultValue(surface, controller.runtimeSnapshot),
|
|
139
|
-
) === 'yes'
|
|
140
|
-
));
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export function isRequiredExternalSetupField(controller: OnboardingWizardController, fieldId: string): boolean {
|
|
144
|
-
if (!REQUIRED_EXTERNAL_SETUP_FIELD_IDS.has(fieldId)) return false;
|
|
145
|
-
const surface = getExternalSurfaceSpecByFieldId(fieldId);
|
|
146
|
-
if (!surface) return false;
|
|
147
|
-
if (!controller.isCapabilitySelected('external-integrations')
|
|
148
|
-
|| !controller.getBooleanFieldValue(
|
|
149
|
-
surface.enabledFieldId,
|
|
150
|
-
isExternalSurfaceSelectedByDefault(surface, controller.runtimeSnapshot),
|
|
151
|
-
)) {
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
if (fieldId === 'external-services.telegram.webhook-secret') {
|
|
155
|
-
return controller.getStringFieldValue('external-services.telegram.mode', 'webhook') === 'webhook';
|
|
156
|
-
}
|
|
157
|
-
if (
|
|
158
|
-
fieldId === 'external-services.whatsapp.verify-token'
|
|
159
|
-
|| fieldId === 'external-services.whatsapp.phone-number-id'
|
|
160
|
-
) {
|
|
161
|
-
return controller.getStringFieldValue('external-services.whatsapp.provider', 'meta-cloud') === 'meta-cloud';
|
|
162
|
-
}
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
4
|
export function getSelectedSecretMedium(controller: OnboardingWizardController): 'secure' | 'plaintext' {
|
|
167
5
|
const policy = controller.getStringFieldValue(
|
|
168
|
-
'
|
|
6
|
+
'agent-setup.secret-policy',
|
|
169
7
|
controller.runtimeSnapshot?.runtimeDefaults.secretStoragePolicy ?? 'preferred_secure',
|
|
170
8
|
);
|
|
171
9
|
if (policy === 'require_secure') return 'secure';
|
|
@@ -174,57 +12,6 @@ export function getSelectedSecretMedium(controller: OnboardingWizardController):
|
|
|
174
12
|
return 'plaintext';
|
|
175
13
|
}
|
|
176
14
|
|
|
177
|
-
export function shouldEnableHttpListener(controller: OnboardingWizardController): boolean {
|
|
178
|
-
return controller.hasServerCapabilitiesSelected()
|
|
179
|
-
&& (controller.isCapabilitySelected('webhook-events') || controller.hasSelectedInboundExternalSurface());
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export function shouldExposeHttpListenerNetworkFields(controller: OnboardingWizardController): boolean {
|
|
183
|
-
return controller.hasServerCapabilitiesSelected()
|
|
184
|
-
&& (
|
|
185
|
-
controller.isCapabilitySelected('webhook-events')
|
|
186
|
-
|| controller.isCapabilitySelected('external-integrations')
|
|
187
|
-
|| controller.hasSelectedInboundExternalSurface()
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export function shouldExposeControlPlaneNetwork(controller: OnboardingWizardController): boolean {
|
|
192
|
-
return controller.hasServerCapabilitiesSelected()
|
|
193
|
-
&& (controller.isCapabilitySelected('browser-access') || controller.isCapabilitySelected('network-access'));
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export function requiresAuthBootstrap(controller: OnboardingWizardController): boolean {
|
|
197
|
-
return controller.hasServerCapabilitiesSelected()
|
|
198
|
-
&& (!controller.hasLocalAuthUser() || controller.hasBootstrapCredentialPresent());
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export function hasAdminAuthUser(controller: OnboardingWizardController): boolean {
|
|
202
|
-
return (controller.runtimeSnapshot?.auth.snapshot.users ?? [])
|
|
203
|
-
.some((user) => user.roles.includes('admin'));
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export function hasLocalAuthUser(controller: OnboardingWizardController): boolean {
|
|
207
|
-
return (controller.runtimeSnapshot?.auth.snapshot.userCount ?? 0) > 0
|
|
208
|
-
|| (controller.runtimeSnapshot?.auth.snapshot.users ?? []).length > 0;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
export function hasBootstrapCredentialPresent(controller: OnboardingWizardController): boolean {
|
|
212
|
-
return controller.runtimeSnapshot?.auth.snapshot.bootstrapCredentialPresent === true;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
export function getDefaultAdminUsername(controller: OnboardingWizardController): string {
|
|
216
|
-
const users = controller.runtimeSnapshot?.auth.snapshot.users ?? [];
|
|
217
|
-
if (controller.hasBootstrapCredentialPresent()) {
|
|
218
|
-
const existingAdmin = users.find((user) => user.roles.includes('admin'));
|
|
219
|
-
if (existingAdmin) return existingAdmin.username;
|
|
220
|
-
}
|
|
221
|
-
const candidates = controller.hasBootstrapCredentialPresent()
|
|
222
|
-
? ['goodvibes-admin', 'admin']
|
|
223
|
-
: ['admin', 'goodvibes-admin'];
|
|
224
|
-
const candidate = candidates.find((username) => !users.some((user) => user.username === username));
|
|
225
|
-
return candidate ?? `goodvibes-admin-${users.length + 1}`;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
15
|
export function getBooleanFieldValue(controller: OnboardingWizardController, fieldId: string, fallback: boolean): boolean {
|
|
229
16
|
return controller.toggleState.get(fieldId) ?? fallback;
|
|
230
17
|
}
|
|
@@ -233,24 +20,3 @@ export function getStringFieldValue(controller: OnboardingWizardController, fiel
|
|
|
233
20
|
const value = controller.textState.get(fieldId) ?? controller.radioState.get(fieldId);
|
|
234
21
|
return normalizeText(value ?? fallback);
|
|
235
22
|
}
|
|
236
|
-
|
|
237
|
-
export function parseIntegerFieldValue(controller: OnboardingWizardController, fieldId: string, fallback: number): number | null {
|
|
238
|
-
const raw = controller.getStringFieldValue(fieldId, String(fallback));
|
|
239
|
-
if (!/^-?\d+$/.test(raw)) return null;
|
|
240
|
-
const parsed = Number.parseInt(raw, 10);
|
|
241
|
-
return Number.isInteger(parsed) ? parsed : null;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export function getPortFieldValue(controller: OnboardingWizardController, fieldId: string, fallback: number): number {
|
|
245
|
-
const parsed = controller.parseIntegerFieldValue(fieldId, fallback);
|
|
246
|
-
if (parsed === null || parsed < 1 || parsed > 65535) return fallback;
|
|
247
|
-
return parsed;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
export function getNumberFieldValue(controller: OnboardingWizardController, fieldId: string, fallback: number, min?: number, max?: number): number {
|
|
251
|
-
const parsed = controller.parseIntegerFieldValue(fieldId, fallback);
|
|
252
|
-
if (parsed === null) return fallback;
|
|
253
|
-
if (min !== undefined && parsed < min) return fallback;
|
|
254
|
-
if (max !== undefined && parsed > max) return fallback;
|
|
255
|
-
return parsed;
|
|
256
|
-
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { ModelPickerTarget } from '../model-picker.ts';
|
|
2
|
-
import
|
|
3
|
-
import { DEFAULT_CAPABILITIES, NETWORK_HOST_FIELD_IDS } from './onboarding-wizard-constants.ts';
|
|
4
|
-
import { areSelectionsEqual, clamp, cloneSelection, getExternalSurfaceSetupFieldSpec, isMalformedGoodVibesSecretReferenceValue, isValidHostValue, normalizeText } from './onboarding-wizard-helpers.ts';
|
|
2
|
+
import { areSelectionsEqual, clamp, cloneSelection, isMalformedGoodVibesSecretReferenceValue, normalizeText } from './onboarding-wizard-helpers.ts';
|
|
5
3
|
import type { OnboardingWizardController } from './onboarding-wizard.ts';
|
|
6
4
|
import type { OnboardingWizardFieldDefinition, OnboardingWizardModelSelection, OnboardingWizardStepDefinition } from './onboarding-wizard-types.ts';
|
|
7
5
|
|
|
@@ -77,53 +75,10 @@ export function getFieldValidationError(
|
|
|
77
75
|
return `${step.shortLabel}: ${field.label} is required.`;
|
|
78
76
|
}
|
|
79
77
|
|
|
80
|
-
if (field.id === 'accounts.admin-username') {
|
|
81
|
-
const password = normalizeText(controller.getStringFieldValue('accounts.admin-password', ''));
|
|
82
|
-
if (!required && password.length > 0 && value.length === 0) {
|
|
83
|
-
return `${step.shortLabel}: ${field.label} is required when setting a local auth password.`;
|
|
84
|
-
}
|
|
85
|
-
const existing = controller.runtimeSnapshot?.auth.snapshot.users.find((user) => user.username === value);
|
|
86
|
-
if ((required || password.length > 0) && existing && !existing.roles.includes('admin')) {
|
|
87
|
-
return `${step.shortLabel}: ${field.label} must be an existing admin user or a new username.`;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (field.id === 'accounts.admin-password' && value.length > 0 && value.length < 8) {
|
|
92
|
-
return `${step.shortLabel}: ${field.label} must be at least 8 characters.`;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
78
|
if (field.kind === 'masked' && isMalformedGoodVibesSecretReferenceValue(value)) {
|
|
96
79
|
return `${step.shortLabel}: ${field.label} must be a secret value or a goodvibes://secrets/... reference.`;
|
|
97
80
|
}
|
|
98
81
|
|
|
99
|
-
if (NETWORK_HOST_FIELD_IDS.has(field.id)) {
|
|
100
|
-
if (!isValidHostValue(value)) {
|
|
101
|
-
return `${step.shortLabel}: ${field.label} must be a host or IP address, not a URL.`;
|
|
102
|
-
}
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (field.id === 'network.service-port' || field.id === 'network.browser-port' || field.id === 'network.webhook-port') {
|
|
107
|
-
const parsed = controller.parseIntegerFieldValue(field.id, Number.parseInt(field.defaultValue, 10));
|
|
108
|
-
if (parsed === null || parsed < 1 || parsed > 65535) {
|
|
109
|
-
return `${step.shortLabel}: ${field.label} must be a port number from 1 to 65535.`;
|
|
110
|
-
}
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (field.kind !== 'text') return null;
|
|
115
|
-
const setupField = getExternalSurfaceSetupFieldSpec(field.id);
|
|
116
|
-
if (setupField?.valueType !== 'number') return null;
|
|
117
|
-
const parsed = controller.parseIntegerFieldValue(field.id, Number.parseInt(field.defaultValue, 10));
|
|
118
|
-
if (parsed === null) {
|
|
119
|
-
return `${step.shortLabel}: ${field.label} must be a number.`;
|
|
120
|
-
}
|
|
121
|
-
if (setupField.min !== undefined && parsed < setupField.min) {
|
|
122
|
-
return `${step.shortLabel}: ${field.label} must be at least ${setupField.min}.`;
|
|
123
|
-
}
|
|
124
|
-
if (setupField.max !== undefined && parsed > setupField.max) {
|
|
125
|
-
return `${step.shortLabel}: ${field.label} must be at most ${setupField.max}.`;
|
|
126
|
-
}
|
|
127
82
|
return null;
|
|
128
83
|
}
|
|
129
84
|
|
|
@@ -340,26 +295,3 @@ export function isFieldSatisfied(controller: OnboardingWizardController, field:
|
|
|
340
295
|
const selection = controller.getFieldValue(field) as OnboardingWizardModelSelection;
|
|
341
296
|
return selection.providerId.length > 0 || selection.modelId.length > 0;
|
|
342
297
|
}
|
|
343
|
-
|
|
344
|
-
export function getCurrentCapabilities(controller: OnboardingWizardController): readonly OnboardingStep1CapabilityItem[] {
|
|
345
|
-
return controller.runtimeDerived.step1Capabilities.length > 0
|
|
346
|
-
? controller.runtimeDerived.step1Capabilities
|
|
347
|
-
: DEFAULT_CAPABILITIES;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
export function getCapabilitySelectionState(controller: OnboardingWizardController): readonly OnboardingStep1CapabilityItem[] {
|
|
351
|
-
return controller.getCurrentCapabilities().map((capability) => ({
|
|
352
|
-
...capability,
|
|
353
|
-
selected: controller.toggleState.get(`capabilities.${capability.id}`) ?? capability.selected,
|
|
354
|
-
}));
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
export function hasExistingAccessState(controller: OnboardingWizardController): boolean {
|
|
358
|
-
const auth = controller.runtimeSnapshot?.auth.snapshot;
|
|
359
|
-
return controller.mode !== 'new'
|
|
360
|
-
|| (controller.runtimeSnapshot?.subscriptions.active.length ?? 0) > 0
|
|
361
|
-
|| (controller.runtimeSnapshot?.subscriptions.pending.length ?? 0) > 0
|
|
362
|
-
|| (auth?.userCount ?? 0) > 0
|
|
363
|
-
|| (auth?.sessionCount ?? 0) > 0
|
|
364
|
-
|| Boolean(auth?.bootstrapCredentialPresent);
|
|
365
|
-
}
|