@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
|
@@ -4,6 +4,10 @@ import { AgentPersonaRegistry, type AgentPersonaRecord } from '../agent/persona-
|
|
|
4
4
|
import { discoverSkills, type SkillRecord } from '../agent/skill-discovery.ts';
|
|
5
5
|
import {
|
|
6
6
|
AgentSkillRegistry,
|
|
7
|
+
buildAgentSkillRequirements,
|
|
8
|
+
evaluateAgentSkillBundleReadiness,
|
|
9
|
+
evaluateAgentSkillReadiness,
|
|
10
|
+
formatAgentSkillRequirement,
|
|
7
11
|
type AgentSkillBundleRecord,
|
|
8
12
|
type AgentSkillRecord,
|
|
9
13
|
} from '../agent/skill-registry.ts';
|
|
@@ -170,7 +174,7 @@ function renderDiscoveredPersonaList(personas: readonly DiscoveredPersonaRecord[
|
|
|
170
174
|
return [
|
|
171
175
|
'Discovered Agent persona files',
|
|
172
176
|
' No persona markdown files found in Agent persona folders.',
|
|
173
|
-
' Search roots: .goodvibes/personas, .goodvibes/agent/personas,
|
|
177
|
+
' Search roots: .goodvibes/personas, .goodvibes/agent/personas, ~/.goodvibes/personas, ~/.goodvibes/agent/personas',
|
|
174
178
|
].join('\n');
|
|
175
179
|
}
|
|
176
180
|
return [
|
|
@@ -204,21 +208,29 @@ function discoveredPersonaFrontmatterList(persona: DiscoveredPersonaRecord, key:
|
|
|
204
208
|
function summarizeSkill(skill: AgentSkillRecord): string {
|
|
205
209
|
const enabled = skill.enabled ? 'enabled' : 'disabled';
|
|
206
210
|
const tags = skill.tags.length > 0 ? ` tags=${skill.tags.join(',')}` : '';
|
|
207
|
-
|
|
211
|
+
const readiness = evaluateAgentSkillReadiness(skill);
|
|
212
|
+
const ready = readiness.ready ? 'ready' : `needs ${readiness.missing.map(formatAgentSkillRequirement).join(',')}`;
|
|
213
|
+
return ` ${skill.id} ${enabled} ${skill.reviewState} ${ready} ${skill.name} - ${skill.description}${tags}`;
|
|
208
214
|
}
|
|
209
215
|
|
|
210
|
-
function summarizeBundle(bundle: AgentSkillBundleRecord): string {
|
|
216
|
+
function summarizeBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentSkillRecord[]): string {
|
|
211
217
|
const enabled = bundle.enabled ? 'enabled' : 'disabled';
|
|
212
|
-
|
|
218
|
+
const readiness = evaluateAgentSkillBundleReadiness(bundle, skills);
|
|
219
|
+
const missing = [
|
|
220
|
+
...readiness.missingRequirements.map(formatAgentSkillRequirement),
|
|
221
|
+
...readiness.missingSkillIds.map((skillId) => `skill:${skillId}`),
|
|
222
|
+
];
|
|
223
|
+
const ready = readiness.ready ? 'ready' : `needs ${missing.join(',')}`;
|
|
224
|
+
return ` ${bundle.id} ${enabled} ${bundle.reviewState} ${ready} ${bundle.name} - ${bundle.description} skills=${bundle.skillIds.join(',')}`;
|
|
213
225
|
}
|
|
214
226
|
|
|
215
|
-
function renderSkillList(title: string, path: string, skills: readonly AgentSkillRecord[]): string {
|
|
227
|
+
function renderSkillList(title: string, path: string, skills: readonly AgentSkillRecord[], emptyMessage?: string): string {
|
|
216
228
|
if (skills.length === 0) {
|
|
217
229
|
return [
|
|
218
230
|
title,
|
|
219
|
-
'
|
|
220
|
-
' Create one with: goodvibes-agent skills create --name <name> --description <summary> --procedure <steps>',
|
|
221
|
-
].join('\n');
|
|
231
|
+
` ${emptyMessage ?? 'No local Agent skills yet.'}`,
|
|
232
|
+
emptyMessage ? '' : ' Create one with: goodvibes-agent skills create --name <name> --description <summary> --procedure <steps>',
|
|
233
|
+
].filter(Boolean).join('\n');
|
|
222
234
|
}
|
|
223
235
|
return [
|
|
224
236
|
`${title} (${skills.length})`,
|
|
@@ -273,26 +285,38 @@ function discoveredFrontmatterList(skill: SkillRecord, key: string): readonly st
|
|
|
273
285
|
return value.split(',').map((entry) => entry.trim()).filter(Boolean);
|
|
274
286
|
}
|
|
275
287
|
|
|
276
|
-
function
|
|
288
|
+
function discoveredFrontmatterAnyList(skill: SkillRecord, keys: readonly string[]): readonly string[] {
|
|
289
|
+
for (const key of keys) {
|
|
290
|
+
const values = discoveredFrontmatterList(skill, key);
|
|
291
|
+
if (values.length > 0) return values;
|
|
292
|
+
}
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function renderBundleList(title: string, path: string, bundles: readonly AgentSkillBundleRecord[], skills: readonly AgentSkillRecord[], emptyMessage?: string): string {
|
|
277
297
|
if (bundles.length === 0) {
|
|
278
298
|
return [
|
|
279
299
|
title,
|
|
280
|
-
'
|
|
281
|
-
' Create one with: goodvibes-agent skills bundle create --name <name> --description <summary> --skills <id,id>',
|
|
282
|
-
].join('\n');
|
|
300
|
+
` ${emptyMessage ?? 'No local Agent skill bundles yet.'}`,
|
|
301
|
+
emptyMessage ? '' : ' Create one with: goodvibes-agent skills bundle create --name <name> --description <summary> --skills <id,id>',
|
|
302
|
+
].filter(Boolean).join('\n');
|
|
283
303
|
}
|
|
284
304
|
return [
|
|
285
305
|
`${title} (${bundles.length})`,
|
|
286
306
|
` store: ${path}`,
|
|
287
|
-
...bundles.map(summarizeBundle),
|
|
307
|
+
...bundles.map((bundle) => summarizeBundle(bundle, skills)),
|
|
288
308
|
].join('\n');
|
|
289
309
|
}
|
|
290
310
|
|
|
291
311
|
function renderSkill(skill: AgentSkillRecord): string {
|
|
312
|
+
const readiness = evaluateAgentSkillReadiness(skill);
|
|
292
313
|
return [
|
|
293
314
|
`Skill ${skill.name}`,
|
|
294
315
|
` id: ${skill.id}`,
|
|
295
316
|
` enabled: ${skill.enabled ? 'yes' : 'no'}`,
|
|
317
|
+
` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
|
|
318
|
+
` requirements: ${skill.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
|
|
319
|
+
readiness.missing.length > 0 ? ` missing: ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
|
|
296
320
|
` review: ${skill.reviewState}`,
|
|
297
321
|
` source: ${skill.source}`,
|
|
298
322
|
` provenance: ${skill.provenance}`,
|
|
@@ -308,11 +332,18 @@ function renderSkill(skill: AgentSkillRecord): string {
|
|
|
308
332
|
].filter((line): line is string => Boolean(line)).join('\n');
|
|
309
333
|
}
|
|
310
334
|
|
|
311
|
-
function renderBundle(bundle: AgentSkillBundleRecord): string {
|
|
335
|
+
function renderBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentSkillRecord[]): string {
|
|
336
|
+
const readiness = evaluateAgentSkillBundleReadiness(bundle, skills);
|
|
337
|
+
const missing = [
|
|
338
|
+
...readiness.missingRequirements.map(formatAgentSkillRequirement),
|
|
339
|
+
...readiness.missingSkillIds.map((skillId) => `skill:${skillId}`),
|
|
340
|
+
];
|
|
312
341
|
return [
|
|
313
342
|
`Skill bundle ${bundle.name}`,
|
|
314
343
|
` id: ${bundle.id}`,
|
|
315
344
|
` enabled: ${bundle.enabled ? 'yes' : 'no'}`,
|
|
345
|
+
` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
|
|
346
|
+
missing.length > 0 ? ` missing: ${missing.join(', ')}` : '',
|
|
316
347
|
` review: ${bundle.reviewState}`,
|
|
317
348
|
` source: ${bundle.source}`,
|
|
318
349
|
` provenance: ${bundle.provenance}`,
|
|
@@ -330,11 +361,11 @@ function usagePersonas(): string {
|
|
|
330
361
|
}
|
|
331
362
|
|
|
332
363
|
function usageSkills(): string {
|
|
333
|
-
return 'Usage: goodvibes-agent skills [list|enabled|active|discover|import-discovered <name> --yes|search <query>|show <id>|create|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes|bundle ...]';
|
|
364
|
+
return 'Usage: goodvibes-agent skills [list|enabled|active|attention|discover|import-discovered <name> --yes|search <query>|show <id>|create [--requires-env A,B] [--requires-command gh,jq]|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes|bundle ...]';
|
|
334
365
|
}
|
|
335
366
|
|
|
336
367
|
function usageBundles(): string {
|
|
337
|
-
return 'Usage: goodvibes-agent skills bundle [list|enabled|search <query>|show <id>|create|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes]';
|
|
368
|
+
return 'Usage: goodvibes-agent skills bundle [list|enabled|attention|search <query>|show <id>|create|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes]';
|
|
338
369
|
}
|
|
339
370
|
|
|
340
371
|
function errorOutput(runtime: CliCommandRuntime, error: unknown, kind: string): CliCommandOutput {
|
|
@@ -473,6 +504,7 @@ function skillPayloadFromOptions(options: ParsedOptions): {
|
|
|
473
504
|
readonly procedure: string;
|
|
474
505
|
readonly tags: readonly string[] | undefined;
|
|
475
506
|
readonly triggers: readonly string[] | undefined;
|
|
507
|
+
readonly requirements: ReturnType<typeof buildAgentSkillRequirements>;
|
|
476
508
|
readonly enabled: boolean | undefined;
|
|
477
509
|
readonly provenance: string;
|
|
478
510
|
} {
|
|
@@ -483,6 +515,10 @@ function skillPayloadFromOptions(options: ParsedOptions): {
|
|
|
483
515
|
procedure: requiredOption(options, 'procedure', usage),
|
|
484
516
|
tags: csvOption(options, 'tags'),
|
|
485
517
|
triggers: csvOption(options, 'triggers'),
|
|
518
|
+
requirements: buildAgentSkillRequirements({
|
|
519
|
+
env: csvOption(options, 'requires-env'),
|
|
520
|
+
commands: csvOption(options, 'requires-command') ?? csvOption(options, 'requires-commands'),
|
|
521
|
+
}),
|
|
486
522
|
enabled: hasFlag(options, 'enabled') ? true : undefined,
|
|
487
523
|
provenance: optionValue(options, 'provenance') ?? 'cli',
|
|
488
524
|
};
|
|
@@ -495,22 +531,26 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
|
|
|
495
531
|
const registry = skillRegistry(runtime);
|
|
496
532
|
const snapshot = registry.snapshot();
|
|
497
533
|
if (normalized === 'list' || normalized === 'ls') {
|
|
498
|
-
return success(runtime, 'agent.skills.bundles.list', { path: snapshot.path, bundles: snapshot.bundles }, renderBundleList('Agent skill bundles', snapshot.path, snapshot.bundles));
|
|
534
|
+
return success(runtime, 'agent.skills.bundles.list', { path: snapshot.path, bundles: snapshot.bundles }, renderBundleList('Agent skill bundles', snapshot.path, snapshot.bundles, snapshot.skills));
|
|
499
535
|
}
|
|
500
536
|
if (normalized === 'enabled') {
|
|
501
|
-
return success(runtime, 'agent.skills.bundles.enabled', { path: snapshot.path, bundles: snapshot.enabledBundles }, renderBundleList('Enabled Agent skill bundles', snapshot.path, snapshot.enabledBundles));
|
|
537
|
+
return success(runtime, 'agent.skills.bundles.enabled', { path: snapshot.path, bundles: snapshot.enabledBundles }, renderBundleList('Enabled Agent skill bundles', snapshot.path, snapshot.enabledBundles, snapshot.skills));
|
|
538
|
+
}
|
|
539
|
+
if (normalized === 'attention' || normalized === 'needs-setup') {
|
|
540
|
+
const bundles = snapshot.bundles.filter((bundle) => !evaluateAgentSkillBundleReadiness(bundle, snapshot.skills).ready);
|
|
541
|
+
return success(runtime, 'agent.skills.bundles.attention', { path: snapshot.path, bundles }, renderBundleList('Agent skill bundles needing setup', snapshot.path, bundles, snapshot.skills, 'No local Agent skill bundles need setup.'));
|
|
502
542
|
}
|
|
503
543
|
if (normalized === 'search' || normalized === 'find') {
|
|
504
544
|
const query = rest.join(' ').trim();
|
|
505
545
|
const results = registry.searchBundles(query);
|
|
506
|
-
return success(runtime, 'agent.skills.bundles.search', { query, results }, renderBundleList(`Agent skill bundles matching "${query}"`, snapshot.path, results));
|
|
546
|
+
return success(runtime, 'agent.skills.bundles.search', { query, results }, renderBundleList(`Agent skill bundles matching "${query}"`, snapshot.path, results, snapshot.skills));
|
|
507
547
|
}
|
|
508
548
|
if (normalized === 'show' || normalized === 'get') {
|
|
509
549
|
const id = rest[0];
|
|
510
550
|
if (!id) return failure(runtime, 'invalid_skill_bundle_command', 'Usage: goodvibes-agent skills bundle show <id>', 2);
|
|
511
551
|
const bundle = registry.getBundle(id);
|
|
512
552
|
if (!bundle) return failure(runtime, 'skill_bundle_not_found', `Unknown Agent skill bundle: ${id}`, 1);
|
|
513
|
-
return success(runtime, 'agent.skills.bundles.show', bundle, renderBundle(bundle));
|
|
553
|
+
return success(runtime, 'agent.skills.bundles.show', bundle, renderBundle(bundle, snapshot.skills));
|
|
514
554
|
}
|
|
515
555
|
if (normalized === 'create') {
|
|
516
556
|
const options = parseOptions(rest);
|
|
@@ -584,9 +624,13 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
|
|
|
584
624
|
if (normalized === 'active') {
|
|
585
625
|
return success(runtime, 'agent.skills.active', { path: snapshot.path, skills: snapshot.activeSkills, bundles: snapshot.enabledBundles }, [
|
|
586
626
|
renderSkillList('Active Agent skills', snapshot.path, snapshot.activeSkills),
|
|
587
|
-
snapshot.enabledBundles.length > 0 ? renderBundleList('Enabled Agent skill bundles', snapshot.path, snapshot.enabledBundles) : '',
|
|
627
|
+
snapshot.enabledBundles.length > 0 ? renderBundleList('Enabled Agent skill bundles', snapshot.path, snapshot.enabledBundles, snapshot.skills) : '',
|
|
588
628
|
].filter(Boolean).join('\n\n'));
|
|
589
629
|
}
|
|
630
|
+
if (normalized === 'attention' || normalized === 'needs-setup') {
|
|
631
|
+
const skills = snapshot.skills.filter((skill) => !evaluateAgentSkillReadiness(skill).ready);
|
|
632
|
+
return success(runtime, 'agent.skills.attention', { path: snapshot.path, skills }, renderSkillList('Agent skills needing setup', snapshot.path, skills, 'No local Agent skills need setup.'));
|
|
633
|
+
}
|
|
590
634
|
if (normalized === 'discover') {
|
|
591
635
|
const discovered = await discoverSkills(shellPaths(runtime));
|
|
592
636
|
return success(runtime, 'agent.skills.discover', { skills: discovered }, renderDiscoveredSkillList(discovered));
|
|
@@ -616,6 +660,10 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
|
|
|
616
660
|
procedure: discovered.body,
|
|
617
661
|
tags: discoveredFrontmatterList(discovered, 'tags'),
|
|
618
662
|
triggers: discoveredFrontmatterList(discovered, 'triggers'),
|
|
663
|
+
requirements: buildAgentSkillRequirements({
|
|
664
|
+
env: discoveredFrontmatterAnyList(discovered, ['requiresEnv', 'requires-env', 'requires_env']),
|
|
665
|
+
commands: discoveredFrontmatterAnyList(discovered, ['requiresCommands', 'requires-commands', 'requires_commands', 'commands']),
|
|
666
|
+
}),
|
|
619
667
|
enabled: hasFlag(options, 'enabled'),
|
|
620
668
|
source: 'imported',
|
|
621
669
|
provenance: `discovered:${discovered.origin}:${discovered.path}`,
|
|
@@ -648,6 +696,12 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
|
|
|
648
696
|
procedure: optionValue(options, 'procedure'),
|
|
649
697
|
tags: csvOption(options, 'tags'),
|
|
650
698
|
triggers: csvOption(options, 'triggers'),
|
|
699
|
+
requirements: options.values.has('requires-env') || options.values.has('requires-command') || options.values.has('requires-commands')
|
|
700
|
+
? buildAgentSkillRequirements({
|
|
701
|
+
env: csvOption(options, 'requires-env'),
|
|
702
|
+
commands: csvOption(options, 'requires-command') ?? csvOption(options, 'requires-commands'),
|
|
703
|
+
})
|
|
704
|
+
: undefined,
|
|
651
705
|
provenance: optionValue(options, 'provenance'),
|
|
652
706
|
});
|
|
653
707
|
return success(runtime, 'agent.skills.update', skill, `Agent skill updated: ${skill.id}`);
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { dirname
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
3
|
import { SecretsManager } from '../config/secrets.ts';
|
|
4
4
|
import { BUILTIN_SECRET_PROVIDER_SOURCES, describeSecretRef, isSecretRefInput, resolveSecretRef } from '@pellux/goodvibes-sdk/platform/config';
|
|
5
5
|
import { getSubscriptionProviderConfig, listAvailableSubscriptionProviders } from '@pellux/goodvibes-sdk/platform/config';
|
|
6
6
|
import { beginOpenAICodexLogin, exchangeOpenAICodexCode } from '@pellux/goodvibes-sdk/platform/config';
|
|
7
7
|
import { inspectProviderAuth } from '@/runtime/index.ts';
|
|
8
|
-
import {
|
|
8
|
+
import { buildCompanionConnectionInfo, encodeConnectionPayload, formatConnectionBlock } from '@pellux/goodvibes-sdk/platform/pairing';
|
|
9
9
|
import { generateQrMatrix, renderQrToString } from '@pellux/goodvibes-sdk/platform/pairing';
|
|
10
10
|
import { resolveRuntimeEndpointBinding } from './endpoints.ts';
|
|
11
11
|
import type { CliCommandRuntime } from './management.ts';
|
|
12
12
|
import { extractAuthorizationCode, formatJsonOrText, hasCommandFlag, openBrowser, urlHostForBindHost, withRuntimeServices, yesNo } from './management.ts';
|
|
13
13
|
import { GOODVIBES_AGENT_PAIRING_SURFACE } from '../config/surface.ts';
|
|
14
|
+
import { connectedHostTokenRequiredMessage, readConnectedHostOperatorToken } from '../runtime/connected-host-auth.ts';
|
|
14
15
|
|
|
15
16
|
export async function renderSubscriptions(runtime: CliCommandRuntime): Promise<string> {
|
|
16
17
|
return await withRuntimeServices(runtime, async (services) => {
|
|
@@ -279,7 +280,7 @@ export async function handleTasks(runtime: CliCommandRuntime): Promise<string> {
|
|
|
279
280
|
const [sub = 'list', ...rest] = runtime.cli.commandArgs;
|
|
280
281
|
if (sub === 'submit') {
|
|
281
282
|
return [
|
|
282
|
-
'GoodVibes Agent blocks CLI task submission from the
|
|
283
|
+
'GoodVibes Agent blocks CLI task submission from the host-owned task workflow.',
|
|
283
284
|
' policy: do normal assistant work in the main Agent conversation or use `goodvibes-agent run <prompt>` for an explicit one-shot run.',
|
|
284
285
|
' build/fix/review: use `goodvibes-agent delegate <task>` for explicit GoodVibes TUI handoff.',
|
|
285
286
|
' result: no local task was started.',
|
|
@@ -289,7 +290,7 @@ export async function handleTasks(runtime: CliCommandRuntime): Promise<string> {
|
|
|
289
290
|
const tasks = [...services.runtimeStore.getState().tasks.tasks.values()];
|
|
290
291
|
if (sub === 'list') {
|
|
291
292
|
return tasks.length === 0
|
|
292
|
-
? 'GoodVibes tasks\n No connected-
|
|
293
|
+
? 'GoodVibes tasks\n No connected-host tasks are currently recorded.'
|
|
293
294
|
: ['GoodVibes tasks', ...tasks.map((task) => ` ${task.id} ${task.status} ${task.kind} ${task.title}`)].join('\n');
|
|
294
295
|
}
|
|
295
296
|
if (sub === 'show') {
|
|
@@ -302,8 +303,8 @@ export async function handleTasks(runtime: CliCommandRuntime): Promise<string> {
|
|
|
302
303
|
}
|
|
303
304
|
|
|
304
305
|
export async function renderPairing(runtime: CliCommandRuntime): Promise<string> {
|
|
305
|
-
const
|
|
306
|
-
|
|
306
|
+
const tokenRecord = readConnectedHostOperatorToken(runtime.homeDirectory);
|
|
307
|
+
if (!tokenRecord.token) return connectedHostTokenRequiredMessage(tokenRecord.path);
|
|
307
308
|
const binding = resolveRuntimeEndpointBinding(runtime.configManager, 'controlPlane');
|
|
308
309
|
const daemonUrl = `http://${urlHostForBindHost(binding.host)}:${binding.port}`;
|
|
309
310
|
const info = buildCompanionConnectionInfo({
|
package/src/cli/management.ts
CHANGED
|
@@ -19,14 +19,9 @@ import { BUILTIN_SECRET_PROVIDER_SOURCES, describeSecretRef, isSecretRefInput, r
|
|
|
19
19
|
import { getSubscriptionProviderConfig, listAvailableSubscriptionProviders } from '@pellux/goodvibes-sdk/platform/config';
|
|
20
20
|
import { beginOpenAICodexLogin, exchangeOpenAICodexCode } from '@pellux/goodvibes-sdk/platform/config';
|
|
21
21
|
import { inspectProviderAuth } from '@/runtime/index.ts';
|
|
22
|
-
import { getOrCreateCompanionToken, buildCompanionConnectionInfo, encodeConnectionPayload, formatConnectionBlock } from '@pellux/goodvibes-sdk/platform/pairing';
|
|
23
|
-
import { generateQrMatrix, renderQrToString } from '@pellux/goodvibes-sdk/platform/pairing';
|
|
24
22
|
import type { GoodVibesCliParseResult } from './types.ts';
|
|
25
23
|
import { formatProviderAuthRoute, summarizeProviderAuthRoutes } from './provider-auth-routes.ts';
|
|
26
24
|
import { classifyProviderSetup } from './provider-classification.ts';
|
|
27
|
-
import { resolveRuntimeEndpointBinding } from './endpoints.ts';
|
|
28
|
-
import { applyRuntimeEndpointFlagOverrides } from './config-overrides.ts';
|
|
29
|
-
import type { RuntimeEndpointId } from './endpoints.ts';
|
|
30
25
|
import { handleBundleCommand } from './bundle-command.ts';
|
|
31
26
|
import { handleSecrets, handleSessions, handleTasks, renderPairing, renderSubscriptions } from './management-commands.ts';
|
|
32
27
|
import { handleAgentKnowledgeCommand, handleAgentKnowledgeShortcutCommand, handleCompatCommand, handleDelegateCommand } from './agent-knowledge-command.ts';
|
|
@@ -132,46 +127,6 @@ export function urlHostForBindHost(host: string): string {
|
|
|
132
127
|
return host || '127.0.0.1';
|
|
133
128
|
}
|
|
134
129
|
|
|
135
|
-
export function enableServicePosture(config: ConfigManager): void {
|
|
136
|
-
config.setDynamic('service.enabled', true);
|
|
137
|
-
config.setDynamic('service.autostart', true);
|
|
138
|
-
config.setDynamic('service.restartOnFailure', true);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export function enableEndpointLanDefault(config: ConfigManager, endpoint: RuntimeEndpointId): void {
|
|
142
|
-
const binding = resolveRuntimeEndpointBinding(config, endpoint);
|
|
143
|
-
if (binding.hostMode === 'custom') return;
|
|
144
|
-
if (endpoint === 'controlPlane') {
|
|
145
|
-
config.setDynamic('controlPlane.hostMode', 'network');
|
|
146
|
-
config.setDynamic('controlPlane.host', '0.0.0.0');
|
|
147
|
-
config.setDynamic('controlPlane.allowRemote', true);
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
if (endpoint === 'httpListener') {
|
|
151
|
-
config.setDynamic('httpListener.hostMode', 'network');
|
|
152
|
-
config.setDynamic('httpListener.host', '0.0.0.0');
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
config.setDynamic('web.hostMode', 'network');
|
|
156
|
-
config.setDynamic('web.host', '0.0.0.0');
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export function applyTargetEndpointFlagsOrDefault(
|
|
160
|
-
runtime: CliCommandRuntime,
|
|
161
|
-
endpoint: RuntimeEndpointId,
|
|
162
|
-
): string | null {
|
|
163
|
-
const errors = applyRuntimeEndpointFlagOverrides(runtime.configManager, endpoint, runtime.cli.flags);
|
|
164
|
-
if (errors.length > 0) return errors.join('\n');
|
|
165
|
-
if (runtime.cli.flags.hostname === undefined) {
|
|
166
|
-
enableEndpointLanDefault(runtime.configManager, endpoint);
|
|
167
|
-
}
|
|
168
|
-
if (endpoint === 'controlPlane') {
|
|
169
|
-
const binding = resolveRuntimeEndpointBinding(runtime.configManager, endpoint);
|
|
170
|
-
runtime.configManager.setDynamic('controlPlane.allowRemote', binding.hostMode !== 'local');
|
|
171
|
-
}
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
130
|
export function openBrowser(url: string): string {
|
|
176
131
|
const platform = process.platform;
|
|
177
132
|
const command = platform === 'darwin' ? 'open' : platform === 'win32' ? 'cmd' : 'xdg-open';
|
|
@@ -544,8 +499,8 @@ async function renderAuth(runtime: CliCommandRuntime): Promise<string> {
|
|
|
544
499
|
]);
|
|
545
500
|
if (blocked.has(sub)) {
|
|
546
501
|
return [
|
|
547
|
-
'Unsupported: connected-
|
|
548
|
-
'GoodVibes Agent does not create, delete, rotate, revoke, or clear connected-
|
|
502
|
+
'Unsupported: connected-host auth user/session administration is outside GoodVibes Agent.',
|
|
503
|
+
'GoodVibes Agent does not create, delete, rotate, revoke, or clear connected-host users, sessions, or bootstrap credentials.',
|
|
549
504
|
'Use the owning GoodVibes host for auth administration.',
|
|
550
505
|
].join('\n');
|
|
551
506
|
}
|
|
@@ -566,21 +521,21 @@ async function renderAuth(runtime: CliCommandRuntime): Promise<string> {
|
|
|
566
521
|
if (sub === 'users' || sub === 'sessions') {
|
|
567
522
|
return formatJsonOrText(runtime.cli)(value, [
|
|
568
523
|
`GoodVibes Agent auth ${sub}`,
|
|
569
|
-
' owner: connected GoodVibes
|
|
524
|
+
' owner: connected GoodVibes host',
|
|
570
525
|
` operator token: ${paths.operatorTokenPresent ? 'present' : 'missing'}`,
|
|
571
526
|
` operator token path: ${paths.operatorTokenPath}`,
|
|
572
527
|
` ${sub}: managed outside Agent`,
|
|
573
|
-
' Agent does not enumerate or mutate connected-
|
|
528
|
+
' Agent does not enumerate or mutate connected-host users/sessions from the local CLI.',
|
|
574
529
|
].join('\n'));
|
|
575
530
|
}
|
|
576
531
|
return formatJsonOrText(runtime.cli)(value, [
|
|
577
532
|
'GoodVibes Agent auth',
|
|
578
|
-
' owner: connected GoodVibes
|
|
533
|
+
' owner: connected GoodVibes host',
|
|
579
534
|
` permission mode: ${String(value.permissionMode)}`,
|
|
580
535
|
` operator token: ${paths.operatorTokenPresent ? 'present' : 'missing'} (${paths.operatorTokenPath})`,
|
|
581
536
|
` compatibility user store: ${paths.userStorePresent ? 'present' : 'missing'} (${paths.userStorePath})`,
|
|
582
537
|
` compatibility bootstrap credential: ${paths.bootstrapCredentialPresent ? 'present' : 'missing'} (${paths.bootstrapCredentialPath})`,
|
|
583
|
-
' connected-
|
|
538
|
+
' connected-host user/session administration: outside Agent',
|
|
584
539
|
' next: goodvibes-agent providers',
|
|
585
540
|
' next: goodvibes-agent subscription providers',
|
|
586
541
|
].join('\n'));
|
package/src/cli/parser.ts
CHANGED
|
@@ -58,7 +58,28 @@ const COMMAND_ALIASES: Readonly<Record<string, GoodVibesCliCommand>> = {
|
|
|
58
58
|
version: 'version',
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
const
|
|
61
|
+
const BLOCKED_PRODUCT_COMMANDS = new Set([
|
|
62
|
+
'app',
|
|
63
|
+
'bridge',
|
|
64
|
+
'control-plane',
|
|
65
|
+
'controlplane',
|
|
66
|
+
'cp',
|
|
67
|
+
'daemon',
|
|
68
|
+
'http-listener',
|
|
69
|
+
'launch',
|
|
70
|
+
'listener',
|
|
71
|
+
'remote',
|
|
72
|
+
'serve',
|
|
73
|
+
'server',
|
|
74
|
+
'service',
|
|
75
|
+
'services',
|
|
76
|
+
'start',
|
|
77
|
+
'surface',
|
|
78
|
+
'surfaces',
|
|
79
|
+
'tui',
|
|
80
|
+
'web',
|
|
81
|
+
'webhook',
|
|
82
|
+
]);
|
|
62
83
|
|
|
63
84
|
function createDefaultFlags(): GoodVibesCliFlags {
|
|
64
85
|
return {
|
|
@@ -200,7 +221,7 @@ export function parseGoodVibesCli(
|
|
|
200
221
|
if (!token.startsWith('-') || token === '-') {
|
|
201
222
|
if (!sawCommand) {
|
|
202
223
|
const commandToken = token.toLowerCase();
|
|
203
|
-
if (
|
|
224
|
+
if (BLOCKED_PRODUCT_COMMANDS.has(commandToken)) {
|
|
204
225
|
command = 'unknown';
|
|
205
226
|
rawCommand = token;
|
|
206
227
|
sawCommand = true;
|