@mottyjs/serve

中文文档
0.2.0发布于 2026/11/02Apache-2.0TypeScriptES Module构建来源已验证

The host side of a motty: serves it as a model over the Chat Completions, Responses and Messages APIs, on Bun or Cloudflare Workers.

原始使用文档

@mottyjs/serve

The host side of the Motty SDK. serve(motty, options) is for a serve file, whose default export Bun starts; mount(motty, options) returns fetch and close for a host that has a server of its own, on Bun or Cloudflare Workers. Both serve the motty as a model over the Chat Completions, Responses and Messages APIs. This package is never in a motty's bundle.

bun add @mottyjs/serve
import { mount, serve } from "@mottyjs/serve";

A motty that requires a caller, and its serve file. The keys are read from the environment and stay with the host. The auth adapter only proves who a caller is, so a motty without .use(auth()) runs for anyone, whatever the adapter says. A host warns of an adapter with no auth(), and of auth() with no adapter, where every caller gets a 401 unless the host states the caller. On Bun the warning is written at start. On Workers it is written at the first request to that mount, once, since what a Worker writes at global scope reaches no log.

// src/motty.ts
import { auth } from "@mottyjs/auth";
import { model, motty } from "@mottyjs/core";

export default motty({ name: "coder" })
  .use(auth())
  .handle(({ prompt }) => model("openai/gpt-6.1-sol").complete(prompt));
// src/serve.ts
import { serve } from "@mottyjs/serve";
import { anthropic } from "@mottyjs/adapters/anthropic";
import { jwt } from "@mottyjs/adapters/jwt";
import { openai } from "@mottyjs/adapters/openai";
import { redis } from "@mottyjs/adapters/redis";
import coder from "./motty";

export default serve(coder, ({ OPENAI_KEY, ANTHROPIC_KEY, REDIS_URL, JWKS_URL }) => ({
  models: [
    openai({ key: OPENAI_KEY }),
    anthropic({ key: ANTHROPIC_KEY }),
  ],
  storage: redis({ url: REDIS_URL }),
  auth: jwt({ jwks: JWKS_URL }),
  limits: { duration: 120_000, calls: 10, afterResponse: 30_000 },
  report: (record) => console.log(JSON.stringify(record)),
}));

Every time is in milliseconds and every size in bytes. A request body is at most limits.body, 32 MB unless stated, and has the edge's receive to arrive, 60 000 unless stated in the third argument beside keepAlive and drain: serve(coder, options, { receive: 30_000 }). Every limit and every time of the edge is checked when the host is made. Every reply to a request that was let in carries the id of its report, in x-request-id on the two OpenAI APIs and in request-id on Messages.

With no report, the failed records are written to stderr, with credentials masked. That covers a failure on the host's side, a 5xx, an upstream's refusal and a name no adapter serves. A 4xx the motty itself gave and a caller leaving write nothing. A report that throws or rejects is written too, with the failures of the record it lost. Masking learns a secret of no known shape from its value in process.env, if that value has at least 8 characters, so on Workers it relies on nodejs_compat with a compatibility date of 2025-04-01 or later, which is what fills process.env.

A host also refuses at start a motty with no route or handle, a bad settings override and a settings group the motty does not have. An async schema's verdict is only written to stderr, as a mount returns at once, and on Workers one that came during start waits for the first request as the warnings do.

In development, start the serve file with bun --watch src/serve.ts, the examples' bun run dev. Bun starts the process again on the same port whenever the motty or a file it imports changes, so the next request is answered by the new code, about 0.1 to 0.3 s later. An edit that does not load prints its error and leaves nothing listening until the file is fixed, when the server comes back by itself. This is for development only: a restart does not drain, and a request in flight is cut off, so a deployed host runs the serve file plainly.

Hosting with mount

mount takes the same options as the serve file above, a function of the environment. On Workers the environment holds the Worker's bindings once nodejs_compat is on and the compatibility date is 2025-04-01 or later; with an older date it is empty.

On Cloudflare Workers a mount is the module's default export. The third argument of fetch has the shape of a Workers execution context, so every record is waited for through ctx.waitUntil with no code of the host's. Turn on the nodejs_compat and enable_request_signal flags, the second so that a caller who leaves is noticed. A bundler other than Wrangler must leave node:* imports external.

export default mount(coder, options);

A host that has already authenticated and numbered a request states both in the third argument, fetch(request, undefined, { id, caller, waitUntil }), and the auth adapter is not asked. The namespace option prefixes every stored key in place of the motty's name, so two motties of one name sharing a storage keep apart when each is given its own namespace. report may return a promise, and the record is waited for until it settles.

A caller of the Responses API through the AI SDK sets providerOptions.openai.store to false, since a motty holds no Responses state on the server and refuses an item_reference.

Claude Code traffic through a motty with an Anthropic upstream is billed to the host's key as Claude Code usage. An Anthropic key that is refused for interactive Claude Code works when the harness is started with CLAUDE_CODE_ENTRYPOINT=sdk-cli.

Codex reaches a motty whose upstream is not OpenAI through a provider of its own that speaks the Responses API, in its config.toml:

model = "gpt-6.1-sol"
model_provider = "motty"
[model_providers.motty]
base_url = "http://127.0.0.1:3000/v1"
wire_api = "responses"
env_key = "MOTTY_KEY"

The SDK as a whole is described in the root README, and the reasons behind its design in ARCHITECTURE.md.

版本与发布记录

@mottyjs/serve 共发布 4 个版本,首次发布于 2026/10/12;过去 12 个月发布了 4 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.2.0latest2026/11/021 天前
0.1.12026/10/1321 天前
0.1.02026/10/1222 天前
0.0.0-stage2026/10/1222 天前

关于 @mottyjs/serve 的常见问题

@mottyjs/serve 是什么?

motty的主机端:在Bun或Cloudflare Workers上将其作为聊天完成、响应和消息api的模型。

如何安装 @mottyjs/serve?

在项目目录运行 npm install @mottyjs/serve,或使用 pnpm add / yarn add / bun add。

@mottyjs/serve 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@mottyjs/serve 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@mottyjs/serve 可以商用吗?

@mottyjs/serve 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@mottyjs/serve 还在维护吗?

最新版本 0.2.0 发布于 2026/11/02(1 天前);至今共发布 4 个版本,其中过去 12 个月发布了 4 个;首次发布于 2026/10/12。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。