@sixthsummit/ship-api 0.0.0-stage → 4.1.1
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/CHANGELOG.md +605 -0
- package/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +58 -2
- package/cli/commands/add.js +537 -0
- package/cli/commands/contract.js +2 -0
- package/cli/commands/create.js +250 -0
- package/cli/commands/dev.js +227 -0
- package/cli/commands/doctor.js +286 -0
- package/cli/commands/generate.js +937 -0
- package/cli/commands/graph.js +2 -0
- package/cli/commands/migrate-orm.js +1171 -0
- package/cli/commands/update.js +37 -0
- package/cli/ship-api.js +285 -0
- package/lib/app/auth/AuthProvider.d.ts +91 -0
- package/lib/app/auth/AuthProvider.d.ts.map +1 -0
- package/lib/app/auth/AuthProvider.js +13 -0
- package/lib/app/auth/AuthProvider.js.map +1 -0
- package/lib/app/auth/adapters/firebase.d.ts +79 -0
- package/lib/app/auth/adapters/firebase.d.ts.map +1 -0
- package/lib/app/auth/adapters/firebase.js +122 -0
- package/lib/app/auth/adapters/firebase.js.map +1 -0
- package/lib/app/auth/adapters/jwtCookie.d.ts +55 -0
- package/lib/app/auth/adapters/jwtCookie.d.ts.map +1 -0
- package/lib/app/auth/adapters/jwtCookie.js +120 -0
- package/lib/app/auth/adapters/jwtCookie.js.map +1 -0
- package/lib/app/auth/index.d.ts +8 -0
- package/lib/app/auth/index.d.ts.map +1 -0
- package/lib/app/auth/index.js +7 -0
- package/lib/app/auth/index.js.map +1 -0
- package/lib/app/auth/jwt/AuthFlow.d.ts +94 -0
- package/lib/app/auth/jwt/AuthFlow.d.ts.map +1 -0
- package/lib/app/auth/jwt/AuthFlow.js +127 -0
- package/lib/app/auth/jwt/AuthFlow.js.map +1 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts +80 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts.map +1 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js +134 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js.map +1 -0
- package/lib/app/auth/jwt/JwtSigner.d.ts +123 -0
- package/lib/app/auth/jwt/JwtSigner.d.ts.map +1 -0
- package/lib/app/auth/jwt/JwtSigner.js +118 -0
- package/lib/app/auth/jwt/JwtSigner.js.map +1 -0
- package/lib/app/auth/jwt/RefreshTokenStore.d.ts +97 -0
- package/lib/app/auth/jwt/RefreshTokenStore.d.ts.map +1 -0
- package/lib/app/auth/jwt/RefreshTokenStore.js +122 -0
- package/lib/app/auth/jwt/RefreshTokenStore.js.map +1 -0
- package/lib/app/auth/permissionDefinition.d.ts +20 -0
- package/lib/app/auth/permissionDefinition.d.ts.map +1 -0
- package/lib/app/auth/permissionDefinition.js +2 -0
- package/lib/app/auth/permissionDefinition.js.map +1 -0
- package/lib/app/context/RequestContext.d.ts +59 -0
- package/lib/app/context/RequestContext.d.ts.map +1 -0
- package/lib/app/context/RequestContext.js +25 -0
- package/lib/app/context/RequestContext.js.map +1 -0
- package/lib/app/db/QueryOptions.d.ts +82 -0
- package/lib/app/db/QueryOptions.d.ts.map +1 -0
- package/lib/app/db/QueryOptions.js +37 -0
- package/lib/app/db/QueryOptions.js.map +1 -0
- package/lib/app/db/baseFields.d.ts +60 -0
- package/lib/app/db/baseFields.d.ts.map +1 -0
- package/lib/app/db/baseFields.js +54 -0
- package/lib/app/db/baseFields.js.map +1 -0
- package/lib/app/db/buildWhere.d.ts +22 -0
- package/lib/app/db/buildWhere.d.ts.map +1 -0
- package/lib/app/db/buildWhere.js +75 -0
- package/lib/app/db/buildWhere.js.map +1 -0
- package/lib/app/db/client.d.ts +111 -0
- package/lib/app/db/client.d.ts.map +1 -0
- package/lib/app/db/client.js +99 -0
- package/lib/app/db/client.js.map +1 -0
- package/lib/app/db/tenantScoped.d.ts +59 -0
- package/lib/app/db/tenantScoped.d.ts.map +1 -0
- package/lib/app/db/tenantScoped.js +54 -0
- package/lib/app/db/tenantScoped.js.map +1 -0
- package/lib/app/db/transaction.d.ts +58 -0
- package/lib/app/db/transaction.d.ts.map +1 -0
- package/lib/app/db/transaction.js +106 -0
- package/lib/app/db/transaction.js.map +1 -0
- package/lib/app/health/HealthCheck.d.ts +121 -0
- package/lib/app/health/HealthCheck.d.ts.map +1 -0
- package/lib/app/health/HealthCheck.js +151 -0
- package/lib/app/health/HealthCheck.js.map +1 -0
- package/lib/app/health/redisHealthCheck.d.ts +14 -0
- package/lib/app/health/redisHealthCheck.d.ts.map +1 -0
- package/lib/app/health/redisHealthCheck.js +21 -0
- package/lib/app/health/redisHealthCheck.js.map +1 -0
- package/lib/app/lifecycle/Bootstrapper.d.ts +92 -0
- package/lib/app/lifecycle/Bootstrapper.d.ts.map +1 -0
- package/lib/app/lifecycle/Bootstrapper.js +99 -0
- package/lib/app/lifecycle/Bootstrapper.js.map +1 -0
- package/lib/app/registry/routes.d.ts +89 -0
- package/lib/app/registry/routes.d.ts.map +1 -0
- package/lib/app/registry/routes.js +72 -0
- package/lib/app/registry/routes.js.map +1 -0
- package/lib/app/services/DrizzleEntityService.d.ts +123 -0
- package/lib/app/services/DrizzleEntityService.d.ts.map +1 -0
- package/lib/app/services/DrizzleEntityService.js +342 -0
- package/lib/app/services/DrizzleEntityService.js.map +1 -0
- package/lib/app/services/RedisProvider.d.ts +52 -0
- package/lib/app/services/RedisProvider.d.ts.map +1 -0
- package/lib/app/services/RedisProvider.js +75 -0
- package/lib/app/services/RedisProvider.js.map +1 -0
- package/lib/app/services/cache/Cache.d.ts +70 -0
- package/lib/app/services/cache/Cache.d.ts.map +1 -0
- package/lib/app/services/cache/Cache.js +18 -0
- package/lib/app/services/cache/Cache.js.map +1 -0
- package/lib/app/services/cache/InMemoryCache.d.ts +35 -0
- package/lib/app/services/cache/InMemoryCache.d.ts.map +1 -0
- package/lib/app/services/cache/InMemoryCache.js +76 -0
- package/lib/app/services/cache/InMemoryCache.js.map +1 -0
- package/lib/app/services/cache/RedisCache.d.ts +99 -0
- package/lib/app/services/cache/RedisCache.d.ts.map +1 -0
- package/lib/app/services/cache/RedisCache.js +150 -0
- package/lib/app/services/cache/RedisCache.js.map +1 -0
- package/lib/app/services/cache/cached.d.ts +30 -0
- package/lib/app/services/cache/cached.d.ts.map +1 -0
- package/lib/app/services/cache/cached.js +38 -0
- package/lib/app/services/cache/cached.js.map +1 -0
- package/lib/app/services/cache/index.d.ts +5 -0
- package/lib/app/services/cache/index.d.ts.map +1 -0
- package/lib/app/services/cache/index.js +4 -0
- package/lib/app/services/cache/index.js.map +1 -0
- package/lib/app/services/cron/defineCron.d.ts +57 -0
- package/lib/app/services/cron/defineCron.d.ts.map +1 -0
- package/lib/app/services/cron/defineCron.js +15 -0
- package/lib/app/services/cron/defineCron.js.map +1 -0
- package/lib/app/services/cron/index.d.ts +2 -0
- package/lib/app/services/cron/index.d.ts.map +1 -0
- package/lib/app/services/cron/index.js +2 -0
- package/lib/app/services/cron/index.js.map +1 -0
- package/lib/app/services/hooks/LifecycleHooks.d.ts +61 -0
- package/lib/app/services/hooks/LifecycleHooks.d.ts.map +1 -0
- package/lib/app/services/hooks/LifecycleHooks.js +85 -0
- package/lib/app/services/hooks/LifecycleHooks.js.map +1 -0
- package/lib/app/services/jobs/JobsManager.d.ts +67 -0
- package/lib/app/services/jobs/JobsManager.d.ts.map +1 -0
- package/lib/app/services/jobs/JobsManager.js +121 -0
- package/lib/app/services/jobs/JobsManager.js.map +1 -0
- package/lib/app/services/jobs/bullBoard.d.ts +72 -0
- package/lib/app/services/jobs/bullBoard.d.ts.map +1 -0
- package/lib/app/services/jobs/bullBoard.js +96 -0
- package/lib/app/services/jobs/bullBoard.js.map +1 -0
- package/lib/app/services/jobs/defineJob.d.ts +81 -0
- package/lib/app/services/jobs/defineJob.d.ts.map +1 -0
- package/lib/app/services/jobs/defineJob.js +49 -0
- package/lib/app/services/jobs/defineJob.js.map +1 -0
- package/lib/app/services/jobs/index.d.ts +4 -0
- package/lib/app/services/jobs/index.d.ts.map +1 -0
- package/lib/app/services/jobs/index.js +4 -0
- package/lib/app/services/jobs/index.js.map +1 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts +23 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts.map +1 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js +51 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js.map +1 -0
- package/lib/app/services/rateLimit/RateLimitBackend.d.ts +41 -0
- package/lib/app/services/rateLimit/RateLimitBackend.d.ts.map +1 -0
- package/lib/app/services/rateLimit/RateLimitBackend.js +19 -0
- package/lib/app/services/rateLimit/RateLimitBackend.js.map +1 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts +16 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts.map +1 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js +80 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js.map +1 -0
- package/lib/app/services/rateLimit/index.d.ts +4 -0
- package/lib/app/services/rateLimit/index.d.ts.map +1 -0
- package/lib/app/services/rateLimit/index.js +3 -0
- package/lib/app/services/rateLimit/index.js.map +1 -0
- package/lib/app/services/storage/DiskStorageAdapter.d.ts +62 -0
- package/lib/app/services/storage/DiskStorageAdapter.d.ts.map +1 -0
- package/lib/app/services/storage/DiskStorageAdapter.js +295 -0
- package/lib/app/services/storage/DiskStorageAdapter.js.map +1 -0
- package/lib/app/services/storage/GCSStorageAdapter.d.ts +44 -0
- package/lib/app/services/storage/GCSStorageAdapter.d.ts.map +1 -0
- package/lib/app/services/storage/GCSStorageAdapter.js +133 -0
- package/lib/app/services/storage/GCSStorageAdapter.js.map +1 -0
- package/lib/app/services/storage/S3StorageAdapter.d.ts +57 -0
- package/lib/app/services/storage/S3StorageAdapter.d.ts.map +1 -0
- package/lib/app/services/storage/S3StorageAdapter.js +162 -0
- package/lib/app/services/storage/S3StorageAdapter.js.map +1 -0
- package/lib/app/services/storage/StorageService.d.ts +88 -0
- package/lib/app/services/storage/StorageService.d.ts.map +1 -0
- package/lib/app/services/storage/StorageService.js +18 -0
- package/lib/app/services/storage/StorageService.js.map +1 -0
- package/lib/app/services/storage/index.d.ts +5 -0
- package/lib/app/services/storage/index.d.ts.map +1 -0
- package/lib/app/services/storage/index.js +4 -0
- package/lib/app/services/storage/index.js.map +1 -0
- package/lib/app/utils/ContextValidators.d.ts +46 -0
- package/lib/app/utils/ContextValidators.d.ts.map +1 -0
- package/lib/app/utils/ContextValidators.js +81 -0
- package/lib/app/utils/ContextValidators.js.map +1 -0
- package/lib/app/utils/defineEnv.d.ts +80 -0
- package/lib/app/utils/defineEnv.d.ts.map +1 -0
- package/lib/app/utils/defineEnv.js +95 -0
- package/lib/app/utils/defineEnv.js.map +1 -0
- package/lib/client.d.ts +139 -0
- package/lib/client.d.ts.map +1 -0
- package/lib/client.js +98 -0
- package/lib/client.js.map +1 -0
- package/lib/contract/application.d.ts +3 -0
- package/lib/contract/application.d.ts.map +1 -0
- package/lib/contract/application.js +2 -0
- package/lib/contract/application.js.map +1 -0
- package/lib/contract/client.d.ts +3 -0
- package/lib/contract/client.d.ts.map +1 -0
- package/lib/contract/client.js +3 -0
- package/lib/contract/client.js.map +1 -0
- package/lib/contract/index.d.ts +3 -0
- package/lib/contract/index.d.ts.map +1 -0
- package/lib/contract/index.js +3 -0
- package/lib/contract/index.js.map +1 -0
- package/lib/contract/manifest.d.ts +3 -0
- package/lib/contract/manifest.d.ts.map +1 -0
- package/lib/contract/manifest.js +2 -0
- package/lib/contract/manifest.js.map +1 -0
- package/lib/contract/openapi.d.ts +3 -0
- package/lib/contract/openapi.d.ts.map +1 -0
- package/lib/contract/openapi.js +3 -0
- package/lib/contract/openapi.js.map +1 -0
- package/lib/contract/project.d.ts +3 -0
- package/lib/contract/project.d.ts.map +1 -0
- package/lib/contract/project.js +3 -0
- package/lib/contract/project.js.map +1 -0
- package/lib/contract/schema.d.ts +3 -0
- package/lib/contract/schema.d.ts.map +1 -0
- package/lib/contract/schema.js +3 -0
- package/lib/contract/schema.js.map +1 -0
- package/lib/drizzle/index.d.ts +3 -0
- package/lib/drizzle/index.d.ts.map +1 -0
- package/lib/drizzle/index.js +3 -0
- package/lib/drizzle/index.js.map +1 -0
- package/lib/hono/auth.d.ts +6 -0
- package/lib/hono/auth.d.ts.map +1 -0
- package/lib/hono/auth.js +54 -0
- package/lib/hono/auth.js.map +1 -0
- package/lib/hono/index.d.ts +4 -0
- package/lib/hono/index.d.ts.map +1 -0
- package/lib/hono/index.js +4 -0
- package/lib/hono/index.js.map +1 -0
- package/lib/http/app/createApp.d.ts +132 -0
- package/lib/http/app/createApp.d.ts.map +1 -0
- package/lib/http/app/createApp.js +215 -0
- package/lib/http/app/createApp.js.map +1 -0
- package/lib/http/app/devRoutes.d.ts +31 -0
- package/lib/http/app/devRoutes.d.ts.map +1 -0
- package/lib/http/app/devRoutes.js +145 -0
- package/lib/http/app/devRoutes.js.map +1 -0
- package/lib/http/app/errors.d.ts +45 -0
- package/lib/http/app/errors.d.ts.map +1 -0
- package/lib/http/app/errors.js +93 -0
- package/lib/http/app/errors.js.map +1 -0
- package/lib/http/app/health.d.ts +66 -0
- package/lib/http/app/health.d.ts.map +1 -0
- package/lib/http/app/health.js +104 -0
- package/lib/http/app/health.js.map +1 -0
- package/lib/http/errors/AppError.d.ts +10 -0
- package/lib/http/errors/AppError.d.ts.map +1 -0
- package/lib/http/errors/AppError.js +19 -0
- package/lib/http/errors/AppError.js.map +1 -0
- package/lib/http/errors/AuthenticationError.d.ts +8 -0
- package/lib/http/errors/AuthenticationError.d.ts.map +1 -0
- package/lib/http/errors/AuthenticationError.js +10 -0
- package/lib/http/errors/AuthenticationError.js.map +1 -0
- package/lib/http/errors/AuthorizationError.d.ts +8 -0
- package/lib/http/errors/AuthorizationError.d.ts.map +1 -0
- package/lib/http/errors/AuthorizationError.js +10 -0
- package/lib/http/errors/AuthorizationError.js.map +1 -0
- package/lib/http/errors/BadRequestError.d.ts +8 -0
- package/lib/http/errors/BadRequestError.d.ts.map +1 -0
- package/lib/http/errors/BadRequestError.js +10 -0
- package/lib/http/errors/BadRequestError.js.map +1 -0
- package/lib/http/errors/ConflictError.d.ts +8 -0
- package/lib/http/errors/ConflictError.d.ts.map +1 -0
- package/lib/http/errors/ConflictError.js +10 -0
- package/lib/http/errors/ConflictError.js.map +1 -0
- package/lib/http/errors/InternalServerError.d.ts +8 -0
- package/lib/http/errors/InternalServerError.d.ts.map +1 -0
- package/lib/http/errors/InternalServerError.js +10 -0
- package/lib/http/errors/InternalServerError.js.map +1 -0
- package/lib/http/errors/NotFoundError.d.ts +8 -0
- package/lib/http/errors/NotFoundError.d.ts.map +1 -0
- package/lib/http/errors/NotFoundError.js +10 -0
- package/lib/http/errors/NotFoundError.js.map +1 -0
- package/lib/http/errors/RateLimitError.d.ts +13 -0
- package/lib/http/errors/RateLimitError.d.ts.map +1 -0
- package/lib/http/errors/RateLimitError.js +16 -0
- package/lib/http/errors/RateLimitError.js.map +1 -0
- package/lib/http/errors/ServiceUnavailableError.d.ts +8 -0
- package/lib/http/errors/ServiceUnavailableError.d.ts.map +1 -0
- package/lib/http/errors/ServiceUnavailableError.js +10 -0
- package/lib/http/errors/ServiceUnavailableError.js.map +1 -0
- package/lib/http/errors/ValidationError.d.ts +9 -0
- package/lib/http/errors/ValidationError.d.ts.map +1 -0
- package/lib/http/errors/ValidationError.js +12 -0
- package/lib/http/errors/ValidationError.js.map +1 -0
- package/lib/http/errors/index.d.ts +11 -0
- package/lib/http/errors/index.d.ts.map +1 -0
- package/lib/http/errors/index.js +12 -0
- package/lib/http/errors/index.js.map +1 -0
- package/lib/http/middleware/apiKey.d.ts +9 -0
- package/lib/http/middleware/apiKey.d.ts.map +1 -0
- package/lib/http/middleware/apiKey.js +71 -0
- package/lib/http/middleware/apiKey.js.map +1 -0
- package/lib/http/middleware/csrf.d.ts +63 -0
- package/lib/http/middleware/csrf.d.ts.map +1 -0
- package/lib/http/middleware/csrf.js +169 -0
- package/lib/http/middleware/csrf.js.map +1 -0
- package/lib/http/middleware/httpLogger.d.ts +39 -0
- package/lib/http/middleware/httpLogger.d.ts.map +1 -0
- package/lib/http/middleware/httpLogger.js +118 -0
- package/lib/http/middleware/httpLogger.js.map +1 -0
- package/lib/http/middleware/idempotency.d.ts +48 -0
- package/lib/http/middleware/idempotency.d.ts.map +1 -0
- package/lib/http/middleware/idempotency.js +180 -0
- package/lib/http/middleware/idempotency.js.map +1 -0
- package/lib/http/middleware/rateLimit.d.ts +105 -0
- package/lib/http/middleware/rateLimit.d.ts.map +1 -0
- package/lib/http/middleware/rateLimit.js +84 -0
- package/lib/http/middleware/rateLimit.js.map +1 -0
- package/lib/http/middleware/requireAuth.d.ts +58 -0
- package/lib/http/middleware/requireAuth.d.ts.map +1 -0
- package/lib/http/middleware/requireAuth.js +63 -0
- package/lib/http/middleware/requireAuth.js.map +1 -0
- package/lib/http/middleware/requirePermission.d.ts +23 -0
- package/lib/http/middleware/requirePermission.d.ts.map +1 -0
- package/lib/http/middleware/requirePermission.js +50 -0
- package/lib/http/middleware/requirePermission.js.map +1 -0
- package/lib/http/middleware/resolveTenant.d.ts +41 -0
- package/lib/http/middleware/resolveTenant.d.ts.map +1 -0
- package/lib/http/middleware/resolveTenant.js +17 -0
- package/lib/http/middleware/resolveTenant.js.map +1 -0
- package/lib/http/streaming/sse.d.ts +31 -0
- package/lib/http/streaming/sse.d.ts.map +1 -0
- package/lib/http/streaming/sse.js +11 -0
- package/lib/http/streaming/sse.js.map +1 -0
- package/lib/http/streaming/streamLLM.d.ts +94 -0
- package/lib/http/streaming/streamLLM.d.ts.map +1 -0
- package/lib/http/streaming/streamLLM.js +94 -0
- package/lib/http/streaming/streamLLM.js.map +1 -0
- package/lib/http/utils/authCookies.d.ts +74 -0
- package/lib/http/utils/authCookies.d.ts.map +1 -0
- package/lib/http/utils/authCookies.js +102 -0
- package/lib/http/utils/authCookies.js.map +1 -0
- package/lib/http/utils/clientIp.d.ts +85 -0
- package/lib/http/utils/clientIp.d.ts.map +1 -0
- package/lib/http/utils/clientIp.js +249 -0
- package/lib/http/utils/clientIp.js.map +1 -0
- package/lib/http/utils/index.d.ts +4 -0
- package/lib/http/utils/index.d.ts.map +1 -0
- package/lib/http/utils/index.js +5 -0
- package/lib/http/utils/index.js.map +1 -0
- package/lib/http/utils/metaTags.d.ts +49 -0
- package/lib/http/utils/metaTags.d.ts.map +1 -0
- package/lib/http/utils/metaTags.js +32 -0
- package/lib/http/utils/metaTags.js.map +1 -0
- package/lib/http/utils/publicSuffix.d.ts +34 -0
- package/lib/http/utils/publicSuffix.d.ts.map +1 -0
- package/lib/http/utils/publicSuffix.js +276 -0
- package/lib/http/utils/publicSuffix.js.map +1 -0
- package/lib/http/utils/uploads.d.ts +92 -0
- package/lib/http/utils/uploads.d.ts.map +1 -0
- package/lib/http/utils/uploads.js +126 -0
- package/lib/http/utils/uploads.js.map +1 -0
- package/lib/http/utils/validate.d.ts +41 -0
- package/lib/http/utils/validate.d.ts.map +1 -0
- package/lib/http/utils/validate.js +55 -0
- package/lib/http/utils/validate.js.map +1 -0
- package/lib/http/utils/webhooks.d.ts +63 -0
- package/lib/http/utils/webhooks.d.ts.map +1 -0
- package/lib/http/utils/webhooks.js +133 -0
- package/lib/http/utils/webhooks.js.map +1 -0
- package/lib/http/ws/auth.d.ts +46 -0
- package/lib/http/ws/auth.d.ts.map +1 -0
- package/lib/http/ws/auth.js +123 -0
- package/lib/http/ws/auth.js.map +1 -0
- package/lib/index.d.ts +80 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +61 -0
- package/lib/index.js.map +1 -0
- package/lib/kernel/index.d.ts +3 -0
- package/lib/kernel/index.d.ts.map +1 -0
- package/lib/kernel/index.js +3 -0
- package/lib/kernel/index.js.map +1 -0
- package/lib/libraries/.gitkeep +0 -0
- package/lib/libraries/ai/CHANGELOG.md +17 -0
- package/lib/libraries/ai/README.md +164 -0
- package/lib/libraries/ai/adapters/AnthropicAdapter.ts +382 -0
- package/lib/libraries/ai/adapters/LLMProvider.ts +76 -0
- package/lib/libraries/ai/adapters/OpenAIAdapter.ts +466 -0
- package/lib/libraries/ai/experimental/index.ts +20 -0
- package/lib/libraries/ai/index.ts +128 -0
- package/lib/libraries/ai/library.json +19 -0
- package/lib/libraries/ai/loop/agentLoop.ts +377 -0
- package/lib/libraries/ai/prompts/definePrompt.ts +0 -0
- package/lib/libraries/ai/rag/retrieveAndAnswer.ts +177 -0
- package/lib/libraries/ai/streaming/streamLLM.ts +94 -0
- package/lib/libraries/ai/structured/completeStructured.ts +143 -0
- package/lib/libraries/ai/tokens/Tokenizer.ts +216 -0
- package/lib/libraries/ai/tools/defineTool.ts +208 -0
- package/lib/libraries/ai/types.ts +260 -0
- package/lib/libraries/chunking/ChunkingService.ts +103 -0
- package/lib/libraries/chunking/README.md +104 -0
- package/lib/libraries/chunking/docs/api-reference.md +549 -0
- package/lib/libraries/chunking/docs/best-practices.md +321 -0
- package/lib/libraries/chunking/docs/code-organization.md +538 -0
- package/lib/libraries/chunking/docs/configuration.md +418 -0
- package/lib/libraries/chunking/docs/index.md +236 -0
- package/lib/libraries/chunking/docs/quick-start.md +298 -0
- package/lib/libraries/chunking/docs/strategies.md +407 -0
- package/lib/libraries/chunking/docs/summary.md +258 -0
- package/lib/libraries/chunking/docs/troubleshooting.md +527 -0
- package/lib/libraries/chunking/index.ts +17 -0
- package/lib/libraries/chunking/library.json +16 -0
- package/lib/libraries/chunking/strategies/ChunkingStrategy.ts +13 -0
- package/lib/libraries/chunking/strategies/FixedLengthChunkingStrategy.ts +88 -0
- package/lib/libraries/chunking/strategies/SemanticChunkingStrategy.ts +389 -0
- package/lib/libraries/chunking/strategies/SlidingWindowChunkingStrategy.ts +258 -0
- package/lib/libraries/chunking/types/index.ts +63 -0
- package/lib/libraries/email/EmailService.ts +591 -0
- package/lib/libraries/email/README.md +777 -0
- package/lib/libraries/email/TemplateRegistry.ts +148 -0
- package/lib/libraries/email/TemplateRenderer.ts +273 -0
- package/lib/libraries/email/index.ts +4 -0
- package/lib/libraries/email/initializeEmailService.ts +60 -0
- package/lib/libraries/email/library.json +12 -0
- package/lib/libraries/email/types/EmailAddress.ts +4 -0
- package/lib/libraries/email/types/EmailAttachment.ts +11 -0
- package/lib/libraries/email/types/EmailTag.ts +9 -0
- package/lib/libraries/email/types/EmailTemplate.ts +124 -0
- package/lib/libraries/email/types/SendBatchEmailsOptions.ts +9 -0
- package/lib/libraries/email/types/SendBatchEmailsResult.ts +9 -0
- package/lib/libraries/email/types/SendEmailOptions.ts +33 -0
- package/lib/libraries/email/types/SendEmailResult.ts +9 -0
- package/lib/libraries/email/types/index.ts +8 -0
- package/lib/libraries/weaviate/QueryBuilder.ts +292 -0
- package/lib/libraries/weaviate/README.md +284 -0
- package/lib/libraries/weaviate/Weaviate.ts +1419 -0
- package/lib/libraries/weaviate/WeaviateConfig.ts +268 -0
- package/lib/libraries/weaviate/docs/.gitkeep +1 -0
- package/lib/libraries/weaviate/docs/API_REFERENCE.md +1067 -0
- package/lib/libraries/weaviate/docs/CONFIGURATION.md +320 -0
- package/lib/libraries/weaviate/docs/ERROR_HANDLING.md +271 -0
- package/lib/libraries/weaviate/docs/MULTI_TENANCY.md +348 -0
- package/lib/libraries/weaviate/docs/PERFORMANCE.md +602 -0
- package/lib/libraries/weaviate/docs/PLUGIN_DEVELOPMENT.md +547 -0
- package/lib/libraries/weaviate/docs/QUICK_START.md +443 -0
- package/lib/libraries/weaviate/docs/README.md +269 -0
- package/lib/libraries/weaviate/docs/SCHEMA_GUIDE.md +630 -0
- package/lib/libraries/weaviate/docs/WEAVIATE_README.md +520 -0
- package/lib/libraries/weaviate/errors/WeaviateError.ts +92 -0
- package/lib/libraries/weaviate/errors/index.ts +1 -0
- package/lib/libraries/weaviate/index.ts +35 -0
- package/lib/libraries/weaviate/library.json +26 -0
- package/lib/libraries/weaviate/plugins/index.ts +2 -0
- package/lib/libraries/weaviate/schemas/SchemaRegistry.ts +284 -0
- package/lib/libraries/weaviate/schemas/index.ts +2 -0
- package/lib/libraries/weaviate/types/BM25SearchOptions.ts +9 -0
- package/lib/libraries/weaviate/types/ExtendedWeaviateClient.ts +7 -0
- package/lib/libraries/weaviate/types/HybridSearchOptions.ts +11 -0
- package/lib/libraries/weaviate/types/MultiTenancy.ts +81 -0
- package/lib/libraries/weaviate/types/Plugin.ts +17 -0
- package/lib/libraries/weaviate/types/SchemaConfig.ts +25 -0
- package/lib/libraries/weaviate/types/SearchMethod.ts +8 -0
- package/lib/libraries/weaviate/types/SearchOptions.ts +16 -0
- package/lib/libraries/weaviate/types/SearchRequest.ts +19 -0
- package/lib/libraries/weaviate/types/SearchResult.ts +16 -0
- package/lib/libraries/weaviate/types/SearchableField.ts +87 -0
- package/lib/libraries/weaviate/types/VectorIndexConfig.ts +19 -0
- package/lib/libraries/weaviate/types/VectorSearchOptions.ts +18 -0
- package/lib/libraries/weaviate/types/VectorizerConfig.ts +8 -0
- package/lib/libraries/weaviate/types/index.ts +29 -0
- package/lib/libraries/weaviate/utils/TenantContextManager.ts +94 -0
- package/lib/modules/accounts/index.ts +47 -0
- package/lib/modules/accounts/module.json +15 -0
- package/lib/modules/accounts/permissions.ts +33 -0
- package/lib/modules/accounts/routes.ts +200 -0
- package/lib/modules/accounts/schema.ts +219 -0
- package/lib/modules/accounts/services/AccountService.ts +44 -0
- package/lib/modules/accounts/validation/schemas.ts +70 -0
- package/lib/modules/oauth/adapters/GmailOAuthAdapter.ts +35 -0
- package/lib/modules/oauth/adapters/GoogleOAuthAdapter.ts +278 -0
- package/lib/modules/oauth/adapters/MicrosoftOAuthAdapter.ts +269 -0
- package/lib/modules/oauth/adapters/MockOAuthAdapter.ts +138 -0
- package/lib/modules/oauth/adapters/OAuthAdapter.ts +211 -0
- package/lib/modules/oauth/adapters/OAuthAdapterRegistry.ts +77 -0
- package/lib/modules/oauth/adapters/OutlookOAuthAdapter.ts +38 -0
- package/lib/modules/oauth/index.ts +79 -0
- package/lib/modules/oauth/module.json +23 -0
- package/lib/modules/oauth/permissions.ts +39 -0
- package/lib/modules/oauth/routes.ts +497 -0
- package/lib/modules/oauth/schema.ts +127 -0
- package/lib/modules/oauth/services/OAuthConnectionService.ts +147 -0
- package/lib/modules/oauth/state.ts +234 -0
- package/lib/modules/oauth/stateJtiCache.ts +85 -0
- package/lib/modules/oauth/verifyIdToken.ts +178 -0
- package/lib/modules/outbox/EventEmitter.ts +106 -0
- package/lib/modules/outbox/OutboxDrainer.ts +163 -0
- package/lib/modules/outbox/handlers/EventHandler.ts +115 -0
- package/lib/modules/outbox/index.ts +43 -0
- package/lib/modules/outbox/module.json +15 -0
- package/lib/modules/outbox/permissions.ts +36 -0
- package/lib/modules/outbox/routes.ts +219 -0
- package/lib/modules/outbox/schema.ts +207 -0
- package/lib/modules/outbox/services/OutboxEventService.ts +223 -0
- package/lib/observability/logger.d.ts +30 -0
- package/lib/observability/logger.d.ts.map +1 -0
- package/lib/observability/logger.js +110 -0
- package/lib/observability/logger.js.map +1 -0
- package/lib/observability/metrics.d.ts +3 -0
- package/lib/observability/metrics.d.ts.map +1 -0
- package/lib/observability/metrics.js +3 -0
- package/lib/observability/metrics.js.map +1 -0
- package/lib/observability/otel.d.ts +3 -0
- package/lib/observability/otel.d.ts.map +1 -0
- package/lib/observability/otel.js +3 -0
- package/lib/observability/otel.js.map +1 -0
- package/lib/observability/safeErrorFields.d.ts +14 -0
- package/lib/observability/safeErrorFields.d.ts.map +1 -0
- package/lib/observability/safeErrorFields.js +14 -0
- package/lib/observability/safeErrorFields.js.map +1 -0
- package/lib/observability/tracing.d.ts +3 -0
- package/lib/observability/tracing.d.ts.map +1 -0
- package/lib/observability/tracing.js +3 -0
- package/lib/observability/tracing.js.map +1 -0
- package/lib/package.json +4 -0
- package/lib/testing.d.ts +3 -0
- package/lib/testing.d.ts.map +1 -0
- package/lib/testing.js +3 -0
- package/lib/testing.js.map +1 -0
- package/package.json +193 -3
- package/templates/default/.claude/agents/qa-brief.md +106 -0
- package/templates/default/.claude/commands/sherpa-brief.md +23 -0
- package/templates/default/.cursor/rules/api.mdc +80 -0
- package/templates/default/.cursor/rules/commits.mdc +88 -0
- package/templates/default/.cursor/rules/security.mdc +92 -0
- package/templates/default/.cursor/rules/testing.mdc +123 -0
- package/templates/default/.cursor/rules/typescript.mdc +86 -0
- package/templates/default/.env.example +79 -0
- package/templates/default/.github/workflows/sherpa-brief.yml +180 -0
- package/templates/default/AGENTS.md +166 -0
- package/templates/default/CLAUDE.md +17 -0
- package/templates/default/README.md +97 -0
- package/templates/default/_gitignore +27 -0
- package/templates/default/docker-compose.yml +83 -0
- package/templates/default/drizzle.config.ts +34 -0
- package/templates/default/eslint.config.mjs +106 -0
- package/templates/default/package.json +57 -0
- package/templates/default/ship-api.config.ts +21 -0
- package/templates/default/src/client.ts +34 -0
- package/templates/default/src/config/modules.ts +23 -0
- package/templates/default/src/db/schema.ts +26 -0
- package/templates/default/src/environment.ts +81 -0
- package/templates/default/src/index.test.ts +53 -0
- package/templates/default/src/index.ts +11 -0
- package/templates/default/src/instrumentation.ts +13 -0
- package/templates/default/src/server.ts +90 -0
- package/templates/default/tsconfig.json +24 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { LLMProvider } from "../adapters/LLMProvider.js";
|
|
3
|
+
import type { CompleteOptions, CompleteResult, ToolDefinition, ToolUsePart } from "../types.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `completeStructured<TSchema>({ llm, schema, ... })` — single-shot
|
|
7
|
+
* call that returns a typed object matching the supplied Zod schema.
|
|
8
|
+
*
|
|
9
|
+
* Pattern: defines a synthetic "respond" tool whose `input_schema` is
|
|
10
|
+
* the JSON-schema view of the user's Zod schema, forces
|
|
11
|
+
* `tool_choice: { type: "tool", name }` so the model MUST invoke it,
|
|
12
|
+
* then parses the tool_use input back through the Zod schema (catches
|
|
13
|
+
* any drift the JSON-schema view didn't constrain — e.g. Zod
|
|
14
|
+
* refinements that don't translate).
|
|
15
|
+
*
|
|
16
|
+
* Provider-portable by design — works against any `LLMProvider` whose
|
|
17
|
+
* `complete()` honors `tools` + `toolChoice`. Provider-specific
|
|
18
|
+
* structured-output APIs (OpenAI `response_format: json_schema`,
|
|
19
|
+
* Anthropic `parse()` helper) can be wired in adapter-specific
|
|
20
|
+
* overrides in a later commit; this primitive ships the load-bearing
|
|
21
|
+
* cross-provider path first.
|
|
22
|
+
*
|
|
23
|
+
* Why a synthetic tool instead of "ask the model for JSON in a code
|
|
24
|
+
* block":
|
|
25
|
+
* - Tool-use is the model's native structured-output channel —
|
|
26
|
+
* providers train it explicitly. JSON-in-text is best-effort and
|
|
27
|
+
* drifts (markdown fences, trailing commentary, hallucinated keys).
|
|
28
|
+
* - The tool's `input_schema` is forced upstream in the request, so
|
|
29
|
+
* the provider can constrain decoding (Anthropic does shape-aware
|
|
30
|
+
* decoding for tool inputs).
|
|
31
|
+
* - Tool inputs come back already-parsed JSON — no re-parsing /
|
|
32
|
+
* stripping markdown.
|
|
33
|
+
*
|
|
34
|
+
* Errors: `StructuredOutputError` thrown when (a) the model returns
|
|
35
|
+
* text instead of invoking the tool (rare with `toolChoice: tool` but
|
|
36
|
+
* possible on `max_tokens` cutoff), (b) the tool input fails Zod
|
|
37
|
+
* validation. Both carry the raw `CompleteResult` for debugging.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
export interface CompleteStructuredOptions<TSchema extends z.ZodTypeAny>
|
|
41
|
+
extends Omit<CompleteOptions, "tools" | "toolChoice"> {
|
|
42
|
+
/** Provider that runs the request. */
|
|
43
|
+
llm: LLMProvider;
|
|
44
|
+
/** Zod schema describing the desired output shape. */
|
|
45
|
+
schema: TSchema;
|
|
46
|
+
/**
|
|
47
|
+
* Override the synthetic tool's name. Default `"respond"`. Useful
|
|
48
|
+
* when the tool name appears in the model's reasoning trace and you
|
|
49
|
+
* want it to read more naturally.
|
|
50
|
+
*/
|
|
51
|
+
responseToolName?: string;
|
|
52
|
+
/** Override the synthetic tool's description shown to the model. */
|
|
53
|
+
responseToolDescription?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface CompleteStructuredResult<T> {
|
|
57
|
+
/** The parsed, schema-validated output. */
|
|
58
|
+
data: T;
|
|
59
|
+
/** The raw provider response (usage / id / model / etc.). */
|
|
60
|
+
raw: CompleteResult;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class StructuredOutputError extends Error {
|
|
64
|
+
constructor(
|
|
65
|
+
message: string,
|
|
66
|
+
public readonly raw: CompleteResult,
|
|
67
|
+
) {
|
|
68
|
+
super(message);
|
|
69
|
+
this.name = "StructuredOutputError";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const DEFAULT_TOOL_NAME = "respond";
|
|
74
|
+
const DEFAULT_TOOL_DESCRIPTION =
|
|
75
|
+
"Respond with the structured output. Call this tool exactly once with the final answer matching the input schema.";
|
|
76
|
+
|
|
77
|
+
export async function completeStructured<TSchema extends z.ZodTypeAny>(
|
|
78
|
+
opts: CompleteStructuredOptions<TSchema>,
|
|
79
|
+
): Promise<CompleteStructuredResult<z.infer<TSchema>>> {
|
|
80
|
+
const inputSchema = z.toJSONSchema(opts.schema, {
|
|
81
|
+
target: "draft-2020-12",
|
|
82
|
+
}) as Record<string, unknown>;
|
|
83
|
+
delete inputSchema["$schema"];
|
|
84
|
+
|
|
85
|
+
const responseTool: ToolDefinition = {
|
|
86
|
+
name: opts.responseToolName ?? DEFAULT_TOOL_NAME,
|
|
87
|
+
description: opts.responseToolDescription ?? DEFAULT_TOOL_DESCRIPTION,
|
|
88
|
+
inputSchema,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Drop the keys we own from the forwarded options.
|
|
92
|
+
const {
|
|
93
|
+
llm,
|
|
94
|
+
schema: _schema,
|
|
95
|
+
responseToolName: _name,
|
|
96
|
+
responseToolDescription: _desc,
|
|
97
|
+
...providerOpts
|
|
98
|
+
} = opts;
|
|
99
|
+
void _schema;
|
|
100
|
+
void _name;
|
|
101
|
+
void _desc;
|
|
102
|
+
|
|
103
|
+
const raw = await llm.complete({
|
|
104
|
+
...providerOpts,
|
|
105
|
+
tools: [responseTool],
|
|
106
|
+
toolChoice: { type: "tool", name: responseTool.name },
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const toolUse = raw.content.find(
|
|
110
|
+
(p): p is ToolUsePart => p.type === "tool_use" && p.name === responseTool.name,
|
|
111
|
+
);
|
|
112
|
+
if (!toolUse) {
|
|
113
|
+
throw new StructuredOutputError(
|
|
114
|
+
`Model did not invoke the "${responseTool.name}" tool — got stop_reason="${raw.stopReason}"`,
|
|
115
|
+
raw,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const parsed = opts.schema.safeParse(toolUse.input);
|
|
120
|
+
if (!parsed.success) {
|
|
121
|
+
throw new StructuredOutputError(
|
|
122
|
+
`Response did not match schema: ${formatZodIssues(parsed.error.issues)}`,
|
|
123
|
+
raw,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return { data: parsed.data as z.infer<TSchema>, raw };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
interface ZodLikeIssue {
|
|
131
|
+
path?: Array<string | number>;
|
|
132
|
+
message: string;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function formatZodIssues(issues: readonly ZodLikeIssue[]): string {
|
|
136
|
+
if (!issues.length) return "validation failed";
|
|
137
|
+
return issues
|
|
138
|
+
.map((issue) => {
|
|
139
|
+
const path = (issue.path ?? []).join(".") || "(root)";
|
|
140
|
+
return `${path}: ${issue.message}`;
|
|
141
|
+
})
|
|
142
|
+
.join("; ");
|
|
143
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import type { Message, MessageContentPart } from "../types.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pluggable tokenizer contract — counts tokens for a given model
|
|
5
|
+
* without committing the library to a specific tokenizer
|
|
6
|
+
* implementation (tiktoken / claude-tokenizer / model-bundled
|
|
7
|
+
* /encoding-rs / online API). Consumers inject the right tokenizer
|
|
8
|
+
* for their provider; this library never imports a tokenizer SDK
|
|
9
|
+
* itself, so the dep graph stays narrow.
|
|
10
|
+
*
|
|
11
|
+
* Why an interface instead of "just use tiktoken":
|
|
12
|
+
* - Tokenization is provider-specific. OpenAI uses tiktoken (cl100k /
|
|
13
|
+
* o200k); Anthropic uses a Claude-specific BPE; Llama / Mistral
|
|
14
|
+
* have their own. One library, three tokenizers.
|
|
15
|
+
* - Tiktoken pulls a 5+ MB WASM blob — fine for server-side, hostile
|
|
16
|
+
* for edge runtimes. An "estimate" tokenizer is preferable when
|
|
17
|
+
* exactness doesn't matter (rate-limit budgeting, prompt-fit
|
|
18
|
+
* gating).
|
|
19
|
+
* - Tests need a predictable in-process tokenizer; consumers can
|
|
20
|
+
* register `HeuristicTokenizer` for cheap deterministic counts.
|
|
21
|
+
*
|
|
22
|
+
* The library ships `HeuristicTokenizer` as a baseline (~4 chars per
|
|
23
|
+
* token, the well-known rule-of-thumb for English). Real tokenizers
|
|
24
|
+
* (tiktoken-backed for OpenAI, claude-tokenizer for Anthropic) are
|
|
25
|
+
* straightforward to implement against this interface and can land in
|
|
26
|
+
* v4.x adapter sub-packages so they're tree-shake-friendly.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
export interface Tokenizer {
|
|
30
|
+
/** Stable model identifier the tokenizer is calibrated for. */
|
|
31
|
+
readonly model: string;
|
|
32
|
+
/**
|
|
33
|
+
* Count tokens in a single string. Synchronous so callers can use it
|
|
34
|
+
* inside hot prompt-assembly loops without await ceremony.
|
|
35
|
+
*/
|
|
36
|
+
count(text: string): number;
|
|
37
|
+
/**
|
|
38
|
+
* Optional encode (text → tokens). Provided when the tokenizer is
|
|
39
|
+
* exact (tiktoken / claude); omitted on heuristic backends.
|
|
40
|
+
*/
|
|
41
|
+
encode?(text: string): number[];
|
|
42
|
+
/** Optional decode (tokens → text). Same caveat as `encode`. */
|
|
43
|
+
decode?(tokens: number[]): string;
|
|
44
|
+
/**
|
|
45
|
+
* Free any resources the tokenizer holds (tiktoken WASM handles,
|
|
46
|
+
* file mappings). Idempotent. Safe to call when nothing was
|
|
47
|
+
* allocated.
|
|
48
|
+
*/
|
|
49
|
+
dispose?(): void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Sum tokens across a `Message[]` history — text parts, tool_use
|
|
54
|
+
* input JSON, tool_result content, image part overhead. Provider-
|
|
55
|
+
* specific message-formatting overhead (per-turn separator tokens,
|
|
56
|
+
* role-name tokens) is approximated by `perMessageOverhead`; refine
|
|
57
|
+
* per provider when exactness matters.
|
|
58
|
+
*/
|
|
59
|
+
export interface CountMessagesOptions {
|
|
60
|
+
/** Tokens added per message (separators / role name). Default 4. */
|
|
61
|
+
perMessageOverhead?: number;
|
|
62
|
+
/**
|
|
63
|
+
* Tokens budgeted per image part. Anthropic / OpenAI both charge a
|
|
64
|
+
* fixed-ish range (~85–1500 depending on resolution). Default 1024
|
|
65
|
+
* — middle of the range; pass a tighter estimate when known.
|
|
66
|
+
*/
|
|
67
|
+
perImageTokens?: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const DEFAULT_PER_MESSAGE_OVERHEAD = 4;
|
|
71
|
+
const DEFAULT_PER_IMAGE_TOKENS = 1024;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @deprecated AI-R3. Token *truth* comes back in the provider response — read
|
|
75
|
+
* `CompleteResult.usage` / `StreamStopEvent.usage` (real, billed counts). This
|
|
76
|
+
* heuristic-driven count is inaccurate (±15%) and a per-model maintenance
|
|
77
|
+
* burden. For pre-call budgeting only, use `estimateMessageTokens`.
|
|
78
|
+
*/
|
|
79
|
+
export function countMessageTokens(
|
|
80
|
+
tokenizer: Tokenizer,
|
|
81
|
+
messages: Message[],
|
|
82
|
+
opts: CountMessagesOptions = {},
|
|
83
|
+
): number {
|
|
84
|
+
const perMessage = opts.perMessageOverhead ?? DEFAULT_PER_MESSAGE_OVERHEAD;
|
|
85
|
+
const perImage = opts.perImageTokens ?? DEFAULT_PER_IMAGE_TOKENS;
|
|
86
|
+
|
|
87
|
+
let total = 0;
|
|
88
|
+
for (const msg of messages) {
|
|
89
|
+
total += perMessage;
|
|
90
|
+
if (typeof msg.content === "string") {
|
|
91
|
+
total += tokenizer.count(msg.content);
|
|
92
|
+
} else {
|
|
93
|
+
total += countParts(tokenizer, msg.content, perImage);
|
|
94
|
+
}
|
|
95
|
+
if (msg.name) total += tokenizer.count(msg.name);
|
|
96
|
+
}
|
|
97
|
+
return total;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function countParts(tokenizer: Tokenizer, parts: MessageContentPart[], perImage: number): number {
|
|
101
|
+
let n = 0;
|
|
102
|
+
for (const p of parts) {
|
|
103
|
+
switch (p.type) {
|
|
104
|
+
case "text":
|
|
105
|
+
n += tokenizer.count(p.text);
|
|
106
|
+
break;
|
|
107
|
+
case "tool_use":
|
|
108
|
+
n += tokenizer.count(p.name);
|
|
109
|
+
// input JSON shows up to the model verbatim — count it.
|
|
110
|
+
try {
|
|
111
|
+
n += tokenizer.count(JSON.stringify(p.input ?? {}));
|
|
112
|
+
} catch {
|
|
113
|
+
// unrenderable input → conservative estimate
|
|
114
|
+
n += 16;
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
case "tool_result":
|
|
118
|
+
n += tokenizer.count(p.content);
|
|
119
|
+
break;
|
|
120
|
+
case "image":
|
|
121
|
+
n += perImage;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return n;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Heuristic tokenizer — `Math.ceil(text.length / 4)`, the canonical
|
|
130
|
+
* rule-of-thumb for English text. ±15% accuracy; good enough for
|
|
131
|
+
* rate-limit budgeting and prompt-fit gating, not for exact billing.
|
|
132
|
+
*
|
|
133
|
+
* Ships zero deps and works in every runtime (Node, Workers, Bun,
|
|
134
|
+
* browser). Real tokenizers swap in via the `Tokenizer` interface
|
|
135
|
+
* without changing call sites.
|
|
136
|
+
*
|
|
137
|
+
* @deprecated AI-R3. Token truth comes back in the provider response — read
|
|
138
|
+
* `CompleteResult.usage`. Use this only as a pre-call estimate; the standalone
|
|
139
|
+
* `estimateTokens` / `estimateMessageTokens` helpers are the lighter, honestly-
|
|
140
|
+
* labelled way to do that without a pluggable-tokenizer subsystem. The
|
|
141
|
+
* `Tokenizer` interface itself is NOT deprecated — a real tiktoken/claude
|
|
142
|
+
* tokenizer still implements it.
|
|
143
|
+
*/
|
|
144
|
+
export class HeuristicTokenizer implements Tokenizer {
|
|
145
|
+
readonly model: string;
|
|
146
|
+
private readonly charsPerToken: number;
|
|
147
|
+
|
|
148
|
+
constructor(opts: { model?: string; charsPerToken?: number } = {}) {
|
|
149
|
+
this.model = opts.model ?? "heuristic";
|
|
150
|
+
this.charsPerToken = opts.charsPerToken ?? 4;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
count(text: string): number {
|
|
154
|
+
if (!text) return 0;
|
|
155
|
+
return Math.ceil(text.length / this.charsPerToken);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const ESTIMATE_CHARS_PER_TOKEN = 4;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Rough pre-call token **estimate** for a single string (`~chars/4`). For
|
|
163
|
+
* prompt-fit / rate-limit gating *before* a request exists — NOT a billing
|
|
164
|
+
* figure (the real count is returned by the provider on the response,
|
|
165
|
+
* `CompleteResult.usage`). ±15%; zero-dep; works in every runtime.
|
|
166
|
+
*/
|
|
167
|
+
export function estimateTokens(text: string): number {
|
|
168
|
+
if (!text) return 0;
|
|
169
|
+
return Math.ceil(text.length / ESTIMATE_CHARS_PER_TOKEN);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Rough pre-call token **estimate** for a `Message[]` history — sums text,
|
|
174
|
+
* tool-use input JSON, tool-result content, plus per-message and per-image
|
|
175
|
+
* overhead. ESTIMATE ONLY, for prompt-fit gating before the request exists;
|
|
176
|
+
* read the response `usage` for real counts. (This is the honest replacement
|
|
177
|
+
* for the deprecated `countMessageTokens`.)
|
|
178
|
+
*/
|
|
179
|
+
export function estimateMessageTokens(
|
|
180
|
+
messages: Message[],
|
|
181
|
+
opts: CountMessagesOptions = {},
|
|
182
|
+
): number {
|
|
183
|
+
const perMessage = opts.perMessageOverhead ?? DEFAULT_PER_MESSAGE_OVERHEAD;
|
|
184
|
+
const perImage = opts.perImageTokens ?? DEFAULT_PER_IMAGE_TOKENS;
|
|
185
|
+
let total = 0;
|
|
186
|
+
for (const msg of messages) {
|
|
187
|
+
total += perMessage;
|
|
188
|
+
if (typeof msg.content === "string") {
|
|
189
|
+
total += estimateTokens(msg.content);
|
|
190
|
+
} else {
|
|
191
|
+
for (const p of msg.content) {
|
|
192
|
+
switch (p.type) {
|
|
193
|
+
case "text":
|
|
194
|
+
total += estimateTokens(p.text);
|
|
195
|
+
break;
|
|
196
|
+
case "tool_use":
|
|
197
|
+
total += estimateTokens(p.name);
|
|
198
|
+
try {
|
|
199
|
+
total += estimateTokens(JSON.stringify(p.input ?? {}));
|
|
200
|
+
} catch {
|
|
201
|
+
total += 16;
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
case "tool_result":
|
|
205
|
+
total += estimateTokens(p.content);
|
|
206
|
+
break;
|
|
207
|
+
case "image":
|
|
208
|
+
total += perImage;
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (msg.name) total += estimateTokens(msg.name);
|
|
214
|
+
}
|
|
215
|
+
return total;
|
|
216
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ToolDefinition } from "../types.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `defineTool({ name, description, schema, handler })` — the load-bearing
|
|
6
|
+
* primitive the agent loop dispatches against. Pairs a Zod schema (the
|
|
7
|
+
* tool's input contract) with a typed handler that consumes the parsed
|
|
8
|
+
* input.
|
|
9
|
+
*
|
|
10
|
+
* Why a factory instead of a class:
|
|
11
|
+
* - The handler's input type is inferred from the Zod schema via
|
|
12
|
+
* `z.infer<typeof schema>`. A factory carries the inferred type
|
|
13
|
+
* through naturally; class generics force the consumer to repeat
|
|
14
|
+
* the inference.
|
|
15
|
+
* - The factory produces a `Tool` value that satisfies both the
|
|
16
|
+
* `ToolDefinition` shape (what providers see) and an `execute`
|
|
17
|
+
* surface (what the agent loop calls), without any inheritance
|
|
18
|
+
* ceremony.
|
|
19
|
+
* - `definition` is computed once at registration time — the
|
|
20
|
+
* `zodToJsonSchema` call doesn't run per-invocation.
|
|
21
|
+
*
|
|
22
|
+
* The handler receives the parsed input, plus a `ToolContext` carrying
|
|
23
|
+
* cancellation + caller metadata. Handlers MAY return any JSON-
|
|
24
|
+
* serializable value; the agent loop stringifies the result back into
|
|
25
|
+
* a `tool_result` content part. Throwing inside the handler short-
|
|
26
|
+
* circuits with `isError: true` (visible to the model) — the loop
|
|
27
|
+
* doesn't crash, it lets the model recover.
|
|
28
|
+
*
|
|
29
|
+
* Strictness: by default, schema parsing is strict (extra keys throw)
|
|
30
|
+
* to catch model output drift early. Pass `strict: false` to switch
|
|
31
|
+
* to lenient parsing if a provider tends to wrap or annotate fields.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
export interface ToolContext {
|
|
35
|
+
/** Caller-supplied abort signal. Honored by long-running handlers. */
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
/**
|
|
38
|
+
* Free-form caller metadata. The agent loop forwards what it was
|
|
39
|
+
* called with — typical contents: `{ requestId, userId }`.
|
|
40
|
+
*/
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type ToolHandler<TInput, TOutput = unknown> = (
|
|
45
|
+
input: TInput,
|
|
46
|
+
ctx: ToolContext,
|
|
47
|
+
) => TOutput | Promise<TOutput>;
|
|
48
|
+
|
|
49
|
+
export interface DefineToolOptions<TSchema extends z.ZodTypeAny, TOutput> {
|
|
50
|
+
/** Stable name. Models reference tools by name; keep it snake_case. */
|
|
51
|
+
name: string;
|
|
52
|
+
/**
|
|
53
|
+
* One-line description shown to the model. The model uses this to
|
|
54
|
+
* decide *when* to call the tool — make it precise. Bad: "Get data."
|
|
55
|
+
* Good: "Look up the current weather forecast for a single city."
|
|
56
|
+
*/
|
|
57
|
+
description: string;
|
|
58
|
+
/**
|
|
59
|
+
* Zod schema for the tool's input. Object schemas are strongly
|
|
60
|
+
* recommended (providers expect JSON Schema with `type: "object"`).
|
|
61
|
+
*/
|
|
62
|
+
schema: TSchema;
|
|
63
|
+
/**
|
|
64
|
+
* Receives the parsed input + a `ToolContext`. Return value is
|
|
65
|
+
* stringified back to the model as the tool result; throwing produces
|
|
66
|
+
* an `isError: true` tool_result the model can see and recover from.
|
|
67
|
+
*/
|
|
68
|
+
handler: ToolHandler<z.infer<TSchema>, TOutput>;
|
|
69
|
+
/**
|
|
70
|
+
* Strict parsing (extra keys throw). Default true — catches model
|
|
71
|
+
* output drift early. Set false for permissive providers.
|
|
72
|
+
*/
|
|
73
|
+
strict?: boolean;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface Tool<TSchema extends z.ZodTypeAny = z.ZodTypeAny, TOutput = unknown> {
|
|
77
|
+
name: string;
|
|
78
|
+
description: string;
|
|
79
|
+
schema: TSchema;
|
|
80
|
+
/** JSON Schema view used by `LLMProvider` adapters. Built once at registration. */
|
|
81
|
+
definition: ToolDefinition;
|
|
82
|
+
/**
|
|
83
|
+
* Run the tool with raw provider-supplied input. Validates against the
|
|
84
|
+
* Zod schema first; on validation failure returns `{ ok: false,
|
|
85
|
+
* isError: true, content }` with the Zod issue path so the model can
|
|
86
|
+
* see what was wrong.
|
|
87
|
+
*
|
|
88
|
+
* On handler success: `{ ok: true, output }` with the raw return
|
|
89
|
+
* value. The agent loop is responsible for serializing `output` for
|
|
90
|
+
* the `tool_result` content part.
|
|
91
|
+
*
|
|
92
|
+
* On handler throw: `{ ok: false, isError: true, content }` with the
|
|
93
|
+
* error message — *not* re-thrown, so the loop survives and the model
|
|
94
|
+
* can decide whether to retry.
|
|
95
|
+
*/
|
|
96
|
+
execute(input: unknown, ctx: ToolContext): Promise<ToolExecuteResult<TOutput>>;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export type ToolExecuteResult<TOutput> =
|
|
100
|
+
| { ok: true; output: TOutput }
|
|
101
|
+
| { ok: false; isError: true; content: string };
|
|
102
|
+
|
|
103
|
+
export function defineTool<TSchema extends z.ZodTypeAny, TOutput>(
|
|
104
|
+
opts: DefineToolOptions<TSchema, TOutput>,
|
|
105
|
+
): Tool<TSchema, TOutput> {
|
|
106
|
+
const inputSchema = z.toJSONSchema(opts.schema, {
|
|
107
|
+
target: "draft-2020-12",
|
|
108
|
+
}) as Record<string, unknown>;
|
|
109
|
+
// Strip the $schema header so providers (which don't expect it) accept the schema.
|
|
110
|
+
delete inputSchema["$schema"];
|
|
111
|
+
|
|
112
|
+
const definition: ToolDefinition = {
|
|
113
|
+
name: opts.name,
|
|
114
|
+
description: opts.description,
|
|
115
|
+
inputSchema,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const strict = opts.strict ?? true;
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
name: opts.name,
|
|
122
|
+
description: opts.description,
|
|
123
|
+
schema: opts.schema,
|
|
124
|
+
definition,
|
|
125
|
+
async execute(input: unknown, ctx: ToolContext): Promise<ToolExecuteResult<TOutput>> {
|
|
126
|
+
const parsed = strict ? opts.schema.safeParse(input) : opts.schema.safeParse(input ?? {});
|
|
127
|
+
if (!parsed.success) {
|
|
128
|
+
return {
|
|
129
|
+
ok: false,
|
|
130
|
+
isError: true,
|
|
131
|
+
content: formatZodIssues(parsed.error.issues),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
const output = await opts.handler(parsed.data as z.infer<TSchema>, ctx);
|
|
136
|
+
return { ok: true, output };
|
|
137
|
+
} catch (err) {
|
|
138
|
+
const message = err instanceof Error ? err.message : String(err ?? "unknown error");
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
isError: true,
|
|
142
|
+
content: `tool "${opts.name}" failed: ${message}`,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
interface ZodLikeIssue {
|
|
150
|
+
path?: Array<string | number>;
|
|
151
|
+
message: string;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function formatZodIssues(issues: readonly ZodLikeIssue[]): string {
|
|
155
|
+
if (!issues.length) return "validation failed";
|
|
156
|
+
return issues
|
|
157
|
+
.map((issue) => {
|
|
158
|
+
const path = (issue.path ?? []).join(".") || "(root)";
|
|
159
|
+
return `${path}: ${issue.message}`;
|
|
160
|
+
})
|
|
161
|
+
.join("; ");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* `ToolRegistry` — ordered map keyed by tool name, with lookup helpers
|
|
166
|
+
* the agent loop needs (`getDefinitions()` for the provider request,
|
|
167
|
+
* `lookup(name)` for dispatch). Constructible standalone (tests) or via
|
|
168
|
+
* the convenience `toolRegistry(...tools)` factory.
|
|
169
|
+
*/
|
|
170
|
+
export class ToolRegistry {
|
|
171
|
+
private readonly tools = new Map<string, Tool<z.ZodTypeAny, unknown>>();
|
|
172
|
+
|
|
173
|
+
constructor(tools: ReadonlyArray<Tool<z.ZodTypeAny, unknown>> = []) {
|
|
174
|
+
for (const tool of tools) this.add(tool);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
add(tool: Tool<z.ZodTypeAny, unknown>): void {
|
|
178
|
+
if (this.tools.has(tool.name)) {
|
|
179
|
+
throw new Error(`ToolRegistry: duplicate tool name "${tool.name}"`);
|
|
180
|
+
}
|
|
181
|
+
this.tools.set(tool.name, tool);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
has(name: string): boolean {
|
|
185
|
+
return this.tools.has(name);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
lookup(name: string): Tool<z.ZodTypeAny, unknown> | undefined {
|
|
189
|
+
return this.tools.get(name);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Tool definitions the agent loop attaches to provider requests. */
|
|
193
|
+
getDefinitions(): ToolDefinition[] {
|
|
194
|
+
return Array.from(this.tools.values()).map((t) => t.definition);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
size(): number {
|
|
198
|
+
return this.tools.size;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
list(): ReadonlyArray<Tool<z.ZodTypeAny, unknown>> {
|
|
202
|
+
return Array.from(this.tools.values());
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function toolRegistry(...tools: Array<Tool<z.ZodTypeAny, unknown>>): ToolRegistry {
|
|
207
|
+
return new ToolRegistry(tools);
|
|
208
|
+
}
|