@vellumai/assistant 0.6.5 → 0.6.6
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 +9 -1
- package/ARCHITECTURE.md +15 -17
- package/Dockerfile +6 -4
- package/__tests__/permissions/gateway-threshold-reader.test.ts +283 -0
- package/docs/architecture/integrations.md +32 -39
- package/docs/architecture/memory.md +25 -30
- package/docs/architecture/security.md +7 -6
- package/docs/browser-use-architecture-phase2.md +63 -20
- package/docs/plugins.md +761 -0
- package/examples/plugins/echo/README.md +132 -0
- package/examples/plugins/echo/package.json +17 -0
- package/examples/plugins/echo/register.ts +187 -0
- package/node_modules/@vellumai/egress-proxy/src/types.ts +19 -0
- package/openapi.yaml +212 -68
- package/package.json +1 -1
- package/src/__tests__/app-compiler.test.ts +57 -0
- package/src/__tests__/approval-cascade.test.ts +7 -2
- package/src/__tests__/auto-analysis-end-to-end.test.ts +1 -0
- package/src/__tests__/avatar-generator.test.ts +4 -2
- package/src/__tests__/bundled-asset.test.ts +6 -6
- package/src/__tests__/catalog-cache.test.ts +69 -0
- package/src/__tests__/checker.test.ts +459 -171
- package/src/__tests__/circuit-breaker-pipeline.test.ts +406 -0
- package/src/__tests__/compaction-events.test.ts +501 -0
- package/src/__tests__/compaction-pipeline.test.ts +210 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +181 -0
- package/src/__tests__/compaction-timeout-recovery.test.ts +262 -0
- package/src/__tests__/config-model-image-provider.test.ts +110 -0
- package/src/__tests__/config-schema.test.ts +22 -9
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -4
- package/src/__tests__/contacts-tools.test.ts +26 -0
- package/src/__tests__/context-overflow-policy.test.ts +7 -7
- package/src/__tests__/context-window-manager.test.ts +355 -4
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +26 -30
- package/src/__tests__/conversation-agent-loop.test.ts +30 -141
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -1
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +2 -16
- package/src/__tests__/conversation-pairing.test.ts +174 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +4 -1
- package/src/__tests__/conversation-process-callsite.test.ts +3 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +16 -7
- package/src/__tests__/conversation-queue.test.ts +29 -14
- package/src/__tests__/conversation-routes-disk-view.test.ts +7 -6
- package/src/__tests__/conversation-runtime-assembly.test.ts +155 -110
- package/src/__tests__/conversation-runtime-workspace.test.ts +23 -38
- package/src/__tests__/conversation-seed-composer.test.ts +2 -2
- package/src/__tests__/conversation-slash-queue.test.ts +7 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +25 -2
- package/src/__tests__/conversation-speed-override.test.ts +6 -1
- package/src/__tests__/conversation-title-service.test.ts +116 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +41 -2
- package/src/__tests__/conversation-usage.test.ts +1 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +4 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +3 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -1
- package/src/__tests__/credential-health-service.test.ts +78 -9
- package/src/__tests__/credential-security-invariants.test.ts +2 -2
- package/src/__tests__/db-schedule-syntax-migration.test.ts +1 -0
- package/src/__tests__/empty-response-pipeline.test.ts +305 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +3 -3
- package/src/__tests__/first-greeting.test.ts +247 -5
- package/src/__tests__/headless-browser-mode.test.ts +57 -0
- package/src/__tests__/history-repair-pipeline.test.ts +399 -0
- package/src/__tests__/host-browser-e2e-cloud.test.ts +307 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +3 -3
- package/src/__tests__/host-proxy-interface.test.ts +36 -2
- package/src/__tests__/image-credentials.test.ts +137 -0
- package/src/__tests__/image-service-dispatcher.test.ts +186 -0
- package/src/__tests__/injector-chain.test.ts +526 -0
- package/src/__tests__/intent-routing.test.ts +0 -26
- package/src/__tests__/llm-call-pipeline.test.ts +285 -0
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/media-generate-image.test.ts +119 -13
- package/src/__tests__/memory-retrieval-pipeline.test.ts +401 -0
- package/src/__tests__/memory-upsert-concurrency.test.ts +1 -0
- package/src/__tests__/migration-import-from-url.test.ts +5 -68
- package/src/__tests__/model-intents.test.ts +4 -2
- package/src/__tests__/notification-broadcaster.test.ts +3 -3
- package/src/__tests__/notification-decision-strategy.test.ts +0 -11
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +108 -0
- package/src/__tests__/oauth-apps-routes.test.ts +1 -1
- package/src/__tests__/oauth-cli.test.ts +14 -12
- package/src/__tests__/oauth-connect-orchestrator.test.ts +4 -13
- package/src/__tests__/oauth-provider-serializer.test.ts +6 -4
- package/src/__tests__/oauth-provider-visibility.test.ts +3 -5
- package/src/__tests__/oauth-providers-routes.test.ts +3 -2
- package/src/__tests__/oauth-store.test.ts +41 -76
- package/src/__tests__/onboarding-template-contract.test.ts +16 -64
- package/src/__tests__/openai-image-service.test.ts +368 -0
- package/src/__tests__/overflow-reduce-pipeline.test.ts +676 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +0 -24
- package/src/__tests__/persist-onboarding-artifacts.test.ts +266 -0
- package/src/__tests__/persistence-pipeline.test.ts +377 -0
- package/src/__tests__/pipeline-runner.test.ts +565 -0
- package/src/__tests__/platform.test.ts +5 -2
- package/src/__tests__/plugin-bootstrap.test.ts +483 -0
- package/src/__tests__/plugin-registry.test.ts +273 -0
- package/src/__tests__/plugin-route-contribution.test.ts +288 -0
- package/src/__tests__/plugin-skill-contribution.test.ts +367 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +286 -0
- package/src/__tests__/plugin-types.test.ts +320 -0
- package/src/__tests__/pricing.test.ts +44 -12
- package/src/__tests__/proxy-approval-callback.test.ts +69 -8
- package/src/__tests__/reaction-persistence.test.ts +1 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +0 -2
- package/src/__tests__/schedule-routes.test.ts +131 -1
- package/src/__tests__/scheduler-recurrence.test.ts +14 -70
- package/src/__tests__/scheduler-reuse-conversation.test.ts +10 -50
- package/src/__tests__/secret-detection-handler.test.ts +0 -10
- package/src/__tests__/shell-identity.test.ts +0 -134
- package/src/__tests__/suggestion-routes.test.ts +103 -4
- package/src/__tests__/task-memory-cleanup.test.ts +1 -0
- package/src/__tests__/task-scheduler.test.ts +3 -15
- package/src/__tests__/test-preload.ts +11 -0
- package/src/__tests__/title-generate-pipeline.test.ts +224 -0
- package/src/__tests__/token-estimate-pipeline.test.ts +431 -0
- package/src/__tests__/tool-error-pipeline.test.ts +244 -0
- package/src/__tests__/tool-execute-pipeline.test.ts +431 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -6
- package/src/__tests__/tool-executor-shell-integration.test.ts +7 -10
- package/src/__tests__/tool-executor.test.ts +141 -0
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +356 -0
- package/src/__tests__/tool-result-truncation.test.ts +0 -110
- package/src/__tests__/user-plugin-loader.test.ts +191 -0
- package/src/__tests__/workspace-migration-046-seed-conversation-starters-callsite.test.ts +185 -0
- package/src/__tests__/workspace-migration-049-release-notes-default-sonnet.test.ts +100 -0
- package/src/__tests__/workspace-migration-050-seed-main-agent-opus-callsite.test.ts +171 -0
- package/src/__tests__/workspace-migration-051-seed-conversation-summarization-callsite.test.ts +252 -0
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +99 -0
- package/src/__tests__/workspace-policy.test.ts +21 -3
- package/src/agent/loop.ts +340 -102
- package/src/approvals/__tests__/guardian-feed-event.test.ts +304 -0
- package/src/approvals/guardian-request-resolvers.ts +80 -0
- package/src/backup/__tests__/backup-worker.test.ts +2 -13
- package/src/backup/backup-worker.ts +3 -15
- package/src/bundler/app-compiler.ts +84 -1
- package/src/calls/call-state.ts +2 -2
- package/src/channels/__tests__/types.test.ts +3 -3
- package/src/channels/types.ts +6 -4
- package/src/cli/__tests__/notifications.test.ts +87 -211
- package/src/cli/commands/__tests__/backup.test.ts +1 -1
- package/src/cli/commands/__tests__/image-generation.test.ts +255 -35
- package/src/cli/commands/__tests__/inference-send.test.ts +12 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +12 -0
- package/src/cli/commands/backup.ts +2 -2
- package/src/cli/commands/clients.ts +138 -0
- package/src/cli/commands/completions.ts +2 -9
- package/src/cli/commands/conversations.ts +55 -7
- package/src/cli/commands/image-generation.ts +33 -34
- package/src/cli/commands/notifications.ts +68 -103
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -1
- package/src/cli/commands/oauth/connect.ts +2 -2
- package/src/cli/commands/oauth/providers.ts +176 -8
- package/src/cli/commands/oauth/status.ts +46 -36
- package/src/cli/commands/skills.ts +3 -4
- package/src/cli/program.ts +25 -29
- package/src/config/__tests__/backup-schema.test.ts +7 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +10 -10
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +66 -87
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +28 -51
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +22 -40
- package/src/config/bundled-skills/image-studio/SKILL.md +2 -1
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +23 -39
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +207 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +12 -0
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +58 -0
- package/src/config/bundled-skills/schedule/SKILL.md +8 -3
- package/src/config/bundled-skills/schedule/TOOLS.json +15 -7
- package/src/config/bundled-skills/schedule/references/SCRIPT_MODE_PATTERNS.md +59 -0
- package/src/config/bundled-tool-registry.ts +0 -15
- package/src/config/feature-flag-registry.json +17 -1
- package/src/config/schema.ts +19 -0
- package/src/config/schemas/backup.ts +1 -1
- package/src/config/schemas/conversations.ts +16 -0
- package/src/config/schemas/llm.ts +2 -3
- package/src/config/schemas/security.ts +6 -6
- package/src/config/schemas/tts.ts +11 -0
- package/src/config/skill-state.ts +6 -2
- package/src/config/skills.ts +94 -5
- package/src/context/__tests__/compact-prompt.test.ts +27 -9
- package/src/context/prompts/compact.md +26 -12
- package/src/context/tool-result-truncation.ts +3 -63
- package/src/context/window-manager.ts +190 -16
- package/src/credential-health/credential-health-service.ts +19 -6
- package/src/daemon/__tests__/conversation-feed-event.test.ts +317 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +4 -12
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +14 -15
- package/src/daemon/config-watcher.ts +0 -2
- package/src/daemon/context-overflow-policy.ts +4 -13
- package/src/daemon/conversation-agent-loop-handlers.ts +83 -22
- package/src/daemon/conversation-agent-loop.ts +984 -683
- package/src/daemon/conversation-history.ts +10 -19
- package/src/daemon/conversation-lifecycle.ts +37 -19
- package/src/daemon/conversation-notifiers.ts +2 -110
- package/src/daemon/conversation-process.ts +14 -7
- package/src/daemon/conversation-runtime-assembly.ts +532 -411
- package/src/daemon/conversation-tool-setup.ts +41 -4
- package/src/daemon/conversation.ts +80 -35
- package/src/daemon/external-plugins-bootstrap.ts +478 -0
- package/src/daemon/first-greeting.ts +191 -14
- package/src/daemon/handlers/config-model.ts +11 -0
- package/src/daemon/handlers/skills.ts +5 -1
- package/src/daemon/lifecycle.ts +33 -68
- package/src/daemon/message-types/computer-use.ts +2 -34
- package/src/daemon/message-types/conversations.ts +49 -0
- package/src/daemon/message-types/messages.ts +12 -0
- package/src/daemon/server.ts +5 -3
- package/src/daemon/shutdown-handlers.ts +2 -12
- package/src/daemon/tool-side-effects.ts +14 -56
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +160 -0
- package/src/heartbeat/heartbeat-service.ts +24 -1
- package/src/home/__tests__/feed-population-integration.test.ts +312 -0
- package/src/home/emit-feed-event.ts +7 -0
- package/src/home/feed-types.ts +41 -2
- package/src/home/rewrite-command-preview.ts +66 -0
- package/src/ipc/__tests__/socket-path.test.ts +11 -50
- package/src/ipc/cli-client.ts +1 -1
- package/src/ipc/cli-server.ts +3 -3
- package/src/ipc/gateway-client.ts +4 -1
- package/src/ipc/routes/browser-context.ts +2 -0
- package/src/ipc/routes/browser.ts +1 -0
- package/src/ipc/routes/get-contact.ts +16 -0
- package/src/ipc/routes/index.ts +14 -0
- package/src/ipc/routes/list-clients.ts +31 -0
- package/src/ipc/routes/merge-contacts.ts +17 -0
- package/src/ipc/routes/notification.ts +133 -0
- package/src/ipc/routes/rename-conversation.ts +59 -0
- package/src/ipc/routes/search-contacts.ts +19 -0
- package/src/ipc/routes/upsert-contact.ts +25 -0
- package/src/ipc/socket-path.ts +14 -38
- package/src/media/app-icon-generator.ts +23 -46
- package/src/media/avatar-router.ts +26 -41
- package/src/media/gemini-image-service.ts +8 -41
- package/src/media/image-credentials.ts +73 -0
- package/src/media/image-service.ts +85 -0
- package/src/media/openai-image-service.ts +131 -0
- package/src/media/types.ts +46 -0
- package/src/memory/conversation-crud.ts +48 -18
- package/src/memory/conversation-queries.ts +57 -4
- package/src/memory/conversation-title-service.ts +25 -0
- package/src/memory/db-init.ts +8 -0
- package/src/memory/embedding-gemini.test.ts +41 -2
- package/src/memory/embedding-gemini.ts +6 -1
- package/src/memory/graph/bootstrap.test.ts +282 -0
- package/src/memory/graph/bootstrap.ts +8 -5
- package/src/memory/graph/extraction.ts +10 -2
- package/src/memory/graph/graph-search.test.ts +1 -0
- package/src/memory/graph/inspect.ts +2 -2
- package/src/memory/graph/retriever.ts +10 -3
- package/src/memory/migrations/041-approval-prompt-ts-tracker.ts +26 -0
- package/src/memory/migrations/149-oauth-tables.ts +1 -0
- package/src/memory/migrations/223-schedule-script-column.ts +11 -0
- package/src/memory/migrations/224-oauth-providers-managed-service-is-paid.ts +24 -0
- package/src/memory/migrations/225-oauth-providers-available-scopes.ts +13 -0
- package/src/memory/migrations/index.ts +4 -0
- package/src/memory/pkb/pkb-index.test.ts +1 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +1 -0
- package/src/memory/pkb/pkb-search.test.ts +65 -4
- package/src/memory/pkb/pkb-search.ts +40 -18
- package/src/memory/qdrant-client.test.ts +60 -0
- package/src/memory/qdrant-client.ts +25 -0
- package/src/memory/schema/infrastructure.ts +1 -0
- package/src/memory/schema/oauth.ts +4 -1
- package/src/messaging/providers/slack/render-transcript.test.ts +77 -29
- package/src/messaging/providers/slack/render-transcript.ts +58 -0
- package/src/notifications/conversation-pairing.ts +78 -19
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/emit-signal.ts +1 -1
- package/src/notifications/signal.ts +1 -2
- package/src/oauth/AGENTS.md +1 -1
- package/src/oauth/__tests__/identity-verifier.test.ts +2 -1
- package/src/oauth/connect-orchestrator.ts +8 -34
- package/src/oauth/connect-types.ts +6 -10
- package/src/oauth/manual-token-connection.ts +23 -0
- package/src/oauth/oauth-store.ts +30 -14
- package/src/oauth/provider-serializer.ts +6 -1
- package/src/oauth/seed-providers.ts +56 -108
- package/src/outbound-proxy/http-forwarder.ts +9 -0
- package/src/permissions/approval-policy.test.ts +293 -18
- package/src/permissions/approval-policy.ts +110 -58
- package/src/permissions/arg-parser.test.ts +161 -0
- package/src/permissions/arg-parser.ts +141 -0
- package/src/permissions/bash-risk-classifier.test.ts +414 -2
- package/src/permissions/bash-risk-classifier.ts +303 -60
- package/src/permissions/checker.ts +157 -29
- package/src/permissions/command-registry.test.ts +239 -0
- package/src/permissions/command-registry.ts +234 -54
- package/src/permissions/defaults.ts +5 -4
- package/src/permissions/gateway-threshold-reader.ts +196 -0
- package/src/permissions/prompter.ts +4 -0
- package/src/permissions/risk-types.ts +61 -4
- package/src/permissions/schedule-risk-classifier.test.ts +129 -0
- package/src/permissions/schedule-risk-classifier.ts +85 -0
- package/src/permissions/shell-identity.ts +2 -42
- package/src/permissions/types.ts +2 -0
- package/src/permissions/workspace-policy.ts +8 -3
- package/src/plugins/defaults/circuit-breaker.ts +146 -0
- package/src/plugins/defaults/compaction.ts +145 -0
- package/src/plugins/defaults/empty-response.ts +126 -0
- package/src/plugins/defaults/history-repair.ts +85 -0
- package/src/plugins/defaults/index.ts +116 -0
- package/src/plugins/defaults/injectors.ts +491 -0
- package/src/plugins/defaults/llm-call.ts +82 -0
- package/src/plugins/defaults/memory-retrieval.ts +226 -0
- package/src/plugins/defaults/overflow-reduce.ts +181 -0
- package/src/plugins/defaults/persistence.ts +129 -0
- package/src/plugins/defaults/title-generate.ts +95 -0
- package/src/plugins/defaults/token-estimate.ts +104 -0
- package/src/plugins/defaults/tool-error.ts +126 -0
- package/src/plugins/defaults/tool-execute.ts +89 -0
- package/src/plugins/defaults/tool-result-truncate.ts +88 -0
- package/src/plugins/pipeline.ts +316 -0
- package/src/plugins/plugin-skill-contributions.ts +292 -0
- package/src/plugins/registry.ts +241 -0
- package/src/plugins/types.ts +1134 -0
- package/src/plugins/user-loader.ts +177 -0
- package/src/prompts/templates/BOOTSTRAP.md +27 -77
- package/src/providers/model-catalog.ts +52 -29
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openrouter/client.ts +5 -1
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +61 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +57 -0
- package/src/providers/speech-to-text/xai-realtime.test.ts +72 -4
- package/src/providers/speech-to-text/xai-realtime.ts +39 -14
- package/src/runtime/AGENTS.md +25 -16
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +3 -3
- package/src/runtime/__tests__/client-registry.test.ts +293 -0
- package/src/runtime/client-registry.ts +261 -0
- package/src/runtime/http-server.ts +77 -8
- package/src/runtime/http-types.ts +0 -2
- package/src/runtime/migrations/vbundle-builder.ts +1 -22
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +51 -31
- package/src/runtime/routes/approval-routes.ts +17 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +27 -8
- package/src/runtime/routes/conversation-routes.ts +223 -116
- package/src/runtime/routes/inbound-message-handler.ts +88 -13
- package/src/runtime/routes/memory-item-routes.test.ts +1 -0
- package/src/runtime/routes/migration-routes.ts +0 -3
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +284 -0
- package/src/runtime/routes/playground/__tests__/guard.test.ts +80 -0
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +294 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +271 -0
- package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +202 -0
- package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +309 -0
- package/src/runtime/routes/playground/__tests__/state.test.ts +224 -0
- package/src/runtime/routes/playground/conversation-not-found.ts +29 -0
- package/src/runtime/routes/playground/deps.ts +56 -0
- package/src/runtime/routes/playground/force-compact.ts +73 -0
- package/src/runtime/routes/playground/guard.ts +37 -0
- package/src/runtime/routes/playground/index.ts +28 -0
- package/src/runtime/routes/playground/inject-failures.ts +159 -0
- package/src/runtime/routes/playground/reset-circuit.ts +115 -0
- package/src/runtime/routes/playground/seed-conversation.ts +139 -0
- package/src/runtime/routes/playground/seeded-conversations.ts +78 -0
- package/src/runtime/routes/playground/state.ts +78 -0
- package/src/runtime/routes/schedule-routes.ts +89 -8
- package/src/runtime/skill-route-registry.ts +75 -15
- package/src/schedule/run-script.ts +68 -0
- package/src/schedule/schedule-store.ts +7 -1
- package/src/schedule/scheduler.ts +48 -8
- package/src/skills/catalog-cache.ts +12 -5
- package/src/tools/browser/__tests__/browser-status.test.ts +189 -0
- package/src/tools/browser/browser-execution.ts +88 -19
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +230 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +146 -3
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +54 -3
- package/src/tools/browser/cdp-client/factory.ts +15 -4
- package/src/tools/executor.ts +126 -74
- package/src/tools/network/script-proxy/session-manager.ts +37 -1
- package/src/tools/permission-checker.ts +98 -49
- package/src/tools/policy-context.ts +4 -0
- package/src/tools/registry.ts +140 -3
- package/src/tools/schedule/create.ts +23 -8
- package/src/tools/schedule/update.ts +3 -1
- package/src/tools/secret-detection-handler.ts +0 -51
- package/src/tools/system/avatar-generator.ts +6 -2
- package/src/tools/types.ts +28 -2
- package/src/util/platform.ts +7 -2
- package/src/util/pricing.ts +26 -3
- package/src/workspace/migrations/006-services-config.ts +2 -4
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +2 -3
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +3 -4
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +108 -0
- package/src/workspace/migrations/047-remove-watch-callsites.ts +54 -0
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +81 -0
- package/src/workspace/migrations/049-release-notes-default-sonnet.ts +80 -0
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +86 -0
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +128 -0
- package/src/workspace/migrations/registry.ts +12 -0
- package/tsconfig.json +1 -1
- package/hook-templates/debug-prompt-logger/hook.json +0 -7
- package/hook-templates/debug-prompt-logger/run.sh +0 -66
- package/src/__tests__/compaction-circuit-breaker.test.ts +0 -336
- package/src/__tests__/context-overflow-approval.test.ts +0 -156
- package/src/__tests__/hooks-blocking.test.ts +0 -178
- package/src/__tests__/hooks-cli.test.ts +0 -182
- package/src/__tests__/hooks-config.test.ts +0 -108
- package/src/__tests__/hooks-discovery.test.ts +0 -211
- package/src/__tests__/hooks-integration.test.ts +0 -196
- package/src/__tests__/hooks-manager.test.ts +0 -226
- package/src/__tests__/hooks-runner.test.ts +0 -175
- package/src/__tests__/hooks-settings.test.ts +0 -160
- package/src/__tests__/hooks-templates.test.ts +0 -169
- package/src/__tests__/hooks-ts-runner.test.ts +0 -170
- package/src/__tests__/hooks-watch.test.ts +0 -112
- package/src/__tests__/notification-schedule-dedup.test.ts +0 -213
- package/src/__tests__/oauth-scope-policy.test.ts +0 -180
- package/src/__tests__/send-notification-tool.test.ts +0 -83
- package/src/cli/commands/shotgun.ts +0 -266
- package/src/config/bundled-skills/conversations/SKILL.md +0 -20
- package/src/config/bundled-skills/conversations/TOOLS.json +0 -23
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +0 -88
- package/src/config/bundled-skills/heartbeat/SKILL.md +0 -43
- package/src/config/bundled-skills/notifications/SKILL.md +0 -40
- package/src/config/bundled-skills/notifications/TOOLS.json +0 -80
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -152
- package/src/config/bundled-skills/notifications/tools/shared.ts +0 -13
- package/src/config/bundled-skills/screen-watch/SKILL.md +0 -27
- package/src/config/bundled-skills/screen-watch/TOOLS.json +0 -35
- package/src/config/bundled-skills/screen-watch/tools/start-screen-watch.ts +0 -12
- package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -84
- package/src/daemon/context-overflow-approval.ts +0 -52
- package/src/daemon/watch-handler.ts +0 -399
- package/src/hooks/cli.ts +0 -253
- package/src/hooks/config.ts +0 -100
- package/src/hooks/discovery.ts +0 -135
- package/src/hooks/manager.ts +0 -179
- package/src/hooks/runner.ts +0 -117
- package/src/hooks/templates.ts +0 -77
- package/src/hooks/types.ts +0 -75
- package/src/oauth/scope-policy.ts +0 -89
- package/src/runtime/gateway-internal-client.ts +0 -94
- package/src/runtime/routes/watch-routes.ts +0 -156
- package/src/signals/shotgun.ts +0 -203
- package/src/tools/watch/screen-watch.ts +0 -144
- package/src/tools/watch/watch-state.ts +0 -142
|
@@ -410,7 +410,7 @@ describe("GET /v1/suggestion", () => {
|
|
|
410
410
|
expect(body.suggestion).toBe("sounds good");
|
|
411
411
|
});
|
|
412
412
|
|
|
413
|
-
test("passes
|
|
413
|
+
test("passes stop_sequences, max_tokens, and XML-framed user prompt", async () => {
|
|
414
414
|
const provider = makeMockProvider("on my way");
|
|
415
415
|
mockGetConfiguredProvider.mockImplementation(async () => provider);
|
|
416
416
|
mockGetConversationByKey.mockImplementation(() => ({
|
|
@@ -454,9 +454,8 @@ describe("GET /v1/suggestion", () => {
|
|
|
454
454
|
};
|
|
455
455
|
};
|
|
456
456
|
|
|
457
|
-
expect(messages.length).toBe(
|
|
458
|
-
expect(messages[
|
|
459
|
-
expect(messages[1].content[0].text).toBe("<reply>");
|
|
457
|
+
expect(messages.length).toBe(1);
|
|
458
|
+
expect(messages[0].role).toBe("user");
|
|
460
459
|
expect(options.config?.stop_sequences).toEqual(["</reply>"]);
|
|
461
460
|
expect(options.config?.max_tokens).toBe(60);
|
|
462
461
|
expect(messages[0].content[0].text).toContain("<assistant_message>");
|
|
@@ -568,4 +567,104 @@ describe("GET /v1/suggestion", () => {
|
|
|
568
567
|
| undefined;
|
|
569
568
|
expect(options?.config?.callSite).toBe("conversationStarters");
|
|
570
569
|
});
|
|
570
|
+
|
|
571
|
+
test("does not send an assistant-role prefill message", async () => {
|
|
572
|
+
// Regression guard: Anthropic rejects assistant-message prefill
|
|
573
|
+
// whenever the request triggers extended thinking (e.g. Opus 4.x at
|
|
574
|
+
// `effort: "xhigh"`). The suggestion generator must only send a
|
|
575
|
+
// single user-role message so it stays compatible with every
|
|
576
|
+
// possible `conversationStarters` call-site config.
|
|
577
|
+
const provider = makeMockProvider("<reply>Sure, works for me</reply>");
|
|
578
|
+
mockGetConfiguredProvider.mockImplementation(async () => provider);
|
|
579
|
+
mockGetConversationByKey.mockImplementation(() => ({
|
|
580
|
+
conversationId: "conv-test",
|
|
581
|
+
}));
|
|
582
|
+
mockGetMessages.mockImplementation(() => [
|
|
583
|
+
{
|
|
584
|
+
id: "msg-asst-1",
|
|
585
|
+
conversationId: "conv-test",
|
|
586
|
+
role: "assistant",
|
|
587
|
+
content: JSON.stringify([
|
|
588
|
+
{ type: "text", text: "Want to meet tomorrow?" },
|
|
589
|
+
]),
|
|
590
|
+
createdAt: Date.now(),
|
|
591
|
+
metadata: null,
|
|
592
|
+
},
|
|
593
|
+
]);
|
|
594
|
+
|
|
595
|
+
const url = makeUrl({ conversationKey: "test-key" });
|
|
596
|
+
const deps = makeDeps();
|
|
597
|
+
const response = await handleGetSuggestion(url, deps);
|
|
598
|
+
|
|
599
|
+
expect(provider.sendMessage).toHaveBeenCalledTimes(1);
|
|
600
|
+
const callArgs = provider.sendMessage.mock.calls[0] as unknown[];
|
|
601
|
+
const messages = callArgs[0] as Array<{ role: string }>;
|
|
602
|
+
expect(messages).toHaveLength(1);
|
|
603
|
+
expect(messages[0].role).toBe("user");
|
|
604
|
+
expect(messages.every((m) => m.role === "user")).toBe(true);
|
|
605
|
+
|
|
606
|
+
// Tag-wrapped response is extracted back to just the reply text.
|
|
607
|
+
const body = (await response.json()) as { suggestion: string | null };
|
|
608
|
+
expect(body.suggestion).toBe("Sure, works for me");
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
test("handles untagged model response by falling back to raw text", async () => {
|
|
612
|
+
// Some non-Anthropic models and some Anthropic configs drop the
|
|
613
|
+
// `<reply>…</reply>` wrapper entirely. The parser must still
|
|
614
|
+
// produce a usable suggestion from the raw text.
|
|
615
|
+
const provider = makeMockProvider("Sounds good to me");
|
|
616
|
+
mockGetConfiguredProvider.mockImplementation(async () => provider);
|
|
617
|
+
mockGetConversationByKey.mockImplementation(() => ({
|
|
618
|
+
conversationId: "conv-test",
|
|
619
|
+
}));
|
|
620
|
+
mockGetMessages.mockImplementation(() => [
|
|
621
|
+
{
|
|
622
|
+
id: "msg-asst-untagged",
|
|
623
|
+
conversationId: "conv-test",
|
|
624
|
+
role: "assistant",
|
|
625
|
+
content: JSON.stringify([
|
|
626
|
+
{ type: "text", text: "Want to meet tomorrow?" },
|
|
627
|
+
]),
|
|
628
|
+
createdAt: Date.now(),
|
|
629
|
+
metadata: null,
|
|
630
|
+
},
|
|
631
|
+
]);
|
|
632
|
+
|
|
633
|
+
const url = makeUrl({ conversationKey: "test-key" });
|
|
634
|
+
const deps = makeDeps();
|
|
635
|
+
const response = await handleGetSuggestion(url, deps);
|
|
636
|
+
|
|
637
|
+
const body = (await response.json()) as { suggestion: string | null };
|
|
638
|
+
expect(body.suggestion).toBe("Sounds good to me");
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
test("extracts reply content when model adds preamble before tag", async () => {
|
|
642
|
+
// Without assistant-role prefill, nothing stops a chatty model from
|
|
643
|
+
// adding a preamble. The parser's tag-extraction step must take the
|
|
644
|
+
// `<reply>…</reply>` span and ignore surrounding commentary.
|
|
645
|
+
const provider = makeMockProvider(
|
|
646
|
+
"Here's a good option:\n\n<reply>Let's do it</reply>",
|
|
647
|
+
);
|
|
648
|
+
mockGetConfiguredProvider.mockImplementation(async () => provider);
|
|
649
|
+
mockGetConversationByKey.mockImplementation(() => ({
|
|
650
|
+
conversationId: "conv-test",
|
|
651
|
+
}));
|
|
652
|
+
mockGetMessages.mockImplementation(() => [
|
|
653
|
+
{
|
|
654
|
+
id: "msg-asst-preamble",
|
|
655
|
+
conversationId: "conv-test",
|
|
656
|
+
role: "assistant",
|
|
657
|
+
content: JSON.stringify([{ type: "text", text: "Ready to ship it?" }]),
|
|
658
|
+
createdAt: Date.now(),
|
|
659
|
+
metadata: null,
|
|
660
|
+
},
|
|
661
|
+
]);
|
|
662
|
+
|
|
663
|
+
const url = makeUrl({ conversationKey: "test-key" });
|
|
664
|
+
const deps = makeDeps();
|
|
665
|
+
const response = await handleGetSuggestion(url, deps);
|
|
666
|
+
|
|
667
|
+
const body = (await response.json()) as { suggestion: string | null };
|
|
668
|
+
expect(body.suggestion).toBe("Let's do it");
|
|
669
|
+
});
|
|
571
670
|
});
|
|
@@ -141,11 +141,7 @@ describe("scheduler run_task detection", () => {
|
|
|
141
141
|
directCalls.push({ conversationId, message, options });
|
|
142
142
|
};
|
|
143
143
|
|
|
144
|
-
const scheduler = startScheduler(
|
|
145
|
-
processMessage,
|
|
146
|
-
() => {},
|
|
147
|
-
() => {},
|
|
148
|
-
);
|
|
144
|
+
const scheduler = startScheduler(processMessage, () => {});
|
|
149
145
|
|
|
150
146
|
// Wait for the initial tick to complete
|
|
151
147
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
@@ -190,11 +186,7 @@ describe("scheduler run_task detection", () => {
|
|
|
190
186
|
processedMessages.push({ conversationId, message, options });
|
|
191
187
|
};
|
|
192
188
|
|
|
193
|
-
const scheduler = startScheduler(
|
|
194
|
-
processMessage,
|
|
195
|
-
() => {},
|
|
196
|
-
() => {},
|
|
197
|
-
);
|
|
189
|
+
const scheduler = startScheduler(processMessage, () => {});
|
|
198
190
|
|
|
199
191
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
200
192
|
scheduler.stop();
|
|
@@ -229,11 +221,7 @@ describe("scheduler run_task detection", () => {
|
|
|
229
221
|
_message: string,
|
|
230
222
|
) => {};
|
|
231
223
|
|
|
232
|
-
const scheduler = startScheduler(
|
|
233
|
-
processMessage,
|
|
234
|
-
() => {},
|
|
235
|
-
() => {},
|
|
236
|
-
);
|
|
224
|
+
const scheduler = startScheduler(processMessage, () => {});
|
|
237
225
|
|
|
238
226
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
239
227
|
scheduler.stop();
|
|
@@ -20,10 +20,16 @@ import { installGatewayIpcMock } from "../__tests__/mock-gateway-ipc.js";
|
|
|
20
20
|
import { resetDb } from "../memory/db-connection.js";
|
|
21
21
|
import { _setStorePath } from "../security/encrypted-store.js";
|
|
22
22
|
|
|
23
|
+
const savedBaseDataDir = process.env.BASE_DATA_DIR;
|
|
24
|
+
|
|
23
25
|
const testDir = realpathSync(
|
|
24
26
|
mkdtempSync(join(tmpdir(), "vellum-test-workspace-")),
|
|
25
27
|
);
|
|
26
28
|
process.env.VELLUM_WORKSPACE_DIR = testDir;
|
|
29
|
+
// Also set BASE_DATA_DIR so that vellumRoot() (and all derived paths like
|
|
30
|
+
// getProtectedDir()) resolve under the temp dir. This gives each test file
|
|
31
|
+
// its own IPC socket path, preventing socket races between parallel files.
|
|
32
|
+
process.env.BASE_DATA_DIR = testDir;
|
|
27
33
|
process.env.VELLUM_PLATFORM_URL = "https://test-platform.vellum.ai";
|
|
28
34
|
process.exitCode = 0;
|
|
29
35
|
|
|
@@ -56,6 +62,11 @@ afterAll(() => {
|
|
|
56
62
|
process.exitCode = 0;
|
|
57
63
|
delete process.env.VELLUM_WORKSPACE_DIR;
|
|
58
64
|
delete process.env.VELLUM_PLATFORM_URL;
|
|
65
|
+
if (savedBaseDataDir !== undefined) {
|
|
66
|
+
process.env.BASE_DATA_DIR = savedBaseDataDir;
|
|
67
|
+
} else {
|
|
68
|
+
delete process.env.BASE_DATA_DIR;
|
|
69
|
+
}
|
|
59
70
|
if (savedIsContainerized !== undefined) {
|
|
60
71
|
process.env.IS_CONTAINERIZED = savedIsContainerized;
|
|
61
72
|
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the `titleGenerate` pipeline (PR 28).
|
|
3
|
+
*
|
|
4
|
+
* The title-generation side effect used to be a direct call to
|
|
5
|
+
* `queueGenerateConversationTitle` inside `conversation-agent-loop.ts`.
|
|
6
|
+
* After PR 28 the assistant routes that call through the plugin pipeline
|
|
7
|
+
* runner, giving plugins an opportunity to observe/replace the default
|
|
8
|
+
* implementation.
|
|
9
|
+
*
|
|
10
|
+
* Covers:
|
|
11
|
+
* - The default plugin's terminal delegates to
|
|
12
|
+
* `queueGenerateConversationTitle` with the same arguments the agent
|
|
13
|
+
* loop constructs.
|
|
14
|
+
* - A custom plugin can install a short-circuit middleware that replaces
|
|
15
|
+
* the terminal with a deterministic generator. The default terminal is
|
|
16
|
+
* NOT invoked in that case.
|
|
17
|
+
*
|
|
18
|
+
* Mocks `memory/conversation-title-service.js` so the tests don't touch
|
|
19
|
+
* the real provider stack, and resets the plugin registry between cases.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
23
|
+
|
|
24
|
+
// Stub the title-generation service before importing anything that binds
|
|
25
|
+
// to it, so both the default plugin and the agent loop capture the
|
|
26
|
+
// stubbed binding.
|
|
27
|
+
const queueGenerateConversationTitleMock = mock(
|
|
28
|
+
(_params: {
|
|
29
|
+
conversationId: string;
|
|
30
|
+
provider?: unknown;
|
|
31
|
+
userMessage?: string;
|
|
32
|
+
onTitleUpdated?: (title: string) => void;
|
|
33
|
+
}): void => undefined,
|
|
34
|
+
);
|
|
35
|
+
mock.module("../memory/conversation-title-service.js", () => ({
|
|
36
|
+
queueGenerateConversationTitle: queueGenerateConversationTitleMock,
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
import { defaultTitleGenerateTerminal } from "../plugins/defaults/title-generate.js";
|
|
40
|
+
import { DEFAULT_TIMEOUTS, runPipeline } from "../plugins/pipeline.js";
|
|
41
|
+
import {
|
|
42
|
+
getMiddlewaresFor,
|
|
43
|
+
registerPlugin,
|
|
44
|
+
resetPluginRegistryForTests,
|
|
45
|
+
} from "../plugins/registry.js";
|
|
46
|
+
import type {
|
|
47
|
+
Middleware,
|
|
48
|
+
Plugin,
|
|
49
|
+
TitleArgs,
|
|
50
|
+
TitleResult,
|
|
51
|
+
TurnContext,
|
|
52
|
+
} from "../plugins/types.js";
|
|
53
|
+
|
|
54
|
+
function makeCtx(overrides: Partial<TurnContext> = {}): TurnContext {
|
|
55
|
+
return {
|
|
56
|
+
requestId: "req-1",
|
|
57
|
+
conversationId: "conv-1",
|
|
58
|
+
turnIndex: 0,
|
|
59
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
60
|
+
...overrides,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function makeArgs(overrides: Partial<TitleArgs> = {}): TitleArgs {
|
|
65
|
+
return {
|
|
66
|
+
conversationId: "conv-1",
|
|
67
|
+
userMessage: "hello world",
|
|
68
|
+
...overrides,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
describe("titleGenerate pipeline", () => {
|
|
73
|
+
beforeEach(() => {
|
|
74
|
+
resetPluginRegistryForTests();
|
|
75
|
+
queueGenerateConversationTitleMock.mockReset();
|
|
76
|
+
queueGenerateConversationTitleMock.mockImplementation(() => undefined);
|
|
77
|
+
// Re-register the default plugin after the registry reset so tests see
|
|
78
|
+
// the same shape the daemon sees at runtime.
|
|
79
|
+
registerPlugin({
|
|
80
|
+
manifest: {
|
|
81
|
+
name: "default-title-generate",
|
|
82
|
+
version: "1.0.0",
|
|
83
|
+
provides: { titleGenerate: "v1" },
|
|
84
|
+
requires: {
|
|
85
|
+
pluginRuntime: "v1",
|
|
86
|
+
titleGenerateApi: "v1",
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("default: pipeline terminal queues a title-generation job", async () => {
|
|
93
|
+
const ctx = makeCtx();
|
|
94
|
+
const onTitleUpdated = mock((_title: string) => undefined);
|
|
95
|
+
const args = makeArgs({
|
|
96
|
+
conversationId: "conv-1",
|
|
97
|
+
userMessage: "first message",
|
|
98
|
+
onTitleUpdated,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
await runPipeline(
|
|
102
|
+
"titleGenerate",
|
|
103
|
+
getMiddlewaresFor("titleGenerate"),
|
|
104
|
+
defaultTitleGenerateTerminal,
|
|
105
|
+
args,
|
|
106
|
+
ctx,
|
|
107
|
+
DEFAULT_TIMEOUTS.titleGenerate,
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
// The default terminal must have delegated to queueGenerateConversationTitle
|
|
111
|
+
// with every argument the caller supplied, including the callback.
|
|
112
|
+
expect(queueGenerateConversationTitleMock).toHaveBeenCalledTimes(1);
|
|
113
|
+
const call = queueGenerateConversationTitleMock.mock.calls[0]?.[0];
|
|
114
|
+
expect(call?.conversationId).toBe("conv-1");
|
|
115
|
+
expect(call?.userMessage).toBe("first message");
|
|
116
|
+
expect(call?.onTitleUpdated).toBe(onTitleUpdated);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("default: pipeline result is the empty object from the terminal", async () => {
|
|
120
|
+
const ctx = makeCtx();
|
|
121
|
+
const result = await runPipeline(
|
|
122
|
+
"titleGenerate",
|
|
123
|
+
getMiddlewaresFor("titleGenerate"),
|
|
124
|
+
defaultTitleGenerateTerminal,
|
|
125
|
+
makeArgs(),
|
|
126
|
+
ctx,
|
|
127
|
+
DEFAULT_TIMEOUTS.titleGenerate,
|
|
128
|
+
);
|
|
129
|
+
expect(result).toEqual({});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test("custom plugin: short-circuit middleware replaces the default with a deterministic generator", async () => {
|
|
133
|
+
// A custom plugin installs middleware that fabricates a title
|
|
134
|
+
// deterministically and never calls `next`, so the default terminal
|
|
135
|
+
// (which would delegate to queueGenerateConversationTitle) is
|
|
136
|
+
// skipped entirely.
|
|
137
|
+
const observedTitles: string[] = [];
|
|
138
|
+
|
|
139
|
+
const deterministicMw: Middleware<TitleArgs, TitleResult> = async (
|
|
140
|
+
args,
|
|
141
|
+
) => {
|
|
142
|
+
const fabricated = `[deterministic] ${args.userMessage}`;
|
|
143
|
+
args.onTitleUpdated?.(fabricated);
|
|
144
|
+
observedTitles.push(fabricated);
|
|
145
|
+
return {};
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const customPlugin: Plugin = {
|
|
149
|
+
manifest: {
|
|
150
|
+
name: "custom-deterministic-title",
|
|
151
|
+
version: "0.0.1",
|
|
152
|
+
requires: {
|
|
153
|
+
pluginRuntime: "v1",
|
|
154
|
+
titleGenerateApi: "v1",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
middleware: { titleGenerate: deterministicMw },
|
|
158
|
+
};
|
|
159
|
+
registerPlugin(customPlugin);
|
|
160
|
+
|
|
161
|
+
const receivedTitle: string[] = [];
|
|
162
|
+
const args = makeArgs({
|
|
163
|
+
userMessage: "what is the weather",
|
|
164
|
+
onTitleUpdated: (title) => {
|
|
165
|
+
receivedTitle.push(title);
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
await runPipeline(
|
|
170
|
+
"titleGenerate",
|
|
171
|
+
getMiddlewaresFor("titleGenerate"),
|
|
172
|
+
defaultTitleGenerateTerminal,
|
|
173
|
+
args,
|
|
174
|
+
makeCtx(),
|
|
175
|
+
DEFAULT_TIMEOUTS.titleGenerate,
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
// Deterministic middleware produced the expected title and invoked
|
|
179
|
+
// the caller's callback.
|
|
180
|
+
expect(observedTitles).toEqual(["[deterministic] what is the weather"]);
|
|
181
|
+
expect(receivedTitle).toEqual(["[deterministic] what is the weather"]);
|
|
182
|
+
// The default terminal must NOT have been reached — it would have
|
|
183
|
+
// called the real title-service stub.
|
|
184
|
+
expect(queueGenerateConversationTitleMock).not.toHaveBeenCalled();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test("custom plugin: passthrough middleware leaves the default in charge", async () => {
|
|
188
|
+
// A plugin that always calls `next` just observes — the default
|
|
189
|
+
// terminal still runs and queues the title-generation job.
|
|
190
|
+
let middlewareSawArgs = false;
|
|
191
|
+
|
|
192
|
+
const passthroughMw: Middleware<TitleArgs, TitleResult> = async (
|
|
193
|
+
args,
|
|
194
|
+
next,
|
|
195
|
+
) => {
|
|
196
|
+
middlewareSawArgs = true;
|
|
197
|
+
return next(args);
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
registerPlugin({
|
|
201
|
+
manifest: {
|
|
202
|
+
name: "observer",
|
|
203
|
+
version: "0.0.1",
|
|
204
|
+
requires: {
|
|
205
|
+
pluginRuntime: "v1",
|
|
206
|
+
titleGenerateApi: "v1",
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
middleware: { titleGenerate: passthroughMw },
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
await runPipeline(
|
|
213
|
+
"titleGenerate",
|
|
214
|
+
getMiddlewaresFor("titleGenerate"),
|
|
215
|
+
defaultTitleGenerateTerminal,
|
|
216
|
+
makeArgs(),
|
|
217
|
+
makeCtx(),
|
|
218
|
+
DEFAULT_TIMEOUTS.titleGenerate,
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
expect(middlewareSawArgs).toBe(true);
|
|
222
|
+
expect(queueGenerateConversationTitleMock).toHaveBeenCalledTimes(1);
|
|
223
|
+
});
|
|
224
|
+
});
|