mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-20 06:05:36 +00:00
* fix(web): restore swarm member list after page refresh * chore: add changeset for swarm roster refresh fix
5.4 KiB
5.4 KiB
server Agent Guide
Package-local rules for packages/server (@moonshot-ai/server).
What it is
The Kimi Code server. It hosts agent-core sessions and exposes them over REST + WebSocket under a single /api/v1 prefix. It is consumed by apps/kimi-code (the CLI/TUI) — do not add a reverse dependency on the CLI app.
Entry points & launch
- Bootstrap:
src/start.tsexportsstartServer(opts): Promise<RunningServer>. The public surface is re-exported fromsrc/index.ts. - Dev: run from the repo root with
pnpm dev:server(auto-restart variantpnpm dev:server:restart). This shells intokimi server runviaapps/kimi-code. This package has nodevscript of its own. - Prod: the CLI command
kimi server run(apps/kimi-code/src/cli/sub/server/run.ts) importsstartServer.
Layout (src/)
- Top level:
start.ts,index.ts,envelope.ts,error-handler.ts,lock.ts,request-id.ts,version.ts. routes/— REST domain modules, theregisterApiV1Routes.tsaggregator,webAssets.ts, andaction-suffix.ts.services/— server-owned DI adapters:approval/,question/,gateway/(rest/ws/broadcast/connectionRegistry/sessionClients/sessionEventJournal/inFlightTurnTracker/subagentRosterTracker),pinoLoggerService.ts,serviceCollection.ts.ws/—connection.ts(WsConnection),protocol.ts(frame builders),rawData.ts.middleware/—defineRoute.ts,schema.ts,validate.ts.openapi/transforms.ts.svc/— OS service managers (launchd / systemd / schtasks) backingkimi server install/start.
DI: how it consumes @moonshot-ai/agent-core
Service conventions (naming, file layout, registration) live in packages/agent-core/src/services/AGENTS.md — read that before adding or changing a service. This package only wires the container:
src/services/serviceCollection.tscreateServerServiceCollection(...)seeds aServiceCollectionwith...getSingletonServiceDescriptors()plus server-owned gateway singletons (ConnectionRegistry,SessionClientsService,WSBroadcastService) and overridesIApprovalService/IQuestionService.services.set(...)overrides:ILogService(Pino adapter),IRestGateway(FastifyRestGateway(app)),IEnvironmentService; thenIWSGateway/ICoreProcessServiceasSyncDescriptors with options; thenserver.serviceOverrideslast (the test seam — later registration wins).start.tsbuildsnew InstantiationService(services), eagerly resolves services insideix.invokeFunction(...), wireswsGw.setAbortHandler/setTerminalHandler/setFsWatchHandler, manually creates + registersFsWatcherService, awaitscoreProcess.ready(), then binds vialistenWithPortRetry(...)(wrapsIRestGateway.listen).
Wire layer
- REST is Fastify. All v1 routes are registered under
/api/v1inroutes/registerApiV1Routes.ts. Declare routes withmiddleware/defineRoute.ts: one object carries the Zod validators and the OpenAPI response schema; the200schema is expanded into the envelopeoneOf. start.tsneuters Fastify's validator/serializer compilers — validation happens indefineRoutepreHandlers, not in Fastify's own pipeline.- Doc/meta endpoints in
start.ts:/openapi.json(@fastify/swagger, lazily imported),/asyncapi.json(createAsyncApiDocumentfrom@moonshot-ai/protocol),/healthz.webAssetsDirenablesregisterWebAssetRoutes. - WebSocket uses the
wspackage; frames/envelopes live inws/protocol.ts(server_hello,ack,event,resync_required, per-sessionseq).
Commands
pnpm --filter @moonshot-ai/server build—tsdown.pnpm --filter @moonshot-ai/server typecheck—tsc -p tsconfig.json --noEmit.pnpm --filter @moonshot-ai/server test—vitest run.pnpm --filter @moonshot-ai/server clean—rm -rf dist.- Dev server:
pnpm dev:serverat the repo root. - E2E: in-process tests live in
test/*.e2e.test.tsand bootstartServerdirectly. Live e2e against a running server lives inpackages/server-e2e(defaulthttp://127.0.0.1:58627, override withKIMI_SERVER_URL).
Gotchas / hard rules
- Path alias:
#/*maps to./src/*.ts(with#/services/...variants). Use#/..., not@/. - Single-instance lock:
start.tscallsacquireLock; a second start throwsServerLockedError. Tests must pass a uniquelockPath/portand useserviceOverrides. - Port-busy policy: the lock is acquired before binding, so any
EADDRINUSEfromlistenis a third-party listener (never another kimi server).listenWithPortRetrythen walksport + 1,+ 2, … (capped byPORT_RETRY_LIMIT) and callslockHandle.updatePort(boundPort)so the lock advertises the real port. Port0(ephemeral) is never retried. The daemon spawner mirrors this inresolveDaemonPort(apps/kimi-code). - Uniform response envelope
{ code, msg, data, request_id }(envelope.ts,error-handler.ts); request id comes fromrequest-id.ts/genReqId. :actionURL convention is handled byroutes/action-suffix.ts(parseActionSuffix) — Fastify cannot disambiguate:idfrom:id:actionon its own.FsWatcherServiceis created manually andservices.set-registered after the collection is built — this is ordering-sensitive; keep the boot wiring instart.ts.debugEndpointsis opt-in: only registerregisterDebugRouteswhenopts.debugEndpoints === true. Swagger plugins are dynamically imported.