kimi-code/packages/kap-server/src/error-handler.ts
haozhe.yang 304883ab81 refactor(kap-server): rename server-v2 package to kap-server
- rename packages/server-v2 to packages/kap-server and update every
  @moonshot-ai/server-v2 reference across apps, packages, flake.nix,
  and build scripts
- remove the experimental `kimi v2` CLI prefix and its tests from the
  apps/kimi-code main entry
- add legacy BackgroundTask protocol types and the `blocked` turn
  interrupt reason for cross-engine compatibility
2026-07-07 16:56:19 +08:00

51 lines
1.8 KiB
TypeScript

/**
* Fastify error hook for unhandled server exceptions.
*
* Wraps unhandled exceptions in the Feishu-style envelope:
* - HTTP status ALWAYS 200 (business outcome lives in `code`);
* - `code: 50001` (`internal.error`) for unknown exceptions;
* - `request_id` echoes the inbound request id (set by Fastify's
* `genReqId` via `resolveRequestId`);
* - `data: null`.
*
* Validation failures are handled by route-level middleware as 40001
* `validation.failed`; this handler remains the catch-all unknown-exception path.
*
* The handler logs `err` + the resolved `request_id` so operators can
* correlate log lines with the envelope returned to the client. This is the
* single place a stack trace ever crosses our process boundary into a log —
* we never bleed it into the JSON response.
*/
import { errEnvelope, ErrorCode } from '@moonshot-ai/protocol';
import type { FastifyError } from 'fastify';
/**
* Loose Fastify-instance shape so this helper accepts both the default
* `FastifyInstance` and the server's pino-typed variant
* (`FastifyInstance<…, ServerLogger>`). The type checker chokes on the
* concrete generic mismatch otherwise.
*/
interface ErrorHandlerHost {
setErrorHandler(
handler: (
err: FastifyError,
req: { id: string; log: { error: (obj: object | string, msg?: string) => void } },
reply: { status(code: number): { send(payload: unknown): void } },
) => void,
): unknown;
}
export function installErrorHandler(app: ErrorHandlerHost): void {
app.setErrorHandler((err, req, reply) => {
const requestId = req.id;
req.log.error({ err, request_id: requestId }, 'unhandled error');
reply.status(200).send(
errEnvelope(
ErrorCode.INTERNAL_ERROR,
err.message !== undefined && err.message !== '' ? err.message : 'internal error',
requestId,
),
);
});
}