@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
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
* Channel delivery routes: delivery ack, dead letters, reply delivery,
|
|
3
3
|
* and post-decision delivery scheduling.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
acknowledgeDelivery,
|
|
7
|
+
getDeadLetterEvents,
|
|
8
|
+
replayDeadLetters,
|
|
9
|
+
} from "../../memory/delivery-status.js";
|
|
6
10
|
import { BadRequestError, NotFoundError } from "./errors.js";
|
|
7
11
|
import type { RouteHandlerArgs } from "./types.js";
|
|
8
12
|
|
|
@@ -10,6 +14,7 @@ export {
|
|
|
10
14
|
type DeliverReplyOptions,
|
|
11
15
|
deliverReplyViaCallback,
|
|
12
16
|
} from "../channel-reply-delivery.js";
|
|
17
|
+
export { finalizeEventDelivery } from "../finalize-event-delivery.js";
|
|
13
18
|
|
|
14
19
|
// ---------------------------------------------------------------------------
|
|
15
20
|
// Dead letter management
|
|
@@ -36,12 +41,11 @@ export function handleReplayDeadLetters({ body = {} }: RouteHandlerArgs) {
|
|
|
36
41
|
// ---------------------------------------------------------------------------
|
|
37
42
|
|
|
38
43
|
export function handleChannelDeliveryAck({ body = {} }: RouteHandlerArgs) {
|
|
39
|
-
const { sourceChannel, conversationExternalId, externalMessageId } =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
44
|
+
const { sourceChannel, conversationExternalId, externalMessageId } = body as {
|
|
45
|
+
sourceChannel?: string;
|
|
46
|
+
conversationExternalId?: string;
|
|
47
|
+
externalMessageId?: string;
|
|
48
|
+
};
|
|
45
49
|
|
|
46
50
|
if (!sourceChannel || typeof sourceChannel !== "string") {
|
|
47
51
|
throw new BadRequestError("sourceChannel is required");
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Static ROUTES array for channel endpoints.
|
|
3
3
|
*/
|
|
4
|
+
import { RuntimeInboundPayloadSchema } from "@vellumai/gateway-client";
|
|
5
|
+
|
|
4
6
|
import { ACTOR_PRINCIPALS, GATEWAY_PRINCIPALS } from "../auth/route-policy.js";
|
|
5
7
|
import {
|
|
6
8
|
handleChannelDeliveryAck,
|
|
@@ -38,6 +40,7 @@ export const CHANNEL_ROUTES: RouteDefinition[] = [
|
|
|
38
40
|
summary: "Process inbound channel message",
|
|
39
41
|
description: "Receive an inbound message from a channel integration.",
|
|
40
42
|
tags: ["channels"],
|
|
43
|
+
requestBody: RuntimeInboundPayloadSchema,
|
|
41
44
|
handler: handleChannelInbound,
|
|
42
45
|
},
|
|
43
46
|
{
|
|
@@ -62,7 +62,9 @@ export function parseCallbackData(
|
|
|
62
62
|
? ("whatsapp_button" as const)
|
|
63
63
|
: sourceChannel === "slack"
|
|
64
64
|
? ("slack_button" as const)
|
|
65
|
-
:
|
|
65
|
+
: sourceChannel === "vellum"
|
|
66
|
+
? ("vellum_surface" as const)
|
|
67
|
+
: ("telegram_button" as const);
|
|
66
68
|
return { action: action as ApprovalAction, source, requestId };
|
|
67
69
|
}
|
|
68
70
|
|
|
@@ -31,6 +31,13 @@ import { getUsageCostForConversationWindow } from "../../memory/llm-usage-store.
|
|
|
31
31
|
import { MEMORY_V2_CONSOLIDATION_SOURCE } from "../../memory/v2/constants.js";
|
|
32
32
|
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
33
33
|
import { BadRequestError } from "./errors.js";
|
|
34
|
+
import {
|
|
35
|
+
paginateRuns,
|
|
36
|
+
parseRunsBeforeCursor,
|
|
37
|
+
parseRunsLimit,
|
|
38
|
+
RUNS_NEXT_CURSOR_SCHEMA,
|
|
39
|
+
RUNS_PAGINATION_QUERY_PARAMS,
|
|
40
|
+
} from "./runs-pagination.js";
|
|
34
41
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
35
42
|
|
|
36
43
|
function isConsolidationAvailable(): boolean {
|
|
@@ -162,13 +169,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
162
169
|
"on the conversation row. Shape mirrors `heartbeat/runs` so the " +
|
|
163
170
|
"schedules settings UI can reuse its run-row component.",
|
|
164
171
|
tags: ["consolidation"],
|
|
165
|
-
queryParams:
|
|
166
|
-
{
|
|
167
|
-
name: "limit",
|
|
168
|
-
schema: { type: "integer" },
|
|
169
|
-
description: "Max runs to return (default 20, max 100)",
|
|
170
|
-
},
|
|
171
|
-
],
|
|
172
|
+
queryParams: RUNS_PAGINATION_QUERY_PARAMS(20),
|
|
172
173
|
responseBody: z.object({
|
|
173
174
|
runs: z
|
|
174
175
|
.array(
|
|
@@ -189,16 +190,18 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
189
190
|
}),
|
|
190
191
|
)
|
|
191
192
|
.describe("Consolidation run records"),
|
|
193
|
+
nextCursor: RUNS_NEXT_CURSOR_SCHEMA,
|
|
192
194
|
}),
|
|
193
195
|
handler: async ({ queryParams }: RouteHandlerArgs) => {
|
|
194
196
|
const params = queryParams ?? {};
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
const limit = parseRunsLimit(params, 20);
|
|
198
|
+
const before = parseRunsBeforeCursor(params);
|
|
199
|
+
const { rows, nextCursor } = paginateRuns(
|
|
200
|
+
listConversationsBySource(MEMORY_V2_CONSOLIDATION_SOURCE, limit + 1, {
|
|
201
|
+
beforeCreatedAt: before,
|
|
202
|
+
}),
|
|
201
203
|
limit,
|
|
204
|
+
(c) => c.createdAt,
|
|
202
205
|
);
|
|
203
206
|
// Aggregate assistant-message stats in one batched query: presence of
|
|
204
207
|
// an assistant message is the strongest "agent emitted output" signal
|
|
@@ -212,6 +215,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
212
215
|
);
|
|
213
216
|
const now = Date.now();
|
|
214
217
|
return {
|
|
218
|
+
nextCursor,
|
|
215
219
|
runs: rows.map((c) => {
|
|
216
220
|
const stat = assistantStats.get(c.id);
|
|
217
221
|
const hasAssistantOutput = (stat?.count ?? 0) > 0;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Route definitions for the per-conversation **compaction
|
|
2
|
+
* Route definitions for the per-conversation **compaction** view.
|
|
3
3
|
*
|
|
4
4
|
* GET /v1/conversations/:id/compaction?callId=…
|
|
5
5
|
*
|
|
@@ -8,48 +8,42 @@
|
|
|
8
8
|
*
|
|
9
9
|
* # Scope
|
|
10
10
|
*
|
|
11
|
-
* Returns
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
11
|
+
* Returns the compaction(s) attributed to the call identified by
|
|
12
|
+
* `callId`, ordered chronologically. A compaction is attributed to the
|
|
13
|
+
* next real LLM call that ran after it, so the compactions for a given
|
|
14
|
+
* call are those that landed strictly between the previous real
|
|
15
|
+
* (non-`compactionAgent`) call and the selected call. This is the data
|
|
16
|
+
* the Inspector's "Compaction" tab shows when you select a call in the
|
|
17
|
+
* rail: it answers "which compaction reshaped the context that this
|
|
18
|
+
* call ran against?".
|
|
17
19
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* user message (or end-of-conversation) that ends it. Tool-result user
|
|
22
|
-
* messages are not turn boundaries. When the conversation has no other
|
|
23
|
-
* messages around the selected call, the window collapses to the
|
|
24
|
-
* call's own `createdAt` and every compaction strictly before it is
|
|
25
|
-
* returned — same as the legacy behavior.
|
|
20
|
+
* The window is usually empty or holds a single compaction, but the
|
|
21
|
+
* recovery cascade can fire several compactions before one call lands,
|
|
22
|
+
* so the response carries a list rather than a single object.
|
|
26
23
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* between two adjacent calls hides most of that activity from the UI
|
|
33
|
-
* — especially for the call that *yields* on a budget-exhausted error,
|
|
34
|
-
* which has no compaction immediately before it but had several
|
|
35
|
-
* earlier in the same turn. The turn is the right unit of analysis.
|
|
24
|
+
* The floor is resolved by `getPreviousNonCompactionCallCreatedAt` on
|
|
25
|
+
* the log source and the ceiling is the selected call's own
|
|
26
|
+
* `createdAt`. Both bounds are exclusive (the stores use strict `>` /
|
|
27
|
+
* `<` predicates), so a compaction whose timestamp lands strictly
|
|
28
|
+
* between the two real calls is in scope without any boundary fudging.
|
|
36
29
|
*
|
|
37
30
|
* # Data sources
|
|
38
31
|
*
|
|
39
32
|
* When `compactionLogs.destination = "clickhouse"` is configured, the
|
|
40
|
-
*
|
|
33
|
+
* data is served from the first-class compaction log: the agent loop's
|
|
41
34
|
* start/end event pairs written by
|
|
42
|
-
* `memory/compaction-log-store-clickhouse.ts`. Those rows carry
|
|
43
|
-
*
|
|
44
|
-
* which exist on
|
|
35
|
+
* `memory/compaction-log-store-clickhouse.ts`. Those rows carry the
|
|
36
|
+
* before/after context-token and message counts, real durations, the
|
|
37
|
+
* trigger, and the summary text — none of which exist on
|
|
38
|
+
* `llm_request_logs`.
|
|
45
39
|
*
|
|
46
40
|
* The legacy projection over `llm_request_logs` rows with
|
|
47
41
|
* `call_site = "compactionAgent"` remains as the fallback: it serves
|
|
48
|
-
*
|
|
42
|
+
* calls that predate the compaction log (the table is append-only from
|
|
49
43
|
* the moment the destination is configured), assistants that never opt
|
|
50
|
-
* in, and reads where the ClickHouse query fails.
|
|
51
|
-
*
|
|
52
|
-
* `
|
|
44
|
+
* in, and reads where the ClickHouse query fails. The legacy path can
|
|
45
|
+
* only recover the summarizer call's own model/usage/text — the
|
|
46
|
+
* before/after counts, duration, and trigger land as `null`.
|
|
53
47
|
*/
|
|
54
48
|
|
|
55
49
|
import { z } from "zod";
|
|
@@ -58,12 +52,9 @@ import {
|
|
|
58
52
|
type CompactionLogEvent,
|
|
59
53
|
getCompactionLogStore,
|
|
60
54
|
} from "../../memory/compaction-log-store-clickhouse.js";
|
|
61
|
-
import {
|
|
62
|
-
getConversation,
|
|
63
|
-
getTurnTimeBounds,
|
|
64
|
-
} from "../../memory/conversation-crud.js";
|
|
55
|
+
import { getConversation } from "../../memory/conversation-crud.js";
|
|
65
56
|
import { getLlmRequestLogSource } from "../../memory/llm-request-log-source.js";
|
|
66
|
-
import type {
|
|
57
|
+
import type { CompactionAgentLogRow } from "../../memory/llm-request-log-store.js";
|
|
67
58
|
import { getLogger } from "../../util/logger.js";
|
|
68
59
|
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
69
60
|
import { BadRequestError, NotFoundError } from "./errors.js";
|
|
@@ -76,29 +67,59 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
|
76
67
|
const log = getLogger("conversation-compaction-routes");
|
|
77
68
|
|
|
78
69
|
/**
|
|
79
|
-
* Wire shape for a single compaction
|
|
80
|
-
*
|
|
81
|
-
* `
|
|
82
|
-
*
|
|
83
|
-
*
|
|
70
|
+
* Wire shape for a single compaction attributed to an LLM call.
|
|
71
|
+
*
|
|
72
|
+
* `responseBody` (below) is the source-of-truth for the generated
|
|
73
|
+
* OpenAPI client type the frontend imports
|
|
74
|
+
* (`ConversationsByIdCompactionGetResponse` in
|
|
75
|
+
* `apps/web/src/generated/daemon/types.gen`); regenerate the client with
|
|
76
|
+
* `bun run openapi-ts` after changing the schema.
|
|
77
|
+
*
|
|
78
|
+
* `null` means the value isn't known for the underlying row — either the
|
|
79
|
+
* legacy projection can't recover it, or the attempt never wrote its end
|
|
80
|
+
* row. The frontend renders missing values as a placeholder.
|
|
84
81
|
*/
|
|
85
82
|
export interface CompactionTrailEvent {
|
|
86
83
|
id: string;
|
|
84
|
+
/** Epoch-ms timestamp the compaction started. */
|
|
87
85
|
createdAt: number;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
/** What triggered the compaction (e.g. `budget`, `overflow`). */
|
|
87
|
+
trigger: string | null;
|
|
88
|
+
/** True when the attempt actually reduced the context. */
|
|
89
|
+
compacted: boolean | null;
|
|
90
|
+
/** True when the summarizer provider call threw. */
|
|
91
|
+
summaryFailed: boolean | null;
|
|
92
|
+
/**
|
|
93
|
+
* Why a no-op attempt did nothing (e.g. below the auto threshold,
|
|
94
|
+
* compaction disabled). Set only when `compacted` is false.
|
|
95
|
+
*/
|
|
96
|
+
skipReason: string | null;
|
|
97
|
+
/** Estimated context input tokens before the compaction ran. */
|
|
98
|
+
contextTokensBefore: number | null;
|
|
99
|
+
/** Estimated context input tokens after the compaction ran. */
|
|
100
|
+
contextTokensAfter: number | null;
|
|
101
|
+
/** Message count in the context before the compaction ran. */
|
|
102
|
+
messagesBefore: number | null;
|
|
103
|
+
/** Message count in the context after the compaction ran. */
|
|
104
|
+
messagesAfter: number | null;
|
|
105
|
+
/** How many messages were folded into the summary. */
|
|
106
|
+
compactedMessages: number | null;
|
|
107
|
+
/** How many recent messages were preserved verbatim past the summary. */
|
|
108
|
+
preservedTailMessages: number | null;
|
|
92
109
|
/**
|
|
93
110
|
* Per-attempt wall-clock latency, in milliseconds. Populated from the
|
|
94
|
-
* compaction log when configured;
|
|
111
|
+
* compaction log when configured; `null` on the legacy
|
|
95
112
|
* `llm_request_logs` path, which has no duration column.
|
|
96
113
|
*/
|
|
97
114
|
durationMs: number | null;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
115
|
+
/** Model that produced the summary. */
|
|
116
|
+
summaryModel: string | null;
|
|
117
|
+
/** Input tokens the summarizer call itself consumed. */
|
|
118
|
+
summaryInputTokens: number | null;
|
|
119
|
+
/** Output tokens the summarizer call itself produced. */
|
|
120
|
+
summaryOutputTokens: number | null;
|
|
121
|
+
/** The summary text that replaced the compacted span. */
|
|
122
|
+
summaryText: string | null;
|
|
102
123
|
}
|
|
103
124
|
|
|
104
125
|
export interface CompactionTrailResponse {
|
|
@@ -109,15 +130,21 @@ export interface CompactionTrailResponse {
|
|
|
109
130
|
const compactionTrailEventSchema = z.object({
|
|
110
131
|
id: z.string(),
|
|
111
132
|
createdAt: z.number(),
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
133
|
+
trigger: z.string().nullable(),
|
|
134
|
+
compacted: z.boolean().nullable(),
|
|
135
|
+
summaryFailed: z.boolean().nullable(),
|
|
136
|
+
skipReason: z.string().nullable(),
|
|
137
|
+
contextTokensBefore: z.number().nullable(),
|
|
138
|
+
contextTokensAfter: z.number().nullable(),
|
|
139
|
+
messagesBefore: z.number().nullable(),
|
|
140
|
+
messagesAfter: z.number().nullable(),
|
|
141
|
+
compactedMessages: z.number().nullable(),
|
|
142
|
+
preservedTailMessages: z.number().nullable(),
|
|
116
143
|
durationMs: z.number().nullable(),
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
144
|
+
summaryModel: z.string().nullable(),
|
|
145
|
+
summaryInputTokens: z.number().nullable(),
|
|
146
|
+
summaryOutputTokens: z.number().nullable(),
|
|
147
|
+
summaryText: z.string().nullable(),
|
|
121
148
|
});
|
|
122
149
|
|
|
123
150
|
const compactionTrailResponseSchema = z.object({
|
|
@@ -126,7 +153,7 @@ const compactionTrailResponseSchema = z.object({
|
|
|
126
153
|
});
|
|
127
154
|
|
|
128
155
|
// ---------------------------------------------------------------------------
|
|
129
|
-
// Projection —
|
|
156
|
+
// Projection — CompactionAgentLogRow → CompactionTrailEvent
|
|
130
157
|
// ---------------------------------------------------------------------------
|
|
131
158
|
|
|
132
159
|
function tryParseJson(value: string): unknown {
|
|
@@ -138,22 +165,27 @@ function tryParseJson(value: string): unknown {
|
|
|
138
165
|
}
|
|
139
166
|
|
|
140
167
|
/**
|
|
141
|
-
* Project a
|
|
142
|
-
* shape.
|
|
143
|
-
*
|
|
168
|
+
* Project a compaction-agent `llm_request_logs` row into the compaction
|
|
169
|
+
* wire shape. This degraded fallback can only recover what the
|
|
170
|
+
* summarizer call itself recorded: `normalizeLlmContextPayloads` pulls
|
|
171
|
+
* the summary model, the summarizer's own token usage, and the summary
|
|
172
|
+
* text from the response payload.
|
|
144
173
|
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
174
|
+
* The before/after context-token and message counts, the duration, and
|
|
175
|
+
* the trigger never existed on `llm_request_logs`, so they land as
|
|
176
|
+
* `null`. The request payload — an entire near-limit context window per
|
|
177
|
+
* compaction — is never loaded; its message count is computed in SQL and
|
|
178
|
+
* arrives on the row as `requestMessageCount` (the messages fed to the
|
|
179
|
+
* summarizer, i.e. the messages that were compacted).
|
|
148
180
|
*
|
|
149
181
|
* Exported only for unit tests; the route handler is the sole production
|
|
150
182
|
* caller.
|
|
151
183
|
*/
|
|
152
184
|
export function projectLogRowToCompactionTrailEvent(
|
|
153
|
-
log:
|
|
185
|
+
log: CompactionAgentLogRow,
|
|
154
186
|
): CompactionTrailEvent {
|
|
155
187
|
const normalized = normalizeLlmContextPayloads({
|
|
156
|
-
requestPayload:
|
|
188
|
+
requestPayload: undefined,
|
|
157
189
|
responsePayload: tryParseJson(log.responsePayload),
|
|
158
190
|
createdAt: log.createdAt,
|
|
159
191
|
});
|
|
@@ -161,28 +193,33 @@ export function projectLogRowToCompactionTrailEvent(
|
|
|
161
193
|
return {
|
|
162
194
|
id: log.id,
|
|
163
195
|
createdAt: log.createdAt,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
196
|
+
trigger: null,
|
|
197
|
+
compacted: null,
|
|
198
|
+
summaryFailed: null,
|
|
199
|
+
skipReason: null,
|
|
200
|
+
contextTokensBefore: null,
|
|
201
|
+
contextTokensAfter: null,
|
|
202
|
+
messagesBefore: null,
|
|
203
|
+
messagesAfter: null,
|
|
204
|
+
compactedMessages: log.requestMessageCount,
|
|
205
|
+
preservedTailMessages: null,
|
|
173
206
|
durationMs: null,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
207
|
+
summaryModel: summary?.model ?? null,
|
|
208
|
+
summaryInputTokens: summary?.inputTokens ?? null,
|
|
209
|
+
summaryOutputTokens: summary?.outputTokens ?? null,
|
|
210
|
+
summaryText: summary?.responsePreview ?? null,
|
|
178
211
|
};
|
|
179
212
|
}
|
|
180
213
|
|
|
181
214
|
/**
|
|
182
|
-
* Project a paired compaction-log event into the
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
215
|
+
* Project a paired compaction-log event into the wire shape. The headline
|
|
216
|
+
* before/after figures are the context reduction the compaction achieved
|
|
217
|
+
* (`contextTokensBefore`/`After`, `messagesBefore`/`After`); the
|
|
218
|
+
* summarizer's own usage (`summaryInputTokens`/`OutputTokens`) is the
|
|
219
|
+
* separate cost of running the compaction itself.
|
|
220
|
+
*
|
|
221
|
+
* `trigger` stores `""` for unknown on the row; map it back to `null` so
|
|
222
|
+
* the wire shape's "not known" sentinel stays consistent.
|
|
186
223
|
*
|
|
187
224
|
* Exported only for unit tests; the route handler is the sole production
|
|
188
225
|
* caller.
|
|
@@ -193,15 +230,21 @@ export function projectCompactionLogEventToTrailEvent(
|
|
|
193
230
|
return {
|
|
194
231
|
id: event.compactionId,
|
|
195
232
|
createdAt: event.startedAt,
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
233
|
+
trigger: event.trigger === "" ? null : event.trigger,
|
|
234
|
+
compacted: event.compacted,
|
|
235
|
+
summaryFailed: event.summaryFailed,
|
|
236
|
+
skipReason: event.reason,
|
|
237
|
+
contextTokensBefore: event.previousEstimatedInputTokens,
|
|
238
|
+
contextTokensAfter: event.estimatedInputTokens,
|
|
239
|
+
messagesBefore: event.preMessageCount,
|
|
240
|
+
messagesAfter: event.resultMessageCount,
|
|
241
|
+
compactedMessages: event.compactedMessages,
|
|
242
|
+
preservedTailMessages: event.preservedTailMessages,
|
|
200
243
|
durationMs: event.durationMs,
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
244
|
+
summaryModel: event.summaryModel,
|
|
245
|
+
summaryInputTokens: event.summaryInputTokens,
|
|
246
|
+
summaryOutputTokens: event.summaryOutputTokens,
|
|
247
|
+
summaryText: event.summaryText,
|
|
205
248
|
};
|
|
206
249
|
}
|
|
207
250
|
|
|
@@ -232,7 +275,10 @@ async function handleGetCompactionTrail({
|
|
|
232
275
|
}
|
|
233
276
|
|
|
234
277
|
const source = await getLlmRequestLogSource();
|
|
235
|
-
|
|
278
|
+
// Metadata-only lookup — the handler needs the call's conversation
|
|
279
|
+
// scope and `createdAt` anchor, never its payloads (a single request
|
|
280
|
+
// payload can be a full context window).
|
|
281
|
+
const selectedCall = await source.getRequestLogMetaById(callId);
|
|
236
282
|
if (!selectedCall) {
|
|
237
283
|
throw new NotFoundError(`LLM call ${callId} not found`);
|
|
238
284
|
}
|
|
@@ -246,34 +292,28 @@ async function handleGetCompactionTrail({
|
|
|
246
292
|
);
|
|
247
293
|
}
|
|
248
294
|
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
//
|
|
255
|
-
//
|
|
256
|
-
//
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
// a regression on conversations with a single message.
|
|
263
|
-
const turnBounds = getTurnTimeBounds(conversationId, selectedCall.createdAt);
|
|
264
|
-
const afterCreatedAt: number | null =
|
|
265
|
-
turnBounds !== null ? turnBounds.startTime - 1 : null;
|
|
266
|
-
const beforeCreatedAt: number =
|
|
267
|
-
turnBounds !== null ? turnBounds.endTime + 1 : selectedCall.createdAt;
|
|
295
|
+
// A compaction is attributed to the next real LLM call that ran after
|
|
296
|
+
// it, so the compactions for the selected call are those that landed
|
|
297
|
+
// strictly between the previous real (non-`compactionAgent`) call and
|
|
298
|
+
// the selected call. The floor is the previous real call's `createdAt`
|
|
299
|
+
// (null when the selected call is the first real call in the
|
|
300
|
+
// conversation, leaving an open floor); the ceiling is the selected
|
|
301
|
+
// call's own `createdAt`. Both stores use strict `>` / `<` predicates,
|
|
302
|
+
// so no boundary fudging is needed.
|
|
303
|
+
const afterCreatedAt = await source.getPreviousNonCompactionCallCreatedAt(
|
|
304
|
+
conversationId,
|
|
305
|
+
selectedCall.createdAt,
|
|
306
|
+
);
|
|
307
|
+
const beforeCreatedAt = selectedCall.createdAt;
|
|
268
308
|
// Prefer the first-class compaction log when the assistant has opted
|
|
269
|
-
// in. Zero rows means the
|
|
309
|
+
// in. Zero rows means the call predates the log (it is append-only from
|
|
270
310
|
// the moment the destination is configured), so fall through to the
|
|
271
|
-
// legacy projection rather than returning an empty
|
|
311
|
+
// legacy projection rather than returning an empty result; same for a
|
|
272
312
|
// failed ClickHouse read. Writes are best-effort and the start/end rows
|
|
273
313
|
// land independently, so an event without its end row (no `finishedAt`)
|
|
274
314
|
// means the end write failed or is lagging — in that case the legacy
|
|
275
315
|
// projection may still have the summarizer call details, so fall back
|
|
276
|
-
// rather than serve
|
|
316
|
+
// rather than serve null counts/duration.
|
|
277
317
|
const compactionStore = getCompactionLogStore();
|
|
278
318
|
if (compactionStore) {
|
|
279
319
|
try {
|
|
@@ -324,9 +364,9 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
324
364
|
requiredScopes: ["chat.read"],
|
|
325
365
|
allowedPrincipalTypes: ACTOR_PRINCIPALS,
|
|
326
366
|
},
|
|
327
|
-
summary: "Get the compaction
|
|
367
|
+
summary: "Get the compaction(s) attributed to an LLM call",
|
|
328
368
|
description:
|
|
329
|
-
'Return the chronological list of
|
|
369
|
+
'Return the chronological list of compactions attributed to the call identified by `callId` — those that ran strictly between the previous real (non-`compactionAgent`) LLM call and the selected call. Served from the first-class compaction log when `compactionLogs.destination = "clickhouse"` is configured, falling back to the legacy projection over `llm_request_logs` rows where `call_site = "compactionAgent"`. Usually empty or a single compaction; the recovery cascade can fire several before one call lands. Drives the Inspector\'s Compaction tab.',
|
|
330
370
|
tags: ["conversations"],
|
|
331
371
|
pathParams: [
|
|
332
372
|
{
|
|
@@ -340,7 +380,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
340
380
|
required: true,
|
|
341
381
|
schema: { type: "string" },
|
|
342
382
|
description:
|
|
343
|
-
"ID of the selected LLM call from the rail. Defines the chronological cutoff for the
|
|
383
|
+
"ID of the selected LLM call from the rail. Defines the chronological cutoff for the attributed compactions.",
|
|
344
384
|
},
|
|
345
385
|
],
|
|
346
386
|
responseBody: compactionTrailResponseSchema,
|
|
@@ -217,17 +217,35 @@ function handleListConversations({ queryParams = {} }: RouteHandlerArgs) {
|
|
|
217
217
|
? "all"
|
|
218
218
|
: "active";
|
|
219
219
|
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
const originChannel =
|
|
221
|
+
queryParams.originChannel !== undefined && queryParams.originChannel !== ""
|
|
222
|
+
? queryParams.originChannel
|
|
223
|
+
: undefined;
|
|
224
|
+
|
|
225
|
+
let rows = listConversations(
|
|
226
|
+
limit,
|
|
227
|
+
conversationType,
|
|
228
|
+
offset,
|
|
229
|
+
archiveStatus,
|
|
230
|
+
originChannel,
|
|
231
|
+
);
|
|
232
|
+
const totalCount = countConversations(
|
|
233
|
+
conversationType,
|
|
234
|
+
archiveStatus,
|
|
235
|
+
originChannel,
|
|
236
|
+
);
|
|
222
237
|
|
|
223
238
|
// On the first page, ensure all pinned conversations are included
|
|
224
239
|
// even if they fall outside the paginated window. Pinned injection is
|
|
225
240
|
// skipped in archived/all views since the Archive page renders archived
|
|
226
|
-
// rows in archive-time order, not pin order.
|
|
241
|
+
// rows in archive-time order, not pin order. Also skipped for
|
|
242
|
+
// channel-scoped queries — those return only items matching the
|
|
243
|
+
// requested origin channel; pinned items render in their own section.
|
|
227
244
|
if (
|
|
228
245
|
offset === 0 &&
|
|
229
246
|
conversationType === "standard" &&
|
|
230
|
-
archiveStatus === "active"
|
|
247
|
+
archiveStatus === "active" &&
|
|
248
|
+
originChannel === undefined
|
|
231
249
|
) {
|
|
232
250
|
const pinned = listPinnedConversations(archiveStatus);
|
|
233
251
|
const seen = new Set(rows.map((c) => c.id));
|
|
@@ -452,6 +470,25 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
452
470
|
'Filter by archive state. Defaults to "active" (non-archived rows only). Pass "archived" to list only archived rows (for the Archive page) or "all" to include both.',
|
|
453
471
|
schema: { type: "string", enum: ["active", "archived", "all"] },
|
|
454
472
|
},
|
|
473
|
+
{
|
|
474
|
+
name: "originChannel",
|
|
475
|
+
type: "string",
|
|
476
|
+
required: false,
|
|
477
|
+
description:
|
|
478
|
+
"Filter by origin channel. When provided, only conversations with this exact origin_channel value are returned. Omit to include all channels.",
|
|
479
|
+
schema: {
|
|
480
|
+
type: "string",
|
|
481
|
+
enum: [
|
|
482
|
+
"slack",
|
|
483
|
+
"telegram",
|
|
484
|
+
"whatsapp",
|
|
485
|
+
"email",
|
|
486
|
+
"a2a",
|
|
487
|
+
"vellum",
|
|
488
|
+
"phone",
|
|
489
|
+
],
|
|
490
|
+
},
|
|
491
|
+
},
|
|
455
492
|
],
|
|
456
493
|
responseBody: listConversationsResponseSchema,
|
|
457
494
|
handler: handleListConversations,
|