# @chamvi/http 中文文档

规范地址：https://npmcn.com/package/%40chamvi/http/

版本：0\.8\.0
npm 元数据更新时间：2026-11-08T20:17:01.533Z
中文译文更新时间：2026-11-09T10:12:03.647Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40chamvi/http
原文对照：https://npmcn.com/package/%40chamvi/http/?lang=original
项目主页：https://chamvi.dev/
源码仓库：https://github.com/chamvi/chamvi

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：418 kB，7 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=26\.0\.0
- 运行依赖：20 个
- peer 依赖：@chamvi/core ^0\.8\.0
- 首次发布：2026-10-25T08:42:08.874Z
- 最新版本发布：2026-11-08T20:17:01.137Z
- 近 30 天下载量：3909（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：15（近 12 个月 15 个）

## 中文简介

REST,SSE,为chamvi代理服务的webhooks和MCP,在routup上.

## 安装

```sh
npm install @chamvi/http
```

也可以使用：`pnpm add @chamvi/http`、`yarn add @chamvi/http`、`bun add @chamvi/http`

## README

![@chamvi/http](https://raw.githubusercontent.com/chamvi/chamvi/master/.github/assets/logo.svg)

# @chamvi/http (中文(简体) )

**REST,SSE,为chamvi代理服务的webhooks和MCP,在routup上.**  
每个chamvi应用一个routup App:人类启动和跟踪运行在REST和SSE,  
频道收货 `/channels/<name>`,代理调用为 MCP 工具.

[![npm version](https://img.shields.io/npm/v/@chamvi/http)](https://www.npmjs.com/package/@chamvi/http) [![CI](https://github.com/chamvi/chamvi/actions/workflows/ci.yml/badge.svg)](https://github.com/chamvi/chamvi/actions/workflows/ci.yml) [![License](https://img.shields.io/npm/l/@chamvi/http)](https://github.com/chamvi/chamvi/blob/master/packages/http/LICENSE)

* * *

**目录**

-   [安装](https://npmcn.com/package/%40chamvi/http/#readme-installation)
-   [使用量](https://npmcn.com/package/%40chamvi/http/#readme-usage)
-   [终点](https://npmcn.com/package/%40chamvi/http/#readme-endpoints)
-   [权限](https://npmcn.com/package/%40chamvi/http/#readme-permissions)
-   [认证器](https://npmcn.com/package/%40chamvi/http/#readme-authenticators)
-   [频道](https://npmcn.com/package/%40chamvi/http/#readme-channels)
-   [MCP工具](https://npmcn.com/package/%40chamvi/http/#readme-mcp-tools)
-   [业务](https://npmcn.com/package/%40chamvi/http/#readme-operations)
-   [关闭](https://npmcn.com/package/%40chamvi/http/#readme-shutdown)
-   [选项](https://npmcn.com/package/%40chamvi/http/#readme-options)
-   [API 密码](https://npmcn.com/package/%40chamvi/http/#readme-api)
-   [许可证](https://npmcn.com/package/%40chamvi/http/#readme-license)

## 安装

```bash
npm install @chamvi/http @chamvi/core --save
```

仅限无害环境管理,节点.js `>=26.0.0`。 。 。 . `@chamvi/core` 是同龄人依赖; [错误](https://www.npmjs.com/package/routup) v6,该 [MCP 类型脚本 SDK](https://www.npmjs.com/package/@modelcontextprotocol/server) v2, (英语), [当然](https://www.npmjs.com/package/vouchly) 而认证服务器适配器则安装在软件包中.

## 使用量

`createHttpApp()` 返回 rout 键 `App`· ; `app.fetch(request)` 回答任何工作组 `Request`和鲁特的 `serve()` 监听端口:

```typescript
import type { LanguageModel } from 'ai';
import { Engine, createMemoryStore, defineModelAgent } from '@chamvi/core';
import {
    createHttpApp,
    createShutdown,
    http,
    httpChannel,
    mcpChannel,
    staticTokens,
} from '@chamvi/http';

export async function createAgentServer(model: LanguageModel) {
    const echo = defineModelAgent({
        name: 'echo',
        model,
        instructions: 'Answer with a short summary of the payload.',
        // http.on() lets REST (POST /agents/echo/runs) and MCP (run_echo) start runs
        channels: [http.on()],
    });

    const engine = new Engine({
        store: createMemoryStore(),
        agents: [echo],
        // REST runs carry channel http, MCP runs channel mcp
        channels: [httpChannel(), mcpChannel()],
    });

    const token = process.env.CHAMVI_TOKEN;

    if (!token) {
        throw new Error('Set CHAMVI_TOKEN (at least 16 characters).');
    }

    const shutdown = createShutdown({ engine });
    const app = createHttpApp({
        // routes read the store, the agents and the clock from the engine
        engine,
        auth: staticTokens({
            tokens: [{
                value: token,
                id: 'ci',
                permissions: ['*'],
            }],
        }),
        shutdown,
    });

    await engine.start();

    // serve it with routup (srvx); let createShutdown own SIGTERM:
    // const server = serve(app, { port: 3000, gracefulShutdown: false });
    // process.once('SIGTERM', () => shutdown.shutdown());
    return {
        app,
        engine,
        shutdown,
    };
}
```

每条路线都会回答JSON. 错误总是 `{ status, code, message, issues? }` (对于无与伦比的路线也是如此)一个5xx的身体说 `Internal Server Error` 和事业走向 `onError`。一个问题保持其 `received` 值只当这个字符最多为 256 个字符为 JSON 时,所以一个 400 个字符从未与一个大体相呼应( 超大小) `attachments` 列表,长 `address` 或媒体类型)后. 每401个 `WWW-Authenticate: Bearer`。 。 。 .

## 终点

路径相对 `basePath` (默认无).

| 方法和路径 | 权限 | 答复 |
| --- | --- | --- |
| `POST /agents/:name/runs` | `agent:<name>:run` | `202 { runId, deduplicated }`页: 1 `{ payload?, idempotencyKey?, address?, attachments? }`,键作为 `Idempotency-Key` 页眉; 代理 `http.on()` 订阅; 运行带载通道 `http` |
| `GET /runs` | `run:read`,或 `agent:<agent>:run` 与 `filter[agent]=<agent>` | `200 { data, meta: { total, limit, offset } }` |
| `GET /runs/:id` | `run:read` 或者说 `agent:<run.agent>:run` | `200` 运行加它 `steps` |
| `GET /runs/:id/stream` | 作为 `GET /runs/:id` | SSE : (英语) `run.updated`, (中文(简体) ), `step.appended` (单位:千美元)`id` =步骤指数, `delta` (实况模型输出,无 `id`, (中文(简体) ), `ping`; 运行结束后结束. `Last-Event-ID` 或者说 `?after=<step index>` 恢复; `503` 与 `Retry-After` 结束 `stream.maxOpen` |
| `GET /runs/:id/artifacts` | 作为 `GET /runs/:id` | `200 { data: Artifact[] }`: 运行附件和文件存储的工具 |
| `GET /runs/:id/artifacts/:artifactId` | 作为 `GET /runs/:id` | `200` 字节:存储的介质类型, `content-disposition: attachment` (法国法郎5987) `filename*` 当命名时, `nosniff`, (中文(简体) ), `private, no-store`· ; `404 artifact_not_found` 对于未知文物或另一跑步 |
| `POST /runs/:id/cancel` | `run:cancel` | `202 { runId, status }` |
| `POST /runs/:id/approve` | `agent:<run.agent>:approve` | `202 { runId, status: 'queued' }`页: 1 `{ approvalId, approved, reason? }`; 答对当前运行的等待点, 没有符号( 409 换到另一个) `approvalId`, 已过期的等待点或未等待的运行) |
| `POST /channels/<name>[/...]` | 频道本身 | 不管频道的 `in` 答案;仅针对 `channels` 选项(参见 [频道](https://npmcn.com/package/%40chamvi/http/#readme-channels)(中文(简体) ) |
| `GET /agents` | `run:read` | `200 { data: AgentSummary[], issues }`: 订阅 `{ channel, id, hook? }` (单位:千美元)`hook`: 订阅此应用程序挂载的 webhook 频道的路径, 预算, 状态收藏 ; `issues` 列出无法装入的代理 |
| `GET /schedules` | `run:read` | `200 { data: ScheduleSummary[] }`: 每笔订阅`@chamvi/channel-cron`是因为 `cron.on()`)及其信道和下个起火时间(来自定义,而不是运行中的调度器) |
| `GET /agents/:name/state/kv` | `state:read` | `200 { data: Array<{ key, value }> }` 以密钥编码点顺序; `page[limit]` (违约50起,最多100起), `page[offset]` |
| `GET /agents/:name/state/kv/:key` | `state:read` | `200 { key, value }` (单位:千美元)`null` 未设置时) |
| `PATCH /agents/:name/state/kv/:key` | `state:write` | `200 { key, value }`页: 1 `{ value }` |
| `GET /agents/:name/state/collections/:collection` | `state:read` | `200 { data }`,每个文档 `{ id, ...fields }` (非对象文件为: `{ id, doc }`); 顶层平等过滤器(`filter[status]=open`; 翻转 rapiq `42`, (中文(简体) ), `007`, (中文(简体) ), `true` 财务报告和审定财务报表 `null` 输入数字, 布尔或无效, 因此双引出一个值来匹配其为字符串 : `filter[issue]="42"`, (中文(简体) ), `page[limit]`· ; `id` 是存储 id,不是文档字段,所以 `filter[id]` 为 400;a `page[offset]` 0以上为400(仅限存储页) |
| `GET /me` | 认证 | `200 { id, kind, name?, permissions }`: 呼叫者本身(名称作为援引者记录),只有自己允许 |
| `/mcp` | 认证 | MCP的终点(参见 [MCP工具](https://npmcn.com/package/%40chamvi/http/#readme-mcp-tools)(中文(简体) ) |
| `GET /healthz` | 无 | `200 { status: 'ok' }` |
| `GET /readyz` | 无 | `200`,或 `503 { status: 'unavailable', reason }` 与 `shutting-down`, (中文(简体) ), `draining` 或者说 `store-unreachable` |
| `GET /metrics` | 无 | 普罗米修斯文本格式 |

`GET /runs` 拿着 [拉皮克语](https://www.npmjs.com/package/@rapiq/codec-url) URL 语法 : `filter[agent]=triage`, (中文(简体) ), `filter[status]=queued,running`, (中文(简体) ), `page[limit]=20` (违约50起,最多100起), `page[offset]=40` 财务报告和审定财务报表 `sort=createdAt` (最古老的,默认)或 `sort=-createdAt` (最新第一). 表达式方言也起作用( :`filter=eq(agent,'triage')`; 仅加入过滤器 `and` 被支持。 未知的密钥, 运算符和类型 回答 400 .

机构是JSON(`application/json` 或者说 `*+json`),最多时 `bodyLimit` 字节( 上面413个, 另一种介质类型为 415个) 。 被拒绝的尸体被排出(至多 `bodyLimit` 更多字节),所以保持-活性连接服务于下个请求;一个较长的连接会关闭连接. 一个受保护的路由在读取正文之前检查了无记名符号,所以一个未经认证的客户端不能让服务器缓冲. 未知的正文密钥被丢弃而不出错 。 NUL 字符 (U+000, Postgres 文本列拒绝此字符) 在 URL 中, 在一个 `idempotencyKey`, (中文(简体) ), `address` 或其他字符串字段,或者在密钥中,网钩来自其有效载荷答案400.

`attachments` 最多取取16个文件 `{ mediaType, filename?, data }`数字 : `mediaType` 实值 `type/subtype` 没有参数, `filename` 1到255个字符, `data` 严格的基数64(加法、标准字母、无白空格);其他的都是400 `validation_error` 与球场的路径, 和什么也没有发出。 这些文件作为运行的文物被存储(参见: `@chamvi/core`),并交给模型作为文件部件. 基地64骑 在JSON的身体,所以 `bodyLimit` 也绑定文件 .

`GET /runs/:id` 403前的答案 404,所以任何认证的正本都可以分辨是否存在运行的ID;运行的ID是随机的UUID. 在铁丝网上跑来跑去的 `claim` (所有权和租赁).

`POST /agents/:name/runs` 和 MCP 软件 `run_<agent>` 将认证的本金记录为运行的援引者(`run.trigger.invoker`数字 : `id`, (中文(简体) ), `kind`, (中文(简体) ), `permissions`,则a `name` 从 `name` 或者说 `preferred_username` 索赔,从未 `email`,因为每个读取器看到它;静态符号没有),所以工具代码和一个核心 `toolPolicy` 能分辨是谁发动了这次逃亡. `POST /runs/:id/approve` 和 MCP 软件 `approve_run` 将批准人记录在 `wait` 步数( e)`output.approver`) (中文(简体) ). 两者都只来自认证者,从不来自一具尸体. Webhook 运行没有引用器 。 请求人和批准人离开包件(REST、SSE、MCP),而无需他们 `permissions`,所以一个 `run:read` 持有者从不学习另一本金.

SSE 流跟随运行 `engine.on` 和民意测验 商店每 `stream.pollMs` (default 2 s)),因此它也会在另一个复制品上看到运行执行. `delta` 活动(`data: { step, kind: 'text' | 'reasoning', text }`) 前进引擎的 `run.delta` 当模型写(`step` 是该 `llm` 步骤生成(每个模式调用一个),而不是 `step.appended` `id`,这也算 `tool` 财务报告和审定财务报表 `wait` 他们没有 `id` (单位:千美元)`Last-Event-ID` 继续保留一个步骤索引),从不重放,只来自执行运行的复制品. `Last-Event-ID` 步骤索引后恢复;查询 `?after=<step index>` 对于不能设置头号的客户端(一个非负整数,给定一次,否则为400个)也这样做。 当两者都存在时 `Last-Event-ID` 胜出, 因为它包含客户端在重新连接上的进展, 而 URL 则保持第一个连接; 错误的 `Last-Event-ID` 读作缺席 `?after` 适用.

溪流只取无记名符. 浏览器 `EventSource` 无法发送 `Authorization` 标题,所以浏览器会读取以获取为基础的SSE读取器(`fetch` 附加一个 SSE 解析器以覆盖响应体 ) `Authorization` 当它重新连接的时候, `Last-Event-ID` 最后一个 `id` (或 `?after=`) (中文(简体) ).

每个应用程序都覆盖开放的SSE流和MCP `run_<agent>` 呼唤等待`waitSeconds` (单位:千美元) `stream.maxOpen` (默认1000,两个都有一个计数器). 盖子上的一股流回音 `503 { code: 'service_unavailable' }` 与 `Retry-After: 5` (未报告) `onError`; MCP 调用上限不会等待并立即以 `{ runId, status, deduplicated }`,如同 `waitSeconds: 0`,因为它已经发出运行。 当流结束( 确定运行、 客户端消失、 失败、 关闭) 或等待答案时, 空出一个空格 ; 一个客户端在没有请求信号中止的情况下取消机体在下次写入时释放它 `stream.pollMs`。 。 。 .

## 权限

| 权限 | 赠款 |
| --- | --- |
| `agent:<name>:run` | 开始代理运行(REST, `webhookChannel()` 交付, MCP `run_<name>`并读取它们 |
| `agent:<name>:approve` | 答复代理人的核准(`POST /runs/:id/approve`, MCP 软件 `approve_run`(中文(简体) ) |
| `run:read` | 阅读和列出每次运行、代理和时间表 |
| `run:cancel` | 取消运行 |
| `state:read`, (中文(简体) ), `state:write` | 读写代理状态 |
| `*` | 所有东西 |

A 类 `*` 段完全匹配一个段 : `agent:*:run` 赠款 `agent:triage:run` 但没有 `agent:triage:approve`,以及 `agent:*` 也没有赠款。 匹配是区分大小写. `agentPermission(agent, action)` 导出; 自己检查本金, 使用 `hasPermission(principal.permissions, permission)` 从 `@chamvi/core`路线使用的匹配器.

`POST /runs/:id/approve { approvalId, approved, reason? }` 单凭批准权限回答当前等待点; 另一条 `approvalId` 而不是跑的当前,一个已过期的等待点,一个没有等待的跑和第二个答案是409.

## 认证器

`auth` 使用一个认证器或链;第一个主胜。 认证器决定 `undefined` 对于它不承认的请求(链条在继续),它会拒绝401个证书。 解决的本金需要非空的 `id` 财务报告和审定财务报表 `kind` (单位:千美元) `permissions` 数组字符串; 其它任何东西都是服务器配置错误( 500, 报告给) `onError`)并结束链.

```ts
const ciToken = process.env.CI_TOKEN;
auth: [
    // static tokens first: authup() in remote mode introspects every non-JWT bearer
    ...(ciToken ?
        [staticTokens({
            tokens: [{
                value: ciToken,
                id: 'ci',
                permissions: ['agent:deploy:run'],
            }],
        })] :
        []),
    // an authup TokenVerifier in remote mode (with a creator), so tokens carry their grants
    authup({ verifier }),
    oidc({ issuers: [githubActions], principal: mapGithubClaims }),
],
```

-   **`staticTokens({ tokens: [{ value, id, permissions }] })`**:无记名标志(`value`)至少16个字符,相较于SHA-256文摘. A 类 `value` 可能出现一次;若干个符号可能共享 `id`,因此一个旋转的令牌可以与旧令牌相重叠. 符合CI和服务账户。 放进去 **在此之前** `authup()` 财务报告和审定财务报表 `oidc()`数字 : `authup()` 在远程模式下,将每个不是JWT的持卡人发送到认证服务器的内向端点,因此在每次请求时都会向服务器泄露后放入一个静态符号.
-   **`authup({ verifier })`**:通过核查 `@authup/server-adapter-web`。只在其 `scope` 包含 `global`其他信使保留他们的身份,却一无所获(因此他们回答403)。 本地核查总是不能产生许可:赠款需要远程模式(`creator`,内论. 权限 `policies`, (中文(简体) ), `realm_id` 财务报告和审定财务报表 `client_id` 不予评价。 缓存( Caching): 缓存结果会送达到符号 `exp`,所以在本地模式下,它比已禁用的签名密钥有效,而在远程模式下,则比已取消的令牌有效(`maxRemoteCacheTTL` 边框远程缓存; 无 `cache`没有缓存.
-   **`oidc({ issuers, principal })`**: 任何 OIDC 发行者通过担保,例如 GitHub 动作符. 每个发行商都需要一个 `audience` (碰巧跳过 `aud` 不检查一个,所以一个公共发行人 的标志任何观众通过; `oidc()` 以其他方式投掷). `principal` 实值 **所需经费** 并将经核实的索偿要求映射给本金(或 `undefined` 拒绝:公众发行商让任何人为观众铸造一个纪念物 `sub` 或者说 `repository` 获得哪些补助。 未配置到下个验证器的发证人发证;无法到达的发证人回答503.

## 频道

代理订阅频道`defineModelAgent({ channels: [...] })`,参见 `@chamvi/core`); 引擎持有通道实例(`new Engine({ channels })`) (中文(简体) ). 这个包裹三号船:

-   **`httpChannel()`** (名称) `http`和 **`mcpChannel()`** (名称) `mcp`: 没有 `in`,没有 `out`。 。 。 . **`http.on({ schema? })`** 是控制平面订阅( id `http`中,每个代理最多一个: `POST /agents/:name/runs` 开始作为频道运行 `http`,和 MCP 软件 `run_<name>` 作为频道 `mcp`,所以两者保持单独的同能范围. 一个没有它的代理在REST上回答404,没有获得MCP工具. `schema` (任何标准Schema)验证有效载荷;故障回答400与 `issues`。引擎拒绝 `http.on()` 订阅,除非持有 `httpChannel()`。 。 。 .
-   **`webhookChannel({ auth, name?, bodyLimit? })`** (名称) `webhook` 默认 : **`webhook.on(path, { schema?, idempotencyKey?, concurrencyKey? })`** (单位:千美元) `webhook:<path>`(每个代理商中有许多人)在代理商的手下按自己的路径提供服务: `webhook.on('/issues')` 关于代理人 `intake` 实值 `POST /channels/webhook/intake/issues`,路径 `/` 实值 `/channels/webhook/intake` (单位:千美元)`GET /agents` 每个列表 `hook` URL) (中文(简体) ). 比赛是准确的, 包括了后遗症。 交货需要主要 `auth` (一个认证器或一个链条,作为应用程序的) `auth`; 需要, 因为应用程序从未认证频道路线) 持有 `agent:<agent>:run`,在读取尸体前检查。 尸体是JSON价值最多 `bodyLimit` 字节(默认为 1 MiB;上方为413,为另一种介质类型为415),是有效载荷. 独能键来自 `Idempotency-Key` 信头,其他来自 `idempotencyKey(payload)`;用一键再试出货,产生一跑. 它立即回答202, 并且从不同步运行代理; 运行不携带引用器 。 二审(`webhookChannel({ name: 'hooks', auth })`(b) 自行订阅 `on()`。签名验证的网络呼号(GitHub)是 `@chamvi/github`频道.

`createHttpApp({ channels })` 挂载 `POST /channels/<name>` 财务报告和审定财务报表 `POST /channels/<name>/...` (每个频道都需要一个) `in` 并且必须是引擎在其名称下持有的对象;否则 `InvalidAgentDefinitionError`) (中文(简体) ). 这些路线是限速的,但从未被应用认证:每个频道检查自己的资质. `in({ request, subpath }, ctx)` 获取原始请求( 未读; 用此软件包读取) `readRequestBody(request, { limit })`,它回答超过极限的413,并关闭连接)和生子路径(`''` 对于赤裸的路径, 否则从 `/`,仍然以百分比编码) `ctx.dispatch` 作为频道发送。 内容 `Response` 已按原样发送; 抛出的错误会像任何路径的错误。 任何其他 `/channels/...` 路径为 404.

## MCP工具

`/mcp` 是一个可流式的HTTP MCP端点(MCP TypeSDK v2;2025-时代的客户端在无国籍状态下得到服务),具有与REST相同的无记名认证. 客户所看到的工具取决于其主因:

| 工具 | 投入 | 答复 |
| --- | --- | --- |
| `run_<agent>` | `{ payload?, idempotencyKey?, address?, waitSeconds? }` | `{ runId, status, deduplicated, output?, error?, waiting? }` |
| `get_run` | `{ runId }` | 运行( 如 `GET /runs/:id`,没有步骤) |
| `list_runs` | `{ agent?, status?, limit?, offset? }` | `{ data: RunSummary[], total }` |
| `approve_run` | `{ runId, approvalId, approved, reason? }` | `{ runId, status: 'queued' }` |

-   `run_<agent>` 列出每个代理人,并附有 `http.on()` 订阅主机可运行( 运行带频道) `mcp`页:1 `payload` 带有订阅图的 JSON Schema( 本地 `$ref`重新扎根于 `payload`) (中文(简体) ). 工具定义在 `createHttpApp`,该投出 `InvalidAgentDefinitionError` 对于有效载荷计划, MCP 验证器无法编译或工具名称高于 MCP 允许的 64个字符( 代理名称高于 60; 设置) `mcp: false` 保留它. `waitSeconds` (默认 0) 等待 `completed`, (中文(简体) ), `failed`, (中文(简体) ), `cancelled` 或者说 `waiting`最多 `mcp.maxWaitSeconds` (默认 60; 较大值被夹住). 等待一个应用程序的 `stream.maxOpen` 插槽; 全部同时带回调用 `{ runId, status, deduplicated }`一样 `waitSeconds: 0`,运行开始。 等待者每隔一秒钟就对商店进行民意测验,所以在另一个复制品上看到跑步被处决,当客户离开时就停止. A 类 `waiting` 回答工具的名称和批准 `title` 财务报告和审定财务报表 `body`。 。 。 .
-   同上,propotency keys是每个代理商、信道和主机的范围: MCP 启动取消 `<agent>:mcp:<kind>:<id>`,在 `<agent>:http:<kind>:<id>` (校长的 `kind` 财务报告和审定财务报表 `id`, URI- encoded)),所以在两种运输方式上使用的一键,或者由两个主键,创建了两跑. Webhook 开始在下面不带引用器和调试器 `<agent>:webhook`。 。 。 .
-   `get_run` 财务报告和审定财务报表 `list_runs` 遵循 REST 读取规则; 被拒绝的权限和未知的运行作为工具错误返回( )`isError`) (中文(简体) ).

## 业务

-   **`/metrics`** 不认证(scrapers 很少发送无记名符号): 防止公众侵犯(网络政策,或单独的内部倾听者),或使其无法使用 `metrics: false`。每个应用程序都有自己的 `prom-client` `Registry`; 数据 `path` 标签是路由模板(`/runs/:id`, (中文(简体) ), `/channels/:name/*`; 未知路径为 `/_unmatched`),所以ids和探测器不是薄荷系列. SSE流和限速请求没有定时. `metrics.normalizePath` 覆盖标签.
-   **费率限制**默认每个客户地址每分钟300个请求, `/healthz`, (中文(简体) ), `/readyz`, (中文(简体) ), `/metrics` 和CORS的飞行前。 关键是套接字地址, 除非 `trustProxy` 设置:在反向代理后,设置(例如:. `'loopback'` 或一个hop计数)或每个客户共享代理的桶; `X-Forwarded-For` 从来没有信任过。 没有套接字地址( 正在进行中) `app.fetch`, unix sockets) 所有客户共享一桶.
-   **(简体中文)** 关闭,除非 `cors` 已提供(`@routup/cors` 选项).
-   **准备情况** 关闭时失败, 引擎会排出, 或商店内部不回答 `readyTimeoutMs`。 。 。 .

## 关闭

`createShutdown()` 运行关闭顺序 : 无法准备, 等待 `readinessDelayMs`运行 `onShutdown` 按添加顺序调回( http app的自有端打开 SSE 流和 MCP) `run_<agent>` 等待(以存储的运行方式等待答案),关闭 MCP;新流和 MCP 请求然后回答 503 , 停止接受连接, `engine.drain()` (它先是停止每个频道,其中的曲折排程) 然后最多等待 `closeTimeoutMs` 在关闭前打开连接。 过 `gracefulShutdown: false` 改为 `serve()` 因此 srvx 不安装自己的信号处理器 :

```ts
import { serve } from 'routup';

let server: ReturnType<typeof serve> | undefined;
const shutdown = createShutdown({
    engine,
    // the server is created after the app; the helper only calls close() at shutdown
    server: { close: async (force) => { await server?.close(force); } },
});
const app = createHttpApp({ engine, auth, shutdown });
server = serve(app, { port: 3000, gracefulShutdown: false });

process.once('SIGTERM', () => {
    void shutdown.shutdown();
});
```

`shutdown.onShutdown(fn)` 添加您自己的清理; 在准备失败后和服务器关闭前运行 .

## 选项

`createHttpApp(options)`数字 :

| 选项 | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| `engine` | `IEngine` | 所需经费 | 调度、取消和恢复运行 `store`、代理人和 `clock` 服务每个路线(运行、步骤和状态从 `engine.store`民意测验、等待和暂停 `engine.clock`(中文(简体) ) |
| `agents` | `string[]` | 每个代理 | 引擎的代理商名称 此应用程序服务( 路由, MCP 工具, 附加路线); 其他的则未知 。 一个挂载的频道为每一个签署该频道的代理人服务. 引擎缺少或两次丢出的名称 `InvalidAgentDefinitionError` |
| `auth` | `Authenticator | Authenticator[]` | 所需经费 | 认证链 |
| `basePath` | `string` | 无 | 每条路线的前缀,例如:. `/api` |
| `trustProxy` | routup 信任代理输入 | 无 | 代理客户端地址( 和利率限制密钥) 信任 |
| `shutdown` | `IShutdown` | 无 | 失败者 `/readyz` 关闭时结束流 |
| `bodyLimit` | `number` | `1_048_576` | REST 或 MCP 请求机构可能有字节 |
| `stream.pollMs` | `number` | `2_000` | SSE流的仓库调查 |
| `stream.maxOpen` | `number` | `1_000` | 打开 SSE 流加等待 MCP `run_<agent>` 每个应用程序的呼叫; 正整数, 否则 `createHttpApp` 掷出 `InvalidAgentDefinitionError` |
| `mcp` | `false | { name?, version?, maxWaitSeconds? }` | `chamvi`, (中文(简体) ), `0.0.0`, (中文(简体) ), `60` | MCP 服务器信息和等待盖; `false` 无挂载 |
| `cors` | `false | CorsOptions` | 关 | `@routup/cors` 选项 |
| `rateLimit` | `false | Partial<RateLimitOptions>` | 每分钟300美元 | `@routup/rate-limit` 选项 |
| `metrics` | `false | Partial<PrometheusOptions>` | `/metrics` | `@routup/prometheus` 选项 |
| `readyTimeoutMs` | `number` | `2_000` | 多长时间 `/readyz` 等着商店 |
| `onError` | `(error) => void` | `console.error` | 5xx原因和背景失败 |
| `channels` | `IChannel[]` | 无 | 频道服务于 `POST /channels/<name>` 及以下(参见 [频道](https://npmcn.com/package/%40chamvi/http/#readme-channels));每个都需要一个 `in` 并且必须是引擎名下的物品 |
| `routes` | `HttpRoute[]` | 无 | 其他软件包的附加路线(例如:. `@chamvi/ui`仪表板,服务于 `basePath` 无 `auth` 除非处理者打电话 `request.authorize(permission?)` (401/403 如内置路线); 静态路径, 从未在内置路线的第一段或公尺路径( 对大小写不敏感) 下, `rateLimit: false` 跳过限制; `prefix: true` 也为下面的每一条路服务 `path/` (其余为 `request.subpath`; 标尺标签 `<path>/*`;该方法在它或在其之下、在测量路径上或以上的任何其它路线;结果可以携带 `headers` (单位:千美元) `Uint8Array` 机构(同意的原文如下:, `application/octet-stream` ; 路由上下文已经 `basePath` |

`createShutdown(options)`数字 :

| 选项 | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| `engine` | `IEngine` | 所需经费 | 关闭期间排水 `clock` 驱动延迟 |
| `server` | `{ close(force?): Promise<void> }` | 无 | Srvx 服务器 |
| `readinessDelayMs` | `number` | `0` | 负载平衡器看到失败准备的时间 |
| `drainTimeoutMs` | `number` | `30_000` | 传到 `engine.drain()` |
| `closeTimeoutMs` | `number` | `5_000` | 等待打开的连接, 然后关闭 |
| `onError` | `(error) => void` | `console.error` | 未恢复和关闭 |

## API 密码

| 导出 | 仁爱 | 目的 |
| --- | --- | --- |
| `createHttpApp` | 函数 | 构建 Routup 应用程序 |
| `createShutdown` | 函数 | 优雅的关机助手 |
| `staticTokens`, (中文(简体) ), `authup`, (中文(简体) ), `oidc` | 函数 | 认证器 |
| `httpChannel`, (中文(简体) ), `mcpChannel`, (中文(简体) ), `webhookChannel` | 函数 | REST、MCP和通用网络呼号发送频道 |
| `http`, (中文(简体) ), `webhook` | 常数 | 订阅构建器 : `http.on({ schema? })`, (中文(简体) ), `webhook.on(path, options?)` |
| `HTTP_CHANNEL_NAME`, (中文(简体) ), `MCP_CHANNEL_NAME`, (中文(简体) ), `WEBHOOK_CHANNEL_NAME` | 常数 | `http`, (中文(简体) ), `mcp`, (中文(简体) ), `webhook` |
| `agentPermission` | 函数 | `agent:<agent>:<action>` (比对是核心) `hasPermission`(中文(简体) ) |
| `Permission` | 常数 | `ALL`, (中文(简体) ), `RUN_READ`, (中文(简体) ), `RUN_CANCEL`, (中文(简体) ), `STATE_READ`, (中文(简体) ), `STATE_WRITE` |
| `DEFAULT_SHUTDOWN_DRAIN_TIMEOUT_MS`, (中文(简体) ), `DEFAULT_SHUTDOWN_CLOSE_TIMEOUT_MS` | 常数 | `30_000`, (中文(简体) ), `5_000` |

类型 : `HttpAppOptions`, (中文(简体) ), `McpOptions`, (中文(简体) ), `CorsOptions`, (中文(简体) ), `RateLimitOptions`, (中文(简体) ), `PrometheusOptions`, (中文(简体) ), `TrustProxyInput`, (中文(简体) ), `Principal`, (中文(简体) ), `Authenticator`, (中文(简体) ), `PermissionName`, (中文(简体) ), `AgentAction`, (中文(简体) ), `StaticToken`, (中文(简体) ), `StaticTokensOptions`, (中文(简体) ), `AuthupOptions`, (中文(简体) ), `OidcOptions`, (中文(简体) ), `IShutdown`, (中文(简体) ), `ShutdownOptions`, (中文(简体) ), `RunView`, (中文(简体) ), `InvokerView`, (中文(简体) ), `RunListQuery`, (中文(简体) ), `RunSummary`, (中文(简体) ), `RunToolResult`, (中文(简体) ), `AgentSummary`, (中文(简体) ), `ScheduleSummary`, (中文(简体) ), `ScheduleOverlap`, (中文(简体) ), `WebhookChannel`, (中文(简体) ), `WebhookChannelOptions`, (中文(简体) ), `HttpSubscriber`, (中文(简体) ), `HttpSubscriptionOptions`, (中文(简体) ), `WebhookSubscriber`, (中文(简体) ), `WebhookSubscriptionOptions`。 。 。 .

## 许可证

原载 [Apache 许可证 2.0](https://npmcn.com/package/%40chamvi/http/LICENSE)。 。 。 .

## 常见问题

### @chamvi/http 是什么？

REST,SSE,为chamvi代理服务的webhooks和MCP,在routup上\.

### 如何安装 @chamvi/http？

在项目目录运行 npm install @chamvi/http，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@chamvi/core（^0\.8\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @chamvi/http 支持 TypeScript 吗？

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

### @chamvi/http 支持 ESM 还是 CommonJS？

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

### @chamvi/http 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=26\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @chamvi/http 可以商用吗？

@chamvi/http 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @chamvi/http 的下载量有多少？

根据 npm 官方下载统计，@chamvi/http 在 2026/10/10 – 2026/11/08 这 30 天内被下载 3,909 次，日均约 130 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @chamvi/http 还在维护吗？

最新版本 0\.8\.0 发布于 2026/11/09（今天）；至今共发布 15 个版本，其中过去 12 个月发布了 15 个；首次发布于 2026/10/25。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

