@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,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ai",
|
|
3
|
+
"description": "LLM helper library — provider adapters (Anthropic, OpenAI), prompt registry, structured outputs, tool-calling, RAG, and an experimental agent loop. Pluggable LLMProvider interface; concrete adapters are opt-in (install only the SDK you use).",
|
|
4
|
+
"version": "0.2.0",
|
|
5
|
+
"dependencies": [],
|
|
6
|
+
"npmDependencies": {},
|
|
7
|
+
"optionalNpmDependencies": {
|
|
8
|
+
"@anthropic-ai/sdk": "^0.91.0",
|
|
9
|
+
"openai": "^6.0.0"
|
|
10
|
+
},
|
|
11
|
+
"requiredEnvVars": [],
|
|
12
|
+
"optionalEnvVars": ["ANTHROPIC_API_KEY", "OPENAI_API_KEY"],
|
|
13
|
+
"postInstall": [
|
|
14
|
+
"Install the SDK for the providers you need: `npm i @anthropic-ai/sdk` and/or `npm i openai`",
|
|
15
|
+
"Import { type LLMProvider } from '@sixthsummit/ship-api/libraries/ai' and the adapter you want (e.g. AnthropicAdapter)",
|
|
16
|
+
"Construct the adapter with your API key: `const llm = new AnthropicAdapter({ apiKey: env.ANTHROPIC_API_KEY })`",
|
|
17
|
+
"All adapters share the same `LLMProvider` interface — swap providers without changing call sites"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import type { LLMProvider } from "../adapters/LLMProvider.js";
|
|
2
|
+
import type { ToolContext, ToolRegistry } from "../tools/defineTool.js";
|
|
3
|
+
import type {
|
|
4
|
+
CompleteResult,
|
|
5
|
+
Message,
|
|
6
|
+
MessageContentPart,
|
|
7
|
+
StopReason,
|
|
8
|
+
TokenUsage,
|
|
9
|
+
ToolChoice,
|
|
10
|
+
ToolResultPart,
|
|
11
|
+
ToolUsePart,
|
|
12
|
+
} from "../types.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `agentLoop({ llm, tools, messages, ... })` — runs the model →
|
|
16
|
+
* tool-call → execute → continue cycle until the model returns
|
|
17
|
+
* `end_turn` (or `max_tokens` / `content_filter`), or until
|
|
18
|
+
* `maxIterations` is exceeded.
|
|
19
|
+
*
|
|
20
|
+
* Each iteration:
|
|
21
|
+
* 1. Call `llm.complete` with the running history + tool definitions.
|
|
22
|
+
* 2. If the response has `tool_use` content parts, execute each via
|
|
23
|
+
* the registry and append a `user` message containing the
|
|
24
|
+
* `tool_result` parts. Loop.
|
|
25
|
+
* 3. Otherwise, return — the model is done.
|
|
26
|
+
*
|
|
27
|
+
* The `assistant` message we append to history preserves *every*
|
|
28
|
+
* content part the model emitted (text + tool_use), in order, so the
|
|
29
|
+
* provider sees a faithful turn record on the next request — Anthropic
|
|
30
|
+
* (and OpenAI) require the assistant message to round-trip exactly so
|
|
31
|
+
* the tool_use IDs align with the matching tool_result.
|
|
32
|
+
*
|
|
33
|
+
* Errors:
|
|
34
|
+
* - Tool handlers that throw → captured as `isError: true`
|
|
35
|
+
* `tool_result` so the model can recover. The loop survives.
|
|
36
|
+
* - Tool not found in the registry → also captured as
|
|
37
|
+
* `isError: true` with a clear message; the model adapts.
|
|
38
|
+
* - `maxIterations` exceeded → throws `AgentLoopMaxIterationsError`
|
|
39
|
+
* with the partial history attached for debugging.
|
|
40
|
+
* - `signal` aborts → SDK rejects, the throw propagates out of the
|
|
41
|
+
* loop without further iteration.
|
|
42
|
+
*
|
|
43
|
+
* Observability hook: `onEvent(event)` fires synchronously for each
|
|
44
|
+
* lifecycle event. Consumers wire it to `streamSSE`, OTel spans,
|
|
45
|
+
* prompt-eval logs — anything that wants per-step visibility. Awaited
|
|
46
|
+
* if it returns a promise so callers can backpressure (e.g. SSE
|
|
47
|
+
* write).
|
|
48
|
+
*
|
|
49
|
+
* @experimental — AI-R2. NOT on the stable API surface; carries no semver
|
|
50
|
+
* stability promise and is expected to be superseded by MCP / provider-native
|
|
51
|
+
* agent runtimes. Import from `@sixthsummit/ship-api/libraries/ai/experimental`.
|
|
52
|
+
* Durable code should prefer `completeStructured` (single-shot) or call
|
|
53
|
+
* `llm.complete` directly.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
export interface AgentLoopOptions {
|
|
57
|
+
/** Provider that drives each iteration. */
|
|
58
|
+
llm: LLMProvider;
|
|
59
|
+
/** Tools the model can invoke. May be empty (degrades to plain `complete`). */
|
|
60
|
+
tools?: ToolRegistry;
|
|
61
|
+
/** Initial conversation history. The loop appends to a copy; the input is not mutated. */
|
|
62
|
+
messages: Message[];
|
|
63
|
+
/** Model identifier. Forwarded to `llm.complete` on every iteration. */
|
|
64
|
+
model: string;
|
|
65
|
+
/** Top-level system prompt. */
|
|
66
|
+
system?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Per-iteration `max_tokens` cap forwarded to `llm.complete`. Adapter
|
|
69
|
+
* defaults apply when omitted.
|
|
70
|
+
*/
|
|
71
|
+
maxTokens?: number;
|
|
72
|
+
/** Sampling temperature forwarded to `llm.complete`. */
|
|
73
|
+
temperature?: number;
|
|
74
|
+
/** Tool-choice override. Defaults to `{ type: "auto" }` when tools are present. */
|
|
75
|
+
toolChoice?: ToolChoice;
|
|
76
|
+
/**
|
|
77
|
+
* Provider-native passthrough forwarded to `llm.complete` on every
|
|
78
|
+
* iteration (e.g. prompt caching, extended thinking). Without it the
|
|
79
|
+
* seam's pass-through never reaches the adapter through the loop (AI-R1).
|
|
80
|
+
*/
|
|
81
|
+
providerOptions?: Record<string, unknown>;
|
|
82
|
+
/** Request-tagging forwarded to `llm.complete` for observability / cost tracking. */
|
|
83
|
+
metadata?: Record<string, string>;
|
|
84
|
+
/**
|
|
85
|
+
* Maximum number of model→tool→model round-trips. The loop throws
|
|
86
|
+
* `AgentLoopMaxIterationsError` if the model never returns
|
|
87
|
+
* `end_turn` within this budget. Default 10.
|
|
88
|
+
*/
|
|
89
|
+
maxIterations?: number;
|
|
90
|
+
/** Cancels in-flight provider requests + tool handlers. */
|
|
91
|
+
signal?: AbortSignal;
|
|
92
|
+
/**
|
|
93
|
+
* Forwarded to each tool handler's `ToolContext.metadata`. Typical
|
|
94
|
+
* contents: `{ requestId, userId, tenantId }`. Caller-defined.
|
|
95
|
+
*/
|
|
96
|
+
toolMetadata?: Record<string, unknown>;
|
|
97
|
+
/** Lifecycle hook — see `AgentEvent` for event shapes. */
|
|
98
|
+
onEvent?: (event: AgentEvent) => void | Promise<void>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export type AgentEvent =
|
|
102
|
+
| { type: "iteration_start"; iteration: number; messages: Message[] }
|
|
103
|
+
| { type: "model_response"; iteration: number; result: CompleteResult }
|
|
104
|
+
| {
|
|
105
|
+
type: "tool_call";
|
|
106
|
+
iteration: number;
|
|
107
|
+
toolUseId: string;
|
|
108
|
+
name: string;
|
|
109
|
+
input: Record<string, unknown>;
|
|
110
|
+
}
|
|
111
|
+
| {
|
|
112
|
+
type: "tool_result";
|
|
113
|
+
iteration: number;
|
|
114
|
+
toolUseId: string;
|
|
115
|
+
name: string;
|
|
116
|
+
ok: boolean;
|
|
117
|
+
output?: unknown;
|
|
118
|
+
error?: string;
|
|
119
|
+
}
|
|
120
|
+
| {
|
|
121
|
+
type: "iteration_end";
|
|
122
|
+
iteration: number;
|
|
123
|
+
stopReason: StopReason;
|
|
124
|
+
}
|
|
125
|
+
| {
|
|
126
|
+
type: "complete";
|
|
127
|
+
finalText: string;
|
|
128
|
+
iterations: number;
|
|
129
|
+
totalUsage: TokenUsage;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export interface AgentLoopResult {
|
|
133
|
+
/** The terminal `complete()` response — i.e. the one with `stopReason !== "tool_use"`. */
|
|
134
|
+
finalMessage: CompleteResult;
|
|
135
|
+
/** Convenience: the final assistant text (already on `finalMessage.text`). */
|
|
136
|
+
finalText: string;
|
|
137
|
+
/** Number of model calls made (≥ 1). */
|
|
138
|
+
iterations: number;
|
|
139
|
+
/** Sum of input + output tokens across every iteration. */
|
|
140
|
+
totalUsage: TokenUsage;
|
|
141
|
+
/**
|
|
142
|
+
* Full conversation history as the loop saw it after termination,
|
|
143
|
+
* including all tool_use + tool_result content parts. Useful for
|
|
144
|
+
* audit trails / tests.
|
|
145
|
+
*/
|
|
146
|
+
history: Message[];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export class AgentLoopError extends Error {
|
|
150
|
+
constructor(message: string) {
|
|
151
|
+
super(message);
|
|
152
|
+
this.name = "AgentLoopError";
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export class AgentLoopMaxIterationsError extends AgentLoopError {
|
|
157
|
+
constructor(
|
|
158
|
+
public readonly iterations: number,
|
|
159
|
+
public readonly history: Message[],
|
|
160
|
+
) {
|
|
161
|
+
super(`Agent loop exceeded maxIterations=${iterations} without reaching end_turn`);
|
|
162
|
+
this.name = "AgentLoopMaxIterationsError";
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const DEFAULT_MAX_ITERATIONS = 10;
|
|
167
|
+
|
|
168
|
+
export async function agentLoop(opts: AgentLoopOptions): Promise<AgentLoopResult> {
|
|
169
|
+
const maxIterations = opts.maxIterations ?? DEFAULT_MAX_ITERATIONS;
|
|
170
|
+
const tools = opts.tools;
|
|
171
|
+
const toolDefs = tools?.getDefinitions();
|
|
172
|
+
const toolChoice =
|
|
173
|
+
opts.toolChoice ?? (toolDefs && toolDefs.length > 0 ? { type: "auto" } : undefined);
|
|
174
|
+
const onEvent = opts.onEvent ?? (() => undefined);
|
|
175
|
+
|
|
176
|
+
const history: Message[] = [...opts.messages];
|
|
177
|
+
let totalUsage: TokenUsage = { inputTokens: 0, outputTokens: 0 };
|
|
178
|
+
|
|
179
|
+
for (let iteration = 1; iteration <= maxIterations; iteration++) {
|
|
180
|
+
if (opts.signal?.aborted) {
|
|
181
|
+
throw new AgentLoopError("Aborted before iteration " + iteration);
|
|
182
|
+
}
|
|
183
|
+
await onEvent({ type: "iteration_start", iteration, messages: history });
|
|
184
|
+
|
|
185
|
+
const result = await opts.llm.complete({
|
|
186
|
+
model: opts.model,
|
|
187
|
+
// Defensive copy: the loop mutates `history` post-call by
|
|
188
|
+
// appending the assistant turn + tool_results. Passing the live
|
|
189
|
+
// reference would leak that mutation back into adapter retry
|
|
190
|
+
// logic / test assertions on `mock.calls[].messages`.
|
|
191
|
+
messages: [...history],
|
|
192
|
+
system: opts.system,
|
|
193
|
+
maxTokens: opts.maxTokens,
|
|
194
|
+
temperature: opts.temperature,
|
|
195
|
+
tools: toolDefs && toolDefs.length > 0 ? toolDefs : undefined,
|
|
196
|
+
toolChoice,
|
|
197
|
+
signal: opts.signal,
|
|
198
|
+
providerOptions: opts.providerOptions,
|
|
199
|
+
metadata: opts.metadata,
|
|
200
|
+
});
|
|
201
|
+
totalUsage = accumulateUsage(totalUsage, result.usage);
|
|
202
|
+
await onEvent({ type: "model_response", iteration, result });
|
|
203
|
+
|
|
204
|
+
if (result.stopReason !== "tool_use") {
|
|
205
|
+
await onEvent({
|
|
206
|
+
type: "iteration_end",
|
|
207
|
+
iteration,
|
|
208
|
+
stopReason: result.stopReason,
|
|
209
|
+
});
|
|
210
|
+
// Persist the final assistant turn so the returned history is
|
|
211
|
+
// self-consistent (consumer can replay).
|
|
212
|
+
history.push({ role: "assistant", content: result.content });
|
|
213
|
+
await onEvent({
|
|
214
|
+
type: "complete",
|
|
215
|
+
finalText: result.text,
|
|
216
|
+
iterations: iteration,
|
|
217
|
+
totalUsage,
|
|
218
|
+
});
|
|
219
|
+
return {
|
|
220
|
+
finalMessage: result,
|
|
221
|
+
finalText: result.text,
|
|
222
|
+
iterations: iteration,
|
|
223
|
+
totalUsage,
|
|
224
|
+
history,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Round-trip the assistant turn verbatim so tool_use IDs align with
|
|
229
|
+
// the tool_result IDs the next user message carries.
|
|
230
|
+
history.push({ role: "assistant", content: result.content });
|
|
231
|
+
|
|
232
|
+
const toolUseParts = result.content.filter((p): p is ToolUsePart => p.type === "tool_use");
|
|
233
|
+
if (toolUseParts.length === 0) {
|
|
234
|
+
// Provider claimed `tool_use` but emitted no tool_use blocks —
|
|
235
|
+
// treat as terminal to avoid infinite loop.
|
|
236
|
+
await onEvent({
|
|
237
|
+
type: "iteration_end",
|
|
238
|
+
iteration,
|
|
239
|
+
stopReason: "unknown",
|
|
240
|
+
});
|
|
241
|
+
await onEvent({
|
|
242
|
+
type: "complete",
|
|
243
|
+
finalText: result.text,
|
|
244
|
+
iterations: iteration,
|
|
245
|
+
totalUsage,
|
|
246
|
+
});
|
|
247
|
+
return {
|
|
248
|
+
finalMessage: result,
|
|
249
|
+
finalText: result.text,
|
|
250
|
+
iterations: iteration,
|
|
251
|
+
totalUsage,
|
|
252
|
+
history,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const toolResults: ToolResultPart[] = [];
|
|
257
|
+
for (const tu of toolUseParts) {
|
|
258
|
+
await onEvent({
|
|
259
|
+
type: "tool_call",
|
|
260
|
+
iteration,
|
|
261
|
+
toolUseId: tu.id,
|
|
262
|
+
name: tu.name,
|
|
263
|
+
input: tu.input,
|
|
264
|
+
});
|
|
265
|
+
const tool = tools?.lookup(tu.name);
|
|
266
|
+
if (!tool) {
|
|
267
|
+
const error = `tool "${tu.name}" not registered`;
|
|
268
|
+
toolResults.push({
|
|
269
|
+
type: "tool_result",
|
|
270
|
+
toolUseId: tu.id,
|
|
271
|
+
content: error,
|
|
272
|
+
isError: true,
|
|
273
|
+
});
|
|
274
|
+
await onEvent({
|
|
275
|
+
type: "tool_result",
|
|
276
|
+
iteration,
|
|
277
|
+
toolUseId: tu.id,
|
|
278
|
+
name: tu.name,
|
|
279
|
+
ok: false,
|
|
280
|
+
error,
|
|
281
|
+
});
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
const ctx: ToolContext = {
|
|
285
|
+
signal: opts.signal,
|
|
286
|
+
metadata: opts.toolMetadata,
|
|
287
|
+
};
|
|
288
|
+
const exec = await tool.execute(tu.input, ctx);
|
|
289
|
+
if (exec.ok) {
|
|
290
|
+
toolResults.push({
|
|
291
|
+
type: "tool_result",
|
|
292
|
+
toolUseId: tu.id,
|
|
293
|
+
content: serializeToolOutput(exec.output),
|
|
294
|
+
});
|
|
295
|
+
await onEvent({
|
|
296
|
+
type: "tool_result",
|
|
297
|
+
iteration,
|
|
298
|
+
toolUseId: tu.id,
|
|
299
|
+
name: tu.name,
|
|
300
|
+
ok: true,
|
|
301
|
+
output: exec.output,
|
|
302
|
+
});
|
|
303
|
+
} else {
|
|
304
|
+
toolResults.push({
|
|
305
|
+
type: "tool_result",
|
|
306
|
+
toolUseId: tu.id,
|
|
307
|
+
content: exec.content,
|
|
308
|
+
isError: true,
|
|
309
|
+
});
|
|
310
|
+
await onEvent({
|
|
311
|
+
type: "tool_result",
|
|
312
|
+
iteration,
|
|
313
|
+
toolUseId: tu.id,
|
|
314
|
+
name: tu.name,
|
|
315
|
+
ok: false,
|
|
316
|
+
error: exec.content,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
history.push({ role: "user", content: toolResults });
|
|
322
|
+
await onEvent({
|
|
323
|
+
type: "iteration_end",
|
|
324
|
+
iteration,
|
|
325
|
+
stopReason: "tool_use",
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
throw new AgentLoopMaxIterationsError(maxIterations, history);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function accumulateUsage(a: TokenUsage, b: TokenUsage): TokenUsage {
|
|
333
|
+
return {
|
|
334
|
+
inputTokens: a.inputTokens + b.inputTokens,
|
|
335
|
+
outputTokens: a.outputTokens + b.outputTokens,
|
|
336
|
+
cacheReadInputTokens: sumOpt(a.cacheReadInputTokens, b.cacheReadInputTokens) ?? undefined,
|
|
337
|
+
cacheCreationInputTokens:
|
|
338
|
+
sumOpt(a.cacheCreationInputTokens, b.cacheCreationInputTokens) ?? undefined,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function sumOpt(a?: number, b?: number): number | undefined {
|
|
343
|
+
if (a === undefined && b === undefined) return undefined;
|
|
344
|
+
return (a ?? 0) + (b ?? 0);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function serializeToolOutput(output: unknown): string {
|
|
348
|
+
if (typeof output === "string") return output;
|
|
349
|
+
if (output === undefined || output === null) return "";
|
|
350
|
+
try {
|
|
351
|
+
return JSON.stringify(output);
|
|
352
|
+
} catch {
|
|
353
|
+
return String(output);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Helper for assertions / observability — flatten the assistant text
|
|
359
|
+
* across every iteration in the history. Useful when you want the
|
|
360
|
+
* model's full reasoning trace, not just the terminal response.
|
|
361
|
+
*/
|
|
362
|
+
export function collectAssistantText(history: Message[]): string[] {
|
|
363
|
+
const out: string[] = [];
|
|
364
|
+
for (const msg of history) {
|
|
365
|
+
if (msg.role !== "assistant") continue;
|
|
366
|
+
if (typeof msg.content === "string") {
|
|
367
|
+
out.push(msg.content);
|
|
368
|
+
} else {
|
|
369
|
+
const text = (msg.content as MessageContentPart[])
|
|
370
|
+
.filter((p): p is { type: "text"; text: string } => p.type === "text")
|
|
371
|
+
.map((p) => p.text)
|
|
372
|
+
.join("");
|
|
373
|
+
if (text) out.push(text);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return out;
|
|
377
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import type { LLMProvider } from "../adapters/LLMProvider.js";
|
|
2
|
+
import { definePrompt, type Prompt } from "../prompts/definePrompt.js";
|
|
3
|
+
import type { CompleteResult, Message } from "../types.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `retrieveAndAnswer({ llm, vectorStore, query, ... })` — RAG pipeline
|
|
7
|
+
* primitive per plan §G. Retrieves the top-k relevant documents from a
|
|
8
|
+
* `VectorStore`, formats them into a context block, and asks the
|
|
9
|
+
* `LLMProvider` to answer the query grounded in those documents.
|
|
10
|
+
*
|
|
11
|
+
* Pluggable on both axes:
|
|
12
|
+
* - `LLMProvider` is the cross-provider interface from
|
|
13
|
+
* `adapters/LLMProvider.ts` — Anthropic / OpenAI / future
|
|
14
|
+
* adapters all work identically.
|
|
15
|
+
* - `VectorStore` is a structural interface defined here. The
|
|
16
|
+
* library deliberately takes no dep on `libraries/weaviate` or
|
|
17
|
+
* any specific store — consumers pass their own implementation
|
|
18
|
+
* (Weaviate, Pinecone, in-memory, Postgres pgvector, …). Keeping
|
|
19
|
+
* the dep narrow means the RAG helper is usable with any
|
|
20
|
+
* retrieval backend the consumer happens to have.
|
|
21
|
+
*
|
|
22
|
+
* The prompt is overridable: callers can pass their own
|
|
23
|
+
* `Prompt<{ query, documents }>` to swap the template (e.g., domain-
|
|
24
|
+
* specific framing, multi-language). The default produces the
|
|
25
|
+
* standard "answer the question using only the documents below"
|
|
26
|
+
* template most RAG flows want.
|
|
27
|
+
*
|
|
28
|
+
* Output shape: `{ answer, sources, raw }`. `sources` is the original
|
|
29
|
+
* `RetrievedDocument[]` (id + score + metadata), so callers can
|
|
30
|
+
* surface citations in their UI without re-querying.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
export interface RetrievedDocument {
|
|
34
|
+
/** Stable identifier — surfaced as a citation marker in the prompt. */
|
|
35
|
+
id: string;
|
|
36
|
+
/** The text the model sees. */
|
|
37
|
+
text: string;
|
|
38
|
+
/** Similarity / relevance score from the store. Higher is better. */
|
|
39
|
+
score: number;
|
|
40
|
+
/** Free-form metadata (source URL, author, timestamp, …). */
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface VectorStoreSearchOptions {
|
|
45
|
+
query: string;
|
|
46
|
+
/** Caller-defined ceiling on retrieved document count. */
|
|
47
|
+
topK: number;
|
|
48
|
+
/**
|
|
49
|
+
* Optional store-specific filter (e.g. tenant scoping). Pass
|
|
50
|
+
* unchanged to the underlying store.
|
|
51
|
+
*/
|
|
52
|
+
filter?: Record<string, unknown>;
|
|
53
|
+
signal?: AbortSignal;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface VectorStore {
|
|
57
|
+
/** Stable identifier ("weaviate", "pinecone", "pgvector", …). */
|
|
58
|
+
readonly name: string;
|
|
59
|
+
/** Retrieve the top-k most relevant documents for the given query. */
|
|
60
|
+
search(opts: VectorStoreSearchOptions): Promise<RetrievedDocument[]>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface RetrieveAndAnswerOptions {
|
|
64
|
+
/** Provider that produces the final answer. */
|
|
65
|
+
llm: LLMProvider;
|
|
66
|
+
/** Vector store to query. */
|
|
67
|
+
vectorStore: VectorStore;
|
|
68
|
+
/** The user question. */
|
|
69
|
+
query: string;
|
|
70
|
+
/** Top-k documents to retrieve. Default 5. */
|
|
71
|
+
topK?: number;
|
|
72
|
+
/** Model id forwarded to `llm.complete`. */
|
|
73
|
+
model: string;
|
|
74
|
+
/**
|
|
75
|
+
* Top-level system prompt. Defaults to a faithful-attribution
|
|
76
|
+
* instruction; override to add tone / domain framing.
|
|
77
|
+
*/
|
|
78
|
+
systemPrompt?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Override the prompt template. Receives `{ query, documents }`
|
|
81
|
+
* (`documents` is the formatted context block). Defaults to the
|
|
82
|
+
* built-in `RAG_DEFAULT_PROMPT`.
|
|
83
|
+
*/
|
|
84
|
+
promptTemplate?: Prompt<{ query: string; documents: string }>;
|
|
85
|
+
/**
|
|
86
|
+
* Filter forwarded to `vectorStore.search` — store-specific
|
|
87
|
+
* (tenant scoping, time range, …).
|
|
88
|
+
*/
|
|
89
|
+
filter?: Record<string, unknown>;
|
|
90
|
+
/**
|
|
91
|
+
* Per-document context formatter. Defaults to numbered citation
|
|
92
|
+
* markers (`[1]`, `[2]`, …) that the model can cite back. Pass a
|
|
93
|
+
* custom formatter for richer formatting (markdown headers,
|
|
94
|
+
* metadata interpolation, …).
|
|
95
|
+
*/
|
|
96
|
+
formatDocument?: (doc: RetrievedDocument, index: number) => string;
|
|
97
|
+
maxTokens?: number;
|
|
98
|
+
temperature?: number;
|
|
99
|
+
signal?: AbortSignal;
|
|
100
|
+
/**
|
|
101
|
+
* Provider-native passthrough forwarded to `llm.complete` (e.g. prompt
|
|
102
|
+
* caching for the system prompt / documents). Without it the seam's
|
|
103
|
+
* pass-through never reaches the adapter through RAG (AI-R1).
|
|
104
|
+
*/
|
|
105
|
+
providerOptions?: Record<string, unknown>;
|
|
106
|
+
/** Request-tagging forwarded to `llm.complete` for observability / cost tracking. */
|
|
107
|
+
metadata?: Record<string, string>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface RetrieveAndAnswerResult {
|
|
111
|
+
/** The model's answer text (joined `text` content parts). */
|
|
112
|
+
answer: string;
|
|
113
|
+
/** Documents the answer was grounded in, in retrieval order. */
|
|
114
|
+
sources: RetrievedDocument[];
|
|
115
|
+
/** The raw provider response (id / model / usage / etc.). */
|
|
116
|
+
raw: CompleteResult;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const DEFAULT_TOP_K = 5;
|
|
120
|
+
const DEFAULT_SYSTEM_PROMPT =
|
|
121
|
+
"You are a careful assistant. Answer the user's question using only the documents provided. If the documents don't contain the answer, say so explicitly. Cite document numbers (e.g. [1], [2]) for any claim sourced from a document.";
|
|
122
|
+
|
|
123
|
+
export const RAG_DEFAULT_PROMPT = definePrompt({
|
|
124
|
+
id: "ship-api.rag.retrieve_and_answer",
|
|
125
|
+
version: 1,
|
|
126
|
+
template:
|
|
127
|
+
"Question:\n{{query}}\n\nDocuments:\n{{documents}}\n\nAnswer the question using only the documents above. Cite document numbers in square brackets for each claim sourced from a document.",
|
|
128
|
+
description: "Default RAG prompt — grounded answer with citations.",
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
export async function retrieveAndAnswer(
|
|
132
|
+
opts: RetrieveAndAnswerOptions,
|
|
133
|
+
): Promise<RetrieveAndAnswerResult> {
|
|
134
|
+
const topK = opts.topK ?? DEFAULT_TOP_K;
|
|
135
|
+
const formatDocument = opts.formatDocument ?? defaultDocumentFormatter;
|
|
136
|
+
const promptTemplate = opts.promptTemplate ?? RAG_DEFAULT_PROMPT;
|
|
137
|
+
|
|
138
|
+
const sources = await opts.vectorStore.search({
|
|
139
|
+
query: opts.query,
|
|
140
|
+
topK,
|
|
141
|
+
filter: opts.filter,
|
|
142
|
+
signal: opts.signal,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const documentsBlock = sources.map((doc, i) => formatDocument(doc, i)).join("\n\n");
|
|
146
|
+
|
|
147
|
+
const userPrompt = promptTemplate.render({
|
|
148
|
+
query: opts.query,
|
|
149
|
+
documents:
|
|
150
|
+
sources.length === 0
|
|
151
|
+
? "(no documents retrieved — answer should explicitly say no source material was available)"
|
|
152
|
+
: documentsBlock,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const messages: Message[] = [{ role: "user", content: userPrompt }];
|
|
156
|
+
|
|
157
|
+
const raw = await opts.llm.complete({
|
|
158
|
+
model: opts.model,
|
|
159
|
+
messages,
|
|
160
|
+
system: opts.systemPrompt ?? DEFAULT_SYSTEM_PROMPT,
|
|
161
|
+
maxTokens: opts.maxTokens,
|
|
162
|
+
temperature: opts.temperature,
|
|
163
|
+
signal: opts.signal,
|
|
164
|
+
providerOptions: opts.providerOptions,
|
|
165
|
+
metadata: opts.metadata,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
answer: raw.text,
|
|
170
|
+
sources,
|
|
171
|
+
raw,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function defaultDocumentFormatter(doc: RetrievedDocument, index: number): string {
|
|
176
|
+
return `[${index + 1}] (${doc.id}) ${doc.text}`;
|
|
177
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { StreamEvent } from "../types.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Structural view of the kernel stream seam handed to streaming operation
|
|
5
|
+
* handlers (`OperationStream` from `@sixthsummit/ship-core`). Declared here so
|
|
6
|
+
* the library keeps zero runtime or type dependencies on the kernel package.
|
|
7
|
+
*/
|
|
8
|
+
export interface LLMFrameStream<TFrame> {
|
|
9
|
+
readonly emit: (frame: TFrame) => Promise<void>;
|
|
10
|
+
readonly signal: AbortSignal;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Minimum shape `streamLLM` requires: a string `type` plus JSON-serializable
|
|
15
|
+
* fields. The full `StreamEvent` union from this library fits.
|
|
16
|
+
*/
|
|
17
|
+
export interface LLMStreamFrame {
|
|
18
|
+
readonly type: string;
|
|
19
|
+
readonly [key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface StreamLLMOptions<TFrame extends LLMStreamFrame> {
|
|
23
|
+
/**
|
|
24
|
+
* Called once if the provider iterator throws, before the error propagates
|
|
25
|
+
* to the kernel (which delivers it as a terminal `error` frame). Throwing
|
|
26
|
+
* here is swallowed so the propagation still completes.
|
|
27
|
+
*/
|
|
28
|
+
readonly onError?: (error: Error) => Promise<void> | void;
|
|
29
|
+
/**
|
|
30
|
+
* Maps a provider event onto the operation's declared frame. Defaults to
|
|
31
|
+
* passing the event through unchanged.
|
|
32
|
+
*/
|
|
33
|
+
readonly toFrame?: (event: StreamEvent | LLMStreamFrame, index: number) => TFrame;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface StreamLLMResult {
|
|
37
|
+
/** Number of frames handed to `emit`. */
|
|
38
|
+
readonly frames: number;
|
|
39
|
+
/** True when the run stopped early because the operation signal aborted. */
|
|
40
|
+
readonly aborted: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* `streamLLM(stream, events, options?)` — pipes an LLM provider stream
|
|
45
|
+
* (typically `LLMProvider.streamComplete()`) through the kernel stream seam.
|
|
46
|
+
* Each provider event becomes one validated frame; cancellation flows from the
|
|
47
|
+
* operation's `AbortSignal` back into the provider iterator via `return()`.
|
|
48
|
+
*
|
|
49
|
+
* This is the operation-kernel counterpart of the compatibility
|
|
50
|
+
* `streamLLM(c, events)` Hono helper in `@sixthsummit/ship-api`, whose SSE
|
|
51
|
+
* layout (`event: <type>`) is unchanged. Under the kernel the frame is the
|
|
52
|
+
* whole event object and the SSE event name is always `frame`.
|
|
53
|
+
*
|
|
54
|
+
* Usage:
|
|
55
|
+
* ```ts
|
|
56
|
+
* handler: async ({ input, services, stream }) => {
|
|
57
|
+
* const events = services.llm.streamComplete({ model, messages, signal: stream.signal });
|
|
58
|
+
* const { frames } = await streamLLM(stream, events);
|
|
59
|
+
* return { frames };
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export async function streamLLM<TFrame extends LLMStreamFrame = StreamEvent>(
|
|
64
|
+
stream: LLMFrameStream<TFrame>,
|
|
65
|
+
events: AsyncIterable<StreamEvent | LLMStreamFrame>,
|
|
66
|
+
options: StreamLLMOptions<TFrame> = {},
|
|
67
|
+
): Promise<StreamLLMResult> {
|
|
68
|
+
const toFrame = options.toFrame ?? ((event) => event as TFrame);
|
|
69
|
+
const iterator = events[Symbol.asyncIterator]();
|
|
70
|
+
let frames = 0;
|
|
71
|
+
try {
|
|
72
|
+
while (true) {
|
|
73
|
+
if (stream.signal.aborted) {
|
|
74
|
+
await iterator.return?.();
|
|
75
|
+
return { frames, aborted: true };
|
|
76
|
+
}
|
|
77
|
+
const next = await iterator.next();
|
|
78
|
+
if (next.done) return { frames, aborted: false };
|
|
79
|
+
await stream.emit(toFrame(next.value, frames));
|
|
80
|
+
frames += 1;
|
|
81
|
+
}
|
|
82
|
+
} catch (caught) {
|
|
83
|
+
const error = caught instanceof Error ? caught : new Error(String(caught));
|
|
84
|
+
if (options.onError) {
|
|
85
|
+
try {
|
|
86
|
+
await options.onError(error);
|
|
87
|
+
} catch {
|
|
88
|
+
// The hook must not mask the original failure.
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
await iterator.return?.().catch(() => undefined);
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|