@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
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* and skipped (no silent provider-safe rewrite — operator must rename).
|
|
27
27
|
* - Multiple workspace tools register in a single batch.
|
|
28
28
|
*/
|
|
29
|
-
import { mkdirSync, rmSync,
|
|
29
|
+
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
30
30
|
import { tmpdir } from "node:os";
|
|
31
31
|
import { join } from "node:path";
|
|
32
32
|
import { afterAll, beforeEach, describe, expect, test } from "bun:test";
|
|
@@ -42,10 +42,7 @@ import {
|
|
|
42
42
|
registerTool,
|
|
43
43
|
} from "../tools/registry.js";
|
|
44
44
|
import type { Tool, ToolContext, ToolExecutionResult } from "../tools/types.js";
|
|
45
|
-
import {
|
|
46
|
-
__resetWorkspaceToolCacheForTesting,
|
|
47
|
-
loadWorkspaceTools,
|
|
48
|
-
} from "../tools/workspace-tools/loader.js";
|
|
45
|
+
import { loadWorkspaceTools } from "../tools/workspace-tools/loader.js";
|
|
49
46
|
|
|
50
47
|
// Per-test counter so each writeTool() call lands in a unique tempdir,
|
|
51
48
|
// defeating bun's per-URL ESM cache between tests. Without this, a
|
|
@@ -90,23 +87,6 @@ function writeRemovedSentinel(name: string): void {
|
|
|
90
87
|
writeFileSync(join(toolsDir, `${name}.removed`), "");
|
|
91
88
|
}
|
|
92
89
|
|
|
93
|
-
/** Delete `<workspaceDir>/tools/<name><ext>` (defaults to `.ts`). */
|
|
94
|
-
function removeToolFile(name: string, ext = ".ts"): void {
|
|
95
|
-
rmSync(join(currentWorkspaceDir, "tools", `${name}${ext}`), { force: true });
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Overwrite an existing tool file and bump its mtime into the future so the
|
|
100
|
-
* reconcile's mtime gate re-imports it even when the rewrite lands within
|
|
101
|
-
* the same millisecond as the original write.
|
|
102
|
-
*/
|
|
103
|
-
function rewriteTool(name: string, body: string, ext = ".ts"): void {
|
|
104
|
-
const path = join(currentWorkspaceDir, "tools", `${name}${ext}`);
|
|
105
|
-
writeFileSync(path, body);
|
|
106
|
-
const future = new Date(Date.now() + 5000);
|
|
107
|
-
utimesSync(path, future, future);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
90
|
function makeFakeCoreTool(name: string): Tool {
|
|
111
91
|
return {
|
|
112
92
|
name,
|
|
@@ -114,9 +94,6 @@ function makeFakeCoreTool(name: string): Tool {
|
|
|
114
94
|
category: "test",
|
|
115
95
|
defaultRiskLevel: RiskLevel.Low,
|
|
116
96
|
executionTarget: "sandbox",
|
|
117
|
-
// Match the finalized shape the registry stores (defaults filled), so
|
|
118
|
-
// `getCoreToolOverride(name)` toEqual comparisons hold after registration.
|
|
119
|
-
exclusive: false,
|
|
120
97
|
input_schema: { type: "object", properties: {}, required: [] },
|
|
121
98
|
async execute(
|
|
122
99
|
_input: Record<string, unknown>,
|
|
@@ -156,7 +133,6 @@ export default {
|
|
|
156
133
|
describe("workspace tool loader", () => {
|
|
157
134
|
beforeEach(() => {
|
|
158
135
|
__clearRegistryForTesting();
|
|
159
|
-
__resetWorkspaceToolCacheForTesting();
|
|
160
136
|
freshWorkspace();
|
|
161
137
|
});
|
|
162
138
|
|
|
@@ -340,173 +316,4 @@ export default 42;
|
|
|
340
316
|
const names = getWorkspaceToolNames().sort();
|
|
341
317
|
expect(names).toEqual(["alpha", "beta", "gamma"]);
|
|
342
318
|
});
|
|
343
|
-
|
|
344
|
-
// ── Reconcile-on-read behavior ─────────────────────────────────────────
|
|
345
|
-
//
|
|
346
|
-
// loadWorkspaceTools() is idempotent and re-derives registry state from
|
|
347
|
-
// disk on every call. These cases cover the deltas a repeat call applies,
|
|
348
|
-
// which is what replaces the old filesystem watcher.
|
|
349
|
-
|
|
350
|
-
test("repeat call with no disk changes is a no-op (does not throw or duplicate)", async () => {
|
|
351
|
-
writeTool("stable_tool", WELL_FORMED_BODY);
|
|
352
|
-
|
|
353
|
-
await loadWorkspaceTools();
|
|
354
|
-
// A second reconcile must not throw on the already-registered name —
|
|
355
|
-
// the mtime cache recognizes the unchanged file and skips re-import.
|
|
356
|
-
await loadWorkspaceTools();
|
|
357
|
-
|
|
358
|
-
expect(getTool("stable_tool")).toBeDefined();
|
|
359
|
-
expect(getWorkspaceToolNames()).toEqual(["stable_tool"]);
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
test("a file added after the first reconcile registers on the next", async () => {
|
|
363
|
-
writeTool("first", WELL_FORMED_BODY);
|
|
364
|
-
await loadWorkspaceTools();
|
|
365
|
-
expect(getWorkspaceToolNames()).toEqual(["first"]);
|
|
366
|
-
|
|
367
|
-
writeTool("second", WELL_FORMED_BODY);
|
|
368
|
-
await loadWorkspaceTools();
|
|
369
|
-
|
|
370
|
-
expect(getWorkspaceToolNames().sort()).toEqual(["first", "second"]);
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
test("a changed file is re-imported on the next reconcile", async () => {
|
|
374
|
-
writeTool("mutable", WELL_FORMED_BODY);
|
|
375
|
-
await loadWorkspaceTools();
|
|
376
|
-
expect(getTool("mutable")?.description).toBe("from workspace");
|
|
377
|
-
|
|
378
|
-
rewriteTool(
|
|
379
|
-
"mutable",
|
|
380
|
-
`
|
|
381
|
-
export default {
|
|
382
|
-
description: "edited in place",
|
|
383
|
-
defaultRiskLevel: "low",
|
|
384
|
-
input_schema: { type: "object", properties: {}, required: [] },
|
|
385
|
-
async execute() {
|
|
386
|
-
return { content: "edited", isError: false };
|
|
387
|
-
},
|
|
388
|
-
};
|
|
389
|
-
`,
|
|
390
|
-
);
|
|
391
|
-
await loadWorkspaceTools();
|
|
392
|
-
|
|
393
|
-
expect(getTool("mutable")?.description).toBe("edited in place");
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
test("a deleted net-new tool file is unregistered on the next reconcile", async () => {
|
|
397
|
-
writeTool("ephemeral", WELL_FORMED_BODY);
|
|
398
|
-
await loadWorkspaceTools();
|
|
399
|
-
expect(getTool("ephemeral")).toBeDefined();
|
|
400
|
-
|
|
401
|
-
removeToolFile("ephemeral");
|
|
402
|
-
await loadWorkspaceTools();
|
|
403
|
-
|
|
404
|
-
expect(getTool("ephemeral")).toBeUndefined();
|
|
405
|
-
expect(getWorkspaceToolNames()).toEqual([]);
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
test("deleting an override file restores the stashed core tool", async () => {
|
|
409
|
-
const core = makeFakeCoreTool("restore_me");
|
|
410
|
-
registerTool(core);
|
|
411
|
-
writeTool("restore_me", WELL_FORMED_BODY);
|
|
412
|
-
|
|
413
|
-
await loadWorkspaceTools();
|
|
414
|
-
expect(getToolOwner("restore_me")?.kind).toBe("workspace");
|
|
415
|
-
|
|
416
|
-
removeToolFile("restore_me");
|
|
417
|
-
await loadWorkspaceTools();
|
|
418
|
-
|
|
419
|
-
expect(getToolOwner("restore_me")).toBeUndefined();
|
|
420
|
-
expect(getTool("restore_me")).toEqual(core);
|
|
421
|
-
expect(getCoreToolOverride("restore_me")).toBeUndefined();
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
test("deleting a .removed sentinel restores the stripped core tool", async () => {
|
|
425
|
-
const core = makeFakeCoreTool("strip_then_restore");
|
|
426
|
-
registerTool(core);
|
|
427
|
-
writeRemovedSentinel("strip_then_restore");
|
|
428
|
-
|
|
429
|
-
await loadWorkspaceTools();
|
|
430
|
-
expect(getTool("strip_then_restore")).toBeUndefined();
|
|
431
|
-
expect(getStrippedCoreToolNames()).toContain("strip_then_restore");
|
|
432
|
-
|
|
433
|
-
removeToolFile("strip_then_restore", ".removed");
|
|
434
|
-
await loadWorkspaceTools();
|
|
435
|
-
|
|
436
|
-
expect(getTool("strip_then_restore")).toEqual(core);
|
|
437
|
-
expect(getStrippedCoreToolNames()).not.toContain("strip_then_restore");
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
test("the registered name is the filename stem, ignoring the file's own name field", async () => {
|
|
441
|
-
// The default export sets a different `name` — the loader must pin the
|
|
442
|
-
// registered name to the stem ("stem_wins") so the mtime cache and the
|
|
443
|
-
// unregister-on-delete path stay keyed by the same name.
|
|
444
|
-
writeTool(
|
|
445
|
-
"stem_wins",
|
|
446
|
-
`
|
|
447
|
-
export default {
|
|
448
|
-
name: "different_name",
|
|
449
|
-
description: "name field should be ignored",
|
|
450
|
-
defaultRiskLevel: "low",
|
|
451
|
-
input_schema: { type: "object", properties: {}, required: [] },
|
|
452
|
-
async execute() {
|
|
453
|
-
return { content: "ok", isError: false };
|
|
454
|
-
},
|
|
455
|
-
};
|
|
456
|
-
`,
|
|
457
|
-
);
|
|
458
|
-
|
|
459
|
-
await loadWorkspaceTools();
|
|
460
|
-
|
|
461
|
-
expect(getTool("stem_wins")).toBeDefined();
|
|
462
|
-
expect(getTool("different_name")).toBeUndefined();
|
|
463
|
-
expect(getWorkspaceToolNames()).toEqual(["stem_wins"]);
|
|
464
|
-
|
|
465
|
-
// Deleting the file unregisters by stem — no leaked "different_name".
|
|
466
|
-
removeToolFile("stem_wins");
|
|
467
|
-
await loadWorkspaceTools();
|
|
468
|
-
expect(getTool("stem_wins")).toBeUndefined();
|
|
469
|
-
expect(getTool("different_name")).toBeUndefined();
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
test("per-tool isolation on reconcile: a bad file does not drop a valid edited tool", async () => {
|
|
473
|
-
writeTool("good_edit", WELL_FORMED_BODY);
|
|
474
|
-
await loadWorkspaceTools();
|
|
475
|
-
expect(getTool("good_edit")?.description).toBe("from workspace");
|
|
476
|
-
|
|
477
|
-
// Add a file that throws at import, and edit the good tool, in the same
|
|
478
|
-
// reconcile. The broken file must not prevent the edited tool from
|
|
479
|
-
// re-registering.
|
|
480
|
-
writeTool("broken_now", `throw new Error("boom at import");`);
|
|
481
|
-
rewriteTool(
|
|
482
|
-
"good_edit",
|
|
483
|
-
`
|
|
484
|
-
export default {
|
|
485
|
-
description: "edited and still here",
|
|
486
|
-
defaultRiskLevel: "low",
|
|
487
|
-
input_schema: { type: "object", properties: {}, required: [] },
|
|
488
|
-
async execute() {
|
|
489
|
-
return { content: "ok", isError: false };
|
|
490
|
-
},
|
|
491
|
-
};
|
|
492
|
-
`,
|
|
493
|
-
);
|
|
494
|
-
await loadWorkspaceTools();
|
|
495
|
-
|
|
496
|
-
expect(getTool("broken_now")).toBeUndefined();
|
|
497
|
-
expect(getTool("good_edit")?.description).toBe("edited and still here");
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
test("an edit that breaks an existing tool keeps the prior registration", async () => {
|
|
501
|
-
writeTool("was_good", WELL_FORMED_BODY);
|
|
502
|
-
await loadWorkspaceTools();
|
|
503
|
-
expect(getTool("was_good")?.description).toBe("from workspace");
|
|
504
|
-
|
|
505
|
-
// Rewrite the file into something that throws at import. The prior,
|
|
506
|
-
// working registration must stay in place rather than being torn down.
|
|
507
|
-
rewriteTool("was_good", `throw new Error("now broken");`);
|
|
508
|
-
await loadWorkspaceTools();
|
|
509
|
-
|
|
510
|
-
expect(getTool("was_good")?.description).toBe("from workspace");
|
|
511
|
-
});
|
|
512
319
|
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests that the `workspace-tools-watcher` feature flag gates the dynamic
|
|
3
|
+
* hot-reload watcher in `WorkspaceToolsWatcher.start()`.
|
|
4
|
+
*
|
|
5
|
+
* The initial disk scan (`loadWorkspaceTools()`) is unconditional and lives
|
|
6
|
+
* elsewhere; this suite only covers whether the live `fs.watch` loop mounts.
|
|
7
|
+
*/
|
|
8
|
+
import { mkdirSync, rmSync } from "node:fs";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
12
|
+
|
|
13
|
+
import { clearFeatureFlagOverridesCache } from "../config/assistant-feature-flags.js";
|
|
14
|
+
import { WorkspaceToolsWatcher } from "../daemon/workspace-tools-watcher.js";
|
|
15
|
+
import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
|
|
16
|
+
|
|
17
|
+
const FLAG = "workspace-tools-watcher";
|
|
18
|
+
const TEST_BASE_DIR = join(
|
|
19
|
+
tmpdir(),
|
|
20
|
+
`vellum-workspace-tools-watcher-flag-test-${process.pid}-${Date.now()}`,
|
|
21
|
+
);
|
|
22
|
+
let caseCounter = 0;
|
|
23
|
+
|
|
24
|
+
function freshWorkspaceWithToolsDir(): void {
|
|
25
|
+
caseCounter += 1;
|
|
26
|
+
const dir = join(TEST_BASE_DIR, `case-${caseCounter}`);
|
|
27
|
+
mkdirSync(join(dir, "tools"), { recursive: true });
|
|
28
|
+
process.env.VELLUM_WORKSPACE_DIR = dir;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
WorkspaceToolsWatcher.resetForTests();
|
|
33
|
+
clearFeatureFlagOverridesCache();
|
|
34
|
+
freshWorkspaceWithToolsDir();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterEach(() => {
|
|
38
|
+
WorkspaceToolsWatcher.resetForTests();
|
|
39
|
+
clearFeatureFlagOverridesCache();
|
|
40
|
+
delete process.env.VELLUM_WORKSPACE_DIR;
|
|
41
|
+
rmSync(TEST_BASE_DIR, { recursive: true, force: true });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("WorkspaceToolsWatcher feature-flag gate", () => {
|
|
45
|
+
test("does not mount the watch loop when the flag is off", () => {
|
|
46
|
+
// GIVEN the workspace tools directory exists
|
|
47
|
+
// AND the watcher flag is disabled
|
|
48
|
+
setOverridesForTesting({ [FLAG]: false });
|
|
49
|
+
|
|
50
|
+
// WHEN the watcher starts
|
|
51
|
+
const watcher = WorkspaceToolsWatcher.getInstance();
|
|
52
|
+
watcher.start();
|
|
53
|
+
|
|
54
|
+
// THEN no fs.watch loop is mounted
|
|
55
|
+
expect(watcher.isWatchingForTests()).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("mounts the watch loop when the flag is on", () => {
|
|
59
|
+
// GIVEN the workspace tools directory exists
|
|
60
|
+
// AND the watcher flag is enabled
|
|
61
|
+
setOverridesForTesting({ [FLAG]: true });
|
|
62
|
+
|
|
63
|
+
// WHEN the watcher starts
|
|
64
|
+
const watcher = WorkspaceToolsWatcher.getInstance();
|
|
65
|
+
watcher.start();
|
|
66
|
+
|
|
67
|
+
// THEN a live fs.watch loop is mounted
|
|
68
|
+
expect(watcher.isWatchingForTests()).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
});
|
package/src/agent/loop.ts
CHANGED
|
@@ -625,20 +625,6 @@ export type LoopToolExecutor = (
|
|
|
625
625
|
activityMetadata?: ToolActivityMetadata;
|
|
626
626
|
}>;
|
|
627
627
|
|
|
628
|
-
/**
|
|
629
|
-
* The benign result returned for a sibling tool call that was deferred because
|
|
630
|
-
* an exclusive tool ran in the same turn. Phrased so the model treats it as a
|
|
631
|
-
* "not run yet" signal — read the exclusive tool's output, then re-issue this
|
|
632
|
-
* call if it is still the right next step.
|
|
633
|
-
*/
|
|
634
|
-
function deferredForExclusiveMessage(exclusiveToolName: string): string {
|
|
635
|
-
return (
|
|
636
|
-
`(not run: \`${exclusiveToolName}\` was called this turn and runs first, on its own, ` +
|
|
637
|
-
`so the rest of your tool calls were held back. Read its output, then call this tool ` +
|
|
638
|
-
`again if it is still the right next step.)`
|
|
639
|
-
);
|
|
640
|
-
}
|
|
641
|
-
|
|
642
628
|
export interface AgentLoopConstructorOptions {
|
|
643
629
|
/** LLM provider the loop issues every call through. */
|
|
644
630
|
provider: Provider;
|
|
@@ -648,14 +634,6 @@ export interface AgentLoopConstructorOptions {
|
|
|
648
634
|
tools?: ToolDefinition[];
|
|
649
635
|
toolExecutor?: LoopToolExecutor;
|
|
650
636
|
resolveTools?: (history: Message[]) => ToolDefinition[];
|
|
651
|
-
/**
|
|
652
|
-
* Decide whether a tool runs exclusively in its turn (see
|
|
653
|
-
* {@link ToolDefinition.exclusive}). When it returns true for a tool present
|
|
654
|
-
* in a multi-call turn, the loop runs only that tool and defers the siblings
|
|
655
|
-
* un-run. Injected by the conversation wiring, which can read the tool
|
|
656
|
-
* registry; lightweight loops that omit it never defer.
|
|
657
|
-
*/
|
|
658
|
-
isExclusiveTool?: (toolName: string) => boolean;
|
|
659
637
|
/**
|
|
660
638
|
* Conversation this loop drives. Scopes the loop-held compaction circuit
|
|
661
639
|
* breaker and is the source of truth the loop's pipeline contexts and
|
|
@@ -681,7 +659,6 @@ export class AgentLoop {
|
|
|
681
659
|
private tools: ToolDefinition[];
|
|
682
660
|
private resolveTools: ((history: Message[]) => ToolDefinition[]) | null;
|
|
683
661
|
private toolExecutor: LoopToolExecutor | null;
|
|
684
|
-
private isExclusiveTool: ((toolName: string) => boolean) | null;
|
|
685
662
|
|
|
686
663
|
/**
|
|
687
664
|
* Conversation this loop drives. Source of truth for the `conversationId`
|
|
@@ -711,7 +688,6 @@ export class AgentLoop {
|
|
|
711
688
|
tools,
|
|
712
689
|
toolExecutor,
|
|
713
690
|
resolveTools,
|
|
714
|
-
isExclusiveTool,
|
|
715
691
|
conversationId,
|
|
716
692
|
resolveConversationDir,
|
|
717
693
|
} = options;
|
|
@@ -721,7 +697,6 @@ export class AgentLoop {
|
|
|
721
697
|
this.tools = tools ?? [];
|
|
722
698
|
this.resolveTools = resolveTools ?? null;
|
|
723
699
|
this.toolExecutor = toolExecutor ?? null;
|
|
724
|
-
this.isExclusiveTool = isExclusiveTool ?? null;
|
|
725
700
|
this.conversationId = conversationId;
|
|
726
701
|
this.resolveConversationDir = resolveConversationDir ?? null;
|
|
727
702
|
this.compactionCircuit = new CompactionCircuit(this.conversationId);
|
|
@@ -1908,39 +1883,8 @@ export class AgentLoop {
|
|
|
1908
1883
|
"Tool execution start",
|
|
1909
1884
|
);
|
|
1910
1885
|
|
|
1911
|
-
// When an exclusive tool (e.g. the advisor) is among this turn's calls,
|
|
1912
|
-
// it must run alone: the model should incorporate its output before
|
|
1913
|
-
// acting on anything else. Run only the first exclusive call and defer
|
|
1914
|
-
// the siblings with a benign, un-run result so the model re-issues them
|
|
1915
|
-
// next turn if still needed. Every tool_use still gets a matching
|
|
1916
|
-
// tool_result, so history stays well-formed.
|
|
1917
|
-
const exclusiveBlock = this.isExclusiveTool
|
|
1918
|
-
? toolUseBlocks.find((block) => this.isExclusiveTool!(block.name))
|
|
1919
|
-
: undefined;
|
|
1920
|
-
const deferSiblings =
|
|
1921
|
-
exclusiveBlock !== undefined && toolUseBlocks.length > 1;
|
|
1922
|
-
if (deferSiblings) {
|
|
1923
|
-
rlog.info(
|
|
1924
|
-
{
|
|
1925
|
-
turn: toolUseTurns,
|
|
1926
|
-
exclusiveTool: exclusiveBlock!.name,
|
|
1927
|
-
deferred: toolUseBlocks
|
|
1928
|
-
.filter((block) => block !== exclusiveBlock)
|
|
1929
|
-
.map((block) => block.name),
|
|
1930
|
-
},
|
|
1931
|
-
"Exclusive tool present — running it alone and deferring sibling tool calls this turn",
|
|
1932
|
-
);
|
|
1933
|
-
}
|
|
1934
|
-
|
|
1935
1886
|
const toolExecutionPromise = Promise.all(
|
|
1936
1887
|
toolUseBlocks.map(async (toolUse) => {
|
|
1937
|
-
if (deferSiblings && toolUse !== exclusiveBlock) {
|
|
1938
|
-
const result: Awaited<ReturnType<LoopToolExecutor>> = {
|
|
1939
|
-
content: deferredForExclusiveMessage(exclusiveBlock!.name),
|
|
1940
|
-
isError: false,
|
|
1941
|
-
};
|
|
1942
|
-
return { toolUse, result };
|
|
1943
|
-
}
|
|
1944
1888
|
const result = await this.toolExecutor!(
|
|
1945
1889
|
toolUse.name,
|
|
1946
1890
|
toolUse.input,
|
package/src/api/index.ts
CHANGED
|
@@ -11,7 +11,6 @@ import { ConfirmationRequestEventSchema } from "./events/confirmation-request.js
|
|
|
11
11
|
import { ContactRequestEventSchema } from "./events/contact-request.js";
|
|
12
12
|
import { ConversationErrorEventSchema } from "./events/conversation-error.js";
|
|
13
13
|
import { ConversationListInvalidatedEventSchema } from "./events/conversation-list-invalidated.js";
|
|
14
|
-
import { ConversationNoticeEventSchema } from "./events/conversation-notice.js";
|
|
15
14
|
import { ConversationTitleUpdatedEventSchema } from "./events/conversation-title-updated.js";
|
|
16
15
|
import { DiskPressureStatusChangedEventSchema } from "./events/disk-pressure-status-changed.js";
|
|
17
16
|
import { DocumentCommentCreatedEventSchema } from "./events/document-comment-created.js";
|
|
@@ -62,10 +61,6 @@ export {
|
|
|
62
61
|
CALL_SITE_COMPACTION_AGENT,
|
|
63
62
|
CALL_SITE_SYNTHETIC_AGENT_ERROR_MESSAGE,
|
|
64
63
|
} from "./constants/call-sites.js";
|
|
65
|
-
export {
|
|
66
|
-
SSE_REPLAY_RING_AGE_LIMIT_MS,
|
|
67
|
-
SSE_REPLAY_RING_COUNT_LIMIT,
|
|
68
|
-
} from "./constants/sse-replay.js";
|
|
69
64
|
export { DEFAULT_TOOL_EXECUTION_TIMEOUT_SEC } from "./constants/tool-execution.js";
|
|
70
65
|
export {
|
|
71
66
|
type AssistantActivityAnchor,
|
|
@@ -139,11 +134,6 @@ export {
|
|
|
139
134
|
type ConversationListInvalidatedReason,
|
|
140
135
|
ConversationListInvalidatedReasonSchema,
|
|
141
136
|
} from "./events/conversation-list-invalidated.js";
|
|
142
|
-
export {
|
|
143
|
-
type ConversationNoticeEvent,
|
|
144
|
-
ConversationNoticeEventSchema,
|
|
145
|
-
ConversationNoticeSourceSchema,
|
|
146
|
-
} from "./events/conversation-notice.js";
|
|
147
137
|
export {
|
|
148
138
|
type ConversationTitleUpdatedEvent,
|
|
149
139
|
ConversationTitleUpdatedEventSchema,
|
|
@@ -440,8 +430,6 @@ export {
|
|
|
440
430
|
LlmContextResponseSchema,
|
|
441
431
|
} from "./responses/llm-context-response.js";
|
|
442
432
|
export {
|
|
443
|
-
type LLMCallError,
|
|
444
|
-
LLMCallErrorSchema,
|
|
445
433
|
type LLMCallSummary,
|
|
446
434
|
LLMCallSummarySchema,
|
|
447
435
|
type LLMContextSection,
|
|
@@ -483,12 +471,7 @@ export {
|
|
|
483
471
|
type WorkflowLeaf,
|
|
484
472
|
WorkflowLeafSchema,
|
|
485
473
|
} from "./responses/workflow-journal.js";
|
|
486
|
-
export {
|
|
487
|
-
type CardSurfaceData,
|
|
488
|
-
CardSurfaceDataSchema,
|
|
489
|
-
type FileUploadSurfaceData,
|
|
490
|
-
FileUploadSurfaceDataSchema,
|
|
491
|
-
} from "./surfaces.js";
|
|
474
|
+
export { type CardSurfaceData, CardSurfaceDataSchema } from "./surfaces.js";
|
|
492
475
|
|
|
493
476
|
/**
|
|
494
477
|
* Canonical SSE event schema for the assistant runtime.
|
|
@@ -515,7 +498,6 @@ export const AssistantEventSchema = z.discriminatedUnion("type", [
|
|
|
515
498
|
ContactRequestEventSchema,
|
|
516
499
|
ConversationErrorEventSchema,
|
|
517
500
|
ConversationListInvalidatedEventSchema,
|
|
518
|
-
ConversationNoticeEventSchema,
|
|
519
501
|
ConversationTitleUpdatedEventSchema,
|
|
520
502
|
DiskPressureStatusChangedEventSchema,
|
|
521
503
|
DocumentCommentCreatedEventSchema,
|
|
@@ -67,34 +67,6 @@ export const LLMContextSectionSchema = z.object({
|
|
|
67
67
|
|
|
68
68
|
export type LLMContextSection = z.infer<typeof LLMContextSectionSchema>;
|
|
69
69
|
|
|
70
|
-
/**
|
|
71
|
-
* Structured provider/transport error recorded when an LLM call was
|
|
72
|
-
* rejected before producing a response. Mirrors the on-disk
|
|
73
|
-
* `responsePayload.error` shape written by
|
|
74
|
-
* `buildProviderErrorResponsePayload` — the inspector branches on the
|
|
75
|
-
* presence of this field to render a failed call distinctly (failure
|
|
76
|
-
* banner in the Response tab, $0.00 cost in the rail, etc.) instead of
|
|
77
|
-
* the generic "section rendering unavailable" fallback.
|
|
78
|
-
*
|
|
79
|
-
* Every field is optional because the serializer degrades a plain
|
|
80
|
-
* `Error` down to just `{ name, message }`; only the wrapper object is
|
|
81
|
-
* guaranteed.
|
|
82
|
-
*/
|
|
83
|
-
export const LLMCallErrorSchema = z.object({
|
|
84
|
-
name: z.string().nullish(),
|
|
85
|
-
message: z.string().nullish(),
|
|
86
|
-
code: z.string().nullish(),
|
|
87
|
-
provider: z.string().nullish(),
|
|
88
|
-
statusCode: z.number().nullish(),
|
|
89
|
-
retryAfterMs: z.number().nullish(),
|
|
90
|
-
apiErrorCode: z.string().nullish(),
|
|
91
|
-
apiErrorType: z.string().nullish(),
|
|
92
|
-
apiErrorParam: z.string().nullish(),
|
|
93
|
-
requestId: z.string().nullish(),
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
export type LLMCallError = z.infer<typeof LLMCallErrorSchema>;
|
|
97
|
-
|
|
98
70
|
/**
|
|
99
71
|
* One LLM request log row.
|
|
100
72
|
*
|
|
@@ -116,7 +88,6 @@ export const LLMRequestLogEntrySchema = z.object({
|
|
|
116
88
|
responseSections: z.array(LLMContextSectionSchema).nullish(),
|
|
117
89
|
agentLoopExitReason: z.string().nullish(),
|
|
118
90
|
callSite: z.string().nullish(),
|
|
119
|
-
error: LLMCallErrorSchema.nullish(),
|
|
120
91
|
});
|
|
121
92
|
|
|
122
93
|
export type LLMRequestLogEntry = z.infer<typeof LLMRequestLogEntrySchema>;
|
|
@@ -31,23 +31,6 @@ export const SubagentDetailEventSchema = z.object({
|
|
|
31
31
|
toolName: z.string().optional(),
|
|
32
32
|
isError: z.boolean().optional(),
|
|
33
33
|
messageId: z.string().optional(),
|
|
34
|
-
/**
|
|
35
|
-
* Tool-call id — the `tool_use.id` on a tool-call event and the referencing
|
|
36
|
-
* `tool_use_id` on its tool-result event, in the daemon's canonical
|
|
37
|
-
* content-block format. That format is provider-agnostic: every provider
|
|
38
|
-
* (Anthropic, OpenAI, Gemini, …) normalizes its native tool calls into these
|
|
39
|
-
* `tool_use`/`tool_result` blocks (see `providers/types.ts`), so this id is
|
|
40
|
-
* present regardless of which model produced the call. Lets the web client
|
|
41
|
-
* pair a result with its call and key the nested tool-detail view, so tool
|
|
42
|
-
* pills on reloaded/history subagents are clickable (not just live ones).
|
|
43
|
-
*/
|
|
44
|
-
toolUseId: z.string().optional(),
|
|
45
|
-
/**
|
|
46
|
-
* Raw tool input object on tool-call events. (`content` also carries a
|
|
47
|
-
* JSON-stringified copy for back-compat / label derivation.) Surfaced in the
|
|
48
|
-
* tool-detail view's input section.
|
|
49
|
-
*/
|
|
50
|
-
input: z.record(z.string(), z.unknown()).optional(),
|
|
51
34
|
});
|
|
52
35
|
|
|
53
36
|
export type SubagentDetailEvent = z.infer<typeof SubagentDetailEventSchema>;
|
package/src/api/surfaces.ts
CHANGED
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
* normalizer *supports* — anything the model sends outside these fields is
|
|
12
12
|
* dropped (and logged) there, which is how we learn the shapes to recover.
|
|
13
13
|
*
|
|
14
|
-
* Card
|
|
15
|
-
* hand-written interfaces in
|
|
16
|
-
* migration.
|
|
14
|
+
* Card is the first surface type migrated to a canonical schema; the remaining
|
|
15
|
+
* types still live as hand-written interfaces in
|
|
16
|
+
* `daemon/message-types/surfaces.ts` pending migration.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { z } from "zod";
|
|
@@ -31,39 +31,3 @@ export const CardSurfaceDataSchema = z.object({
|
|
|
31
31
|
templateData: z.record(z.string(), z.unknown()).optional(),
|
|
32
32
|
});
|
|
33
33
|
export type CardSurfaceData = z.infer<typeof CardSurfaceDataSchema>;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Accepted MIME-type / extension patterns for a `file_upload` surface.
|
|
37
|
-
*
|
|
38
|
-
* The renderer consumes this as a `string[]` — it calls `.join`/`.some`/
|
|
39
|
-
* `.length` on the value — but the model may emit a single comma-joined string
|
|
40
|
-
* ("image/*, application/pdf") or a bare string. Coercing every shape to a
|
|
41
|
-
* clean `string[]` keeps that array invariant intact: a string is split on
|
|
42
|
-
* commas; array entries are stringified and trimmed; blanks and any non-array
|
|
43
|
-
* value collapse to `undefined` (no restriction).
|
|
44
|
-
*/
|
|
45
|
-
const FileUploadAcceptedTypesSchema = z.preprocess((value) => {
|
|
46
|
-
const items =
|
|
47
|
-
typeof value === "string"
|
|
48
|
-
? value.split(",")
|
|
49
|
-
: Array.isArray(value)
|
|
50
|
-
? value
|
|
51
|
-
: [];
|
|
52
|
-
const cleaned = items
|
|
53
|
-
.map((item) =>
|
|
54
|
-
typeof item === "string" || typeof item === "number"
|
|
55
|
-
? String(item).trim()
|
|
56
|
-
: "",
|
|
57
|
-
)
|
|
58
|
-
.filter((item) => item.length > 0);
|
|
59
|
-
return cleaned.length > 0 ? cleaned : undefined;
|
|
60
|
-
}, z.array(z.string()).optional());
|
|
61
|
-
|
|
62
|
-
export const FileUploadSurfaceDataSchema = z.object({
|
|
63
|
-
prompt: z.coerce.string().optional(),
|
|
64
|
-
acceptedTypes: FileUploadAcceptedTypesSchema,
|
|
65
|
-
/** A non-positive or non-numeric value is dropped rather than rejecting the surface. */
|
|
66
|
-
maxFiles: z.coerce.number().int().positive().optional().catch(undefined),
|
|
67
|
-
maxSizeBytes: z.coerce.number().positive().optional().catch(undefined),
|
|
68
|
-
});
|
|
69
|
-
export type FileUploadSurfaceData = z.infer<typeof FileUploadSurfaceDataSchema>;
|
|
@@ -36,7 +36,6 @@ import { deliverChannelReply } from "../runtime/gateway-client.js";
|
|
|
36
36
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
37
37
|
import { TC_GRANT_WAIT_MAX_MS } from "../tools/tool-approval-handler.js";
|
|
38
38
|
import { getLogger } from "../util/logger.js";
|
|
39
|
-
import { resolveDeliverCallbackUrlForChannel } from "./guardian-channel-delivery.js";
|
|
40
39
|
|
|
41
40
|
const log = getLogger("guardian-request-resolvers");
|
|
42
41
|
|
|
@@ -243,6 +242,17 @@ export type ResolverResult =
|
|
|
243
242
|
}
|
|
244
243
|
| { ok: false; reason: string };
|
|
245
244
|
|
|
245
|
+
function resolveDeliverCallbackUrlForChannel(channel: string): string | null {
|
|
246
|
+
switch (channel) {
|
|
247
|
+
case "telegram":
|
|
248
|
+
case "whatsapp":
|
|
249
|
+
case "slack":
|
|
250
|
+
return `/deliver/${channel}`;
|
|
251
|
+
default:
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
246
256
|
/** Interface that kind-specific resolvers implement. */
|
|
247
257
|
export interface GuardianRequestResolver {
|
|
248
258
|
/** The request kind this resolver handles (matches canonical_guardian_requests.kind). */
|