diff --git a/apps/api/src/api-v1/consumers/admin-activate-consumer.ts b/apps/api/src/api-v1/consumers/admin-activate-consumer.ts index 53d60ba2..0141d520 100644 --- a/apps/api/src/api-v1/consumers/admin-activate-consumer.ts +++ b/apps/api/src/api-v1/consumers/admin-activate-consumer.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseConsumerAdminSelectSchema } from '@/db/schema' import { aclAdmin } from '@/lib/acl-admin' import { openapiAuthenticatedSecuritySchemas, @@ -57,6 +58,6 @@ export function registerV1AdminActivateConsumer( assert(consumer, 404, `Consumer not found "${consumerId}"`) setAdminCacheControlForConsumer(c, consumer) - return c.json(parseZodSchema(schema.consumerAdminSelectSchema, consumer)) + return c.json(parseConsumerAdminSelectSchema(consumer)) }) } diff --git a/apps/api/src/api-v1/consumers/admin-get-consumer-by-token.ts b/apps/api/src/api-v1/consumers/admin-get-consumer-by-token.ts index ee8bf763..a517a7c1 100644 --- a/apps/api/src/api-v1/consumers/admin-get-consumer-by-token.ts +++ b/apps/api/src/api-v1/consumers/admin-get-consumer-by-token.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseConsumerAdminSelectSchema } from '@/db/schema' import { aclAdmin } from '@/lib/acl-admin' import { openapiAuthenticatedSecuritySchemas, @@ -55,6 +56,6 @@ export function registerV1AdminGetConsumerByToken( assert(consumer, 404, `API token not found "${token}"`) setAdminCacheControlForConsumer(c, consumer) - return c.json(parseZodSchema(schema.consumerAdminSelectSchema, consumer)) + return c.json(parseConsumerAdminSelectSchema(consumer)) }) } diff --git a/apps/api/src/api-v1/consumers/create-consumer-checkout-session.ts b/apps/api/src/api-v1/consumers/create-consumer-checkout-session.ts index 2bb41e71..8503e955 100644 --- a/apps/api/src/api-v1/consumers/create-consumer-checkout-session.ts +++ b/apps/api/src/api-v1/consumers/create-consumer-checkout-session.ts @@ -1,8 +1,9 @@ -import { parseZodSchema, pick } from '@agentic/platform-core' +import { pick } from '@agentic/platform-core' import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { schema } from '@/db' +import { parseConsumerSelectSchema } from '@/db/schema' import { upsertConsumerStripeCheckout } from '@/lib/consumers/upsert-consumer-stripe-checkout' import { openapiAuthenticatedSecuritySchemas, @@ -64,7 +65,7 @@ export function registerV1CreateConsumerCheckoutSession( return c.json({ checkoutSession: pick(checkoutSession, 'id', 'url'), - consumer: parseZodSchema(schema.consumerSelectSchema, consumer) + consumer: parseConsumerSelectSchema(consumer) }) }) } diff --git a/apps/api/src/api-v1/consumers/create-consumer.ts b/apps/api/src/api-v1/consumers/create-consumer.ts index ee00933c..92660de0 100644 --- a/apps/api/src/api-v1/consumers/create-consumer.ts +++ b/apps/api/src/api-v1/consumers/create-consumer.ts @@ -1,8 +1,8 @@ -import { parseZodSchema } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { schema } from '@/db' +import { parseConsumerSelectSchema } from '@/db/schema' import { upsertConsumer } from '@/lib/consumers/upsert-consumer' import { openapiAuthenticatedSecuritySchemas, @@ -53,6 +53,6 @@ export function registerV1CreateConsumer( const body = c.req.valid('json') const consumer = await upsertConsumer(c, body) - return c.json(parseZodSchema(schema.consumerSelectSchema, consumer)) + return c.json(parseConsumerSelectSchema(consumer)) }) } diff --git a/apps/api/src/api-v1/consumers/get-consumer-by-project-identifier.ts b/apps/api/src/api-v1/consumers/get-consumer-by-project-identifier.ts index 220a578a..71d6f553 100644 --- a/apps/api/src/api-v1/consumers/get-consumer-by-project-identifier.ts +++ b/apps/api/src/api-v1/consumers/get-consumer-by-project-identifier.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { and, db, eq, schema } from '@/db' +import { parseConsumerSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { aclPublicProject } from '@/lib/acl-public-project' import { @@ -49,7 +50,7 @@ export function registerV1GetConsumerByProjectIdentifier( where: eq(schema.projects.identifier, projectIdentifier) }) assert(project, 404, `Project not found "${projectIdentifier}"`) - await aclPublicProject(project) + aclPublicProject(project) const consumer = await db.query.consumers.findFirst({ where: and( @@ -67,6 +68,6 @@ export function registerV1GetConsumerByProjectIdentifier( ) await acl(c, consumer, { label: 'Consumer' }) - return c.json(parseZodSchema(schema.consumerSelectSchema, consumer)) + return c.json(parseConsumerSelectSchema(consumer)) }) } diff --git a/apps/api/src/api-v1/consumers/get-consumer.ts b/apps/api/src/api-v1/consumers/get-consumer.ts index d799956d..eaa8ce84 100644 --- a/apps/api/src/api-v1/consumers/get-consumer.ts +++ b/apps/api/src/api-v1/consumers/get-consumer.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseConsumerSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { openapiAuthenticatedSecuritySchemas, @@ -51,6 +52,6 @@ export function registerV1GetConsumer(app: OpenAPIHono) { assert(consumer, 404, `Consumer not found "${consumerId}"`) await acl(c, consumer, { label: 'Consumer' }) - return c.json(parseZodSchema(schema.consumerSelectSchema, consumer)) + return c.json(parseConsumerSelectSchema(consumer)) }) } diff --git a/apps/api/src/api-v1/consumers/list-consumers.ts b/apps/api/src/api-v1/consumers/list-consumers.ts index 092efffa..0c78db59 100644 --- a/apps/api/src/api-v1/consumers/list-consumers.ts +++ b/apps/api/src/api-v1/consumers/list-consumers.ts @@ -1,8 +1,8 @@ -import { parseZodSchema } from '@agentic/platform-core' import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseConsumerSelectArraySchema } from '@/db/schema' import { ensureAuthUser } from '@/lib/ensure-auth-user' import { openapiAuthenticatedSecuritySchemas, @@ -62,8 +62,6 @@ export function registerV1ListConsumers( limit }) - return c.json( - parseZodSchema(z.array(schema.consumerSelectSchema), consumers) - ) + return c.json(parseConsumerSelectArraySchema(consumers)) }) } diff --git a/apps/api/src/api-v1/consumers/list-project-consumers.ts b/apps/api/src/api-v1/consumers/list-project-consumers.ts index 1b3bef47..4d74788d 100644 --- a/apps/api/src/api-v1/consumers/list-project-consumers.ts +++ b/apps/api/src/api-v1/consumers/list-project-consumers.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseConsumerSelectArraySchema } from '@/db/schema' import { acl } from '@/lib/acl' import { openapiAuthenticatedSecuritySchemas, @@ -71,8 +72,6 @@ export function registerV1ListConsumersForProject( limit }) - return c.json( - parseZodSchema(z.array(schema.consumerSelectSchema), consumers) - ) + return c.json(parseConsumerSelectArraySchema(consumers)) }) } diff --git a/apps/api/src/api-v1/consumers/refresh-consumer-token.ts b/apps/api/src/api-v1/consumers/refresh-consumer-token.ts index f5eb66a3..e4dbfbed 100644 --- a/apps/api/src/api-v1/consumers/refresh-consumer-token.ts +++ b/apps/api/src/api-v1/consumers/refresh-consumer-token.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseConsumerSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { createConsumerToken } from '@/lib/create-consumer-token' import { @@ -59,6 +60,6 @@ export function registerV1RefreshConsumerToken( .returning() assert(consumer, 500, 'Error updating consumer') - return c.json(parseZodSchema(schema.consumerSelectSchema, consumer)) + return c.json(parseConsumerSelectSchema(consumer)) }) } diff --git a/apps/api/src/api-v1/consumers/update-consumer.ts b/apps/api/src/api-v1/consumers/update-consumer.ts index 9a11e49f..d0293399 100644 --- a/apps/api/src/api-v1/consumers/update-consumer.ts +++ b/apps/api/src/api-v1/consumers/update-consumer.ts @@ -1,8 +1,8 @@ -import { parseZodSchema } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { schema } from '@/db' +import { parseConsumerSelectSchema } from '@/db/schema' import { upsertConsumer } from '@/lib/consumers/upsert-consumer' import { openapiAuthenticatedSecuritySchemas, @@ -61,6 +61,6 @@ export function registerV1UpdateConsumer( consumerId }) - return c.json(parseZodSchema(schema.consumerSelectSchema, consumer)) + return c.json(parseConsumerSelectSchema(consumer)) }) } diff --git a/apps/api/src/api-v1/consumers/utils.ts b/apps/api/src/api-v1/consumers/utils.ts index 3465164e..ab509b66 100644 --- a/apps/api/src/api-v1/consumers/utils.ts +++ b/apps/api/src/api-v1/consumers/utils.ts @@ -1,10 +1,10 @@ -import type { Consumer } from '@/db' +import type { RawConsumer } from '@/db' import type { AuthenticatedHonoContext } from '@/lib/types' import { setPublicCacheControl } from '@/lib/cache-control' export function setAdminCacheControlForConsumer( c: AuthenticatedHonoContext, - consumer: Consumer + consumer: RawConsumer ) { if ( consumer.plan === 'free' || diff --git a/apps/api/src/api-v1/deployments/admin-get-deployment-by-identifier.ts b/apps/api/src/api-v1/deployments/admin-get-deployment-by-identifier.ts index c8f50352..8ed2b597 100644 --- a/apps/api/src/api-v1/deployments/admin-get-deployment-by-identifier.ts +++ b/apps/api/src/api-v1/deployments/admin-get-deployment-by-identifier.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { schema } from '@/db' +import { parseDeploymentAdminSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { aclAdmin } from '@/lib/acl-admin' import { tryGetDeploymentByIdentifier } from '@/lib/deployments/try-get-deployment-by-identifier' @@ -67,7 +68,7 @@ export function registerV1AdminGetDeploymentByIdentifier( const hasPopulateProject = populate.includes('project') return c.json( - parseZodSchema(schema.deploymentAdminSelectSchema, { + parseDeploymentAdminSelectSchema({ ...deployment, ...(hasPopulateProject ? { project } : {}), _secret: project._secret diff --git a/apps/api/src/api-v1/deployments/create-deployment.ts b/apps/api/src/api-v1/deployments/create-deployment.ts index 91fd2da1..d7e654de 100644 --- a/apps/api/src/api-v1/deployments/create-deployment.ts +++ b/apps/api/src/api-v1/deployments/create-deployment.ts @@ -1,5 +1,5 @@ import { resolveAgenticProjectConfig } from '@agentic/platform' -import { assert, parseZodSchema, sha256, slugify } from '@agentic/platform-core' +import { assert, sha256, slugify } from '@agentic/platform-core' import { isValidDeploymentIdentifier, parseProjectIdentifier @@ -8,6 +8,7 @@ import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseDeploymentSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { normalizeDeploymentVersion } from '@/lib/deployments/normalize-deployment-version' import { publishDeployment } from '@/lib/deployments/publish-deployment' @@ -189,6 +190,6 @@ export function registerV1CreateDeployment( }) } - return c.json(parseZodSchema(schema.deploymentSelectSchema, deployment)) + return c.json(parseDeploymentSelectSchema(deployment)) }) } diff --git a/apps/api/src/api-v1/deployments/get-deployment-by-identifier.ts b/apps/api/src/api-v1/deployments/get-deployment-by-identifier.ts index bd06cc78..32fc3477 100644 --- a/apps/api/src/api-v1/deployments/get-deployment-by-identifier.ts +++ b/apps/api/src/api-v1/deployments/get-deployment-by-identifier.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { schema } from '@/db' +import { parseDeploymentSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { tryGetDeploymentByIdentifier } from '@/lib/deployments/try-get-deployment-by-identifier' import { @@ -53,6 +54,6 @@ export function registerV1GetDeploymentByIdentifier( assert(deployment, 404, `Deployment not found "${deploymentIdentifier}"`) await acl(c, deployment, { label: 'Deployment' }) - return c.json(parseZodSchema(schema.deploymentSelectSchema, deployment)) + return c.json(parseDeploymentSelectSchema(deployment)) }) } diff --git a/apps/api/src/api-v1/deployments/get-deployment.ts b/apps/api/src/api-v1/deployments/get-deployment.ts index 7899c71c..2e111a0b 100644 --- a/apps/api/src/api-v1/deployments/get-deployment.ts +++ b/apps/api/src/api-v1/deployments/get-deployment.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { schema } from '@/db' +import { parseDeploymentSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { getDeploymentById } from '@/lib/deployments/get-deployment-by-id' import { @@ -54,6 +55,6 @@ export function registerV1GetDeployment( assert(deployment, 404, `Deployment not found "${deploymentId}"`) await acl(c, deployment, { label: 'Deployment' }) - return c.json(parseZodSchema(schema.deploymentSelectSchema, deployment)) + return c.json(parseDeploymentSelectSchema(deployment)) }) } diff --git a/apps/api/src/api-v1/deployments/get-public-deployment-by-identifier.ts b/apps/api/src/api-v1/deployments/get-public-deployment-by-identifier.ts index 9b77020e..ab89ac8f 100644 --- a/apps/api/src/api-v1/deployments/get-public-deployment-by-identifier.ts +++ b/apps/api/src/api-v1/deployments/get-public-deployment-by-identifier.ts @@ -1,8 +1,9 @@ import type { DefaultHonoEnv } from '@agentic/platform-hono' -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import { schema } from '@/db' +import { parseDeploymentSelectSchema } from '@/db/schema' import { aclPublicProject } from '@/lib/acl-public-project' import { tryGetDeploymentByIdentifier } from '@/lib/deployments/try-get-deployment-by-identifier' import { @@ -57,8 +58,8 @@ export function registerV1GetPublicDeploymentByIdentifier( 404, `Project not found for deployment "${deploymentIdentifier}"` ) - await aclPublicProject(deployment.project!) + aclPublicProject(deployment.project!) - return c.json(parseZodSchema(schema.deploymentSelectSchema, deployment)) + return c.json(parseDeploymentSelectSchema(deployment)) }) } diff --git a/apps/api/src/api-v1/deployments/list-deployments.ts b/apps/api/src/api-v1/deployments/list-deployments.ts index b5868fb9..d7ab6867 100644 --- a/apps/api/src/api-v1/deployments/list-deployments.ts +++ b/apps/api/src/api-v1/deployments/list-deployments.ts @@ -1,8 +1,8 @@ -import { parseZodSchema } from '@agentic/platform-core' import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { and, db, eq, schema } from '@/db' +import { parseDeploymentSelectArraySchema } from '@/db/schema' import { acl } from '@/lib/acl' import { ensureAuthUser } from '@/lib/ensure-auth-user' import { @@ -88,8 +88,6 @@ export function registerV1ListDeployments( limit }) - return c.json( - parseZodSchema(z.array(schema.deploymentSelectSchema), deployments) - ) + return c.json(parseDeploymentSelectArraySchema(deployments)) }) } diff --git a/apps/api/src/api-v1/deployments/publish-deployment.ts b/apps/api/src/api-v1/deployments/publish-deployment.ts index 173e86dd..912515eb 100644 --- a/apps/api/src/api-v1/deployments/publish-deployment.ts +++ b/apps/api/src/api-v1/deployments/publish-deployment.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { schema } from '@/db' +import { parseDeploymentSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { getDeploymentById } from '@/lib/deployments/get-deployment-by-id' import { publishDeployment } from '@/lib/deployments/publish-deployment' @@ -63,8 +64,6 @@ export function registerV1PublishDeployment( version }) - return c.json( - parseZodSchema(schema.deploymentSelectSchema, publishedDeployment) - ) + return c.json(parseDeploymentSelectSchema(publishedDeployment)) }) } diff --git a/apps/api/src/api-v1/deployments/update-deployment.ts b/apps/api/src/api-v1/deployments/update-deployment.ts index dfc67079..dd979969 100644 --- a/apps/api/src/api-v1/deployments/update-deployment.ts +++ b/apps/api/src/api-v1/deployments/update-deployment.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseDeploymentSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { getDeploymentById } from '@/lib/deployments/get-deployment-by-id' import { @@ -65,6 +66,6 @@ export function registerV1UpdateDeployment( .returning() assert(deployment, 500, `Failed to update deployment "${deploymentId}"`) - return c.json(parseZodSchema(schema.deploymentSelectSchema, deployment)) + return c.json(parseDeploymentSelectSchema(deployment)) }) } diff --git a/apps/api/src/api-v1/projects/create-project.ts b/apps/api/src/api-v1/projects/create-project.ts index 3903d9b7..8420f605 100644 --- a/apps/api/src/api-v1/projects/create-project.ts +++ b/apps/api/src/api-v1/projects/create-project.ts @@ -1,9 +1,10 @@ -import { assert, parseZodSchema, sha256 } from '@agentic/platform-core' +import { assert, sha256 } from '@agentic/platform-core' import { parseProjectIdentifier } from '@agentic/platform-validators' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, schema } from '@/db' +import { parseProjectSelectSchema } from '@/db/schema' import { ensureAuthUser } from '@/lib/ensure-auth-user' import { env } from '@/lib/env' import { @@ -86,6 +87,6 @@ export function registerV1CreateProject( .returning() assert(project, 500, `Failed to create project "${body.name}"`) - return c.json(parseZodSchema(schema.projectSelectSchema, project)) + return c.json(parseProjectSelectSchema(project)) }) } diff --git a/apps/api/src/api-v1/projects/get-project-by-identifier.ts b/apps/api/src/api-v1/projects/get-project-by-identifier.ts index 69761c74..c16a2895 100644 --- a/apps/api/src/api-v1/projects/get-project-by-identifier.ts +++ b/apps/api/src/api-v1/projects/get-project-by-identifier.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseProjectSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { openapiAuthenticatedSecuritySchemas, @@ -53,6 +54,6 @@ export function registerV1GetProjectByIdentifier( assert(project, 404, `Project not found "${projectIdentifier}"`) await acl(c, project, { label: 'Project' }) - return c.json(parseZodSchema(schema.projectSelectSchema, project)) + return c.json(parseProjectSelectSchema(project)) }) } diff --git a/apps/api/src/api-v1/projects/get-project.ts b/apps/api/src/api-v1/projects/get-project.ts index 40418730..5c098801 100644 --- a/apps/api/src/api-v1/projects/get-project.ts +++ b/apps/api/src/api-v1/projects/get-project.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseProjectSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { openapiAuthenticatedSecuritySchemas, @@ -52,6 +53,6 @@ export function registerV1GetProject(app: OpenAPIHono) { assert(project, 404, `Project not found "${projectId}"`) await acl(c, project, { label: 'Project' }) - return c.json(parseZodSchema(schema.projectSelectSchema, project)) + return c.json(parseProjectSelectSchema(project)) }) } diff --git a/apps/api/src/api-v1/projects/get-public-project-by-identifier.ts b/apps/api/src/api-v1/projects/get-public-project-by-identifier.ts index bc5965d5..9dd4cf21 100644 --- a/apps/api/src/api-v1/projects/get-public-project-by-identifier.ts +++ b/apps/api/src/api-v1/projects/get-public-project-by-identifier.ts @@ -1,8 +1,8 @@ import type { DefaultHonoEnv } from '@agentic/platform-hono' -import { parseZodSchema } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import { db, eq, schema } from '@/db' +import { parseProjectSelectSchema } from '@/db/schema' import { aclPublicProject } from '@/lib/acl-public-project' import { openapiAuthenticatedSecuritySchemas, @@ -50,8 +50,8 @@ export function registerV1GetPublicProjectByIdentifier( ...Object.fromEntries(populate.map((field) => [field, true])) } }) - await aclPublicProject(project, projectIdentifier) + aclPublicProject(project, projectIdentifier) - return c.json(parseZodSchema(schema.projectSelectSchema, project)) + return c.json(parseProjectSelectSchema(project)) }) } diff --git a/apps/api/src/api-v1/projects/get-public-project.ts b/apps/api/src/api-v1/projects/get-public-project.ts index 99700b71..2b006a1b 100644 --- a/apps/api/src/api-v1/projects/get-public-project.ts +++ b/apps/api/src/api-v1/projects/get-public-project.ts @@ -1,8 +1,8 @@ import type { DefaultHonoEnv } from '@agentic/platform-hono' -import { parseZodSchema } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import { db, eq, schema } from '@/db' +import { parseProjectSelectSchema } from '@/db/schema' import { aclPublicProject } from '@/lib/acl-public-project' import { openapiAuthenticatedSecuritySchemas, @@ -49,8 +49,8 @@ export function registerV1GetPublicProject(app: OpenAPIHono) { ...Object.fromEntries(populate.map((field) => [field, true])) } }) - await aclPublicProject(project, projectId) + aclPublicProject(project, projectId) - return c.json(parseZodSchema(schema.projectSelectSchema, project)) + return c.json(parseProjectSelectSchema(project)) }) } diff --git a/apps/api/src/api-v1/projects/list-projects.ts b/apps/api/src/api-v1/projects/list-projects.ts index c042768d..defb235d 100644 --- a/apps/api/src/api-v1/projects/list-projects.ts +++ b/apps/api/src/api-v1/projects/list-projects.ts @@ -1,8 +1,8 @@ -import { parseZodSchema } from '@agentic/platform-core' import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseProjectSelectArraySchema } from '@/db/schema' import { ensureAuthUser } from '@/lib/ensure-auth-user' import { openapiAuthenticatedSecuritySchemas, @@ -65,6 +65,6 @@ export function registerV1ListProjects(app: OpenAPIHono) { limit }) - return c.json(parseZodSchema(z.array(schema.projectSelectSchema), projects)) + return c.json(parseProjectSelectArraySchema(projects)) }) } diff --git a/apps/api/src/api-v1/projects/list-public-projects.ts b/apps/api/src/api-v1/projects/list-public-projects.ts index 91c23e18..78f769c1 100644 --- a/apps/api/src/api-v1/projects/list-public-projects.ts +++ b/apps/api/src/api-v1/projects/list-public-projects.ts @@ -1,8 +1,8 @@ import type { DefaultHonoEnv } from '@agentic/platform-hono' -import { parseZodSchema } from '@agentic/platform-core' import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi' import { and, db, eq, isNotNull, schema } from '@/db' +import { parseProjectSelectArraySchema } from '@/db/schema' import { openapiAuthenticatedSecuritySchemas, openapiErrorResponses @@ -61,6 +61,6 @@ export function registerV1ListPublicProjects(app: OpenAPIHono) { limit }) - return c.json(parseZodSchema(z.array(schema.projectSelectSchema), projects)) + return c.json(parseProjectSelectArraySchema(projects)) }) } diff --git a/apps/api/src/api-v1/projects/update-project.ts b/apps/api/src/api-v1/projects/update-project.ts index 54726fca..cb8ee936 100644 --- a/apps/api/src/api-v1/projects/update-project.ts +++ b/apps/api/src/api-v1/projects/update-project.ts @@ -1,8 +1,9 @@ -import { assert, parseZodSchema } from '@agentic/platform-core' +import { assert } from '@agentic/platform-core' import { createRoute, type OpenAPIHono } from '@hono/zod-openapi' import type { AuthenticatedHonoEnv } from '@/lib/types' import { db, eq, schema } from '@/db' +import { parseProjectSelectSchema } from '@/db/schema' import { acl } from '@/lib/acl' import { openapiAuthenticatedSecuritySchemas, @@ -66,6 +67,6 @@ export function registerV1UpdateProject( .returning() assert(project, 500, `Failed to update project "${projectId}"`) - return c.json(parseZodSchema(schema.projectSelectSchema, project)) + return c.json(parseProjectSelectSchema(project)) }) } diff --git a/apps/api/src/db/schema/consumer.ts b/apps/api/src/db/schema/consumer.ts index 8edc714a..9c3c828f 100644 --- a/apps/api/src/db/schema/consumer.ts +++ b/apps/api/src/db/schema/consumer.ts @@ -1,3 +1,4 @@ +import { parseZodSchema } from '@agentic/platform-core' import { type StripeSubscriptionItemIdMap, stripeSubscriptionItemIdMapSchema @@ -12,6 +13,9 @@ import { } from '@fisch0920/drizzle-orm/pg-core' import { z } from '@hono/zod-openapi' +import { env } from '@/lib/env' + +import type { Consumer } from '../types' import { consumerIdSchema, deploymentIdSchema, @@ -185,6 +189,21 @@ export const consumerSelectSchema = createSelectSchema(consumers, { .optional() }) .strip() + // These are all derived virtual URLs that are not stored in the database + .extend({ + /** + * A private admin URL for managing the customer's subscription. This URL + * is only accessible by the customer. + * + * @example https://agentic.so/app/consumers/cons_123 + */ + adminUrl: z + .string() + .url() + .describe( + "A private admin URL for managing the customer's subscription. This URL is only accessible by the customer." + ) + }) .describe( `A Consumer represents a user who has subscribed to a Project and is used to track usage and billing. @@ -196,12 +215,36 @@ owner's connected Stripe account if the project has Stripe Connect enabled.` ) .openapi('Consumer') +export function parseConsumerSelectSchema( + consumer: Record +): Consumer { + return parseZodSchema(consumerSelectSchema, { + ...consumer, + adminUrl: `${env.AGENTIC_WEB_BASE_URL}/app/consumers/${consumer.id}` + }) +} + +export function parseConsumerSelectArraySchema( + consumers: Record[] +): Consumer[] { + return consumers.map(parseConsumerSelectSchema) +} + export const consumerAdminSelectSchema = consumerSelectSchema .extend({ _stripeCustomerId: z.string().nonempty() }) .openapi('AdminConsumer') +export function parseConsumerAdminSelectSchema( + consumer: Record +): Consumer { + return parseZodSchema(consumerAdminSelectSchema, { + ...parseConsumerSelectSchema(consumer), + ...consumer + }) +} + export const consumerInsertSchema = createInsertSchema(consumers, { deploymentId: deploymentIdSchema.optional(), diff --git a/apps/api/src/db/schema/deployment.ts b/apps/api/src/db/schema/deployment.ts index 6ff5b144..06229b40 100644 --- a/apps/api/src/db/schema/deployment.ts +++ b/apps/api/src/db/schema/deployment.ts @@ -1,3 +1,4 @@ +import { parseZodSchema } from '@agentic/platform-core' import { agenticProjectConfigSchema, defaultRequestsRateLimit, @@ -8,7 +9,10 @@ import { type Tool, type ToolConfig } from '@agentic/platform-types' -import { isValidDeploymentHash } from '@agentic/platform-validators' +import { + isValidDeploymentHash, + parseDeploymentIdentifier +} from '@agentic/platform-validators' import { relations } from '@fisch0920/drizzle-orm' import { boolean, @@ -20,6 +24,9 @@ import { } from '@fisch0920/drizzle-orm/pg-core' import { z } from '@hono/zod-openapi' +import { env } from '@/lib/env' + +import type { Deployment } from '../types' import { deploymentIdentifierSchema, deploymentIdSchema, @@ -209,6 +216,59 @@ export const deploymentSelectSchema = createSelectSchema(deployments, { // project: z.object({}).optional().openapi('Project', { type: 'object' }) }) .strip() + // These are all derived virtual URLs that are not stored in the database + .extend({ + /** + * The public base HTTP URL for the deployment supporting HTTP POST requests + * for individual tools at `/tool-name` subpaths. + * + * @example https://gateway.agentic.com/@agentic/search@latest + */ + gatewayBaseUrl: z + .string() + .url() + .describe( + 'The public base HTTP URL for the deployment supporting HTTP POST requests for individual tools at `/tool-name` subpaths.' + ), + + /** + * The public MCP URL for the deployment supporting the Streamable HTTP + * transport. + * + * @example https://gateway.agentic.com/@agentic/search@latest/mcp + */ + gatewayMcpUrl: z + .string() + .url() + .describe( + 'The public MCP URL for the deployment supporting the Streamable HTTP transport.' + ), + + /** + * The public marketplace URL for the deployment's project. + * + * Note that only published deployments are visible on the marketplace. + * + * @example https://agentic.so/marketplace/projects/@agentic/search + */ + marketplaceUrl: z + .string() + .url() + .describe("The public marketplace URL for the deployment's project."), + + /** + * A private admin URL for managing the deployment. This URL is only accessible + * by project owners. + * + * @example https://agentic.so/app/projects/@agentic/search/deployments/123 + */ + adminUrl: z + .string() + .url() + .describe( + 'A private admin URL for managing the deployment. This URL is only accessible by project owners.' + ) + }) .describe( `A Deployment is a single, immutable instance of a Project. Each deployment contains pricing plans, origin server config (OpenAPI or MCP server), tool definitions, and metadata. @@ -216,6 +276,28 @@ Deployments are private to a developer or team until they are published, at whic ) .openapi('Deployment') +export function parseDeploymentSelectSchema( + deployment: Record +): Deployment { + const { projectIdentifier, deploymentIdentifier } = parseDeploymentIdentifier( + deployment.identifier + ) + + return parseZodSchema(deploymentSelectSchema, { + ...deployment, + gatewayBaseUrl: `${env.AGENTIC_GATEWAY_BASE_URL}/${deploymentIdentifier}`, + gatewayMcpUrl: `${env.AGENTIC_GATEWAY_BASE_URL}/${deploymentIdentifier}/mcp`, + marketplaceUrl: `${env.AGENTIC_WEB_BASE_URL}/marketplace/projects/${projectIdentifier}`, + adminUrl: `${env.AGENTIC_WEB_BASE_URL}/app/projects/${projectIdentifier}/deployments/${deployment.hash}` + }) +} + +export function parseDeploymentSelectArraySchema( + deployments: Record[] +): Deployment[] { + return deployments.map(parseDeploymentSelectSchema) +} + export const deploymentAdminSelectSchema = deploymentSelectSchema .extend({ origin: resolvedAgenticProjectConfigSchema.shape.origin, @@ -223,6 +305,15 @@ export const deploymentAdminSelectSchema = deploymentSelectSchema }) .openapi('AdminDeployment') +export function parseDeploymentAdminSelectSchema( + deployment: Record +): z.infer { + return parseZodSchema(deploymentAdminSelectSchema, { + ...parseDeploymentSelectSchema(deployment), + ...deployment + }) +} + export const deploymentInsertSchema = agenticProjectConfigSchema.strict() // TODO: Deployments should be immutable, so we should not allow updates aside diff --git a/apps/api/src/db/schema/project.ts b/apps/api/src/db/schema/project.ts index a303eedc..5a187b7e 100644 --- a/apps/api/src/db/schema/project.ts +++ b/apps/api/src/db/schema/project.ts @@ -1,3 +1,4 @@ +import { parseZodSchema } from '@agentic/platform-core' import { agenticProjectConfigSchema, pricingIntervalSchema, @@ -20,6 +21,9 @@ import { } from '@fisch0920/drizzle-orm/pg-core' import { z } from '@hono/zod-openapi' +import { env } from '@/lib/env' + +import type { Project } from '../types' import { deploymentIdSchema, projectIdentifierSchema, @@ -293,13 +297,56 @@ export const projectSelectSchema = createSelectSchema(projects, { .optional() }) .strip() - // TODO - // .refine((project) => ({ - // ...project, - // gatewayBaseUrl: `${env.AGENTIC_GATEWAY_BASE_URL}/${project.identifier}`, - // gatewayMcpUrl: `${env.AGENTIC_GATEWAY_BASE_URL}/${project.identifier}/mcp`, - // webBaseUrl: `${env.AGENTIC_WEB_BASE_URL}/marketplace/projects/${project.identifier}` - // })) + // These are all derived virtual URLs that are not stored in the database + .extend({ + /** + * The public base HTTP URL for the project supporting HTTP POST requests for + * individual tools at `/tool-name` subpaths. + * + * @example https://gateway.agentic.com/@agentic/search + */ + gatewayBaseUrl: z + .string() + .url() + .describe( + 'The public base HTTP URL for the project supporting HTTP POST requests for individual tools at `/tool-name` subpaths.' + ), + + /** + * The public MCP URL for the project supporting the Streamable HTTP transport. + * + * @example https://gateway.agentic.com/@agentic/search/mcp + */ + gatewayMcpUrl: z + .string() + .url() + .describe( + 'The public MCP URL for the project supporting the Streamable HTTP transport.' + ), + + /** + * The public marketplace URL for the project. + * + * @example https://agentic.so/marketplace/projects/@agentic/search + */ + marketplaceUrl: z + .string() + .url() + .describe('The public marketplace URL for the project.'), + + /** + * A private admin URL for managing the project. This URL is only accessible + * by project owners. + * + * @example https://agentic.so/app/projects/@agentic/search + */ + adminUrl: z + .string() + .url() + .describe( + 'A private admin URL for managing the project. This URL is only accessible by project owners.' + ) + }) .describe( `A Project represents a single Agentic API product. It is comprised of a series of immutable Deployments, each of which contains pricing data, origin API config, OpenAPI or MCP specs, tool definitions, and various metadata. @@ -309,6 +356,24 @@ Internally, Projects manage all of the Stripe billing resources across Deploymen ) .openapi('Project') +export function parseProjectSelectSchema( + project: Record +): Project { + return parseZodSchema(projectSelectSchema, { + ...project, + gatewayBaseUrl: `${env.AGENTIC_GATEWAY_BASE_URL}/${project.identifier}`, + gatewayMcpUrl: `${env.AGENTIC_GATEWAY_BASE_URL}/${project.identifier}/mcp`, + marketplaceUrl: `${env.AGENTIC_WEB_BASE_URL}/marketplace/projects/${project.identifier}`, + adminUrl: `${env.AGENTIC_WEB_BASE_URL}/app/projects/${project.identifier}` + }) +} + +export function parseProjectSelectArraySchema( + projects: Record[] +): Project[] { + return projects.map(parseProjectSelectSchema) +} + export const projectInsertSchema = createInsertSchema(projects, { identifier: projectIdentifierSchema, diff --git a/apps/api/src/lib/acl-public-project.ts b/apps/api/src/lib/acl-public-project.ts index 6b55828a..5cd77c27 100644 --- a/apps/api/src/lib/acl-public-project.ts +++ b/apps/api/src/lib/acl-public-project.ts @@ -2,10 +2,10 @@ import { assert } from '@agentic/platform-core' import type { RawProject } from '@/db' -export async function aclPublicProject( +export function aclPublicProject( project: RawProject | undefined, projectId?: string -) { +): asserts project { assert( project, 404, diff --git a/apps/api/src/lib/consumers/upsert-consumer-stripe-checkout.ts b/apps/api/src/lib/consumers/upsert-consumer-stripe-checkout.ts index 5a69253d..f5fdb39b 100644 --- a/apps/api/src/lib/consumers/upsert-consumer-stripe-checkout.ts +++ b/apps/api/src/lib/consumers/upsert-consumer-stripe-checkout.ts @@ -72,7 +72,7 @@ export async function upsertConsumerStripeCheckout( 404, `Project not found "${projectId}" for deployment "${deploymentId}"` ) - await aclPublicProject(project) + aclPublicProject(project) // Validate the deployment only after we're sure the project is publicly // accessible. diff --git a/apps/api/src/lib/consumers/upsert-consumer.ts b/apps/api/src/lib/consumers/upsert-consumer.ts index dd69859b..73765b43 100644 --- a/apps/api/src/lib/consumers/upsert-consumer.ts +++ b/apps/api/src/lib/consumers/upsert-consumer.ts @@ -60,7 +60,7 @@ export async function upsertConsumer( 404, `Project not found "${projectId}" for deployment "${deploymentId}"` ) - await aclPublicProject(project) + aclPublicProject(project) // Validate the deployment only after we're sure the project is publicly // accessible. diff --git a/apps/web/public/schema.json b/apps/web/public/schema.json index 8e2ec26c..a25172e8 100644 --- a/apps/web/public/schema.json +++ b/apps/web/public/schema.json @@ -117,7 +117,7 @@ "name": { "type": "string", "minLength": 1, - "description": "Human-readable name for the pricing plan (eg, \"Free\", \"Starter Monthly\", \"Pro Annual\", etc)" + "description": "Display name for the pricing plan (eg, \"Free\", \"Starter Monthly\", \"Pro Annual\", etc)" }, "slug": { "type": "string", @@ -305,8 +305,7 @@ "type": "string", "enum": [ "sum", - "count", - "last" + "count" ], "default": "sum" } diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx index c7826c1e..b59a4aa3 100644 --- a/apps/web/src/app/page.tsx +++ b/apps/web/src/app/page.tsx @@ -70,8 +70,11 @@ export default async function TheBestDamnLandingPageEver() {

