| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
- import fs from 'node:fs'
- import path from 'node:path'
- import { fileURLToPath } from 'node:url'
- import cookie from '@fastify/cookie'
- import multipart from '@fastify/multipart'
- import fastifyStatic from '@fastify/static'
- import Fastify, { type FastifyServerOptions } from 'fastify'
- import type { ApiErrorBody } from '@agent-server/shared'
- import type { App } from '../app'
- import { config } from '../config'
- import { AppError } from '../lib/errors'
- import adminRoutes from './routes/admin'
- import v1Routes from './routes/v1'
- import { registerGateway } from '../mcp-gateway/server'
- export async function buildServer(app: App, opts: { logger: FastifyServerOptions['loggerInstance'] }) {
- const f = Fastify({ loggerInstance: opts.logger, trustProxy: config.trustProxy, bodyLimit: 2 * 1048576 })
- await f.register(cookie)
- await f.register(multipart)
- f.setErrorHandler((err, req, reply) => {
- if (err instanceof AppError) {
- const body: ApiErrorBody = { error: { code: err.code, message: err.message, details: err.details } }
- return reply.code(err.status).send(body)
- }
- const status = (err as { statusCode?: number }).statusCode ?? 500
- if (status >= 500) req.log.error({ err }, 'unhandled error')
- const body: ApiErrorBody = { error: { code: status >= 500 ? 'internal_error' : 'bad_request', message: status >= 500 ? '服务器内部错误' : (err as Error).message } }
- return reply.code(status).send(body)
- })
- f.get('/healthz', async () => ({ ok: true }))
- f.get('/readyz', async () => {
- app.db.$client.prepare('select 1').get()
- return { ok: true, runs: app.runs.stats() }
- })
- await f.register(v1Routes, { prefix: '/v1', app })
- registerGateway(f, app.gatewayTokens)
- await f.register(adminRoutes, { prefix: '/admin/v1', app })
- // 生产环境由服务托管后台静态资源,同源访问
- // 源码运行时位于 src/http,打包后位于 dist,两种情况都向上寻找 apps/admin/dist
- const here = path.dirname(fileURLToPath(import.meta.url))
- const adminDist = config.adminDist
- ?? [path.resolve(here, '../../../admin/dist'), path.resolve(here, '../../admin/dist')].find(p => fs.existsSync(path.join(p, 'index.html')))
- if (adminDist && fs.existsSync(path.join(adminDist, 'index.html'))) {
- await f.register(fastifyStatic, { root: adminDist, prefix: '/admin/', wildcard: false })
- f.get('/admin/*', (_req, reply) => reply.sendFile('index.html'))
- f.get('/', (_req, reply) => reply.redirect('/admin/'))
- }
- return f
- }
|