@pellux/goodvibes-agent 0.1.117 → 1.0.1
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 +20 -4
- package/README.md +35 -14
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +176093 -171065
- package/docs/README.md +11 -5
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +3 -3
- package/docs/getting-started.md +29 -15
- package/docs/knowledge-artifacts-and-multimodal.md +91 -0
- package/docs/project-planning.md +79 -0
- package/docs/providers-and-routing.md +46 -0
- package/docs/release-and-publishing.md +44 -9
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +2 -5
- package/src/agent/channel-delivery.ts +201 -0
- package/src/agent/media-generation.ts +159 -0
- package/src/agent/memory-prompt.ts +0 -1
- package/src/agent/note-registry.ts +329 -0
- package/src/agent/operator-actions.ts +343 -0
- package/src/agent/persona-registry.ts +15 -14
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +26 -25
- package/src/agent/routine-registry.ts +13 -12
- package/src/agent/routine-schedule-args.ts +2 -1
- package/src/agent/routine-schedule-format.ts +77 -53
- package/src/agent/routine-schedule-promotion.ts +34 -32
- package/src/agent/routine-schedule-receipts.ts +28 -26
- package/src/agent/runtime-profile-starters.ts +2 -2
- package/src/agent/runtime-profile.ts +18 -17
- package/src/agent/skill-registry.ts +25 -24
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +39 -33
- package/src/cli/agent-knowledge-format.ts +80 -67
- package/src/cli/agent-knowledge-methods.ts +1 -1
- package/src/cli/agent-knowledge-runtime.ts +32 -26
- package/src/cli/bundle-command.ts +13 -8
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +29 -11
- package/src/cli/local-library-command.ts +159 -73
- package/src/cli/management-commands.ts +98 -62
- package/src/cli/management.ts +52 -26
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -24
- package/src/cli/profiles-command.ts +52 -35
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +59 -39
- package/src/cli/service-posture.ts +6 -6
- package/src/cli/status.ts +46 -121
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-activation.ts +33 -7
- package/src/input/agent-workspace-basic-command-editor-submission.ts +7 -3
- package/src/input/agent-workspace-basic-command-editors.ts +30 -10
- package/src/input/agent-workspace-categories.ts +276 -64
- package/src/input/agent-workspace-channel-command-editor-submission.ts +34 -0
- package/src/input/agent-workspace-channel-command-editors.ts +23 -5
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +18 -2
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +1 -1
- package/src/input/agent-workspace-editors.ts +140 -2
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-knowledge-url-editor.ts +4 -11
- package/src/input/agent-workspace-learned-behavior.ts +2 -2
- package/src/input/agent-workspace-library-command-editor-submission.ts +1 -1
- package/src/input/agent-workspace-library-command-editors.ts +2 -2
- package/src/input/agent-workspace-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
- package/src/input/agent-workspace-media-command-editors.ts +27 -0
- package/src/input/agent-workspace-memory-command-editors.ts +1 -1
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +38 -2
- package/src/input/agent-workspace-notify-editor-submission.ts +16 -2
- package/src/input/agent-workspace-operations-command-editor-submission.ts +63 -1
- package/src/input/agent-workspace-operations-command-editors.ts +80 -3
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
- package/src/input/agent-workspace-search.ts +169 -0
- package/src/input/agent-workspace-setup.ts +22 -11
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +6 -6
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +10 -10
- package/src/input/agent-workspace-snapshot.ts +112 -13
- package/src/input/agent-workspace-task-command-editors.ts +4 -4
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +92 -4
- package/src/input/agent-workspace-voice-media.ts +3 -6
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace.ts +136 -208
- package/src/input/command-registry.ts +4 -1
- package/src/input/commands/agent-local-library-args.ts +52 -0
- package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
- package/src/input/commands/agent-skills-runtime.ts +87 -99
- package/src/input/commands/agent-workspace-runtime.ts +23 -7
- package/src/input/commands/brief-runtime.ts +25 -24
- package/src/input/commands/channels-runtime.ts +145 -31
- package/src/input/commands/delegation-runtime.ts +29 -23
- package/src/input/commands/experience-runtime.ts +6 -4
- package/src/input/commands/guidance-runtime.ts +4 -4
- package/src/input/commands/health-runtime.ts +140 -115
- package/src/input/commands/knowledge.ts +57 -56
- package/src/input/commands/local-provider-runtime.ts +36 -18
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +7 -7
- package/src/input/commands/mcp-runtime.ts +118 -50
- package/src/input/commands/notify-runtime.ts +38 -9
- package/src/input/commands/operator-actions-runtime.ts +138 -0
- package/src/input/commands/operator-runtime.ts +6 -17
- package/src/input/commands/personas-runtime.ts +49 -59
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +29 -29
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +45 -6
- package/src/input/commands/recall-bundle.ts +11 -11
- package/src/input/commands/recall-capture.ts +13 -11
- package/src/input/commands/recall-query.ts +29 -21
- package/src/input/commands/recall-review.ts +2 -1
- package/src/input/commands/routines-runtime.ts +63 -72
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +4 -4
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +132 -93
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +32 -17
- package/src/input/commands/subscription-runtime.ts +53 -179
- package/src/input/commands/tasks-runtime.ts +20 -20
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +2 -2
- package/src/input/feed-context-factory.ts +2 -1
- package/src/input/file-picker.ts +3 -2
- package/src/input/handler-command-route.ts +4 -7
- package/src/input/handler-content-actions.ts +89 -1
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -3
- package/src/input/handler-interactions.ts +7 -5
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +24 -80
- package/src/input/handler-shortcuts.ts +15 -4
- package/src/input/handler.ts +47 -17
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +22 -11
- package/src/input/onboarding/onboarding-wizard-apply.ts +13 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +147 -57
- package/src/input/onboarding/onboarding-wizard-steps.ts +46 -29
- package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
- package/src/input/onboarding/onboarding-wizard.ts +68 -0
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +22 -4
- package/src/input/settings-modal-behavior.ts +0 -3
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +2 -13
- package/src/input/settings-modal.ts +6 -52
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -8
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +2 -2
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +1 -10
- package/src/panels/builtin/session.ts +9 -9
- package/src/panels/builtin/shared.ts +2 -2
- package/src/panels/cost-tracker-panel.ts +1 -1
- package/src/panels/docs-panel.ts +5 -3
- package/src/panels/index.ts +0 -1
- package/src/panels/knowledge-panel.ts +6 -5
- package/src/panels/memory-panel.ts +7 -6
- package/src/panels/panel-list-panel.ts +36 -80
- package/src/panels/project-planning-panel.ts +18 -11
- package/src/panels/provider-account-snapshot.ts +51 -25
- package/src/panels/provider-accounts-panel.ts +33 -18
- package/src/panels/provider-health-domains.ts +45 -4
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +1 -1
- package/src/panels/schedule-panel.ts +9 -17
- package/src/panels/security-panel.ts +8 -8
- package/src/panels/session-browser-panel.ts +10 -10
- package/src/panels/subscription-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +1 -1
- package/src/panels/tasks-panel.ts +20 -13
- package/src/panels/tool-inspector-panel.ts +19 -12
- package/src/panels/work-plan-panel.ts +5 -5
- package/src/planning/project-planning-coordinator.ts +1 -1
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +228 -52
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/bookmark-modal.ts +19 -4
- package/src/renderer/buffer.ts +4 -2
- package/src/renderer/context-inspector.ts +50 -13
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +19 -6
- package/src/renderer/help-overlay.ts +106 -33
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +164 -50
- package/src/renderer/model-picker-overlay.ts +58 -2
- package/src/renderer/model-workspace.ts +104 -20
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +20 -4
- package/src/renderer/search-overlay.ts +25 -5
- package/src/renderer/selection-modal-overlay.ts +46 -14
- package/src/renderer/session-picker-modal.ts +18 -1
- package/src/renderer/settings-modal-helpers.ts +2 -40
- package/src/renderer/settings-modal.ts +83 -50
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +6 -6
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +9 -7
- package/src/runtime/bootstrap-core.ts +19 -1
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +31 -22
- package/src/runtime/connected-host-auth.ts +7 -2
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -1
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +80 -79
- package/src/runtime/onboarding/derivation.ts +5 -8
- package/src/runtime/onboarding/snapshot.ts +0 -15
- package/src/runtime/onboarding/types.ts +8 -19
- package/src/runtime/onboarding/verify.ts +32 -10
- package/src/runtime/operator-token-cleanup.ts +1 -1
- package/src/runtime/services.ts +91 -22
- package/src/runtime/store/selectors/index.ts +3 -3
- package/src/runtime/store/state.ts +1 -4
- package/src/runtime/surface-feature-flags.ts +41 -6
- package/src/runtime/ui-read-models.ts +3 -4
- package/src/runtime/ui-services.ts +6 -6
- package/src/shell/blocking-input.ts +2 -1
- package/src/shell/ui-openers.ts +3 -13
- package/src/tools/agent-analysis-registry-policy.ts +0 -1
- package/src/tools/agent-channel-send-tool.ts +133 -0
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
- package/src/tools/agent-knowledge-tool.ts +170 -0
- package/src/tools/agent-local-registry-tool.ts +269 -69
- package/src/tools/agent-media-generate-tool.ts +133 -0
- package/src/tools/agent-notify-tool.ts +143 -0
- package/src/tools/agent-operator-action-tool.ts +137 -0
- package/src/tools/agent-operator-briefing-tool.ts +217 -0
- package/src/tools/agent-reminder-schedule-tool.ts +237 -0
- package/src/tools/agent-tool-policy-guard.ts +8 -8
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -13
- package/src/panels/panel-picker.ts +0 -105
- package/src/panels/policy-panel.ts +0 -308
- package/src/renderer/panel-picker-overlay.ts +0 -202
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createShellPathService } from '@/runtime/index.ts';
|
|
2
2
|
import { discoverPersonas, type DiscoveredPersonaRecord } from '../agent/persona-discovery.ts';
|
|
3
3
|
import { AgentPersonaRegistry, type AgentPersonaRecord } from '../agent/persona-registry.ts';
|
|
4
|
+
import { formatAgentRecordOrigin, formatAgentRecordReviewState } from '../agent/record-labels.ts';
|
|
4
5
|
import { discoverSkills, type SkillRecord } from '../agent/skill-discovery.ts';
|
|
5
6
|
import {
|
|
6
7
|
AgentSkillRegistry,
|
|
@@ -32,6 +33,20 @@ interface ParsedOptions {
|
|
|
32
33
|
readonly positionals: readonly string[];
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
const LOCAL_LIBRARY_VALUE_OPTIONS = [
|
|
37
|
+
'name',
|
|
38
|
+
'description',
|
|
39
|
+
'body',
|
|
40
|
+
'procedure',
|
|
41
|
+
'tags',
|
|
42
|
+
'triggers',
|
|
43
|
+
'requires-env',
|
|
44
|
+
'requires-command',
|
|
45
|
+
'requires-commands',
|
|
46
|
+
'skills',
|
|
47
|
+
'provenance',
|
|
48
|
+
] as const;
|
|
49
|
+
|
|
35
50
|
function jsonOrText(runtime: CliCommandRuntime, value: unknown, text: string): string {
|
|
36
51
|
return runtime.cli.flags.outputFormat === 'json' ? JSON.stringify(value, null, 2) : text;
|
|
37
52
|
}
|
|
@@ -49,24 +64,30 @@ function failure(runtime: CliCommandRuntime, kind: string, error: string, exitCo
|
|
|
49
64
|
};
|
|
50
65
|
}
|
|
51
66
|
|
|
52
|
-
function parseOptions(args: readonly string[]): ParsedOptions {
|
|
67
|
+
function parseOptions(args: readonly string[], valueOptions: readonly string[] = LOCAL_LIBRARY_VALUE_OPTIONS): ParsedOptions {
|
|
68
|
+
const valued = new Set(valueOptions);
|
|
53
69
|
const values = new Map<string, string>();
|
|
54
70
|
const flags = new Set<string>();
|
|
55
71
|
const positionals: string[] = [];
|
|
56
72
|
for (let index = 0; index < args.length; index += 1) {
|
|
57
73
|
const arg = args[index] ?? '';
|
|
74
|
+
if (arg === '--') {
|
|
75
|
+
positionals.push(...args.slice(index + 1));
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
58
78
|
if (!arg.startsWith('--')) {
|
|
59
79
|
positionals.push(arg);
|
|
60
80
|
continue;
|
|
61
81
|
}
|
|
62
|
-
const
|
|
82
|
+
const raw = arg.slice(2);
|
|
83
|
+
const equalIndex = raw.indexOf('=');
|
|
63
84
|
if (equalIndex >= 0) {
|
|
64
|
-
values.set(
|
|
85
|
+
values.set(raw.slice(0, equalIndex), raw.slice(equalIndex + 1));
|
|
65
86
|
continue;
|
|
66
87
|
}
|
|
67
|
-
const name =
|
|
88
|
+
const name = raw;
|
|
68
89
|
const next = args[index + 1];
|
|
69
|
-
if (next !== undefined && !next.startsWith('--')) {
|
|
90
|
+
if (next !== undefined && (valued.has(name) || !next.startsWith('--'))) {
|
|
70
91
|
values.set(name, next);
|
|
71
92
|
index += 1;
|
|
72
93
|
continue;
|
|
@@ -122,8 +143,8 @@ function shellPaths(runtime: CliCommandRuntime): ReturnType<typeof createShellPa
|
|
|
122
143
|
|
|
123
144
|
function summarizePersona(persona: AgentPersonaRecord, activePersonaId: string | null): string {
|
|
124
145
|
const active = persona.id === activePersonaId ? 'active' : 'available';
|
|
125
|
-
const tags = persona.tags.length > 0 ? `
|
|
126
|
-
return ` ${persona.id} ${active} ${persona.reviewState} ${persona.name} - ${persona.description}${tags}`;
|
|
146
|
+
const tags = persona.tags.length > 0 ? ` tags ${persona.tags.join(', ')}` : '';
|
|
147
|
+
return ` ${persona.id} ${active} ${formatAgentRecordReviewState(persona.reviewState)} ${persona.name} - ${persona.description}${tags}`;
|
|
127
148
|
}
|
|
128
149
|
|
|
129
150
|
function renderPersonaList(title: string, path: string, personas: readonly AgentPersonaRecord[], activePersonaId: string | null): string {
|
|
@@ -131,12 +152,13 @@ function renderPersonaList(title: string, path: string, personas: readonly Agent
|
|
|
131
152
|
return [
|
|
132
153
|
title,
|
|
133
154
|
' No local Agent personas yet.',
|
|
155
|
+
' No Agent-local personas yet.',
|
|
134
156
|
' Create one with: goodvibes-agent personas create --name <name> --description <summary> --body <instructions>',
|
|
135
157
|
].join('\n');
|
|
136
158
|
}
|
|
137
159
|
return [
|
|
138
160
|
`${title} (${personas.length})`,
|
|
139
|
-
` store
|
|
161
|
+
` store ${path}`,
|
|
140
162
|
...personas.map((persona) => summarizePersona(persona, activePersonaId)),
|
|
141
163
|
].join('\n');
|
|
142
164
|
}
|
|
@@ -144,11 +166,10 @@ function renderPersonaList(title: string, path: string, personas: readonly Agent
|
|
|
144
166
|
function renderPersona(persona: AgentPersonaRecord, activePersonaId: string | null): string {
|
|
145
167
|
return [
|
|
146
168
|
`Persona ${persona.name}`,
|
|
147
|
-
` id
|
|
169
|
+
` id ${persona.id}`,
|
|
148
170
|
` active: ${persona.id === activePersonaId ? 'yes' : 'no'}`,
|
|
149
|
-
` review: ${persona.reviewState}`,
|
|
150
|
-
`
|
|
151
|
-
` provenance: ${persona.provenance}`,
|
|
171
|
+
` review: ${formatAgentRecordReviewState(persona.reviewState)}`,
|
|
172
|
+
` origin: ${formatAgentRecordOrigin(persona.source, persona.provenance)}`,
|
|
152
173
|
` tags: ${persona.tags.join(', ') || '(none)'}`,
|
|
153
174
|
` triggers: ${persona.triggers.join(', ') || '(manual)'}`,
|
|
154
175
|
` created: ${persona.createdAt}`,
|
|
@@ -165,7 +186,7 @@ function summarizeDiscoveredPersona(persona: DiscoveredPersonaRecord): string {
|
|
|
165
186
|
const description = persona.description ? ` - ${persona.description}` : '';
|
|
166
187
|
return [
|
|
167
188
|
` ${persona.name} ${persona.origin}${description}`,
|
|
168
|
-
` path
|
|
189
|
+
` path ${persona.path}`,
|
|
169
190
|
].join('\n');
|
|
170
191
|
}
|
|
171
192
|
|
|
@@ -207,10 +228,10 @@ function discoveredPersonaFrontmatterList(persona: DiscoveredPersonaRecord, key:
|
|
|
207
228
|
|
|
208
229
|
function summarizeSkill(skill: AgentSkillRecord): string {
|
|
209
230
|
const enabled = skill.enabled ? 'enabled' : 'disabled';
|
|
210
|
-
const tags = skill.tags.length > 0 ? `
|
|
231
|
+
const tags = skill.tags.length > 0 ? ` tags ${skill.tags.join(', ')}` : '';
|
|
211
232
|
const readiness = evaluateAgentSkillReadiness(skill);
|
|
212
233
|
const ready = readiness.ready ? 'ready' : `needs ${readiness.missing.map(formatAgentSkillRequirement).join(',')}`;
|
|
213
|
-
return ` ${skill.id} ${enabled} ${skill.reviewState} ${ready} ${skill.name} - ${skill.description}${tags}`;
|
|
234
|
+
return ` ${skill.id} ${enabled} ${formatAgentRecordReviewState(skill.reviewState)} ${ready} ${skill.name} - ${skill.description}${tags}`;
|
|
214
235
|
}
|
|
215
236
|
|
|
216
237
|
function summarizeBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentSkillRecord[]): string {
|
|
@@ -221,31 +242,32 @@ function summarizeBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentS
|
|
|
221
242
|
...readiness.missingSkillIds.map((skillId) => `skill:${skillId}`),
|
|
222
243
|
];
|
|
223
244
|
const ready = readiness.ready ? 'ready' : `needs ${missing.join(',')}`;
|
|
224
|
-
return ` ${bundle.id} ${enabled} ${bundle.reviewState} ${ready} ${bundle.name} - ${bundle.description} skills
|
|
245
|
+
return ` ${bundle.id} ${enabled} ${formatAgentRecordReviewState(bundle.reviewState)} ${ready} ${bundle.name} - ${bundle.description} skills ${bundle.skillIds.join(',')}`;
|
|
225
246
|
}
|
|
226
247
|
|
|
227
248
|
function renderSkillList(title: string, path: string, skills: readonly AgentSkillRecord[], emptyMessage?: string): string {
|
|
228
249
|
if (skills.length === 0) {
|
|
229
250
|
return [
|
|
230
251
|
title,
|
|
231
|
-
|
|
252
|
+
emptyMessage ? '' : ' No local Agent skills yet.',
|
|
253
|
+
` ${emptyMessage ?? 'No Agent-local skills yet.'}`,
|
|
232
254
|
emptyMessage ? '' : ' Create one with: goodvibes-agent skills create --name <name> --description <summary> --procedure <steps>',
|
|
233
255
|
].filter(Boolean).join('\n');
|
|
234
256
|
}
|
|
235
257
|
return [
|
|
236
258
|
`${title} (${skills.length})`,
|
|
237
|
-
` store
|
|
259
|
+
` store ${path}`,
|
|
238
260
|
...skills.map(summarizeSkill),
|
|
239
261
|
].join('\n');
|
|
240
262
|
}
|
|
241
263
|
|
|
242
264
|
function summarizeDiscoveredSkill(skill: SkillRecord): string {
|
|
243
265
|
const description = skill.description ? ` - ${skill.description}` : '';
|
|
244
|
-
const dependencies = skill.dependencies.length > 0 ? `
|
|
245
|
-
const includes = skill.includes.length > 0 ? `
|
|
266
|
+
const dependencies = skill.dependencies.length > 0 ? ` dependencies ${skill.dependencies.join(', ')}` : '';
|
|
267
|
+
const includes = skill.includes.length > 0 ? ` includes ${skill.includes.join(', ')}` : '';
|
|
246
268
|
return [
|
|
247
269
|
` ${skill.name} ${skill.origin}${description}${dependencies}${includes}`,
|
|
248
|
-
` path
|
|
270
|
+
` path ${skill.path}`,
|
|
249
271
|
].join('\n');
|
|
250
272
|
}
|
|
251
273
|
|
|
@@ -297,13 +319,13 @@ function renderBundleList(title: string, path: string, bundles: readonly AgentSk
|
|
|
297
319
|
if (bundles.length === 0) {
|
|
298
320
|
return [
|
|
299
321
|
title,
|
|
300
|
-
` ${emptyMessage ?? 'No local
|
|
322
|
+
` ${emptyMessage ?? 'No Agent-local skill bundles yet.'}`,
|
|
301
323
|
emptyMessage ? '' : ' Create one with: goodvibes-agent skills bundle create --name <name> --description <summary> --skills <id,id>',
|
|
302
324
|
].filter(Boolean).join('\n');
|
|
303
325
|
}
|
|
304
326
|
return [
|
|
305
327
|
`${title} (${bundles.length})`,
|
|
306
|
-
` store
|
|
328
|
+
` store ${path}`,
|
|
307
329
|
...bundles.map((bundle) => summarizeBundle(bundle, skills)),
|
|
308
330
|
].join('\n');
|
|
309
331
|
}
|
|
@@ -312,14 +334,13 @@ function renderSkill(skill: AgentSkillRecord): string {
|
|
|
312
334
|
const readiness = evaluateAgentSkillReadiness(skill);
|
|
313
335
|
return [
|
|
314
336
|
`Skill ${skill.name}`,
|
|
315
|
-
` id
|
|
337
|
+
` id ${skill.id}`,
|
|
316
338
|
` enabled: ${skill.enabled ? 'yes' : 'no'}`,
|
|
317
339
|
` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
|
|
318
340
|
` requirements: ${skill.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
|
|
319
341
|
readiness.missing.length > 0 ? ` missing: ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
|
|
320
|
-
` review: ${skill.reviewState}`,
|
|
321
|
-
`
|
|
322
|
-
` provenance: ${skill.provenance}`,
|
|
342
|
+
` review: ${formatAgentRecordReviewState(skill.reviewState)}`,
|
|
343
|
+
` origin: ${formatAgentRecordOrigin(skill.source, skill.provenance)}`,
|
|
323
344
|
` tags: ${skill.tags.join(', ') || '(none)'}`,
|
|
324
345
|
` triggers: ${skill.triggers.join(', ') || '(manual)'}`,
|
|
325
346
|
` created: ${skill.createdAt}`,
|
|
@@ -340,13 +361,12 @@ function renderBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentSkil
|
|
|
340
361
|
];
|
|
341
362
|
return [
|
|
342
363
|
`Skill bundle ${bundle.name}`,
|
|
343
|
-
` id
|
|
364
|
+
` id ${bundle.id}`,
|
|
344
365
|
` enabled: ${bundle.enabled ? 'yes' : 'no'}`,
|
|
345
366
|
` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
|
|
346
367
|
missing.length > 0 ? ` missing: ${missing.join(', ')}` : '',
|
|
347
|
-
` review: ${bundle.reviewState}`,
|
|
348
|
-
`
|
|
349
|
-
` provenance: ${bundle.provenance}`,
|
|
368
|
+
` review: ${formatAgentRecordReviewState(bundle.reviewState)}`,
|
|
369
|
+
` origin: ${formatAgentRecordOrigin(bundle.source, bundle.provenance)}`,
|
|
350
370
|
` skills: ${bundle.skillIds.join(', ')}`,
|
|
351
371
|
` created: ${bundle.createdAt}`,
|
|
352
372
|
` updated: ${bundle.updatedAt}`,
|
|
@@ -398,17 +418,17 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
|
|
|
398
418
|
if (!name) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas import-discovered <name> [--use] --yes', 2);
|
|
399
419
|
const discovered = findDiscoveredPersona(await discoverPersonas(shellPaths(runtime)), name);
|
|
400
420
|
if (!discovered) {
|
|
401
|
-
return failure(runtime, 'persona_discovery_not_found', `Unknown discovered Agent persona
|
|
421
|
+
return failure(runtime, 'persona_discovery_not_found', `Unknown discovered Agent persona ${name}\nRun goodvibes-agent personas discover to inspect available persona files.`, 1);
|
|
402
422
|
}
|
|
403
423
|
if (!hasFlag(options, 'yes')) {
|
|
404
424
|
return success(runtime, 'agent.personas.import_discovered.preview', { persona: discovered }, [
|
|
405
425
|
'Agent persona import preview',
|
|
406
|
-
` name
|
|
407
|
-
` origin
|
|
408
|
-
` path
|
|
409
|
-
` description
|
|
410
|
-
` body characters
|
|
411
|
-
' next
|
|
426
|
+
` name ${discovered.name}`,
|
|
427
|
+
` origin ${discovered.origin}`,
|
|
428
|
+
` path ${discovered.path}`,
|
|
429
|
+
` description ${discovered.description || '(none)'}`,
|
|
430
|
+
` body characters ${discovered.body.length}`,
|
|
431
|
+
' next rerun with --yes to import into the Agent-local persona registry',
|
|
412
432
|
].join('\n'));
|
|
413
433
|
}
|
|
414
434
|
const persona = registry.create({
|
|
@@ -421,7 +441,11 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
|
|
|
421
441
|
provenance: `discovered:${discovered.origin}:${discovered.path}`,
|
|
422
442
|
});
|
|
423
443
|
if (hasFlag(options, 'use')) registry.setActive(persona.id);
|
|
424
|
-
return success(runtime, 'agent.personas.import_discovered', persona,
|
|
444
|
+
return success(runtime, 'agent.personas.import_discovered', persona, [
|
|
445
|
+
`Imported Agent persona ${persona.id}: ${persona.name}${hasFlag(options, 'use') ? ' (active)' : ''}`,
|
|
446
|
+
` name ${persona.name}`,
|
|
447
|
+
` active ${hasFlag(options, 'use') ? 'yes' : 'no'}`,
|
|
448
|
+
].join('\n'));
|
|
425
449
|
}
|
|
426
450
|
if (normalized === 'search' || normalized === 'find') {
|
|
427
451
|
const query = rest.join(' ').trim();
|
|
@@ -432,7 +456,7 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
|
|
|
432
456
|
const id = rest[0];
|
|
433
457
|
if (!id) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas show <id>', 2);
|
|
434
458
|
const persona = registry.get(id);
|
|
435
|
-
if (!persona) return failure(runtime, 'persona_not_found', `Unknown Agent persona
|
|
459
|
+
if (!persona) return failure(runtime, 'persona_not_found', `Unknown Agent persona ${id}`, 1);
|
|
436
460
|
return success(runtime, 'agent.personas.show', persona, renderPersona(persona, snapshot.activePersonaId));
|
|
437
461
|
}
|
|
438
462
|
if (normalized === 'create') {
|
|
@@ -443,10 +467,15 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
|
|
|
443
467
|
body: requiredOption(options, 'body', 'Usage: goodvibes-agent personas create --name <name> --description <summary> --body <instructions>'),
|
|
444
468
|
tags: csvOption(options, 'tags'),
|
|
445
469
|
triggers: csvOption(options, 'triggers'),
|
|
446
|
-
provenance: optionValue(options, 'provenance') ?? '
|
|
470
|
+
provenance: optionValue(options, 'provenance') ?? 'Command',
|
|
447
471
|
});
|
|
448
472
|
if (hasFlag(options, 'use')) registry.setActive(persona.id);
|
|
449
|
-
return success(runtime, 'agent.personas.create', persona,
|
|
473
|
+
return success(runtime, 'agent.personas.create', persona, [
|
|
474
|
+
'Agent persona created',
|
|
475
|
+
` id ${persona.id}`,
|
|
476
|
+
hasFlag(options, 'use') ? ' (active)' : '',
|
|
477
|
+
` active ${hasFlag(options, 'use') ? 'yes' : 'no'}`,
|
|
478
|
+
].filter(Boolean).join('\n'));
|
|
450
479
|
}
|
|
451
480
|
if (normalized === 'update') {
|
|
452
481
|
const id = rest[0];
|
|
@@ -460,13 +489,19 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
|
|
|
460
489
|
triggers: csvOption(options, 'triggers'),
|
|
461
490
|
provenance: optionValue(options, 'provenance'),
|
|
462
491
|
});
|
|
463
|
-
return success(runtime, 'agent.personas.update', persona,
|
|
492
|
+
return success(runtime, 'agent.personas.update', persona, [
|
|
493
|
+
'Agent persona updated',
|
|
494
|
+
` id ${persona.id}`,
|
|
495
|
+
].join('\n'));
|
|
464
496
|
}
|
|
465
497
|
if (normalized === 'use') {
|
|
466
498
|
const id = rest[0];
|
|
467
499
|
if (!id) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas use <id>', 2);
|
|
468
500
|
const persona = registry.setActive(id);
|
|
469
|
-
return success(runtime, 'agent.personas.use', persona,
|
|
501
|
+
return success(runtime, 'agent.personas.use', persona, [
|
|
502
|
+
'Active Agent persona',
|
|
503
|
+
` id ${persona.id}`,
|
|
504
|
+
].join('\n'));
|
|
470
505
|
}
|
|
471
506
|
if (normalized === 'clear') {
|
|
472
507
|
registry.clearActive();
|
|
@@ -476,13 +511,19 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
|
|
|
476
511
|
const id = rest[0];
|
|
477
512
|
if (!id) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas review <id>', 2);
|
|
478
513
|
const persona = registry.markReviewed(id);
|
|
479
|
-
return success(runtime, 'agent.personas.review', persona,
|
|
514
|
+
return success(runtime, 'agent.personas.review', persona, [
|
|
515
|
+
'Agent persona reviewed',
|
|
516
|
+
` id ${persona.id}`,
|
|
517
|
+
].join('\n'));
|
|
480
518
|
}
|
|
481
519
|
if (normalized === 'stale') {
|
|
482
520
|
const id = rest[0];
|
|
483
521
|
if (!id || rest.length < 2) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas stale <id> <reason>', 2);
|
|
484
522
|
const persona = registry.markStale(id, rest.slice(1).join(' '));
|
|
485
|
-
return success(runtime, 'agent.personas.stale', persona,
|
|
523
|
+
return success(runtime, 'agent.personas.stale', persona, [
|
|
524
|
+
'Agent persona marked stale',
|
|
525
|
+
` id ${persona.id}`,
|
|
526
|
+
].join('\n'));
|
|
486
527
|
}
|
|
487
528
|
if (normalized === 'delete' || normalized === 'remove' || normalized === 'rm') {
|
|
488
529
|
const options = parseOptions(rest);
|
|
@@ -490,7 +531,10 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
|
|
|
490
531
|
if (!id) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas delete <id> --yes', 2);
|
|
491
532
|
if (!hasFlag(options, 'yes')) return failure(runtime, 'confirmation_required', `Refusing to delete Agent persona ${id} without --yes.`, 2);
|
|
492
533
|
const persona = registry.deletePersona(id);
|
|
493
|
-
return success(runtime, 'agent.personas.delete', persona,
|
|
534
|
+
return success(runtime, 'agent.personas.delete', persona, [
|
|
535
|
+
`Agent persona deleted: ${id}`,
|
|
536
|
+
` id ${persona.id}`,
|
|
537
|
+
].join('\n'));
|
|
494
538
|
}
|
|
495
539
|
return failure(runtime, 'invalid_persona_command', usagePersonas(), 2);
|
|
496
540
|
} catch (error) {
|
|
@@ -520,7 +564,7 @@ function skillPayloadFromOptions(options: ParsedOptions): {
|
|
|
520
564
|
commands: csvOption(options, 'requires-command') ?? csvOption(options, 'requires-commands'),
|
|
521
565
|
}),
|
|
522
566
|
enabled: hasFlag(options, 'enabled') ? true : undefined,
|
|
523
|
-
provenance: optionValue(options, 'provenance') ?? '
|
|
567
|
+
provenance: optionValue(options, 'provenance') ?? 'Command',
|
|
524
568
|
};
|
|
525
569
|
}
|
|
526
570
|
|
|
@@ -538,7 +582,7 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
|
|
|
538
582
|
}
|
|
539
583
|
if (normalized === 'attention' || normalized === 'needs-setup') {
|
|
540
584
|
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
|
|
585
|
+
return success(runtime, 'agent.skills.bundles.attention', { path: snapshot.path, bundles }, renderBundleList('Agent skill bundles needing setup', snapshot.path, bundles, snapshot.skills, 'No Agent-local skill bundles need setup.'));
|
|
542
586
|
}
|
|
543
587
|
if (normalized === 'search' || normalized === 'find') {
|
|
544
588
|
const query = rest.join(' ').trim();
|
|
@@ -549,7 +593,7 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
|
|
|
549
593
|
const id = rest[0];
|
|
550
594
|
if (!id) return failure(runtime, 'invalid_skill_bundle_command', 'Usage: goodvibes-agent skills bundle show <id>', 2);
|
|
551
595
|
const bundle = registry.getBundle(id);
|
|
552
|
-
if (!bundle) return failure(runtime, 'skill_bundle_not_found', `Unknown Agent skill bundle
|
|
596
|
+
if (!bundle) return failure(runtime, 'skill_bundle_not_found', `Unknown Agent skill bundle ${id}`, 1);
|
|
553
597
|
return success(runtime, 'agent.skills.bundles.show', bundle, renderBundle(bundle, snapshot.skills));
|
|
554
598
|
}
|
|
555
599
|
if (normalized === 'create') {
|
|
@@ -560,9 +604,12 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
|
|
|
560
604
|
description: requiredOption(options, 'description', usage),
|
|
561
605
|
skillIds: requiredOption(options, 'skills', usage).split(',').map((entry) => entry.trim()).filter(Boolean),
|
|
562
606
|
enabled: hasFlag(options, 'enabled'),
|
|
563
|
-
provenance: optionValue(options, 'provenance') ?? '
|
|
607
|
+
provenance: optionValue(options, 'provenance') ?? 'Command',
|
|
564
608
|
});
|
|
565
|
-
return success(runtime, 'agent.skills.bundles.create', bundle,
|
|
609
|
+
return success(runtime, 'agent.skills.bundles.create', bundle, [
|
|
610
|
+
'Agent skill bundle created',
|
|
611
|
+
` id ${bundle.id}`,
|
|
612
|
+
].join('\n'));
|
|
566
613
|
}
|
|
567
614
|
if (normalized === 'update') {
|
|
568
615
|
const id = rest[0];
|
|
@@ -574,25 +621,37 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
|
|
|
574
621
|
skillIds: csvOption(options, 'skills'),
|
|
575
622
|
provenance: optionValue(options, 'provenance'),
|
|
576
623
|
});
|
|
577
|
-
return success(runtime, 'agent.skills.bundles.update', bundle,
|
|
624
|
+
return success(runtime, 'agent.skills.bundles.update', bundle, [
|
|
625
|
+
'Agent skill bundle updated',
|
|
626
|
+
` id ${bundle.id}`,
|
|
627
|
+
].join('\n'));
|
|
578
628
|
}
|
|
579
629
|
if (normalized === 'enable' || normalized === 'disable') {
|
|
580
630
|
const id = rest[0];
|
|
581
631
|
if (!id) return failure(runtime, 'invalid_skill_bundle_command', `Usage: goodvibes-agent skills bundle ${normalized} <id>`, 2);
|
|
582
632
|
const bundle = registry.setBundleEnabled(id, normalized === 'enable');
|
|
583
|
-
return success(runtime, `agent.skills.bundles.${normalized}`, bundle,
|
|
633
|
+
return success(runtime, `agent.skills.bundles.${normalized}`, bundle, [
|
|
634
|
+
`Agent skill bundle ${normalized === 'enable' ? 'enabled' : 'disabled'}`,
|
|
635
|
+
` id ${bundle.id}`,
|
|
636
|
+
].join('\n'));
|
|
584
637
|
}
|
|
585
638
|
if (normalized === 'review') {
|
|
586
639
|
const id = rest[0];
|
|
587
640
|
if (!id) return failure(runtime, 'invalid_skill_bundle_command', 'Usage: goodvibes-agent skills bundle review <id>', 2);
|
|
588
641
|
const bundle = registry.markBundleReviewed(id);
|
|
589
|
-
return success(runtime, 'agent.skills.bundles.review', bundle,
|
|
642
|
+
return success(runtime, 'agent.skills.bundles.review', bundle, [
|
|
643
|
+
'Agent skill bundle reviewed',
|
|
644
|
+
` id ${bundle.id}`,
|
|
645
|
+
].join('\n'));
|
|
590
646
|
}
|
|
591
647
|
if (normalized === 'stale') {
|
|
592
648
|
const id = rest[0];
|
|
593
649
|
if (!id || rest.length < 2) return failure(runtime, 'invalid_skill_bundle_command', 'Usage: goodvibes-agent skills bundle stale <id> <reason>', 2);
|
|
594
650
|
const bundle = registry.markBundleStale(id, rest.slice(1).join(' '));
|
|
595
|
-
return success(runtime, 'agent.skills.bundles.stale', bundle,
|
|
651
|
+
return success(runtime, 'agent.skills.bundles.stale', bundle, [
|
|
652
|
+
'Agent skill bundle marked stale',
|
|
653
|
+
` id ${bundle.id}`,
|
|
654
|
+
].join('\n'));
|
|
596
655
|
}
|
|
597
656
|
if (normalized === 'delete' || normalized === 'remove' || normalized === 'rm') {
|
|
598
657
|
const options = parseOptions(rest);
|
|
@@ -600,7 +659,10 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
|
|
|
600
659
|
if (!id) return failure(runtime, 'invalid_skill_bundle_command', 'Usage: goodvibes-agent skills bundle delete <id> --yes', 2);
|
|
601
660
|
if (!hasFlag(options, 'yes')) return failure(runtime, 'confirmation_required', `Refusing to delete Agent skill bundle ${id} without --yes.`, 2);
|
|
602
661
|
const bundle = registry.deleteBundle(id);
|
|
603
|
-
return success(runtime, 'agent.skills.bundles.delete', bundle,
|
|
662
|
+
return success(runtime, 'agent.skills.bundles.delete', bundle, [
|
|
663
|
+
'Agent skill bundle deleted',
|
|
664
|
+
` id ${bundle.id}`,
|
|
665
|
+
].join('\n'));
|
|
604
666
|
}
|
|
605
667
|
return failure(runtime, 'invalid_skill_bundle_command', usageBundles(), 2);
|
|
606
668
|
} catch (error) {
|
|
@@ -629,7 +691,7 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
|
|
|
629
691
|
}
|
|
630
692
|
if (normalized === 'attention' || normalized === 'needs-setup') {
|
|
631
693
|
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
|
|
694
|
+
return success(runtime, 'agent.skills.attention', { path: snapshot.path, skills }, renderSkillList('Agent skills needing setup', snapshot.path, skills, 'No Agent-local skills need setup.'));
|
|
633
695
|
}
|
|
634
696
|
if (normalized === 'discover') {
|
|
635
697
|
const discovered = await discoverSkills(shellPaths(runtime));
|
|
@@ -641,17 +703,17 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
|
|
|
641
703
|
if (!name) return failure(runtime, 'invalid_skill_command', 'Usage: goodvibes-agent skills import-discovered <name> [--enabled] --yes', 2);
|
|
642
704
|
const discovered = findDiscoveredSkill(await discoverSkills(shellPaths(runtime)), name);
|
|
643
705
|
if (!discovered) {
|
|
644
|
-
return failure(runtime, 'skill_discovery_not_found', `Unknown discovered Agent skill
|
|
706
|
+
return failure(runtime, 'skill_discovery_not_found', `Unknown discovered Agent skill ${name}\nRun goodvibes-agent skills discover to inspect available skill files.`, 1);
|
|
645
707
|
}
|
|
646
708
|
if (!hasFlag(options, 'yes')) {
|
|
647
709
|
return success(runtime, 'agent.skills.import_discovered.preview', { skill: discovered }, [
|
|
648
710
|
'Agent skill import preview',
|
|
649
|
-
` name
|
|
650
|
-
` origin
|
|
651
|
-
` path
|
|
652
|
-
` description
|
|
653
|
-
` procedure characters
|
|
654
|
-
' next
|
|
711
|
+
` name ${discovered.name}`,
|
|
712
|
+
` origin ${discovered.origin}`,
|
|
713
|
+
` path ${discovered.path}`,
|
|
714
|
+
` description ${discovered.description || '(none)'}`,
|
|
715
|
+
` procedure characters ${discovered.body.length}`,
|
|
716
|
+
' next rerun with --yes to import into the Agent-local skill registry',
|
|
655
717
|
].join('\n'));
|
|
656
718
|
}
|
|
657
719
|
const skill = registry.create({
|
|
@@ -668,7 +730,11 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
|
|
|
668
730
|
source: 'imported',
|
|
669
731
|
provenance: `discovered:${discovered.origin}:${discovered.path}`,
|
|
670
732
|
});
|
|
671
|
-
return success(runtime, 'agent.skills.import_discovered', skill,
|
|
733
|
+
return success(runtime, 'agent.skills.import_discovered', skill, [
|
|
734
|
+
`Imported Agent skill ${skill.id}: ${skill.name}${skill.enabled ? ' (enabled)' : ''}`,
|
|
735
|
+
` name ${skill.name}`,
|
|
736
|
+
` enabled ${skill.enabled ? 'yes' : 'no'}`,
|
|
737
|
+
].join('\n'));
|
|
672
738
|
}
|
|
673
739
|
if (normalized === 'search' || normalized === 'find') {
|
|
674
740
|
const query = rest.join(' ').trim();
|
|
@@ -679,12 +745,17 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
|
|
|
679
745
|
const id = rest[0];
|
|
680
746
|
if (!id) return failure(runtime, 'invalid_skill_command', 'Usage: goodvibes-agent skills show <id>', 2);
|
|
681
747
|
const skill = registry.get(id);
|
|
682
|
-
if (!skill) return failure(runtime, 'skill_not_found', `Unknown Agent skill
|
|
748
|
+
if (!skill) return failure(runtime, 'skill_not_found', `Unknown Agent skill ${id}`, 1);
|
|
683
749
|
return success(runtime, 'agent.skills.show', skill, renderSkill(skill));
|
|
684
750
|
}
|
|
685
751
|
if (normalized === 'create') {
|
|
686
752
|
const skill = registry.create(skillPayloadFromOptions(parseOptions(rest)));
|
|
687
|
-
return success(runtime, 'agent.skills.create', skill,
|
|
753
|
+
return success(runtime, 'agent.skills.create', skill, [
|
|
754
|
+
'Agent skill created',
|
|
755
|
+
` id ${skill.id}`,
|
|
756
|
+
skill.enabled ? ' (enabled)' : '',
|
|
757
|
+
` enabled ${skill.enabled ? 'yes' : 'no'}`,
|
|
758
|
+
].filter(Boolean).join('\n'));
|
|
688
759
|
}
|
|
689
760
|
if (normalized === 'update') {
|
|
690
761
|
const id = rest[0];
|
|
@@ -704,25 +775,37 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
|
|
|
704
775
|
: undefined,
|
|
705
776
|
provenance: optionValue(options, 'provenance'),
|
|
706
777
|
});
|
|
707
|
-
return success(runtime, 'agent.skills.update', skill,
|
|
778
|
+
return success(runtime, 'agent.skills.update', skill, [
|
|
779
|
+
'Agent skill updated',
|
|
780
|
+
` id ${skill.id}`,
|
|
781
|
+
].join('\n'));
|
|
708
782
|
}
|
|
709
783
|
if (normalized === 'enable' || normalized === 'disable') {
|
|
710
784
|
const id = rest[0];
|
|
711
785
|
if (!id) return failure(runtime, 'invalid_skill_command', `Usage: goodvibes-agent skills ${normalized} <id>`, 2);
|
|
712
786
|
const skill = registry.setEnabled(id, normalized === 'enable');
|
|
713
|
-
return success(runtime, `agent.skills.${normalized}`, skill,
|
|
787
|
+
return success(runtime, `agent.skills.${normalized}`, skill, [
|
|
788
|
+
`Agent skill ${normalized === 'enable' ? 'enabled' : 'disabled'}`,
|
|
789
|
+
` id ${skill.id}`,
|
|
790
|
+
].join('\n'));
|
|
714
791
|
}
|
|
715
792
|
if (normalized === 'review') {
|
|
716
793
|
const id = rest[0];
|
|
717
794
|
if (!id) return failure(runtime, 'invalid_skill_command', 'Usage: goodvibes-agent skills review <id>', 2);
|
|
718
795
|
const skill = registry.markReviewed(id);
|
|
719
|
-
return success(runtime, 'agent.skills.review', skill,
|
|
796
|
+
return success(runtime, 'agent.skills.review', skill, [
|
|
797
|
+
'Agent skill reviewed',
|
|
798
|
+
` id ${skill.id}`,
|
|
799
|
+
].join('\n'));
|
|
720
800
|
}
|
|
721
801
|
if (normalized === 'stale') {
|
|
722
802
|
const id = rest[0];
|
|
723
803
|
if (!id || rest.length < 2) return failure(runtime, 'invalid_skill_command', 'Usage: goodvibes-agent skills stale <id> <reason>', 2);
|
|
724
804
|
const skill = registry.markStale(id, rest.slice(1).join(' '));
|
|
725
|
-
return success(runtime, 'agent.skills.stale', skill,
|
|
805
|
+
return success(runtime, 'agent.skills.stale', skill, [
|
|
806
|
+
'Agent skill marked stale',
|
|
807
|
+
` id ${skill.id}`,
|
|
808
|
+
].join('\n'));
|
|
726
809
|
}
|
|
727
810
|
if (normalized === 'delete' || normalized === 'remove' || normalized === 'rm') {
|
|
728
811
|
const options = parseOptions(rest);
|
|
@@ -730,7 +813,10 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
|
|
|
730
813
|
if (!id) return failure(runtime, 'invalid_skill_command', 'Usage: goodvibes-agent skills delete <id> --yes', 2);
|
|
731
814
|
if (!hasFlag(options, 'yes')) return failure(runtime, 'confirmation_required', `Refusing to delete Agent skill ${id} without --yes.`, 2);
|
|
732
815
|
const skill = registry.deleteSkill(id);
|
|
733
|
-
return success(runtime, 'agent.skills.delete', skill,
|
|
816
|
+
return success(runtime, 'agent.skills.delete', skill, [
|
|
817
|
+
`Agent skill deleted: ${id}`,
|
|
818
|
+
` id ${skill.id}`,
|
|
819
|
+
].join('\n'));
|
|
734
820
|
}
|
|
735
821
|
return failure(runtime, 'invalid_skill_command', usageSkills(), 2);
|
|
736
822
|
} catch (error) {
|