@pellux/goodvibes-agent 0.1.114 → 0.1.117
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 +41 -650
- package/README.md +40 -50
- package/dist/package/main.js +38224 -35673
- package/docs/README.md +5 -4
- package/docs/{connected-services.md → connected-host.md} +18 -10
- package/docs/getting-started.md +43 -42
- package/docs/release-and-publishing.md +6 -4
- package/package.json +3 -3
- package/src/agent/behavior-discovery-summary.ts +165 -0
- package/src/agent/persona-discovery.ts +1 -3
- package/src/agent/persona-registry.ts +5 -3
- package/src/agent/reminder-schedule-format.ts +6 -6
- package/src/agent/reminder-schedule.ts +1 -1
- package/src/agent/routine-registry.ts +43 -4
- package/src/agent/routine-schedule-format.ts +6 -6
- package/src/agent/routine-schedule-promotion.ts +1 -1
- package/src/agent/routine-schedule-receipts.ts +1 -1
- package/src/agent/runtime-profile-starters.ts +331 -0
- package/src/agent/runtime-profile.ts +228 -330
- package/src/agent/skill-registry.ts +190 -13
- package/src/cli/agent-knowledge-command.ts +2 -2
- package/src/cli/agent-knowledge-format.ts +2 -2
- package/src/cli/agent-knowledge-runtime.ts +1 -1
- package/src/cli/bundle-command.ts +1 -1
- package/src/cli/entrypoint.ts +16 -7
- package/src/cli/help.ts +26 -19
- package/src/cli/local-library-command.ts +75 -21
- package/src/cli/management-commands.ts +7 -6
- package/src/cli/management.ts +6 -51
- package/src/cli/parser.ts +23 -2
- package/src/cli/profiles-command.ts +247 -1
- package/src/cli/routines-command.ts +139 -11
- package/src/cli/service-posture.ts +11 -11
- package/src/cli/status.ts +21 -25
- package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
- package/src/input/agent-workspace-access-command-editors.ts +170 -0
- package/src/input/agent-workspace-activation.ts +2 -1
- package/src/input/agent-workspace-basic-command-editor-submission.ts +787 -0
- package/src/input/agent-workspace-basic-command-editors.ts +524 -459
- package/src/input/agent-workspace-categories.ts +177 -14
- package/src/input/agent-workspace-channel-command-editor-submission.ts +49 -0
- package/src/input/agent-workspace-channel-command-editors.ts +47 -0
- package/src/input/agent-workspace-command-editor.ts +25 -1
- package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
- package/src/input/agent-workspace-editors.ts +27 -0
- package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
- package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
- package/src/input/agent-workspace-learned-behavior.ts +67 -0
- package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
- package/src/input/agent-workspace-library-command-editors.ts +35 -0
- package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
- package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
- package/src/input/agent-workspace-memory-command-editors.ts +180 -0
- package/src/input/agent-workspace-navigation.ts +45 -0
- package/src/input/agent-workspace-notify-editor-submission.ts +107 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +146 -0
- package/src/input/agent-workspace-operations-command-editors.ts +119 -0
- package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
- package/src/input/agent-workspace-provider-command-editors.ts +93 -0
- package/src/input/agent-workspace-requirements.ts +11 -0
- package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
- package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
- package/src/input/agent-workspace-session-command-editors.ts +249 -0
- package/src/input/agent-workspace-setup.ts +49 -19
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
- package/src/input/agent-workspace-snapshot.ts +56 -8
- package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
- package/src/input/agent-workspace-task-command-editors.ts +47 -0
- package/src/input/agent-workspace-types.ts +124 -0
- package/src/input/agent-workspace-voice-media.ts +1 -1
- package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
- package/src/input/agent-workspace.ts +47 -37
- package/src/input/command-registry.ts +1 -1
- package/src/input/commands/agent-runtime-profile-runtime.ts +160 -6
- package/src/input/commands/agent-skills-runtime.ts +76 -12
- package/src/input/commands/agent-workspace-runtime.ts +4 -3
- package/src/input/commands/brief-runtime.ts +38 -9
- package/src/input/commands/channels-runtime.ts +3 -3
- package/src/input/commands/compat-runtime.ts +32 -0
- package/src/input/commands/health-runtime.ts +22 -24
- package/src/input/commands/knowledge.ts +26 -5
- package/src/input/commands/local-provider-runtime.ts +7 -3
- package/src/input/commands/local-setup-review.ts +4 -14
- package/src/input/commands/mcp-runtime.ts +8 -12
- package/src/input/commands/operator-runtime.ts +8 -67
- package/src/input/commands/personas-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +7 -70
- package/src/input/commands/policy-dispatch.ts +1 -1
- package/src/input/commands/policy.ts +1 -5
- package/src/input/commands/product-runtime.ts +2 -2
- package/src/input/commands/qrcode-runtime.ts +6 -4
- package/src/input/commands/routines-runtime.ts +44 -6
- package/src/input/commands/runtime-services.ts +1 -14
- package/src/input/commands/security-runtime.ts +3 -8
- package/src/input/commands/session-content.ts +1 -1
- package/src/input/commands/session-workflow.ts +5 -14
- package/src/input/commands/shell-core.ts +8 -2
- package/src/input/commands/subscription-runtime.ts +1 -6
- package/src/input/commands/support-bundle-runtime.ts +53 -0
- package/src/input/commands/tasks-runtime.ts +2 -2
- package/src/input/commands.ts +4 -0
- package/src/input/feed-context-factory.ts +0 -1
- package/src/input/handler-content-actions.ts +0 -25
- package/src/input/handler-feed.ts +0 -2
- package/src/input/handler-interactions.ts +2 -31
- package/src/input/handler-onboarding.ts +29 -12
- package/src/input/handler-shortcuts.ts +1 -3
- package/src/input/handler.ts +4 -7
- package/src/input/keybindings.ts +9 -9
- package/src/input/mcp-workspace.ts +90 -26
- package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
- package/src/input/onboarding/onboarding-wizard-apply.ts +49 -0
- package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +126 -11
- package/src/input/onboarding/onboarding-wizard-steps.ts +15 -8
- package/src/input/onboarding/onboarding-wizard-types.ts +1 -0
- package/src/input/onboarding/onboarding-wizard.ts +19 -2
- package/src/input/profile-picker-modal.ts +2 -2
- package/src/input/settings-modal-agent-policy.ts +6 -6
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal.ts +14 -14
- package/src/main.ts +0 -2
- package/src/panels/automation-control-panel.ts +3 -3
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +2 -2
- package/src/panels/builtin/session.ts +26 -18
- package/src/panels/builtin/shared.ts +6 -6
- package/src/panels/project-planning-panel.ts +1 -1
- package/src/panels/provider-health-domains.ts +3 -3
- package/src/panels/qr-panel.ts +44 -20
- package/src/panels/subscription-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +2 -2
- package/src/panels/tasks-panel.ts +4 -4
- package/src/planning/project-planning-coordinator.ts +2 -2
- package/src/renderer/agent-workspace.ts +52 -5
- package/src/renderer/block-actions.ts +1 -3
- package/src/renderer/help-overlay.ts +13 -8
- package/src/renderer/mcp-workspace.ts +32 -13
- package/src/renderer/model-picker-overlay.ts +0 -1
- package/src/renderer/model-workspace.ts +0 -2
- package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
- package/src/renderer/panel-picker-overlay.ts +1 -1
- package/src/renderer/profile-picker-modal.ts +2 -2
- package/src/renderer/settings-modal-helpers.ts +23 -23
- package/src/renderer/settings-modal.ts +18 -18
- package/src/renderer/system-message.ts +1 -1
- package/src/runtime/agent-runtime-events.ts +129 -0
- package/src/runtime/bootstrap-command-parts.ts +3 -2
- package/src/runtime/bootstrap-core.ts +4 -64
- package/src/runtime/bootstrap-shell.ts +42 -4
- package/src/runtime/bootstrap.ts +8 -27
- package/src/runtime/connected-host-auth.ts +42 -0
- package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
- package/src/runtime/index.ts +1 -5
- package/src/runtime/onboarding/apply.ts +213 -0
- package/src/runtime/onboarding/derivation.ts +25 -6
- package/src/runtime/onboarding/snapshot.ts +4 -2
- package/src/runtime/onboarding/types.ts +28 -1
- package/src/runtime/onboarding/verify.ts +81 -2
- package/src/runtime/operator-token-cleanup.ts +2 -2
- package/src/runtime/services.ts +27 -12
- package/src/shell/service-settings-sync.ts +7 -7
- package/src/shell/ui-openers.ts +27 -38
- package/src/tools/agent-local-registry-tool.ts +10 -4
- package/src/tools/agent-tool-policy-guard.ts +5 -7
- package/src/version.ts +1 -1
- package/src/cli/package-verification.ts +0 -274
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createAgentRuntimeProfile,
|
|
3
|
+
createAgentRuntimeProfileFromDiscovered,
|
|
4
|
+
createAgentRuntimeProfileTemplateFromDiscovered,
|
|
5
|
+
clearAgentRuntimeProfileSelection,
|
|
3
6
|
deleteAgentRuntimeProfile,
|
|
4
7
|
exportAgentRuntimeProfileTemplate,
|
|
5
8
|
importAgentRuntimeProfileTemplate,
|
|
6
9
|
isAgentRuntimeProfileTemplateId,
|
|
7
10
|
listAgentRuntimeProfiles,
|
|
8
11
|
listAgentRuntimeProfileTemplates,
|
|
12
|
+
readAgentRuntimeProfileSelection,
|
|
9
13
|
resolveAgentRuntimeProfileHome,
|
|
14
|
+
setAgentRuntimeProfileSelection,
|
|
10
15
|
type AgentRuntimeProfileTemplateId,
|
|
11
16
|
type AgentRuntimeProfileCommandResult,
|
|
12
17
|
type AgentRuntimeProfileInfo,
|
|
@@ -16,6 +21,7 @@ import type { CliCommandOutput, GoodVibesCliParseResult } from './types.ts';
|
|
|
16
21
|
interface ProfilesCommandRuntime {
|
|
17
22
|
readonly cli: GoodVibesCliParseResult;
|
|
18
23
|
readonly homeDirectory: string;
|
|
24
|
+
readonly workingDirectory: string;
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
function hasYes(args: readonly string[]): boolean {
|
|
@@ -53,6 +59,12 @@ function parseTemplate(args: readonly string[]): AgentRuntimeProfileTemplateId |
|
|
|
53
59
|
throw new Error(`Unknown Agent starter profile template: ${raw}. Use profiles templates to list starters.`);
|
|
54
60
|
}
|
|
55
61
|
|
|
62
|
+
function parseCsvFlag(args: readonly string[], names: readonly string[]): readonly string[] | undefined {
|
|
63
|
+
const raw = flagValue(args, names);
|
|
64
|
+
if (!raw) return undefined;
|
|
65
|
+
return raw.split(',').map((entry) => entry.trim()).filter(Boolean);
|
|
66
|
+
}
|
|
67
|
+
|
|
56
68
|
function profileLine(profile: AgentRuntimeProfileInfo): string {
|
|
57
69
|
const created = profile.createdAt ? ` created=${profile.createdAt}` : '';
|
|
58
70
|
const starter = profile.starterTemplateId ? ` starter=${profile.starterTemplateId}` : '';
|
|
@@ -99,6 +111,41 @@ function renderProfilesResult(result: AgentRuntimeProfileCommandResult): string
|
|
|
99
111
|
` use: goodvibes-agent profiles create <name> --template ${result.data.template.id} --yes`,
|
|
100
112
|
].join('\n');
|
|
101
113
|
}
|
|
114
|
+
if (result.kind === 'agent.profiles.template.from_discovered' && result.data?.template) {
|
|
115
|
+
return [
|
|
116
|
+
`Agent starter template created from discovered behavior: ${result.data.template.id}`,
|
|
117
|
+
` name: ${result.data.template.name}`,
|
|
118
|
+
` persona: ${result.data.template.personaName}`,
|
|
119
|
+
` skills: ${result.data.template.skillNames.join(', ')}`,
|
|
120
|
+
` routines: ${result.data.template.routineNames.join(', ')}`,
|
|
121
|
+
` use: goodvibes-agent profiles create <name> --template ${result.data.template.id} --yes`,
|
|
122
|
+
].join('\n');
|
|
123
|
+
}
|
|
124
|
+
if (result.kind === 'agent.profiles.default') {
|
|
125
|
+
const selected = result.data?.selectedProfile;
|
|
126
|
+
if (!selected) return 'No default Agent profile selected. Use: goodvibes-agent profiles use <name> --yes';
|
|
127
|
+
return [
|
|
128
|
+
`Default Agent profile: ${selected.id}${selected.exists ? '' : ' (missing)'}`,
|
|
129
|
+
` home: ${selected.homeDirectory}`,
|
|
130
|
+
selected.selectedAt ? ` selectedAt: ${selected.selectedAt}` : '',
|
|
131
|
+
` next launch: ${result.data?.nextCommand ?? 'goodvibes-agent'}`,
|
|
132
|
+
selected.exists ? '' : ' fix: create the profile again or clear it with goodvibes-agent profiles default clear --yes',
|
|
133
|
+
].filter(Boolean).join('\n');
|
|
134
|
+
}
|
|
135
|
+
if (result.kind === 'agent.profiles.default.clear') {
|
|
136
|
+
return 'Default Agent profile cleared. Next launch uses the base Agent home unless --agent-profile is provided.';
|
|
137
|
+
}
|
|
138
|
+
if (result.kind === 'agent.profiles.create_from_discovered' && result.data?.profile && result.data.template) {
|
|
139
|
+
return [
|
|
140
|
+
`Agent profile created from discovered behavior: ${result.data.profile.id}`,
|
|
141
|
+
` home: ${result.data.profile.homeDirectory}`,
|
|
142
|
+
` starter: ${result.data.template.id}`,
|
|
143
|
+
` persona: ${result.data.template.personaName}`,
|
|
144
|
+
` skills: ${result.data.template.skillNames.join(', ')}`,
|
|
145
|
+
` routines: ${result.data.template.routineNames.join(', ')}`,
|
|
146
|
+
` launch: ${result.data.nextCommand ?? `goodvibes-agent --agent-profile ${result.data.profile.id}`}`,
|
|
147
|
+
].join('\n');
|
|
148
|
+
}
|
|
102
149
|
const profile = result.data?.profile;
|
|
103
150
|
if (result.kind === 'agent.profiles.create' && profile) {
|
|
104
151
|
const template = result.data?.appliedTemplate;
|
|
@@ -142,6 +189,51 @@ export async function handleProfilesCommand(runtime: ProfilesCommandRuntime): Pr
|
|
|
142
189
|
|
|
143
190
|
if (sub === 'templates' || sub === 'starters') {
|
|
144
191
|
const [templateAction, templateId, templatePath] = values;
|
|
192
|
+
if (templateAction === 'from-discovered' || templateAction === 'import-discovered') {
|
|
193
|
+
if (!templateId) {
|
|
194
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
195
|
+
ok: false,
|
|
196
|
+
kind: 'agent.profiles.error',
|
|
197
|
+
error: 'Usage: goodvibes-agent profiles templates from-discovered <id> [--name <name>] [--description <summary>] [--persona <name>] [--skills all|name,name] [--routines all|name,name] [--replace] --yes',
|
|
198
|
+
};
|
|
199
|
+
return {
|
|
200
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
201
|
+
exitCode: 2,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
if (!hasYes(rawRest)) {
|
|
205
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
206
|
+
ok: false,
|
|
207
|
+
kind: 'agent.profiles.error',
|
|
208
|
+
error: `Refusing to create Agent starter template ${templateId} from discovered behavior without --yes.`,
|
|
209
|
+
};
|
|
210
|
+
return {
|
|
211
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
212
|
+
exitCode: 2,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const template = await createAgentRuntimeProfileTemplateFromDiscovered({
|
|
216
|
+
homeDirectory: runtime.homeDirectory,
|
|
217
|
+
workingDirectory: runtime.workingDirectory,
|
|
218
|
+
}, {
|
|
219
|
+
id: templateId,
|
|
220
|
+
name: flagValue(rawRest, ['--name']) ?? undefined,
|
|
221
|
+
description: flagValue(rawRest, ['--description']) ?? undefined,
|
|
222
|
+
persona: flagValue(rawRest, ['--persona']) ?? undefined,
|
|
223
|
+
skills: parseCsvFlag(rawRest, ['--skills']),
|
|
224
|
+
routines: parseCsvFlag(rawRest, ['--routines']),
|
|
225
|
+
replace: hasYes(rawRest) && rawRest.includes('--replace'),
|
|
226
|
+
});
|
|
227
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
228
|
+
ok: true,
|
|
229
|
+
kind: 'agent.profiles.template.from_discovered',
|
|
230
|
+
data: { template },
|
|
231
|
+
};
|
|
232
|
+
return {
|
|
233
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
234
|
+
exitCode: 0,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
145
237
|
if (templateAction === 'export') {
|
|
146
238
|
if (!templateId || !templatePath) {
|
|
147
239
|
const result: AgentRuntimeProfileCommandResult = {
|
|
@@ -221,6 +313,107 @@ export async function handleProfilesCommand(runtime: ProfilesCommandRuntime): Pr
|
|
|
221
313
|
};
|
|
222
314
|
}
|
|
223
315
|
|
|
316
|
+
if (sub === 'default') {
|
|
317
|
+
const target = values[0];
|
|
318
|
+
if (target === 'clear' || target === 'none' || target === 'base') {
|
|
319
|
+
if (!hasYes(rawRest)) {
|
|
320
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
321
|
+
ok: false,
|
|
322
|
+
kind: 'agent.profiles.error',
|
|
323
|
+
error: 'Refusing to clear the default Agent profile without --yes.',
|
|
324
|
+
};
|
|
325
|
+
return {
|
|
326
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
327
|
+
exitCode: 2,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
clearAgentRuntimeProfileSelection(runtime.homeDirectory);
|
|
331
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
332
|
+
ok: true,
|
|
333
|
+
kind: 'agent.profiles.default.clear',
|
|
334
|
+
};
|
|
335
|
+
return {
|
|
336
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
337
|
+
exitCode: 0,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
if (target) {
|
|
341
|
+
if (!hasYes(rawRest)) {
|
|
342
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
343
|
+
ok: false,
|
|
344
|
+
kind: 'agent.profiles.error',
|
|
345
|
+
error: `Refusing to set default Agent profile ${target} without --yes.`,
|
|
346
|
+
};
|
|
347
|
+
return {
|
|
348
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
349
|
+
exitCode: 2,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
const selected = setAgentRuntimeProfileSelection(runtime.homeDirectory, target);
|
|
353
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
354
|
+
ok: true,
|
|
355
|
+
kind: 'agent.profiles.default',
|
|
356
|
+
data: {
|
|
357
|
+
selectedProfile: selected,
|
|
358
|
+
nextCommand: 'goodvibes-agent',
|
|
359
|
+
},
|
|
360
|
+
};
|
|
361
|
+
return {
|
|
362
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
363
|
+
exitCode: 0,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
const selected = readAgentRuntimeProfileSelection(runtime.homeDirectory);
|
|
367
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
368
|
+
ok: true,
|
|
369
|
+
kind: 'agent.profiles.default',
|
|
370
|
+
data: selected ? { selectedProfile: selected, nextCommand: 'goodvibes-agent' } : undefined,
|
|
371
|
+
};
|
|
372
|
+
return {
|
|
373
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
374
|
+
exitCode: 0,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (sub === 'use' || sub === 'select' || sub === 'switch') {
|
|
379
|
+
const name = values[0];
|
|
380
|
+
if (!name) {
|
|
381
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
382
|
+
ok: false,
|
|
383
|
+
kind: 'agent.profiles.error',
|
|
384
|
+
error: 'Usage: goodvibes-agent profiles use <name> --yes',
|
|
385
|
+
};
|
|
386
|
+
return {
|
|
387
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
388
|
+
exitCode: 2,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
if (!hasYes(rawRest)) {
|
|
392
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
393
|
+
ok: false,
|
|
394
|
+
kind: 'agent.profiles.error',
|
|
395
|
+
error: `Refusing to set default Agent profile ${name} without --yes.`,
|
|
396
|
+
};
|
|
397
|
+
return {
|
|
398
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
399
|
+
exitCode: 2,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
const selected = setAgentRuntimeProfileSelection(runtime.homeDirectory, name);
|
|
403
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
404
|
+
ok: true,
|
|
405
|
+
kind: 'agent.profiles.default',
|
|
406
|
+
data: {
|
|
407
|
+
selectedProfile: selected,
|
|
408
|
+
nextCommand: 'goodvibes-agent',
|
|
409
|
+
},
|
|
410
|
+
};
|
|
411
|
+
return {
|
|
412
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
413
|
+
exitCode: 0,
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
224
417
|
if (sub === 'show' || sub === 'path' || sub === 'home') {
|
|
225
418
|
const name = values[0];
|
|
226
419
|
if (!name) {
|
|
@@ -290,6 +483,59 @@ export async function handleProfilesCommand(runtime: ProfilesCommandRuntime): Pr
|
|
|
290
483
|
};
|
|
291
484
|
}
|
|
292
485
|
|
|
486
|
+
if (sub === 'create-from-discovered' || sub === 'create-discovered') {
|
|
487
|
+
const name = values[0];
|
|
488
|
+
if (!name) {
|
|
489
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
490
|
+
ok: false,
|
|
491
|
+
kind: 'agent.profiles.error',
|
|
492
|
+
error: 'Usage: goodvibes-agent profiles create-from-discovered <name> [--template-id <id>] [--profile-name <display>] [--description <summary>] [--persona <name>] [--skills all|name,name] [--routines all|name,name] [--replace] --yes',
|
|
493
|
+
};
|
|
494
|
+
return {
|
|
495
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
496
|
+
exitCode: 2,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
if (!hasYes(rawRest)) {
|
|
500
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
501
|
+
ok: false,
|
|
502
|
+
kind: 'agent.profiles.error',
|
|
503
|
+
error: `Refusing to create Agent profile ${name} from discovered behavior without --yes.`,
|
|
504
|
+
};
|
|
505
|
+
return {
|
|
506
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
507
|
+
exitCode: 2,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
const created = await createAgentRuntimeProfileFromDiscovered({
|
|
511
|
+
homeDirectory: runtime.homeDirectory,
|
|
512
|
+
workingDirectory: runtime.workingDirectory,
|
|
513
|
+
}, {
|
|
514
|
+
profileName: name,
|
|
515
|
+
templateId: flagValue(rawRest, ['--template-id', '--starter-id']) ?? undefined,
|
|
516
|
+
name: flagValue(rawRest, ['--profile-name', '--name']) ?? undefined,
|
|
517
|
+
description: flagValue(rawRest, ['--description']) ?? undefined,
|
|
518
|
+
persona: flagValue(rawRest, ['--persona']) ?? undefined,
|
|
519
|
+
skills: parseCsvFlag(rawRest, ['--skills']),
|
|
520
|
+
routines: parseCsvFlag(rawRest, ['--routines']),
|
|
521
|
+
replace: rawRest.includes('--replace'),
|
|
522
|
+
});
|
|
523
|
+
const result: AgentRuntimeProfileCommandResult = {
|
|
524
|
+
ok: true,
|
|
525
|
+
kind: 'agent.profiles.create_from_discovered',
|
|
526
|
+
data: {
|
|
527
|
+
profile: created.profile,
|
|
528
|
+
appliedTemplate: created.profile.starterTemplateApplication,
|
|
529
|
+
template: created.template,
|
|
530
|
+
nextCommand: `goodvibes-agent --agent-profile ${created.profile.id}`,
|
|
531
|
+
},
|
|
532
|
+
};
|
|
533
|
+
return {
|
|
534
|
+
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
535
|
+
exitCode: 0,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
|
|
293
539
|
if (sub === 'delete' || sub === 'remove') {
|
|
294
540
|
const name = values[0];
|
|
295
541
|
if (!name) {
|
|
@@ -336,7 +582,7 @@ export async function handleProfilesCommand(runtime: ProfilesCommandRuntime): Pr
|
|
|
336
582
|
const result: AgentRuntimeProfileCommandResult = {
|
|
337
583
|
ok: false,
|
|
338
584
|
kind: 'agent.profiles.error',
|
|
339
|
-
error: 'Usage: goodvibes-agent profiles [list|templates|show <name>|create <name> [--template <id>] --yes|delete <name> --yes]',
|
|
585
|
+
error: 'Usage: goodvibes-agent profiles [list|templates|default [<name>|clear] --yes|use <name> --yes|show <name>|create <name> [--template <id>] --yes|delete <name> --yes]',
|
|
340
586
|
};
|
|
341
587
|
return {
|
|
342
588
|
output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createShellPathService } from '@/runtime/index.ts';
|
|
2
2
|
import { discoverRoutines, type DiscoveredRoutineRecord } from '../agent/routine-discovery.ts';
|
|
3
|
-
import { AgentRoutineRegistry, type AgentRoutineRecord } from '../agent/routine-registry.ts';
|
|
3
|
+
import { AgentRoutineRegistry, evaluateAgentRoutineReadiness, type AgentRoutineRecord } from '../agent/routine-registry.ts';
|
|
4
|
+
import { buildAgentSkillRequirements, formatAgentSkillRequirement } from '../agent/skill-registry.ts';
|
|
4
5
|
import {
|
|
5
6
|
buildRoutineSchedulePreview,
|
|
6
7
|
promoteRoutineToDaemonSchedule,
|
|
@@ -34,10 +35,26 @@ interface RoutinesCommandFailure {
|
|
|
34
35
|
readonly error: string;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
interface ParsedRoutineOptions {
|
|
39
|
+
readonly positionals: readonly string[];
|
|
40
|
+
readonly flags: ReadonlyMap<string, string>;
|
|
41
|
+
readonly yes: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const ROUTINE_CREATE_USAGE = 'Usage: goodvibes-agent routines create --name <name> --description <summary> --steps <steps> [--tags a,b] [--triggers a,b] [--requires-env A,B] [--requires-command gh,jq] [--enabled]';
|
|
45
|
+
|
|
37
46
|
function jsonOrText(runtime: CliCommandRuntime, value: unknown, text: string): string {
|
|
38
47
|
return runtime.cli.flags.outputFormat === 'json' ? JSON.stringify(value, null, 2) : text;
|
|
39
48
|
}
|
|
40
49
|
|
|
50
|
+
function commandFailure(runtime: CliCommandRuntime, kind: string, error: string, exitCode: number): CliCommandOutput {
|
|
51
|
+
const failure: RoutinesCommandFailure = { ok: false, kind, error };
|
|
52
|
+
return {
|
|
53
|
+
output: runtime.cli.flags.outputFormat === 'json' ? JSON.stringify(failure, null, 2) : error,
|
|
54
|
+
exitCode,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
41
58
|
function routineRegistry(runtime: CliCommandRuntime): AgentRoutineRegistry {
|
|
42
59
|
return AgentRoutineRegistry.fromShellPaths(createShellPathService({
|
|
43
60
|
workingDirectory: runtime.workingDirectory,
|
|
@@ -64,6 +81,47 @@ function splitList(value: string | undefined): readonly string[] {
|
|
|
64
81
|
return value.split(',').map((entry) => entry.trim()).filter(Boolean);
|
|
65
82
|
}
|
|
66
83
|
|
|
84
|
+
function parseRoutineOptions(args: readonly string[]): ParsedRoutineOptions {
|
|
85
|
+
const flags = new Map<string, string>();
|
|
86
|
+
const positionals: string[] = [];
|
|
87
|
+
let yes = false;
|
|
88
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
89
|
+
const token = args[index] ?? '';
|
|
90
|
+
if (token === '--yes') {
|
|
91
|
+
yes = true;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (token.startsWith('--')) {
|
|
95
|
+
const key = token.slice(2);
|
|
96
|
+
const next = args[index + 1];
|
|
97
|
+
if (next !== undefined && !next.startsWith('--')) {
|
|
98
|
+
flags.set(key, next);
|
|
99
|
+
index += 1;
|
|
100
|
+
} else {
|
|
101
|
+
flags.set(key, 'true');
|
|
102
|
+
}
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
positionals.push(token);
|
|
106
|
+
}
|
|
107
|
+
return { positionals, flags, yes };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function optionValue(options: ParsedRoutineOptions, key: string): string | undefined {
|
|
111
|
+
const value = options.flags.get(key)?.trim();
|
|
112
|
+
return value ? value : undefined;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function hasFlag(options: ParsedRoutineOptions, key: string): boolean {
|
|
116
|
+
return options.flags.get(key) === 'true';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function requiredOption(options: ParsedRoutineOptions, key: string): string {
|
|
120
|
+
const value = optionValue(options, key);
|
|
121
|
+
if (!value) throw new Error(`${ROUTINE_CREATE_USAGE}\nMissing --${key}.`);
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
|
|
67
125
|
function parseImportFlags(args: readonly string[]): {
|
|
68
126
|
readonly name: string;
|
|
69
127
|
readonly enabled: boolean;
|
|
@@ -89,7 +147,9 @@ function parseImportFlags(args: readonly string[]): {
|
|
|
89
147
|
function summarizeRoutine(routine: AgentRoutineRecord): string {
|
|
90
148
|
const enabled = routine.enabled ? 'enabled' : 'disabled';
|
|
91
149
|
const tags = routine.tags.length > 0 ? ` tags=${routine.tags.join(',')}` : '';
|
|
92
|
-
|
|
150
|
+
const readiness = evaluateAgentRoutineReadiness(routine);
|
|
151
|
+
const ready = readiness.ready ? 'ready' : `needs ${readiness.missing.map(formatAgentSkillRequirement).join(',')}`;
|
|
152
|
+
return ` ${routine.id} ${enabled} ${routine.reviewState} ${ready} starts=${routine.startCount} ${routine.name} - ${routine.description}${tags}`;
|
|
93
153
|
}
|
|
94
154
|
|
|
95
155
|
function summarizeDiscoveredRoutine(routine: DiscoveredRoutineRecord): string {
|
|
@@ -136,13 +196,21 @@ function discoveredRoutineFrontmatterList(routine: DiscoveredRoutineRecord, key:
|
|
|
136
196
|
return splitList(value);
|
|
137
197
|
}
|
|
138
198
|
|
|
139
|
-
function
|
|
199
|
+
function discoveredRoutineFrontmatterAnyList(routine: DiscoveredRoutineRecord, keys: readonly string[]): readonly string[] {
|
|
200
|
+
for (const key of keys) {
|
|
201
|
+
const values = discoveredRoutineFrontmatterList(routine, key);
|
|
202
|
+
if (values.length > 0) return values;
|
|
203
|
+
}
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function renderRoutineList(title: string, path: string, routines: readonly AgentRoutineRecord[], emptyMessage?: string): string {
|
|
140
208
|
if (routines.length === 0) {
|
|
141
209
|
return [
|
|
142
210
|
title,
|
|
143
|
-
'
|
|
144
|
-
'
|
|
145
|
-
].join('\n');
|
|
211
|
+
` ${emptyMessage ?? 'No local Agent routines yet.'}`,
|
|
212
|
+
emptyMessage ? '' : ' Open /agent routines in the TUI, or use goodvibes-agent routines create for scripted setup.',
|
|
213
|
+
].filter(Boolean).join('\n');
|
|
146
214
|
}
|
|
147
215
|
return [
|
|
148
216
|
`${title} (${routines.length})`,
|
|
@@ -152,10 +220,14 @@ function renderRoutineList(title: string, path: string, routines: readonly Agent
|
|
|
152
220
|
}
|
|
153
221
|
|
|
154
222
|
function renderRoutine(routine: AgentRoutineRecord): string {
|
|
223
|
+
const readiness = evaluateAgentRoutineReadiness(routine);
|
|
155
224
|
return [
|
|
156
225
|
`Routine ${routine.name}`,
|
|
157
226
|
` id: ${routine.id}`,
|
|
158
227
|
` enabled: ${routine.enabled ? 'yes' : 'no'}`,
|
|
228
|
+
` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
|
|
229
|
+
` requirements: ${routine.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
|
|
230
|
+
readiness.missing.length > 0 ? ` missing: ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
|
|
159
231
|
` review: ${routine.reviewState}`,
|
|
160
232
|
` source: ${routine.source}`,
|
|
161
233
|
` provenance: ${routine.provenance}`,
|
|
@@ -235,15 +307,23 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
235
307
|
const registry = routineRegistry(runtime);
|
|
236
308
|
const snapshot = registry.snapshot();
|
|
237
309
|
const normalized = sub.toLowerCase();
|
|
238
|
-
if (normalized === 'list' || normalized === 'enabled') {
|
|
239
|
-
const routines = normalized === 'enabled'
|
|
310
|
+
if (normalized === 'list' || normalized === 'enabled' || normalized === 'attention' || normalized === 'needs-setup') {
|
|
311
|
+
const routines = normalized === 'enabled'
|
|
312
|
+
? snapshot.enabledRoutines
|
|
313
|
+
: normalized === 'attention' || normalized === 'needs-setup'
|
|
314
|
+
? snapshot.routines.filter((routine) => !evaluateAgentRoutineReadiness(routine).ready)
|
|
315
|
+
: snapshot.routines;
|
|
240
316
|
const value: RoutinesCommandSuccess<{
|
|
241
317
|
readonly path: string;
|
|
242
318
|
readonly routines: readonly AgentRoutineRecord[];
|
|
243
319
|
readonly enabledCount: number;
|
|
244
320
|
}> = {
|
|
245
321
|
ok: true,
|
|
246
|
-
kind: normalized === 'enabled'
|
|
322
|
+
kind: normalized === 'enabled'
|
|
323
|
+
? 'agent.routines.enabled'
|
|
324
|
+
: normalized === 'attention' || normalized === 'needs-setup'
|
|
325
|
+
? 'agent.routines.attention'
|
|
326
|
+
: 'agent.routines.list',
|
|
247
327
|
data: {
|
|
248
328
|
path: snapshot.path,
|
|
249
329
|
routines,
|
|
@@ -251,7 +331,16 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
251
331
|
},
|
|
252
332
|
};
|
|
253
333
|
return {
|
|
254
|
-
output: jsonOrText(runtime, value, renderRoutineList(
|
|
334
|
+
output: jsonOrText(runtime, value, renderRoutineList(
|
|
335
|
+
normalized === 'enabled'
|
|
336
|
+
? 'Enabled Agent routines'
|
|
337
|
+
: normalized === 'attention' || normalized === 'needs-setup'
|
|
338
|
+
? 'Agent routines needing setup'
|
|
339
|
+
: 'Agent routines',
|
|
340
|
+
snapshot.path,
|
|
341
|
+
routines,
|
|
342
|
+
normalized === 'attention' || normalized === 'needs-setup' ? 'No local Agent routines need setup.' : undefined,
|
|
343
|
+
)),
|
|
255
344
|
exitCode: 0,
|
|
256
345
|
};
|
|
257
346
|
}
|
|
@@ -317,6 +406,10 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
317
406
|
steps: discovered.steps,
|
|
318
407
|
tags: discoveredRoutineFrontmatterList(discovered, 'tags'),
|
|
319
408
|
triggers: discoveredRoutineFrontmatterList(discovered, 'triggers'),
|
|
409
|
+
requirements: buildAgentSkillRequirements({
|
|
410
|
+
env: discoveredRoutineFrontmatterAnyList(discovered, ['requiresEnv', 'requires-env', 'requires_env']),
|
|
411
|
+
commands: discoveredRoutineFrontmatterAnyList(discovered, ['requiresCommands', 'requires-commands', 'requires_commands', 'commands']),
|
|
412
|
+
}),
|
|
320
413
|
enabled: parsed.enabled,
|
|
321
414
|
source: 'imported',
|
|
322
415
|
provenance: `discovered:${discovered.origin}:${discovered.path}`,
|
|
@@ -331,6 +424,41 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
331
424
|
exitCode: 0,
|
|
332
425
|
};
|
|
333
426
|
}
|
|
427
|
+
if (normalized === 'create') {
|
|
428
|
+
const options = parseRoutineOptions(rest);
|
|
429
|
+
try {
|
|
430
|
+
const routine = registry.create({
|
|
431
|
+
name: requiredOption(options, 'name'),
|
|
432
|
+
description: requiredOption(options, 'description'),
|
|
433
|
+
steps: optionValue(options, 'steps') ?? options.positionals.join(' ').trim(),
|
|
434
|
+
tags: splitList(optionValue(options, 'tags')),
|
|
435
|
+
triggers: splitList(optionValue(options, 'triggers')),
|
|
436
|
+
requirements: buildAgentSkillRequirements({
|
|
437
|
+
env: splitList(optionValue(options, 'requires-env')),
|
|
438
|
+
commands: splitList(optionValue(options, 'requires-command') ?? optionValue(options, 'requires-commands')),
|
|
439
|
+
}),
|
|
440
|
+
enabled: hasFlag(options, 'enabled'),
|
|
441
|
+
source: 'user',
|
|
442
|
+
provenance: 'cli',
|
|
443
|
+
});
|
|
444
|
+
const value: RoutinesCommandSuccess<AgentRoutineRecord> = {
|
|
445
|
+
ok: true,
|
|
446
|
+
kind: 'agent.routines.create',
|
|
447
|
+
data: routine,
|
|
448
|
+
};
|
|
449
|
+
return {
|
|
450
|
+
output: jsonOrText(runtime, value, `Created Agent routine ${routine.id}: ${routine.name}${routine.enabled ? ' (enabled)' : ''}`),
|
|
451
|
+
exitCode: 0,
|
|
452
|
+
};
|
|
453
|
+
} catch (error) {
|
|
454
|
+
return commandFailure(
|
|
455
|
+
runtime,
|
|
456
|
+
error instanceof Error && error.message.startsWith('Usage:') ? 'invalid_routine_command' : 'agent.routines.create.error',
|
|
457
|
+
error instanceof Error ? error.message : String(error),
|
|
458
|
+
error instanceof Error && error.message.startsWith('Usage:') ? 2 : 1,
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
334
462
|
if (normalized === 'show') {
|
|
335
463
|
const id = rest[0];
|
|
336
464
|
if (!id) return { output: 'Usage: goodvibes-agent routines show <id>', exitCode: 2 };
|
|
@@ -396,7 +524,7 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
396
524
|
return handleRoutinePromotion(runtime, rest);
|
|
397
525
|
}
|
|
398
526
|
return {
|
|
399
|
-
output:
|
|
527
|
+
output: `Usage: goodvibes-agent routines [list|enabled|attention|discover|import-discovered <name> --yes|create --name <name> --description <summary> --steps <steps>|show <id>|receipts|reconcile|receipt <id>|promote <id> (--cron <expr>|--every <interval>|--at <iso-time>) [--delivery-channel <channel>|--delivery-route <route>|--delivery-webhook <url>] --yes]`,
|
|
400
528
|
exitCode: 2,
|
|
401
529
|
};
|
|
402
530
|
}
|
|
@@ -32,7 +32,7 @@ export interface CliServiceLogPosture {
|
|
|
32
32
|
readonly readError?: string;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export interface
|
|
35
|
+
export interface CliExternalHostLifecyclePosture {
|
|
36
36
|
readonly platform: 'manual';
|
|
37
37
|
readonly path: string;
|
|
38
38
|
readonly installed: false;
|
|
@@ -54,7 +54,7 @@ export interface CliServicePosture {
|
|
|
54
54
|
readonly restartOnFailure: boolean;
|
|
55
55
|
readonly daemonEnabled: boolean;
|
|
56
56
|
};
|
|
57
|
-
readonly managed:
|
|
57
|
+
readonly managed: CliExternalHostLifecyclePosture;
|
|
58
58
|
readonly endpoints: readonly CliServiceEndpointPosture[];
|
|
59
59
|
readonly log: CliServiceLogPosture;
|
|
60
60
|
readonly issues: readonly string[];
|
|
@@ -140,10 +140,10 @@ function resolveConfiguredLogPath(runtime: CliServiceRuntime): string | undefine
|
|
|
140
140
|
return isAbsolute(trimmed) ? trimmed : join(runtime.homeDirectory, trimmed);
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
function
|
|
143
|
+
function createExternalHostLifecycle(logPath: string | undefined): CliExternalHostLifecyclePosture {
|
|
144
144
|
return {
|
|
145
145
|
platform: 'manual',
|
|
146
|
-
path: 'connected GoodVibes
|
|
146
|
+
path: 'connected GoodVibes host',
|
|
147
147
|
installed: false,
|
|
148
148
|
autostart: false,
|
|
149
149
|
running: false,
|
|
@@ -151,7 +151,7 @@ function createExternalDaemonLifecycle(logPath: string | undefined): CliExternal
|
|
|
151
151
|
commandPreview: 'managed outside goodvibes-agent',
|
|
152
152
|
suggestedCommands: [],
|
|
153
153
|
lastAction: 'status',
|
|
154
|
-
pidPath: 'connected GoodVibes
|
|
154
|
+
pidPath: 'connected GoodVibes host',
|
|
155
155
|
lastError: null,
|
|
156
156
|
};
|
|
157
157
|
}
|
|
@@ -184,7 +184,7 @@ export async function buildCliServicePosture(
|
|
|
184
184
|
const issues: string[] = [];
|
|
185
185
|
|
|
186
186
|
if (serverBackedEnabled && !config.enabled) {
|
|
187
|
-
issues.push('Connected-
|
|
187
|
+
issues.push('Connected-host settings are present, but Agent host ownership is disabled by design.');
|
|
188
188
|
}
|
|
189
189
|
for (const endpoint of endpoints) {
|
|
190
190
|
if (endpoint.enabled && options.probe && endpoint.reachable === false) {
|
|
@@ -209,7 +209,7 @@ export async function buildCliServicePosture(
|
|
|
209
209
|
|
|
210
210
|
return {
|
|
211
211
|
config,
|
|
212
|
-
managed:
|
|
212
|
+
managed: createExternalHostLifecycle(configuredLogPath),
|
|
213
213
|
endpoints,
|
|
214
214
|
log,
|
|
215
215
|
issues,
|
|
@@ -223,16 +223,16 @@ function yesNo(value: boolean): string {
|
|
|
223
223
|
export function formatCliServicePosture(posture: CliServicePosture, json = false): string {
|
|
224
224
|
if (json) return JSON.stringify(posture, null, 2);
|
|
225
225
|
return [
|
|
226
|
-
'GoodVibes Agent
|
|
227
|
-
'
|
|
228
|
-
' Agent
|
|
226
|
+
'GoodVibes Agent connected-host diagnostics',
|
|
227
|
+
' lifecycle owner: outside goodvibes-agent',
|
|
228
|
+
' Agent starts connected host: no',
|
|
229
229
|
` external host config present: ${yesNo(posture.config.enabled)}`,
|
|
230
230
|
' external host lifecycle config: ignored by Agent',
|
|
231
231
|
` legacy host switch present: ${yesNo(posture.config.daemonEnabled)}`,
|
|
232
232
|
` log: ${posture.log.path ?? 'n/a'} (${posture.log.exists ? 'present' : 'missing'})`,
|
|
233
233
|
...(posture.log.readError ? [` log read error: ${posture.log.readError}`] : []),
|
|
234
234
|
'',
|
|
235
|
-
'Connected
|
|
235
|
+
'Connected API checks:',
|
|
236
236
|
...posture.endpoints.map((endpoint) =>
|
|
237
237
|
` ${endpoint.label}: enabled=${yesNo(endpoint.enabled)} ${endpoint.binding.hostMode} ${endpoint.binding.host}:${endpoint.binding.port} posture=${endpoint.bindPosture.label}${endpoint.reachable === undefined ? '' : ` reachable=${yesNo(endpoint.reachable)}`}`,
|
|
238
238
|
),
|