# @reinsjs/lowering-fetch 中文文档

规范地址：https://npmcn.com/package/%40reinsjs/lowering-fetch/

版本：0\.5\.1
npm 元数据更新时间：2026-11-02T06:36:05.062Z
中文译文更新时间：2026-11-02T08:45:24.837Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40reinsjs/lowering-fetch
原文对照：https://npmcn.com/package/%40reinsjs/lowering-fetch/?lang=original
项目主页：https://github.com/AdRate-io/reins/tree/main/packages/lowering-fetch#readme
源码仓库：https://github.com/AdRate-io/reins

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

- 包体积（解压后）：399 kB，7 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22
- 运行依赖：1 个
- 首次发布：2026-09-15T07:37:55.058Z
- 最新版本发布：2026-11-02T06:36:04.869Z
- 已发布版本数：7（近 12 个月 7 个）

## 中文简介

缰—获取上的零依赖降低层：事件当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种的当下一种

## 安装

```sh
npm install @reinsjs/lowering-fetch
```

也可以使用：`pnpm add @reinsjs/lowering-fetch`、`yarn add @reinsjs/lowering-fetch`、`bun add @reinsjs/lowering-fetch`

## README

# @reinsjs / lowering-fetch

的零依赖降低层 [缰绳](https://npmcn.com/package/README.md)：时间线事件→提供程序连接协议→事件草稿，只使用 `fetch` 以及一个手写的SSE解析器。没有供应商SDK，没有 `node:*`在Node、Workers、Deno和Bun上使用相同的代码。

三种有线协议： **OpenAI聊天完成** （兼容openai生态系统的前门：DeepSeek、Qwen、vLLM、网关） **人为的消息** （会话中系统放置，签名思考重播，显式缓存断点）和 **OpenAI反应** (无状态 `store: false`、加密推理回放、开发者消息等)。

```bash
pnpm add @reinsjs/lowering-fetch
```

```ts
import { anthropic, anthropicMessages, deepseek, openai, openaiChat, openaiResponses, chatCompletions } from "@reinsjs/lowering-fetch"
import { createAgent } from "@reinsjs/agent"

const opus = anthropic("claude-opus-5", { apiKey: process.env.ANTHROPIC_API_KEY! })
const ds = deepseek("deepseek-flash", { apiKey: process.env.DEEPSEEK_API_KEY! })
const gpt = openai("gpt-5-mini", { apiKey: process.env.OPENAI_API_KEY!, requestOptions: { reasoning: { effort: "low", summary: "auto" } } })
const mini = openaiChat("gpt-4o-mini", { apiKey: process.env.OPENAI_API_KEY! })
// any Anthropic-protocol endpoint (DeepSeek's compatible port, a gateway)
const dsClaude = anthropicMessages("deepseek-v4-flash", {
  provider: "deepseek",
  baseUrl: "https://api.deepseek.com/anthropic",
  apiKey: process.env.DEEPSEEK_API_KEY!,
  reasoning: true,
  midConversationSystem: true,
})
const qwen = chatCompletions("qwen-max", {
  provider: "qwen",
  baseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1",
  apiKey: process.env.DASHSCOPE_API_KEY!,
  contextWindow: 128_000,
})

export const agent = createAgent({ model: ds, store, tools })
```

每个工厂返回一个 `BoundModel = { model, lowering }`. `apiKey` 是必需的，并且从不从环境中读取。对于一个降低实例上的多个模型，构造 `FetchLowering` 你自己和传球 `models`.

## 选择 `@reinsjs/lowering-fetch` 和 `@reinsjs/lowering-pi`

两者实现相同 `Lowering` 界面与 `@reinsjs/core` 每一次降落都是a `LOSS_MATRIX`； `createAgent` 不在乎你经过哪一个。它们是有意共存的——选择每个主机，而不是每个项目。

|  | `@reinsjs/lowering-fetch` | `@reinsjs/lowering-pi` |
| --- | --- | --- |
| 协议 | OpenAI聊天完成，Anthropic消息，OpenAI响应 | Anthropic Messages, OpenAI Responses |
| 延期工具（人为的） `defer_loading` + `tool_reference`，用于 `lazyTools()`） | 是的, `capabilities.deferredTools` 官方Anthropic模型 | 没有（请求整形是pi-ai的；引用以文本形式呈现） |
| 依赖关系 | `@reinsjs/core` 仅（≈90 KB的ESM） | `pi-ai` 及其10个依赖项（安装约65 MB） |
| 请求体 | `payload.body` 是发送的内容 | pre-rewrite形状;真正的身体是在pi-ai中产生的 `onPayload` 钩 |
| 在交谈 `system` 在人为 | 由编码器放置 | 通过重写pi-ai的有效载荷来放置 |
| 无符号思维 | `dropped` (声明) | 可以退回到可见文本 |
| 模型表 | 每个模型覆盖的最小内置表 | Pi-ai的桌子，维护在上游 |
| 运行时 | 在最严格的层（2023兼容日期，no . 5）的Cloudflare workerd上验证 `nodejs_compat`)、Bun、Deno (`--allow-net` 只有)和Vercel `edge-runtime`，针对实时提供商的所有三个协议 | 在相同的四个运行时上验证，两个协议；Deno需求 `--allow-sys=osRelease`， Edge运行时需要 `process` OpenAI路径的全局 |

