@elevasis/core 0.1.0
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/dist/index.d.ts +435 -0
- package/dist/index.js +403 -0
- package/dist/organization-model/index.d.ts +435 -0
- package/dist/organization-model/index.js +403 -0
- package/package.json +62 -0
- package/src/README.md +34 -0
- package/src/__tests__/observability-exports.test.ts +36 -0
- package/src/__tests__/publish.test.ts +18 -0
- package/src/__tests__/template-foundations-compatibility.test.ts +34 -0
- package/src/auth/index.ts +8 -0
- package/src/auth/multi-tenancy/credentials/README.md +38 -0
- package/src/auth/multi-tenancy/credentials/__tests__/encryption.test.ts +216 -0
- package/src/auth/multi-tenancy/credentials/__tests__/service.test.ts +174 -0
- package/src/auth/multi-tenancy/credentials/index.ts +6 -0
- package/src/auth/multi-tenancy/credentials/server/encryption.ts +39 -0
- package/src/auth/multi-tenancy/credentials/server/service.ts +60 -0
- package/src/auth/multi-tenancy/index.ts +17 -0
- package/src/auth/multi-tenancy/invitations/__tests__/invitation.test.ts +237 -0
- package/src/auth/multi-tenancy/invitations/api-schemas.ts +107 -0
- package/src/auth/multi-tenancy/invitations/index.ts +38 -0
- package/src/auth/multi-tenancy/invitations/invitation.ts +86 -0
- package/src/auth/multi-tenancy/invitations/server/index.ts +25 -0
- package/src/auth/multi-tenancy/invitations/server/transforms.ts +24 -0
- package/src/auth/multi-tenancy/invitations/server/workos.ts +24 -0
- package/src/auth/multi-tenancy/invitations/supabase.ts +50 -0
- package/src/auth/multi-tenancy/memberships/__tests__/membership.test.ts +227 -0
- package/src/auth/multi-tenancy/memberships/__tests__/supabase-transforms.test.ts +88 -0
- package/src/auth/multi-tenancy/memberships/__tests__/workos-transforms.test.ts +139 -0
- package/src/auth/multi-tenancy/memberships/api-schemas.ts +126 -0
- package/src/auth/multi-tenancy/memberships/index.ts +22 -0
- package/src/auth/multi-tenancy/memberships/membership.ts +138 -0
- package/src/auth/multi-tenancy/memberships/server/index.ts +15 -0
- package/src/auth/multi-tenancy/memberships/server/transforms.ts +32 -0
- package/src/auth/multi-tenancy/memberships/server/workos.ts +21 -0
- package/src/auth/multi-tenancy/memberships/supabase.ts +46 -0
- package/src/auth/multi-tenancy/organizations/__tests__/organization.test.ts +249 -0
- package/src/auth/multi-tenancy/organizations/api-schemas.ts +128 -0
- package/src/auth/multi-tenancy/organizations/index.ts +23 -0
- package/src/auth/multi-tenancy/organizations/organization.ts +25 -0
- package/src/auth/multi-tenancy/organizations/server/index.ts +10 -0
- package/src/auth/multi-tenancy/organizations/server/transforms.ts +35 -0
- package/src/auth/multi-tenancy/organizations/server/workos.ts +20 -0
- package/src/auth/multi-tenancy/types.ts +89 -0
- package/src/auth/multi-tenancy/users/__tests__/user.test.ts +208 -0
- package/src/auth/multi-tenancy/users/api-schemas.ts +194 -0
- package/src/auth/multi-tenancy/users/index.ts +28 -0
- package/src/auth/multi-tenancy/users/server/index.ts +19 -0
- package/src/auth/multi-tenancy/users/server/transforms.ts +21 -0
- package/src/auth/multi-tenancy/users/server/workos.ts +16 -0
- package/src/auth/multi-tenancy/users/user.ts +65 -0
- package/src/business/acquisition/api-schemas.ts +759 -0
- package/src/business/acquisition/index.ts +109 -0
- package/src/business/acquisition/types.ts +400 -0
- package/src/business/crm/api-schemas.ts +75 -0
- package/src/business/delivery/index.ts +1 -0
- package/src/business/delivery/types.ts +89 -0
- package/src/business/index.ts +12 -0
- package/src/business/pdf/assets/ElevasisLogo.png +0 -0
- package/src/business/pdf/browser/image-utils.ts +74 -0
- package/src/business/pdf/browser/index.ts +16 -0
- package/src/business/pdf/browser/pdfmake-browser.ts +229 -0
- package/src/business/pdf/index.ts +10 -0
- package/src/business/pdf/sections/acceptance.ts +112 -0
- package/src/business/pdf/sections/automation.ts +56 -0
- package/src/business/pdf/sections/cover.ts +51 -0
- package/src/business/pdf/sections/index.ts +57 -0
- package/src/business/pdf/sections/investment.ts +69 -0
- package/src/business/pdf/sections/proposal-document.ts +200 -0
- package/src/business/pdf/sections/summary-investment.ts +124 -0
- package/src/business/pdf/sections/summary.ts +55 -0
- package/src/business/pdf/sections/table-summary.ts +59 -0
- package/src/business/pdf/sections/types.ts +124 -0
- package/src/business/pdf/server/__tests__/pdfmake-test.ts +219 -0
- package/src/business/pdf/server/index.ts +21 -0
- package/src/business/pdf/server/pdfmake-service.ts +237 -0
- package/src/business/pdf/server/themes/default.ts +8 -0
- package/src/business/pdf/server/themes/index.ts +9 -0
- package/src/business/pdf/server/themes/types.ts +8 -0
- package/src/business/pdf/shared/convert.ts +514 -0
- package/src/business/pdf/shared/index.ts +12 -0
- package/src/business/pdf/themes.ts +78 -0
- package/src/business/pdf/types.ts +272 -0
- package/src/business/seo/__tests__/linking.test.ts +549 -0
- package/src/business/seo/__tests__/types.test.ts +404 -0
- package/src/business/seo/index.ts +2 -0
- package/src/business/seo/linking.ts +281 -0
- package/src/business/seo/types.ts +199 -0
- package/src/commands/index.ts +8 -0
- package/src/commands/queue/index.ts +3 -0
- package/src/commands/queue/schemas.test.ts +593 -0
- package/src/commands/queue/schemas.ts +125 -0
- package/src/commands/queue/sse-events.ts +61 -0
- package/src/commands/queue/types/action.ts +52 -0
- package/src/commands/queue/types/checkpoint.ts +44 -0
- package/src/commands/queue/types/index.ts +7 -0
- package/src/commands/queue/types/task.ts +116 -0
- package/src/commands/queue/types.ts +14 -0
- package/src/content/distribution-metadata.ts +61 -0
- package/src/content/index.ts +10 -0
- package/src/deployments/index.ts +22 -0
- package/src/execution/calibration/__tests__/schemas.test.ts +320 -0
- package/src/execution/calibration/index.ts +3 -0
- package/src/execution/calibration/schemas.ts +121 -0
- package/src/execution/calibration/sse-events.ts +125 -0
- package/src/execution/calibration/types.ts +190 -0
- package/src/execution/core/__tests__/api-schemas.test.ts +667 -0
- package/src/execution/core/__tests__/archived-logs.test.ts +72 -0
- package/src/execution/core/api-schemas.ts +312 -0
- package/src/execution/core/index.ts +11 -0
- package/src/execution/core/resource-validator.test.ts +63 -0
- package/src/execution/core/runner-types.ts +80 -0
- package/src/execution/core/server/environment.ts +31 -0
- package/src/execution/core/sse-executions.ts +119 -0
- package/src/execution/core/types.ts +29 -0
- package/src/execution/engine/__tests__/fixtures/index.ts +2 -0
- package/src/execution/engine/__tests__/fixtures/mock-scenarios.ts +60 -0
- package/src/execution/engine/__tests__/fixtures/test-agents.ts +85 -0
- package/src/execution/engine/__tests__/integration/agent-framework.integration.test.ts +1031 -0
- package/src/execution/engine/__tests__/timeout.test.ts +565 -0
- package/src/execution/engine/agent/__tests__/errors.test.ts +508 -0
- package/src/execution/engine/agent/actions/__tests__/processor.test.ts +531 -0
- package/src/execution/engine/agent/actions/executor.ts +205 -0
- package/src/execution/engine/agent/actions/navigate-knowledge-executor.ts +230 -0
- package/src/execution/engine/agent/actions/processor.ts +116 -0
- package/src/execution/engine/agent/actions/types.ts +70 -0
- package/src/execution/engine/agent/core/__tests__/agent.test.ts +614 -0
- package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +134 -0
- package/src/execution/engine/agent/core/agent.ts +810 -0
- package/src/execution/engine/agent/core/types.ts +155 -0
- package/src/execution/engine/agent/errors.ts +251 -0
- package/src/execution/engine/agent/index.ts +78 -0
- package/src/execution/engine/agent/knowledge-map/__tests__/navigate-knowledge-executor.test.ts +580 -0
- package/src/execution/engine/agent/knowledge-map/__tests__/utils.test.ts +622 -0
- package/src/execution/engine/agent/knowledge-map/types.ts +106 -0
- package/src/execution/engine/agent/knowledge-map/utils.ts +101 -0
- package/src/execution/engine/agent/memory/__tests__/domains.test.ts +72 -0
- package/src/execution/engine/agent/memory/__tests__/manager.test.ts +754 -0
- package/src/execution/engine/agent/memory/__tests__/utils.test.ts +285 -0
- package/src/execution/engine/agent/memory/domains.ts +99 -0
- package/src/execution/engine/agent/memory/manager.ts +365 -0
- package/src/execution/engine/agent/memory/processor.ts +66 -0
- package/src/execution/engine/agent/memory/types.ts +90 -0
- package/src/execution/engine/agent/memory/utils.ts +134 -0
- package/src/execution/engine/agent/observability/logging.ts +467 -0
- package/src/execution/engine/agent/observability/types.ts +64 -0
- package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +209 -0
- package/src/execution/engine/agent/reasoning/adapters/agent-adapter-helpers.ts +349 -0
- package/src/execution/engine/agent/reasoning/processor.ts +92 -0
- package/src/execution/engine/agent/reasoning/prompt-sections/base-actions.ts +134 -0
- package/src/execution/engine/agent/reasoning/prompt-sections/completion.ts +49 -0
- package/src/execution/engine/agent/reasoning/prompt-sections/knowledge-map.ts +93 -0
- package/src/execution/engine/agent/reasoning/prompt-sections/memory.ts +65 -0
- package/src/execution/engine/agent/reasoning/prompt-sections/security.ts +32 -0
- package/src/execution/engine/agent/reasoning/prompt-sections/tools.ts +44 -0
- package/src/execution/engine/agent/reasoning/request-builder.ts +169 -0
- package/src/execution/engine/agent/reasoning/types.ts +18 -0
- package/src/execution/engine/base/__tests__/errors.test.ts +246 -0
- package/src/execution/engine/base/__tests__/serialization.test.ts +670 -0
- package/src/execution/engine/base/__tests__/utils.test.ts +45 -0
- package/src/execution/engine/base/errors.ts +118 -0
- package/src/execution/engine/base/index.ts +2 -0
- package/src/execution/engine/base/logging.ts +31 -0
- package/src/execution/engine/base/serialization.ts +324 -0
- package/src/execution/engine/base/types.ts +126 -0
- package/src/execution/engine/base/utils.ts +41 -0
- package/src/execution/engine/index.ts +440 -0
- package/src/execution/engine/interface/index.ts +1 -0
- package/src/execution/engine/interface/types.ts +62 -0
- package/src/execution/engine/llm/__tests__/errors.test.ts +318 -0
- package/src/execution/engine/llm/__tests__/input-sanitizer.test.ts +286 -0
- package/src/execution/engine/llm/__tests__/model-info.test.ts +50 -0
- package/src/execution/engine/llm/__tests__/model-validation.test.ts +321 -0
- package/src/execution/engine/llm/__tests__/response-schema-validator.test.ts +115 -0
- package/src/execution/engine/llm/adapters/__tests__/adapter-factory.test.ts +375 -0
- package/src/execution/engine/llm/adapters/__tests__/anthropic-adapter.test.ts +463 -0
- package/src/execution/engine/llm/adapters/__tests__/anthropic.integration.test.ts +177 -0
- package/src/execution/engine/llm/adapters/__tests__/circuit-breaker-error.test.ts +94 -0
- package/src/execution/engine/llm/adapters/__tests__/google-adapter.test.ts +722 -0
- package/src/execution/engine/llm/adapters/__tests__/google.integration.test.ts +376 -0
- package/src/execution/engine/llm/adapters/__tests__/mock-adapter.test.ts +432 -0
- package/src/execution/engine/llm/adapters/__tests__/openai-adapter.test.ts +551 -0
- package/src/execution/engine/llm/adapters/__tests__/openrouter-adapter.test.ts +563 -0
- package/src/execution/engine/llm/adapters/__tests__/openrouter.integration.test.ts +105 -0
- package/src/execution/engine/llm/adapters/__tests__/universal-adapter.test.ts +537 -0
- package/src/execution/engine/llm/adapters/circuit-breaker.ts +147 -0
- package/src/execution/engine/llm/adapters/index.ts +17 -0
- package/src/execution/engine/llm/adapters/mock-adapter.ts +116 -0
- package/src/execution/engine/llm/adapters/server/adapter-factory.ts +130 -0
- package/src/execution/engine/llm/adapters/server/anthropic.ts +137 -0
- package/src/execution/engine/llm/adapters/server/compose-signal.ts +18 -0
- package/src/execution/engine/llm/adapters/server/google.ts +283 -0
- package/src/execution/engine/llm/adapters/server/index.ts +12 -0
- package/src/execution/engine/llm/adapters/server/openai.ts +206 -0
- package/src/execution/engine/llm/adapters/server/openrouter.ts +235 -0
- package/src/execution/engine/llm/adapters/universal-adapter.ts +230 -0
- package/src/execution/engine/llm/errors.ts +186 -0
- package/src/execution/engine/llm/input-sanitizer.ts +129 -0
- package/src/execution/engine/llm/model-info.ts +332 -0
- package/src/execution/engine/llm/response-schema-validator.ts +113 -0
- package/src/execution/engine/llm/types.ts +86 -0
- package/src/execution/engine/test-utils/index.ts +6 -0
- package/src/execution/engine/test-utils/mocks.ts +56 -0
- package/src/execution/engine/tools/__tests__/tooling-error.test.ts +265 -0
- package/src/execution/engine/tools/__tests__/types.test.ts +47 -0
- package/src/execution/engine/tools/integration/base-integration-adapter.ts +50 -0
- package/src/execution/engine/tools/integration/index.ts +53 -0
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/anymailfinder-adapter.ts +73 -0
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/anymailfinder-tools.ts +209 -0
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-company-email/index.ts +82 -0
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-decision-maker-email/index.ts +122 -0
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-person-email/index.ts +89 -0
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/verify-email/index.ts +84 -0
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/index.ts +16 -0
- package/src/execution/engine/tools/integration/server/adapters/apify/__tests__/apify-run-actor.integration.test.ts +293 -0
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +100 -0
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-tools.ts +217 -0
- package/src/execution/engine/tools/integration/server/adapters/apify/fetch/get-dataset-items/index.ts +92 -0
- package/src/execution/engine/tools/integration/server/adapters/apify/fetch/run-actor/index.ts +218 -0
- package/src/execution/engine/tools/integration/server/adapters/apify/fetch/start-actor/index.ts +87 -0
- package/src/execution/engine/tools/integration/server/adapters/apify/index.ts +11 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/__tests__/attio-crud.integration.test.ts +362 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/attio-adapter.ts +162 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/attio-tools.ts +594 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/README.md +632 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-attribute/index.ts +214 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-note/index.ts +152 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-record/index.ts +141 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/delete-note/index.ts +86 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/delete-record/index.ts +105 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/get-record/index.test.ts +186 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/get-record/index.ts +118 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-attributes/index.ts +165 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-notes/index.ts +96 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-objects/index.ts +104 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-records/index.test.ts +338 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-records/index.ts +156 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/update-attribute/index.ts +220 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/update-record/index.ts +140 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/utils/types.ts +147 -0
- package/src/execution/engine/tools/integration/server/adapters/attio/index.ts +31 -0
- package/src/execution/engine/tools/integration/server/adapters/dropbox/__tests__/dropbox-adapter.test.ts +409 -0
- package/src/execution/engine/tools/integration/server/adapters/dropbox/dropbox-adapter.ts +281 -0
- package/src/execution/engine/tools/integration/server/adapters/dropbox/dropbox-tools.ts +106 -0
- package/src/execution/engine/tools/integration/server/adapters/dropbox/fetch/create-folder/__tests__/index.test.ts +451 -0
- package/src/execution/engine/tools/integration/server/adapters/dropbox/fetch/create-folder/index.ts +114 -0
- package/src/execution/engine/tools/integration/server/adapters/dropbox/fetch/upload-file/__tests__/index.test.ts +415 -0
- package/src/execution/engine/tools/integration/server/adapters/dropbox/fetch/upload-file/index.ts +111 -0
- package/src/execution/engine/tools/integration/server/adapters/dropbox/index.ts +25 -0
- package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-adapter.ts +210 -0
- package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-tools.ts +104 -0
- package/src/execution/engine/tools/integration/server/adapters/google-sheets/__tests__/google-sheets.integration.test.ts +261 -0
- package/src/execution/engine/tools/integration/server/adapters/google-sheets/google-sheets-adapter.ts +1189 -0
- package/src/execution/engine/tools/integration/server/adapters/google-sheets/google-sheets-tools.ts +641 -0
- package/src/execution/engine/tools/integration/server/adapters/google-sheets/index.ts +18 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/activate-campaign/index.ts +86 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/add-to-campaign/__tests__/index.test.ts +289 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/add-to-campaign/index.ts +154 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-add-leads/__tests__/index.test.ts +325 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-add-leads/index.ts +153 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-delete-leads/index.ts +84 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/create-campaign/index.ts +125 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/create-inbox-test/index.ts +107 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/delete-campaign/index.ts +85 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-account-health/index.ts +91 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign/index.ts +92 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign-analytics/__tests__/index.test.ts +195 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign-analytics/index.ts +113 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-daily-campaign-analytics/index.ts +104 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-emails/index.ts +155 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-step-analytics/__tests__/index.test.ts +196 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-step-analytics/index.ts +102 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-campaigns/__tests__/index.test.ts +189 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-campaigns/index.ts +87 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-leads/index.ts +112 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/patch-lead/index.ts +76 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/pause-campaign/index.ts +86 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/remove-from-subsequence/index.ts +98 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/send-reply/index.ts +126 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-campaign/__tests__/index.test.ts +193 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-campaign/index.ts +99 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-interest-status/__tests__/index.test.ts +621 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-interest-status/index.ts +125 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/index.ts +29 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-adapter.ts +178 -0
- package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-tools.ts +1473 -0
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/fetch/check-credits/index.ts +59 -0
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/fetch/verify-email/index.ts +102 -0
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/index.ts +17 -0
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-adapter.ts +80 -0
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-tools.ts +102 -0
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/get-email/index.ts +102 -0
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.ts +134 -0
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/utils/types.ts +75 -0
- package/src/execution/engine/tools/integration/server/adapters/resend/index.ts +27 -0
- package/src/execution/engine/tools/integration/server/adapters/resend/resend-adapter.ts +108 -0
- package/src/execution/engine/tools/integration/server/adapters/resend/resend-tools.ts +132 -0
- package/src/execution/engine/tools/integration/server/adapters/resend/types.ts +44 -0
- package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/create-envelope/index.ts +274 -0
- package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/download-document/index.ts +230 -0
- package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/get-envelope/index.ts +133 -0
- package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/utils/types.ts +246 -0
- package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/void-envelope/index.ts +90 -0
- package/src/execution/engine/tools/integration/server/adapters/signature-api/index.ts +38 -0
- package/src/execution/engine/tools/integration/server/adapters/signature-api/signature-api-adapter.ts +87 -0
- package/src/execution/engine/tools/integration/server/adapters/signature-api/signature-api-tools.ts +179 -0
- package/src/execution/engine/tools/integration/server/adapters/stripe/fetch/utils/types.ts +210 -0
- package/src/execution/engine/tools/integration/server/adapters/stripe/index.ts +44 -0
- package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-adapter.ts +517 -0
- package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-tools.ts +309 -0
- package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/domain-search/index.ts +133 -0
- package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/email-finder/index.ts +122 -0
- package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/email-verifier/index.ts +111 -0
- package/src/execution/engine/tools/integration/server/adapters/tomba/index.ts +11 -0
- package/src/execution/engine/tools/integration/server/adapters/tomba/tomba-adapter.ts +78 -0
- package/src/execution/engine/tools/integration/server/adapters/tomba/tomba-tools.ts +222 -0
- package/src/execution/engine/tools/integration/server/index.ts +61 -0
- package/src/execution/engine/tools/integration/service.ts +161 -0
- package/src/execution/engine/tools/integration/tool.ts +253 -0
- package/src/execution/engine/tools/integration/types/anymailfinder.ts +74 -0
- package/src/execution/engine/tools/integration/types/apify.ts +92 -0
- package/src/execution/engine/tools/integration/types/attio.ts +354 -0
- package/src/execution/engine/tools/integration/types/dropbox.ts +64 -0
- package/src/execution/engine/tools/integration/types/gmail.ts +35 -0
- package/src/execution/engine/tools/integration/types/google-sheets.ts +303 -0
- package/src/execution/engine/tools/integration/types/index.ts +19 -0
- package/src/execution/engine/tools/integration/types/instantly.ts +557 -0
- package/src/execution/engine/tools/integration/types/millionverifier.ts +56 -0
- package/src/execution/engine/tools/integration/types/resend.ts +63 -0
- package/src/execution/engine/tools/integration/types/signature-api.ts +164 -0
- package/src/execution/engine/tools/integration/types/stripe.ts +162 -0
- package/src/execution/engine/tools/integration/types/tomba.ts +94 -0
- package/src/execution/engine/tools/lead-service-types.ts +884 -0
- package/src/execution/engine/tools/llm/index.ts +11 -0
- package/src/execution/engine/tools/llm/server/index.ts +8 -0
- package/src/execution/engine/tools/llm/server/llm-call-tool.ts +118 -0
- package/src/execution/engine/tools/platform/__tests__/approval.test.ts +242 -0
- package/src/execution/engine/tools/platform/__tests__/email.test.ts +482 -0
- package/src/execution/engine/tools/platform/__tests__/hitl-cancel.test.ts +97 -0
- package/src/execution/engine/tools/platform/__tests__/notification.test.ts +208 -0
- package/src/execution/engine/tools/platform/__tests__/pdf.test.ts +441 -0
- package/src/execution/engine/tools/platform/__tests__/scheduler.test.ts +189 -0
- package/src/execution/engine/tools/platform/__tests__/schedules.test.ts +336 -0
- package/src/execution/engine/tools/platform/acquisition/company-tools.ts +248 -0
- package/src/execution/engine/tools/platform/acquisition/contact-tools.ts +319 -0
- package/src/execution/engine/tools/platform/acquisition/index.ts +43 -0
- package/src/execution/engine/tools/platform/acquisition/list-tools.ts +148 -0
- package/src/execution/engine/tools/platform/acquisition/types.ts +260 -0
- package/src/execution/engine/tools/platform/approval/cancel-by-metadata.ts +65 -0
- package/src/execution/engine/tools/platform/approval/index.ts +4 -0
- package/src/execution/engine/tools/platform/approval/tool.ts +99 -0
- package/src/execution/engine/tools/platform/email/index.ts +122 -0
- package/src/execution/engine/tools/platform/email/types.ts +96 -0
- package/src/execution/engine/tools/platform/index.ts +181 -0
- package/src/execution/engine/tools/platform/notification.ts +81 -0
- package/src/execution/engine/tools/platform/pdf/index.ts +110 -0
- package/src/execution/engine/tools/platform/pdf/types.ts +77 -0
- package/src/execution/engine/tools/platform/resource-invocation/__tests__/edge-cases.test.ts +507 -0
- package/src/execution/engine/tools/platform/resource-invocation/__tests__/resource-invocation-service.test.ts +500 -0
- package/src/execution/engine/tools/platform/resource-invocation/__tests__/tool.test.ts +555 -0
- package/src/execution/engine/tools/platform/resource-invocation/dynamic-tool.ts +94 -0
- package/src/execution/engine/tools/platform/resource-invocation/index.ts +14 -0
- package/src/execution/engine/tools/platform/resource-invocation/resource-invocation-service.ts +147 -0
- package/src/execution/engine/tools/platform/resource-invocation/tool.ts +115 -0
- package/src/execution/engine/tools/platform/resource-invocation/types.ts +31 -0
- package/src/execution/engine/tools/platform/scheduler.ts +87 -0
- package/src/execution/engine/tools/platform/schedules/cancel-by-key-tool.ts +48 -0
- package/src/execution/engine/tools/platform/schedules/cancel-by-metadata-tool.ts +42 -0
- package/src/execution/engine/tools/platform/schedules/delete-by-key-tool.ts +43 -0
- package/src/execution/engine/tools/platform/schedules/index.ts +13 -0
- package/src/execution/engine/tools/platform/schedules/list-tool.ts +56 -0
- package/src/execution/engine/tools/platform/schedules/types.ts +88 -0
- package/src/execution/engine/tools/platform/storage/__tests__/storage.test.ts +998 -0
- package/src/execution/engine/tools/platform/storage/index.ts +370 -0
- package/src/execution/engine/tools/platform/storage/types.ts +128 -0
- package/src/execution/engine/tools/platform/types.ts +148 -0
- package/src/execution/engine/tools/registry.ts +590 -0
- package/src/execution/engine/tools/tool-maps.ts +694 -0
- package/src/execution/engine/tools/types.ts +233 -0
- package/src/execution/engine/workflow/__tests__/errors.test.ts +139 -0
- package/src/execution/engine/workflow/__tests__/utils.test.ts +645 -0
- package/src/execution/engine/workflow/__tests__/workflow.test.ts +818 -0
- package/src/execution/engine/workflow/errors.ts +63 -0
- package/src/execution/engine/workflow/helpers/index.ts +11 -0
- package/src/execution/engine/workflow/helpers/server/index.ts +8 -0
- package/src/execution/engine/workflow/helpers/server/llm-call.ts +93 -0
- package/src/execution/engine/workflow/index.ts +19 -0
- package/src/execution/engine/workflow/log-truncate.ts +26 -0
- package/src/execution/engine/workflow/logging.ts +191 -0
- package/src/execution/engine/workflow/types.ts +183 -0
- package/src/execution/engine/workflow/utils.ts +280 -0
- package/src/execution/engine/workflow/workflow.ts +168 -0
- package/src/execution/index.ts +20 -0
- package/src/execution/scheduler/__tests__/api-schemas.test.ts +733 -0
- package/src/execution/scheduler/__tests__/retry.test.ts +37 -0
- package/src/execution/scheduler/__tests__/utils.test.ts +1009 -0
- package/src/execution/scheduler/api-schemas.ts +296 -0
- package/src/execution/scheduler/index.ts +50 -0
- package/src/execution/scheduler/schemas.ts +264 -0
- package/src/execution/scheduler/types.ts +111 -0
- package/src/execution/scheduler/utils.ts +364 -0
- package/src/forms/index.ts +7 -0
- package/src/forms/schemas.test.ts +113 -0
- package/src/forms/schemas.ts +69 -0
- package/src/forms/types.ts +70 -0
- package/src/index.ts +54 -0
- package/src/integrations/credentials/__tests__/api-schemas.test.ts +496 -0
- package/src/integrations/credentials/__tests__/schemas.test.ts +82 -0
- package/src/integrations/credentials/__tests__/utils.test.ts +144 -0
- package/src/integrations/credentials/api-schemas.ts +143 -0
- package/src/integrations/credentials/index.ts +32 -0
- package/src/integrations/credentials/schemas.ts +164 -0
- package/src/integrations/credentials/utils.ts +59 -0
- package/src/integrations/oauth/__tests__/provider-registry.test.ts +59 -0
- package/src/integrations/oauth/api-schemas.ts +92 -0
- package/src/integrations/oauth/index.ts +19 -0
- package/src/integrations/oauth/provider-registry.ts +61 -0
- package/src/integrations/oauth/server/__tests__/refresh-concurrent.test.ts +183 -0
- package/src/integrations/oauth/server/__tests__/refresh.integration.test.ts +257 -0
- package/src/integrations/oauth/server/__tests__/refresh.test.ts +577 -0
- package/src/integrations/oauth/server/credentials.ts +39 -0
- package/src/integrations/oauth/server/refresh.ts +214 -0
- package/src/integrations/oauth/types.ts +34 -0
- package/src/integrations/webhook-endpoints/__tests__/api-schemas.test.ts +318 -0
- package/src/integrations/webhook-endpoints/api-schemas.ts +102 -0
- package/src/integrations/webhook-endpoints/index.ts +28 -0
- package/src/integrations/webhook-endpoints/types.ts +51 -0
- package/src/operations/activities/api-schemas.ts +79 -0
- package/src/operations/activities/index.ts +9 -0
- package/src/operations/activities/sse-events.ts +30 -0
- package/src/operations/activities/types.ts +63 -0
- package/src/operations/debug-logs/client.ts +60 -0
- package/src/operations/debug-logs/debug-logger.ts +83 -0
- package/src/operations/debug-logs/index.ts +8 -0
- package/src/operations/debug-logs/server.ts +19 -0
- package/src/operations/debug-logs/types.ts +33 -0
- package/src/operations/index.ts +50 -0
- package/src/operations/notifications/__tests__/api-schemas.test.ts +216 -0
- package/src/operations/notifications/api-schemas.ts +91 -0
- package/src/operations/notifications/index.ts +3 -0
- package/src/operations/notifications/sse-events.ts +21 -0
- package/src/operations/notifications/types.ts +47 -0
- package/src/operations/observability/__tests__/openrouter-cost-flow.test.ts +297 -0
- package/src/operations/observability/__tests__/schemas.test.ts +151 -0
- package/src/operations/observability/__tests__/types.test.ts +109 -0
- package/src/operations/observability/__tests__/utils.test.ts +54 -0
- package/src/operations/observability/ai-usage-collector.ts +64 -0
- package/src/operations/observability/index.ts +13 -0
- package/src/operations/observability/metrics-collector.ts +49 -0
- package/src/operations/observability/schemas.ts +39 -0
- package/src/operations/observability/types.ts +463 -0
- package/src/operations/observability/utils.ts +77 -0
- package/src/operations/sessions/__tests__/api-schemas.test.ts +361 -0
- package/src/operations/sessions/__tests__/manager.test.ts +821 -0
- package/src/operations/sessions/api-schemas.ts +166 -0
- package/src/operations/sessions/index.ts +26 -0
- package/src/operations/sessions/server/manager.ts +90 -0
- package/src/operations/sessions/server/session.ts +180 -0
- package/src/operations/sessions/types.ts +98 -0
- package/src/operations/triggers/index.ts +12 -0
- package/src/operations/triggers/webhook/definitions/__tests__/instantly-reply-received.test.ts +72 -0
- package/src/operations/triggers/webhook/definitions/instantly-account-error.ts +44 -0
- package/src/operations/triggers/webhook/definitions/instantly-auto-reply-received.ts +51 -0
- package/src/operations/triggers/webhook/definitions/instantly-campaign-completed.ts +45 -0
- package/src/operations/triggers/webhook/definitions/instantly-email-bounced.ts +49 -0
- package/src/operations/triggers/webhook/definitions/instantly-lead-unsubscribed.ts +45 -0
- package/src/operations/triggers/webhook/definitions/instantly-reply-received.ts +54 -0
- package/src/operations/triggers/webhook/index.ts +35 -0
- package/src/operations/triggers/webhook/types.ts +74 -0
- package/src/organization-model/README.md +79 -0
- package/src/organization-model/__tests__/graph.test.ts +250 -0
- package/src/organization-model/__tests__/resolve.test.ts +47 -0
- package/src/organization-model/defaults.ts +60 -0
- package/src/organization-model/domains/branding.ts +22 -0
- package/src/organization-model/domains/crm.ts +46 -0
- package/src/organization-model/domains/delivery.ts +48 -0
- package/src/organization-model/domains/features.ts +57 -0
- package/src/organization-model/domains/lead-gen.ts +33 -0
- package/src/organization-model/domains/navigation.ts +103 -0
- package/src/organization-model/domains/shared.ts +42 -0
- package/src/organization-model/graph/build.ts +432 -0
- package/src/organization-model/graph/index.ts +4 -0
- package/src/organization-model/graph/schema.ts +50 -0
- package/src/organization-model/graph/types.ts +52 -0
- package/src/organization-model/index.ts +11 -0
- package/src/organization-model/published.ts +18 -0
- package/src/organization-model/resolve.ts +42 -0
- package/src/organization-model/schema.ts +21 -0
- package/src/organization-model/types.ts +27 -0
- package/src/platform/api/index.ts +1 -0
- package/src/platform/api/types.ts +35 -0
- package/src/platform/constants/http.ts +37 -0
- package/src/platform/constants/index.ts +5 -0
- package/src/platform/constants/limits.ts +32 -0
- package/src/platform/constants/resilience.ts +51 -0
- package/src/platform/constants/timeouts.ts +20 -0
- package/src/platform/constants/versions.ts +3 -0
- package/src/platform/index.ts +27 -0
- package/src/platform/registry/__tests__/command-view.test.ts +410 -0
- package/src/platform/registry/__tests__/resource-registry-static.test.ts +347 -0
- package/src/platform/registry/__tests__/resource-registry.integration.test.ts +1004 -0
- package/src/platform/registry/__tests__/resource-registry.list-executable.test.ts +393 -0
- package/src/platform/registry/__tests__/resource-registry.test.ts +1942 -0
- package/src/platform/registry/__tests__/serialization.test.ts +1127 -0
- package/src/platform/registry/__tests__/validation.test.ts +1086 -0
- package/src/platform/registry/command-view.ts +180 -0
- package/src/platform/registry/domains.ts +165 -0
- package/src/platform/registry/index.ts +93 -0
- package/src/platform/registry/reserved.ts +24 -0
- package/src/platform/registry/resource-metadata.ts +59 -0
- package/src/platform/registry/resource-registry.command-queue-groups.test.ts +129 -0
- package/src/platform/registry/resource-registry.ts +788 -0
- package/src/platform/registry/serialization.ts +273 -0
- package/src/platform/registry/serialized-types.ts +231 -0
- package/src/platform/registry/stats-types.ts +66 -0
- package/src/platform/registry/types.ts +404 -0
- package/src/platform/registry/validation.ts +513 -0
- package/src/platform/resilience/__tests__/circuit-breaker.test.ts +291 -0
- package/src/platform/resilience/__tests__/http-error-mapper.test.ts +173 -0
- package/src/platform/resilience/__tests__/rate-limiter.test.ts +471 -0
- package/src/platform/resilience/__tests__/retry.test.ts +380 -0
- package/src/platform/resilience/__tests__/timeout.test.ts +219 -0
- package/src/platform/resilience/circuit-breaker.ts +164 -0
- package/src/platform/resilience/errors.ts +68 -0
- package/src/platform/resilience/http-error-mapper.ts +129 -0
- package/src/platform/resilience/index.ts +93 -0
- package/src/platform/resilience/rate-limiter-types.ts +46 -0
- package/src/platform/resilience/rate-limiter.ts +140 -0
- package/src/platform/resilience/retry.ts +89 -0
- package/src/platform/resilience/timeout.ts +63 -0
- package/src/platform/sse/events.ts +67 -0
- package/src/platform/sse/index.ts +7 -0
- package/src/platform/utils/__tests__/currency.test.ts +77 -0
- package/src/platform/utils/__tests__/validation.test.ts +1083 -0
- package/src/platform/utils/currency.ts +96 -0
- package/src/platform/utils/debounce.ts +52 -0
- package/src/platform/utils/error.ts +42 -0
- package/src/platform/utils/hmac.test.ts +97 -0
- package/src/platform/utils/index.ts +32 -0
- package/src/platform/utils/server/betterstack-logger.ts +210 -0
- package/src/platform/utils/server/hmac.ts +44 -0
- package/src/platform/utils/server/unsubscribe.ts +111 -0
- package/src/platform/utils/token-counter.ts +96 -0
- package/src/platform/utils/validation.ts +425 -0
- package/src/projects/api-schemas.ts +265 -0
- package/src/published.ts +1 -0
- package/src/server.ts +273 -0
- package/src/supabase/__tests__/helpers.test.ts +51 -0
- package/src/supabase/database.types.ts +2674 -0
- package/src/supabase/helpers.ts +20 -0
- package/src/supabase/index.ts +52 -0
- package/src/supabase/server/client.ts +58 -0
- package/src/test-utils/README.md +150 -0
- package/src/test-utils/browser-mocks.ts +54 -0
- package/src/test-utils/fixtures/api-keys.ts +52 -0
- package/src/test-utils/fixtures/index.ts +4 -0
- package/src/test-utils/fixtures/memberships.ts +80 -0
- package/src/test-utils/fixtures/organizations.ts +69 -0
- package/src/test-utils/fixtures/users.ts +79 -0
- package/src/test-utils/index.ts +11 -0
- package/src/test-utils/mocks/index.ts +2 -0
- package/src/test-utils/mocks/supabase.ts +142 -0
- package/src/test-utils/mocks/workos.ts +108 -0
- package/src/test-utils/rls/RLSTestContext.ts +586 -0
- package/src/test-utils/rls/index.ts +1 -0
|
@@ -0,0 +1,818 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
+
import { Workflow } from '../workflow'
|
|
3
|
+
import type { WorkflowDefinition, WorkflowConfig, WorkflowStep, NextConfig } from '../types'
|
|
4
|
+
import { StepType } from '../types'
|
|
5
|
+
import type { Contract, ExecutionContext } from '../../base/types'
|
|
6
|
+
import { z } from 'zod'
|
|
7
|
+
import { WorkflowStepError, WorkflowValidationError } from '../errors'
|
|
8
|
+
|
|
9
|
+
describe('Workflow Execution', () => {
|
|
10
|
+
// Helper: Create mock execution context
|
|
11
|
+
const createMockContext = (): ExecutionContext => ({
|
|
12
|
+
executionId: 'exec-123',
|
|
13
|
+
organizationId: 'org-123',
|
|
14
|
+
userId: 'user-123',
|
|
15
|
+
logger: {
|
|
16
|
+
info: vi.fn(),
|
|
17
|
+
error: vi.fn(),
|
|
18
|
+
warn: vi.fn(),
|
|
19
|
+
debug: vi.fn()
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
// Helper: Create step with handler
|
|
24
|
+
const createStep = <T, R>(
|
|
25
|
+
id: string,
|
|
26
|
+
description: string,
|
|
27
|
+
handler: (input: T, context: ExecutionContext) => Promise<R> | R,
|
|
28
|
+
next: NextConfig = null
|
|
29
|
+
): WorkflowStep => ({
|
|
30
|
+
id,
|
|
31
|
+
name: `Step ${id}`,
|
|
32
|
+
description,
|
|
33
|
+
handler,
|
|
34
|
+
inputSchema: z.unknown(),
|
|
35
|
+
outputSchema: z.unknown(),
|
|
36
|
+
next
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
// Helper: Create minimal workflow definition
|
|
40
|
+
const createWorkflowDefinition = (steps: WorkflowStep[], entryPoint: string): WorkflowDefinition => {
|
|
41
|
+
const config: WorkflowConfig = {
|
|
42
|
+
type: 'workflow',
|
|
43
|
+
resourceId: 'test-workflow',
|
|
44
|
+
name: 'Test Workflow',
|
|
45
|
+
description: 'Workflow for testing',
|
|
46
|
+
environment: 'dev'
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const contract: Contract = {
|
|
50
|
+
inputSchema: z.object({ value: z.number() }),
|
|
51
|
+
outputSchema: z.object({ result: z.number() })
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const stepsRecord: Record<string, WorkflowStep> = {}
|
|
55
|
+
steps.forEach((step) => { stepsRecord[step.id] = step })
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
config,
|
|
59
|
+
contract,
|
|
60
|
+
steps: stepsRecord,
|
|
61
|
+
entryPoint
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
describe('Constructor Validation', () => {
|
|
66
|
+
it('creates workflow instance from definition', () => {
|
|
67
|
+
const step1 = createStep('step1', 'Terminal step', async (input) => input)
|
|
68
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
69
|
+
|
|
70
|
+
const workflow = new Workflow(definition)
|
|
71
|
+
|
|
72
|
+
expect(workflow.config).toEqual(definition.config)
|
|
73
|
+
expect(workflow.contract).toEqual(definition.contract)
|
|
74
|
+
expect(workflow.steps).toEqual(definition.steps)
|
|
75
|
+
expect(workflow.entryPoint).toBe('step1')
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('validates entry point exists', () => {
|
|
79
|
+
const step1 = createStep('step1', 'Step 1', async (input) => input)
|
|
80
|
+
const definition = createWorkflowDefinition([step1], 'nonexistent')
|
|
81
|
+
|
|
82
|
+
expect(() => new Workflow(definition)).toThrow(WorkflowValidationError)
|
|
83
|
+
expect(() => new Workflow(definition)).toThrow(/Entry point.*not found/)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('validates at least one terminal step exists', () => {
|
|
87
|
+
const step1 = createStep('step1', 'Step 1', async (input) => input, {
|
|
88
|
+
type: StepType.LINEAR,
|
|
89
|
+
target: 'step2'
|
|
90
|
+
})
|
|
91
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
92
|
+
|
|
93
|
+
expect(() => new Workflow(definition)).toThrow(WorkflowValidationError)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('validates step references point to existing steps', () => {
|
|
97
|
+
const step1 = createStep('step1', 'Step 1', async (input) => input, {
|
|
98
|
+
type: StepType.LINEAR,
|
|
99
|
+
target: 'missing'
|
|
100
|
+
})
|
|
101
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
102
|
+
|
|
103
|
+
// This will actually fail on "no terminal steps" first, since step1 points to 'missing' (not null)
|
|
104
|
+
expect(() => new Workflow(definition)).toThrow(WorkflowValidationError)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('allows valid workflow with multiple steps', () => {
|
|
108
|
+
const step1 = createStep('step1', 'Step 1', async (input) => input, {
|
|
109
|
+
type: StepType.LINEAR,
|
|
110
|
+
target: 'step2'
|
|
111
|
+
})
|
|
112
|
+
const step2 = createStep('step2', 'Step 2', async (input) => input)
|
|
113
|
+
const definition = createWorkflowDefinition([step1, step2], 'step1')
|
|
114
|
+
|
|
115
|
+
expect(() => new Workflow(definition)).not.toThrow()
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
describe('Linear Execution', () => {
|
|
120
|
+
it('executes single step workflow', async () => {
|
|
121
|
+
const handler = vi.fn(async (input: { value: number }) => ({ result: input.value * 2 }))
|
|
122
|
+
const step1 = createStep('step1', 'Multiply by 2', handler)
|
|
123
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
124
|
+
|
|
125
|
+
const workflow = new Workflow(definition)
|
|
126
|
+
const context = createMockContext()
|
|
127
|
+
|
|
128
|
+
const output = await workflow.execute({ value: 5 }, context)
|
|
129
|
+
|
|
130
|
+
expect(handler).toHaveBeenCalledWith({ value: 5 }, context)
|
|
131
|
+
expect(output).toEqual({ result: 10 })
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
it('executes steps in sequence (linear flow)', async () => {
|
|
135
|
+
const executionOrder: string[] = []
|
|
136
|
+
|
|
137
|
+
const step1 = createStep(
|
|
138
|
+
'step1',
|
|
139
|
+
'Add 1',
|
|
140
|
+
async (input: { value: number }) => {
|
|
141
|
+
executionOrder.push('step1')
|
|
142
|
+
return { value: input.value + 1 }
|
|
143
|
+
},
|
|
144
|
+
{ type: StepType.LINEAR, target: 'step2' }
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
const step2 = createStep(
|
|
148
|
+
'step2',
|
|
149
|
+
'Multiply by 2',
|
|
150
|
+
async (input: { value: number }) => {
|
|
151
|
+
executionOrder.push('step2')
|
|
152
|
+
return { value: input.value * 2 }
|
|
153
|
+
},
|
|
154
|
+
{ type: StepType.LINEAR, target: 'step3' }
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
const step3 = createStep(
|
|
158
|
+
'step3',
|
|
159
|
+
'Return result',
|
|
160
|
+
async (input: { value: number }) => {
|
|
161
|
+
executionOrder.push('step3')
|
|
162
|
+
return { result: input.value }
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
const definition = createWorkflowDefinition([step1, step2, step3], 'step1')
|
|
167
|
+
const workflow = new Workflow(definition)
|
|
168
|
+
const context = createMockContext()
|
|
169
|
+
|
|
170
|
+
const output = await workflow.execute({ value: 5 }, context)
|
|
171
|
+
|
|
172
|
+
expect(executionOrder).toEqual(['step1', 'step2', 'step3'])
|
|
173
|
+
expect(output).toEqual({ result: 12 }) // (5 + 1) * 2 = 12
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('passes data between steps', async () => {
|
|
177
|
+
const step1 = createStep(
|
|
178
|
+
'step1',
|
|
179
|
+
'Add 10',
|
|
180
|
+
async (input: { value: number }) => ({ intermediate: input.value + 10 }),
|
|
181
|
+
{ type: StepType.LINEAR, target: 'step2' }
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
const step2Handler = vi.fn(async (input: { intermediate: number }) => ({
|
|
185
|
+
result: input.intermediate * 3
|
|
186
|
+
}))
|
|
187
|
+
const step2 = createStep('step2', 'Multiply by 3', step2Handler)
|
|
188
|
+
|
|
189
|
+
const definition = createWorkflowDefinition([step1, step2], 'step1')
|
|
190
|
+
const workflow = new Workflow(definition)
|
|
191
|
+
const context = createMockContext()
|
|
192
|
+
|
|
193
|
+
const output = await workflow.execute({ value: 5 }, context)
|
|
194
|
+
|
|
195
|
+
expect(step2Handler).toHaveBeenCalledWith({ intermediate: 15 }, context)
|
|
196
|
+
expect(output).toEqual({ result: 45 })
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
it('validates input against contract schema', async () => {
|
|
200
|
+
const step1 = createStep('step1', 'Return result', async (_input) => ({ result: 0 }))
|
|
201
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
202
|
+
|
|
203
|
+
const workflow = new Workflow(definition)
|
|
204
|
+
const context = createMockContext()
|
|
205
|
+
|
|
206
|
+
const invalidInput = { wrong: 'field' }
|
|
207
|
+
|
|
208
|
+
await expect(workflow.execute(invalidInput as unknown, context)).rejects.toThrow()
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
it('validates step input schemas', async () => {
|
|
212
|
+
const step1: WorkflowStep = {
|
|
213
|
+
id: 'step1',
|
|
214
|
+
name: 'Step 1',
|
|
215
|
+
description: 'Process value',
|
|
216
|
+
handler: async (input: { value: number }) => ({ result: input.value }),
|
|
217
|
+
inputSchema: z.object({ value: z.number() }),
|
|
218
|
+
outputSchema: z.object({ result: z.number() }),
|
|
219
|
+
next: null
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
223
|
+
const workflow = new Workflow(definition)
|
|
224
|
+
const context = createMockContext()
|
|
225
|
+
|
|
226
|
+
// Valid input
|
|
227
|
+
const output = await workflow.execute({ value: 10 }, context)
|
|
228
|
+
expect(output).toEqual({ result: 10 })
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
it('validates step output schemas', async () => {
|
|
232
|
+
const step1: WorkflowStep = {
|
|
233
|
+
id: 'step1',
|
|
234
|
+
name: 'Step 1',
|
|
235
|
+
description: 'Invalid output',
|
|
236
|
+
handler: async () => ({ wrong: 'output' }), // Invalid output
|
|
237
|
+
inputSchema: z.object({ value: z.number() }),
|
|
238
|
+
outputSchema: z.object({ data: z.number() }),
|
|
239
|
+
next: null
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
243
|
+
const workflow = new Workflow(definition)
|
|
244
|
+
const context = createMockContext()
|
|
245
|
+
|
|
246
|
+
await expect(workflow.execute({ value: 10 }, context)).rejects.toThrow(WorkflowStepError)
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
it('validates terminal step output against workflow contract', async () => {
|
|
250
|
+
const step1 = createStep('step1', 'Invalid result', async () => ({ result: 'string instead of number' }))
|
|
251
|
+
|
|
252
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
253
|
+
const workflow = new Workflow(definition)
|
|
254
|
+
const context = createMockContext()
|
|
255
|
+
|
|
256
|
+
await expect(workflow.execute({ value: 10 }, context)).rejects.toThrow()
|
|
257
|
+
})
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
describe('Conditional Branching', () => {
|
|
261
|
+
it('executes conditional next step', async () => {
|
|
262
|
+
const step1: WorkflowStep = {
|
|
263
|
+
id: 'step1',
|
|
264
|
+
name: 'Decision',
|
|
265
|
+
description: 'Route based on value',
|
|
266
|
+
handler: async (input: { value: number }) => ({ value: input.value }),
|
|
267
|
+
inputSchema: z.object({ value: z.number() }),
|
|
268
|
+
outputSchema: z.object({ value: z.number() }),
|
|
269
|
+
next: {
|
|
270
|
+
type: StepType.CONDITIONAL,
|
|
271
|
+
routes: [
|
|
272
|
+
{
|
|
273
|
+
condition: (output: { value: number }) => output.value > 10,
|
|
274
|
+
target: 'pathA'
|
|
275
|
+
}
|
|
276
|
+
],
|
|
277
|
+
default: 'pathB'
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const pathA = createStep('pathA', 'Path A', async () => ({ result: 100 }))
|
|
282
|
+
const pathB = createStep('pathB', 'Path B', async () => ({ result: 200 }))
|
|
283
|
+
|
|
284
|
+
const definition = createWorkflowDefinition([step1, pathA, pathB], 'step1')
|
|
285
|
+
const workflow = new Workflow(definition)
|
|
286
|
+
const context = createMockContext()
|
|
287
|
+
|
|
288
|
+
// Test pathA (value > 10)
|
|
289
|
+
const outputA = await workflow.execute({ value: 15 }, context)
|
|
290
|
+
expect(outputA).toEqual({ result: 100 })
|
|
291
|
+
|
|
292
|
+
// Test pathB (value <= 10)
|
|
293
|
+
const outputB = await workflow.execute({ value: 5 }, context)
|
|
294
|
+
expect(outputB).toEqual({ result: 200 })
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
it('handles complex branching logic', async () => {
|
|
298
|
+
const executionPath: string[] = []
|
|
299
|
+
|
|
300
|
+
const step1: WorkflowStep = {
|
|
301
|
+
id: 'step1',
|
|
302
|
+
name: 'Router',
|
|
303
|
+
description: 'Route by category',
|
|
304
|
+
handler: async (input: { value: number }) => {
|
|
305
|
+
executionPath.push('step1')
|
|
306
|
+
return { value: input.value }
|
|
307
|
+
},
|
|
308
|
+
inputSchema: z.object({ value: z.number() }),
|
|
309
|
+
outputSchema: z.object({ value: z.number() }),
|
|
310
|
+
next: {
|
|
311
|
+
type: StepType.CONDITIONAL,
|
|
312
|
+
routes: [
|
|
313
|
+
{
|
|
314
|
+
condition: (output: { value: number }) => output.value < 10,
|
|
315
|
+
target: 'handleSmall'
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
condition: (output: { value: number }) => output.value < 50,
|
|
319
|
+
target: 'handleMedium'
|
|
320
|
+
}
|
|
321
|
+
],
|
|
322
|
+
default: 'handleLarge'
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const handleSmall = createStep('handleSmall', 'Handle small', async () => {
|
|
327
|
+
executionPath.push('handleSmall')
|
|
328
|
+
return { result: 1 }
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
const handleMedium = createStep('handleMedium', 'Handle medium', async () => {
|
|
332
|
+
executionPath.push('handleMedium')
|
|
333
|
+
return { result: 2 }
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
const handleLarge = createStep('handleLarge', 'Handle large', async () => {
|
|
337
|
+
executionPath.push('handleLarge')
|
|
338
|
+
return { result: 3 }
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
const definition = createWorkflowDefinition([step1, handleSmall, handleMedium, handleLarge], 'step1')
|
|
342
|
+
const workflow = new Workflow(definition)
|
|
343
|
+
const context = createMockContext()
|
|
344
|
+
|
|
345
|
+
// Test small path
|
|
346
|
+
executionPath.length = 0
|
|
347
|
+
const small = await workflow.execute({ value: 5 }, context)
|
|
348
|
+
expect(executionPath).toEqual(['step1', 'handleSmall'])
|
|
349
|
+
expect(small).toEqual({ result: 1 })
|
|
350
|
+
|
|
351
|
+
// Test medium path
|
|
352
|
+
executionPath.length = 0
|
|
353
|
+
const medium = await workflow.execute({ value: 25 }, context)
|
|
354
|
+
expect(executionPath).toEqual(['step1', 'handleMedium'])
|
|
355
|
+
expect(medium).toEqual({ result: 2 })
|
|
356
|
+
|
|
357
|
+
// Test large path (default)
|
|
358
|
+
executionPath.length = 0
|
|
359
|
+
const large = await workflow.execute({ value: 100 }, context)
|
|
360
|
+
expect(executionPath).toEqual(['step1', 'handleLarge'])
|
|
361
|
+
expect(large).toEqual({ result: 3 })
|
|
362
|
+
})
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
describe('Error Handling', () => {
|
|
366
|
+
it('propagates errors from step handlers as WorkflowStepError', async () => {
|
|
367
|
+
const step1 = createStep('step1', 'Failing step', async () => {
|
|
368
|
+
throw new Error('Step handler failed')
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
372
|
+
const workflow = new Workflow(definition)
|
|
373
|
+
const context = createMockContext()
|
|
374
|
+
|
|
375
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow(WorkflowStepError)
|
|
376
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow(/Step failed.*step1/)
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
it('includes step ID and name in error context', async () => {
|
|
380
|
+
const step1: WorkflowStep = {
|
|
381
|
+
id: 'processData',
|
|
382
|
+
name: 'Data Processor',
|
|
383
|
+
description: 'Process data',
|
|
384
|
+
handler: async () => {
|
|
385
|
+
throw new Error('Processing error')
|
|
386
|
+
},
|
|
387
|
+
inputSchema: z.unknown(),
|
|
388
|
+
outputSchema: z.unknown(),
|
|
389
|
+
next: null
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const definition = createWorkflowDefinition([step1], 'processData')
|
|
393
|
+
const workflow = new Workflow(definition)
|
|
394
|
+
const context = createMockContext()
|
|
395
|
+
|
|
396
|
+
try {
|
|
397
|
+
await workflow.execute({ value: 1 }, context)
|
|
398
|
+
expect.unreachable('Should have thrown')
|
|
399
|
+
} catch (error) {
|
|
400
|
+
expect(error).toBeInstanceOf(WorkflowStepError)
|
|
401
|
+
const stepError = error as WorkflowStepError
|
|
402
|
+
expect(stepError.context).toHaveProperty('stepId', 'processData')
|
|
403
|
+
expect(stepError.context).toHaveProperty('stepName', 'Data Processor')
|
|
404
|
+
expect(stepError.context).toHaveProperty('workflowId', 'test-workflow')
|
|
405
|
+
}
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
it('stops execution on step failure', async () => {
|
|
409
|
+
const step1Handler = vi.fn(async () => {
|
|
410
|
+
throw new Error('Failed')
|
|
411
|
+
})
|
|
412
|
+
const step2Handler = vi.fn(async () => ({ result: 1 }))
|
|
413
|
+
|
|
414
|
+
const step1 = createStep('step1', 'Step 1', step1Handler, {
|
|
415
|
+
type: StepType.LINEAR,
|
|
416
|
+
target: 'step2'
|
|
417
|
+
})
|
|
418
|
+
const step2 = createStep('step2', 'Step 2', step2Handler)
|
|
419
|
+
|
|
420
|
+
const definition = createWorkflowDefinition([step1, step2], 'step1')
|
|
421
|
+
const workflow = new Workflow(definition)
|
|
422
|
+
const context = createMockContext()
|
|
423
|
+
|
|
424
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow()
|
|
425
|
+
|
|
426
|
+
expect(step1Handler).toHaveBeenCalled()
|
|
427
|
+
expect(step2Handler).not.toHaveBeenCalled()
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
it('handles validation errors in step input', async () => {
|
|
431
|
+
const step1 = createStep('step1', 'Step 1', async () => ({ wrong: 'output' }), {
|
|
432
|
+
type: StepType.LINEAR,
|
|
433
|
+
target: 'step2'
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
const step2: WorkflowStep = {
|
|
437
|
+
id: 'step2',
|
|
438
|
+
name: 'Step 2',
|
|
439
|
+
description: 'Requires string input',
|
|
440
|
+
handler: async (input: { required: string }) => ({ result: input.required.length }),
|
|
441
|
+
inputSchema: z.object({ required: z.string() }),
|
|
442
|
+
outputSchema: z.object({ result: z.number() }),
|
|
443
|
+
next: null
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const definition = createWorkflowDefinition([step1, step2], 'step1')
|
|
447
|
+
const workflow = new Workflow(definition)
|
|
448
|
+
const context = createMockContext()
|
|
449
|
+
|
|
450
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow()
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
it('handles null input gracefully', async () => {
|
|
454
|
+
const step1 = createStep('step1', 'Step 1', async () => ({ result: 1 }))
|
|
455
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
456
|
+
const workflow = new Workflow(definition)
|
|
457
|
+
const context = createMockContext()
|
|
458
|
+
|
|
459
|
+
await expect(workflow.execute(null as unknown, context)).rejects.toThrow()
|
|
460
|
+
})
|
|
461
|
+
|
|
462
|
+
it('handles undefined input gracefully', async () => {
|
|
463
|
+
const step1 = createStep('step1', 'Step 1', async () => ({ result: 1 }))
|
|
464
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
465
|
+
const workflow = new Workflow(definition)
|
|
466
|
+
const context = createMockContext()
|
|
467
|
+
|
|
468
|
+
await expect(workflow.execute(undefined as unknown, context)).rejects.toThrow()
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
it('handles step handler returning null', async () => {
|
|
472
|
+
const step1 = createStep('step1', 'Returns null', async () => null, {
|
|
473
|
+
type: StepType.LINEAR,
|
|
474
|
+
target: 'step2'
|
|
475
|
+
})
|
|
476
|
+
const step2 = createStep('step2', 'Step 2', async () => ({ result: 1 }))
|
|
477
|
+
|
|
478
|
+
const definition = createWorkflowDefinition([step1, step2], 'step1')
|
|
479
|
+
const workflow = new Workflow(definition)
|
|
480
|
+
const context = createMockContext()
|
|
481
|
+
|
|
482
|
+
// Workflow may pass null to next step which handles it gracefully
|
|
483
|
+
// This tests that the workflow doesn't crash
|
|
484
|
+
const output = await workflow.execute({ value: 1 }, context)
|
|
485
|
+
expect(output).toBeDefined()
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
it('handles step handler returning undefined', async () => {
|
|
489
|
+
const step1 = createStep('step1', 'Returns undefined', async () => undefined)
|
|
490
|
+
|
|
491
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
492
|
+
const workflow = new Workflow(definition)
|
|
493
|
+
const context = createMockContext()
|
|
494
|
+
|
|
495
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow()
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
it('handles async errors in step handlers', async () => {
|
|
499
|
+
const step1 = createStep('step1', 'Async error', async () => {
|
|
500
|
+
await new Promise((resolve) => setTimeout(resolve, 10))
|
|
501
|
+
throw new Error('Async operation failed')
|
|
502
|
+
})
|
|
503
|
+
|
|
504
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
505
|
+
const workflow = new Workflow(definition)
|
|
506
|
+
const context = createMockContext()
|
|
507
|
+
|
|
508
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow(/Async operation failed/)
|
|
509
|
+
})
|
|
510
|
+
|
|
511
|
+
it('handles errors in conditional route evaluation', async () => {
|
|
512
|
+
const step1: WorkflowStep = {
|
|
513
|
+
id: 'step1',
|
|
514
|
+
name: 'Broken condition',
|
|
515
|
+
description: 'Condition throws error',
|
|
516
|
+
handler: async (input: { value: number }) => ({ value: input.value }),
|
|
517
|
+
inputSchema: z.object({ value: z.number() }),
|
|
518
|
+
outputSchema: z.object({ value: z.number() }),
|
|
519
|
+
next: {
|
|
520
|
+
type: StepType.CONDITIONAL,
|
|
521
|
+
routes: [
|
|
522
|
+
{
|
|
523
|
+
condition: (_output: unknown) => {
|
|
524
|
+
throw new Error('Condition evaluation failed')
|
|
525
|
+
},
|
|
526
|
+
target: 'pathA'
|
|
527
|
+
}
|
|
528
|
+
],
|
|
529
|
+
default: 'pathB'
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const pathA = createStep('pathA', 'Path A', async () => ({ result: 1 }))
|
|
534
|
+
const pathB = createStep('pathB', 'Path B', async () => ({ result: 2 }))
|
|
535
|
+
|
|
536
|
+
const definition = createWorkflowDefinition([step1, pathA, pathB], 'step1')
|
|
537
|
+
const workflow = new Workflow(definition)
|
|
538
|
+
const context = createMockContext()
|
|
539
|
+
|
|
540
|
+
// If condition throws, workflow may fall back to default route
|
|
541
|
+
// Test that it handles this gracefully (either throws or uses default)
|
|
542
|
+
try {
|
|
543
|
+
const output = await workflow.execute({ value: 1 }, context)
|
|
544
|
+
// If it succeeds, should have used default path
|
|
545
|
+
expect(output).toEqual({ result: 2 })
|
|
546
|
+
} catch (error) {
|
|
547
|
+
// Or it may throw the error - both are acceptable
|
|
548
|
+
expect(error).toBeDefined()
|
|
549
|
+
}
|
|
550
|
+
})
|
|
551
|
+
|
|
552
|
+
it('handles missing conditional default route when no condition matches', async () => {
|
|
553
|
+
const step1: WorkflowStep = {
|
|
554
|
+
id: 'step1',
|
|
555
|
+
name: 'No default',
|
|
556
|
+
description: 'No default route',
|
|
557
|
+
handler: async (input: { value: number }) => ({ value: input.value }),
|
|
558
|
+
inputSchema: z.object({ value: z.number() }),
|
|
559
|
+
outputSchema: z.object({ value: z.number() }),
|
|
560
|
+
next: {
|
|
561
|
+
type: StepType.CONDITIONAL,
|
|
562
|
+
routes: [
|
|
563
|
+
{
|
|
564
|
+
condition: (output: unknown) => (output as { value: number }).value > 100,
|
|
565
|
+
target: 'pathA'
|
|
566
|
+
}
|
|
567
|
+
],
|
|
568
|
+
default: 'pathTerminal' // Need a valid default
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
const pathA = createStep('pathA', 'Path A', async () => ({ result: 1 }))
|
|
573
|
+
const pathTerminal = createStep('pathTerminal', 'Terminal', async () => ({ result: 0 }))
|
|
574
|
+
|
|
575
|
+
const definition = createWorkflowDefinition([step1, pathA, pathTerminal], 'step1')
|
|
576
|
+
const workflow = new Workflow(definition)
|
|
577
|
+
const context = createMockContext()
|
|
578
|
+
|
|
579
|
+
// When value <= 100, should use default route
|
|
580
|
+
const output = await workflow.execute({ value: 50 }, context)
|
|
581
|
+
expect(output).toEqual({ result: 0 })
|
|
582
|
+
})
|
|
583
|
+
|
|
584
|
+
it('handles step that violates output schema constraints', async () => {
|
|
585
|
+
const step1: WorkflowStep = {
|
|
586
|
+
id: 'step1',
|
|
587
|
+
name: 'Schema violation',
|
|
588
|
+
description: 'Violates constraints',
|
|
589
|
+
handler: async () => ({ count: -5 }), // Negative number
|
|
590
|
+
inputSchema: z.object({ value: z.number() }),
|
|
591
|
+
outputSchema: z.object({ count: z.number().positive() }), // Must be positive
|
|
592
|
+
next: null
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
596
|
+
const workflow = new Workflow(definition)
|
|
597
|
+
const context = createMockContext()
|
|
598
|
+
|
|
599
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow()
|
|
600
|
+
})
|
|
601
|
+
|
|
602
|
+
it('handles complex nested schema validation failures', async () => {
|
|
603
|
+
const step1: WorkflowStep = {
|
|
604
|
+
id: 'step1',
|
|
605
|
+
name: 'Complex schema',
|
|
606
|
+
description: 'Complex nested output',
|
|
607
|
+
handler: async () => ({
|
|
608
|
+
data: {
|
|
609
|
+
items: [
|
|
610
|
+
{ id: 'invalid-format' } // Missing required fields
|
|
611
|
+
]
|
|
612
|
+
}
|
|
613
|
+
}),
|
|
614
|
+
inputSchema: z.object({ value: z.number() }),
|
|
615
|
+
outputSchema: z.object({
|
|
616
|
+
data: z.object({
|
|
617
|
+
items: z.array(
|
|
618
|
+
z.object({
|
|
619
|
+
id: z.string().uuid(),
|
|
620
|
+
name: z.string(),
|
|
621
|
+
count: z.number()
|
|
622
|
+
})
|
|
623
|
+
)
|
|
624
|
+
})
|
|
625
|
+
}),
|
|
626
|
+
next: null
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
630
|
+
const workflow = new Workflow(definition)
|
|
631
|
+
const context = createMockContext()
|
|
632
|
+
|
|
633
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow()
|
|
634
|
+
})
|
|
635
|
+
|
|
636
|
+
it('handles step throwing non-Error objects', async () => {
|
|
637
|
+
const step1 = createStep('step1', 'Throws string', async () => {
|
|
638
|
+
throw 'String error'
|
|
639
|
+
})
|
|
640
|
+
|
|
641
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
642
|
+
const workflow = new Workflow(definition)
|
|
643
|
+
const context = createMockContext()
|
|
644
|
+
|
|
645
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow()
|
|
646
|
+
})
|
|
647
|
+
|
|
648
|
+
it('handles step throwing object without message', async () => {
|
|
649
|
+
const step1 = createStep('step1', 'Throws object', async () => {
|
|
650
|
+
throw { code: 'ERR_CUSTOM', details: 'Something went wrong' }
|
|
651
|
+
})
|
|
652
|
+
|
|
653
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
654
|
+
const workflow = new Workflow(definition)
|
|
655
|
+
const context = createMockContext()
|
|
656
|
+
|
|
657
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow()
|
|
658
|
+
})
|
|
659
|
+
|
|
660
|
+
it('handles errors in multi-step workflows at different positions', async () => {
|
|
661
|
+
const step1Handler = vi.fn(async (input: { value: number }) => ({ value: input.value + 1 }))
|
|
662
|
+
const step2Handler = vi.fn(async () => {
|
|
663
|
+
throw new Error('Error in middle step')
|
|
664
|
+
})
|
|
665
|
+
const step3Handler = vi.fn(async () => ({ result: 1 }))
|
|
666
|
+
|
|
667
|
+
const step1 = createStep('step1', 'Step 1', step1Handler, {
|
|
668
|
+
type: StepType.LINEAR,
|
|
669
|
+
target: 'step2'
|
|
670
|
+
})
|
|
671
|
+
const step2 = createStep('step2', 'Step 2', step2Handler, {
|
|
672
|
+
type: StepType.LINEAR,
|
|
673
|
+
target: 'step3'
|
|
674
|
+
})
|
|
675
|
+
const step3 = createStep('step3', 'Step 3', step3Handler)
|
|
676
|
+
|
|
677
|
+
const definition = createWorkflowDefinition([step1, step2, step3], 'step1')
|
|
678
|
+
const workflow = new Workflow(definition)
|
|
679
|
+
const context = createMockContext()
|
|
680
|
+
|
|
681
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow(WorkflowStepError)
|
|
682
|
+
|
|
683
|
+
// Verify execution stopped at step2
|
|
684
|
+
expect(step1Handler).toHaveBeenCalled()
|
|
685
|
+
expect(step2Handler).toHaveBeenCalled()
|
|
686
|
+
expect(step3Handler).not.toHaveBeenCalled()
|
|
687
|
+
})
|
|
688
|
+
|
|
689
|
+
it('logs detailed error information', async () => {
|
|
690
|
+
const step1 = createStep('step1', 'Failing step', async () => {
|
|
691
|
+
throw new Error('Detailed error message')
|
|
692
|
+
})
|
|
693
|
+
|
|
694
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
695
|
+
const workflow = new Workflow(definition)
|
|
696
|
+
const context = createMockContext()
|
|
697
|
+
|
|
698
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow()
|
|
699
|
+
|
|
700
|
+
// Verify error was logged
|
|
701
|
+
expect(context.logger.error).toHaveBeenCalled()
|
|
702
|
+
})
|
|
703
|
+
})
|
|
704
|
+
|
|
705
|
+
describe('Cycle Detection', () => {
|
|
706
|
+
it('detects simple cycle (A -> A) at runtime', async () => {
|
|
707
|
+
const stepA: WorkflowStep = {
|
|
708
|
+
id: 'stepA',
|
|
709
|
+
name: 'Step A',
|
|
710
|
+
description: 'Points to itself',
|
|
711
|
+
handler: async (input: unknown) => input,
|
|
712
|
+
inputSchema: z.unknown(),
|
|
713
|
+
outputSchema: z.unknown(),
|
|
714
|
+
next: { type: StepType.LINEAR, target: 'stepA' }
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Add terminal step to pass constructor validation
|
|
718
|
+
const terminalStep = createStep('terminal', 'Terminal', async () => ({ result: 1 }))
|
|
719
|
+
|
|
720
|
+
const definition = createWorkflowDefinition([stepA, terminalStep], 'stepA')
|
|
721
|
+
const workflow = new Workflow(definition)
|
|
722
|
+
const context = createMockContext()
|
|
723
|
+
|
|
724
|
+
// Cycle will be detected during execution
|
|
725
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow(WorkflowStepError)
|
|
726
|
+
})
|
|
727
|
+
|
|
728
|
+
it('detects two-step cycle (A -> B -> A) at runtime', async () => {
|
|
729
|
+
const stepA = createStep('stepA', 'Step A', async (input: unknown) => input, {
|
|
730
|
+
type: StepType.LINEAR,
|
|
731
|
+
target: 'stepB'
|
|
732
|
+
})
|
|
733
|
+
|
|
734
|
+
const stepB = createStep('stepB', 'Step B', async (input: unknown) => input, {
|
|
735
|
+
type: StepType.LINEAR,
|
|
736
|
+
target: 'stepA'
|
|
737
|
+
})
|
|
738
|
+
|
|
739
|
+
// Add terminal step to pass constructor validation
|
|
740
|
+
const terminalStep = createStep('terminal', 'Terminal', async () => ({ result: 1 }))
|
|
741
|
+
|
|
742
|
+
const definition = createWorkflowDefinition([stepA, stepB, terminalStep], 'stepA')
|
|
743
|
+
const workflow = new Workflow(definition)
|
|
744
|
+
const context = createMockContext()
|
|
745
|
+
|
|
746
|
+
// Cycle will be detected during execution
|
|
747
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow(WorkflowStepError)
|
|
748
|
+
})
|
|
749
|
+
|
|
750
|
+
it('allows revisiting steps in different execution paths (no cycle)', async () => {
|
|
751
|
+
const step1 = createStep('step1', 'Step 1', async (input: { value: number }) => ({ value: input.value }), {
|
|
752
|
+
type: StepType.LINEAR,
|
|
753
|
+
target: 'step2'
|
|
754
|
+
})
|
|
755
|
+
const step2 = createStep('step2', 'Step 2', async () => ({ result: 100 }))
|
|
756
|
+
|
|
757
|
+
const definition = createWorkflowDefinition([step1, step2], 'step1')
|
|
758
|
+
const workflow = new Workflow(definition)
|
|
759
|
+
const context = createMockContext()
|
|
760
|
+
|
|
761
|
+
// Execute twice - should work both times
|
|
762
|
+
await workflow.execute({ value: 1 }, context)
|
|
763
|
+
await workflow.execute({ value: 2 }, context)
|
|
764
|
+
|
|
765
|
+
expect(true).toBe(true) // Both executions succeeded
|
|
766
|
+
})
|
|
767
|
+
})
|
|
768
|
+
|
|
769
|
+
describe('Execution Logging', () => {
|
|
770
|
+
it('logs workflow start', async () => {
|
|
771
|
+
const step1 = createStep('step1', 'Step 1', async () => ({ result: 1 }))
|
|
772
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
773
|
+
|
|
774
|
+
const workflow = new Workflow(definition)
|
|
775
|
+
const context = createMockContext()
|
|
776
|
+
|
|
777
|
+
await workflow.execute({ value: 1 }, context)
|
|
778
|
+
|
|
779
|
+
expect(context.logger.info).toHaveBeenCalledWith(
|
|
780
|
+
expect.stringContaining('Executing workflow'),
|
|
781
|
+
expect.any(Object)
|
|
782
|
+
)
|
|
783
|
+
})
|
|
784
|
+
|
|
785
|
+
it('logs workflow success with execution path', async () => {
|
|
786
|
+
const step1 = createStep('step1', 'Step 1', async () => ({ value: 1 }), {
|
|
787
|
+
type: StepType.LINEAR,
|
|
788
|
+
target: 'step2'
|
|
789
|
+
})
|
|
790
|
+
const step2 = createStep('step2', 'Step 2', async () => ({ result: 1 }))
|
|
791
|
+
const definition = createWorkflowDefinition([step1, step2], 'step1')
|
|
792
|
+
|
|
793
|
+
const workflow = new Workflow(definition)
|
|
794
|
+
const context = createMockContext()
|
|
795
|
+
|
|
796
|
+
await workflow.execute({ value: 1 }, context)
|
|
797
|
+
|
|
798
|
+
expect(context.logger.info).toHaveBeenCalledWith(
|
|
799
|
+
expect.stringContaining('Workflow completed successfully'),
|
|
800
|
+
expect.any(Object)
|
|
801
|
+
)
|
|
802
|
+
})
|
|
803
|
+
|
|
804
|
+
it('logs workflow failure', async () => {
|
|
805
|
+
const step1 = createStep('step1', 'Step 1', async () => {
|
|
806
|
+
throw new Error('Failed')
|
|
807
|
+
})
|
|
808
|
+
const definition = createWorkflowDefinition([step1], 'step1')
|
|
809
|
+
|
|
810
|
+
const workflow = new Workflow(definition)
|
|
811
|
+
const context = createMockContext()
|
|
812
|
+
|
|
813
|
+
await expect(workflow.execute({ value: 1 }, context)).rejects.toThrow()
|
|
814
|
+
|
|
815
|
+
expect(context.logger.error).toHaveBeenCalled()
|
|
816
|
+
})
|
|
817
|
+
})
|
|
818
|
+
})
|