This example uses the{' '} - - @agentic/search + + {projectIdentifier} {' '} tool to provide an LLM access to the web.

diff --git a/docs/publishing/guides/existing-mcp-server.mdx b/docs/publishing/guides/existing-mcp-server.mdx index d5a3b1be..1b269b9e 100644 --- a/docs/publishing/guides/existing-mcp-server.mdx +++ b/docs/publishing/guides/existing-mcp-server.mdx @@ -145,11 +145,11 @@ Every time you make a change to your project, you can run `agentic deploy` which ```json { - "id": "depl_m2yl7dpdpc5xk8b3cwvuzkg3", - "createdAt": "2025-06-27 18:14:34.641308+00", - "updatedAt": "2025-06-27 18:14:34.641308+00", - "identifier": "@dev/search@b57dc301", - "hash": "b57dc301", + "id": "depl_kf4c3o8efh2y84dp5iwsha95", + "createdAt": "2025-06-28 05:38:34.960754+00", + "updatedAt": "2025-06-28 05:38:34.960754+00", + "identifier": "@dev/search@42ad78bf", + "hash": "42ad78bf", "published": false, "description": "Official Google Search tool. Useful for finding up-to-date news and information about any topic.", "readme": "", @@ -160,6 +160,7 @@ Every time you make a change to your project, you can run `agentic deploy` which "name": "search", "description": "Uses Google Search to return the most relevant web pages for a given query. Useful for finding up-to-date news and information about any topic.", "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "num": { @@ -186,10 +187,10 @@ Every time you make a change to your project, you can run `agentic deploy` which } }, "required": ["query"], - "additionalProperties": false, - "$schema": "http://json-schema.org/draft-07/schema#" + "additionalProperties": false }, "outputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "news": {}, @@ -201,8 +202,7 @@ Every time you make a change to your project, you can run `agentic deploy` which "answerBox": {}, "knowledgeGraph": {} }, - "additionalProperties": false, - "$schema": "http://json-schema.org/draft-07/schema#" + "additionalProperties": false } } ], @@ -284,7 +284,11 @@ Every time you make a change to your project, you can run `agentic deploy` which "limit": 1000, "mode": "approximate", "enabled": true - } + }, + "gatewayBaseUrl": "https://gateway.agentic.so/@dev/search@42ad78bf", + "gatewayMcpUrl": "https://gateway.agentic.so/@dev/search@42ad78bf/mcp", + "marketplaceUrl": "https://agentic.so/marketplace/projects/@dev/search", + "adminUrl": "https://agentic.so/app/projects/@dev/search/deployments/42ad78bf" } ``` @@ -292,9 +296,9 @@ Every time you make a change to your project, you can run `agentic deploy` which ## 5. Test your deployment -The easiest way to test your deployment is to visit it in your Agentic dashboard: `https://agentic.so/app/projects/`. +The easiest way to test your deployment is to visit it in your Agentic admin dashboard. This will be the `adminUrl` in the returned deployment and should look like: `https://agentic.so/app/projects//deployments/`. -This page will show all the tools available on your deployment and includes a GUI for how to call them with various MCP clients, TS LLM SDKs, Python LLM SDKs, and raw HTTP. +This page shows you all the tools available for your deployment and includes a GUI showing how to call them with various MCP clients, TS LLM SDKs, Python LLM SDKs, and simple HTTP. `. +The easiest way to test your deployment is to visit it in your Agentic admin dashboard. This will be the `adminUrl` in the returned deployment and should look like: `https://agentic.so/app/projects//deployments/`. -This page will show all the tools available on your deployment and includes a GUI for how to call them with various MCP clients, TS LLM SDKs, Python LLM SDKs, and raw HTTP. +This page shows you all the tools available for your deployment and includes a GUI showing how to call them with various MCP clients, TS LLM SDKs, Python LLM SDKs, and simple HTTP.