@pellux/goodvibes-tui 0.18.4
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 +89 -0
- package/.goodvibes/skills/add-provider/SKILL.md +199 -0
- package/CHANGELOG.md +1681 -0
- package/README.md +1607 -0
- package/bin/goodvibes +66 -0
- package/docs/README.md +32 -0
- package/docs/foundation-artifacts/README.md +16 -0
- package/docs/foundation-artifacts/knowledge-graphql.graphql +397 -0
- package/docs/foundation-artifacts/knowledge-store.sql +183 -0
- package/docs/foundation-artifacts/operator-contract.json +55157 -0
- package/docs/foundation-artifacts/peer-contract.json +2384 -0
- package/package.json +114 -0
- package/scripts/postinstall.mjs +203 -0
- package/src/acp/connection.ts +447 -0
- package/src/acp/index.ts +7 -0
- package/src/acp/manager.ts +133 -0
- package/src/adapters/bluebubbles/index.ts +127 -0
- package/src/adapters/discord/index.ts +297 -0
- package/src/adapters/github/index.ts +73 -0
- package/src/adapters/google-chat/index.ts +119 -0
- package/src/adapters/imessage/index.ts +92 -0
- package/src/adapters/index.ts +15 -0
- package/src/adapters/matrix/index.ts +116 -0
- package/src/adapters/mattermost/index.ts +151 -0
- package/src/adapters/msteams/index.ts +180 -0
- package/src/adapters/ntfy/index.ts +118 -0
- package/src/adapters/signal/index.ts +92 -0
- package/src/adapters/slack/index.ts +323 -0
- package/src/adapters/telegram/index.ts +160 -0
- package/src/adapters/types.ts +97 -0
- package/src/adapters/webhook/index.ts +178 -0
- package/src/adapters/whatsapp/index.ts +135 -0
- package/src/agents/message-bus-core.ts +312 -0
- package/src/agents/message-bus.ts +2 -0
- package/src/agents/orchestrator-prompts.ts +351 -0
- package/src/agents/orchestrator-runner.ts +668 -0
- package/src/agents/orchestrator.ts +437 -0
- package/src/agents/session.ts +108 -0
- package/src/agents/worktree.ts +153 -0
- package/src/agents/wrfc-config.ts +47 -0
- package/src/agents/wrfc-controller.ts +747 -0
- package/src/agents/wrfc-gate-runtime.ts +75 -0
- package/src/agents/wrfc-reporting.ts +284 -0
- package/src/agents/wrfc-runtime-events.ts +150 -0
- package/src/agents/wrfc-types.ts +67 -0
- package/src/automation/delivery-manager.ts +368 -0
- package/src/automation/index.ts +72 -0
- package/src/automation/manager-runtime-delivery.ts +139 -0
- package/src/automation/manager-runtime-events.ts +131 -0
- package/src/automation/manager-runtime-execution.ts +511 -0
- package/src/automation/manager-runtime-helpers.ts +433 -0
- package/src/automation/manager-runtime-job-mutations.ts +175 -0
- package/src/automation/manager-runtime-reconcile.ts +148 -0
- package/src/automation/manager-runtime-scheduling.ts +189 -0
- package/src/automation/manager-runtime-sync.ts +54 -0
- package/src/automation/manager-runtime.ts +721 -0
- package/src/automation/manager.ts +10 -0
- package/src/automation/service.ts +242 -0
- package/src/channels/builtin/account-actions.ts +490 -0
- package/src/channels/builtin/accounts.ts +433 -0
- package/src/channels/builtin/contracts.ts +405 -0
- package/src/channels/builtin/plugins.ts +308 -0
- package/src/channels/builtin/rendering.ts +174 -0
- package/src/channels/builtin/setup-schema.ts +504 -0
- package/src/channels/builtin/shared.ts +96 -0
- package/src/channels/builtin/surfaces.ts +57 -0
- package/src/channels/builtin/targets.ts +693 -0
- package/src/channels/builtin-runtime.ts +443 -0
- package/src/channels/delivery/shared.ts +199 -0
- package/src/channels/delivery/strategies-bridge.ts +246 -0
- package/src/channels/delivery/strategies-core.ts +299 -0
- package/src/channels/delivery/strategies-enterprise.ts +178 -0
- package/src/channels/delivery/types.ts +59 -0
- package/src/channels/delivery-router.ts +127 -0
- package/src/channels/index.ts +77 -0
- package/src/channels/plugin-registry.ts +551 -0
- package/src/channels/provider-runtime.ts +330 -0
- package/src/channels/reply-pipeline.ts +522 -0
- package/src/channels/route-manager.ts +340 -0
- package/src/channels/surface-registry.ts +186 -0
- package/src/config/helper-model.ts +233 -0
- package/src/config/index.ts +193 -0
- package/src/config/manager.ts +404 -0
- package/src/config/secrets.ts +547 -0
- package/src/config/service-registry.ts +329 -0
- package/src/config/subscription-auth.ts +31 -0
- package/src/config/subscription-providers.ts +127 -0
- package/src/config/tool-llm.ts +110 -0
- package/src/control-plane/approval-broker.ts +351 -0
- package/src/control-plane/gateway.ts +713 -0
- package/src/control-plane/index.ts +54 -0
- package/src/control-plane/media-contract-schemas.ts +208 -0
- package/src/control-plane/method-catalog-admin.ts +136 -0
- package/src/control-plane/method-catalog-channels.ts +591 -0
- package/src/control-plane/method-catalog-control-automation.ts +475 -0
- package/src/control-plane/method-catalog-control-core.ts +594 -0
- package/src/control-plane/method-catalog-control.ts +8 -0
- package/src/control-plane/method-catalog-events.ts +74 -0
- package/src/control-plane/method-catalog-knowledge.ts +531 -0
- package/src/control-plane/method-catalog-media.ts +279 -0
- package/src/control-plane/method-catalog-runtime.ts +304 -0
- package/src/control-plane/method-catalog-shared.ts +223 -0
- package/src/control-plane/method-catalog.ts +242 -0
- package/src/control-plane/operator-contract-schemas-admin.ts +639 -0
- package/src/control-plane/operator-contract-schemas-channels.ts +375 -0
- package/src/control-plane/operator-contract-schemas-control.ts +226 -0
- package/src/control-plane/operator-contract-schemas-domains.ts +4 -0
- package/src/control-plane/operator-contract-schemas-knowledge.ts +582 -0
- package/src/control-plane/operator-contract-schemas-media.ts +297 -0
- package/src/control-plane/operator-contract-schemas-permissions.ts +100 -0
- package/src/control-plane/operator-contract-schemas-remote.ts +38 -0
- package/src/control-plane/operator-contract-schemas-runtime.ts +563 -0
- package/src/control-plane/operator-contract-schemas-shared.ts +85 -0
- package/src/control-plane/operator-contract-schemas-telemetry.ts +349 -0
- package/src/control-plane/operator-contract-schemas.ts +6 -0
- package/src/control-plane/operator-contract.ts +163 -0
- package/src/control-plane/session-broker.ts +780 -0
- package/src/core/compaction-sections.ts +492 -0
- package/src/core/compaction-types.ts +147 -0
- package/src/core/composer-state.ts +59 -0
- package/src/core/context-compaction.ts +542 -0
- package/src/core/conversation-compaction.ts +68 -0
- package/src/core/conversation-diff.ts +55 -0
- package/src/core/conversation-rendering.ts +343 -0
- package/src/core/conversation-utils.ts +72 -0
- package/src/core/conversation.ts +775 -0
- package/src/core/event-replay.ts +287 -0
- package/src/core/orchestrator-context-runtime.ts +407 -0
- package/src/core/orchestrator-follow-up-runtime.ts +134 -0
- package/src/core/orchestrator-runtime.ts +132 -0
- package/src/core/orchestrator-tool-runtime.ts +468 -0
- package/src/core/orchestrator-turn-helpers.ts +355 -0
- package/src/core/orchestrator-turn-loop.ts +443 -0
- package/src/core/orchestrator.ts +733 -0
- package/src/core/plan-command-handler.ts +169 -0
- package/src/core/system-message-router.ts +210 -0
- package/src/core/transcript-events/classify.ts +95 -0
- package/src/core/transcript-events/index.ts +15 -0
- package/src/daemon/cli.ts +88 -0
- package/src/daemon/control-plane.ts +522 -0
- package/src/daemon/facade-composition.ts +397 -0
- package/src/daemon/facade.ts +638 -0
- package/src/daemon/helpers.ts +74 -0
- package/src/daemon/http/router-route-contexts.ts +370 -0
- package/src/daemon/http/router.ts +531 -0
- package/src/daemon/http-listener.ts +301 -0
- package/src/daemon/index.ts +3 -0
- package/src/daemon/server.ts +1 -0
- package/src/daemon/service-manager.ts +413 -0
- package/src/daemon/surface-actions.ts +183 -0
- package/src/daemon/surface-delivery.ts +530 -0
- package/src/daemon/surface-policy.ts +60 -0
- package/src/daemon/transport-events.ts +110 -0
- package/src/daemon/types.ts +191 -0
- package/src/export/markdown.ts +213 -0
- package/src/export/session-export.ts +633 -0
- package/src/git/index.ts +1 -0
- package/src/git/service.ts +414 -0
- package/src/hooks/chain-engine.ts +414 -0
- package/src/hooks/dispatcher.ts +414 -0
- package/src/hooks/hook-api.ts +170 -0
- package/src/hooks/index.ts +48 -0
- package/src/hooks/runners/agent.ts +93 -0
- package/src/hooks/runners/prompt.ts +69 -0
- package/src/hooks/workbench.ts +360 -0
- package/src/input/autocomplete.ts +96 -0
- package/src/input/bookmark-modal.ts +115 -0
- package/src/input/command-registry.ts +300 -0
- package/src/input/commands/branch-runtime.ts +72 -0
- package/src/input/commands/config.ts +515 -0
- package/src/input/commands/control-room-runtime.ts +255 -0
- package/src/input/commands/conversation-runtime.ts +207 -0
- package/src/input/commands/diff-runtime.ts +161 -0
- package/src/input/commands/discovery-runtime.ts +45 -0
- package/src/input/commands/eval.ts +204 -0
- package/src/input/commands/experience-runtime.ts +278 -0
- package/src/input/commands/git-runtime.ts +81 -0
- package/src/input/commands/guidance-runtime.ts +101 -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 +368 -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 +458 -0
- package/src/input/commands/local-setup-review.ts +192 -0
- package/src/input/commands/local-setup-transfer.ts +134 -0
- package/src/input/commands/local-setup.ts +292 -0
- package/src/input/commands/managed-runtime.ts +208 -0
- package/src/input/commands/marketplace-runtime.ts +290 -0
- package/src/input/commands/mcp-runtime.ts +202 -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/operator-panel-runtime.ts +141 -0
- package/src/input/commands/operator-runtime.ts +392 -0
- package/src/input/commands/permissions-runtime.ts +104 -0
- package/src/input/commands/planning-runtime.ts +97 -0
- package/src/input/commands/platform-access-runtime.ts +422 -0
- package/src/input/commands/platform-runtime.ts +6 -0
- package/src/input/commands/platform-sandbox-qemu.ts +137 -0
- package/src/input/commands/platform-sandbox-runtime.ts +406 -0
- package/src/input/commands/platform-sandbox-session.ts +128 -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/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 +531 -0
- package/src/input/commands/replay-runtime.ts +18 -0
- package/src/input/commands/runtime-services.ts +279 -0
- package/src/input/commands/schedule-runtime.ts +332 -0
- package/src/input/commands/services-runtime.ts +207 -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 +376 -0
- package/src/input/commands/settings-sync-runtime.ts +173 -0
- package/src/input/commands/share-runtime.ts +114 -0
- package/src/input/commands/shell-core.ts +320 -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 +374 -0
- package/src/input/commands/teleport-runtime.ts +57 -0
- package/src/input/commands/worktree-runtime.ts +137 -0
- package/src/input/commands.ts +127 -0
- package/src/input/file-picker.ts +192 -0
- package/src/input/handler-command-route.ts +106 -0
- package/src/input/handler-content-actions.ts +465 -0
- package/src/input/handler-feed-routes.ts +541 -0
- package/src/input/handler-feed.ts +361 -0
- package/src/input/handler-modal-routes.ts +335 -0
- package/src/input/handler-modal-stack.ts +237 -0
- package/src/input/handler-modal-token-routes.ts +272 -0
- package/src/input/handler-picker-routes.ts +416 -0
- package/src/input/handler-prompt-buffer.ts +320 -0
- package/src/input/handler-shortcuts.ts +195 -0
- package/src/input/handler-ui-state.ts +294 -0
- package/src/input/handler.ts +798 -0
- package/src/input/input-history.ts +267 -0
- package/src/input/keybindings.ts +256 -0
- package/src/input/model-picker.ts +730 -0
- package/src/input/panel-integration-actions.ts +77 -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.ts +718 -0
- package/src/input/submission-intent.ts +18 -0
- package/src/input/submission-router.ts +64 -0
- package/src/integrations/index.ts +42 -0
- package/src/integrations/notifier.ts +206 -0
- package/src/integrations/webhooks.ts +177 -0
- package/src/knowledge/consolidation.ts +346 -0
- package/src/knowledge/graphql.ts +324 -0
- package/src/knowledge/index.ts +60 -0
- package/src/knowledge/ingest-compile.ts +386 -0
- package/src/knowledge/ingest-context.ts +18 -0
- package/src/knowledge/ingest-inputs.ts +387 -0
- package/src/knowledge/ingest.ts +20 -0
- package/src/knowledge/internal.ts +257 -0
- package/src/knowledge/knowledge-api.ts +432 -0
- package/src/knowledge/lint.ts +121 -0
- package/src/knowledge/memory-sync.ts +62 -0
- package/src/knowledge/packet.ts +370 -0
- package/src/knowledge/scheduling.ts +283 -0
- package/src/knowledge/service.ts +715 -0
- package/src/main.ts +798 -0
- package/src/mcp/client.ts +383 -0
- package/src/mcp/index.ts +12 -0
- package/src/mcp/mcp-api.ts +90 -0
- package/src/mcp/registry.ts +508 -0
- package/src/media/builtin-image-understanding.ts +303 -0
- package/src/media/builtin-providers.ts +26 -0
- package/src/media/index.ts +18 -0
- package/src/multimodal/index.ts +13 -0
- package/src/multimodal/service.ts +492 -0
- package/src/panels/agent-inspector-panel.ts +515 -0
- package/src/panels/agent-inspector-shared.ts +94 -0
- package/src/panels/agent-logs-panel.ts +539 -0
- package/src/panels/agent-logs-shared.ts +129 -0
- package/src/panels/approval-panel.ts +169 -0
- package/src/panels/automation-control-panel.ts +253 -0
- package/src/panels/base-panel.ts +72 -0
- package/src/panels/builtin/agent.ts +88 -0
- package/src/panels/builtin/development.ts +111 -0
- package/src/panels/builtin/knowledge.ts +26 -0
- package/src/panels/builtin/operations.ts +385 -0
- package/src/panels/builtin/session.ts +61 -0
- package/src/panels/builtin/shared.ts +240 -0
- package/src/panels/builtin-panels.ts +23 -0
- package/src/panels/cockpit-panel.ts +183 -0
- package/src/panels/communication-panel.ts +191 -0
- package/src/panels/context-visualizer-panel.ts +199 -0
- package/src/panels/control-plane-panel.ts +266 -0
- package/src/panels/cost-tracker-panel.ts +444 -0
- package/src/panels/debug-panel.ts +432 -0
- package/src/panels/diff-panel.ts +518 -0
- package/src/panels/docs-panel.ts +283 -0
- package/src/panels/eval-panel.ts +399 -0
- package/src/panels/file-explorer-panel.ts +556 -0
- package/src/panels/file-preview-panel.ts +412 -0
- package/src/panels/forensics-panel.ts +364 -0
- package/src/panels/git-panel.ts +630 -0
- package/src/panels/hooks-panel.ts +274 -0
- package/src/panels/incident-review-panel.ts +247 -0
- package/src/panels/index.ts +48 -0
- package/src/panels/intelligence-panel.ts +176 -0
- package/src/panels/knowledge-panel.ts +328 -0
- package/src/panels/local-auth-panel.ts +146 -0
- package/src/panels/marketplace-panel.ts +223 -0
- package/src/panels/mcp-panel.ts +260 -0
- package/src/panels/memory-panel.ts +293 -0
- package/src/panels/ops-control-panel.ts +184 -0
- package/src/panels/ops-strategy-panel.ts +235 -0
- package/src/panels/orchestration-panel.ts +254 -0
- package/src/panels/panel-list-panel.ts +508 -0
- package/src/panels/panel-manager.ts +538 -0
- package/src/panels/panel-picker.ts +106 -0
- package/src/panels/plan-dashboard-panel.ts +272 -0
- package/src/panels/plugins-panel.ts +201 -0
- package/src/panels/policy-panel.ts +308 -0
- package/src/panels/polish.ts +668 -0
- package/src/panels/provider-account-snapshot.ts +259 -0
- package/src/panels/provider-accounts-panel.ts +221 -0
- package/src/panels/provider-health-domains.ts +211 -0
- package/src/panels/provider-health-panel.ts +725 -0
- package/src/panels/provider-health-tracker.ts +115 -0
- package/src/panels/provider-stats-panel.ts +366 -0
- package/src/panels/remote-panel.ts +449 -0
- package/src/panels/routes-panel.ts +228 -0
- package/src/panels/sandbox-panel.ts +289 -0
- package/src/panels/schedule-panel.ts +344 -0
- package/src/panels/search-focus.ts +32 -0
- package/src/panels/security-panel.ts +329 -0
- package/src/panels/services-panel.ts +271 -0
- package/src/panels/session-browser-panel.ts +399 -0
- package/src/panels/session-maintenance.ts +125 -0
- package/src/panels/settings-sync-panel.ts +164 -0
- package/src/panels/skills-panel.ts +475 -0
- package/src/panels/subscription-panel.ts +273 -0
- package/src/panels/symbol-outline-panel.ts +486 -0
- package/src/panels/system-messages-panel.ts +224 -0
- package/src/panels/tasks-panel.ts +448 -0
- package/src/panels/thinking-panel.ts +304 -0
- package/src/panels/token-budget-panel.ts +469 -0
- package/src/panels/tool-inspector-panel.ts +434 -0
- package/src/panels/types.ts +44 -0
- package/src/panels/watchers-panel.ts +241 -0
- package/src/panels/welcome-panel.ts +64 -0
- package/src/panels/worktree-panel.ts +180 -0
- package/src/panels/wrfc-panel.ts +480 -0
- package/src/permissions/briefs/build.ts +88 -0
- package/src/permissions/manager.ts +356 -0
- package/src/permissions/prompt.ts +184 -0
- package/src/plugins/api.ts +383 -0
- package/src/plugins/loader.ts +304 -0
- package/src/plugins/manager.ts +481 -0
- package/src/profiles/shape.ts +58 -0
- package/src/providers/amazon-bedrock-mantle.ts +50 -0
- package/src/providers/amazon-bedrock.ts +61 -0
- package/src/providers/anthropic-compat.ts +373 -0
- package/src/providers/anthropic-sdk-provider.ts +230 -0
- package/src/providers/anthropic-vertex.ts +59 -0
- package/src/providers/anthropic.ts +469 -0
- package/src/providers/auto-register.ts +417 -0
- package/src/providers/builtin-catalog.ts +326 -0
- package/src/providers/builtin-registry.ts +575 -0
- package/src/providers/cache-planner.ts +258 -0
- package/src/providers/capabilities.ts +601 -0
- package/src/providers/custom-loader.ts +425 -0
- package/src/providers/discovered-compat.ts +18 -0
- package/src/providers/discovered-factory.ts +61 -0
- package/src/providers/discovered-traits.ts +138 -0
- package/src/providers/gemini.ts +462 -0
- package/src/providers/github-copilot.ts +254 -0
- package/src/providers/index.ts +47 -0
- package/src/providers/interface.ts +185 -0
- package/src/providers/llama-cpp.ts +402 -0
- package/src/providers/lm-studio-helpers.ts +367 -0
- package/src/providers/lm-studio.ts +484 -0
- package/src/providers/model-catalog-cache.ts +221 -0
- package/src/providers/model-catalog-notifications.ts +97 -0
- package/src/providers/model-catalog-synthetic.ts +202 -0
- package/src/providers/model-catalog.ts +211 -0
- package/src/providers/model-limits.ts +280 -0
- package/src/providers/ollama.ts +469 -0
- package/src/providers/openai-codex.ts +472 -0
- package/src/providers/openai-compat.ts +615 -0
- package/src/providers/openai.ts +231 -0
- package/src/providers/optimizer.ts +381 -0
- package/src/providers/provider-api.ts +553 -0
- package/src/providers/registry-helpers.ts +34 -0
- package/src/providers/registry-models.ts +77 -0
- package/src/providers/registry-types.ts +67 -0
- package/src/providers/registry.ts +729 -0
- package/src/providers/runtime-metadata.ts +149 -0
- package/src/providers/runtime-snapshot.ts +130 -0
- package/src/providers/synthetic.ts +561 -0
- package/src/providers/tier-prompts.ts +84 -0
- package/src/providers/tool-formats.ts +414 -0
- package/src/renderer/agent-detail-modal.ts +285 -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 +34 -0
- package/src/renderer/code-block.ts +373 -0
- package/src/renderer/compositor.ts +261 -0
- package/src/renderer/context-inspector.ts +219 -0
- package/src/renderer/conversation-layout.ts +67 -0
- package/src/renderer/conversation-overlays.ts +123 -0
- package/src/renderer/conversation-surface.ts +260 -0
- package/src/renderer/diff-view.ts +132 -0
- package/src/renderer/diff.ts +122 -0
- package/src/renderer/file-picker-overlay.ts +101 -0
- package/src/renderer/file-tree.ts +153 -0
- package/src/renderer/git-status.ts +89 -0
- package/src/renderer/help-overlay.ts +247 -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 +777 -0
- package/src/renderer/modal-factory.ts +467 -0
- package/src/renderer/modal-utils.ts +24 -0
- package/src/renderer/model-picker-overlay.ts +396 -0
- package/src/renderer/overlay-box.ts +165 -0
- package/src/renderer/overlay-viewport.ts +104 -0
- package/src/renderer/panel-composite.ts +80 -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 +38 -0
- package/src/renderer/process-indicator.ts +96 -0
- package/src/renderer/process-modal.ts +295 -0
- package/src/renderer/profile-picker-modal.ts +129 -0
- package/src/renderer/progress.ts +98 -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.ts +701 -0
- package/src/renderer/shell-surface.ts +88 -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 +233 -0
- package/src/renderer/ui-factory.ts +524 -0
- package/src/renderer/ui-primitives.ts +96 -0
- package/src/runtime/auth/inspection.ts +125 -0
- package/src/runtime/bootstrap-background.ts +147 -0
- package/src/runtime/bootstrap-command-context.ts +265 -0
- package/src/runtime/bootstrap-command-parts.ts +357 -0
- package/src/runtime/bootstrap-core.ts +375 -0
- package/src/runtime/bootstrap-helpers.ts +88 -0
- package/src/runtime/bootstrap-hook-bridge.ts +271 -0
- package/src/runtime/bootstrap-runtime-events.ts +254 -0
- package/src/runtime/bootstrap-services.ts +197 -0
- package/src/runtime/bootstrap-shell.ts +262 -0
- package/src/runtime/bootstrap.ts +488 -0
- package/src/runtime/compaction/index.ts +90 -0
- package/src/runtime/compaction/lifecycle.ts +167 -0
- package/src/runtime/compaction/manager.ts +474 -0
- package/src/runtime/compaction/quality-score.ts +279 -0
- package/src/runtime/compaction/resume-repair.ts +183 -0
- package/src/runtime/compaction/strategies/autocompact.ts +65 -0
- package/src/runtime/compaction/strategies/boundary-commit.ts +106 -0
- package/src/runtime/compaction/strategies/collapse.ts +90 -0
- package/src/runtime/compaction/strategies/index.ts +23 -0
- package/src/runtime/compaction/strategies/microcompact.ts +74 -0
- package/src/runtime/compaction/strategies/reactive.ts +89 -0
- package/src/runtime/compaction/types.ts +221 -0
- package/src/runtime/context.ts +158 -0
- package/src/runtime/diagnostics/actions.ts +776 -0
- package/src/runtime/diagnostics/index.ts +99 -0
- package/src/runtime/diagnostics/panels/agents.ts +252 -0
- package/src/runtime/diagnostics/panels/events.ts +188 -0
- package/src/runtime/diagnostics/panels/health.ts +242 -0
- package/src/runtime/diagnostics/panels/index.ts +24 -0
- package/src/runtime/diagnostics/panels/ops.ts +156 -0
- package/src/runtime/diagnostics/panels/policy.ts +176 -0
- package/src/runtime/diagnostics/panels/tasks.ts +251 -0
- package/src/runtime/diagnostics/panels/tool-calls.ts +267 -0
- package/src/runtime/diagnostics/provider.ts +262 -0
- package/src/runtime/ecosystem/catalog.ts +606 -0
- package/src/runtime/ecosystem/recommendations.ts +117 -0
- package/src/runtime/emitters/agents.ts +96 -0
- package/src/runtime/emitters/automation.ts +112 -0
- package/src/runtime/emitters/communication.ts +53 -0
- package/src/runtime/emitters/compaction.ts +161 -0
- package/src/runtime/emitters/control-plane.ts +65 -0
- package/src/runtime/emitters/deliveries.ts +65 -0
- package/src/runtime/emitters/forensics.ts +17 -0
- package/src/runtime/emitters/index.ts +59 -0
- package/src/runtime/emitters/knowledge.ts +129 -0
- package/src/runtime/emitters/mcp.ts +95 -0
- package/src/runtime/emitters/ops.ts +163 -0
- package/src/runtime/emitters/orchestration.ts +87 -0
- package/src/runtime/emitters/permissions.ts +98 -0
- package/src/runtime/emitters/planner.ts +23 -0
- package/src/runtime/emitters/plugins.ts +78 -0
- package/src/runtime/emitters/providers.ts +30 -0
- package/src/runtime/emitters/routes.ts +57 -0
- package/src/runtime/emitters/security.ts +53 -0
- package/src/runtime/emitters/session.ts +93 -0
- package/src/runtime/emitters/surfaces.ts +57 -0
- package/src/runtime/emitters/tasks.ts +69 -0
- package/src/runtime/emitters/tools.ts +140 -0
- package/src/runtime/emitters/transport.ts +78 -0
- package/src/runtime/emitters/turn.ts +155 -0
- package/src/runtime/emitters/ui.ts +57 -0
- package/src/runtime/emitters/watchers.ts +57 -0
- package/src/runtime/emitters/workflows.ts +79 -0
- package/src/runtime/eval/index.ts +48 -0
- package/src/runtime/eval/runner.ts +163 -0
- package/src/runtime/eval/suites.ts +264 -0
- package/src/runtime/events/domain-map.ts +148 -0
- package/src/runtime/events/index.ts +194 -0
- package/src/runtime/events/turn.ts +60 -0
- package/src/runtime/events/workflows.ts +17 -0
- package/src/runtime/forensics/collector.ts +693 -0
- package/src/runtime/forensics/index.ts +23 -0
- package/src/runtime/foundation-clients.ts +78 -0
- package/src/runtime/foundation-services.ts +96 -0
- package/src/runtime/guidance.ts +183 -0
- package/src/runtime/health/effect-handlers.ts +189 -0
- package/src/runtime/health/index.ts +70 -0
- package/src/runtime/health/wiring.ts +115 -0
- package/src/runtime/index.ts +174 -0
- package/src/runtime/integration/helpers.ts +640 -0
- package/src/runtime/lifecycle.ts +107 -0
- package/src/runtime/mcp/index.ts +68 -0
- package/src/runtime/mcp/manager.ts +513 -0
- package/src/runtime/network/inbound.ts +131 -0
- package/src/runtime/network/index.ts +30 -0
- package/src/runtime/network/outbound.ts +292 -0
- package/src/runtime/network/shared.ts +82 -0
- package/src/runtime/operator-client.ts +235 -0
- package/src/runtime/ops/control-plane.ts +363 -0
- package/src/runtime/ops/index.ts +122 -0
- package/src/runtime/ops/playbooks/index.ts +10 -0
- package/src/runtime/ops/playbooks/session-unrecoverable.ts +196 -0
- package/src/runtime/ops/playbooks/stuck-turn.ts +197 -0
- package/src/runtime/ops/runtime-context.ts +100 -0
- package/src/runtime/ops-api.ts +27 -0
- package/src/runtime/orchestration/spawn-policy.ts +83 -0
- package/src/runtime/peer-client.ts +404 -0
- package/src/runtime/perf/index.ts +57 -0
- package/src/runtime/perf/slo-collector.ts +375 -0
- package/src/runtime/permissions/index.ts +190 -0
- package/src/runtime/permissions/policy-runtime.ts +175 -0
- package/src/runtime/permissions/preflight.ts +101 -0
- package/src/runtime/permissions/rule-suggestions.ts +36 -0
- package/src/runtime/plugins/hot-reload.ts +221 -0
- package/src/runtime/plugins/index.ts +84 -0
- package/src/runtime/plugins/lifecycle.ts +95 -0
- package/src/runtime/plugins/manager.ts +474 -0
- package/src/runtime/plugins/manifest.ts +167 -0
- package/src/runtime/plugins/quarantine.ts +202 -0
- package/src/runtime/plugins/trust.ts +291 -0
- package/src/runtime/plugins/types.ts +205 -0
- package/src/runtime/provider-accounts/registry.ts +326 -0
- package/src/runtime/remote/distributed-runtime-contract-schemas.ts +386 -0
- package/src/runtime/remote/index.ts +488 -0
- package/src/runtime/remote/runner-registry.ts +438 -0
- package/src/runtime/remote/supervisor.ts +70 -0
- package/src/runtime/runtime-hook-api.ts +5 -0
- package/src/runtime/runtime-knowledge-api.ts +14 -0
- package/src/runtime/runtime-mcp-api.ts +5 -0
- package/src/runtime/runtime-ops-api.ts +86 -0
- package/src/runtime/runtime-provider-api.ts +18 -0
- package/src/runtime/sandbox/backend.ts +291 -0
- package/src/runtime/sandbox/manager.ts +364 -0
- package/src/runtime/sandbox/provisioning.ts +422 -0
- package/src/runtime/sandbox/session-registry.ts +289 -0
- package/src/runtime/services.ts +541 -0
- package/src/runtime/session-maintenance.ts +188 -0
- package/src/runtime/session-persistence.ts +288 -0
- package/src/runtime/session-return-context.ts +195 -0
- package/src/runtime/settings/control-plane-store.ts +258 -0
- package/src/runtime/settings/control-plane.ts +599 -0
- package/src/runtime/shell-command-extensions.ts +54 -0
- package/src/runtime/shell-command-ops.ts +207 -0
- package/src/runtime/shell-command-platform.ts +47 -0
- package/src/runtime/shell-command-services.ts +143 -0
- package/src/runtime/shell-command-workspace.ts +31 -0
- package/src/runtime/store/domains/conversation.ts +181 -0
- package/src/runtime/store/domains/domain-read-matrix.ts +17 -0
- package/src/runtime/store/domains/index.ts +222 -0
- package/src/runtime/store/domains/panels.ts +117 -0
- package/src/runtime/store/domains/permissions.ts +143 -0
- package/src/runtime/store/domains/ui-perf.ts +103 -0
- package/src/runtime/store/helpers/reducers/conversation.ts +228 -0
- package/src/runtime/store/helpers/reducers/lifecycle.ts +440 -0
- package/src/runtime/store/helpers/reducers/shared.ts +60 -0
- package/src/runtime/store/helpers/reducers/sync.ts +555 -0
- package/src/runtime/store/helpers/reducers.ts +30 -0
- package/src/runtime/store/index.ts +304 -0
- package/src/runtime/store/selectors/index.ts +354 -0
- package/src/runtime/store/state.ts +137 -0
- package/src/runtime/tasks/adapters/acp-adapter.ts +211 -0
- package/src/runtime/tasks/adapters/agent-adapter.ts +208 -0
- package/src/runtime/tasks/adapters/index.ts +16 -0
- package/src/runtime/tasks/adapters/process-adapter.ts +214 -0
- package/src/runtime/tasks/adapters/scheduler-adapter.ts +193 -0
- package/src/runtime/tasks/index.ts +68 -0
- package/src/runtime/tasks/manager.ts +415 -0
- package/src/runtime/telemetry/api-helpers.ts +517 -0
- package/src/runtime/telemetry/api.ts +768 -0
- package/src/runtime/telemetry/index.ts +178 -0
- package/src/runtime/telemetry/instrumentation/domain-bridge-agent-session.ts +440 -0
- package/src/runtime/telemetry/instrumentation/domain-bridge-plugin-mcp.ts +200 -0
- package/src/runtime/telemetry/instrumentation/domain-bridge-shared.ts +18 -0
- package/src/runtime/telemetry/instrumentation/domain-bridge-transport-task.ts +204 -0
- package/src/runtime/telemetry/instrumentation/domain-bridge.ts +125 -0
- package/src/runtime/telemetry/instrumentation/index.ts +67 -0
- package/src/runtime/tools/context.ts +114 -0
- package/src/runtime/tools/index.ts +46 -0
- package/src/runtime/tools/phased-executor.ts +448 -0
- package/src/runtime/tools/phases/budget.ts +130 -0
- package/src/runtime/tools/phases/execute.ts +69 -0
- package/src/runtime/tools/phases/index.ts +13 -0
- package/src/runtime/tools/phases/map-output.ts +98 -0
- package/src/runtime/tools/phases/permission.ts +133 -0
- package/src/runtime/tools/phases/posthook.ts +57 -0
- package/src/runtime/tools/phases/prehook.ts +68 -0
- package/src/runtime/tools/phases/validate.ts +53 -0
- package/src/runtime/transports/direct.ts +73 -0
- package/src/runtime/transports/http-helpers.ts +218 -0
- package/src/runtime/transports/http-types.ts +364 -0
- package/src/runtime/transports/http.ts +629 -0
- package/src/runtime/transports/realtime.ts +50 -0
- package/src/runtime/transports/remote-events.ts +16 -0
- package/src/runtime/transports/shared.ts +39 -0
- package/src/runtime/transports/ui-runtime-events.ts +35 -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 +69 -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 +46 -0
- package/src/runtime/ui-read-model-helpers.ts +32 -0
- package/src/runtime/ui-read-models-core.ts +95 -0
- package/src/runtime/ui-read-models-observability-maintenance.ts +81 -0
- package/src/runtime/ui-read-models-observability-options.ts +5 -0
- package/src/runtime/ui-read-models-observability-remote.ts +73 -0
- package/src/runtime/ui-read-models-observability-security.ts +172 -0
- package/src/runtime/ui-read-models-observability-system.ts +217 -0
- package/src/runtime/ui-read-models-observability.ts +59 -0
- package/src/runtime/ui-read-models-operations.ts +203 -0
- package/src/runtime/ui-read-models.ts +61 -0
- package/src/runtime/ui-service-queries.ts +114 -0
- package/src/runtime/ui-services.ts +163 -0
- package/src/runtime/worktree/registry.ts +252 -0
- package/src/scripts/process-messages.ts +42 -0
- package/src/sessions/manager.ts +388 -0
- package/src/shell/blocking-input.ts +89 -0
- package/src/shell/ui-openers.ts +163 -0
- package/src/state/file-watcher.ts +294 -0
- package/src/state/index.ts +56 -0
- package/src/state/knowledge-injection.ts +214 -0
- package/src/state/memory-embedding-http.ts +642 -0
- package/src/state/memory-embeddings.ts +312 -0
- package/src/state/memory-ingest.ts +132 -0
- package/src/state/memory-registry.ts +111 -0
- package/src/state/memory-store-helpers.ts +160 -0
- package/src/state/memory-store.ts +728 -0
- package/src/state/memory-vector-store.ts +418 -0
- package/src/templates/manager.ts +187 -0
- package/src/tools/agent/index.ts +610 -0
- package/src/tools/agent/manager.ts +476 -0
- package/src/tools/analyze/git-modes.ts +380 -0
- package/src/tools/analyze/index.ts +128 -0
- package/src/tools/channel/agent-tools.ts +16 -0
- package/src/tools/channel/index.ts +268 -0
- package/src/tools/control/index.ts +90 -0
- package/src/tools/edit/core.ts +619 -0
- package/src/tools/edit/index.ts +4 -0
- package/src/tools/edit/phased.ts +33 -0
- package/src/tools/fetch/index.ts +3 -0
- package/src/tools/fetch/phased.ts +34 -0
- package/src/tools/fetch/runtime.ts +499 -0
- package/src/tools/index.ts +186 -0
- package/src/tools/mcp/index.ts +190 -0
- package/src/tools/remote-trigger/index.ts +130 -0
- package/src/tools/repl/index.ts +318 -0
- package/src/tools/shared/auto-heal.ts +282 -0
- package/src/tools/state/index.ts +688 -0
- package/src/tools/web-search/index.ts +38 -0
- package/src/tools/write/index.ts +604 -0
- package/src/tools/write/phased.ts +41 -0
- package/src/types/generated/foundation-client-types.ts +22 -0
- package/src/types/sql-js.d.ts +15 -0
- package/src/utils/splash-lines.ts +46 -0
- package/src/version.ts +17 -0
- package/src/watchers/index.ts +11 -0
- package/src/watchers/registry.ts +517 -0
- package/src/web-search/index.ts +26 -0
- package/src/web-search/provider-registry.ts +64 -0
- package/src/web-search/providers/brave.ts +100 -0
- package/src/web-search/providers/duckduckgo.ts +270 -0
- package/src/web-search/providers/exa.ts +77 -0
- package/src/web-search/providers/firecrawl.ts +90 -0
- package/src/web-search/providers/perplexity.ts +86 -0
- package/src/web-search/providers/searxng.ts +88 -0
- package/src/web-search/providers/shared.ts +249 -0
- package/src/web-search/providers/tavily.ts +90 -0
- package/src/web-search/service.ts +142 -0
- package/src/widget/index.ts +2 -0
- package/src/widget/types.ts +9 -0
- package/src/widget/widget.ts +8 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import type { CommandRegistry, SlashCommand } from '../input/command-registry.ts';
|
|
2
|
+
import type { ModelDefinition, ProviderRegistry, RuntimeProviderRegistration, TokenLimits, ModelTier } from '../providers/registry.ts';
|
|
3
|
+
import type { LLMProvider } from '../providers/interface.ts';
|
|
4
|
+
import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools/registry';
|
|
5
|
+
import type { ToolDefinition } from '@pellux/goodvibes-sdk/platform/types/tools';
|
|
6
|
+
import type { RuntimeEventBus, AnyRuntimeEvent, RuntimeEventPayload } from '../runtime/events/index.ts';
|
|
7
|
+
import type { GatewayMethodCatalog, GatewayMethodDescriptor, GatewayMethodHandler } from '../control-plane/index.ts';
|
|
8
|
+
import {
|
|
9
|
+
type ChannelDeliveryStrategy,
|
|
10
|
+
type ChannelPlugin,
|
|
11
|
+
} from '../channels/index.ts';
|
|
12
|
+
import type { ChannelDeliveryRouter, ChannelPluginRegistry } from '../channels/index.ts';
|
|
13
|
+
import type { MemoryEmbeddingProvider, MemoryEmbeddingProviderRegistry } from '../state/index.ts';
|
|
14
|
+
import type { VoiceProvider, VoiceProviderRegistry } from '@pellux/goodvibes-sdk/platform/voice/index';
|
|
15
|
+
import type { MediaProvider, MediaProviderRegistry } from '../media/index.ts';
|
|
16
|
+
import type { WebSearchProvider, WebSearchProviderRegistry } from '../web-search/index.ts';
|
|
17
|
+
import { logger } from '@pellux/goodvibes-sdk/platform/utils/logger';
|
|
18
|
+
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils/error-display';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* PluginProviderConfig — minimal config for registering a custom LLM provider
|
|
22
|
+
* via an OpenAI-compatible endpoint.
|
|
23
|
+
*/
|
|
24
|
+
export interface PluginProviderConfig {
|
|
25
|
+
/** Base URL for an OpenAI-compatible endpoint (e.g. "http://localhost:8080/v1"). */
|
|
26
|
+
baseURL: string;
|
|
27
|
+
/** API key. May be empty string for local/unauthenticated servers. */
|
|
28
|
+
apiKey?: string;
|
|
29
|
+
/** Model IDs this provider exposes. */
|
|
30
|
+
models: string[];
|
|
31
|
+
/** Optional display label shown in the model picker. */
|
|
32
|
+
displayName?: string;
|
|
33
|
+
/** Optional embedding model exposed by the endpoint. */
|
|
34
|
+
embeddingModel?: string;
|
|
35
|
+
/** Optional reasoning-format override for compatible endpoints. */
|
|
36
|
+
reasoningFormat?: 'mercury' | 'openrouter' | 'llamacpp' | 'none';
|
|
37
|
+
/** Optional context-window metadata for runtime-registered model picker entries. */
|
|
38
|
+
contextWindow?: number;
|
|
39
|
+
/** Optional runtime capability hints for the registered model entries. */
|
|
40
|
+
capabilities?: Partial<ModelDefinition['capabilities']>;
|
|
41
|
+
/** Optional reasoning effort options surfaced in the picker. */
|
|
42
|
+
reasoningEffort?: string[];
|
|
43
|
+
/** Optional provider tier surfaced in the picker. */
|
|
44
|
+
tier?: ModelTier;
|
|
45
|
+
/** Optional token limits surfaced in the picker. */
|
|
46
|
+
tokenLimits?: TokenLimits;
|
|
47
|
+
/** Optional auth env vars for provider posture. */
|
|
48
|
+
authEnvVars?: readonly string[];
|
|
49
|
+
/** Optional service names that expose service-owned OAuth. */
|
|
50
|
+
serviceNames?: readonly string[];
|
|
51
|
+
/** Optional subscription-provider identity used for stored OAuth posture. */
|
|
52
|
+
subscriptionProviderId?: string;
|
|
53
|
+
/** Optional catalog suppressions for runtime clients. */
|
|
54
|
+
suppressCatalogModels?: readonly string[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface PluginRuntimeProviderModel {
|
|
58
|
+
readonly id: string;
|
|
59
|
+
readonly displayName?: string;
|
|
60
|
+
readonly description?: string;
|
|
61
|
+
readonly contextWindow?: number;
|
|
62
|
+
readonly selectable?: boolean;
|
|
63
|
+
readonly capabilities?: Partial<ModelDefinition['capabilities']>;
|
|
64
|
+
readonly reasoningEffort?: string[];
|
|
65
|
+
readonly tier?: ModelTier;
|
|
66
|
+
readonly tokenLimits?: TokenLimits;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface PluginProviderRegistration {
|
|
70
|
+
readonly provider: LLMProvider;
|
|
71
|
+
readonly models?: readonly PluginRuntimeProviderModel[];
|
|
72
|
+
readonly suppressCatalogModels?: readonly string[];
|
|
73
|
+
readonly replace?: boolean;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* PluginToolSchema — JSON Schema for a tool parameter object.
|
|
78
|
+
*/
|
|
79
|
+
export type PluginToolSchema = Record<string, unknown>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* PluginToolHandler — Called when the LLM invokes a plugin-registered tool.
|
|
83
|
+
*/
|
|
84
|
+
export type PluginToolHandler = (
|
|
85
|
+
args: Record<string, unknown>,
|
|
86
|
+
) => Promise<{ success: boolean; output?: string; error?: string }>;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* PluginCommandHandler — Called when a user runs a plugin-registered slash command.
|
|
90
|
+
*/
|
|
91
|
+
export type PluginCommandHandler = (args: string[]) => void | Promise<void>;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* PluginAPI — The constrained API surface exposed to plugins.
|
|
95
|
+
* Plugins receive an instance of this interface during init; they cannot
|
|
96
|
+
* access the wider application internals directly.
|
|
97
|
+
*/
|
|
98
|
+
export interface PluginAPI {
|
|
99
|
+
/** Register a custom slash command. */
|
|
100
|
+
registerCommand(
|
|
101
|
+
name: string,
|
|
102
|
+
description: string,
|
|
103
|
+
handler: PluginCommandHandler,
|
|
104
|
+
): void;
|
|
105
|
+
|
|
106
|
+
/** Register a custom LLM provider (OpenAI-compatible endpoint). */
|
|
107
|
+
registerProvider(name: string, config: PluginProviderConfig): Promise<void>;
|
|
108
|
+
|
|
109
|
+
/** Register a fully custom runtime provider instance with optional model entries. */
|
|
110
|
+
registerProviderInstance(registration: PluginProviderRegistration): void;
|
|
111
|
+
|
|
112
|
+
/** Register a custom tool available to the LLM. */
|
|
113
|
+
registerTool(
|
|
114
|
+
name: string,
|
|
115
|
+
schema: PluginToolSchema,
|
|
116
|
+
handler: PluginToolHandler,
|
|
117
|
+
): void;
|
|
118
|
+
|
|
119
|
+
/** Register a callable control-plane gateway method. */
|
|
120
|
+
registerGatewayMethod(
|
|
121
|
+
descriptor: Omit<GatewayMethodDescriptor, 'source' | 'pluginId'> & Partial<Pick<GatewayMethodDescriptor, 'source' | 'pluginId'>>,
|
|
122
|
+
handler: GatewayMethodHandler,
|
|
123
|
+
): void;
|
|
124
|
+
|
|
125
|
+
/** Register a channel plugin for a surface such as Slack, Discord, ntfy, or webhooks. */
|
|
126
|
+
registerChannelPlugin(plugin: ChannelPlugin): void;
|
|
127
|
+
|
|
128
|
+
/** Register an outbound channel delivery strategy. */
|
|
129
|
+
registerDeliveryStrategy(strategy: ChannelDeliveryStrategy, options?: { readonly replace?: boolean }): void;
|
|
130
|
+
|
|
131
|
+
/** Register a memory embedding provider. Sync providers can power sqlite-vec indexing immediately. */
|
|
132
|
+
registerMemoryEmbeddingProvider(provider: MemoryEmbeddingProvider, options?: { readonly replace?: boolean; readonly makeDefault?: boolean }): void;
|
|
133
|
+
|
|
134
|
+
/** Register a TS-only voice provider for TTS, STT, or realtime session negotiation. */
|
|
135
|
+
registerVoiceProvider(provider: VoiceProvider, options?: { readonly replace?: boolean }): void;
|
|
136
|
+
|
|
137
|
+
/** Register a TS-only media provider for analysis, transform, or generation. */
|
|
138
|
+
registerMediaProvider(provider: MediaProvider, options?: { readonly replace?: boolean }): void;
|
|
139
|
+
|
|
140
|
+
/** Register a provider-backed web search adapter. */
|
|
141
|
+
registerWebSearchProvider(provider: WebSearchProvider, options?: { readonly replace?: boolean }): void;
|
|
142
|
+
|
|
143
|
+
/** Subscribe to a typed runtime event. Returns an unsubscribe function. */
|
|
144
|
+
onEvent<K extends AnyRuntimeEvent['type']>(
|
|
145
|
+
eventName: K,
|
|
146
|
+
handler: (payload: RuntimeEventPayload<K>) => void,
|
|
147
|
+
): () => void;
|
|
148
|
+
|
|
149
|
+
/** Read a plugin-specific config value from the plugin's stored settings. */
|
|
150
|
+
getConfig(key: string): unknown;
|
|
151
|
+
|
|
152
|
+
/** Emit structured log output to the application logger. */
|
|
153
|
+
log(level: 'info' | 'warn' | 'error' | 'debug', message: string): void;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* PluginAPIContext — Internal dependencies passed when creating a PluginAPI instance.
|
|
158
|
+
* Not exposed to plugins.
|
|
159
|
+
*/
|
|
160
|
+
export interface PluginAPIContext {
|
|
161
|
+
pluginName: string;
|
|
162
|
+
runtimeBus: RuntimeEventBus;
|
|
163
|
+
commandRegistry: CommandRegistry;
|
|
164
|
+
providerRegistry: ProviderRegistry;
|
|
165
|
+
toolRegistry: ToolRegistry;
|
|
166
|
+
gatewayMethods: GatewayMethodCatalog;
|
|
167
|
+
channelRegistry: ChannelPluginRegistry;
|
|
168
|
+
channelDeliveryRouter: ChannelDeliveryRouter;
|
|
169
|
+
memoryEmbeddingRegistry: MemoryEmbeddingProviderRegistry;
|
|
170
|
+
voiceProviderRegistry: VoiceProviderRegistry;
|
|
171
|
+
mediaProviderRegistry: MediaProviderRegistry;
|
|
172
|
+
webSearchProviderRegistry: WebSearchProviderRegistry;
|
|
173
|
+
/** Plugin-specific config key-value pairs from plugins.json state. */
|
|
174
|
+
pluginConfig: Record<string, unknown>;
|
|
175
|
+
/** Collect cleanup callbacks so the manager can teardown on disable/reload. */
|
|
176
|
+
cleanup: Array<() => void>;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* createPluginAPI — Factory that creates a sandboxed PluginAPI for a single plugin.
|
|
181
|
+
* All registrations are tracked in `ctx.cleanup` so they can be undone on deactivation.
|
|
182
|
+
*/
|
|
183
|
+
export function createPluginAPI(ctx: PluginAPIContext): PluginAPI {
|
|
184
|
+
return {
|
|
185
|
+
registerCommand(name, description, handler) {
|
|
186
|
+
// Namespace commands to avoid collisions: "plugin-<pluginName>-<name>"
|
|
187
|
+
const cmdName = `plugin-${ctx.pluginName}-${name}`;
|
|
188
|
+
const cmd: SlashCommand = {
|
|
189
|
+
name: cmdName,
|
|
190
|
+
description: `[${ctx.pluginName}] ${description}`,
|
|
191
|
+
handler: async (args, _context) => {
|
|
192
|
+
try {
|
|
193
|
+
await handler(args);
|
|
194
|
+
} catch (err) {
|
|
195
|
+
logger.error(`[plugin:${ctx.pluginName}] Command '${name}' threw: ${summarizeError(err)}`);
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
ctx.commandRegistry.register(cmd);
|
|
200
|
+
ctx.cleanup.push(() => ctx.commandRegistry.unregister(cmdName));
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
async registerProvider(name, config) {
|
|
204
|
+
// Dynamically import to avoid circular dependency at module load time.
|
|
205
|
+
try {
|
|
206
|
+
const { OpenAICompatProvider } = await import('../providers/openai-compat.ts');
|
|
207
|
+
try {
|
|
208
|
+
const provider = new OpenAICompatProvider({
|
|
209
|
+
name,
|
|
210
|
+
baseURL: config.baseURL,
|
|
211
|
+
apiKey: config.apiKey ?? '',
|
|
212
|
+
defaultModel: config.models[0] ?? '',
|
|
213
|
+
models: config.models,
|
|
214
|
+
...(config.embeddingModel ? { embeddingModel: config.embeddingModel } : {}),
|
|
215
|
+
...(config.reasoningFormat ? { reasoningFormat: config.reasoningFormat } : {}),
|
|
216
|
+
...(config.authEnvVars ? { authEnvVars: config.authEnvVars } : {}),
|
|
217
|
+
...(config.serviceNames ? { serviceNames: config.serviceNames } : {}),
|
|
218
|
+
...(config.subscriptionProviderId ? { subscriptionProviderId: config.subscriptionProviderId } : {}),
|
|
219
|
+
...(config.suppressCatalogModels ? { suppressedModels: config.suppressCatalogModels } : {}),
|
|
220
|
+
});
|
|
221
|
+
const unregister = ctx.providerRegistry.registerRuntimeProvider({
|
|
222
|
+
provider,
|
|
223
|
+
models: config.models.map((modelId) => ({
|
|
224
|
+
id: modelId,
|
|
225
|
+
provider: name,
|
|
226
|
+
registryKey: `${name}:${modelId}`,
|
|
227
|
+
displayName: config.displayName ?? modelId,
|
|
228
|
+
description: `Plugin provider ${name}`,
|
|
229
|
+
contextWindow: config.contextWindow ?? 8192,
|
|
230
|
+
selectable: true,
|
|
231
|
+
capabilities: {
|
|
232
|
+
toolCalling: config.capabilities?.toolCalling ?? true,
|
|
233
|
+
codeEditing: config.capabilities?.codeEditing ?? true,
|
|
234
|
+
reasoning: config.capabilities?.reasoning ?? false,
|
|
235
|
+
multimodal: config.capabilities?.multimodal ?? false,
|
|
236
|
+
},
|
|
237
|
+
...(config.reasoningEffort ? { reasoningEffort: config.reasoningEffort } : {}),
|
|
238
|
+
...(config.tier ? { tier: config.tier } : {}),
|
|
239
|
+
...(config.tokenLimits ? { tokenLimits: config.tokenLimits } : {}),
|
|
240
|
+
})),
|
|
241
|
+
suppressCatalogModels: config.suppressCatalogModels,
|
|
242
|
+
});
|
|
243
|
+
ctx.cleanup.push(unregister);
|
|
244
|
+
logger.info(`[plugin:${ctx.pluginName}] Registered provider '${name}' with ${config.models.length} model(s)`);
|
|
245
|
+
} catch (err) {
|
|
246
|
+
logger.error(`[plugin:${ctx.pluginName}] registerProvider '${name}' failed: ${summarizeError(err)}`);
|
|
247
|
+
throw err;
|
|
248
|
+
}
|
|
249
|
+
} catch (err) {
|
|
250
|
+
logger.error(`[plugin:${ctx.pluginName}] Could not import OpenAICompatProvider: ${summarizeError(err)}`);
|
|
251
|
+
throw err;
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
registerProviderInstance(registration) {
|
|
256
|
+
const unregister = ctx.providerRegistry.registerRuntimeProvider({
|
|
257
|
+
provider: registration.provider,
|
|
258
|
+
models: (registration.models ?? []).map((model) => ({
|
|
259
|
+
id: model.id,
|
|
260
|
+
provider: registration.provider.name,
|
|
261
|
+
registryKey: `${registration.provider.name}:${model.id}`,
|
|
262
|
+
displayName: model.displayName ?? model.id,
|
|
263
|
+
description: model.description ?? `Plugin provider ${registration.provider.name}`,
|
|
264
|
+
contextWindow: model.contextWindow ?? 8192,
|
|
265
|
+
selectable: model.selectable ?? true,
|
|
266
|
+
capabilities: {
|
|
267
|
+
toolCalling: model.capabilities?.toolCalling ?? true,
|
|
268
|
+
codeEditing: model.capabilities?.codeEditing ?? true,
|
|
269
|
+
reasoning: model.capabilities?.reasoning ?? false,
|
|
270
|
+
multimodal: model.capabilities?.multimodal ?? false,
|
|
271
|
+
},
|
|
272
|
+
...(model.reasoningEffort ? { reasoningEffort: model.reasoningEffort } : {}),
|
|
273
|
+
...(model.tier ? { tier: model.tier } : {}),
|
|
274
|
+
...(model.tokenLimits ? { tokenLimits: model.tokenLimits } : {}),
|
|
275
|
+
})),
|
|
276
|
+
suppressCatalogModels: registration.suppressCatalogModels,
|
|
277
|
+
replace: registration.replace,
|
|
278
|
+
} satisfies RuntimeProviderRegistration);
|
|
279
|
+
ctx.cleanup.push(unregister);
|
|
280
|
+
logger.info(`[plugin:${ctx.pluginName}] Registered provider instance '${registration.provider.name}'`);
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
registerTool(name, schema, handler) {
|
|
284
|
+
const toolName = `plugin_${ctx.pluginName}_${name}`;
|
|
285
|
+
if (ctx.toolRegistry.has(toolName)) {
|
|
286
|
+
logger.warn(`[plugin:${ctx.pluginName}] Tool '${toolName}' already registered — skipping`);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const definition: ToolDefinition = {
|
|
290
|
+
name: toolName,
|
|
291
|
+
description: (schema.description as string) ?? `Plugin tool: ${name}`,
|
|
292
|
+
parameters: schema,
|
|
293
|
+
};
|
|
294
|
+
ctx.toolRegistry.register({
|
|
295
|
+
definition,
|
|
296
|
+
execute: async (args) => {
|
|
297
|
+
try {
|
|
298
|
+
return await handler(args);
|
|
299
|
+
} catch (err) {
|
|
300
|
+
return { success: false, error: summarizeError(err) };
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
// ToolRegistry has no unregister method. Track for cleanup awareness.
|
|
305
|
+
ctx.cleanup.push(() => {
|
|
306
|
+
logger.warn(`[plugin:${ctx.pluginName}] Tool '${toolName}' cannot be unregistered on deactivate — it persists until process restart`);
|
|
307
|
+
});
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
registerGatewayMethod(descriptor, handler) {
|
|
311
|
+
const methodId = descriptor.id.startsWith(`plugin.${ctx.pluginName}.`)
|
|
312
|
+
? descriptor.id
|
|
313
|
+
: `plugin.${ctx.pluginName}.${descriptor.id}`;
|
|
314
|
+
const unregister = ctx.gatewayMethods.register({
|
|
315
|
+
...descriptor,
|
|
316
|
+
id: methodId,
|
|
317
|
+
source: 'plugin',
|
|
318
|
+
pluginId: ctx.pluginName,
|
|
319
|
+
}, handler);
|
|
320
|
+
ctx.cleanup.push(unregister);
|
|
321
|
+
logger.info(`[plugin:${ctx.pluginName}] Registered gateway method '${methodId}'`);
|
|
322
|
+
},
|
|
323
|
+
|
|
324
|
+
registerChannelPlugin(plugin) {
|
|
325
|
+
const registry = ctx.channelRegistry;
|
|
326
|
+
registry.register(plugin);
|
|
327
|
+
ctx.cleanup.push(() => {
|
|
328
|
+
if (registry.get(plugin.id) === plugin) registry.unregister(plugin.id);
|
|
329
|
+
});
|
|
330
|
+
logger.info(`[plugin:${ctx.pluginName}] Registered channel plugin '${plugin.id}'`);
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
registerDeliveryStrategy(strategy, options = {}) {
|
|
334
|
+
const router = ctx.channelDeliveryRouter;
|
|
335
|
+
router.registerStrategy(strategy, options);
|
|
336
|
+
ctx.cleanup.push(() => {
|
|
337
|
+
router.unregisterStrategy(strategy.id);
|
|
338
|
+
});
|
|
339
|
+
logger.info(`[plugin:${ctx.pluginName}] Registered delivery strategy '${strategy.id}'`);
|
|
340
|
+
},
|
|
341
|
+
|
|
342
|
+
registerMemoryEmbeddingProvider(provider, options = {}) {
|
|
343
|
+
const unregister = ctx.memoryEmbeddingRegistry.register(provider, options);
|
|
344
|
+
ctx.cleanup.push(unregister);
|
|
345
|
+
logger.info(`[plugin:${ctx.pluginName}] Registered memory embedding provider '${provider.id}'`);
|
|
346
|
+
},
|
|
347
|
+
|
|
348
|
+
registerVoiceProvider(provider, options = {}) {
|
|
349
|
+
const unregister = ctx.voiceProviderRegistry.register(provider, options);
|
|
350
|
+
ctx.cleanup.push(unregister);
|
|
351
|
+
logger.info(`[plugin:${ctx.pluginName}] Registered voice provider '${provider.id}'`);
|
|
352
|
+
},
|
|
353
|
+
|
|
354
|
+
registerMediaProvider(provider, options = {}) {
|
|
355
|
+
const unregister = ctx.mediaProviderRegistry.register(provider, options);
|
|
356
|
+
ctx.cleanup.push(unregister);
|
|
357
|
+
logger.info(`[plugin:${ctx.pluginName}] Registered media provider '${provider.id}'`);
|
|
358
|
+
},
|
|
359
|
+
|
|
360
|
+
registerWebSearchProvider(provider, options = {}) {
|
|
361
|
+
const unregister = ctx.webSearchProviderRegistry.register(provider, options);
|
|
362
|
+
ctx.cleanup.push(unregister);
|
|
363
|
+
logger.info(`[plugin:${ctx.pluginName}] Registered web search provider '${provider.id}'`);
|
|
364
|
+
},
|
|
365
|
+
|
|
366
|
+
onEvent(eventName, handler) {
|
|
367
|
+
const unsub = ctx.runtimeBus.on(
|
|
368
|
+
eventName,
|
|
369
|
+
(envelope) => handler(envelope.payload as RuntimeEventPayload<typeof eventName>),
|
|
370
|
+
);
|
|
371
|
+
ctx.cleanup.push(unsub);
|
|
372
|
+
return unsub;
|
|
373
|
+
},
|
|
374
|
+
|
|
375
|
+
getConfig(key) {
|
|
376
|
+
return ctx.pluginConfig[key];
|
|
377
|
+
},
|
|
378
|
+
|
|
379
|
+
log(level, message) {
|
|
380
|
+
logger[level](`[plugin:${ctx.pluginName}] ${message}`);
|
|
381
|
+
},
|
|
382
|
+
};
|
|
383
|
+
}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
|
|
2
|
+
import { join, resolve, isAbsolute } from 'path';
|
|
3
|
+
import { logger } from '@pellux/goodvibes-sdk/platform/utils/logger';
|
|
4
|
+
import { createPluginAPI, type PluginAPIContext } from './api.ts';
|
|
5
|
+
import type { CommandRegistry } from '../input/command-registry.ts';
|
|
6
|
+
import type { ProviderRegistry } from '../providers/registry.ts';
|
|
7
|
+
import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools/registry';
|
|
8
|
+
import type { RuntimeEventBus } from '../runtime/events/index.ts';
|
|
9
|
+
import type { GatewayMethodCatalog } from '../control-plane/index.ts';
|
|
10
|
+
import type { ChannelDeliveryRouter, ChannelPluginRegistry } from '../channels/index.ts';
|
|
11
|
+
import type { MemoryEmbeddingProviderRegistry } from '../state/index.ts';
|
|
12
|
+
import type { VoiceProviderRegistry } from '@pellux/goodvibes-sdk/platform/voice/index';
|
|
13
|
+
import type { MediaProviderRegistry } from '../media/index.ts';
|
|
14
|
+
import type { WebSearchProviderRegistry } from '../web-search/index.ts';
|
|
15
|
+
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils/error-display';
|
|
16
|
+
|
|
17
|
+
export interface PluginPathOptions {
|
|
18
|
+
readonly cwd: string;
|
|
19
|
+
readonly homeDir: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Plugin search directories in precedence order.
|
|
24
|
+
* Project-local plugins override global plugins with the same manifest name.
|
|
25
|
+
*/
|
|
26
|
+
export function getUserPluginDirectory(options: PluginPathOptions): string {
|
|
27
|
+
return join(options.homeDir, '.goodvibes', 'tui', 'plugins');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function getPluginDirectories(options: PluginPathOptions): string[] {
|
|
31
|
+
return [
|
|
32
|
+
join(options.cwd, '.goodvibes', 'plugins'),
|
|
33
|
+
join(options.cwd, '.goodvibes', 'tui', 'plugins'),
|
|
34
|
+
getUserPluginDirectory(options),
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* PluginManifest — The structure of a plugin's manifest.json.
|
|
40
|
+
*/
|
|
41
|
+
export interface PluginManifest {
|
|
42
|
+
/** Unique plugin identifier (no spaces, lowercase-kebab). */
|
|
43
|
+
name: string;
|
|
44
|
+
version: string;
|
|
45
|
+
description: string;
|
|
46
|
+
author?: string;
|
|
47
|
+
/** Entry point relative to plugin directory. Defaults to "index.ts". */
|
|
48
|
+
main?: string;
|
|
49
|
+
/** Optional list of runtime event names the plugin subscribes to. */
|
|
50
|
+
hooks?: string[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* PluginEntryPoint — The exports expected from a plugin's entry file.
|
|
55
|
+
*/
|
|
56
|
+
export interface PluginEntryPoint {
|
|
57
|
+
/** Called once after the plugin is loaded. Receives the sandboxed PluginAPI. */
|
|
58
|
+
init(api: ReturnType<typeof createPluginAPI>): void | Promise<void>;
|
|
59
|
+
/** Optional: called when the plugin is activated (after init). */
|
|
60
|
+
activate?(): void | Promise<void>;
|
|
61
|
+
/** Optional: called when the plugin is deactivated (before cleanup). */
|
|
62
|
+
deactivate?(): void | Promise<void>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* LoadedPlugin — Runtime state of a single loaded plugin.
|
|
67
|
+
*/
|
|
68
|
+
export interface LoadedPlugin {
|
|
69
|
+
manifest: PluginManifest;
|
|
70
|
+
/** Absolute path to the plugin directory. */
|
|
71
|
+
pluginDir: string;
|
|
72
|
+
/** Whether the plugin is currently active (init + activate completed). */
|
|
73
|
+
active: boolean;
|
|
74
|
+
/** Cleanup callbacks accumulated during plugin API use. */
|
|
75
|
+
cleanup: Array<() => void>;
|
|
76
|
+
/** The resolved entry point module (available after load). */
|
|
77
|
+
entry?: PluginEntryPoint;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* DiscoveredPlugin — Result of scanning the plugins directory.
|
|
82
|
+
*/
|
|
83
|
+
export interface DiscoveredPlugin {
|
|
84
|
+
pluginDir: string;
|
|
85
|
+
manifest: PluginManifest;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* discoverPlugins — Scan the configured plugin directories for valid plugin folders.
|
|
90
|
+
* Each subdirectory with a readable manifest.json is a candidate.
|
|
91
|
+
*/
|
|
92
|
+
function scanPluginDirectory(rootDir: string): DiscoveredPlugin[] {
|
|
93
|
+
if (!existsSync(rootDir)) return [];
|
|
94
|
+
const results: DiscoveredPlugin[] = [];
|
|
95
|
+
let entries: string[];
|
|
96
|
+
try {
|
|
97
|
+
entries = readdirSync(rootDir);
|
|
98
|
+
} catch (err) {
|
|
99
|
+
logger.warn(`[plugins] Could not read plugins directory '${rootDir}': ${summarizeError(err)}`);
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (const entry of entries) {
|
|
104
|
+
const pluginDir = join(rootDir, entry);
|
|
105
|
+
try {
|
|
106
|
+
if (!statSync(pluginDir).isDirectory()) continue;
|
|
107
|
+
|
|
108
|
+
const manifestPath = join(pluginDir, 'manifest.json');
|
|
109
|
+
if (!existsSync(manifestPath)) continue;
|
|
110
|
+
|
|
111
|
+
const raw = readFileSync(manifestPath, 'utf-8');
|
|
112
|
+
const manifest = JSON.parse(raw) as PluginManifest;
|
|
113
|
+
|
|
114
|
+
if (!manifest.name || !manifest.version) {
|
|
115
|
+
logger.warn(`[plugins] ${entry}: manifest.json missing required fields (name, version)`);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Validate manifest field types
|
|
120
|
+
if (typeof manifest.name !== 'string' || typeof manifest.version !== 'string') {
|
|
121
|
+
logger.warn(`[plugins] ${entry}: manifest.json 'name' and 'version' must be strings`);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (manifest.main !== undefined) {
|
|
125
|
+
if (typeof manifest.main !== 'string') {
|
|
126
|
+
logger.warn(`[plugins] ${entry}: manifest.json 'main' must be a string`);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (isAbsolute(manifest.main)) {
|
|
130
|
+
logger.warn(`[plugins] ${entry}: manifest.json 'main' must be a relative path, not absolute`);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
results.push({ pluginDir, manifest });
|
|
136
|
+
} catch (err) {
|
|
137
|
+
logger.warn(`[plugins] ${entry}: failed to parse manifest — ${summarizeError(err)}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return results;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function discoverPlugins(options: PluginPathOptions): DiscoveredPlugin[] {
|
|
145
|
+
const discovered = new Map<string, DiscoveredPlugin>();
|
|
146
|
+
for (const dir of getPluginDirectories(options)) {
|
|
147
|
+
for (const plugin of scanPluginDirectory(dir)) {
|
|
148
|
+
if (!discovered.has(plugin.manifest.name)) {
|
|
149
|
+
discovered.set(plugin.manifest.name, plugin);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return [...discovered.values()];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* PluginLoaderDeps — External dependencies injected into the loader.
|
|
158
|
+
*/
|
|
159
|
+
export interface PluginLoaderDeps {
|
|
160
|
+
runtimeBus: RuntimeEventBus;
|
|
161
|
+
commandRegistry: CommandRegistry;
|
|
162
|
+
providerRegistry: ProviderRegistry;
|
|
163
|
+
toolRegistry: ToolRegistry;
|
|
164
|
+
gatewayMethods: GatewayMethodCatalog;
|
|
165
|
+
channelRegistry: ChannelPluginRegistry;
|
|
166
|
+
channelDeliveryRouter: ChannelDeliveryRouter;
|
|
167
|
+
memoryEmbeddingRegistry: MemoryEmbeddingProviderRegistry;
|
|
168
|
+
voiceProviderRegistry: VoiceProviderRegistry;
|
|
169
|
+
mediaProviderRegistry: MediaProviderRegistry;
|
|
170
|
+
webSearchProviderRegistry: WebSearchProviderRegistry;
|
|
171
|
+
/** Returns plugin-specific config given a plugin name. */
|
|
172
|
+
getPluginConfig(name: string): Record<string, unknown>;
|
|
173
|
+
/** Returns whether a plugin is enabled in persistent state. */
|
|
174
|
+
isEnabled(name: string): boolean;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* loadPlugin — Load, init, and activate a single plugin.
|
|
179
|
+
* Returns a LoadedPlugin on success, or null on failure.
|
|
180
|
+
*
|
|
181
|
+
* @param cacheBust - Optional timestamp suffix appended to the import URL to bypass
|
|
182
|
+
* Bun's module cache. Pass `Date.now()` on reload to force fresh execution.
|
|
183
|
+
*/
|
|
184
|
+
export async function loadPlugin(
|
|
185
|
+
discovered: DiscoveredPlugin,
|
|
186
|
+
deps: PluginLoaderDeps,
|
|
187
|
+
cacheBust?: number,
|
|
188
|
+
): Promise<LoadedPlugin | null> {
|
|
189
|
+
const { manifest, pluginDir } = discovered;
|
|
190
|
+
const entryFile = manifest.main ?? 'index.ts';
|
|
191
|
+
const entryPath = join(pluginDir, entryFile);
|
|
192
|
+
|
|
193
|
+
// Path traversal guard: resolved entry must remain within pluginDir
|
|
194
|
+
const resolvedEntry = resolve(entryPath);
|
|
195
|
+
const resolvedPluginDir = resolve(pluginDir);
|
|
196
|
+
if (!resolvedEntry.startsWith(resolvedPluginDir + '/') && resolvedEntry !== resolvedPluginDir) {
|
|
197
|
+
logger.error(`[plugins] ${manifest.name}: path traversal detected — entry '${entryFile}' resolves outside plugin directory`);
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (!existsSync(entryPath)) {
|
|
202
|
+
logger.warn(`[plugins] ${manifest.name}: entry file not found: ${entryPath}`);
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Trust notice — plugins run as trusted code (like VS Code extensions)
|
|
207
|
+
logger.warn(`[plugins] Loading '${manifest.name}' — plugins are trusted code and run with full application access`);
|
|
208
|
+
|
|
209
|
+
const loaded: LoadedPlugin = {
|
|
210
|
+
manifest,
|
|
211
|
+
pluginDir,
|
|
212
|
+
active: false,
|
|
213
|
+
cleanup: [],
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
// Dynamic import — Bun supports TS imports directly.
|
|
218
|
+
// Append cache-bust query param on reload so Bun re-executes the module.
|
|
219
|
+
const importPath = cacheBust !== undefined ? `${entryPath}?t=${cacheBust}` : entryPath;
|
|
220
|
+
const mod = await import(importPath) as unknown;
|
|
221
|
+
|
|
222
|
+
// Validate module shape before casting
|
|
223
|
+
if (!mod || typeof mod !== 'object') {
|
|
224
|
+
logger.warn(`[plugins] ${manifest.name}: entry file did not export a module object`);
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
const modObj = mod as Record<string, unknown>;
|
|
228
|
+
if (typeof modObj['init'] !== 'function') {
|
|
229
|
+
logger.warn(`[plugins] ${manifest.name}: entry file must export an init() function`);
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
if (modObj['activate'] !== undefined && typeof modObj['activate'] !== 'function') {
|
|
233
|
+
logger.warn(`[plugins] ${manifest.name}: entry file 'activate' export must be a function`);
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
if (modObj['deactivate'] !== undefined && typeof modObj['deactivate'] !== 'function') {
|
|
237
|
+
logger.warn(`[plugins] ${manifest.name}: entry file 'deactivate' export must be a function`);
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
const entry = mod as PluginEntryPoint;
|
|
241
|
+
|
|
242
|
+
loaded.entry = entry;
|
|
243
|
+
|
|
244
|
+
const ctx: PluginAPIContext = {
|
|
245
|
+
pluginName: manifest.name,
|
|
246
|
+
runtimeBus: deps.runtimeBus,
|
|
247
|
+
commandRegistry: deps.commandRegistry,
|
|
248
|
+
providerRegistry: deps.providerRegistry,
|
|
249
|
+
toolRegistry: deps.toolRegistry,
|
|
250
|
+
gatewayMethods: deps.gatewayMethods,
|
|
251
|
+
channelRegistry: deps.channelRegistry,
|
|
252
|
+
channelDeliveryRouter: deps.channelDeliveryRouter,
|
|
253
|
+
memoryEmbeddingRegistry: deps.memoryEmbeddingRegistry,
|
|
254
|
+
voiceProviderRegistry: deps.voiceProviderRegistry,
|
|
255
|
+
mediaProviderRegistry: deps.mediaProviderRegistry,
|
|
256
|
+
webSearchProviderRegistry: deps.webSearchProviderRegistry,
|
|
257
|
+
pluginConfig: deps.getPluginConfig(manifest.name),
|
|
258
|
+
cleanup: loaded.cleanup,
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const api = createPluginAPI(ctx);
|
|
262
|
+
|
|
263
|
+
// Lifecycle: init
|
|
264
|
+
await entry.init(api);
|
|
265
|
+
|
|
266
|
+
// Lifecycle: activate
|
|
267
|
+
if (typeof entry.activate === 'function') {
|
|
268
|
+
await entry.activate();
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
loaded.active = true;
|
|
272
|
+
logger.info(`[plugins] ${manifest.name} v${manifest.version} activated`);
|
|
273
|
+
return loaded;
|
|
274
|
+
} catch (err) {
|
|
275
|
+
logger.error(`[plugins] ${manifest.name}: load failed — ${summarizeError(err)}`);
|
|
276
|
+
// Run cleanup for anything that was registered before the error
|
|
277
|
+
for (const fn of loaded.cleanup) {
|
|
278
|
+
try { fn(); } catch { /* best-effort */ }
|
|
279
|
+
}
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* unloadPlugin — Deactivate a plugin and run all cleanup callbacks.
|
|
286
|
+
*/
|
|
287
|
+
export async function unloadPlugin(plugin: LoadedPlugin): Promise<void> {
|
|
288
|
+
if (!plugin.active) return;
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
if (typeof plugin.entry?.deactivate === 'function') {
|
|
292
|
+
await plugin.entry.deactivate();
|
|
293
|
+
}
|
|
294
|
+
} catch (err) {
|
|
295
|
+
logger.warn(`[plugins] ${plugin.manifest.name}: deactivate threw — ${summarizeError(err)}`);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
for (const fn of plugin.cleanup) {
|
|
299
|
+
try { fn(); } catch { /* best-effort */ }
|
|
300
|
+
}
|
|
301
|
+
plugin.cleanup.length = 0;
|
|
302
|
+
plugin.active = false;
|
|
303
|
+
logger.info(`[plugins] ${plugin.manifest.name} deactivated`);
|
|
304
|
+
}
|