@vellumai/assistant 0.10.2 → 0.10.3-dev.202606252046.9075fd5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lock +20 -0
- package/docs/workspace-tools.md +42 -33
- package/eslint-rules/cli-no-daemon-internals.js +6 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +31 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +44 -0
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +48 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +14 -0
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +17 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +28 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +41 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/openapi.yaml +196 -56
- package/package.json +4 -1
- package/scripts/test.sh +36 -15
- package/src/__tests__/actor-token-service.test.ts +36 -14
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +83 -31
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
- package/src/__tests__/annotate-activity-metadata.test.ts +2 -0
- package/src/__tests__/annotate-risk-options.test.ts +2 -0
- package/src/__tests__/approval-cascade.test.ts +2 -0
- package/src/__tests__/assistant-attachments.test.ts +42 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -0
- package/src/__tests__/btw-routes.test.ts +2 -0
- package/src/__tests__/build-persisted-content.test.ts +2 -0
- package/src/__tests__/call-controller.test.ts +19 -0
- package/src/__tests__/channel-approval-routes.test.ts +21 -26
- package/src/__tests__/channel-delivery-store.test.ts +28 -0
- package/src/__tests__/channel-guardian.test.ts +164 -78
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +11 -19
- package/src/__tests__/channel-reply-delivery.test.ts +2 -0
- package/src/__tests__/code-search-tool.test.ts +585 -0
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/compaction-ledger-store.test.ts +128 -0
- package/src/__tests__/compaction.benchmark.test.ts +2 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +2 -0
- package/src/__tests__/compactor-low-watermark-cut.test.ts +2 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +2 -0
- package/src/__tests__/compactor-summary-call-truncation.test.ts +2 -0
- package/src/__tests__/compactor-web-search-strip.test.ts +2 -0
- package/src/__tests__/config-loader-backfill.test.ts +123 -10
- package/src/__tests__/config-schema.test.ts +1 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +31 -29
- package/src/__tests__/consult-deadline.test.ts +60 -0
- package/src/__tests__/contact-store-interaction-info.test.ts +156 -0
- package/src/__tests__/contact-store-user-file.test.ts +7 -10
- package/src/__tests__/contacts-relay-reads.test.ts +19 -24
- package/src/__tests__/contacts-write.test.ts +0 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop.test.ts +134 -0
- package/src/__tests__/conversation-analysis-routes.test.ts +2 -0
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +2 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +9 -11
- package/src/__tests__/conversation-confirmation-signals.test.ts +2 -0
- package/src/__tests__/conversation-fork-crud.test.ts +354 -24
- package/src/__tests__/conversation-history-web-search.test.ts +2 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +2 -0
- package/src/__tests__/conversation-load-history-stripped.test.ts +2 -0
- package/src/__tests__/conversation-pairing.test.ts +2 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
- package/src/__tests__/conversation-process-callsite.test.ts +2 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
- package/src/__tests__/conversation-queue.test.ts +91 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +14 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +14 -0
- package/src/__tests__/conversation-slash-queue.test.ts +2 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
- package/src/__tests__/conversation-speed-override.test.ts +2 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +29 -0
- package/src/__tests__/conversation-title-service.test.ts +2 -0
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +47 -0
- package/src/__tests__/conversation-usage.test.ts +2 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/db-compaction-events-migration.test.ts +129 -0
- package/src/__tests__/db-migration-rollback.test.ts +205 -171
- package/src/__tests__/db-test-helpers.ts +5 -4
- package/src/__tests__/delete-propagation.test.ts +5 -3
- package/src/__tests__/deterministic-verification-control-plane.test.ts +4 -2
- package/src/__tests__/disk-pressure-guard.test.ts +41 -0
- package/src/__tests__/dm-backfill.test.ts +6 -4
- package/src/__tests__/dm-persistence.test.ts +2 -0
- package/src/__tests__/emit-signal-routing-intent.test.ts +7 -6
- package/src/__tests__/events-dev-bypass-actor.test.ts +7 -1
- package/src/__tests__/exploration-drift-hook.test.ts +3 -2
- package/src/__tests__/filing-service.test.ts +2 -0
- package/src/__tests__/guardian-binding-drift-heal.test.ts +104 -19
- package/src/__tests__/guardian-dispatch.test.ts +140 -1
- package/src/__tests__/guardian-expiry-notifier.test.ts +282 -0
- package/src/__tests__/guardian-outbound-http.test.ts +13 -0
- package/src/__tests__/guardian-routing-state.test.ts +6 -10
- package/src/__tests__/heartbeat-disk-pressure.test.ts +2 -0
- package/src/__tests__/heartbeat-service.test.ts +2 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +46 -19
- package/src/__tests__/helpers/create-guardian-binding.ts +15 -23
- package/src/__tests__/helpers/mock-logger.ts +1 -0
- package/src/__tests__/helpers/seed-contact-channel.ts +96 -0
- package/src/__tests__/host-app-control-routes.test.ts +24 -30
- package/src/__tests__/host-bash-routes.test.ts +31 -41
- package/src/__tests__/host-browser-routes.test.ts +26 -32
- package/src/__tests__/host-cu-routes-targeted.test.ts +25 -33
- package/src/__tests__/host-file-routes-targeted.test.ts +40 -52
- package/src/__tests__/host-transfer-routes-targeted.test.ts +31 -43
- package/src/__tests__/http-user-message-parity.test.ts +290 -8
- package/src/__tests__/inbound-invite-redemption.test.ts +115 -10
- package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/invite-redemption-service.test.ts +471 -53
- package/src/__tests__/invite-routes-http.test.ts +34 -0
- package/src/__tests__/invite-service-ipc.test.ts +65 -2
- package/src/__tests__/llm-context-normalization.test.ts +105 -0
- package/src/__tests__/llm-request-log-error-payload.test.ts +71 -9
- package/src/__tests__/llm-usage-store.test.ts +25 -0
- package/src/__tests__/mcp-config-secret-boundary.test.ts +392 -0
- package/src/__tests__/mcp-health-check.test.ts +2 -1
- package/src/__tests__/media-stream-server-integration.test.ts +127 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +2 -0
- package/src/__tests__/messaging-send-tool.test.ts +2 -0
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +275 -5
- package/src/__tests__/native-web-search.test.ts +2 -0
- package/src/__tests__/non-member-access-request.test.ts +191 -17
- package/src/__tests__/notification-broadcaster.test.ts +4 -0
- package/src/__tests__/notification-decision-recipient-context.test.ts +33 -32
- package/src/__tests__/notification-deep-link.test.ts +6 -0
- package/src/__tests__/notification-guardian-path.test.ts +19 -0
- package/src/__tests__/onboarding-persona-write.test.ts +52 -22
- package/src/__tests__/openai-provider.test.ts +22 -12
- package/src/__tests__/openai-responses-provider.test.ts +12 -2
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/pending-interactions-resolved-event.test.ts +7 -4
- package/src/__tests__/persist-onboarding-artifacts.test.ts +1 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
- package/src/__tests__/persona-resolver.test.ts +75 -45
- package/src/__tests__/plugin-bootstrap.test.ts +21 -83
- package/src/__tests__/plugin-disabled-state.test.ts +190 -0
- package/src/__tests__/plugin-pipeline.test.ts +96 -0
- package/src/__tests__/plugin-route-contribution.test.ts +6 -19
- package/src/__tests__/plugin-tool-contribution.test.ts +5 -20
- package/src/__tests__/plugin-types.test.ts +2 -4
- package/src/__tests__/process-message-background-slack.test.ts +2 -0
- package/src/__tests__/process-message-display-content.test.ts +2 -0
- package/src/__tests__/provider-error-scenarios.test.ts +5 -4
- package/src/__tests__/provider-usage-tracking.test.ts +39 -0
- package/src/__tests__/reaction-intercept-cold-cache-warm.test.ts +135 -0
- package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +158 -0
- package/src/__tests__/reaction-persistence.test.ts +51 -4
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +2 -0
- package/src/__tests__/registry.test.ts +4 -1
- package/src/__tests__/relay-server.test.ts +758 -32
- package/src/__tests__/runtime-attachment-metadata.test.ts +9 -12
- package/src/__tests__/secret-ingress-http.test.ts +14 -0
- package/src/__tests__/send-endpoint-busy.test.ts +30 -8
- package/src/__tests__/settings-routes.test.ts +32 -0
- package/src/__tests__/skills.test.ts +44 -0
- package/src/__tests__/slack-inbound-verification.test.ts +47 -2
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +79 -0
- package/src/__tests__/steer-on-enqueue-question.test.ts +181 -0
- package/src/__tests__/stt-hints.test.ts +49 -15
- package/src/__tests__/subagent-detail.test.ts +27 -0
- package/src/__tests__/subagent-disposal.test.ts +65 -0
- package/src/__tests__/subagent-fork-prompt-role.test.ts +195 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +6 -7
- package/src/__tests__/subagent-notify-parent.test.ts +2 -0
- package/src/__tests__/subagent-role-registry.test.ts +24 -6
- package/src/__tests__/subagent-spawn-and-await.test.ts +546 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +2 -0
- package/src/__tests__/subagent-tools.test.ts +398 -1
- package/src/__tests__/suggestion-routes.test.ts +2 -0
- package/src/__tests__/thread-backfill.test.ts +3 -3
- package/src/__tests__/title-generate-hook.test.ts +2 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -0
- package/src/__tests__/tool-executor.test.ts +16 -11
- package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +2 -0
- package/src/__tests__/tool-start-timestamp.test.ts +2 -0
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +37 -51
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +12 -12
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -7
- package/src/__tests__/trusted-contact-multichannel.test.ts +16 -7
- package/src/__tests__/trusted-contact-verification.test.ts +79 -54
- package/src/__tests__/twilio-routes.test.ts +96 -0
- package/src/__tests__/ui-file-upload-surface.test.ts +86 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -0
- package/src/__tests__/voice-guardian-cold-cache-warm.test.ts +137 -0
- package/src/__tests__/voice-invite-redemption.test.ts +216 -20
- package/src/__tests__/web-search-backend-failure.test.ts +2 -0
- package/src/__tests__/workspace-migration-102-preserve-heartbeat-enabled-for-existing-workspaces.test.ts +3 -3
- package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +208 -0
- package/src/__tests__/workspace-migration-112-remove-advisor-callsite-override.test.ts +170 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +196 -238
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +14 -35
- package/src/__tests__/workspace-tool-loader.test.ts +195 -2
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +35 -47
- package/src/agent/loop-exclusive-tool.test.ts +154 -0
- package/src/agent/loop-native-web-search.test.ts +200 -0
- package/src/agent/loop.ts +164 -1
- package/src/api/constants/sse-replay.ts +41 -0
- package/src/api/events/conversation-notice.ts +26 -0
- package/src/api/index.ts +19 -1
- package/src/api/responses/llm-request-log-entry.ts +29 -0
- package/src/api/responses/subagent-detail.ts +17 -0
- package/src/api/surfaces.ts +39 -3
- package/src/approvals/guardian-channel-delivery.ts +30 -0
- package/src/approvals/guardian-expiry-notifier.ts +148 -0
- package/src/approvals/guardian-request-resolvers.ts +17 -15
- package/src/calls/__tests__/relay-setup-router.test.ts +267 -17
- package/src/calls/call-domain.ts +3 -3
- package/src/calls/guardian-dispatch.ts +14 -9
- package/src/calls/inbound-trust-reader.ts +24 -2
- package/src/calls/media-stream-server.ts +21 -0
- package/src/calls/relay-access-wait.ts +6 -6
- package/src/calls/relay-server.ts +188 -51
- package/src/calls/relay-setup-router.ts +47 -17
- package/src/calls/relay-verification.ts +4 -4
- package/src/calls/stt-hints.ts +9 -12
- package/src/calls/twilio-routes.ts +14 -4
- package/src/channels/types.ts +10 -20
- package/src/cli/commands/__tests__/cache.test.ts +8 -1
- package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -0
- package/src/cli/commands/cache.ts +194 -181
- package/src/cli/commands/contacts.ts +10 -7
- package/src/cli/commands/db/__tests__/repair.test.ts +6 -5
- package/src/cli/commands/db/status.ts +37 -1
- package/src/cli/commands/mcp.ts +252 -218
- package/src/cli/commands/memory/__tests__/worker.test.ts +432 -0
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/worker.ts +242 -0
- package/src/cli/commands/plugins.ts +125 -13
- package/src/cli/lib/__tests__/install-from-github.test.ts +102 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +160 -1
- package/src/cli/lib/__tests__/publish-plugin.test.ts +404 -0
- package/src/cli/lib/list-installed-plugins.ts +179 -1
- package/src/cli/lib/publish-plugin.ts +633 -0
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +143 -0
- package/src/config/__tests__/sync-gated-profiles.test.ts +16 -10
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +27 -17
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +13 -3
- package/src/config/bundled-skills/subagent/SKILL.md +17 -2
- package/src/config/bundled-skills/subagent/TOOLS.json +5 -4
- package/src/config/call-site-defaults.ts +0 -6
- package/src/config/feature-flag-registry.json +5 -13
- package/src/config/llm-resolver.ts +0 -3
- package/src/config/loader.ts +38 -5
- package/src/config/prune-seeded-callsite-defaults.ts +110 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +0 -7
- package/src/config/schemas/heartbeat.ts +2 -5
- package/src/config/schemas/llm.ts +3 -12
- package/src/config/schemas/memory-lifecycle.ts +12 -0
- package/src/config/schemas/memory-v3.ts +7 -0
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/timeouts.ts +8 -0
- package/src/config/seed-inference-profiles.ts +30 -34
- package/src/config/skills.ts +27 -5
- package/src/config/sync-gated-profiles.ts +12 -16
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +128 -0
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +312 -0
- package/src/contacts/__tests__/member-write-relay.test.ts +226 -0
- package/src/contacts/contact-store.ts +27 -237
- package/src/contacts/contacts-write.ts +18 -55
- package/src/contacts/gateway-channel-read.ts +51 -0
- package/src/contacts/guardian-delivery-reader.ts +223 -0
- package/src/contacts/member-write-relay.ts +183 -0
- package/src/contacts/types.ts +3 -15
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +35 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +0 -44
- package/src/daemon/assistant-attachments.ts +27 -4
- package/src/daemon/conversation-agent-loop.ts +28 -0
- package/src/daemon/conversation-notices.ts +60 -0
- package/src/daemon/conversation-process.ts +35 -16
- package/src/daemon/conversation-surfaces.ts +111 -38
- package/src/daemon/conversation-tool-setup.ts +71 -30
- package/src/daemon/conversation.ts +23 -1
- package/src/daemon/disk-pressure-guard.ts +12 -2
- package/src/daemon/event-loop-watchdog.ts +28 -1
- package/src/daemon/external-plugins-bootstrap.ts +17 -41
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -2
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +25 -2
- package/src/daemon/handlers/__tests__/config-channels.test.ts +220 -0
- package/src/daemon/handlers/config-a2a.ts +6 -14
- package/src/daemon/handlers/config-channels.ts +67 -26
- package/src/daemon/handlers/conversations.ts +77 -0
- package/src/daemon/lifecycle.ts +16 -0
- package/src/daemon/mcp-reload-service.ts +10 -0
- package/src/daemon/memory-v2-startup.test.ts +72 -0
- package/src/daemon/memory-v2-startup.ts +87 -19
- package/src/daemon/message-types/conversations.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +12 -12
- package/src/daemon/server.ts +0 -4
- package/src/daemon/shutdown-handlers.ts +20 -0
- package/src/daemon/tool-setup-types.ts +9 -0
- package/src/heartbeat/heartbeat-service.ts +5 -0
- package/src/home/relationship-state-writer.ts +5 -0
- package/src/hooks/hook-loader.ts +341 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
- package/src/ipc/assistant-server.ts +2 -2
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +1 -0
- package/src/mcp/client.ts +15 -1
- package/src/mcp/mcp-auth-orchestrator.ts +6 -1
- package/src/mcp/mcp-header-store.ts +134 -0
- package/src/mcp/mcp-oauth-provider.ts +19 -8
- package/src/memory/__tests__/301-create-watchdog-events.test.ts +110 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
- package/src/memory/__tests__/prompt-override.test.ts +192 -0
- package/src/memory/__tests__/watchdog-events-store.test.ts +161 -0
- package/src/memory/compaction-ledger-store.ts +107 -0
- package/src/memory/conversation-crud.ts +129 -61
- package/src/memory/db-connection.ts +22 -3
- package/src/memory/db-init.ts +37 -503
- package/src/memory/db-singleton.ts +6 -4
- package/src/memory/jobs-worker.ts +104 -0
- package/src/memory/llm-request-log-store.ts +26 -1
- package/src/memory/llm-usage-store.ts +48 -20
- package/src/memory/memory-retrospective-job.ts +14 -8
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +152 -56
- package/src/memory/migrations/300-add-processing-started-at.ts +30 -0
- package/src/memory/migrations/301-create-watchdog-events.ts +45 -0
- package/src/memory/migrations/302-create-compaction-events.ts +107 -0
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +297 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
- package/src/memory/migrations/run-migrations.ts +106 -10
- package/src/memory/migrations/validate-migration-state.ts +105 -67
- package/src/memory/prompt-override.ts +129 -0
- package/src/memory/schema/contacts.ts +6 -2
- package/src/memory/schema/conversations.ts +37 -0
- package/src/memory/schema/infrastructure.ts +20 -0
- package/src/memory/steps.ts +1294 -0
- package/src/memory/v2/__tests__/cli-command-store.test.ts +25 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +80 -0
- package/src/memory/v2/cli-command-store.ts +75 -38
- package/src/memory/v2/prompts/consolidation.ts +13 -82
- package/src/memory/v2/prompts/router.ts +21 -93
- package/src/memory/v2/skill-store.ts +68 -31
- package/src/memory/watchdog-events-store.ts +87 -0
- package/src/memory/worker-control.ts +204 -0
- package/src/memory/worker-process.ts +89 -0
- package/src/messaging/channel-binding-metadata.ts +31 -0
- package/src/messaging/provider-types.ts +8 -0
- package/src/messaging/providers/slack/binding-metadata.ts +60 -0
- package/src/notifications/__tests__/broadcaster.test.ts +8 -8
- package/src/notifications/__tests__/connected-channels.test.ts +86 -0
- package/src/notifications/__tests__/decision-engine.test.ts +78 -9
- package/src/notifications/__tests__/destination-resolver.test.ts +151 -0
- package/src/notifications/broadcaster.ts +8 -1
- package/src/notifications/decision-engine.ts +15 -7
- package/src/notifications/destination-resolver.ts +53 -25
- package/src/notifications/emit-signal.ts +34 -15
- package/src/onboarding/checkin-event.test.ts +222 -0
- package/src/onboarding/checkin-event.ts +321 -0
- package/src/onboarding/schedule-checkin.ts +190 -0
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +7 -4
- package/src/plugin-api/index.ts +12 -12
- package/src/plugin-api/types.ts +12 -14
- package/src/plugin-api/vision-support.test.ts +28 -4
- package/src/plugin-api/vision-support.ts +66 -31
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/empty-response/hooks/stop.ts +2 -2
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +4 -3
- package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/history-repair/hooks/stop.ts +2 -2
- package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +47 -7
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +12 -13
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +14 -22
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +42 -11
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/image-recovery/hooks/stop.ts +2 -2
- package/src/plugins/defaults/index.ts +0 -35
- package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/max-tokens-continue/hooks/stop.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +33 -3
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +48 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +4 -8
- package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +43 -15
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +11 -2
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +146 -0
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +77 -13
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +12 -11
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +2 -2
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +2 -2
- package/src/plugins/defaults/title-generate/hooks/stop.ts +2 -2
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +2 -2
- package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +2 -2
- package/src/plugins/disabled-state.ts +31 -0
- package/src/plugins/external-plugin-loader.ts +2 -2
- package/src/plugins/mtime-cache.ts +186 -330
- package/src/plugins/pipeline.ts +111 -13
- package/src/plugins/registry.ts +59 -16
- package/src/plugins/surface-import.ts +121 -0
- package/src/plugins/types.ts +7 -9
- package/src/prompts/persona-resolver.ts +43 -11
- package/src/providers/anthropic/client.ts +5 -0
- package/src/providers/call-site-routing.ts +45 -0
- package/src/providers/model-catalog.ts +16 -0
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +321 -0
- package/src/providers/openai/api-error-normalization.ts +270 -0
- package/src/providers/openai/chat-completions-provider.ts +37 -83
- package/src/providers/openai/responses-provider.ts +50 -46
- package/src/providers/openrouter/client.ts +5 -0
- package/src/providers/provider-send-message.ts +10 -0
- package/src/providers/ratelimit.ts +10 -0
- package/src/providers/registry.ts +1 -1
- package/src/providers/retry.ts +10 -0
- package/src/providers/types.ts +22 -0
- package/src/providers/usage-tracking.ts +10 -0
- package/src/runtime/__tests__/channel-verification-service.test.ts +133 -0
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +184 -0
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +66 -0
- package/src/runtime/__tests__/local-principal-trust.test.ts +162 -0
- package/src/runtime/__tests__/member-verdict-cache.test.ts +119 -0
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +402 -123
- package/src/runtime/access-request-helper.ts +18 -39
- package/src/runtime/actor-trust-resolver.ts +46 -19
- package/src/runtime/anchored-guardian.test.ts +109 -0
- package/src/runtime/anchored-guardian.ts +86 -0
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/assistant-stream-state.ts +9 -2
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +99 -0
- package/src/runtime/auth/require-bound-guardian.ts +21 -11
- package/src/runtime/channel-verification-service.ts +56 -31
- package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
- package/src/runtime/guardian-vellum-migration.ts +69 -8
- package/src/runtime/invite-redemption-service.ts +213 -187
- package/src/runtime/local-actor-identity.test.ts +108 -0
- package/src/runtime/local-actor-identity.ts +85 -13
- package/src/runtime/local-principal-trust.ts +52 -0
- package/src/runtime/member-verdict-cache.ts +0 -0
- package/src/runtime/pending-interactions.ts +11 -1
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +56 -5
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/contact-routes.test.ts +305 -0
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +92 -0
- package/src/runtime/routes/__tests__/http-adapter-actor-header.test.ts +129 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +188 -0
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +13 -5
- package/src/runtime/routes/channel-verification-routes.ts +3 -3
- package/src/runtime/routes/contact-routes.ts +48 -57
- package/src/runtime/routes/conversation-cli-routes.ts +4 -5
- package/src/runtime/routes/conversation-list-routes.ts +4 -7
- package/src/runtime/routes/conversation-query-routes.ts +72 -0
- package/src/runtime/routes/conversation-routes.ts +84 -85
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/global-search-routes.ts +3 -1
- package/src/runtime/routes/guardian-action-routes.ts +4 -5
- package/src/runtime/routes/host-app-control-routes.ts +5 -4
- package/src/runtime/routes/host-bash-routes.ts +5 -4
- package/src/runtime/routes/host-browser-routes.ts +9 -11
- package/src/runtime/routes/host-cu-routes.ts +5 -4
- package/src/runtime/routes/host-file-routes.ts +5 -4
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +16 -1
- package/src/runtime/routes/identity-routes.ts +3 -2
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +97 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +61 -59
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +13 -5
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +21 -8
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -3
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +19 -0
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/llm-context-normalization.ts +83 -0
- package/src/runtime/routes/mcp-auth-routes.ts +171 -19
- package/src/runtime/routes/migration-rollback-routes.ts +4 -3
- package/src/runtime/routes/migration-routes.ts +4 -1
- package/src/runtime/routes/onboarding-checkin-routes.ts +86 -0
- package/src/runtime/routes/settings-routes.ts +8 -3
- package/src/runtime/routes/subagents-routes.ts +5 -0
- package/src/runtime/routes/surface-action-routes.ts +42 -56
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
- package/src/runtime/services/conversation-serializer.ts +13 -58
- package/src/runtime/tool-grant-request-helper.ts +3 -3
- package/src/runtime/trust-verdict-consumer.ts +111 -40
- package/src/runtime/verification-outbound-actions.ts +18 -18
- package/src/signals/user-message.ts +16 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +35 -0
- package/src/{plugins/defaults/advisor/__tests__/transcript.test.ts → subagent/__tests__/consult-transcript.test.ts} +47 -10
- package/src/{plugins/defaults/advisor/steering.ts → subagent/consult-prompt.ts} +22 -32
- package/src/{plugins/defaults/advisor/transcript.ts → subagent/consult-transcript.ts} +18 -8
- package/src/subagent/index.ts +1 -1
- package/src/subagent/manager.ts +254 -33
- package/src/subagent/types.ts +11 -4
- package/src/telemetry/types.ts +34 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
- package/src/telemetry/usage-telemetry-reporter.ts +87 -3
- package/src/tools/ask-question/ask-question-tool.test.ts +29 -0
- package/src/tools/ask-question/ask-question-tool.ts +13 -0
- package/src/tools/executor.ts +4 -4
- package/src/tools/filesystem/search.ts +543 -0
- package/src/tools/registry.ts +38 -0
- package/src/tools/shared/filesystem/path-policy.ts +12 -5
- package/src/tools/subagent/consult-deadline.ts +49 -0
- package/src/tools/subagent/spawn.ts +234 -5
- package/src/tools/tool-approval-handler.ts +1 -1
- package/src/tools/tool-defaults.ts +9 -2
- package/src/tools/tool-manifest.ts +3 -0
- package/src/tools/types.ts +131 -25
- package/src/tools/workspace-tools/loader.ts +348 -244
- package/src/util/errors.ts +26 -1
- package/src/util/logger.ts +9 -0
- package/src/util/platform.ts +19 -0
- package/src/util/telemetry-db-path.ts +24 -0
- package/src/workflows/library.test.ts +140 -0
- package/src/workflows/library.ts +82 -28
- package/src/workspace/migrations/017-seed-persona-dirs.ts +3 -34
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +3 -24
- package/src/workspace/migrations/031-drop-user-md.ts +232 -148
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +14 -66
- package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +134 -0
- package/src/workspace/migrations/112-remove-advisor-callsite-override.ts +64 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +0 -70
- package/src/daemon/workspace-tools-watcher.ts +0 -328
- package/src/memory/migrations/registry.ts +0 -573
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +0 -56
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +0 -43
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +0 -137
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -153
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +0 -138
- package/src/plugins/defaults/advisor/advisor-gate.ts +0 -29
- package/src/plugins/defaults/advisor/advisor-state-store.ts +0 -94
- package/src/plugins/defaults/advisor/config.ts +0 -21
- package/src/plugins/defaults/advisor/consult.ts +0 -93
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +0 -34
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +0 -30
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +0 -19
- package/src/plugins/defaults/advisor/package.json +0 -14
- package/src/plugins/defaults/advisor/tools/advisor.ts +0 -65
- package/src/providers/openai/__tests__/api-error-detail.test.ts +0 -120
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A progress-aware deadline for the synchronous advisor consult.
|
|
3
|
+
*
|
|
4
|
+
* A reasoning advisor profile spends most of its window *thinking*, streaming
|
|
5
|
+
* reasoning tokens the whole time. A fixed wall-clock ceiling would cut it off
|
|
6
|
+
* mid-thought, so this aborts only after the consult goes `idleMs` without any
|
|
7
|
+
* streamed token (thinking or text) — i.e. genuine silence — with an absolute
|
|
8
|
+
* `maxMs` backstop so a runaway or looping stream can't block the parent
|
|
9
|
+
* forever.
|
|
10
|
+
*
|
|
11
|
+
* Usage: combine `signal` with the caller's own signal, call `recordProgress()`
|
|
12
|
+
* on every streamed chunk, and `dispose()` once the consult settles.
|
|
13
|
+
*/
|
|
14
|
+
export interface ConsultDeadline {
|
|
15
|
+
/** Aborts when the idle window lapses or the absolute max elapses. */
|
|
16
|
+
readonly signal: AbortSignal;
|
|
17
|
+
/** Reset the idle window — call on every streamed chunk (thinking or text). */
|
|
18
|
+
recordProgress(): void;
|
|
19
|
+
/** Clear both timers; call once the consult settles (success or failure). */
|
|
20
|
+
dispose(): void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function createConsultDeadline(opts: {
|
|
24
|
+
idleMs: number;
|
|
25
|
+
maxMs: number;
|
|
26
|
+
}): ConsultDeadline {
|
|
27
|
+
const controller = new AbortController();
|
|
28
|
+
let idleTimer: ReturnType<typeof setTimeout> | undefined;
|
|
29
|
+
|
|
30
|
+
const recordProgress = (): void => {
|
|
31
|
+
// Once aborted, don't re-arm — the consult is already being torn down.
|
|
32
|
+
if (controller.signal.aborted) return;
|
|
33
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
34
|
+
idleTimer = setTimeout(() => controller.abort(), opts.idleMs);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Absolute backstop, independent of streaming progress.
|
|
38
|
+
const maxTimer = setTimeout(() => controller.abort(), opts.maxMs);
|
|
39
|
+
|
|
40
|
+
// Arm the idle window immediately so time-to-first-token is bounded too.
|
|
41
|
+
recordProgress();
|
|
42
|
+
|
|
43
|
+
const dispose = (): void => {
|
|
44
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
45
|
+
clearTimeout(maxTimer);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return { signal: controller.signal, recordProgress, dispose };
|
|
49
|
+
}
|
|
@@ -2,11 +2,45 @@ import { validateInferenceProfileKey } from "../../config/inference-profile-vali
|
|
|
2
2
|
import { resolveDefaultProfileKey } from "../../config/llm-resolver.js";
|
|
3
3
|
import { getConfig } from "../../config/loader.js";
|
|
4
4
|
import { findConversation } from "../../daemon/conversation-registry.js";
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
|
|
5
|
+
import type { ServerMessage } from "../../daemon/message-protocol.js";
|
|
6
|
+
import {
|
|
7
|
+
getConversationOverrideProfile,
|
|
8
|
+
getMessages,
|
|
9
|
+
} from "../../memory/conversation-crud.js";
|
|
10
|
+
import type { ContentBlock, Message } from "../../providers/types.js";
|
|
11
|
+
import {
|
|
12
|
+
advisorRequestText,
|
|
13
|
+
buildAdvisorSystem,
|
|
14
|
+
} from "../../subagent/consult-prompt.js";
|
|
15
|
+
import { sanitizeConsultTranscript } from "../../subagent/consult-transcript.js";
|
|
16
|
+
import {
|
|
17
|
+
getSubagentManager,
|
|
18
|
+
SubagentAbortedError,
|
|
19
|
+
} from "../../subagent/index.js";
|
|
8
20
|
import type { SubagentRole } from "../../subagent/types.js";
|
|
21
|
+
import { getLogger } from "../../util/logger.js";
|
|
9
22
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
23
|
+
import { createConsultDeadline } from "./consult-deadline.js";
|
|
24
|
+
|
|
25
|
+
const log = getLogger("subagent-spawn");
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Idle ceiling on a single advisor consult: abort only after this much time
|
|
29
|
+
* passes with NO streamed token (thinking or text). A reasoning advisor profile
|
|
30
|
+
* streams its reasoning while it works, so a fixed wall-clock ceiling would kill
|
|
31
|
+
* it mid-thought; an idle window instead fires only when the consult is
|
|
32
|
+
* genuinely stalled (or never starts). Generous enough to also span
|
|
33
|
+
* time-to-first-token over a large inherited transcript.
|
|
34
|
+
*/
|
|
35
|
+
const ADVISOR_IDLE_TIMEOUT_MS = 60_000;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Absolute backstop on a single advisor consult regardless of streaming
|
|
39
|
+
* progress, so a runaway or looping stream can't block the parent forever.
|
|
40
|
+
* Either ceiling still yields the partial guidance (recovered in the
|
|
41
|
+
* `SubagentAbortedError` branch below), not a discard.
|
|
42
|
+
*/
|
|
43
|
+
const ADVISOR_MAX_TIMEOUT_MS = 300_000;
|
|
10
44
|
|
|
11
45
|
export async function executeSubagentSpawn(
|
|
12
46
|
input: Record<string, unknown>,
|
|
@@ -63,6 +97,19 @@ export async function executeSubagentSpawn(
|
|
|
63
97
|
};
|
|
64
98
|
}
|
|
65
99
|
|
|
100
|
+
// ── Advisor role: synchronous, tool-less, stronger-model consult ──
|
|
101
|
+
// Branch before the fire-and-forget path: the advisor blocks on the run and
|
|
102
|
+
// returns its guidance as the tool result in the same turn.
|
|
103
|
+
if (role === "advisor") {
|
|
104
|
+
return runAdvisorConsult({
|
|
105
|
+
context,
|
|
106
|
+
label,
|
|
107
|
+
objective,
|
|
108
|
+
sendToClient: sendToClient as (msg: ServerMessage) => void,
|
|
109
|
+
requestedOverrideProfile,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
66
113
|
// ── Fork mode: resolve parent context ────────────────────────────
|
|
67
114
|
let forkFields:
|
|
68
115
|
| {
|
|
@@ -138,8 +185,8 @@ export async function executeSubagentSpawn(
|
|
|
138
185
|
objective,
|
|
139
186
|
context: extraContext,
|
|
140
187
|
sendResultToUser,
|
|
141
|
-
//
|
|
142
|
-
//
|
|
188
|
+
// Regular forks omit the role so they default to general; the advisor
|
|
189
|
+
// role is special-cased earlier via runAdvisorConsult, not here.
|
|
143
190
|
...(!fork && role ? { role: role as SubagentRole } : {}),
|
|
144
191
|
...(inheritedOverrideProfile
|
|
145
192
|
? { overrideProfile: inheritedOverrideProfile }
|
|
@@ -168,3 +215,185 @@ export async function executeSubagentSpawn(
|
|
|
168
215
|
return { content: `Failed to spawn subagent: ${msg}`, isError: true };
|
|
169
216
|
}
|
|
170
217
|
}
|
|
218
|
+
|
|
219
|
+
// ── Advisor consult ──────────────────────────────────────────────────
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Run the `advisor` role as a synchronous, context-inheriting, stronger-model
|
|
223
|
+
* consult and return its guidance as the tool result.
|
|
224
|
+
*
|
|
225
|
+
* Inherits the parent transcript (sanitized), frames it as advice via
|
|
226
|
+
* `buildAdvisorSystem`, runs tool-less on `llm.advisorProfile` (unless the
|
|
227
|
+
* caller passed an explicit `inference_profile`), and is bounded by a
|
|
228
|
+
* progress-aware deadline: an idle window (`ADVISOR_IDLE_TIMEOUT_MS`) reset on
|
|
229
|
+
* every streamed token so a reasoning model isn't killed mid-thought, plus an
|
|
230
|
+
* absolute `ADVISOR_MAX_TIMEOUT_MS` backstop. If either ceiling is hit, the
|
|
231
|
+
* partial guidance produced so far is recovered and returned with a "may be cut
|
|
232
|
+
* off" note rather than discarded. Degrades to a benign non-error notice on any
|
|
233
|
+
* other failure (including the depth-limit rejection when a subagent itself
|
|
234
|
+
* calls the advisor).
|
|
235
|
+
*/
|
|
236
|
+
async function runAdvisorConsult(args: {
|
|
237
|
+
context: ToolContext;
|
|
238
|
+
label: string;
|
|
239
|
+
/** The agent's own `objective` — its framing of what it wants advised on. */
|
|
240
|
+
objective: string;
|
|
241
|
+
sendToClient: (msg: ServerMessage) => void;
|
|
242
|
+
requestedOverrideProfile: string | undefined;
|
|
243
|
+
}): Promise<ToolExecutionResult> {
|
|
244
|
+
const { context, label, objective, sendToClient, requestedOverrideProfile } =
|
|
245
|
+
args;
|
|
246
|
+
|
|
247
|
+
try {
|
|
248
|
+
const parentConversation = findConversation(context.conversationId);
|
|
249
|
+
if (!parentConversation) {
|
|
250
|
+
return {
|
|
251
|
+
content:
|
|
252
|
+
"(advisor unavailable: parent conversation could not be resolved)",
|
|
253
|
+
isError: false,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Snapshot the parent's in-memory transcript and system prompt, then append
|
|
258
|
+
// the in-flight assistant turn (the plan/text the model wrote THIS turn,
|
|
259
|
+
// before calling the advisor). The in-memory array does not yet hold that
|
|
260
|
+
// turn — the agent loop only writes it back to `conversation.messages` after
|
|
261
|
+
// the turn settles — but it is already persisted to the DB (the assistant
|
|
262
|
+
// row is finalized at `message_complete`, which fires before tool execution).
|
|
263
|
+
// `sanitizeConsultTranscript` then strips the dangling advisor `tool_use`
|
|
264
|
+
// off that final assistant turn so the inherited transcript is provider-safe.
|
|
265
|
+
const parentSystemPrompt = parentConversation.getCurrentSystemPrompt();
|
|
266
|
+
const withInFlight = appendInFlightAssistantTurn(
|
|
267
|
+
[...parentConversation.messages],
|
|
268
|
+
context.conversationId,
|
|
269
|
+
);
|
|
270
|
+
const sanitizedMessages = sanitizeConsultTranscript(withInFlight);
|
|
271
|
+
|
|
272
|
+
// Default to the stronger advisor profile when the caller did not pin one;
|
|
273
|
+
// an explicit `inference_profile` wins (already forced upstream).
|
|
274
|
+
const advisorProfile = getConfig().llm.advisorProfile;
|
|
275
|
+
const overrideProfile = requestedOverrideProfile ?? advisorProfile;
|
|
276
|
+
const forceOverrideProfile = overrideProfile !== undefined;
|
|
277
|
+
|
|
278
|
+
// Progress-aware deadline: reset on every streamed token so the consult
|
|
279
|
+
// isn't killed mid-thought, with an absolute backstop. Combine it with the
|
|
280
|
+
// caller's own signal.
|
|
281
|
+
const deadline = createConsultDeadline({
|
|
282
|
+
idleMs: ADVISOR_IDLE_TIMEOUT_MS,
|
|
283
|
+
maxMs: ADVISOR_MAX_TIMEOUT_MS,
|
|
284
|
+
});
|
|
285
|
+
const signal = context.signal
|
|
286
|
+
? AbortSignal.any([context.signal, deadline.signal])
|
|
287
|
+
: deadline.signal;
|
|
288
|
+
// Every streamed chunk (thinking or text) counts as progress and resets the
|
|
289
|
+
// idle window, then forwards to the caller's stream sink if one is present.
|
|
290
|
+
const onText = (chunk: string): void => {
|
|
291
|
+
deadline.recordProgress();
|
|
292
|
+
context.onOutput?.(chunk);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
const advice = await getSubagentManager().spawnAndAwait(
|
|
297
|
+
{
|
|
298
|
+
parentConversationId: context.conversationId,
|
|
299
|
+
label,
|
|
300
|
+
// Carry the agent's own objective into the consult request — the
|
|
301
|
+
// agent states the task here, and the inherited transcript can be thin.
|
|
302
|
+
objective: advisorRequestText(objective),
|
|
303
|
+
sendResultToUser: false,
|
|
304
|
+
role: "advisor",
|
|
305
|
+
fork: true,
|
|
306
|
+
parentMessages: sanitizedMessages,
|
|
307
|
+
systemPromptOverride: buildAdvisorSystem(parentSystemPrompt),
|
|
308
|
+
...(overrideProfile ? { overrideProfile } : {}),
|
|
309
|
+
...(forceOverrideProfile ? { forceOverrideProfile: true } : {}),
|
|
310
|
+
...(context.toolUseId ? { parentToolUseId: context.toolUseId } : {}),
|
|
311
|
+
},
|
|
312
|
+
sendToClient,
|
|
313
|
+
{ signal, onText },
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
const trimmed = advice.trim();
|
|
317
|
+
return {
|
|
318
|
+
content:
|
|
319
|
+
trimmed.length > 0 ? trimmed : "(advisor returned no guidance)",
|
|
320
|
+
isError: false,
|
|
321
|
+
};
|
|
322
|
+
} finally {
|
|
323
|
+
deadline.dispose();
|
|
324
|
+
}
|
|
325
|
+
} catch (err) {
|
|
326
|
+
// Timed out mid-generation: salvage whatever guidance the advisor had
|
|
327
|
+
// written rather than throwing it away. Partial strategic advice is far
|
|
328
|
+
// more useful to the agent than an "unavailable" notice — especially on a
|
|
329
|
+
// slow reasoning profile that needs most of the window to think.
|
|
330
|
+
if (err instanceof SubagentAbortedError) {
|
|
331
|
+
const partial = err.partialText.trim();
|
|
332
|
+
if (partial.length > 0) {
|
|
333
|
+
log.warn(
|
|
334
|
+
{ conversationId: context.conversationId },
|
|
335
|
+
"Advisor consult timed out; returning partial guidance",
|
|
336
|
+
);
|
|
337
|
+
return {
|
|
338
|
+
content: `${partial}\n\n_(The advisor reached its time limit while still writing — the guidance above may be cut off.)_`,
|
|
339
|
+
isError: false,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
344
|
+
log.warn(
|
|
345
|
+
{ err, conversationId: context.conversationId },
|
|
346
|
+
"Advisor consult failed",
|
|
347
|
+
);
|
|
348
|
+
// Never fail the turn — the advisor is advice, not a blocker.
|
|
349
|
+
return { content: `(advisor unavailable: ${reason})`, isError: false };
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Append the in-flight assistant turn (persisted this turn before the advisor
|
|
355
|
+
* tool ran) to an in-memory message snapshot, unless the snapshot already ends
|
|
356
|
+
* with it. The latest persisted assistant row carries the plan/text the model
|
|
357
|
+
* wrote immediately before calling the advisor plus the dangling advisor
|
|
358
|
+
* `tool_use`; `sanitizeConsultTranscript` strips the dangling call.
|
|
359
|
+
*
|
|
360
|
+
* Best-effort: a malformed or missing row leaves the snapshot unchanged so the
|
|
361
|
+
* consult still runs over the in-memory history.
|
|
362
|
+
*/
|
|
363
|
+
function appendInFlightAssistantTurn(
|
|
364
|
+
messages: Message[],
|
|
365
|
+
conversationId: string,
|
|
366
|
+
): Message[] {
|
|
367
|
+
// When the snapshot already ends on an assistant turn, the in-flight turn is
|
|
368
|
+
// present (or there is none to add) — appending the latest row would duplicate it.
|
|
369
|
+
if (messages[messages.length - 1]?.role === "assistant") return messages;
|
|
370
|
+
|
|
371
|
+
let rows;
|
|
372
|
+
try {
|
|
373
|
+
rows = getMessages(conversationId);
|
|
374
|
+
} catch {
|
|
375
|
+
return messages;
|
|
376
|
+
}
|
|
377
|
+
if (!rows || rows.length === 0) return messages;
|
|
378
|
+
|
|
379
|
+
const lastRow = rows[rows.length - 1];
|
|
380
|
+
if (lastRow.role !== "assistant") return messages;
|
|
381
|
+
|
|
382
|
+
let blocks: ContentBlock[];
|
|
383
|
+
try {
|
|
384
|
+
const parsed = JSON.parse(lastRow.content);
|
|
385
|
+
if (Array.isArray(parsed)) {
|
|
386
|
+
blocks = parsed as ContentBlock[];
|
|
387
|
+
} else if (typeof parsed === "string") {
|
|
388
|
+
blocks = [{ type: "text", text: parsed }];
|
|
389
|
+
} else {
|
|
390
|
+
return messages;
|
|
391
|
+
}
|
|
392
|
+
} catch {
|
|
393
|
+
// Plain-text content (no JSON envelope).
|
|
394
|
+
blocks = [{ type: "text", text: lastRow.content }];
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (blocks.length === 0) return messages;
|
|
398
|
+
return [...messages, { role: "assistant", content: blocks }];
|
|
399
|
+
}
|
|
@@ -553,7 +553,7 @@ export class ToolApprovalHandler {
|
|
|
553
553
|
const inputDigest =
|
|
554
554
|
deferredConsumeParams?.inputDigest ??
|
|
555
555
|
computeToolApprovalDigest(name, input);
|
|
556
|
-
const escalation = createOrReuseToolGrantRequest({
|
|
556
|
+
const escalation = await createOrReuseToolGrantRequest({
|
|
557
557
|
assistantId: context.assistantId,
|
|
558
558
|
sourceChannel: context.executionChannel as ChannelId,
|
|
559
559
|
conversationId: context.conversationId,
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* is a `Tool` (`Required<ToolDefinition>`).
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { resolveExecutionTarget } from "./execution-target.js";
|
|
13
14
|
import type {
|
|
14
15
|
RiskLevel,
|
|
15
16
|
Tool,
|
|
@@ -30,7 +31,10 @@ import type {
|
|
|
30
31
|
* are rejected at the JSON-schema layer.
|
|
31
32
|
* - `executionTarget` defaults to `sandbox` — author-supplied tool code
|
|
32
33
|
* runs in the assistant container by default; opt in to `host` when
|
|
33
|
-
* the tool proxies work to the connected client.
|
|
34
|
+
* the tool proxies work to the connected client. The name-prefix
|
|
35
|
+
* heuristic (`host_*` / `computer_use_*` resolves to host) is applied
|
|
36
|
+
* by `resolveExecutionTarget` in `finalizeTool`, so a tool named
|
|
37
|
+
* `host_my_thing` defaults to host even without an explicit field.
|
|
34
38
|
* - `category` defaults to empty — Slack channel `allowedToolCategories`
|
|
35
39
|
* policy denies uncategorized tools when a category allow-list is set,
|
|
36
40
|
* which is the correct deny-by-default for tools the author didn't
|
|
@@ -90,8 +94,10 @@ export function finalizeTool(tool: ToolDefinition, defaultName = ""): Tool {
|
|
|
90
94
|
content: `tool ${name} has no execute implementation`,
|
|
91
95
|
isError: true,
|
|
92
96
|
});
|
|
93
|
-
const executionTarget =
|
|
97
|
+
const executionTarget =
|
|
98
|
+
tool.executionTarget ?? resolveExecutionTarget({ name });
|
|
94
99
|
const category = tool.category ?? TOOL_DEFAULTS.category;
|
|
100
|
+
const exclusive = tool.exclusive ?? false;
|
|
95
101
|
return {
|
|
96
102
|
...tool,
|
|
97
103
|
name,
|
|
@@ -101,5 +107,6 @@ export function finalizeTool(tool: ToolDefinition, defaultName = ""): Tool {
|
|
|
101
107
|
executionTarget,
|
|
102
108
|
execute,
|
|
103
109
|
category,
|
|
110
|
+
exclusive,
|
|
104
111
|
};
|
|
105
112
|
}
|
|
@@ -18,6 +18,7 @@ import { runAuthenticatedCommandTool } from "./credential-execution/run-authenti
|
|
|
18
18
|
import { fileEditTool } from "./filesystem/edit.js";
|
|
19
19
|
import { fileListTool } from "./filesystem/list.js";
|
|
20
20
|
import { fileReadTool } from "./filesystem/read.js";
|
|
21
|
+
import { codeSearchTool } from "./filesystem/search.js";
|
|
21
22
|
import { fileWriteTool } from "./filesystem/write.js";
|
|
22
23
|
import { recallTool, rememberTool } from "./memory/register.js";
|
|
23
24
|
import { webFetchTool } from "./network/web-fetch.js";
|
|
@@ -59,6 +60,7 @@ export const eagerModuleToolNames: string[] = [
|
|
|
59
60
|
"file_write",
|
|
60
61
|
"file_edit",
|
|
61
62
|
"file_list",
|
|
63
|
+
"code_search",
|
|
62
64
|
"web_search",
|
|
63
65
|
"web_fetch",
|
|
64
66
|
"skill_execute",
|
|
@@ -81,6 +83,7 @@ export const explicitTools: ToolDefinition[] = [
|
|
|
81
83
|
fileWriteTool,
|
|
82
84
|
fileEditTool,
|
|
83
85
|
fileListTool,
|
|
86
|
+
codeSearchTool,
|
|
84
87
|
webFetchTool,
|
|
85
88
|
webSearchTool,
|
|
86
89
|
skillExecuteTool,
|
package/src/tools/types.ts
CHANGED
|
@@ -249,6 +249,26 @@ export function stringifyToolInput(input: Record<string, unknown>): string {
|
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Runtime context passed as the second argument to every tool's `execute`.
|
|
254
|
+
*
|
|
255
|
+
* The fields fall into two groups:
|
|
256
|
+
*
|
|
257
|
+
* - A small, stable core that we are comfortable exposing to any tool —
|
|
258
|
+
* including workspace- and plugin-authored tools via `@vellumai/plugin-api`:
|
|
259
|
+
* `conversationId`, `workingDir`, `requestId`, `signal`, `onOutput`,
|
|
260
|
+
* `assistantId`, `isInteractive`.
|
|
261
|
+
* - Everything tagged `@legacy` below: host-internal routing, permission,
|
|
262
|
+
* trust, requester-identity, proxy, and telemetry metadata that historically
|
|
263
|
+
* accreted on this single context. These are NOT a surface we want third-party
|
|
264
|
+
* tools to depend on; we are triaging them post-launch with the goal of
|
|
265
|
+
* moving them off the public context (or removing them) over time. Grep for
|
|
266
|
+
* `@legacy` to enumerate the set. Do not add new fields here — extend the
|
|
267
|
+
* stable core only when a field is genuinely safe and stable to expose.
|
|
268
|
+
*
|
|
269
|
+
* The daemon constructs and passes the full object to every tool at runtime; a
|
|
270
|
+
* tool that only reads the stable core is unaffected by the eventual cleanup.
|
|
271
|
+
*/
|
|
252
272
|
export interface ToolContext {
|
|
253
273
|
/** Identifier of the conversation this tool invocation belongs to. */
|
|
254
274
|
conversationId: string;
|
|
@@ -262,23 +282,44 @@ export interface ToolContext {
|
|
|
262
282
|
onOutput?: (chunk: string) => void;
|
|
263
283
|
/** Logical assistant scope for multi-assistant routing. */
|
|
264
284
|
assistantId?: string;
|
|
265
|
-
/**
|
|
285
|
+
/** True when an interactive client is connected (not just a no-op callback). */
|
|
286
|
+
isInteractive?: boolean;
|
|
287
|
+
/**
|
|
288
|
+
* When set, the tool execution is part of a task run. Used to retrieve ephemeral permission rules.
|
|
289
|
+
* @legacy
|
|
290
|
+
*/
|
|
266
291
|
taskRunId?: string;
|
|
267
292
|
/**
|
|
268
293
|
* Model attribution snapshot for the conversation at invocation time
|
|
269
294
|
* (provider/model/profile that issued this tool call). Used by tool
|
|
270
295
|
* telemetry; never sent to the tool itself.
|
|
296
|
+
* @legacy
|
|
271
297
|
*/
|
|
272
298
|
attribution?: UsageAttributionSnapshot | null;
|
|
273
|
-
/**
|
|
299
|
+
/**
|
|
300
|
+
* Optional callback for tool lifecycle events (start/prompt/deny/execute/error).
|
|
301
|
+
* @legacy
|
|
302
|
+
*/
|
|
274
303
|
onToolLifecycleEvent?: ToolLifecycleEventHandler;
|
|
275
|
-
/**
|
|
304
|
+
/**
|
|
305
|
+
* Optional resolver for proxy tools - delegates execution to an external client.
|
|
306
|
+
* @legacy
|
|
307
|
+
*/
|
|
276
308
|
proxyToolResolver?: ProxyToolResolver;
|
|
277
|
-
/**
|
|
309
|
+
/**
|
|
310
|
+
* When set, only tools in this set may execute. Tools outside the set are blocked with an error.
|
|
311
|
+
* @legacy
|
|
312
|
+
*/
|
|
278
313
|
allowedToolNames?: Set<string>;
|
|
279
|
-
/**
|
|
314
|
+
/**
|
|
315
|
+
* True when this turn is restricted to storage cleanup-safe tools.
|
|
316
|
+
* @legacy
|
|
317
|
+
*/
|
|
280
318
|
diskPressureCleanupModeActive?: boolean;
|
|
281
|
-
/**
|
|
319
|
+
/**
|
|
320
|
+
* Prompt the user for a secret value via native SecureField UI.
|
|
321
|
+
* @legacy
|
|
322
|
+
*/
|
|
282
323
|
requestSecret?: (params: {
|
|
283
324
|
service: string;
|
|
284
325
|
field: string;
|
|
@@ -289,11 +330,15 @@ export interface ToolContext {
|
|
|
289
330
|
allowedTools?: string[];
|
|
290
331
|
allowedDomains?: string[];
|
|
291
332
|
}) => Promise<SecretPromptResult>;
|
|
292
|
-
/**
|
|
333
|
+
/**
|
|
334
|
+
* Optional callback to send a message to the connected client (e.g. open_url).
|
|
335
|
+
* @legacy
|
|
336
|
+
*/
|
|
293
337
|
sendToClient?: (msg: { type: string; [key: string]: unknown }) => void;
|
|
294
|
-
/**
|
|
295
|
-
|
|
296
|
-
|
|
338
|
+
/**
|
|
339
|
+
* When true, tools with side effects should always prompt for confirmation.
|
|
340
|
+
* @legacy
|
|
341
|
+
*/
|
|
297
342
|
forcePromptSideEffects?: boolean;
|
|
298
343
|
/**
|
|
299
344
|
* When true, the tool requires a fresh interactive approval for every
|
|
@@ -304,26 +349,46 @@ export interface ToolContext {
|
|
|
304
349
|
* temporary override options in the prompt UI. Used by
|
|
305
350
|
* `manage_secure_command_tool` to ensure a human reviews each secure
|
|
306
351
|
* bundle installation.
|
|
352
|
+
* @legacy
|
|
307
353
|
*/
|
|
308
354
|
requireFreshApproval?: boolean;
|
|
309
|
-
/**
|
|
355
|
+
/**
|
|
356
|
+
* Approval callback for proxy policy decisions that require user confirmation.
|
|
357
|
+
* @legacy
|
|
358
|
+
*/
|
|
310
359
|
proxyApprovalCallback?: ProxyApprovalCallback;
|
|
311
|
-
/**
|
|
360
|
+
/**
|
|
361
|
+
* Optional principal identifier propagated to sub-tool confirmation flows.
|
|
362
|
+
* @legacy
|
|
363
|
+
*/
|
|
312
364
|
principal?: string;
|
|
313
365
|
/**
|
|
314
366
|
* Trust classification of the actor who initiated this tool invocation.
|
|
315
367
|
* Determines permission level: guardians self-approve, trusted contacts
|
|
316
368
|
* may escalate to guardian for approval, unknown actors are fail-closed.
|
|
317
369
|
* See {@link TrustClass} in actor-trust-resolver.ts for value semantics.
|
|
370
|
+
* @legacy
|
|
318
371
|
*/
|
|
319
372
|
trustClass: TrustClass;
|
|
320
|
-
/**
|
|
373
|
+
/**
|
|
374
|
+
* Channel through which the tool invocation originates (e.g. 'telegram', 'phone'). Used for scoped grant consumption.
|
|
375
|
+
* @legacy
|
|
376
|
+
*/
|
|
321
377
|
executionChannel?: string;
|
|
322
|
-
/**
|
|
378
|
+
/**
|
|
379
|
+
* Voice/call session ID, if the invocation originates from a call. Used for scoped grant consumption.
|
|
380
|
+
* @legacy
|
|
381
|
+
*/
|
|
323
382
|
callSessionId?: string;
|
|
324
|
-
/**
|
|
383
|
+
/**
|
|
384
|
+
* True when the tool invocation was triggered by a user clicking a surface action button (not a regular message).
|
|
385
|
+
* @legacy
|
|
386
|
+
*/
|
|
325
387
|
triggeredBySurfaceAction?: boolean;
|
|
326
|
-
/**
|
|
388
|
+
/**
|
|
389
|
+
* True when the user explicitly approved this tool invocation via the interactive permission prompt (not auto-approved by trust rules or temporary overrides).
|
|
390
|
+
* @legacy
|
|
391
|
+
*/
|
|
327
392
|
approvedViaPrompt?: boolean;
|
|
328
393
|
/**
|
|
329
394
|
* True when the invocation is inside a scheduled task run whose
|
|
@@ -331,21 +396,43 @@ export interface ToolContext {
|
|
|
331
396
|
* Tools that normally require a surface-action click (e.g. bulk archive,
|
|
332
397
|
* unsubscribe) may treat this as equivalent consent, since the user
|
|
333
398
|
* already reviewed the tool list when the task was saved.
|
|
399
|
+
* @legacy
|
|
334
400
|
*/
|
|
335
401
|
batchAuthorizedByTask?: boolean;
|
|
336
|
-
/**
|
|
402
|
+
/**
|
|
403
|
+
* External user ID of the requester (non-guardian actor). Used for scoped grant consumption.
|
|
404
|
+
* @legacy
|
|
405
|
+
*/
|
|
337
406
|
requesterExternalUserId?: string;
|
|
338
|
-
/**
|
|
407
|
+
/**
|
|
408
|
+
* Chat ID of the requester (non-guardian actor). Used for tool grant request escalation notifications.
|
|
409
|
+
* @legacy
|
|
410
|
+
*/
|
|
339
411
|
requesterChatId?: string;
|
|
340
|
-
/**
|
|
412
|
+
/**
|
|
413
|
+
* Human-readable identifier for the requester (e.g., @username).
|
|
414
|
+
* @legacy
|
|
415
|
+
*/
|
|
341
416
|
requesterIdentifier?: string;
|
|
342
|
-
/**
|
|
417
|
+
/**
|
|
418
|
+
* Preferred display name for the requester.
|
|
419
|
+
* @legacy
|
|
420
|
+
*/
|
|
343
421
|
requesterDisplayName?: string;
|
|
344
|
-
/**
|
|
422
|
+
/**
|
|
423
|
+
* Slack channel ID for channel-scoped permission enforcement. When set, tools are checked against the channel's permission profile.
|
|
424
|
+
* @legacy
|
|
425
|
+
*/
|
|
345
426
|
channelPermissionChannelId?: string;
|
|
346
|
-
/**
|
|
427
|
+
/**
|
|
428
|
+
* The tool_use block ID from the LLM response, used to correlate confirmation prompts with specific tool invocations.
|
|
429
|
+
* @legacy
|
|
430
|
+
*/
|
|
347
431
|
toolUseId?: string;
|
|
348
|
-
/**
|
|
432
|
+
/**
|
|
433
|
+
* True when the assistant is running as a platform-managed remote instance. Used to auto-approve sandboxed bash tools.
|
|
434
|
+
* @legacy
|
|
435
|
+
*/
|
|
349
436
|
isPlatformHosted?: boolean;
|
|
350
437
|
/**
|
|
351
438
|
* The interface ID of the connected client driving the current turn (e.g.
|
|
@@ -353,6 +440,7 @@ export interface ToolContext {
|
|
|
353
440
|
* transport preference — for example, macOS-originated turns prefer the
|
|
354
441
|
* user's real Chrome session via the paired extension before falling back
|
|
355
442
|
* to cdp-inspect or local Playwright.
|
|
443
|
+
* @legacy
|
|
356
444
|
*/
|
|
357
445
|
transportInterface?: InterfaceId;
|
|
358
446
|
/**
|
|
@@ -363,6 +451,7 @@ export interface ToolContext {
|
|
|
363
451
|
* has `inferenceProfile` set — the override only flows through the
|
|
364
452
|
* in-memory `SubagentConfig.overrideProfile` chain. See
|
|
365
453
|
* `executeSubagentSpawn` in tools/subagent/spawn.ts.
|
|
454
|
+
* @legacy
|
|
366
455
|
*/
|
|
367
456
|
overrideProfile?: string;
|
|
368
457
|
/**
|
|
@@ -371,6 +460,7 @@ export interface ToolContext {
|
|
|
371
460
|
* default a spawned subagent's inference profile to the profile the invoking
|
|
372
461
|
* turn resolved to, so subagents match whatever agent invoked them rather
|
|
373
462
|
* than always falling back to the static `subagentSpawn` call-site default.
|
|
463
|
+
* @legacy
|
|
374
464
|
*/
|
|
375
465
|
invokingCallSite?: LLMCallSite;
|
|
376
466
|
/**
|
|
@@ -379,6 +469,7 @@ export interface ToolContext {
|
|
|
379
469
|
* Used by host proxies to bind cross-client targeted execution to the same
|
|
380
470
|
* authenticated user identity. May be undefined for legacy/internal flows
|
|
381
471
|
* with no resolved actor identity.
|
|
472
|
+
* @legacy
|
|
382
473
|
*/
|
|
383
474
|
sourceActorPrincipalId?: string;
|
|
384
475
|
}
|
|
@@ -449,6 +540,15 @@ export const ToolDefinitionSchema = z.object({
|
|
|
449
540
|
) => Promise<ToolExecutionResult>
|
|
450
541
|
>()
|
|
451
542
|
.optional(),
|
|
543
|
+
/**
|
|
544
|
+
* When true, this tool runs alone in its turn. If the model emits it
|
|
545
|
+
* alongside other tool calls, the agent loop executes only this one and
|
|
546
|
+
* defers the siblings — returning them un-run with a benign notice — so the
|
|
547
|
+
* model incorporates this tool's output before acting on anything else. The
|
|
548
|
+
* `advisor` tool sets this so its guidance lands before the agent commits to
|
|
549
|
+
* a path. Default false (the loop runs sibling calls concurrently as usual).
|
|
550
|
+
*/
|
|
551
|
+
exclusive: z.boolean().optional(),
|
|
452
552
|
});
|
|
453
553
|
|
|
454
554
|
/**
|
|
@@ -460,8 +560,14 @@ export const ToolDefinitionSchema = z.object({
|
|
|
460
560
|
*/
|
|
461
561
|
export type ToolDefinition = z.infer<typeof ToolDefinitionSchema>;
|
|
462
562
|
|
|
463
|
-
/**
|
|
464
|
-
|
|
563
|
+
/**
|
|
564
|
+
* Tool after the loader has derived its name and filled defaults. Every field
|
|
565
|
+
* is required except `exclusive`, which stays optional — most tools never set
|
|
566
|
+
* it, and the agent loop reads it as `?.exclusive === true`, so forcing every
|
|
567
|
+
* hand-built `Tool` (MCP/meet/test fixtures) to carry it would be noise.
|
|
568
|
+
*/
|
|
569
|
+
export type Tool = Required<Omit<ToolDefinition, "exclusive">> &
|
|
570
|
+
Pick<ToolDefinition, "exclusive">;
|
|
465
571
|
|
|
466
572
|
/** The kind of extension that owns a tool. Core tools have no owner. */
|
|
467
573
|
export type OwnerKind = "skill" | "mcp" | "plugin" | "workspace";
|