@pellux/goodvibes-agent 0.1.116 → 1.0.0
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 +48 -661
- package/README.md +64 -57
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +199180 -192185
- package/docs/README.md +15 -8
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +59 -0
- package/docs/getting-started.md +61 -50
- 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 +48 -11
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +3 -6
- package/src/agent/behavior-discovery-summary.ts +1 -3
- 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-discovery.ts +1 -3
- package/src/agent/persona-registry.ts +19 -16
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +27 -26
- package/src/agent/routine-registry.ts +54 -14
- 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 +35 -33
- package/src/agent/routine-schedule-receipts.ts +29 -27
- package/src/agent/runtime-profile-starters.ts +5 -5
- package/src/agent/runtime-profile.ts +91 -12
- package/src/agent/skill-registry.ts +210 -32
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +40 -34
- 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 +14 -9
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/entrypoint.ts +16 -7
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +54 -29
- package/src/cli/local-library-command.ts +203 -83
- package/src/cli/management-commands.ts +105 -68
- package/src/cli/management.ts +55 -74
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -3
- package/src/cli/profiles-command.ts +166 -31
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +176 -40
- package/src/cli/service-posture.ts +16 -16
- package/src/cli/status.ts +56 -135
- package/src/core/conversation-message-snapshot.ts +131 -0
- 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 +35 -8
- package/src/input/agent-workspace-basic-command-editor-submission.ts +351 -94
- package/src/input/agent-workspace-basic-command-editors.ts +502 -9
- package/src/input/agent-workspace-categories.ts +423 -51
- package/src/input/agent-workspace-channel-command-editor-submission.ts +83 -0
- package/src/input/agent-workspace-channel-command-editors.ts +65 -0
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +41 -3
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
- package/src/input/agent-workspace-editors.ts +166 -1
- 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-knowledge-query-editor.ts +1 -1
- 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-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -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-editor-submission.ts +232 -0
- package/src/input/agent-workspace-memory-command-editors.ts +180 -0
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +81 -0
- package/src/input/agent-workspace-notify-editor-submission.ts +121 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +208 -0
- package/src/input/agent-workspace-operations-command-editors.ts +196 -0
- package/src/input/agent-workspace-panel-route.ts +43 -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-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-requirements.ts +11 -0
- 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-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 +37 -16
- 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 +162 -21
- 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-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +212 -4
- package/src/input/agent-workspace-voice-media.ts +4 -7
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
- package/src/input/agent-workspace.ts +178 -240
- package/src/input/command-registry.ts +5 -2
- package/src/input/commands/agent-runtime-profile-runtime.ts +126 -37
- package/src/input/commands/agent-skills-runtime.ts +149 -72
- package/src/input/commands/agent-workspace-runtime.ts +23 -6
- package/src/input/commands/brief-runtime.ts +55 -25
- package/src/input/commands/channels-runtime.ts +147 -33
- package/src/input/commands/compat-runtime.ts +32 -0
- 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 +149 -126
- package/src/input/commands/knowledge.ts +82 -60
- package/src/input/commands/local-provider-runtime.ts +43 -21
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +10 -20
- package/src/input/commands/mcp-runtime.ts +63 -46
- 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 -76
- package/src/input/commands/personas-runtime.ts +46 -31
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +35 -98
- package/src/input/commands/product-runtime.ts +2 -2
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +50 -9
- 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 +99 -45
- package/src/input/commands/runtime-services.ts +1 -14
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +6 -11
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +134 -104
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +38 -17
- package/src/input/commands/subscription-runtime.ts +54 -185
- package/src/input/commands/support-bundle-runtime.ts +53 -0
- package/src/input/commands/tasks-runtime.ts +21 -21
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +6 -2
- package/src/input/feed-context-factory.ts +2 -2
- 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 -26
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -5
- package/src/input/handler-interactions.ts +9 -36
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +52 -91
- package/src/input/handler-shortcuts.ts +16 -7
- package/src/input/handler.ts +50 -23
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +27 -16
- 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 +62 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +223 -55
- package/src/input/onboarding/onboarding-wizard-steps.ts +59 -35
- package/src/input/onboarding/onboarding-wizard-types.ts +4 -1
- package/src/input/onboarding/onboarding-wizard.ts +87 -2
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +21 -4
- package/src/input/settings-modal-agent-policy.ts +6 -6
- 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 +20 -66
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -10
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +4 -4
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +3 -12
- package/src/panels/builtin/session.ts +32 -24
- package/src/panels/builtin/shared.ts +7 -7
- 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 +19 -12
- 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 +48 -7
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +44 -20
- 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 +6 -6
- package/src/panels/system-messages-panel.ts +3 -3
- package/src/panels/tasks-panel.ts +21 -14
- 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 +3 -3
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +254 -57
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/block-actions.ts +1 -3
- 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 +112 -34
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +176 -43
- package/src/renderer/model-picker-overlay.ts +58 -3
- package/src/renderer/model-workspace.ts +104 -22
- package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +21 -5
- 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 +88 -55
- package/src/renderer/system-message.ts +1 -1
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +129 -0
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +11 -8
- package/src/runtime/bootstrap-core.ts +23 -65
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +46 -8
- package/src/runtime/bootstrap.ts +36 -46
- package/src/runtime/connected-host-auth.ts +47 -0
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -5
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +288 -74
- package/src/runtime/onboarding/derivation.ts +10 -13
- package/src/runtime/onboarding/snapshot.ts +2 -17
- package/src/runtime/onboarding/types.ts +34 -20
- package/src/runtime/onboarding/verify.ts +105 -4
- package/src/runtime/operator-token-cleanup.ts +3 -3
- package/src/runtime/services.ts +95 -11
- 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/service-settings-sync.ts +7 -7
- package/src/shell/ui-openers.ts +17 -38
- 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 +279 -73
- 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 +13 -15
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/docs/connected-services.md +0 -51
- package/src/cli/package-verification.ts +0 -274
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -17
- 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,5 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AgentSkillRegistry,
|
|
3
|
+
buildAgentSkillRequirements,
|
|
4
|
+
evaluateAgentSkillBundleReadiness,
|
|
5
|
+
evaluateAgentSkillReadiness,
|
|
6
|
+
formatAgentSkillRequirement,
|
|
7
|
+
type AgentSkillBundleRecord,
|
|
8
|
+
type AgentSkillRecord,
|
|
9
|
+
} from '../../agent/skill-registry.ts';
|
|
2
10
|
import { discoverSkills, type SkillRecord } from '../../agent/skill-discovery.ts';
|
|
11
|
+
import { formatAgentRecordOrigin, formatAgentRecordReviewState } from '../../agent/record-labels.ts';
|
|
3
12
|
import type { CommandContext, CommandRegistry } from '../command-registry.ts';
|
|
4
13
|
import { requireShellPaths } from './runtime-services.ts';
|
|
5
14
|
|
|
@@ -50,35 +59,56 @@ function requiredFlag(flags: ReadonlyMap<string, string>, key: string): string {
|
|
|
50
59
|
return value;
|
|
51
60
|
}
|
|
52
61
|
|
|
62
|
+
function formatSkillReceipt(title: string, record: { readonly id: string; readonly name: string }, extra: readonly string[] = []): string {
|
|
63
|
+
return [
|
|
64
|
+
`${title} ${record.id}`,
|
|
65
|
+
` id ${record.id}`,
|
|
66
|
+
` name ${record.name}`,
|
|
67
|
+
...extra,
|
|
68
|
+
].join('\n');
|
|
69
|
+
}
|
|
70
|
+
|
|
53
71
|
function summarizeSkill(skill: AgentSkillRecord): string {
|
|
54
72
|
const enabled = skill.enabled ? 'enabled' : 'disabled';
|
|
55
|
-
const tags = skill.tags.length > 0 ? ` tags
|
|
56
|
-
|
|
73
|
+
const tags = skill.tags.length > 0 ? ` tags ${skill.tags.join(', ')}` : '';
|
|
74
|
+
const readiness = evaluateAgentSkillReadiness(skill);
|
|
75
|
+
const review = formatAgentRecordReviewState(skill.reviewState);
|
|
76
|
+
const ready = readiness.ready ? 'ready' : `needs ${readiness.missing.map(formatAgentSkillRequirement).join(',')}`;
|
|
77
|
+
return ` ${skill.id} ${enabled} ${review} ${ready} ${skill.name} - ${skill.description}${tags}`;
|
|
57
78
|
}
|
|
58
79
|
|
|
59
|
-
function summarizeBundle(bundle: AgentSkillBundleRecord): string {
|
|
80
|
+
function summarizeBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentSkillRecord[]): string {
|
|
60
81
|
const enabled = bundle.enabled ? 'enabled' : 'disabled';
|
|
61
|
-
|
|
82
|
+
const readiness = evaluateAgentSkillBundleReadiness(bundle, skills);
|
|
83
|
+
const review = formatAgentRecordReviewState(bundle.reviewState);
|
|
84
|
+
const missing = [
|
|
85
|
+
...readiness.missingRequirements.map(formatAgentSkillRequirement),
|
|
86
|
+
...readiness.missingSkillIds.map((skillId) => `skill ${skillId}`),
|
|
87
|
+
];
|
|
88
|
+
const ready = readiness.ready ? 'ready' : `needs ${missing.join(',')}`;
|
|
89
|
+
return ` ${bundle.id} ${enabled} ${review} ${ready} ${bundle.name} - ${bundle.description} skills ${bundle.skillIds.join(', ')}`;
|
|
62
90
|
}
|
|
63
91
|
|
|
64
|
-
function renderList(title: string, registry: AgentSkillRegistry, skills: readonly AgentSkillRecord[]): string {
|
|
92
|
+
function renderList(title: string, registry: AgentSkillRegistry, skills: readonly AgentSkillRecord[], emptyMessage?: string): string {
|
|
65
93
|
const snapshot = registry.snapshot();
|
|
66
94
|
if (skills.length === 0) {
|
|
67
|
-
return
|
|
95
|
+
return emptyMessage
|
|
96
|
+
? `${title}\n ${emptyMessage}`
|
|
97
|
+
: `${title}\n No Agent-local skills yet. Create one with /skills create --name <name> --description <summary> --procedure <steps>.`;
|
|
68
98
|
}
|
|
69
99
|
return [
|
|
70
100
|
`${title} (${skills.length})`,
|
|
71
|
-
` store
|
|
72
|
-
` enabled
|
|
101
|
+
` store ${snapshot.path}`,
|
|
102
|
+
` enabled ${snapshot.enabledSkills.length}`,
|
|
73
103
|
...skills.map(summarizeSkill),
|
|
74
104
|
].join('\n');
|
|
75
105
|
}
|
|
76
106
|
|
|
77
107
|
function summarizeDiscoveredSkill(skill: SkillRecord): string {
|
|
78
108
|
const description = skill.description ? ` - ${skill.description}` : '';
|
|
79
|
-
const dependencies = skill.dependencies.length > 0 ? ` deps
|
|
80
|
-
const includes = skill.includes.length > 0 ? ` includes
|
|
81
|
-
return ` ${skill.name} ${skill.origin}${description}${dependencies}${includes}\n path
|
|
109
|
+
const dependencies = skill.dependencies.length > 0 ? ` deps ${skill.dependencies.join(', ')}` : '';
|
|
110
|
+
const includes = skill.includes.length > 0 ? ` includes ${skill.includes.join(', ')}` : '';
|
|
111
|
+
return ` ${skill.name} ${skill.origin}${description}${dependencies}${includes}\n path ${skill.path}`;
|
|
82
112
|
}
|
|
83
113
|
|
|
84
114
|
function renderDiscoveredSkills(skills: readonly SkillRecord[]): string {
|
|
@@ -93,7 +123,7 @@ function renderDiscoveredSkills(skills: readonly SkillRecord[]): string {
|
|
|
93
123
|
`Discovered Agent skill files (${skills.length})`,
|
|
94
124
|
...skills.map(summarizeDiscoveredSkill),
|
|
95
125
|
'',
|
|
96
|
-
'Import one with: /
|
|
126
|
+
'Import one with: /skills import-discovered <name> --yes',
|
|
97
127
|
].join('\n');
|
|
98
128
|
}
|
|
99
129
|
|
|
@@ -120,27 +150,35 @@ function frontmatterList(skill: SkillRecord, key: string): readonly string[] {
|
|
|
120
150
|
return splitList(value);
|
|
121
151
|
}
|
|
122
152
|
|
|
153
|
+
function frontmatterAnyList(skill: SkillRecord, keys: readonly string[]): readonly string[] {
|
|
154
|
+
for (const key of keys) {
|
|
155
|
+
const values = frontmatterList(skill, key);
|
|
156
|
+
if (values.length > 0) return values;
|
|
157
|
+
}
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
|
|
123
161
|
async function importDiscoveredSkill(args: readonly string[], ctx: CommandContext, skillRegistry: AgentSkillRegistry): Promise<void> {
|
|
124
162
|
const parsed = parseSkillArgs(args);
|
|
125
163
|
const name = parsed.rest.join(' ').trim();
|
|
126
164
|
if (!name) {
|
|
127
|
-
ctx.print('Usage: /
|
|
165
|
+
ctx.print('Usage: /skills import-discovered <name> [--enabled] --yes');
|
|
128
166
|
return;
|
|
129
167
|
}
|
|
130
168
|
const discovered = findDiscoveredSkill(await discoverSkills(requireShellPaths(ctx)), name);
|
|
131
169
|
if (!discovered) {
|
|
132
|
-
ctx.print(`Unknown discovered Agent skill
|
|
170
|
+
ctx.print(`Unknown discovered Agent skill ${name}\nRun /skills discover to inspect available skill files.`);
|
|
133
171
|
return;
|
|
134
172
|
}
|
|
135
173
|
if (!parsed.yes) {
|
|
136
174
|
ctx.print([
|
|
137
175
|
'Agent skill import preview',
|
|
138
|
-
` name
|
|
139
|
-
` origin
|
|
140
|
-
` path
|
|
141
|
-
` description
|
|
142
|
-
` procedure characters
|
|
143
|
-
' next
|
|
176
|
+
` name ${discovered.name}`,
|
|
177
|
+
` origin ${discovered.origin}`,
|
|
178
|
+
` path ${discovered.path}`,
|
|
179
|
+
` description ${discovered.description || '(none)'}`,
|
|
180
|
+
` procedure characters ${discovered.body.length}`,
|
|
181
|
+
' next rerun with --yes to import into the Agent-local skill registry',
|
|
144
182
|
].join('\n'));
|
|
145
183
|
return;
|
|
146
184
|
}
|
|
@@ -150,35 +188,44 @@ async function importDiscoveredSkill(args: readonly string[], ctx: CommandContex
|
|
|
150
188
|
procedure: discovered.body,
|
|
151
189
|
triggers: frontmatterList(discovered, 'triggers'),
|
|
152
190
|
tags: frontmatterList(discovered, 'tags'),
|
|
191
|
+
requirements: buildAgentSkillRequirements({
|
|
192
|
+
env: frontmatterAnyList(discovered, ['requiresEnv', 'requires-env', 'requires_env']),
|
|
193
|
+
commands: frontmatterAnyList(discovered, ['requiresCommands', 'requires-commands', 'requires_commands', 'commands']),
|
|
194
|
+
}),
|
|
153
195
|
enabled: parsed.flags.get('enabled') === 'true',
|
|
154
196
|
source: 'imported',
|
|
155
|
-
provenance: `
|
|
197
|
+
provenance: `Imported file (${discovered.origin}): ${discovered.path}`,
|
|
156
198
|
});
|
|
157
|
-
ctx.print(
|
|
199
|
+
ctx.print(formatSkillReceipt('Imported Agent skill', skill, [` enabled ${skill.enabled ? 'yes' : 'no'}`]));
|
|
158
200
|
}
|
|
159
201
|
|
|
160
|
-
function renderBundleList(title: string, registry: AgentSkillRegistry, bundles: readonly AgentSkillBundleRecord[]): string {
|
|
202
|
+
function renderBundleList(title: string, registry: AgentSkillRegistry, bundles: readonly AgentSkillBundleRecord[], emptyMessage?: string): string {
|
|
161
203
|
const snapshot = registry.snapshot();
|
|
162
204
|
if (bundles.length === 0) {
|
|
163
|
-
return
|
|
205
|
+
return emptyMessage
|
|
206
|
+
? `${title}\n ${emptyMessage}`
|
|
207
|
+
: `${title}\n No Agent-local skill bundles yet. Create one with /skills bundle create --name <name> --description <summary> --skills <id,id>.`;
|
|
164
208
|
}
|
|
165
209
|
return [
|
|
166
210
|
`${title} (${bundles.length})`,
|
|
167
|
-
` store
|
|
211
|
+
` store ${snapshot.path}`,
|
|
168
212
|
` enabled bundles: ${snapshot.enabledBundles.length}`,
|
|
169
213
|
` active skills: ${snapshot.activeSkills.length}`,
|
|
170
|
-
...bundles.map(summarizeBundle),
|
|
214
|
+
...bundles.map((bundle) => summarizeBundle(bundle, snapshot.skills)),
|
|
171
215
|
].join('\n');
|
|
172
216
|
}
|
|
173
217
|
|
|
174
218
|
function renderSkill(skill: AgentSkillRecord): string {
|
|
219
|
+
const readiness = evaluateAgentSkillReadiness(skill);
|
|
175
220
|
return [
|
|
176
221
|
`Skill ${skill.name}`,
|
|
177
|
-
` id
|
|
222
|
+
` id ${skill.id}`,
|
|
178
223
|
` enabled: ${skill.enabled ? 'yes' : 'no'}`,
|
|
179
|
-
`
|
|
180
|
-
`
|
|
181
|
-
`
|
|
224
|
+
` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
|
|
225
|
+
` requirements: ${skill.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
|
|
226
|
+
readiness.missing.length > 0 ? ` missing: ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
|
|
227
|
+
` review: ${formatAgentRecordReviewState(skill.reviewState)}`,
|
|
228
|
+
` origin: ${formatAgentRecordOrigin(skill.source, skill.provenance)}`,
|
|
182
229
|
` tags: ${skill.tags.join(', ') || '(none)'}`,
|
|
183
230
|
` triggers: ${skill.triggers.join(', ') || '(manual)'}`,
|
|
184
231
|
` created: ${skill.createdAt}`,
|
|
@@ -195,13 +242,19 @@ function renderBundle(bundle: AgentSkillBundleRecord, registry: AgentSkillRegist
|
|
|
195
242
|
const skills = bundle.skillIds
|
|
196
243
|
.map((skillId) => registry.get(skillId))
|
|
197
244
|
.filter((skill): skill is AgentSkillRecord => skill !== null);
|
|
245
|
+
const readiness = evaluateAgentSkillBundleReadiness(bundle, registry.snapshot().skills);
|
|
246
|
+
const missing = [
|
|
247
|
+
...readiness.missingRequirements.map(formatAgentSkillRequirement),
|
|
248
|
+
...readiness.missingSkillIds.map((skillId) => `skill ${skillId}`),
|
|
249
|
+
];
|
|
198
250
|
return [
|
|
199
251
|
`Skill Bundle ${bundle.name}`,
|
|
200
|
-
` id
|
|
252
|
+
` id ${bundle.id}`,
|
|
201
253
|
` enabled: ${bundle.enabled ? 'yes' : 'no'}`,
|
|
202
|
-
`
|
|
203
|
-
`
|
|
204
|
-
`
|
|
254
|
+
` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
|
|
255
|
+
missing.length > 0 ? ` missing: ${missing.join(', ')}` : '',
|
|
256
|
+
` review: ${formatAgentRecordReviewState(bundle.reviewState)}`,
|
|
257
|
+
` origin: ${formatAgentRecordOrigin(bundle.source, bundle.provenance)}`,
|
|
205
258
|
` skills: ${bundle.skillIds.join(', ')}`,
|
|
206
259
|
` created: ${bundle.createdAt}`,
|
|
207
260
|
` updated: ${bundle.updatedAt}`,
|
|
@@ -214,7 +267,10 @@ function renderBundle(bundle: AgentSkillBundleRecord, registry: AgentSkillRegist
|
|
|
214
267
|
}
|
|
215
268
|
|
|
216
269
|
function printError(ctx: CommandContext, error: unknown): void {
|
|
217
|
-
ctx.print(
|
|
270
|
+
ctx.print([
|
|
271
|
+
'Error',
|
|
272
|
+
` message ${error instanceof Error ? error.message : String(error)}`,
|
|
273
|
+
].join('\n'));
|
|
218
274
|
}
|
|
219
275
|
|
|
220
276
|
function runBundleCommand(args: readonly string[], ctx: CommandContext, skillRegistry: AgentSkillRegistry): void {
|
|
@@ -228,6 +284,12 @@ function runBundleCommand(args: readonly string[], ctx: CommandContext, skillReg
|
|
|
228
284
|
ctx.print(renderBundleList('Enabled Agent Skill Bundles', skillRegistry, snapshot.enabledBundles));
|
|
229
285
|
return;
|
|
230
286
|
}
|
|
287
|
+
if (sub === 'attention' || sub === 'needs-setup') {
|
|
288
|
+
const snapshot = skillRegistry.snapshot();
|
|
289
|
+
const bundles = snapshot.bundles.filter((bundle) => !evaluateAgentSkillBundleReadiness(bundle, snapshot.skills).ready);
|
|
290
|
+
ctx.print(renderBundleList('Agent Skill Bundles needing setup', skillRegistry, bundles, 'No Agent-local skill bundles need setup.'));
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
231
293
|
if (sub === 'search') {
|
|
232
294
|
const query = args.slice(1).join(' ').trim();
|
|
233
295
|
ctx.print(renderBundleList(query ? `Agent Skill Bundles matching "${query}"` : 'Agent Skill Bundles', skillRegistry, skillRegistry.searchBundles(query)));
|
|
@@ -236,11 +298,11 @@ function runBundleCommand(args: readonly string[], ctx: CommandContext, skillReg
|
|
|
236
298
|
if (sub === 'show') {
|
|
237
299
|
const id = args[1];
|
|
238
300
|
if (!id) {
|
|
239
|
-
ctx.print('Usage: /
|
|
301
|
+
ctx.print('Usage: /skills bundle show <id>');
|
|
240
302
|
return;
|
|
241
303
|
}
|
|
242
304
|
const bundle = skillRegistry.getBundle(id);
|
|
243
|
-
ctx.print(bundle ? renderBundle(bundle, skillRegistry) : `Unknown Agent skill bundle
|
|
305
|
+
ctx.print(bundle ? renderBundle(bundle, skillRegistry) : `Unknown Agent skill bundle ${id}`);
|
|
244
306
|
return;
|
|
245
307
|
}
|
|
246
308
|
if (sub === 'create') {
|
|
@@ -251,15 +313,15 @@ function runBundleCommand(args: readonly string[], ctx: CommandContext, skillReg
|
|
|
251
313
|
skillIds: splitList(requiredFlag(parsed.flags, 'skills')),
|
|
252
314
|
enabled: parsed.flags.get('enabled') === 'true',
|
|
253
315
|
source: 'user',
|
|
254
|
-
provenance: '
|
|
316
|
+
provenance: 'Command',
|
|
255
317
|
});
|
|
256
|
-
ctx.print(
|
|
318
|
+
ctx.print(formatSkillReceipt('Created Agent skill bundle', bundle));
|
|
257
319
|
return;
|
|
258
320
|
}
|
|
259
321
|
if (sub === 'update') {
|
|
260
322
|
const id = args[1];
|
|
261
323
|
if (!id) {
|
|
262
|
-
ctx.print('Usage: /
|
|
324
|
+
ctx.print('Usage: /skills bundle update <id> [--name ...] [--description ...] [--skills id,id]');
|
|
263
325
|
return;
|
|
264
326
|
}
|
|
265
327
|
const parsed = parseSkillArgs(args.slice(2));
|
|
@@ -267,46 +329,46 @@ function runBundleCommand(args: readonly string[], ctx: CommandContext, skillReg
|
|
|
267
329
|
name: parsed.flags.get('name'),
|
|
268
330
|
description: parsed.flags.get('description'),
|
|
269
331
|
skillIds: parsed.flags.has('skills') ? splitList(parsed.flags.get('skills')) : undefined,
|
|
270
|
-
provenance: '
|
|
332
|
+
provenance: 'Command',
|
|
271
333
|
});
|
|
272
|
-
ctx.print(
|
|
334
|
+
ctx.print(formatSkillReceipt('Updated Agent skill bundle', updated));
|
|
273
335
|
return;
|
|
274
336
|
}
|
|
275
337
|
if (sub === 'enable' || sub === 'disable') {
|
|
276
338
|
const id = args[1];
|
|
277
339
|
if (!id) {
|
|
278
|
-
ctx.print(`Usage: /
|
|
340
|
+
ctx.print(`Usage: /skills bundle ${sub} <id>`);
|
|
279
341
|
return;
|
|
280
342
|
}
|
|
281
343
|
const bundle = skillRegistry.setBundleEnabled(id, sub === 'enable');
|
|
282
|
-
ctx.print(`${sub === 'enable' ? 'Enabled' : 'Disabled'} Agent skill bundle
|
|
344
|
+
ctx.print(formatSkillReceipt(`${sub === 'enable' ? 'Enabled' : 'Disabled'} Agent skill bundle`, bundle));
|
|
283
345
|
return;
|
|
284
346
|
}
|
|
285
347
|
if (sub === 'review') {
|
|
286
348
|
const id = args[1];
|
|
287
349
|
if (!id) {
|
|
288
|
-
ctx.print('Usage: /
|
|
350
|
+
ctx.print('Usage: /skills bundle review <id>');
|
|
289
351
|
return;
|
|
290
352
|
}
|
|
291
353
|
const bundle = skillRegistry.markBundleReviewed(id);
|
|
292
|
-
ctx.print(
|
|
354
|
+
ctx.print(formatSkillReceipt('Reviewed Agent skill bundle', bundle));
|
|
293
355
|
return;
|
|
294
356
|
}
|
|
295
357
|
if (sub === 'stale') {
|
|
296
358
|
const id = args[1];
|
|
297
359
|
if (!id) {
|
|
298
|
-
ctx.print('Usage: /
|
|
360
|
+
ctx.print('Usage: /skills bundle stale <id> <reason...>');
|
|
299
361
|
return;
|
|
300
362
|
}
|
|
301
363
|
const bundle = skillRegistry.markBundleStale(id, args.slice(2).join(' '));
|
|
302
|
-
ctx.print(
|
|
364
|
+
ctx.print(formatSkillReceipt('Marked Agent skill bundle stale', bundle));
|
|
303
365
|
return;
|
|
304
366
|
}
|
|
305
367
|
if (sub === 'delete' || sub === 'remove') {
|
|
306
368
|
const parsed = parseSkillArgs(args.slice(1));
|
|
307
369
|
const id = parsed.rest[0];
|
|
308
370
|
if (!id) {
|
|
309
|
-
ctx.print('Usage: /
|
|
371
|
+
ctx.print('Usage: /skills bundle delete <id> --yes');
|
|
310
372
|
return;
|
|
311
373
|
}
|
|
312
374
|
if (!parsed.yes) {
|
|
@@ -314,10 +376,10 @@ function runBundleCommand(args: readonly string[], ctx: CommandContext, skillReg
|
|
|
314
376
|
return;
|
|
315
377
|
}
|
|
316
378
|
const removed = skillRegistry.deleteBundle(id);
|
|
317
|
-
ctx.print(
|
|
379
|
+
ctx.print(formatSkillReceipt('Deleted Agent skill bundle', removed));
|
|
318
380
|
return;
|
|
319
381
|
}
|
|
320
|
-
ctx.print('Usage: /
|
|
382
|
+
ctx.print('Usage: /skills bundle [list|enabled|attention|search|show|create|update|enable|disable|review|stale|delete]');
|
|
321
383
|
}
|
|
322
384
|
|
|
323
385
|
export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx: CommandContext): Promise<void> {
|
|
@@ -349,6 +411,11 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
|
|
|
349
411
|
ctx.print(renderList('Enabled Agent Skills', skillRegistry, snapshot.enabledSkills));
|
|
350
412
|
return;
|
|
351
413
|
}
|
|
414
|
+
if (sub === 'attention' || sub === 'needs-setup') {
|
|
415
|
+
const skills = skillRegistry.list().filter((skill) => !evaluateAgentSkillReadiness(skill).ready);
|
|
416
|
+
ctx.print(renderList('Agent Skills needing setup', skillRegistry, skills, 'No Agent-local skills need setup.'));
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
352
419
|
if (sub === 'search') {
|
|
353
420
|
const query = args.slice(1).join(' ').trim();
|
|
354
421
|
ctx.print(renderList(query ? `Agent Skills matching "${query}"` : 'Agent Skills', skillRegistry, skillRegistry.search(query)));
|
|
@@ -357,11 +424,11 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
|
|
|
357
424
|
if (sub === 'show') {
|
|
358
425
|
const id = args[1];
|
|
359
426
|
if (!id) {
|
|
360
|
-
ctx.print('Usage: /
|
|
427
|
+
ctx.print('Usage: /skills show <id>');
|
|
361
428
|
return;
|
|
362
429
|
}
|
|
363
430
|
const skill = skillRegistry.get(id);
|
|
364
|
-
ctx.print(skill ? renderSkill(skill) : `Unknown Agent skill
|
|
431
|
+
ctx.print(skill ? renderSkill(skill) : `Unknown Agent skill ${id}`);
|
|
365
432
|
return;
|
|
366
433
|
}
|
|
367
434
|
if (sub === 'create') {
|
|
@@ -373,17 +440,21 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
|
|
|
373
440
|
procedure,
|
|
374
441
|
triggers: splitList(parsed.flags.get('triggers')),
|
|
375
442
|
tags: splitList(parsed.flags.get('tags')),
|
|
443
|
+
requirements: buildAgentSkillRequirements({
|
|
444
|
+
env: splitList(parsed.flags.get('requires-env')),
|
|
445
|
+
commands: splitList(parsed.flags.get('requires-command') ?? parsed.flags.get('requires-commands')),
|
|
446
|
+
}),
|
|
376
447
|
enabled: parsed.flags.get('enabled') === 'true',
|
|
377
448
|
source: 'user',
|
|
378
|
-
provenance: '
|
|
449
|
+
provenance: 'Command',
|
|
379
450
|
});
|
|
380
|
-
ctx.print(
|
|
451
|
+
ctx.print(formatSkillReceipt('Created Agent skill', skill));
|
|
381
452
|
return;
|
|
382
453
|
}
|
|
383
454
|
if (sub === 'update') {
|
|
384
455
|
const id = args[1];
|
|
385
456
|
if (!id) {
|
|
386
|
-
ctx.print('Usage: /
|
|
457
|
+
ctx.print('Usage: /skills update <id> [--name ...] [--description ...] [--procedure ...]');
|
|
387
458
|
return;
|
|
388
459
|
}
|
|
389
460
|
const parsed = parseSkillArgs(args.slice(2));
|
|
@@ -393,46 +464,52 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
|
|
|
393
464
|
procedure: parsed.flags.get('procedure'),
|
|
394
465
|
triggers: parsed.flags.has('triggers') ? splitList(parsed.flags.get('triggers')) : undefined,
|
|
395
466
|
tags: parsed.flags.has('tags') ? splitList(parsed.flags.get('tags')) : undefined,
|
|
396
|
-
|
|
467
|
+
requirements: parsed.flags.has('requires-env') || parsed.flags.has('requires-command') || parsed.flags.has('requires-commands')
|
|
468
|
+
? buildAgentSkillRequirements({
|
|
469
|
+
env: splitList(parsed.flags.get('requires-env')),
|
|
470
|
+
commands: splitList(parsed.flags.get('requires-command') ?? parsed.flags.get('requires-commands')),
|
|
471
|
+
})
|
|
472
|
+
: undefined,
|
|
473
|
+
provenance: 'Command',
|
|
397
474
|
});
|
|
398
|
-
ctx.print(
|
|
475
|
+
ctx.print(formatSkillReceipt('Updated Agent skill', updated));
|
|
399
476
|
return;
|
|
400
477
|
}
|
|
401
478
|
if (sub === 'enable' || sub === 'disable') {
|
|
402
479
|
const id = args[1];
|
|
403
480
|
if (!id) {
|
|
404
|
-
ctx.print(`Usage: /
|
|
481
|
+
ctx.print(`Usage: /skills ${sub} <id>`);
|
|
405
482
|
return;
|
|
406
483
|
}
|
|
407
484
|
const skill = skillRegistry.setEnabled(id, sub === 'enable');
|
|
408
|
-
ctx.print(`${sub === 'enable' ? 'Enabled' : 'Disabled'} Agent skill
|
|
485
|
+
ctx.print(formatSkillReceipt(`${sub === 'enable' ? 'Enabled' : 'Disabled'} Agent skill`, skill));
|
|
409
486
|
return;
|
|
410
487
|
}
|
|
411
488
|
if (sub === 'review') {
|
|
412
489
|
const id = args[1];
|
|
413
490
|
if (!id) {
|
|
414
|
-
ctx.print('Usage: /
|
|
491
|
+
ctx.print('Usage: /skills review <id>');
|
|
415
492
|
return;
|
|
416
493
|
}
|
|
417
494
|
const skill = skillRegistry.markReviewed(id);
|
|
418
|
-
ctx.print(
|
|
495
|
+
ctx.print(formatSkillReceipt('Reviewed Agent skill', skill));
|
|
419
496
|
return;
|
|
420
497
|
}
|
|
421
498
|
if (sub === 'stale') {
|
|
422
499
|
const id = args[1];
|
|
423
500
|
if (!id) {
|
|
424
|
-
ctx.print('Usage: /
|
|
501
|
+
ctx.print('Usage: /skills stale <id> <reason...>');
|
|
425
502
|
return;
|
|
426
503
|
}
|
|
427
504
|
const skill = skillRegistry.markStale(id, args.slice(2).join(' '));
|
|
428
|
-
ctx.print(
|
|
505
|
+
ctx.print(formatSkillReceipt('Marked Agent skill stale', skill));
|
|
429
506
|
return;
|
|
430
507
|
}
|
|
431
508
|
if (sub === 'delete' || sub === 'remove') {
|
|
432
509
|
const parsed = parseSkillArgs(args.slice(1));
|
|
433
510
|
const id = parsed.rest[0];
|
|
434
511
|
if (!id) {
|
|
435
|
-
ctx.print('Usage: /
|
|
512
|
+
ctx.print('Usage: /skills delete <id> --yes');
|
|
436
513
|
return;
|
|
437
514
|
}
|
|
438
515
|
if (!parsed.yes) {
|
|
@@ -440,10 +517,10 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
|
|
|
440
517
|
return;
|
|
441
518
|
}
|
|
442
519
|
const removed = skillRegistry.deleteSkill(id);
|
|
443
|
-
ctx.print(
|
|
520
|
+
ctx.print(formatSkillReceipt('Deleted Agent skill', removed));
|
|
444
521
|
return;
|
|
445
522
|
}
|
|
446
|
-
ctx.print('Usage: /
|
|
523
|
+
ctx.print('Usage: /skills [list|enabled|attention|discover|import-discovered|search|show|create|update|enable|disable|review|stale|delete|bundle]');
|
|
447
524
|
} catch (error) {
|
|
448
525
|
printError(ctx, error);
|
|
449
526
|
}
|
|
@@ -451,10 +528,10 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
|
|
|
451
528
|
|
|
452
529
|
export function registerAgentSkillsRuntimeCommands(registry: CommandRegistry): void {
|
|
453
530
|
registry.register({
|
|
454
|
-
name: '
|
|
455
|
-
aliases: ['
|
|
456
|
-
description: 'Manage local
|
|
457
|
-
usage: '[list|enabled|discover|import-discovered <name> --yes|search <query>|show <id>|create --name <name> --description <summary> --procedure <steps
|
|
531
|
+
name: 'skills',
|
|
532
|
+
aliases: ['skill', 'agent-skills', 'askills', 'local-skills'],
|
|
533
|
+
description: 'Manage Agent-local skills',
|
|
534
|
+
usage: '[list|enabled|attention|discover|import-discovered <name> --yes|search <query>|show <id>|create --name <name> --description <summary> --procedure <steps> [--requires-env A,B] [--requires-command gh,jq]|update <id> [--name ...] [--description ...] [--procedure ...]|enable <id>|disable <id>|review <id>|stale <id> <reason...>|delete <id> --yes|bundle ...]',
|
|
458
535
|
handler: runAgentSkillsRuntimeCommand,
|
|
459
536
|
});
|
|
460
537
|
}
|
|
@@ -1,17 +1,34 @@
|
|
|
1
|
-
import type { CommandRegistry } from '../command-registry.ts';
|
|
1
|
+
import type { CommandContext, CommandRegistry } from '../command-registry.ts';
|
|
2
|
+
import { AGENT_WORKSPACE_CATEGORY_IDS } from '../agent-workspace-types.ts';
|
|
3
|
+
|
|
4
|
+
const AGENT_WORKSPACE_ARGS_HINT = `${AGENT_WORKSPACE_CATEGORY_IDS.join('|')}|connected-host`;
|
|
2
5
|
|
|
3
6
|
export function registerAgentWorkspaceRuntimeCommands(registry: CommandRegistry): void {
|
|
7
|
+
function openAgentWorkspace(ctx: CommandContext, categoryId: string | undefined): void {
|
|
8
|
+
if (!ctx.openAgentWorkspace) {
|
|
9
|
+
ctx.print('Agent operator workspace is not available in this runtime.');
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
ctx.openAgentWorkspace(categoryId);
|
|
13
|
+
}
|
|
14
|
+
|
|
4
15
|
registry.register({
|
|
5
16
|
name: 'agent',
|
|
6
17
|
aliases: ['home', 'operator'],
|
|
7
18
|
description: 'Open the GoodVibes Agent operator workspace',
|
|
19
|
+
usage: '[category]',
|
|
20
|
+
argsHint: AGENT_WORKSPACE_ARGS_HINT,
|
|
21
|
+
handler(args, ctx) {
|
|
22
|
+
openAgentWorkspace(ctx, args[0]);
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
registry.register({
|
|
26
|
+
name: 'notes',
|
|
27
|
+
aliases: ['scratchpad'],
|
|
28
|
+
description: 'Open Agent-local scratchpad notes in the operator workspace',
|
|
8
29
|
usage: '',
|
|
9
30
|
handler(_args, ctx) {
|
|
10
|
-
|
|
11
|
-
ctx.print('Agent operator workspace is not available in this runtime.');
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
ctx.openAgentWorkspace();
|
|
31
|
+
openAgentWorkspace(ctx, 'notes');
|
|
15
32
|
},
|
|
16
33
|
});
|
|
17
34
|
}
|
|
@@ -34,8 +34,12 @@ function plural(count: number, singular: string, pluralWord = `${singular}s`): s
|
|
|
34
34
|
return `${count} ${count === 1 ? singular : pluralWord}`;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
function countSetupGaps(items: readonly { readonly missingRequirementCount?: number }[]): number {
|
|
38
|
+
return items.filter((item) => (item.missingRequirementCount ?? 0) > 0).length;
|
|
39
|
+
}
|
|
40
|
+
|
|
37
41
|
function formatWorkPlanLine(total: number, counts: StatusCounts): string {
|
|
38
|
-
if (total === 0) return ' work plan
|
|
42
|
+
if (total === 0) return ' work plan empty';
|
|
39
43
|
const active = counts.pending + counts.in_progress + counts.blocked;
|
|
40
44
|
return [
|
|
41
45
|
` work plan: ${plural(total, 'item')}`,
|
|
@@ -48,8 +52,8 @@ function formatWorkPlanLine(total: number, counts: StatusCounts): string {
|
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
function formatWarnings(warnings: readonly string[]): readonly string[] {
|
|
51
|
-
if (warnings.length === 0) return [' warnings
|
|
52
|
-
return [' warnings
|
|
55
|
+
if (warnings.length === 0) return [' warnings none'];
|
|
56
|
+
return [' warnings', ...warnings.slice(0, 4).map((warning) => ` - ${warning}`)];
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
export function formatAgentOperatorBriefing(ctx: CommandContext): string {
|
|
@@ -62,48 +66,74 @@ export function formatAgentOperatorBriefing(ctx: CommandContext): string {
|
|
|
62
66
|
const setupBlocked = countReady(snapshot.setupChecklist, 'blocked');
|
|
63
67
|
const readyChannels = snapshot.channels.filter((channel) => channel.ready).length;
|
|
64
68
|
const enabledChannels = snapshot.channels.filter((channel) => channel.enabled).length;
|
|
69
|
+
const channelSetupGaps = snapshot.channels.filter((channel) => channel.enabled && !channel.ready).length;
|
|
70
|
+
const skillSetupGaps = countSetupGaps(snapshot.localSkills);
|
|
71
|
+
const skillBundleSetupGaps = countSetupGaps(snapshot.localSkillBundles);
|
|
72
|
+
const routineSetupGaps = countSetupGaps(snapshot.localRoutines);
|
|
73
|
+
const voiceSetupNeedsReview = snapshot.voiceSurfaceEnabled && snapshot.voiceMediaReadiness.selectedTtsProviderStatus !== 'ready';
|
|
74
|
+
const mediaSetupNeedsReview = snapshot.mediaProviderCount > 0 && snapshot.voiceMediaReadiness.readyMediaProviderCount === 0;
|
|
75
|
+
const hasLocalSkillBehavior = snapshot.localSkillCount > 0 || snapshot.localSkillBundleCount > 0;
|
|
65
76
|
|
|
66
77
|
const nextActions = [
|
|
67
78
|
snapshot.provider === 'unknown' || snapshot.model === 'unknown'
|
|
68
|
-
? 'Choose the assistant model
|
|
79
|
+
? 'Choose the assistant model from Agent Workspace -> Home -> Choose model.'
|
|
69
80
|
: '',
|
|
70
81
|
snapshot.localMemoryCount === 0
|
|
71
|
-
? 'Store durable non-secret facts
|
|
82
|
+
? 'Store durable non-secret facts from Agent Workspace -> Memory -> Add memory.'
|
|
72
83
|
: snapshot.localMemoryReviewQueueCount > 0
|
|
73
|
-
? `Review ${plural(snapshot.localMemoryReviewQueueCount, 'memory record')}
|
|
74
|
-
: '',
|
|
75
|
-
snapshot.localSkillCount === 0 && snapshot.localSkillBundleCount === 0
|
|
76
|
-
? 'Create reusable procedures with /agent-skills create or import reviewed skill files.'
|
|
77
|
-
: snapshot.activeSkillCount === 0
|
|
78
|
-
? 'Enable reviewed skills or bundles with /agent-skills enabled and /agent-skills bundle enabled.'
|
|
84
|
+
? `Review ${plural(snapshot.localMemoryReviewQueueCount, 'memory record')} from Agent Workspace -> Memory -> Review queue.`
|
|
79
85
|
: '',
|
|
86
|
+
!hasLocalSkillBehavior
|
|
87
|
+
? 'Create reusable procedures from Agent Workspace -> Skills or import reviewed skill files.'
|
|
88
|
+
: '',
|
|
89
|
+
skillSetupGaps > 0
|
|
90
|
+
? `Resolve ${plural(skillSetupGaps, 'skill')} with setup gaps from Agent Workspace -> Skills.`
|
|
91
|
+
: '',
|
|
92
|
+
skillBundleSetupGaps > 0
|
|
93
|
+
? `Resolve ${plural(skillBundleSetupGaps, 'skill bundle')} with setup gaps from Agent Workspace -> Skills.`
|
|
94
|
+
: '',
|
|
95
|
+
hasLocalSkillBehavior && skillSetupGaps === 0 && skillBundleSetupGaps === 0 && snapshot.activeSkillCount === 0
|
|
96
|
+
? 'Enable reviewed skills or bundles from Agent Workspace -> Skills.'
|
|
97
|
+
: '',
|
|
80
98
|
snapshot.localRoutineCount === 0
|
|
81
|
-
? 'Create repeatable workflows
|
|
82
|
-
:
|
|
83
|
-
?
|
|
99
|
+
? 'Create repeatable workflows from Agent Workspace -> Routines; promote schedules only with explicit confirmation.'
|
|
100
|
+
: routineSetupGaps > 0
|
|
101
|
+
? `Resolve ${plural(routineSetupGaps, 'routine')} with setup gaps from Agent Workspace -> Routines.`
|
|
102
|
+
: snapshot.enabledRoutineCount === 0
|
|
103
|
+
? 'Enable reviewed routines from Agent Workspace -> Routines.'
|
|
84
104
|
: '',
|
|
85
|
-
|
|
86
|
-
|
|
105
|
+
channelSetupGaps > 0
|
|
106
|
+
? `Review ${plural(channelSetupGaps, 'enabled channel')} needing setup from Agent Workspace -> Channels.`
|
|
107
|
+
: '',
|
|
108
|
+
voiceSetupNeedsReview
|
|
109
|
+
? 'Review voice setup from Agent Workspace -> Voice & Media before relying on spoken replies.'
|
|
110
|
+
: '',
|
|
111
|
+
mediaSetupNeedsReview
|
|
112
|
+
? 'Review media provider setup from Agent Workspace -> Voice & Media before relying on image or media workflows.'
|
|
113
|
+
: '',
|
|
114
|
+
'Use Agent Workspace -> Knowledge for Agent Knowledge status, search, and explicit ingest forms.',
|
|
115
|
+
'Use Agent Workspace -> Build Delegation only for explicit build, fix, implementation, or review handoff to GoodVibes TUI.',
|
|
87
116
|
].filter((line): line is string => line.length > 0);
|
|
88
117
|
|
|
89
118
|
return [
|
|
90
119
|
'Agent Briefing',
|
|
91
120
|
` chat route: ${snapshot.provider} / ${snapshot.modelDisplayName}`,
|
|
92
|
-
` session
|
|
93
|
-
` profile
|
|
94
|
-
` policy
|
|
95
|
-
` knowledge
|
|
121
|
+
` session ${snapshot.sessionId}`,
|
|
122
|
+
` profile ${snapshot.activeRuntimeProfile}`,
|
|
123
|
+
` policy ${snapshot.executionPolicy}; delegated review ${snapshot.delegatedReviewPolicy}`,
|
|
124
|
+
` knowledge ${snapshot.knowledgeRoute} (${snapshot.knowledgeIsolation}; no fallback)`,
|
|
96
125
|
'',
|
|
97
126
|
'Readiness',
|
|
98
|
-
` setup
|
|
127
|
+
` setup ${setupReady}/${snapshot.setupChecklist.length} ready; ${setupRecommended} recommended; ${setupBlocked} blocked`,
|
|
99
128
|
` local memory: ${plural(snapshot.localMemoryCount, 'record')}; prompt-active ${snapshot.localMemoryPromptActiveCount}; review queue ${snapshot.localMemoryReviewQueueCount}`,
|
|
129
|
+
` scratchpad notes: ${plural(snapshot.localNoteCount, 'note')}; review queue ${snapshot.localNoteReviewQueueCount}`,
|
|
100
130
|
` personas: ${plural(snapshot.localPersonaCount, 'persona')}; active ${snapshot.activePersonaName}`,
|
|
101
|
-
` skills: ${snapshot.enabledSkillCount}/${snapshot.localSkillCount} enabled; bundles ${snapshot.enabledSkillBundleCount}/${snapshot.localSkillBundleCount}; active ${snapshot.activeSkillCount}`,
|
|
102
|
-
` routines: ${snapshot.enabledRoutineCount}/${snapshot.localRoutineCount} enabled`,
|
|
103
|
-
` channels: ${readyChannels}/${snapshot.channels.length} ready; ${enabledChannels} enabled`,
|
|
131
|
+
` skills: ${snapshot.enabledSkillCount}/${snapshot.localSkillCount} enabled; bundles ${snapshot.enabledSkillBundleCount}/${snapshot.localSkillBundleCount}; active ${snapshot.activeSkillCount}; setup gaps ${skillSetupGaps} skill, ${skillBundleSetupGaps} bundle`,
|
|
132
|
+
` routines: ${snapshot.enabledRoutineCount}/${snapshot.localRoutineCount} enabled; setup gaps ${routineSetupGaps}`,
|
|
133
|
+
` channels: ${readyChannels}/${snapshot.channels.length} ready; ${enabledChannels} enabled; setup gaps ${channelSetupGaps}`,
|
|
104
134
|
` voice/media: ${snapshot.voiceProviderCount} voice, ${snapshot.mediaProviderCount} media; browser tools ${snapshot.voiceMediaReadiness.browserToolState}`,
|
|
105
135
|
formatWorkPlanLine(workPlan.total, workPlan.counts),
|
|
106
|
-
` schedules
|
|
136
|
+
` schedules ${enabledJobs}/${jobs.length} visible jobs enabled`,
|
|
107
137
|
'',
|
|
108
138
|
'Next Actions',
|
|
109
139
|
...nextActions.map((line) => ` - ${line}`),
|