@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
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
ACTIVITY_SKIP_SET,
|
|
27
27
|
injectActivityField,
|
|
28
28
|
} from "../tools/schema-transforms.js";
|
|
29
|
+
import { resolveSkillExecuteInput } from "../tools/skills/execute.js";
|
|
29
30
|
import { resolveToolInvocationAlias } from "../tools/tool-name-aliases.js";
|
|
30
31
|
import {
|
|
31
32
|
isDiskPressureCleanupToolName,
|
|
@@ -61,8 +62,16 @@ import {
|
|
|
61
62
|
buildSwitchInferenceProfileToolDef,
|
|
62
63
|
SWITCH_INFERENCE_PROFILE_TOOL_NAME,
|
|
63
64
|
} from "./switch-inference-profile-tool.js";
|
|
64
|
-
import type {
|
|
65
|
-
|
|
65
|
+
import type {
|
|
66
|
+
SubagentToolGateMode,
|
|
67
|
+
ToolSetupContext,
|
|
68
|
+
WakeToolContextPin,
|
|
69
|
+
} from "./tool-setup-types.js";
|
|
70
|
+
export type {
|
|
71
|
+
SubagentToolGateMode,
|
|
72
|
+
ToolSetupContext,
|
|
73
|
+
WakeToolContextPin,
|
|
74
|
+
} from "./tool-setup-types.js";
|
|
66
75
|
|
|
67
76
|
// ── resolveConversationAttribution ───────────────────────────────────
|
|
68
77
|
|
|
@@ -128,6 +137,23 @@ export function createToolExecutor(
|
|
|
128
137
|
ctx.sendToClient(msg),
|
|
129
138
|
);
|
|
130
139
|
|
|
140
|
+
// Execution-layer allowlist gate (`subagentToolGateMode === "execution"`,
|
|
141
|
+
// see {@link SubagentToolGateMode}): rejects non-allowlisted calls BEFORE
|
|
142
|
+
// any executor dispatch, so a non-allowlisted tool's executor never runs.
|
|
143
|
+
// The error tool_result lets the model continue or finish.
|
|
144
|
+
const rejectNonAllowlistedTool = (
|
|
145
|
+
toolName: string,
|
|
146
|
+
): ToolExecutionResult | null => {
|
|
147
|
+
if (ctx.subagentToolGateMode !== "execution") return null;
|
|
148
|
+
const allowlist = ctx.subagentAllowedTools;
|
|
149
|
+
if (!allowlist || allowlist.has(toolName)) return null;
|
|
150
|
+
const allowed = [...allowlist].sort().join(", ");
|
|
151
|
+
return {
|
|
152
|
+
content: `This background pass may only use: ${allowed}.`,
|
|
153
|
+
isError: true,
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
|
|
131
157
|
return async (
|
|
132
158
|
name: string,
|
|
133
159
|
input: Record<string, unknown>,
|
|
@@ -137,6 +163,17 @@ export function createToolExecutor(
|
|
|
137
163
|
const { name: executionName, input: executionInput } =
|
|
138
164
|
resolveToolInvocationAlias(name, input, ctx.allowedToolNames);
|
|
139
165
|
|
|
166
|
+
// The execution-layer gate must run FIRST — before any interception or
|
|
167
|
+
// pre-execution side effect (switch_inference_profile profile switching,
|
|
168
|
+
// DoorDash step marking) — so a non-allowlisted tool can neither run nor
|
|
169
|
+
// mutate conversation state. `skill_execute` is dispatch indirection: it
|
|
170
|
+
// is gated on its resolved inner tool name inside the interception below,
|
|
171
|
+
// mirroring how wire mode gates the underlying tool, not the wrapper.
|
|
172
|
+
if (executionName !== "skill_execute") {
|
|
173
|
+
const rejection = rejectNonAllowlistedTool(executionName);
|
|
174
|
+
if (rejection) return rejection;
|
|
175
|
+
}
|
|
176
|
+
|
|
140
177
|
if (isDoordashCommand(executionName, executionInput)) {
|
|
141
178
|
markDoordashStepInProgress(ctx, executionInput);
|
|
142
179
|
}
|
|
@@ -260,10 +297,7 @@ export function createToolExecutor(
|
|
|
260
297
|
if (executionName === "skill_execute") {
|
|
261
298
|
const rawToolName =
|
|
262
299
|
typeof executionInput.tool === "string" ? executionInput.tool : "";
|
|
263
|
-
const rawToolInput =
|
|
264
|
-
executionInput.input != null && typeof executionInput.input === "object"
|
|
265
|
-
? (executionInput.input as Record<string, unknown>)
|
|
266
|
-
: {};
|
|
300
|
+
const rawToolInput = resolveSkillExecuteInput(executionInput);
|
|
267
301
|
|
|
268
302
|
// Clone to avoid mutating shared input objects
|
|
269
303
|
const { name: toolName, input: toolInput } = resolveToolInvocationAlias(
|
|
@@ -280,6 +314,12 @@ export function createToolExecutor(
|
|
|
280
314
|
};
|
|
281
315
|
}
|
|
282
316
|
|
|
317
|
+
// Gate the resolved inner tool, not the skill_execute wrapper — the
|
|
318
|
+
// wrapper is dispatch indirection, mirroring how wire mode gates the
|
|
319
|
+
// underlying tool via the executor's allowedToolNames check.
|
|
320
|
+
const innerRejection = rejectNonAllowlistedTool(toolName);
|
|
321
|
+
if (innerRejection) return innerRejection;
|
|
322
|
+
|
|
283
323
|
const result = await executor.execute(toolName, toolInput, toolContext);
|
|
284
324
|
if (toolContext.approvedViaPrompt) {
|
|
285
325
|
ctx.approvedViaPromptThisTurn = true;
|
|
@@ -361,6 +401,18 @@ export interface SkillProjectionContext {
|
|
|
361
401
|
readonly hasNoClient?: boolean;
|
|
362
402
|
/** When set, only tools in this set are included in the resolved tool list (subagent delegation). */
|
|
363
403
|
subagentAllowedTools?: Set<string>;
|
|
404
|
+
/**
|
|
405
|
+
* How {@link subagentAllowedTools} is enforced — see
|
|
406
|
+
* {@link SubagentToolGateMode}. Absent means `"wire"`.
|
|
407
|
+
*/
|
|
408
|
+
subagentToolGateMode?: SubagentToolGateMode;
|
|
409
|
+
/**
|
|
410
|
+
* When set (execution-gate-mode wakes), tool-definition resolution reads
|
|
411
|
+
* `hasNoClient` / `transportInterface` / `channelCapabilities` exclusively
|
|
412
|
+
* from this pin instead of the live conversation — see
|
|
413
|
+
* {@link WakeToolContextPin}.
|
|
414
|
+
*/
|
|
415
|
+
readonly toolContextPin?: WakeToolContextPin;
|
|
364
416
|
/** True when the current turn is restricted to disk-pressure cleanup-safe tools. */
|
|
365
417
|
diskPressureCleanupModeActive?: boolean;
|
|
366
418
|
/** True when this conversation belongs to a subagent spawned by SubagentManager. */
|
|
@@ -479,10 +531,29 @@ export function isToolActiveForContext(
|
|
|
479
531
|
name: string,
|
|
480
532
|
ctx: SkillProjectionContext,
|
|
481
533
|
): boolean {
|
|
534
|
+
// Execution-gate-mode wakes pin the client-context inputs so the wire tool
|
|
535
|
+
// surface matches the SOURCE conversation's live turns rather than the
|
|
536
|
+
// fork's clientless hydration (see {@link WakeToolContextPin}). When the
|
|
537
|
+
// pin is present it replaces all three values — channel capabilities pin
|
|
538
|
+
// to `undefined` (see the pin's doc for why unset IS parity), never
|
|
539
|
+
// falling through to live state.
|
|
540
|
+
const pin = ctx.toolContextPin;
|
|
541
|
+
const hasNoClient = pin ? pin.hasNoClient : ctx.hasNoClient;
|
|
542
|
+
const channelCapabilities = pin ? undefined : ctx.channelCapabilities;
|
|
543
|
+
const transportInterface = pin
|
|
544
|
+
? pin.transportInterface
|
|
545
|
+
: ctx.transportInterface;
|
|
546
|
+
|
|
482
547
|
// When the conversation is acting as a subagent, the parent orchestrator
|
|
483
548
|
// restricts the tool list. A tool that isn't on the allowlist is not
|
|
484
549
|
// available for this turn, so short-circuit before any capability checks.
|
|
485
|
-
|
|
550
|
+
// In execution gate mode the allowlist is enforced at execution time
|
|
551
|
+
// instead — the full tool surface stays visible on the wire.
|
|
552
|
+
if (
|
|
553
|
+
ctx.subagentAllowedTools &&
|
|
554
|
+
ctx.subagentToolGateMode !== "execution" &&
|
|
555
|
+
!ctx.subagentAllowedTools.has(name)
|
|
556
|
+
) {
|
|
486
557
|
return false;
|
|
487
558
|
}
|
|
488
559
|
// `createResolveToolsCallback` returns an empty tool list when tools are
|
|
@@ -507,16 +578,16 @@ export function isToolActiveForContext(
|
|
|
507
578
|
}
|
|
508
579
|
if (UI_SURFACE_TOOL_NAMES.has(name)) {
|
|
509
580
|
if (
|
|
510
|
-
|
|
581
|
+
channelCapabilities?.channel === "slack" &&
|
|
511
582
|
SLACK_TASK_PROGRESS_UI_TOOL_NAMES.has(name)
|
|
512
583
|
) {
|
|
513
|
-
return !
|
|
584
|
+
return !hasNoClient;
|
|
514
585
|
}
|
|
515
|
-
return
|
|
586
|
+
return channelCapabilities?.supportsDynamicUi ?? !hasNoClient;
|
|
516
587
|
}
|
|
517
588
|
if (HOST_TOOL_NAMES.has(name)) {
|
|
518
589
|
const capability = HOST_TOOL_TO_CAPABILITY.get(name);
|
|
519
|
-
const transport =
|
|
590
|
+
const transport = transportInterface;
|
|
520
591
|
|
|
521
592
|
// Per-capability check is authoritative for structural support: if the
|
|
522
593
|
// transport cannot service this capability, the tool is filtered out.
|
|
@@ -535,7 +606,7 @@ export function isToolActiveForContext(
|
|
|
535
606
|
capability &&
|
|
536
607
|
CROSS_CLIENT_EXPOSED_CAPABILITIES.has(capability) &&
|
|
537
608
|
transport !== "chrome-extension" &&
|
|
538
|
-
!
|
|
609
|
+
!hasNoClient &&
|
|
539
610
|
assistantEventHub.listClientsByCapability(capability).length > 0
|
|
540
611
|
) {
|
|
541
612
|
return true;
|
|
@@ -555,23 +626,20 @@ export function isToolActiveForContext(
|
|
|
555
626
|
// For transports that surface approvals over SSE (macos, backwards-compat
|
|
556
627
|
// fallback), deny when no client is present so the guardian auto-approve
|
|
557
628
|
// path cannot execute host commands unattended.
|
|
558
|
-
return !
|
|
629
|
+
return !hasNoClient;
|
|
559
630
|
}
|
|
560
631
|
if (CLIENT_CAPABILITY_TOOL_NAMES.has(name)) {
|
|
561
|
-
if (
|
|
562
|
-
name === "ask_question" &&
|
|
563
|
-
ctx.channelCapabilities?.clientOS === "macos"
|
|
564
|
-
) {
|
|
632
|
+
if (name === "ask_question" && channelCapabilities?.clientOS === "macos") {
|
|
565
633
|
// macOS has no UI handler for question_request yet; hiding the tool
|
|
566
634
|
// avoids a 5-minute prompter timeout when the LLM would otherwise call it.
|
|
567
635
|
return false;
|
|
568
636
|
}
|
|
569
|
-
return !
|
|
637
|
+
return !hasNoClient;
|
|
570
638
|
}
|
|
571
639
|
if (PLATFORM_TOOL_NAMES.has(name)) {
|
|
572
640
|
// Check the *client's* platform, not the daemon's process.platform.
|
|
573
641
|
// In Docker the daemon runs on Linux but the connected client may be macOS.
|
|
574
|
-
return
|
|
642
|
+
return channelCapabilities?.clientOS === "macos" && !hasNoClient;
|
|
575
643
|
}
|
|
576
644
|
if (SUBAGENT_ONLY_TOOL_NAMES.has(name)) {
|
|
577
645
|
return ctx.isSubagent === true;
|
|
@@ -628,9 +696,16 @@ export function createResolveToolsCallback(
|
|
|
628
696
|
);
|
|
629
697
|
|
|
630
698
|
// When the conversation is acting as a subagent, restrict core tools to
|
|
631
|
-
// only those explicitly allowed by the parent orchestrator.
|
|
632
|
-
|
|
633
|
-
|
|
699
|
+
// only those explicitly allowed by the parent orchestrator. In
|
|
700
|
+
// `"execution"` gate mode the allowlist is NOT applied to the wire
|
|
701
|
+
// definitions (see {@link SubagentToolGateMode}) — the executor callback
|
|
702
|
+
// rejects non-allowlisted calls at execution time instead.
|
|
703
|
+
const wireAllowlist =
|
|
704
|
+
ctx.subagentToolGateMode === "execution"
|
|
705
|
+
? undefined
|
|
706
|
+
: ctx.subagentAllowedTools;
|
|
707
|
+
const scopedCoreDefs = wireAllowlist
|
|
708
|
+
? filteredCoreDefs.filter((d) => wireAllowlist.has(d.name))
|
|
634
709
|
: filteredCoreDefs;
|
|
635
710
|
|
|
636
711
|
// Re-read MCP tool definitions from the registry each turn so conversations
|
|
@@ -644,8 +719,8 @@ export function createResolveToolsCallback(
|
|
|
644
719
|
},
|
|
645
720
|
"MCP tools resolved for turn",
|
|
646
721
|
);
|
|
647
|
-
const scopedMcpDefs =
|
|
648
|
-
? currentMcpDefs.filter((d) =>
|
|
722
|
+
const scopedMcpDefs = wireAllowlist
|
|
723
|
+
? currentMcpDefs.filter((d) => wireAllowlist.has(d.name))
|
|
649
724
|
: currentMcpDefs;
|
|
650
725
|
const excluded = new Set(getConfig().tools.exclude);
|
|
651
726
|
const allBaseDefs = [...scopedCoreDefs, ...scopedMcpDefs].filter(
|
|
@@ -676,8 +751,10 @@ export function createResolveToolsCallback(
|
|
|
676
751
|
});
|
|
677
752
|
const turnAllowed = new Set(allBaseDefs.map((d) => d.name));
|
|
678
753
|
for (const name of projection.allowedToolNames) {
|
|
679
|
-
// When a subagent allowlist is active, exclude skill tools
|
|
680
|
-
|
|
754
|
+
// When a wire-gated subagent allowlist is active, exclude skill tools
|
|
755
|
+
// not on it. (Execution gate mode keeps them available here and
|
|
756
|
+
// rejects non-allowlisted calls in the executor callback instead.)
|
|
757
|
+
if (wireAllowlist && !wireAllowlist.has(name)) {
|
|
681
758
|
continue;
|
|
682
759
|
}
|
|
683
760
|
if (excluded.has(name)) continue;
|
|
@@ -214,6 +214,8 @@ export function recordUsage(
|
|
|
214
214
|
conversationId: ctx.conversationId,
|
|
215
215
|
inputTokens,
|
|
216
216
|
outputTokens,
|
|
217
|
+
cacheCreationInputTokens: normalizedCacheCreationInputTokens,
|
|
218
|
+
cacheReadInputTokens: normalizedCacheReadInputTokens,
|
|
217
219
|
totalInputTokens: ctx.usageStats.inputTokens,
|
|
218
220
|
totalOutputTokens: ctx.usageStats.outputTokens,
|
|
219
221
|
estimatedCost,
|
|
@@ -76,6 +76,7 @@ import { filterPrunedCardSections } from "../plugins/defaults/memory-v3-shadow/p
|
|
|
76
76
|
import {
|
|
77
77
|
applyBootstrapTemplate,
|
|
78
78
|
buildSystemPrompt,
|
|
79
|
+
type SystemPromptPersonaOverride,
|
|
79
80
|
} from "../prompts/system-prompt.js";
|
|
80
81
|
import type { ContentBlock, Message } from "../providers/types.js";
|
|
81
82
|
import type { Provider } from "../providers/types.js";
|
|
@@ -146,7 +147,11 @@ import {
|
|
|
146
147
|
handleSurfaceUndo as handleSurfaceUndoImpl,
|
|
147
148
|
type SurfaceActionResult,
|
|
148
149
|
} from "./conversation-surfaces.js";
|
|
149
|
-
import type {
|
|
150
|
+
import type {
|
|
151
|
+
SubagentToolGateMode,
|
|
152
|
+
ToolSetupContext,
|
|
153
|
+
WakeToolContextPin,
|
|
154
|
+
} from "./conversation-tool-setup.js";
|
|
150
155
|
import {
|
|
151
156
|
createResolveToolsCallback,
|
|
152
157
|
createToolExecutor,
|
|
@@ -177,6 +182,26 @@ export interface CleanResult {
|
|
|
177
182
|
preservedMessages: number;
|
|
178
183
|
}
|
|
179
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Optional context-window sizing inputs for {@link Conversation.maybeCompact}.
|
|
187
|
+
*
|
|
188
|
+
* The auto-threshold gate sizes its window against `mainAgent` by default,
|
|
189
|
+
* but an agent wake can run under a different call site (and a forced
|
|
190
|
+
* override profile) that resolves a SMALLER effective window — sized against
|
|
191
|
+
* `mainAgent`, such a wake passes the gate un-compacted and then overflows at
|
|
192
|
+
* the provider. Wakes thread their already-resolved inputs here so the gate's
|
|
193
|
+
* threshold matches the window the wake's calls actually get. Sizing only:
|
|
194
|
+
* the compaction execution (summary call profile) is unchanged.
|
|
195
|
+
*/
|
|
196
|
+
export interface CompactionSizing {
|
|
197
|
+
/** Call site the upcoming run resolves its context window against. */
|
|
198
|
+
callSite: LLMCallSite;
|
|
199
|
+
/** Inference profile the run resolves under, if any. */
|
|
200
|
+
overrideProfile?: string;
|
|
201
|
+
/** Float `overrideProfile` above the call-site layers (resolver escape hatch). */
|
|
202
|
+
forceOverrideProfile?: boolean;
|
|
203
|
+
}
|
|
204
|
+
|
|
180
205
|
export { findLastUndoableUserMessageIndex } from "./conversation-history.js";
|
|
181
206
|
export type {
|
|
182
207
|
QueueDrainReason,
|
|
@@ -220,6 +245,21 @@ export class Conversation {
|
|
|
220
245
|
/** @internal */ toolsDisabledDepth = 0;
|
|
221
246
|
/** @internal */ preactivatedSkillIds?: string[];
|
|
222
247
|
/** @internal */ subagentAllowedTools?: Set<string>;
|
|
248
|
+
/**
|
|
249
|
+
* How {@link subagentAllowedTools} is enforced — see
|
|
250
|
+
* {@link SubagentToolGateMode}. Set and restored alongside the allowlist
|
|
251
|
+
* by `scopeWakeAllowedTools`.
|
|
252
|
+
* @internal
|
|
253
|
+
*/
|
|
254
|
+
subagentToolGateMode?: SubagentToolGateMode;
|
|
255
|
+
/**
|
|
256
|
+
* Client-context pin for execution-gate-mode wakes — see
|
|
257
|
+
* {@link WakeToolContextPin}. Set and restored alongside the allowlist by
|
|
258
|
+
* `scopeWakeAllowedTools`; read only by tool-DEFINITION resolution
|
|
259
|
+
* (`isToolActiveForContext`), never by executor or host-proxy paths.
|
|
260
|
+
* @internal
|
|
261
|
+
*/
|
|
262
|
+
toolContextPin?: WakeToolContextPin;
|
|
223
263
|
/** @internal */ coreToolNames: Set<string>;
|
|
224
264
|
/** @internal */ readonly skillProjectionState = new Map<string, string>();
|
|
225
265
|
/** @internal */ readonly skillProjectionCache: SkillProjectionCache = {};
|
|
@@ -295,6 +335,18 @@ export class Conversation {
|
|
|
295
335
|
*/
|
|
296
336
|
currentTurnInboundActorContext?: InboundActorContext | null;
|
|
297
337
|
/** @internal */ currentTurnChannelCapabilities?: ChannelCapabilities;
|
|
338
|
+
/**
|
|
339
|
+
* Explicit persona/channel slugs for the system-prompt build, set (and
|
|
340
|
+
* cleared) by `wakeAgentForOpportunity` around a wake's agent-loop run.
|
|
341
|
+
* Wakes bypass the orchestrator's turn-start snapshots above, so without
|
|
342
|
+
* this their prompt is built from whatever snapshot the conversation
|
|
343
|
+
* already holds (for a freshly hydrated conversation: the no-trust-context
|
|
344
|
+
* persona derivation) regardless of which actor/channel the conversation
|
|
345
|
+
* belongs to. Takes precedence over the trust-context derivation when set.
|
|
346
|
+
* Persona selection only — never read for trust/approval decisions.
|
|
347
|
+
* @internal
|
|
348
|
+
*/
|
|
349
|
+
wakePersonaOverride?: SystemPromptPersonaOverride;
|
|
298
350
|
/** @internal */ currentTurnOverrideProfile?: string;
|
|
299
351
|
/** @internal */ toolRoutedProfile?: string;
|
|
300
352
|
/** @internal */ authContext?: AuthContext;
|
|
@@ -594,6 +646,7 @@ export class Conversation {
|
|
|
594
646
|
hasNoClient: this.hasNoClient,
|
|
595
647
|
trustContext: this.currentTurnTrustContext,
|
|
596
648
|
channelCapabilities: this.currentTurnChannelCapabilities,
|
|
649
|
+
personaOverride: this.wakePersonaOverride,
|
|
597
650
|
onboardingContext: this.getOnboardingContext(),
|
|
598
651
|
conversationId: this.conversationId,
|
|
599
652
|
}),
|
|
@@ -729,6 +782,7 @@ export class Conversation {
|
|
|
729
782
|
hasNoClient: this.hasNoClient,
|
|
730
783
|
trustContext: this.currentTurnTrustContext,
|
|
731
784
|
channelCapabilities: this.currentTurnChannelCapabilities,
|
|
785
|
+
personaOverride: this.wakePersonaOverride,
|
|
732
786
|
onboardingContext: this.getOnboardingContext(),
|
|
733
787
|
conversationId: this.conversationId,
|
|
734
788
|
});
|
|
@@ -1503,17 +1557,65 @@ export class Conversation {
|
|
|
1503
1557
|
}
|
|
1504
1558
|
|
|
1505
1559
|
async forceCompact(): Promise<ContextWindowResult> {
|
|
1560
|
+
return this.runCompaction(true);
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
/**
|
|
1564
|
+
* Auto-threshold compaction gate. Runs the same durable compaction
|
|
1565
|
+
* pipeline as {@link forceCompact} (summary call, circuit-breaker
|
|
1566
|
+
* accounting, Slack provenance, in-memory + DB commit) but honors the
|
|
1567
|
+
* `compaction.autoThreshold` check — an under-threshold history is a
|
|
1568
|
+
* cheap no-op — and the compaction circuit breaker, returning `null`
|
|
1569
|
+
* without estimating anything while the breaker is open. Used by the
|
|
1570
|
+
* agent-wake path (`runtime/agent-wake.ts`), which bypasses the daemon
|
|
1571
|
+
* orchestrator's in-loop budget gate and needs an equivalent turn-start
|
|
1572
|
+
* compaction before snapshotting its run input.
|
|
1573
|
+
*
|
|
1574
|
+
* `sizing` lets a wake thread its own call-site/profile resolution into
|
|
1575
|
+
* the gate's context-window sizing — see {@link CompactionSizing}. Absent,
|
|
1576
|
+
* the gate sizes against `mainAgent` (the live-turn behavior).
|
|
1577
|
+
*/
|
|
1578
|
+
async maybeCompact(
|
|
1579
|
+
sizing?: CompactionSizing,
|
|
1580
|
+
): Promise<ContextWindowResult | null> {
|
|
1581
|
+
if (await this.agentLoop.compactionCircuit.isOpen()) {
|
|
1582
|
+
return null;
|
|
1583
|
+
}
|
|
1584
|
+
return this.runCompaction(false, sizing);
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
/**
|
|
1588
|
+
* Shared compaction pipeline behind {@link forceCompact} and
|
|
1589
|
+
* {@link maybeCompact}. `force` skips the auto-threshold check inside the
|
|
1590
|
+
* context-window manager (user-initiated `/compact`); without it the
|
|
1591
|
+
* manager no-ops below the threshold.
|
|
1592
|
+
*/
|
|
1593
|
+
private async runCompaction(
|
|
1594
|
+
force: boolean,
|
|
1595
|
+
sizing?: CompactionSizing,
|
|
1596
|
+
): Promise<ContextWindowResult> {
|
|
1506
1597
|
const overrideProfile = resolveOverrideProfile(this) ?? null;
|
|
1507
1598
|
const config = getConfig();
|
|
1599
|
+
// Threshold/window sizing. The default (`mainAgent` + the conversation's
|
|
1600
|
+
// own pinned profile) matches live turns; caller-supplied `sizing` makes
|
|
1601
|
+
// the gate's threshold reflect the window the caller's run will actually
|
|
1602
|
+
// resolve. Sizing only — the summary call below still runs under the
|
|
1603
|
+
// conversation's own profile.
|
|
1604
|
+
const sizingCallSite = sizing?.callSite ?? "mainAgent";
|
|
1605
|
+
const sizingOverrideProfile = sizing
|
|
1606
|
+
? sizing.overrideProfile
|
|
1607
|
+
: (overrideProfile ?? undefined);
|
|
1508
1608
|
const effectiveContextWindow = resolveEffectiveContextWindow({
|
|
1509
1609
|
llm: config.llm,
|
|
1510
|
-
callSite:
|
|
1511
|
-
overrideProfile:
|
|
1610
|
+
callSite: sizingCallSite,
|
|
1611
|
+
overrideProfile: sizingOverrideProfile,
|
|
1612
|
+
forceOverrideProfile: sizing?.forceOverrideProfile,
|
|
1512
1613
|
});
|
|
1513
1614
|
this.contextWindowManager.updateConfig(
|
|
1514
1615
|
contextWindowConfigFromEffective(
|
|
1515
|
-
resolveCallSiteConfig(
|
|
1516
|
-
overrideProfile:
|
|
1616
|
+
resolveCallSiteConfig(sizingCallSite, config.llm, {
|
|
1617
|
+
overrideProfile: sizingOverrideProfile,
|
|
1618
|
+
forceOverrideProfile: sizing?.forceOverrideProfile,
|
|
1517
1619
|
}).contextWindow,
|
|
1518
1620
|
effectiveContextWindow,
|
|
1519
1621
|
),
|
|
@@ -1538,15 +1640,17 @@ export class Conversation {
|
|
|
1538
1640
|
conversationId: this.conversationId,
|
|
1539
1641
|
messages: messagesToCompact,
|
|
1540
1642
|
signal: this.abortController?.signal ?? undefined,
|
|
1541
|
-
force
|
|
1643
|
+
force,
|
|
1542
1644
|
overrideProfile,
|
|
1543
1645
|
actorTrustClass: this.trustContext?.trustClass,
|
|
1544
1646
|
});
|
|
1545
|
-
// Track circuit-breaker state for
|
|
1546
|
-
//
|
|
1547
|
-
//
|
|
1548
|
-
// is `undefined` on
|
|
1549
|
-
//
|
|
1647
|
+
// Track circuit-breaker state for every compaction that ran a summary
|
|
1648
|
+
// call — user-initiated `/compact`, other forced paths, and the wake's
|
|
1649
|
+
// auto gate — so a success clears a stuck counter and a run of failures
|
|
1650
|
+
// still trips the breaker. `summaryFailed` is `undefined` on
|
|
1651
|
+
// early-return paths (no eligible messages, disabled, below the auto
|
|
1652
|
+
// threshold, etc.) — skip those so they don't silently reset the
|
|
1653
|
+
// counter.
|
|
1550
1654
|
if (result.summaryFailed !== undefined) {
|
|
1551
1655
|
await this.agentLoop.compactionCircuit.recordOutcome(
|
|
1552
1656
|
result.summaryFailed,
|
|
@@ -13,6 +13,7 @@ import type { SecretPromptResult } from "../../permissions/secret-prompter.js";
|
|
|
13
13
|
import { isPlaceholderSentinelText } from "../../providers/placeholder-sentinels.js";
|
|
14
14
|
import { broadcastMessage } from "../../runtime/assistant-event-hub.js";
|
|
15
15
|
import type { AuthContext } from "../../runtime/auth/types.js";
|
|
16
|
+
import * as pendingInteractions from "../../runtime/pending-interactions.js";
|
|
16
17
|
import { unwrapExternalContentForDisplay } from "../../security/untrusted-content.js";
|
|
17
18
|
import { getLogger } from "../../util/logger.js";
|
|
18
19
|
import { estimateBase64Bytes } from "../assistant-attachments.js";
|
|
@@ -28,15 +29,6 @@ export const CONFIG_RELOAD_DEBOUNCE_MS = 300;
|
|
|
28
29
|
|
|
29
30
|
const HISTORY_ATTACHMENT_TEXT_LIMIT = 500;
|
|
30
31
|
|
|
31
|
-
// Module-level map for non-conversation secret prompts (e.g. publish_page)
|
|
32
|
-
const pendingStandaloneSecrets = new Map<
|
|
33
|
-
string,
|
|
34
|
-
{
|
|
35
|
-
resolve: (result: SecretPromptResult) => void;
|
|
36
|
-
timer: ReturnType<typeof setTimeout>;
|
|
37
|
-
}
|
|
38
|
-
>();
|
|
39
|
-
|
|
40
32
|
/**
|
|
41
33
|
* A single tool call rendered into a history row. Alias of the canonical
|
|
42
34
|
* wire-contract type so `renderHistoryContent` (the producer) cannot drift
|
|
@@ -166,6 +158,13 @@ export interface ConversationCreateOptions {
|
|
|
166
158
|
* `resolveCallSiteConfig` instead of the global default.
|
|
167
159
|
*/
|
|
168
160
|
callSite?: LLMCallSite;
|
|
161
|
+
/**
|
|
162
|
+
* Optional ad-hoc inference-profile override (`llm.profiles` key) applied
|
|
163
|
+
* to every LLM call the turn issues. Background callers with a pinned
|
|
164
|
+
* profile (e.g. schedules) pass it here so the agent loop layers the
|
|
165
|
+
* profile via `SendMessageOptions.config.overrideProfile`.
|
|
166
|
+
*/
|
|
167
|
+
overrideProfile?: string;
|
|
169
168
|
/**
|
|
170
169
|
* Slack inbound metadata captured at the channel ingress boundary. When
|
|
171
170
|
* present (and the turn channel resolves to Slack), persistence writes a
|
|
@@ -697,9 +696,15 @@ export function renderHistoryContent(
|
|
|
697
696
|
}
|
|
698
697
|
|
|
699
698
|
/**
|
|
700
|
-
* Send a `secret_request` to the client and wait for the response,
|
|
701
|
-
*
|
|
702
|
-
*
|
|
699
|
+
* Send a `secret_request` to the client and wait for the response, outside of a
|
|
700
|
+
* conversation context (e.g. from IPC routes like credentials/prompt).
|
|
701
|
+
*
|
|
702
|
+
* Lifecycle state (resolver, timer) is registered in pendingInteractions — the
|
|
703
|
+
* same tracker the in-conversation SecretPrompter uses — so `POST /v1/secret`
|
|
704
|
+
* resolves the prompt generically. When a `conversationId` is supplied (the CLI
|
|
705
|
+
* `credentials prompt` command forwards `__CONVERSATION_ID`), the broadcast is
|
|
706
|
+
* scoped to that conversation so clients deliver it; otherwise it is
|
|
707
|
+
* conversation-less.
|
|
703
708
|
*/
|
|
704
709
|
export function requestSecretStandalone(params: {
|
|
705
710
|
service: string;
|
|
@@ -710,15 +715,21 @@ export function requestSecretStandalone(params: {
|
|
|
710
715
|
purpose?: string;
|
|
711
716
|
allowedTools?: string[];
|
|
712
717
|
allowedDomains?: string[];
|
|
718
|
+
conversationId?: string;
|
|
713
719
|
}): Promise<SecretPromptResult> {
|
|
714
720
|
const requestId = uuid();
|
|
715
721
|
const config = getConfig();
|
|
716
722
|
return new Promise((resolve) => {
|
|
717
723
|
const timer = setTimeout(() => {
|
|
718
|
-
|
|
724
|
+
pendingInteractions.resolve(requestId, "cancelled");
|
|
719
725
|
resolve({ value: null, delivery: "store" });
|
|
720
726
|
}, config.timeouts.permissionTimeoutSec * 1000);
|
|
721
|
-
|
|
727
|
+
pendingInteractions.register(requestId, {
|
|
728
|
+
conversationId: params.conversationId,
|
|
729
|
+
kind: "secret",
|
|
730
|
+
rpcResolve: resolve as (value: unknown) => void,
|
|
731
|
+
timer,
|
|
732
|
+
});
|
|
722
733
|
broadcastMessage({
|
|
723
734
|
type: "secret_request",
|
|
724
735
|
requestId,
|
|
@@ -727,6 +738,7 @@ export function requestSecretStandalone(params: {
|
|
|
727
738
|
label: params.label,
|
|
728
739
|
description: params.description,
|
|
729
740
|
placeholder: params.placeholder,
|
|
741
|
+
conversationId: params.conversationId,
|
|
730
742
|
purpose: params.purpose,
|
|
731
743
|
allowedTools: params.allowedTools,
|
|
732
744
|
allowedDomains: params.allowedDomains,
|
|
@@ -473,19 +473,22 @@ export class HostCuProxy {
|
|
|
473
473
|
for (const requestId of this._ownedRequests) {
|
|
474
474
|
const entry = pendingInteractions.resolve(requestId, "cancelled");
|
|
475
475
|
if (!entry) continue;
|
|
476
|
+
const { conversationId } = entry;
|
|
476
477
|
try {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
478
|
+
if (conversationId !== undefined) {
|
|
479
|
+
broadcastMessage(
|
|
480
|
+
{
|
|
481
|
+
type: "host_cu_cancel",
|
|
482
|
+
requestId,
|
|
483
|
+
conversationId,
|
|
484
|
+
...(entry.targetClientId != null
|
|
485
|
+
? { targetClientId: entry.targetClientId }
|
|
486
|
+
: {}),
|
|
487
|
+
},
|
|
488
|
+
conversationId,
|
|
489
|
+
{ targetClientId: entry.targetClientId as string | undefined },
|
|
490
|
+
);
|
|
491
|
+
}
|
|
489
492
|
} catch {
|
|
490
493
|
// Best-effort cancel notification
|
|
491
494
|
}
|
|
@@ -277,19 +277,22 @@ export class HostFileProxy {
|
|
|
277
277
|
dispose(): void {
|
|
278
278
|
for (const entry of pendingInteractions.getByKind("host_file")) {
|
|
279
279
|
pendingInteractions.resolve(entry.requestId, "cancelled");
|
|
280
|
+
const { conversationId } = entry;
|
|
280
281
|
try {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
282
|
+
if (conversationId !== undefined) {
|
|
283
|
+
broadcastMessage(
|
|
284
|
+
{
|
|
285
|
+
type: "host_file_cancel",
|
|
286
|
+
requestId: entry.requestId,
|
|
287
|
+
conversationId,
|
|
288
|
+
...(entry.targetClientId != null
|
|
289
|
+
? { targetClientId: entry.targetClientId }
|
|
290
|
+
: {}),
|
|
291
|
+
},
|
|
292
|
+
conversationId,
|
|
293
|
+
{ targetClientId: entry.targetClientId as string | undefined },
|
|
294
|
+
);
|
|
295
|
+
}
|
|
293
296
|
} catch {
|
|
294
297
|
// Best-effort cancel notification
|
|
295
298
|
}
|