manifest 5.45.0 → 6.0.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/CONTRACT.md +50 -0
- package/README.md +69 -100
- package/dist/index.cjs +472 -0
- package/dist/index.d.cts +24 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +443 -12
- package/docs/guide.md +77 -0
- package/package.json +36 -79
- package/dist/backend/analytics/analytics.module.js +0 -60
- package/dist/backend/analytics/controllers/agent-analytics.controller.js +0 -69
- package/dist/backend/analytics/controllers/agents.controller.js +0 -176
- package/dist/backend/analytics/controllers/costs.controller.js +0 -71
- package/dist/backend/analytics/controllers/messages.controller.js +0 -67
- package/dist/backend/analytics/controllers/overview.controller.js +0 -104
- package/dist/backend/analytics/controllers/tokens.controller.js +0 -74
- package/dist/backend/analytics/dto/messages-query.dto.js +0 -73
- package/dist/backend/analytics/services/agent-analytics.service.js +0 -125
- package/dist/backend/analytics/services/agent-lifecycle.service.js +0 -102
- package/dist/backend/analytics/services/aggregation.service.js +0 -205
- package/dist/backend/analytics/services/message-details.service.js +0 -146
- package/dist/backend/analytics/services/messages-query.service.js +0 -196
- package/dist/backend/analytics/services/query-helpers.js +0 -45
- package/dist/backend/analytics/services/timeseries-queries.service.js +0 -237
- package/dist/backend/app.module.js +0 -94
- package/dist/backend/auth/auth.instance.js +0 -121
- package/dist/backend/auth/auth.module.js +0 -17
- package/dist/backend/auth/current-user.decorator.js +0 -9
- package/dist/backend/auth/local-auth.guard.js +0 -51
- package/dist/backend/auth/session.guard.js +0 -57
- package/dist/backend/common/common.module.js +0 -41
- package/dist/backend/common/constants/api-key.constants.js +0 -6
- package/dist/backend/common/constants/cache.constants.js +0 -8
- package/dist/backend/common/constants/local-mode.constants.js +0 -102
- package/dist/backend/common/constants/ollama.js +0 -5
- package/dist/backend/common/constants/providers.js +0 -134
- package/dist/backend/common/decorators/public.decorator.js +0 -8
- package/dist/backend/common/dto/create-agent.dto.js +0 -26
- package/dist/backend/common/dto/range-query.dto.js +0 -29
- package/dist/backend/common/dto/rename-agent.dto.js +0 -26
- package/dist/backend/common/filters/spa-fallback.filter.js +0 -46
- package/dist/backend/common/guards/api-key.guard.js +0 -89
- package/dist/backend/common/interceptors/agent-cache.interceptor.js +0 -39
- package/dist/backend/common/interceptors/user-cache.interceptor.js +0 -39
- package/dist/backend/common/services/ingest-event-bus.service.js +0 -44
- package/dist/backend/common/services/manifest-runtime.service.js +0 -39
- package/dist/backend/common/services/tenant-cache.service.js +0 -56
- package/dist/backend/common/utils/anthropic-model-id.js +0 -36
- package/dist/backend/common/utils/cost-calculator.js +0 -19
- package/dist/backend/common/utils/crypto.util.js +0 -72
- package/dist/backend/common/utils/frontend-path.js +0 -21
- package/dist/backend/common/utils/hash.util.js +0 -32
- package/dist/backend/common/utils/local-ip.js +0 -33
- package/dist/backend/common/utils/period.util.js +0 -55
- package/dist/backend/common/utils/provider-aliases.js +0 -13
- package/dist/backend/common/utils/provider-inference.js +0 -7
- package/dist/backend/common/utils/range.util.js +0 -29
- package/dist/backend/common/utils/slugify.js +0 -13
- package/dist/backend/common/utils/sql-dialect.js +0 -71
- package/dist/backend/common/utils/subscription-support.js +0 -12
- package/dist/backend/common/utils/ttl-cache.js +0 -59
- package/dist/backend/common/utils/url-validation.js +0 -107
- package/dist/backend/config/app.config.js +0 -48
- package/dist/backend/database/database-seeder.service.js +0 -180
- package/dist/backend/database/database.module.js +0 -199
- package/dist/backend/database/datasource.js +0 -28
- package/dist/backend/database/local-bootstrap.service.js +0 -161
- package/dist/backend/database/migrations/1771464895790-InitialSchema.js +0 -91
- package/dist/backend/database/migrations/1771500000000-HashApiKeys.js +0 -67
- package/dist/backend/database/migrations/1771600000000-AddModelCapabilities.js +0 -27
- package/dist/backend/database/migrations/1771600000000-ModelPricingImprovements.js +0 -60
- package/dist/backend/database/migrations/1771700000000-AddRoutingTables.js +0 -50
- package/dist/backend/database/migrations/1771700000000-EmailProviderConfigs.js +0 -31
- package/dist/backend/database/migrations/1771800000000-AddNotificationEmailAndOptionalDomain.js +0 -16
- package/dist/backend/database/migrations/1771800000000-AddQualityScore.js +0 -50
- package/dist/backend/database/migrations/1771800100000-SeedQualityScores.js +0 -45
- package/dist/backend/database/migrations/1771900000000-EncryptApiKeys.js +0 -34
- package/dist/backend/database/migrations/1772000000000-MakeApiKeyNullable.js +0 -16
- package/dist/backend/database/migrations/1772100000000-AddRoutingTier.js +0 -17
- package/dist/backend/database/migrations/1772200000000-AddLimitAction.js +0 -17
- package/dist/backend/database/migrations/1772300000000-AddRoutingReason.js +0 -17
- package/dist/backend/database/migrations/1772400000000-AddAgentDisplayName.js +0 -13
- package/dist/backend/database/migrations/1772500000000-PerAgentRouting.js +0 -82
- package/dist/backend/database/migrations/1772668898071-AddCustomProviders.js +0 -31
- package/dist/backend/database/migrations/1772682112419-NullablePricing.js +0 -17
- package/dist/backend/database/migrations/1772843035514-AddPerformanceIndexes.js +0 -56
- package/dist/backend/database/migrations/1772900000000-AddProviderAuthType.js +0 -13
- package/dist/backend/database/migrations/1772905146384-AddDashboardIndexes.js +0 -24
- package/dist/backend/database/migrations/1772905260464-AddFallbacks.js +0 -18
- package/dist/backend/database/migrations/1772920000000-AddModelDisplayName.js +0 -14
- package/dist/backend/database/migrations/1772940000000-DropRedundantIndexes.js +0 -39
- package/dist/backend/database/migrations/1772948502780-BackfillTenantId.js +0 -20
- package/dist/backend/database/migrations/1772960000000-DropUnusedIndexes.js +0 -19
- package/dist/backend/database/migrations/1772960000000-PurgeNonCuratedModels.js +0 -86
- package/dist/backend/database/migrations/1773000000000-ExpandProviderUniqueKey.js +0 -19
- package/dist/backend/database/migrations/1773100000000-AddOverrideAuthType.js +0 -18
- package/dist/backend/database/migrations/1773200000000-AddMessageAuthType.js +0 -18
- package/dist/backend/database/migrations/1773202787708-AddModelsAgentIndex.js +0 -16
- package/dist/backend/database/migrations/1773300000000-AddEmailProviderKeyPrefix.js +0 -13
- package/dist/backend/database/migrations/1773400000000-AddProviderModelCache.js +0 -15
- package/dist/backend/database/migrations/1773500000000-DropModelPricingTables.js +0 -51
- package/dist/backend/database/migrations/1773600000000-AddOverrideProvider.js +0 -18
- package/dist/backend/database/migrations/1773650000000-AddProviderRegion.js +0 -13
- package/dist/backend/database/migrations/1773700000000-DropSecurityEventTable.js +0 -24
- package/dist/backend/database/migrations/1773800000000-FixNegativeCosts.js +0 -12
- package/dist/backend/database/migrations/1773900000000-AddKeyPrefixIndex.js +0 -15
- package/dist/backend/database/migrations/1774000000000-WidenKeyHashColumn.js +0 -15
- package/dist/backend/database/migrations/1774896789000-WidenApiKeyColumn.js +0 -14
- package/dist/backend/database/models-dev-sync.service.js +0 -238
- package/dist/backend/database/ollama-sync.service.js +0 -70
- package/dist/backend/database/pricing-sync.service.js +0 -116
- package/dist/backend/database/quality-score.util.js +0 -76
- package/dist/backend/database/seed-messages.js +0 -66
- package/dist/backend/entities/agent-api-key.entity.js +0 -91
- package/dist/backend/entities/agent-log.entity.js +0 -71
- package/dist/backend/entities/agent-message.entity.js +0 -158
- package/dist/backend/entities/agent.entity.js +0 -75
- package/dist/backend/entities/api-key.entity.js +0 -62
- package/dist/backend/entities/cost-snapshot.entity.js +0 -56
- package/dist/backend/entities/custom-provider.entity.js +0 -64
- package/dist/backend/entities/email-provider-config.entity.js +0 -72
- package/dist/backend/entities/llm-call.entity.js +0 -106
- package/dist/backend/entities/notification-log.entity.js +0 -67
- package/dist/backend/entities/notification-rule.entity.js +0 -84
- package/dist/backend/entities/tenant.entity.js +0 -62
- package/dist/backend/entities/tier-assignment.entity.js +0 -72
- package/dist/backend/entities/token-usage-snapshot.entity.js +0 -71
- package/dist/backend/entities/tool-execution.entity.js +0 -60
- package/dist/backend/entities/user-provider.entity.js +0 -87
- package/dist/backend/github/github.controller.js +0 -53
- package/dist/backend/github/github.module.js +0 -20
- package/dist/backend/health/health.controller.js +0 -51
- package/dist/backend/health/health.module.js +0 -22
- package/dist/backend/health/version-check.service.js +0 -95
- package/dist/backend/main.js +0 -153
- package/dist/backend/model-discovery/anthropic-subscription-probe.js +0 -87
- package/dist/backend/model-discovery/known-model-prices.js +0 -18
- package/dist/backend/model-discovery/model-discovery.module.js +0 -28
- package/dist/backend/model-discovery/model-discovery.service.js +0 -309
- package/dist/backend/model-discovery/model-fallback.js +0 -234
- package/dist/backend/model-discovery/model-fetcher.js +0 -3
- package/dist/backend/model-discovery/provider-model-fetcher.service.js +0 -376
- package/dist/backend/model-discovery/provider-model-registry.service.js +0 -84
- package/dist/backend/model-prices/model-name-normalizer.js +0 -129
- package/dist/backend/model-prices/model-prices.controller.js +0 -39
- package/dist/backend/model-prices/model-prices.module.js +0 -41
- package/dist/backend/model-prices/model-prices.service.js +0 -45
- package/dist/backend/model-prices/model-pricing-cache.service.js +0 -171
- package/dist/backend/notifications/dto/notification-rule.dto.js +0 -82
- package/dist/backend/notifications/dto/set-email-provider.dto.js +0 -86
- package/dist/backend/notifications/dto/set-notification-email.dto.js +0 -24
- package/dist/backend/notifications/emails/reset-password.js +0 -108
- package/dist/backend/notifications/emails/test-email.js +0 -91
- package/dist/backend/notifications/emails/threshold-alert.js +0 -187
- package/dist/backend/notifications/emails/verify-email.js +0 -108
- package/dist/backend/notifications/notifications.controller.js +0 -208
- package/dist/backend/notifications/notifications.module.js +0 -35
- package/dist/backend/notifications/services/email-provider-config.service.js +0 -184
- package/dist/backend/notifications/services/email-provider-validation.js +0 -47
- package/dist/backend/notifications/services/email-providers/email-provider.interface.js +0 -3
- package/dist/backend/notifications/services/email-providers/mailgun.provider.js +0 -62
- package/dist/backend/notifications/services/email-providers/resend.provider.js +0 -51
- package/dist/backend/notifications/services/email-providers/resolve-provider.js +0 -19
- package/dist/backend/notifications/services/email-providers/send-email.js +0 -34
- package/dist/backend/notifications/services/email-providers/sendgrid.provider.js +0 -59
- package/dist/backend/notifications/services/limit-check.service.js +0 -160
- package/dist/backend/notifications/services/notification-cron.service.js +0 -151
- package/dist/backend/notifications/services/notification-email.service.js +0 -65
- package/dist/backend/notifications/services/notification-log.service.js +0 -84
- package/dist/backend/notifications/services/notification-rules.service.js +0 -156
- package/dist/backend/otlp/guards/agent-key-auth.guard.js +0 -226
- package/dist/backend/otlp/interfaces/ingestion-context.interface.js +0 -3
- package/dist/backend/otlp/otlp-deprecated.controller.js +0 -61
- package/dist/backend/otlp/otlp.module.js +0 -30
- package/dist/backend/otlp/services/api-key.service.js +0 -143
- package/dist/backend/public-stats/public-stats.controller.js +0 -141
- package/dist/backend/public-stats/public-stats.module.js +0 -26
- package/dist/backend/public-stats/public-stats.service.js +0 -226
- package/dist/backend/routing/copilot.controller.js +0 -79
- package/dist/backend/routing/custom-provider/custom-provider.controller.js +0 -131
- package/dist/backend/routing/custom-provider/custom-provider.module.js +0 -27
- package/dist/backend/routing/custom-provider/custom-provider.service.js +0 -161
- package/dist/backend/routing/dto/custom-provider.dto.js +0 -124
- package/dist/backend/routing/dto/resolve-request.dto.js +0 -63
- package/dist/backend/routing/dto/resolve-response.js +0 -3
- package/dist/backend/routing/dto/routing.dto.js +0 -136
- package/dist/backend/routing/model.controller.js +0 -105
- package/dist/backend/routing/oauth/copilot-device-auth.service.js +0 -77
- package/dist/backend/routing/oauth/minimax-oauth-helpers.js +0 -70
- package/dist/backend/routing/oauth/minimax-oauth.controller.js +0 -80
- package/dist/backend/routing/oauth/minimax-oauth.service.js +0 -252
- package/dist/backend/routing/oauth/oauth.module.js +0 -29
- package/dist/backend/routing/oauth/openai-oauth.controller.js +0 -138
- package/dist/backend/routing/oauth/openai-oauth.service.js +0 -273
- package/dist/backend/routing/oauth/openai-oauth.types.js +0 -45
- package/dist/backend/routing/provider-base-url.js +0 -25
- package/dist/backend/routing/provider.controller.js +0 -152
- package/dist/backend/routing/proxy/anthropic-adapter.js +0 -295
- package/dist/backend/routing/proxy/cache-injection.js +0 -33
- package/dist/backend/routing/proxy/chatgpt-adapter.js +0 -272
- package/dist/backend/routing/proxy/chatgpt-helpers.js +0 -108
- package/dist/backend/routing/proxy/copilot-token.service.js +0 -63
- package/dist/backend/routing/proxy/fallback-status-codes.js +0 -7
- package/dist/backend/routing/proxy/google-adapter.js +0 -314
- package/dist/backend/routing/proxy/provider-client-converters.js +0 -190
- package/dist/backend/routing/proxy/provider-client.js +0 -130
- package/dist/backend/routing/proxy/provider-endpoints.js +0 -182
- package/dist/backend/routing/proxy/proxy-error-sanitizer.js +0 -40
- package/dist/backend/routing/proxy/proxy-exception.filter.js +0 -67
- package/dist/backend/routing/proxy/proxy-fallback.service.js +0 -227
- package/dist/backend/routing/proxy/proxy-friendly-response.js +0 -115
- package/dist/backend/routing/proxy/proxy-message-dedup.js +0 -121
- package/dist/backend/routing/proxy/proxy-message-recorder.js +0 -262
- package/dist/backend/routing/proxy/proxy-rate-limiter.js +0 -81
- package/dist/backend/routing/proxy/proxy-response-handler.js +0 -202
- package/dist/backend/routing/proxy/proxy-transport.js +0 -90
- package/dist/backend/routing/proxy/proxy-types.js +0 -3
- package/dist/backend/routing/proxy/proxy.controller.js +0 -174
- package/dist/backend/routing/proxy/proxy.module.js +0 -62
- package/dist/backend/routing/proxy/proxy.service.js +0 -227
- package/dist/backend/routing/proxy/session-momentum.service.js +0 -66
- package/dist/backend/routing/proxy/stream-writer.js +0 -147
- package/dist/backend/routing/proxy/thought-signature-cache.js +0 -45
- package/dist/backend/routing/qwen-region.js +0 -51
- package/dist/backend/routing/resolve/resolve.controller.js +0 -106
- package/dist/backend/routing/resolve/resolve.module.js +0 -28
- package/dist/backend/routing/resolve/resolve.service.js +0 -126
- package/dist/backend/routing/routing-core/provider-key.service.js +0 -190
- package/dist/backend/routing/routing-core/provider.service.js +0 -305
- package/dist/backend/routing/routing-core/resolve-agent.service.js +0 -62
- package/dist/backend/routing/routing-core/routing-cache.service.js +0 -73
- package/dist/backend/routing/routing-core/routing-core.module.js +0 -56
- package/dist/backend/routing/routing-core/routing-invalidation.service.js +0 -90
- package/dist/backend/routing/routing-core/tier-auto-assign.service.js +0 -138
- package/dist/backend/routing/routing-core/tier.service.js +0 -179
- package/dist/backend/routing/routing.module.js +0 -46
- package/dist/backend/routing/tier.controller.js +0 -129
- package/dist/backend/scoring/__tests__/fixtures.js +0 -191
- package/dist/backend/scoring/config.js +0 -383
- package/dist/backend/scoring/dimensions/contextual-dimensions.js +0 -85
- package/dist/backend/scoring/dimensions/index.js +0 -17
- package/dist/backend/scoring/dimensions/keyword-dimensions.js +0 -47
- package/dist/backend/scoring/dimensions/structural-dimensions.js +0 -118
- package/dist/backend/scoring/index.js +0 -186
- package/dist/backend/scoring/keyword-trie.js +0 -75
- package/dist/backend/scoring/momentum.js +0 -50
- package/dist/backend/scoring/overrides.js +0 -55
- package/dist/backend/scoring/sigmoid.js +0 -24
- package/dist/backend/scoring/text-extractor.js +0 -67
- package/dist/backend/scoring/types.js +0 -6
- package/dist/backend/sse/sse.controller.js +0 -45
- package/dist/backend/sse/sse.module.js +0 -20
- package/dist/node_modules/manifest-shared/dist/cjs/api-key.d.ts +0 -2
- package/dist/node_modules/manifest-shared/dist/cjs/api-key.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/api-key.js +0 -5
- package/dist/node_modules/manifest-shared/dist/cjs/api-key.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/auth-types.d.ts +0 -3
- package/dist/node_modules/manifest-shared/dist/cjs/auth-types.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/auth-types.js +0 -5
- package/dist/node_modules/manifest-shared/dist/cjs/auth-types.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/index.d.ts +0 -10
- package/dist/node_modules/manifest-shared/dist/cjs/index.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/index.js +0 -22
- package/dist/node_modules/manifest-shared/dist/cjs/index.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/provider-inference.d.ts +0 -8
- package/dist/node_modules/manifest-shared/dist/cjs/provider-inference.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/provider-inference.js +0 -37
- package/dist/node_modules/manifest-shared/dist/cjs/provider-inference.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/resolve-response.d.ts +0 -12
- package/dist/node_modules/manifest-shared/dist/cjs/resolve-response.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/resolve-response.js +0 -3
- package/dist/node_modules/manifest-shared/dist/cjs/resolve-response.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/configs.d.ts +0 -4
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/configs.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/configs.js +0 -80
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/configs.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/helpers.d.ts +0 -6
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/helpers.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/helpers.js +0 -25
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/helpers.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/index.d.ts +0 -4
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/index.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/index.js +0 -12
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/index.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/types.d.ts +0 -17
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/types.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/types.js +0 -3
- package/dist/node_modules/manifest-shared/dist/cjs/subscription/types.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/tiers.d.ts +0 -5
- package/dist/node_modules/manifest-shared/dist/cjs/tiers.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/cjs/tiers.js +0 -17
- package/dist/node_modules/manifest-shared/dist/cjs/tiers.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/api-key.d.ts +0 -2
- package/dist/node_modules/manifest-shared/dist/esm/api-key.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/api-key.js +0 -2
- package/dist/node_modules/manifest-shared/dist/esm/api-key.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/auth-types.d.ts +0 -3
- package/dist/node_modules/manifest-shared/dist/esm/auth-types.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/auth-types.js +0 -2
- package/dist/node_modules/manifest-shared/dist/esm/auth-types.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/index.d.ts +0 -10
- package/dist/node_modules/manifest-shared/dist/esm/index.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/index.js +0 -6
- package/dist/node_modules/manifest-shared/dist/esm/index.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/provider-inference.d.ts +0 -8
- package/dist/node_modules/manifest-shared/dist/esm/provider-inference.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/provider-inference.js +0 -33
- package/dist/node_modules/manifest-shared/dist/esm/provider-inference.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/resolve-response.d.ts +0 -12
- package/dist/node_modules/manifest-shared/dist/esm/resolve-response.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/resolve-response.js +0 -2
- package/dist/node_modules/manifest-shared/dist/esm/resolve-response.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/subscription/configs.d.ts +0 -4
- package/dist/node_modules/manifest-shared/dist/esm/subscription/configs.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/subscription/configs.js +0 -77
- package/dist/node_modules/manifest-shared/dist/esm/subscription/configs.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/subscription/helpers.d.ts +0 -6
- package/dist/node_modules/manifest-shared/dist/esm/subscription/helpers.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/subscription/helpers.js +0 -19
- package/dist/node_modules/manifest-shared/dist/esm/subscription/helpers.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/subscription/index.d.ts +0 -4
- package/dist/node_modules/manifest-shared/dist/esm/subscription/index.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/subscription/index.js +0 -3
- package/dist/node_modules/manifest-shared/dist/esm/subscription/index.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/subscription/types.d.ts +0 -17
- package/dist/node_modules/manifest-shared/dist/esm/subscription/types.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/subscription/types.js +0 -2
- package/dist/node_modules/manifest-shared/dist/esm/subscription/types.js.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/tiers.d.ts +0 -5
- package/dist/node_modules/manifest-shared/dist/esm/tiers.d.ts.map +0 -1
- package/dist/node_modules/manifest-shared/dist/esm/tiers.js +0 -14
- package/dist/node_modules/manifest-shared/dist/esm/tiers.js.map +0 -1
- package/dist/node_modules/manifest-shared/package.json +0 -26
- package/dist/openclaw.plugin.json +0 -37
- package/dist/package.json +0 -94
- package/dist/server.d.ts +0 -8
- package/dist/server.js +0 -69
- package/openclaw.plugin.json +0 -37
- package/public/assets/Account-B_3C4z7e.js +0 -1
- package/public/assets/AuthBadge-Dj2KkXRW.js +0 -1
- package/public/assets/ConnectProvider-DxPYovG2.js +0 -1
- package/public/assets/CopyButton-BWMVlK2w.js +0 -1
- package/public/assets/FreeModels-BzNWxfZl.js +0 -1
- package/public/assets/Help-ifWIlcDo.js +0 -1
- package/public/assets/Limits-BLW0fW8j.js +0 -1
- package/public/assets/Login-DvUR0ri0.js +0 -1
- package/public/assets/MessageLog-BsuwgHos.js +0 -1
- package/public/assets/ModelPrices-8EpyI4cZ.js +0 -1
- package/public/assets/Overview-B2DQeTd2.js +0 -1
- package/public/assets/Pagination-D8BOkffh.js +0 -1
- package/public/assets/ProviderTokens-nv6wk29Y.js +0 -1
- package/public/assets/Register-WBrQ1E73.js +0 -1
- package/public/assets/ResetPassword-CWdklAXJ.js +0 -1
- package/public/assets/Routing-BqfY1unJ.js +0 -6
- package/public/assets/Settings-na6aYffS.js +0 -1
- package/public/assets/SetupStepAddProvider-CSNkQmoC.js +0 -3
- package/public/assets/SocialButtons-DG2BtKEz.js +0 -1
- package/public/assets/auth-Bcnz6mJV.js +0 -1
- package/public/assets/chart-utils-DTt1NOye.js +0 -1
- package/public/assets/charts-Cty976qB.js +0 -3
- package/public/assets/charts-Saz_VHki.css +0 -1
- package/public/assets/index-ByYwCwOa.js +0 -2
- package/public/assets/index-DhaXpWfr.css +0 -1
- package/public/assets/model-display-Bd0Zg5Lp.js +0 -1
- package/public/assets/overview-B6Wy_RSw.js +0 -1
- package/public/assets/overview-vZEzTjBP.css +0 -1
- package/public/assets/provider-api-key-urls-1G6okUJ7.js +0 -1
- package/public/assets/routing-UGVXjYdE.js +0 -1
- package/public/assets/routing-utils-BVCa9TKk.js +0 -1
- package/public/assets/vendor-C-Y5oNOq.js +0 -1
- package/public/example-messages.svg +0 -1
- package/public/example-overview.svg +0 -1
- package/public/favicon.ico +0 -0
- package/public/fonts/boxicons/boxicons-duotone.min.css +0 -37
- package/public/fonts/boxicons/boxicons-duotone.woff2 +0 -0
- package/public/fonts/bricolage-grotesque-latin.woff2 +0 -0
- package/public/fonts/dm-sans-latin.woff2 +0 -0
- package/public/fonts/jetbrains-mono-latin.woff2 +0 -0
- package/public/icons/caret-down.svg +0 -1
- package/public/icons/cohere.svg +0 -30
- package/public/icons/free.svg +0 -91
- package/public/icons/gemini.svg +0 -25
- package/public/icons/kilocode.jpg +0 -0
- package/public/icons/nvidia.svg +0 -1
- package/public/icons/providers/alibaba.svg +0 -1
- package/public/icons/providers/amazon.svg +0 -1
- package/public/icons/providers/anthropic.svg +0 -1
- package/public/icons/providers/cohere.svg +0 -1
- package/public/icons/providers/deepseek.svg +0 -1
- package/public/icons/providers/google.svg +0 -1
- package/public/icons/providers/meta.svg +0 -1
- package/public/icons/providers/mistral.svg +0 -1
- package/public/icons/providers/moonshot.svg +0 -1
- package/public/icons/providers/openai.svg +0 -1
- package/public/icons/providers/xai.svg +0 -1
- package/public/icons/providers/zhipu.svg +0 -1
- package/public/icons/qwen.svg +0 -1
- package/public/images/oauth-callback-example.mp4 +0 -0
- package/public/images/oauth-callback-example.png +0 -0
- package/public/index.html +0 -41
- package/public/logo-white.svg +0 -93
- package/public/logo.svg +0 -93
- package/public/logos/mailgun.svg +0 -13
- package/public/logos/resend.svg +0 -4
- package/public/logos/sendgrid.svg +0 -18
- package/public/manifest-logo.png +0 -0
- package/public/theme-init.js +0 -6
package/dist/index.js
CHANGED
|
@@ -1,12 +1,443 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
// src/runtime.ts
|
|
2
|
+
import { randomUUID } from "crypto";
|
|
3
|
+
|
|
4
|
+
// src/wire.ts
|
|
5
|
+
var secretNames = /* @__PURE__ */ new Set([
|
|
6
|
+
"api_key",
|
|
7
|
+
"apikey",
|
|
8
|
+
"api_token",
|
|
9
|
+
"key",
|
|
10
|
+
"token",
|
|
11
|
+
"access_token",
|
|
12
|
+
"refresh_token",
|
|
13
|
+
"auth",
|
|
14
|
+
"authorization",
|
|
15
|
+
"signature",
|
|
16
|
+
"sig",
|
|
17
|
+
"secret",
|
|
18
|
+
"client_secret",
|
|
19
|
+
"password",
|
|
20
|
+
"session",
|
|
21
|
+
"session_id",
|
|
22
|
+
"bearer",
|
|
23
|
+
"jwt",
|
|
24
|
+
"id_token",
|
|
25
|
+
"auth_token",
|
|
26
|
+
"pwd",
|
|
27
|
+
"passwd",
|
|
28
|
+
"private_key"
|
|
29
|
+
]);
|
|
30
|
+
var roots = ["auth", "key", "token", "secret", "session", "password", "passwd", "cookie", "signature", "credential", "bearer", "jwt"];
|
|
31
|
+
var normalize = (name) => name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replaceAll("-", "_").toLowerCase().replace(/^x_/, "");
|
|
32
|
+
var isSecret = (name) => secretNames.has(normalize(name));
|
|
33
|
+
var isObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
34
|
+
function safeUrl(raw) {
|
|
35
|
+
const url = new URL(raw);
|
|
36
|
+
url.username = "";
|
|
37
|
+
url.password = "";
|
|
38
|
+
url.hash = "";
|
|
39
|
+
const pairs = [...url.searchParams].map(([key, value]) => [key, isSecret(key) ? "REDACTED" : value]);
|
|
40
|
+
url.search = new URLSearchParams(pairs).toString();
|
|
41
|
+
return url.toString();
|
|
42
|
+
}
|
|
43
|
+
function safeHeaders(headers) {
|
|
44
|
+
return Object.fromEntries([...headers].map(([key, value]) => [
|
|
45
|
+
key,
|
|
46
|
+
isSecret(key) || roots.some((root) => normalize(key).includes(root)) ? "REDACTED" : value.slice(0, 1024)
|
|
47
|
+
]));
|
|
48
|
+
}
|
|
49
|
+
function travelingBody(body) {
|
|
50
|
+
return isObject(body) ? Object.fromEntries(Object.entries(body).filter(([key]) => !isSecret(key))) : body;
|
|
51
|
+
}
|
|
52
|
+
function mergeBody(original, healed) {
|
|
53
|
+
if (!isObject(original) || !isObject(healed)) return healed;
|
|
54
|
+
return { ...Object.fromEntries(Object.entries(original).filter(([key]) => isSecret(key) && !Object.hasOwn(healed, key))), ...healed };
|
|
55
|
+
}
|
|
56
|
+
function boundedJson(value) {
|
|
57
|
+
const stack = [[value, 0]];
|
|
58
|
+
let count = 0;
|
|
59
|
+
while (stack.length) {
|
|
60
|
+
const [item, depth] = stack.pop();
|
|
61
|
+
if (++count > 1e5 || depth > 64) return false;
|
|
62
|
+
if (item !== null && typeof item === "object") {
|
|
63
|
+
for (const child of Object.values(item)) stack.push([child, depth + 1]);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
function parseJson(bytes) {
|
|
69
|
+
try {
|
|
70
|
+
const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
71
|
+
return boundedJson(value) ? value : null;
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function errorBody(bytes) {
|
|
77
|
+
const parsed = parseJson(bytes);
|
|
78
|
+
const text = Buffer.from(bytes).toString("utf8");
|
|
79
|
+
return parsed ?? new TextDecoder().decode(Buffer.from(text).subarray(0, 65536), { stream: true });
|
|
80
|
+
}
|
|
81
|
+
var TRANSPORT_ERROR = "Upstream retry failed before an HTTP response";
|
|
82
|
+
|
|
83
|
+
// src/capture.ts
|
|
84
|
+
var REQUEST_LIMIT = 262144;
|
|
85
|
+
var RESPONSE_LIMIT = 65536;
|
|
86
|
+
var CAPTURE_MS = 1e3;
|
|
87
|
+
async function prefix(reader, limit, timeoutMs) {
|
|
88
|
+
const chunks = [];
|
|
89
|
+
let size = 0;
|
|
90
|
+
let pending;
|
|
91
|
+
let timer;
|
|
92
|
+
const deadline = new Promise((resolve) => {
|
|
93
|
+
timer = setTimeout(() => resolve(null), timeoutMs);
|
|
94
|
+
});
|
|
95
|
+
let complete = false;
|
|
96
|
+
try {
|
|
97
|
+
while (size <= limit) {
|
|
98
|
+
pending = reader.read();
|
|
99
|
+
const read = await Promise.race([pending, deadline]);
|
|
100
|
+
if (read === null) break;
|
|
101
|
+
pending = void 0;
|
|
102
|
+
if (read.done) {
|
|
103
|
+
complete = true;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
chunks.push(read.value);
|
|
107
|
+
size += read.value.byteLength;
|
|
108
|
+
}
|
|
109
|
+
} catch {
|
|
110
|
+
} finally {
|
|
111
|
+
clearTimeout(timer);
|
|
112
|
+
}
|
|
113
|
+
return { chunks, complete, pending, bytes: Buffer.concat(chunks, size).subarray(0, limit) };
|
|
114
|
+
}
|
|
115
|
+
async function captureRequest(request) {
|
|
116
|
+
if (!request.body) return { body: null, complete: true };
|
|
117
|
+
const clone = request.clone();
|
|
118
|
+
const reader = clone.body.getReader();
|
|
119
|
+
try {
|
|
120
|
+
const result = await prefix(reader, REQUEST_LIMIT, CAPTURE_MS);
|
|
121
|
+
return { body: result.complete ? parseJson(result.bytes) : null, complete: result.complete };
|
|
122
|
+
} finally {
|
|
123
|
+
void reader.cancel().catch(() => {
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function metadata(response, original) {
|
|
128
|
+
const clone = response.clone.bind(response);
|
|
129
|
+
Object.defineProperties(response, {
|
|
130
|
+
url: { value: original.url },
|
|
131
|
+
redirected: { value: original.redirected },
|
|
132
|
+
type: { value: original.type },
|
|
133
|
+
clone: { value: () => metadata(clone(), original) }
|
|
134
|
+
});
|
|
135
|
+
return response;
|
|
136
|
+
}
|
|
137
|
+
async function captureResponse(original, limit = RESPONSE_LIMIT, timeoutMs = CAPTURE_MS) {
|
|
138
|
+
if (!original.body) return { response: original, body: null, truncated: false, complete: true };
|
|
139
|
+
const reader = original.body.getReader();
|
|
140
|
+
const captured = await prefix(reader, limit, timeoutMs);
|
|
141
|
+
let index = 0;
|
|
142
|
+
let pending = captured.pending;
|
|
143
|
+
const stream = new ReadableStream({
|
|
144
|
+
async pull(controller) {
|
|
145
|
+
try {
|
|
146
|
+
if (index < captured.chunks.length) {
|
|
147
|
+
controller.enqueue(captured.chunks[index++]);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const read = await (pending ?? reader.read());
|
|
151
|
+
pending = void 0;
|
|
152
|
+
if (read.done) {
|
|
153
|
+
reader.releaseLock();
|
|
154
|
+
controller.close();
|
|
155
|
+
} else controller.enqueue(read.value);
|
|
156
|
+
} catch (error) {
|
|
157
|
+
controller.error(error);
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
async cancel(reason) {
|
|
161
|
+
await reader.cancel(reason);
|
|
162
|
+
}
|
|
163
|
+
}, { highWaterMark: 0 });
|
|
164
|
+
const response = metadata(new Response(stream, {
|
|
165
|
+
status: original.status,
|
|
166
|
+
statusText: original.statusText,
|
|
167
|
+
headers: original.headers
|
|
168
|
+
}), original);
|
|
169
|
+
return { response, body: errorBody(captured.bytes), truncated: !captured.complete || Buffer.byteLength(Buffer.from(captured.bytes).toString("utf8")) > limit, complete: captured.complete };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/api.ts
|
|
173
|
+
var VERSION = "6.0.0";
|
|
174
|
+
var warn = (message) => process.emitWarning(message, { code: "MNFST" });
|
|
175
|
+
var HealApi = class {
|
|
176
|
+
constructor(rawFetch, key, url, timeoutMs = 6e4, reportTimeoutMs = 5e3) {
|
|
177
|
+
this.rawFetch = rawFetch;
|
|
178
|
+
this.key = key;
|
|
179
|
+
this.url = url;
|
|
180
|
+
this.timeoutMs = timeoutMs;
|
|
181
|
+
this.reportTimeoutMs = reportTimeoutMs;
|
|
182
|
+
}
|
|
183
|
+
rawFetch;
|
|
184
|
+
key;
|
|
185
|
+
url;
|
|
186
|
+
timeoutMs;
|
|
187
|
+
reportTimeoutMs;
|
|
188
|
+
disabledUntil = 0;
|
|
189
|
+
inFlight = 0;
|
|
190
|
+
pending = /* @__PURE__ */ new Set();
|
|
191
|
+
enabled() {
|
|
192
|
+
return performance.now() >= this.disabledUntil;
|
|
193
|
+
}
|
|
194
|
+
headers() {
|
|
195
|
+
return {
|
|
196
|
+
authorization: `Bearer ${this.key}`,
|
|
197
|
+
"content-type": "application/json",
|
|
198
|
+
"user-agent": `mnfst-node/${VERSION}`,
|
|
199
|
+
"x-mnfst-source": "node-sdk"
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
async heal(capture, signal) {
|
|
203
|
+
if (!this.enabled() || this.inFlight >= 8) return null;
|
|
204
|
+
this.inFlight++;
|
|
205
|
+
const controller = new AbortController();
|
|
206
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
207
|
+
try {
|
|
208
|
+
const response = await this.rawFetch(new URL("v1/heal", this.url), {
|
|
209
|
+
method: "POST",
|
|
210
|
+
headers: this.headers(),
|
|
211
|
+
body: JSON.stringify(capture),
|
|
212
|
+
signal: AbortSignal.any([signal, controller.signal]),
|
|
213
|
+
redirect: "error"
|
|
214
|
+
});
|
|
215
|
+
if (response.status !== 200 && response.status !== 403) {
|
|
216
|
+
void response.body?.cancel().catch(() => {
|
|
217
|
+
});
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
const captured = await captureResponse(response, 1048576, this.timeoutMs);
|
|
221
|
+
void captured.response.body?.cancel().catch(() => {
|
|
222
|
+
});
|
|
223
|
+
if (!captured.complete || !isObject(captured.body) || !boundedJson(captured.body)) return null;
|
|
224
|
+
if (response.status === 403 && captured.body.error === "project_disabled") {
|
|
225
|
+
this.disabledUntil = performance.now() + 3e5;
|
|
226
|
+
}
|
|
227
|
+
if (response.status !== 200 || typeof captured.body.status !== "string") return null;
|
|
228
|
+
return {
|
|
229
|
+
status: captured.body.status,
|
|
230
|
+
...typeof captured.body.healAttemptId === "string" ? { healAttemptId: captured.body.healAttemptId } : {},
|
|
231
|
+
...Array.isArray(captured.body.operations) ? { operations: captured.body.operations } : {},
|
|
232
|
+
...isObject(captured.body.healedRequest) ? { healedRequest: captured.body.healedRequest } : {}
|
|
233
|
+
};
|
|
234
|
+
} catch {
|
|
235
|
+
return null;
|
|
236
|
+
} finally {
|
|
237
|
+
clearTimeout(timer);
|
|
238
|
+
this.inFlight--;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
report(id, outcome) {
|
|
242
|
+
if (!id) return;
|
|
243
|
+
if (this.pending.size >= 64) {
|
|
244
|
+
warn("Outcome report capacity reached; report dropped");
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const promise = this.send(id, outcome);
|
|
248
|
+
this.pending.add(promise);
|
|
249
|
+
void promise.then(() => this.pending.delete(promise));
|
|
250
|
+
}
|
|
251
|
+
async send(id, outcome) {
|
|
252
|
+
const controller = new AbortController();
|
|
253
|
+
const timer = setTimeout(() => controller.abort(), this.reportTimeoutMs);
|
|
254
|
+
try {
|
|
255
|
+
const response = await this.rawFetch(new URL(`v1/heal-attempts/${encodeURIComponent(id)}`, this.url), {
|
|
256
|
+
method: "PATCH",
|
|
257
|
+
headers: this.headers(),
|
|
258
|
+
body: JSON.stringify(outcome),
|
|
259
|
+
signal: controller.signal,
|
|
260
|
+
redirect: "error"
|
|
261
|
+
});
|
|
262
|
+
void response.body?.cancel().catch(() => {
|
|
263
|
+
});
|
|
264
|
+
if (!response.ok) warn("Outcome report rejected; attempt remains unconfirmed");
|
|
265
|
+
} catch {
|
|
266
|
+
warn("Outcome report failed; attempt remains unconfirmed");
|
|
267
|
+
} finally {
|
|
268
|
+
clearTimeout(timer);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async flush(timeoutMs = 5e3) {
|
|
272
|
+
let timer;
|
|
273
|
+
try {
|
|
274
|
+
await Promise.race([
|
|
275
|
+
Promise.allSettled([...this.pending]),
|
|
276
|
+
new Promise((resolve) => {
|
|
277
|
+
timer = setTimeout(resolve, Math.max(0, timeoutMs));
|
|
278
|
+
})
|
|
279
|
+
]);
|
|
280
|
+
} finally {
|
|
281
|
+
clearTimeout(timer);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// src/runtime.ts
|
|
287
|
+
var eligible = /* @__PURE__ */ new Set([400, 404, 422]);
|
|
288
|
+
var Runtime = class {
|
|
289
|
+
constructor(options, original, api) {
|
|
290
|
+
this.options = options;
|
|
291
|
+
this.original = original;
|
|
292
|
+
this.api = api ?? new HealApi(original, options.key, options.url);
|
|
293
|
+
}
|
|
294
|
+
options;
|
|
295
|
+
original;
|
|
296
|
+
api;
|
|
297
|
+
fetch = async (input, init) => {
|
|
298
|
+
const request = new Request(input, init);
|
|
299
|
+
const extras = { ...init };
|
|
300
|
+
delete extras.body;
|
|
301
|
+
delete extras.headers;
|
|
302
|
+
const bodyPromise = captureRequest(request).catch(() => ({ body: null, complete: false }));
|
|
303
|
+
const started = performance.now();
|
|
304
|
+
const response = await this.original(request, extras);
|
|
305
|
+
const responseTimeMs = performance.now() - started;
|
|
306
|
+
if (!eligible.has(response.status) || response.redirected || !this.api.enabled()) return response;
|
|
307
|
+
return this.repair(request, extras, response, await bodyPromise, responseTimeMs);
|
|
308
|
+
};
|
|
309
|
+
async repair(request, extras, original, body, responseTimeMs) {
|
|
310
|
+
let response = original;
|
|
311
|
+
let result = null;
|
|
312
|
+
const started = performance.now();
|
|
313
|
+
let replayStatusCode = null;
|
|
314
|
+
let replayAttempted = false;
|
|
315
|
+
try {
|
|
316
|
+
const captured = await captureResponse(response);
|
|
317
|
+
response = captured.response;
|
|
318
|
+
const payload = {
|
|
319
|
+
traceId: randomUUID(),
|
|
320
|
+
request: { method: request.method, url: safeUrl(request.url), headers: safeHeaders(request.headers), body: travelingBody(body.body) },
|
|
321
|
+
response: { statusCode: response.status, body: captured.body, truncated: captured.truncated },
|
|
322
|
+
responseTimeMs: Math.round(responseTimeMs)
|
|
323
|
+
};
|
|
324
|
+
request.signal.throwIfAborted();
|
|
325
|
+
result = await this.api.heal(payload, request.signal);
|
|
326
|
+
request.signal.throwIfAborted();
|
|
327
|
+
const retry = body.complete && captured.complete ? buildRetry(request, body.body, result) : null;
|
|
328
|
+
if (!retry) {
|
|
329
|
+
this.api.report(result?.healAttemptId, { failure: { kind: "not_attempted", message: "replay_not_attempted" } });
|
|
330
|
+
return response;
|
|
331
|
+
}
|
|
332
|
+
replayAttempted = true;
|
|
333
|
+
let retried;
|
|
334
|
+
try {
|
|
335
|
+
retried = await this.original(retry, extras);
|
|
336
|
+
} catch {
|
|
337
|
+
this.api.report(result?.healAttemptId, { failure: { kind: "transport_error", message: TRANSPORT_ERROR } });
|
|
338
|
+
request.signal.throwIfAborted();
|
|
339
|
+
return response;
|
|
340
|
+
}
|
|
341
|
+
replayStatusCode = retried.status;
|
|
342
|
+
if (retried.status >= 400) {
|
|
343
|
+
const capturedRetry = await captureResponse(retried);
|
|
344
|
+
retried = capturedRetry.response;
|
|
345
|
+
this.api.report(result?.healAttemptId, { response: { statusCode: retried.status, body: capturedRetry.body, truncated: capturedRetry.truncated } });
|
|
346
|
+
} else {
|
|
347
|
+
this.api.report(result?.healAttemptId, { response: { statusCode: retried.status } });
|
|
348
|
+
}
|
|
349
|
+
void response.body?.cancel().catch(() => {
|
|
350
|
+
});
|
|
351
|
+
return retried;
|
|
352
|
+
} catch {
|
|
353
|
+
request.signal.throwIfAborted();
|
|
354
|
+
this.api.report(result?.healAttemptId, { failure: { kind: "not_attempted", message: "replay_not_attempted" } });
|
|
355
|
+
return response;
|
|
356
|
+
} finally {
|
|
357
|
+
if (this.options.onHeal) {
|
|
358
|
+
try {
|
|
359
|
+
void Promise.resolve(this.options.onHeal({
|
|
360
|
+
url: safeUrl(request.url),
|
|
361
|
+
statusCode: original.status,
|
|
362
|
+
healStatus: replayAttempted && replayStatusCode === null ? "replay_failed" : result?.status ?? "heal_unreachable",
|
|
363
|
+
replayStatusCode,
|
|
364
|
+
healMs: Math.round(performance.now() - started),
|
|
365
|
+
operations: result?.operations
|
|
366
|
+
})).catch(() => warn("onHeal callback failed"));
|
|
367
|
+
} catch {
|
|
368
|
+
warn("onHeal callback failed");
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
function buildRetry(request, originalBody, result) {
|
|
375
|
+
if (!result || !["patched", "unverified"].includes(result.status) || !isObject(result.healedRequest)) return null;
|
|
376
|
+
const healed = result.healedRequest;
|
|
377
|
+
if (!["url", "headers", "body"].some((key) => Object.hasOwn(healed, key))) return null;
|
|
378
|
+
try {
|
|
379
|
+
const url = new URL(healed.url ?? request.url);
|
|
380
|
+
if (url.origin !== new URL(request.url).origin || url.username || url.password) return null;
|
|
381
|
+
const headers = new Headers(request.headers);
|
|
382
|
+
headers.delete("content-length");
|
|
383
|
+
if (healed.headers !== void 0 && !isObject(healed.headers)) return null;
|
|
384
|
+
for (const [name, value] of Object.entries(healed.headers ?? {})) {
|
|
385
|
+
if (value === null) headers.delete(name);
|
|
386
|
+
else if (typeof value === "string") headers.set(name, value);
|
|
387
|
+
else return null;
|
|
388
|
+
}
|
|
389
|
+
const body = Object.hasOwn(healed, "body") ? mergeBody(originalBody, healed.body) : originalBody;
|
|
390
|
+
if (body === null && !["GET", "HEAD"].includes(request.method)) return null;
|
|
391
|
+
return new Request(url, {
|
|
392
|
+
method: request.method,
|
|
393
|
+
headers,
|
|
394
|
+
body: ["GET", "HEAD"].includes(request.method) ? void 0 : JSON.stringify(body),
|
|
395
|
+
signal: request.signal,
|
|
396
|
+
redirect: request.redirect,
|
|
397
|
+
credentials: request.credentials,
|
|
398
|
+
cache: request.cache,
|
|
399
|
+
integrity: request.integrity,
|
|
400
|
+
keepalive: request.keepalive,
|
|
401
|
+
mode: request.mode,
|
|
402
|
+
referrer: request.referrer,
|
|
403
|
+
referrerPolicy: request.referrerPolicy
|
|
404
|
+
});
|
|
405
|
+
} catch {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// src/index.ts
|
|
411
|
+
var STATE = /* @__PURE__ */ Symbol.for("mnfst.node.runtime.v1");
|
|
412
|
+
var globals = globalThis;
|
|
413
|
+
function manifest(options = {}) {
|
|
414
|
+
const key = options.key || process.env.MNFST_KEY;
|
|
415
|
+
if (!key) {
|
|
416
|
+
warn("MNFST_KEY is not set; Manifest is disabled");
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
const url = new URL(options.url || process.env.MNFST_URL || "https://api.manifest.build");
|
|
420
|
+
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password || url.search || url.hash) {
|
|
421
|
+
throw new TypeError("Manifest URL must be an HTTP(S) base URL without credentials, query or fragment");
|
|
422
|
+
}
|
|
423
|
+
if (!url.pathname.endsWith("/")) url.pathname += "/";
|
|
424
|
+
const resolved = { ...options, key, url: url.toString() };
|
|
425
|
+
const existing = globals[STATE];
|
|
426
|
+
if (existing) {
|
|
427
|
+
if (existing.options.key !== key || existing.options.url !== resolved.url || existing.options.onHeal !== options.onHeal) {
|
|
428
|
+
warn("Manifest is already configured; changing configuration requires a process restart");
|
|
429
|
+
}
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
const runtime = new Runtime(resolved, globalThis.fetch.bind(globalThis));
|
|
433
|
+
globalThis.fetch = runtime.fetch;
|
|
434
|
+
globals[STATE] = runtime;
|
|
435
|
+
}
|
|
436
|
+
async function flush(options = {}) {
|
|
437
|
+
await globals[STATE]?.api.flush(options.timeoutMs ?? 5e3);
|
|
438
|
+
}
|
|
439
|
+
export {
|
|
440
|
+
VERSION,
|
|
441
|
+
flush,
|
|
442
|
+
manifest
|
|
443
|
+
};
|
package/docs/guide.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# SDK guide
|
|
2
|
+
|
|
3
|
+
[← Quick start](../README.md)
|
|
4
|
+
|
|
5
|
+
## Configuration
|
|
6
|
+
|
|
7
|
+
Call `manifest()` once at startup, before other libraries save a reference to `fetch`.
|
|
8
|
+
|
|
9
|
+
| Option | Environment | Default |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| `key` | `MNFST_KEY` | Disabled with a warning if missing |
|
|
12
|
+
| `url` | `MNFST_URL` | `https://api.manifest.build` |
|
|
13
|
+
| `onHeal` | — | Optional local callback |
|
|
14
|
+
|
|
15
|
+
Explicit options take precedence. Reconfiguration requires a restart. ESM and CommonJS imports share one process-wide installation.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
manifest({
|
|
19
|
+
url: 'http://127.0.0.1:5310',
|
|
20
|
+
onHeal(event) {
|
|
21
|
+
console.log(event.healStatus, event.replayStatusCode);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`onHeal` receives `url`, `statusCode`, `healStatus`, `replayStatusCode`, `healMs` and optional `operations`. URLs have known credential query fields masked. Callback errors do not fail application requests.
|
|
27
|
+
|
|
28
|
+
## Supported traffic
|
|
29
|
+
|
|
30
|
+
- Built-in global `fetch`, including `Request` inputs and libraries that call global fetch after installation.
|
|
31
|
+
- Failures after automatic redirects pass through: the original method/body may not describe the failing hop.
|
|
32
|
+
- Captures HTTP 400, 404 and 422. Other statuses and network failures before an HTTP response pass through.
|
|
33
|
+
- Generic JSON APIs, including LLM APIs. No provider-specific request format is required.
|
|
34
|
+
- One retry per capture. Same-origin URL and header repairs are supported by the SDK; the current app returns JSON body repairs.
|
|
35
|
+
- Successful calls and successful retries remain streamed. Failed responses retain their bytes, status, headers, URL and redirect metadata.
|
|
36
|
+
|
|
37
|
+
**Not covered:** browser JavaScript, `node:http`/`node:https`, the default Axios HTTP adapter, directly imported `undici.fetch`/`node-fetch`, and fetch references saved before initialization. Those transports need separate integration. This SDK does not claim to intercept every Node HTTP client.
|
|
38
|
+
|
|
39
|
+
## Limits and failure behavior
|
|
40
|
+
|
|
41
|
+
- Request capture is bounded to 256 KiB and JSON depth 64. It tees the upload alongside the original call, reading for at most one second. Oversized or slow uploads travel as `null` and are not retried.
|
|
42
|
+
- Error capture reads at most 64 KiB plus one transport chunk, within one second. The prefix and remaining stream are preserved for the caller. Incomplete errors are reported without retry. One unusually large transport chunk can exceed that memory estimate.
|
|
43
|
+
- The Manifest heal call has a 60-second deadline and at most eight concurrent requests. Capacity exhaustion and service errors return the original API error response.
|
|
44
|
+
- Caller abort signals apply during healing and retry; cancellation remains observable to the caller.
|
|
45
|
+
- A transport failure on retry returns the original error response and reports inconclusive evidence. If the retry returns another HTTP error, its raw body is reported so the app can distinguish recurrence from a new issue.
|
|
46
|
+
- Automatic retries can repeat side effects. Use APIs with safe retry semantics and caller-managed idempotency keys; these headers are preserved unless explicitly changed by a repair.
|
|
47
|
+
- A disabled project's HTTP 403 response suppresses healing for five minutes.
|
|
48
|
+
|
|
49
|
+
Outcome reports are best effort, limited to 64 concurrent requests with five-second deadlines. Failures and drops emit Node warnings with code `MNFST`. Before a short-lived process exits, flush reports explicitly:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { flush } from 'manifest';
|
|
53
|
+
await flush({ timeoutMs: 5000 });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`flush` waits within one total deadline; it does not uninstall the SDK or guarantee delivery. Abrupt termination can lose reports.
|
|
57
|
+
|
|
58
|
+
## Data sent to Manifest
|
|
59
|
+
|
|
60
|
+
Failed URLs, request headers, JSON bodies and raw error responses go to the configured server. Known credential names in query parameters and headers are masked; credential-named top-level request body fields are withheld and restored on retry. Exception prose is not sent for transport failures.
|
|
61
|
+
|
|
62
|
+
This is not general secret detection: nested fields, arbitrary secret names, business data and response bodies may contain sensitive information. Enable it only for traffic you permit Manifest to process and store. The SDK makes the actual retry locally.
|
|
63
|
+
|
|
64
|
+
## Development
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
npm ci
|
|
68
|
+
npm run typecheck
|
|
69
|
+
npm test
|
|
70
|
+
npm pack
|
|
71
|
+
# Optional: creates a synthetic customer/project in a disposable app.
|
|
72
|
+
MNFST_TEST_APP_URL=http://127.0.0.1:5310 npm run test:live
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
CI runs Node 22, 24 and 26, checks both declaration formats, and installs the packed artifact. The live app test runs locally because cross-repository CI access to the private app is not configured.
|
|
76
|
+
|
|
77
|
+
Deploy the outcome contract in [app PR #3](https://github.com/mnfst/app/pull/3) before using this SDK. See [CONTRACT.md](../CONTRACT.md) for the shared Python/Node wire protocol.
|
package/package.json
CHANGED
|
@@ -1,93 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "manifest",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
"version": "6.0.0",
|
|
4
|
+
"description": "Repair eligible failed JSON API calls made with Node fetch.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
16
20
|
},
|
|
17
21
|
"files": [
|
|
18
|
-
"dist
|
|
19
|
-
"dist/server.js",
|
|
20
|
-
"dist/server.d.ts",
|
|
21
|
-
"dist/backend",
|
|
22
|
-
"dist/package.json",
|
|
23
|
-
"dist/node_modules",
|
|
24
|
-
"public",
|
|
25
|
-
"openclaw.plugin.json",
|
|
22
|
+
"dist",
|
|
26
23
|
"README.md",
|
|
27
|
-
"
|
|
24
|
+
"CONTRACT.md",
|
|
25
|
+
"docs"
|
|
28
26
|
],
|
|
29
|
-
"openclaw": {
|
|
30
|
-
"extensions": [
|
|
31
|
-
"./dist/index.js"
|
|
32
|
-
]
|
|
33
|
-
},
|
|
34
27
|
"engines": {
|
|
35
|
-
"node": ">=
|
|
28
|
+
"node": ">=22"
|
|
36
29
|
},
|
|
37
30
|
"scripts": {
|
|
38
|
-
"
|
|
39
|
-
"build": "tsx build.ts && tsc -p tsconfig.server.json && node scripts/copy-assets.js",
|
|
40
|
-
"prepublishOnly": "npm run build && cp ../../../README.md README.md",
|
|
31
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
41
32
|
"typecheck": "tsc --noEmit",
|
|
42
|
-
"test": "
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"openclaw",
|
|
46
|
-
"openclaw-plugin",
|
|
47
|
-
"manifest",
|
|
48
|
-
"manifest-local",
|
|
49
|
-
"llm-router",
|
|
50
|
-
"self-hosted",
|
|
51
|
-
"local-first",
|
|
52
|
-
"sqlite",
|
|
53
|
-
"ai-dashboard",
|
|
54
|
-
"embedded-server"
|
|
55
|
-
],
|
|
56
|
-
"dependencies": {
|
|
57
|
-
"@nestjs/cache-manager": "^3.1.0",
|
|
58
|
-
"@nestjs/common": "^11.0.0",
|
|
59
|
-
"@nestjs/config": "^4.0.0",
|
|
60
|
-
"@nestjs/core": "^11.0.0",
|
|
61
|
-
"@nestjs/platform-express": "^11.0.0",
|
|
62
|
-
"@nestjs/schedule": "^6.1.1",
|
|
63
|
-
"@nestjs/serve-static": "^5.0.4",
|
|
64
|
-
"@nestjs/throttler": "^6.0.0",
|
|
65
|
-
"@nestjs/typeorm": "^11.0.0",
|
|
66
|
-
"@react-email/components": "^1.0.7",
|
|
67
|
-
"@react-email/render": "^2.0.4",
|
|
68
|
-
"better-auth": "^1.4.18",
|
|
69
|
-
"cache-manager": "^7.2.8",
|
|
70
|
-
"class-transformer": "^0.5.1",
|
|
71
|
-
"class-validator": "^0.14.0",
|
|
72
|
-
"compression": "^1.8.1",
|
|
73
|
-
"express-rate-limit": "^8.3.1",
|
|
74
|
-
"helmet": "^8.1.0",
|
|
75
|
-
"pg": "^8.13.0",
|
|
76
|
-
"protobufjs": "^8.0.0",
|
|
77
|
-
"react": "^19.2.4",
|
|
78
|
-
"react-dom": "^19.2.4",
|
|
79
|
-
"reflect-metadata": "^0.2.0",
|
|
80
|
-
"rxjs": "^7.8.0",
|
|
81
|
-
"sql.js": "^1.12.0",
|
|
82
|
-
"typeorm": "^0.3.0",
|
|
83
|
-
"uuid": "^11.0.0"
|
|
33
|
+
"test": "tsx --test tests/*.test.ts",
|
|
34
|
+
"test:live": "tsx --test tests/live.test.ts",
|
|
35
|
+
"prepare": "npm run build"
|
|
84
36
|
},
|
|
85
37
|
"devDependencies": {
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
|
|
91
|
-
|
|
38
|
+
"@types/node": "^22.0.0",
|
|
39
|
+
"tsup": "^8.5.0",
|
|
40
|
+
"tsx": "^4.20.0",
|
|
41
|
+
"typescript": "^5.9.0"
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/mnfst/manifest-node.git"
|
|
46
|
+
},
|
|
47
|
+
"overrides": {
|
|
48
|
+
"esbuild": "^0.28.2"
|
|
92
49
|
}
|
|
93
50
|
}
|