@vellumai/assistant 0.8.10 → 0.8.11-staging.1
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/bun.lock +62 -1
- package/docs/workspace-tools.md +196 -0
- package/examples/plugins/echo/README.md +3 -3
- package/knip.json +1 -0
- package/openapi.yaml +460 -128
- package/package.json +2 -1
- package/scripts/build-plugin-api.ts +299 -0
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +7 -0
- package/src/__tests__/agent-loop-compaction-events.test.ts +197 -0
- package/src/__tests__/agent-loop-exit-reason.test.ts +93 -96
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +2 -0
- package/src/__tests__/agent-loop-output-hooks.test.ts +274 -1
- package/src/__tests__/agent-loop-override-profile.test.ts +3 -0
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +4 -0
- package/src/__tests__/agent-loop-thinking.test.ts +4 -0
- package/src/__tests__/agent-loop.test.ts +578 -5
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -1
- package/src/__tests__/approval-cascade.test.ts +1 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
- package/src/__tests__/btw-routes.test.ts +0 -1
- package/src/__tests__/build-persisted-content.test.ts +75 -1
- package/src/__tests__/catalog-install-normalize.test.ts +141 -0
- package/src/__tests__/ces-startup-timeout.test.ts +60 -0
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
- package/src/__tests__/context-overflow-reducer.test.ts +264 -124
- package/src/__tests__/context-window-manager-overflow-rung.test.ts +351 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +13 -5
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +284 -455
- package/src/__tests__/conversation-agent-loop.test.ts +131 -551
- package/src/__tests__/conversation-app-control-instantiation.test.ts +13 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-fork-crud.test.ts +259 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-lifecycle.test.ts +257 -1
- package/src/__tests__/conversation-process-callsite.test.ts +1 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +38 -377
- package/src/__tests__/conversation-queue.test.ts +1 -39
- package/src/__tests__/conversation-runtime-assembly.test.ts +119 -8
- package/src/__tests__/conversation-skill-tools.test.ts +491 -5
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -0
- package/src/__tests__/conversation-speed-override.test.ts +1 -0
- package/src/__tests__/conversation-store.test.ts +74 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +4 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +323 -0
- package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +34 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -0
- package/src/__tests__/corrected-target.test.ts +93 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +3 -5
- package/src/__tests__/credential-execution-tools.test.ts +23 -11
- package/src/__tests__/credential-security-invariants.test.ts +6 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +80 -0
- package/src/__tests__/device-id.test.ts +70 -1
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
- package/src/__tests__/empty-response-hook.test.ts +242 -66
- package/src/__tests__/external-plugin-loader.test.ts +0 -31
- package/src/__tests__/get-skill-detail-audit.test.ts +43 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +91 -0
- package/src/__tests__/history-repair-hook.test.ts +228 -3
- package/src/__tests__/host-app-control-proxy.test.ts +45 -0
- package/src/__tests__/host-browser-proxy.test.ts +254 -9
- package/src/__tests__/identity-routes.test.ts +1 -0
- package/src/__tests__/image-recovery-hook.test.ts +387 -0
- package/src/__tests__/injector-chain.test.ts +5 -4
- package/src/__tests__/injector-v3-suppression.test.ts +373 -47
- package/src/__tests__/intent-routing.test.ts +7 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +117 -15
- package/src/__tests__/notification-decision-strategy.test.ts +3 -3
- package/src/__tests__/oauth-store.test.ts +0 -85
- package/src/__tests__/{context-overflow-policy.test.ts → overflow-policy.test.ts} +1 -1
- package/src/__tests__/parallel-tool.benchmark.test.ts +4 -0
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +29 -9
- package/src/__tests__/persist-unsendable-image.test.ts +4 -4
- package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
- package/src/__tests__/plugin-bootstrap.test.ts +82 -73
- package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
- package/src/__tests__/plugin-types.test.ts +0 -8
- package/src/__tests__/provider-catalog-visibility.test.ts +1 -9
- package/src/__tests__/prune-old-conversations-job.test.ts +99 -0
- package/src/__tests__/registry.test.ts +240 -1
- package/src/__tests__/require-fresh-approval.test.ts +3 -0
- package/src/__tests__/schedule-routes.test.ts +116 -1
- package/src/__tests__/schedule-store.test.ts +28 -0
- package/src/__tests__/schedule-tools.test.ts +94 -1
- package/src/__tests__/server-history-render.test.ts +39 -0
- package/src/__tests__/skill-projection-feature-flag.test.ts +13 -0
- package/src/__tests__/skill-projection.benchmark.test.ts +25 -7
- package/src/__tests__/skills.test.ts +202 -0
- package/src/__tests__/slim-skill-category.test.ts +195 -0
- package/src/__tests__/strip-memory-injections.test.ts +33 -39
- package/src/__tests__/test-support/tool-invocation-seed.ts +79 -0
- package/src/__tests__/title-generate-hook.test.ts +9 -7
- package/src/__tests__/tool-audit-listener.test.ts +264 -1
- package/src/__tests__/tool-error-hook.test.ts +4 -3
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +273 -0
- package/src/__tests__/tool-result-truncate-hook.test.ts +1 -0
- package/src/__tests__/tool-start-timestamp.test.ts +218 -0
- package/src/__tests__/tools-get-route.test.ts +202 -0
- package/src/__tests__/workspace-tool-loader.test.ts +319 -0
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
- package/src/agent/loop.ts +569 -319
- package/src/api/events/tool-result.ts +9 -0
- package/src/api/events/tool-use-start.ts +7 -0
- package/src/api/index.ts +10 -0
- package/src/api/responses/conversation-message.ts +135 -27
- package/src/api/responses/memory-v3-selection-log.ts +4 -4
- package/src/approvals/guardian-request-resolvers.ts +26 -0
- package/src/browser-session/backends/host-bridge.ts +29 -0
- package/src/browser-session/index.ts +1 -0
- package/src/browser-session/types.ts +5 -1
- package/src/cli/commands/__tests__/schedules.test.ts +62 -4
- package/src/cli/commands/__tests__/skills.test.ts +53 -0
- package/src/cli/commands/channel-verification-sessions.ts +6 -6
- package/src/cli/commands/inference-providers.ts +0 -8
- package/src/cli/commands/plugins.ts +2 -2
- package/src/cli/commands/schedules.ts +27 -4
- package/src/cli/commands/skills.ts +187 -146
- package/src/cli/commands/tools.ts +106 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +256 -328
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +6 -2
- package/src/cli/lib/__tests__/plugin-details.test.ts +10 -16
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +2 -2
- package/src/cli/lib/__tests__/search-plugins.test.ts +145 -240
- package/src/cli/lib/install-from-github.ts +187 -117
- package/src/cli/lib/plugin-catalog-cache.ts +9 -9
- package/src/cli/lib/plugin-details.ts +38 -68
- package/src/cli/lib/plugin-marketplace.ts +42 -14
- package/src/cli/lib/search-plugins.ts +29 -129
- package/src/cli/program.ts +2 -0
- package/src/config/bundled-skills/acp/SKILL.md +1 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -0
- package/src/config/bundled-skills/app-control/SKILL.md +1 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +1 -0
- package/src/config/bundled-skills/contacts/SKILL.md +1 -0
- package/src/config/bundled-skills/document-editor/SKILL.md +1 -0
- package/src/config/bundled-skills/followups/SKILL.md +1 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +1 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +1 -0
- package/src/config/bundled-skills/messaging/SKILL.md +1 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -0
- package/src/config/bundled-skills/playbooks/SKILL.md +1 -0
- package/src/config/bundled-skills/schedule/SKILL.md +1 -0
- package/src/config/bundled-skills/schedule/TOOLS.json +11 -3
- package/src/config/bundled-skills/sequences/SKILL.md +1 -0
- package/src/config/bundled-skills/settings/SKILL.md +1 -0
- package/src/config/bundled-skills/skill-management/SKILL.md +101 -1
- package/src/config/bundled-skills/subagent/SKILL.md +1 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +1 -0
- package/src/config/env-registry.ts +23 -0
- package/src/config/feature-flag-registry.json +17 -81
- package/src/config/loader.ts +5 -22
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/__tests__/compaction-logs.test.ts +56 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +0 -1
- package/src/config/schemas/__tests__/memory-v3.test.ts +61 -1
- package/src/config/schemas/compaction-logs.ts +79 -0
- package/src/config/schemas/memory-v2.ts +0 -8
- package/src/config/schemas/memory-v3.ts +104 -33
- package/src/config/seed-inference-profiles.ts +1 -1
- package/src/config/skills.ts +117 -47
- package/src/context/compactor.ts +11 -0
- package/src/context/strip-injections.ts +38 -4
- package/src/credential-execution/feature-gates.ts +0 -21
- package/src/credential-execution/startup-timeout.ts +32 -4
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +18 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +140 -91
- package/src/daemon/conversation-agent-loop.ts +123 -658
- package/src/daemon/conversation-error.ts +6 -33
- package/src/daemon/conversation-lifecycle.ts +1 -1
- package/src/daemon/conversation-runtime-assembly.ts +183 -22
- package/src/daemon/conversation-skill-tools.ts +137 -8
- package/src/daemon/conversation-slash.ts +0 -14
- package/src/daemon/conversation-store.ts +2 -19
- package/src/daemon/conversation-tool-setup.ts +87 -1
- package/src/daemon/conversation.ts +119 -50
- package/src/daemon/external-plugins-bootstrap.ts +36 -95
- package/src/daemon/handlers/config-channels.ts +11 -2
- package/src/daemon/handlers/shared.ts +9 -1
- package/src/daemon/handlers/skills.ts +10 -4
- package/src/daemon/host-app-control-proxy.ts +72 -57
- package/src/daemon/host-browser-proxy.ts +117 -22
- package/src/daemon/lifecycle.ts +34 -5
- package/src/daemon/message-protocol.ts +0 -7
- package/src/daemon/message-types/schedules.ts +1 -0
- package/src/daemon/message-types/skills.ts +17 -0
- package/src/daemon/providers-setup.ts +3 -0
- package/src/daemon/server.ts +3 -3
- package/src/daemon/tool-setup-types.ts +9 -3
- package/src/daemon/trust-context.ts +23 -0
- package/src/daemon/workspace-tools-watcher.ts +324 -0
- package/src/events/tool-audit-listener.ts +78 -16
- package/src/events/tool-metrics-listener.ts +2 -5
- package/src/memory/__tests__/compaction-log-writer-clickhouse.test.ts +227 -0
- package/src/memory/__tests__/conversation-queries.test.ts +176 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +20 -32
- package/src/memory/compaction-log-writer-clickhouse.ts +418 -0
- package/src/memory/conversation-crud.ts +134 -3
- package/src/memory/conversation-queries.ts +64 -7
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.test.ts +130 -1
- package/src/memory/embedding-backend.ts +79 -106
- package/src/memory/embedding-gemini.ts +5 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +12 -0
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +19 -0
- package/src/memory/graph/conversation-graph-memory.ts +36 -25
- package/src/memory/graph/tool-handlers.ts +3 -0
- package/src/memory/job-handlers/cleanup.ts +3 -1
- package/src/memory/jobs-store.ts +0 -28
- package/src/memory/jobs-worker.ts +10 -22
- package/src/memory/memory-marker.ts +29 -0
- package/src/memory/memory-retrospective-startup-cleanup.ts +1 -1
- package/src/memory/migrations/268-add-memory-v3-selections.ts +6 -0
- package/src/memory/migrations/270-schedule-description.ts +36 -0
- package/src/memory/migrations/275-tool-invocations-add-skill-id.test.ts +81 -0
- package/src/memory/migrations/275-tool-invocations-add-skill-id.ts +20 -0
- package/src/memory/migrations/276-tool-invocations-created-at-id-index.test.ts +68 -0
- package/src/memory/migrations/276-tool-invocations-created-at-id-index.ts +20 -0
- package/src/memory/migrations/277-add-memory-v3-ever-injected.ts +29 -0
- package/src/memory/migrations/278-tool-invocations-telemetry-columns.test.ts +96 -0
- package/src/memory/migrations/278-tool-invocations-telemetry-columns.ts +39 -0
- package/src/memory/migrations/279-create-skill-loaded-events.test.ts +84 -0
- package/src/memory/migrations/279-create-skill-loaded-events.ts +26 -0
- package/src/memory/migrations/280-conversations-surfaced-at.test.ts +88 -0
- package/src/memory/migrations/280-conversations-surfaced-at.ts +24 -0
- package/src/memory/migrations/index.ts +10 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/schema/conversations.ts +16 -0
- package/src/memory/schema/infrastructure.ts +26 -0
- package/src/memory/skill-loaded-events-store.test.ts +160 -0
- package/src/memory/skill-loaded-events-store.ts +95 -0
- package/src/memory/tool-executed-events-store.test.ts +219 -0
- package/src/memory/tool-executed-events-store.ts +102 -0
- package/src/memory/tool-usage-store.ts +15 -3
- package/src/memory/v2/__tests__/consolidation-job.test.ts +117 -12
- package/src/memory/v2/__tests__/consolidation-prompt-flag-gating-guard.test.ts +189 -0
- package/src/memory/v2/__tests__/injected-block-slugs.test.ts +90 -0
- package/src/memory/v2/__tests__/page-store.test.ts +33 -0
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +88 -15
- package/src/memory/v2/activation-store.ts +50 -1
- package/src/memory/v2/consolidation-job.ts +113 -29
- package/src/memory/v2/injected-block-slugs.ts +79 -0
- package/src/memory/v2/injection.ts +6 -1
- package/src/memory/v2/prompts/consolidation.ts +414 -13
- package/src/memory/v2/router.ts +2 -28
- package/src/memory/v2/static-context.ts +1 -1
- package/src/memory/v2/types.ts +16 -0
- package/src/notifications/__tests__/copy-composer.test.ts +244 -0
- package/src/notifications/access-request-copy.ts +298 -0
- package/src/notifications/adapters/slack.ts +3 -3
- package/src/notifications/adapters/telegram.ts +2 -1
- package/src/notifications/copy-composer.ts +49 -267
- package/src/notifications/decision-engine.ts +16 -35
- package/src/notifications/home-feed-side-effect.ts +1 -6
- package/src/oauth/oauth-store.ts +0 -9
- package/src/permissions/checker.test.ts +83 -1
- package/src/permissions/checker.ts +25 -2
- package/src/permissions/gateway-threshold-reader.test.ts +182 -0
- package/src/permissions/gateway-threshold-reader.ts +80 -0
- package/src/platform/client.ts +1 -3
- package/src/platform/feature-gate.ts +3 -12
- package/src/plugin-api/constants.ts +4 -2
- package/src/plugin-api/index.ts +63 -11
- package/src/plugin-api/types.ts +236 -71
- package/src/plugins/defaults/compaction/compact.ts +66 -2
- package/src/plugins/defaults/compaction/context-overflow-reducer.ts +240 -32
- package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
- package/src/{daemon/context-overflow-policy.ts → plugins/defaults/compaction/overflow-policy.ts} +1 -1
- package/src/plugins/defaults/compaction/window-manager.ts +303 -1
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +173 -0
- package/src/plugins/defaults/empty-response/hooks/stop.ts +11 -115
- package/src/plugins/defaults/empty-response/nudge-state-store.ts +46 -0
- package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +50 -0
- package/src/plugins/defaults/history-repair/hooks/stop.ts +22 -0
- package/src/plugins/defaults/history-repair/repair-state-store.ts +51 -0
- package/src/plugins/defaults/history-repair/terminal.ts +39 -2
- package/src/plugins/defaults/image-recovery/detect.ts +25 -0
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +73 -0
- package/src/plugins/defaults/image-recovery/hooks/stop.ts +22 -0
- package/src/plugins/defaults/image-recovery/image-recovery-state-store.ts +48 -0
- package/src/plugins/defaults/image-recovery/package.json +14 -0
- package/src/{daemon/persist-unsendable-image.ts → plugins/defaults/image-recovery/recover.ts} +67 -14
- package/src/plugins/defaults/index.ts +71 -5
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +76 -112
- package/src/plugins/defaults/memory-retrieval/hooks/{user-prompt-submit-temp.ts → user-prompt-submit.ts} +83 -74
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +14 -8
- package/src/plugins/defaults/memory-retrieval/injectors.ts +2 -18
- package/src/plugins/defaults/memory-retrieval/package.json +14 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1157 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +683 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +161 -140
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +160 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +335 -316
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +145 -53
- package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +38 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +18 -8
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +112 -71
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +192 -51
- package/src/plugins/defaults/memory-v3-shadow/__tests__/types.test.ts +4 -16
- package/src/plugins/defaults/memory-v3-shadow/card.test.ts +173 -0
- package/src/plugins/defaults/memory-v3-shadow/card.ts +116 -0
- package/src/plugins/defaults/memory-v3-shadow/core-set.test.ts +104 -0
- package/src/plugins/defaults/memory-v3-shadow/core-set.ts +59 -0
- package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.test.ts +305 -0
- package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.ts +278 -0
- package/src/plugins/defaults/memory-v3-shadow/hot-set.test.ts +138 -0
- package/src/plugins/defaults/memory-v3-shadow/hot-set.ts +85 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +331 -24
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +119 -13
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +169 -114
- package/src/plugins/defaults/memory-v3-shadow/page-content.ts +47 -16
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +144 -66
- package/src/plugins/defaults/memory-v3-shadow/prune.test.ts +758 -0
- package/src/plugins/defaults/memory-v3-shadow/prune.ts +471 -0
- package/src/plugins/defaults/memory-v3-shadow/render-injection.ts +68 -16
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +19 -12
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +96 -43
- package/src/plugins/defaults/memory-v3-shadow/types.ts +34 -17
- package/src/plugins/defaults/title-generate/hooks/stop.ts +9 -11
- package/src/plugins/pipeline.ts +8 -5
- package/src/plugins/types.ts +5 -51
- package/src/providers/cache-control.ts +26 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +1 -2
- package/src/providers/model-catalog.ts +13 -1
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +147 -0
- package/src/providers/openai/chat-completions-provider.ts +46 -0
- package/src/providers/openai/responses-provider.ts +45 -0
- package/src/providers/registry.ts +0 -8
- package/src/runtime/__tests__/agent-wake.test.ts +0 -1
- package/src/runtime/agent-wake.ts +13 -0
- package/src/runtime/routes/__tests__/acp-routes.test.ts +151 -0
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +12 -50
- package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +322 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +0 -62
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +31 -11
- package/src/runtime/routes/acp-routes.test.ts +106 -0
- package/src/runtime/routes/acp-routes.ts +248 -2
- package/src/runtime/routes/browser-tabs-routes.ts +1 -1
- package/src/runtime/routes/channel-verification-routes.ts +14 -5
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +0 -14
- package/src/runtime/routes/consolidation-routes.ts +6 -82
- package/src/runtime/routes/conversation-list-routes.ts +6 -0
- package/src/runtime/routes/conversation-management-routes.ts +71 -0
- package/src/runtime/routes/identity-routes.ts +8 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
- package/src/runtime/routes/inference-provider-connection-routes.ts +0 -45
- package/src/runtime/routes/plugins-routes.ts +34 -45
- package/src/runtime/routes/schedule-routes.ts +43 -5
- package/src/runtime/routes/settings-routes.ts +140 -15
- package/src/runtime/routes/skills-routes.ts +18 -6
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +140 -0
- package/src/runtime/services/conversation-serializer.ts +38 -1
- package/src/runtime/verification-outbound-actions.ts +147 -2
- package/src/runtime/verification-templates.ts +29 -3
- package/src/schedule/schedule-store.ts +19 -0
- package/src/skills/catalog-install.ts +77 -13
- package/src/tasks/task-scheduler.ts +1 -0
- package/src/telemetry/types.ts +66 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +542 -13
- package/src/telemetry/usage-telemetry-reporter.ts +213 -20
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +49 -2
- package/src/tools/browser/__tests__/browser-status.test.ts +29 -5
- package/src/tools/browser/browser-execution.ts +27 -9
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +380 -4
- package/src/tools/browser/cdp-client/__tests__/host-bridge-cdp-client.test.ts +107 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +6 -1
- package/src/tools/browser/cdp-client/factory.ts +217 -17
- package/src/tools/browser/cdp-client/host-bridge-cdp-client.ts +67 -0
- package/src/tools/browser/cdp-client/types.ts +22 -2
- package/src/tools/credential-execution/make-authenticated-request.ts +2 -1
- package/src/tools/credential-execution/manage-secure-command-tool.ts +169 -164
- package/src/tools/credential-execution/run-authenticated-command.ts +2 -1
- package/src/tools/executor.ts +39 -7
- package/src/tools/registry.ts +387 -5
- package/src/tools/schedule/create.ts +16 -0
- package/src/tools/schedule/list.ts +12 -4
- package/src/tools/schedule/update.ts +12 -0
- package/src/tools/skills/load.ts +11 -6
- package/src/tools/terminal/safe-env.ts +2 -0
- package/src/tools/types.ts +65 -9
- package/src/tools/workspace-tools/loader.ts +673 -0
- package/src/usage/attribution.ts +28 -0
- package/src/util/device-id.ts +17 -3
- package/src/util/platform.ts +16 -0
- package/tsconfig.plugin-api.json +13 -0
- package/src/__tests__/plugin-external-api.test.ts +0 -68
- package/src/__tests__/plugin-skill-contribution.test.ts +0 -355
- package/src/daemon/message-types/browser.ts +0 -10
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/eval-turns.json +0 -36
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/live-turns.json +0 -37
- package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-eviction.test.ts +0 -106
- package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-skeleton.test.ts +0 -44
- package/src/plugins/defaults/memory-v3-shadow/working-set.ts +0 -91
- package/src/plugins/external-api.ts +0 -114
- package/src/plugins/plugin-skill-contributions.ts +0 -292
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vellumai/assistant",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.11-staging.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
"@resvg/resvg-js-darwin-x64": "2.6.2"
|
|
97
97
|
},
|
|
98
98
|
"devDependencies": {
|
|
99
|
+
"@microsoft/api-extractor": "7.58.8",
|
|
99
100
|
"@types/archiver": "7.0.0",
|
|
100
101
|
"@types/bun": "1.3.10",
|
|
101
102
|
"@types/node": "25.5.0",
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Builds the publishable `@vellumai/plugin-api` npm package: a types-first
|
|
4
|
+
* package whose public `index.d.ts` is a single self-contained rollup of the
|
|
5
|
+
* plugin authoring surface (`src/plugin-api/index.ts`), with the workspace
|
|
6
|
+
* `@vellumai/*` contract types inlined and `zod` as the only external dep.
|
|
7
|
+
*
|
|
8
|
+
* Why a rollup: the authoring surface re-exports types from internal workspace
|
|
9
|
+
* packages that ship `.ts` source (not published to npm), so a naive emit
|
|
10
|
+
* leaves dangling `@vellumai/*` imports that no external consumer can resolve.
|
|
11
|
+
* Microsoft API Extractor inlines exactly the reachable declarations into one
|
|
12
|
+
* file, so a standalone plugin repo type-checks against the real contract
|
|
13
|
+
* without vendoring a hand-maintained shim.
|
|
14
|
+
*
|
|
15
|
+
* Why a trivial runtime: inside a live assistant workspace the host
|
|
16
|
+
* materializes a `node_modules/@vellumai/plugin-api` shim that re-binds the
|
|
17
|
+
* already-loaded namespace off `globalThis` (see `ensure-plugin-api-shim.ts`).
|
|
18
|
+
* The published `index.js` is the same re-bind so the npm package behaves
|
|
19
|
+
* identically when present, and degrades to `undefined` exports when imported
|
|
20
|
+
* outside a host (it is a dev-time authoring contract, not a runtime library).
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* cd assistant && bun run scripts/build-plugin-api.ts --version 1.2.3
|
|
24
|
+
*
|
|
25
|
+
* Output: a ready-to-pack package directory (default
|
|
26
|
+
* `.plugin-api-build/package`) containing `package.json`, `index.d.ts`, and
|
|
27
|
+
* `index.js`. The release workflow runs `npm pack` / `npm publish` against it.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { execFileSync } from "node:child_process";
|
|
31
|
+
import {
|
|
32
|
+
cpSync,
|
|
33
|
+
existsSync,
|
|
34
|
+
mkdirSync,
|
|
35
|
+
readdirSync,
|
|
36
|
+
readFileSync,
|
|
37
|
+
rmSync,
|
|
38
|
+
symlinkSync,
|
|
39
|
+
writeFileSync,
|
|
40
|
+
} from "node:fs";
|
|
41
|
+
import { join, resolve } from "node:path";
|
|
42
|
+
|
|
43
|
+
import {
|
|
44
|
+
PLUGIN_API_EXPORTS,
|
|
45
|
+
PLUGIN_API_REGISTRY_KEY,
|
|
46
|
+
} from "../src/embedded/plugin-api.js";
|
|
47
|
+
|
|
48
|
+
const ASSISTANT_DIR = resolve(import.meta.dir, "..");
|
|
49
|
+
const NODE_MODULES = join(ASSISTANT_DIR, "node_modules");
|
|
50
|
+
const TSC = join(NODE_MODULES, ".bin", "tsc");
|
|
51
|
+
const API_EXTRACTOR = join(NODE_MODULES, ".bin", "api-extractor");
|
|
52
|
+
|
|
53
|
+
/** The published types reference `z.*`, so the package declares the same `zod`
|
|
54
|
+
* version the assistant resolved — read from the installed package so it can
|
|
55
|
+
* never drift from the contract the rollup was generated against. */
|
|
56
|
+
const ZOD_VERSION = (
|
|
57
|
+
JSON.parse(
|
|
58
|
+
readFileSync(join(NODE_MODULES, "zod", "package.json"), "utf8"),
|
|
59
|
+
) as { version: string }
|
|
60
|
+
).version;
|
|
61
|
+
|
|
62
|
+
interface Args {
|
|
63
|
+
version: string;
|
|
64
|
+
buildDir: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function parseArgs(argv: string[]): Args {
|
|
68
|
+
let version = "";
|
|
69
|
+
let buildDir = join(ASSISTANT_DIR, ".plugin-api-build");
|
|
70
|
+
for (let i = 0; i < argv.length; i++) {
|
|
71
|
+
const arg = argv[i];
|
|
72
|
+
if (arg === "--version") version = argv[++i] ?? "";
|
|
73
|
+
else if (arg === "--out") buildDir = resolve(argv[++i] ?? "");
|
|
74
|
+
}
|
|
75
|
+
if (!version) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
"Missing required --version <semver> (the release version to stamp).",
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
return { version, buildDir };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function run(bin: string, args: string[], cwd: string): void {
|
|
84
|
+
execFileSync(bin, args, { cwd, stdio: "inherit" });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Emit `.d.ts` for one workspace contract package into `dest`, resolving its
|
|
88
|
+
* dependencies through `assistant/node_modules` (the layout CI produces after
|
|
89
|
+
* `bun install`). Returns true if a usable `index.d.ts` was produced. */
|
|
90
|
+
function emitContract(pkgDir: string, dest: string): boolean {
|
|
91
|
+
try {
|
|
92
|
+
execFileSync(
|
|
93
|
+
TSC,
|
|
94
|
+
[
|
|
95
|
+
"--emitDeclarationOnly",
|
|
96
|
+
"--declaration",
|
|
97
|
+
"--declarationMap",
|
|
98
|
+
"false",
|
|
99
|
+
"--sourceMap",
|
|
100
|
+
"false",
|
|
101
|
+
"--rootDir",
|
|
102
|
+
"src",
|
|
103
|
+
"--outDir",
|
|
104
|
+
dest,
|
|
105
|
+
],
|
|
106
|
+
{ cwd: pkgDir, stdio: "pipe" },
|
|
107
|
+
);
|
|
108
|
+
} catch {
|
|
109
|
+
// Best-effort: a package that fails to emit standalone is only a problem
|
|
110
|
+
// if the public surface actually reaches it, in which case API Extractor
|
|
111
|
+
// fails loudly below with the offending unresolved import.
|
|
112
|
+
}
|
|
113
|
+
return existsSync(join(dest, "index.d.ts"));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
interface ContractPackageJson {
|
|
117
|
+
name: string;
|
|
118
|
+
version?: string;
|
|
119
|
+
type?: string;
|
|
120
|
+
exports?: Record<string, unknown>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Write a `package.json` for an emitted contract whose `types`/`exports`
|
|
124
|
+
* resolve to the `.d.ts` files (not the unpublished `src/*.ts`). API
|
|
125
|
+
* Extractor resolves a `bundledPackage`'s entry through its real
|
|
126
|
+
* `package.json`, so without this it would follow `exports` back to source
|
|
127
|
+
* and reject the `.ts`. Subpath keys map to same-named `.d.ts` siblings. */
|
|
128
|
+
function writeContractManifest(srcManifestPath: string, destDir: string): void {
|
|
129
|
+
const orig = JSON.parse(
|
|
130
|
+
readFileSync(srcManifestPath, "utf8"),
|
|
131
|
+
) as ContractPackageJson;
|
|
132
|
+
const origExports = orig.exports ?? { ".": "./src/index.ts" };
|
|
133
|
+
const exports: Record<string, string> = {};
|
|
134
|
+
for (const key of Object.keys(origExports)) {
|
|
135
|
+
exports[key] = key === "." ? "./index.d.ts" : `${key}.d.ts`;
|
|
136
|
+
}
|
|
137
|
+
writeFileSync(
|
|
138
|
+
join(destDir, "package.json"),
|
|
139
|
+
`${JSON.stringify(
|
|
140
|
+
{
|
|
141
|
+
name: orig.name,
|
|
142
|
+
version: orig.version ?? "0.0.0",
|
|
143
|
+
type: orig.type ?? "module",
|
|
144
|
+
types: "./index.d.ts",
|
|
145
|
+
exports,
|
|
146
|
+
},
|
|
147
|
+
null,
|
|
148
|
+
2,
|
|
149
|
+
)}\n`,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function buildRuntimeShim(): string {
|
|
154
|
+
const key = JSON.stringify(PLUGIN_API_REGISTRY_KEY.description ?? "");
|
|
155
|
+
const lines = [
|
|
156
|
+
"// Generated by scripts/build-plugin-api.ts — do not edit by hand.",
|
|
157
|
+
`const api = globalThis[Symbol.for(${key})] ?? {};`,
|
|
158
|
+
...PLUGIN_API_EXPORTS.map((name) => `export const ${name} = api.${name};`),
|
|
159
|
+
];
|
|
160
|
+
return `${lines.join("\n")}\n`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function main(): void {
|
|
164
|
+
const { version, buildDir } = parseArgs(Bun.argv.slice(2));
|
|
165
|
+
|
|
166
|
+
const outDir = join(buildDir, "out");
|
|
167
|
+
const pkgDir = join(buildDir, "package");
|
|
168
|
+
const nodeModulesDir = join(buildDir, "node_modules");
|
|
169
|
+
const vellumOverlay = join(nodeModulesDir, "@vellumai");
|
|
170
|
+
|
|
171
|
+
rmSync(buildDir, { recursive: true, force: true });
|
|
172
|
+
mkdirSync(vellumOverlay, { recursive: true });
|
|
173
|
+
|
|
174
|
+
// 1. Emit declarations for the authoring surface and everything it reaches.
|
|
175
|
+
console.log("[plugin-api] emitting authoring-surface declarations…");
|
|
176
|
+
run(TSC, ["-p", "tsconfig.plugin-api.json"], ASSISTANT_DIR);
|
|
177
|
+
|
|
178
|
+
// 2. Emit each `@vellumai/*` contract the surface reaches into an overlay
|
|
179
|
+
// `node_modules`, each with a `package.json` pointing at its `.d.ts`, so
|
|
180
|
+
// API Extractor inlines them (as `bundledPackages`) instead of leaving
|
|
181
|
+
// dangling `@vellumai/*` imports an external consumer can't resolve.
|
|
182
|
+
console.log("[plugin-api] emitting workspace contract declarations…");
|
|
183
|
+
const vellumDir = join(NODE_MODULES, "@vellumai");
|
|
184
|
+
const bundled: string[] = [];
|
|
185
|
+
for (const name of readdirSync(vellumDir)) {
|
|
186
|
+
const dir = join(vellumDir, name);
|
|
187
|
+
if (!existsSync(join(dir, "tsconfig.json"))) continue;
|
|
188
|
+
if (!existsSync(join(dir, "src"))) continue;
|
|
189
|
+
const dest = join(vellumOverlay, name);
|
|
190
|
+
if (emitContract(dir, dest)) {
|
|
191
|
+
writeContractManifest(join(dir, "package.json"), dest);
|
|
192
|
+
bundled.push(`@vellumai/${name}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
bundled.sort();
|
|
196
|
+
|
|
197
|
+
// `zod` is the sole external dependency of the rolled-up surface; symlink it
|
|
198
|
+
// so the compiler resolves it while API Extractor leaves it as an import.
|
|
199
|
+
symlinkSync(join(NODE_MODULES, "zod"), join(nodeModulesDir, "zod"), "dir");
|
|
200
|
+
|
|
201
|
+
// 3. Generate the API Extractor compiler tsconfig + config.
|
|
202
|
+
writeFileSync(
|
|
203
|
+
join(buildDir, "tsconfig.dts.json"),
|
|
204
|
+
`${JSON.stringify(
|
|
205
|
+
{
|
|
206
|
+
compilerOptions: {
|
|
207
|
+
target: "ES2022",
|
|
208
|
+
module: "NodeNext",
|
|
209
|
+
moduleResolution: "NodeNext",
|
|
210
|
+
skipLibCheck: true,
|
|
211
|
+
types: [],
|
|
212
|
+
},
|
|
213
|
+
include: ["dts/**/*.d.ts"],
|
|
214
|
+
},
|
|
215
|
+
null,
|
|
216
|
+
2,
|
|
217
|
+
)}\n`,
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
writeFileSync(
|
|
221
|
+
join(buildDir, "api-extractor.json"),
|
|
222
|
+
`${JSON.stringify(
|
|
223
|
+
{
|
|
224
|
+
$schema:
|
|
225
|
+
"https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
|
226
|
+
projectFolder: ".",
|
|
227
|
+
mainEntryPointFilePath: "<projectFolder>/dts/plugin-api/index.d.ts",
|
|
228
|
+
bundledPackages: bundled,
|
|
229
|
+
compiler: { tsconfigFilePath: "<projectFolder>/tsconfig.dts.json" },
|
|
230
|
+
dtsRollup: {
|
|
231
|
+
enabled: true,
|
|
232
|
+
untrimmedFilePath: "<projectFolder>/out/index.d.ts",
|
|
233
|
+
},
|
|
234
|
+
apiReport: { enabled: false },
|
|
235
|
+
docModel: { enabled: false },
|
|
236
|
+
tsdocMetadata: { enabled: false },
|
|
237
|
+
messages: {
|
|
238
|
+
compilerMessageReporting: { default: { logLevel: "none" } },
|
|
239
|
+
extractorMessageReporting: { default: { logLevel: "none" } },
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
null,
|
|
243
|
+
2,
|
|
244
|
+
)}\n`,
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
// 4. Roll up the reachable declarations into a single self-contained file.
|
|
248
|
+
console.log("[plugin-api] rolling up declarations with API Extractor…");
|
|
249
|
+
run(API_EXTRACTOR, ["run", "--local", "-c", "api-extractor.json"], buildDir);
|
|
250
|
+
|
|
251
|
+
const rollup = join(outDir, "index.d.ts");
|
|
252
|
+
if (!existsSync(rollup)) {
|
|
253
|
+
throw new Error(`API Extractor did not produce ${rollup}`);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// 5. Assemble the publishable package directory.
|
|
257
|
+
mkdirSync(pkgDir, { recursive: true });
|
|
258
|
+
cpSync(rollup, join(pkgDir, "index.d.ts"));
|
|
259
|
+
writeFileSync(join(pkgDir, "index.js"), buildRuntimeShim());
|
|
260
|
+
writeFileSync(
|
|
261
|
+
join(pkgDir, "package.json"),
|
|
262
|
+
`${JSON.stringify(
|
|
263
|
+
{
|
|
264
|
+
name: "@vellumai/plugin-api",
|
|
265
|
+
version,
|
|
266
|
+
description:
|
|
267
|
+
"Public TypeScript authoring contract for Vellum assistant plugins.",
|
|
268
|
+
license: "MIT",
|
|
269
|
+
type: "module",
|
|
270
|
+
main: "./index.js",
|
|
271
|
+
types: "./index.d.ts",
|
|
272
|
+
exports: {
|
|
273
|
+
".": {
|
|
274
|
+
types: "./index.d.ts",
|
|
275
|
+
import: "./index.js",
|
|
276
|
+
default: "./index.js",
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
files: ["index.js", "index.d.ts"],
|
|
280
|
+
dependencies: { zod: ZOD_VERSION },
|
|
281
|
+
publishConfig: { access: "public" },
|
|
282
|
+
repository: {
|
|
283
|
+
type: "git",
|
|
284
|
+
url: "git+https://github.com/vellum-ai/vellum-assistant.git",
|
|
285
|
+
directory: "assistant/src/plugin-api",
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
null,
|
|
289
|
+
2,
|
|
290
|
+
)}\n`,
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
console.log(
|
|
294
|
+
`[plugin-api] built @vellumai/plugin-api@${version} → ${pkgDir}\n` +
|
|
295
|
+
`[plugin-api] inlined contracts: ${bundled.join(", ")}`,
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
main();
|
|
@@ -108,6 +108,7 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
await loop.run({
|
|
111
|
+
requestId: "test-request",
|
|
111
112
|
messages: [userMessage],
|
|
112
113
|
onEvent: () => {},
|
|
113
114
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
@@ -139,6 +140,7 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
139
140
|
});
|
|
140
141
|
|
|
141
142
|
await loop.run({
|
|
143
|
+
requestId: "test-request",
|
|
142
144
|
messages: [userMessage],
|
|
143
145
|
onEvent: () => {},
|
|
144
146
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
@@ -173,6 +175,7 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
173
175
|
});
|
|
174
176
|
|
|
175
177
|
await loop.run({
|
|
178
|
+
requestId: "test-request",
|
|
176
179
|
messages: [userMessage],
|
|
177
180
|
onEvent: () => {},
|
|
178
181
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
@@ -212,6 +215,7 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
212
215
|
});
|
|
213
216
|
|
|
214
217
|
await loop.run({
|
|
218
|
+
requestId: "test-request",
|
|
215
219
|
messages: [userMessage],
|
|
216
220
|
onEvent: () => {},
|
|
217
221
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
@@ -242,6 +246,7 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
242
246
|
});
|
|
243
247
|
|
|
244
248
|
await loop.run({
|
|
249
|
+
requestId: "test-request",
|
|
245
250
|
messages: [userMessage],
|
|
246
251
|
onEvent: () => {},
|
|
247
252
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
@@ -280,6 +285,7 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
280
285
|
});
|
|
281
286
|
|
|
282
287
|
await loop.run({
|
|
288
|
+
requestId: "test-request",
|
|
283
289
|
messages: [userMessage],
|
|
284
290
|
onEvent: () => {},
|
|
285
291
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
@@ -318,6 +324,7 @@ describe("AgentLoop — call-site precedence", () => {
|
|
|
318
324
|
});
|
|
319
325
|
|
|
320
326
|
await loop.run({
|
|
327
|
+
requestId: "test-request",
|
|
321
328
|
messages: [userMessage],
|
|
322
329
|
onEvent: () => {},
|
|
323
330
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the loop's compaction start/end event pair.
|
|
3
|
+
*
|
|
4
|
+
* The compaction pipeline between `context_compacting` (start) and
|
|
5
|
+
* `compaction_completed` (end) is plugin-owned, so consumers reconstruct a
|
|
6
|
+
* compaction attempt purely from the pair — correlated by `compactionId`.
|
|
7
|
+
* These tests pin the pairing contract: shared id, trigger, timestamps, and
|
|
8
|
+
* pre-compaction state on the start event.
|
|
9
|
+
*/
|
|
10
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
11
|
+
|
|
12
|
+
import type { PostCompactContext } from "@vellumai/plugin-api";
|
|
13
|
+
|
|
14
|
+
import type { AgentEvent } from "../agent/loop.js";
|
|
15
|
+
import { AgentLoop } from "../agent/loop.js";
|
|
16
|
+
import type { ContextWindowConfig } from "../config/types.js";
|
|
17
|
+
import type { TrustContext } from "../daemon/trust-context.js";
|
|
18
|
+
import { HOOKS } from "../plugin-api/constants.js";
|
|
19
|
+
import {
|
|
20
|
+
createContextWindowManager,
|
|
21
|
+
disposeContextWindowManager,
|
|
22
|
+
getContextWindowManager,
|
|
23
|
+
} from "../plugins/defaults/compaction/manager-store.js";
|
|
24
|
+
import {
|
|
25
|
+
registerPlugin,
|
|
26
|
+
resetPluginRegistryForTests,
|
|
27
|
+
} from "../plugins/registry.js";
|
|
28
|
+
import type {
|
|
29
|
+
Message,
|
|
30
|
+
Provider,
|
|
31
|
+
ProviderResponse,
|
|
32
|
+
SendMessageOptions,
|
|
33
|
+
ToolDefinition,
|
|
34
|
+
} from "../providers/types.js";
|
|
35
|
+
|
|
36
|
+
// Identity post-compact hook: keeps the history the loop handed in, standing
|
|
37
|
+
// in for the daemon-level re-injector these unit tests do not run.
|
|
38
|
+
const testPostCompactPlugin = {
|
|
39
|
+
manifest: { name: "test-post-compact", version: "0.0.0" },
|
|
40
|
+
hooks: {
|
|
41
|
+
[HOOKS.POST_COMPACT]: async (
|
|
42
|
+
_input: PostCompactContext,
|
|
43
|
+
): Promise<void> => {},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
function createMockProvider(responses: ProviderResponse[]): {
|
|
48
|
+
provider: Provider;
|
|
49
|
+
} {
|
|
50
|
+
let callIndex = 0;
|
|
51
|
+
const provider: Provider = {
|
|
52
|
+
name: "mock",
|
|
53
|
+
async sendMessage(
|
|
54
|
+
_messages: Message[],
|
|
55
|
+
_options?: SendMessageOptions,
|
|
56
|
+
): Promise<ProviderResponse> {
|
|
57
|
+
const response = responses[callIndex] ?? responses[responses.length - 1];
|
|
58
|
+
callIndex++;
|
|
59
|
+
return response;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
return { provider };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function textResponse(text: string): ProviderResponse {
|
|
66
|
+
return {
|
|
67
|
+
content: [{ type: "text", text }],
|
|
68
|
+
model: "mock-model",
|
|
69
|
+
usage: { inputTokens: 10, outputTokens: 5 },
|
|
70
|
+
stopReason: "end_turn",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function toolUseResponse(
|
|
75
|
+
id: string,
|
|
76
|
+
name: string,
|
|
77
|
+
input: Record<string, unknown>,
|
|
78
|
+
): ProviderResponse {
|
|
79
|
+
return {
|
|
80
|
+
content: [{ type: "tool_use", id, name, input }],
|
|
81
|
+
model: "mock-model",
|
|
82
|
+
usage: { inputTokens: 10, outputTokens: 5 },
|
|
83
|
+
stopReason: "tool_use",
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const dummyTools: ToolDefinition[] = [
|
|
88
|
+
{
|
|
89
|
+
name: "read_file",
|
|
90
|
+
description: "Read a file",
|
|
91
|
+
input_schema: { type: "object", properties: { path: { type: "string" } } },
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
const userMessage: Message = {
|
|
96
|
+
role: "user",
|
|
97
|
+
content: [{ type: "text", text: "Hello" }],
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
function fakeCompaction(
|
|
101
|
+
conversationId: string,
|
|
102
|
+
result: { compacted: boolean; exhausted: boolean },
|
|
103
|
+
): { trust: TrustContext } {
|
|
104
|
+
createContextWindowManager({
|
|
105
|
+
provider: { name: "mock-provider" } as unknown as Provider,
|
|
106
|
+
systemPrompt: "system",
|
|
107
|
+
config: {} as unknown as ContextWindowConfig,
|
|
108
|
+
conversationId,
|
|
109
|
+
});
|
|
110
|
+
const manager = getContextWindowManager(conversationId);
|
|
111
|
+
if (manager) {
|
|
112
|
+
manager.maybeCompact = (async () =>
|
|
113
|
+
result) as unknown as typeof manager.maybeCompact;
|
|
114
|
+
}
|
|
115
|
+
return { trust: { sourceChannel: "vellum", trustClass: "unknown" } };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
type StartEvent = Extract<AgentEvent, { type: "context_compacting" }>;
|
|
119
|
+
type EndEvent = Extract<AgentEvent, { type: "compaction_completed" }>;
|
|
120
|
+
|
|
121
|
+
describe("AgentLoop compaction start/end event pair", () => {
|
|
122
|
+
beforeEach(() => {
|
|
123
|
+
resetPluginRegistryForTests();
|
|
124
|
+
registerPlugin(testPostCompactPlugin);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
afterEach(() => {
|
|
128
|
+
disposeContextWindowManager("test-conversation");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("budget-gate compaction emits a correlated start/end pair with full data", async () => {
|
|
132
|
+
const { provider } = createMockProvider([
|
|
133
|
+
toolUseResponse("t1", "read_file", { path: "/a.txt" }),
|
|
134
|
+
textResponse("done after compaction"),
|
|
135
|
+
]);
|
|
136
|
+
const toolExecutor = async () => ({ content: "ok", isError: false });
|
|
137
|
+
const loop = new AgentLoop({
|
|
138
|
+
provider,
|
|
139
|
+
systemPrompt: "system",
|
|
140
|
+
conversationId: "test-conversation",
|
|
141
|
+
tools: dummyTools,
|
|
142
|
+
toolExecutor,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const events: AgentEvent[] = [];
|
|
146
|
+
const before = Date.now();
|
|
147
|
+
await loop.run({
|
|
148
|
+
requestId: "test-request",
|
|
149
|
+
messages: [userMessage],
|
|
150
|
+
onEvent: (event) => {
|
|
151
|
+
events.push(event);
|
|
152
|
+
},
|
|
153
|
+
resolveContextWindow: () => ({
|
|
154
|
+
maxInputTokens: 10,
|
|
155
|
+
overflowRecovery: { enabled: true, safetyMarginRatio: 0 },
|
|
156
|
+
}),
|
|
157
|
+
compactInPlace: true,
|
|
158
|
+
...fakeCompaction("test-conversation", {
|
|
159
|
+
compacted: true,
|
|
160
|
+
exhausted: false,
|
|
161
|
+
}),
|
|
162
|
+
});
|
|
163
|
+
const after = Date.now();
|
|
164
|
+
|
|
165
|
+
const start = events.find(
|
|
166
|
+
(e): e is StartEvent => e.type === "context_compacting",
|
|
167
|
+
);
|
|
168
|
+
const end = events.find(
|
|
169
|
+
(e): e is EndEvent => e.type === "compaction_completed",
|
|
170
|
+
);
|
|
171
|
+
expect(start).toBeDefined();
|
|
172
|
+
expect(end).toBeDefined();
|
|
173
|
+
|
|
174
|
+
// Pair correlation: shared id, trigger, and start timestamp.
|
|
175
|
+
expect(start!.compactionId).toBe(end!.compactionId);
|
|
176
|
+
expect(start!.compactionId.length).toBeGreaterThan(0);
|
|
177
|
+
expect(start!.requestId).toBe("test-request");
|
|
178
|
+
expect(end!.requestId).toBe("test-request");
|
|
179
|
+
expect(start!.trigger).toBe("budget");
|
|
180
|
+
expect(end!.trigger).toBe("budget");
|
|
181
|
+
expect(end!.startedAt).toBe(start!.startedAt);
|
|
182
|
+
|
|
183
|
+
// Timestamps bound the attempt within the run.
|
|
184
|
+
expect(start!.startedAt).toBeGreaterThanOrEqual(before);
|
|
185
|
+
expect(end!.finishedAt).toBeGreaterThanOrEqual(end!.startedAt);
|
|
186
|
+
expect(end!.finishedAt).toBeLessThanOrEqual(after);
|
|
187
|
+
|
|
188
|
+
// Start carries the pre-compaction history; end carries the result and
|
|
189
|
+
// the stripped history the summary was built from.
|
|
190
|
+
expect(start!.messages.length).toBeGreaterThan(0);
|
|
191
|
+
expect(end!.result.compacted).toBe(true);
|
|
192
|
+
expect(end!.messages.length).toBeGreaterThan(0);
|
|
193
|
+
|
|
194
|
+
// Start precedes end in the event stream.
|
|
195
|
+
expect(events.indexOf(start!)).toBeLessThan(events.indexOf(end!));
|
|
196
|
+
});
|
|
197
|
+
});
|