@vellumai/assistant 0.10.2 → 0.10.3-dev.202606252046.9075fd5
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/bun.lock +20 -0
- package/docs/workspace-tools.md +42 -33
- package/eslint-rules/cli-no-daemon-internals.js +6 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +31 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +44 -0
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +48 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +14 -0
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +17 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +28 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +41 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/openapi.yaml +196 -56
- package/package.json +4 -1
- package/scripts/test.sh +36 -15
- package/src/__tests__/actor-token-service.test.ts +36 -14
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +83 -31
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
- package/src/__tests__/annotate-activity-metadata.test.ts +2 -0
- package/src/__tests__/annotate-risk-options.test.ts +2 -0
- package/src/__tests__/approval-cascade.test.ts +2 -0
- package/src/__tests__/assistant-attachments.test.ts +42 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -0
- package/src/__tests__/btw-routes.test.ts +2 -0
- package/src/__tests__/build-persisted-content.test.ts +2 -0
- package/src/__tests__/call-controller.test.ts +19 -0
- package/src/__tests__/channel-approval-routes.test.ts +21 -26
- package/src/__tests__/channel-delivery-store.test.ts +28 -0
- package/src/__tests__/channel-guardian.test.ts +164 -78
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +11 -19
- package/src/__tests__/channel-reply-delivery.test.ts +2 -0
- package/src/__tests__/code-search-tool.test.ts +585 -0
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/compaction-ledger-store.test.ts +128 -0
- package/src/__tests__/compaction.benchmark.test.ts +2 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +2 -0
- package/src/__tests__/compactor-low-watermark-cut.test.ts +2 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +2 -0
- package/src/__tests__/compactor-summary-call-truncation.test.ts +2 -0
- package/src/__tests__/compactor-web-search-strip.test.ts +2 -0
- package/src/__tests__/config-loader-backfill.test.ts +123 -10
- package/src/__tests__/config-schema.test.ts +1 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +31 -29
- package/src/__tests__/consult-deadline.test.ts +60 -0
- package/src/__tests__/contact-store-interaction-info.test.ts +156 -0
- package/src/__tests__/contact-store-user-file.test.ts +7 -10
- package/src/__tests__/contacts-relay-reads.test.ts +19 -24
- package/src/__tests__/contacts-write.test.ts +0 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop.test.ts +134 -0
- package/src/__tests__/conversation-analysis-routes.test.ts +2 -0
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +2 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +9 -11
- package/src/__tests__/conversation-confirmation-signals.test.ts +2 -0
- package/src/__tests__/conversation-fork-crud.test.ts +354 -24
- package/src/__tests__/conversation-history-web-search.test.ts +2 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +2 -0
- package/src/__tests__/conversation-load-history-stripped.test.ts +2 -0
- package/src/__tests__/conversation-pairing.test.ts +2 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
- package/src/__tests__/conversation-process-callsite.test.ts +2 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
- package/src/__tests__/conversation-queue.test.ts +91 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +14 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +14 -0
- package/src/__tests__/conversation-slash-queue.test.ts +2 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
- package/src/__tests__/conversation-speed-override.test.ts +2 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +29 -0
- package/src/__tests__/conversation-title-service.test.ts +2 -0
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +47 -0
- package/src/__tests__/conversation-usage.test.ts +2 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/db-compaction-events-migration.test.ts +129 -0
- package/src/__tests__/db-migration-rollback.test.ts +205 -171
- package/src/__tests__/db-test-helpers.ts +5 -4
- package/src/__tests__/delete-propagation.test.ts +5 -3
- package/src/__tests__/deterministic-verification-control-plane.test.ts +4 -2
- package/src/__tests__/disk-pressure-guard.test.ts +41 -0
- package/src/__tests__/dm-backfill.test.ts +6 -4
- package/src/__tests__/dm-persistence.test.ts +2 -0
- package/src/__tests__/emit-signal-routing-intent.test.ts +7 -6
- package/src/__tests__/events-dev-bypass-actor.test.ts +7 -1
- package/src/__tests__/exploration-drift-hook.test.ts +3 -2
- package/src/__tests__/filing-service.test.ts +2 -0
- package/src/__tests__/guardian-binding-drift-heal.test.ts +104 -19
- package/src/__tests__/guardian-dispatch.test.ts +140 -1
- package/src/__tests__/guardian-expiry-notifier.test.ts +282 -0
- package/src/__tests__/guardian-outbound-http.test.ts +13 -0
- package/src/__tests__/guardian-routing-state.test.ts +6 -10
- package/src/__tests__/heartbeat-disk-pressure.test.ts +2 -0
- package/src/__tests__/heartbeat-service.test.ts +2 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +46 -19
- package/src/__tests__/helpers/create-guardian-binding.ts +15 -23
- package/src/__tests__/helpers/mock-logger.ts +1 -0
- package/src/__tests__/helpers/seed-contact-channel.ts +96 -0
- package/src/__tests__/host-app-control-routes.test.ts +24 -30
- package/src/__tests__/host-bash-routes.test.ts +31 -41
- package/src/__tests__/host-browser-routes.test.ts +26 -32
- package/src/__tests__/host-cu-routes-targeted.test.ts +25 -33
- package/src/__tests__/host-file-routes-targeted.test.ts +40 -52
- package/src/__tests__/host-transfer-routes-targeted.test.ts +31 -43
- package/src/__tests__/http-user-message-parity.test.ts +290 -8
- package/src/__tests__/inbound-invite-redemption.test.ts +115 -10
- package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/invite-redemption-service.test.ts +471 -53
- package/src/__tests__/invite-routes-http.test.ts +34 -0
- package/src/__tests__/invite-service-ipc.test.ts +65 -2
- package/src/__tests__/llm-context-normalization.test.ts +105 -0
- package/src/__tests__/llm-request-log-error-payload.test.ts +71 -9
- package/src/__tests__/llm-usage-store.test.ts +25 -0
- package/src/__tests__/mcp-config-secret-boundary.test.ts +392 -0
- package/src/__tests__/mcp-health-check.test.ts +2 -1
- package/src/__tests__/media-stream-server-integration.test.ts +127 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +2 -0
- package/src/__tests__/messaging-send-tool.test.ts +2 -0
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +275 -5
- package/src/__tests__/native-web-search.test.ts +2 -0
- package/src/__tests__/non-member-access-request.test.ts +191 -17
- package/src/__tests__/notification-broadcaster.test.ts +4 -0
- package/src/__tests__/notification-decision-recipient-context.test.ts +33 -32
- package/src/__tests__/notification-deep-link.test.ts +6 -0
- package/src/__tests__/notification-guardian-path.test.ts +19 -0
- package/src/__tests__/onboarding-persona-write.test.ts +52 -22
- package/src/__tests__/openai-provider.test.ts +22 -12
- package/src/__tests__/openai-responses-provider.test.ts +12 -2
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/pending-interactions-resolved-event.test.ts +7 -4
- package/src/__tests__/persist-onboarding-artifacts.test.ts +1 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
- package/src/__tests__/persona-resolver.test.ts +75 -45
- package/src/__tests__/plugin-bootstrap.test.ts +21 -83
- package/src/__tests__/plugin-disabled-state.test.ts +190 -0
- package/src/__tests__/plugin-pipeline.test.ts +96 -0
- package/src/__tests__/plugin-route-contribution.test.ts +6 -19
- package/src/__tests__/plugin-tool-contribution.test.ts +5 -20
- package/src/__tests__/plugin-types.test.ts +2 -4
- package/src/__tests__/process-message-background-slack.test.ts +2 -0
- package/src/__tests__/process-message-display-content.test.ts +2 -0
- package/src/__tests__/provider-error-scenarios.test.ts +5 -4
- package/src/__tests__/provider-usage-tracking.test.ts +39 -0
- package/src/__tests__/reaction-intercept-cold-cache-warm.test.ts +135 -0
- package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +158 -0
- package/src/__tests__/reaction-persistence.test.ts +51 -4
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +2 -0
- package/src/__tests__/registry.test.ts +4 -1
- package/src/__tests__/relay-server.test.ts +758 -32
- package/src/__tests__/runtime-attachment-metadata.test.ts +9 -12
- package/src/__tests__/secret-ingress-http.test.ts +14 -0
- package/src/__tests__/send-endpoint-busy.test.ts +30 -8
- package/src/__tests__/settings-routes.test.ts +32 -0
- package/src/__tests__/skills.test.ts +44 -0
- package/src/__tests__/slack-inbound-verification.test.ts +47 -2
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +79 -0
- package/src/__tests__/steer-on-enqueue-question.test.ts +181 -0
- package/src/__tests__/stt-hints.test.ts +49 -15
- package/src/__tests__/subagent-detail.test.ts +27 -0
- package/src/__tests__/subagent-disposal.test.ts +65 -0
- package/src/__tests__/subagent-fork-prompt-role.test.ts +195 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +6 -7
- package/src/__tests__/subagent-notify-parent.test.ts +2 -0
- package/src/__tests__/subagent-role-registry.test.ts +24 -6
- package/src/__tests__/subagent-spawn-and-await.test.ts +546 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +2 -0
- package/src/__tests__/subagent-tools.test.ts +398 -1
- package/src/__tests__/suggestion-routes.test.ts +2 -0
- package/src/__tests__/thread-backfill.test.ts +3 -3
- package/src/__tests__/title-generate-hook.test.ts +2 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -0
- package/src/__tests__/tool-executor.test.ts +16 -11
- package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +2 -0
- package/src/__tests__/tool-start-timestamp.test.ts +2 -0
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +37 -51
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +12 -12
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -7
- package/src/__tests__/trusted-contact-multichannel.test.ts +16 -7
- package/src/__tests__/trusted-contact-verification.test.ts +79 -54
- package/src/__tests__/twilio-routes.test.ts +96 -0
- package/src/__tests__/ui-file-upload-surface.test.ts +86 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -0
- package/src/__tests__/voice-guardian-cold-cache-warm.test.ts +137 -0
- package/src/__tests__/voice-invite-redemption.test.ts +216 -20
- package/src/__tests__/web-search-backend-failure.test.ts +2 -0
- package/src/__tests__/workspace-migration-102-preserve-heartbeat-enabled-for-existing-workspaces.test.ts +3 -3
- package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +208 -0
- package/src/__tests__/workspace-migration-112-remove-advisor-callsite-override.test.ts +170 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +196 -238
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +14 -35
- package/src/__tests__/workspace-tool-loader.test.ts +195 -2
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +35 -47
- package/src/agent/loop-exclusive-tool.test.ts +154 -0
- package/src/agent/loop-native-web-search.test.ts +200 -0
- package/src/agent/loop.ts +164 -1
- package/src/api/constants/sse-replay.ts +41 -0
- package/src/api/events/conversation-notice.ts +26 -0
- package/src/api/index.ts +19 -1
- package/src/api/responses/llm-request-log-entry.ts +29 -0
- package/src/api/responses/subagent-detail.ts +17 -0
- package/src/api/surfaces.ts +39 -3
- package/src/approvals/guardian-channel-delivery.ts +30 -0
- package/src/approvals/guardian-expiry-notifier.ts +148 -0
- package/src/approvals/guardian-request-resolvers.ts +17 -15
- package/src/calls/__tests__/relay-setup-router.test.ts +267 -17
- package/src/calls/call-domain.ts +3 -3
- package/src/calls/guardian-dispatch.ts +14 -9
- package/src/calls/inbound-trust-reader.ts +24 -2
- package/src/calls/media-stream-server.ts +21 -0
- package/src/calls/relay-access-wait.ts +6 -6
- package/src/calls/relay-server.ts +188 -51
- package/src/calls/relay-setup-router.ts +47 -17
- package/src/calls/relay-verification.ts +4 -4
- package/src/calls/stt-hints.ts +9 -12
- package/src/calls/twilio-routes.ts +14 -4
- package/src/channels/types.ts +10 -20
- package/src/cli/commands/__tests__/cache.test.ts +8 -1
- package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -0
- package/src/cli/commands/cache.ts +194 -181
- package/src/cli/commands/contacts.ts +10 -7
- package/src/cli/commands/db/__tests__/repair.test.ts +6 -5
- package/src/cli/commands/db/status.ts +37 -1
- package/src/cli/commands/mcp.ts +252 -218
- package/src/cli/commands/memory/__tests__/worker.test.ts +432 -0
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/worker.ts +242 -0
- package/src/cli/commands/plugins.ts +125 -13
- package/src/cli/lib/__tests__/install-from-github.test.ts +102 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +160 -1
- package/src/cli/lib/__tests__/publish-plugin.test.ts +404 -0
- package/src/cli/lib/list-installed-plugins.ts +179 -1
- package/src/cli/lib/publish-plugin.ts +633 -0
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +143 -0
- package/src/config/__tests__/sync-gated-profiles.test.ts +16 -10
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +27 -17
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +13 -3
- package/src/config/bundled-skills/subagent/SKILL.md +17 -2
- package/src/config/bundled-skills/subagent/TOOLS.json +5 -4
- package/src/config/call-site-defaults.ts +0 -6
- package/src/config/feature-flag-registry.json +5 -13
- package/src/config/llm-resolver.ts +0 -3
- package/src/config/loader.ts +38 -5
- package/src/config/prune-seeded-callsite-defaults.ts +110 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +0 -7
- package/src/config/schemas/heartbeat.ts +2 -5
- package/src/config/schemas/llm.ts +3 -12
- package/src/config/schemas/memory-lifecycle.ts +12 -0
- package/src/config/schemas/memory-v3.ts +7 -0
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/timeouts.ts +8 -0
- package/src/config/seed-inference-profiles.ts +30 -34
- package/src/config/skills.ts +27 -5
- package/src/config/sync-gated-profiles.ts +12 -16
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +128 -0
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +312 -0
- package/src/contacts/__tests__/member-write-relay.test.ts +226 -0
- package/src/contacts/contact-store.ts +27 -237
- package/src/contacts/contacts-write.ts +18 -55
- package/src/contacts/gateway-channel-read.ts +51 -0
- package/src/contacts/guardian-delivery-reader.ts +223 -0
- package/src/contacts/member-write-relay.ts +183 -0
- package/src/contacts/types.ts +3 -15
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +35 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +0 -44
- package/src/daemon/assistant-attachments.ts +27 -4
- package/src/daemon/conversation-agent-loop.ts +28 -0
- package/src/daemon/conversation-notices.ts +60 -0
- package/src/daemon/conversation-process.ts +35 -16
- package/src/daemon/conversation-surfaces.ts +111 -38
- package/src/daemon/conversation-tool-setup.ts +71 -30
- package/src/daemon/conversation.ts +23 -1
- package/src/daemon/disk-pressure-guard.ts +12 -2
- package/src/daemon/event-loop-watchdog.ts +28 -1
- package/src/daemon/external-plugins-bootstrap.ts +17 -41
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -2
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +25 -2
- package/src/daemon/handlers/__tests__/config-channels.test.ts +220 -0
- package/src/daemon/handlers/config-a2a.ts +6 -14
- package/src/daemon/handlers/config-channels.ts +67 -26
- package/src/daemon/handlers/conversations.ts +77 -0
- package/src/daemon/lifecycle.ts +16 -0
- package/src/daemon/mcp-reload-service.ts +10 -0
- package/src/daemon/memory-v2-startup.test.ts +72 -0
- package/src/daemon/memory-v2-startup.ts +87 -19
- package/src/daemon/message-types/conversations.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +12 -12
- package/src/daemon/server.ts +0 -4
- package/src/daemon/shutdown-handlers.ts +20 -0
- package/src/daemon/tool-setup-types.ts +9 -0
- package/src/heartbeat/heartbeat-service.ts +5 -0
- package/src/home/relationship-state-writer.ts +5 -0
- package/src/hooks/hook-loader.ts +341 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
- package/src/ipc/assistant-server.ts +2 -2
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +1 -0
- package/src/mcp/client.ts +15 -1
- package/src/mcp/mcp-auth-orchestrator.ts +6 -1
- package/src/mcp/mcp-header-store.ts +134 -0
- package/src/mcp/mcp-oauth-provider.ts +19 -8
- package/src/memory/__tests__/301-create-watchdog-events.test.ts +110 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
- package/src/memory/__tests__/prompt-override.test.ts +192 -0
- package/src/memory/__tests__/watchdog-events-store.test.ts +161 -0
- package/src/memory/compaction-ledger-store.ts +107 -0
- package/src/memory/conversation-crud.ts +129 -61
- package/src/memory/db-connection.ts +22 -3
- package/src/memory/db-init.ts +37 -503
- package/src/memory/db-singleton.ts +6 -4
- package/src/memory/jobs-worker.ts +104 -0
- package/src/memory/llm-request-log-store.ts +26 -1
- package/src/memory/llm-usage-store.ts +48 -20
- package/src/memory/memory-retrospective-job.ts +14 -8
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +152 -56
- package/src/memory/migrations/300-add-processing-started-at.ts +30 -0
- package/src/memory/migrations/301-create-watchdog-events.ts +45 -0
- package/src/memory/migrations/302-create-compaction-events.ts +107 -0
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +297 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
- package/src/memory/migrations/run-migrations.ts +106 -10
- package/src/memory/migrations/validate-migration-state.ts +105 -67
- package/src/memory/prompt-override.ts +129 -0
- package/src/memory/schema/contacts.ts +6 -2
- package/src/memory/schema/conversations.ts +37 -0
- package/src/memory/schema/infrastructure.ts +20 -0
- package/src/memory/steps.ts +1294 -0
- package/src/memory/v2/__tests__/cli-command-store.test.ts +25 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +80 -0
- package/src/memory/v2/cli-command-store.ts +75 -38
- package/src/memory/v2/prompts/consolidation.ts +13 -82
- package/src/memory/v2/prompts/router.ts +21 -93
- package/src/memory/v2/skill-store.ts +68 -31
- package/src/memory/watchdog-events-store.ts +87 -0
- package/src/memory/worker-control.ts +204 -0
- package/src/memory/worker-process.ts +89 -0
- package/src/messaging/channel-binding-metadata.ts +31 -0
- package/src/messaging/provider-types.ts +8 -0
- package/src/messaging/providers/slack/binding-metadata.ts +60 -0
- package/src/notifications/__tests__/broadcaster.test.ts +8 -8
- package/src/notifications/__tests__/connected-channels.test.ts +86 -0
- package/src/notifications/__tests__/decision-engine.test.ts +78 -9
- package/src/notifications/__tests__/destination-resolver.test.ts +151 -0
- package/src/notifications/broadcaster.ts +8 -1
- package/src/notifications/decision-engine.ts +15 -7
- package/src/notifications/destination-resolver.ts +53 -25
- package/src/notifications/emit-signal.ts +34 -15
- package/src/onboarding/checkin-event.test.ts +222 -0
- package/src/onboarding/checkin-event.ts +321 -0
- package/src/onboarding/schedule-checkin.ts +190 -0
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +7 -4
- package/src/plugin-api/index.ts +12 -12
- package/src/plugin-api/types.ts +12 -14
- package/src/plugin-api/vision-support.test.ts +28 -4
- package/src/plugin-api/vision-support.ts +66 -31
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/empty-response/hooks/stop.ts +2 -2
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +4 -3
- package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/history-repair/hooks/stop.ts +2 -2
- package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +47 -7
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +12 -13
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +14 -22
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +42 -11
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/image-recovery/hooks/stop.ts +2 -2
- package/src/plugins/defaults/index.ts +0 -35
- package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/max-tokens-continue/hooks/stop.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +33 -3
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +48 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +4 -8
- package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +43 -15
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +11 -2
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +146 -0
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +77 -13
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +12 -11
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +2 -2
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +2 -2
- package/src/plugins/defaults/title-generate/hooks/stop.ts +2 -2
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +2 -2
- package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +2 -2
- package/src/plugins/disabled-state.ts +31 -0
- package/src/plugins/external-plugin-loader.ts +2 -2
- package/src/plugins/mtime-cache.ts +186 -330
- package/src/plugins/pipeline.ts +111 -13
- package/src/plugins/registry.ts +59 -16
- package/src/plugins/surface-import.ts +121 -0
- package/src/plugins/types.ts +7 -9
- package/src/prompts/persona-resolver.ts +43 -11
- package/src/providers/anthropic/client.ts +5 -0
- package/src/providers/call-site-routing.ts +45 -0
- package/src/providers/model-catalog.ts +16 -0
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +321 -0
- package/src/providers/openai/api-error-normalization.ts +270 -0
- package/src/providers/openai/chat-completions-provider.ts +37 -83
- package/src/providers/openai/responses-provider.ts +50 -46
- package/src/providers/openrouter/client.ts +5 -0
- package/src/providers/provider-send-message.ts +10 -0
- package/src/providers/ratelimit.ts +10 -0
- package/src/providers/registry.ts +1 -1
- package/src/providers/retry.ts +10 -0
- package/src/providers/types.ts +22 -0
- package/src/providers/usage-tracking.ts +10 -0
- package/src/runtime/__tests__/channel-verification-service.test.ts +133 -0
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +184 -0
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +66 -0
- package/src/runtime/__tests__/local-principal-trust.test.ts +162 -0
- package/src/runtime/__tests__/member-verdict-cache.test.ts +119 -0
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +402 -123
- package/src/runtime/access-request-helper.ts +18 -39
- package/src/runtime/actor-trust-resolver.ts +46 -19
- package/src/runtime/anchored-guardian.test.ts +109 -0
- package/src/runtime/anchored-guardian.ts +86 -0
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/assistant-stream-state.ts +9 -2
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +99 -0
- package/src/runtime/auth/require-bound-guardian.ts +21 -11
- package/src/runtime/channel-verification-service.ts +56 -31
- package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
- package/src/runtime/guardian-vellum-migration.ts +69 -8
- package/src/runtime/invite-redemption-service.ts +213 -187
- package/src/runtime/local-actor-identity.test.ts +108 -0
- package/src/runtime/local-actor-identity.ts +85 -13
- package/src/runtime/local-principal-trust.ts +52 -0
- package/src/runtime/member-verdict-cache.ts +0 -0
- package/src/runtime/pending-interactions.ts +11 -1
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +56 -5
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/contact-routes.test.ts +305 -0
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +92 -0
- package/src/runtime/routes/__tests__/http-adapter-actor-header.test.ts +129 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +188 -0
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +13 -5
- package/src/runtime/routes/channel-verification-routes.ts +3 -3
- package/src/runtime/routes/contact-routes.ts +48 -57
- package/src/runtime/routes/conversation-cli-routes.ts +4 -5
- package/src/runtime/routes/conversation-list-routes.ts +4 -7
- package/src/runtime/routes/conversation-query-routes.ts +72 -0
- package/src/runtime/routes/conversation-routes.ts +84 -85
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/global-search-routes.ts +3 -1
- package/src/runtime/routes/guardian-action-routes.ts +4 -5
- package/src/runtime/routes/host-app-control-routes.ts +5 -4
- package/src/runtime/routes/host-bash-routes.ts +5 -4
- package/src/runtime/routes/host-browser-routes.ts +9 -11
- package/src/runtime/routes/host-cu-routes.ts +5 -4
- package/src/runtime/routes/host-file-routes.ts +5 -4
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +16 -1
- package/src/runtime/routes/identity-routes.ts +3 -2
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +97 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +61 -59
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +13 -5
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +21 -8
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -3
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +19 -0
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/llm-context-normalization.ts +83 -0
- package/src/runtime/routes/mcp-auth-routes.ts +171 -19
- package/src/runtime/routes/migration-rollback-routes.ts +4 -3
- package/src/runtime/routes/migration-routes.ts +4 -1
- package/src/runtime/routes/onboarding-checkin-routes.ts +86 -0
- package/src/runtime/routes/settings-routes.ts +8 -3
- package/src/runtime/routes/subagents-routes.ts +5 -0
- package/src/runtime/routes/surface-action-routes.ts +42 -56
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
- package/src/runtime/services/conversation-serializer.ts +13 -58
- package/src/runtime/tool-grant-request-helper.ts +3 -3
- package/src/runtime/trust-verdict-consumer.ts +111 -40
- package/src/runtime/verification-outbound-actions.ts +18 -18
- package/src/signals/user-message.ts +16 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +35 -0
- package/src/{plugins/defaults/advisor/__tests__/transcript.test.ts → subagent/__tests__/consult-transcript.test.ts} +47 -10
- package/src/{plugins/defaults/advisor/steering.ts → subagent/consult-prompt.ts} +22 -32
- package/src/{plugins/defaults/advisor/transcript.ts → subagent/consult-transcript.ts} +18 -8
- package/src/subagent/index.ts +1 -1
- package/src/subagent/manager.ts +254 -33
- package/src/subagent/types.ts +11 -4
- package/src/telemetry/types.ts +34 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
- package/src/telemetry/usage-telemetry-reporter.ts +87 -3
- package/src/tools/ask-question/ask-question-tool.test.ts +29 -0
- package/src/tools/ask-question/ask-question-tool.ts +13 -0
- package/src/tools/executor.ts +4 -4
- package/src/tools/filesystem/search.ts +543 -0
- package/src/tools/registry.ts +38 -0
- package/src/tools/shared/filesystem/path-policy.ts +12 -5
- package/src/tools/subagent/consult-deadline.ts +49 -0
- package/src/tools/subagent/spawn.ts +234 -5
- package/src/tools/tool-approval-handler.ts +1 -1
- package/src/tools/tool-defaults.ts +9 -2
- package/src/tools/tool-manifest.ts +3 -0
- package/src/tools/types.ts +131 -25
- package/src/tools/workspace-tools/loader.ts +348 -244
- package/src/util/errors.ts +26 -1
- package/src/util/logger.ts +9 -0
- package/src/util/platform.ts +19 -0
- package/src/util/telemetry-db-path.ts +24 -0
- package/src/workflows/library.test.ts +140 -0
- package/src/workflows/library.ts +82 -28
- package/src/workspace/migrations/017-seed-persona-dirs.ts +3 -34
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +3 -24
- package/src/workspace/migrations/031-drop-user-md.ts +232 -148
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +14 -66
- package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +134 -0
- package/src/workspace/migrations/112-remove-advisor-callsite-override.ts +64 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +0 -70
- package/src/daemon/workspace-tools-watcher.ts +0 -328
- package/src/memory/migrations/registry.ts +0 -573
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +0 -56
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +0 -43
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +0 -137
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -153
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +0 -138
- package/src/plugins/defaults/advisor/advisor-gate.ts +0 -29
- package/src/plugins/defaults/advisor/advisor-state-store.ts +0 -94
- package/src/plugins/defaults/advisor/config.ts +0 -21
- package/src/plugins/defaults/advisor/consult.ts +0 -93
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +0 -34
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +0 -30
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +0 -19
- package/src/plugins/defaults/advisor/package.json +0 -14
- package/src/plugins/defaults/advisor/tools/advisor.ts +0 -65
- package/src/providers/openai/__tests__/api-error-detail.test.ts +0 -120
|
@@ -29,7 +29,11 @@ import {
|
|
|
29
29
|
PluginAlreadyInstalledError,
|
|
30
30
|
PluginNotFoundError,
|
|
31
31
|
} from "../lib/install-from-github.js";
|
|
32
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
type AllPluginInfo,
|
|
34
|
+
listAllPlugins,
|
|
35
|
+
listInstalledPlugins,
|
|
36
|
+
} from "../lib/list-installed-plugins.js";
|
|
33
37
|
import type { FingerprintComparison } from "../lib/plugin-fingerprint.js";
|
|
34
38
|
import {
|
|
35
39
|
DEFAULT_PIN_HISTORY_LIMIT,
|
|
@@ -38,6 +42,7 @@ import {
|
|
|
38
42
|
PluginPinHistoryError,
|
|
39
43
|
resolvePinToMarketplaceCommit,
|
|
40
44
|
} from "../lib/plugin-pin-history.js";
|
|
45
|
+
import { runPublish } from "../lib/publish-plugin.js";
|
|
41
46
|
import { registerCommand } from "../lib/register-command.js";
|
|
42
47
|
import {
|
|
43
48
|
InvalidSearchPatternError,
|
|
@@ -85,6 +90,8 @@ Examples:
|
|
|
85
90
|
$ assistant plugins install example --pin <sha> --force
|
|
86
91
|
$ assistant plugins list
|
|
87
92
|
$ assistant plugins list --json
|
|
93
|
+
$ assistant plugins list --all
|
|
94
|
+
$ assistant plugins list --all --json
|
|
88
95
|
$ assistant plugins inspect example
|
|
89
96
|
$ assistant plugins inspect example --json
|
|
90
97
|
$ assistant plugins diff example
|
|
@@ -155,7 +162,6 @@ Examples:
|
|
|
155
162
|
console.log(
|
|
156
163
|
`Installed plugin "${result.name}" (${result.fileCount} file${result.fileCount === 1 ? "" : "s"})${pinned} → ${result.target}`,
|
|
157
164
|
);
|
|
158
|
-
console.log("Restart the assistant to pick up the new plugin.");
|
|
159
165
|
} catch (err) {
|
|
160
166
|
if (err instanceof PluginAlreadyInstalledError) {
|
|
161
167
|
console.error(`${err.message}\nPass --force to overwrite.`);
|
|
@@ -239,9 +245,58 @@ Examples:
|
|
|
239
245
|
|
|
240
246
|
plugins
|
|
241
247
|
.command("list")
|
|
242
|
-
.description("List plugins installed
|
|
248
|
+
.description("List plugins installed in your workspace.")
|
|
243
249
|
.option("--json", "Emit machine-readable JSON instead of a table")
|
|
244
|
-
.
|
|
250
|
+
.option(
|
|
251
|
+
"--all",
|
|
252
|
+
"Include first-party default plugins and disabled plugins in the listing",
|
|
253
|
+
)
|
|
254
|
+
.action((opts: { json?: boolean; all?: boolean }) => {
|
|
255
|
+
if (opts.all) {
|
|
256
|
+
const all = listAllPlugins();
|
|
257
|
+
|
|
258
|
+
if (opts.json) {
|
|
259
|
+
process.stdout.write(JSON.stringify(all, null, 2) + "\n");
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (all.length === 0) {
|
|
264
|
+
console.log("No plugins found.");
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const rows = all.map((p) => ({
|
|
269
|
+
name: p.name,
|
|
270
|
+
version: p.packageJson?.version ?? "—",
|
|
271
|
+
source: p.source,
|
|
272
|
+
status: formatAllPluginStatus(p),
|
|
273
|
+
}));
|
|
274
|
+
const nameW = Math.max(4, ...rows.map((r) => r.name.length));
|
|
275
|
+
const versionW = Math.max(7, ...rows.map((r) => r.version.length));
|
|
276
|
+
const sourceW = Math.max(6, ...rows.map((r) => r.source.length));
|
|
277
|
+
const pad = (s: string, w: number) => s + " ".repeat(w - s.length);
|
|
278
|
+
console.log(
|
|
279
|
+
`${pad("NAME", nameW)} ${pad("VERSION", versionW)} ${pad("SOURCE", sourceW)} STATUS`,
|
|
280
|
+
);
|
|
281
|
+
for (const r of rows) {
|
|
282
|
+
console.log(
|
|
283
|
+
`${pad(r.name, nameW)} ${pad(r.version, versionW)} ${pad(r.source, sourceW)} ${r.status}`,
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const userCount = all.filter((p) => p.source === "user").length;
|
|
288
|
+
const defaultCount = all.length - userCount;
|
|
289
|
+
const disabledCount = all.filter((p) => p.disabled).length;
|
|
290
|
+
console.log("");
|
|
291
|
+
console.log(
|
|
292
|
+
`${all.length} plugin${all.length === 1 ? "" : "s"} ` +
|
|
293
|
+
`(${userCount} user, ${defaultCount} default` +
|
|
294
|
+
(disabledCount > 0 ? `, ${disabledCount} disabled` : "") +
|
|
295
|
+
`).`,
|
|
296
|
+
);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
245
300
|
const installed = listInstalledPlugins();
|
|
246
301
|
|
|
247
302
|
if (opts.json) {
|
|
@@ -451,6 +506,56 @@ Examples:
|
|
|
451
506
|
}
|
|
452
507
|
});
|
|
453
508
|
|
|
509
|
+
plugins
|
|
510
|
+
.command("publish")
|
|
511
|
+
.description(
|
|
512
|
+
"Validate and submit the plugin in the current directory to the Vellum marketplace catalog",
|
|
513
|
+
)
|
|
514
|
+
.option(
|
|
515
|
+
"--print",
|
|
516
|
+
"Print the entry JSON without submitting to the platform",
|
|
517
|
+
)
|
|
518
|
+
.option(
|
|
519
|
+
"--path <dir>",
|
|
520
|
+
"Validate a plugin at the given path instead of CWD",
|
|
521
|
+
)
|
|
522
|
+
.option("--force", "Skip the confirmation prompt")
|
|
523
|
+
.option("--json", "Emit machine-readable JSON instead of human output")
|
|
524
|
+
.option(
|
|
525
|
+
"--category <cat>",
|
|
526
|
+
"Set the category, skipping the interactive prompt",
|
|
527
|
+
)
|
|
528
|
+
.addHelpText(
|
|
529
|
+
"after",
|
|
530
|
+
`
|
|
531
|
+
|
|
532
|
+
Validates the plugin in the current directory (or --path), resolves the
|
|
533
|
+
git commit SHA and GitHub remote, and submits the entry to the Vellum
|
|
534
|
+
platform API. The platform creates a pull request against
|
|
535
|
+
vellum-ai/vellum-assistant adding the plugin to the marketplace catalog.
|
|
536
|
+
|
|
537
|
+
Requires a connected Vellum platform account (run \`assistant platform connect\`).
|
|
538
|
+
Use --print to validate and print the entry without submitting.
|
|
539
|
+
|
|
540
|
+
Examples:
|
|
541
|
+
$ assistant plugins publish
|
|
542
|
+
$ assistant plugins publish --print
|
|
543
|
+
$ assistant plugins publish --path ./my-plugin --category productivity
|
|
544
|
+
$ assistant plugins publish --json`,
|
|
545
|
+
)
|
|
546
|
+
.action(
|
|
547
|
+
async (opts: {
|
|
548
|
+
print?: boolean;
|
|
549
|
+
path?: string;
|
|
550
|
+
force?: boolean;
|
|
551
|
+
json?: boolean;
|
|
552
|
+
category?: string;
|
|
553
|
+
}) => {
|
|
554
|
+
const ok = await runPublish(opts, { confirmPrompt });
|
|
555
|
+
if (!ok) process.exitCode = 1;
|
|
556
|
+
},
|
|
557
|
+
);
|
|
558
|
+
|
|
454
559
|
plugins
|
|
455
560
|
.command("uninstall <name>")
|
|
456
561
|
.description("Remove a plugin from <workspaceDir>/plugins/<name>/")
|
|
@@ -480,7 +585,6 @@ Examples:
|
|
|
480
585
|
console.log(
|
|
481
586
|
`Uninstalled plugin "${result.name}" from ${result.target}`,
|
|
482
587
|
);
|
|
483
|
-
console.log("Restart the assistant to drop the plugin.");
|
|
484
588
|
} catch (err) {
|
|
485
589
|
if (err instanceof InvalidPluginNameError) {
|
|
486
590
|
console.error(err.message);
|
|
@@ -501,15 +605,13 @@ Examples:
|
|
|
501
605
|
plugins
|
|
502
606
|
.command("disable <name>")
|
|
503
607
|
.description(
|
|
504
|
-
"Disable a plugin by creating a .disabled sentinel file. Works for both user-installed and default plugins.
|
|
608
|
+
"Disable a plugin by creating a .disabled sentinel file. Works for both user-installed and default plugins. Takes effect immediately in a running assistant.",
|
|
505
609
|
)
|
|
506
610
|
.action((name: string) => {
|
|
507
611
|
try {
|
|
508
612
|
const result = disablePlugin(name);
|
|
509
613
|
log.info({ name: result.name }, "plugin disabled");
|
|
510
|
-
console.log(
|
|
511
|
-
`Disabled plugin "${result.name}". Restart the assistant for the change to take effect.`,
|
|
512
|
-
);
|
|
614
|
+
console.log(`Disabled plugin "${result.name}".`);
|
|
513
615
|
} catch (err) {
|
|
514
616
|
if (
|
|
515
617
|
err instanceof PluginAlreadyInStateException ||
|
|
@@ -529,15 +631,13 @@ Examples:
|
|
|
529
631
|
plugins
|
|
530
632
|
.command("enable <name>")
|
|
531
633
|
.description(
|
|
532
|
-
"Re-enable a disabled plugin by removing the .disabled sentinel file.
|
|
634
|
+
"Re-enable a disabled plugin by removing the .disabled sentinel file. Takes effect immediately.",
|
|
533
635
|
)
|
|
534
636
|
.action((name: string) => {
|
|
535
637
|
try {
|
|
536
638
|
const result = enablePlugin(name);
|
|
537
639
|
log.info({ name: result.name }, "plugin enabled");
|
|
538
|
-
console.log(
|
|
539
|
-
`Enabled plugin "${result.name}". Restart the assistant for the change to take effect.`,
|
|
540
|
-
);
|
|
640
|
+
console.log(`Enabled plugin "${result.name}".`);
|
|
541
641
|
} catch (err) {
|
|
542
642
|
if (
|
|
543
643
|
err instanceof PluginAlreadyInStateException ||
|
|
@@ -757,6 +857,18 @@ function formatTimestamp(iso: string | null): string {
|
|
|
757
857
|
return new Date(ms).toISOString().slice(0, 19);
|
|
758
858
|
}
|
|
759
859
|
|
|
860
|
+
/**
|
|
861
|
+
* Build a human-readable status string for a plugin in the `--all` listing.
|
|
862
|
+
* Combines disabled state with any structural issues.
|
|
863
|
+
*/
|
|
864
|
+
function formatAllPluginStatus(p: AllPluginInfo): string {
|
|
865
|
+
const parts: string[] = [];
|
|
866
|
+
if (p.disabled) parts.push("disabled");
|
|
867
|
+
if (p.issues.length > 0) parts.push(p.issues.join("; "));
|
|
868
|
+
if (parts.length === 0) parts.push("enabled");
|
|
869
|
+
return parts.join(", ");
|
|
870
|
+
}
|
|
871
|
+
|
|
760
872
|
/** Human-readable status line for an inspection result. The from/to revisions
|
|
761
873
|
* now live in the installed/remote blocks, so the status itself is just words. */
|
|
762
874
|
function statusLine(status: PluginInspection["status"]): string {
|
|
@@ -436,6 +436,108 @@ describe("installPlugin — marketplace resolution", () => {
|
|
|
436
436
|
expect(meta.contentHash).toMatch(/^v2:[0-9a-f]{64}$/);
|
|
437
437
|
});
|
|
438
438
|
|
|
439
|
+
test("installs a plugin rooted at a sub-path, copying only that subtree", async () => {
|
|
440
|
+
// GIVEN a marketplace entry whose source pins a directory *within* a repo
|
|
441
|
+
// (a monorepo that ships several plugins) rather than the repo root.
|
|
442
|
+
const NESTED_SHA = "0f".repeat(20);
|
|
443
|
+
const NESTED_MANIFEST = {
|
|
444
|
+
name: "vellum-assistant",
|
|
445
|
+
plugins: [
|
|
446
|
+
{
|
|
447
|
+
name: "nested-plugin",
|
|
448
|
+
source: {
|
|
449
|
+
source: "github",
|
|
450
|
+
repo: "example-org/monorepo",
|
|
451
|
+
path: "packages/my-plugin",
|
|
452
|
+
ref: NESTED_SHA,
|
|
453
|
+
},
|
|
454
|
+
description: "A plugin that lives in a monorepo sub-directory.",
|
|
455
|
+
},
|
|
456
|
+
],
|
|
457
|
+
};
|
|
458
|
+
const fetch = makeContentsFetch({ tree: {}, manifest: NESTED_MANIFEST });
|
|
459
|
+
// The clone carries files both at the repo root and under the pinned
|
|
460
|
+
// sub-path; only the sub-path subtree should be materialized.
|
|
461
|
+
const runGit = fakeGitRunner({
|
|
462
|
+
tree: {
|
|
463
|
+
"package.json": '{"name":"monorepo-root"}',
|
|
464
|
+
"README.md": "# monorepo root",
|
|
465
|
+
"packages/my-plugin/package.json": '{"name":"nested-plugin"}',
|
|
466
|
+
"packages/my-plugin/README.md": "# nested plugin",
|
|
467
|
+
"packages/my-plugin/hooks/init.ts": "export default async () => {};",
|
|
468
|
+
"packages/other-plugin/package.json": '{"name":"other"}',
|
|
469
|
+
},
|
|
470
|
+
commit: NESTED_SHA,
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
// WHEN we install by name
|
|
474
|
+
const result = await installPlugin(
|
|
475
|
+
{ name: "nested-plugin", ref: "main" },
|
|
476
|
+
{ fetch, runGit, workspacePluginsDir: pluginsDir },
|
|
477
|
+
);
|
|
478
|
+
|
|
479
|
+
// THEN only the sub-path subtree lands, rooted at <pluginsDir>/nested-plugin
|
|
480
|
+
const target = join(pluginsDir, "nested-plugin");
|
|
481
|
+
expect(result.target).toBe(target);
|
|
482
|
+
expect(readFileSync(join(target, "package.json"), "utf-8")).toBe(
|
|
483
|
+
'{"name":"nested-plugin"}',
|
|
484
|
+
);
|
|
485
|
+
expect(existsSync(join(target, "README.md"))).toBe(true);
|
|
486
|
+
expect(existsSync(join(target, "hooks", "init.ts"))).toBe(true);
|
|
487
|
+
// AND the repo-root and sibling-package files are NOT copied in — the
|
|
488
|
+
// install is scoped to the pinned directory.
|
|
489
|
+
expect(result.fileCount).toBe(3);
|
|
490
|
+
expect(readFileSync(join(target, "package.json"), "utf-8")).not.toContain(
|
|
491
|
+
"monorepo-root",
|
|
492
|
+
);
|
|
493
|
+
expect(existsSync(join(target, "packages"))).toBe(false);
|
|
494
|
+
|
|
495
|
+
// AND provenance records the sub-path so an upgrade/diff re-resolves the
|
|
496
|
+
// same directory rather than the repo root.
|
|
497
|
+
const meta = readInstallMeta(target);
|
|
498
|
+
expect(meta?.source.owner).toBe("example-org");
|
|
499
|
+
expect(meta?.source.repo).toBe("monorepo");
|
|
500
|
+
expect(meta?.source.path).toBe("packages/my-plugin");
|
|
501
|
+
expect(meta?.source.ref).toBe(NESTED_SHA);
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
test("a sub-path that does not exist in the clone surfaces a clean not-found", async () => {
|
|
505
|
+
// GIVEN an entry pinning a directory the cloned ref doesn't contain
|
|
506
|
+
const MISSING_SHA = "1a".repeat(20);
|
|
507
|
+
const MISSING_PATH_MANIFEST = {
|
|
508
|
+
name: "vellum-assistant",
|
|
509
|
+
plugins: [
|
|
510
|
+
{
|
|
511
|
+
name: "nested-plugin",
|
|
512
|
+
source: {
|
|
513
|
+
source: "github",
|
|
514
|
+
repo: "example-org/monorepo",
|
|
515
|
+
path: "packages/does-not-exist",
|
|
516
|
+
ref: MISSING_SHA,
|
|
517
|
+
},
|
|
518
|
+
},
|
|
519
|
+
],
|
|
520
|
+
};
|
|
521
|
+
const fetch = makeContentsFetch({
|
|
522
|
+
tree: {},
|
|
523
|
+
manifest: MISSING_PATH_MANIFEST,
|
|
524
|
+
});
|
|
525
|
+
const runGit = fakeGitRunner({
|
|
526
|
+
tree: { "package.json": '{"name":"monorepo-root"}' },
|
|
527
|
+
commit: MISSING_SHA,
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
// WHEN we install
|
|
531
|
+
// THEN the absent sub-path yields a hard not-found and nothing is staged
|
|
532
|
+
await expect(
|
|
533
|
+
installPlugin(
|
|
534
|
+
{ name: "nested-plugin", ref: "main" },
|
|
535
|
+
{ fetch, runGit, workspacePluginsDir: pluginsDir },
|
|
536
|
+
),
|
|
537
|
+
).rejects.toBeInstanceOf(PluginNotFoundError);
|
|
538
|
+
expect(readdirSync(pluginsDir)).toEqual([]);
|
|
539
|
+
});
|
|
540
|
+
|
|
439
541
|
test("refuses to install when the checked-out commit differs from the pinned SHA", async () => {
|
|
440
542
|
// GIVEN a clone whose resolved HEAD does not match the manifest's pinned
|
|
441
543
|
// commit SHA — i.e. the upstream object served something unexpected
|
|
@@ -17,7 +17,7 @@ import { tmpdir } from "node:os";
|
|
|
17
17
|
import { join } from "node:path";
|
|
18
18
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
19
19
|
|
|
20
|
-
import { listInstalledPlugins } from "../list-installed-plugins.js";
|
|
20
|
+
import { listAllPlugins, listInstalledPlugins } from "../list-installed-plugins.js";
|
|
21
21
|
|
|
22
22
|
let pluginsDir: string;
|
|
23
23
|
|
|
@@ -152,3 +152,162 @@ describe("listInstalledPlugins", () => {
|
|
|
152
152
|
expect(result.map((p) => p.name)).toEqual(["valid"]);
|
|
153
153
|
});
|
|
154
154
|
});
|
|
155
|
+
|
|
156
|
+
describe("listAllPlugins", () => {
|
|
157
|
+
test("includes default plugins with source=default", () => {
|
|
158
|
+
const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
|
|
159
|
+
const defaults = result.filter((p) => p.source === "default");
|
|
160
|
+
// All 14 default plugins should be present.
|
|
161
|
+
expect(defaults.length).toBe(14);
|
|
162
|
+
// Names should all start with "default-".
|
|
163
|
+
expect(defaults.every((p) => p.name.startsWith("default-"))).toBe(true);
|
|
164
|
+
// None should be disabled by default in a fresh temp dir.
|
|
165
|
+
expect(defaults.every((p) => !p.disabled)).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test("includes user plugins with source=user", () => {
|
|
169
|
+
mkdirSync(join(pluginsDir, "my-plugin"));
|
|
170
|
+
writeFileSync(
|
|
171
|
+
join(pluginsDir, "my-plugin", "package.json"),
|
|
172
|
+
JSON.stringify({ name: "my-plugin", version: "1.0.0" }),
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
|
|
176
|
+
const user = result.filter((p) => p.source === "user");
|
|
177
|
+
expect(user).toHaveLength(1);
|
|
178
|
+
expect(user[0]!.name).toBe("my-plugin");
|
|
179
|
+
expect(user[0]!.disabled).toBe(false);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test("user plugins appear before default plugins", () => {
|
|
183
|
+
mkdirSync(join(pluginsDir, "zzz-user"));
|
|
184
|
+
writeFileSync(
|
|
185
|
+
join(pluginsDir, "zzz-user", "package.json"),
|
|
186
|
+
JSON.stringify({ name: "zzz-user", version: "1.0.0" }),
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
|
|
190
|
+
const firstDefaultIdx = result.findIndex((p) => p.source === "default");
|
|
191
|
+
const lastUserIdx = result
|
|
192
|
+
.map((p, i) => (p.source === "user" ? i : -1))
|
|
193
|
+
.filter((i) => i >= 0)
|
|
194
|
+
.pop();
|
|
195
|
+
|
|
196
|
+
expect(lastUserIdx).toBeDefined();
|
|
197
|
+
expect(firstDefaultIdx).toBeGreaterThan(lastUserIdx!);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("detects disabled state for user plugins", () => {
|
|
201
|
+
mkdirSync(join(pluginsDir, "my-plugin"));
|
|
202
|
+
writeFileSync(
|
|
203
|
+
join(pluginsDir, "my-plugin", "package.json"),
|
|
204
|
+
JSON.stringify({ name: "my-plugin", version: "1.0.0" }),
|
|
205
|
+
);
|
|
206
|
+
writeFileSync(join(pluginsDir, "my-plugin", ".disabled"), "");
|
|
207
|
+
|
|
208
|
+
const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
|
|
209
|
+
const entry = result.find((p) => p.name === "my-plugin");
|
|
210
|
+
expect(entry).toBeDefined();
|
|
211
|
+
expect(entry!.disabled).toBe(true);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test("detects disabled state for default plugins via stub directory", () => {
|
|
215
|
+
mkdirSync(join(pluginsDir, "default-compaction"), { recursive: true });
|
|
216
|
+
writeFileSync(join(pluginsDir, "default-compaction", ".disabled"), "");
|
|
217
|
+
|
|
218
|
+
const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
|
|
219
|
+
const compaction = result.find((p) => p.name === "default-compaction");
|
|
220
|
+
expect(compaction).toBeDefined();
|
|
221
|
+
expect(compaction!.disabled).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test("default stub directory is excluded from user listing", () => {
|
|
225
|
+
mkdirSync(join(pluginsDir, "default-compaction"), { recursive: true });
|
|
226
|
+
writeFileSync(join(pluginsDir, "default-compaction", ".disabled"), "");
|
|
227
|
+
|
|
228
|
+
const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
|
|
229
|
+
// Should appear exactly once, as a default entry (not a user entry).
|
|
230
|
+
const compactionEntries = result.filter((p) => p.name === "default-compaction");
|
|
231
|
+
expect(compactionEntries).toHaveLength(1);
|
|
232
|
+
expect(compactionEntries[0]!.source).toBe("default");
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test("sort order: enabled user, disabled user, enabled default, disabled default", () => {
|
|
236
|
+
// User plugins
|
|
237
|
+
mkdirSync(join(pluginsDir, "aaa-enabled"));
|
|
238
|
+
writeFileSync(
|
|
239
|
+
join(pluginsDir, "aaa-enabled", "package.json"),
|
|
240
|
+
JSON.stringify({ name: "aaa-enabled", version: "1.0.0" }),
|
|
241
|
+
);
|
|
242
|
+
mkdirSync(join(pluginsDir, "bbb-disabled"));
|
|
243
|
+
writeFileSync(
|
|
244
|
+
join(pluginsDir, "bbb-disabled", "package.json"),
|
|
245
|
+
JSON.stringify({ name: "bbb-disabled", version: "1.0.0" }),
|
|
246
|
+
);
|
|
247
|
+
writeFileSync(join(pluginsDir, "bbb-disabled", ".disabled"), "");
|
|
248
|
+
|
|
249
|
+
// Disable one default plugin
|
|
250
|
+
mkdirSync(join(pluginsDir, "default-compaction"), { recursive: true });
|
|
251
|
+
writeFileSync(join(pluginsDir, "default-compaction", ".disabled"), "");
|
|
252
|
+
|
|
253
|
+
const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
|
|
254
|
+
|
|
255
|
+
const enabledUserIdx = result.findIndex(
|
|
256
|
+
(p) => p.source === "user" && !p.disabled,
|
|
257
|
+
);
|
|
258
|
+
const disabledUserIdx = result.findIndex(
|
|
259
|
+
(p) => p.source === "user" && p.disabled,
|
|
260
|
+
);
|
|
261
|
+
const enabledDefaultIdx = result.findIndex(
|
|
262
|
+
(p) => p.source === "default" && !p.disabled,
|
|
263
|
+
);
|
|
264
|
+
const disabledDefaultIdx = result.findIndex(
|
|
265
|
+
(p) => p.source === "default" && p.disabled,
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
// All groups present.
|
|
269
|
+
expect(enabledUserIdx).toBeGreaterThanOrEqual(0);
|
|
270
|
+
expect(disabledUserIdx).toBeGreaterThan(enabledUserIdx);
|
|
271
|
+
expect(enabledDefaultIdx).toBeGreaterThan(disabledUserIdx);
|
|
272
|
+
expect(disabledDefaultIdx).toBeGreaterThan(enabledDefaultIdx);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
test("user plugins sorted by install date within each group", () => {
|
|
276
|
+
// Create two user plugins with different install dates.
|
|
277
|
+
// First plugin (older).
|
|
278
|
+
mkdirSync(join(pluginsDir, "older-plugin"));
|
|
279
|
+
writeFileSync(
|
|
280
|
+
join(pluginsDir, "older-plugin", "package.json"),
|
|
281
|
+
JSON.stringify({ name: "older-plugin", version: "1.0.0" }),
|
|
282
|
+
);
|
|
283
|
+
writeFileSync(
|
|
284
|
+
join(pluginsDir, "older-plugin", "install-meta.json"),
|
|
285
|
+
JSON.stringify({ installedAt: "2025-01-01T00:00:00.000Z" }),
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
// Second plugin (newer).
|
|
289
|
+
mkdirSync(join(pluginsDir, "newer-plugin"));
|
|
290
|
+
writeFileSync(
|
|
291
|
+
join(pluginsDir, "newer-plugin", "package.json"),
|
|
292
|
+
JSON.stringify({ name: "newer-plugin", version: "1.0.0" }),
|
|
293
|
+
);
|
|
294
|
+
writeFileSync(
|
|
295
|
+
join(pluginsDir, "newer-plugin", "install-meta.json"),
|
|
296
|
+
JSON.stringify({ installedAt: "2025-06-01T00:00:00.000Z" }),
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
|
|
300
|
+
const userPlugins = result.filter((p) => p.source === "user");
|
|
301
|
+
expect(userPlugins).toHaveLength(2);
|
|
302
|
+
// Older plugin should come first (install date ascending).
|
|
303
|
+
expect(userPlugins[0]!.name).toBe("older-plugin");
|
|
304
|
+
expect(userPlugins[1]!.name).toBe("newer-plugin");
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
test("default plugins have version from their manifest", () => {
|
|
308
|
+
const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
|
|
309
|
+
const compaction = result.find((p) => p.name === "default-compaction");
|
|
310
|
+
expect(compaction).toBeDefined();
|
|
311
|
+
expect(compaction!.packageJson?.version).toBeTruthy();
|
|
312
|
+
});
|
|
313
|
+
});
|