@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
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `assistant memory worker` CLI subgroup.
|
|
3
|
-
*
|
|
4
|
-
* Manages the memory jobs worker as its own OS process — separate from the
|
|
5
|
-
* daemon's main event loop. This prevents long-running embedding jobs from
|
|
6
|
-
* blocking user-facing HTTP traffic.
|
|
7
|
-
*
|
|
8
|
-
* Subcommands:
|
|
9
|
-
*
|
|
10
|
-
* - `start` — spawn the worker process (detached, background).
|
|
11
|
-
* - `stop` — send SIGTERM to the running worker process.
|
|
12
|
-
* - `status` — report whether the worker process is running.
|
|
13
|
-
*
|
|
14
|
-
* All three run directly in the CLI process (transport: "local") — no IPC
|
|
15
|
-
* round-trip to the daemon.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import type { Command } from "commander";
|
|
19
|
-
|
|
20
|
-
import {
|
|
21
|
-
probeMemoryWorker,
|
|
22
|
-
spawnMemoryWorkerProcess,
|
|
23
|
-
} from "../../../memory/worker-control.js";
|
|
24
|
-
import { getMemoryWorkerPidPath } from "../../../util/platform.js";
|
|
25
|
-
import { registerCommand } from "../../lib/register-command.js";
|
|
26
|
-
import { log } from "../../logger.js";
|
|
27
|
-
import { shouldOutputJson, writeOutput } from "../../output.js";
|
|
28
|
-
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
// `start`
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
|
-
|
|
33
|
-
async function startWorker(
|
|
34
|
-
opts: { json?: boolean },
|
|
35
|
-
cmd: Command,
|
|
36
|
-
): Promise<void> {
|
|
37
|
-
let result: { pid: number; alreadyRunning: boolean };
|
|
38
|
-
try {
|
|
39
|
-
result = await spawnMemoryWorkerProcess();
|
|
40
|
-
} catch (err) {
|
|
41
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
42
|
-
if (shouldOutputJson(cmd)) {
|
|
43
|
-
writeOutput(cmd, { ok: false, error: msg });
|
|
44
|
-
} else {
|
|
45
|
-
log.error(msg);
|
|
46
|
-
}
|
|
47
|
-
process.exitCode = 1;
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (result.alreadyRunning) {
|
|
52
|
-
const msg = `Memory worker is already running (PID ${result.pid})`;
|
|
53
|
-
if (shouldOutputJson(cmd)) {
|
|
54
|
-
writeOutput(cmd, { ok: false, error: msg, pid: result.pid });
|
|
55
|
-
} else {
|
|
56
|
-
log.error(msg);
|
|
57
|
-
}
|
|
58
|
-
process.exitCode = 1;
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (shouldOutputJson(cmd)) {
|
|
63
|
-
writeOutput(cmd, {
|
|
64
|
-
ok: true,
|
|
65
|
-
pid: result.pid,
|
|
66
|
-
pidPath: getMemoryWorkerPidPath(),
|
|
67
|
-
});
|
|
68
|
-
} else {
|
|
69
|
-
log.info(`Memory worker started (PID ${result.pid})`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// ---------------------------------------------------------------------------
|
|
74
|
-
// `stop`
|
|
75
|
-
// ---------------------------------------------------------------------------
|
|
76
|
-
|
|
77
|
-
function stopWorker(opts: { json?: boolean }, cmd: Command): void {
|
|
78
|
-
const current = probeMemoryWorker();
|
|
79
|
-
if (current.status !== "running" || current.pid == null) {
|
|
80
|
-
const msg = "Memory worker is not running";
|
|
81
|
-
if (shouldOutputJson(cmd)) {
|
|
82
|
-
writeOutput(cmd, { ok: false, error: msg });
|
|
83
|
-
} else {
|
|
84
|
-
log.error(msg);
|
|
85
|
-
}
|
|
86
|
-
process.exitCode = 1;
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const pid = current.pid;
|
|
91
|
-
try {
|
|
92
|
-
process.kill(pid, "SIGTERM");
|
|
93
|
-
} catch (err) {
|
|
94
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
95
|
-
if (shouldOutputJson(cmd)) {
|
|
96
|
-
writeOutput(cmd, { ok: false, error: msg, pid });
|
|
97
|
-
} else {
|
|
98
|
-
log.error(`Failed to stop memory worker (PID ${pid}): ${msg}`);
|
|
99
|
-
}
|
|
100
|
-
process.exitCode = 1;
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (shouldOutputJson(cmd)) {
|
|
105
|
-
writeOutput(cmd, { ok: true, pid });
|
|
106
|
-
} else {
|
|
107
|
-
log.info(`Memory worker stop signal sent (PID ${pid})`);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// ---------------------------------------------------------------------------
|
|
112
|
-
// `status`
|
|
113
|
-
// ---------------------------------------------------------------------------
|
|
114
|
-
|
|
115
|
-
function statusWorker(opts: { json?: boolean }, cmd: Command): void {
|
|
116
|
-
const result = probeMemoryWorker();
|
|
117
|
-
if (shouldOutputJson(cmd)) {
|
|
118
|
-
writeOutput(cmd, result);
|
|
119
|
-
} else {
|
|
120
|
-
if (result.status === "running") {
|
|
121
|
-
log.info(`Memory worker is running (PID ${result.pid})`);
|
|
122
|
-
} else {
|
|
123
|
-
log.info("Memory worker is not running");
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// ---------------------------------------------------------------------------
|
|
129
|
-
// Registration
|
|
130
|
-
// ---------------------------------------------------------------------------
|
|
131
|
-
|
|
132
|
-
export function registerMemoryWorkerCommand(memory: Command): void {
|
|
133
|
-
registerCommand(memory, {
|
|
134
|
-
name: "worker",
|
|
135
|
-
transport: "local",
|
|
136
|
-
description: "Manage the memory jobs worker process (start/stop/status)",
|
|
137
|
-
build: (worker) => {
|
|
138
|
-
worker.addHelpText(
|
|
139
|
-
"after",
|
|
140
|
-
`
|
|
141
|
-
The memory worker processes embedding, consolidation, and cleanup jobs in a
|
|
142
|
-
separate OS process so they do not block the daemon's main event loop.
|
|
143
|
-
|
|
144
|
-
Examples:
|
|
145
|
-
$ assistant memory worker start
|
|
146
|
-
$ assistant memory worker status
|
|
147
|
-
$ assistant memory worker stop`,
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
worker
|
|
151
|
-
.command("start")
|
|
152
|
-
.description("Start the memory worker as a background process")
|
|
153
|
-
.option("--json", "Emit raw JSON instead of a formatted summary")
|
|
154
|
-
.action(async (opts: { json?: boolean }, cmd: Command) => {
|
|
155
|
-
await startWorker(opts, cmd);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
worker
|
|
159
|
-
.command("stop")
|
|
160
|
-
.description("Stop the running memory worker process")
|
|
161
|
-
.option("--json", "Emit raw JSON instead of a formatted summary")
|
|
162
|
-
.action((opts: { json?: boolean }, cmd: Command) => {
|
|
163
|
-
stopWorker(opts, cmd);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
worker
|
|
167
|
-
.command("status")
|
|
168
|
-
.description("Check whether the memory worker process is running")
|
|
169
|
-
.option("--json", "Emit raw JSON instead of a formatted summary")
|
|
170
|
-
.action((opts: { json?: boolean }, cmd: Command) => {
|
|
171
|
-
statusWorker(opts, cmd);
|
|
172
|
-
});
|
|
173
|
-
},
|
|
174
|
-
});
|
|
175
|
-
}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
afterAll,
|
|
5
|
-
afterEach,
|
|
6
|
-
beforeEach,
|
|
7
|
-
describe,
|
|
8
|
-
expect,
|
|
9
|
-
mock,
|
|
10
|
-
test,
|
|
11
|
-
} from "bun:test";
|
|
12
|
-
|
|
13
|
-
const WORKSPACE_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
14
|
-
const CONFIG_PATH = join(WORKSPACE_DIR, "config.json");
|
|
15
|
-
|
|
16
|
-
function ensureTestDir(): void {
|
|
17
|
-
const dirs = [
|
|
18
|
-
WORKSPACE_DIR,
|
|
19
|
-
join(WORKSPACE_DIR, "data"),
|
|
20
|
-
join(WORKSPACE_DIR, "data", "memory"),
|
|
21
|
-
join(WORKSPACE_DIR, "data", "logs"),
|
|
22
|
-
];
|
|
23
|
-
for (const dir of dirs) {
|
|
24
|
-
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function makeLoggerStub(): Record<string, unknown> {
|
|
29
|
-
const stub: Record<string, unknown> = {};
|
|
30
|
-
for (const m of [
|
|
31
|
-
"info",
|
|
32
|
-
"warn",
|
|
33
|
-
"error",
|
|
34
|
-
"debug",
|
|
35
|
-
"trace",
|
|
36
|
-
"fatal",
|
|
37
|
-
"silent",
|
|
38
|
-
"child",
|
|
39
|
-
]) {
|
|
40
|
-
stub[m] = m === "child" ? () => makeLoggerStub() : () => {};
|
|
41
|
-
}
|
|
42
|
-
return stub;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
mock.module("../../util/logger.js", () => ({
|
|
46
|
-
getLogger: () => makeLoggerStub(),
|
|
47
|
-
}));
|
|
48
|
-
|
|
49
|
-
afterAll(() => {
|
|
50
|
-
mock.restore();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
import { resolveCallSiteConfig } from "../llm-resolver.js";
|
|
54
|
-
import { invalidateConfigCache, loadConfig } from "../loader.js";
|
|
55
|
-
|
|
56
|
-
function writeConfig(obj: unknown): void {
|
|
57
|
-
writeFileSync(CONFIG_PATH, JSON.stringify(obj, null, 2) + "\n");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Base config where the active profile resolves to a DIFFERENT model than the
|
|
62
|
-
* `balanced` profile that the shipped `memoryV3SelectL2` call-site default
|
|
63
|
-
* points at. This lets each test distinguish the two failure modes:
|
|
64
|
-
* - call-site default applied (fixed) -> model "balanced-model"
|
|
65
|
-
* - silently downgraded to active -> model "active-model"
|
|
66
|
-
*/
|
|
67
|
-
function baseLlm(callSites: Record<string, unknown>): unknown {
|
|
68
|
-
return {
|
|
69
|
-
llm: {
|
|
70
|
-
default: { provider: "anthropic", model: "default-model" },
|
|
71
|
-
profiles: {
|
|
72
|
-
balanced: { provider: "anthropic", model: "balanced-model" },
|
|
73
|
-
speedy: { provider: "anthropic", model: "active-model" },
|
|
74
|
-
},
|
|
75
|
-
activeProfile: "speedy",
|
|
76
|
-
callSites,
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
describe("config recovery prunes call-site overrides emptied by a strip", () => {
|
|
82
|
-
beforeEach(() => {
|
|
83
|
-
ensureTestDir();
|
|
84
|
-
if (existsSync(CONFIG_PATH)) rmSync(CONFIG_PATH, { force: true });
|
|
85
|
-
delete process.env.IS_PLATFORM;
|
|
86
|
-
invalidateConfigCache();
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
afterEach(() => {
|
|
90
|
-
delete process.env.IS_PLATFORM;
|
|
91
|
-
if (existsSync(CONFIG_PATH)) rmSync(CONFIG_PATH, { force: true });
|
|
92
|
-
invalidateConfigCache();
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
test("an undefined call-site profile ref falls back to the shipped default, not the active profile", () => {
|
|
96
|
-
// The `.profile` ref is invalid (no such profile), so schema recovery
|
|
97
|
-
// strips it. Before the fix this left `callSites.memoryV3SelectL2 = {}`,
|
|
98
|
-
// which the resolver treats as a present override and so skips the shipped
|
|
99
|
-
// `{profile:"balanced"}` default — silently resolving to the active profile.
|
|
100
|
-
writeConfig(baseLlm({ memoryV3SelectL2: { profile: "ghost-profile" } }));
|
|
101
|
-
|
|
102
|
-
const config = loadConfig();
|
|
103
|
-
|
|
104
|
-
// The emptied call-site entry must be pruned entirely, not left as `{}`.
|
|
105
|
-
expect(config.llm.callSites?.memoryV3SelectL2).toBeUndefined();
|
|
106
|
-
|
|
107
|
-
// Resolution now lands on the shipped call-site default (balanced), not the
|
|
108
|
-
// active profile ("active-model"), which is what the bug produced.
|
|
109
|
-
const resolved = resolveCallSiteConfig("memoryV3SelectL2", config.llm);
|
|
110
|
-
expect(resolved.model).toBe("balanced-model");
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test("a valid sibling call-site override survives while the invalid one is pruned", () => {
|
|
114
|
-
// memoryRouter -> balanced is valid and must be preserved; only the invalid
|
|
115
|
-
// memoryV3SelectL2 entry is pruned. Guards against over-pruning the parent.
|
|
116
|
-
writeConfig(
|
|
117
|
-
baseLlm({
|
|
118
|
-
memoryV3SelectL2: { profile: "missing" },
|
|
119
|
-
memoryRouter: { profile: "balanced" },
|
|
120
|
-
}),
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
const config = loadConfig();
|
|
124
|
-
|
|
125
|
-
expect(config.llm.callSites?.memoryV3SelectL2).toBeUndefined();
|
|
126
|
-
expect(config.llm.callSites?.memoryRouter).toEqual({ profile: "balanced" });
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
test("a partial override keeping other fields is not pruned", () => {
|
|
130
|
-
// Stripping the invalid `.profile` leaves a non-empty `{temperature:0.5}`,
|
|
131
|
-
// a legitimate user override the resolver should keep (and which therefore
|
|
132
|
-
// still shadows the shipped default per existing either/or semantics).
|
|
133
|
-
writeConfig(
|
|
134
|
-
baseLlm({ memoryV3SelectL2: { profile: "missing", temperature: 0.5 } }),
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
const config = loadConfig();
|
|
138
|
-
|
|
139
|
-
expect(config.llm.callSites?.memoryV3SelectL2).toEqual({
|
|
140
|
-
temperature: 0.5,
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
});
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
// Exact system-owned default materializations. These are resolved through
|
|
2
|
-
// shipped call-site defaults rather than persisted as user overrides.
|
|
3
|
-
const SEEDED_CALL_SITES: Record<string, Record<string, unknown>> = {
|
|
4
|
-
guardianQuestionCopy: latencySeed(),
|
|
5
|
-
interactionClassifier: latencySeed(),
|
|
6
|
-
skillCategoryInference: latencySeed(),
|
|
7
|
-
inviteInstructionGenerator: latencySeed(),
|
|
8
|
-
notificationDecision: latencySeed(),
|
|
9
|
-
preferenceExtraction: latencySeed(),
|
|
10
|
-
commitMessage: {
|
|
11
|
-
model: "claude-haiku-4-5-20251001",
|
|
12
|
-
maxTokens: 120,
|
|
13
|
-
temperature: 0.2,
|
|
14
|
-
effort: "low",
|
|
15
|
-
thinking: { enabled: false },
|
|
16
|
-
},
|
|
17
|
-
conversationStarters: latencySeed(),
|
|
18
|
-
conversationSummarization: {
|
|
19
|
-
model: "claude-opus-4-7",
|
|
20
|
-
effort: "low",
|
|
21
|
-
thinking: { enabled: false },
|
|
22
|
-
},
|
|
23
|
-
recall: {
|
|
24
|
-
profile: "cost-optimized",
|
|
25
|
-
maxTokens: 4096,
|
|
26
|
-
effort: "low",
|
|
27
|
-
thinking: { enabled: false, streamThinking: false },
|
|
28
|
-
temperature: 0,
|
|
29
|
-
disableCache: true,
|
|
30
|
-
},
|
|
31
|
-
heartbeatAgent: {
|
|
32
|
-
profile: "cost-optimized",
|
|
33
|
-
maxTokens: 2048,
|
|
34
|
-
effort: "low",
|
|
35
|
-
temperature: 0,
|
|
36
|
-
thinking: { enabled: false, streamThinking: false },
|
|
37
|
-
contextWindow: { maxInputTokens: 16000 },
|
|
38
|
-
},
|
|
39
|
-
replySuggestion: {
|
|
40
|
-
model: "claude-haiku-4-5-20251001",
|
|
41
|
-
effort: "low",
|
|
42
|
-
thinking: { enabled: false },
|
|
43
|
-
disableCache: true,
|
|
44
|
-
},
|
|
45
|
-
memoryRouter: {
|
|
46
|
-
profile: "cost-optimized",
|
|
47
|
-
contextWindow: { maxInputTokens: 1_000_000 },
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export function pruneSeededCallsiteDefaultsFromConfig(
|
|
52
|
-
config: Record<string, unknown>,
|
|
53
|
-
): boolean {
|
|
54
|
-
const llm = readObject(config.llm);
|
|
55
|
-
if (llm === null) return false;
|
|
56
|
-
|
|
57
|
-
const callSites = readObject(llm.callSites);
|
|
58
|
-
if (callSites === null) return false;
|
|
59
|
-
|
|
60
|
-
let changed = false;
|
|
61
|
-
for (const [callSite, seed] of Object.entries(SEEDED_CALL_SITES)) {
|
|
62
|
-
if (deepEqual(callSites[callSite], seed)) {
|
|
63
|
-
delete callSites[callSite];
|
|
64
|
-
changed = true;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
if (!changed) return false;
|
|
68
|
-
|
|
69
|
-
if (Object.keys(callSites).length === 0) {
|
|
70
|
-
delete llm.callSites;
|
|
71
|
-
} else {
|
|
72
|
-
llm.callSites = callSites;
|
|
73
|
-
}
|
|
74
|
-
config.llm = llm;
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function latencySeed(): Record<string, unknown> {
|
|
79
|
-
return {
|
|
80
|
-
model: "claude-haiku-4-5-20251001",
|
|
81
|
-
effort: "low",
|
|
82
|
-
thinking: { enabled: false },
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function readObject(value: unknown): Record<string, unknown> | null {
|
|
87
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
return value as Record<string, unknown>;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function deepEqual(a: unknown, b: unknown): boolean {
|
|
94
|
-
if (a === b) return true;
|
|
95
|
-
if (a === null || b === null) return false;
|
|
96
|
-
if (typeof a !== "object" || typeof b !== "object") return false;
|
|
97
|
-
if (Array.isArray(a) || Array.isArray(b)) return false;
|
|
98
|
-
|
|
99
|
-
const aRecord = a as Record<string, unknown>;
|
|
100
|
-
const bRecord = b as Record<string, unknown>;
|
|
101
|
-
const aKeys = Object.keys(aRecord);
|
|
102
|
-
const bKeys = Object.keys(bRecord);
|
|
103
|
-
if (aKeys.length !== bKeys.length) return false;
|
|
104
|
-
|
|
105
|
-
for (const key of aKeys) {
|
|
106
|
-
if (!Object.prototype.hasOwnProperty.call(bRecord, key)) return false;
|
|
107
|
-
if (!deepEqual(aRecord[key], bRecord[key])) return false;
|
|
108
|
-
}
|
|
109
|
-
return true;
|
|
110
|
-
}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the gateway-first member-revoke relay.
|
|
3
|
-
*
|
|
4
|
-
* revokeMemberChannel downgrades the channel's ACL status through the gateway
|
|
5
|
-
* (source of truth) via `ipcCallPersistent("mark_channel_revoked", ...)` first,
|
|
6
|
-
* then mirrors the downgrade to the assistant DB best-effort. A local mirror
|
|
7
|
-
* failure is swallowed so the gateway-owned outcome stands.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
11
|
-
|
|
12
|
-
import type { ContactWriteResult } from "../types.js";
|
|
13
|
-
|
|
14
|
-
type IpcCall = { method: string; params?: Record<string, unknown> };
|
|
15
|
-
|
|
16
|
-
let ipcCalls: IpcCall[] = [];
|
|
17
|
-
let ipcOk = true;
|
|
18
|
-
|
|
19
|
-
const ipcCallPersistentMock = mock(
|
|
20
|
-
async (method: string, params?: Record<string, unknown>) => {
|
|
21
|
-
ipcCalls.push({ method, params });
|
|
22
|
-
return {
|
|
23
|
-
ok: ipcOk,
|
|
24
|
-
didWrite: ipcOk,
|
|
25
|
-
channel: {
|
|
26
|
-
id: (params?.contactChannelId as string) ?? "ch1",
|
|
27
|
-
contactId: "c1",
|
|
28
|
-
type: "telegram",
|
|
29
|
-
address: "addr",
|
|
30
|
-
status: "revoked",
|
|
31
|
-
revokedReason: (params?.reason as string) ?? null,
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
},
|
|
35
|
-
);
|
|
36
|
-
const actualGatewayClient = await import("../../ipc/gateway-client.js");
|
|
37
|
-
mock.module("../../ipc/gateway-client.js", () => ({
|
|
38
|
-
...actualGatewayClient,
|
|
39
|
-
ipcCallPersistent: ipcCallPersistentMock,
|
|
40
|
-
}));
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// Local-mirror primitive.
|
|
44
|
-
const revokeMemberResult: ContactWriteResult = {
|
|
45
|
-
contact: { id: "c1" } as ContactWriteResult["contact"],
|
|
46
|
-
channel: { id: "ch1", status: "revoked" } as ContactWriteResult["channel"],
|
|
47
|
-
};
|
|
48
|
-
const revokeMemberMock = mock((_memberId: string, _reason?: string) =>
|
|
49
|
-
revokeMemberResult,
|
|
50
|
-
);
|
|
51
|
-
const actualContactsWrite = await import("../contacts-write.js");
|
|
52
|
-
mock.module("../contacts-write.js", () => ({
|
|
53
|
-
...actualContactsWrite,
|
|
54
|
-
revokeMember: revokeMemberMock,
|
|
55
|
-
}));
|
|
56
|
-
|
|
57
|
-
const { revokeMemberChannel } = await import("../member-write-relay.js");
|
|
58
|
-
|
|
59
|
-
describe("revokeMemberChannel gateway-first relay", () => {
|
|
60
|
-
beforeEach(() => {
|
|
61
|
-
ipcCalls = [];
|
|
62
|
-
ipcOk = true;
|
|
63
|
-
ipcCallPersistentMock.mockClear();
|
|
64
|
-
revokeMemberMock.mockClear();
|
|
65
|
-
revokeMemberMock.mockImplementation(() => revokeMemberResult);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("relays the revoke to the gateway before mirroring locally", async () => {
|
|
69
|
-
const result = await revokeMemberChannel("ch1", "removed");
|
|
70
|
-
|
|
71
|
-
expect(ipcCalls).toEqual([
|
|
72
|
-
{
|
|
73
|
-
method: "mark_channel_revoked",
|
|
74
|
-
params: { contactChannelId: "ch1", reason: "removed" },
|
|
75
|
-
},
|
|
76
|
-
]);
|
|
77
|
-
expect(revokeMemberMock).toHaveBeenCalledTimes(1);
|
|
78
|
-
expect(revokeMemberMock).toHaveBeenCalledWith("ch1", "removed");
|
|
79
|
-
expect(result).toBe(revokeMemberResult);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test("strips the composite contactId:channelId prefix before the relay", async () => {
|
|
83
|
-
await revokeMemberChannel("c1:ch1");
|
|
84
|
-
|
|
85
|
-
expect(ipcCalls[0]?.params?.contactChannelId).toBe("ch1");
|
|
86
|
-
// The local mirror still receives the original composite id it accepts.
|
|
87
|
-
expect(revokeMemberMock).toHaveBeenCalledWith("c1:ch1", undefined);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test("always relays — never skips based on local mirror status", async () => {
|
|
91
|
-
// The gateway owns the ACL outcome; the relay must fire even if the local
|
|
92
|
-
// mirror lags (says revoked) while the gateway row is still active.
|
|
93
|
-
await revokeMemberChannel("ch1");
|
|
94
|
-
|
|
95
|
-
expect(ipcCalls).toEqual([
|
|
96
|
-
{
|
|
97
|
-
method: "mark_channel_revoked",
|
|
98
|
-
params: { contactChannelId: "ch1", reason: undefined },
|
|
99
|
-
},
|
|
100
|
-
]);
|
|
101
|
-
expect(revokeMemberMock).toHaveBeenCalledTimes(1);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test("swallows a local-mirror failure without throwing; the gateway revoke stands", async () => {
|
|
105
|
-
revokeMemberMock.mockImplementation(() => {
|
|
106
|
-
throw new Error("local mirror exploded");
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
const result = await revokeMemberChannel("ch1", "removed");
|
|
110
|
-
|
|
111
|
-
expect(ipcCalls).toHaveLength(1);
|
|
112
|
-
expect(result).toBeNull();
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test("throws when the gateway relay returns ok: false", async () => {
|
|
116
|
-
ipcOk = false;
|
|
117
|
-
|
|
118
|
-
let thrown: Error | undefined;
|
|
119
|
-
try {
|
|
120
|
-
await revokeMemberChannel("ch1");
|
|
121
|
-
} catch (err) {
|
|
122
|
-
thrown = err as Error;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
expect(thrown).toBeDefined();
|
|
126
|
-
// Local mirror must not run when the gateway refuses the downgrade.
|
|
127
|
-
expect(revokeMemberMock).not.toHaveBeenCalled();
|
|
128
|
-
});
|
|
129
|
-
});
|