@vellumai/assistant 0.8.12 → 0.9.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/AGENTS.md +0 -14
- package/ARCHITECTURE.md +45 -45
- package/README.md +1 -1
- package/bun.lock +200 -154
- package/docs/architecture/integrations.md +3 -3
- package/docs/architecture/memory.md +2 -2
- package/docs/architecture/security.md +10 -10
- package/docs/runbook-trusted-contacts.md +12 -12
- package/docs/skills.md +6 -6
- package/docs/workflows-testing.md +221 -0
- package/docs/workflows.md +510 -0
- package/examples/plugins/echo/README.md +5 -5
- package/knip.json +2 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +105 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +12 -0
- package/openapi.yaml +7197 -5708
- package/package.json +8 -4
- package/scripts/generate-openapi.ts +66 -114
- package/src/__tests__/access-request-seed-content-blocks.test.ts +213 -0
- package/src/__tests__/adaptive-thinking-repair.test.ts +32 -3
- package/src/__tests__/agent-loop-output-hooks.test.ts +183 -0
- package/src/__tests__/agent-loop-regrowth-guard.test.ts +506 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +77 -0
- package/src/__tests__/app-compiler.test.ts +7 -1
- package/src/__tests__/app-dir-path-guard.test.ts +27 -3
- package/src/__tests__/app-executors.test.ts +43 -0
- package/src/__tests__/approval-cascade.test.ts +0 -5
- package/src/__tests__/approval-routes-http.test.ts +91 -0
- package/src/__tests__/assistant-stream-state.test.ts +107 -0
- package/src/__tests__/browser-fill-credential.test.ts +3 -3
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +1 -1
- package/src/__tests__/compaction-events.test.ts +63 -7
- package/src/__tests__/compaction-trail-store.test.ts +74 -1
- package/src/__tests__/compaction.benchmark.test.ts +63 -41
- package/src/__tests__/compactor-low-watermark-cut.test.ts +349 -0
- package/src/__tests__/context-window-manager-compact-retry.test.ts +64 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -5
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -5
- package/src/__tests__/conversation-history-web-search.test.ts +7 -0
- package/src/__tests__/conversation-process-callsite.test.ts +0 -5
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -5
- package/src/__tests__/conversation-queue.test.ts +0 -5
- package/src/__tests__/conversation-slash-queue.test.ts +0 -5
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -5
- package/src/__tests__/conversation-speed-override.test.ts +0 -5
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +97 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
- package/src/__tests__/conversation-usage.test.ts +2 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -5
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -5
- package/src/__tests__/credential-broker-browser-fill.test.ts +2 -2
- package/src/__tests__/credential-broker-server-use.test.ts +2 -2
- package/src/__tests__/credential-broker.test.ts +1 -1
- package/src/__tests__/credential-prompt-route.test.ts +417 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault.test.ts +37 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +24 -0
- package/src/__tests__/dynamic-page-surface.test.ts +219 -0
- package/src/__tests__/empty-state-greeting-cache.test.ts +94 -0
- package/src/__tests__/gateway-flag-listener.test.ts +24 -7
- package/src/__tests__/guardian-action-sweep.test.ts +56 -219
- package/src/__tests__/guardian-routing-invariants.test.ts +138 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
- package/src/__tests__/list-messages-hidden-metadata.test.ts +99 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +87 -1
- package/src/__tests__/llm-resolver.test.ts +115 -0
- package/src/__tests__/managed-profile-guard.test.ts +6 -5
- package/src/__tests__/max-tokens-continue-hook.test.ts +184 -0
- package/src/__tests__/media-generate-image.test.ts +20 -9
- package/src/__tests__/mock-gateway-ipc.ts +23 -0
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/normalize-onboarding.test.ts +26 -0
- package/src/__tests__/notification-decision-strategy.test.ts +4 -2
- package/src/__tests__/notification-telegram-adapter.test.ts +21 -3
- package/src/__tests__/pending-interactions-resolved-event.test.ts +62 -0
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +72 -18
- package/src/__tests__/require-fresh-approval.test.ts +425 -1
- package/src/__tests__/resolve-app-id.test.ts +56 -0
- package/src/__tests__/runtime-events-sse-parity.test.ts +2 -0
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +408 -0
- package/src/__tests__/schedule-routes.test.ts +257 -4
- package/src/__tests__/schedule-store.test.ts +60 -0
- package/src/__tests__/schedule-tools.test.ts +247 -2
- package/src/__tests__/skill-execute-input.test.ts +85 -0
- package/src/__tests__/skill-secret-handling-guard.test.ts +21 -20
- package/src/__tests__/skills.test.ts +3 -3
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +1 -1
- package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +547 -0
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/__tests__/task-progress-nudge-hook.test.ts +372 -0
- package/src/__tests__/task-scheduler.test.ts +299 -0
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +209 -0
- package/src/__tests__/tool-result-spool.test.ts +3 -1
- package/src/__tests__/workspace-migration-102-preserve-heartbeat-enabled-for-existing-workspaces.test.ts +181 -0
- package/src/__tests__/workspace-migration-103-upgrade-quality-profile-to-opus-4-8.test.ts +174 -0
- package/src/agent/compaction-circuit.ts +11 -0
- package/src/agent/loop.ts +181 -12
- package/src/api/constants/call-sites.ts +12 -0
- package/src/api/events/assistant-thinking-delta.ts +10 -0
- package/src/api/events/usage-update.ts +7 -0
- package/src/api/index.ts +4 -1
- package/src/api/responses/memory-v3-selection-log.ts +18 -11
- package/src/approvals/approval-primitive.ts +2 -2
- package/src/background-wake/background-wake-routes.test.ts +5 -2
- package/src/bundler/compiler-tools.ts +1 -1
- package/src/bundler/package-resolver.ts +0 -1
- package/src/calls/call-domain.ts +1 -1
- package/src/calls/guardian-action-sweep.ts +16 -93
- package/src/cli/AGENTS.md +4 -0
- package/src/cli/commands/__tests__/schedules.test.ts +430 -1
- package/src/cli/commands/credentials.ts +28 -24
- package/src/cli/commands/image-generation.ts +23 -9
- package/src/cli/commands/notifications.ts +1 -1
- package/src/cli/commands/plugins.ts +89 -46
- package/src/cli/commands/schedules.ts +384 -11
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +69 -5
- package/src/cli/lib/__tests__/install-from-github.test.ts +15 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +81 -4
- package/src/cli/lib/inspect-plugin.ts +62 -1
- package/src/cli/lib/install-from-github.ts +52 -5
- package/src/cli/lib/upgrade-plugin.ts +18 -0
- package/src/config/__tests__/workflows-schema.test.ts +60 -0
- package/src/config/bundled-skills/acp/SKILL.md +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +6 -1
- package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +7 -1
- package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +7 -1
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +10 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +66 -19
- package/src/config/bundled-skills/image-studio/TOOLS.json +1 -6
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +22 -3
- package/src/config/bundled-skills/personal-page/SKILL.md +57 -0
- package/src/config/bundled-skills/personal-page/TOOLS.json +27 -0
- package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +17 -0
- package/src/config/bundled-skills/schedule/SKILL.md +7 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +48 -4
- package/src/config/bundled-skills/workflows/SKILL.md +214 -0
- package/src/config/bundled-skills/workflows/TOOLS.json +84 -0
- package/src/config/bundled-skills/workflows/tools/manage-workflows.ts +12 -0
- package/src/config/bundled-skills/workflows/tools/run-workflow.ts +12 -0
- package/src/config/bundled-tool-registry.ts +14 -2
- package/src/config/call-site-defaults.ts +5 -0
- package/src/config/feature-flag-registry.json +12 -4
- package/src/config/llm-context-resolution.ts +8 -0
- package/src/config/llm-resolver.ts +30 -0
- package/src/config/preloaded-apps/personal-page/src/components/About.tsx +22 -0
- package/src/config/preloaded-apps/personal-page/src/components/App.tsx +16 -0
- package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +77 -0
- package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +57 -0
- package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +28 -0
- package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +234 -0
- package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +48 -0
- package/src/config/preloaded-apps/personal-page/src/components/media.ts +16 -0
- package/src/config/preloaded-apps/personal-page/src/index.html +20 -0
- package/src/config/preloaded-apps/personal-page/src/main.tsx +7 -0
- package/src/config/preloaded-apps/personal-page/src/profile-data.ts +82 -0
- package/src/config/preloaded-apps/personal-page/src/styles.css +759 -0
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/heartbeat.ts +4 -1
- package/src/config/schemas/llm.ts +33 -26
- package/src/config/schemas/memory-retrospective.ts +19 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/services.ts +5 -2
- package/src/config/schemas/workflows.ts +42 -0
- package/src/config/skills.ts +3 -3
- package/src/context/compactor.ts +273 -39
- package/src/context/post-turn-tool-result-truncation.ts +23 -6
- package/src/context/tool-result-spool.ts +12 -17
- package/src/credential-execution/executable-discovery.ts +1 -1
- package/src/credential-execution/process-manager.ts +37 -3
- package/src/credential-execution/prompted-credential.ts +205 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +14 -0
- package/src/daemon/conversation-process.ts +11 -2
- package/src/daemon/conversation-surfaces.ts +167 -3
- package/src/daemon/conversation-tool-setup.ts +103 -26
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +115 -11
- package/src/daemon/handlers/shared.ts +26 -14
- package/src/daemon/host-cu-proxy.ts +15 -12
- package/src/daemon/host-file-proxy.ts +15 -12
- package/src/daemon/host-transfer-proxy.ts +30 -24
- package/src/daemon/lifecycle.ts +40 -3
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/messages.ts +2 -10
- package/src/daemon/message-types/workflows.ts +49 -0
- package/src/daemon/parse-actual-tokens-from-error.test.ts +62 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +43 -4
- package/src/daemon/process-message.ts +6 -0
- package/src/daemon/tool-setup-types.ts +57 -0
- package/src/daemon/wake-conversation-ops.ts +18 -0
- package/src/heartbeat/heartbeat-run-store.ts +8 -2
- package/src/home/feed-types.ts +1 -1
- package/src/ipc/gateway-flag-listener.ts +28 -6
- package/src/mcp/mcp-auth-state.ts +8 -20
- package/src/media/__tests__/image-models.test.ts +57 -0
- package/src/media/image-models.ts +66 -0
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +38 -0
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +12 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +911 -34
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +227 -5
- package/src/memory/__tests__/memory-retrospective-state.test.ts +195 -0
- package/src/memory/__tests__/preloaded-apps.test.ts +85 -0
- package/src/memory/auto-analysis-enqueue.ts +14 -1
- package/src/memory/compaction-log-store-clickhouse.ts +6 -4
- package/src/memory/conversation-crud.ts +9 -2
- package/src/memory/conversation-disk-view.ts +1 -1
- package/src/memory/conversation-queries.ts +22 -7
- package/src/memory/db-init.ts +20 -0
- package/src/memory/db-maintenance.ts +16 -0
- package/src/memory/embedding-runtime-manager.ts +1 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +112 -14
- package/src/memory/llm-request-log-source-local.ts +19 -1
- package/src/memory/llm-request-log-source.ts +35 -6
- package/src/memory/llm-request-log-store.ts +90 -2
- package/src/memory/memory-retrospective-constants.ts +9 -0
- package/src/memory/memory-retrospective-enqueue.ts +3 -6
- package/src/memory/memory-retrospective-fork-boundary.ts +94 -0
- package/src/memory/memory-retrospective-job.ts +500 -208
- package/src/memory/memory-retrospective-startup-cleanup.ts +97 -19
- package/src/memory/memory-retrospective-state.ts +85 -2
- package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +40 -0
- package/src/memory/migrations/282-schedule-inference-profile.test.ts +77 -0
- package/src/memory/migrations/282-schedule-inference-profile.ts +26 -0
- package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.test.ts +102 -0
- package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.ts +53 -0
- package/src/memory/migrations/284-workflow-runs.ts +51 -0
- package/src/memory/migrations/285-schedule-workflow-mode.ts +26 -0
- package/src/memory/migrations/286-workflow-run-trust.ts +27 -0
- package/src/memory/migrations/287-conversation-origin-channel-index.ts +15 -0
- package/src/memory/migrations/288-backfill-origin-channel-from-bindings.ts +43 -0
- package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +115 -0
- package/src/memory/migrations/290-schedule-capabilities.test.ts +77 -0
- package/src/memory/migrations/290-schedule-capabilities.ts +25 -0
- package/src/memory/migrations/__tests__/281-memory-retrospective-remembered-log.test.ts +96 -0
- package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +571 -0
- package/src/memory/migrations/index.ts +10 -0
- package/src/memory/preloaded-apps.ts +116 -0
- package/src/memory/schema/infrastructure.ts +4 -0
- package/src/memory/schema/memory-core.ts +4 -0
- package/src/memory/v2/__tests__/concept-page-frontmatter-schema.test.ts +45 -0
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +11 -7
- package/src/memory/v2/__tests__/page-store.test.ts +13 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +24 -0
- package/src/memory/v2/frontmatter-sweep.ts +7 -6
- package/src/memory/v2/page-store.ts +4 -3
- package/src/memory/v2/qdrant.ts +42 -3
- package/src/memory/v2/types.ts +16 -10
- package/src/messaging/draft-store.ts +1 -1
- package/src/notifications/access-request-copy.ts +200 -113
- package/src/notifications/adapters/slack.ts +250 -111
- package/src/notifications/adapters/telegram.ts +7 -44
- package/src/notifications/approval-card-builder.ts +93 -0
- package/src/notifications/broadcaster.ts +74 -0
- package/src/notifications/conversation-pairing.ts +8 -6
- package/src/notifications/copy-composer.ts +32 -26
- package/src/notifications/decision-engine.ts +59 -7
- package/src/notifications/guardian-question-mode.ts +145 -155
- package/src/notifications/home-feed-side-effect.ts +28 -11
- package/src/notifications/notification-utils.ts +66 -0
- package/src/notifications/signal.ts +6 -0
- package/src/notifications/tool-approval-copy.ts +142 -0
- package/src/notifications/types.ts +19 -0
- package/src/permissions/threshold.ts +11 -0
- package/src/plugin-api/types.ts +16 -4
- package/src/plugins/defaults/compaction/window-manager.ts +44 -0
- package/src/plugins/defaults/index.ts +46 -0
- package/src/plugins/defaults/max-tokens-continue/continue-state-store.ts +53 -0
- package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +80 -0
- package/src/plugins/defaults/max-tokens-continue/hooks/stop.ts +20 -0
- package/src/plugins/defaults/max-tokens-continue/package.json +14 -0
- package/src/plugins/defaults/memory-retrieval/hooks/__tests__/user-prompt-submit.test.ts +37 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +29 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +8 -3
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +4 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +28 -18
- package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +67 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +122 -22
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +2 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +63 -1
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +61 -18
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +1 -1
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +39 -10
- package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +34 -1
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +112 -47
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +78 -15
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +206 -0
- package/src/plugins/defaults/task-progress-nudge/package.json +15 -0
- package/src/prompts/__tests__/system-prompt.test.ts +100 -1
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +5 -7
- package/src/prompts/normalize-onboarding.ts +2 -0
- package/src/prompts/persona-resolver.ts +3 -0
- package/src/prompts/system-prompt.ts +51 -2
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +3 -1
- package/src/prompts/templates/system-sections.ts +8 -3
- package/src/providers/call-site-routing.ts +6 -3
- package/src/providers/fireworks/client.ts +3 -0
- package/src/providers/inference/auth.ts +52 -46
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/openai/__tests__/coerce-object-args.test.ts +105 -0
- package/src/providers/openai/chat-completions-provider.ts +47 -9
- package/src/providers/openai/coerce-object-args.ts +104 -0
- package/src/providers/retry.ts +8 -5
- package/src/providers/types.ts +10 -0
- package/src/runtime/__tests__/agent-wake.test.ts +629 -7
- package/src/runtime/access-request-helper.ts +16 -9
- package/src/runtime/agent-wake.ts +302 -51
- package/src/runtime/assistant-stream-state.ts +141 -8
- package/src/runtime/background-job-runner.ts +9 -0
- package/src/runtime/channel-approval-types.ts +1 -0
- package/src/runtime/channel-invite-transports/telegram.ts +6 -5
- package/src/runtime/channel-invite-transports/voice.ts +2 -2
- package/src/runtime/channel-invite-types.ts +4 -2
- package/src/runtime/channel-retry-sweep.ts +19 -41
- package/src/runtime/finalize-event-delivery.ts +72 -0
- package/src/runtime/guardian-action-message-composer.ts +0 -54
- package/src/runtime/http-server.ts +6 -14
- package/src/runtime/http-types.ts +0 -1
- package/src/runtime/message-composer-types.ts +0 -9
- package/src/runtime/middleware/__tests__/rate-limiter.test.ts +63 -0
- package/src/runtime/middleware/auth.ts +27 -3
- package/src/runtime/middleware/rate-limiter.ts +28 -1
- package/src/runtime/migrations/vbundle-builder.ts +6 -5
- package/src/runtime/pending-interactions.ts +20 -1
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +232 -173
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +18 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +436 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +11 -0
- package/src/runtime/routes/approval-routes.ts +35 -8
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -1
- package/src/runtime/routes/btw-routes.ts +37 -1
- package/src/runtime/routes/channel-delivery-routes.ts +11 -7
- package/src/runtime/routes/channel-route-definitions.ts +3 -0
- package/src/runtime/routes/channel-route-shared.ts +3 -1
- package/src/runtime/routes/consolidation-routes.ts +17 -13
- package/src/runtime/routes/conversation-compaction-routes.ts +159 -119
- package/src/runtime/routes/conversation-list-routes.ts +41 -4
- package/src/runtime/routes/conversation-query-routes.ts +196 -11
- package/src/runtime/routes/conversation-routes.ts +15 -1
- package/src/runtime/routes/credential-prompt-routes.ts +39 -17
- package/src/runtime/routes/empty-state-greeting-cache.ts +65 -0
- package/src/runtime/routes/heartbeat-routes.ts +18 -13
- package/src/runtime/routes/image-generation-routes.ts +20 -2
- package/src/runtime/routes/inbound-message-handler.ts +13 -12
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +32 -31
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +7 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +7 -21
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +5 -5
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +6 -15
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +1 -1
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/log-export/AGENTS.md +1 -1
- package/src/runtime/routes/log-export/workspace-allowlist.ts +1 -1
- package/src/runtime/routes/migration-routes.ts +5 -9
- package/src/runtime/routes/plugins-routes.ts +26 -0
- package/src/runtime/routes/ps-routes.ts +10 -8
- package/src/runtime/routes/retrospective-routes.ts +235 -0
- package/src/runtime/routes/runs-pagination.ts +75 -0
- package/src/runtime/routes/schedule-routes.ts +367 -59
- package/src/runtime/routes/sounds-config-routes.ts +239 -0
- package/src/runtime/routes/surface-action-routes.ts +84 -4
- package/src/runtime/routes/workflow-routes.test.ts +372 -0
- package/src/runtime/routes/workflow-routes.ts +363 -0
- package/src/runtime/routes/workspace-routes.test.ts +61 -1
- package/src/runtime/routes/workspace-routes.ts +26 -1
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +38 -0
- package/src/runtime/services/analyze-conversation.ts +26 -13
- package/src/schedule/inference-profile.ts +28 -0
- package/src/schedule/schedule-store.ts +152 -4
- package/src/schedule/scheduler-types.ts +6 -0
- package/src/schedule/scheduler.ts +96 -0
- package/src/security/secret-allowlist.ts +1 -1
- package/src/skills/path-classifier.ts +1 -1
- package/src/tools/apps/executors.ts +23 -0
- package/src/tools/apps/resolve-app-id.ts +42 -0
- package/src/tools/browser/browser-execution.ts +9 -11
- package/src/tools/credentials/broker.ts +4 -4
- package/src/tools/credentials/vault.ts +26 -137
- package/src/tools/executor.ts +69 -0
- package/src/tools/flag-gated-tools.test.ts +76 -0
- package/src/tools/permission-checker.ts +8 -1
- package/src/tools/registry.ts +51 -0
- package/src/tools/schedule/create.ts +77 -1
- package/src/tools/schedule/list.ts +1 -0
- package/src/tools/schedule/update.ts +73 -1
- package/src/tools/skills/execute.ts +56 -0
- package/src/tools/terminal/shell.ts +1 -1
- package/src/tools/ui-surface/definitions.ts +91 -2
- package/src/tools/workflows/manage-workflows.ts +183 -0
- package/src/tools/workflows/run-workflow.test.ts +442 -0
- package/src/tools/workflows/run-workflow.ts +88 -0
- package/src/types/onboarding-context.ts +2 -0
- package/src/usage/attribution.ts +24 -0
- package/src/util/canonicalize-identity.ts +12 -3
- package/src/util/platform.ts +17 -17
- package/src/watcher/__tests__/engine.test.ts +24 -0
- package/src/watcher/__tests__/telemetry.test.ts +135 -0
- package/src/watcher/engine.ts +7 -0
- package/src/watcher/telemetry.ts +74 -0
- package/src/workflows/capabilities.test.ts +365 -0
- package/src/workflows/capabilities.ts +359 -0
- package/src/workflows/deterministic-stringify.ts +27 -0
- package/src/workflows/engine-integration.test.ts +656 -0
- package/src/workflows/engine.test.ts +1144 -0
- package/src/workflows/engine.ts +1078 -0
- package/src/workflows/fanout-load.test.ts +168 -0
- package/src/workflows/journal-store.test.ts +369 -0
- package/src/workflows/journal-store.ts +470 -0
- package/src/workflows/leaf-runner.test.ts +704 -0
- package/src/workflows/leaf-runner.ts +589 -0
- package/src/workflows/library.test.ts +134 -0
- package/src/workflows/library.ts +124 -0
- package/src/workflows/run-manager.test.ts +711 -0
- package/src/workflows/run-manager.ts +593 -0
- package/src/workflows/sandbox-escape.test.ts +339 -0
- package/src/workflows/sandbox.test.ts +251 -0
- package/src/workflows/sandbox.ts +447 -0
- package/src/workspace/adaptive-thinking-repair.ts +33 -11
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +1 -1
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +1 -1
- package/src/workspace/migrations/026-backfill-install-meta.ts +1 -1
- package/src/workspace/migrations/030-seed-pkb-autoinject.ts +2 -1
- package/src/workspace/migrations/031-drop-user-md.ts +1 -4
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +1 -1
- package/src/workspace/migrations/056-release-notes-inference-profile-reordering.ts +5 -2
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +1 -1
- package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +8 -2
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +41 -14
- package/src/workspace/migrations/102-preserve-heartbeat-enabled-for-existing-workspaces.ts +69 -0
- package/src/workspace/migrations/103-upgrade-quality-profile-to-opus-4-8.ts +83 -0
- package/src/workspace/migrations/104-recheck-adaptive-thinking-model-implied-anthropic.ts +133 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/migrations/runner.ts +1 -1
- package/tsconfig.json +1 -1
- package/src/__tests__/guardian-action-copy-generator.test.ts +0 -200
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -579
- package/src/__tests__/guardian-action-store.test.ts +0 -106
- package/src/daemon/guardian-action-generators.ts +0 -71
- package/src/memory/guardian-action-store.ts +0 -484
- package/src/runtime/guardian-action-grant-minter.ts +0 -150
|
@@ -56,6 +56,12 @@ export interface AccessRequestParams {
|
|
|
56
56
|
previousMemberStatus?: Exclude<ChannelStatus, "unverified">;
|
|
57
57
|
/** Preview of the requester's original message, shown to the guardian. */
|
|
58
58
|
messagePreview?: string;
|
|
59
|
+
/** Slack-specific: user is from an external workspace (Slack Connect). */
|
|
60
|
+
isStranger?: boolean;
|
|
61
|
+
/** Slack-specific: user is a guest / restricted account. */
|
|
62
|
+
isRestricted?: boolean;
|
|
63
|
+
/** Slack message timestamp for permalink construction. */
|
|
64
|
+
messageTs?: string;
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
export type AccessRequestResult =
|
|
@@ -92,6 +98,9 @@ export function notifyGuardianOfAccessRequest(
|
|
|
92
98
|
actorUsername,
|
|
93
99
|
previousMemberStatus,
|
|
94
100
|
messagePreview,
|
|
101
|
+
isStranger,
|
|
102
|
+
isRestricted,
|
|
103
|
+
messageTs,
|
|
95
104
|
} = params;
|
|
96
105
|
|
|
97
106
|
if (!actorExternalId) {
|
|
@@ -193,15 +202,10 @@ export function notifyGuardianOfAccessRequest(
|
|
|
193
202
|
|
|
194
203
|
let vellumDeliveryId: string | null = null;
|
|
195
204
|
// When the access request originates from a text channel with
|
|
196
|
-
// notification delivery support (Slack, Telegram)
|
|
197
|
-
//
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
// to deliver the verification code. Phone is excluded because it is
|
|
201
|
-
// not a deliverable notification channel.
|
|
202
|
-
// When the guardian was resolved via a verified same-channel contact,
|
|
203
|
-
// route only to that channel — delivering on desktop as well is noisy
|
|
204
|
-
// and the desktop path lacks the channel delivery context for approval.
|
|
205
|
+
// notification delivery support (Slack, Telegram) and the guardian was
|
|
206
|
+
// resolved via a verified same-channel contact, route the notification
|
|
207
|
+
// only to that channel to reduce noise. Phone is excluded because it
|
|
208
|
+
// is not a deliverable notification channel.
|
|
205
209
|
// When the guardian was NOT verified on the source channel (e.g. resolved
|
|
206
210
|
// via vellum anchor), route to all channels so the guardian can see
|
|
207
211
|
// the request on desktop/other channels where they ARE verified.
|
|
@@ -238,6 +242,9 @@ export function notifyGuardianOfAccessRequest(
|
|
|
238
242
|
guardianResolutionSource,
|
|
239
243
|
previousMemberStatus: previousMemberStatus ?? null,
|
|
240
244
|
messagePreview: messagePreview ?? null,
|
|
245
|
+
...(isStranger !== undefined ? { isStranger } : {}),
|
|
246
|
+
...(isRestricted !== undefined ? { isRestricted } : {}),
|
|
247
|
+
...(messageTs ? { messageTs } : {}),
|
|
241
248
|
},
|
|
242
249
|
dedupeKey: `access-request:${canonicalRequest.id}`,
|
|
243
250
|
onConversationCreated: (info) => {
|
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Semantics:
|
|
9
9
|
* - Resolves the conversation context exactly as a normal user turn.
|
|
10
|
+
* - Runs the conversation's auto-threshold compaction gate
|
|
11
|
+
* (`conversation.maybeCompact()`) before snapshotting the history —
|
|
12
|
+
* the wake bypasses the orchestrator's in-loop compaction, so this is
|
|
13
|
+
* its turn-start equivalent. Callers can pass
|
|
14
|
+
* `suppressAutoCompaction: true` to skip it; a suppressed wake whose
|
|
15
|
+
* input exceeds the effective context window fails deterministically
|
|
16
|
+
* with `reason: "context_overflow"` instead of compacting.
|
|
10
17
|
* - Appends `hint` as a non-persisted assistant message sandwiched
|
|
11
18
|
* between two static user messages — never shows up in the transcript
|
|
12
19
|
* or SSE feed. The assistant role prevents prompt injection (LLMs
|
|
@@ -56,6 +63,11 @@ import {
|
|
|
56
63
|
classifyDiskPressureTurnPolicy,
|
|
57
64
|
type DiskPressureTurnPolicyDecision,
|
|
58
65
|
} from "../daemon/disk-pressure-policy.js";
|
|
66
|
+
import { looksLikeContextOverflowError } from "../daemon/parse-actual-tokens-from-error.js";
|
|
67
|
+
import type {
|
|
68
|
+
SubagentToolGateMode,
|
|
69
|
+
WakeToolContextPin,
|
|
70
|
+
} from "../daemon/tool-setup-types.js";
|
|
59
71
|
import type { TrustContext } from "../daemon/trust-context.js";
|
|
60
72
|
import {
|
|
61
73
|
broadcastWakeSurface,
|
|
@@ -73,6 +85,7 @@ import {
|
|
|
73
85
|
recordRequestLog,
|
|
74
86
|
setAgentLoopExitReasonOnLatestLog,
|
|
75
87
|
} from "../memory/llm-request-log-store.js";
|
|
88
|
+
import type { SystemPromptPersonaOverride } from "../prompts/system-prompt.js";
|
|
76
89
|
import type { Message } from "../providers/types.js";
|
|
77
90
|
import { getLogger } from "../util/logger.js";
|
|
78
91
|
|
|
@@ -86,6 +99,14 @@ const WAKE_PREAMBLE =
|
|
|
86
99
|
const WAKE_POSTAMBLE =
|
|
87
100
|
"[system] End of message from external system, continue the conversation.";
|
|
88
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Warn line shared by the two reactive over-window failure sites (provider
|
|
104
|
+
* rejection escaped as a throw / swallowed into a no-output stop). The
|
|
105
|
+
* pre-flight estimate site logs its own distinct message.
|
|
106
|
+
*/
|
|
107
|
+
const OVER_WINDOW_REJECTION_LOG_MESSAGE =
|
|
108
|
+
"agent-wake: provider rejected the input as over-window with auto-compaction suppressed; failing the wake";
|
|
109
|
+
|
|
89
110
|
export interface WakeOptions {
|
|
90
111
|
conversationId: string;
|
|
91
112
|
hint: string;
|
|
@@ -113,6 +134,19 @@ export interface WakeOptions {
|
|
|
113
134
|
* tune the model/profile and observability bucket independently.
|
|
114
135
|
*/
|
|
115
136
|
callSite?: LLMCallSite;
|
|
137
|
+
/**
|
|
138
|
+
* Run the wake's LLM calls under this inference profile, floated ABOVE the
|
|
139
|
+
* call site's named profile and call-site overrides (the resolver's
|
|
140
|
+
* `forceOverrideProfile` escape hatch). When set, it replaces the
|
|
141
|
+
* conversation's own pinned-profile lookup. Used by fork-based memory
|
|
142
|
+
* retrospectives to resolve the SAME model/thinking/effort as the source
|
|
143
|
+
* conversation's turns so the provider prompt-cache prefix can be reused.
|
|
144
|
+
* A profile name that no longer exists in `llm.profiles` silently falls
|
|
145
|
+
* back to normal call-site resolution (the resolver's standard
|
|
146
|
+
* missing-reference semantics). Logging/attribution still bucket under
|
|
147
|
+
* `callSite`.
|
|
148
|
+
*/
|
|
149
|
+
forceOverrideProfile?: string;
|
|
116
150
|
/**
|
|
117
151
|
* Role to use for the injected hint message. Defaults to `"assistant"` so
|
|
118
152
|
* the hint is sandwiched between two static user bookends — the canonical
|
|
@@ -124,22 +158,25 @@ export interface WakeOptions {
|
|
|
124
158
|
*/
|
|
125
159
|
hintRole?: "assistant" | "user";
|
|
126
160
|
/**
|
|
127
|
-
*
|
|
161
|
+
* Skip the wake's pre-run auto-threshold compaction gate and refuse to
|
|
162
|
+
* run over-window instead of compacting.
|
|
128
163
|
*
|
|
129
|
-
*
|
|
130
|
-
* `conversation.agentLoop.run()`
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
164
|
+
* By default the wake runs `conversation.maybeCompact()` before
|
|
165
|
+
* snapshotting the history — the wake invokes `conversation.agentLoop.run()`
|
|
166
|
+
* directly with the loop's in-loop budget gate disabled, so this pre-run
|
|
167
|
+
* gate is the wake path's equivalent of the turn-start compaction the
|
|
168
|
+
* daemon orchestrator (`conversation-agent-loop.ts`) performs for user
|
|
169
|
+
* turns. Passing `true` skips the gate entirely; if the wake input would
|
|
170
|
+
* then exceed the effective context window, the wake fails fast with
|
|
171
|
+
* `reason: "context_overflow"` instead of compacting, and a provider
|
|
172
|
+
* context-overflow rejection mid-run is mapped to the same failure.
|
|
137
173
|
*
|
|
138
174
|
* Used by fork-based memory retrospectives: the wake operates on a
|
|
139
|
-
* freshly-forked conversation that may already be near (or
|
|
140
|
-
* source's auto-threshold, but the goal is to operate on that
|
|
141
|
-
* context — running a compaction LLM call before the wake's own
|
|
142
|
-
* call would waste tokens
|
|
175
|
+
* freshly-forked throwaway conversation that may already be near (or
|
|
176
|
+
* past) the source's auto-threshold, but the goal is to operate on that
|
|
177
|
+
* exact context — running a compaction LLM call before the wake's own
|
|
178
|
+
* first call would waste tokens, defeat prompt-cache reuse, and fire
|
|
179
|
+
* compaction side-effects on a fork that is deleted afterwards.
|
|
143
180
|
*/
|
|
144
181
|
suppressAutoCompaction?: boolean;
|
|
145
182
|
/**
|
|
@@ -161,9 +198,48 @@ export interface WakeOptions {
|
|
|
161
198
|
/**
|
|
162
199
|
* Optional exact tool allowlist for this wake. Used by internal maintenance
|
|
163
200
|
* jobs that need the assistant's judgment but must not execute arbitrary
|
|
164
|
-
* side-effect tools.
|
|
201
|
+
* side-effect tools. Enforcement depends on `toolGateMode`: in `"wire"`
|
|
202
|
+
* mode (default) the tool definitions sent to the provider are filtered to
|
|
203
|
+
* the allowlist; in `"execution"` mode the full tool surface stays on the
|
|
204
|
+
* wire and non-allowlisted calls are rejected with an error tool_result
|
|
205
|
+
* before their executor runs. Either way, only allowlisted tools can
|
|
206
|
+
* execute during the wake.
|
|
165
207
|
*/
|
|
166
208
|
allowedTools?: readonly string[];
|
|
209
|
+
/**
|
|
210
|
+
* How `allowedTools` is enforced — see {@link SubagentToolGateMode} for the
|
|
211
|
+
* wire-vs-execution semantics and cache-parity rationale. Defaults to
|
|
212
|
+
* `"wire"` (the historical behavior, byte-identical when absent). Ignored
|
|
213
|
+
* when `allowedTools` is absent.
|
|
214
|
+
*/
|
|
215
|
+
toolGateMode?: SubagentToolGateMode;
|
|
216
|
+
/**
|
|
217
|
+
* Client-context pin applied (and restored) alongside `allowedTools` for
|
|
218
|
+
* the duration of the wake — see {@link WakeToolContextPin}. Pass only
|
|
219
|
+
* with `toolGateMode: "execution"`: it exists purely so the wire tool
|
|
220
|
+
* definitions resolve under the SOURCE conversation's client context
|
|
221
|
+
* (provider prompt-cache parity) and is pointless when the wire is
|
|
222
|
+
* allowlist-filtered anyway. Definition resolution only — pinned-in tools
|
|
223
|
+
* remain execution-rejected by the gate. Ignored when `allowedTools` is
|
|
224
|
+
* absent.
|
|
225
|
+
*/
|
|
226
|
+
toolContextPin?: WakeToolContextPin;
|
|
227
|
+
/**
|
|
228
|
+
* Explicit persona/channel slugs for the wake's system-prompt build,
|
|
229
|
+
* applied to the conversation for the duration of the run and restored
|
|
230
|
+
* afterwards. Wakes bypass the orchestrator's turn-start persona snapshot,
|
|
231
|
+
* so their prompt is otherwise built from whatever snapshot the
|
|
232
|
+
* conversation already holds — for a freshly hydrated conversation (the
|
|
233
|
+
* fork-retrospective case) that is the no-trust-context derivation
|
|
234
|
+
* (guardian persona + "vellum" channel) regardless of which actor/channel
|
|
235
|
+
* the conversation belongs to. Used by fork-based memory retrospectives to
|
|
236
|
+
* render the SOURCE conversation's persona sections — both for review
|
|
237
|
+
* quality and for byte-parity with the source's cached system-prompt
|
|
238
|
+
* prefix. May also pin `hasNoClient` for the prompt build (see
|
|
239
|
+
* {@link SystemPromptPersonaOverride}). Prompt-build selection only; trust
|
|
240
|
+
* class and approval semantics are governed solely by `trustContext`.
|
|
241
|
+
*/
|
|
242
|
+
personaOverride?: SystemPromptPersonaOverride;
|
|
167
243
|
}
|
|
168
244
|
|
|
169
245
|
/**
|
|
@@ -177,7 +253,14 @@ export type WakeSkipReason =
|
|
|
177
253
|
| "archived"
|
|
178
254
|
| "timeout"
|
|
179
255
|
| "no_resolver"
|
|
180
|
-
| "disk_pressure"
|
|
256
|
+
| "disk_pressure"
|
|
257
|
+
/**
|
|
258
|
+
* The wake input exceeds the effective context window and the caller
|
|
259
|
+
* suppressed auto-compaction (`suppressAutoCompaction: true`), so the
|
|
260
|
+
* run cannot proceed without the compaction it was told not to perform.
|
|
261
|
+
* Only possible on suppressed wakes.
|
|
262
|
+
*/
|
|
263
|
+
| "context_overflow";
|
|
181
264
|
|
|
182
265
|
export interface WakeResult {
|
|
183
266
|
invoked: boolean;
|
|
@@ -331,10 +414,12 @@ function classifyWakeDiskPressurePolicy(opts: WakeOptions): {
|
|
|
331
414
|
}
|
|
332
415
|
|
|
333
416
|
/**
|
|
334
|
-
* Trust snapshot the wake hands to the agent loop.
|
|
335
|
-
* path (it runs with overflow recovery disabled
|
|
336
|
-
*
|
|
337
|
-
*
|
|
417
|
+
* Trust snapshot the wake hands to the agent loop. The wake's loop run has
|
|
418
|
+
* no in-loop compaction path (it runs with overflow recovery disabled; the
|
|
419
|
+
* wake compacts via the pre-run gate instead, which resolves trust from the
|
|
420
|
+
* conversation's own trust context), so this snapshot is unread except on
|
|
421
|
+
* the disk-pressure cleanup-mode path, whose guardian value scopes the
|
|
422
|
+
* compactor's image manifest if cleanup ever compacts. Other wakes pass an
|
|
338
423
|
* `unknown`-class snapshot so a missing actor cannot grant elevated trust.
|
|
339
424
|
*/
|
|
340
425
|
function buildWakeTrust(
|
|
@@ -420,6 +505,7 @@ export async function wakeAgentForOpportunity(
|
|
|
420
505
|
deps?: WakeDeps,
|
|
421
506
|
): Promise<WakeResult> {
|
|
422
507
|
const { conversationId, hint, source } = opts;
|
|
508
|
+
const suppressAutoCompaction = opts.suppressAutoCompaction === true;
|
|
423
509
|
const resolveTarget = deps?.resolveTarget ?? defaultResolveTarget;
|
|
424
510
|
const nowFn = deps?.now ?? Date.now;
|
|
425
511
|
const startedAt = nowFn();
|
|
@@ -486,6 +572,85 @@ export async function wakeAgentForOpportunity(
|
|
|
486
572
|
conversation.setTrustContext(opts.trustContext);
|
|
487
573
|
}
|
|
488
574
|
|
|
575
|
+
// Honor the conversation's pinned inference-profile override (if any).
|
|
576
|
+
// Without this, scheduled-task wakes and other opportunity wakes bypass
|
|
577
|
+
// `runAgentLoopImpl` entirely and execute under workspace defaults,
|
|
578
|
+
// silently violating the user's pinned preference. A caller-supplied
|
|
579
|
+
// `forceOverrideProfile` replaces that lookup and additionally floats the
|
|
580
|
+
// profile above the call-site layers (see the option's doc). Resolve the
|
|
581
|
+
// effective context budget here as well because wakes bypass the normal
|
|
582
|
+
// user-turn path that computes it for tool-result truncation. Read before
|
|
583
|
+
// `setProcessing(true)` so a thrown DB/config read can't strand the
|
|
584
|
+
// processing flag.
|
|
585
|
+
const forceOverrideProfile = opts.forceOverrideProfile !== undefined;
|
|
586
|
+
const overrideProfile =
|
|
587
|
+
opts.forceOverrideProfile ??
|
|
588
|
+
getConversationOverrideProfile(conversationId);
|
|
589
|
+
const callSite = opts.callSite ?? "mainAgent";
|
|
590
|
+
const config = getConfig();
|
|
591
|
+
const effectiveContextWindow = resolveEffectiveContextWindow({
|
|
592
|
+
llm: config.llm,
|
|
593
|
+
callSite,
|
|
594
|
+
overrideProfile,
|
|
595
|
+
forceOverrideProfile,
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
// Apply the caller's persona override for the duration of the run. The
|
|
599
|
+
// wake's agent loop builds the system prompt through the conversation's
|
|
600
|
+
// resolveSystemPrompt callback, which reads this field; cleared (below,
|
|
601
|
+
// before drainQueue) so a queued user turn never builds its prompt under
|
|
602
|
+
// the wake's override. Assigned only AFTER the profile/config reads above
|
|
603
|
+
// — those can throw, and they run before the try/finally that clears the
|
|
604
|
+
// override, so an earlier assignment would strand the override on the
|
|
605
|
+
// cached Conversation and corrupt every later prompt build on it.
|
|
606
|
+
if (opts.personaOverride) {
|
|
607
|
+
conversation.wakePersonaOverride = opts.personaOverride;
|
|
608
|
+
}
|
|
609
|
+
const clearWakePersonaOverride = (): void => {
|
|
610
|
+
if (opts.personaOverride) {
|
|
611
|
+
conversation.wakePersonaOverride = undefined;
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
// Mark processing for the duration of the wake — including the pre-run
|
|
616
|
+
// compaction gate below, whose summary LLM call must not race a user
|
|
617
|
+
// send into a concurrent agent loop on the same conversation. A user
|
|
618
|
+
// message arriving while the flag is set is queued by `enqueueMessage()`
|
|
619
|
+
// and drained after the wake's tail is pushed + persisted. This happens
|
|
620
|
+
// before applying a wake-scoped tool allowlist so a concurrent user turn
|
|
621
|
+
// cannot start under the wake's restricted tool set.
|
|
622
|
+
conversation.setProcessing(true);
|
|
623
|
+
|
|
624
|
+
// ── Pre-run auto-compaction gate ──────────────────────────────────
|
|
625
|
+
// The wake invokes `conversation.agentLoop.run()` with the loop's
|
|
626
|
+
// in-loop budget gate disabled (see `resolveContextWindow` below), so
|
|
627
|
+
// the orchestrator's turn-start compaction never fires for wakes.
|
|
628
|
+
// Mirror it here: run the conversation's auto-threshold compaction
|
|
629
|
+
// before snapshotting the baseline — a successful compaction replaces
|
|
630
|
+
// `conversation.messages`, so it must precede the snapshot. Callers
|
|
631
|
+
// like fork-based memory retrospectives suppress this gate: the fork
|
|
632
|
+
// is throwaway and a summarization LLM call on it is wasted spend.
|
|
633
|
+
// Failure is non-fatal — the wake proceeds on the uncompacted history
|
|
634
|
+
// exactly as it would have before the gate existed. The gate's window
|
|
635
|
+
// sizing is threaded from the wake's own call-site resolution above —
|
|
636
|
+
// without it, `maybeCompact` sizes the threshold against `mainAgent`,
|
|
637
|
+
// which can pass un-compacted a wake whose call site resolves a smaller
|
|
638
|
+
// window (and then overflow at the provider).
|
|
639
|
+
if (!suppressAutoCompaction) {
|
|
640
|
+
try {
|
|
641
|
+
await conversation.maybeCompact({
|
|
642
|
+
callSite,
|
|
643
|
+
overrideProfile,
|
|
644
|
+
forceOverrideProfile,
|
|
645
|
+
});
|
|
646
|
+
} catch (err) {
|
|
647
|
+
log.warn(
|
|
648
|
+
{ conversationId, source, err },
|
|
649
|
+
"agent-wake: pre-run auto-compaction failed; continuing with the uncompacted history",
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
489
654
|
const baseline = conversation.getMessages();
|
|
490
655
|
// Snapshot the baseline length BEFORE the run starts. Incremental
|
|
491
656
|
// persistence pushes onto `conversation.messages` mid-run, which grows the
|
|
@@ -564,6 +729,14 @@ export async function wakeAgentForOpportunity(
|
|
|
564
729
|
// so the latest-row lookup in `setAgentLoopExitReasonOnLatestLog`
|
|
565
730
|
// can see the freshly-persisted final usage row.
|
|
566
731
|
let pendingExitReason: string | null = null;
|
|
732
|
+
// Set when the provider rejects a call as context-too-large while
|
|
733
|
+
// auto-compaction is suppressed. The loop has no recovery ladder to
|
|
734
|
+
// drive (overflow recovery is disabled for wakes), so it swallows the
|
|
735
|
+
// rejection into a graceful no-output stop — which would read as a
|
|
736
|
+
// *successful* silent no-op to callers like the memory-retrospective
|
|
737
|
+
// job. Capture the signal here so the wake can fail deterministically
|
|
738
|
+
// instead (`reason: "context_overflow"`).
|
|
739
|
+
let suppressedContextOverflow = false;
|
|
567
740
|
const persistLog = (record: PendingLog): void => {
|
|
568
741
|
try {
|
|
569
742
|
recordRequestLog(
|
|
@@ -572,7 +745,7 @@ export async function wakeAgentForOpportunity(
|
|
|
572
745
|
JSON.stringify(record.rawResponse),
|
|
573
746
|
undefined,
|
|
574
747
|
record.provider,
|
|
575
|
-
|
|
748
|
+
callSite,
|
|
576
749
|
);
|
|
577
750
|
} catch (err) {
|
|
578
751
|
log.warn(
|
|
@@ -658,6 +831,19 @@ export async function wakeAgentForOpportunity(
|
|
|
658
831
|
persistExitReason(event.reason);
|
|
659
832
|
}
|
|
660
833
|
}
|
|
834
|
+
// Detect an over-window rejection on a compaction-suppressed wake.
|
|
835
|
+
// `provider_error` fires at the provider-call site; `error` fires from
|
|
836
|
+
// the loop's generic catch — check both so a rewrapping retry layer
|
|
837
|
+
// can't hide the signal. The heuristic check also catches adapter
|
|
838
|
+
// paths (e.g. managed-proxy rewrappers) that surface the overflow as
|
|
839
|
+
// an untyped error the typed `instanceof` check would miss.
|
|
840
|
+
if (
|
|
841
|
+
suppressAutoCompaction &&
|
|
842
|
+
(event.type === "provider_error" || event.type === "error") &&
|
|
843
|
+
looksLikeContextOverflowError(event.error)
|
|
844
|
+
) {
|
|
845
|
+
suppressedContextOverflow = true;
|
|
846
|
+
}
|
|
661
847
|
if (mode === "buffering") {
|
|
662
848
|
buffered.push(event);
|
|
663
849
|
return;
|
|
@@ -758,23 +944,6 @@ export async function wakeAgentForOpportunity(
|
|
|
758
944
|
persistedTailIndex += newMessages.length;
|
|
759
945
|
};
|
|
760
946
|
|
|
761
|
-
// Honor the conversation's pinned inference-profile override (if any).
|
|
762
|
-
// Without this, scheduled-task wakes and other opportunity wakes bypass
|
|
763
|
-
// `runAgentLoopImpl` entirely and execute under workspace defaults,
|
|
764
|
-
// silently violating the user's pinned preference. Resolve the effective
|
|
765
|
-
// context budget here as well because wakes bypass the normal user-turn
|
|
766
|
-
// path that computes it for tool-result truncation. Read before
|
|
767
|
-
// `setProcessing(true)` so a thrown DB/config read can't strand the
|
|
768
|
-
// processing flag.
|
|
769
|
-
const overrideProfile = getConversationOverrideProfile(conversationId);
|
|
770
|
-
const callSite = opts.callSite ?? "mainAgent";
|
|
771
|
-
const config = getConfig();
|
|
772
|
-
const effectiveContextWindow = resolveEffectiveContextWindow({
|
|
773
|
-
llm: config.llm,
|
|
774
|
-
callSite,
|
|
775
|
-
overrideProfile,
|
|
776
|
-
});
|
|
777
|
-
|
|
778
947
|
let wakeToolScopeRestored = false;
|
|
779
948
|
let restoreWakeToolScope: (() => void) | null = null;
|
|
780
949
|
const restoreWakeAllowedTools = (): void => {
|
|
@@ -796,6 +965,8 @@ export async function wakeAgentForOpportunity(
|
|
|
796
965
|
restoreWakeToolScope = scopeWakeAllowedTools(
|
|
797
966
|
conversation,
|
|
798
967
|
new Set(opts.allowedTools),
|
|
968
|
+
opts.toolGateMode,
|
|
969
|
+
opts.toolContextPin,
|
|
799
970
|
);
|
|
800
971
|
return true;
|
|
801
972
|
} catch (err) {
|
|
@@ -807,14 +978,6 @@ export async function wakeAgentForOpportunity(
|
|
|
807
978
|
}
|
|
808
979
|
};
|
|
809
980
|
|
|
810
|
-
// Mark processing for the duration of the run so a concurrent user
|
|
811
|
-
// send is queued by `enqueueMessage()` rather than spawning a second
|
|
812
|
-
// concurrent agent loop on the same conversation (which would
|
|
813
|
-
// interleave writes to `conversation.messages`). This happens before
|
|
814
|
-
// applying a wake-scoped tool allowlist so a concurrent user turn cannot
|
|
815
|
-
// start under the wake's restricted tool set.
|
|
816
|
-
conversation.setProcessing(true);
|
|
817
|
-
|
|
818
981
|
// Fires after each tool-execution turn finalizes (assistant message
|
|
819
982
|
// + matching tool_result user message both in history). A single
|
|
820
983
|
// tool turn is unambiguous evidence of output — promote to live
|
|
@@ -834,7 +997,64 @@ export async function wakeAgentForOpportunity(
|
|
|
834
997
|
let toolUseNames: string[] = [];
|
|
835
998
|
let tailMessageCount = 0;
|
|
836
999
|
let drainedInTry = false;
|
|
1000
|
+
// Set when the wake fails with `reason: "context_overflow"`. The finally
|
|
1001
|
+
// block skips its generic outcome log for this path — the failure
|
|
1002
|
+
// already logged its own dedicated warn line.
|
|
1003
|
+
let failedContextOverflow = false;
|
|
1004
|
+
// Shared failure path for an over-window condition on a
|
|
1005
|
+
// compaction-suppressed wake (reached from the pre-flight estimate, from
|
|
1006
|
+
// the run's catch when the rejection escaped as a throw, or post-run when
|
|
1007
|
+
// the loop swallowed it into a graceful no-output stop and only the event
|
|
1008
|
+
// capture saw it). `extraLogFields` is spread into the warn line so each
|
|
1009
|
+
// site can attach its own context (err, token estimates).
|
|
1010
|
+
const failSuppressedContextOverflow = (
|
|
1011
|
+
logMessage: string,
|
|
1012
|
+
extraLogFields: Record<string, unknown> = {},
|
|
1013
|
+
): WakeResult => {
|
|
1014
|
+
failedContextOverflow = true;
|
|
1015
|
+
log.warn({ conversationId, source, ...extraLogFields }, logMessage);
|
|
1016
|
+
return {
|
|
1017
|
+
invoked: false,
|
|
1018
|
+
producedToolCalls: false,
|
|
1019
|
+
reason: "context_overflow" as const,
|
|
1020
|
+
};
|
|
1021
|
+
};
|
|
837
1022
|
try {
|
|
1023
|
+
// ── Over-window policy under suppressed auto-compaction ─────────
|
|
1024
|
+
// The pre-run gate above is the wake's only compaction path (the
|
|
1025
|
+
// loop's in-loop budget gate stays disabled), so when the caller
|
|
1026
|
+
// suppressed it an over-window input has no recovery. Fail fast and
|
|
1027
|
+
// deterministically — before spending any LLM call — instead of
|
|
1028
|
+
// letting the provider reject the run into a silent no-op. Estimated
|
|
1029
|
+
// with the same estimator the auto-compaction pre-check uses; an
|
|
1030
|
+
// estimator failure proceeds fail-open (the reactive
|
|
1031
|
+
// `suppressedContextOverflow` capture below still maps a provider
|
|
1032
|
+
// rejection to the same failure).
|
|
1033
|
+
if (suppressAutoCompaction) {
|
|
1034
|
+
let estimatedInputTokens: number | null = null;
|
|
1035
|
+
try {
|
|
1036
|
+
estimatedInputTokens =
|
|
1037
|
+
conversation.contextWindowManager.estimateInputTokens(runInput);
|
|
1038
|
+
} catch (err) {
|
|
1039
|
+
log.warn(
|
|
1040
|
+
{ conversationId, source, err },
|
|
1041
|
+
"agent-wake: over-window pre-flight estimate failed; proceeding without it",
|
|
1042
|
+
);
|
|
1043
|
+
}
|
|
1044
|
+
if (
|
|
1045
|
+
estimatedInputTokens !== null &&
|
|
1046
|
+
estimatedInputTokens > effectiveContextWindow.maxInputTokens
|
|
1047
|
+
) {
|
|
1048
|
+
return failSuppressedContextOverflow(
|
|
1049
|
+
"agent-wake: input exceeds the effective context window and auto-compaction is suppressed; failing fast",
|
|
1050
|
+
{
|
|
1051
|
+
estimatedInputTokens,
|
|
1052
|
+
maxInputTokens: effectiveContextWindow.maxInputTokens,
|
|
1053
|
+
},
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
|
|
838
1058
|
if (!applyWakeAllowedTools()) {
|
|
839
1059
|
return {
|
|
840
1060
|
invoked: false,
|
|
@@ -859,16 +1079,33 @@ export async function wakeAgentForOpportunity(
|
|
|
859
1079
|
callSite,
|
|
860
1080
|
trust: wakeTrust,
|
|
861
1081
|
overrideProfile,
|
|
862
|
-
|
|
863
|
-
//
|
|
864
|
-
//
|
|
865
|
-
//
|
|
1082
|
+
forceOverrideProfile,
|
|
1083
|
+
// The wake's compaction lives in the pre-run gate above
|
|
1084
|
+
// (`conversation.maybeCompact()`), never in the loop: the in-loop
|
|
1085
|
+
// budget gate and overflow-recovery ladder stay disabled because
|
|
1086
|
+
// the wake's tail accounting holds external indexes into the
|
|
1087
|
+
// returned history (`baselineLength` + hint count), which an
|
|
1088
|
+
// in-loop compaction rebase would invalidate. `maxInputTokens` is
|
|
1089
|
+
// still supplied for tool-result truncation.
|
|
866
1090
|
resolveContextWindow: () => ({
|
|
867
1091
|
maxInputTokens: effectiveContextWindow.maxInputTokens,
|
|
868
1092
|
overflowRecovery: { enabled: false, safetyMarginRatio: 0 },
|
|
869
1093
|
}),
|
|
870
1094
|
}));
|
|
871
1095
|
} catch (err) {
|
|
1096
|
+
// An over-window throw on a compaction-suppressed wake is the
|
|
1097
|
+
// suppression contract's failure mode, not a generic loop error —
|
|
1098
|
+
// surface it as a deterministic failed result. The heuristic check
|
|
1099
|
+
// also catches rewrapped (untyped) provider overflow errors.
|
|
1100
|
+
if (
|
|
1101
|
+
suppressedContextOverflow ||
|
|
1102
|
+
(suppressAutoCompaction && looksLikeContextOverflowError(err))
|
|
1103
|
+
) {
|
|
1104
|
+
return failSuppressedContextOverflow(
|
|
1105
|
+
OVER_WINDOW_REJECTION_LOG_MESSAGE,
|
|
1106
|
+
{ err },
|
|
1107
|
+
);
|
|
1108
|
+
}
|
|
872
1109
|
// Capture the error for post-finally logging, then short-circuit
|
|
873
1110
|
// the rest of the try body — no tail to push/persist when the
|
|
874
1111
|
// run threw mid-flight. The outer finally still runs to release
|
|
@@ -877,6 +1114,15 @@ export async function wakeAgentForOpportunity(
|
|
|
877
1114
|
return { invoked: true, producedToolCalls: false };
|
|
878
1115
|
}
|
|
879
1116
|
|
|
1117
|
+
// The loop swallows provider rejections into a graceful no-output
|
|
1118
|
+
// stop, so an over-window rejection on a compaction-suppressed wake
|
|
1119
|
+
// surfaces only through the event stream (captured into
|
|
1120
|
+
// `suppressedContextOverflow` by `onEvent`). Map it to a deterministic
|
|
1121
|
+
// failure instead of the silent no-op it would otherwise read as.
|
|
1122
|
+
if (suppressedContextOverflow) {
|
|
1123
|
+
return failSuppressedContextOverflow(OVER_WINDOW_REJECTION_LOG_MESSAGE);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
880
1126
|
// Run completed cleanly. The canonical user-turn pattern
|
|
881
1127
|
// (conversation-agent-loop.ts:1860, 2106-2126) updates
|
|
882
1128
|
// `ctx.messages` first, then clears the flag via `ctx.setProcessing(false)`, then
|
|
@@ -925,6 +1171,7 @@ export async function wakeAgentForOpportunity(
|
|
|
925
1171
|
// processing to already be false). The finally block handles the
|
|
926
1172
|
// error/early-return paths where no tail was produced.
|
|
927
1173
|
restoreWakeAllowedTools();
|
|
1174
|
+
clearWakePersonaOverride();
|
|
928
1175
|
try {
|
|
929
1176
|
conversation.setProcessing(false);
|
|
930
1177
|
} catch (err) {
|
|
@@ -952,6 +1199,7 @@ export async function wakeAgentForOpportunity(
|
|
|
952
1199
|
// `drainedInTry` is still false.
|
|
953
1200
|
if (!drainedInTry) {
|
|
954
1201
|
restoreWakeAllowedTools();
|
|
1202
|
+
clearWakePersonaOverride();
|
|
955
1203
|
try {
|
|
956
1204
|
conversation.setProcessing(false);
|
|
957
1205
|
} catch (err) {
|
|
@@ -971,9 +1219,12 @@ export async function wakeAgentForOpportunity(
|
|
|
971
1219
|
}
|
|
972
1220
|
|
|
973
1221
|
const durationMs = nowFn() - startedAt;
|
|
974
|
-
const suppressAutoCompaction = opts.suppressAutoCompaction === true;
|
|
975
1222
|
const suppressWakeSurface = opts.suppressWakeSurface === true;
|
|
976
|
-
if (
|
|
1223
|
+
if (failedContextOverflow) {
|
|
1224
|
+
// Already logged its own dedicated warn line at the failure site;
|
|
1225
|
+
// a generic "silent no-op" line here would misclassify a failed
|
|
1226
|
+
// wake as a successful empty one.
|
|
1227
|
+
} else if (runError) {
|
|
977
1228
|
log.error(
|
|
978
1229
|
{
|
|
979
1230
|
conversationId,
|