@vellumai/assistant 0.9.0 → 0.10.0-staging.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/ARCHITECTURE.md +18 -34
- package/bun.lock +7 -8
- package/docs/activation-funnel-telemetry.md +28 -22
- package/docs/architecture/security.md +29 -28
- package/docs/stt-provider-onboarding.md +3 -5
- package/docs/workflows-testing.md +13 -44
- package/docs/workflows.md +3 -5
- package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
- package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +32 -6
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
- package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
- package/openapi.yaml +976 -63
- package/package.json +2 -1
- package/scripts/sync-llm-catalog.ts +6 -15
- package/scripts/sync-web-search-catalog.ts +3 -11
- package/src/__tests__/access-request-card-view.test.ts +98 -0
- package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +72 -32
- package/src/__tests__/agent-loop-compaction-strip.test.ts +241 -0
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
- package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
- package/src/__tests__/app-compiler.test.ts +15 -1
- package/src/__tests__/app-dir-path-guard.test.ts +0 -1
- package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
- package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
- package/src/__tests__/avatar-identity-sync.test.ts +2 -27
- package/src/__tests__/btw-routes.test.ts +6 -8
- package/src/__tests__/call-pointer-messages.test.ts +28 -0
- package/src/__tests__/cancel-clears-processing.test.ts +89 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -4
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
- package/src/__tests__/checker.test.ts +0 -3
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
- package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
- package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
- package/src/__tests__/config-loader-backfill.test.ts +268 -27
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/config-watcher.test.ts +0 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +0 -6
- package/src/__tests__/contacts-tools.test.ts +29 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +58 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-lifecycle.test.ts +7 -9
- package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
- package/src/__tests__/conversation-title-service.test.ts +62 -0
- package/src/__tests__/credential-broker.test.ts +449 -1
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
- package/src/__tests__/credential-execution-tools.test.ts +0 -1
- package/src/__tests__/credential-prompt-route.test.ts +4 -4
- package/src/__tests__/credential-routes.test.ts +360 -0
- package/src/__tests__/credential-security-invariants.test.ts +4 -13
- package/src/__tests__/disk-pressure-policy.test.ts +12 -0
- package/src/__tests__/disk-usage.test.ts +65 -0
- package/src/__tests__/dynamic-page-surface.test.ts +152 -1
- package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
- package/src/__tests__/gateway-flag-listener.test.ts +110 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -7
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
- package/src/__tests__/guardian-grant-minting.test.ts +3 -35
- package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
- package/src/__tests__/guardian-routing-state.test.ts +0 -1
- package/src/__tests__/headless-browser-mode.test.ts +10 -0
- package/src/__tests__/headless-browser-navigate.test.ts +8 -3
- package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
- package/src/__tests__/host-browser-proxy.test.ts +87 -0
- package/src/__tests__/identity-routes.test.ts +0 -189
- package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
- package/src/__tests__/injector-v3-suppression.test.ts +27 -20
- package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
- package/src/__tests__/invite-redemption-service.test.ts +4 -7
- package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
- package/src/__tests__/llm-catalog-parity.test.ts +30 -23
- package/src/__tests__/llm-resolver.test.ts +70 -24
- package/src/__tests__/llm-schema.test.ts +1 -0
- package/src/__tests__/managed-profile-guard.test.ts +163 -4
- package/src/__tests__/mcp-health-check.test.ts +6 -7
- package/src/__tests__/media-stream-server-integration.test.ts +317 -13
- package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
- package/src/__tests__/onboarding-persona-write.test.ts +1 -1
- package/src/__tests__/path-policy.test.ts +34 -0
- package/src/__tests__/persona-resolver.test.ts +49 -14
- package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
- package/src/__tests__/plugin-api-provider.test.ts +24 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
- package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
- package/src/__tests__/reaction-persistence.test.ts +150 -29
- package/src/__tests__/registry.test.ts +2 -7
- package/src/__tests__/relay-server.test.ts +285 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
- package/src/__tests__/schedule-routes.test.ts +0 -30
- package/src/__tests__/schedule-tools.test.ts +2 -18
- package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
- package/src/__tests__/skill-execute-input.test.ts +51 -1
- package/src/__tests__/skill-runtime-path.test.ts +2 -3
- package/src/__tests__/skills.test.ts +51 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
- package/src/__tests__/subagent-tools.test.ts +266 -0
- package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
- package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
- package/src/__tests__/title-generate-hook.test.ts +100 -3
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
- package/src/__tests__/token-manager.test.ts +519 -0
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
- package/src/__tests__/tool-audit-listener.test.ts +7 -7
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
- package/src/__tests__/tool-executor.test.ts +0 -79
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
- package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
- package/src/__tests__/trusted-contact-verification.test.ts +8 -10
- package/src/__tests__/twilio-routes.test.ts +81 -1
- package/src/__tests__/voice-invite-redemption.test.ts +2 -3
- package/src/__tests__/weak-open-model.test.ts +30 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
- package/src/__tests__/workspace-greetings.test.ts +152 -0
- package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
- package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
- package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
- package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
- package/src/agent/loop.ts +49 -29
- package/src/api/README.md +6 -6
- package/src/api/events/tool-result.ts +6 -0
- package/src/api/events/workflow-completed.ts +53 -0
- package/src/api/events/workflow-leaf-finished.ts +38 -0
- package/src/api/events/workflow-leaf-started.ts +35 -0
- package/src/api/events/workflow-progress.ts +32 -0
- package/src/api/events/workflow-started.ts +31 -0
- package/src/api/index.ts +40 -0
- package/src/api/responses/conversation-message.ts +28 -4
- package/src/api/responses/home.ts +26 -4
- package/src/api/responses/workflow-journal.ts +53 -0
- package/src/approvals/guardian-card-withdrawal.ts +145 -0
- package/src/approvals/guardian-decision-primitive.ts +26 -3
- package/src/approvals/guardian-request-resolvers.ts +183 -80
- package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
- package/src/calls/call-pointer-messages.ts +10 -4
- package/src/calls/channel-admission-reader.ts +104 -0
- package/src/calls/guardian-dispatch.ts +17 -45
- package/src/calls/media-stream-server.ts +84 -2
- package/src/calls/relay-access-wait.ts +1 -1
- package/src/calls/relay-server.ts +66 -0
- package/src/calls/relay-setup-router.ts +82 -1
- package/src/calls/twilio-routes.ts +17 -8
- package/src/calls/voice-session-bridge.ts +2 -2
- package/src/cli/commands/clients.ts +3 -0
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
- package/src/cli/commands/memory/index.ts +30 -0
- package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
- package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
- package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
- package/src/cli/commands/oauth/status.test.ts +36 -0
- package/src/cli/commands/oauth/status.ts +23 -3
- package/src/cli/commands/plugins.ts +197 -4
- package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
- package/src/cli/lib/diff-plugin.ts +346 -0
- package/src/cli/lib/inspect-plugin.ts +12 -1
- package/src/cli/lib/install-from-github.ts +105 -17
- package/src/cli/lib/merge-plugin-tree.ts +328 -0
- package/src/cli/lib/plugin-fingerprint.ts +14 -0
- package/src/cli/lib/plugin-surfaces.ts +104 -0
- package/src/cli/lib/upgrade-plugin.ts +298 -10
- package/src/cli/program.ts +2 -6
- package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
- package/src/config/assistant-feature-flags.ts +22 -7
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
- package/src/config/bundled-skills/messaging/SKILL.md +6 -4
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
- package/src/config/bundled-skills/subagent/SKILL.md +4 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
- package/src/config/bundled-skills/workflows/SKILL.md +14 -8
- package/src/config/bundled-tool-registry.ts +2 -7
- package/src/config/call-site-defaults.ts +15 -2
- package/src/config/feature-flag-registry.json +46 -31
- package/src/config/inference-profile-validation.ts +26 -0
- package/src/config/llm-resolver.ts +3 -0
- package/src/config/loader.ts +4 -0
- package/src/config/memory-v3-gate.ts +11 -0
- package/src/config/profile-order.ts +28 -0
- package/src/config/schema.ts +8 -6
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/channels.ts +11 -0
- package/src/config/schemas/elevenlabs.ts +0 -1
- package/src/config/schemas/llm.ts +31 -0
- package/src/config/schemas/memory-lifecycle.ts +3 -7
- package/src/config/schemas/memory-v3.ts +6 -0
- package/src/config/schemas/platform.ts +0 -8
- package/src/config/schemas/services.ts +18 -0
- package/src/config/seed-inference-profiles.ts +109 -44
- package/src/config/skills.ts +21 -0
- package/src/config/sync-gated-profiles.ts +220 -0
- package/src/contacts/contact-store.ts +89 -106
- package/src/contacts/contacts-write.ts +5 -22
- package/src/contacts/types.ts +0 -1
- package/src/context/compactor.ts +88 -54
- package/src/context/strip-injections.ts +58 -10
- package/src/context/token-estimator.ts +1 -1
- package/src/credential-execution/process-manager.ts +55 -14
- package/src/credential-execution/prompted-credential.ts +2 -3
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
- package/src/daemon/config-watcher.ts +0 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
- package/src/daemon/conversation-agent-loop.ts +114 -22
- package/src/daemon/conversation-history.ts +1 -1
- package/src/daemon/conversation-lifecycle.ts +3 -5
- package/src/daemon/conversation-process.ts +13 -5
- package/src/daemon/conversation-runtime-assembly.ts +13 -15
- package/src/daemon/conversation-slash.ts +2 -23
- package/src/daemon/conversation-surfaces.ts +26 -0
- package/src/daemon/conversation-tool-setup.ts +27 -14
- package/src/daemon/conversation.ts +66 -14
- package/src/daemon/disk-pressure-policy.ts +5 -3
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
- package/src/daemon/handlers/config-a2a.ts +0 -2
- package/src/daemon/handlers/config-channels.ts +15 -16
- package/src/daemon/handlers/config-slack-channel.ts +22 -3
- package/src/daemon/handlers/conversations.ts +107 -0
- package/src/daemon/host-browser-proxy.ts +41 -0
- package/src/daemon/lifecycle.ts +55 -27
- package/src/daemon/message-provenance.ts +2 -0
- package/src/daemon/message-types/contacts.ts +0 -1
- package/src/daemon/message-types/conversations.ts +3 -3
- package/src/daemon/message-types/sync.ts +0 -1
- package/src/daemon/message-types/web-activity.ts +7 -1
- package/src/daemon/message-types/workflows.ts +83 -1
- package/src/daemon/orphan-reaper.test.ts +0 -19
- package/src/daemon/orphan-reaper.ts +2 -24
- package/src/daemon/server.ts +0 -10
- package/src/daemon/tool-setup-types.ts +4 -0
- package/src/daemon/trust-context.ts +1 -1
- package/src/events/tool-audit-listener.ts +2 -2
- package/src/home/feed-source-enrichment.test.ts +151 -0
- package/src/home/feed-source-enrichment.ts +176 -0
- package/src/home/relationship-state.ts +2 -4
- package/src/instrument.ts +18 -6
- package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
- package/src/ipc/assistant-server.ts +37 -4
- package/src/ipc/gateway-flag-listener.ts +18 -2
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
- package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
- package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
- package/src/memory/auth-fallback-events-store.ts +2 -2
- package/src/memory/auto-analysis-enqueue.ts +3 -5
- package/src/memory/bookmark-crud.ts +1 -2
- package/src/memory/canonical-guardian-store.ts +39 -1
- package/src/memory/conversation-crud.ts +9 -4
- package/src/memory/conversation-key-store.ts +17 -2
- package/src/memory/conversation-title-service.ts +64 -7
- package/src/memory/db-init.ts +17 -17
- package/src/memory/embedding-backend.ts +38 -1
- package/src/memory/embedding-billing-breaker.ts +96 -0
- package/src/memory/jobs-store.ts +25 -13
- package/src/memory/jobs-worker.ts +54 -1
- package/src/memory/lifecycle-events-store.ts +2 -2
- package/src/memory/memory-retrospective-constants.ts +4 -4
- package/src/memory/memory-retrospective-enqueue.ts +31 -6
- package/src/memory/memory-retrospective-job.ts +28 -227
- package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
- package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
- package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
- package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
- package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
- package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
- package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
- package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
- package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
- package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/run-migrations.ts +41 -0
- package/src/memory/migrations/validate-migration-state.ts +1 -1
- package/src/memory/onboarding-events-store.ts +3 -3
- package/src/memory/schema/contacts.ts +0 -5
- package/src/memory/skill-loaded-events-store.test.ts +7 -15
- package/src/memory/skill-loaded-events-store.ts +2 -2
- package/src/memory/tool-executed-events-store.test.ts +7 -7
- package/src/memory/turn-trace-store.test.ts +736 -0
- package/src/memory/turn-trace-store.ts +364 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
- package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
- package/src/memory/v2/consolidation-job.ts +2 -2
- package/src/memory/v2/skill-content.ts +25 -7
- package/src/memory/v2/skill-store.ts +7 -1
- package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
- package/src/memory/v3-eval/eval-packets.ts +546 -0
- package/src/messaging/providers/slack/adapter.ts +1 -1
- package/src/messaging/providers/slack/api.ts +31 -0
- package/src/messaging/providers/slack/send.test.ts +114 -2
- package/src/messaging/providers/slack/send.ts +30 -7
- package/src/messaging/providers/slack/withdraw.test.ts +200 -0
- package/src/messaging/providers/slack/withdraw.ts +161 -0
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/access-request-copy.ts +72 -59
- package/src/notifications/adapters/shared.ts +29 -0
- package/src/notifications/adapters/slack.ts +58 -103
- package/src/notifications/adapters/telegram.ts +2 -20
- package/src/notifications/approval-card-data.ts +333 -0
- package/src/notifications/broadcaster.ts +16 -3
- package/src/notifications/canonical-delivery-recorder.ts +139 -0
- package/src/notifications/copy-composer.ts +3 -3
- package/src/notifications/decision-engine.ts +4 -2
- package/src/notifications/destination-resolver.ts +4 -6
- package/src/notifications/guardian-question-mode.ts +10 -0
- package/src/notifications/home-feed-side-effect.ts +7 -16
- package/src/notifications/notification-utils.ts +19 -20
- package/src/notifications/signal.ts +79 -43
- package/src/notifications/types.ts +98 -121
- package/src/oauth/AGENTS.md +5 -24
- package/src/permissions/checker.test.ts +51 -0
- package/src/permissions/checker.ts +185 -26
- package/src/permissions/ipc-risk-types.ts +24 -0
- package/src/permissions/question-prompter.test.ts +27 -0
- package/src/permissions/question-prompter.ts +4 -0
- package/src/platform/client.test.ts +119 -0
- package/src/platform/client.ts +66 -0
- package/src/platform/consent-cache.test.ts +267 -0
- package/src/platform/consent-cache.ts +174 -0
- package/src/plugin-api/constants.ts +1 -1
- package/src/plugin-api/index.ts +33 -1
- package/src/plugin-api/model-profiles.ts +33 -0
- package/src/plugin-api/types.ts +50 -2
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
- package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
- package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
- package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
- package/src/plugins/defaults/advisor/config.ts +21 -0
- package/src/plugins/defaults/advisor/consult.ts +93 -0
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/advisor/package.json +14 -0
- package/src/plugins/defaults/advisor/steering.ts +67 -0
- package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
- package/src/plugins/defaults/advisor/transcript.ts +76 -0
- package/src/plugins/defaults/index.ts +60 -0
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
- package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
- package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
- package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
- package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
- package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
- package/src/prompts/persona-resolver.ts +14 -4
- package/src/prompts/templates/system-sections.ts +7 -2
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
- package/src/providers/__tests__/retry-callsite.test.ts +176 -0
- package/src/providers/atlascloud/client.ts +85 -0
- package/src/providers/fetch-provider-catalog.ts +85 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/model-catalog.ts +58 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
- package/src/providers/openai/chat-completions-provider.ts +7 -0
- package/src/providers/openai/responses-provider.ts +10 -0
- package/src/providers/provider-send-message.ts +11 -3
- package/src/providers/retry.ts +53 -12
- package/src/providers/search-provider-catalog.ts +10 -0
- package/src/providers/weak-open-model.ts +22 -0
- package/src/runtime/AGENTS.md +0 -1
- package/src/runtime/__tests__/agent-wake.test.ts +181 -0
- package/src/runtime/__tests__/client-health.test.ts +44 -0
- package/src/runtime/access-request-helper.ts +21 -53
- package/src/runtime/actor-trust-resolver.ts +59 -63
- package/src/runtime/agent-wake.ts +52 -0
- package/src/runtime/assistant-event-hub.ts +18 -4
- package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
- package/src/runtime/auth/require-bound-guardian.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -6
- package/src/runtime/capabilities.test.ts +120 -0
- package/src/runtime/capabilities.ts +197 -0
- package/src/runtime/channel-approval-types.ts +22 -45
- package/src/runtime/channel-invite-transports/telegram.ts +4 -4
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/channel-verification-service.ts +3 -3
- package/src/runtime/client-health.ts +26 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
- package/src/runtime/effective-capabilities.test.ts +128 -0
- package/src/runtime/effective-capabilities.ts +84 -0
- package/src/runtime/guardian-reply-router.ts +106 -21
- package/src/runtime/invite-redemption-service.ts +9 -25
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +123 -0
- package/src/runtime/migrations/vbundle-builder.ts +49 -20
- package/src/runtime/pending-interactions.ts +15 -0
- package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +240 -1
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
- package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
- package/src/runtime/routes/browser-tabs-routes.ts +9 -0
- package/src/runtime/routes/btw-routes.ts +1 -27
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
- package/src/runtime/routes/client-routes.ts +10 -0
- package/src/runtime/routes/contact-routes.ts +31 -8
- package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
- package/src/runtime/routes/conversation-management-routes.ts +80 -1
- package/src/runtime/routes/conversation-query-routes.ts +68 -22
- package/src/runtime/routes/conversation-routes.ts +39 -14
- package/src/runtime/routes/credential-routes.ts +40 -16
- package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
- package/src/runtime/routes/events-routes.ts +1 -3
- package/src/runtime/routes/guardian-approval-interception.ts +14 -73
- package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
- package/src/runtime/routes/home-feed-routes.ts +8 -3
- package/src/runtime/routes/identity-routes.ts +1 -296
- package/src/runtime/routes/inbound-message-handler.ts +214 -228
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
- package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
- package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
- package/src/runtime/routes/integrations/slack/channel.ts +36 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
- package/src/runtime/routes/mcp-auth-routes.ts +233 -41
- package/src/runtime/routes/memory-eval-routes.ts +87 -0
- package/src/runtime/routes/notification-routes.ts +122 -133
- package/src/runtime/routes/platform-routes.ts +2 -2
- package/src/runtime/routes/plugins-routes.ts +202 -3
- package/src/runtime/routes/schedule-routes.ts +0 -22
- package/src/runtime/routes/secret-routes.ts +10 -0
- package/src/runtime/routes/surface-action-routes.ts +2 -1
- package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
- package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
- package/src/runtime/routes/workflow-routes.test.ts +229 -44
- package/src/runtime/routes/workflow-routes.ts +131 -29
- package/src/runtime/routes/workspace-greetings.ts +55 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -11
- package/src/runtime/tool-grant-request-helper.ts +18 -16
- package/src/runtime/trust-context-resolver.ts +8 -5
- package/src/schedule/inference-profile.ts +2 -14
- package/src/schedule/schedule-store.ts +1 -1
- package/src/schedule/scheduler-types.ts +5 -1
- package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
- package/src/security/secret-patterns.ts +3 -0
- package/src/subagent/manager.ts +17 -4
- package/src/subagent/types.ts +6 -0
- package/src/telemetry/trace-collection-policy.test.ts +28 -0
- package/src/telemetry/trace-collection-policy.ts +30 -0
- package/src/telemetry/types.ts +89 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
- package/src/telemetry/usage-telemetry-reporter.ts +148 -41
- package/src/tools/AGENTS.md +3 -3
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
- package/src/tools/browser/browser-execution.ts +30 -19
- package/src/tools/document/document-tool.ts +2 -3
- package/src/tools/executor.ts +5 -3
- package/src/tools/host-terminal/host-shell.ts +5 -4
- package/src/tools/memory/register.ts +2 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
- package/src/tools/network/__tests__/web-search.test.ts +143 -0
- package/src/tools/network/web-fetch.ts +372 -1
- package/src/tools/network/web-search-error.ts +1 -1
- package/src/tools/network/web-search.ts +213 -10
- package/src/tools/permission-checker.ts +4 -3
- package/src/tools/registry.ts +20 -0
- package/src/tools/schedule/create.ts +7 -12
- package/src/tools/schedule/update.ts +4 -11
- package/src/tools/shared/filesystem/path-policy.ts +39 -13
- package/src/tools/side-effects.ts +2 -17
- package/src/tools/skills/execute.ts +33 -0
- package/src/tools/subagent/spawn.ts +61 -12
- package/src/tools/terminal/shell.ts +10 -4
- package/src/tools/tool-approval-handler.ts +18 -13
- package/src/tools/tool-manifest.ts +0 -2
- package/src/tools/types.ts +9 -0
- package/src/tools/ui-surface/definitions.ts +64 -3
- package/src/tools/verification-control-plane-policy.ts +3 -1
- package/src/tools/workflows/run-workflow.test.ts +8 -18
- package/src/tools/workflows/run-workflow.ts +1 -0
- package/src/util/disk-usage.ts +78 -23
- package/src/util/platform.ts +10 -3
- package/src/watcher/telemetry.ts +2 -2
- package/src/workflows/capabilities.ts +2 -3
- package/src/workflows/engine.test.ts +175 -1
- package/src/workflows/engine.ts +82 -0
- package/src/workflows/journal-store.test.ts +70 -0
- package/src/workflows/journal-store.ts +18 -3
- package/src/workflows/run-manager.test.ts +171 -28
- package/src/workflows/run-manager.ts +66 -24
- package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
- package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
- package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
- package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
- package/src/__tests__/credential-security-e2e.test.ts +0 -362
- package/src/__tests__/credential-vault-unit.test.ts +0 -1528
- package/src/__tests__/credential-vault.test.ts +0 -1706
- package/src/__tests__/identity-intro-cache.test.ts +0 -315
- package/src/__tests__/secret-onetime-send.test.ts +0 -182
- package/src/cli/commands/__tests__/task.test.ts +0 -914
- package/src/cli/commands/task.ts +0 -771
- package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
- package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
- package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
- package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
- package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
- package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
- package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
- package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
- package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
- package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
- package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
- package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
- package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
- package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
- package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
- package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
- package/src/memory/preloaded-apps.ts +0 -116
- package/src/notifications/tool-approval-copy.ts +0 -142
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
- package/src/runtime/routes/identity-intro-cache.ts +0 -172
- package/src/tools/credentials/vault.ts +0 -712
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-conversation capture store for the advisor plugin.
|
|
3
|
+
*
|
|
4
|
+
* A tool's `execute` does not receive the conversation transcript — only
|
|
5
|
+
* lifecycle hooks do. So the hooks snapshot what the executor saw (the system
|
|
6
|
+
* prompt from `pre-model-call`, the running transcript from `post-model-call`)
|
|
7
|
+
* into this module-level store, keyed by conversation id, and the `advisor`
|
|
8
|
+
* tool reads the latest snapshot when the model calls it. This reproduces the
|
|
9
|
+
* advisor-tool property that the model calls the tool with no arguments and the
|
|
10
|
+
* full context is supplied for it.
|
|
11
|
+
*
|
|
12
|
+
* Bounded by a small LRU so a long-lived daemon does not accumulate state for
|
|
13
|
+
* every conversation it has ever served.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { Message } from "../../../providers/types.js";
|
|
17
|
+
|
|
18
|
+
export interface AdvisorCapture {
|
|
19
|
+
/** The executor's system prompt (steering stripped), or null if unseen. */
|
|
20
|
+
systemPrompt: string | null;
|
|
21
|
+
/** The transcript the executor most recently saw on a `mainAgent` call. */
|
|
22
|
+
messages: Message[];
|
|
23
|
+
/** Last-write timestamp, used for LRU eviction. */
|
|
24
|
+
updatedAt: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const MAX_CONVERSATIONS = 200;
|
|
28
|
+
const store = new Map<string, AdvisorCapture>();
|
|
29
|
+
|
|
30
|
+
/** Move an entry to most-recently-used and evict the oldest past the cap. */
|
|
31
|
+
function bump(conversationId: string, entry: AdvisorCapture): void {
|
|
32
|
+
entry.updatedAt = Date.now();
|
|
33
|
+
store.delete(conversationId);
|
|
34
|
+
store.set(conversationId, entry);
|
|
35
|
+
while (store.size > MAX_CONVERSATIONS) {
|
|
36
|
+
const oldest = store.keys().next().value;
|
|
37
|
+
if (oldest === undefined) break;
|
|
38
|
+
store.delete(oldest);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function ensure(conversationId: string): AdvisorCapture {
|
|
43
|
+
return (
|
|
44
|
+
store.get(conversationId) ?? {
|
|
45
|
+
systemPrompt: null,
|
|
46
|
+
messages: [],
|
|
47
|
+
updatedAt: Date.now(),
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Seed the capture at the start of a user turn with the inbound history, so an
|
|
54
|
+
* advisor call on the very first model turn still has context even before
|
|
55
|
+
* `post-model-call` snapshots the running transcript.
|
|
56
|
+
*/
|
|
57
|
+
export function seedCapture(
|
|
58
|
+
conversationId: string,
|
|
59
|
+
messages: ReadonlyArray<Message>,
|
|
60
|
+
): void {
|
|
61
|
+
const entry = ensure(conversationId);
|
|
62
|
+
entry.messages = [...messages];
|
|
63
|
+
bump(conversationId, entry);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Record the executor's system prompt (steering already stripped). */
|
|
67
|
+
export function recordSystemPrompt(
|
|
68
|
+
conversationId: string,
|
|
69
|
+
systemPrompt: string | null,
|
|
70
|
+
): void {
|
|
71
|
+
const entry = ensure(conversationId);
|
|
72
|
+
entry.systemPrompt = systemPrompt;
|
|
73
|
+
bump(conversationId, entry);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Snapshot the transcript the executor just saw (before tools run). */
|
|
77
|
+
export function recordMessages(
|
|
78
|
+
conversationId: string,
|
|
79
|
+
messages: ReadonlyArray<Message>,
|
|
80
|
+
): void {
|
|
81
|
+
const entry = ensure(conversationId);
|
|
82
|
+
entry.messages = [...messages];
|
|
83
|
+
bump(conversationId, entry);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** The latest capture for a conversation, or `undefined` if none recorded. */
|
|
87
|
+
export function getCapture(conversationId: string): AdvisorCapture | undefined {
|
|
88
|
+
return store.get(conversationId);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Test-only: clear all captured state. */
|
|
92
|
+
export function resetAdvisorStateForTests(): void {
|
|
93
|
+
store.clear();
|
|
94
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static behavioral configuration for the advisor.
|
|
3
|
+
*
|
|
4
|
+
* The advisor *model* is no longer hardcoded here: it routes through the
|
|
5
|
+
* dedicated `advisor` call site, whose default profile (`quality-optimized`)
|
|
6
|
+
* lives in CALL_SITE_DEFAULTS and is overridden per workspace by
|
|
7
|
+
* `llm.advisorProfile`. Whether the advisor is active is decided per chat
|
|
8
|
+
* profile by `ProfileEntry.advisorEnabled` (default on).
|
|
9
|
+
*/
|
|
10
|
+
export const ADVISOR_CONFIG = {
|
|
11
|
+
// No advisor-specific output cap: the consult omits `max_tokens` (so the
|
|
12
|
+
// resolver applies the profile's normal output budget) and the request text
|
|
13
|
+
// carries no word limit. The advisor decides its own length.
|
|
14
|
+
/** Abort the consult if the sub-call runs longer than this. */
|
|
15
|
+
timeoutMs: 60_000,
|
|
16
|
+
/**
|
|
17
|
+
* Global kill-switch for the steering injection. The per-chat-profile
|
|
18
|
+
* `advisorEnabled` toggle gates it further; this stays as a hard off switch.
|
|
19
|
+
*/
|
|
20
|
+
steeringEnabled: true,
|
|
21
|
+
} as const;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run one advisor consult.
|
|
3
|
+
*
|
|
4
|
+
* Routed entirely through the assistant's own inference: `getConfiguredProvider`
|
|
5
|
+
* resolves the general-purpose `inference` call site (with the advisor profile
|
|
6
|
+
* applied as an `overrideProfile`) to a provider/model/credentials from the
|
|
7
|
+
* configured profiles — managed-proxy or BYOK, no separate API key. The consult
|
|
8
|
+
* then runs a tool-less, capped one-shot completion through `provider.sendMessage`
|
|
9
|
+
* and returns the text.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { getConfig } from "../../../config/loader.js";
|
|
13
|
+
import type { LLMCallSite } from "../../../config/schemas/llm.js";
|
|
14
|
+
import {
|
|
15
|
+
extractAllText,
|
|
16
|
+
getConfiguredProvider,
|
|
17
|
+
userMessage,
|
|
18
|
+
} from "../../../providers/provider-send-message.js";
|
|
19
|
+
import type { Message } from "../../../providers/types.js";
|
|
20
|
+
import { ADVISOR_CONFIG } from "./config.js";
|
|
21
|
+
import { advisorRequestText, buildAdvisorSystem } from "./steering.js";
|
|
22
|
+
import { toAdvisorMessages } from "./transcript.js";
|
|
23
|
+
|
|
24
|
+
// Dedicated advisor call site. Its default profile (`quality-optimized`) lives
|
|
25
|
+
// in CALL_SITE_DEFAULTS; a workspace overrides which profile the advisor runs
|
|
26
|
+
// on via `llm.advisorProfile`, which we float above the call-site layers.
|
|
27
|
+
const ADVISOR_CALL_SITE: LLMCallSite = "advisor";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the routing override for the advisor consult. When the workspace has
|
|
31
|
+
* set `llm.advisorProfile`, force it above the call-site layers so it is
|
|
32
|
+
* authoritative; otherwise return `{}` so the `advisor` call site resolves to
|
|
33
|
+
* its default profile.
|
|
34
|
+
*/
|
|
35
|
+
function advisorOverride(): {
|
|
36
|
+
overrideProfile?: string;
|
|
37
|
+
forceOverrideProfile?: boolean;
|
|
38
|
+
} {
|
|
39
|
+
const advisorProfile = getConfig().llm.advisorProfile;
|
|
40
|
+
return advisorProfile
|
|
41
|
+
? { overrideProfile: advisorProfile, forceOverrideProfile: true }
|
|
42
|
+
: {};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ConsultParams {
|
|
46
|
+
systemPrompt: string | null;
|
|
47
|
+
messages: ReadonlyArray<Message>;
|
|
48
|
+
signal?: AbortSignal;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Combine the caller's signal with a consult timeout. */
|
|
52
|
+
function withTimeout(signal: AbortSignal | undefined, ms: number): AbortSignal {
|
|
53
|
+
const timeout = AbortSignal.timeout(ms);
|
|
54
|
+
return signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Returns the advisor's guidance text, or a short benign notice when the
|
|
59
|
+
* advisor can't run. Callers should surface the string as a non-error tool
|
|
60
|
+
* result so the executor continues regardless.
|
|
61
|
+
*/
|
|
62
|
+
export async function consultAdvisor(params: ConsultParams): Promise<string> {
|
|
63
|
+
const history = toAdvisorMessages(params.messages);
|
|
64
|
+
if (history.length === 0) {
|
|
65
|
+
return "(advisor: no conversation context is available yet)";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const override = advisorOverride();
|
|
69
|
+
|
|
70
|
+
const provider = await getConfiguredProvider(ADVISOR_CALL_SITE, override);
|
|
71
|
+
if (!provider) {
|
|
72
|
+
return "(advisor unavailable: no inference provider is configured)";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Append the consult instruction as the final user turn, then run a
|
|
76
|
+
// tool-less completion through the resolved provider. No `max_tokens` is
|
|
77
|
+
// set, so the resolver applies the profile's normal output budget rather
|
|
78
|
+
// than an advisor-specific cap.
|
|
79
|
+
const messages: Message[] = [...history, userMessage(advisorRequestText())];
|
|
80
|
+
|
|
81
|
+
const response = await provider.sendMessage(messages, {
|
|
82
|
+
systemPrompt: buildAdvisorSystem(params.systemPrompt),
|
|
83
|
+
config: {
|
|
84
|
+
callSite: ADVISOR_CALL_SITE,
|
|
85
|
+
...override,
|
|
86
|
+
tool_choice: { type: "none" },
|
|
87
|
+
},
|
|
88
|
+
signal: withTimeout(params.signal, ADVISOR_CONFIG.timeoutMs),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const advice = extractAllText(response).trim();
|
|
92
|
+
return advice.length > 0 ? advice : "(advisor returned no guidance)";
|
|
93
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `post-model-call` hook: snapshot the transcript the executor just saw. Fires
|
|
3
|
+
* after the model returns its message (which may carry the `advisor` tool_use)
|
|
4
|
+
* but before tools run, so when `advisor.execute()` runs an instant later it
|
|
5
|
+
* reads exactly this snapshot.
|
|
6
|
+
*
|
|
7
|
+
* Pure observer: never mutates `content` or the continue/stop `decision`. Gated
|
|
8
|
+
* to the user-facing reply, so background/subagent/compaction calls — and the
|
|
9
|
+
* advisor's own `inference`-call-site sub-call — are ignored.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { PluginHookFn, PostModelCallContext } from "@vellumai/plugin-api";
|
|
13
|
+
|
|
14
|
+
import { recordMessages } from "../advisor-state-store.js";
|
|
15
|
+
|
|
16
|
+
const postModelCall: PluginHookFn<PostModelCallContext> = async (ctx) => {
|
|
17
|
+
if (ctx.callSite !== "mainAgent") return;
|
|
18
|
+
if (ctx.error) return;
|
|
19
|
+
// `ctx.messages` is the pre-reply history; the turn the model just produced —
|
|
20
|
+
// including any text/plan it wrote before the `advisor` tool_use — lives in
|
|
21
|
+
// `ctx.content` and is not yet in `messages`. Append it (cloned) so the
|
|
22
|
+
// advisor reviews the full current transcript, not just the prior history.
|
|
23
|
+
// `transcript.ts` strips the pending tool_use from this final assistant turn.
|
|
24
|
+
const messages =
|
|
25
|
+
ctx.content.length > 0
|
|
26
|
+
? [
|
|
27
|
+
...ctx.messages,
|
|
28
|
+
{ role: "assistant" as const, content: [...ctx.content] },
|
|
29
|
+
]
|
|
30
|
+
: ctx.messages;
|
|
31
|
+
recordMessages(ctx.conversationId, messages);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default postModelCall;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `pre-model-call` hook: for the user-facing reply (`mainAgent`), capture the
|
|
3
|
+
* executor's system prompt (steering stripped) so the advisor can be given it
|
|
4
|
+
* as context, and inject the advisor steering so the model reaches for the
|
|
5
|
+
* tool. Idempotent via the steering marker.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { PluginHookFn, PreModelCallContext } from "@vellumai/plugin-api";
|
|
9
|
+
|
|
10
|
+
import { advisorEnabledForProfile } from "../advisor-gate.js";
|
|
11
|
+
import { recordSystemPrompt } from "../advisor-state-store.js";
|
|
12
|
+
import { ADVISOR_CONFIG } from "../config.js";
|
|
13
|
+
import { appendSteering, stripSteering } from "../steering.js";
|
|
14
|
+
|
|
15
|
+
const preModelCall: PluginHookFn<PreModelCallContext> = async (ctx) => {
|
|
16
|
+
if (ctx.callSite !== "mainAgent") return;
|
|
17
|
+
|
|
18
|
+
recordSystemPrompt(ctx.conversationId, stripSteering(ctx.systemPrompt));
|
|
19
|
+
|
|
20
|
+
// Steer the model to consult only when the steering is globally on AND the
|
|
21
|
+
// chat profile this turn routes to has the advisor enabled (default on).
|
|
22
|
+
if (
|
|
23
|
+
ADVISOR_CONFIG.steeringEnabled &&
|
|
24
|
+
advisorEnabledForProfile(ctx.modelProfile)
|
|
25
|
+
) {
|
|
26
|
+
ctx.systemPrompt = appendSteering(ctx.systemPrompt);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default preModelCall;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `user-prompt-submit` hook: seed the per-conversation capture at the start of a
|
|
3
|
+
* user turn with the inbound history, so an advisor call on the very first model
|
|
4
|
+
* turn still has context even before `post-model-call` snapshots the running
|
|
5
|
+
* transcript.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
PluginHookFn,
|
|
10
|
+
UserPromptSubmitContext,
|
|
11
|
+
} from "@vellumai/plugin-api";
|
|
12
|
+
|
|
13
|
+
import { seedCapture } from "../advisor-state-store.js";
|
|
14
|
+
|
|
15
|
+
const userPromptSubmit: PluginHookFn<UserPromptSubmitContext> = async (ctx) => {
|
|
16
|
+
seedCapture(ctx.conversationId, ctx.latestMessages);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default userPromptSubmit;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "default-advisor",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "First-party default plugin that adds an `advisor` tool: a no-argument tool the model calls mid-task to consult a stronger inference profile on the full conversation transcript for strategic guidance, routed through the assistant's own inference.",
|
|
5
|
+
"private": true,
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=20.12.0"
|
|
10
|
+
},
|
|
11
|
+
"peerDependencies": {
|
|
12
|
+
"@vellumai/plugin-api": "^0.8.0"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt fragments for the advisor plugin:
|
|
3
|
+
* - `appendSteering` / `stripSteering` — the executor-facing steering block the
|
|
4
|
+
* `pre-model-call` hook injects so the model reaches for the advisor tool at
|
|
5
|
+
* the right times.
|
|
6
|
+
* - `buildAdvisorSystem` / `advisorRequestText` — the advisor-facing framing for
|
|
7
|
+
* the consult itself.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Idempotency marker; the steering block is appended at the end of the prompt. */
|
|
11
|
+
export const STEERING_MARKER = "<!-- advisor:steering -->";
|
|
12
|
+
|
|
13
|
+
const STEERING_BODY = `You have an \`advisor\` tool backed by a stronger reviewer model. It takes NO parameters — calling it forwards your entire conversation automatically (the task, every tool call, every result). Call advisor BEFORE you start building or implementing: once you understand what's being asked, consult it to shape the plan — it can lay out the plan when you don't have one yet, or pressure-test and sharpen a plan you've already drafted. Orient yourself first (read the relevant files, understand the task), then call advisor before you commit to an approach and start producing work. Also call it when you get stuck, when you're weighing a change in direction, and once before you declare the task done. Give its guidance serious weight; only override it when primary-source evidence contradicts a specific claim, and say so when you do.`;
|
|
14
|
+
|
|
15
|
+
const ADVISOR_STEERING = `${STEERING_MARKER}\n${STEERING_BODY}`;
|
|
16
|
+
|
|
17
|
+
/** Append the steering block to the executor's system prompt (idempotent). */
|
|
18
|
+
export function appendSteering(systemPrompt: string | null): string | null {
|
|
19
|
+
if (systemPrompt === null) return null;
|
|
20
|
+
if (systemPrompt.includes(STEERING_MARKER)) return systemPrompt;
|
|
21
|
+
return `${systemPrompt}\n\n${ADVISOR_STEERING}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Remove a previously-appended steering block, recovering the original prompt. */
|
|
25
|
+
export function stripSteering(systemPrompt: string | null): string | null {
|
|
26
|
+
if (systemPrompt === null) return null;
|
|
27
|
+
const idx = systemPrompt.indexOf(STEERING_MARKER);
|
|
28
|
+
if (idx === -1) return systemPrompt;
|
|
29
|
+
return systemPrompt.slice(0, idx).trimEnd();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* System prompt for the advisor sub-call. Frames the advisor's role and, for
|
|
34
|
+
* context, quotes the executor's own system prompt (as the advisor tool does —
|
|
35
|
+
* the advisor sees the system prompt as context about the executor's task).
|
|
36
|
+
*/
|
|
37
|
+
export function buildAdvisorSystem(
|
|
38
|
+
originalSystemPrompt: string | null,
|
|
39
|
+
): string {
|
|
40
|
+
const base = `You are a senior advisor consulted by another AI agent working on a task — most often at the planning stage, before it starts building, but sometimes partway through. The entire conversation above is the agent's working context: its task or goal, every tool call it has made, and every result it has seen. The agent has paused to consult you because you bring a second, independent perspective it cannot get from inside its own reasoning loop. Your job is to maximize its odds of completing the task correctly and efficiently.
|
|
41
|
+
|
|
42
|
+
Evaluate the work along these dimensions, and lead with whatever matters most right now:
|
|
43
|
+
|
|
44
|
+
- Approach & plan: If the agent has already drafted a plan or chosen an approach, pressure-test it — is it the right one, or is there a materially better path? If it hasn't committed to one yet, lay out a concrete plan for how to proceed. Either way, be specific about the path you would take and why.
|
|
45
|
+
- Assumptions & requirements: Surface any wrong, unstated, or unverified assumption the agent is building on, and any part of the task it has misread, silently narrowed, or skipped. These are the failures it is least able to see itself.
|
|
46
|
+
- Critical risk: Identify the single failure mode most likely to derail the task — or that already has — and how to avoid or recover from it.
|
|
47
|
+
- Next step: Give one concrete action the agent can take immediately. Name the specific file, function, command, interface, or decision involved — not a generic direction.
|
|
48
|
+
- Verification: If the agent has no clear way to confirm its work is correct, tell it how it will know.
|
|
49
|
+
|
|
50
|
+
How to advise:
|
|
51
|
+
- Be specific and grounded. Cite what you actually see in the transcript — a particular result, a line of reasoning, a command that failed. Never invent details that aren't there; if a decisive fact is missing, say what the agent should go find out.
|
|
52
|
+
- Be decisive. Give a clear recommendation, not a menu of equally weighted options. When genuinely uncertain, say so and state what would resolve it.
|
|
53
|
+
- Prioritize ruthlessly. Lead with the highest-leverage point. Don't restate at length what the agent already did well, and don't pad the response with minor nitpicks — a focused, well-reasoned critique beats an exhaustive one.
|
|
54
|
+
- Stay in your lane. Advise the agent; do not role-play as it, write its final deliverable, or take its next action for it. If the agent is already on the right track, confirm it and sharpen the plan rather than manufacturing objections.
|
|
55
|
+
|
|
56
|
+
Write as much as the guidance genuinely needs, and no more.`;
|
|
57
|
+
if (!originalSystemPrompt) return base;
|
|
58
|
+
return `${base}\n\nFor context, the agent is operating under this system prompt:\n<agent_system_prompt>\n${originalSystemPrompt}\n</agent_system_prompt>`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The final user turn appended to the transcript for the advisor sub-call. Asks
|
|
63
|
+
* for guidance; imposes no length limit — the advisor decides how much to say.
|
|
64
|
+
*/
|
|
65
|
+
export function advisorRequestText(): string {
|
|
66
|
+
return `Review the conversation above — the task, the tool calls, and their results — and give focused strategic guidance on how to proceed.`;
|
|
67
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `advisor` tool — a no-argument tool the model calls to consult a stronger
|
|
3
|
+
* model for strategic guidance. The model supplies no input; the plugin reads
|
|
4
|
+
* the transcript captured by the lifecycle hooks and runs the consult, routed
|
|
5
|
+
* through the assistant's own inference.
|
|
6
|
+
*
|
|
7
|
+
* Default export = the tool definition. `defaults/index.ts` finalizes it and
|
|
8
|
+
* attaches it to the advisor plugin's `tools` array, which `bootstrapPlugins`
|
|
9
|
+
* registers into the model-visible tool catalog.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {
|
|
13
|
+
ToolContext,
|
|
14
|
+
ToolDefinition,
|
|
15
|
+
ToolExecutionResult,
|
|
16
|
+
} from "@vellumai/plugin-api";
|
|
17
|
+
import { RiskLevel } from "@vellumai/plugin-api";
|
|
18
|
+
|
|
19
|
+
import { advisorEnabledForProfile } from "../advisor-gate.js";
|
|
20
|
+
import { getCapture } from "../advisor-state-store.js";
|
|
21
|
+
import { consultAdvisor } from "../consult.js";
|
|
22
|
+
|
|
23
|
+
const advisorTool: ToolDefinition = {
|
|
24
|
+
name: "advisor",
|
|
25
|
+
description:
|
|
26
|
+
"Consult a stronger advisor model to shape your plan and get strategic guidance. " +
|
|
27
|
+
"Takes NO parameters — your full conversation (the task, every tool call, and every " +
|
|
28
|
+
"result) is forwarded automatically. Call it BEFORE you start building: it can lay out " +
|
|
29
|
+
"a plan when you don't have one yet, or review and sharpen the plan you've already " +
|
|
30
|
+
"drafted. Also call it when you're stuck, when weighing a change in approach, and once " +
|
|
31
|
+
"before declaring a task complete. Give its guidance serious weight.",
|
|
32
|
+
input_schema: { type: "object", properties: {}, additionalProperties: false },
|
|
33
|
+
// Read-only advice; low risk so the consult isn't gated behind a prompt.
|
|
34
|
+
defaultRiskLevel: RiskLevel.Low,
|
|
35
|
+
async execute(
|
|
36
|
+
_input: Record<string, unknown>,
|
|
37
|
+
ctx: ToolContext,
|
|
38
|
+
): Promise<ToolExecutionResult> {
|
|
39
|
+
// Defense-in-depth: the steering is already gated per profile, but a model
|
|
40
|
+
// could still call the tool. Honor the chat profile this turn runs under —
|
|
41
|
+
// the per-turn override (per-conversation / profile-session) when present,
|
|
42
|
+
// else the workspace active profile.
|
|
43
|
+
if (!advisorEnabledForProfile(ctx.overrideProfile ?? null)) {
|
|
44
|
+
return {
|
|
45
|
+
content: "(advisor is disabled for the active profile)",
|
|
46
|
+
isError: false,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const capture = getCapture(ctx.conversationId);
|
|
51
|
+
const advice = await consultAdvisor({
|
|
52
|
+
systemPrompt: capture?.systemPrompt ?? null,
|
|
53
|
+
messages: capture?.messages ?? [],
|
|
54
|
+
signal: ctx.signal,
|
|
55
|
+
});
|
|
56
|
+
return { content: advice, isError: false };
|
|
57
|
+
} catch (err) {
|
|
58
|
+
// Degrade like the advisor tool: never fail the turn over a consult.
|
|
59
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
60
|
+
return { content: `(advisor unavailable: ${reason})`, isError: false };
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default advisorTool;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a captured executor transcript into the message list sent to the
|
|
3
|
+
* advisor sub-call.
|
|
4
|
+
*
|
|
5
|
+
* Strips blocks the advisor shouldn't (or can't) replay:
|
|
6
|
+
* - thinking / redacted-thinking (the advisor tool drops thinking),
|
|
7
|
+
* - files,
|
|
8
|
+
* - `server_tool_use` AND `web_search_tool_result` — provider-side tool calls
|
|
9
|
+
* (e.g. web search) and their results are dropped *together*. Dropping the
|
|
10
|
+
* result without its paired `server_tool_use` would leave an orphaned call
|
|
11
|
+
* block the provider rejects, so any consult after prior web-search history
|
|
12
|
+
* would fail; dropping both keeps the sequence valid.
|
|
13
|
+
*
|
|
14
|
+
* Images are preserved — top-level and nested inside `tool_result.contentBlocks`
|
|
15
|
+
* (which are recursively sanitized) — so the advisor sees what the executor saw.
|
|
16
|
+
* Visual tasks depend on it; the advisor profile is expected to be vision-capable.
|
|
17
|
+
*
|
|
18
|
+
* It also strips the *pending* client tool calls from the final assistant turn:
|
|
19
|
+
* at capture time (a `post-model-call` before tools run) the last assistant
|
|
20
|
+
* message carries the `advisor` tool_use with no matching `tool_result` yet, so
|
|
21
|
+
* sending it would be a dangling call. Earlier, completed `tool_use` /
|
|
22
|
+
* `tool_result` pairs are preserved intact.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import type { ContentBlock, Message } from "../../../providers/types.js";
|
|
26
|
+
|
|
27
|
+
/** Drop disallowed blocks; recursively sanitize tool_result content. `null` = drop. */
|
|
28
|
+
function sanitize(block: ContentBlock): ContentBlock | null {
|
|
29
|
+
switch (block.type) {
|
|
30
|
+
case "thinking":
|
|
31
|
+
case "redacted_thinking":
|
|
32
|
+
case "file":
|
|
33
|
+
case "server_tool_use":
|
|
34
|
+
case "web_search_tool_result":
|
|
35
|
+
return null;
|
|
36
|
+
case "tool_result": {
|
|
37
|
+
if (!block.contentBlocks) return block;
|
|
38
|
+
// Keep images (and other allowed blocks) nested in the tool result; drop
|
|
39
|
+
// the disallowed ones.
|
|
40
|
+
const contentBlocks = block.contentBlocks
|
|
41
|
+
.map(sanitize)
|
|
42
|
+
.filter((b): b is ContentBlock => b !== null);
|
|
43
|
+
return {
|
|
44
|
+
...block,
|
|
45
|
+
contentBlocks: contentBlocks.length > 0 ? contentBlocks : undefined,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
default:
|
|
49
|
+
// text, image, tool_use — kept.
|
|
50
|
+
return block;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function toAdvisorMessages(messages: ReadonlyArray<Message>): Message[] {
|
|
55
|
+
const out: Message[] = [];
|
|
56
|
+
const lastIndex = messages.length - 1;
|
|
57
|
+
|
|
58
|
+
messages.forEach((message, index) => {
|
|
59
|
+
let content = message.content
|
|
60
|
+
.map(sanitize)
|
|
61
|
+
.filter((b): b is ContentBlock => b !== null);
|
|
62
|
+
|
|
63
|
+
// The final assistant turn's client tool calls have no results yet — drop
|
|
64
|
+
// them so we never send a dangling tool_use. (server_tool_use is already
|
|
65
|
+
// dropped above.)
|
|
66
|
+
if (index === lastIndex && message.role === "assistant") {
|
|
67
|
+
content = content.filter(
|
|
68
|
+
(b) => b.type !== "tool_use" && b.type !== "server_tool_use",
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (content.length > 0) out.push({ role: message.role, content });
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
@@ -24,8 +24,15 @@
|
|
|
24
24
|
* {@link registerDefaultPlugins} at call time.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
+
import { finalizeTool } from "../../tools/tool-defaults.js";
|
|
27
28
|
import { registerPlugin, resetPluginRegistryForTests } from "../registry.js";
|
|
28
29
|
import { type Plugin, PluginExecutionError } from "../types.js";
|
|
30
|
+
import { resetAdvisorStateForTests } from "./advisor/advisor-state-store.js";
|
|
31
|
+
import advisorPostModelCall from "./advisor/hooks/post-model-call.js";
|
|
32
|
+
import advisorPreModelCall from "./advisor/hooks/pre-model-call.js";
|
|
33
|
+
import advisorUserPromptSubmit from "./advisor/hooks/user-prompt-submit.js";
|
|
34
|
+
import advisorPkg from "./advisor/package.json" with { type: "json" };
|
|
35
|
+
import advisorTool from "./advisor/tools/advisor.js";
|
|
29
36
|
import compactionPkg from "./compaction/package.json" with { type: "json" };
|
|
30
37
|
import emptyResponsePostModelCall from "./empty-response/hooks/post-model-call.js";
|
|
31
38
|
import emptyResponseStop from "./empty-response/hooks/stop.js";
|
|
@@ -54,6 +61,10 @@ import memoryRetrievalPkg from "./memory-retrieval/package.json" with { type: "j
|
|
|
54
61
|
import memoryV3PostCompact from "./memory-v3-shadow/hooks/post-compact.js";
|
|
55
62
|
import memoryV3UserPromptSubmit from "./memory-v3-shadow/hooks/user-prompt-submit.js";
|
|
56
63
|
import memoryV3Pkg from "./memory-v3-shadow/package.json" with { type: "json" };
|
|
64
|
+
import surfaceCompletionNudgePostModelCall from "./surface-completion-nudge/hooks/post-model-call.js";
|
|
65
|
+
import surfaceCompletionNudgeStop from "./surface-completion-nudge/hooks/stop.js";
|
|
66
|
+
import { resetSurfaceCompletionNudgeStoreForTests } from "./surface-completion-nudge/nudge-state-store.js";
|
|
67
|
+
import surfaceCompletionNudgePkg from "./surface-completion-nudge/package.json" with { type: "json" };
|
|
57
68
|
import taskProgressNudgePostToolUse, {
|
|
58
69
|
resetTaskProgressNudgeStateForTests,
|
|
59
70
|
} from "./task-progress-nudge/hooks/post-tool-use.js";
|
|
@@ -259,6 +270,25 @@ export const defaultTaskProgressNudgePlugin: Plugin = {
|
|
|
259
270
|
},
|
|
260
271
|
};
|
|
261
272
|
|
|
273
|
+
/**
|
|
274
|
+
* `surface-completion-nudge` — a `post-model-call` hook that, when a user-facing
|
|
275
|
+
* turn is about to end with a progress surface (a `task_progress` card or
|
|
276
|
+
* `work_result`) the model showed but never advanced to a terminal status or
|
|
277
|
+
* dismissed, nudges the model once to close it and re-queries so it can act; the
|
|
278
|
+
* `stop` hook clears the one-shot bound on a terminal stop so the next run
|
|
279
|
+
* nudges afresh.
|
|
280
|
+
*/
|
|
281
|
+
export const defaultSurfaceCompletionNudgePlugin: Plugin = {
|
|
282
|
+
manifest: {
|
|
283
|
+
name: surfaceCompletionNudgePkg.name,
|
|
284
|
+
version: surfaceCompletionNudgePkg.version,
|
|
285
|
+
},
|
|
286
|
+
hooks: {
|
|
287
|
+
"post-model-call": surfaceCompletionNudgePostModelCall,
|
|
288
|
+
stop: surfaceCompletionNudgeStop,
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
|
|
262
292
|
/**
|
|
263
293
|
* `tool-result-truncate` — a `post-tool-use` hook that tail-drops an oversized
|
|
264
294
|
* tool result down to a character budget derived from the model's context
|
|
@@ -274,6 +304,30 @@ export const defaultToolResultTruncatePlugin: Plugin = {
|
|
|
274
304
|
},
|
|
275
305
|
};
|
|
276
306
|
|
|
307
|
+
/**
|
|
308
|
+
* `advisor` — adds the model-visible `advisor` tool: a no-argument tool the
|
|
309
|
+
* model calls to consult a stronger inference profile (the `inference` call
|
|
310
|
+
* site with a `quality-optimized` override) on the full transcript, routed
|
|
311
|
+
* through the assistant's own inference. Three hooks feed it: `user-prompt-submit`
|
|
312
|
+
* seeds the capture, `pre-model-call` records the executor's system prompt and
|
|
313
|
+
* injects the steering that nudges the model to consult, and `post-model-call`
|
|
314
|
+
* snapshots the transcript the tool reads. `finalizeTool` fills the tool's
|
|
315
|
+
* defaults so it satisfies `Tool`, and `bootstrapPlugins` registers it into the
|
|
316
|
+
* catalog.
|
|
317
|
+
*/
|
|
318
|
+
export const defaultAdvisorPlugin: Plugin = {
|
|
319
|
+
manifest: {
|
|
320
|
+
name: advisorPkg.name,
|
|
321
|
+
version: advisorPkg.version,
|
|
322
|
+
},
|
|
323
|
+
hooks: {
|
|
324
|
+
"user-prompt-submit": advisorUserPromptSubmit,
|
|
325
|
+
"pre-model-call": advisorPreModelCall,
|
|
326
|
+
"post-model-call": advisorPostModelCall,
|
|
327
|
+
},
|
|
328
|
+
tools: [finalizeTool(advisorTool, "advisor")],
|
|
329
|
+
};
|
|
330
|
+
|
|
277
331
|
/**
|
|
278
332
|
* Full set of first-party default plugins. Used by
|
|
279
333
|
* {@link registerDefaultPlugins} to drive the registration loop; the array
|
|
@@ -289,11 +343,15 @@ function getAllDefaultPlugins(): readonly Plugin[] {
|
|
|
289
343
|
defaultToolErrorPlugin,
|
|
290
344
|
defaultExplorationDriftPlugin,
|
|
291
345
|
defaultTaskProgressNudgePlugin,
|
|
346
|
+
defaultSurfaceCompletionNudgePlugin,
|
|
292
347
|
defaultHistoryRepairPlugin,
|
|
293
348
|
defaultImageRecoveryPlugin,
|
|
294
349
|
defaultCompactionPlugin,
|
|
295
350
|
defaultTitleGeneratePlugin,
|
|
296
351
|
memoryV3ShadowPlugin,
|
|
352
|
+
// Registered last so its capture hooks observe the fully-processed turn
|
|
353
|
+
// (memory injections, history repair) that the executor actually sees.
|
|
354
|
+
defaultAdvisorPlugin,
|
|
297
355
|
];
|
|
298
356
|
}
|
|
299
357
|
|
|
@@ -339,5 +397,7 @@ export function resetPluginRegistryAndRegisterDefaults(): void {
|
|
|
339
397
|
resetImageRecoveryStoreForTests();
|
|
340
398
|
resetExplorationDriftStateForTests();
|
|
341
399
|
resetTaskProgressNudgeStateForTests();
|
|
400
|
+
resetSurfaceCompletionNudgeStoreForTests();
|
|
401
|
+
resetAdvisorStateForTests();
|
|
342
402
|
registerDefaultPlugins();
|
|
343
403
|
}
|