@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
package/src/agent/loop.ts
CHANGED
|
@@ -60,6 +60,28 @@ const MID_LOOP_YIELD_THRESHOLD_RATIO = 0.85;
|
|
|
60
60
|
const LONG_HISTORY_MESSAGE_THRESHOLD = 50;
|
|
61
61
|
const LONG_HISTORY_SAFETY_MARGIN_FLOOR = 0.15;
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Minimum token regrowth, measured from the post-compaction watermark, before
|
|
65
|
+
* the budget gate will compact again. A compaction pass that just ran already
|
|
66
|
+
* proved how far the history can shrink; if the estimate has not climbed at
|
|
67
|
+
* least this far past that watermark, another pass cannot free more than it
|
|
68
|
+
* already did and would only thrash (the production failure mode: each pass
|
|
69
|
+
* lands a hair under the trigger, one tick pushes it back over, repeat).
|
|
70
|
+
*
|
|
71
|
+
* Sized as `max(2048, 2% of maxInputTokens)` so it scales with the window but
|
|
72
|
+
* never collapses to a trivial value on small budgets. Overflow-driven
|
|
73
|
+
* compaction bypasses this guard entirely — a provider-confirmed overflow must
|
|
74
|
+
* always be allowed to compact.
|
|
75
|
+
*/
|
|
76
|
+
const MIN_REGROWTH_FLOOR_TOKENS = 2048;
|
|
77
|
+
const MIN_REGROWTH_WINDOW_RATIO = 0.02;
|
|
78
|
+
function minRegrowthTokens(maxInputTokens: number): number {
|
|
79
|
+
return Math.max(
|
|
80
|
+
MIN_REGROWTH_FLOOR_TOKENS,
|
|
81
|
+
Math.floor(maxInputTokens * MIN_REGROWTH_WINDOW_RATIO),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
63
85
|
export interface AgentLoopConfig {
|
|
64
86
|
maxTokens: number;
|
|
65
87
|
maxInputTokens?: number; // context window size for tool result truncation
|
|
@@ -493,6 +515,16 @@ export interface AgentLoopRunOptions {
|
|
|
493
515
|
* call-site named profile. Missing profile names silently fall through.
|
|
494
516
|
*/
|
|
495
517
|
overrideProfile?: string;
|
|
518
|
+
/**
|
|
519
|
+
* Float the override profile above the call-site layers (named site
|
|
520
|
+
* profile + call-site override) for non-main-agent call sites — the
|
|
521
|
+
* resolver's `forceOverrideProfile` escape hatch. Threaded onto each
|
|
522
|
+
* send's `SendMessageOptions.config` alongside `overrideProfile`. Used by
|
|
523
|
+
* wakes that must run a background call site under a specific
|
|
524
|
+
* conversation's inference profile (e.g. fork-based memory
|
|
525
|
+
* retrospectives).
|
|
526
|
+
*/
|
|
527
|
+
forceOverrideProfile?: boolean;
|
|
496
528
|
resolveOverrideProfile?: () => string | undefined;
|
|
497
529
|
/**
|
|
498
530
|
* Resolves the orchestrator's effective context window for this turn: the
|
|
@@ -856,6 +888,7 @@ export class AgentLoop {
|
|
|
856
888
|
callSite,
|
|
857
889
|
trust,
|
|
858
890
|
overrideProfile,
|
|
891
|
+
forceOverrideProfile = false,
|
|
859
892
|
resolveOverrideProfile,
|
|
860
893
|
resolveContextWindow,
|
|
861
894
|
compactInPlace = false,
|
|
@@ -899,6 +932,28 @@ export class AgentLoop {
|
|
|
899
932
|
// `context_too_large`) instead of looping.
|
|
900
933
|
let overflowLadderExhausted = false;
|
|
901
934
|
let overflowAutoCompressApplied = false;
|
|
935
|
+
// Per-turn suppression for floor-dominated proactive-compaction thrash.
|
|
936
|
+
// Set when a proactive (non-overflow) pass completes WITHOUT clearing the
|
|
937
|
+
// mid-loop gate (the manager returned `exhausted` — it could not get below
|
|
938
|
+
// its success threshold). During a tool-heavy turn each tool round grows the
|
|
939
|
+
// PROTECTED in-flight region past the regrowth guard's re-arm delta, but
|
|
940
|
+
// that region is exactly what compaction cannot touch, so every subsequent
|
|
941
|
+
// gate check would fire another futile full-context pass. Once set, the
|
|
942
|
+
// budget gate skips proactive compaction for the rest of THIS turn; it
|
|
943
|
+
// clears when a later proactive pass succeeds (non-exhausted). Overflow-
|
|
944
|
+
// driven compaction always bypasses it — a provider-confirmed overflow must
|
|
945
|
+
// always compact.
|
|
946
|
+
//
|
|
947
|
+
// Lifetime is exactly one turn: this is a `run()`-local (like
|
|
948
|
+
// `budgetGateArmed` / `pendingOverflowSignal` / `overflowLadderExhausted`),
|
|
949
|
+
// not an instance field. The AgentLoop instance is constructed once per
|
|
950
|
+
// Conversation and `run()` is invoked once per turn (a checkpoint handoff
|
|
951
|
+
// breaks out of the loop and the queued message resumes in a fresh `run()`),
|
|
952
|
+
// so a `run()`-local resets implicitly at every turn start — no manual reset
|
|
953
|
+
// point is needed, and suppression can never leak across turns the way an
|
|
954
|
+
// instance field would. (The regrowth watermark, by contrast, lives on the
|
|
955
|
+
// cross-turn `compactionCircuit` precisely because it must persist.)
|
|
956
|
+
let proactiveCompactionFutileThisTurn = false;
|
|
902
957
|
const rlog = log.child({ requestId });
|
|
903
958
|
|
|
904
959
|
// Conversation directory for the result-time tool-result spool/stub pass.
|
|
@@ -1052,7 +1107,47 @@ export class AgentLoop {
|
|
|
1052
1107
|
overflowDriven ||
|
|
1053
1108
|
!isFirstCallGate ||
|
|
1054
1109
|
!(await this.compactionCircuit.isOpen());
|
|
1055
|
-
|
|
1110
|
+
// Regrowth hysteresis: a proactive pass that just ran proved how
|
|
1111
|
+
// far this history can shrink. If the estimate has not climbed at
|
|
1112
|
+
// least `minRegrowth` past that watermark, another pass cannot free
|
|
1113
|
+
// more and would only thrash — skip it and let the provider call
|
|
1114
|
+
// proceed (overflow recovery remains the safety net). Overflow-
|
|
1115
|
+
// driven compaction always bypasses the guard.
|
|
1116
|
+
const watermark = this.compactionCircuit.lastPostCompactionEstimate;
|
|
1117
|
+
const minRegrowth = minRegrowthTokens(maxInputTokens);
|
|
1118
|
+
const regrowthGuardSkip =
|
|
1119
|
+
!overflowDriven &&
|
|
1120
|
+
watermark !== null &&
|
|
1121
|
+
estimated - watermark < minRegrowth;
|
|
1122
|
+
// Floor-dominated thrash guard: a proactive pass earlier this turn
|
|
1123
|
+
// already exhausted the compactor (couldn't clear the gate because
|
|
1124
|
+
// the over-budget region is the protected in-flight turn). The
|
|
1125
|
+
// regrowth guard cannot catch this — each tool round's growth lands
|
|
1126
|
+
// in that protected region and re-arms the regrowth delta — so this
|
|
1127
|
+
// per-turn latch is what stops the repeated futile passes. Overflow-
|
|
1128
|
+
// driven compaction bypasses it.
|
|
1129
|
+
const proactiveFutileSkip =
|
|
1130
|
+
!overflowDriven && proactiveCompactionFutileThisTurn;
|
|
1131
|
+
if (
|
|
1132
|
+
shouldCompact &&
|
|
1133
|
+
compactionAllowed &&
|
|
1134
|
+
(regrowthGuardSkip || proactiveFutileSkip)
|
|
1135
|
+
) {
|
|
1136
|
+
rlog.info(
|
|
1137
|
+
{
|
|
1138
|
+
turn: toolUseTurns,
|
|
1139
|
+
estimated,
|
|
1140
|
+
postCompactionWatermark: watermark,
|
|
1141
|
+
minRegrowth,
|
|
1142
|
+
reason: proactiveFutileSkip
|
|
1143
|
+
? "proactive_compaction_exhausted_this_turn"
|
|
1144
|
+
: "history_not_regrown",
|
|
1145
|
+
},
|
|
1146
|
+
proactiveFutileSkip
|
|
1147
|
+
? "Skipping compaction: a proactive pass already exhausted the compactor this turn — the over-budget region is the protected in-flight turn, so re-compacting would free nothing"
|
|
1148
|
+
: "Skipping compaction: history has not regrown past the post-compaction watermark — re-compacting would not free more",
|
|
1149
|
+
);
|
|
1150
|
+
} else if (shouldCompact && compactionAllowed) {
|
|
1056
1151
|
rlog.info(
|
|
1057
1152
|
{
|
|
1058
1153
|
turn: toolUseTurns,
|
|
@@ -1078,6 +1173,11 @@ export class AgentLoop {
|
|
|
1078
1173
|
// The compacted, re-injected array is the new base; output
|
|
1079
1174
|
// produced after this point is what the wrapper persists.
|
|
1080
1175
|
newMessagesStart = history.length;
|
|
1176
|
+
// Record the post-compaction estimate so the regrowth guard can
|
|
1177
|
+
// tell, on a later gate crossing, whether the history has grown
|
|
1178
|
+
// enough to be worth compacting again.
|
|
1179
|
+
this.compactionCircuit.lastPostCompactionEstimate =
|
|
1180
|
+
this.estimateTokens(history);
|
|
1081
1181
|
}
|
|
1082
1182
|
if (overflowDriven) {
|
|
1083
1183
|
// Carry the ladder's terminal state to the catch: if the
|
|
@@ -1085,6 +1185,12 @@ export class AgentLoop {
|
|
|
1085
1185
|
// ends instead of looping.
|
|
1086
1186
|
overflowLadderExhausted = attempt.exhausted;
|
|
1087
1187
|
overflowAutoCompressApplied = attempt.autoCompressApplied;
|
|
1188
|
+
} else {
|
|
1189
|
+
// Proactive (non-overflow) pass. If it exhausted the compactor
|
|
1190
|
+
// without clearing the gate, latch suppression so later gate
|
|
1191
|
+
// checks this turn skip the futile re-pass; a pass that DID
|
|
1192
|
+
// clear the gate (non-exhausted) releases the latch.
|
|
1193
|
+
proactiveCompactionFutileThisTurn = attempt.exhausted;
|
|
1088
1194
|
}
|
|
1089
1195
|
}
|
|
1090
1196
|
}
|
|
@@ -1195,6 +1301,9 @@ export class AgentLoop {
|
|
|
1195
1301
|
const effectiveOverrideProfile = resolveEffectiveOverrideProfile();
|
|
1196
1302
|
if (effectiveOverrideProfile) {
|
|
1197
1303
|
providerConfig.overrideProfile = effectiveOverrideProfile;
|
|
1304
|
+
if (forceOverrideProfile) {
|
|
1305
|
+
providerConfig.forceOverrideProfile = true;
|
|
1306
|
+
}
|
|
1198
1307
|
}
|
|
1199
1308
|
|
|
1200
1309
|
// Rate-limit consecutive LLM calls to prevent spin when tools return instantly
|
|
@@ -1504,8 +1613,10 @@ export class AgentLoop {
|
|
|
1504
1613
|
content: response.content,
|
|
1505
1614
|
};
|
|
1506
1615
|
|
|
1507
|
-
//
|
|
1508
|
-
|
|
1616
|
+
// The model's own tool calls. The executable set is finalized after
|
|
1617
|
+
// the `post-model-call` hook below, which may add or drop tool calls;
|
|
1618
|
+
// this raw set drives only the completion log and the max-tokens branch.
|
|
1619
|
+
const modelToolUseBlocks = response.content.filter(
|
|
1509
1620
|
(block): block is Extract<ContentBlock, { type: "tool_use" }> =>
|
|
1510
1621
|
block.type === "tool_use",
|
|
1511
1622
|
);
|
|
@@ -1515,7 +1626,7 @@ export class AgentLoop {
|
|
|
1515
1626
|
turn: toolUseTurns,
|
|
1516
1627
|
stopReason: response.stopReason,
|
|
1517
1628
|
contentBlocks: response.content.length,
|
|
1518
|
-
toolUseCount:
|
|
1629
|
+
toolUseCount: modelToolUseBlocks.length,
|
|
1519
1630
|
durationMs: providerDurationMs,
|
|
1520
1631
|
},
|
|
1521
1632
|
"LLM call complete",
|
|
@@ -1534,20 +1645,59 @@ export class AgentLoop {
|
|
|
1534
1645
|
stopReason: response.stopReason,
|
|
1535
1646
|
contentBlocks: response.content.length,
|
|
1536
1647
|
safeContentBlocks: safeContent.length,
|
|
1537
|
-
toolUseCount:
|
|
1648
|
+
toolUseCount: modelToolUseBlocks.length,
|
|
1538
1649
|
},
|
|
1539
1650
|
"LLM response reached output token limit",
|
|
1540
1651
|
);
|
|
1541
1652
|
// Run the hook on the truncated reply so output-filter plugins still
|
|
1542
1653
|
// see it, and so a turn that streamed nothing live gets its final
|
|
1543
|
-
// emit (without this the client would see nothing).
|
|
1544
|
-
//
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1654
|
+
// emit (without this the client would see nothing). A recovery hook
|
|
1655
|
+
// (max-tokens-continue) may set `decision: "continue"` to resume the
|
|
1656
|
+
// truncated turn: it leaves `messages` as the next history (the
|
|
1657
|
+
// truncated turn followed by a continuation nudge), so unlike the
|
|
1658
|
+
// no-tool retry below the partial output is kept, not discarded.
|
|
1659
|
+
// Otherwise the stop is terminal and the continuation card surfaces.
|
|
1660
|
+
const {
|
|
1661
|
+
finalized: rawSafeAssistantMessage,
|
|
1662
|
+
decision: maxTokensDecision,
|
|
1663
|
+
messages: maxTokensMessages,
|
|
1664
|
+
} = await finalizeAssistantMessage({
|
|
1665
|
+
role: "assistant",
|
|
1666
|
+
content: safeContent,
|
|
1667
|
+
});
|
|
1668
|
+
// A truncated turn never executes tools — the model's own tool calls
|
|
1669
|
+
// were stripped into `safeContent` above. The hook can still append a
|
|
1670
|
+
// `tool_use` block while transforming the reply, but this branch
|
|
1671
|
+
// short-circuits without an executor pass, so honoring it would
|
|
1672
|
+
// persist a tool call with no matching `tool_result`. Drop hook-added
|
|
1673
|
+
// tool calls here too: tool injection is supported only on the
|
|
1674
|
+
// non-truncated path below, which runs the executor.
|
|
1675
|
+
const safeAssistantMessage: Message = {
|
|
1676
|
+
...rawSafeAssistantMessage,
|
|
1677
|
+
content: rawSafeAssistantMessage.content.filter(
|
|
1678
|
+
(block) =>
|
|
1679
|
+
block.type !== "tool_use" &&
|
|
1680
|
+
block.type !== "server_tool_use" &&
|
|
1681
|
+
block.type !== "web_search_tool_result",
|
|
1682
|
+
),
|
|
1683
|
+
};
|
|
1550
1684
|
emitFinalAssistantText(safeAssistantMessage.content);
|
|
1685
|
+
if (
|
|
1686
|
+
maxTokensDecision === "continue" &&
|
|
1687
|
+
postModelCallContinues < MAX_POST_MODEL_CALL_CONTINUES
|
|
1688
|
+
) {
|
|
1689
|
+
postModelCallContinues++;
|
|
1690
|
+
rlog.warn(
|
|
1691
|
+
{ turn: toolUseTurns, retry: postModelCallContinues },
|
|
1692
|
+
"max-tokens stop — auto-continuing the truncated turn",
|
|
1693
|
+
);
|
|
1694
|
+
await onEvent({
|
|
1695
|
+
type: "message_complete",
|
|
1696
|
+
message: safeAssistantMessage,
|
|
1697
|
+
});
|
|
1698
|
+
history = maxTokensMessages;
|
|
1699
|
+
continue;
|
|
1700
|
+
}
|
|
1551
1701
|
history.push(safeAssistantMessage);
|
|
1552
1702
|
await onEvent({
|
|
1553
1703
|
type: "max_tokens_reached",
|
|
@@ -1575,6 +1725,25 @@ export class AgentLoop {
|
|
|
1575
1725
|
} = await finalizeAssistantMessage(assistantMessage);
|
|
1576
1726
|
assistantMessage = finalizedAssistantMessage;
|
|
1577
1727
|
|
|
1728
|
+
// Execution follows the FINALIZED content, not the raw reply. A
|
|
1729
|
+
// `post-model-call` hook may append a `tool_use` block to run a tool as
|
|
1730
|
+
// if the model had called it (the supported way for a plugin to surface
|
|
1731
|
+
// a card or take a follow-up action), or drop one the model emitted, so
|
|
1732
|
+
// the loop runs whatever the assistant message ends up carrying.
|
|
1733
|
+
// Normalize ids so the executor and tool_result correlation stay 1:1 —
|
|
1734
|
+
// a hook-added block may carry an empty or duplicate id.
|
|
1735
|
+
toolUseBlocks = assistantMessage.content.filter(
|
|
1736
|
+
(block): block is Extract<ContentBlock, { type: "tool_use" }> =>
|
|
1737
|
+
block.type === "tool_use",
|
|
1738
|
+
);
|
|
1739
|
+
const seenToolUseIds = new Set<string>();
|
|
1740
|
+
for (const block of toolUseBlocks) {
|
|
1741
|
+
if (block.id.length === 0 || seenToolUseIds.has(block.id)) {
|
|
1742
|
+
block.id = crypto.randomUUID();
|
|
1743
|
+
}
|
|
1744
|
+
seenToolUseIds.add(block.id);
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1578
1747
|
// At the no-tool stop boundary the retry decision is actionable: a
|
|
1579
1748
|
// recovery hook may repair history and ask to re-query (a tool-bearing
|
|
1580
1749
|
// turn already continues, so its decision is ignored). A re-query
|
|
@@ -25,3 +25,15 @@
|
|
|
25
25
|
*/
|
|
26
26
|
export const CALL_SITE_SYNTHETIC_AGENT_ERROR_MESSAGE =
|
|
27
27
|
"syntheticAgentErrorMessage";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Marks the summarizer LLM call the agent loop makes to compact a
|
|
31
|
+
* conversation's history when it approaches the context limit. The row
|
|
32
|
+
* lands in the inspector rail like any other call, so the frontend
|
|
33
|
+
* branches on this value to tag it as a compaction rather than a
|
|
34
|
+
* main-agent call.
|
|
35
|
+
*
|
|
36
|
+
* Mirrors the `compactionAgent` member of the backend's `LLMCallSite`
|
|
37
|
+
* enum (the value stamped on the row at write time).
|
|
38
|
+
*/
|
|
39
|
+
export const CALL_SITE_COMPACTION_AGENT = "compactionAgent";
|
|
@@ -12,6 +12,13 @@
|
|
|
12
12
|
* Absent on streams produced by older daemons that pre-date the anchor
|
|
13
13
|
* protocol.
|
|
14
14
|
*
|
|
15
|
+
* `timestampMs` is the daemon's wall-clock emission time for the delta. The
|
|
16
|
+
* transport envelope (`AssistantEvent.emittedAt`) carries the same instant,
|
|
17
|
+
* but it is dropped once the inner message is unwrapped for persistence,
|
|
18
|
+
* debug buffers, and backend storage — so the timestamp is carried on the
|
|
19
|
+
* payload itself to make per-delta timing observable wherever the message
|
|
20
|
+
* travels.
|
|
21
|
+
*
|
|
15
22
|
* Only emitted when thinking streaming is enabled for the turn; turns that
|
|
16
23
|
* suppress reasoning output produce none.
|
|
17
24
|
*
|
|
@@ -26,6 +33,9 @@ export const AssistantThinkingDeltaEventSchema = z.object({
|
|
|
26
33
|
thinking: z.string(),
|
|
27
34
|
messageId: z.string().optional(),
|
|
28
35
|
conversationId: z.string().optional(),
|
|
36
|
+
/** Epoch milliseconds (`Date.now()`) at which the daemon emitted this
|
|
37
|
+
* delta. Absent on streams produced by daemons that pre-date this field. */
|
|
38
|
+
timestampMs: z.number().optional(),
|
|
29
39
|
});
|
|
30
40
|
|
|
31
41
|
export type AssistantThinkingDeltaEvent = z.infer<
|
|
@@ -23,6 +23,13 @@ export const UsageUpdateEventSchema = z.object({
|
|
|
23
23
|
conversationId: z.string(),
|
|
24
24
|
inputTokens: z.number(),
|
|
25
25
|
outputTokens: z.number(),
|
|
26
|
+
/**
|
|
27
|
+
* Per-call prompt-cache token counts, as reported by the provider.
|
|
28
|
+
* Optional: older daemons omit them, and providers without prompt
|
|
29
|
+
* caching never supply them. `inputTokens` already includes these.
|
|
30
|
+
*/
|
|
31
|
+
cacheCreationInputTokens: z.number().optional(),
|
|
32
|
+
cacheReadInputTokens: z.number().optional(),
|
|
26
33
|
totalInputTokens: z.number(),
|
|
27
34
|
totalOutputTokens: z.number(),
|
|
28
35
|
estimatedCost: z.number(),
|
package/src/api/index.ts
CHANGED
|
@@ -53,7 +53,10 @@ import { UsageProgressEventSchema } from "./events/usage-progress.js";
|
|
|
53
53
|
import { UsageUpdateEventSchema } from "./events/usage-update.js";
|
|
54
54
|
import { UserMessageEchoEventSchema } from "./events/user-message-echo.js";
|
|
55
55
|
|
|
56
|
-
export {
|
|
56
|
+
export {
|
|
57
|
+
CALL_SITE_COMPACTION_AGENT,
|
|
58
|
+
CALL_SITE_SYNTHETIC_AGENT_ERROR_MESSAGE,
|
|
59
|
+
} from "./constants/call-sites.js";
|
|
57
60
|
export { DEFAULT_TOOL_EXECUTION_TIMEOUT_SEC } from "./constants/tool-execution.js";
|
|
58
61
|
export {
|
|
59
62
|
type AssistantActivityAnchor,
|
|
@@ -15,14 +15,13 @@
|
|
|
15
15
|
* `injectedText` reflects the live selection; when only `shadow` is true it is
|
|
16
16
|
* the block that WOULD have been injected.
|
|
17
17
|
*
|
|
18
|
-
* `injectedText` is
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* follow-up.
|
|
18
|
+
* `injectedText` is inspector-only, not a verbatim record of the live cards +
|
|
19
|
+
* spotlight. It re-renders each selection's matched section — resolved from the
|
|
20
|
+
* persisted `(slug, sectionOrdinal)` against the CURRENT page — falling back to
|
|
21
|
+
* the full page when no section was recorded. Because the section text is
|
|
22
|
+
* re-derived from the current page, it reflects bounded page-drift if the page
|
|
23
|
+
* changed since the turn (the same approximation the v2 inspector accepts). The
|
|
24
|
+
* selected slug set and each row's matched-section heading are exact as logged.
|
|
26
25
|
*/
|
|
27
26
|
|
|
28
27
|
import { z } from "zod";
|
|
@@ -33,20 +32,28 @@ import { z } from "zod";
|
|
|
33
32
|
* rows may carry retired labels) — but the schema stays a permissive string
|
|
34
33
|
* so a new lane label (or a historical pre-lane row) doesn't break parsing on
|
|
35
34
|
* the FE. `pinned` marks a page the turn was centrally about.
|
|
35
|
+
* `sectionOrdinal`/`sectionHeading` identify the matched section a finder lane
|
|
36
|
+
* surfaced (null for core/hot/fresh/edge selections and pre-migration rows).
|
|
36
37
|
*/
|
|
37
38
|
export const MemoryV3SelectionRowSchema = z.object({
|
|
38
39
|
slug: z.string(),
|
|
39
40
|
source: z.string(),
|
|
40
41
|
pinned: z.boolean(),
|
|
42
|
+
// The matched section a finder lane surfaced for this selection. Null for
|
|
43
|
+
// core/hot/fresh/edge selections with no matched section, and for rows
|
|
44
|
+
// written before the section columns existed. Optional + nullable so older
|
|
45
|
+
// clients and pre-migration rows round-trip.
|
|
46
|
+
sectionOrdinal: z.number().nullable().optional(),
|
|
47
|
+
sectionHeading: z.string().nullable().optional(),
|
|
41
48
|
});
|
|
42
49
|
|
|
43
50
|
export type MemoryV3SelectionRow = z.infer<typeof MemoryV3SelectionRowSchema>;
|
|
44
51
|
|
|
45
52
|
/**
|
|
46
53
|
* Memory v3 selection log shape. `injectedText` is the rendered
|
|
47
|
-
* `<memory>…</memory>` block for the selection —
|
|
48
|
-
*
|
|
49
|
-
*
|
|
54
|
+
* `<memory>…</memory>` block for the selection — re-rendered from the persisted
|
|
55
|
+
* rows, with each selection's matched section resolved from its
|
|
56
|
+
* `(slug, sectionOrdinal)` (full-page fallback when none). See the file header.
|
|
50
57
|
*/
|
|
51
58
|
export const MemoryV3SelectionLogSchema = z.object({
|
|
52
59
|
turn: z.number(),
|
|
@@ -289,8 +289,8 @@ const GRANT_RETRY_MAX_WAIT_MS = 10_000;
|
|
|
289
289
|
* polling to handle the voice pipeline race condition where the grant
|
|
290
290
|
* may still be in-flight: `answerCall()` triggers the voice turn as
|
|
291
291
|
* fire-and-forget, and the voice LLM can attempt tool execution before
|
|
292
|
-
*
|
|
293
|
-
* grant. Polling bridges this timing gap without changing the
|
|
292
|
+
* the guardian-decision
|
|
293
|
+
* classifier finishes minting the grant. Polling bridges this timing gap without changing the
|
|
294
294
|
* fire-and-forget architecture.
|
|
295
295
|
*/
|
|
296
296
|
export async function consumeGrantForInvocation(
|
|
@@ -648,7 +648,10 @@ describe("background wake runtime routes", () => {
|
|
|
648
648
|
},
|
|
649
649
|
});
|
|
650
650
|
const handler = findHandler("drainDueBackgroundWake");
|
|
651
|
-
|
|
651
|
+
// Keep the deadline far enough ahead that the synchronous start-check always
|
|
652
|
+
// sees it as live; the wait below outlasts it, so completion is verified to
|
|
653
|
+
// hold until the work settles rather than fire when the deadline elapses.
|
|
654
|
+
const deadlineAt = Date.now() + 200;
|
|
652
655
|
|
|
653
656
|
const firstResponse = await handler({
|
|
654
657
|
body: drainBodyFixture({
|
|
@@ -658,7 +661,7 @@ describe("background wake runtime routes", () => {
|
|
|
658
661
|
});
|
|
659
662
|
|
|
660
663
|
try {
|
|
661
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
664
|
+
await new Promise((resolve) => setTimeout(resolve, 280));
|
|
662
665
|
expect(mockCompleteBackgroundWakeLease).not.toHaveBeenCalled();
|
|
663
666
|
|
|
664
667
|
const duplicateResponse = await handler({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* JIT download and cache of esbuild binary + preact for app compilation.
|
|
3
3
|
*
|
|
4
4
|
* Instead of shipping these in the .app bundle (~11 MB), we download them
|
|
5
|
-
* on first compile to
|
|
5
|
+
* on first compile to $VELLUM_WORKSPACE_DIR/compiler-tools/. Follows the
|
|
6
6
|
* same pattern as EmbeddingRuntimeManager.
|
|
7
7
|
*/
|
|
8
8
|
|
package/src/calls/call-domain.ts
CHANGED
|
@@ -212,7 +212,7 @@ export async function resolveCallerIdentity(
|
|
|
212
212
|
return {
|
|
213
213
|
ok: false,
|
|
214
214
|
error:
|
|
215
|
-
"user_number mode requires a user phone number. Set calls.callerIdentity.userNumber in config or store credential/twilio/user_phone_number via
|
|
215
|
+
"user_number mode requires a user phone number. Set calls.callerIdentity.userNumber in config or store credential/twilio/user_phone_number via `assistant credentials set`.",
|
|
216
216
|
};
|
|
217
217
|
}
|
|
218
218
|
|
|
@@ -1,42 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Guardian action expiry notices.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* 2. Expires the associated pending question so the call-side timeout fires
|
|
8
|
-
* 3. Sends expiry notices to external delivery destinations (telegram)
|
|
9
|
-
* 4. Adds an expiry message to mac guardian conversations
|
|
4
|
+
* Sends "this request has expired" notices to guardian delivery
|
|
5
|
+
* destinations — vellum conversations get an assistant message, external
|
|
6
|
+
* channels (telegram, slack) get a direct channel reply.
|
|
10
7
|
*/
|
|
11
8
|
|
|
12
9
|
import { addMessage } from "../memory/conversation-crud.js";
|
|
13
|
-
import {
|
|
14
|
-
expireGuardianActionRequest,
|
|
15
|
-
getDeliveriesByRequestId,
|
|
16
|
-
getExpiredGuardianActionRequests,
|
|
17
|
-
} from "../memory/guardian-action-store.js";
|
|
18
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
19
10
|
import { deliverChannelReply } from "../runtime/gateway-client.js";
|
|
20
11
|
import { composeGuardianActionMessageGenerative } from "../runtime/guardian-action-message-composer.js";
|
|
21
|
-
import type { GuardianActionCopyGenerator } from "../runtime/http-types.js";
|
|
22
12
|
import { getLogger } from "../util/logger.js";
|
|
23
|
-
import { expirePendingQuestions } from "./call-store.js";
|
|
24
13
|
|
|
25
14
|
const log = getLogger("guardian-action-sweep");
|
|
26
15
|
|
|
27
|
-
const SWEEP_INTERVAL_MS = 60_000;
|
|
28
|
-
|
|
29
|
-
let sweepTimer: ReturnType<typeof setInterval> | null = null;
|
|
30
|
-
let sweepInProgress = false;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Send expiry notices to all delivery destinations for a guardian action
|
|
34
|
-
* request. Handles both vellum/mac conversation messages and external channel
|
|
35
|
-
* replies (telegram, slack).
|
|
36
|
-
*
|
|
37
|
-
* Deliveries must be captured *before* their status is changed to 'expired'
|
|
38
|
-
* so the sent/pending filter still matches.
|
|
39
|
-
*/
|
|
40
16
|
/** Minimal delivery shape used by the expiry notice sender. */
|
|
41
17
|
export interface ExpiryDeliveryInfo {
|
|
42
18
|
id: string;
|
|
@@ -46,23 +22,26 @@ export interface ExpiryDeliveryInfo {
|
|
|
46
22
|
destinationChatId: string | null;
|
|
47
23
|
}
|
|
48
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Send expiry notices to all delivery destinations for a guardian action
|
|
27
|
+
* request. Handles both vellum/mac conversation messages and external channel
|
|
28
|
+
* replies (telegram, slack).
|
|
29
|
+
*
|
|
30
|
+
* Deliveries must be captured *before* their status is changed to 'expired'
|
|
31
|
+
* so the sent/pending filter still matches.
|
|
32
|
+
*/
|
|
49
33
|
export async function sendGuardianExpiryNotices(
|
|
50
34
|
deliveries: ExpiryDeliveryInfo[],
|
|
51
35
|
assistantId: string,
|
|
52
|
-
guardianActionCopyGenerator?: GuardianActionCopyGenerator,
|
|
53
36
|
): Promise<void> {
|
|
54
37
|
for (const delivery of deliveries) {
|
|
55
38
|
if (delivery.status !== "sent" && delivery.status !== "pending") continue;
|
|
56
39
|
|
|
57
40
|
try {
|
|
58
|
-
const expiryText = await composeGuardianActionMessageGenerative(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
},
|
|
63
|
-
{},
|
|
64
|
-
guardianActionCopyGenerator,
|
|
65
|
-
);
|
|
41
|
+
const expiryText = await composeGuardianActionMessageGenerative({
|
|
42
|
+
scenario: "guardian_stale_expired",
|
|
43
|
+
channel: delivery.destinationChannel,
|
|
44
|
+
});
|
|
66
45
|
|
|
67
46
|
if (
|
|
68
47
|
delivery.destinationChannel === "vellum" &&
|
|
@@ -99,59 +78,3 @@ export async function sendGuardianExpiryNotices(
|
|
|
99
78
|
}
|
|
100
79
|
}
|
|
101
80
|
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Sweep expired guardian action requests and clean up.
|
|
105
|
-
*/
|
|
106
|
-
export async function sweepExpiredGuardianActions(
|
|
107
|
-
guardianActionCopyGenerator?: GuardianActionCopyGenerator,
|
|
108
|
-
): Promise<void> {
|
|
109
|
-
const expired = getExpiredGuardianActionRequests();
|
|
110
|
-
|
|
111
|
-
for (const request of expired) {
|
|
112
|
-
// Capture deliveries before expiring (since expiry changes their status)
|
|
113
|
-
const deliveries = getDeliveriesByRequestId(request.id);
|
|
114
|
-
|
|
115
|
-
// Expire the request and all deliveries
|
|
116
|
-
expireGuardianActionRequest(request.id, "sweep_timeout");
|
|
117
|
-
|
|
118
|
-
// Expire associated pending questions
|
|
119
|
-
expirePendingQuestions(request.callSessionId);
|
|
120
|
-
|
|
121
|
-
log.info(
|
|
122
|
-
{ requestId: request.id, callSessionId: request.callSessionId },
|
|
123
|
-
"Expired guardian action request",
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
await sendGuardianExpiryNotices(
|
|
127
|
-
deliveries,
|
|
128
|
-
DAEMON_INTERNAL_ASSISTANT_ID,
|
|
129
|
-
guardianActionCopyGenerator,
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export function startGuardianActionSweep(
|
|
135
|
-
guardianActionCopyGenerator?: GuardianActionCopyGenerator,
|
|
136
|
-
): void {
|
|
137
|
-
if (sweepTimer) return;
|
|
138
|
-
sweepTimer = setInterval(async () => {
|
|
139
|
-
if (sweepInProgress) return;
|
|
140
|
-
sweepInProgress = true;
|
|
141
|
-
try {
|
|
142
|
-
await sweepExpiredGuardianActions(guardianActionCopyGenerator);
|
|
143
|
-
} catch (err) {
|
|
144
|
-
log.error({ err }, "Guardian action sweep failed");
|
|
145
|
-
} finally {
|
|
146
|
-
sweepInProgress = false;
|
|
147
|
-
}
|
|
148
|
-
}, SWEEP_INTERVAL_MS);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export function stopGuardianActionSweep(): void {
|
|
152
|
-
if (sweepTimer) {
|
|
153
|
-
clearInterval(sweepTimer);
|
|
154
|
-
sweepTimer = null;
|
|
155
|
-
}
|
|
156
|
-
sweepInProgress = false;
|
|
157
|
-
}
|
package/src/cli/AGENTS.md
CHANGED
|
@@ -14,6 +14,10 @@ For commands that manage the **lifecycle of assistant instances** (create, start
|
|
|
14
14
|
|
|
15
15
|
Examples: `config`, `contacts`, `memory`, `autonomy`, `conversations` belong here. `hatch`, `wake`, `sleep`, `retire`, `ps`, `ssh` belong in `cli/`.
|
|
16
16
|
|
|
17
|
+
## Full CRUD for Resource Namespaces
|
|
18
|
+
|
|
19
|
+
Every namespace that manages a resource (schedules, contacts, tasks, …) must expose the full CRUD surface — create, get/list, update, delete — each wired to a daemon route. Intentional exceptions (e.g. create restricted to one mode) must be documented inline in the namespace help text so agents know the gap is deliberate. Partial surfaces are not a smaller scope, they are a hazard: when a CRUD verb is missing, the model bypasses the CLI and hand-writes SQLite rows instead.
|
|
20
|
+
|
|
17
21
|
## Conventions
|
|
18
22
|
|
|
19
23
|
- Commands use [Commander.js](https://github.com/tj/commander.js) and follow the `registerXCommand(program: Command)` pattern.
|