@pellux/goodvibes-agent 1.4.3 → 1.5.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 +24 -0
- package/README.md +7 -7
- package/dist/package/main.js +7450 -12285
- package/docs/README.md +2 -2
- package/docs/channels-remote-and-api.md +1 -1
- package/docs/getting-started.md +2 -2
- package/docs/release-and-publishing.md +1 -1
- package/docs/tools-and-commands.md +5 -5
- package/package.json +4 -2
- package/release/performance-snapshot.json +2 -2
- package/release/release-notes.md +11 -7
- package/release/release-readiness.json +6 -6
- package/src/agent/behavior-discovery-summary.ts +4 -18
- package/src/agent/calendar-registry.ts +322 -0
- package/src/agent/competitive-feature-inventory.ts +268 -130
- package/src/agent/document-registry.ts +5 -1
- package/src/agent/email/email-service.ts +350 -0
- package/src/agent/email/imap-client.ts +596 -0
- package/src/agent/email/smtp-client.ts +453 -0
- package/src/agent/ics-calendar.ts +662 -0
- package/src/agent/ics-timezone.ts +172 -0
- package/src/agent/markdown-frontmatter.ts +31 -0
- package/src/agent/memory-safety.ts +1 -1
- package/src/agent/note-registry.ts +3 -9
- package/src/agent/persona-discovery.ts +3 -15
- package/src/agent/persona-registry.ts +1 -10
- package/src/agent/research-source-registry.ts +5 -1
- package/src/agent/routine-discovery.ts +3 -15
- package/src/agent/runtime-profile.ts +3 -0
- package/src/agent/skill-discovery.ts +3 -15
- package/src/agent/skill-draft-proposer.ts +203 -0
- package/src/agent/skill-draft-runner.ts +201 -0
- package/src/agent/skill-registry.ts +36 -1
- package/src/agent/skill-standard.ts +99 -0
- package/src/agent/vibe-file.ts +7 -22
- package/src/cli/completion.ts +1 -1
- package/src/cli/config-overrides.ts +10 -1
- package/src/cli/redaction.ts +17 -5
- package/src/config/provider-model.ts +2 -1
- package/src/config/secret-config.ts +13 -6
- package/src/core/activity-feed.ts +97 -0
- package/src/core/away-digest.ts +161 -0
- package/src/core/conversation-rendering.ts +7 -3
- package/src/core/conversation.ts +22 -15
- package/src/core/hardware-profile.ts +362 -0
- package/src/core/last-seen-store.ts +78 -0
- package/src/core/plain-language.ts +52 -0
- package/src/core/setup-incomplete-hint.ts +90 -0
- package/src/core/system-message-router.ts +38 -87
- package/src/input/agent-workspace-basic-command-editor-submission.ts +60 -220
- package/src/input/agent-workspace-basic-command-editors.ts +39 -141
- package/src/input/agent-workspace-categories.ts +63 -158
- package/src/input/agent-workspace-command-editor.ts +4 -0
- package/src/input/agent-workspace-host-category.ts +0 -5
- package/src/input/agent-workspace-local-editor-submission.ts +3 -1
- package/src/input/agent-workspace-navigation.ts +10 -3
- package/src/input/agent-workspace-onboarding-actions.ts +132 -0
- package/src/input/agent-workspace-onboarding-categories.ts +29 -26
- package/src/input/agent-workspace-onboarding-finish.ts +11 -4
- package/src/input/agent-workspace-onboarding-state.ts +111 -0
- package/src/input/agent-workspace-profile-editor-submission.ts +260 -0
- package/src/input/agent-workspace-profile-editors.ts +155 -0
- package/src/input/agent-workspace-subscription-editor.ts +7 -0
- package/src/input/agent-workspace-types.ts +5 -1
- package/src/input/agent-workspace.ts +65 -39
- package/src/input/command-registry.ts +18 -5
- package/src/input/commands/agent-runtime-profile-runtime.ts +2 -1
- package/src/input/commands/agent-skills-runtime.ts +60 -3
- package/src/input/commands/calendar-runtime.ts +209 -0
- package/src/input/commands/channels-runtime.ts +1 -0
- package/src/input/commands/command-error.ts +9 -0
- package/src/input/commands/compat-runtime.ts +1 -0
- package/src/input/commands/config.ts +1 -0
- package/src/input/commands/conversation-runtime.ts +1 -1
- package/src/input/commands/delegation-runtime.ts +5 -6
- package/src/input/commands/email-runtime.ts +387 -0
- package/src/input/commands/experience-runtime.ts +17 -4
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/health-runtime.ts +6 -1
- package/src/input/commands/knowledge-format.ts +73 -0
- package/src/input/commands/knowledge.ts +9 -74
- package/src/input/commands/local-provider-runtime.ts +2 -1
- package/src/input/commands/local-runtime.ts +10 -4
- package/src/input/commands/mcp-runtime.ts +7 -0
- package/src/input/commands/notify-runtime.ts +17 -1
- package/src/input/commands/onboarding-runtime.ts +1 -0
- package/src/input/commands/operator-actions-runtime.ts +1 -0
- package/src/input/commands/operator-runtime.ts +3 -0
- package/src/input/commands/personas-runtime.ts +1 -0
- package/src/input/commands/platform-access-runtime.ts +40 -17
- package/src/input/commands/product-runtime.ts +6 -1
- package/src/input/commands/provider-accounts-runtime.ts +3 -2
- package/src/input/commands/qrcode-runtime.ts +1 -0
- package/src/input/commands/routines-runtime.ts +1 -0
- package/src/input/commands/runtime-services.ts +0 -13
- package/src/input/commands/security-runtime.ts +1 -0
- package/src/input/commands/session-content.ts +1 -0
- package/src/input/commands/shell-core.ts +5 -2
- package/src/input/commands/subscription-runtime.ts +33 -9
- package/src/input/commands/support-bundle-runtime.ts +8 -1
- package/src/input/commands/tasks-runtime.ts +1 -0
- package/src/input/commands/tts-runtime.ts +1 -0
- package/src/input/commands/vibe-runtime.ts +1 -0
- package/src/input/commands.ts +4 -0
- package/src/input/feed-context-factory.ts +3 -12
- package/src/input/handler-command-route.ts +7 -60
- package/src/input/handler-feed-routes.ts +0 -194
- package/src/input/handler-feed.ts +2 -54
- package/src/input/handler-interactions.ts +0 -2
- package/src/input/handler-modal-stack.ts +0 -9
- package/src/input/handler-picker-routes.ts +24 -1
- package/src/input/handler-shortcuts.ts +11 -40
- package/src/input/handler-ui-state.ts +13 -0
- package/src/input/handler.ts +8 -35
- package/src/input/keybindings.ts +40 -17
- package/src/input/model-picker-local-fit.ts +130 -0
- package/src/input/submission-router.ts +0 -5
- package/src/main.ts +111 -89
- package/src/renderer/activity-sidebar.ts +186 -0
- package/src/renderer/agent-workspace-context-lines.ts +5 -48
- package/src/renderer/agent-workspace-style.ts +1 -1
- package/src/renderer/agent-workspace.ts +14 -2
- package/src/renderer/compositor.ts +37 -125
- package/src/renderer/conversation-overlays.ts +3 -3
- package/src/renderer/help-overlay.ts +7 -5
- package/src/renderer/model-workspace.ts +101 -86
- package/src/{panels → renderer}/polish.ts +3 -3
- package/src/renderer/shell-surface.ts +4 -5
- package/src/renderer/status-token.ts +31 -11
- package/src/renderer/tab-strip.ts +1 -1
- package/src/renderer/tool-call.ts +7 -8
- package/src/renderer/tool-labels.ts +92 -0
- package/src/renderer/ui-factory.ts +48 -96
- package/src/runtime/bootstrap-command-context.ts +0 -5
- package/src/runtime/bootstrap-command-parts.ts +6 -15
- package/src/runtime/bootstrap-core.ts +34 -13
- package/src/runtime/bootstrap-hook-bridge.ts +3 -1
- package/src/runtime/bootstrap-shell.ts +3 -50
- package/src/runtime/bootstrap.ts +3 -4
- package/src/runtime/context.ts +1 -1
- package/src/runtime/diagnostics/panels/index.ts +0 -1
- package/src/runtime/diagnostics/panels/policy.ts +1 -1
- package/src/runtime/execution-ledger.ts +16 -1
- package/src/runtime/index.ts +6 -1
- package/src/runtime/onboarding/index.ts +1 -0
- package/src/runtime/onboarding/onboarding-state.ts +200 -0
- package/src/{panels → runtime}/provider-account-snapshot.ts +5 -2
- package/src/runtime/services.ts +16 -4
- package/src/runtime/terminal-output-guard.ts +7 -0
- package/src/runtime/tool-permission-safety.ts +1 -1
- package/src/runtime/ui/model-picker/data-provider.ts +1 -1
- package/src/runtime/ui/model-picker/health-enrichment.ts +2 -2
- package/src/runtime/ui/model-picker/types.ts +2 -2
- package/src/runtime/ui/provider-health/data-provider.ts +3 -3
- package/src/runtime/ui/provider-health/types.ts +2 -2
- package/src/runtime/ui-services.ts +0 -2
- package/src/shell/agent-workspace-fullscreen.ts +0 -1
- package/src/shell/autonomy-surfacing.ts +272 -0
- package/src/shell/session-continuity-hints.ts +0 -6
- package/src/shell/startup-wiring.ts +221 -0
- package/src/shell/ui-openers.ts +18 -29
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-harness-background-processes.ts +4 -4
- package/src/tools/agent-harness-browser-cockpit-route.ts +3 -3
- package/src/tools/agent-harness-command-runner.ts +6 -1
- package/src/tools/agent-harness-document-ops.ts +26 -53
- package/src/tools/agent-harness-execution-history.ts +1 -13
- package/src/tools/agent-harness-execution-posture.ts +0 -15
- package/src/tools/agent-harness-keybinding-metadata.ts +28 -29
- package/src/tools/agent-harness-local-model-cookbook.ts +24 -1
- package/src/tools/agent-harness-metadata.ts +16 -0
- package/src/tools/agent-harness-mode-catalog.ts +2 -9
- package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
- package/src/tools/agent-harness-setup-posture-utils.ts +1 -1
- package/src/tools/agent-harness-tool-schema.ts +13 -14
- package/src/tools/agent-harness-tool.ts +27 -23
- package/src/tools/agent-harness-ui-surface-metadata.ts +10 -20
- package/src/tools/agent-harness-workspace-action-runner.ts +3 -4
- package/src/tools/agent-workspace-tool.ts +2 -33
- package/src/utils/terminal-width.ts +9 -3
- package/src/version.ts +1 -1
- package/src/input/agent-workspace-panel-route.ts +0 -44
- package/src/input/panel-integration-actions.ts +0 -26
- package/src/panels/approval-panel.ts +0 -149
- package/src/panels/automation-control-panel.ts +0 -212
- package/src/panels/base-panel.ts +0 -254
- package/src/panels/builtin/agent.ts +0 -58
- package/src/panels/builtin/knowledge.ts +0 -26
- package/src/panels/builtin/operations.ts +0 -121
- package/src/panels/builtin/session.ts +0 -138
- package/src/panels/builtin/shared.ts +0 -275
- package/src/panels/builtin/usage.ts +0 -21
- package/src/panels/builtin-panels.ts +0 -23
- package/src/panels/confirm-state.ts +0 -61
- package/src/panels/context-visualizer-panel.ts +0 -204
- package/src/panels/cost-tracker-panel.ts +0 -444
- package/src/panels/docs-panel.ts +0 -285
- package/src/panels/index.ts +0 -25
- package/src/panels/knowledge-panel.ts +0 -417
- package/src/panels/memory-panel.ts +0 -226
- package/src/panels/panel-list-panel.ts +0 -464
- package/src/panels/panel-manager.ts +0 -570
- package/src/panels/provider-accounts-panel.ts +0 -233
- package/src/panels/provider-health-domains.ts +0 -208
- package/src/panels/provider-health-panel.ts +0 -720
- package/src/panels/provider-health-tracker.ts +0 -115
- package/src/panels/provider-stats-panel.ts +0 -366
- package/src/panels/qr-panel.ts +0 -207
- package/src/panels/schedule-panel.ts +0 -321
- package/src/panels/scrollable-list-panel.ts +0 -491
- package/src/panels/search-focus.ts +0 -32
- package/src/panels/security-panel.ts +0 -295
- package/src/panels/session-browser-panel.ts +0 -395
- package/src/panels/session-maintenance.ts +0 -125
- package/src/panels/subscription-panel.ts +0 -263
- package/src/panels/system-messages-panel.ts +0 -230
- package/src/panels/tasks-panel.ts +0 -344
- package/src/panels/thinking-panel.ts +0 -304
- package/src/panels/token-budget-panel.ts +0 -475
- package/src/panels/tool-inspector-panel.ts +0 -436
- package/src/panels/types.ts +0 -54
- package/src/renderer/panel-composite.ts +0 -158
- package/src/renderer/panel-tab-bar.ts +0 -69
- package/src/renderer/panel-workspace-bar.ts +0 -42
- package/src/runtime/diagnostics/panels/panel-resources.ts +0 -118
- package/src/tools/agent-harness-panel-metadata.ts +0 -211
- /package/src/runtime/perf/{panel-health-monitor.ts → component-health.ts} +0 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
|
|
2
|
+
|
|
3
|
+
export type AgentWorkspaceProfileEditorKind = Extract<
|
|
4
|
+
AgentWorkspaceEditorKind,
|
|
5
|
+
| 'profile-template-export'
|
|
6
|
+
| 'profile-template-import'
|
|
7
|
+
| 'profile-template-show'
|
|
8
|
+
| 'profile-show'
|
|
9
|
+
| 'profile-template-from-discovered'
|
|
10
|
+
| 'profile-from-discovered'
|
|
11
|
+
| 'profile-default'
|
|
12
|
+
| 'profile-default-clear'
|
|
13
|
+
| 'profile-delete'
|
|
14
|
+
>;
|
|
15
|
+
|
|
16
|
+
export function isAgentWorkspaceProfileEditorKind(kind: AgentWorkspaceEditorKind): kind is AgentWorkspaceProfileEditorKind {
|
|
17
|
+
return kind === 'profile-template-export'
|
|
18
|
+
|| kind === 'profile-template-import'
|
|
19
|
+
|| kind === 'profile-template-show'
|
|
20
|
+
|| kind === 'profile-show'
|
|
21
|
+
|| kind === 'profile-template-from-discovered'
|
|
22
|
+
|| kind === 'profile-from-discovered'
|
|
23
|
+
|| kind === 'profile-default'
|
|
24
|
+
|| kind === 'profile-default-clear'
|
|
25
|
+
|| kind === 'profile-delete';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function createAgentWorkspaceProfileEditor(kind: AgentWorkspaceProfileEditorKind): AgentWorkspaceLocalEditor {
|
|
29
|
+
if (kind === 'profile-template-export') {
|
|
30
|
+
return {
|
|
31
|
+
kind,
|
|
32
|
+
mode: 'create',
|
|
33
|
+
title: 'Export Agent Starter Template',
|
|
34
|
+
selectedFieldIndex: 0,
|
|
35
|
+
message: 'Export a starter template JSON file for review and customization. Type yes on the final field to confirm.',
|
|
36
|
+
fields: [
|
|
37
|
+
{ id: 'templateId', label: 'Starter id', value: '', required: true, multiline: false, hint: 'Existing starter id from /agent-profile templates.' },
|
|
38
|
+
{ id: 'path', label: 'Output path', value: '', required: true, multiline: false, hint: 'Workspace-relative JSON path to write.' },
|
|
39
|
+
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile template export with --yes.' },
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (kind === 'profile-template-import') {
|
|
44
|
+
return {
|
|
45
|
+
kind,
|
|
46
|
+
mode: 'create',
|
|
47
|
+
title: 'Import Agent Starter Template',
|
|
48
|
+
selectedFieldIndex: 0,
|
|
49
|
+
message: 'Import a reviewed starter template JSON file into this Agent home. Type yes on the final field to confirm.',
|
|
50
|
+
fields: [
|
|
51
|
+
{ id: 'path', label: 'Template path', value: '', required: true, multiline: false, hint: 'Workspace-relative JSON path to import.' },
|
|
52
|
+
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile template import with --yes.' },
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (kind === 'profile-template-show') {
|
|
57
|
+
return {
|
|
58
|
+
kind,
|
|
59
|
+
mode: 'create',
|
|
60
|
+
title: 'Preview Agent Starter Template',
|
|
61
|
+
selectedFieldIndex: 0,
|
|
62
|
+
message: 'Preview one built-in or local starter template before creating or exporting a profile.',
|
|
63
|
+
fields: [
|
|
64
|
+
{ id: 'id', label: 'Starter id', value: '', required: true, multiline: false, hint: 'Starter template id from /agent-profile templates.' },
|
|
65
|
+
],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (kind === 'profile-show') {
|
|
69
|
+
return {
|
|
70
|
+
kind,
|
|
71
|
+
mode: 'create',
|
|
72
|
+
title: 'Show Agent Profile',
|
|
73
|
+
selectedFieldIndex: 0,
|
|
74
|
+
message: 'Show one isolated Agent profile home, starter metadata, and launch command.',
|
|
75
|
+
fields: [
|
|
76
|
+
{ id: 'profile', label: 'Profile name', value: '', required: true, multiline: false, hint: 'Existing isolated Agent profile name from /agent-profile list.' },
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (kind === 'profile-template-from-discovered') {
|
|
81
|
+
return {
|
|
82
|
+
kind,
|
|
83
|
+
mode: 'create',
|
|
84
|
+
title: 'Create Starter from Discovered Behavior',
|
|
85
|
+
selectedFieldIndex: 0,
|
|
86
|
+
message: 'Create an Agent-local starter template from reviewed discovered persona, skill, and routine markdown. Type yes on the final field to confirm.',
|
|
87
|
+
fields: [
|
|
88
|
+
{ id: 'id', label: 'Starter id', value: '', required: true, multiline: false, hint: 'New local starter id, for example research-desk.' },
|
|
89
|
+
{ id: 'name', label: 'Starter name', value: '', required: false, multiline: false, hint: 'Optional display name. Defaults to the selected persona name.' },
|
|
90
|
+
{ id: 'description', label: 'Description', value: '', required: false, multiline: false, hint: 'Optional one-line summary.' },
|
|
91
|
+
{ id: 'persona', label: 'Persona', value: '', required: false, multiline: false, hint: 'Optional discovered persona name/path. Blank uses the first discovered persona.' },
|
|
92
|
+
{ id: 'skills', label: 'Skills', value: '', required: false, multiline: false, hint: 'all or comma-separated discovered skill names. Blank includes all.' },
|
|
93
|
+
{ id: 'routines', label: 'Routines', value: '', required: false, multiline: false, hint: 'all or comma-separated discovered routine names. Blank includes all.' },
|
|
94
|
+
{ id: 'replace', label: 'Replace existing', value: 'no', required: false, multiline: false, hint: 'yes/no. Existing starter ids are protected unless this is yes.' },
|
|
95
|
+
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile template from-discovered with --yes.' },
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (kind === 'profile-from-discovered') {
|
|
100
|
+
return {
|
|
101
|
+
kind,
|
|
102
|
+
mode: 'create',
|
|
103
|
+
title: 'Create Profile from Discovered Behavior',
|
|
104
|
+
selectedFieldIndex: 0,
|
|
105
|
+
message: 'Create a local starter template and isolated Agent profile from reviewed discovered behavior markdown. Type yes on the final field to confirm.',
|
|
106
|
+
fields: [
|
|
107
|
+
{ id: 'profile', label: 'Profile name', value: '', required: true, multiline: false, hint: 'New isolated Agent profile name, for example research-desk.' },
|
|
108
|
+
{ id: 'templateId', label: 'Starter id', value: '', required: false, multiline: false, hint: 'Optional local starter id. Blank uses the profile name.' },
|
|
109
|
+
{ id: 'name', label: 'Starter name', value: '', required: false, multiline: false, hint: 'Optional display name for the generated starter.' },
|
|
110
|
+
{ id: 'description', label: 'Description', value: '', required: false, multiline: false, hint: 'Optional one-line summary.' },
|
|
111
|
+
{ id: 'persona', label: 'Persona', value: '', required: false, multiline: false, hint: 'Optional discovered persona name/path. Blank uses the first discovered persona.' },
|
|
112
|
+
{ id: 'skills', label: 'Skills', value: '', required: false, multiline: false, hint: 'all or comma-separated discovered skill names. Blank includes all.' },
|
|
113
|
+
{ id: 'routines', label: 'Routines', value: '', required: false, multiline: false, hint: 'all or comma-separated discovered routine names. Blank includes all.' },
|
|
114
|
+
{ id: 'replace', label: 'Replace starter', value: 'no', required: false, multiline: false, hint: 'yes/no. Existing starter ids are protected unless this is yes.' },
|
|
115
|
+
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile create-from-discovered with --yes.' },
|
|
116
|
+
],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
if (kind === 'profile-default') {
|
|
120
|
+
return {
|
|
121
|
+
kind,
|
|
122
|
+
mode: 'update',
|
|
123
|
+
title: 'Use Default Agent Profile',
|
|
124
|
+
selectedFieldIndex: 0,
|
|
125
|
+
message: 'Select which isolated Agent profile the next plain goodvibes-agent run should use. Type yes on the final field to confirm.',
|
|
126
|
+
fields: [
|
|
127
|
+
{ id: 'profile', label: 'Profile name', value: '', required: true, multiline: false, hint: 'Existing isolated Agent profile name from /agent-profile list.' },
|
|
128
|
+
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile use with --yes.' },
|
|
129
|
+
],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (kind === 'profile-default-clear') {
|
|
133
|
+
return {
|
|
134
|
+
kind,
|
|
135
|
+
mode: 'update',
|
|
136
|
+
title: 'Clear Default Agent Profile',
|
|
137
|
+
selectedFieldIndex: 0,
|
|
138
|
+
message: 'Return the next plain goodvibes-agent run to the base Agent home. Type yes to confirm.',
|
|
139
|
+
fields: [
|
|
140
|
+
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile default clear with --yes.' },
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
kind,
|
|
146
|
+
mode: 'delete',
|
|
147
|
+
title: 'Delete Agent Profile',
|
|
148
|
+
selectedFieldIndex: 0,
|
|
149
|
+
message: 'Delete one isolated Agent profile home. Type yes on the final field to confirm.',
|
|
150
|
+
fields: [
|
|
151
|
+
{ id: 'profile', label: 'Profile name', value: '', required: true, multiline: false, hint: 'Existing isolated Agent profile name from /agent-profile list.' },
|
|
152
|
+
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile delete with --yes.' },
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
@@ -12,6 +12,12 @@ export interface AgentWorkspaceSubscriptionEditorHost {
|
|
|
12
12
|
status: string;
|
|
13
13
|
lastActionResult: AgentWorkspaceActionResult | null;
|
|
14
14
|
clampSelection(): void;
|
|
15
|
+
/**
|
|
16
|
+
* Called after a successful sign-in so the host can refresh onboarding state
|
|
17
|
+
* and navigate to the next onboarding step (e.g. account-model). Optional —
|
|
18
|
+
* only available when running in ONBOARDING mode.
|
|
19
|
+
*/
|
|
20
|
+
onSubscriptionLoginSuccess?(): void;
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
export type AgentWorkspaceSubscriptionFieldReader = (id: string) => string;
|
|
@@ -140,6 +146,7 @@ export async function submitAgentWorkspaceSubscriptionLoginFinishEditor(
|
|
|
140
146
|
safety: 'safe',
|
|
141
147
|
};
|
|
142
148
|
host.clampSelection();
|
|
149
|
+
host.onSubscriptionLoginSuccess?.();
|
|
143
150
|
} catch (error) {
|
|
144
151
|
const detail = error instanceof Error ? error.message : String(error);
|
|
145
152
|
host.localEditor = { ...editor, message: detail };
|
|
@@ -151,6 +151,8 @@ export type AgentWorkspaceEditorKind =
|
|
|
151
151
|
| 'persona-discovery-import'
|
|
152
152
|
| 'routine-discovery-import'
|
|
153
153
|
| 'skill-discovery-import'
|
|
154
|
+
| 'skill-standard-import'
|
|
155
|
+
| 'skill-standard-export'
|
|
154
156
|
| 'learned-behavior'
|
|
155
157
|
| 'profile-template-export'
|
|
156
158
|
| 'profile-template-import'
|
|
@@ -334,7 +336,7 @@ export interface AgentWorkspaceActionSearchResult {
|
|
|
334
336
|
export type AgentWorkspaceCommandDispatcher = (command: string, behavior?: 'inline' | 'compose' | 'exit') => void;
|
|
335
337
|
export type AgentWorkspacePromptDispatcher = (prompt: string) => void;
|
|
336
338
|
|
|
337
|
-
export type AgentWorkspaceActionResultKind = 'guidance' | 'blocked' | 'dispatched' | 'refreshed' | 'error';
|
|
339
|
+
export type AgentWorkspaceActionResultKind = 'guidance' | 'blocked' | 'dispatched' | 'refreshed' | 'error' | 'recap';
|
|
338
340
|
|
|
339
341
|
export interface AgentWorkspaceActionResult {
|
|
340
342
|
readonly kind: AgentWorkspaceActionResultKind;
|
|
@@ -342,6 +344,8 @@ export interface AgentWorkspaceActionResult {
|
|
|
342
344
|
readonly detail: string;
|
|
343
345
|
readonly command?: string;
|
|
344
346
|
readonly safety?: AgentWorkspaceAction['safety'];
|
|
347
|
+
/** Lines to display when kind is 'recap'. */
|
|
348
|
+
readonly lines?: readonly string[];
|
|
345
349
|
}
|
|
346
350
|
|
|
347
351
|
export interface AgentWorkspaceLocalLibraryItem {
|
|
@@ -24,7 +24,9 @@ import { buildAgentWorkspaceRuntimeSnapshot } from './agent-workspace-snapshot.t
|
|
|
24
24
|
import { submitAgentWorkspaceSubscriptionLoginFinishEditor, submitAgentWorkspaceSubscriptionLoginStartEditor, submitAgentWorkspaceSubscriptionLogoutEditor } from './agent-workspace-subscription-editor.ts';
|
|
25
25
|
import type { AgentWorkspaceAction, AgentWorkspaceActionResult, AgentWorkspaceActionSearchResult, AgentWorkspaceCategory, AgentWorkspaceCategoryGroup, AgentWorkspaceCommandDispatcher, AgentWorkspaceEditorField, AgentWorkspaceFocusPane, AgentWorkspaceLocalEditor, AgentWorkspaceLocalEditorKind, AgentWorkspaceLocalLibraryItem, AgentWorkspaceLocalOperation, AgentWorkspacePromptDispatcher, AgentWorkspaceRuntimeSnapshot } from './agent-workspace-types.ts';
|
|
26
26
|
import { ONBOARDING_COMPLETE_SYNTHETIC_ACTION, shouldShowOnboardingFinishFooter } from './agent-workspace-onboarding-finish.ts';
|
|
27
|
-
import {
|
|
27
|
+
import { completeOnboardingAction, onSubscriptionLoginSuccessAction } from './agent-workspace-onboarding-actions.ts';
|
|
28
|
+
import { computeOnboardingStateFromSnapshot, deriveOnboardingEntry, updateRevealedOnboardingCategories } from './agent-workspace-onboarding-state.ts';
|
|
29
|
+
import type { OnboardingState } from '../runtime/onboarding/onboarding-state.ts';
|
|
28
30
|
|
|
29
31
|
export type { AgentWorkspaceChannelRisk, AgentWorkspaceChannelStatus } from './agent-workspace-channels.ts';
|
|
30
32
|
export type { AgentWorkspaceAction, AgentWorkspaceActionResult, AgentWorkspaceActionSearchResult, AgentWorkspaceCategory, AgentWorkspaceCategoryId, AgentWorkspaceCommandDispatcher, AgentWorkspaceEditorField, AgentWorkspaceFocusPane, AgentWorkspaceLocalEditor, AgentWorkspaceLocalEditorKind, AgentWorkspaceLocalLibraryItem, AgentWorkspaceLocalOperation, AgentWorkspacePromptDispatcher, AgentWorkspaceRuntimeSnapshot } from './agent-workspace-types.ts';
|
|
@@ -48,13 +50,20 @@ export class AgentWorkspace {
|
|
|
48
50
|
private dispatchCommand: AgentWorkspaceCommandDispatcher | null = null;
|
|
49
51
|
private dispatchPrompt: AgentWorkspacePromptDispatcher | null = null;
|
|
50
52
|
private _onlyGroup: AgentWorkspaceCategoryGroup | null = null;
|
|
53
|
+
private _onboardingState: OnboardingState | null = null;
|
|
54
|
+
private _revealedOnboardingCategoryIds = new Set<string>(); // monotonic reveal set
|
|
55
|
+
private _awaitingRecapDismiss = false; // true while showing recap before final close
|
|
51
56
|
|
|
52
57
|
open(context: CommandContext, dispatchCommand: AgentWorkspaceCommandDispatcher, categoryId?: string, dispatchPrompt?: AgentWorkspacePromptDispatcher, onlyGroup?: AgentWorkspaceCategoryGroup): void {
|
|
53
58
|
this.context = context;
|
|
54
59
|
this.dispatchCommand = dispatchCommand;
|
|
55
60
|
this.dispatchPrompt = dispatchPrompt ?? null;
|
|
56
61
|
this._onlyGroup = onlyGroup ?? null;
|
|
62
|
+
this._awaitingRecapDismiss = false;
|
|
57
63
|
this.runtimeSnapshot = buildAgentWorkspaceRuntimeSnapshot(context);
|
|
64
|
+
const shellPaths = context.workspace?.shellPaths;
|
|
65
|
+
this._onboardingState = computeOnboardingStateFromSnapshot(this.runtimeSnapshot, shellPaths);
|
|
66
|
+
if (this._onboardingState) updateRevealedOnboardingCategories(this._onboardingState, this._revealedOnboardingCategoryIds);
|
|
58
67
|
this.active = true;
|
|
59
68
|
this.focusPane = 'actions';
|
|
60
69
|
this.status = 'Ready. Choose an operator flow; ordinary assistant work stays in the main conversation.';
|
|
@@ -75,6 +84,14 @@ export class AgentWorkspace {
|
|
|
75
84
|
safety: 'safe',
|
|
76
85
|
};
|
|
77
86
|
}
|
|
87
|
+
if (onlyGroup === 'ONBOARDING' && this._onboardingState) {
|
|
88
|
+
const entry = deriveOnboardingEntry(this._onboardingState);
|
|
89
|
+
this.status = entry.status;
|
|
90
|
+
if (entry.categoryId) {
|
|
91
|
+
const idx = this.categories.findIndex((c) => c.id === entry.categoryId);
|
|
92
|
+
if (idx >= 0) this.selectedCategoryIndex = idx;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
78
95
|
this.clampSelection();
|
|
79
96
|
}
|
|
80
97
|
|
|
@@ -89,9 +106,21 @@ export class AgentWorkspace {
|
|
|
89
106
|
this.actionSearchActive = false;
|
|
90
107
|
this.actionSearchQuery = '';
|
|
91
108
|
this._onlyGroup = null;
|
|
109
|
+
this._onboardingState = null;
|
|
110
|
+
this._awaitingRecapDismiss = false;
|
|
92
111
|
}
|
|
93
112
|
|
|
94
113
|
get categories(): readonly AgentWorkspaceCategory[] {
|
|
114
|
+
if (this._onlyGroup === 'ONBOARDING') {
|
|
115
|
+
// Pure read — reveal set is updated at every _onboardingState assignment
|
|
116
|
+
// (open, onSubscriptionLoginSuccess), not here. Recompute is O(categories)
|
|
117
|
+
// and intentionally simple; the list is small and no caching is needed.
|
|
118
|
+
const onboarding = AGENT_WORKSPACE_CATEGORIES.filter((c) => c.group === 'ONBOARDING');
|
|
119
|
+
if (this._onboardingState) {
|
|
120
|
+
return onboarding.filter((c) => this._revealedOnboardingCategoryIds.has(c.id));
|
|
121
|
+
}
|
|
122
|
+
return onboarding;
|
|
123
|
+
}
|
|
95
124
|
if (this._onlyGroup) {
|
|
96
125
|
return AGENT_WORKSPACE_CATEGORIES.filter((category) => category.group === this._onlyGroup);
|
|
97
126
|
}
|
|
@@ -105,7 +134,7 @@ export class AgentWorkspace {
|
|
|
105
134
|
get actions(): readonly AgentWorkspaceAction[] {
|
|
106
135
|
if (this.actionSearchActive) return this.actionSearchResults.map((result) => result.action);
|
|
107
136
|
const base = this.selectedCategory.actions.filter((action) => isAgentWorkspaceActionVisible(this.context, action));
|
|
108
|
-
if (shouldShowOnboardingFinishFooter(this.selectedCategory, base)) {
|
|
137
|
+
if (shouldShowOnboardingFinishFooter(this.selectedCategory, base, this._onlyGroup === 'ONBOARDING' ? this._onboardingState?.readyToChat : undefined)) {
|
|
109
138
|
return [...base, ONBOARDING_COMPLETE_SYNTHETIC_ACTION];
|
|
110
139
|
}
|
|
111
140
|
return base;
|
|
@@ -169,21 +198,10 @@ export class AgentWorkspace {
|
|
|
169
198
|
this.focusPane = this.focusPane === 'categories' ? 'actions' : 'categories';
|
|
170
199
|
}
|
|
171
200
|
|
|
172
|
-
moveUp(): void {
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
moveDown(): void {
|
|
177
|
-
moveAgentWorkspaceSelection(this, 1);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
jumpHome(): void {
|
|
181
|
-
jumpAgentWorkspaceSelection(this, 'home');
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
jumpEnd(): void {
|
|
185
|
-
jumpAgentWorkspaceSelection(this, 'end');
|
|
186
|
-
}
|
|
201
|
+
moveUp(): void { moveAgentWorkspaceSelection(this, -1); }
|
|
202
|
+
moveDown(): void { moveAgentWorkspaceSelection(this, 1); }
|
|
203
|
+
jumpHome(): void { jumpAgentWorkspaceSelection(this, 'home'); }
|
|
204
|
+
jumpEnd(): void { jumpAgentWorkspaceSelection(this, 'end'); }
|
|
187
205
|
|
|
188
206
|
refreshRuntimeSnapshot(): void {
|
|
189
207
|
if (!this.context) {
|
|
@@ -306,6 +324,7 @@ export class AgentWorkspace {
|
|
|
306
324
|
clampAgentWorkspaceLocalLibrarySelection(this.runtimeSnapshot, this.selectedLibraryItemIndexes, 'persona');
|
|
307
325
|
clampAgentWorkspaceLocalLibrarySelection(this.runtimeSnapshot, this.selectedLibraryItemIndexes, 'skill');
|
|
308
326
|
clampAgentWorkspaceLocalLibrarySelection(this.runtimeSnapshot, this.selectedLibraryItemIndexes, 'routine');
|
|
327
|
+
clampAgentWorkspaceLocalLibrarySelection(this.runtimeSnapshot, this.selectedLibraryItemIndexes, 'profile');
|
|
309
328
|
}
|
|
310
329
|
|
|
311
330
|
moveLocalLibraryItemSelection(kind: AgentWorkspaceLocalEditorKind, delta: number): void {
|
|
@@ -323,30 +342,37 @@ export class AgentWorkspace {
|
|
|
323
342
|
}
|
|
324
343
|
|
|
325
344
|
completeOnboarding(): void {
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
this.
|
|
329
|
-
this.
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
345
|
+
const result = completeOnboardingAction({
|
|
346
|
+
awaitingRecapDismiss: this._awaitingRecapDismiss,
|
|
347
|
+
runtimeSnapshot: this.runtimeSnapshot,
|
|
348
|
+
shellPaths: this.context?.workspace?.shellPaths,
|
|
349
|
+
dismissAgentWorkspace: this.context?.dismissAgentWorkspace,
|
|
350
|
+
close: () => this.close(),
|
|
351
|
+
});
|
|
352
|
+
if (result.dismissed) return;
|
|
353
|
+
this._awaitingRecapDismiss = result.awaitingRecapDismiss;
|
|
354
|
+
this.status = result.status;
|
|
355
|
+
this.lastActionResult = result.lastActionResult;
|
|
356
|
+
}
|
|
337
357
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
this.
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
358
|
+
onSubscriptionLoginSuccess(): void {
|
|
359
|
+
const result = onSubscriptionLoginSuccessAction({
|
|
360
|
+
onlyGroup: this._onlyGroup,
|
|
361
|
+
runtimeSnapshot: this.runtimeSnapshot,
|
|
362
|
+
shellPaths: this.context?.workspace?.shellPaths,
|
|
363
|
+
});
|
|
364
|
+
if (this._onlyGroup !== 'ONBOARDING') return;
|
|
365
|
+
// Update _onboardingState and reveal set FIRST so that this.categories
|
|
366
|
+
// reflects any newly-unlocked lane (e.g. account-model after sign-in)
|
|
367
|
+
// before we try to resolve the target index against the fresh list.
|
|
368
|
+
this._onboardingState = result.onboardingState;
|
|
369
|
+
if (!result.onboardingState) return;
|
|
370
|
+
if (this._onboardingState) updateRevealedOnboardingCategories(this._onboardingState, this._revealedOnboardingCategoryIds);
|
|
371
|
+
if (result.targetCategoryId) {
|
|
372
|
+
const idx = this.categories.findIndex((c) => c.id === result.targetCategoryId);
|
|
373
|
+
if (idx >= 0) this.selectedCategoryIndex = idx;
|
|
349
374
|
}
|
|
375
|
+
this.status = result.status;
|
|
350
376
|
}
|
|
351
377
|
|
|
352
378
|
openModelPickerAction(action: AgentWorkspaceAction, requestRender?: () => void): void {
|
|
@@ -8,7 +8,6 @@ import type { ProcessManager } from '@pellux/goodvibes-sdk/platform/tools';
|
|
|
8
8
|
import type { PermissionRequestHandler } from '@pellux/goodvibes-sdk/platform/permissions';
|
|
9
9
|
import type { SelectionItem, SelectionResult, SelectionAction } from './selection-modal.ts';
|
|
10
10
|
import type { FileUndoManager } from '@pellux/goodvibes-sdk/platform/state';
|
|
11
|
-
import type { PanelManager } from '../panels/panel-manager.ts';
|
|
12
11
|
import type { KeybindingsManager } from './keybindings.ts';
|
|
13
12
|
import type { KnowledgeApi } from '@pellux/goodvibes-sdk/platform/knowledge';
|
|
14
13
|
import type { HookApi } from '@pellux/goodvibes-sdk/platform/hooks';
|
|
@@ -124,9 +123,7 @@ export interface CommandShellUiOpeners {
|
|
|
124
123
|
openProfilePicker?: () => void;
|
|
125
124
|
openShortcutsOverlay?: () => void;
|
|
126
125
|
getScrollTop?: () => number;
|
|
127
|
-
|
|
128
|
-
showPanel?: (panelId: string, pane?: 'top' | 'bottom') => void;
|
|
129
|
-
focusPanels?: () => void;
|
|
126
|
+
openWorkspacePicker?: () => void;
|
|
130
127
|
focusPrompt?: () => void;
|
|
131
128
|
openMcpWorkspace?: () => void;
|
|
132
129
|
openAgentWorkspace?: (categoryId?: string) => void;
|
|
@@ -134,6 +131,7 @@ export interface CommandShellUiOpeners {
|
|
|
134
131
|
openSecurityPanel?: () => void;
|
|
135
132
|
openKnowledgePanel?: () => void;
|
|
136
133
|
openSubscriptionPanel?: () => void;
|
|
134
|
+
toggleActivitySidebar?: () => void;
|
|
137
135
|
}
|
|
138
136
|
|
|
139
137
|
export interface CommandSessionServices {
|
|
@@ -159,7 +157,6 @@ export interface CommandProviderServices {
|
|
|
159
157
|
export interface CommandWorkspaceUiServices {
|
|
160
158
|
keybindingsManager?: KeybindingsManager;
|
|
161
159
|
fileUndoManager?: FileUndoManager;
|
|
162
|
-
panelManager?: PanelManager;
|
|
163
160
|
processManager?: ProcessManager;
|
|
164
161
|
profileManager?: import('@pellux/goodvibes-sdk/platform/profiles').ProfileManager;
|
|
165
162
|
bookmarkManager?: import('@pellux/goodvibes-sdk/platform/bookmarks').BookmarkManager;
|
|
@@ -243,6 +240,13 @@ export interface SlashCommand {
|
|
|
243
240
|
usage?: string;
|
|
244
241
|
/** Short inline argument hint shown after cursor in dim grey, e.g. "[name]". Falls back to usage if not set. */
|
|
245
242
|
argsHint?: string;
|
|
243
|
+
/**
|
|
244
|
+
* Hidden commands still run when typed, but stay out of fuzzy autocomplete
|
|
245
|
+
* suggestions. They surface in autocomplete on an exact name or alias match.
|
|
246
|
+
* The /help overlay also filters them. The /commands slash command lists
|
|
247
|
+
* all commands including hidden ones, labeled "(hidden)".
|
|
248
|
+
*/
|
|
249
|
+
hidden?: boolean;
|
|
246
250
|
/** The function executed when the command is invoked. */
|
|
247
251
|
handler: (args: string[], context: CommandContext) => void | Promise<void>;
|
|
248
252
|
}
|
|
@@ -286,6 +290,11 @@ export class CommandRegistry {
|
|
|
286
290
|
return Array.from(this.commands.values());
|
|
287
291
|
}
|
|
288
292
|
|
|
293
|
+
/** Commands that should appear in autocomplete and /help listings. */
|
|
294
|
+
getVisible(): SlashCommand[] {
|
|
295
|
+
return this.getAll().filter((command) => !command.hidden);
|
|
296
|
+
}
|
|
297
|
+
|
|
289
298
|
/**
|
|
290
299
|
* list - Compatibility alias for the simpler SDK registry surface.
|
|
291
300
|
*/
|
|
@@ -310,6 +319,10 @@ export class CommandRegistry {
|
|
|
310
319
|
if (score > bestScore) bestScore = score;
|
|
311
320
|
}
|
|
312
321
|
|
|
322
|
+
// Hidden commands stay out of suggestions until the user types the
|
|
323
|
+
// exact name or alias — they still execute normally.
|
|
324
|
+
if (cmd.hidden && !names.map((n) => n.toLowerCase()).includes(q)) continue;
|
|
325
|
+
|
|
313
326
|
if (bestScore > 0 || q === '') {
|
|
314
327
|
results.push({ command: cmd, score: q === '' ? 1 : bestScore });
|
|
315
328
|
}
|
|
@@ -139,6 +139,7 @@ export function registerAgentRuntimeProfileRuntimeCommands(registry: CommandRegi
|
|
|
139
139
|
name: 'agent-profile',
|
|
140
140
|
aliases: ['runtime-profile', 'agent-profiles'],
|
|
141
141
|
description: 'Manage isolated Agent profiles and starter templates',
|
|
142
|
+
hidden: true,
|
|
142
143
|
usage: '[list|show|default|use|templates|guide|template show|template export|template import|template from-discovered|create|create-from-discovered|delete]',
|
|
143
144
|
async handler(args, ctx) {
|
|
144
145
|
const shellPaths = requireShellPaths(ctx);
|
|
@@ -244,7 +245,7 @@ export function registerAgentRuntimeProfileRuntimeCommands(registry: CommandRegi
|
|
|
244
245
|
const templateId = commandArgs[2];
|
|
245
246
|
const pathArg = commandArgs[3];
|
|
246
247
|
if (!templateId || !pathArg) {
|
|
247
|
-
|
|
248
|
+
ctx.print('Usage: /agent-profile template export <id> <path> [--include-vibe] --yes');
|
|
248
249
|
return;
|
|
249
250
|
}
|
|
250
251
|
if (!parsed.yes) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
1
2
|
import {
|
|
2
3
|
AgentSkillRegistry,
|
|
3
4
|
buildAgentSkillRequirements,
|
|
@@ -8,6 +9,7 @@ import {
|
|
|
8
9
|
type AgentSkillRecord,
|
|
9
10
|
} from '../../agent/skill-registry.ts';
|
|
10
11
|
import { discoverSkills, type SkillRecord } from '../../agent/skill-discovery.ts';
|
|
12
|
+
import { parseSkillStandardMarkdown } from '../../agent/skill-standard.ts';
|
|
11
13
|
import { formatAgentRecordOrigin, formatAgentRecordReviewState } from '../../agent/record-labels.ts';
|
|
12
14
|
import type { CommandContext, CommandRegistry } from '../command-registry.ts';
|
|
13
15
|
import { parseAgentLocalLibraryArgs, type ParsedAgentLocalLibraryArgs } from './agent-local-library-args.ts';
|
|
@@ -137,7 +139,7 @@ async function importDiscoveredSkill(args: readonly string[], ctx: CommandContex
|
|
|
137
139
|
const parsed = parseSkillArgs(args);
|
|
138
140
|
const name = parsed.rest.join(' ').trim();
|
|
139
141
|
if (!name) {
|
|
140
|
-
ctx.print('Usage: /skills import-discovered <name>
|
|
142
|
+
ctx.print('Usage: /skills import-discovered <name> --yes\n Note: discovered skills import disabled; review then enable via /skills enable <name>.');
|
|
141
143
|
return;
|
|
142
144
|
}
|
|
143
145
|
const discovered = findDiscoveredSkill(await discoverSkills(requireShellPaths(ctx)), name);
|
|
@@ -167,11 +169,14 @@ async function importDiscoveredSkill(args: readonly string[], ctx: CommandContex
|
|
|
167
169
|
env: frontmatterAnyList(discovered, ['requiresEnv', 'requires-env', 'requires_env']),
|
|
168
170
|
commands: frontmatterAnyList(discovered, ['requiresCommands', 'requires-commands', 'requires_commands', 'commands']),
|
|
169
171
|
}),
|
|
170
|
-
enabled:
|
|
172
|
+
enabled: false,
|
|
171
173
|
source: 'imported',
|
|
172
174
|
provenance: `Imported file (${discovered.origin}): ${discovered.path}`,
|
|
173
175
|
});
|
|
174
|
-
ctx.print(formatSkillReceipt('Imported Agent skill', skill, [
|
|
176
|
+
ctx.print(formatSkillReceipt('Imported Agent skill', skill, [
|
|
177
|
+
' enabled no — imported disabled (review it, then enable it)',
|
|
178
|
+
' review pending',
|
|
179
|
+
]));
|
|
175
180
|
}
|
|
176
181
|
|
|
177
182
|
function renderBundleList(title: string, registry: AgentSkillRegistry, bundles: readonly AgentSkillBundleRecord[], emptyMessage?: string): string {
|
|
@@ -377,6 +382,57 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
|
|
|
377
382
|
await importDiscoveredSkill(args.slice(1), ctx, skillRegistry);
|
|
378
383
|
return;
|
|
379
384
|
}
|
|
385
|
+
if (sub === 'import-standard') {
|
|
386
|
+
const parsed = parseSkillArgs(args.slice(1));
|
|
387
|
+
const filePath = parsed.rest[0];
|
|
388
|
+
if (!filePath) {
|
|
389
|
+
ctx.print('Usage: /skills import-standard <path/to/SKILL.md> --yes');
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
if (!parsed.yes) {
|
|
393
|
+
ctx.print([
|
|
394
|
+
'Agent skill standard import preview',
|
|
395
|
+
` path ${filePath}`,
|
|
396
|
+
' next rerun with --yes to import into the Agent-local skill registry',
|
|
397
|
+
].join('\n'));
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
401
|
+
const parseResult = parseSkillStandardMarkdown(content);
|
|
402
|
+
if ('error' in parseResult) {
|
|
403
|
+
ctx.print(`Skill standard import rejected: ${parseResult.error}`);
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const skill = skillRegistry.importFromStandard(content);
|
|
407
|
+
ctx.print(formatSkillReceipt('Imported shared skill', skill, [` source ${filePath}`, ` review-state ${skill.reviewState}`]));
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
if (sub === 'export-standard') {
|
|
411
|
+
const parsed = parseSkillArgs(args.slice(1));
|
|
412
|
+
const skillId = parsed.rest[0];
|
|
413
|
+
const destDir = parsed.rest[1];
|
|
414
|
+
if (!skillId || !destDir) {
|
|
415
|
+
ctx.print('Usage: /skills export-standard <id> <dest-directory> --yes');
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (!parsed.yes) {
|
|
419
|
+
const skill = skillRegistry.get(skillId);
|
|
420
|
+
if (!skill) {
|
|
421
|
+
ctx.print(`Unknown Agent skill ${skillId}`);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
ctx.print([
|
|
425
|
+
'Agent skill standard export preview',
|
|
426
|
+
` skill ${skill.id} (${skill.name})`,
|
|
427
|
+
` dest ${destDir}/${skill.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '')}/SKILL.md`,
|
|
428
|
+
' next rerun with --yes to write the file',
|
|
429
|
+
].join('\n'));
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
const written = skillRegistry.exportToStandard(skillId, destDir);
|
|
433
|
+
ctx.print(`Exported skill to ${written}`);
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
380
436
|
if (sub === 'list' || sub === 'open') {
|
|
381
437
|
ctx.print(renderList('Agent Skills', skillRegistry, skillRegistry.list()));
|
|
382
438
|
return;
|
|
@@ -506,6 +562,7 @@ export function registerAgentSkillsRuntimeCommands(registry: CommandRegistry): v
|
|
|
506
562
|
name: 'skills',
|
|
507
563
|
aliases: ['skill', 'agent-skills', 'askills', 'local-skills'],
|
|
508
564
|
description: 'Manage Agent-local skills',
|
|
565
|
+
hidden: true,
|
|
509
566
|
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 ...]',
|
|
510
567
|
handler: runAgentSkillsRuntimeCommand,
|
|
511
568
|
});
|