@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,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock LLM Adapter
|
|
3
|
+
* Provides a simple mock implementation for testing purposes
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { LLMAdapter, LLMGenerateRequest, LLMGenerateResponse } from '../types'
|
|
7
|
+
import type { AgentAction } from '../../agent/actions/types'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Mock response for agent iteration scenarios
|
|
11
|
+
*/
|
|
12
|
+
export interface MockIterationResponse {
|
|
13
|
+
reasoning?: string
|
|
14
|
+
memoryOps?: { set?: Record<string, string>, delete?: string[] }
|
|
15
|
+
nextActions?: AgentAction[]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Configuration for MockAdapter
|
|
20
|
+
* Supports multi-iteration scenarios via response queue
|
|
21
|
+
*/
|
|
22
|
+
export interface MockAdapterConfig {
|
|
23
|
+
// Queue of responses for multi-iteration scenarios
|
|
24
|
+
responses?: MockIterationResponse[]
|
|
25
|
+
|
|
26
|
+
// Completion phase output
|
|
27
|
+
completionOutput?: unknown
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Check if the model and provider combination is for Mock
|
|
32
|
+
*
|
|
33
|
+
* @param model - Model identifier (e.g., 'mock')
|
|
34
|
+
* @param provider - Provider name
|
|
35
|
+
* @returns True if this is a mock model configuration
|
|
36
|
+
*/
|
|
37
|
+
export function isMockModel(model: string, provider: string): boolean {
|
|
38
|
+
return model === 'mock' || provider === 'mock'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Mock adapter that returns appropriate responses based on request schema
|
|
43
|
+
* Used for testing and development without making real API calls
|
|
44
|
+
*
|
|
45
|
+
* Supports:
|
|
46
|
+
* - Response queue for multi-iteration testing
|
|
47
|
+
* - Call count tracking
|
|
48
|
+
* - Realistic token usage simulation
|
|
49
|
+
* - Backward compatible default behavior
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* Minimal JSON Schema interface for checking schema structure
|
|
53
|
+
*/
|
|
54
|
+
interface JsonSchemaWithProperties {
|
|
55
|
+
properties?: Record<string, unknown>
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export class MockAdapter implements LLMAdapter {
|
|
59
|
+
private responseQueue: MockIterationResponse[] = []
|
|
60
|
+
private callCount = 0
|
|
61
|
+
|
|
62
|
+
constructor(private config: MockAdapterConfig = {}) {
|
|
63
|
+
this.responseQueue = [...(config.responses || [])]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async generate<T = unknown>(request: LLMGenerateRequest): Promise<LLMGenerateResponse<T>> {
|
|
67
|
+
// Check if this is an agent iteration request (has reasoning + nextActions)
|
|
68
|
+
const schema = request.responseSchema as JsonSchemaWithProperties | undefined
|
|
69
|
+
const isAgentIteration = schema?.properties?.reasoning && schema?.properties?.nextActions
|
|
70
|
+
|
|
71
|
+
this.callCount++
|
|
72
|
+
|
|
73
|
+
if (isAgentIteration) {
|
|
74
|
+
// Use next response from queue, or default to immediate completion
|
|
75
|
+
const response = this.responseQueue.shift() || {
|
|
76
|
+
reasoning: 'Mock reasoning',
|
|
77
|
+
nextActions: [{ type: 'complete' }]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Return agent iteration response
|
|
81
|
+
return {
|
|
82
|
+
output: {
|
|
83
|
+
reasoning: response.reasoning || 'Mock reasoning',
|
|
84
|
+
memoryOps: response.memoryOps || {},
|
|
85
|
+
nextActions: response.nextActions || [{ type: 'complete' }]
|
|
86
|
+
} as T,
|
|
87
|
+
usage: {
|
|
88
|
+
inputTokens: 100 * this.callCount,
|
|
89
|
+
outputTokens: 50 * this.callCount,
|
|
90
|
+
totalTokens: 150 * this.callCount
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Return generic completion response
|
|
96
|
+
return {
|
|
97
|
+
output: (this.config.completionOutput || {
|
|
98
|
+
response: 'Mock response',
|
|
99
|
+
processedAt: new Date().toISOString()
|
|
100
|
+
}) as T,
|
|
101
|
+
usage: {
|
|
102
|
+
inputTokens: 50,
|
|
103
|
+
outputTokens: 25,
|
|
104
|
+
totalTokens: 75
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get total number of generate() calls made
|
|
111
|
+
* Useful for verifying expected iteration counts in tests
|
|
112
|
+
*/
|
|
113
|
+
getCallCount(): number {
|
|
114
|
+
return this.callCount
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM Adapter Factory
|
|
3
|
+
* Creates LLM adapter instances based on model configuration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { LLMAdapter } from '../../types'
|
|
7
|
+
import type { ModelConfig, OpenRouterOptions, GoogleOptions, AnthropicOptions } from '../../model-info'
|
|
8
|
+
import { OpenAIAdapter, isOpenAIModel } from './openai'
|
|
9
|
+
import { OpenRouterAdapter, isOpenRouterModel } from './openrouter'
|
|
10
|
+
import { GoogleAdapter, isGoogleModel } from './google'
|
|
11
|
+
import { AnthropicAdapter, isAnthropicModel } from './anthropic'
|
|
12
|
+
import { MockAdapter, isMockModel } from '../mock-adapter'
|
|
13
|
+
import { UniversalLLMAdapter } from '../universal-adapter'
|
|
14
|
+
import type { AIUsageCollector } from '../../../../../operations/observability/ai-usage-collector'
|
|
15
|
+
import type { AICallContext, BaseAICall } from '../../../../../operations/observability/types'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Resolve API key at runtime
|
|
19
|
+
* Handles the case where env vars weren't loaded at module import time
|
|
20
|
+
* (e.g., in Docker when dotenv runs after module imports)
|
|
21
|
+
*
|
|
22
|
+
* @param configApiKey - API key from config (may be placeholder)
|
|
23
|
+
* @param provider - Provider name to determine which env var to check
|
|
24
|
+
* @returns Resolved API key
|
|
25
|
+
*/
|
|
26
|
+
function resolveApiKey(configApiKey: string, provider: string): string {
|
|
27
|
+
// If the config has a real API key (not a placeholder), use it
|
|
28
|
+
const isPlaceholder =
|
|
29
|
+
!configApiKey ||
|
|
30
|
+
configApiKey.startsWith('placeholder-') ||
|
|
31
|
+
configApiKey.includes('placeholder') ||
|
|
32
|
+
configApiKey.includes('test-api-key')
|
|
33
|
+
if (!isPlaceholder) {
|
|
34
|
+
return configApiKey
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Resolve from environment at runtime based on provider
|
|
38
|
+
const envVarMap: Record<string, string | undefined> = {
|
|
39
|
+
anthropic: process.env.ANTHROPIC_API_KEY,
|
|
40
|
+
openai: process.env.OPENAI_API_KEY,
|
|
41
|
+
openrouter: process.env.OPENROUTER_API_KEY,
|
|
42
|
+
google: process.env.GOOGLE_AI_STUDIO_KEY
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const envKey = envVarMap[provider]
|
|
46
|
+
if (envKey) {
|
|
47
|
+
return envKey
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Fallback to config value (will fail at API call time with auth error)
|
|
51
|
+
return configApiKey
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Create base adapter based on model configuration
|
|
56
|
+
* Routes to the appropriate provider-specific adapter
|
|
57
|
+
*
|
|
58
|
+
* @param config - Model configuration from resource definition
|
|
59
|
+
* @returns Base LLM adapter instance (without observability wrapper)
|
|
60
|
+
*/
|
|
61
|
+
function createBaseAdapter(config: ModelConfig): LLMAdapter {
|
|
62
|
+
const { model, provider, modelOptions } = config
|
|
63
|
+
const apiKey = resolveApiKey(config.apiKey, provider)
|
|
64
|
+
|
|
65
|
+
// OpenAI models
|
|
66
|
+
if (isOpenAIModel(model, provider)) {
|
|
67
|
+
return new OpenAIAdapter({
|
|
68
|
+
apiKey,
|
|
69
|
+
model,
|
|
70
|
+
modelOptions // Flat structure - no vendor namespace needed
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// OpenRouter models (access to 400+ models via single API)
|
|
75
|
+
if (isOpenRouterModel(model)) {
|
|
76
|
+
return new OpenRouterAdapter({
|
|
77
|
+
apiKey,
|
|
78
|
+
model,
|
|
79
|
+
modelOptions: modelOptions as OpenRouterOptions
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Google models (direct SDK access via @google/genai)
|
|
84
|
+
if (isGoogleModel(model, provider)) {
|
|
85
|
+
return new GoogleAdapter({
|
|
86
|
+
apiKey,
|
|
87
|
+
model,
|
|
88
|
+
modelOptions: modelOptions as GoogleOptions
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Anthropic models (direct SDK access via @anthropic-ai/sdk)
|
|
93
|
+
if (isAnthropicModel(model, provider)) {
|
|
94
|
+
return new AnthropicAdapter({
|
|
95
|
+
apiKey,
|
|
96
|
+
model,
|
|
97
|
+
modelOptions: modelOptions as AnthropicOptions
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Mock provider (for testing)
|
|
102
|
+
if (isMockModel(model, provider)) {
|
|
103
|
+
return new MockAdapter()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
throw new Error(`Unsupported model: ${model} with provider: ${provider}`)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Create LLM adapter based on model configuration
|
|
111
|
+
* Creates a stateless adapter instance for the execution
|
|
112
|
+
* Automatically wraps with UniversalLLMAdapter for reliability and observability
|
|
113
|
+
*
|
|
114
|
+
* @param config - Model configuration from resource definition (includes model identifier)
|
|
115
|
+
* @param aiUsageCollector - Optional collector for tracking AI usage
|
|
116
|
+
* @param callType - Optional call type discriminator for observability
|
|
117
|
+
* @param context - Optional typed context for observability
|
|
118
|
+
* @returns Stateless LLM adapter instance (wrapped with UniversalLLMAdapter)
|
|
119
|
+
*/
|
|
120
|
+
export function createLLMAdapter(
|
|
121
|
+
config: ModelConfig,
|
|
122
|
+
aiUsageCollector?: AIUsageCollector,
|
|
123
|
+
callType?: BaseAICall['callType'],
|
|
124
|
+
context?: AICallContext
|
|
125
|
+
): LLMAdapter {
|
|
126
|
+
const baseAdapter = createBaseAdapter(config)
|
|
127
|
+
|
|
128
|
+
// Wrap with UniversalLLMAdapter for automatic retry, circuit breaker, and observability
|
|
129
|
+
return new UniversalLLMAdapter(baseAdapter, config.model, aiUsageCollector, callType, context)
|
|
130
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic Adapter
|
|
3
|
+
* Stateless translation layer between Universal Protocol and Anthropic API
|
|
4
|
+
*
|
|
5
|
+
* Responsibilities:
|
|
6
|
+
* 1. Translate LLMGenerateRequest to Anthropic message format
|
|
7
|
+
* 2. Call Anthropic SDK with tool_use for structured output
|
|
8
|
+
* 3. Parse Anthropic response (extract from tool_use block)
|
|
9
|
+
* 4. Translate back to LLMGenerateResponse
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { LLMAdapter, LLMGenerateRequest, LLMGenerateResponse } from '../../types'
|
|
13
|
+
import type { LLMModel, ModelSpecificOptions } from '../../model-info'
|
|
14
|
+
import { bslogExternalServiceError, isSystemError } from '../../../../../platform/utils/server/betterstack-logger'
|
|
15
|
+
import { composeSignal } from './compose-signal'
|
|
16
|
+
import { DEFAULT_LLM_TIMEOUT } from '../../../../../platform/constants/timeouts'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Anthropic adapter configuration
|
|
20
|
+
*/
|
|
21
|
+
export interface AnthropicAdapterConfig {
|
|
22
|
+
apiKey: string
|
|
23
|
+
model: LLMModel
|
|
24
|
+
modelOptions?: ModelSpecificOptions
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Check if the model and provider combination is for Anthropic
|
|
29
|
+
*
|
|
30
|
+
* @param model - Model identifier (e.g., 'claude-opus-4-5-20251101')
|
|
31
|
+
* @param provider - Provider name
|
|
32
|
+
* @returns True if this is an Anthropic model configuration
|
|
33
|
+
*/
|
|
34
|
+
export function isAnthropicModel(model: LLMModel, provider: string): boolean {
|
|
35
|
+
return model.startsWith('claude-') && provider === 'anthropic'
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Anthropic Claude Adapter - Implements universal protocol
|
|
40
|
+
* Uses tool_use for structured output (Anthropic's recommended approach)
|
|
41
|
+
*
|
|
42
|
+
* Key differences from other adapters:
|
|
43
|
+
* - System messages go in separate `system` field (not in messages array)
|
|
44
|
+
* - Structured output via tool_use (not native JSON mode)
|
|
45
|
+
* - Response content is array of blocks (not string)
|
|
46
|
+
* - max_tokens is required (not optional)
|
|
47
|
+
* - Total tokens must be calculated (not provided)
|
|
48
|
+
*/
|
|
49
|
+
export class AnthropicAdapter implements LLMAdapter {
|
|
50
|
+
private clientPromise: Promise<import('@anthropic-ai/sdk').default>
|
|
51
|
+
private model: LLMModel
|
|
52
|
+
|
|
53
|
+
constructor(config: AnthropicAdapterConfig) {
|
|
54
|
+
// Lazy load Anthropic SDK
|
|
55
|
+
this.clientPromise = import('@anthropic-ai/sdk').then(
|
|
56
|
+
({ default: AnthropicClass }) => new AnthropicClass({ apiKey: config.apiKey })
|
|
57
|
+
)
|
|
58
|
+
this.model = config.model
|
|
59
|
+
// modelOptions reserved for future use (e.g., extended thinking)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Generate structured output from messages using Anthropic Claude
|
|
64
|
+
*
|
|
65
|
+
* @param request - Generic generation request
|
|
66
|
+
* @returns Structured output with usage metadata
|
|
67
|
+
*/
|
|
68
|
+
async generate<T>(request: LLMGenerateRequest): Promise<LLMGenerateResponse<T>> {
|
|
69
|
+
const client = await this.clientPromise
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
// Extract system messages (Anthropic uses separate system field)
|
|
73
|
+
const systemMessages = request.messages.filter((msg) => msg.role === 'system')
|
|
74
|
+
const nonSystemMessages = request.messages.filter((msg) => msg.role !== 'system')
|
|
75
|
+
|
|
76
|
+
// Build system content (combine multiple system messages)
|
|
77
|
+
const systemContent =
|
|
78
|
+
systemMessages.length > 0 ? systemMessages.map((msg) => msg.content).join('\n\n') : undefined
|
|
79
|
+
|
|
80
|
+
// Convert messages to Anthropic format
|
|
81
|
+
const anthropicMessages = nonSystemMessages.map((msg) => ({
|
|
82
|
+
role: msg.role as 'user' | 'assistant',
|
|
83
|
+
content: msg.content
|
|
84
|
+
}))
|
|
85
|
+
|
|
86
|
+
// Use tool_use for structured output (Anthropic's recommended approach)
|
|
87
|
+
// This guarantees schema compliance without requiring JSON mode
|
|
88
|
+
// Stream + finalMessage() to avoid SDK non-streaming timeout rejection
|
|
89
|
+
// at high max_tokens values (SDK calculates estimated time > 10 min → error)
|
|
90
|
+
const stream = client.messages.stream(
|
|
91
|
+
{
|
|
92
|
+
model: this.model,
|
|
93
|
+
max_tokens: request.maxOutputTokens || 4000, // Required for Anthropic
|
|
94
|
+
system: systemContent,
|
|
95
|
+
messages: anthropicMessages,
|
|
96
|
+
tools: [
|
|
97
|
+
{
|
|
98
|
+
name: 'structured_output',
|
|
99
|
+
description: 'Return structured output matching the required schema',
|
|
100
|
+
input_schema: request.responseSchema as import('@anthropic-ai/sdk').Anthropic.Tool['input_schema']
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
tool_choice: { type: 'tool', name: 'structured_output' },
|
|
104
|
+
temperature: request.temperature,
|
|
105
|
+
top_p: request.topP
|
|
106
|
+
},
|
|
107
|
+
{ signal: composeSignal(DEFAULT_LLM_TIMEOUT, request.signal) }
|
|
108
|
+
)
|
|
109
|
+
const response = await stream.finalMessage()
|
|
110
|
+
|
|
111
|
+
// Extract structured output from tool_use block
|
|
112
|
+
const toolUseBlock = response.content.find((block) => block.type === 'tool_use')
|
|
113
|
+
if (!toolUseBlock || toolUseBlock.type !== 'tool_use') {
|
|
114
|
+
throw new Error('Anthropic response missing tool_use block for structured output')
|
|
115
|
+
}
|
|
116
|
+
const output = toolUseBlock.input as T
|
|
117
|
+
|
|
118
|
+
// Calculate total tokens (Anthropic doesn't provide total_tokens)
|
|
119
|
+
const usage = {
|
|
120
|
+
inputTokens: response.usage.input_tokens,
|
|
121
|
+
outputTokens: response.usage.output_tokens,
|
|
122
|
+
totalTokens: response.usage.input_tokens + response.usage.output_tokens
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return { output, usage }
|
|
126
|
+
} catch (error) {
|
|
127
|
+
// Add Better Stack logging for system errors (5xx only)
|
|
128
|
+
if (isSystemError(error)) {
|
|
129
|
+
bslogExternalServiceError('anthropic', 'messages.create', error as Error, {
|
|
130
|
+
model: this.model
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
throw error
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signal composition helper for LLM adapter timeouts
|
|
3
|
+
* Composes an execution-level abort signal with a per-call timeout
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Compose an abort signal from a per-call timeout and an optional execution-level signal.
|
|
8
|
+
* Returns a single signal that fires when either source aborts.
|
|
9
|
+
*
|
|
10
|
+
* @param timeoutMs - Per-call timeout in milliseconds
|
|
11
|
+
* @param executionSignal - Optional execution-level abort signal (from coordinator)
|
|
12
|
+
* @returns Composed AbortSignal via AbortSignal.any()
|
|
13
|
+
*/
|
|
14
|
+
export function composeSignal(timeoutMs: number, executionSignal?: AbortSignal): AbortSignal {
|
|
15
|
+
const signals: AbortSignal[] = [AbortSignal.timeout(timeoutMs)]
|
|
16
|
+
if (executionSignal) signals.push(executionSignal)
|
|
17
|
+
return AbortSignal.any(signals)
|
|
18
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Gemini Adapter
|
|
3
|
+
* Stateless translation layer between universal protocol and Google GenAI SDK
|
|
4
|
+
*
|
|
5
|
+
* Responsibilities:
|
|
6
|
+
* 1. Translate LLMGenerateRequest to Google GenAI format
|
|
7
|
+
* 2. Transform JSON Schema to Gemini-compatible format (const -> enum, inline $ref)
|
|
8
|
+
* 3. Call Google GenAI SDK with structured output
|
|
9
|
+
* 4. Parse Google response
|
|
10
|
+
* 5. Translate back to LLMGenerateResponse
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { LLMAdapter, LLMGenerateRequest, LLMGenerateResponse } from '../../types'
|
|
14
|
+
import type { LLMModel, GoogleModel, ModelSpecificOptions } from '../../model-info'
|
|
15
|
+
import { LLMResponseParseError } from '../../errors'
|
|
16
|
+
import { bslogExternalServiceError, isSystemError } from '../../../../../platform/utils/server/betterstack-logger'
|
|
17
|
+
import { composeSignal } from './compose-signal'
|
|
18
|
+
import { DEFAULT_LLM_TIMEOUT } from '../../../../../platform/constants/timeouts'
|
|
19
|
+
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Schema Transformation for Gemini Compatibility
|
|
22
|
+
// ============================================================================
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Transform JSON Schema for Gemini API compatibility
|
|
26
|
+
*
|
|
27
|
+
* Gemini uses a subset of JSON Schema. This function handles:
|
|
28
|
+
* 1. const: "value" -> enum: ["value"] + type: "string" (const keyword not supported)
|
|
29
|
+
* 2. Inline $ref references from $defs (for schema reuse)
|
|
30
|
+
* 3. Remove $schema property (Gemini rejects it)
|
|
31
|
+
* 4. Add placeholder property to empty object types (Gemini requires non-empty properties)
|
|
32
|
+
* 5. Ensure objects with additionalProperties also have a properties field
|
|
33
|
+
*
|
|
34
|
+
* @param schema - JSON Schema object to transform
|
|
35
|
+
* @param definitions - Map of $defs for $ref resolution (built during traversal)
|
|
36
|
+
* @returns Gemini-compatible schema
|
|
37
|
+
*/
|
|
38
|
+
function transformSchemaForGemini(schema: unknown, definitions?: Record<string, unknown>): unknown {
|
|
39
|
+
// Base case: null, undefined, or primitive values pass through unchanged
|
|
40
|
+
if (!schema || typeof schema !== 'object') {
|
|
41
|
+
return schema
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const obj = schema as Record<string, unknown>
|
|
45
|
+
const result: Record<string, unknown> = {}
|
|
46
|
+
|
|
47
|
+
// Extract $defs at the current level for reference resolution
|
|
48
|
+
// These definitions are accumulated as we traverse down
|
|
49
|
+
if (obj.$defs && typeof obj.$defs === 'object') {
|
|
50
|
+
definitions = { ...definitions, ...(obj.$defs as Record<string, unknown>) }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
54
|
+
// Skip $schema - Gemini doesn't accept JSON Schema meta-schema
|
|
55
|
+
if (key === '$schema') {
|
|
56
|
+
continue
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Skip $defs - definitions are inlined when $ref is encountered
|
|
60
|
+
if (key === '$defs') {
|
|
61
|
+
continue
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Handle $ref - inline the referenced definition
|
|
65
|
+
// Format: "#/$defs/DefinitionName"
|
|
66
|
+
if (key === '$ref' && typeof value === 'string') {
|
|
67
|
+
const refPath = value.replace('#/$defs/', '')
|
|
68
|
+
if (definitions?.[refPath]) {
|
|
69
|
+
// Return the inlined definition (transformed recursively)
|
|
70
|
+
return transformSchemaForGemini(definitions[refPath], definitions)
|
|
71
|
+
}
|
|
72
|
+
// Skip unresolvable refs - they would cause errors anyway
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Transform const to enum - Gemini doesn't support JSON Schema const keyword
|
|
77
|
+
// const: "value" becomes type: "string", enum: ["value"]
|
|
78
|
+
// This handles z.literal() from Zod which generates const
|
|
79
|
+
// Note: Gemini requires type: "string" when enum is present
|
|
80
|
+
if (key === 'const') {
|
|
81
|
+
result.type = 'string'
|
|
82
|
+
result.enum = [value]
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Recursively transform nested structures
|
|
87
|
+
if (Array.isArray(value)) {
|
|
88
|
+
// Transform each array element (e.g., anyOf, oneOf, allOf, items as tuple)
|
|
89
|
+
result[key] = value.map((item) => transformSchemaForGemini(item, definitions))
|
|
90
|
+
} else if (value && typeof value === 'object') {
|
|
91
|
+
// Transform nested objects (properties, items, additionalProperties, etc.)
|
|
92
|
+
result[key] = transformSchemaForGemini(value, definitions)
|
|
93
|
+
} else {
|
|
94
|
+
// Primitive values pass through unchanged
|
|
95
|
+
result[key] = value
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// SAFEGUARD: Gemini requires objects to have non-empty properties
|
|
100
|
+
// This handles several cases:
|
|
101
|
+
// 1. Object with empty properties: { type: "object", properties: {} }
|
|
102
|
+
// 2. Object with additionalProperties but no properties: { type: "object", additionalProperties: true }
|
|
103
|
+
// 3. Object with no properties field at all: { type: "object" }
|
|
104
|
+
//
|
|
105
|
+
// Google's API strictly requires properties to be non-empty for OBJECT type,
|
|
106
|
+
// even when additionalProperties is present.
|
|
107
|
+
if (result.type === 'object') {
|
|
108
|
+
const props = result.properties as Record<string, unknown> | undefined
|
|
109
|
+
|
|
110
|
+
if (!props || Object.keys(props).length === 0) {
|
|
111
|
+
// Use a property name that:
|
|
112
|
+
// 1. Google accepts (no underscore prefix)
|
|
113
|
+
// 2. Is clearly a placeholder (won't conflict with real data)
|
|
114
|
+
// 3. Is optional so it won't pollute required outputs
|
|
115
|
+
result.properties = {
|
|
116
|
+
placeholderField: {
|
|
117
|
+
type: 'string',
|
|
118
|
+
description: 'System placeholder for empty object schema. Ignore this field.'
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return result
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Google adapter configuration
|
|
129
|
+
*/
|
|
130
|
+
export interface GoogleAdapterConfig {
|
|
131
|
+
apiKey: string
|
|
132
|
+
model: GoogleModel
|
|
133
|
+
modelOptions?: ModelSpecificOptions
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Check if the model and provider combination is for Google
|
|
138
|
+
*
|
|
139
|
+
* @param model - Model identifier (e.g., 'gemini-3-flash-preview')
|
|
140
|
+
* @param provider - Provider name
|
|
141
|
+
* @returns True if this is a Google model configuration
|
|
142
|
+
*/
|
|
143
|
+
export function isGoogleModel(model: LLMModel, provider: string): model is GoogleModel {
|
|
144
|
+
return model.startsWith('gemini-') && provider === 'google'
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Google Gemini Adapter - Implements universal protocol
|
|
149
|
+
* Uses structured output via JSON schema for guaranteed schema compliance
|
|
150
|
+
*/
|
|
151
|
+
export class GoogleAdapter implements LLMAdapter {
|
|
152
|
+
private clientPromise: Promise<import('@google/genai').GoogleGenAI>
|
|
153
|
+
private model: GoogleModel
|
|
154
|
+
private modelOptions?: ModelSpecificOptions
|
|
155
|
+
|
|
156
|
+
constructor(config: GoogleAdapterConfig) {
|
|
157
|
+
// Lazy load Google GenAI SDK
|
|
158
|
+
this.clientPromise = import('@google/genai').then(
|
|
159
|
+
({ GoogleGenAI }) =>
|
|
160
|
+
new GoogleGenAI({
|
|
161
|
+
apiKey: config.apiKey
|
|
162
|
+
})
|
|
163
|
+
)
|
|
164
|
+
this.model = config.model
|
|
165
|
+
this.modelOptions = config.modelOptions
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Generate structured output from messages using Google Gemini
|
|
170
|
+
*
|
|
171
|
+
* @param request - Generic generation request
|
|
172
|
+
* @returns Structured output with usage metadata
|
|
173
|
+
*/
|
|
174
|
+
async generate<T>(request: LLMGenerateRequest): Promise<LLMGenerateResponse<T>> {
|
|
175
|
+
const ai = await this.clientPromise
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
// Build config object for structured output
|
|
179
|
+
// Transform schema for Gemini compatibility (const -> enum, inline $ref)
|
|
180
|
+
const generateConfig: Record<string, unknown> = {
|
|
181
|
+
responseMimeType: 'application/json',
|
|
182
|
+
responseSchema: transformSchemaForGemini(request.responseSchema)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Add thinking level if specified (Gemini 3 specific feature)
|
|
186
|
+
if (this.modelOptions && 'thinkingLevel' in this.modelOptions) {
|
|
187
|
+
generateConfig.thinkingConfig = {
|
|
188
|
+
thinkingLevel: this.modelOptions.thinkingLevel
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Add max tokens if specified
|
|
193
|
+
if (request.maxOutputTokens) {
|
|
194
|
+
generateConfig.maxOutputTokens = request.maxOutputTokens
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Convert messages to Gemini format
|
|
198
|
+
// Gemini uses 'model' role instead of 'assistant' for AI messages
|
|
199
|
+
// System messages need special handling - prepend to first user message or use systemInstruction
|
|
200
|
+
const systemMessages = request.messages.filter((msg) => msg.role === 'system')
|
|
201
|
+
const nonSystemMessages = request.messages.filter((msg) => msg.role !== 'system')
|
|
202
|
+
|
|
203
|
+
// Use systemInstruction for system messages if present
|
|
204
|
+
if (systemMessages.length > 0) {
|
|
205
|
+
generateConfig.systemInstruction = systemMessages.map((msg) => msg.content).join('\n\n')
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Convert remaining messages to Gemini content format
|
|
209
|
+
const contents = nonSystemMessages.map((msg) => ({
|
|
210
|
+
role: msg.role === 'assistant' ? 'model' : 'user',
|
|
211
|
+
parts: [{ text: msg.content }]
|
|
212
|
+
}))
|
|
213
|
+
|
|
214
|
+
const response = await ai.models.generateContent({
|
|
215
|
+
model: this.model,
|
|
216
|
+
contents,
|
|
217
|
+
config: { ...generateConfig, abortSignal: composeSignal(DEFAULT_LLM_TIMEOUT, request.signal) }
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
// Detect empty/blocked responses before parsing
|
|
221
|
+
// Gemini returns no text when: safety filters block output, prompt is blocked,
|
|
222
|
+
// model produces empty candidates, or finish reason is non-STOP
|
|
223
|
+
if (!response.text) {
|
|
224
|
+
const candidate = response.candidates?.[0]
|
|
225
|
+
const finishReason = candidate?.finishReason
|
|
226
|
+
const blockReason = response.promptFeedback?.blockReason
|
|
227
|
+
|
|
228
|
+
const reasons: string[] = []
|
|
229
|
+
if (blockReason) reasons.push(`prompt blocked: ${blockReason}`)
|
|
230
|
+
if (finishReason && finishReason !== 'STOP') reasons.push(`finish reason: ${finishReason}`)
|
|
231
|
+
if (!response.candidates?.length) reasons.push('no candidates returned')
|
|
232
|
+
|
|
233
|
+
const detail = reasons.length > 0 ? reasons.join(', ') : 'empty response.text with no diagnostic metadata'
|
|
234
|
+
|
|
235
|
+
throw new LLMResponseParseError(`Google Gemini returned no output (${detail})`, {
|
|
236
|
+
finishReason,
|
|
237
|
+
blockReason,
|
|
238
|
+
hasCandidates: (response.candidates?.length ?? 0) > 0
|
|
239
|
+
})
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Parse structured output from response with error wrapping for retry support
|
|
243
|
+
let output: unknown
|
|
244
|
+
try {
|
|
245
|
+
output = JSON.parse(response.text)
|
|
246
|
+
} catch (error) {
|
|
247
|
+
if (error instanceof SyntaxError) {
|
|
248
|
+
throw new LLMResponseParseError(`Failed to parse LLM response as JSON: ${error.message}`, {
|
|
249
|
+
rawContent: response.text.substring(0, 500),
|
|
250
|
+
parseError: error.message
|
|
251
|
+
})
|
|
252
|
+
}
|
|
253
|
+
throw error
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Extract usage metadata for observability tracking
|
|
257
|
+
const usage = response.usageMetadata
|
|
258
|
+
? {
|
|
259
|
+
inputTokens: response.usageMetadata.promptTokenCount || 0,
|
|
260
|
+
outputTokens: response.usageMetadata.candidatesTokenCount || 0,
|
|
261
|
+
totalTokens: response.usageMetadata.totalTokenCount || 0
|
|
262
|
+
}
|
|
263
|
+
: undefined
|
|
264
|
+
|
|
265
|
+
// Return response with usage (wrapper will extract and strip it)
|
|
266
|
+
return {
|
|
267
|
+
output: output as T,
|
|
268
|
+
usage
|
|
269
|
+
}
|
|
270
|
+
} catch (error) {
|
|
271
|
+
// Add Better Stack logging for system errors (5xx only)
|
|
272
|
+
if (isSystemError(error)) {
|
|
273
|
+
bslogExternalServiceError('google-genai', 'models.generateContent', error as Error, {
|
|
274
|
+
model: this.model,
|
|
275
|
+
thinkingLevel:
|
|
276
|
+
this.modelOptions && 'thinkingLevel' in this.modelOptions ? this.modelOptions.thinkingLevel : undefined
|
|
277
|
+
})
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
throw error
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|