@vellumai/assistant 0.9.0 → 0.10.0-dev.202606192226.8ed8a6a
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/ARCHITECTURE.md +19 -35
- package/bun.lock +7 -8
- package/docs/activation-funnel-telemetry.md +28 -22
- package/docs/architecture/security.md +29 -28
- package/docs/stt-provider-onboarding.md +3 -5
- package/docs/workflows-testing.md +13 -44
- package/docs/workflows.md +3 -5
- package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
- package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +32 -6
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
- package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
- package/openapi.yaml +1128 -119
- package/package.json +2 -1
- package/scripts/sync-llm-catalog.ts +6 -15
- package/scripts/sync-web-search-catalog.ts +3 -11
- package/src/__tests__/access-request-card-view.test.ts +98 -0
- package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +72 -32
- package/src/__tests__/agent-loop-compaction-strip.test.ts +241 -0
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
- package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
- package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
- package/src/__tests__/app-compiler.test.ts +15 -1
- package/src/__tests__/app-dir-path-guard.test.ts +0 -1
- package/src/__tests__/approval-cascade.test.ts +6 -0
- package/src/__tests__/approval-routes-http.test.ts +128 -0
- package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
- package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
- package/src/__tests__/avatar-identity-sync.test.ts +2 -27
- package/src/__tests__/btw-routes.test.ts +6 -8
- package/src/__tests__/call-pointer-messages.test.ts +28 -0
- package/src/__tests__/cancel-clears-processing.test.ts +89 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -4
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
- package/src/__tests__/checker.test.ts +0 -3
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
- package/src/__tests__/compaction-events.test.ts +6 -0
- package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
- package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
- package/src/__tests__/config-loader-backfill.test.ts +268 -27
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/config-watcher.test.ts +0 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +0 -6
- package/src/__tests__/contacts-tools.test.ts +29 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +58 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
- package/src/__tests__/conversation-lifecycle.test.ts +7 -9
- package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
- package/src/__tests__/conversation-process-callsite.test.ts +6 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-queue.test.ts +6 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
- package/src/__tests__/conversation-slash-queue.test.ts +6 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +6 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
- package/src/__tests__/conversation-title-service.test.ts +62 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/credential-broker.test.ts +449 -1
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
- package/src/__tests__/credential-execution-tools.test.ts +0 -1
- package/src/__tests__/credential-prompt-route.test.ts +4 -4
- package/src/__tests__/credential-routes.test.ts +360 -0
- package/src/__tests__/credential-security-invariants.test.ts +4 -13
- package/src/__tests__/disk-pressure-policy.test.ts +12 -0
- package/src/__tests__/disk-pressure-tools.test.ts +41 -1
- package/src/__tests__/disk-usage.test.ts +65 -0
- package/src/__tests__/document-tool-security.test.ts +9 -6
- package/src/__tests__/document-update-default-surface.test.ts +202 -0
- package/src/__tests__/dynamic-page-surface.test.ts +152 -1
- package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
- package/src/__tests__/gateway-flag-listener.test.ts +110 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -7
- package/src/__tests__/gemini-count-tokens.test.ts +70 -0
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
- package/src/__tests__/guardian-grant-minting.test.ts +3 -35
- package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
- package/src/__tests__/guardian-routing-state.test.ts +0 -1
- package/src/__tests__/headless-browser-mode.test.ts +10 -0
- package/src/__tests__/headless-browser-navigate.test.ts +8 -3
- package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
- package/src/__tests__/host-browser-proxy.test.ts +87 -0
- package/src/__tests__/identity-routes.test.ts +0 -189
- package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
- package/src/__tests__/injector-disk-pressure.test.ts +10 -5
- package/src/__tests__/injector-v3-suppression.test.ts +27 -20
- package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
- package/src/__tests__/invite-redemption-service.test.ts +4 -7
- package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
- package/src/__tests__/llm-catalog-parity.test.ts +30 -23
- package/src/__tests__/llm-resolver.test.ts +70 -24
- package/src/__tests__/llm-schema.test.ts +1 -0
- package/src/__tests__/managed-profile-guard.test.ts +163 -4
- package/src/__tests__/mcp-health-check.test.ts +6 -7
- package/src/__tests__/media-stream-server-integration.test.ts +317 -13
- package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
- package/src/__tests__/onboarding-persona-write.test.ts +1 -1
- package/src/__tests__/path-policy.test.ts +34 -0
- package/src/__tests__/persona-resolver.test.ts +49 -14
- package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
- package/src/__tests__/plugin-api-provider.test.ts +24 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
- package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
- package/src/__tests__/reaction-persistence.test.ts +150 -29
- package/src/__tests__/registry.test.ts +2 -7
- package/src/__tests__/relay-server.test.ts +285 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
- package/src/__tests__/schedule-routes.test.ts +0 -30
- package/src/__tests__/schedule-tools.test.ts +2 -18
- package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
- package/src/__tests__/secret-response-routing.test.ts +35 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +16 -2
- package/src/__tests__/skill-execute-input.test.ts +177 -1
- package/src/__tests__/skill-load-tool.test.ts +72 -0
- package/src/__tests__/skill-runtime-path.test.ts +2 -3
- package/src/__tests__/skills.test.ts +51 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
- package/src/__tests__/subagent-tools.test.ts +266 -0
- package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
- package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
- package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
- package/src/__tests__/title-generate-hook.test.ts +100 -3
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
- package/src/__tests__/token-manager.test.ts +519 -0
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
- package/src/__tests__/tool-audit-listener.test.ts +7 -7
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
- package/src/__tests__/tool-executor.test.ts +0 -79
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
- package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
- package/src/__tests__/trusted-contact-verification.test.ts +8 -10
- package/src/__tests__/twilio-routes.test.ts +81 -1
- package/src/__tests__/voice-invite-redemption.test.ts +2 -3
- package/src/__tests__/weak-open-model.test.ts +30 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
- package/src/__tests__/workspace-greetings.test.ts +152 -0
- package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
- package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
- package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
- package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
- package/src/agent/loop.ts +75 -29
- package/src/api/README.md +6 -6
- package/src/api/events/tool-result.ts +6 -0
- package/src/api/events/workflow-completed.ts +53 -0
- package/src/api/events/workflow-leaf-finished.ts +38 -0
- package/src/api/events/workflow-leaf-started.ts +35 -0
- package/src/api/events/workflow-progress.ts +32 -0
- package/src/api/events/workflow-started.ts +31 -0
- package/src/api/index.ts +40 -0
- package/src/api/responses/conversation-message.ts +28 -4
- package/src/api/responses/home.ts +26 -4
- package/src/api/responses/workflow-journal.ts +53 -0
- package/src/approvals/guardian-card-withdrawal.ts +145 -0
- package/src/approvals/guardian-decision-primitive.ts +26 -3
- package/src/approvals/guardian-request-resolvers.ts +183 -80
- package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
- package/src/calls/call-pointer-messages.ts +10 -4
- package/src/calls/channel-admission-reader.ts +104 -0
- package/src/calls/guardian-dispatch.ts +17 -45
- package/src/calls/media-stream-server.ts +84 -2
- package/src/calls/relay-access-wait.ts +1 -1
- package/src/calls/relay-server.ts +66 -0
- package/src/calls/relay-setup-router.ts +82 -1
- package/src/calls/twilio-routes.ts +17 -8
- package/src/calls/voice-session-bridge.ts +2 -2
- package/src/cli/commands/clients.ts +3 -0
- package/src/cli/commands/db/status.ts +37 -3
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
- package/src/cli/commands/memory/index.ts +30 -0
- package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
- package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
- package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
- package/src/cli/commands/oauth/status.test.ts +36 -0
- package/src/cli/commands/oauth/status.ts +23 -3
- package/src/cli/commands/plugins.ts +400 -14
- package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +31 -0
- package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
- package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
- package/src/cli/lib/diff-plugin.ts +346 -0
- package/src/cli/lib/inspect-plugin.ts +12 -1
- package/src/cli/lib/install-from-github.ts +128 -19
- package/src/cli/lib/merge-plugin-tree.ts +328 -0
- package/src/cli/lib/plugin-fingerprint.ts +14 -0
- package/src/cli/lib/plugin-marketplace.ts +11 -0
- package/src/cli/lib/plugin-pin-history.ts +257 -0
- package/src/cli/lib/plugin-surfaces.ts +104 -0
- package/src/cli/lib/upgrade-plugin.ts +298 -10
- package/src/cli/program.ts +2 -6
- package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
- package/src/config/assistant-feature-flags.ts +22 -7
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
- package/src/config/bundled-skills/document-editor/SKILL.md +3 -3
- package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
- package/src/config/bundled-skills/messaging/SKILL.md +6 -4
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
- package/src/config/bundled-skills/subagent/SKILL.md +4 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
- package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
- package/src/config/bundled-skills/workflows/SKILL.md +14 -8
- package/src/config/bundled-tool-registry.ts +2 -7
- package/src/config/call-site-defaults.ts +15 -2
- package/src/config/feature-flag-registry.json +46 -31
- package/src/config/inference-profile-validation.ts +26 -0
- package/src/config/llm-resolver.ts +3 -0
- package/src/config/loader.ts +4 -0
- package/src/config/memory-v3-gate.ts +11 -0
- package/src/config/profile-order.ts +28 -0
- package/src/config/schema.ts +8 -6
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/channels.ts +11 -0
- package/src/config/schemas/elevenlabs.ts +0 -1
- package/src/config/schemas/llm.ts +31 -0
- package/src/config/schemas/memory-lifecycle.ts +3 -7
- package/src/config/schemas/memory-v3.ts +6 -0
- package/src/config/schemas/platform.ts +0 -8
- package/src/config/schemas/services.ts +18 -0
- package/src/config/seed-inference-profiles.ts +109 -44
- package/src/config/skills.ts +21 -0
- package/src/config/sync-gated-profiles.ts +220 -0
- package/src/contacts/contact-store.ts +89 -106
- package/src/contacts/contacts-write.ts +5 -22
- package/src/contacts/types.ts +0 -1
- package/src/context/compactor.ts +88 -54
- package/src/context/strip-injections.ts +58 -10
- package/src/context/token-estimator.ts +1 -1
- package/src/credential-execution/process-manager.ts +55 -14
- package/src/credential-execution/prompted-credential.ts +2 -3
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
- package/src/daemon/config-watcher.ts +0 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
- package/src/daemon/conversation-agent-loop.ts +114 -22
- package/src/daemon/conversation-history.ts +1 -1
- package/src/daemon/conversation-lifecycle.ts +3 -5
- package/src/daemon/conversation-process.ts +13 -5
- package/src/daemon/conversation-runtime-assembly.ts +13 -15
- package/src/daemon/conversation-slash.ts +2 -23
- package/src/daemon/conversation-surfaces.ts +26 -0
- package/src/daemon/conversation-tool-setup.ts +53 -19
- package/src/daemon/conversation.ts +131 -20
- package/src/daemon/disk-pressure-policy.ts +5 -3
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
- package/src/daemon/handlers/config-a2a.ts +0 -2
- package/src/daemon/handlers/config-channels.ts +15 -16
- package/src/daemon/handlers/config-slack-channel.ts +22 -3
- package/src/daemon/handlers/conversations.ts +107 -0
- package/src/daemon/host-browser-proxy.ts +41 -0
- package/src/daemon/lifecycle.ts +55 -27
- package/src/daemon/memory-v2-startup.test.ts +131 -0
- package/src/daemon/memory-v2-startup.ts +100 -1
- package/src/daemon/message-provenance.ts +2 -0
- package/src/daemon/message-types/contacts.ts +0 -1
- package/src/daemon/message-types/conversations.ts +3 -3
- package/src/daemon/message-types/sync.ts +0 -1
- package/src/daemon/message-types/web-activity.ts +7 -1
- package/src/daemon/message-types/workflows.ts +83 -1
- package/src/daemon/orphan-reaper.test.ts +0 -19
- package/src/daemon/orphan-reaper.ts +2 -24
- package/src/daemon/server.ts +0 -10
- package/src/daemon/tool-setup-types.ts +4 -0
- package/src/daemon/trust-context.ts +1 -1
- package/src/daemon/wake-conversation-ops.ts +1 -0
- package/src/events/tool-audit-listener.ts +2 -2
- package/src/home/feed-source-enrichment.test.ts +151 -0
- package/src/home/feed-source-enrichment.ts +176 -0
- package/src/home/relationship-state.ts +2 -4
- package/src/instrument.ts +18 -6
- package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
- package/src/ipc/assistant-server.ts +37 -4
- package/src/ipc/gateway-flag-listener.ts +18 -2
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
- package/src/memory/__tests__/db-logs-attach.test.ts +122 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
- package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
- package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
- package/src/memory/auth-fallback-events-store.ts +2 -2
- package/src/memory/auto-analysis-enqueue.ts +3 -5
- package/src/memory/bookmark-crud.ts +1 -2
- package/src/memory/canonical-guardian-store.ts +39 -1
- package/src/memory/conversation-crud.ts +9 -4
- package/src/memory/conversation-key-store.ts +17 -2
- package/src/memory/conversation-title-service.ts +64 -7
- package/src/memory/db-async-query.ts +20 -2
- package/src/memory/db-connection.ts +49 -5
- package/src/memory/db-init.ts +17 -17
- package/src/memory/embedding-backend.ts +38 -1
- package/src/memory/embedding-billing-breaker.ts +96 -0
- package/src/memory/jobs-store.ts +25 -13
- package/src/memory/jobs-worker.ts +54 -1
- package/src/memory/lifecycle-events-store.ts +2 -2
- package/src/memory/memory-retrospective-constants.ts +4 -4
- package/src/memory/memory-retrospective-enqueue.ts +31 -6
- package/src/memory/memory-retrospective-job.ts +28 -227
- package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
- package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
- package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
- package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
- package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
- package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
- package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
- package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
- package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
- package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/run-migrations.ts +41 -0
- package/src/memory/migrations/validate-migration-state.ts +1 -1
- package/src/memory/onboarding-events-store.ts +3 -3
- package/src/memory/schema/contacts.ts +0 -5
- package/src/memory/skill-loaded-events-store.test.ts +7 -15
- package/src/memory/skill-loaded-events-store.ts +2 -2
- package/src/memory/tool-executed-events-store.test.ts +7 -7
- package/src/memory/turn-trace-store.test.ts +736 -0
- package/src/memory/turn-trace-store.ts +364 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
- package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
- package/src/memory/v2/consolidation-job.ts +2 -2
- package/src/memory/v2/skill-content.ts +25 -7
- package/src/memory/v2/skill-store.ts +7 -1
- package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
- package/src/memory/v3-eval/eval-packets.ts +546 -0
- package/src/messaging/providers/slack/adapter.ts +1 -1
- package/src/messaging/providers/slack/api.ts +31 -0
- package/src/messaging/providers/slack/send.test.ts +114 -2
- package/src/messaging/providers/slack/send.ts +30 -7
- package/src/messaging/providers/slack/withdraw.test.ts +200 -0
- package/src/messaging/providers/slack/withdraw.ts +161 -0
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/access-request-copy.ts +72 -59
- package/src/notifications/adapters/shared.ts +29 -0
- package/src/notifications/adapters/slack.ts +58 -103
- package/src/notifications/adapters/telegram.ts +2 -20
- package/src/notifications/approval-card-data.ts +333 -0
- package/src/notifications/broadcaster.ts +16 -3
- package/src/notifications/canonical-delivery-recorder.ts +139 -0
- package/src/notifications/copy-composer.ts +3 -3
- package/src/notifications/decision-engine.ts +4 -2
- package/src/notifications/destination-resolver.ts +4 -6
- package/src/notifications/guardian-question-mode.ts +10 -0
- package/src/notifications/home-feed-side-effect.ts +7 -16
- package/src/notifications/notification-utils.ts +19 -20
- package/src/notifications/signal.ts +79 -43
- package/src/notifications/types.ts +98 -121
- package/src/oauth/AGENTS.md +5 -24
- package/src/permissions/checker.test.ts +51 -0
- package/src/permissions/checker.ts +185 -26
- package/src/permissions/ipc-risk-types.ts +24 -0
- package/src/permissions/question-prompter.test.ts +27 -0
- package/src/permissions/question-prompter.ts +4 -0
- package/src/permissions/secret-prompter.ts +15 -1
- package/src/platform/client.test.ts +119 -0
- package/src/platform/client.ts +66 -0
- package/src/platform/consent-cache.test.ts +267 -0
- package/src/platform/consent-cache.ts +174 -0
- package/src/plugin-api/constants.ts +1 -1
- package/src/plugin-api/index.ts +33 -1
- package/src/plugin-api/model-profiles.ts +33 -0
- package/src/plugin-api/types.ts +50 -2
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
- package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
- package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
- package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
- package/src/plugins/defaults/advisor/config.ts +21 -0
- package/src/plugins/defaults/advisor/consult.ts +93 -0
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/advisor/package.json +14 -0
- package/src/plugins/defaults/advisor/steering.ts +67 -0
- package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
- package/src/plugins/defaults/advisor/transcript.ts +76 -0
- package/src/plugins/defaults/compaction/window-manager.ts +18 -0
- package/src/plugins/defaults/index.ts +60 -0
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
- package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
- package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
- package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
- package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
- package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
- package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
- package/src/prompts/persona-resolver.ts +14 -4
- package/src/prompts/templates/system-sections.ts +7 -2
- package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
- package/src/providers/__tests__/retry-callsite.test.ts +176 -0
- package/src/providers/anthropic/client.ts +230 -175
- package/src/providers/atlascloud/client.ts +85 -0
- package/src/providers/call-site-routing.ts +10 -0
- package/src/providers/fetch-provider-catalog.ts +85 -0
- package/src/providers/gemini/client.ts +43 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/model-catalog.ts +58 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
- package/src/providers/openai/chat-completions-provider.ts +7 -0
- package/src/providers/openai/responses-provider.ts +10 -0
- package/src/providers/provider-send-message.ts +11 -3
- package/src/providers/ratelimit.ts +9 -0
- package/src/providers/retry.ts +62 -12
- package/src/providers/search-provider-catalog.ts +10 -0
- package/src/providers/types.ts +16 -0
- package/src/providers/usage-tracking.ts +7 -0
- package/src/providers/weak-open-model.ts +22 -0
- package/src/runtime/AGENTS.md +0 -1
- package/src/runtime/__tests__/agent-wake.test.ts +227 -0
- package/src/runtime/__tests__/client-health.test.ts +44 -0
- package/src/runtime/access-request-helper.ts +21 -53
- package/src/runtime/actor-trust-resolver.ts +59 -63
- package/src/runtime/agent-wake.ts +71 -0
- package/src/runtime/assistant-event-hub.ts +18 -4
- package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
- package/src/runtime/auth/require-bound-guardian.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -6
- package/src/runtime/capabilities.test.ts +120 -0
- package/src/runtime/capabilities.ts +197 -0
- package/src/runtime/channel-approval-types.ts +22 -45
- package/src/runtime/channel-invite-transports/telegram.ts +4 -4
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/channel-verification-service.ts +3 -3
- package/src/runtime/client-health.ts +26 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
- package/src/runtime/effective-capabilities.test.ts +128 -0
- package/src/runtime/effective-capabilities.ts +84 -0
- package/src/runtime/guardian-reply-router.ts +106 -21
- package/src/runtime/invite-redemption-service.ts +9 -25
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +126 -0
- package/src/runtime/migrations/vbundle-builder.ts +49 -20
- package/src/runtime/pending-interactions.ts +35 -0
- package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +383 -1
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/approval-routes.ts +40 -9
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
- package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
- package/src/runtime/routes/browser-tabs-routes.ts +9 -0
- package/src/runtime/routes/btw-routes.ts +1 -27
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
- package/src/runtime/routes/client-routes.ts +10 -0
- package/src/runtime/routes/contact-routes.ts +31 -8
- package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
- package/src/runtime/routes/conversation-management-routes.ts +80 -1
- package/src/runtime/routes/conversation-query-routes.ts +68 -22
- package/src/runtime/routes/conversation-routes.ts +39 -14
- package/src/runtime/routes/credential-routes.ts +40 -16
- package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
- package/src/runtime/routes/events-routes.ts +1 -3
- package/src/runtime/routes/guardian-approval-interception.ts +14 -73
- package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
- package/src/runtime/routes/home-feed-routes.ts +8 -3
- package/src/runtime/routes/identity-routes.ts +1 -296
- package/src/runtime/routes/inbound-message-handler.ts +214 -228
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
- package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
- package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
- package/src/runtime/routes/integrations/slack/channel.ts +36 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
- package/src/runtime/routes/mcp-auth-routes.ts +233 -41
- package/src/runtime/routes/memory-eval-routes.ts +87 -0
- package/src/runtime/routes/notification-routes.ts +122 -133
- package/src/runtime/routes/platform-routes.ts +2 -2
- package/src/runtime/routes/plugins-routes.ts +366 -11
- package/src/runtime/routes/schedule-routes.ts +0 -22
- package/src/runtime/routes/secret-routes.ts +15 -0
- package/src/runtime/routes/surface-action-routes.ts +2 -1
- package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
- package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
- package/src/runtime/routes/workflow-routes.test.ts +229 -44
- package/src/runtime/routes/workflow-routes.ts +131 -29
- package/src/runtime/routes/workspace-greetings.ts +55 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -11
- package/src/runtime/tool-grant-request-helper.ts +18 -16
- package/src/runtime/trust-context-resolver.ts +8 -5
- package/src/schedule/inference-profile.ts +2 -14
- package/src/schedule/schedule-store.ts +1 -1
- package/src/schedule/scheduler-types.ts +5 -1
- package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
- package/src/security/secret-patterns.ts +3 -0
- package/src/subagent/manager.ts +17 -4
- package/src/subagent/types.ts +6 -0
- package/src/telemetry/trace-collection-policy.test.ts +28 -0
- package/src/telemetry/trace-collection-policy.ts +30 -0
- package/src/telemetry/types.ts +89 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
- package/src/telemetry/usage-telemetry-reporter.ts +148 -41
- package/src/tools/AGENTS.md +3 -3
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
- package/src/tools/browser/browser-execution.ts +30 -19
- package/src/tools/document/document-tool.ts +30 -6
- package/src/tools/executor.ts +5 -3
- package/src/tools/host-terminal/host-shell.ts +5 -4
- package/src/tools/memory/register.ts +2 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
- package/src/tools/network/__tests__/web-search.test.ts +143 -0
- package/src/tools/network/web-fetch.ts +372 -1
- package/src/tools/network/web-search-error.ts +1 -1
- package/src/tools/network/web-search.ts +213 -10
- package/src/tools/permission-checker.ts +4 -3
- package/src/tools/registry.ts +20 -0
- package/src/tools/schedule/create.ts +7 -12
- package/src/tools/schedule/update.ts +4 -11
- package/src/tools/shared/filesystem/path-policy.ts +39 -13
- package/src/tools/side-effects.ts +2 -17
- package/src/tools/skills/execute.ts +99 -2
- package/src/tools/skills/load.ts +43 -2
- package/src/tools/subagent/spawn.ts +64 -15
- package/src/tools/terminal/shell.ts +10 -4
- package/src/tools/tool-approval-handler.ts +18 -13
- package/src/tools/tool-manifest.ts +0 -2
- package/src/tools/types.ts +10 -0
- package/src/tools/ui-surface/definitions.ts +64 -3
- package/src/tools/verification-control-plane-policy.ts +3 -1
- package/src/tools/workflows/run-workflow.test.ts +8 -18
- package/src/tools/workflows/run-workflow.ts +1 -0
- package/src/util/disk-usage.ts +78 -23
- package/src/util/logs-db-path.ts +22 -0
- package/src/util/platform.ts +10 -3
- package/src/watcher/telemetry.ts +2 -2
- package/src/workflows/capabilities.ts +2 -3
- package/src/workflows/engine.test.ts +175 -1
- package/src/workflows/engine.ts +82 -0
- package/src/workflows/journal-store.test.ts +70 -0
- package/src/workflows/journal-store.ts +18 -3
- package/src/workflows/run-manager.test.ts +171 -28
- package/src/workflows/run-manager.ts +66 -24
- package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
- package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
- package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
- package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
- package/src/__tests__/credential-security-e2e.test.ts +0 -362
- package/src/__tests__/credential-vault-unit.test.ts +0 -1528
- package/src/__tests__/credential-vault.test.ts +0 -1706
- package/src/__tests__/identity-intro-cache.test.ts +0 -315
- package/src/__tests__/secret-onetime-send.test.ts +0 -182
- package/src/cli/commands/__tests__/task.test.ts +0 -914
- package/src/cli/commands/task.ts +0 -771
- package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
- package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
- package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
- package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
- package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
- package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
- package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
- package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
- package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
- package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
- package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
- package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
- package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
- package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
- package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
- package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
- package/src/memory/preloaded-apps.ts +0 -116
- package/src/notifications/tool-approval-copy.ts +0 -142
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
- package/src/runtime/routes/identity-intro-cache.ts +0 -172
- package/src/tools/credentials/vault.ts +0 -712
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for render-time enrichment of history tool calls with the in-flight
|
|
3
|
+
* `ask_question` prompt read from the pending-interactions registry.
|
|
4
|
+
*/
|
|
5
|
+
import { afterEach, describe, expect, test } from "bun:test";
|
|
6
|
+
|
|
7
|
+
import type { QuestionEntry } from "../../api/events/question-request.js";
|
|
8
|
+
import type { ConversationMessageToolCall } from "../../api/responses/conversation-message.js";
|
|
9
|
+
import { clear, register } from "../pending-interactions.js";
|
|
10
|
+
import {
|
|
11
|
+
collectPendingQuestions,
|
|
12
|
+
enrichToolCallsWithQuestion,
|
|
13
|
+
} from "./tool-call-question-enrichment.js";
|
|
14
|
+
|
|
15
|
+
function toolCall(
|
|
16
|
+
overrides: Partial<ConversationMessageToolCall>,
|
|
17
|
+
): ConversationMessageToolCall {
|
|
18
|
+
return {
|
|
19
|
+
name: "ask_question",
|
|
20
|
+
input: {},
|
|
21
|
+
...overrides,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const ENTRIES: QuestionEntry[] = [
|
|
26
|
+
{
|
|
27
|
+
id: "q1",
|
|
28
|
+
question: "What's the email about?",
|
|
29
|
+
options: [
|
|
30
|
+
{ id: "a", label: "iOS app is live" },
|
|
31
|
+
{ id: "b", label: "Open source" },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
clear();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe("collectPendingQuestions", () => {
|
|
41
|
+
test("keys question interactions by toolUseId", () => {
|
|
42
|
+
// GIVEN a question interaction registered for a conversation with a
|
|
43
|
+
// tool-use id and the full question entries
|
|
44
|
+
register("req-1", {
|
|
45
|
+
conversationId: "conv-1",
|
|
46
|
+
kind: "question",
|
|
47
|
+
toolUseId: "tool-abc",
|
|
48
|
+
questionDetails: { entries: ENTRIES },
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// WHEN we collect the conversation's pending questions
|
|
52
|
+
const byToolUseId = collectPendingQuestions("conv-1");
|
|
53
|
+
|
|
54
|
+
// THEN the interaction is keyed by its tool-use id
|
|
55
|
+
expect(byToolUseId.size).toBe(1);
|
|
56
|
+
expect(byToolUseId.get("tool-abc")?.requestId).toBe("req-1");
|
|
57
|
+
expect(byToolUseId.get("tool-abc")?.entries).toEqual(ENTRIES);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("ignores interactions lacking a toolUseId, details, or the question kind", () => {
|
|
61
|
+
// GIVEN a question without a toolUseId, a question without details, AND a
|
|
62
|
+
// non-question interaction in the same conversation
|
|
63
|
+
register("req-no-tool", {
|
|
64
|
+
conversationId: "conv-2",
|
|
65
|
+
kind: "question",
|
|
66
|
+
questionDetails: { entries: ENTRIES },
|
|
67
|
+
});
|
|
68
|
+
register("req-no-details", {
|
|
69
|
+
conversationId: "conv-2",
|
|
70
|
+
kind: "question",
|
|
71
|
+
toolUseId: "tool-no-details",
|
|
72
|
+
});
|
|
73
|
+
register("req-confirmation", {
|
|
74
|
+
conversationId: "conv-2",
|
|
75
|
+
kind: "confirmation",
|
|
76
|
+
toolUseId: "tool-xyz",
|
|
77
|
+
confirmationDetails: {
|
|
78
|
+
toolName: "file_read",
|
|
79
|
+
input: {},
|
|
80
|
+
riskLevel: "low",
|
|
81
|
+
allowlistOptions: [],
|
|
82
|
+
scopeOptions: [],
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// WHEN we collect the conversation's pending questions
|
|
87
|
+
const byToolUseId = collectPendingQuestions("conv-2");
|
|
88
|
+
|
|
89
|
+
// THEN none is included
|
|
90
|
+
expect(byToolUseId.size).toBe(0);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe("enrichToolCallsWithQuestion", () => {
|
|
95
|
+
test("stamps the pending question when the registry has a match", () => {
|
|
96
|
+
// GIVEN a registry entry matching the tool call by id
|
|
97
|
+
register("req-1", {
|
|
98
|
+
conversationId: "conv-fixture",
|
|
99
|
+
kind: "question",
|
|
100
|
+
toolUseId: "tool-abc",
|
|
101
|
+
questionDetails: { entries: ENTRIES },
|
|
102
|
+
});
|
|
103
|
+
const pendingQuestions = collectPendingQuestions("conv-fixture");
|
|
104
|
+
const calls = [toolCall({ id: "tool-abc" })];
|
|
105
|
+
|
|
106
|
+
// WHEN we enrich it
|
|
107
|
+
const [enriched] = enrichToolCallsWithQuestion(calls, { pendingQuestions });
|
|
108
|
+
|
|
109
|
+
// THEN the outstanding prompt is projected onto the tool call so a cold
|
|
110
|
+
// reconnect can rehydrate the question card
|
|
111
|
+
expect(enriched?.pendingQuestion?.requestId).toBe("req-1");
|
|
112
|
+
expect(enriched?.pendingQuestion?.entries).toEqual(ENTRIES);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("leaves tool calls without a match untouched (same reference)", () => {
|
|
116
|
+
// GIVEN a tool call with no matching registry entry
|
|
117
|
+
const original = toolCall({ id: "tool-unmatched" });
|
|
118
|
+
register("req-other", {
|
|
119
|
+
conversationId: "conv-fixture",
|
|
120
|
+
kind: "question",
|
|
121
|
+
toolUseId: "tool-abc",
|
|
122
|
+
questionDetails: { entries: ENTRIES },
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// WHEN we enrich it
|
|
126
|
+
const [enriched] = enrichToolCallsWithQuestion([original], {
|
|
127
|
+
pendingQuestions: collectPendingQuestions("conv-fixture"),
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// THEN the tool call is returned unchanged
|
|
131
|
+
expect(enriched).toBe(original);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("returns the input array untouched when there are no pending questions", () => {
|
|
135
|
+
// GIVEN tool calls and an empty registry
|
|
136
|
+
const calls = [toolCall({ id: "tool-abc" })];
|
|
137
|
+
|
|
138
|
+
// WHEN we enrich with an empty lookup
|
|
139
|
+
const enriched = enrichToolCallsWithQuestion(calls, {
|
|
140
|
+
pendingQuestions: new Map(),
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// THEN the original array is returned
|
|
144
|
+
expect(enriched).toBe(calls);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render-time enrichment of history tool calls with in-flight question context.
|
|
3
|
+
*
|
|
4
|
+
* `pendingQuestion` — the outstanding `ask_question` prompt for a tool call
|
|
5
|
+
* still awaiting a user answer — is read from the in-memory
|
|
6
|
+
* `pending-interactions` registry (the authoritative store of unresolved
|
|
7
|
+
* prompts) and stamped onto its tool call so the web/API clients can restore
|
|
8
|
+
* the same question card on a cold reconnect (or a history reopen after the
|
|
9
|
+
* live event buffer has aged out) that the live `question_request` SSE stream
|
|
10
|
+
* would have produced. It appears only while the prompt is genuinely
|
|
11
|
+
* outstanding. Mirrors the confirmation enrichment in
|
|
12
|
+
* `tool-call-confirmation-enrichment.ts`.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { QuestionEntry } from "../../api/events/question-request.js";
|
|
16
|
+
import type { ConversationMessageToolCall } from "../../api/responses/conversation-message.js";
|
|
17
|
+
import { getByConversation } from "../pending-interactions.js";
|
|
18
|
+
|
|
19
|
+
/** A pending question matched to the tool call it prompts for, keyed by `toolUseId`. */
|
|
20
|
+
interface PendingQuestionMatch {
|
|
21
|
+
requestId: string;
|
|
22
|
+
entries: QuestionEntry[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Build the `toolUseId → pending question` lookup for a conversation from the
|
|
27
|
+
* registry. Only question interactions that carry both a `toolUseId` and
|
|
28
|
+
* `questionDetails` can be stamped onto a wire tool call.
|
|
29
|
+
*/
|
|
30
|
+
export function collectPendingQuestions(
|
|
31
|
+
conversationId: string,
|
|
32
|
+
): Map<string, PendingQuestionMatch> {
|
|
33
|
+
const byToolUseId = new Map<string, PendingQuestionMatch>();
|
|
34
|
+
for (const interaction of getByConversation(conversationId)) {
|
|
35
|
+
if (
|
|
36
|
+
interaction.kind === "question" &&
|
|
37
|
+
interaction.questionDetails &&
|
|
38
|
+
interaction.toolUseId
|
|
39
|
+
) {
|
|
40
|
+
byToolUseId.set(interaction.toolUseId, {
|
|
41
|
+
requestId: interaction.requestId,
|
|
42
|
+
entries: interaction.questionDetails.entries,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return byToolUseId;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Layer any outstanding `pendingQuestion` onto a message's rendered tool calls.
|
|
51
|
+
* Returns a new array; tool calls without a match are returned unchanged.
|
|
52
|
+
*/
|
|
53
|
+
export function enrichToolCallsWithQuestion(
|
|
54
|
+
toolCalls: ConversationMessageToolCall[],
|
|
55
|
+
opts: { pendingQuestions: ReadonlyMap<string, PendingQuestionMatch> },
|
|
56
|
+
): ConversationMessageToolCall[] {
|
|
57
|
+
if (opts.pendingQuestions.size === 0) return toolCalls;
|
|
58
|
+
return toolCalls.map((tc) => {
|
|
59
|
+
const match = tc.id ? opts.pendingQuestions.get(tc.id) : undefined;
|
|
60
|
+
if (!match) return tc;
|
|
61
|
+
return {
|
|
62
|
+
...tc,
|
|
63
|
+
pendingQuestion: { requestId: match.requestId, entries: match.entries },
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
|
|
3
|
+
import type {
|
|
4
|
+
WorkflowJournalEntry,
|
|
5
|
+
WorkflowRun,
|
|
6
|
+
} from "../../workflows/journal-store.js";
|
|
5
7
|
import type { SavedWorkflowEntry } from "../../workflows/library.js";
|
|
6
8
|
import {
|
|
7
9
|
WorkflowResumeNotPossibleError,
|
|
@@ -59,14 +61,31 @@ interface FakeManager {
|
|
|
59
61
|
resume: (id: string) => { runId: string };
|
|
60
62
|
}
|
|
61
63
|
|
|
64
|
+
function makeJournalEntry(
|
|
65
|
+
overrides: Partial<WorkflowJournalEntry> = {},
|
|
66
|
+
): WorkflowJournalEntry {
|
|
67
|
+
return {
|
|
68
|
+
runId: "run-1",
|
|
69
|
+
seq: 0,
|
|
70
|
+
callHash: "call-0",
|
|
71
|
+
kind: "agent",
|
|
72
|
+
request: null,
|
|
73
|
+
result: null,
|
|
74
|
+
status: "completed",
|
|
75
|
+
createdAt: 1000,
|
|
76
|
+
...overrides,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
62
80
|
function setup(opts: {
|
|
63
|
-
flagEnabled?: boolean;
|
|
64
81
|
runs?: WorkflowRun[];
|
|
65
82
|
saved?: SavedWorkflowEntry[];
|
|
66
83
|
/** Custom resume impl; defaults to a success that records the id. */
|
|
67
84
|
resume?: (id: string) => { runId: string };
|
|
68
85
|
/** Resolved auto-approve threshold for the resume posture gate. */
|
|
69
86
|
threshold?: "none" | "low" | "medium" | "high";
|
|
87
|
+
/** Journal entries returned by getJournal, keyed by run id. */
|
|
88
|
+
journal?: Record<string, WorkflowJournalEntry[]>;
|
|
70
89
|
}): {
|
|
71
90
|
aborted: string[];
|
|
72
91
|
resumed: string[];
|
|
@@ -98,9 +117,8 @@ function setup(opts: {
|
|
|
98
117
|
__setWorkflowRoutesDeps({
|
|
99
118
|
getManager: () => manager,
|
|
100
119
|
listWorkflows: () => opts.saved ?? [],
|
|
101
|
-
getConfig: () => ({}) as AssistantConfig,
|
|
102
|
-
isFlagEnabled: () => opts.flagEnabled ?? true,
|
|
103
120
|
getAutoApproveThreshold: async () => opts.threshold ?? "none",
|
|
121
|
+
getJournal: (runId) => opts.journal?.[runId] ?? [],
|
|
104
122
|
});
|
|
105
123
|
return { aborted, resumed, listCalls };
|
|
106
124
|
}
|
|
@@ -113,10 +131,9 @@ afterEach(() => {
|
|
|
113
131
|
// Happy paths
|
|
114
132
|
// ---------------------------------------------------------------------------
|
|
115
133
|
|
|
116
|
-
describe("workflow routes (
|
|
134
|
+
describe("workflow routes (happy paths)", () => {
|
|
117
135
|
beforeEach(() => {
|
|
118
136
|
setup({
|
|
119
|
-
flagEnabled: true,
|
|
120
137
|
runs: [
|
|
121
138
|
makeRun({ id: "run-1" }),
|
|
122
139
|
makeRun({ id: "run-2", status: "completed" }),
|
|
@@ -145,7 +162,6 @@ describe("workflow routes (flag on)", () => {
|
|
|
145
162
|
|
|
146
163
|
test("listWorkflowRuns honors limit + status query params", async () => {
|
|
147
164
|
const { listCalls } = setup({
|
|
148
|
-
flagEnabled: true,
|
|
149
165
|
runs: [makeRun({ id: "run-1", status: "completed" })],
|
|
150
166
|
});
|
|
151
167
|
await route("listWorkflowRuns").handler({
|
|
@@ -163,7 +179,6 @@ describe("workflow routes (flag on)", () => {
|
|
|
163
179
|
|
|
164
180
|
test("abortWorkflowRun aborts a known run", async () => {
|
|
165
181
|
const { aborted } = setup({
|
|
166
|
-
flagEnabled: true,
|
|
167
182
|
runs: [makeRun({ id: "run-1" })],
|
|
168
183
|
});
|
|
169
184
|
const result = (await route("abortWorkflowRun").handler({
|
|
@@ -175,7 +190,6 @@ describe("workflow routes (flag on)", () => {
|
|
|
175
190
|
|
|
176
191
|
test("resumeWorkflowRun resumes an interrupted run", async () => {
|
|
177
192
|
const { resumed } = setup({
|
|
178
|
-
flagEnabled: true,
|
|
179
193
|
runs: [makeRun({ id: "run-1", status: "interrupted" })],
|
|
180
194
|
});
|
|
181
195
|
const result = (await route("resumeWorkflowRun").handler({
|
|
@@ -192,7 +206,6 @@ describe("workflow routes (flag on)", () => {
|
|
|
192
206
|
// full-access posture it must refuse rather than silently bypass consent —
|
|
193
207
|
// resume() is never called.
|
|
194
208
|
const { resumed } = setup({
|
|
195
|
-
flagEnabled: true,
|
|
196
209
|
threshold: "medium",
|
|
197
210
|
runs: [
|
|
198
211
|
makeRun({
|
|
@@ -213,7 +226,6 @@ describe("workflow routes (flag on)", () => {
|
|
|
213
226
|
// high-risk tools, so no prompt is needed — the side-effecting resume
|
|
214
227
|
// proceeds directly.
|
|
215
228
|
const { resumed } = setup({
|
|
216
|
-
flagEnabled: true,
|
|
217
229
|
threshold: "high",
|
|
218
230
|
runs: [
|
|
219
231
|
makeRun({
|
|
@@ -236,7 +248,6 @@ describe("workflow routes (flag on)", () => {
|
|
|
236
248
|
// the object shape too — a strict parse would treat it as read-only and let
|
|
237
249
|
// the side-effecting resume through without approval.
|
|
238
250
|
const { resumed } = setup({
|
|
239
|
-
flagEnabled: true,
|
|
240
251
|
threshold: "medium",
|
|
241
252
|
runs: [
|
|
242
253
|
makeRun({
|
|
@@ -259,7 +270,6 @@ describe("workflow routes (flag on)", () => {
|
|
|
259
270
|
// An explicit empty manifest grants no side effects, so the route resumes
|
|
260
271
|
// it directly — the gate keys on the stored manifest, not run existence.
|
|
261
272
|
const { resumed } = setup({
|
|
262
|
-
flagEnabled: true,
|
|
263
273
|
threshold: "medium",
|
|
264
274
|
runs: [
|
|
265
275
|
makeRun({
|
|
@@ -275,7 +285,6 @@ describe("workflow routes (flag on)", () => {
|
|
|
275
285
|
|
|
276
286
|
test("resumeWorkflowRun maps a non-interrupted run to a 409 ConflictError", async () => {
|
|
277
287
|
setup({
|
|
278
|
-
flagEnabled: true,
|
|
279
288
|
runs: [makeRun({ id: "run-1", status: "completed" })],
|
|
280
289
|
resume: (id) => {
|
|
281
290
|
throw new WorkflowResumeNotPossibleError(
|
|
@@ -292,7 +301,6 @@ describe("workflow routes (flag on)", () => {
|
|
|
292
301
|
|
|
293
302
|
test("resumeWorkflowRun maps a cap error to a 429 TooManyRequestsError", async () => {
|
|
294
303
|
setup({
|
|
295
|
-
flagEnabled: true,
|
|
296
304
|
runs: [makeRun({ id: "run-1", status: "interrupted" })],
|
|
297
305
|
resume: () => {
|
|
298
306
|
throw new WorkflowRunCapError(3);
|
|
@@ -317,20 +325,222 @@ describe("workflow routes (flag on)", () => {
|
|
|
317
325
|
});
|
|
318
326
|
});
|
|
319
327
|
|
|
328
|
+
// ---------------------------------------------------------------------------
|
|
329
|
+
// Journal projection
|
|
330
|
+
// ---------------------------------------------------------------------------
|
|
331
|
+
|
|
332
|
+
interface WireLeaf {
|
|
333
|
+
seq: number;
|
|
334
|
+
kind: string;
|
|
335
|
+
label?: string;
|
|
336
|
+
phase?: string;
|
|
337
|
+
promptSummary?: string;
|
|
338
|
+
status: string;
|
|
339
|
+
resultSummary?: string;
|
|
340
|
+
inputTokens?: number;
|
|
341
|
+
outputTokens?: number;
|
|
342
|
+
createdAt: number | null;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
interface WireJournal {
|
|
346
|
+
runId: string;
|
|
347
|
+
status: string;
|
|
348
|
+
agentsSpawned: number;
|
|
349
|
+
inputTokens: number;
|
|
350
|
+
outputTokens: number;
|
|
351
|
+
leaves: WireLeaf[];
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
describe("getWorkflowRunJournal", () => {
|
|
355
|
+
test("projects agent leaves with label/phase/promptSummary/resultSummary extracted", async () => {
|
|
356
|
+
setup({
|
|
357
|
+
runs: [makeRun({ id: "run-1" })],
|
|
358
|
+
journal: {
|
|
359
|
+
"run-1": [
|
|
360
|
+
makeJournalEntry({
|
|
361
|
+
seq: 0,
|
|
362
|
+
kind: "agent",
|
|
363
|
+
request: {
|
|
364
|
+
prompt: "Investigate the failing build",
|
|
365
|
+
opts: { label: "investigate", phase: "triage" },
|
|
366
|
+
},
|
|
367
|
+
result: { summary: "found the flaky test" },
|
|
368
|
+
status: "completed",
|
|
369
|
+
inputTokens: 120,
|
|
370
|
+
outputTokens: 45,
|
|
371
|
+
}),
|
|
372
|
+
],
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
const result = (await route("getWorkflowRunJournal").handler({
|
|
376
|
+
pathParams: { id: "run-1" },
|
|
377
|
+
})) as WireJournal;
|
|
378
|
+
|
|
379
|
+
expect(result.runId).toBe("run-1");
|
|
380
|
+
expect(result.status).toBe("running");
|
|
381
|
+
expect(result.agentsSpawned).toBe(2);
|
|
382
|
+
expect(result.leaves.map((l) => l.seq)).toEqual([0]);
|
|
383
|
+
|
|
384
|
+
const first = result.leaves[0];
|
|
385
|
+
expect(first.kind).toBe("agent");
|
|
386
|
+
expect(first.label).toBe("investigate");
|
|
387
|
+
expect(first.phase).toBe("triage");
|
|
388
|
+
expect(first.promptSummary).toBe("Investigate the failing build");
|
|
389
|
+
expect(first.resultSummary).toContain("found the flaky test");
|
|
390
|
+
// Per-leaf token usage is projected onto the wire leaf.
|
|
391
|
+
expect(first.inputTokens).toBe(120);
|
|
392
|
+
expect(first.outputTokens).toBe(45);
|
|
393
|
+
// The bulky raw request/result payloads are dropped.
|
|
394
|
+
expect(first).not.toHaveProperty("request");
|
|
395
|
+
expect(first).not.toHaveProperty("result");
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
test("omits per-leaf token fields when the journal entry carries none", async () => {
|
|
399
|
+
setup({
|
|
400
|
+
runs: [makeRun({ id: "run-1" })],
|
|
401
|
+
journal: {
|
|
402
|
+
"run-1": [
|
|
403
|
+
makeJournalEntry({
|
|
404
|
+
seq: 0,
|
|
405
|
+
kind: "agent",
|
|
406
|
+
request: { prompt: "no tokens recorded", opts: {} },
|
|
407
|
+
status: "completed",
|
|
408
|
+
}),
|
|
409
|
+
],
|
|
410
|
+
},
|
|
411
|
+
});
|
|
412
|
+
const result = (await route("getWorkflowRunJournal").handler({
|
|
413
|
+
pathParams: { id: "run-1" },
|
|
414
|
+
})) as WireJournal;
|
|
415
|
+
|
|
416
|
+
const leaf = result.leaves[0];
|
|
417
|
+
expect(leaf).not.toHaveProperty("inputTokens");
|
|
418
|
+
expect(leaf).not.toHaveProperty("outputTokens");
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
test("excludes kind:workflow entries so the backfill matches the live agent-only stream", async () => {
|
|
422
|
+
// The live `workflow_leaf_*` stream is emitted only for agent leaves; nested
|
|
423
|
+
// `workflow(name)` resolutions never reach it. The journal route must filter
|
|
424
|
+
// to agent leaves too, or a nested-workflow run renders a phantom unlabeled
|
|
425
|
+
// node on backfill and a different leaf set than live.
|
|
426
|
+
setup({
|
|
427
|
+
runs: [makeRun({ id: "run-1" })],
|
|
428
|
+
journal: {
|
|
429
|
+
"run-1": [
|
|
430
|
+
makeJournalEntry({
|
|
431
|
+
seq: 0,
|
|
432
|
+
kind: "agent",
|
|
433
|
+
request: { prompt: "first agent", opts: { label: "first" } },
|
|
434
|
+
status: "completed",
|
|
435
|
+
}),
|
|
436
|
+
makeJournalEntry({
|
|
437
|
+
seq: 1,
|
|
438
|
+
kind: "workflow",
|
|
439
|
+
request: { name: "child", args: { foo: 1 } },
|
|
440
|
+
result: "child done",
|
|
441
|
+
status: "completed",
|
|
442
|
+
}),
|
|
443
|
+
makeJournalEntry({
|
|
444
|
+
seq: 2,
|
|
445
|
+
kind: "agent",
|
|
446
|
+
request: { prompt: "second agent", opts: { label: "second" } },
|
|
447
|
+
status: "completed",
|
|
448
|
+
}),
|
|
449
|
+
],
|
|
450
|
+
},
|
|
451
|
+
});
|
|
452
|
+
const result = (await route("getWorkflowRunJournal").handler({
|
|
453
|
+
pathParams: { id: "run-1" },
|
|
454
|
+
})) as WireJournal;
|
|
455
|
+
|
|
456
|
+
// Only the agent leaves survive, in seq order; the workflow-kind entry (seq
|
|
457
|
+
// 1) is dropped entirely.
|
|
458
|
+
expect(result.leaves.map((l) => l.seq)).toEqual([0, 2]);
|
|
459
|
+
expect(result.leaves.every((l) => l.kind === "agent")).toBe(true);
|
|
460
|
+
expect(result.leaves.map((l) => l.label)).toEqual(["first", "second"]);
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
test("surfaces a failed leaf's { error } result as resultSummary", async () => {
|
|
464
|
+
setup({
|
|
465
|
+
runs: [makeRun({ id: "run-1" })],
|
|
466
|
+
journal: {
|
|
467
|
+
"run-1": [
|
|
468
|
+
makeJournalEntry({
|
|
469
|
+
seq: 0,
|
|
470
|
+
status: "failed",
|
|
471
|
+
request: { prompt: "do the thing", opts: {} },
|
|
472
|
+
result: { error: "agent crashed: out of tokens" },
|
|
473
|
+
}),
|
|
474
|
+
],
|
|
475
|
+
},
|
|
476
|
+
});
|
|
477
|
+
const result = (await route("getWorkflowRunJournal").handler({
|
|
478
|
+
pathParams: { id: "run-1" },
|
|
479
|
+
})) as WireJournal;
|
|
480
|
+
|
|
481
|
+
expect(result.leaves[0].status).toBe("failed");
|
|
482
|
+
expect(result.leaves[0].resultSummary).toContain(
|
|
483
|
+
"agent crashed: out of tokens",
|
|
484
|
+
);
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
test("truncates a long prompt/result to ~200 chars", async () => {
|
|
488
|
+
const longPrompt = "x".repeat(500);
|
|
489
|
+
const longResult = "y".repeat(500);
|
|
490
|
+
setup({
|
|
491
|
+
runs: [makeRun({ id: "run-1" })],
|
|
492
|
+
journal: {
|
|
493
|
+
"run-1": [
|
|
494
|
+
makeJournalEntry({
|
|
495
|
+
seq: 0,
|
|
496
|
+
request: { prompt: longPrompt, opts: {} },
|
|
497
|
+
result: longResult,
|
|
498
|
+
}),
|
|
499
|
+
],
|
|
500
|
+
},
|
|
501
|
+
});
|
|
502
|
+
const result = (await route("getWorkflowRunJournal").handler({
|
|
503
|
+
pathParams: { id: "run-1" },
|
|
504
|
+
})) as WireJournal;
|
|
505
|
+
|
|
506
|
+
const leaf = result.leaves[0];
|
|
507
|
+
expect(leaf.promptSummary!.length).toBeLessThanOrEqual(201);
|
|
508
|
+
expect(leaf.promptSummary!.startsWith("x")).toBe(true);
|
|
509
|
+
// A truncated summary ends with the ellipsis marker.
|
|
510
|
+
expect(leaf.promptSummary!.endsWith("…")).toBe(true);
|
|
511
|
+
expect(leaf.resultSummary!.length).toBeLessThanOrEqual(201);
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
test("returns an empty leaf list for a run with no journal entries", async () => {
|
|
515
|
+
setup({ runs: [makeRun({ id: "run-1" })] });
|
|
516
|
+
const result = (await route("getWorkflowRunJournal").handler({
|
|
517
|
+
pathParams: { id: "run-1" },
|
|
518
|
+
})) as WireJournal;
|
|
519
|
+
expect(result.leaves).toEqual([]);
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
test("throws NotFoundError for an unknown id", () => {
|
|
523
|
+
setup({ runs: [] });
|
|
524
|
+
expect(() =>
|
|
525
|
+
route("getWorkflowRunJournal").handler({ pathParams: { id: "nope" } }),
|
|
526
|
+
).toThrow(NotFoundError);
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
|
|
320
530
|
// ---------------------------------------------------------------------------
|
|
321
531
|
// Unknown run → 404
|
|
322
532
|
// ---------------------------------------------------------------------------
|
|
323
533
|
|
|
324
534
|
describe("workflow routes (unknown run)", () => {
|
|
325
535
|
test("getWorkflowRun throws NotFoundError for an unknown id", () => {
|
|
326
|
-
setup({
|
|
536
|
+
setup({ runs: [] });
|
|
327
537
|
expect(() =>
|
|
328
538
|
route("getWorkflowRun").handler({ pathParams: { id: "nope" } }),
|
|
329
539
|
).toThrow(NotFoundError);
|
|
330
540
|
});
|
|
331
541
|
|
|
332
542
|
test("abortWorkflowRun throws NotFoundError for an unknown id", () => {
|
|
333
|
-
const { aborted } = setup({
|
|
543
|
+
const { aborted } = setup({ runs: [] });
|
|
334
544
|
expect(() =>
|
|
335
545
|
route("abortWorkflowRun").handler({ pathParams: { id: "nope" } }),
|
|
336
546
|
).toThrow(NotFoundError);
|
|
@@ -338,35 +548,10 @@ describe("workflow routes (unknown run)", () => {
|
|
|
338
548
|
});
|
|
339
549
|
|
|
340
550
|
test("resumeWorkflowRun throws NotFoundError for an unknown id", async () => {
|
|
341
|
-
const { resumed } = setup({
|
|
551
|
+
const { resumed } = setup({ runs: [] });
|
|
342
552
|
await expect(
|
|
343
553
|
route("resumeWorkflowRun").handler({ pathParams: { id: "nope" } }),
|
|
344
554
|
).rejects.toThrow(NotFoundError);
|
|
345
555
|
expect(resumed).toEqual([]);
|
|
346
556
|
});
|
|
347
557
|
});
|
|
348
|
-
|
|
349
|
-
// ---------------------------------------------------------------------------
|
|
350
|
-
// Flag off → every route 404s
|
|
351
|
-
// ---------------------------------------------------------------------------
|
|
352
|
-
|
|
353
|
-
describe("workflow routes (flag off)", () => {
|
|
354
|
-
beforeEach(() => {
|
|
355
|
-
setup({ flagEnabled: false, runs: [makeRun({ id: "run-1" })], saved: [] });
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
test.each([
|
|
359
|
-
["listWorkflowRuns", { queryParams: {} }],
|
|
360
|
-
["getWorkflowRun", { pathParams: { id: "run-1" } }],
|
|
361
|
-
["abortWorkflowRun", { pathParams: { id: "run-1" } }],
|
|
362
|
-
["listSavedWorkflows", {}],
|
|
363
|
-
] as const)("%s throws NotFoundError when the flag is off", (op, args) => {
|
|
364
|
-
expect(() => route(op).handler(args)).toThrow(NotFoundError);
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
test("resumeWorkflowRun rejects with NotFoundError when the flag is off", async () => {
|
|
368
|
-
await expect(
|
|
369
|
-
route("resumeWorkflowRun").handler({ pathParams: { id: "run-1" } }),
|
|
370
|
-
).rejects.toThrow(NotFoundError);
|
|
371
|
-
});
|
|
372
|
-
});
|