diff --git a/apps/api/src/api-v1/health-check.ts b/apps/api/src/api-v1/health-check.ts index f071f0de..6b79c1dd 100644 --- a/apps/api/src/api-v1/health-check.ts +++ b/apps/api/src/api-v1/health-check.ts @@ -1,4 +1,6 @@ -import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi' +import { createRoute, z } from '@hono/zod-openapi' + +import type { HonoApp } from '@/lib/types' const route = createRoute({ method: 'get', @@ -17,7 +19,7 @@ const route = createRoute({ } }) -export function registerHealthCheck(app: OpenAPIHono) { +export function registerHealthCheck(app: HonoApp) { return app.openapi(route, async (c) => { return c.json({ status: 'ok' }) }) diff --git a/apps/api/src/api-v1/index.ts b/apps/api/src/api-v1/index.ts index c79b891d..aece1de5 100644 --- a/apps/api/src/api-v1/index.ts +++ b/apps/api/src/api-v1/index.ts @@ -1,3 +1,4 @@ +import type { DefaultHonoEnv } from '@agentic/platform-hono' import { OpenAPIHono } from '@hono/zod-openapi' import { fromError } from 'zod-validation-error' @@ -39,12 +40,14 @@ import { registerV1StripeWebhook } from './webhooks/stripe-webhook' // Note that the order of some of these routes is important because of // wildcards, so be careful when updating them or adding new routes. -export const apiV1 = new OpenAPIHono({ +export const apiV1 = new OpenAPIHono({ defaultHook: (result, ctx) => { if (!result.success) { + const requestId = ctx.get('requestId') return ctx.json( { - error: fromError(result.error).toString() + error: fromError(result.error).toString(), + requestId }, 400 ) @@ -61,7 +64,7 @@ apiV1.openAPIRegistry.registerComponent('securitySchemes', 'Bearer', { registerOpenAPIErrorResponses(apiV1) // Public routes -const publicRouter = new OpenAPIHono() +const publicRouter = new OpenAPIHono() // Private, authenticated routes const privateRouter = new OpenAPIHono() diff --git a/apps/api/src/api-v1/webhooks/stripe-webhook.ts b/apps/api/src/api-v1/webhooks/stripe-webhook.ts index 5781cf60..d5763b5c 100644 --- a/apps/api/src/api-v1/webhooks/stripe-webhook.ts +++ b/apps/api/src/api-v1/webhooks/stripe-webhook.ts @@ -1,7 +1,7 @@ -import type { OpenAPIHono } from '@hono/zod-openapi' import type Stripe from 'stripe' import { assert, HttpError } from '@agentic/platform-core' +import type { HonoApp } from '@/lib/types' import { and, db, eq, schema } from '@/db' import { setConsumerStripeSubscriptionStatus } from '@/lib/consumers/utils' import { env } from '@/lib/env' @@ -11,7 +11,7 @@ const relevantStripeEvents = new Set([ 'customer.subscription.updated' ]) -export function registerV1StripeWebhook(app: OpenAPIHono) { +export function registerV1StripeWebhook(app: HonoApp) { return app.post('webhooks/stripe', async (ctx) => { const body = await ctx.req.text() const signature = ctx.req.header('Stripe-Signature') diff --git a/apps/api/src/lib/openapi-utils.ts b/apps/api/src/lib/openapi-utils.ts index 9a57b7a1..cd18edba 100644 --- a/apps/api/src/lib/openapi-utils.ts +++ b/apps/api/src/lib/openapi-utils.ts @@ -1,4 +1,4 @@ -import type { OpenAPIHono } from '@hono/zod-openapi' +import type { HonoApp } from './types' export const openapiErrorResponses = { 400: { @@ -44,14 +44,17 @@ const openapiErrorContent = { properties: { error: { type: 'string' as const + }, + requestId: { + type: 'string' as const } }, - required: ['error' as const] + required: ['error', 'requestId'] } } } -export function registerOpenAPIErrorResponses(app: OpenAPIHono) { +export function registerOpenAPIErrorResponses(app: HonoApp) { app.openAPIRegistry.registerComponent('responses', '400', { description: 'Bad Request', content: openapiErrorContent diff --git a/apps/api/src/lib/types.ts b/apps/api/src/lib/types.ts index 568fd5bb..c0fc3078 100644 --- a/apps/api/src/lib/types.ts +++ b/apps/api/src/lib/types.ts @@ -1,7 +1,9 @@ import type { DefaultHonoBindings, + DefaultHonoEnv, DefaultHonoVariables } from '@agentic/platform-hono' +import type { OpenAPIHono } from '@hono/zod-openapi' import type { Context } from 'hono' import type { Simplify } from 'type-fest' @@ -25,3 +27,6 @@ export type AuthenticatedHonoEnv = { } export type AuthenticatedHonoContext = Context + +export type HonoApp = OpenAPIHono +export type AuthenticatedHonoApp = OpenAPIHono diff --git a/apps/api/src/server.ts b/apps/api/src/server.ts index 2adcaa10..2871efa5 100644 --- a/apps/api/src/server.ts +++ b/apps/api/src/server.ts @@ -39,7 +39,7 @@ app.route('/v1', apiV1) app.doc31('/docs', { openapi: '3.1.0', - info: { title: 'Agentic', version: '1.0.0' } + info: { title: 'Agentic', version: '0.1.0' } }) const server = serve({ diff --git a/apps/gateway/src/app.ts b/apps/gateway/src/app.ts index 60c9104b..89176222 100644 --- a/apps/gateway/src/app.ts +++ b/apps/gateway/src/app.ts @@ -117,9 +117,10 @@ app.all(async (ctx) => { const originTimespan = now - originStartTime res.headers.set('x-origin-response-time', `${originTimespan}ms`) - // Reset server to agentic because Cloudflare likes to override things + // Reset server to Agentic because Cloudflare likes to override things res.headers.set('server', 'agentic') + // Remove extra Cloudflare headers res.headers.delete('x-powered-by') res.headers.delete('via') res.headers.delete('nel') @@ -135,7 +136,7 @@ app.all(async (ctx) => { return res - // TODO: move this `finally` blockto a middleware handler + // TODO: move this `finally` block to a middleware handler // const now = Date.now() // Report usage. // Note that we are not awaiting the results of this on purpose so we can diff --git a/packages/fixtures/package.json b/packages/fixtures/package.json index b8e74f08..d8ab4256 100644 --- a/packages/fixtures/package.json +++ b/packages/fixtures/package.json @@ -26,5 +26,9 @@ }, "dependencies": { "@agentic/platform": "workspace:*" + }, + "devDependencies": { + "@modelcontextprotocol/sdk": "catalog:", + "zod": "catalog:" } } diff --git a/packages/hono/src/error-handler.ts b/packages/hono/src/error-handler.ts index ed914794..17bf476d 100644 --- a/packages/hono/src/error-handler.ts +++ b/packages/hono/src/error-handler.ts @@ -12,6 +12,7 @@ export function errorHandler( ): Response { const isProd = ctx.env?.isProd ?? true const logger = ctx.get('logger') ?? console + const requestId = ctx.get('requestId') let message = 'Internal Server Error' let status: ContentfulStatusCode = 500 @@ -36,5 +37,5 @@ export function errorHandler( logger.warn(status, err) } - return ctx.json({ error: message }, status) + return ctx.json({ error: message, requestId }, status) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8a063be0..68c78cc8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -426,7 +426,7 @@ importers: version: link:../../packages/validators '@hono/zod-validator': specifier: 'catalog:' - version: 0.7.0(hono@4.7.11)(zod@3.25.36) + version: 0.7.0(hono@4.7.11)(zod@3.25.51) '@modelcontextprotocol/sdk': specifier: 'catalog:' version: 1.12.1 @@ -584,6 +584,13 @@ importers: '@agentic/platform': specifier: workspace:* version: link:../platform + devDependencies: + '@modelcontextprotocol/sdk': + specifier: 'catalog:' + version: 1.12.1 + zod: + specifier: 'catalog:' + version: 3.25.51 packages/hono: dependencies: @@ -5438,9 +5445,6 @@ packages: zod@3.22.3: resolution: {integrity: sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==} - zod@3.25.36: - resolution: {integrity: sha512-eRFS3i8T0IrpGdL8HQyqFAugGOn7jOjyGgGdtv5NY4Wkhi7lJDk732bNZ609YMIGFbLoaj6J69O1Mura23gfIw==} - zod@3.25.51: resolution: {integrity: sha512-TQSnBldh+XSGL+opiSIq0575wvDPqu09AqWe1F7JhUMKY+M91/aGlK4MhpVNO7MgYfHcVCB1ffwAUTJzllKJqg==} @@ -5859,11 +5863,6 @@ snapshots: hono: 4.7.11 zod: 3.25.51 - '@hono/zod-validator@0.7.0(hono@4.7.11)(zod@3.25.36)': - dependencies: - hono: 4.7.11 - zod: 3.25.36 - '@hono/zod-validator@0.7.0(hono@4.7.11)(zod@3.25.51)': dependencies: hono: 4.7.11 @@ -6080,8 +6079,8 @@ snapshots: express-rate-limit: 7.5.0(express@5.1.0) pkce-challenge: 5.0.0 raw-body: 3.0.0 - zod: 3.25.36 - zod-to-json-schema: 3.24.5(zod@3.25.36) + zod: 3.25.51 + zod-to-json-schema: 3.24.5(zod@3.25.51) transitivePeerDependencies: - supports-color @@ -10227,10 +10226,6 @@ snapshots: mustache: 4.2.0 stacktracey: 2.1.8 - zod-to-json-schema@3.24.5(zod@3.25.36): - dependencies: - zod: 3.25.36 - zod-to-json-schema@3.24.5(zod@3.25.51): dependencies: zod: 3.25.51 @@ -10241,6 +10236,4 @@ snapshots: zod@3.22.3: {} - zod@3.25.36: {} - zod@3.25.51: {} diff --git a/readme.md b/readme.md index 5aff8857..4598130f 100644 --- a/readme.md +++ b/readme.md @@ -36,6 +36,7 @@ - add support for custom headers on responses - how to handle binary bodies and responses? - add requestId to all JSON error responses +- add support for `immutable` in `toolConfigs` ## TODO Post-MVP