@pellux/goodvibes-agent 0.1.56 → 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 +14 -9
- package/README.md +3 -3
- package/docs/README.md +1 -1
- package/docs/getting-started.md +3 -3
- package/docs/release-and-publishing.md +2 -2
- package/package.json +1 -3
- 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,322 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CloudflareDaemonRouteError,
|
|
3
|
-
createCloudflareDaemonClient,
|
|
4
|
-
type CloudflareComponentSelection,
|
|
5
|
-
type CloudflareDaemonClient,
|
|
6
|
-
type CloudflareDiscoverResult,
|
|
7
|
-
type CloudflareTokenRequirementsResult,
|
|
8
|
-
type CloudflareValidateResult,
|
|
9
|
-
type CloudflareVerifyResult,
|
|
10
|
-
} from '../runtime/cloudflare-control-plane.ts';
|
|
11
|
-
import type { OnboardingVerificationItem } from '../runtime/onboarding/index.ts';
|
|
12
|
-
import type { InputHandler } from './handler.ts';
|
|
13
|
-
import type { OnboardingWizardAction, OnboardingWizardApplyFeedback } from './onboarding/onboarding-wizard.ts';
|
|
14
|
-
import {
|
|
15
|
-
buildCloudflareApiTokenRef,
|
|
16
|
-
getCloudflareBatchMode,
|
|
17
|
-
getCloudflareComponentSelection,
|
|
18
|
-
getCloudflareSetupSource,
|
|
19
|
-
shouldShowCloudflareStep,
|
|
20
|
-
} from './onboarding/onboarding-wizard-cloudflare.ts';
|
|
21
|
-
|
|
22
|
-
type CloudflareOnboardingAction = Extract<OnboardingWizardAction,
|
|
23
|
-
| 'cloudflare-token-requirements'
|
|
24
|
-
| 'cloudflare-create-operational-token'
|
|
25
|
-
| 'cloudflare-discover'
|
|
26
|
-
| 'cloudflare-validate'
|
|
27
|
-
| 'cloudflare-provision'
|
|
28
|
-
| 'cloudflare-verify'
|
|
29
|
-
| 'cloudflare-disable'
|
|
30
|
-
>;
|
|
31
|
-
|
|
32
|
-
function getCloudflareDaemonClientForHandler(handler: InputHandler): CloudflareDaemonClient {
|
|
33
|
-
return createCloudflareDaemonClient({
|
|
34
|
-
configManager: handler.uiServices.platform.configManager,
|
|
35
|
-
homeDirectory: handler.uiServices.environment.homeDirectory,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function normalizeCloudflareActionError(error: unknown): string {
|
|
40
|
-
if (error instanceof CloudflareDaemonRouteError) {
|
|
41
|
-
return `${error.message} (HTTP ${error.status}, ${error.code})`;
|
|
42
|
-
}
|
|
43
|
-
return error instanceof Error ? error.message : String(error);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function setCloudflareWizardStatusForHandler(
|
|
47
|
-
handler: InputHandler,
|
|
48
|
-
title: string,
|
|
49
|
-
lines: readonly string[],
|
|
50
|
-
severity: OnboardingWizardApplyFeedback['severity'] = 'info',
|
|
51
|
-
): void {
|
|
52
|
-
const message = [title, ...lines].filter((line) => line.length > 0).join('\n');
|
|
53
|
-
handler.onboardingWizard.textState.set('cloudflare.action-status', message);
|
|
54
|
-
handler.onboardingWizard.setApplyFeedback({
|
|
55
|
-
severity,
|
|
56
|
-
title,
|
|
57
|
-
summary: lines[0] ?? title,
|
|
58
|
-
messages: lines.length > 0 ? lines : [title],
|
|
59
|
-
});
|
|
60
|
-
const targetIndex = handler.onboardingWizard.steps.findIndex((step) => step.id === 'cloudflare');
|
|
61
|
-
if (targetIndex >= 0) handler.onboardingWizard.setStep(targetIndex);
|
|
62
|
-
handler.commandContext?.print?.(message);
|
|
63
|
-
handler.requestRender();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function formatCloudflareComponents(components: CloudflareComponentSelection): string {
|
|
67
|
-
const enabled = Object.entries(components)
|
|
68
|
-
.filter(([, selected]) => selected === true)
|
|
69
|
-
.map(([component]) => component);
|
|
70
|
-
return enabled.length > 0 ? enabled.join(', ') : 'none';
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function formatCloudflareRequirements(result: CloudflareTokenRequirementsResult): string[] {
|
|
74
|
-
const permissionLines = result.permissions.length > 0
|
|
75
|
-
? result.permissions.map((permission) => ` ${permission.scope}: ${permission.permission} (${permission.component}) - ${permission.reason}`)
|
|
76
|
-
: [' No permissions returned for the selected components.'];
|
|
77
|
-
return [
|
|
78
|
-
`components: ${formatCloudflareComponents(result.components)}`,
|
|
79
|
-
'required permissions:',
|
|
80
|
-
...permissionLines,
|
|
81
|
-
...(result.bootstrapToken.instructions.length > 0
|
|
82
|
-
? ['', 'bootstrap token instructions:', ...result.bootstrapToken.instructions.map((line) => ` ${line}`)]
|
|
83
|
-
: []),
|
|
84
|
-
];
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function formatCloudflareValidation(result: CloudflareValidateResult): string[] {
|
|
88
|
-
return [
|
|
89
|
-
`token: ${result.ok ? 'valid' : 'not valid'}`,
|
|
90
|
-
`source: ${result.tokenSource}`,
|
|
91
|
-
result.account
|
|
92
|
-
? `account: ${result.account.name} (${result.account.id})`
|
|
93
|
-
: 'account: not resolved',
|
|
94
|
-
];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function formatCloudflareDiscovery(result: CloudflareDiscoverResult): string[] {
|
|
98
|
-
return [
|
|
99
|
-
`token source: ${result.tokenSource}`,
|
|
100
|
-
`accounts: ${result.accounts.length}`,
|
|
101
|
-
`zones: ${result.zones.length}`,
|
|
102
|
-
`worker subdomain: ${result.workerSubdomain || 'not detected'}`,
|
|
103
|
-
`queues: ${result.queues?.length ?? 0}`,
|
|
104
|
-
`KV namespaces: ${result.kvNamespaces?.length ?? 0}`,
|
|
105
|
-
`R2 buckets: ${result.r2Buckets?.length ?? 0}`,
|
|
106
|
-
...(result.selectedAccount ? [`selected account: ${result.selectedAccount.name} (${result.selectedAccount.id})`] : []),
|
|
107
|
-
...(result.selectedZone ? [`selected zone: ${result.selectedZone.name} (${result.selectedZone.id})`] : []),
|
|
108
|
-
...result.warnings.map((warning) => `warning: ${warning}`),
|
|
109
|
-
];
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function formatCloudflareVerify(result: CloudflareVerifyResult): string[] {
|
|
113
|
-
return [
|
|
114
|
-
`worker health: ${result.workerHealth.ok ? 'ok' : 'failed'} (HTTP ${result.workerHealth.status})${result.workerHealth.error ? ` - ${result.workerHealth.error}` : ''}`,
|
|
115
|
-
...(result.daemonBatchProxy
|
|
116
|
-
? [`daemon batch proxy: ${result.daemonBatchProxy.ok ? 'ok' : 'failed'} (HTTP ${result.daemonBatchProxy.status})${result.daemonBatchProxy.error ? ` - ${result.daemonBatchProxy.error}` : ''}`]
|
|
117
|
-
: []),
|
|
118
|
-
];
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function getCloudflareBootstrapTokenFromWizard(handler: InputHandler): string {
|
|
122
|
-
const wizard = handler.onboardingWizard;
|
|
123
|
-
const setupSource = getCloudflareSetupSource(wizard);
|
|
124
|
-
if (setupSource === 'bootstrap-token') {
|
|
125
|
-
return wizard.getStringFieldValue('cloudflare.bootstrap-token', '');
|
|
126
|
-
}
|
|
127
|
-
if (setupSource === 'bootstrap-env') {
|
|
128
|
-
const envName = wizard.getStringFieldValue('cloudflare.bootstrap-env-name', 'GOODVIBES_CLOUDFLARE_BOOTSTRAP_TOKEN');
|
|
129
|
-
return process.env[envName] ?? '';
|
|
130
|
-
}
|
|
131
|
-
return '';
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function getCloudflareOperationalTokenFromWizard(handler: InputHandler): string {
|
|
135
|
-
const wizard = handler.onboardingWizard;
|
|
136
|
-
return getCloudflareSetupSource(wizard) === 'operational-token'
|
|
137
|
-
? wizard.getStringFieldValue('cloudflare.operational-token', '')
|
|
138
|
-
: '';
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function getCloudflareApiTokenRefFromWizard(handler: InputHandler): string {
|
|
142
|
-
const wizard = handler.onboardingWizard;
|
|
143
|
-
const setupSource = getCloudflareSetupSource(wizard);
|
|
144
|
-
if (setupSource === 'operational-env') {
|
|
145
|
-
return buildCloudflareApiTokenRef(wizard.getStringFieldValue('cloudflare.operational-env-name', 'CLOUDFLARE_API_TOKEN'));
|
|
146
|
-
}
|
|
147
|
-
return wizard.runtimeSnapshot?.config.cloudflare.apiTokenRef ?? '';
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function buildCloudflareDiscoveryInputForHandler(handler: InputHandler): Parameters<CloudflareDaemonClient['discover']>[0] {
|
|
151
|
-
const wizard = handler.onboardingWizard;
|
|
152
|
-
const accountId = wizard.getStringFieldValue('cloudflare.account-id', wizard.runtimeSnapshot?.config.cloudflare.accountId ?? '');
|
|
153
|
-
const zoneId = wizard.getStringFieldValue('cloudflare.zone-id', wizard.runtimeSnapshot?.config.cloudflare.zoneId ?? '');
|
|
154
|
-
const zoneName = wizard.getStringFieldValue('cloudflare.zone-name', wizard.runtimeSnapshot?.config.cloudflare.zoneName ?? '');
|
|
155
|
-
const bootstrapToken = getCloudflareBootstrapTokenFromWizard(handler);
|
|
156
|
-
const apiToken = getCloudflareOperationalTokenFromWizard(handler) || bootstrapToken;
|
|
157
|
-
const apiTokenRef = getCloudflareApiTokenRefFromWizard(handler);
|
|
158
|
-
return {
|
|
159
|
-
components: getCloudflareComponentSelection(wizard),
|
|
160
|
-
includeResources: true,
|
|
161
|
-
...(accountId ? { accountId } : {}),
|
|
162
|
-
...(zoneId ? { zoneId } : {}),
|
|
163
|
-
...(zoneName ? { zoneName } : {}),
|
|
164
|
-
...(apiToken ? { apiToken } : apiTokenRef ? { apiTokenRef } : {}),
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function blockedCloudflareMutationLines(action: CloudflareOnboardingAction): string[] {
|
|
169
|
-
switch (action) {
|
|
170
|
-
case 'cloudflare-create-operational-token':
|
|
171
|
-
return [
|
|
172
|
-
'Creating and storing Cloudflare tokens is a side-effecting operation.',
|
|
173
|
-
'Run /cloudflare create-token [flags] --yes from the main prompt when you explicitly want that mutation.',
|
|
174
|
-
];
|
|
175
|
-
case 'cloudflare-provision':
|
|
176
|
-
return [
|
|
177
|
-
'Provisioning creates or updates Cloudflare resources.',
|
|
178
|
-
'Run /cloudflare provision [flags] --yes from the main prompt when you explicitly want that mutation.',
|
|
179
|
-
];
|
|
180
|
-
case 'cloudflare-disable':
|
|
181
|
-
return [
|
|
182
|
-
'Disabling Cloudflare changes persisted daemon integration config.',
|
|
183
|
-
'Run /cloudflare disable [flags] --yes from the main prompt when you explicitly want that mutation.',
|
|
184
|
-
];
|
|
185
|
-
default:
|
|
186
|
-
return [];
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function isBlockedCloudflareMutation(action: CloudflareOnboardingAction): boolean {
|
|
191
|
-
return action === 'cloudflare-create-operational-token'
|
|
192
|
-
|| action === 'cloudflare-provision'
|
|
193
|
-
|| action === 'cloudflare-disable';
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function buildCloudflareValidateInputForHandler(handler: InputHandler): Parameters<CloudflareDaemonClient['validate']>[0] {
|
|
197
|
-
const wizard = handler.onboardingWizard;
|
|
198
|
-
const accountId = wizard.getStringFieldValue('cloudflare.account-id', wizard.runtimeSnapshot?.config.cloudflare.accountId ?? '');
|
|
199
|
-
const bootstrapToken = getCloudflareBootstrapTokenFromWizard(handler);
|
|
200
|
-
const apiToken = getCloudflareOperationalTokenFromWizard(handler) || bootstrapToken;
|
|
201
|
-
const apiTokenRef = getCloudflareApiTokenRefFromWizard(handler);
|
|
202
|
-
return {
|
|
203
|
-
...(accountId ? { accountId } : {}),
|
|
204
|
-
...(apiToken ? { apiToken } : apiTokenRef ? { apiTokenRef } : {}),
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export async function handleCloudflareOnboardingActionForHandler(
|
|
209
|
-
handler: InputHandler,
|
|
210
|
-
action: CloudflareOnboardingAction,
|
|
211
|
-
): Promise<void> {
|
|
212
|
-
if (handler.onboardingApplyPending) return;
|
|
213
|
-
handler.onboardingApplyPending = true;
|
|
214
|
-
handler.onboardingWizard.clearApplyFeedback();
|
|
215
|
-
handler.requestRender();
|
|
216
|
-
try {
|
|
217
|
-
if (isBlockedCloudflareMutation(action)) {
|
|
218
|
-
setCloudflareWizardStatusForHandler(
|
|
219
|
-
handler,
|
|
220
|
-
'Cloudflare mutation requires explicit command',
|
|
221
|
-
blockedCloudflareMutationLines(action),
|
|
222
|
-
'warning',
|
|
223
|
-
);
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const client = getCloudflareDaemonClientForHandler(handler);
|
|
228
|
-
if (action === 'cloudflare-token-requirements') {
|
|
229
|
-
const result = await client.tokenRequirements({
|
|
230
|
-
components: getCloudflareComponentSelection(handler.onboardingWizard),
|
|
231
|
-
includeBootstrap: true,
|
|
232
|
-
});
|
|
233
|
-
setCloudflareWizardStatusForHandler(handler, 'Cloudflare token requirements', formatCloudflareRequirements(result));
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (action === 'cloudflare-discover') {
|
|
238
|
-
const result = await client.discover(buildCloudflareDiscoveryInputForHandler(handler));
|
|
239
|
-
if (result.selectedAccount && !handler.onboardingWizard.getStringFieldValue('cloudflare.account-id', '')) {
|
|
240
|
-
handler.onboardingWizard.setFieldValue('cloudflare.account-id', result.selectedAccount.id);
|
|
241
|
-
} else if (result.accounts.length === 1 && !handler.onboardingWizard.getStringFieldValue('cloudflare.account-id', '')) {
|
|
242
|
-
handler.onboardingWizard.setFieldValue('cloudflare.account-id', result.accounts[0]!.id);
|
|
243
|
-
}
|
|
244
|
-
if (result.selectedZone && !handler.onboardingWizard.getStringFieldValue('cloudflare.zone-id', '')) {
|
|
245
|
-
handler.onboardingWizard.setFieldValue('cloudflare.zone-id', result.selectedZone.id);
|
|
246
|
-
handler.onboardingWizard.setFieldValue('cloudflare.zone-name', result.selectedZone.name);
|
|
247
|
-
} else if (result.zones.length === 1 && !handler.onboardingWizard.getStringFieldValue('cloudflare.zone-id', '')) {
|
|
248
|
-
handler.onboardingWizard.setFieldValue('cloudflare.zone-id', result.zones[0]!.id);
|
|
249
|
-
handler.onboardingWizard.setFieldValue('cloudflare.zone-name', result.zones[0]!.name);
|
|
250
|
-
}
|
|
251
|
-
if (result.workerSubdomain && !handler.onboardingWizard.getStringFieldValue('cloudflare.worker-subdomain', '')) {
|
|
252
|
-
handler.onboardingWizard.setFieldValue('cloudflare.worker-subdomain', result.workerSubdomain);
|
|
253
|
-
}
|
|
254
|
-
setCloudflareWizardStatusForHandler(handler, 'Cloudflare discovery completed', formatCloudflareDiscovery(result));
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
if (action === 'cloudflare-validate') {
|
|
259
|
-
const result = await client.validate(buildCloudflareValidateInputForHandler(handler));
|
|
260
|
-
setCloudflareWizardStatusForHandler(
|
|
261
|
-
handler,
|
|
262
|
-
result.ok ? 'Cloudflare token validated' : 'Cloudflare token validation needs attention',
|
|
263
|
-
formatCloudflareValidation(result),
|
|
264
|
-
result.ok ? 'info' : 'warning',
|
|
265
|
-
);
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (action === 'cloudflare-verify') {
|
|
270
|
-
const result = await client.verify({
|
|
271
|
-
workerBaseUrl: handler.onboardingWizard.getStringFieldValue('cloudflare.worker-base-url', handler.onboardingWizard.runtimeSnapshot?.config.cloudflare.workerBaseUrl ?? ''),
|
|
272
|
-
workerClientTokenRef: handler.onboardingWizard.runtimeSnapshot?.config.cloudflare.workerClientTokenRef ?? '',
|
|
273
|
-
});
|
|
274
|
-
setCloudflareWizardStatusForHandler(
|
|
275
|
-
handler,
|
|
276
|
-
result.ok ? 'Cloudflare Worker verified' : 'Cloudflare Worker verification needs attention',
|
|
277
|
-
formatCloudflareVerify(result),
|
|
278
|
-
result.ok ? 'info' : 'warning',
|
|
279
|
-
);
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
} catch (error) {
|
|
283
|
-
setCloudflareWizardStatusForHandler(handler, 'Cloudflare action failed', [normalizeCloudflareActionError(error)], 'error');
|
|
284
|
-
} finally {
|
|
285
|
-
handler.onboardingApplyPending = false;
|
|
286
|
-
handler.requestRender();
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
export async function maybeProvisionCloudflareOnFinalApplyForHandler(handler: InputHandler): Promise<readonly OnboardingVerificationItem[]> {
|
|
291
|
-
const wizard = handler.onboardingWizard;
|
|
292
|
-
if (!shouldShowCloudflareStep(wizard)) return [];
|
|
293
|
-
const cloudflareEnabled = wizard.getBooleanFieldValue('cloudflare.enabled', wizard.isCapabilitySelected('cloudflare-batch') || wizard.runtimeSnapshot?.config.cloudflare.enabled === true);
|
|
294
|
-
if (!cloudflareEnabled) {
|
|
295
|
-
return [{
|
|
296
|
-
id: 'cloudflare:disabled',
|
|
297
|
-
status: 'pass',
|
|
298
|
-
message: 'Cloudflare integration is disabled; local daemon behavior remains active.',
|
|
299
|
-
target: 'cloudflare',
|
|
300
|
-
}];
|
|
301
|
-
}
|
|
302
|
-
const provisionOnApply = wizard.getStringFieldValue('cloudflare.provision-on-apply', 'no') === 'yes';
|
|
303
|
-
if (!provisionOnApply) {
|
|
304
|
-
return [{
|
|
305
|
-
id: 'cloudflare:configuration-saved',
|
|
306
|
-
status: 'pass',
|
|
307
|
-
message: `Cloudflare settings were saved. Batch mode is ${getCloudflareBatchMode(wizard)}; provisioning was not requested on final apply.`,
|
|
308
|
-
target: 'cloudflare',
|
|
309
|
-
}];
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
handler.onboardingWizard.textState.set('cloudflare.action-status', [
|
|
313
|
-
'Cloudflare provisioning was not run during final apply.',
|
|
314
|
-
'GoodVibes Agent requires an explicit /cloudflare provision [flags] --yes command for Cloudflare resource mutations.',
|
|
315
|
-
].join('\n'));
|
|
316
|
-
return [{
|
|
317
|
-
id: 'cloudflare:provision',
|
|
318
|
-
status: 'warn',
|
|
319
|
-
message: 'Cloudflare settings were saved, but provisioning was blocked because Agent onboarding cannot create/update Cloudflare resources. Run /cloudflare provision [flags] --yes explicitly.',
|
|
320
|
-
target: 'cloudflare',
|
|
321
|
-
}];
|
|
322
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import type { HostServiceStatus } from '@/runtime/index.ts';
|
|
2
|
-
|
|
3
|
-
export interface OnboardingExternalServiceState {
|
|
4
|
-
readonly daemonRunning?: boolean;
|
|
5
|
-
readonly daemonPortInUse?: boolean;
|
|
6
|
-
readonly httpListenerRunning?: boolean;
|
|
7
|
-
readonly httpListenerPortInUse?: boolean;
|
|
8
|
-
readonly daemonStatus?: HostServiceStatus;
|
|
9
|
-
readonly httpListenerStatus?: HostServiceStatus;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type OnboardingRuntimeEndpoint = 'daemon' | 'httpListener';
|
|
13
|
-
|
|
14
|
-
export function runtimePortDiagnostic(
|
|
15
|
-
binding: { readonly label: string; readonly host: string; readonly port: number },
|
|
16
|
-
portInUse: boolean | undefined,
|
|
17
|
-
status?: HostServiceStatus,
|
|
18
|
-
): string {
|
|
19
|
-
if (status) {
|
|
20
|
-
const reason = status.reason ? ` ${status.reason}` : '';
|
|
21
|
-
if (status.mode === 'blocked') {
|
|
22
|
-
return `The configured endpoint ${status.baseUrl} is occupied but was not usable by this Agent instance.${reason}`;
|
|
23
|
-
}
|
|
24
|
-
if (status.mode === 'disabled') {
|
|
25
|
-
return `The configured endpoint ${status.baseUrl} is disabled in the runtime service configuration.${reason}`;
|
|
26
|
-
}
|
|
27
|
-
if (status.mode === 'unavailable') {
|
|
28
|
-
return `The configured endpoint ${status.baseUrl} is unavailable to Agent.${reason}`;
|
|
29
|
-
}
|
|
30
|
-
if (status.mode === 'external') {
|
|
31
|
-
const version = status.version ? ` version ${status.version}` : '';
|
|
32
|
-
return `An existing GoodVibes service was verified at ${status.baseUrl}${version}.`;
|
|
33
|
-
}
|
|
34
|
-
return `A GoodVibes service reports embedded mode at ${status.baseUrl}; Agent still treats daemon lifecycle as external.`;
|
|
35
|
-
}
|
|
36
|
-
if (portInUse) {
|
|
37
|
-
return `The configured port ${binding.host}:${binding.port} is occupied; another GoodVibes process or another service may own it.`;
|
|
38
|
-
}
|
|
39
|
-
return `No process is listening on ${binding.host}:${binding.port}.`;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function getRuntimeEndpointStatus(
|
|
43
|
-
state: OnboardingExternalServiceState | undefined,
|
|
44
|
-
endpoint: OnboardingRuntimeEndpoint,
|
|
45
|
-
): HostServiceStatus | undefined {
|
|
46
|
-
return endpoint === 'daemon' ? state?.daemonStatus : state?.httpListenerStatus;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function isRuntimeEndpointActive(
|
|
50
|
-
state: OnboardingExternalServiceState | undefined,
|
|
51
|
-
endpoint: OnboardingRuntimeEndpoint,
|
|
52
|
-
): boolean {
|
|
53
|
-
const status = getRuntimeEndpointStatus(state, endpoint);
|
|
54
|
-
if (status) return status.mode === 'embedded' || status.mode === 'external';
|
|
55
|
-
return endpoint === 'daemon'
|
|
56
|
-
? state?.daemonRunning === true
|
|
57
|
-
: state?.httpListenerRunning === true;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function isRuntimeEndpointOccupyingConfiguredPort(
|
|
61
|
-
state: OnboardingExternalServiceState | undefined,
|
|
62
|
-
endpoint: OnboardingRuntimeEndpoint,
|
|
63
|
-
): boolean {
|
|
64
|
-
const status = getRuntimeEndpointStatus(state, endpoint);
|
|
65
|
-
if (status) return status.mode === 'embedded' || status.mode === 'external' || status.mode === 'blocked';
|
|
66
|
-
return endpoint === 'daemon'
|
|
67
|
-
? state?.daemonRunning === true || state?.daemonPortInUse === true
|
|
68
|
-
: state?.httpListenerRunning === true || state?.httpListenerPortInUse === true;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function formatRuntimeActiveSuccessMessage(
|
|
72
|
-
endpoint: OnboardingRuntimeEndpoint,
|
|
73
|
-
state: OnboardingExternalServiceState | undefined,
|
|
74
|
-
): string {
|
|
75
|
-
const status = getRuntimeEndpointStatus(state, endpoint);
|
|
76
|
-
const label = endpoint === 'daemon' ? 'GoodVibes daemon' : 'HTTP listener';
|
|
77
|
-
if (status?.mode === 'external') {
|
|
78
|
-
const version = status.version ? ` version ${status.version}` : '';
|
|
79
|
-
return `${label} is already running as a verified external GoodVibes service at ${status.baseUrl}${version}.`;
|
|
80
|
-
}
|
|
81
|
-
if (status?.mode === 'embedded') {
|
|
82
|
-
return `${label} reports embedded mode at ${status.baseUrl}; Agent does not own that service lifecycle.`;
|
|
83
|
-
}
|
|
84
|
-
return endpoint === 'daemon'
|
|
85
|
-
? 'The GoodVibes daemon is reachable to Agent.'
|
|
86
|
-
: 'The HTTP listener is reachable to Agent.';
|
|
87
|
-
}
|