@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
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shape-only tests for the plugin core types (PR 11).
|
|
3
|
+
*
|
|
4
|
+
* These tests don't exercise any runtime behavior — they only assert, via
|
|
5
|
+
* the `satisfies` operator, that a fully-populated `Plugin` literal lines
|
|
6
|
+
* up with the public interface. If a later PR changes a field name or
|
|
7
|
+
* signature in a breaking way, this file fails to type-check and the
|
|
8
|
+
* regression is caught at `tsc --noEmit` / `bun test` time.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, expect, test } from "bun:test";
|
|
12
|
+
|
|
13
|
+
import type { TrustContext } from "../daemon/conversation-runtime-assembly.js";
|
|
14
|
+
import { RiskLevel } from "../permissions/types.js";
|
|
15
|
+
import {
|
|
16
|
+
type CircuitBreakerArgs,
|
|
17
|
+
type CircuitBreakerResult,
|
|
18
|
+
type CompactionArgs,
|
|
19
|
+
type CompactionResult,
|
|
20
|
+
type EmptyResponseArgs,
|
|
21
|
+
type EmptyResponseResult,
|
|
22
|
+
type EstimateArgs,
|
|
23
|
+
type EstimateResult,
|
|
24
|
+
type Injector,
|
|
25
|
+
type LLMCallArgs,
|
|
26
|
+
type LLMCallResult,
|
|
27
|
+
type MemoryArgs,
|
|
28
|
+
type MemoryResult,
|
|
29
|
+
type Middleware,
|
|
30
|
+
type OverflowReduceArgs,
|
|
31
|
+
type OverflowReduceResult,
|
|
32
|
+
type PersistArgs,
|
|
33
|
+
type PersistResult,
|
|
34
|
+
type Plugin,
|
|
35
|
+
PluginExecutionError,
|
|
36
|
+
type PluginInitContext,
|
|
37
|
+
type PluginManifest,
|
|
38
|
+
PluginTimeoutError,
|
|
39
|
+
type TitleArgs,
|
|
40
|
+
type TitleResult,
|
|
41
|
+
type ToolErrorArgs,
|
|
42
|
+
type ToolErrorDecision,
|
|
43
|
+
type ToolExecuteArgs,
|
|
44
|
+
type ToolExecuteResult,
|
|
45
|
+
type ToolResultTruncateArgs,
|
|
46
|
+
type ToolResultTruncateResult,
|
|
47
|
+
type TurnContext,
|
|
48
|
+
} from "../plugins/types.js";
|
|
49
|
+
import type { Tool } from "../tools/types.js";
|
|
50
|
+
|
|
51
|
+
const sampleTrust: TrustContext = {
|
|
52
|
+
sourceChannel: "vellum",
|
|
53
|
+
trustClass: "guardian",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const sampleTurnContext: TurnContext = {
|
|
57
|
+
requestId: "req-abc",
|
|
58
|
+
conversationId: "conv-xyz",
|
|
59
|
+
turnIndex: 0,
|
|
60
|
+
pluginName: "sample-plugin",
|
|
61
|
+
trust: sampleTrust,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
describe("plugin core types", () => {
|
|
65
|
+
test("a fully-populated Plugin literal satisfies the interface", () => {
|
|
66
|
+
const manifest: PluginManifest = {
|
|
67
|
+
name: "sample-plugin",
|
|
68
|
+
version: "0.1.0",
|
|
69
|
+
provides: { sampleApi: "v1" },
|
|
70
|
+
requires: { pluginRuntime: "v1" },
|
|
71
|
+
requiresCredential: ["SAMPLE_API_KEY"],
|
|
72
|
+
requiresFlag: ["sample-feature"],
|
|
73
|
+
config: { parse: (input: unknown) => input },
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Generic passthrough — typed per slot below because per-pipeline
|
|
77
|
+
// arg/result types have diverged from the early `{input: unknown}` /
|
|
78
|
+
// `{output: unknown}` placeholders as individual pipeline wrap-up PRs
|
|
79
|
+
// land.
|
|
80
|
+
function passthroughFor<A, R>(): Middleware<A, R> {
|
|
81
|
+
return async (args, next, _ctx) => next(args);
|
|
82
|
+
}
|
|
83
|
+
const passthrough: Middleware<
|
|
84
|
+
{ input: unknown },
|
|
85
|
+
{ output: unknown }
|
|
86
|
+
> = async (args, next, _ctx) => next(args);
|
|
87
|
+
const passthroughHistoryRepair = passthroughFor<
|
|
88
|
+
import("../plugins/types.js").HistoryRepairArgs,
|
|
89
|
+
import("../plugins/types.js").HistoryRepairResult
|
|
90
|
+
>();
|
|
91
|
+
|
|
92
|
+
// `llmCall` has concrete arg/result types (upgraded in PR 15).
|
|
93
|
+
const llmCallPassthrough: Middleware<LLMCallArgs, LLMCallResult> = async (
|
|
94
|
+
args,
|
|
95
|
+
next,
|
|
96
|
+
_ctx,
|
|
97
|
+
) => next(args);
|
|
98
|
+
|
|
99
|
+
// `toolExecute` has concrete arg/result types (refined in PR 16).
|
|
100
|
+
const toolExecutePassthrough: Middleware<
|
|
101
|
+
ToolExecuteArgs,
|
|
102
|
+
ToolExecuteResult
|
|
103
|
+
> = async (args, next, _ctx) => next(args);
|
|
104
|
+
|
|
105
|
+
// `toolResultTruncate` has a concrete args/result shape (PR 17) so we
|
|
106
|
+
// need a dedicated passthrough for that slot.
|
|
107
|
+
const truncatePassthrough: Middleware<
|
|
108
|
+
ToolResultTruncateArgs,
|
|
109
|
+
ToolResultTruncateResult
|
|
110
|
+
> = async (args, _next, _ctx) => ({
|
|
111
|
+
content: args.content,
|
|
112
|
+
truncated: false,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// The `emptyResponse` slot has concrete args/result types; use a
|
|
116
|
+
// dedicated passthrough so the `satisfies Plugin` check stays honest.
|
|
117
|
+
const emptyResponsePassthrough: Middleware<
|
|
118
|
+
EmptyResponseArgs,
|
|
119
|
+
EmptyResponseResult
|
|
120
|
+
> = async (args, next, _ctx) => next(args);
|
|
121
|
+
|
|
122
|
+
// The `toolError` slot has concrete args/result types (PR 19); use a
|
|
123
|
+
// dedicated passthrough so the shape-only test keeps compiling as types
|
|
124
|
+
// get tightened.
|
|
125
|
+
const toolErrorPassthrough: Middleware<
|
|
126
|
+
ToolErrorArgs,
|
|
127
|
+
ToolErrorDecision
|
|
128
|
+
> = async (args, next, _ctx) => next(args);
|
|
129
|
+
|
|
130
|
+
// `memoryRetrieval` has a concrete typed signature (MemoryArgs →
|
|
131
|
+
// MemoryResult) introduced in PR 20, so it can't use the generic
|
|
132
|
+
// `{ input }` passthrough above.
|
|
133
|
+
const memoryPassthrough: Middleware<MemoryArgs, MemoryResult> = async (
|
|
134
|
+
args,
|
|
135
|
+
next,
|
|
136
|
+
_ctx,
|
|
137
|
+
) => next(args);
|
|
138
|
+
|
|
139
|
+
// `tokenEstimate` has a concrete arg/result shape (refined in the
|
|
140
|
+
// tokenEstimate-pipeline PR), so its middleware can't share the generic
|
|
141
|
+
// `{ input, output }` passthrough. A slot-specific passthrough keeps the
|
|
142
|
+
// shape-only assertion honest across type-refinement PRs.
|
|
143
|
+
const tokenEstimatePassthrough: Middleware<
|
|
144
|
+
EstimateArgs,
|
|
145
|
+
EstimateResult
|
|
146
|
+
> = async (args, next, _ctx) => next(args);
|
|
147
|
+
|
|
148
|
+
// `overflowReduce` has a concrete arg/result shape (PR 23). Uses a
|
|
149
|
+
// dedicated passthrough that returns a structurally-correct result so
|
|
150
|
+
// `satisfies Plugin` keeps verifying the signature.
|
|
151
|
+
const overflowReducePassthrough: Middleware<
|
|
152
|
+
OverflowReduceArgs,
|
|
153
|
+
OverflowReduceResult
|
|
154
|
+
> = async (args, _next, _ctx) => ({
|
|
155
|
+
messages: args.messages,
|
|
156
|
+
runMessages: args.runMessages,
|
|
157
|
+
injectionMode: "full",
|
|
158
|
+
reducerState: {
|
|
159
|
+
appliedTiers: [],
|
|
160
|
+
injectionMode: "full",
|
|
161
|
+
exhausted: true,
|
|
162
|
+
},
|
|
163
|
+
reducerCompacted: false,
|
|
164
|
+
attempts: 0,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Slot-specific passthrough for the `compaction` pipeline — PR 25
|
|
168
|
+
// narrowed its args/result away from the generic `{ input: unknown }`
|
|
169
|
+
// placeholder, so the generic `passthrough` no longer satisfies its
|
|
170
|
+
// middleware signature. This dedicated middleware keeps the shape-only
|
|
171
|
+
// assertion for the slot without forcing every other slot to narrow.
|
|
172
|
+
const compactionPassthrough: Middleware<
|
|
173
|
+
CompactionArgs,
|
|
174
|
+
CompactionResult
|
|
175
|
+
> = async (args, next, _ctx) => next(args);
|
|
176
|
+
|
|
177
|
+
// `circuitBreaker` carries a concrete arg shape (pipeline wrapping
|
|
178
|
+
// landed ahead of the other slots) so it needs its own passthrough
|
|
179
|
+
// rather than reusing the generic placeholder.
|
|
180
|
+
const circuitPassthrough: Middleware<
|
|
181
|
+
CircuitBreakerArgs,
|
|
182
|
+
CircuitBreakerResult
|
|
183
|
+
> = async (args, next, _ctx) => next(args);
|
|
184
|
+
|
|
185
|
+
// `persistence` has concrete discriminated-union arg/result types
|
|
186
|
+
// (upgraded from the initial `{ input }/{ output }` placeholder in PR 27)
|
|
187
|
+
// so it gets its own passthrough rather than sharing the generic one
|
|
188
|
+
// above.
|
|
189
|
+
const persistPassthrough: Middleware<PersistArgs, PersistResult> = async (
|
|
190
|
+
args,
|
|
191
|
+
next,
|
|
192
|
+
_ctx,
|
|
193
|
+
) => next(args);
|
|
194
|
+
|
|
195
|
+
// The `titleGenerate` slot now has concrete arg/result types (PR 28)
|
|
196
|
+
// rather than the placeholder `{ input/output: unknown }` shape, so it
|
|
197
|
+
// needs its own passthrough implementation.
|
|
198
|
+
const titlePassthrough: Middleware<TitleArgs, TitleResult> = async (
|
|
199
|
+
args,
|
|
200
|
+
next,
|
|
201
|
+
_ctx,
|
|
202
|
+
) => next(args);
|
|
203
|
+
|
|
204
|
+
const injector: Injector = {
|
|
205
|
+
name: "sample-injector",
|
|
206
|
+
order: 10,
|
|
207
|
+
async produce(_ctx) {
|
|
208
|
+
return { id: "sample-block", text: "hello", meta: { kind: "demo" } };
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const sampleTool: Tool = {
|
|
213
|
+
name: "sample-tool",
|
|
214
|
+
description: "Sample plugin tool",
|
|
215
|
+
category: "plugins",
|
|
216
|
+
defaultRiskLevel: RiskLevel.Low,
|
|
217
|
+
getDefinition() {
|
|
218
|
+
return {
|
|
219
|
+
name: "sample-tool",
|
|
220
|
+
description: "Sample plugin tool",
|
|
221
|
+
input_schema: { type: "object", properties: {}, required: [] },
|
|
222
|
+
};
|
|
223
|
+
},
|
|
224
|
+
async execute() {
|
|
225
|
+
return { content: "ok", isError: false };
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const plugin = {
|
|
230
|
+
manifest,
|
|
231
|
+
async init(ctx: PluginInitContext) {
|
|
232
|
+
// Touch every field so refactors that rename any of them break here.
|
|
233
|
+
void ctx.config;
|
|
234
|
+
void ctx.credentials;
|
|
235
|
+
void ctx.logger;
|
|
236
|
+
void ctx.pluginStorageDir;
|
|
237
|
+
void ctx.assistantVersion;
|
|
238
|
+
void ctx.apiVersions;
|
|
239
|
+
},
|
|
240
|
+
async onShutdown() {
|
|
241
|
+
// no-op
|
|
242
|
+
},
|
|
243
|
+
tools: [sampleTool],
|
|
244
|
+
routes: [
|
|
245
|
+
{
|
|
246
|
+
pattern: /^\/sample$/,
|
|
247
|
+
methods: ["GET"],
|
|
248
|
+
handler: async () => new Response("ok", { status: 200 }),
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
skills: [
|
|
252
|
+
{
|
|
253
|
+
id: "sample-skill",
|
|
254
|
+
name: "Sample Skill",
|
|
255
|
+
description: "Demo plugin-contributed skill",
|
|
256
|
+
body: "## Sample\n\nPlugin-provided skill body.",
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
injectors: [injector],
|
|
260
|
+
middleware: {
|
|
261
|
+
turn: passthrough,
|
|
262
|
+
llmCall: llmCallPassthrough,
|
|
263
|
+
toolExecute: toolExecutePassthrough,
|
|
264
|
+
memoryRetrieval: memoryPassthrough,
|
|
265
|
+
historyRepair: passthroughHistoryRepair,
|
|
266
|
+
tokenEstimate: tokenEstimatePassthrough,
|
|
267
|
+
compaction: compactionPassthrough,
|
|
268
|
+
overflowReduce: overflowReducePassthrough,
|
|
269
|
+
persistence: persistPassthrough,
|
|
270
|
+
titleGenerate: titlePassthrough,
|
|
271
|
+
toolResultTruncate: truncatePassthrough,
|
|
272
|
+
emptyResponse: emptyResponsePassthrough,
|
|
273
|
+
toolError: toolErrorPassthrough,
|
|
274
|
+
circuitBreaker: circuitPassthrough,
|
|
275
|
+
},
|
|
276
|
+
} satisfies Plugin;
|
|
277
|
+
|
|
278
|
+
// Minimal runtime check so the test body is non-empty.
|
|
279
|
+
expect(plugin.manifest.name).toBe("sample-plugin");
|
|
280
|
+
expect(plugin.middleware.turn).toBe(passthrough);
|
|
281
|
+
expect(plugin.middleware.historyRepair).toBe(passthroughHistoryRepair);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test("PluginTimeoutError carries pipeline, plugin, and elapsed fields", () => {
|
|
285
|
+
const err = new PluginTimeoutError("compaction", "sample-plugin", 30000);
|
|
286
|
+
expect(err).toBeInstanceOf(Error);
|
|
287
|
+
expect(err.name).toBe("PluginTimeoutError");
|
|
288
|
+
expect(err.pipeline).toBe("compaction");
|
|
289
|
+
expect(err.pluginName).toBe("sample-plugin");
|
|
290
|
+
expect(err.elapsedMs).toBe(30000);
|
|
291
|
+
expect(err.message).toContain("compaction");
|
|
292
|
+
expect(err.message).toContain("30000");
|
|
293
|
+
expect(err.message).toContain("sample-plugin");
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
test("PluginTimeoutError omits plugin suffix when unknown", () => {
|
|
297
|
+
const err = new PluginTimeoutError("llmCall", undefined, 1234);
|
|
298
|
+
expect(err.pluginName).toBeUndefined();
|
|
299
|
+
expect(err.message).not.toContain("offending plugin");
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
test("PluginExecutionError carries the plugin name and message", () => {
|
|
303
|
+
const err = new PluginExecutionError(
|
|
304
|
+
"plugin 'x' requires memoryApi@v2, assistant exposes v1",
|
|
305
|
+
"x",
|
|
306
|
+
);
|
|
307
|
+
expect(err).toBeInstanceOf(Error);
|
|
308
|
+
expect(err.name).toBe("PluginExecutionError");
|
|
309
|
+
expect(err.pluginName).toBe("x");
|
|
310
|
+
expect(err.message).toContain("memoryApi@v2");
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
test("TurnContext references the canonical TrustContext", () => {
|
|
314
|
+
// Assignment is the real assertion — if `TurnContext.trust` drifts from
|
|
315
|
+
// `TrustContext` this fails to compile.
|
|
316
|
+
const ctx: TurnContext = sampleTurnContext;
|
|
317
|
+
expect(ctx.trust.trustClass).toBe("guardian");
|
|
318
|
+
expect(ctx.trust.sourceChannel).toBe("vellum");
|
|
319
|
+
});
|
|
320
|
+
});
|
|
@@ -30,7 +30,7 @@ describe("resolvePricing", () => {
|
|
|
30
30
|
1_000_000,
|
|
31
31
|
);
|
|
32
32
|
expect(result.pricingStatus).toBe("priced");
|
|
33
|
-
expect(result.estimatedCostUsd).toBe(
|
|
33
|
+
expect(result.estimatedCostUsd).toBe(5 + 25);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
test("returns priced for claude-sonnet-4", () => {
|
|
@@ -52,7 +52,7 @@ describe("resolvePricing", () => {
|
|
|
52
52
|
1_000_000,
|
|
53
53
|
);
|
|
54
54
|
expect(result.pricingStatus).toBe("priced");
|
|
55
|
-
expect(result.estimatedCostUsd).toBe(
|
|
55
|
+
expect(result.estimatedCostUsd).toBe(1 + 5);
|
|
56
56
|
});
|
|
57
57
|
});
|
|
58
58
|
|
|
@@ -202,7 +202,7 @@ describe("resolvePricing", () => {
|
|
|
202
202
|
1_000_000,
|
|
203
203
|
);
|
|
204
204
|
expect(result.pricingStatus).toBe("priced");
|
|
205
|
-
expect(result.estimatedCostUsd).toBe(
|
|
205
|
+
expect(result.estimatedCostUsd).toBe(5 + 25);
|
|
206
206
|
});
|
|
207
207
|
|
|
208
208
|
test("matches gpt-4o-mini-2024-07-18 via gpt-4o-mini prefix", () => {
|
|
@@ -269,6 +269,7 @@ describe("resolvePricingForUsage", () => {
|
|
|
269
269
|
);
|
|
270
270
|
|
|
271
271
|
expect(result.pricingStatus).toBe("priced");
|
|
272
|
+
// 5 (input) + 50 (output) + 0.15 (cache-read) + 1.25 (5m write) + 1.0 (1h write) = 57.4
|
|
272
273
|
expect(result.estimatedCostUsd).toBeCloseTo(57.4, 10);
|
|
273
274
|
});
|
|
274
275
|
|
|
@@ -306,7 +307,11 @@ describe("fast mode pricing", () => {
|
|
|
306
307
|
speed: "fast",
|
|
307
308
|
};
|
|
308
309
|
|
|
309
|
-
const result = resolvePricingForUsage(
|
|
310
|
+
const result = resolvePricingForUsage(
|
|
311
|
+
"anthropic",
|
|
312
|
+
"claude-opus-4-6",
|
|
313
|
+
usage,
|
|
314
|
+
);
|
|
310
315
|
|
|
311
316
|
// Base: $5 input + $25 output = $30; fast: $30 * 6 = $180
|
|
312
317
|
expect(result.pricingStatus).toBe("priced");
|
|
@@ -323,7 +328,11 @@ describe("fast mode pricing", () => {
|
|
|
323
328
|
speed: "standard",
|
|
324
329
|
};
|
|
325
330
|
|
|
326
|
-
const result = resolvePricingForUsage(
|
|
331
|
+
const result = resolvePricingForUsage(
|
|
332
|
+
"anthropic",
|
|
333
|
+
"claude-opus-4-6",
|
|
334
|
+
usage,
|
|
335
|
+
);
|
|
327
336
|
|
|
328
337
|
expect(result.pricingStatus).toBe("priced");
|
|
329
338
|
expect(result.estimatedCostUsd).toBe(5 + 25);
|
|
@@ -339,7 +348,11 @@ describe("fast mode pricing", () => {
|
|
|
339
348
|
speed: null,
|
|
340
349
|
};
|
|
341
350
|
|
|
342
|
-
const result = resolvePricingForUsage(
|
|
351
|
+
const result = resolvePricingForUsage(
|
|
352
|
+
"anthropic",
|
|
353
|
+
"claude-opus-4-6",
|
|
354
|
+
usage,
|
|
355
|
+
);
|
|
343
356
|
|
|
344
357
|
expect(result.pricingStatus).toBe("priced");
|
|
345
358
|
expect(result.estimatedCostUsd).toBe(5 + 25);
|
|
@@ -374,7 +387,9 @@ describe("fast mode pricing", () => {
|
|
|
374
387
|
expect(fastResult.pricingStatus).toBe("priced");
|
|
375
388
|
expect(standardResult.pricingStatus).toBe("priced");
|
|
376
389
|
// Fast mode applies 6x to base rates; cache multipliers stack on top
|
|
377
|
-
expect(fastResult.estimatedCostUsd).toBe(
|
|
390
|
+
expect(fastResult.estimatedCostUsd).toBe(
|
|
391
|
+
standardResult.estimatedCostUsd! * 6,
|
|
392
|
+
);
|
|
378
393
|
});
|
|
379
394
|
|
|
380
395
|
test("does not apply fast mode multiplier for non-Anthropic providers", () => {
|
|
@@ -459,7 +474,7 @@ describe("Anthropic models on OpenRouter", () => {
|
|
|
459
474
|
1_000_000,
|
|
460
475
|
);
|
|
461
476
|
expect(result.pricingStatus).toBe("priced");
|
|
462
|
-
expect(result.estimatedCostUsd).toBe(
|
|
477
|
+
expect(result.estimatedCostUsd).toBe(1 + 5);
|
|
463
478
|
});
|
|
464
479
|
|
|
465
480
|
test("prices bare claude-opus-4-6 slug returned unprefixed", () => {
|
|
@@ -528,7 +543,7 @@ describe("Anthropic models on OpenRouter", () => {
|
|
|
528
543
|
1_000_000,
|
|
529
544
|
);
|
|
530
545
|
expect(result.pricingStatus).toBe("priced");
|
|
531
|
-
expect(result.estimatedCostUsd).toBe(
|
|
546
|
+
expect(result.estimatedCostUsd).toBe(1 + 5);
|
|
532
547
|
});
|
|
533
548
|
|
|
534
549
|
test("returns unpriced for unknown anthropic model on OpenRouter", () => {
|
|
@@ -542,13 +557,24 @@ describe("Anthropic models on OpenRouter", () => {
|
|
|
542
557
|
expect(result.estimatedCostUsd).toBeNull();
|
|
543
558
|
});
|
|
544
559
|
|
|
545
|
-
test("
|
|
560
|
+
test("prices non-Anthropic OpenRouter model from catalog", () => {
|
|
546
561
|
const result = resolvePricing(
|
|
547
562
|
"openrouter",
|
|
548
563
|
"x-ai/grok-4.20-beta",
|
|
549
564
|
1_000_000,
|
|
550
565
|
1_000_000,
|
|
551
566
|
);
|
|
567
|
+
expect(result.pricingStatus).toBe("priced");
|
|
568
|
+
expect(result.estimatedCostUsd).toBe(3 + 15);
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
test("returns unpriced for unknown non-Anthropic OpenRouter model", () => {
|
|
572
|
+
const result = resolvePricing(
|
|
573
|
+
"openrouter",
|
|
574
|
+
"unknown-provider/some-model",
|
|
575
|
+
1_000_000,
|
|
576
|
+
1_000_000,
|
|
577
|
+
);
|
|
552
578
|
expect(result.pricingStatus).toBe("unpriced");
|
|
553
579
|
expect(result.estimatedCostUsd).toBeNull();
|
|
554
580
|
});
|
|
@@ -566,7 +592,11 @@ describe("Anthropic models on OpenRouter", () => {
|
|
|
566
592
|
"anthropic/claude-opus-4.6",
|
|
567
593
|
usage,
|
|
568
594
|
);
|
|
569
|
-
const direct = resolvePricingForUsage(
|
|
595
|
+
const direct = resolvePricingForUsage(
|
|
596
|
+
"anthropic",
|
|
597
|
+
"claude-opus-4-6",
|
|
598
|
+
usage,
|
|
599
|
+
);
|
|
570
600
|
|
|
571
601
|
// Cache-read tokens are charged at 10% of input rate for Anthropic models.
|
|
572
602
|
expect(openRouter.pricingStatus).toBe("priced");
|
|
@@ -623,7 +653,9 @@ describe("Anthropic models on OpenRouter", () => {
|
|
|
623
653
|
|
|
624
654
|
describe("usesAnthropicPricingRules", () => {
|
|
625
655
|
test("returns true for direct Anthropic", () => {
|
|
626
|
-
expect(usesAnthropicPricingRules("anthropic", "claude-opus-4-6")).toBe(
|
|
656
|
+
expect(usesAnthropicPricingRules("anthropic", "claude-opus-4-6")).toBe(
|
|
657
|
+
true,
|
|
658
|
+
);
|
|
627
659
|
});
|
|
628
660
|
|
|
629
661
|
test("returns true for anthropic/* on OpenRouter", () => {
|
|
@@ -133,13 +133,6 @@ describe("createProxyApprovalCallback", () => {
|
|
|
133
133
|
test("returns true when user allows an ask_missing_credential request", async () => {
|
|
134
134
|
const ctx = makeContext();
|
|
135
135
|
|
|
136
|
-
const _resolvePrompt:
|
|
137
|
-
| ((v: {
|
|
138
|
-
decision: string;
|
|
139
|
-
selectedPattern?: string;
|
|
140
|
-
selectedScope?: string;
|
|
141
|
-
}) => void)
|
|
142
|
-
| null = null;
|
|
143
136
|
const prompterSendToClient = mock(() => {});
|
|
144
137
|
const prompter = new PermissionPrompter(prompterSendToClient);
|
|
145
138
|
|
|
@@ -381,7 +374,14 @@ describe("createProxyApprovalCallback", () => {
|
|
|
381
374
|
// Verify the confirmation request uses the network_request tool name
|
|
382
375
|
expect(msg.toolName).toBe("network_request");
|
|
383
376
|
expect(msg.input).toHaveProperty("url", "https://api.fal.ai:443/v1/run");
|
|
384
|
-
expect(msg.input).toHaveProperty("
|
|
377
|
+
expect(msg.input).toHaveProperty("scheme", "https");
|
|
378
|
+
expect(msg.input).toHaveProperty("known_credential_patterns", [
|
|
379
|
+
"*.fal.ai",
|
|
380
|
+
]);
|
|
381
|
+
expect(msg.input.reason).toMatch(
|
|
382
|
+
/A known credential template matches this host.*caller-supplied auth headers will still be sent/,
|
|
383
|
+
);
|
|
384
|
+
expect(msg.input).not.toHaveProperty("proxy_session_id");
|
|
385
385
|
prompter.resolveConfirmation(msg.requestId, "allow");
|
|
386
386
|
return p;
|
|
387
387
|
};
|
|
@@ -390,6 +390,67 @@ describe("createProxyApprovalCallback", () => {
|
|
|
390
390
|
await callback(makeAskMissingCredentialRequest());
|
|
391
391
|
});
|
|
392
392
|
|
|
393
|
+
test("surfaces method and curated headers when the proxy has HTTP-level context", async () => {
|
|
394
|
+
const ctx = makeContext();
|
|
395
|
+
const prompterSendToClient = mock(() => {});
|
|
396
|
+
const prompter = new PermissionPrompter(prompterSendToClient);
|
|
397
|
+
|
|
398
|
+
const originalPrompt = prompter.prompt.bind(prompter);
|
|
399
|
+
prompter.prompt = async (...args) => {
|
|
400
|
+
const p = originalPrompt(...args);
|
|
401
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
402
|
+
const call = (prompterSendToClient.mock.calls as unknown[][])[0];
|
|
403
|
+
const msg = call[0] as {
|
|
404
|
+
requestId: string;
|
|
405
|
+
input: Record<string, unknown>;
|
|
406
|
+
};
|
|
407
|
+
expect(msg.input).toHaveProperty("method", "POST");
|
|
408
|
+
expect(msg.input).toHaveProperty("request_headers", {
|
|
409
|
+
"content-type": "application/json",
|
|
410
|
+
"user-agent": "curl/8.5.0",
|
|
411
|
+
});
|
|
412
|
+
expect(msg.input).not.toHaveProperty("connection_detail_available");
|
|
413
|
+
prompter.resolveConfirmation(msg.requestId, "allow");
|
|
414
|
+
return p;
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
const callback = createProxyApprovalCallback(prompter, ctx);
|
|
418
|
+
await callback(
|
|
419
|
+
makeAskUnauthenticatedRequest({
|
|
420
|
+
method: "POST",
|
|
421
|
+
requestHeaders: {
|
|
422
|
+
"content-type": "application/json",
|
|
423
|
+
"user-agent": "curl/8.5.0",
|
|
424
|
+
},
|
|
425
|
+
}),
|
|
426
|
+
);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
test("marks connection_detail_available=no for HTTPS CONNECT approvals", async () => {
|
|
430
|
+
const ctx = makeContext();
|
|
431
|
+
const prompterSendToClient = mock(() => {});
|
|
432
|
+
const prompter = new PermissionPrompter(prompterSendToClient);
|
|
433
|
+
|
|
434
|
+
const originalPrompt = prompter.prompt.bind(prompter);
|
|
435
|
+
prompter.prompt = async (...args) => {
|
|
436
|
+
const p = originalPrompt(...args);
|
|
437
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
438
|
+
const call = (prompterSendToClient.mock.calls as unknown[][])[0];
|
|
439
|
+
const msg = call[0] as {
|
|
440
|
+
requestId: string;
|
|
441
|
+
input: Record<string, unknown>;
|
|
442
|
+
};
|
|
443
|
+
expect(msg.input).toHaveProperty("connection_detail_available", "no");
|
|
444
|
+
expect(msg.input).not.toHaveProperty("method");
|
|
445
|
+
expect(msg.input).not.toHaveProperty("request_headers");
|
|
446
|
+
prompter.resolveConfirmation(msg.requestId, "allow");
|
|
447
|
+
return p;
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
const callback = createProxyApprovalCallback(prompter, ctx);
|
|
451
|
+
await callback(makeAskUnauthenticatedRequest());
|
|
452
|
+
});
|
|
453
|
+
|
|
393
454
|
test("sends correct tool name for ask_unauthenticated decisions", async () => {
|
|
394
455
|
const ctx = makeContext();
|
|
395
456
|
const prompterSendToClient = mock(() => {});
|
|
@@ -117,8 +117,6 @@ describe("tool manifest", () => {
|
|
|
117
117
|
expect(names).toContain("recall");
|
|
118
118
|
expect(names).toContain("remember");
|
|
119
119
|
expect(names).toContain("credential_store");
|
|
120
|
-
// start_screen_watch moved to the screen-watch bundled skill
|
|
121
|
-
expect(names).not.toContain("start_screen_watch");
|
|
122
120
|
});
|
|
123
121
|
|
|
124
122
|
test("registered tool count is at least eager + host", async () => {
|