@x1a0f3n9/dsh-llm 0.1.5-alpha.2 → 0.1.5-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -3,4 +3,4 @@
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/llm/llm/README.md
5
5
  README.md: 75a5d3e1d51ada12338a41e54b42ad8d6d21c279
6
- README.zh.md: e10706108d86f337c333b1f80a15c731fd2a00cf
6
+ README.zh.md: 6c0d42dc1cb01fe8d5fc01d3384e909b6cdc044a
package/README.zh.md CHANGED
@@ -25,7 +25,7 @@ kind: "package-reference"
25
25
  <a id="use-this-package"></a>
26
26
  ## 使用本包
27
27
 
28
- 任何调用模型提供方的组合——agent loop、会话标题生成器、压缩(compaction)摘要器——都会通过本服务流式发起请求。与至少一个提供方适配器一起挂载它;服务本身没有任何配置,也不包含提供方协议代码。
28
+ 任何调用模型提供方的组合——agent loop(智能体循环)、会话标题生成器、压缩(compaction)摘要器——都会通过本服务流式发起请求。与至少一个提供方适配器一起挂载它;服务本身没有任何配置,也不包含提供方协议代码。
29
29
 
30
30
  ### 何时选择
31
31
 
@@ -60,10 +60,10 @@ for await (const chunk of ctx.llm.stream({
60
60
 
61
61
  - **流式发起一次模型调用**——`ctx.llm.stream(options)` 为任何已注册提供方与模型产出原始分片(token 级增量);消费方用 `BlockAssembler` 组装。
62
62
  - **注册提供方适配器**——一个适配器拥有一个或多个提供方路由,其注册会捕获该路由的重试策略;重复注册同一路由会以 `DUPLICATE_ADAPTER` 失败。
63
- - **通过配置暴露并激活提供方**——适配器声明可配置提供方路由与 settings namespace,配置界面因此可以激活休眠提供方并编辑连接事实,无需重启。`LlmConfigurableProvider.error` 报告供修复的配置诊断;未受影响的模型仍可提供服务。
63
+ - **通过配置暴露并激活提供方**——适配器声明可配置提供方路由与 settings namespace,配置界面因此可以激活休眠提供方并编辑连接信息,无需重启。`LlmConfigurableProvider.error` 报告供修复的配置诊断;未受影响的模型仍可提供服务。
64
64
  - **发现与解析模型**——列出适配器公布的模型、询问端点它提供哪些模型,并解析某个精确模型的上下文窗口、输出默认值、推理(reasoning)强度、输入模态与系统提示词更新模式:当模型把任意位置最新的 `system` 消息读作有效系统提示词时,`LlmResolvedModelInfo.systemPromptUpdate` 为 `'in-history'`;只读取开头 system 消息时该字段缺失;`normalizeModelInfo` 以 `INVALID_MODEL_INFO` 拒绝任何其他值。
65
65
  - **校验调用配置**——显式或配置的推理强度会在任何提供方 I/O 之前对照精确模型校验;请求省略输出上限时,会填入适配器配置的输出上限。
66
- - **不展开即读取内嵌 Assistant 流**——`assistantStreamFirstTokenTime`(首 token)、`assistantStreamHasVisibleContent`(任一可见内容)与 `assistantStreamHasVisibleText`(任一可见文本)以提前退出从紧凑记录回答各自的问题;`lastAssistantStreamChunk` 反向扫描到某一类型的最后一个原始 chunk,`assistantStreamChunks` 与 `joinAssistantStreamText` 扫描整个流,`assembleAssistantStream` 向 `BlockAssembler` 每个 run 喂一段拼接 delta,blocks/usage/replayState 与逐成员展开相同。`runFirstTokenTime` 与 `runFirstVisibleTime` 对单个打包 run 做提前退出扫描,`isTokenDelta`、`isVisibleChunk` 与 `chunkHasVisibleText` 定义单个 chunk 的 token 与可见性规则。`expandAssistantStream` 仍是持久边界读取记录的校验路径;它不被记忆化,因为保留的展开在事件生命周期内约花费紧凑流的十倍内存。
66
+ - **不展开即读取内嵌 Assistant 流**——`assistantStreamFirstTokenTime`(首 token)、`assistantStreamHasVisibleContent`(任一可见内容)与 `assistantStreamHasVisibleText`(任一可见文本)通过可提前退出的扫描直接从紧凑记录得出结果;`lastAssistantStreamChunk` 反向扫描到某一类型的最后一个原始 chunk,`assistantStreamChunks` 与 `joinAssistantStreamText` 扫描整个流,`assembleAssistantStream` 向 `BlockAssembler` 每个 run 喂一段拼接 delta,blocks/usage/replayState 与逐成员展开相同。`runFirstTokenTime` 与 `runFirstVisibleTime` 对单个打包 run 做提前退出扫描,`isTokenDelta`、`isVisibleChunk` 与 `chunkHasVisibleText` 定义单个 chunk 的 token 与可见性规则。`expandAssistantStream` 仍是持久边界读取记录的校验路径;它不被记忆化,因为保留的展开在事件生命周期内约花费紧凑流的十倍内存。
67
67
 
68
68
  ### 失败与恢复
69
69
 
@@ -81,7 +81,7 @@ for await (const chunk of ctx.llm.stream({
81
81
 
82
82
  ### 设计理念
83
83
 
84
- 服务建立在一个分离之上:**逻辑约定是提供方无关的,适配器拥有协议。** 它一次性地定义规范消息、内容块与流式分片词汇,每个提供方适配器只把自己的协议格式翻译为该词汇。注册表是拓扑的拥有者——适配器路由、可配置提供方条目与发现 offer 都在这里注册,并随其 fiber 一起 dispose(资源释放)——而请求始终是会话日志的纯函数:loop 构建的请求以深度冻结状态到达,因此监听器与适配器只能读取,绝不能改写。
84
+ 本服务基于一项职责分离原则:**逻辑约定是提供方无关的,适配器拥有协议。** 它一次性地定义规范消息、内容块与流式分片词汇,每个提供方适配器只把自己的协议格式翻译为该词汇。注册表是拓扑的拥有者——适配器路由、可配置提供方条目与发现 offer 都在这里注册,并随其 fiber 一起 dispose(资源释放)——而请求始终是会话日志的纯函数:loop 构建的请求以深度冻结状态到达,因此监听器与适配器只能读取,绝不能改写。
85
85
 
86
86
  ### 源码地图
87
87
 
@@ -91,7 +91,7 @@ for await (const chunk of ctx.llm.stream({
91
91
  | [`src/types.ts`](src/types.ts) | `StreamChunk` 协议、内容块映射、结束原因与共享词汇 |
92
92
  | [`src/message.ts`](src/message.ts) | 投递、历史与请求共享的不可变消息构造函数 |
93
93
  | [`src/assembler.ts`](src/assembler.ts) | `BlockAssembler`:分片到块的增量组装 |
94
- | [`src/assistant-stream.ts`](src/assistant-stream.ts) | 紧凑带时间 Assistant stream 的累积、严格校验、精确展开与记录级读取器 |
94
+ | [`src/assistant-stream.ts`](src/assistant-stream.ts) | 带时间信息的紧凑 Assistant 流累积、严格校验、精确展开与记录级读取器 |
95
95
  | [`src/call-config.ts`](src/call-config.ts) | 调用配置校验、适配器默认值填入与请求冻结 |
96
96
  | [`src/retry-policy.ts`](src/retry-policy.ts) | 提供方自有重试策略解析(normal 与 always 模式) |
97
97
  | [`src/error.ts`](src/error.ts) | `HarnessError`/`LlmError` 分类体系与提供方无关失败 code |
@@ -101,7 +101,7 @@ for await (const chunk of ctx.llm.stream({
101
101
 
102
102
  ### 主流程
103
103
 
104
- 请求会对照其精确模型的能力——上下文窗口、输出默认值、推理强度、输入模态与 `systemPromptUpdate` 模式——校验,填入任何适配器配置的默认值,然后整个请求被深度冻结。`prepareCall()` 把这些事实、分离的上下文与重试策略绑定到执行最终分发的精确适配器代次,因此 HMR 或动态设置无法把一个代次的图片能力与另一代次的端点混用。支持图片的适配器把持久引用投影为路由专用请求版本;`resolveImageAttachmentAccess()` 会单独把附件提供方的可选宿主对象映射进当前工具执行世界,而不改变请求图片或其 `variantId`。纯文本路由接收确定性的逐图片占位符,包括嵌套工具结果图片,而不会改写仅追加会话历史。持久 `FileBlock` 引用永远不会到达任何适配器:请求组装把每个引用(包括嵌套工具结果中的出现)替换为确定性 handle 文本,指出文件与其只读保存路径,路径经由挂载的附件与文件系统提供方解析。`ctx.llm.fileRequestText(ref)` 向请求计量公开相同的同步投影。`offloadRequestImagesWithPolicy()` 按原始字节或 base64 大小以及图片数或字节步长,确定性地从最旧图片开始移除;纯函数 `offloadedImagePrefixCount()` 公开同一决策,使路由所属的请求定价无需构建投影即可复现它。对视觉 token 收费的适配器声明按路由的 `imageRequestPricing`,`ctx.llm.imageRequestPricing(provider, model)` 为 token meter 同步解析它。分发经过 `llm/stream` waterfall,随后分片以 token 级增量返回,每个适配器结果都以唯一一个终止 `finish` 分片到达消费方。
104
+ 请求会对照其精确模型的能力——上下文窗口、输出默认值、推理强度、输入模态与 `systemPromptUpdate` 模式——校验,填入任何适配器配置的默认值,然后整个请求被深度冻结。`prepareCall()` 把这些事实、分离的上下文与重试策略绑定到执行最终分发的精确适配器代次,因此 HMR(热模块替换)或动态设置无法把一个代次的图片能力与另一代次的端点混用。支持图片的适配器把持久引用投影为路由专用请求版本;`resolveImageAttachmentAccess()` 会单独把附件提供方的可选宿主对象映射进当前工具执行世界,而不改变请求图片或其 `variantId`。纯文本路由接收确定性的逐图片占位符,包括嵌套工具结果图片,而不会改写仅追加会话历史。持久 `FileBlock` 引用永远不会到达任何适配器:请求组装把每个引用(包括嵌套工具结果中的出现)替换为确定性句柄文本,指出文件与其只读保存路径,路径经由挂载的附件与文件系统提供方解析。`ctx.llm.fileRequestText(ref)` 向请求计量公开相同的同步投影。`offloadRequestImagesWithPolicy()` 按原始字节或 base64 大小以及图片数或字节步长,确定性地从最旧图片开始移除;纯函数 `offloadedImagePrefixCount()` 公开同一决策,使路由所属的请求定价无需构建投影即可复现它。对视觉 token 收费的适配器声明按路由的 `imageRequestPricing`,`ctx.llm.imageRequestPricing(provider, model)` 为 token meter 同步解析它。分发经过 `llm/stream` waterfall(瀑布式事件),随后分片以 token 级增量返回,每个适配器结果都以唯一一个终止 `finish` 分片到达消费方。
105
105
 
106
106
  文件检测在每次请求时读取当前内容,包括嵌套工具结果,不缓存消息身份或冻结状态。[文件扫描决策](../../../.agents/notes/implemented/simplification/2026-09-07-file-content-scan.zh.md)记录了实测遍历成本。
107
107
 
@@ -111,7 +111,7 @@ for await (const chunk of ctx.llm.stream({
111
111
  - **回放状态只在同一适配器内流动**——仅当同一适配器实例同时拥有历史路由与目标路由时,assistant 回放状态才会随行;否则在分发前被丢弃。
112
112
  - **已准备调用是一次性的**——已准备调用只能分发一次,且其调用配置字段必须与准备好的配置一致。
113
113
  - **图片投影遵循捕获的路由**——只有支持图片的模型会把持久 `ImageBlock` 引用转换为路由专用请求版本;纯文本模型接收稳定占位符。
114
- - **文件投影无条件进行**——没有任何提供方会收到文件字节;每条路由对每个 `FileBlock` 都得到一行确定性 handle 文本,模型在需要时用文件工具读取保存的副本。
114
+ - **文件投影无条件进行**——没有任何提供方会收到文件字节;每条路由对每个 `FileBlock` 都得到一行确定性句柄文本,模型在需要时用文件工具读取保存的副本。
115
115
  - **协议顺序**——`usage` 先于 `finish`,工具参数保持原始 JSON 字符串,终止 `finish` 之后不再有任何内容。
116
116
  - **注册表变更具有原子性**——路由与目录注册会在任何变动前整体校验候选集合,因此被拒绝的变更会让此前状态继续服务。
117
117
 
@@ -124,7 +124,7 @@ for await (const chunk of ctx.llm.stream({
124
124
 
125
125
  当包级约定不够用时阅读以下页面。它们从共享类型逐步进入具体适配器、重试执行器与计量服务。
126
126
 
127
- - [LLM 流式子系统](../../../docs/subsystems/llm-streaming.zh.md)——消息与块类型、紧凑 Assistant stream record、`StreamChunk` 协议与适配器约定。
127
+ - [LLM(大语言模型)流式子系统](../../../docs/subsystems/llm-streaming.zh.md)——消息与块类型、紧凑的 Assistant 流记录、`StreamChunk` 协议与适配器约定。
128
128
  - [llm-deepseek 适配器](../llm-deepseek/README.zh.md)——DeepSeek chat-completions 直连实现。
129
129
  - [llm-pi-ai 适配器](../llm-pi-ai/README.zh.md)——基于 pi-ai 的多提供方实现。
130
130
  - [llm-retry](../llm-retry/README.zh.md)——重跑失败模型请求的重试执行器。
package/lib/index.js CHANGED
@@ -229,7 +229,7 @@ function isHarnessError(value) {
229
229
  *
230
230
  * @module @x1a0f3n9/dsh-llm/retry-policy
231
231
  */
232
- const DEFAULT_MAX_RETRIES = 5;
232
+ const DEFAULT_MAX_RETRIES = 20;
233
233
  const DEFAULT_INITIAL_DELAY_MS = 500;
234
234
  const DEFAULT_MAX_DELAY_MS = 1e4;
235
235
  const DEFAULT_JITTER_RATIO = .1;
@@ -20,7 +20,7 @@ export interface BackoffConfig {
20
20
  export interface NormalRetryPolicyConfig {
21
21
  /** Retry only configured transient failure codes. */
22
22
  mode: 'normal';
23
- /** Maximum eligible retries after the first request (default 5). */
23
+ /** Maximum eligible retries after the first request (default 20). */
24
24
  maxRetries?: number;
25
25
  /** Stable failure codes eligible for this policy. */
26
26
  retryableCodes?: string[];
@@ -9,7 +9,7 @@
9
9
  import z from '@deepseek-ai/schemastery';
10
10
  import { MAX_TIMER_DELAY_MS } from '@x1a0f3n9/dsh-timeout';
11
11
  import { EMPTY_RESPONSE_CODE } from "./error.js";
12
- const DEFAULT_MAX_RETRIES = 5;
12
+ const DEFAULT_MAX_RETRIES = 20;
13
13
  const DEFAULT_INITIAL_DELAY_MS = 500;
14
14
  const DEFAULT_MAX_DELAY_MS = 10_000;
15
15
  const DEFAULT_JITTER_RATIO = 0.1;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@x1a0f3n9/dsh-llm",
3
3
  "description": "Provider-neutral LLM service interface for the DeepSeek Harness",
4
- "version": "0.1.5-alpha.2",
4
+ "version": "0.1.5-rc.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -65,16 +65,16 @@
65
65
  },
66
66
  "dependencies": {
67
67
  "zod": "^4.4.3",
68
- "@x1a0f3n9/dsh-util-crypto": "^0.1.5-alpha.2",
68
+ "@x1a0f3n9/dsh-util-crypto": "^0.1.5-rc.2",
69
69
  "@deepseek-ai/schemastery": "^3.18.2",
70
- "@x1a0f3n9/dsh-timeout": "^0.1.5-alpha.2",
71
- "@x1a0f3n9/dsh-brand": "^0.1.5-alpha.2",
72
- "@x1a0f3n9/dsh-util-values": "^0.1.5-alpha.2",
73
- "@x1a0f3n9/dsh-typert-protocol": "^0.1.5-alpha.2"
70
+ "@x1a0f3n9/dsh-timeout": "^0.1.5-rc.2",
71
+ "@x1a0f3n9/dsh-brand": "^0.1.5-rc.2",
72
+ "@x1a0f3n9/dsh-util-values": "^0.1.5-rc.2",
73
+ "@x1a0f3n9/dsh-typert-protocol": "^0.1.5-rc.2"
74
74
  },
75
75
  "devDependencies": {
76
- "@x1a0f3n9/dsh-attachment": "^0.1.5-alpha.2",
77
- "@x1a0f3n9/dsh-invariants": "^0.1.5-alpha.2",
76
+ "@x1a0f3n9/dsh-attachment": "^0.1.5-rc.2",
77
+ "@x1a0f3n9/dsh-invariants": "^0.1.5-rc.2",
78
78
  "@deepseek-ai/cordis": "^4.0.2"
79
79
  }
80
80
  }