@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
|
@@ -272,6 +272,7 @@ describe("WhatsApp channel ingress attachment resolution", () => {
|
|
|
272
272
|
const trustVerdict = resolveLocalTrustVerdict({
|
|
273
273
|
channelType: "whatsapp",
|
|
274
274
|
actorExternalId: WHATSAPP_USER_ID,
|
|
275
|
+
externalChatId: "whatsapp-chat-1",
|
|
275
276
|
});
|
|
276
277
|
return {
|
|
277
278
|
sourceChannel: "whatsapp",
|
|
@@ -96,8 +96,6 @@ const addMessageMock = mock(
|
|
|
96
96
|
);
|
|
97
97
|
|
|
98
98
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
99
|
-
setConversationProcessingStartedAt: () => {},
|
|
100
|
-
isConversationProcessing: () => false,
|
|
101
99
|
addMessage: (
|
|
102
100
|
conversationId: string,
|
|
103
101
|
role: string,
|
|
@@ -129,18 +127,6 @@ mock.module("../runtime/trust-context-resolver.js", () => ({
|
|
|
129
127
|
}),
|
|
130
128
|
}));
|
|
131
129
|
|
|
132
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
133
|
-
getGuardianDelivery: async () => [
|
|
134
|
-
{
|
|
135
|
-
channelType: "vellum",
|
|
136
|
-
contactId: "guardian-contact",
|
|
137
|
-
principalId: "test-user",
|
|
138
|
-
address: "test-user",
|
|
139
|
-
status: "active",
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
|
-
}));
|
|
143
|
-
|
|
144
130
|
mock.module("../runtime/guardian-reply-router.js", () => ({
|
|
145
131
|
routeGuardianReply: async () => ({
|
|
146
132
|
consumed: false,
|
|
@@ -109,38 +109,17 @@ mock.module("../daemon/approval-generators.js", () => ({
|
|
|
109
109
|
createApprovalConversationGenerator: () => _approvalGenerator,
|
|
110
110
|
}));
|
|
111
111
|
|
|
112
|
-
//
|
|
113
|
-
//
|
|
112
|
+
// Mock local-actor-identity to return a stable guardian context that uses
|
|
113
|
+
// the same principal as the canonical requests created in tests.
|
|
114
114
|
mock.module("../runtime/local-actor-identity.js", () => ({
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
// returns a single active vellum guardian whose principal matches the
|
|
122
|
-
// dev-bypass-resolved id; any other method throws so unexpected IPC surfaces.
|
|
123
|
-
mock.module("../ipc/gateway-client.js", () => ({
|
|
124
|
-
ipcCall: async (method: string) => {
|
|
125
|
-
if (method === "resolve_guardian_delivery") {
|
|
126
|
-
return {
|
|
127
|
-
guardians: [
|
|
128
|
-
{
|
|
129
|
-
channelType: "vellum",
|
|
130
|
-
contactId: "test-contact-id",
|
|
131
|
-
principalId: "test-principal-id",
|
|
132
|
-
address: "test-principal-id",
|
|
133
|
-
externalChatId: "test-principal-id",
|
|
134
|
-
status: "active",
|
|
135
|
-
},
|
|
136
|
-
],
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
throw new Error(`Unexpected ipcCall in test: ${method}`);
|
|
140
|
-
},
|
|
115
|
+
resolveLocalTrustContext: () => ({
|
|
116
|
+
sourceChannel: "vellum",
|
|
117
|
+
trustClass: "guardian",
|
|
118
|
+
guardianPrincipalId: "test-principal-id",
|
|
119
|
+
guardianExternalUserId: "test-principal-id",
|
|
120
|
+
}),
|
|
141
121
|
}));
|
|
142
122
|
|
|
143
|
-
import { __resetGuardianDeliveryCacheForTest } from "../contacts/guardian-delivery-reader.js";
|
|
144
123
|
import { getDb } from "../memory/db-connection.js";
|
|
145
124
|
import { initializeDb } from "../memory/db-init.js";
|
|
146
125
|
import type { AssistantEvent } from "../runtime/assistant-event.js";
|
|
@@ -364,7 +343,6 @@ describe("POST /v1/messages — queue-if-busy and hub publishing", () => {
|
|
|
364
343
|
db.run("DELETE FROM contact_channels");
|
|
365
344
|
db.run("DELETE FROM contacts");
|
|
366
345
|
pendingInteractions.clear();
|
|
367
|
-
__resetGuardianDeliveryCacheForTest();
|
|
368
346
|
|
|
369
347
|
createGuardianBinding({
|
|
370
348
|
channel: "vellum",
|
|
@@ -351,50 +351,6 @@ describe("plugin-resident skills", () => {
|
|
|
351
351
|
expect(skill).toBeUndefined();
|
|
352
352
|
});
|
|
353
353
|
|
|
354
|
-
test("warns when a plugin directory is missing package.json", () => {
|
|
355
|
-
const warnings: unknown[][] = [];
|
|
356
|
-
const originalWarn = noopLogger.warn;
|
|
357
|
-
noopLogger.warn = (...args: unknown[]) => {
|
|
358
|
-
warnings.push(args);
|
|
359
|
-
};
|
|
360
|
-
try {
|
|
361
|
-
writePluginSkill(
|
|
362
|
-
"the-force",
|
|
363
|
-
"software-engineering",
|
|
364
|
-
"Software Engineering",
|
|
365
|
-
"Engineering workflow",
|
|
366
|
-
"body",
|
|
367
|
-
{ withPackageJson: false },
|
|
368
|
-
);
|
|
369
|
-
|
|
370
|
-
const skill = loadSkillCatalog().find(
|
|
371
|
-
(s) => s.id === "software-engineering",
|
|
372
|
-
);
|
|
373
|
-
expect(skill).toBeUndefined();
|
|
374
|
-
|
|
375
|
-
const warnedForDir = warnings.some(
|
|
376
|
-
(args) =>
|
|
377
|
-
typeof args[0] === "object" &&
|
|
378
|
-
args[0] !== null &&
|
|
379
|
-
"pluginDir" in args[0] &&
|
|
380
|
-
(args[0] as { pluginDir: string }).pluginDir.endsWith("the-force") &&
|
|
381
|
-
typeof args[1] === "string" &&
|
|
382
|
-
args[1].includes("missing package.json"),
|
|
383
|
-
);
|
|
384
|
-
expect(warnedForDir).toBe(true);
|
|
385
|
-
} finally {
|
|
386
|
-
noopLogger.warn = originalWarn;
|
|
387
|
-
}
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
test("does not load resident skills from a plugin disabled via .disabled", () => {
|
|
391
|
-
writePluginSkill("caveman", "caveman", "Caveman", "Terse mode");
|
|
392
|
-
writeFileSync(join(pluginsDir, "caveman", ".disabled"), "");
|
|
393
|
-
|
|
394
|
-
const skill = loadSkillCatalog().find((s) => s.id === "caveman");
|
|
395
|
-
expect(skill).toBeUndefined();
|
|
396
|
-
});
|
|
397
|
-
|
|
398
354
|
test("workspace skill overrides a plugin-resident skill with the same id", () => {
|
|
399
355
|
const WORKSPACE_DIR = join(
|
|
400
356
|
tmpdir(),
|
|
@@ -55,35 +55,6 @@ mock.module("../runtime/gateway-client.js", () => ({
|
|
|
55
55
|
},
|
|
56
56
|
}));
|
|
57
57
|
|
|
58
|
-
// Guardian identity resolves via the gateway delivery reader, not the local
|
|
59
|
-
// contacts DB. Seed it to mirror the createGuardianBinding calls below.
|
|
60
|
-
interface GatewayGuardian {
|
|
61
|
-
channelType: string;
|
|
62
|
-
contactId: string;
|
|
63
|
-
principalId?: string | null;
|
|
64
|
-
displayName?: string | null;
|
|
65
|
-
address: string;
|
|
66
|
-
externalChatId?: string | null;
|
|
67
|
-
status: string;
|
|
68
|
-
verifiedAt?: number | null;
|
|
69
|
-
}
|
|
70
|
-
let gatewayGuardians: GatewayGuardian[] = [];
|
|
71
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
72
|
-
getGuardianDelivery: async () => gatewayGuardians,
|
|
73
|
-
guardianForChannel: (list: GatewayGuardian[], channelType: string) =>
|
|
74
|
-
list.find((g) => g.channelType === channelType && g.status === "active"),
|
|
75
|
-
}));
|
|
76
|
-
|
|
77
|
-
function seedGatewayGuardian(
|
|
78
|
-
g: Partial<GatewayGuardian> & { channelType: string; address: string },
|
|
79
|
-
): void {
|
|
80
|
-
gatewayGuardians.push({
|
|
81
|
-
contactId: `c-${g.channelType}`,
|
|
82
|
-
status: "active",
|
|
83
|
-
...g,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
58
|
import { getDb } from "../memory/db-connection.js";
|
|
88
59
|
import { initializeDb } from "../memory/db-init.js";
|
|
89
60
|
import { findActiveSession } from "../runtime/channel-verification-service.js";
|
|
@@ -109,16 +80,7 @@ function resetState(): void {
|
|
|
109
80
|
db.run("DELETE FROM canonical_guardian_deliveries");
|
|
110
81
|
db.run("DELETE FROM contact_channels");
|
|
111
82
|
db.run("DELETE FROM contacts");
|
|
112
|
-
|
|
113
|
-
// Seed the vellum guardian binding (gateway does this at startup in
|
|
114
|
-
// production). The gateway list is the source of truth for guardian
|
|
115
|
-
// resolution; the DB write mirrors it for any local INFO reads.
|
|
116
|
-
seedGatewayGuardian({
|
|
117
|
-
channelType: "vellum",
|
|
118
|
-
address: "guardian-principal",
|
|
119
|
-
principalId: "guardian-principal",
|
|
120
|
-
displayName: "guardian-principal",
|
|
121
|
-
});
|
|
83
|
+
// Seed the vellum guardian binding (gateway does this at startup in production)
|
|
122
84
|
createGuardianBinding({
|
|
123
85
|
channel: "vellum",
|
|
124
86
|
guardianExternalUserId: "guardian-principal",
|
|
@@ -200,14 +162,7 @@ describe("Slack inbound trusted contact verification", () => {
|
|
|
200
162
|
});
|
|
201
163
|
|
|
202
164
|
test("guardian is notified of the access attempt alongside verification", async () => {
|
|
203
|
-
// Set up a guardian binding so the notification can target it
|
|
204
|
-
// list resolves guardian identity; the DB write mirrors it.
|
|
205
|
-
seedGatewayGuardian({
|
|
206
|
-
channelType: "slack",
|
|
207
|
-
address: "U_GUARDIAN",
|
|
208
|
-
externalChatId: "D_GUARDIAN_DM",
|
|
209
|
-
principalId: "guardian-principal",
|
|
210
|
-
});
|
|
165
|
+
// Set up a guardian binding so the notification can target it
|
|
211
166
|
createGuardianBinding({
|
|
212
167
|
channel: "slack",
|
|
213
168
|
guardianExternalUserId: "U_GUARDIAN",
|
|
@@ -13,15 +13,6 @@ let mockRecentContacts: ContactWithChannels[] = [];
|
|
|
13
13
|
let mockFindContactByAddressThrows = false;
|
|
14
14
|
let mockListContactsThrows = false;
|
|
15
15
|
|
|
16
|
-
// Guardian deliveries returned by the mocked gateway reader. resolveGuardianName
|
|
17
|
-
// is mocked to echo mockGuardianName, so the displayName here is captured below.
|
|
18
|
-
let mockGuardianDelivery: Array<{
|
|
19
|
-
channelType: string;
|
|
20
|
-
status: string;
|
|
21
|
-
displayName: string | null;
|
|
22
|
-
}> | null = null;
|
|
23
|
-
let lastGuardianDisplayNameSeen: string | null | undefined;
|
|
24
|
-
|
|
25
16
|
const logWarnFn = mock(() => {});
|
|
26
17
|
|
|
27
18
|
// ---------------------------------------------------------------------------
|
|
@@ -34,10 +25,7 @@ mock.module("../daemon/identity-helpers.js", () => ({
|
|
|
34
25
|
|
|
35
26
|
mock.module("../prompts/user-reference.js", () => ({
|
|
36
27
|
DEFAULT_USER_REFERENCE: "my human",
|
|
37
|
-
resolveGuardianName: (
|
|
38
|
-
lastGuardianDisplayNameSeen = displayName;
|
|
39
|
-
return mockGuardianName;
|
|
40
|
-
},
|
|
28
|
+
resolveGuardianName: () => mockGuardianName,
|
|
41
29
|
}));
|
|
42
30
|
|
|
43
31
|
mock.module("../contacts/contact-store.js", () => ({
|
|
@@ -47,6 +35,8 @@ mock.module("../contacts/contact-store.js", () => ({
|
|
|
47
35
|
}
|
|
48
36
|
return mockTargetContact;
|
|
49
37
|
},
|
|
38
|
+
findGuardianForChannel: () => null,
|
|
39
|
+
listGuardianChannels: () => null,
|
|
50
40
|
listContacts: (_limit?: number) => {
|
|
51
41
|
if (mockListContactsThrows) {
|
|
52
42
|
throw new Error("DB error: listContacts");
|
|
@@ -55,15 +45,6 @@ mock.module("../contacts/contact-store.js", () => ({
|
|
|
55
45
|
},
|
|
56
46
|
}));
|
|
57
47
|
|
|
58
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
59
|
-
getGuardianDelivery: async () => mockGuardianDelivery,
|
|
60
|
-
guardianForChannel: (
|
|
61
|
-
list: Array<{ channelType: string; status: string }>,
|
|
62
|
-
channelType: string,
|
|
63
|
-
) => list.find((g) => g.channelType === channelType && g.status === "active"),
|
|
64
|
-
anyGuardian: (list: unknown[]) => list[0],
|
|
65
|
-
}));
|
|
66
|
-
|
|
67
48
|
// Bun's mock.module for "../util/logger.js" doesn't intercept the transitive
|
|
68
49
|
// import in stt-hints.ts due to a Bun limitation. Mocking pino at the package
|
|
69
50
|
// level works because getLogger uses a Proxy that lazily creates a pino child
|
|
@@ -338,22 +319,10 @@ describe("resolveCallHints", () => {
|
|
|
338
319
|
mockRecentContacts = [];
|
|
339
320
|
mockFindContactByAddressThrows = false;
|
|
340
321
|
mockListContactsThrows = false;
|
|
341
|
-
mockGuardianDelivery = null;
|
|
342
|
-
lastGuardianDisplayNameSeen = undefined;
|
|
343
322
|
logWarnFn.mockClear();
|
|
344
323
|
});
|
|
345
324
|
|
|
346
|
-
test("
|
|
347
|
-
mockGuardianDelivery = [
|
|
348
|
-
{ channelType: "phone", status: "active", displayName: "GatewayGuardian" },
|
|
349
|
-
];
|
|
350
|
-
|
|
351
|
-
await resolveCallHints(null, []);
|
|
352
|
-
|
|
353
|
-
expect(lastGuardianDisplayNameSeen).toBe("GatewayGuardian");
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
test("happy path wires all sources correctly", async () => {
|
|
325
|
+
test("happy path wires all sources correctly", () => {
|
|
357
326
|
mockTargetContact = makeContact("Alice");
|
|
358
327
|
mockRecentContacts = [makeContact("Bob"), makeContact("Charlie")];
|
|
359
328
|
|
|
@@ -366,7 +335,7 @@ describe("resolveCallHints", () => {
|
|
|
366
335
|
inviteGuardianName: "Eve",
|
|
367
336
|
};
|
|
368
337
|
|
|
369
|
-
const result =
|
|
338
|
+
const result = resolveCallHints(session, ["StaticHint"]);
|
|
370
339
|
const parts = result.split(",");
|
|
371
340
|
|
|
372
341
|
expect(parts).toContain("StaticHint");
|
|
@@ -382,7 +351,7 @@ describe("resolveCallHints", () => {
|
|
|
382
351
|
expect(logWarnFn).not.toHaveBeenCalled();
|
|
383
352
|
});
|
|
384
353
|
|
|
385
|
-
test("findContactByAddress failure is caught and logged without throwing",
|
|
354
|
+
test("findContactByAddress failure is caught and logged without throwing", () => {
|
|
386
355
|
mockFindContactByAddressThrows = true;
|
|
387
356
|
mockRecentContacts = [makeContact("Bob")];
|
|
388
357
|
|
|
@@ -396,7 +365,7 @@ describe("resolveCallHints", () => {
|
|
|
396
365
|
};
|
|
397
366
|
|
|
398
367
|
// Should not throw
|
|
399
|
-
const result =
|
|
368
|
+
const result = resolveCallHints(session, []);
|
|
400
369
|
const parts = result.split(",");
|
|
401
370
|
|
|
402
371
|
// Target contact should be absent (lookup failed)
|
|
@@ -407,7 +376,7 @@ describe("resolveCallHints", () => {
|
|
|
407
376
|
expect(logWarnFn).toHaveBeenCalled();
|
|
408
377
|
});
|
|
409
378
|
|
|
410
|
-
test("listContacts failure is caught and logged without throwing",
|
|
379
|
+
test("listContacts failure is caught and logged without throwing", () => {
|
|
411
380
|
mockListContactsThrows = true;
|
|
412
381
|
mockTargetContact = makeContact("Alice");
|
|
413
382
|
|
|
@@ -421,7 +390,7 @@ describe("resolveCallHints", () => {
|
|
|
421
390
|
};
|
|
422
391
|
|
|
423
392
|
// Should not throw
|
|
424
|
-
const result =
|
|
393
|
+
const result = resolveCallHints(session, []);
|
|
425
394
|
const parts = result.split(",");
|
|
426
395
|
|
|
427
396
|
// Recent contacts should be absent (listing failed)
|
|
@@ -432,7 +401,7 @@ describe("resolveCallHints", () => {
|
|
|
432
401
|
expect(logWarnFn).toHaveBeenCalled();
|
|
433
402
|
});
|
|
434
403
|
|
|
435
|
-
test("inbound call resolves caller contact from fromNumber",
|
|
404
|
+
test("inbound call resolves caller contact from fromNumber", () => {
|
|
436
405
|
mockTargetContact = makeContact("Alice");
|
|
437
406
|
mockRecentContacts = [makeContact("Bob")];
|
|
438
407
|
|
|
@@ -445,7 +414,7 @@ describe("resolveCallHints", () => {
|
|
|
445
414
|
inviteGuardianName: null,
|
|
446
415
|
};
|
|
447
416
|
|
|
448
|
-
const result =
|
|
417
|
+
const result = resolveCallHints(session, []);
|
|
449
418
|
const parts = result.split(",");
|
|
450
419
|
|
|
451
420
|
// For inbound, the contact found via fromNumber should appear as caller, not target
|
|
@@ -456,10 +425,10 @@ describe("resolveCallHints", () => {
|
|
|
456
425
|
expect(logWarnFn).not.toHaveBeenCalled();
|
|
457
426
|
});
|
|
458
427
|
|
|
459
|
-
test("null session produces hints from assistant name, guardian name, and recent contacts",
|
|
428
|
+
test("null session produces hints from assistant name, guardian name, and recent contacts", () => {
|
|
460
429
|
mockRecentContacts = [makeContact("RecentOne"), makeContact("RecentTwo")];
|
|
461
430
|
|
|
462
|
-
const result =
|
|
431
|
+
const result = resolveCallHints(null, ["Static"]);
|
|
463
432
|
const parts = result.split(",");
|
|
464
433
|
|
|
465
434
|
expect(parts).toContain("Static");
|
|
@@ -130,33 +130,6 @@ describe("parseSubagentMessages", () => {
|
|
|
130
130
|
expect(result.objective).toBe("Research vampire lore");
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
-
test("emits toolUseId and raw input on tool_use, toolUseId on tool_result", () => {
|
|
134
|
-
const messages = [
|
|
135
|
-
msg("user", [{ type: "text", text: "Do something" }]),
|
|
136
|
-
msg("assistant", [
|
|
137
|
-
{
|
|
138
|
-
type: "tool_use",
|
|
139
|
-
id: "t-abc",
|
|
140
|
-
name: "bash",
|
|
141
|
-
input: { command: "ls -la" },
|
|
142
|
-
},
|
|
143
|
-
]),
|
|
144
|
-
msg("user", [
|
|
145
|
-
{ type: "tool_result", tool_use_id: "t-abc", content: "total 0" },
|
|
146
|
-
]),
|
|
147
|
-
];
|
|
148
|
-
|
|
149
|
-
const result = parseSubagentMessages("sub-1", messages);
|
|
150
|
-
const toolUse = result.events.find((e) => e.type === "tool_use");
|
|
151
|
-
expect(toolUse).toBeDefined();
|
|
152
|
-
expect(toolUse!.toolUseId).toBe("t-abc");
|
|
153
|
-
expect(toolUse!.input).toEqual({ command: "ls -la" });
|
|
154
|
-
|
|
155
|
-
const toolResult = result.events.find((e) => e.type === "tool_result");
|
|
156
|
-
expect(toolResult).toBeDefined();
|
|
157
|
-
expect(toolResult!.toolUseId).toBe("t-abc");
|
|
158
|
-
});
|
|
159
|
-
|
|
160
133
|
test("includes messageId on text events from assistant messages", () => {
|
|
161
134
|
const messages = [
|
|
162
135
|
msg("user", [{ type: "text", text: "Do something" }]),
|
|
@@ -326,68 +326,3 @@ describe("SubagentManager terminal disposal", () => {
|
|
|
326
326
|
asInternals(manager).stopSweep();
|
|
327
327
|
});
|
|
328
328
|
});
|
|
329
|
-
|
|
330
|
-
describe("SubagentManager.abort usage", () => {
|
|
331
|
-
test("emits the conversation's latest usage on abort, not zeros", () => {
|
|
332
|
-
const manager = new SubagentManager();
|
|
333
|
-
const sent: ServerMessage[] = [];
|
|
334
|
-
const sender = (msg: ServerMessage) => sent.push(msg);
|
|
335
|
-
|
|
336
|
-
const subagentId = "sa-abort-usage";
|
|
337
|
-
// state.usage starts at {0,0,0}; the live (fake) conversation has accrued
|
|
338
|
-
// usage (makeFakeConversation → {100, 50, 0.005}). Wire `sender` as the
|
|
339
|
-
// stored parent sender so `setStatus` routes the terminal event through it.
|
|
340
|
-
injectFakeSubagent(manager, subagentId, makeState(subagentId), sender);
|
|
341
|
-
|
|
342
|
-
const aborted = manager.abort(subagentId, sender, undefined, {
|
|
343
|
-
suppressNotification: true,
|
|
344
|
-
});
|
|
345
|
-
expect(aborted).toBe(true);
|
|
346
|
-
|
|
347
|
-
const statusMsg = sent.find(
|
|
348
|
-
(m): m is Extract<ServerMessage, { type: "subagent_status_changed" }> =>
|
|
349
|
-
m.type === "subagent_status_changed",
|
|
350
|
-
);
|
|
351
|
-
expect(statusMsg).toBeDefined();
|
|
352
|
-
expect(statusMsg!.status).toBe("aborted");
|
|
353
|
-
// The emitted usage is the conversation's accrued total — NOT the {0,0,0}
|
|
354
|
-
// init — so the client doesn't flush the token panel to zero on stop.
|
|
355
|
-
expect(statusMsg!.usage).toEqual({
|
|
356
|
-
inputTokens: 100,
|
|
357
|
-
outputTokens: 50,
|
|
358
|
-
estimatedCost: 0.005,
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
asInternals(manager).stopSweep();
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
test("keeps the last-known state.usage when the conversation was already released", () => {
|
|
365
|
-
const manager = new SubagentManager();
|
|
366
|
-
const sent: ServerMessage[] = [];
|
|
367
|
-
const sender = (msg: ServerMessage) => sent.push(msg);
|
|
368
|
-
|
|
369
|
-
const subagentId = "sa-abort-no-conv";
|
|
370
|
-
// No live conversation (released), but state carries a last-known usage —
|
|
371
|
-
// the abort must surface that, not overwrite it.
|
|
372
|
-
const state = makeState(subagentId, {
|
|
373
|
-
usage: { inputTokens: 320, outputTokens: 80, estimatedCost: 0.004 },
|
|
374
|
-
});
|
|
375
|
-
injectFakeSubagent(manager, subagentId, state, sender, null);
|
|
376
|
-
|
|
377
|
-
manager.abort(subagentId, sender, undefined, {
|
|
378
|
-
suppressNotification: true,
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
const statusMsg = sent.find(
|
|
382
|
-
(m): m is Extract<ServerMessage, { type: "subagent_status_changed" }> =>
|
|
383
|
-
m.type === "subagent_status_changed",
|
|
384
|
-
);
|
|
385
|
-
expect(statusMsg!.usage).toEqual({
|
|
386
|
-
inputTokens: 320,
|
|
387
|
-
outputTokens: 80,
|
|
388
|
-
estimatedCost: 0.004,
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
asInternals(manager).stopSweep();
|
|
392
|
-
});
|
|
393
|
-
});
|
|
@@ -4,8 +4,6 @@ import { describe, expect, mock, test } from "bun:test";
|
|
|
4
4
|
|
|
5
5
|
// Mock conversation-crud before importing tool executors that depend on it.
|
|
6
6
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
7
|
-
setConversationProcessingStartedAt: () => {},
|
|
8
|
-
isConversationProcessing: () => false,
|
|
9
7
|
setConversationOriginChannelIfUnset: () => {},
|
|
10
8
|
updateConversationContextWindow: () => {},
|
|
11
9
|
deleteMessageById: () => {},
|
|
@@ -70,11 +70,8 @@ describe("SUBAGENT_ROLE_REGISTRY", () => {
|
|
|
70
70
|
expect(SUBAGENT_ROLE_REGISTRY.planner.allowedTools!).toContain("recall");
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
-
test(
|
|
74
|
-
|
|
75
|
-
expect(tools).not.toContain("bash");
|
|
76
|
-
expect(tools).not.toContain("host_bash");
|
|
77
|
-
expect(tools).toContain("code_search");
|
|
73
|
+
test('investigator includes "bash" for grep/find-based code and log investigation', () => {
|
|
74
|
+
expect(SUBAGENT_ROLE_REGISTRY.investigator.allowedTools!).toContain("bash");
|
|
78
75
|
});
|
|
79
76
|
|
|
80
77
|
test("investigator excludes file write tools (read-only investigation)", () => {
|
|
@@ -88,8 +85,6 @@ describe("SUBAGENT_ROLE_REGISTRY", () => {
|
|
|
88
85
|
expect(preamble).toContain("Root cause");
|
|
89
86
|
expect(preamble).toContain("Evidence");
|
|
90
87
|
expect(preamble).toContain("notify_parent");
|
|
91
|
-
expect(preamble).not.toContain("shell access");
|
|
92
|
-
expect(preamble).toContain("code_search");
|
|
93
88
|
});
|
|
94
89
|
|
|
95
90
|
test("no role references the old memory_recall tool name", () => {
|
|
@@ -3,8 +3,6 @@ import { mock } from "bun:test";
|
|
|
3
3
|
|
|
4
4
|
// Mock conversation-crud before importing tool executors that depend on it.
|
|
5
5
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
6
|
-
setConversationProcessingStartedAt: () => {},
|
|
7
|
-
isConversationProcessing: () => false,
|
|
8
6
|
setConversationOriginChannelIfUnset: () => {},
|
|
9
7
|
updateConversationContextWindow: () => {},
|
|
10
8
|
deleteMessageById: () => {},
|
|
@@ -29,8 +29,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
29
29
|
}),
|
|
30
30
|
}));
|
|
31
31
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
32
|
-
setConversationProcessingStartedAt: () => {},
|
|
33
|
-
isConversationProcessing: () => false,
|
|
34
32
|
setConversationOriginChannelIfUnset: () => {},
|
|
35
33
|
updateConversationContextWindow: () => {},
|
|
36
34
|
deleteMessageById: () => {},
|
|
@@ -50,8 +50,6 @@ const mockGetMessages = mock((_conversationId: string) => [
|
|
|
50
50
|
]);
|
|
51
51
|
|
|
52
52
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
53
|
-
setConversationProcessingStartedAt: () => {},
|
|
54
|
-
isConversationProcessing: () => false,
|
|
55
53
|
getMessages: mockGetMessages,
|
|
56
54
|
getConversation: (_id: string) => null,
|
|
57
55
|
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
@@ -78,8 +78,6 @@ mock.module("../permissions/checker.js", () => ({
|
|
|
78
78
|
}));
|
|
79
79
|
|
|
80
80
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
81
|
-
setConversationProcessingStartedAt: () => {},
|
|
82
|
-
isConversationProcessing: () => false,
|
|
83
81
|
createConversation: (title: string) => ({ id: "conversation-1", title }),
|
|
84
82
|
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
85
83
|
}));
|
|
@@ -17,7 +17,6 @@ const mockConfig = {
|
|
|
17
17
|
shellDefaultTimeoutSec: 120,
|
|
18
18
|
shellMaxTimeoutSec: 600,
|
|
19
19
|
permissionTimeoutSec: 300,
|
|
20
|
-
questionResponseTimeoutSec: 1800,
|
|
21
20
|
},
|
|
22
21
|
sandbox: {
|
|
23
22
|
enabled: false,
|
|
@@ -1301,31 +1300,27 @@ describe("ToolExecutionResult includes risk metadata from classifier assessment"
|
|
|
1301
1300
|
|
|
1302
1301
|
describe("computePerToolTimeoutMs ask_question budget", () => {
|
|
1303
1302
|
// Regression guard: ask_question blocks on user input inside execute() via
|
|
1304
|
-
// QuestionPrompter, which waits up to
|
|
1305
|
-
//
|
|
1306
|
-
//
|
|
1307
|
-
//
|
|
1303
|
+
// QuestionPrompter, which waits up to permissionTimeoutSec. The executor's
|
|
1304
|
+
// generic toolExecutionTimeoutSec wrapper must give ask_question a budget
|
|
1305
|
+
// strictly larger than that prompt timeout — otherwise the wrapper fires
|
|
1306
|
+
// first and orphans the still-pending prompt behind the confusing "may
|
|
1308
1307
|
// still be running in the background" error. These assertions fail if the
|
|
1309
|
-
// special case is removed and ask_question falls back to the generic budget
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
test("execution-timeout budget exceeds the prompt's own questionResponseTimeoutSec", () => {
|
|
1313
|
-
const { questionResponseTimeoutSec } = mockConfig.timeouts;
|
|
1308
|
+
// special case is removed and ask_question falls back to the generic budget.
|
|
1309
|
+
test("execution-timeout budget exceeds the prompt's own permissionTimeoutSec", () => {
|
|
1310
|
+
const { permissionTimeoutSec } = mockConfig.timeouts;
|
|
1314
1311
|
const askQuestionBudgetMs = computePerToolTimeoutMs("ask_question", {});
|
|
1315
1312
|
|
|
1316
|
-
expect(askQuestionBudgetMs).toBeGreaterThan(
|
|
1317
|
-
|
|
1318
|
-
);
|
|
1319
|
-
expect(askQuestionBudgetMs).toBe((questionResponseTimeoutSec + 5) * 1000);
|
|
1313
|
+
expect(askQuestionBudgetMs).toBeGreaterThan(permissionTimeoutSec * 1000);
|
|
1314
|
+
expect(askQuestionBudgetMs).toBe((permissionTimeoutSec + 5) * 1000);
|
|
1320
1315
|
});
|
|
1321
1316
|
|
|
1322
1317
|
test("the generic budget that would otherwise apply is shorter than the prompt timeout", () => {
|
|
1323
|
-
const {
|
|
1318
|
+
const { permissionTimeoutSec } = mockConfig.timeouts;
|
|
1324
1319
|
const genericBudgetMs = computePerToolTimeoutMs("some_other_tool", {});
|
|
1325
1320
|
|
|
1326
1321
|
// This is the collision the ask_question special case fixes: the generic
|
|
1327
1322
|
// execution-timeout budget is shorter than the prompter's own wait, so
|
|
1328
1323
|
// without the special case the wrapper trips first.
|
|
1329
|
-
expect(genericBudgetMs).toBeLessThan(
|
|
1324
|
+
expect(genericBudgetMs).toBeLessThan(permissionTimeoutSec * 1000);
|
|
1330
1325
|
});
|
|
1331
1326
|
});
|
|
@@ -60,8 +60,6 @@ const reserveMessageMock = mock(
|
|
|
60
60
|
const updateMessageContentMock = mock((_id: string, _content: string) => {});
|
|
61
61
|
|
|
62
62
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
63
|
-
setConversationProcessingStartedAt: () => {},
|
|
64
|
-
isConversationProcessing: () => false,
|
|
65
63
|
getConversation: () => null,
|
|
66
64
|
getMessageById: () => null,
|
|
67
65
|
updateMessageContent: updateMessageContentMock,
|
|
@@ -40,8 +40,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
40
40
|
}));
|
|
41
41
|
|
|
42
42
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
43
|
-
setConversationProcessingStartedAt: () => {},
|
|
44
|
-
isConversationProcessing: () => false,
|
|
45
43
|
addMessage: () => ({ id: "mock-msg-id" }),
|
|
46
44
|
getMessageById: () => null,
|
|
47
45
|
updateMessageContent: () => {},
|
|
@@ -43,8 +43,6 @@ let mockedRowContent = "";
|
|
|
43
43
|
const updates: Array<{ id: string; content: string }> = [];
|
|
44
44
|
|
|
45
45
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
46
|
-
setConversationProcessingStartedAt: () => {},
|
|
47
|
-
isConversationProcessing: () => false,
|
|
48
46
|
addMessage: () => ({ id: "mock-msg-id" }),
|
|
49
47
|
getMessageById: (id: string) =>
|
|
50
48
|
mockedRowContent ? { id, content: mockedRowContent } : null,
|