@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.2
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 +0 -20
- package/docs/workspace-tools.md +33 -42
- package/eslint-rules/cli-no-daemon-internals.js +0 -6
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
- package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
- package/node_modules/@vellumai/service-contracts/package.json +0 -1
- package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
- package/openapi.yaml +0 -155
- package/package.json +1 -4
- package/scripts/test.sh +15 -36
- package/src/__tests__/actor-token-service.test.ts +14 -36
- package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
- package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
- package/src/__tests__/annotate-risk-options.test.ts +0 -2
- package/src/__tests__/approval-cascade.test.ts +0 -2
- package/src/__tests__/assistant-attachments.test.ts +0 -42
- package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
- package/src/__tests__/btw-routes.test.ts +0 -2
- package/src/__tests__/build-persisted-content.test.ts +0 -2
- package/src/__tests__/call-controller.test.ts +0 -19
- package/src/__tests__/channel-guardian.test.ts +58 -94
- package/src/__tests__/channel-reply-delivery.test.ts +0 -2
- package/src/__tests__/compaction-events.test.ts +0 -2
- package/src/__tests__/compaction.benchmark.test.ts +0 -2
- package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
- package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
- package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
- package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
- package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
- package/src/__tests__/config-loader-backfill.test.ts +10 -123
- package/src/__tests__/config-schema.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
- package/src/__tests__/contacts-relay-reads.test.ts +15 -13
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop.test.ts +0 -134
- package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
- package/src/__tests__/conversation-history-web-search.test.ts +0 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
- package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
- package/src/__tests__/conversation-pairing.test.ts +0 -2
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
- package/src/__tests__/conversation-process-callsite.test.ts +0 -2
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
- package/src/__tests__/conversation-queue.test.ts +0 -91
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
- package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
- package/src/__tests__/conversation-slash-queue.test.ts +0 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
- package/src/__tests__/conversation-speed-override.test.ts +0 -2
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
- package/src/__tests__/conversation-title-service.test.ts +0 -2
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
- package/src/__tests__/conversation-usage.test.ts +0 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/db-migration-rollback.test.ts +171 -205
- package/src/__tests__/db-test-helpers.ts +4 -5
- package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
- package/src/__tests__/disk-pressure-guard.test.ts +0 -41
- package/src/__tests__/dm-persistence.test.ts +0 -2
- package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
- package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
- package/src/__tests__/exploration-drift-hook.test.ts +2 -3
- package/src/__tests__/filing-service.test.ts +0 -2
- package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
- package/src/__tests__/guardian-dispatch.test.ts +1 -95
- package/src/__tests__/guardian-outbound-http.test.ts +0 -13
- package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
- package/src/__tests__/heartbeat-service.test.ts +0 -2
- package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
- package/src/__tests__/host-app-control-routes.test.ts +30 -24
- package/src/__tests__/host-bash-routes.test.ts +41 -31
- package/src/__tests__/host-browser-routes.test.ts +32 -26
- package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
- package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
- package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
- package/src/__tests__/http-user-message-parity.test.ts +8 -290
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
- package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
- package/src/__tests__/invite-redemption-service.test.ts +0 -198
- package/src/__tests__/llm-context-normalization.test.ts +0 -105
- package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
- package/src/__tests__/llm-usage-store.test.ts +0 -25
- package/src/__tests__/mcp-health-check.test.ts +1 -2
- package/src/__tests__/media-stream-server-integration.test.ts +0 -127
- package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
- package/src/__tests__/messaging-send-tool.test.ts +0 -2
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +5 -146
- package/src/__tests__/native-web-search.test.ts +0 -2
- package/src/__tests__/non-member-access-request.test.ts +17 -189
- package/src/__tests__/notification-broadcaster.test.ts +0 -4
- package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
- package/src/__tests__/notification-deep-link.test.ts +0 -6
- package/src/__tests__/notification-guardian-path.test.ts +0 -19
- package/src/__tests__/openai-provider.test.ts +12 -22
- package/src/__tests__/openai-responses-provider.test.ts +2 -12
- package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
- package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
- package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
- package/src/__tests__/plugin-bootstrap.test.ts +73 -3
- package/src/__tests__/plugin-route-contribution.test.ts +17 -4
- package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
- package/src/__tests__/plugin-types.test.ts +2 -0
- package/src/__tests__/process-message-background-slack.test.ts +0 -2
- package/src/__tests__/process-message-display-content.test.ts +0 -2
- package/src/__tests__/provider-error-scenarios.test.ts +4 -5
- package/src/__tests__/provider-usage-tracking.test.ts +0 -39
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
- package/src/__tests__/registry.test.ts +1 -4
- package/src/__tests__/relay-server.test.ts +25 -694
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
- package/src/__tests__/secret-ingress-http.test.ts +0 -14
- package/src/__tests__/send-endpoint-busy.test.ts +8 -30
- package/src/__tests__/skills.test.ts +0 -44
- package/src/__tests__/slack-inbound-verification.test.ts +2 -47
- package/src/__tests__/stt-hints.test.ts +13 -44
- package/src/__tests__/subagent-detail.test.ts +0 -27
- package/src/__tests__/subagent-disposal.test.ts +0 -65
- package/src/__tests__/subagent-notify-parent.test.ts +0 -2
- package/src/__tests__/subagent-role-registry.test.ts +2 -7
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
- package/src/__tests__/subagent-tools.test.ts +0 -2
- package/src/__tests__/suggestion-routes.test.ts +0 -2
- package/src/__tests__/title-generate-hook.test.ts +0 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
- package/src/__tests__/tool-executor.test.ts +11 -16
- package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
- package/src/__tests__/tool-start-timestamp.test.ts +0 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
- package/src/__tests__/twilio-routes.test.ts +0 -96
- package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +0 -33
- package/src/__tests__/web-search-backend-failure.test.ts +0 -2
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
- package/src/__tests__/workspace-tool-loader.test.ts +2 -195
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
- package/src/agent/loop.ts +0 -56
- package/src/api/index.ts +1 -19
- package/src/api/responses/llm-request-log-entry.ts +0 -29
- package/src/api/responses/subagent-detail.ts +0 -17
- package/src/api/surfaces.ts +3 -39
- package/src/approvals/guardian-request-resolvers.ts +11 -1
- package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
- package/src/calls/call-domain.ts +3 -3
- package/src/calls/guardian-dispatch.ts +8 -10
- package/src/calls/inbound-trust-reader.ts +1 -17
- package/src/calls/media-stream-server.ts +0 -21
- package/src/calls/relay-server.ts +50 -167
- package/src/calls/relay-setup-router.ts +7 -37
- package/src/calls/relay-verification.ts +4 -4
- package/src/calls/stt-hints.ts +12 -9
- package/src/calls/twilio-routes.ts +4 -14
- package/src/channels/types.ts +20 -10
- package/src/cli/commands/__tests__/cache.test.ts +1 -8
- package/src/cli/commands/cache.ts +181 -194
- package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
- package/src/cli/commands/db/status.ts +1 -37
- package/src/cli/commands/mcp.ts +218 -252
- package/src/cli/commands/memory/index.ts +0 -2
- package/src/cli/commands/plugins.ts +3 -75
- package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
- package/src/cli/lib/list-installed-plugins.ts +1 -179
- package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
- package/src/config/bundled-skills/subagent/SKILL.md +1 -1
- package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
- package/src/config/feature-flag-registry.json +13 -5
- package/src/config/loader.ts +5 -38
- package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
- package/src/config/schemas/memory-lifecycle.ts +0 -12
- package/src/config/schemas/memory-v3.ts +0 -7
- package/src/config/schemas/memory.ts +0 -4
- package/src/config/schemas/timeouts.ts +0 -8
- package/src/config/seed-inference-profiles.ts +11 -21
- package/src/config/skills.ts +5 -27
- package/src/config/sync-gated-profiles.ts +13 -12
- package/src/contacts/contacts-write.ts +0 -3
- package/src/daemon/assistant-attachments.ts +4 -27
- package/src/daemon/conversation-agent-loop.ts +0 -28
- package/src/daemon/conversation-process.ts +16 -35
- package/src/daemon/conversation-surfaces.ts +38 -111
- package/src/daemon/conversation-tool-setup.ts +16 -50
- package/src/daemon/conversation.ts +1 -13
- package/src/daemon/disk-pressure-guard.ts +2 -12
- package/src/daemon/event-loop-watchdog.ts +1 -28
- package/src/daemon/external-plugins-bootstrap.ts +34 -4
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
- package/src/daemon/handlers/config-a2a.ts +14 -6
- package/src/daemon/handlers/config-channels.ts +22 -78
- package/src/daemon/handlers/conversations.ts +0 -77
- package/src/daemon/lifecycle.ts +0 -4
- package/src/daemon/mcp-reload-service.ts +0 -10
- package/src/daemon/memory-v2-startup.test.ts +0 -72
- package/src/daemon/memory-v2-startup.ts +19 -87
- package/src/daemon/message-types/conversations.ts +0 -2
- package/src/daemon/message-types/surfaces.ts +12 -12
- package/src/daemon/server.ts +4 -0
- package/src/daemon/shutdown-handlers.ts +0 -20
- package/src/daemon/tool-setup-types.ts +0 -9
- package/src/daemon/workspace-tools-watcher.ts +328 -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 +0 -1
- package/src/mcp/client.ts +1 -15
- package/src/mcp/mcp-auth-orchestrator.ts +1 -6
- package/src/mcp/mcp-oauth-provider.ts +8 -19
- package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
- package/src/memory/conversation-crud.ts +0 -38
- package/src/memory/db-connection.ts +3 -22
- package/src/memory/db-init.ts +502 -36
- package/src/memory/db-singleton.ts +4 -6
- package/src/memory/jobs-worker.ts +0 -58
- package/src/memory/llm-request-log-store.ts +1 -26
- package/src/memory/llm-usage-store.ts +20 -48
- package/src/memory/memory-retrospective-job.ts +8 -9
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
- package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
- package/src/memory/migrations/registry.ts +573 -0
- package/src/memory/migrations/run-migrations.ts +6 -90
- package/src/memory/migrations/validate-migration-state.ts +66 -101
- package/src/memory/schema/conversations.ts +0 -9
- package/src/memory/schema/infrastructure.ts +0 -20
- package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
- package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
- package/src/memory/v2/cli-command-store.ts +38 -75
- package/src/memory/v2/prompts/consolidation.ts +82 -13
- package/src/memory/v2/prompts/router.ts +93 -21
- package/src/memory/v2/skill-store.ts +31 -68
- package/src/notifications/__tests__/broadcaster.test.ts +8 -16
- package/src/notifications/__tests__/decision-engine.test.ts +9 -78
- package/src/notifications/broadcaster.ts +1 -8
- package/src/notifications/decision-engine.ts +7 -15
- package/src/notifications/destination-resolver.ts +24 -68
- package/src/notifications/emit-signal.ts +14 -39
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +4 -7
- package/src/plugin-api/index.ts +6 -6
- package/src/plugin-api/types.ts +5 -3
- package/src/plugin-api/vision-support.test.ts +4 -28
- package/src/plugin-api/vision-support.ts +31 -66
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
- package/src/plugins/defaults/advisor/consult.ts +6 -110
- package/src/plugins/defaults/advisor/steering.ts +2 -14
- package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
- package/src/plugins/mtime-cache.ts +291 -76
- package/src/plugins/pipeline.ts +13 -111
- package/src/plugins/types.ts +2 -0
- package/src/providers/anthropic/client.ts +0 -5
- package/src/providers/call-site-routing.ts +0 -4
- package/src/providers/model-catalog.ts +0 -16
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/chat-completions-provider.ts +83 -37
- package/src/providers/openai/responses-provider.ts +46 -50
- package/src/providers/openrouter/client.ts +0 -5
- package/src/providers/provider-send-message.ts +0 -4
- package/src/providers/ratelimit.ts +0 -4
- package/src/providers/retry.ts +0 -4
- package/src/providers/types.ts +0 -9
- package/src/providers/usage-tracking.ts +0 -4
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
- package/src/runtime/access-request-helper.ts +39 -19
- package/src/runtime/actor-trust-resolver.ts +2 -2
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/assistant-stream-state.ts +2 -9
- package/src/runtime/auth/require-bound-guardian.ts +11 -21
- package/src/runtime/channel-verification-service.ts +31 -56
- package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
- package/src/runtime/guardian-vellum-migration.ts +7 -66
- package/src/runtime/invite-redemption-service.ts +187 -198
- package/src/runtime/local-actor-identity.ts +11 -76
- package/src/runtime/pending-interactions.ts +1 -11
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
- package/src/runtime/routes/channel-verification-routes.ts +3 -3
- package/src/runtime/routes/contact-routes.ts +32 -8
- package/src/runtime/routes/conversation-cli-routes.ts +5 -4
- package/src/runtime/routes/conversation-list-routes.ts +7 -4
- package/src/runtime/routes/conversation-query-routes.ts +0 -72
- package/src/runtime/routes/conversation-routes.ts +85 -84
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/global-search-routes.ts +1 -3
- package/src/runtime/routes/guardian-action-routes.ts +5 -4
- package/src/runtime/routes/host-app-control-routes.ts +4 -5
- package/src/runtime/routes/host-bash-routes.ts +4 -5
- package/src/runtime/routes/host-browser-routes.ts +11 -9
- package/src/runtime/routes/host-cu-routes.ts +4 -5
- package/src/runtime/routes/host-file-routes.ts +4 -5
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +1 -1
- package/src/runtime/routes/identity-routes.ts +2 -3
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
- package/src/runtime/routes/index.ts +0 -2
- package/src/runtime/routes/llm-context-normalization.ts +0 -83
- package/src/runtime/routes/mcp-auth-routes.ts +19 -171
- package/src/runtime/routes/migration-rollback-routes.ts +3 -4
- package/src/runtime/routes/migration-routes.ts +1 -4
- package/src/runtime/routes/subagents-routes.ts +0 -5
- package/src/runtime/routes/surface-action-routes.ts +56 -42
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
- package/src/runtime/services/conversation-serializer.ts +9 -7
- package/src/runtime/tool-grant-request-helper.ts +3 -3
- package/src/runtime/trust-verdict-consumer.ts +9 -85
- package/src/runtime/verification-outbound-actions.ts +18 -18
- package/src/signals/user-message.ts +0 -16
- package/src/subagent/manager.ts +0 -9
- package/src/subagent/types.ts +3 -3
- package/src/telemetry/types.ts +1 -34
- package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
- package/src/telemetry/usage-telemetry-reporter.ts +3 -87
- package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
- package/src/tools/ask-question/ask-question-tool.ts +0 -13
- package/src/tools/executor.ts +4 -4
- package/src/tools/registry.ts +0 -18
- package/src/tools/shared/filesystem/path-policy.ts +5 -12
- package/src/tools/tool-approval-handler.ts +1 -1
- package/src/tools/tool-defaults.ts +2 -9
- package/src/tools/tool-manifest.ts +0 -3
- package/src/tools/types.ts +2 -17
- package/src/tools/workspace-tools/loader.ts +244 -348
- package/src/util/errors.ts +1 -26
- package/src/util/platform.ts +0 -5
- package/src/workflows/library.test.ts +0 -140
- package/src/workflows/library.ts +28 -82
- package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
- package/src/workspace/migrations/registry.ts +0 -2
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
- package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
- package/src/__tests__/code-search-tool.test.ts +0 -585
- package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
- package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
- package/src/__tests__/plugin-pipeline.test.ts +0 -96
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
- package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
- package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
- package/src/agent/loop-exclusive-tool.test.ts +0 -150
- package/src/api/constants/sse-replay.ts +0 -41
- package/src/api/events/conversation-notice.ts +0 -26
- package/src/approvals/guardian-channel-delivery.ts +0 -30
- package/src/approvals/guardian-expiry-notifier.ts +0 -148
- package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
- package/src/cli/commands/memory/worker.ts +0 -175
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
- package/src/config/prune-seeded-callsite-defaults.ts +0 -110
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
- package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
- package/src/contacts/guardian-delivery-reader.ts +0 -223
- package/src/contacts/member-write-relay.ts +0 -189
- package/src/daemon/conversation-notices.ts +0 -60
- package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
- package/src/hooks/hook-loader.ts +0 -341
- package/src/mcp/mcp-header-store.ts +0 -134
- package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
- package/src/memory/__tests__/prompt-override.test.ts +0 -192
- package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
- package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
- package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
- package/src/memory/prompt-override.ts +0 -129
- package/src/memory/steps.ts +0 -573
- package/src/memory/watchdog-events-store.ts +0 -87
- package/src/memory/worker-control.ts +0 -118
- package/src/memory/worker-process.ts +0 -72
- package/src/notifications/__tests__/connected-channels.test.ts +0 -114
- package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
- package/src/onboarding/checkin-event.test.ts +0 -222
- package/src/onboarding/checkin-event.ts +0 -321
- package/src/onboarding/schedule-checkin.ts +0 -190
- package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
- package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
- package/src/plugins/defaults/advisor/context-pack.ts +0 -288
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
- package/src/plugins/surface-import.ts +0 -121
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
- package/src/providers/openai/api-error-normalization.ts +0 -270
- package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
- package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
- package/src/runtime/anchored-guardian.test.ts +0 -156
- package/src/runtime/anchored-guardian.ts +0 -135
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
- package/src/runtime/local-principal-trust.ts +0 -52
- package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
- package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
- package/src/tools/filesystem/search.ts +0 -543
- package/src/util/telemetry-db-path.ts +0 -24
- package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
|
@@ -436,108 +436,6 @@ 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
|
-
|
|
541
439
|
test("refuses to install when the checked-out commit differs from the pinned SHA", async () => {
|
|
542
440
|
// GIVEN a clone whose resolved HEAD does not match the manifest's pinned
|
|
543
441
|
// 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 {
|
|
20
|
+
import { listInstalledPlugins } from "../list-installed-plugins.js";
|
|
21
21
|
|
|
22
22
|
let pluginsDir: string;
|
|
23
23
|
|
|
@@ -152,162 +152,3 @@ 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 15 default plugins should be present.
|
|
161
|
-
expect(defaults.length).toBe(15);
|
|
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-advisor"), { recursive: true });
|
|
216
|
-
writeFileSync(join(pluginsDir, "default-advisor", ".disabled"), "");
|
|
217
|
-
|
|
218
|
-
const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
|
|
219
|
-
const advisor = result.find((p) => p.name === "default-advisor");
|
|
220
|
-
expect(advisor).toBeDefined();
|
|
221
|
-
expect(advisor!.disabled).toBe(true);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
test("default stub directory is excluded from user listing", () => {
|
|
225
|
-
mkdirSync(join(pluginsDir, "default-advisor"), { recursive: true });
|
|
226
|
-
writeFileSync(join(pluginsDir, "default-advisor", ".disabled"), "");
|
|
227
|
-
|
|
228
|
-
const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
|
|
229
|
-
// Should appear exactly once, as a default entry (not a user entry).
|
|
230
|
-
const advisorEntries = result.filter((p) => p.name === "default-advisor");
|
|
231
|
-
expect(advisorEntries).toHaveLength(1);
|
|
232
|
-
expect(advisorEntries[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-advisor"), { recursive: true });
|
|
251
|
-
writeFileSync(join(pluginsDir, "default-advisor", ".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 advisor = result.find((p) => p.name === "default-advisor");
|
|
310
|
-
expect(advisor).toBeDefined();
|
|
311
|
-
expect(advisor!.packageJson?.version).toBeTruthy();
|
|
312
|
-
});
|
|
313
|
-
});
|
|
@@ -13,25 +13,10 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
16
|
-
import {
|
|
16
|
+
import { join } from "node:path";
|
|
17
17
|
|
|
18
18
|
import { getWorkspacePluginsDir } from "../../util/platform.js";
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
* Directory containing first-party default plugin packages. Each subdirectory
|
|
22
|
-
* has a `package.json` with `name` (prefixed `default-`) and `version`.
|
|
23
|
-
* Read from the filesystem at call time to avoid pulling hook/tool
|
|
24
|
-
* implementations into the CLI process (which would create circular
|
|
25
|
-
* dependencies in test environments).
|
|
26
|
-
*/
|
|
27
|
-
const DEFAULT_PLUGINS_DIR = join(
|
|
28
|
-
dirname(new URL(import.meta.url).pathname),
|
|
29
|
-
"..",
|
|
30
|
-
"..",
|
|
31
|
-
"plugins",
|
|
32
|
-
"defaults",
|
|
33
|
-
);
|
|
34
|
-
|
|
35
20
|
/** Minimal manifest fields surfaced to the CLI. */
|
|
36
21
|
export interface PluginPackageMetadata {
|
|
37
22
|
readonly name?: string;
|
|
@@ -55,20 +40,6 @@ export interface InstalledPluginInfo {
|
|
|
55
40
|
readonly issues: readonly string[];
|
|
56
41
|
}
|
|
57
42
|
|
|
58
|
-
/** Where the plugin comes from. */
|
|
59
|
-
export type PluginSource = "user" | "default";
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Extended plugin entry that includes source (`user` vs `default`) and
|
|
63
|
-
* disabled status. Used by {@link listAllPlugins}.
|
|
64
|
-
*/
|
|
65
|
-
export interface AllPluginInfo extends InstalledPluginInfo {
|
|
66
|
-
/** Whether this is a user-installed or first-party default plugin. */
|
|
67
|
-
readonly source: PluginSource;
|
|
68
|
-
/** Whether the plugin is disabled via a `.disabled` sentinel file. */
|
|
69
|
-
readonly disabled: boolean;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
43
|
/** Options accepted by {@link listInstalledPlugins}. */
|
|
73
44
|
export interface ListInstalledPluginsOptions {
|
|
74
45
|
/** Override the workspace plugins directory. Falls back to {@link getWorkspacePluginsDir}. */
|
|
@@ -175,152 +146,3 @@ function readPluginEntry(
|
|
|
175
146
|
|
|
176
147
|
return { name, target, packageJson, issues };
|
|
177
148
|
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* List all plugins — both user-installed (from `<workspace>/plugins/`) and
|
|
181
|
-
* first-party defaults (from the source tree). Each entry is annotated with
|
|
182
|
-
* its `source` (`"user"` or `"default"`) and `disabled` status (whether a
|
|
183
|
-
* `.disabled` sentinel file exists in the plugin's workspace directory).
|
|
184
|
-
*
|
|
185
|
-
* For user plugins, the `.disabled` file lives in the plugin's own install
|
|
186
|
-
* directory. For default plugins, it lives in a stub directory at
|
|
187
|
-
* `<workspace>/plugins/<manifest-name>/` (created by `plugins disable`).
|
|
188
|
-
*
|
|
189
|
-
* Stub directories created by `plugins disable <default-name>` are excluded
|
|
190
|
-
* from the user listing so a disabled default plugin appears only once (as a
|
|
191
|
-
* default entry, not a duplicate user entry with "missing package.json").
|
|
192
|
-
*
|
|
193
|
-
* Sort order:
|
|
194
|
-
* 1. Enabled user plugins (by install date, oldest first — matches
|
|
195
|
-
* hook/tool resolution order)
|
|
196
|
-
* 2. Disabled user plugins (by install date)
|
|
197
|
-
* 3. Enabled default plugins (by repo array order — matches registration
|
|
198
|
-
* order which fixes hook-chain order)
|
|
199
|
-
* 4. Disabled default plugins (by repo array order)
|
|
200
|
-
*/
|
|
201
|
-
export function listAllPlugins(
|
|
202
|
-
opts: ListInstalledPluginsOptions = {},
|
|
203
|
-
): AllPluginInfo[] {
|
|
204
|
-
const pluginsDir = opts.workspacePluginsDir ?? getWorkspacePluginsDir();
|
|
205
|
-
|
|
206
|
-
// ── User plugins ───────────────────────────────────────────────────────
|
|
207
|
-
// Filter out default-plugin stub directories (created by `plugins disable
|
|
208
|
-
// default-<name>`) so they don't show up as duplicate user entries.
|
|
209
|
-
const defaultNames = new Set(
|
|
210
|
-
readDefaultPluginManifests().map((m) => m.name),
|
|
211
|
-
);
|
|
212
|
-
const userPlugins: AllPluginInfo[] = listInstalledPlugins(opts)
|
|
213
|
-
.filter((entry) => !defaultNames.has(entry.name))
|
|
214
|
-
.map((entry) => ({
|
|
215
|
-
...entry,
|
|
216
|
-
source: "user" as const,
|
|
217
|
-
disabled: existsSync(join(entry.target, ".disabled")),
|
|
218
|
-
}));
|
|
219
|
-
|
|
220
|
-
// ── Default plugins ────────────────────────────────────────────────────
|
|
221
|
-
// Default plugins live in the source tree at src/plugins/defaults/<name>/.
|
|
222
|
-
// Read each package.json from the filesystem to get name+version without
|
|
223
|
-
// importing hook/tool implementations (which would create circular
|
|
224
|
-
// dependencies in test environments). The .disabled sentinel lives in a
|
|
225
|
-
// stub directory at <workspace>/plugins/<manifest-name>/.
|
|
226
|
-
// readDefaultPluginManifests returns in repo array (registration) order.
|
|
227
|
-
const defaultPlugins: AllPluginInfo[] = readDefaultPluginManifests().map(
|
|
228
|
-
(manifest) => {
|
|
229
|
-
const target = join(pluginsDir, manifest.name);
|
|
230
|
-
const disabled = existsSync(join(target, ".disabled"));
|
|
231
|
-
return {
|
|
232
|
-
name: manifest.name,
|
|
233
|
-
target,
|
|
234
|
-
packageJson: {
|
|
235
|
-
name: manifest.name,
|
|
236
|
-
version: manifest.version,
|
|
237
|
-
},
|
|
238
|
-
issues: [],
|
|
239
|
-
source: "default" as const,
|
|
240
|
-
disabled,
|
|
241
|
-
};
|
|
242
|
-
},
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
// Sort: enabled user (install date), disabled user (install date),
|
|
246
|
-
// enabled default (repo order), disabled default (repo order).
|
|
247
|
-
const enabledUser = userPlugins.filter((p) => !p.disabled);
|
|
248
|
-
const disabledUser = userPlugins.filter((p) => p.disabled);
|
|
249
|
-
const enabledDefault = defaultPlugins.filter((p) => !p.disabled);
|
|
250
|
-
const disabledDefault = defaultPlugins.filter((p) => p.disabled);
|
|
251
|
-
|
|
252
|
-
enabledUser.sort((a, b) => getPluginInstallDate(a) - getPluginInstallDate(b));
|
|
253
|
-
disabledUser.sort(
|
|
254
|
-
(a, b) => getPluginInstallDate(a) - getPluginInstallDate(b),
|
|
255
|
-
);
|
|
256
|
-
// enabledDefault and disabledDefault keep repo array order (no sort).
|
|
257
|
-
|
|
258
|
-
return [...enabledUser, ...disabledUser, ...enabledDefault, ...disabledDefault];
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
interface DefaultPluginManifest {
|
|
262
|
-
readonly name: string;
|
|
263
|
-
readonly version?: string;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Read first-party default plugin manifests from the filesystem. Each
|
|
268
|
-
* subdirectory under {@link DEFAULT_PLUGINS_DIR} that has a `package.json`
|
|
269
|
-
* with a `name` field is included. This avoids importing `defaults/index.ts`
|
|
270
|
-
* (which would pull in hook/tool implementations and create circular
|
|
271
|
-
* dependencies in test environments).
|
|
272
|
-
*/
|
|
273
|
-
function readDefaultPluginManifests(): readonly DefaultPluginManifest[] {
|
|
274
|
-
if (!existsSync(DEFAULT_PLUGINS_DIR)) return [];
|
|
275
|
-
|
|
276
|
-
const entries = readdirSync(DEFAULT_PLUGINS_DIR, { withFileTypes: true })
|
|
277
|
-
.filter((e) => e.isDirectory())
|
|
278
|
-
.map((e) => e.name)
|
|
279
|
-
.sort();
|
|
280
|
-
|
|
281
|
-
const manifests: DefaultPluginManifest[] = [];
|
|
282
|
-
for (const name of entries) {
|
|
283
|
-
const pkgJsonPath = join(DEFAULT_PLUGINS_DIR, name, "package.json");
|
|
284
|
-
if (!existsSync(pkgJsonPath)) continue;
|
|
285
|
-
try {
|
|
286
|
-
const raw = readFileSync(pkgJsonPath, "utf8");
|
|
287
|
-
const parsed = JSON.parse(raw) as Record<string, unknown>;
|
|
288
|
-
if (typeof parsed.name === "string") {
|
|
289
|
-
manifests.push({
|
|
290
|
-
name: parsed.name,
|
|
291
|
-
version:
|
|
292
|
-
typeof parsed.version === "string" ? parsed.version : undefined,
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
} catch {
|
|
296
|
-
// Skip malformed entries — lenient like listInstalledPlugins.
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return manifests;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Resolve the install date for a user plugin directory, in epoch ms.
|
|
304
|
-
* Reads `install-meta.json`'s `installedAt` field first, falling back to
|
|
305
|
-
* the directory's birthtime. Mirrors the logic in mtime-cache's
|
|
306
|
-
* `getInstallDate` so the sort order matches hook/tool resolution order.
|
|
307
|
-
*/
|
|
308
|
-
function getPluginInstallDate(plugin: AllPluginInfo): number {
|
|
309
|
-
const metaPath = join(plugin.target, "install-meta.json");
|
|
310
|
-
try {
|
|
311
|
-
if (existsSync(metaPath)) {
|
|
312
|
-
const raw = JSON.parse(readFileSync(metaPath, "utf8")) as Record<string, unknown>;
|
|
313
|
-
if (typeof raw.installedAt === "string") {
|
|
314
|
-
const ms = Date.parse(raw.installedAt);
|
|
315
|
-
if (Number.isFinite(ms)) return ms;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
} catch {
|
|
319
|
-
// Fall through to birthtime.
|
|
320
|
-
}
|
|
321
|
-
try {
|
|
322
|
-
return statSync(plugin.target).birthtimeMs;
|
|
323
|
-
} catch {
|
|
324
|
-
return 0;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
@@ -109,13 +109,10 @@ describe("reconcileFlagGatedProfiles", () => {
|
|
|
109
109
|
|
|
110
110
|
const raw = readConfig();
|
|
111
111
|
const osBeta = raw.llm.profiles["os-beta"]!;
|
|
112
|
-
expect(osBeta.model).toBe("
|
|
113
|
-
expect(osBeta.provider_connection).toBe("
|
|
114
|
-
expect(osBeta.provider).toBe("together");
|
|
112
|
+
expect(osBeta.model).toBe("accounts/fireworks/models/glm-5p2");
|
|
113
|
+
expect(osBeta.provider_connection).toBe("fireworks-managed");
|
|
115
114
|
expect(osBeta.source).toBe("managed");
|
|
116
115
|
expect(osBeta.label).toBe("OS Beta");
|
|
117
|
-
expect(osBeta.effort).toBe("low");
|
|
118
|
-
expect(osBeta.topP).toBe(0.95);
|
|
119
116
|
|
|
120
117
|
const order = raw.llm.profileOrder;
|
|
121
118
|
expect(order.indexOf("os-beta")).toBe(order.indexOf("balanced") + 1);
|
|
@@ -131,7 +128,6 @@ describe("reconcileFlagGatedProfiles", () => {
|
|
|
131
128
|
expect(osBeta.status).toBe("disabled");
|
|
132
129
|
expect(osBeta.label).toBe("OS Beta (Managed)");
|
|
133
130
|
expect(osBeta.source).toBe("managed");
|
|
134
|
-
expect(osBeta.effort).toBe("low");
|
|
135
131
|
});
|
|
136
132
|
|
|
137
133
|
test("flag on is idempotent across repeated runs", () => {
|
|
@@ -154,7 +150,6 @@ describe("reconcileFlagGatedProfiles", () => {
|
|
|
154
150
|
raw.llm.profiles["os-beta"]!.label = "My OS Beta";
|
|
155
151
|
raw.llm.profiles["os-beta"]!.status = "disabled";
|
|
156
152
|
raw.llm.profiles["os-beta"]!.advisorEnabled = true;
|
|
157
|
-
raw.llm.profiles["os-beta"]!.topP = 0.8;
|
|
158
153
|
writeConfig(raw);
|
|
159
154
|
invalidateConfigCache();
|
|
160
155
|
|
|
@@ -164,10 +159,7 @@ describe("reconcileFlagGatedProfiles", () => {
|
|
|
164
159
|
expect(after.label).toBe("My OS Beta");
|
|
165
160
|
expect(after.status).toBe("disabled");
|
|
166
161
|
expect(after.advisorEnabled).toBe(true);
|
|
167
|
-
expect(after.
|
|
168
|
-
expect(after.model).toBe("MiniMaxAI/MiniMax-M3");
|
|
169
|
-
expect(after.provider_connection).toBe("together-managed");
|
|
170
|
-
expect(after.effort).toBe("low");
|
|
162
|
+
expect(after.model).toBe("accounts/fireworks/models/glm-5p2");
|
|
171
163
|
});
|
|
172
164
|
|
|
173
165
|
test("flag off removes a managed os-beta and applies fallbacks", () => {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type { ContactWithChannels } from "../../../../contacts/types.js";
|
|
3
2
|
import { cliIpcCall } from "../../../../ipc/cli-client.js";
|
|
4
3
|
import { resolveGuardianName } from "../../../../prompts/user-reference.js";
|
|
5
4
|
import type {
|
|
@@ -7,12 +6,6 @@ import type {
|
|
|
7
6
|
ToolExecutionResult,
|
|
8
7
|
} from "../../../../tools/types.js";
|
|
9
8
|
|
|
10
|
-
function guardianAwareName(contact: Pick<ContactRead, "role" | "displayName">) {
|
|
11
|
-
return contact.role === "guardian"
|
|
12
|
-
? resolveGuardianName(contact.displayName)
|
|
13
|
-
: contact.displayName;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
9
|
export async function executeContactMerge(
|
|
17
10
|
input: Record<string, unknown>,
|
|
18
11
|
_context: ToolContext,
|
|
@@ -29,10 +22,10 @@ export async function executeContactMerge(
|
|
|
29
22
|
|
|
30
23
|
// Validate both contacts exist before merging
|
|
31
24
|
const [keepRes, mergeRes] = await Promise.all([
|
|
32
|
-
cliIpcCall<{ contact:
|
|
25
|
+
cliIpcCall<{ contact: ContactWithChannels }>("getContact", {
|
|
33
26
|
pathParams: { id: keepId },
|
|
34
27
|
}),
|
|
35
|
-
cliIpcCall<{ contact:
|
|
28
|
+
cliIpcCall<{ contact: ContactWithChannels }>("getContact", {
|
|
36
29
|
pathParams: { id: mergeId },
|
|
37
30
|
}),
|
|
38
31
|
]);
|
|
@@ -49,7 +42,7 @@ export async function executeContactMerge(
|
|
|
49
42
|
|
|
50
43
|
const mergeResult = await cliIpcCall<{
|
|
51
44
|
ok: boolean;
|
|
52
|
-
contact:
|
|
45
|
+
contact: ContactWithChannels;
|
|
53
46
|
}>("merge_contacts", {
|
|
54
47
|
body: { keepId, mergeId },
|
|
55
48
|
});
|
|
@@ -58,22 +51,19 @@ export async function executeContactMerge(
|
|
|
58
51
|
return { content: `Error: ${mergeResult.error}`, isError: true };
|
|
59
52
|
}
|
|
60
53
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const displayName = guardianAwareName(merged);
|
|
75
|
-
const keepName = guardianAwareName(keepContact);
|
|
76
|
-
const mergeName = guardianAwareName(mergeContact);
|
|
54
|
+
const merged = mergeResult.result!.contact;
|
|
55
|
+
const displayName =
|
|
56
|
+
merged.role === "guardian"
|
|
57
|
+
? resolveGuardianName(merged.displayName)
|
|
58
|
+
: merged.displayName;
|
|
59
|
+
const keepName =
|
|
60
|
+
keepContact.role === "guardian"
|
|
61
|
+
? resolveGuardianName(keepContact.displayName)
|
|
62
|
+
: keepContact.displayName;
|
|
63
|
+
const mergeName =
|
|
64
|
+
mergeContact.role === "guardian"
|
|
65
|
+
? resolveGuardianName(mergeContact.displayName)
|
|
66
|
+
: mergeContact.displayName;
|
|
77
67
|
|
|
78
68
|
const channelList = merged.channels
|
|
79
69
|
.map(
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type { ContactWithChannels } from "../../../../contacts/types.js";
|
|
3
2
|
import { cliIpcCall } from "../../../../ipc/cli-client.js";
|
|
4
3
|
import { resolveGuardianName } from "../../../../prompts/user-reference.js";
|
|
5
4
|
import type {
|
|
@@ -7,16 +6,7 @@ import type {
|
|
|
7
6
|
ToolExecutionResult,
|
|
8
7
|
} from "../../../../tools/types.js";
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
// on the gateway `ContactRead` channel contract.
|
|
12
|
-
type SearchChannel = ContactRead["channels"][number] & {
|
|
13
|
-
externalChatId?: string | null;
|
|
14
|
-
};
|
|
15
|
-
type SearchContact = Omit<ContactRead, "channels"> & {
|
|
16
|
-
channels: SearchChannel[];
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
function formatContactSummary(c: SearchContact): string {
|
|
9
|
+
function formatContactSummary(c: ContactWithChannels): string {
|
|
20
10
|
const displayName =
|
|
21
11
|
c.role === "guardian" ? resolveGuardianName(c.displayName) : c.displayName;
|
|
22
12
|
const parts = [`- **${displayName}** (ID: ${c.id})`];
|
|
@@ -55,7 +45,7 @@ export async function executeContactSearch(
|
|
|
55
45
|
};
|
|
56
46
|
}
|
|
57
47
|
|
|
58
|
-
const res = await cliIpcCall<
|
|
48
|
+
const res = await cliIpcCall<ContactWithChannels[]>("search_contacts", {
|
|
59
49
|
body: { query, channelAddress, channelType, limit },
|
|
60
50
|
});
|
|
61
51
|
|
|
@@ -39,7 +39,7 @@ Each subagent is spawned with a role that determines its tool access. Choose the
|
|
|
39
39
|
| `researcher` | `web_search`, `web_fetch`, `file_read`, `file_list`, `recall`, `notify_parent` | Information gathering, web research, codebase exploration, reading documentation |
|
|
40
40
|
| `coder` | `bash`, `file_read`, `file_write`, `file_edit`, `web_search`, `recall`, `notify_parent` | Code changes, file editing, running commands, build/test tasks |
|
|
41
41
|
| `planner` | `file_read`, `file_list`, `web_search`, `web_fetch`, `recall`, `notify_parent` | Analysis, planning, synthesizing information, reviewing approaches |
|
|
42
|
-
| `investigator` | `
|
|
42
|
+
| `investigator` | `bash`, `file_read`, `file_list`, `web_search`, `web_fetch`, `recall`, `notify_parent` | Root-cause analysis: debugging, log forensics, tracing behavior across many files. Shell access is for read-only investigation (grep/find/reading logs); returns a compact root-cause report |
|
|
43
43
|
|
|
44
44
|
All specialized roles (`researcher`, `coder`, `planner`) include `notify_parent` for mid-run communication with the parent.
|
|
45
45
|
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"planner",
|
|
39
39
|
"investigator"
|
|
40
40
|
],
|
|
41
|
-
"description": "Agent specialization that controls tool access. 'researcher': read-only (web, files, memory). 'coder': file and bash access. 'planner': read-only analysis. 'investigator': root-cause analysis — debugging, log forensics, tracing behavior across many files;
|
|
41
|
+
"description": "Agent specialization that controls tool access. 'researcher': read-only (web, files, memory). 'coder': file and bash access. 'planner': read-only analysis. 'investigator': root-cause analysis — debugging, log forensics, tracing behavior across many files; has bash for read-only investigation (grep/find/log inspection) and returns a compact root-cause report. 'general': full access (default). Ignored when fork: true (forks always use general)."
|
|
42
42
|
},
|
|
43
43
|
"inference_profile": {
|
|
44
44
|
"type": "string",
|