**从……开始 `lowering-fetch`** 对于一个新主持人来说，它涵盖了一切 `lowering-pi` 覆盖和openai兼容的生态系统，除了这个包什么都没有，你调试的请求就是发送的请求。呆在 `lowering-pi` 当您已经在它上运行时（没有什么需要迁移的），或者当您希望提供程序表和新的有线协议特性通过pi-ai而不是通过这个包到达时。由一层编写的事件通过另一层重放： `replay.thinkingSignature` 在两者上使用相同的形状，因此切换不会使存储的时间轴失效。

## 运行时

否 `node:*`,没有 `process`,没有 `Buffer` -一样 `dist/index.js` 运行在节点≥22和Cloudflare worker上的2023 `compatibility_date` 没有兼容性标志(`spikes/edge-runtime-check`层：模块负载，针对本地假端点的字节切片SSE流，以及每个协议一个实时请求)。Bun 1.4, Deno 2.9（仅限） `--allow-net` 需要-层不读取系统信息)和Vercel的 `edge-runtime` (裸vm，不 `process`,没有 `eval`)通过相同的探测，所有三个协议都针对活动提供商(`spikes/runtime-matrix`）。

## 选项

| 选项 | 意义 |
| --- | --- |
| `apiKey` | 要求;使用 `auth: "none"` 当凭证存在时 `headers` (Cloudflare AI Gateway的 `cf-aig-authorization`） |
| `baseUrl` | 协议根; `/chat/completions` (OpenAI: `…/v1`（DeepSeek：裸主机）； `/messages` (人为: `…/v1`)或 `/responses` (OpenAI: `…/v1`)是附加的 |
| `contextWindow`， `maxOutputTokens`， `reasoning`， `images`， `cost`， `midConversationSystem` | 覆盖内置表；未知模型从保守默认值开始（128k / 16k /无推理/无图像） |
| `chat.reasoningContent` | DeepSeek方言：重放 `reasoning_content` (默认在 `deepseek()`，见下文) |
| `chat.liftToolImages` | 当模型获取图像时，将工具结果中的图像移动到a中 `user` 消息后的批次 `tool` 消息(默认 `true`）; 集 `false` 对于上游，拒绝形状和图像再次成为占位符 |
| `anthropic.betas` | 的值 `anthropic-beta` 头;只在设置时发送（会话中系统不需要） |
| `anthropic.cacheBreakpoints`， `anthropic.cacheTtl`， `anthropic.midSystemCacheBreakpoint` | 显式缓存断点在Anthropic（默认开启，5分钟）；当请求结束时该怎么办 `"automatic"` (默认,顶级 `cache_control`)， `"previous-user"`， `"drop"` |
| `anthropic.deferredTools` | 是否 `ToolSpec.deferLoading` 变成了 `defer_loading: true` 和 `tool_reference` 内容部分变成原生的 `tool_reference` 块。默认值：开启 `provider: "anthropic"`，对于第三方Anthropic-protocol端点（DeepSeek的兼容端点忽略）关闭 `defer_loading`，所以每个工具都是可见的)。当关闭时，延迟的工具将不会被发送，并且引用将被呈现为文本 |
| `responses.systemRole` | 应答中的系统提示和注释的角色：default `developer` 对于推理模型， `system` 否则;把它钉在上游，拒绝其中一个 |
| `responses.encryptedReasoning` | 推理模型默认为： `include: ["reasoning.encrypted_content"]` 是不是总是发这样的推理题下可以重播 `store: false`;关闭拒绝的上游 `include` (当时 `thinkingReplay` 报告 `false`） |
| `requestOptions` | 扩散到体内(`max_tokens`， `temperature`， `thinking`, OpenAI `parallel_tool_calls`,反应 `reasoning` / `max_output_tokens` / `prompt_cache_key`…); `messages` / `input` / `tools` / `system` / `model` / `stream` / `store` / `previous_response_id` 不能被覆盖。在人为 `max_tokens` 默认为模型的 `maxOutputTokens` 和 `thinking` 留给你(Opus 5+默认为自适应服务器端；Haiku 4.5仍然需要 `budget_tokens`）; 在反应 `reasoning` 你的(gpt-5默认值是？ `medium`， gpt-5.1+ to `none`） |
| `timeoutMs` | 整个请求截止日期包括流，默认为600000；超时是一个可重试的错误，一个主机 `signal` 流产是 `aborted` |
| `trustMarkers` | 默认开启：工具输出被封装在 `<untrusted source="tool:…">` 在请求中；日志保存原件 |

## 事件如何在聊天完成时发生

每次降落都要申报 `LOSS_MATRIX["openai-chat"]` 并由测试断言——没有什么是无声地掉落的。

-   `system_note` →谈话中途 `system` 消息(`exact`;在OpenAI和DeepSeek上验证)。集 `midConversationSystem: false` 如果上游拒绝了它，音符就会以框架的形式发出 `user` 消息(`lossy`）. 一张写着 `directive: true` (模型必须执行的指令，例如 `compact`（他的请求）总是被框出去 `user` 消息，在所有三个协议上。
-   当工具结果仍然挂起时到达的用户消息或注释在连线上移动到它们之后(`tool` 消息必须直接跟随 `assistant` 这叫他们)；记录用户留言 `lossy(user)`，日志顺序不变。
-   **思考**聊天完成没有重放槽（没有签名，没有加密项目）。关于官方API的思考事件是 `dropped`． 与 `chat.reasoningContent` （DeepSeek）它们被重播为 `reasoning_content` ——和DeepSeek _需要_ 每条历史助理信息上的字段 `tools` 是存在的（否则是400），所以层总是发送它，当没有什么可重放时为空。
-   一个回合与几个文本块合并为一个回合 `content` 字符串(`lossy(merged-text)`); `tool` 消息只携带文本：当模型拍摄图像时，每个图像都会留下一个指针(`[image n attached in the next user message]`)，这些图像合二为一 `user` 整批后的消息 `tool` 消息-在批处理后移动的任何用户消息之前-每个结果用一行命名工具，调用id和图像计数，并说这是工具输出，而不是用户；不可信的结果保持不变 `<untrusted>` 标记(`lossy(tool+lifted-images)`;在DeepSeek的官方API上验证-在依赖它之前检查其他openai兼容的上游，并将其关闭 `chat.liftToolImages: false` 如果他们拒绝这个形状)。没有图像支持，或有 `chat.liftToolImages: false`，图像成为占位符(`lossy(tool-text-only)`); `isError` 在此协议上没有标志，表示为 `[tool error]` 前缀(`lossy`）。
-   此协议上不存在显式缓存断点；提供程序端自动前缀缓存应用和 `cached_tokens` 据报道为 `cacheRead`.
-   用法遵循核心语义： `input` 未缓存的提示计数。 `costUsd` 使用内置价格表（DeepSeek：峰值费率，上限）。

## 事件是如何登陆人类信息的

中声明 `LOSS_MATRIX["anthropic-messages"]`，细胞对细胞比较 `@reinsjs/lowering-pi`.

-   `system_note` →谈话中途 `{ role: "system" }` 关于接受它的模范家庭的信息（表5）。x /神话；x / Opus 5 / Opus 4.8或 `midConversationSystem: true`）. 提供者需要这样的消息来跟随 `user` 转过身来，后面跟着一个 `assistant` 转或结束请求，因此音符在下一个辅助转之前（或在结束时）保持并发出；当这个槽跟随助手的转-或者这张纸条将是第一条信息-这张纸条将作为一个框发出 `user` 文本(`lossy(user-role)`）. 其他模型总是得到框架文本。
    
-   工具结果和在它们之后移动的任何东西（在结果挂起时到达的用户消息）共享一个 `user` 消息,所以 `tool_result` 街区直接沿着 `tool_use` 转弯。 `is_error` 是本地携带的。
    
-   **思考** 只有当事件带有 `signature` 来自同一个提供者，API **和模型** （`thinking` / `redacted_thinking` 块);未签名的思维（中断的流），来自另一个提供者的思维，或者来自同一提供者的另一个模型的思维 `dropped` 声明——它不会变成可见的文本（签名只对产生它的模型有效：跨模型重播一个签名是400）。带有签名的空文本思维块(`display: "omitted"`)被保存和重播。
    
-   **缓存断点**一个在最后一个系统模块上，一个在最后一个工具上，一个在最后一个模块上 `user` 消息。当注释是最后一条消息时，对话断点将成为顶级断点 `cache_control` （与未注射时相同）。总共不超过四个。
    
-   用法: `input_tokens` 已经是未缓存计数； `cache_read_input_tokens` / `cache_creation_input_tokens` 映射到 `cacheRead` / `cacheWrite`. `stop_reason: "refusal"` 变成不可重试的 `error` 携带 `stop_details`.
    
-   延期工具(`ToolSpec.deferLoading`，由 `lazyTools()` 当 `capabilities.deferredTools` 是真实的): `defer_loading: true` 在该工具上，缓存断点移动到最后一个非延迟工具（延迟工具不能携带） `cache_control`)，如果每个工具都要延迟，那么没有一个工具会延迟（API会拒绝）。一个 `tool_result` 它的内容只有 `tool_reference` 部件，来自系统信任的结果，并命名此请求中出现的工具 `tools` 发送为 `tool_reference` 阻止了API的扩展——工具列表永远不会改变，所以缓存前缀会保留(`exact` / `tool-reference`）; 在同一结果中的文本部分被移动到批后 `tool_result` 块(`lossy` / `tool-reference`，它们不能混合)。对不在此请求中的工具的引用，或者在不受信任的结果中对工具的引用，将被呈现为文本——API将验证整个历史记录中的每个引用，并对未知名称回答400。
    

## 事件如何登陆OpenAI响应

中声明 `LOSS_MATRIX["openai-responses"]`，细胞对细胞比较 `@reinsjs/lowering-pi`.

-   **无国籍建筑。** 每个请求都包含整个历史 `input`； `store: false` 是被迫的 `previous_response_id` 在 `requestOptions` 时间轴是唯一的真实来源，OpenAI的服务器端会话状态从不依赖。
-   系统提示和 `system_note` 是 `developer` 消息（推理模型）或 `system` 消息（其他）在任何位置 `input` -永远没有放置规则 `exact`. `compaction` 是一个框架吗？ `user` 文本(`lossy`）。
-   **推理**：推理模型总是要求 `include: ["reasoning.encrypted_content"]`;每个推理项都完整地存储在事件中 `replay.thinkingSignature` 并逐字重播（提供者验证加密的有效载荷—伪造的有效载荷是400）。项目没有 `encrypted_content` (一条中断的小溪， `include` 拒绝)，来自另一个提供者，或来自另一个模型 `dropped` 而宣言，从未化作文字。具有加密有效负载但没有摘要的推理项目被保存为空文本思考事件，以便下一轮可以重播它们。
-   辅助文本变成了 `type: "message"` 项，重播提供者的 `msg_` id (`replay.textSignature`（也接受lower -pi的JSON格式）或生成的格式。工具调用是 `function_call` 项目: `call_id` 是事件的 `toolCallId`, `fc_` 项目id驻留在 `replay.itemId` 并且只对相同的模型重播(OpenAI验证配对 `fc_` 和 `rs_` 项目); `arguments` 是一个JSON字符串，所以非对象参数不需要包装。工具随附 `strict: false`.
-   工具结果如下 `function_call_output` 匹配的项目 `call_id`：纯文本时为字符串，为的数组 `input_text` / `input_image` 当结果包含图像并且模型接受它们时，将阻塞； `isError` 在此协议上没有标志，表示为 `[tool error]` 前缀(`lossy`）。
-   用法: `input_tokens` 包括缓存和缓存写入令牌，所以 `input` 是 `input_tokens − cached_tokens − cache_write_tokens`，两者映射到 `cacheRead` / `cacheWrite`. `status: "incomplete"` 与 `max_output_tokens` 是 `length`;与 `content_filter` 一个non-retryable `error`； `response.failed` 和 `error` 帧是携带提供者代码和消息的错误。自动前缀缓存是OpenAI方面的最大努力；通过 `prompt_cache_key` 在 `requestOptions` 提高命中率。
-   内置表：gpt-5系列（5.5 / 5.4 / 5.4-mini / 5.2 / 5.1 / 5 / 5-mini / 5-nano）， o3 / o4-mini和gpt-4.1 / 4.1-mini / 40 -mini的响应；相同的OpenAI id也存在于聊天完成项中，其中 `openaiChat()` 按协议选择。一个光秃秃的 `{ provider: "openai", id }` 在一个 `FetchLowering` 你构建自己的决心来回应。

## 错误和重试

非2xx响应抛出 `HttpError` 与 `status`， `headers` 生的身体(`"<status> <body>"`（与官方sdk使用的形状相同），所以 `runLoop`408 / 409 / 429 / 5xx可以重试，其他的都不能。网络故障从 `fetch` 都没动。

## 文档

`docs/archive/implementation-plans/2026-09-08-技术方案v1.0.md` §11日 `docs/系统全景图_模块盘点/lowering-fetch.md`， `spikes/f1-chat-live/`， `spikes/f2-anthropic-live/`， `spikes/f3-responses-live/` （对DeepSeek进行实时验证，并通过Cloudflare AI网关、OpenAI和Anthropic进行验证）和 `spikes/edge-runtime-check/` （Cloudflare workerd） -中文，在存储库根目录。

MIT©2026 newate Limited

## 常见问题

### @reinsjs/lowering-fetch 是什么？

缰—获取上的零依赖降低层：事件当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种当下一种的当下一种

### 如何安装 @reinsjs/lowering-fetch？

在项目目录运行 npm install @reinsjs/lowering-fetch，或使用 pnpm add / yarn add / bun add。

### @reinsjs/lowering-fetch 支持 TypeScript 吗？

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

### @reinsjs/lowering-fetch 支持 ESM 还是 CommonJS？

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

### @reinsjs/lowering-fetch 需要什么版本的 Node\.js？

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

### @reinsjs/lowering-fetch 可以商用吗？

@reinsjs/lowering-fetch 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @reinsjs/lowering-fetch 还在维护吗？

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

