@pellux/goodvibes-agent 0.1.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/.goodvibes/GOODVIBES.md +35 -0
- package/.goodvibes/agents/reviewer.md +48 -0
- package/.goodvibes/skills/add-provider/SKILL.md +199 -0
- package/CHANGELOG.md +25 -0
- package/README.md +74 -0
- package/bin/goodvibes-agent.ts +2 -0
- package/docs/README.md +23 -0
- package/docs/deployment-and-services.md +57 -0
- package/docs/getting-started.md +53 -0
- package/docs/release-and-publishing.md +46 -0
- package/package.json +134 -0
- package/scripts/check-bun.sh +20 -0
- package/src/audio/player.ts +156 -0
- package/src/audio/spoken-turn-controller.ts +203 -0
- package/src/audio/spoken-turn-model-routing.ts +117 -0
- package/src/audio/spoken-turn-wiring.ts +44 -0
- package/src/audio/text-chunker.ts +110 -0
- package/src/cli/bundle-command.ts +227 -0
- package/src/cli/completion.ts +90 -0
- package/src/cli/config-overrides.ts +159 -0
- package/src/cli/endpoints.ts +63 -0
- package/src/cli/entrypoint.ts +172 -0
- package/src/cli/help.ts +299 -0
- package/src/cli/index.ts +11 -0
- package/src/cli/management-commands.ts +426 -0
- package/src/cli/management.ts +744 -0
- package/src/cli/network-posture.ts +46 -0
- package/src/cli/package-verification.ts +123 -0
- package/src/cli/parser.ts +369 -0
- package/src/cli/provider-auth-routes.ts +22 -0
- package/src/cli/provider-classification.ts +107 -0
- package/src/cli/redaction.ts +105 -0
- package/src/cli/service-command.ts +26 -0
- package/src/cli/service-posture.ts +482 -0
- package/src/cli/status.ts +383 -0
- package/src/cli/surface-command.ts +247 -0
- package/src/cli/tui-startup.ts +32 -0
- package/src/cli/types.ts +69 -0
- package/src/cli-flags.ts +21 -0
- package/src/config/goodvibes-home-audit.ts +465 -0
- package/src/config/index.ts +57 -0
- package/src/config/provider-model.ts +23 -0
- package/src/config/secret-config.ts +119 -0
- package/src/config/secrets.ts +71 -0
- package/src/config/surface.ts +1 -0
- package/src/core/composer-state.ts +61 -0
- package/src/core/conversation-rendering.ts +359 -0
- package/src/core/conversation.ts +551 -0
- package/src/core/history.ts +45 -0
- package/src/core/orchestrator.ts +7 -0
- package/src/core/system-message-router.ts +171 -0
- package/src/daemon/cli.ts +55 -0
- package/src/daemon/safe-serve.ts +61 -0
- package/src/input/agent-workspace.ts +428 -0
- package/src/input/autocomplete.ts +96 -0
- package/src/input/bookmark-modal.ts +115 -0
- package/src/input/command-args-hint.ts +36 -0
- package/src/input/command-registry.ts +329 -0
- package/src/input/commands/agent-externalized-tui.ts +73 -0
- package/src/input/commands/agent-workspace-runtime.ts +17 -0
- package/src/input/commands/branch-runtime.ts +72 -0
- package/src/input/commands/cloudflare-runtime.ts +370 -0
- package/src/input/commands/config.ts +18 -0
- package/src/input/commands/control-room-runtime.ts +255 -0
- package/src/input/commands/conversation-runtime.ts +207 -0
- package/src/input/commands/discovery-runtime.ts +52 -0
- package/src/input/commands/eval.ts +204 -0
- package/src/input/commands/experience-runtime.ts +278 -0
- package/src/input/commands/guidance-runtime.ts +106 -0
- package/src/input/commands/health-runtime.ts +434 -0
- package/src/input/commands/hooks-runtime.ts +148 -0
- package/src/input/commands/incident-runtime.ts +95 -0
- package/src/input/commands/integration-runtime.ts +394 -0
- package/src/input/commands/intelligence-runtime.ts +223 -0
- package/src/input/commands/knowledge.ts +531 -0
- package/src/input/commands/local-auth-runtime.ts +105 -0
- package/src/input/commands/local-provider-runtime.ts +170 -0
- package/src/input/commands/local-runtime.ts +392 -0
- package/src/input/commands/local-setup-review.ts +199 -0
- package/src/input/commands/local-setup-transfer.ts +135 -0
- package/src/input/commands/local-setup.ts +282 -0
- package/src/input/commands/managed-runtime.ts +209 -0
- package/src/input/commands/marketplace-runtime.ts +290 -0
- package/src/input/commands/mcp-runtime.ts +432 -0
- package/src/input/commands/memory-product-runtime.ts +111 -0
- package/src/input/commands/memory.ts +151 -0
- package/src/input/commands/notify-runtime.ts +83 -0
- package/src/input/commands/onboarding-runtime.ts +14 -0
- package/src/input/commands/operator-panel-runtime.ts +146 -0
- package/src/input/commands/operator-runtime.ts +392 -0
- package/src/input/commands/planning-runtime.ts +205 -0
- package/src/input/commands/platform-access-runtime.ts +422 -0
- package/src/input/commands/platform-services-runtime.ts +246 -0
- package/src/input/commands/policy-dispatch.ts +339 -0
- package/src/input/commands/policy.ts +17 -0
- package/src/input/commands/product-runtime.ts +351 -0
- package/src/input/commands/profile-sync-runtime.ts +99 -0
- package/src/input/commands/provider-accounts-runtime.ts +113 -0
- package/src/input/commands/provider.ts +363 -0
- package/src/input/commands/qrcode-runtime.ts +20 -0
- package/src/input/commands/quit-shared.ts +162 -0
- package/src/input/commands/recall-bundle.ts +132 -0
- package/src/input/commands/recall-capture.ts +152 -0
- package/src/input/commands/recall-query.ts +229 -0
- package/src/input/commands/recall-review.ts +98 -0
- package/src/input/commands/recall-shared.ts +22 -0
- package/src/input/commands/remote-runtime-pool.ts +106 -0
- package/src/input/commands/remote-runtime-setup.ts +199 -0
- package/src/input/commands/remote-runtime.ts +431 -0
- package/src/input/commands/replay-runtime.ts +18 -0
- package/src/input/commands/runtime-services.ts +291 -0
- package/src/input/commands/schedule-runtime.ts +91 -0
- package/src/input/commands/services-runtime.ts +209 -0
- package/src/input/commands/session-content.ts +408 -0
- package/src/input/commands/session-workflow.ts +464 -0
- package/src/input/commands/session.ts +375 -0
- package/src/input/commands/settings-sync-runtime.ts +174 -0
- package/src/input/commands/share-runtime.ts +119 -0
- package/src/input/commands/shell-core.ts +307 -0
- package/src/input/commands/skills-runtime.ts +221 -0
- package/src/input/commands/subscription-runtime.ts +434 -0
- package/src/input/commands/tasks-runtime.ts +230 -0
- package/src/input/commands/teamwork-runtime.ts +339 -0
- package/src/input/commands/teleport-runtime.ts +57 -0
- package/src/input/commands/tts-runtime.ts +29 -0
- package/src/input/commands/work-plan-runtime.ts +169 -0
- package/src/input/commands.ts +131 -0
- package/src/input/feed-context-factory.ts +254 -0
- package/src/input/file-picker.ts +192 -0
- package/src/input/handler-command-route.ts +180 -0
- package/src/input/handler-content-actions.ts +497 -0
- package/src/input/handler-feed-routes.ts +648 -0
- package/src/input/handler-feed.ts +452 -0
- package/src/input/handler-interactions.ts +281 -0
- package/src/input/handler-modal-routes.ts +418 -0
- package/src/input/handler-modal-stack.ts +263 -0
- package/src/input/handler-modal-token-routes.ts +329 -0
- package/src/input/handler-onboarding-cloudflare.ts +391 -0
- package/src/input/handler-onboarding.ts +620 -0
- package/src/input/handler-picker-routes.ts +472 -0
- package/src/input/handler-prompt-buffer.ts +320 -0
- package/src/input/handler-shortcuts.ts +213 -0
- package/src/input/handler-ui-state.ts +372 -0
- package/src/input/handler.ts +729 -0
- package/src/input/input-history.ts +297 -0
- package/src/input/keybindings.ts +292 -0
- package/src/input/mcp-workspace.ts +554 -0
- package/src/input/model-picker-provider-filter.ts +28 -0
- package/src/input/model-picker-types.ts +137 -0
- package/src/input/model-picker.ts +797 -0
- package/src/input/onboarding/handler-onboarding-routes.ts +125 -0
- package/src/input/onboarding/onboarding-runtime-status.ts +87 -0
- package/src/input/onboarding/onboarding-wizard-apply.ts +277 -0
- package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +494 -0
- package/src/input/onboarding/onboarding-wizard-cloudflare.ts +204 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +158 -0
- package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +130 -0
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +762 -0
- package/src/input/onboarding/onboarding-wizard-helpers.ts +167 -0
- package/src/input/onboarding/onboarding-wizard-rules.ts +256 -0
- package/src/input/onboarding/onboarding-wizard-state.ts +365 -0
- package/src/input/onboarding/onboarding-wizard-steps.ts +798 -0
- package/src/input/onboarding/onboarding-wizard-types.ts +195 -0
- package/src/input/onboarding/onboarding-wizard.ts +711 -0
- package/src/input/panel-integration-actions.ts +78 -0
- package/src/input/profile-picker-modal.ts +222 -0
- package/src/input/search.ts +100 -0
- package/src/input/selection-modal.ts +163 -0
- package/src/input/selection.ts +135 -0
- package/src/input/session-picker-modal.ts +136 -0
- package/src/input/settings-modal-behavior.ts +37 -0
- package/src/input/settings-modal-secrets.ts +41 -0
- package/src/input/settings-modal-subscriptions.ts +95 -0
- package/src/input/settings-modal-types.ts +91 -0
- package/src/input/settings-modal.ts +793 -0
- package/src/input/submission-intent.ts +17 -0
- package/src/input/submission-router.ts +59 -0
- package/src/input/tts-settings-actions.ts +100 -0
- package/src/main.ts +792 -0
- package/src/mcp/runtime-reload.ts +81 -0
- package/src/panels/agent-inspector-panel.ts +521 -0
- package/src/panels/agent-inspector-shared.ts +94 -0
- package/src/panels/agent-logs-panel.ts +559 -0
- package/src/panels/agent-logs-shared.ts +129 -0
- package/src/panels/approval-panel.ts +150 -0
- package/src/panels/automation-control-panel.ts +212 -0
- package/src/panels/base-panel.ts +254 -0
- package/src/panels/builtin/agent.ts +117 -0
- package/src/panels/builtin/development.ts +31 -0
- package/src/panels/builtin/knowledge.ts +26 -0
- package/src/panels/builtin/operations.ts +349 -0
- package/src/panels/builtin/session.ts +129 -0
- package/src/panels/builtin/shared.ts +274 -0
- package/src/panels/builtin-panels.ts +23 -0
- package/src/panels/cockpit-panel.ts +183 -0
- package/src/panels/communication-panel.ts +153 -0
- package/src/panels/confirm-state.ts +61 -0
- package/src/panels/context-visualizer-panel.ts +204 -0
- package/src/panels/control-plane-panel.ts +211 -0
- package/src/panels/cost-tracker-panel.ts +444 -0
- package/src/panels/debug-panel.ts +432 -0
- package/src/panels/diff-panel.ts +520 -0
- package/src/panels/docs-panel.ts +283 -0
- package/src/panels/eval-panel.ts +399 -0
- package/src/panels/file-explorer-panel.ts +584 -0
- package/src/panels/file-preview-panel.ts +434 -0
- package/src/panels/forensics-panel.ts +364 -0
- package/src/panels/git-panel.ts +638 -0
- package/src/panels/hooks-panel.ts +239 -0
- package/src/panels/incident-review-panel.ts +197 -0
- package/src/panels/index.ts +46 -0
- package/src/panels/intelligence-panel.ts +176 -0
- package/src/panels/knowledge-panel.ts +345 -0
- package/src/panels/local-auth-panel.ts +130 -0
- package/src/panels/marketplace-panel.ts +212 -0
- package/src/panels/memory-panel.ts +225 -0
- package/src/panels/ops-control-panel.ts +150 -0
- package/src/panels/ops-strategy-panel.ts +235 -0
- package/src/panels/orchestration-panel.ts +273 -0
- package/src/panels/panel-list-panel.ts +509 -0
- package/src/panels/panel-manager.ts +570 -0
- package/src/panels/panel-picker.ts +106 -0
- package/src/panels/plan-dashboard-panel.ts +274 -0
- package/src/panels/plugins-panel.ts +178 -0
- package/src/panels/policy-panel.ts +308 -0
- package/src/panels/polish.ts +717 -0
- package/src/panels/project-planning-panel.ts +711 -0
- package/src/panels/provider-account-snapshot.ts +259 -0
- package/src/panels/provider-accounts-panel.ts +218 -0
- package/src/panels/provider-health-domains.ts +215 -0
- package/src/panels/provider-health-panel.ts +727 -0
- package/src/panels/provider-health-tracker.ts +115 -0
- package/src/panels/provider-stats-panel.ts +366 -0
- package/src/panels/qr-panel.ts +182 -0
- package/src/panels/remote-panel.ts +449 -0
- package/src/panels/routes-panel.ts +178 -0
- package/src/panels/sandbox-panel.ts +283 -0
- package/src/panels/schedule-panel.ts +329 -0
- package/src/panels/scrollable-list-panel.ts +491 -0
- package/src/panels/search-focus.ts +32 -0
- package/src/panels/security-panel.ts +295 -0
- package/src/panels/services-panel.ts +231 -0
- package/src/panels/session-browser-panel.ts +400 -0
- package/src/panels/session-maintenance.ts +125 -0
- package/src/panels/settings-sync-panel.ts +120 -0
- package/src/panels/skills-panel.ts +431 -0
- package/src/panels/subscription-panel.ts +263 -0
- package/src/panels/symbol-outline-panel.ts +486 -0
- package/src/panels/system-messages-panel.ts +230 -0
- package/src/panels/tasks-panel.ts +399 -0
- package/src/panels/thinking-panel.ts +304 -0
- package/src/panels/token-budget-panel.ts +475 -0
- package/src/panels/tool-inspector-panel.ts +429 -0
- package/src/panels/types.ts +54 -0
- package/src/panels/watchers-panel.ts +193 -0
- package/src/panels/work-plan-panel.ts +175 -0
- package/src/panels/worktree-panel.ts +182 -0
- package/src/panels/wrfc-panel.ts +609 -0
- package/src/permissions/prompt.ts +165 -0
- package/src/planning/project-planning-coordinator.ts +543 -0
- package/src/plugins/loader.ts +15 -0
- package/src/renderer/agent-detail-modal.ts +331 -0
- package/src/renderer/agent-workspace.ts +238 -0
- package/src/renderer/ansi-sanitize.ts +76 -0
- package/src/renderer/autocomplete-overlay.ts +154 -0
- package/src/renderer/block-actions.ts +76 -0
- package/src/renderer/bookmark-modal.ts +101 -0
- package/src/renderer/bottom-bar.ts +58 -0
- package/src/renderer/buffer.ts +113 -0
- package/src/renderer/code-block.ts +373 -0
- package/src/renderer/compositor.ts +283 -0
- package/src/renderer/context-inspector.ts +219 -0
- package/src/renderer/conversation-layout.ts +67 -0
- package/src/renderer/conversation-overlays.ts +140 -0
- package/src/renderer/conversation-surface.ts +260 -0
- package/src/renderer/diff-view.ts +132 -0
- package/src/renderer/diff.ts +130 -0
- package/src/renderer/file-picker-overlay.ts +101 -0
- package/src/renderer/file-tree.ts +153 -0
- package/src/renderer/fullscreen-primitives.ts +130 -0
- package/src/renderer/fullscreen-workspace.ts +199 -0
- package/src/renderer/git-status.ts +89 -0
- package/src/renderer/help-overlay.ts +267 -0
- package/src/renderer/history-search-overlay.ts +73 -0
- package/src/renderer/layout-engine.ts +97 -0
- package/src/renderer/layout.ts +32 -0
- package/src/renderer/live-tail-modal.ts +156 -0
- package/src/renderer/markdown.ts +635 -0
- package/src/renderer/mcp-workspace.ts +237 -0
- package/src/renderer/modal-factory.ts +467 -0
- package/src/renderer/modal-utils.ts +24 -0
- package/src/renderer/model-picker-overlay.ts +473 -0
- package/src/renderer/model-workspace.ts +488 -0
- package/src/renderer/onboarding/onboarding-wizard.ts +615 -0
- package/src/renderer/overlay-box.ts +146 -0
- package/src/renderer/overlay-viewport.ts +104 -0
- package/src/renderer/panel-composite.ts +158 -0
- package/src/renderer/panel-picker-overlay.ts +202 -0
- package/src/renderer/panel-tab-bar.ts +69 -0
- package/src/renderer/panel-workspace-bar.ts +42 -0
- package/src/renderer/process-indicator.ts +96 -0
- package/src/renderer/process-modal.ts +656 -0
- package/src/renderer/process-summary.ts +67 -0
- package/src/renderer/profile-picker-modal.ts +129 -0
- package/src/renderer/progress.ts +98 -0
- package/src/renderer/qr-renderer.ts +120 -0
- package/src/renderer/search-overlay.ts +54 -0
- package/src/renderer/selection-modal-overlay.ts +214 -0
- package/src/renderer/semantic-diff.ts +369 -0
- package/src/renderer/session-picker-modal.ts +127 -0
- package/src/renderer/settings-modal-helpers.ts +193 -0
- package/src/renderer/settings-modal.ts +537 -0
- package/src/renderer/shell-surface.ts +88 -0
- package/src/renderer/status-glyphs.ts +21 -0
- package/src/renderer/status-token.ts +67 -0
- package/src/renderer/surface-layout.ts +101 -0
- package/src/renderer/syntax-highlighter.ts +542 -0
- package/src/renderer/system-message.ts +83 -0
- package/src/renderer/tab-strip.ts +108 -0
- package/src/renderer/text-layout.ts +31 -0
- package/src/renderer/thinking.ts +17 -0
- package/src/renderer/tool-call.ts +234 -0
- package/src/renderer/ui-factory.ts +524 -0
- package/src/renderer/ui-primitives.ts +96 -0
- package/src/runtime/bootstrap-command-context.ts +278 -0
- package/src/runtime/bootstrap-command-parts.ts +386 -0
- package/src/runtime/bootstrap-core.ts +540 -0
- package/src/runtime/bootstrap-hook-bridge.ts +112 -0
- package/src/runtime/bootstrap-shell.ts +283 -0
- package/src/runtime/bootstrap.ts +575 -0
- package/src/runtime/cloudflare-control-plane.ts +349 -0
- package/src/runtime/context.ts +142 -0
- package/src/runtime/diagnostics/panels/index.ts +24 -0
- package/src/runtime/diagnostics/panels/ops.ts +156 -0
- package/src/runtime/diagnostics/panels/panel-resources.ts +118 -0
- package/src/runtime/diagnostics/panels/policy.ts +177 -0
- package/src/runtime/index.ts +662 -0
- package/src/runtime/onboarding/apply.ts +642 -0
- package/src/runtime/onboarding/derivation.ts +534 -0
- package/src/runtime/onboarding/index.ts +7 -0
- package/src/runtime/onboarding/markers.ts +148 -0
- package/src/runtime/onboarding/snapshot.ts +406 -0
- package/src/runtime/onboarding/state.ts +141 -0
- package/src/runtime/onboarding/types.ts +404 -0
- package/src/runtime/onboarding/verify.ts +171 -0
- package/src/runtime/operator-token-cleanup.ts +27 -0
- package/src/runtime/perf/panel-contracts.ts +32 -0
- package/src/runtime/perf/panel-health-monitor.ts +18 -0
- package/src/runtime/sandbox-public-gaps.ts +358 -0
- package/src/runtime/services.ts +670 -0
- package/src/runtime/store/domains/domain-read-matrix.ts +15 -0
- package/src/runtime/store/domains/index.ts +222 -0
- package/src/runtime/store/domains/panels.ts +117 -0
- package/src/runtime/store/domains/ui-perf.ts +103 -0
- package/src/runtime/store/index.ts +305 -0
- package/src/runtime/store/selectors/index.ts +359 -0
- package/src/runtime/store/state.ts +145 -0
- package/src/runtime/surface-feature-flags.ts +65 -0
- package/src/runtime/terminal-output-guard.ts +228 -0
- package/src/runtime/ui/index.ts +39 -0
- package/src/runtime/ui/model-picker/data-provider.ts +182 -0
- package/src/runtime/ui/model-picker/health-enrichment.ts +228 -0
- package/src/runtime/ui/model-picker/index.ts +59 -0
- package/src/runtime/ui/model-picker/types.ts +149 -0
- package/src/runtime/ui/provider-health/data-provider.ts +244 -0
- package/src/runtime/ui/provider-health/fallback-visualizer.ts +71 -0
- package/src/runtime/ui/provider-health/index.ts +46 -0
- package/src/runtime/ui/provider-health/types.ts +146 -0
- package/src/runtime/ui-events.ts +1 -0
- package/src/runtime/ui-read-model-helpers.ts +1 -0
- package/src/runtime/ui-read-models-observability-maintenance.ts +1 -0
- package/src/runtime/ui-read-models-observability-options.ts +1 -0
- package/src/runtime/ui-read-models-observability-remote.ts +1 -0
- package/src/runtime/ui-read-models-observability-security.ts +1 -0
- package/src/runtime/ui-read-models-observability-system.ts +1 -0
- package/src/runtime/ui-read-models-observability.ts +1 -0
- package/src/runtime/ui-read-models.ts +61 -0
- package/src/runtime/ui-service-queries.ts +1 -0
- package/src/runtime/ui-services.ts +190 -0
- package/src/scripts/process-messages.ts +42 -0
- package/src/shell/blocking-input.ts +98 -0
- package/src/shell/service-settings-sync.ts +273 -0
- package/src/shell/ui-openers.ts +352 -0
- package/src/tools/index.ts +1 -0
- package/src/tools/wrfc-agent-guard.ts +49 -0
- package/src/types/grid.ts +48 -0
- package/src/types/sql-js.d.ts +15 -0
- package/src/utils/clipboard.ts +22 -0
- package/src/utils/splash-lines.ts +46 -0
- package/src/utils/terminal-width.ts +185 -0
- package/src/verification/live-verifier.ts +430 -0
- package/src/verification/verification-ledger.ts +242 -0
- package/src/version.ts +17 -0
- package/src/widget/index.ts +2 -0
- package/src/widget/types.ts +9 -0
- package/src/widget/widget.ts +8 -0
- package/src/work-plans/work-plan-store.ts +374 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import type { CommandRegistry } from '../command-registry.ts';
|
|
2
|
+
import type { SelectionItem } from '../selection-modal.ts';
|
|
3
|
+
import { EFFORT_DESCRIPTIONS } from '@pellux/goodvibes-sdk/platform/providers';
|
|
4
|
+
import { REASONING_BUDGET_MAP } from '@pellux/goodvibes-sdk/platform/providers';
|
|
5
|
+
import { executeWriteQuit } from './quit-shared.ts';
|
|
6
|
+
import { compactConversation, requireKeybindingsManager, requireProviderApi } from './runtime-services.ts';
|
|
7
|
+
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
8
|
+
import { logger } from '@pellux/goodvibes-sdk/platform/utils';
|
|
9
|
+
|
|
10
|
+
export function registerShellCoreCommands(registry: CommandRegistry): void {
|
|
11
|
+
registry.register({
|
|
12
|
+
name: 'model',
|
|
13
|
+
aliases: ['m'],
|
|
14
|
+
description: 'Select or display the current LLM model',
|
|
15
|
+
usage: '[model-id]',
|
|
16
|
+
argsHint: '[name]',
|
|
17
|
+
async handler(args, ctx) {
|
|
18
|
+
const providerApi = requireProviderApi(ctx);
|
|
19
|
+
if (args.length === 0) {
|
|
20
|
+
if (ctx.openModelPicker) {
|
|
21
|
+
ctx.openModelPicker();
|
|
22
|
+
} else {
|
|
23
|
+
const models = await providerApi.listModels({ selectableOnly: true });
|
|
24
|
+
const lines = ['Available models:', ...models.map((model) =>
|
|
25
|
+
` ${model.current ? '▶' : ' '} ${model.registryKey.padEnd(36)} ${model.displayName} (${model.providerId})`,
|
|
26
|
+
)];
|
|
27
|
+
ctx.print(lines.join('\n'));
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
const modelId = args[0];
|
|
31
|
+
try {
|
|
32
|
+
const selected = await providerApi.selectModel(modelId);
|
|
33
|
+
ctx.session.runtime.model = selected.registryKey;
|
|
34
|
+
ctx.session.runtime.provider = selected.providerId;
|
|
35
|
+
ctx.platform.configManager.set('provider.model', selected.registryKey);
|
|
36
|
+
ctx.print(`Switched to model: ${selected.displayName} (${selected.providerId})`);
|
|
37
|
+
void providerApi.recordModelUsage(selected.registryKey).catch((err) => { logger.debug('model usage record failed', { err }); });
|
|
38
|
+
} catch (e) {
|
|
39
|
+
ctx.print(`Error: ${summarizeError(e)}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
registry.register({
|
|
46
|
+
name: 'commands',
|
|
47
|
+
aliases: ['cmds'],
|
|
48
|
+
description: 'Browse all commands in a scrollable list',
|
|
49
|
+
handler(_args, ctx) {
|
|
50
|
+
if (ctx.openHelpOverlay) {
|
|
51
|
+
ctx.openHelpOverlay();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
ctx.print('Use /help for interactive command list');
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
registry.register({
|
|
59
|
+
name: 'shortcuts',
|
|
60
|
+
aliases: ['keys', 'keybinds'],
|
|
61
|
+
description: 'Show keyboard shortcuts reference',
|
|
62
|
+
handler(_args, ctx) {
|
|
63
|
+
if (ctx.openShortcutsOverlay) {
|
|
64
|
+
ctx.openShortcutsOverlay();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
ctx.print('Use ? key or /help for shortcuts');
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
registry.register({
|
|
72
|
+
name: 'keybindings',
|
|
73
|
+
aliases: ['kb'],
|
|
74
|
+
description: 'List current keyboard bindings and their config file path',
|
|
75
|
+
handler(_args, ctx) {
|
|
76
|
+
const km = requireKeybindingsManager(ctx);
|
|
77
|
+
const all = km.getAll();
|
|
78
|
+
const lines: string[] = [
|
|
79
|
+
`Keybindings config: ${km.getConfigPath()}`,
|
|
80
|
+
'',
|
|
81
|
+
` ${'Action'.padEnd(28)} ${'Binding'.padEnd(20)} Description`,
|
|
82
|
+
` ${'─'.repeat(28)} ${'─'.repeat(20)} ${'─'.repeat(34)}`,
|
|
83
|
+
];
|
|
84
|
+
for (const { action, combos, description } of all) {
|
|
85
|
+
const label = combos.map((combo) => km.formatCombo(combo)).join(', ');
|
|
86
|
+
lines.push(` ${action.padEnd(28)} ${label.padEnd(20)} ${description}`);
|
|
87
|
+
}
|
|
88
|
+
lines.push('');
|
|
89
|
+
lines.push('To customize: create the config file with { "action": { "key": "x", "ctrl": true } }');
|
|
90
|
+
ctx.print(lines.join('\n'));
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
registry.register({
|
|
95
|
+
name: 'paste',
|
|
96
|
+
aliases: ['clip'],
|
|
97
|
+
description: 'Insert clipboard text or image into the prompt',
|
|
98
|
+
handler(_args, ctx) {
|
|
99
|
+
if (!ctx.pasteFromClipboard) {
|
|
100
|
+
ctx.print('Paste is not available in this context.');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const result = ctx.pasteFromClipboard();
|
|
104
|
+
if (!result.pasted) {
|
|
105
|
+
ctx.print('Clipboard does not contain supported text or image data.');
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
registry.register({
|
|
111
|
+
name: 'help',
|
|
112
|
+
aliases: ['h', '?'],
|
|
113
|
+
description: 'Show available commands and keyboard shortcuts',
|
|
114
|
+
argsHint: '[command]',
|
|
115
|
+
handler(_args, ctx) {
|
|
116
|
+
if (ctx.openSelection) {
|
|
117
|
+
const items: SelectionItem[] = [
|
|
118
|
+
{ id: '/agent', label: '/agent', detail: 'Open the Agent operator workspace', category: 'Agent Operator' },
|
|
119
|
+
{ id: '/home', label: '/home', detail: 'Alias for the Agent operator workspace', category: 'Agent Operator' },
|
|
120
|
+
{ id: '/model', label: '/model [id]', detail: 'Select LLM model', category: 'Model & Provider' },
|
|
121
|
+
{ id: '/provider', label: '/provider [name]', detail: 'Switch provider', category: 'Model & Provider' },
|
|
122
|
+
{ id: '/effort', label: '/effort [level]', detail: 'Reasoning effort (instant/low/medium/high)', category: 'Model & Provider' },
|
|
123
|
+
{ id: '/config', label: '/config [category|key]', detail: 'Open fullscreen configuration workspace', category: 'Config & Display' },
|
|
124
|
+
{ id: '/debug', label: '/debug', detail: 'Toggle debug mode', category: 'Config & Display' },
|
|
125
|
+
{ id: '/expand', label: '/expand [type]', detail: 'Expand blocks (all|thinking|tool|code)', category: 'Config & Display' },
|
|
126
|
+
{ id: '/collapse', label: '/collapse [type]', detail: 'Collapse blocks', category: 'Config & Display' },
|
|
127
|
+
{ id: '/bookmarks', label: '/bookmarks', detail: 'List bookmarked blocks', category: 'Config & Display' },
|
|
128
|
+
{ id: '/clear', label: '/clear', detail: 'Clear display (keep context)', category: 'Conversation' },
|
|
129
|
+
{ id: '/reset', label: '/reset', detail: 'Clear display + context', category: 'Conversation' },
|
|
130
|
+
{ id: '/compact', label: '/compact', detail: 'Summarize to free context', category: 'Conversation' },
|
|
131
|
+
{ id: '/export', label: '/export [file]', detail: 'Export as markdown', category: 'Conversation' },
|
|
132
|
+
{ id: '/title', label: '/title [text]', detail: 'Show or set title', category: 'Conversation' },
|
|
133
|
+
{ id: '/save', label: '/save [name]', detail: 'Save session', category: 'Conversation' },
|
|
134
|
+
{ id: '/load', label: '/load <name>', detail: 'Load session', category: 'Conversation' },
|
|
135
|
+
{ id: '/sessions', label: '/sessions', detail: 'List saved sessions', category: 'Conversation' },
|
|
136
|
+
{ id: '/session', label: '/session', detail: 'Current session info', category: 'Conversation' },
|
|
137
|
+
{ id: '/session list', label: '/session list', detail: 'List all sessions', category: 'Conversation' },
|
|
138
|
+
{ id: '/session rename', label: '/session rename <name>', detail: 'Rename current session', category: 'Conversation' },
|
|
139
|
+
{ id: '/session resume', label: '/session resume <id>', detail: 'Load and resume a session', category: 'Conversation' },
|
|
140
|
+
{ id: '/session fork', label: '/session fork [name]', detail: 'Fork current session to new ID', category: 'Conversation' },
|
|
141
|
+
{ id: '/session save', label: '/session save [name]', detail: 'Force-save current session', category: 'Conversation' },
|
|
142
|
+
{ id: '/session info', label: '/session info [id]', detail: 'Show session details', category: 'Conversation' },
|
|
143
|
+
{ id: '/session export', label: '/session export <id> [format]', detail: 'Export session as markdown/text', category: 'Conversation' },
|
|
144
|
+
{ id: '/session search', label: '/session search <query>', detail: 'Search across all sessions', category: 'Conversation' },
|
|
145
|
+
{ id: '/session delete', label: '/session delete <id>', detail: 'Delete a session', category: 'Conversation' },
|
|
146
|
+
{ id: '/undo', label: '/undo', detail: 'Remove last turn', category: 'Conversation' },
|
|
147
|
+
{ id: '/redo', label: '/redo', detail: 'Restore undone turn', category: 'Conversation' },
|
|
148
|
+
{ id: '/retry', label: '/retry [text]', detail: 'Re-send last message', category: 'Conversation' },
|
|
149
|
+
{ id: '/fork', label: '/fork [name]', detail: 'Snapshot conversation as a named branch', category: 'Conversation' },
|
|
150
|
+
{ id: '/branch', label: '/branch [name]', detail: 'List branches or switch to one', category: 'Conversation' },
|
|
151
|
+
{ id: '/merge', label: '/merge <name>', detail: 'Append messages from a branch', category: 'Conversation' },
|
|
152
|
+
{ id: '/template', label: '/template', detail: 'Browse templates', category: 'Templates' },
|
|
153
|
+
{ id: '/template save', label: '/template save <name>', detail: 'Save prompt as template', category: 'Templates' },
|
|
154
|
+
{ id: '/template use', label: '/template use <name>', detail: 'Execute template', category: 'Templates' },
|
|
155
|
+
{ id: '/tools', label: '/tools', detail: 'List available tools', category: 'Tools & System' },
|
|
156
|
+
{ id: '/paste', label: '/paste', detail: 'Insert clipboard text or image into the prompt', category: 'Tools & System' },
|
|
157
|
+
{ id: '/shortcuts', label: '/shortcuts', detail: 'View keyboard shortcuts reference', category: 'Tools & System' },
|
|
158
|
+
{ id: '/commands', label: '/commands', detail: 'Browse all commands in a scrollable list', category: 'Tools & System' },
|
|
159
|
+
{ id: '/secrets', label: '/secrets set|link|get|test|list|delete', detail: 'Manage encrypted and provider-backed secrets', category: 'Tools & System' },
|
|
160
|
+
{ id: '/help', label: '/help', detail: 'This help', category: 'Tools & System' },
|
|
161
|
+
{ id: '/quit', label: '/quit', detail: 'Exit', category: 'Tools & System' },
|
|
162
|
+
{ id: '/wq', label: '/wq', detail: 'Commit all git changes and then exit', category: 'Tools & System' },
|
|
163
|
+
];
|
|
164
|
+
ctx.openSelection('Help — Commands', items, { allowSearch: true }, (result) => {
|
|
165
|
+
if (!result) return;
|
|
166
|
+
const command = result.item.id;
|
|
167
|
+
if (command.startsWith('/')) {
|
|
168
|
+
const parts = command.slice(1).trim().split(/\s+/);
|
|
169
|
+
const name = parts[0];
|
|
170
|
+
const cmdArgs = parts.slice(1);
|
|
171
|
+
void (ctx.executeCommand?.(name, cmdArgs) ?? registry.execute(name, cmdArgs, ctx));
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
ctx.print('Use /help to open the help modal. Commands: /agent, /model, /provider, /config, /template, /tools, /paste, /sessions, /bookmarks, /save, /load, /undo, /redo, /retry, /clear, /reset, /compact, /export, /title, /effort, /expand, /collapse, /debug, /quit, /wq');
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
registry.register({
|
|
181
|
+
name: 'clear',
|
|
182
|
+
aliases: ['cls'],
|
|
183
|
+
description: 'Clear the conversation display (keeps LLM context)',
|
|
184
|
+
handler(_args, ctx) {
|
|
185
|
+
ctx.session.conversationManager.clearDisplay();
|
|
186
|
+
ctx.renderRequest();
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
registry.register({
|
|
191
|
+
name: 'reset',
|
|
192
|
+
aliases: [],
|
|
193
|
+
description: 'Full reset: clear display and conversation context',
|
|
194
|
+
handler(_args, ctx) {
|
|
195
|
+
ctx.session.conversationManager.resetAll();
|
|
196
|
+
if (ctx.reloadSystemPrompt) {
|
|
197
|
+
ctx.session.runtime.systemPrompt = ctx.reloadSystemPrompt();
|
|
198
|
+
}
|
|
199
|
+
ctx.session.conversationManager.rebuildHistory();
|
|
200
|
+
ctx.renderRequest();
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
registry.register({
|
|
205
|
+
name: 'compact',
|
|
206
|
+
aliases: [],
|
|
207
|
+
description: 'Summarize conversation to free context window',
|
|
208
|
+
async handler(_args, ctx) {
|
|
209
|
+
ctx.print('Compacting conversation...');
|
|
210
|
+
await compactConversation(ctx);
|
|
211
|
+
ctx.print('Conversation compacted.');
|
|
212
|
+
ctx.renderRequest();
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
registry.register({
|
|
217
|
+
name: 'quit',
|
|
218
|
+
aliases: [':q'],
|
|
219
|
+
description: 'Exit the application',
|
|
220
|
+
handler(_args, ctx) {
|
|
221
|
+
ctx.exit();
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
registry.register({
|
|
226
|
+
name: 'wq',
|
|
227
|
+
aliases: [':wq'],
|
|
228
|
+
description: 'Commit all git changes and then exit',
|
|
229
|
+
async handler(_args, ctx) {
|
|
230
|
+
await executeWriteQuit(ctx);
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
registry.register({
|
|
235
|
+
name: 'debug',
|
|
236
|
+
aliases: [],
|
|
237
|
+
description: 'Toggle debug mode',
|
|
238
|
+
handler(_args, ctx) {
|
|
239
|
+
ctx.session.runtime.debugMode = !ctx.session.runtime.debugMode;
|
|
240
|
+
ctx.print(`Debug mode: ${ctx.session.runtime.debugMode ? 'ON' : 'OFF'}`);
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
registry.register({
|
|
245
|
+
name: 'effort',
|
|
246
|
+
aliases: ['e'],
|
|
247
|
+
description: 'Show or set reasoning effort level',
|
|
248
|
+
usage: '[level]',
|
|
249
|
+
argsHint: '<instant|low|medium|high>',
|
|
250
|
+
async handler(args, ctx) {
|
|
251
|
+
const currentModel = await requireProviderApi(ctx).getCurrentModel();
|
|
252
|
+
const validLevels = currentModel.reasoningEffort ?? [];
|
|
253
|
+
|
|
254
|
+
if (validLevels.length === 0) {
|
|
255
|
+
ctx.print(`Current model (${currentModel.displayName}) does not support configurable reasoning effort.`);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (args.length === 0) {
|
|
260
|
+
const current = (ctx.session.runtime.reasoningEffort || ctx.platform.configManager.get('provider.reasoningEffort') || 'medium') as string;
|
|
261
|
+
if (ctx.openSelection) {
|
|
262
|
+
const descriptions: Record<string, string> = {
|
|
263
|
+
...EFFORT_DESCRIPTIONS,
|
|
264
|
+
medium: 'Balanced speed and quality (default)',
|
|
265
|
+
};
|
|
266
|
+
const items: SelectionItem[] = validLevels.map((level) => ({
|
|
267
|
+
id: level,
|
|
268
|
+
label: level,
|
|
269
|
+
detail: level === current ? `◉ ${descriptions[level] ?? level}` : (descriptions[level] ?? level),
|
|
270
|
+
}));
|
|
271
|
+
ctx.openSelection('Reasoning Effort', items, { preSelectId: current, allowSearch: false }, (result) => {
|
|
272
|
+
if (!result) return;
|
|
273
|
+
const level = result.item.id as 'instant' | 'low' | 'medium' | 'high';
|
|
274
|
+
ctx.session.runtime.reasoningEffort = level;
|
|
275
|
+
ctx.platform.configManager.set('provider.reasoningEffort', level);
|
|
276
|
+
ctx.print(`Reasoning effort set to: ${level}`);
|
|
277
|
+
ctx.renderRequest();
|
|
278
|
+
});
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const budget = REASONING_BUDGET_MAP[current];
|
|
282
|
+
const lines = [
|
|
283
|
+
`Reasoning effort: ${current}`,
|
|
284
|
+
` Mercury-2: reasoning_effort = '${current}'`,
|
|
285
|
+
` Claude: thinking.budget_tokens = ${budget}`,
|
|
286
|
+
` Gemini: thinking_config.thinking_budget = ${budget}`,
|
|
287
|
+
` GPT-5: (no-op)`,
|
|
288
|
+
'',
|
|
289
|
+
`Levels: ${validLevels.join(', ')}`,
|
|
290
|
+
];
|
|
291
|
+
ctx.print(lines.join('\n'));
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const level = args[0] as 'instant' | 'low' | 'medium' | 'high';
|
|
296
|
+
if (!validLevels.includes(level)) {
|
|
297
|
+
ctx.print(`Invalid effort level: ${level}\nValid levels: ${validLevels.join(', ')}`);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
ctx.session.runtime.reasoningEffort = level;
|
|
302
|
+
ctx.platform.configManager.set('provider.reasoningEffort', level);
|
|
303
|
+
ctx.print(`Reasoning effort set to: ${level}`);
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import type { CommandRegistry } from '../command-registry.ts';
|
|
2
|
+
import { discoverSkills } from '../../panels/skills-panel.ts';
|
|
3
|
+
import {
|
|
4
|
+
installEcosystemCatalogEntry,
|
|
5
|
+
listInstalledEcosystemEntries,
|
|
6
|
+
loadEcosystemCatalog,
|
|
7
|
+
removeEcosystemCatalogEntry,
|
|
8
|
+
reviewEcosystemCatalogEntry,
|
|
9
|
+
searchEcosystemCatalog,
|
|
10
|
+
uninstallEcosystemCatalogEntry,
|
|
11
|
+
updateInstalledEcosystemEntry,
|
|
12
|
+
upsertEcosystemCatalogEntry,
|
|
13
|
+
} from '@/runtime/index.ts';
|
|
14
|
+
import { requireEcosystemCatalogPaths, requirePanelManager, requireShellPaths } from './runtime-services.ts';
|
|
15
|
+
|
|
16
|
+
export function registerSkillsRuntimeCommands(registry: CommandRegistry): void {
|
|
17
|
+
registry.register({
|
|
18
|
+
name: 'skills',
|
|
19
|
+
aliases: ['skill'],
|
|
20
|
+
description: 'Inspect installed skill packs',
|
|
21
|
+
usage: '[open|list|show <name>|origins|browse [query]|installed|catalog-review <id>|publish-local <id> <path> <summary...>|unpublish <id>|install-hint <catalog-id>|install <id> [project|user]|update <id> [project|user]|uninstall <id> [project|user]]',
|
|
22
|
+
async handler(args, ctx) {
|
|
23
|
+
const sub = args[0] ?? 'open';
|
|
24
|
+
if (sub === 'open' || sub === 'panel') {
|
|
25
|
+
if (ctx.showPanel) ctx.showPanel('skills');
|
|
26
|
+
else {
|
|
27
|
+
const panelManager = requirePanelManager(ctx);
|
|
28
|
+
panelManager.open('skills');
|
|
29
|
+
panelManager.show();
|
|
30
|
+
ctx.renderRequest();
|
|
31
|
+
}
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const skills = await discoverSkills(requireShellPaths(ctx));
|
|
35
|
+
const ecosystemPaths = requireEcosystemCatalogPaths(ctx);
|
|
36
|
+
if (sub === 'list') {
|
|
37
|
+
if (skills.length === 0) {
|
|
38
|
+
ctx.print('No skills discovered.');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
ctx.print([
|
|
42
|
+
`Skills (${skills.length})`,
|
|
43
|
+
...skills.map((skill) => ` ${skill.name} [${skill.origin}] ${skill.description || 'No description provided.'}`),
|
|
44
|
+
].join('\n'));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (sub === 'origins') {
|
|
48
|
+
const counts = new Map<string, number>();
|
|
49
|
+
for (const skill of skills) counts.set(skill.origin, (counts.get(skill.origin) ?? 0) + 1);
|
|
50
|
+
ctx.print([
|
|
51
|
+
'Skill Origins',
|
|
52
|
+
...[...counts.entries()].map(([origin, count]) => ` ${origin}: ${count}`),
|
|
53
|
+
].join('\n'));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (sub === 'show') {
|
|
57
|
+
const name = args[1];
|
|
58
|
+
if (!name) {
|
|
59
|
+
ctx.print('Usage: /skills show <name>');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const skill = skills.find((entry) => entry.name === name);
|
|
63
|
+
if (!skill) {
|
|
64
|
+
ctx.print(`Unknown skill: ${name}`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
ctx.print([
|
|
68
|
+
`Skill ${skill.name}`,
|
|
69
|
+
` origin: ${skill.origin}`,
|
|
70
|
+
` path: ${skill.path}`,
|
|
71
|
+
` description: ${skill.description || 'No description provided.'}`,
|
|
72
|
+
` dependencies: ${skill.dependencies.join(', ') || '(none)'}`,
|
|
73
|
+
` includes: ${skill.includes.join(', ') || '(none)'}`,
|
|
74
|
+
].join('\n'));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (sub === 'browse' || sub === 'catalog') {
|
|
78
|
+
const query = args.slice(1).join(' ');
|
|
79
|
+
const entries = query ? searchEcosystemCatalog('skill', query, ecosystemPaths) : loadEcosystemCatalog('skill', ecosystemPaths);
|
|
80
|
+
if (entries.length === 0) {
|
|
81
|
+
ctx.print(query
|
|
82
|
+
? `No curated skill catalog entries matched "${query}".`
|
|
83
|
+
: 'No curated skill catalog entries found. Add .goodvibes/agent/ecosystem/skills.json to publish a local-first skill catalog.');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
ctx.print([
|
|
87
|
+
`Curated Skill Catalog (${entries.length})`,
|
|
88
|
+
...entries.map((entry) => ` ${entry.id} ${entry.name} [${entry.tags.join(', ') || 'untagged'}] ${entry.summary}`),
|
|
89
|
+
].join('\n'));
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (sub === 'installed') {
|
|
93
|
+
const receipts = listInstalledEcosystemEntries('skill', ecosystemPaths);
|
|
94
|
+
if (receipts.length === 0) {
|
|
95
|
+
ctx.print('No curated skills installed from local catalogs yet.');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
ctx.print([
|
|
99
|
+
`Installed Curated Skills (${receipts.length})`,
|
|
100
|
+
...receipts.map((receipt) => ` ${receipt.entry.id} ${receipt.scope} ${receipt.targetPath}`),
|
|
101
|
+
].join('\n'));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (sub === 'catalog-review') {
|
|
105
|
+
const entryId = args[1];
|
|
106
|
+
if (!entryId) {
|
|
107
|
+
ctx.print('Usage: /skills catalog-review <catalog-id>');
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const entry = loadEcosystemCatalog('skill', ecosystemPaths).find((candidate) => candidate.id === entryId);
|
|
111
|
+
if (!entry) {
|
|
112
|
+
ctx.print(`Unknown curated skill entry: ${entryId}`);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const review = reviewEcosystemCatalogEntry(entry, ecosystemPaths);
|
|
116
|
+
ctx.print([
|
|
117
|
+
`Skill Catalog Review: ${entry.name}`,
|
|
118
|
+
` id: ${entry.id}`,
|
|
119
|
+
` source: ${entry.source}`,
|
|
120
|
+
` sourceKind: ${review.sourceKind}`,
|
|
121
|
+
` sourceExists: ${review.sourceExists ? 'yes' : 'no'}`,
|
|
122
|
+
` recommendedScope: ${review.recommendedScope}`,
|
|
123
|
+
` risk: ${review.riskLevel}`,
|
|
124
|
+
` trust notes: ${entry.trustNotes ?? '(none)'}`,
|
|
125
|
+
` provenance: ${entry.provenance ?? '(none)'}`,
|
|
126
|
+
` update hint: ${entry.updateHint ?? '(none)'}`,
|
|
127
|
+
].join('\n'));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (sub === 'publish-local') {
|
|
131
|
+
const entryId = args[1];
|
|
132
|
+
const sourcePath = args[2];
|
|
133
|
+
const summary = args.slice(3).join(' ').trim();
|
|
134
|
+
if (!entryId || !sourcePath || !summary) {
|
|
135
|
+
ctx.print('Usage: /skills publish-local <catalog-id> <path> <summary...>');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const result = upsertEcosystemCatalogEntry({
|
|
139
|
+
id: entryId,
|
|
140
|
+
kind: 'skill',
|
|
141
|
+
name: entryId.replace(/[-_]/g, ' ').replace(/\b\w/g, (char) => char.toUpperCase()),
|
|
142
|
+
summary,
|
|
143
|
+
source: sourcePath,
|
|
144
|
+
tags: ['local-first', 'published'],
|
|
145
|
+
provenance: 'operator-published',
|
|
146
|
+
updateHint: 'Use /skills publish-local again to refresh catalog metadata after edits.',
|
|
147
|
+
}, ecosystemPaths);
|
|
148
|
+
ctx.print(result.ok ? `Published curated skill ${entryId} into ${result.path}` : `Error: ${result.error}`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (sub === 'unpublish') {
|
|
152
|
+
const entryId = args[1];
|
|
153
|
+
if (!entryId) {
|
|
154
|
+
ctx.print('Usage: /skills unpublish <catalog-id>');
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const result = removeEcosystemCatalogEntry('skill', entryId, ecosystemPaths);
|
|
158
|
+
ctx.print(result.ok ? `Removed curated skill ${entryId} from ${result.path}` : `Error: ${result.error}`);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (sub === 'install-hint') {
|
|
162
|
+
const entryId = args[1];
|
|
163
|
+
if (!entryId) {
|
|
164
|
+
ctx.print('Usage: /skills install-hint <catalog-id>');
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const entry = loadEcosystemCatalog('skill', ecosystemPaths).find((candidate) => candidate.id === entryId);
|
|
168
|
+
if (!entry) {
|
|
169
|
+
ctx.print(`Unknown curated skill entry: ${entryId}`);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
ctx.print([
|
|
173
|
+
`Skill Install Guidance: ${entry.name}`,
|
|
174
|
+
` id: ${entry.id}`,
|
|
175
|
+
` source: ${entry.source}`,
|
|
176
|
+
` tags: ${entry.tags.join(', ') || '(none)'}`,
|
|
177
|
+
` trust notes: ${entry.trustNotes ?? '(none)'}`,
|
|
178
|
+
` install hint: ${entry.installHint ?? 'Place the skill pack under a configured skill directory and refresh the skills panel.'}`,
|
|
179
|
+
].join('\n'));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (sub === 'install') {
|
|
183
|
+
const entryId = args[1];
|
|
184
|
+
const scopeArg = args[2];
|
|
185
|
+
if (!entryId) {
|
|
186
|
+
ctx.print('Usage: /skills install <catalog-id> [project|user]');
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const scope = scopeArg === 'project' ? 'project' : 'user';
|
|
190
|
+
const result = installEcosystemCatalogEntry('skill', entryId, { ...ecosystemPaths, scope });
|
|
191
|
+
ctx.print(result.ok ? `Installed curated skill ${entryId} into ${result.receipt.targetPath}` : `Error: ${result.error}`);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (sub === 'update') {
|
|
195
|
+
const entryId = args[1];
|
|
196
|
+
const scopeArg = args[2];
|
|
197
|
+
if (!entryId) {
|
|
198
|
+
ctx.print('Usage: /skills update <catalog-id> [project|user]');
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const scope = scopeArg === 'project' ? 'project' : 'user';
|
|
202
|
+
const result = updateInstalledEcosystemEntry('skill', entryId, { ...ecosystemPaths, scope });
|
|
203
|
+
ctx.print(result.ok ? `Updated curated skill ${entryId} in ${result.receipt.targetPath}` : `Error: ${result.error}`);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (sub === 'uninstall') {
|
|
207
|
+
const entryId = args[1];
|
|
208
|
+
const scopeArg = args[2];
|
|
209
|
+
if (!entryId) {
|
|
210
|
+
ctx.print('Usage: /skills uninstall <catalog-id> [project|user]');
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const scope = scopeArg === 'project' ? 'project' : 'user';
|
|
214
|
+
const result = uninstallEcosystemCatalogEntry('skill', entryId, { ...ecosystemPaths, scope });
|
|
215
|
+
ctx.print(result.ok ? `Uninstalled curated skill ${entryId} from ${result.removedPath}` : `Error: ${result.error}`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
ctx.print('Usage: /skills [open|list|show <name>|origins|browse [query]|installed|catalog-review <id>|publish-local <id> <path> <summary...>|unpublish <id>|install-hint <catalog-id>|install <id> [project|user]|update <id> [project|user]|uninstall <id> [project|user]]');
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
}
|