@acosmi/sdk-ts 1.5.0 → 1.5.1

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/CHANGELOG.md CHANGED
@@ -9,6 +9,52 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ---
11
11
 
12
+ ## [1.5.1] — 2026-05-23
13
+
14
+ > **Docs / examples patch — 无 API 变化**。对 README、`docs/compliance.md`、`docs/开发与发布手册.md`、`examples/`、源码注释做全量复核与修订,消除发现的 8 项漂移与遗漏。无 runtime 行为变更、无新增/移除导出符号、无 wire-format 变化;`typecheck` / `lint` / `vitest`(214) / `build` / `test:pack` 全绿。
15
+
16
+ ### Changed — README.md
17
+
18
+ - 补全 API 总览表 25+ 漏列方法:`chatMessages` / `chatMessagesStream` / `buildChatRequest` / `loginWithHandler` / `isAuthorized` / `getTokenSet` / 浏览器 Web OAuth 4 原语 / `discoverWithProfile` / `register` / `revokeToken` / `generateState` / `ensureModelCached` / `browseSkillStore` / `getSkillSummary` / `certifySkill` / `getCertificationStatus` / `markAllNotificationsRead` / `deleteNotification` / `unregisterDevice` / `updateNotificationPreference` / WS `connect`/`disconnect`/`isConnected` / `listConsumeRecords` / `invalidateCoefficientCache` / `getTokenPackageDetail` / `listMyOrders` / `Client.create`。
19
+ - 修复 §"双格式红线" 把 `preferredFormat` / `supportedFormats` 错写为 camelCase 的描述——`ManagedModel` 上这两个字段是 snake_case wire 字段;同步说明 `modelId` / `isEnabled` / `inputModalities` 等顶层走 camelCase。
20
+ - 修复 Quick Start / 流式 / Web Search 三个示例的 `ChatRequest` 字段:`maxTokens` → `max_tokens`(与 `src/models/types.ts:ChatRequest.max_tokens` 对齐)。
21
+ - 重写 §"手动 OAuth" 段:`register/authorize/exchangeCode` 全部按 `src/auth/auth.ts` 真实签名重写——`register` 不接 scopes / `authorize` 需 `reg.client_id`+`handler:` 而非 `onEvent:`、返回 `{ result, verifier }` / `exchangeCode` 需 5 个位置参数含 `result.redirectURI` + `verifier`;指向 `examples/auth-oauth-flow.ts` 完整示例;加浏览器 Web OAuth 替代品指引。
22
+ - §错误处理表补 `ModelNotFoundError`(`chat` / `ensureModelCached` listModels 自动刷新后仍未命中);为既有 `NetworkError` / `StreamError` / `CompliancePollError` 补字段细节。
23
+ - §Agent Runs 段补 `AgentRunStreamEvent` 完整 13 类事件表(`run_started` / `status` / `text_delta` / `reasoning_delta` / `tool_call` / `tool_result` / `local_tool_request` / `artifact` / `sources` / `usage` / `settle` / `error` / `done`)。
24
+ - 新增 §`sanitize` 命名空间小节:列 `client.setDefensiveSanitize` / `setAutoStripEphemeralHistory` / `applyRequestSanitizers` 三个 mixin 方法 + `sanitize.sanitize` / `dropBlocks` / `stripEphemeral` + 17 个 `Block*` 常量 + `MinimalSanitizeConfig` 字段(`maxMessagesTurns` / `permanentDenyBlocks` / `maxImageBytes` / `maxVideoBytes` / `maxPDFBytes`)+ thinking 块硬豁免红线。
25
+ - §历史表 1.5.0 行补"compliance gateway S1-S6 全量 rollup + scope 总数 15"说明。
26
+
27
+ ### Changed — docs/compliance.md
28
+
29
+ - 6 处版本号漂移修订:`Since v1.6.0 / 1.7.0 / 1.8.0 / 1.9.0 / 1.10.0` + `Contract-template scopes (added in v1.10.0)` → 统一为 `v1.5.0 (originally planned as v1.X.0 — see CHANGELOG §"SN:..."`,避免消费者误以为这些方法在未来版本才有。
30
+
31
+ ### Changed — docs/开发与发布手册.md
32
+
33
+ - §7 必测清单:`test/compliance-scopes.test.ts — 12 个` → `15 个`,附 12 → 13(v1.3.2)→ 15(v1.5.0 S5)演进注解。
34
+ - §7 新增"Compliance gateway S1-S6 rollup(v1.5.0)"小节,逐 S 列出新增 25+ SDK 方法、对应后端 G1-G6、新增 scope 与 fail-closed 红线。
35
+
36
+ ### Changed — examples/
37
+
38
+ - `examples/compliance-evidence-timestamp.ts` 补 `ScopeComplianceReportsWrite`(`createReport` 自 v1.3.2 起改用独立 write scope;过去用 `ScopeComplianceReportsRead` 在生产会 401)。
39
+ - `examples/auth-oauth-flow.ts` 顶部注释指向 v1.4.0+ Web OAuth 原语(`discoverWebOAuthMetadata` / `registerWebOAuthClient` / `createWebAuthorizationRequest` / `completeWebAuthorizationRequest`)+ `Config.browserRefreshMode` / `refreshProxyURL` (v1.4.1+) CORS 规避方案。
40
+ - `examples/core-chat.ts` 顶部注释把 `preferredFormat` / `supportedFormats` 改回 snake_case;补 `ChatRequest` snake_case wire / `ManagedModel` 顶层 camelCase 字段命名说明。
41
+
42
+ ### Changed — 源码注释(无 runtime 影响)
43
+
44
+ - `src/index.ts` 顶部注释从"端口源 acosmi-sdk-go v0.19.0 (一字不差对齐)"改为"自 2026-05-22 起 TS 是主实现 / 事实标准",与 README §状态 + 手册 §1 / §10 一致。
45
+ - `src/browser.ts` 顶部注释加 v1.4.0+ Web OAuth 替代品 + v1.4.1+ `browserRefreshMode` 指引。
46
+ - `src/auth/auth.ts` 顶部 + `authorize()` doc:从"浏览器侧应自行实现 popup window"改为指向同文件内 Web OAuth 原语。
47
+ - `docs/api/`(TypeDoc 生成)已同步重生成。
48
+
49
+ ### Verified
50
+
51
+ - `typecheck`:0 errors
52
+ - `vitest`:17 files / **214 tests passed**
53
+ - `npm pack --dry-run`:tarball 内容无变化
54
+ - 跨语言契约印记(snake_case wire / 双 adapter 等地位 / bug-for-bug 行为)零回归
55
+
56
+ ---
57
+
12
58
  ## [1.5.0] — 2026-05-23
13
59
 
14
60
  > 众律宝 SaaS 工作台 SDK / 后端能力缺口总账(`docs/audit/saas-sdk-backend-capability-gap-register-2026-05-22`)
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  ## 状态
8
8
 
9
9
  - 主实现 / 事实标准:本 TS SDK 现为 Acosmi SDK 的主力实现。Go SDK [acosmi-sdk-go](https://github.com/acosmi/acosmi-sdk-go) 已暂停维护,待 TS 稳定后再从 TS 反向翻译补齐
10
- - 当前版本:**1.5.0**(沉淀 `src/shared/` 跨域共享 DTO——分页 / operation / retryAdvice / principal / gate 原语;`1.4.2` `src/` 按业务域重组;`1.4.x` 浏览器 Web OAuth;`1.3.x` `client.compliance` 合规域客户端;详见 [CHANGELOG](./CHANGELOG.md)
10
+ - 当前版本:**1.5.1**(文档 / examples / 源码注释全量复核与修订——补 25+ 漏列 API、修 OAuth/Chat 示例签名漂移、`docs/compliance.md` 6 处版本号统一为 1.5.0、`examples/compliance-evidence-timestamp.ts` `compliance:reports:write` scope;无 API / wire-format 变化)。`1.5.0` 沉淀 `src/shared/` 跨域共享 DTO + compliance gateway S1-S6 全量 rollup;`1.4.2` `src/` 按业务域重组;`1.4.x` 浏览器 Web OAuth;`1.3.x` `client.compliance` 合规域客户端;详见 [CHANGELOG](./CHANGELOG.md)
11
11
  - 测试:发布前需通过 typecheck/lint/vitest/build/packed-tarball smoke (`npm run test:pack`)
12
12
  - API 参考文档:`npm run docs` 经 TypeDoc 生成到 `docs/api/`
13
13
  - 包链接:[npm](https://www.npmjs.com/package/@acosmi/sdk-ts) · [GitHub Releases](https://github.com/acosmi/sdk-ts/releases)
@@ -28,7 +28,7 @@ await client.login('My App', allScopes());
28
28
 
29
29
  const resp = await client.chat('claude-opus-4-7', {
30
30
  messages: [{ role: 'user', content: 'Hello' }],
31
- maxTokens: 1024,
31
+ max_tokens: 1024, // ChatRequest 走 snake_case wire 字段(与上游 Go json tag 对齐)
32
32
  });
33
33
  console.log(resp.content);
34
34
  ```
@@ -42,12 +42,12 @@ SDK 同时提供 **Anthropic + OpenAI 两条 endpoint**,**等地位**,对应
42
42
  | `AnthropicAdapter` | `POST /managed-models/:id/anthropic` | Anthropic 原生格式(含 thinking 等)|
43
43
  | `OpenAIAdapter` | `POST /managed-models/:id/chat` | OpenAI 兼容格式(DeepSeek/GLM 等) |
44
44
 
45
- 路由由 `getAdapterForModel(model)` 按 ManagedModel 的 `preferredFormat` / `supportedFormats` 决策:
45
+ 路由由 `getAdapterForModel(model)` 按 ManagedModel 的 `preferred_format` / `supported_formats` 决策(wire-format 字段,snake_case 与上游 Go json tag 严格对齐;ManagedModel 上其余顶层字段如 `modelId` / `isEnabled` / `inputModalities` 走 camelCase,详见 `src/models/types.ts`):
46
46
 
47
- 1. `preferredFormat` 非空 → 按值(`anthropic` | `openai`)
48
- 2. `supportedFormats` 含 `anthropic` → AnthropicAdapter
49
- 3. `supportedFormats` 含 `openai` → OpenAIAdapter
50
- 4. 两字段均空(旧上游)→ 按 provider 名回落
47
+ 1. `preferred_format` 非空 → 按值(`anthropic` | `openai`)
48
+ 2. `supported_formats` 含 `anthropic` → AnthropicAdapter
49
+ 3. `supported_formats` 含 `openai` → OpenAIAdapter
50
+ 4. 两字段均空(旧上游)→ 按 `provider` 名回落
51
51
 
52
52
  `client.chat()` / `client.chatStream()` 内部自动调 `getAdapterForModel`,使用方无需关心。
53
53
 
@@ -66,7 +66,7 @@ SDK 同时提供 **Anthropic + OpenAI 两条 endpoint**,**等地位**,对应
66
66
  ```ts
67
67
  const stream = client.chatStream('claude-opus-4-7', {
68
68
  messages: [{ role: 'user', content: '写一首诗' }],
69
- maxTokens: 1024,
69
+ max_tokens: 1024,
70
70
  });
71
71
 
72
72
  for await (const ev of stream) {
@@ -142,6 +142,24 @@ await client.agentRuns.cancel(run.runId); // safe to call from UI cancel buttons
142
142
 
143
143
  `stream(runId)` 支持 durable replay:断线后重新连接同一个 run,会先回放已持久化的 Agent Run SSE 事件,再继续消费运行中的事件。`usage` / `settle` 事件会暴露 `exact`、`cacheReadTokens`、`cacheCreateTokens` 等字段,便于下游展示真实结算状态。
144
144
 
145
+ **`AgentRunStreamEvent` 完整事件类型**(union,详见 `src/agent-runs/types.ts`;上面示例只演示了 4 种常见分支):
146
+
147
+ | `type` | 触发 / 含义 | 关键字段 |
148
+ | --- | --- | --- |
149
+ | `run_started` | 流首事件,确认服务端已开始执行 | `runId`、`sessionId` |
150
+ | `status` | 任务粗粒度状态变化 | `status` (`queued`/`running`/`completed`/`failed`/`cancelled`)、`message?` |
151
+ | `text_delta` | 主要文本输出增量 | `text` |
152
+ | `reasoning_delta` | 推理 / 思考过程增量(debug 用,不一定向终端用户展示) | `text` |
153
+ | `tool_call` | Agent 发起内置 / 网关工具调用 | `id`、`name`、`input?` |
154
+ | `tool_result` | 内置 / 网关工具调用结果 | `id`、`name?`、`result?`、`error?` |
155
+ | `local_tool_request` | Agent 请求宿主提供本地只读工具结果,宿主须用 `submitLocalToolResult` 回填 | `requestId`、`name`、`input` |
156
+ | `artifact` | 产出文件(图片 / 代码 / 文档等);用 `downloadArtifact(runId, artifact.id)` 下载 | `artifact: AgentRunArtifact` |
157
+ | `sources` | 网络检索 / RAG 来源信息 | `sources` |
158
+ | `usage` | provider/ADK 透传的 token usage | `usage.exact`、`inputTokens`、`outputTokens`、`totalTokens`、`cacheReadTokens`、`cacheCreateTokens` |
159
+ | `settle` | 服务端结算事件 | `settlement.status`、`tokenRemaining`、`callRemaining`、`exact`、`retryQueued` |
160
+ | `error` | 失败事件(`throwOnError:true` 默认会转 `AgentRunStreamError` 抛出) | `error.code`、`error.message`、`error.stage`、`error.retryable` |
161
+ | `done` | 流终止 | `runId`、`status` |
162
+
145
163
  ## 认证
146
164
 
147
165
  ### 浏览器内 / 自动 OAuth(推荐)
@@ -153,17 +171,45 @@ const token = await client.ensureToken(); // 拿到当前有效 access toke
153
171
 
154
172
  ### 手动 OAuth(CLI / 自定义流程)
155
173
 
174
+ 底层 helper 适用于自管 token 的 CLI / 自定义授权 UI。**大多数场景直接用 `client.login(appName, scopes)` 即可**——它内部封装了下面全部步骤。完整可运行示例见 [`examples/auth-oauth-flow.ts`](./examples/auth-oauth-flow.ts)。
175
+
156
176
  ```ts
157
- import { discover, register, authorize, exchangeCode } from '@acosmi/sdk-ts';
177
+ import {
178
+ discover, // RFC 8414 元数据发现
179
+ register, // RFC 7591 动态客户端注册
180
+ authorize, // 本地 loopback PKCE(仅 Node)
181
+ exchangeCode, // code + verifier → token
182
+ refreshToken, // 续期
183
+ newTokenSet, // 把 TokenResponse 包成可持久化 TokenSet
184
+ FileTokenStore,
185
+ allScopes,
186
+ } from '@acosmi/sdk-ts';
158
187
 
159
188
  const meta = await discover(process.env.ACOSMI_SERVER_URL!);
160
- const reg = await register(meta, 'My CLI', allScopes());
161
- const result = await authorize(meta, reg, allScopes(), {
162
- onEvent: (ev) => console.log(ev.type, ev.url),
189
+ const reg = await register(meta, 'My CLI'); // 不接 scopes 参数
190
+ const scopes = allScopes();
191
+
192
+ // authorize 返回 { result, verifier },result.code + result.redirectURI 给 exchangeCode
193
+ const { result, verifier } = await authorize(meta, reg.client_id, scopes, {
194
+ handler: (ev) => {
195
+ if (ev.type === 'auth_url') console.log('open in browser:', ev.url);
196
+ },
163
197
  });
164
- const tokens = await exchangeCode(meta, reg, result.code, result.codeVerifier);
198
+
199
+ const tokenResp = await exchangeCode(
200
+ meta,
201
+ reg.client_id,
202
+ result.code,
203
+ result.redirectURI, // 来自 authorize 返回;不是手动构造的 redirect_uri
204
+ verifier, // 来自 authorize 返回;不是 result.* 上的字段
205
+ );
206
+
207
+ const tokens = newTokenSet(tokenResp, reg.client_id, process.env.ACOSMI_SERVER_URL!);
208
+ await new FileTokenStore('./tokens.json').save(tokens);
165
209
  ```
166
210
 
211
+ > 浏览器侧(无法启 loopback HTTP server)请改用 v1.4.0+ Web OAuth 原语 `discoverWebOAuthMetadata` + `registerWebOAuthClient` + `createWebAuthorizationRequest` + `completeWebAuthorizationRequest`,由调用方实现 popup / 同窗口 redirect handler,SDK 负责 PKCE / state 校验 / token 兑换。
212
+
167
213
  ### Token 持久化
168
214
 
169
215
  ```ts
@@ -179,16 +225,20 @@ const client = new Client({ serverURL: process.env.ACOSMI_SERVER_URL!, store: ne
179
225
 
180
226
  | 模块 | 主要方法 |
181
227
  | ------------ | ------------------------------------------------------------------------------------ |
182
- | **Chat** | `chat`, `chatStream`, `chatStreamWithUsage` |
228
+ | **Client 构造** | `new Client(cfg)`(同步),`Client.create(cfg)`(async;预加载已有 TokenStore) |
229
+ | **Chat** | `chat`, `chatStream`, `chatStreamWithUsage`, `chatMessages`, `chatMessagesStream`, `buildChatRequest` |
183
230
  | **Agent Runs** | `agentRuns.create`, `agentRuns.stream`, `agentRuns.run`, `agentRuns.cancel`, `agentRuns.get`, `agentRuns.listArtifacts`, `agentRuns.downloadArtifact`, `agentRuns.submitLocalToolResult`, `agentRuns.runWithLocalTools` |
184
- | **Auth** | `login`, `logout`, `ensureToken`, `forceRefresh`, `discover`, `authorize`, `exchangeCode`, `refreshToken` |
185
- | **Models** | `listModels`, `listModelsWithStatus`, `getModelCapabilities`, `getQuotaSummary`, `modelSupportsInputModality`, `modelSupportsImageInput`, `findFirstModelByInputModality`, `findDesktopVisualUnderstandingModel` |
186
- | **Skills** | `browseSkills`, `browseSkillsList`, `getSkillDetail`, `resolveSkill`, `installSkill`, `downloadSkill`, `uploadSkill`, `generateSkill`, `optimizeSkill`, `validateSkill` |
231
+ | **Auth — 内置 Loopback OAuth** | `login`, `loginWithHandler`, `logout`, `ensureToken`, `forceRefresh`, `isAuthorized`, `getTokenSet` |
232
+ | **Auth — 手动 OAuth 原语** | `discover`, `discoverWithProfile`, `register`, `authorize`, `exchangeCode`, `refreshToken`, `revokeToken`, `generateState` |
233
+ | **Auth 浏览器 Web OAuth (v1.4.0+)** | `discoverWebOAuthMetadata`, `registerWebOAuthClient`, `createWebAuthorizationRequest`, `completeWebAuthorizationRequest` |
234
+ | **Models** | `listModels`, `listModelsWithStatus`, `getModelCapabilities`, `getQuotaSummary`, `ensureModelCached`, `modelSupportsInputModality`, `modelSupportsImageInput`, `findFirstModelByInputModality`, `findDesktopVisualUnderstandingModel` |
235
+ | **Skills** | `browseSkillStore`, `browseSkills`, `browseSkillsList`, `getSkillDetail`, `getSkillSummary`, `resolveSkill`, `installSkill`, `downloadSkill`, `uploadSkill`, `generateSkill`, `optimizeSkill`, `validateSkill`, `certifySkill`, `getCertificationStatus` |
187
236
  | **Tools** | `listTools`, `getTool` |
188
237
  | **Wallet** | `getWalletStats`, `getWalletTransactions` |
189
- | **Entitlements** | `getBalance`, `getBalanceDetail`, `listEntitlements`, `claimMonthlyFree`, `getByModel`, `listBuckets`, `listCoefficients` |
190
- | **Packages** | `listTokenPackages`, `buyTokenPackage`, `getOrderStatus`, `waitForPayment` |
191
- | **Notifications** | `listNotifications`, `getUnreadCount`, `markNotificationRead`, `registerDevice`, `listNotificationPreferences` |
238
+ | **Entitlements** | `getBalance`, `getBalanceDetail`, `listEntitlements`, `listConsumeRecords`, `claimMonthlyFree`, `getByModel`, `listBuckets`, `listCoefficients`, `invalidateCoefficientCache` |
239
+ | **Packages** | `listTokenPackages`, `getTokenPackageDetail`, `buyTokenPackage`, `getOrderStatus`, `listMyOrders`, `waitForPayment` |
240
+ | **Notifications** | `listNotifications`, `getUnreadCount`, `markNotificationRead`, `markAllNotificationsRead`, `deleteNotification`, `registerDevice`, `unregisterDevice`, `listNotificationPreferences`, `updateNotificationPreference` |
241
+ | **Notifications — WebSocket** | `connect`, `disconnect`, `isConnected` (实时推送订阅;浏览器走原生 WebSocket,Node 18-21 需自装 `ws`,Node 22+ 用原生) |
192
242
  | **Bug Report** | `submitBugReport`, `getBugReport` |
193
243
  | **Web Search** | `newWebSearchTool` (factory) |
194
244
  | **Compliance** | `compliance.createEvidenceAsset`, `compliance.issueTimestamp`, `compliance.waitForTimestampVerified`, `compliance.buildEvidencePackage`, `compliance.createReport`, `compliance.downloadReport`, `compliance.createSigningEnvelope`, `compliance.signEnvelope`, `compliance.getProviderRequest`, `compliance.waitForProviderRequestTerminal` |
@@ -216,6 +266,39 @@ const client = new Client({ serverURL: process.env.ACOSMI_SERVER_URL!, store: ne
216
266
  > `compliance` 分页 / gate 能力预沉淀的【共享原语】;消费这些类型的命名空间方法
217
267
  > 须待对应后端端点就绪后才落地,当前 8 个占位命名空间尚未从根入口导出。
218
268
 
269
+ ### `sanitize` 命名空间(历史消息清理)
270
+
271
+ `@acosmi/sdk-ts` 把 `src/sanitize/` 整体以命名空间方式导出(`import { sanitize } from '@acosmi/sdk-ts'`),同时也通过 `@acosmi/sdk-ts/sanitize` 子路径单独导入。Client 与 ChatRequest 的粘合(`Client.prototype.applyRequestSanitizers`)由 `src/core/sanitize-bridge.ts` 通过 declaration merging 自动注入。**默认零开销**——只有显式调用 `client.setDefensiveSanitize(cfg)` 或 `client.setAutoStripEphemeralHistory(true)` 后才走流水线。
272
+
273
+ | 公开符号 | 形态 | 用途 |
274
+ | --- | --- | --- |
275
+ | `client.setDefensiveSanitize(cfg)` | Client 方法(runtime 注入) | 配置请求前底线防御(`maxMessagesTurns` 历史轮深度、`permanentDenyBlocks` block 类型黑名单、`maxImageBytes` / `maxVideoBytes` / `maxPDFBytes` base64 内联媒体上限);传 `{}` 关闭 |
276
+ | `client.setAutoStripEphemeralHistory(on)` | Client 方法(runtime 注入) | 开启后每次请求自动从 `rawMessages` 剥除带 `acosmi_ephemeral:true` 标记的 block,并联动剥引用已剥 `tool_use_id` 的 `tool_result` |
277
+ | `client.applyRequestSanitizers(req)` | Client 方法(buildChatRequest 内部自动调用) | 一般无需手动调;自定义 build 链路时可直接复用 |
278
+ | `sanitize.sanitize(messages, cfg)` | 函数 | 对消息历史做白名单过滤 + 深度 / 尺寸校验 + ephemeral 剥离,返回新数组 |
279
+ | `sanitize.dropBlocks(messages, predicate)` | 函数 | 按谓词剔除 content blocks(联动剔除引用同 tool_use_id 的 tool_result) |
280
+ | `sanitize.stripEphemeral(messages)` | 函数 | 剥离 `acosmi_ephemeral:true` 块(端口自 Go `sanitize.StripEphemeral`,bug-for-bug) |
281
+ | `sanitize.MinimalSanitizeConfig` | 类型 | sanitize 配置 |
282
+ | `sanitize.BlockType` / `BlockText` / `BlockImage` / `BlockVideo` / `BlockDocument` / `BlockSearchResult` / `BlockThinking` / `BlockRedactedThinking` / `BlockToolUse` / `BlockToolResult` / `BlockToolReference` / `BlockServerToolUse` / `BlockWebSearchToolResult` / `BlockCodeExecutionToolResult` / `BlockMCPToolUse` / `BlockMCPToolResult` / `BlockContainerUpload` | 类型 + 常量 | 已知 block 类型常量 |
283
+ | `sanitize.HistoryTooDeepError` / `BlockDeniedError` / `SizeError` | 错误 | sanitize 规则不通过时分类抛出(也导出对应单例 `ErrHistoryTooDeep` / `ErrBlockDenied`) |
284
+
285
+ ```ts
286
+ import { Client, sanitize } from '@acosmi/sdk-ts';
287
+
288
+ const client = new Client({ serverURL });
289
+
290
+ // 启用底线防御 + 自动剥 ephemeral
291
+ client.setDefensiveSanitize({
292
+ maxMessagesTurns: 64,
293
+ // 其他字段按 MinimalSanitizeConfig 形态填充
294
+ });
295
+ client.setAutoStripEphemeralHistory(true);
296
+
297
+ // 之后 chat / chatStream 走 buildChatRequest 时自动应用 applyRequestSanitizers。
298
+ ```
299
+
300
+ > 红线:**thinking 块在 Anthropic 续轮的"上一轮返回什么、下一轮就必须原样回传"硬约束下走豁免**,禁止从历史中剔除;`tool_use_id` 联动剔除规则参考 `test/sanitize/history.test.ts` 的 P0 红线测试。详细行为见 `src/sanitize/history.ts` + `defensive.ts`。
301
+
219
302
  ### 示例:Skill 商店搜索
220
303
 
221
304
  ```ts
@@ -246,7 +329,7 @@ const tool = newWebSearchTool({
246
329
 
247
330
  const resp = await client.chat('claude-opus-4-7', {
248
331
  messages: [{ role: 'user', content: '查一下 Web Components 最新规范' }],
249
- maxTokens: 2048,
332
+ max_tokens: 2048,
250
333
  tools: [tool],
251
334
  });
252
335
  ```
@@ -323,13 +406,14 @@ const view = await client.getBugReport(result.feedback_id);
323
406
  | 错误类型 | 触发 |
324
407
  | -------------------- | ---------------------------------------------------------------------- |
325
408
  | `HTTPError` | 4xx/5xx,含 `statusCode` / `body` / `type` / `retryAfter` |
326
- | `NetworkError` | TCP/DNS/TLS 失败 |
327
- | `StreamError` | SSE 流解析失败 |
409
+ | `NetworkError` | TCP/DNS/TLS 失败;含 `isTimeout()` / `isEOF()` 便捷判定 |
410
+ | `StreamError` | gateway `managed_model_stream_failed` 事件解析(含 `code` / `stage` / `retryable`) |
328
411
  | `AgentRunStreamError` | Agent Runs 流返回 `error` 事件(默认抛出;可设 `throwOnError:false` 自行消费) |
329
412
  | `BusinessError` | 网关返回 `code !== 0`,含 `code` (number) / `message` (字符串) |
330
413
  | `RateLimitError` | 429(含 `retryAfter`) |
331
414
  | `OrderTerminalError` | `waitForPayment` 终态失败 |
332
- | `CompliancePollError` | `waitForTimestampVerified` / `waitForProviderRequestTerminal` 终态失败或超时 |
415
+ | `ModelNotFoundError` | `chat` / `ensureModelCached`:listModels 自动刷新一次后仍未命中目标 modelId(v0.13.x 起替代旧硬返 anthropic 占位的行为,含 `modelId` 字段) |
416
+ | `CompliancePollError` | `waitForTimestampVerified` / `waitForProviderRequestTerminal` 终态失败或超时(含 `kind: 'timeout' | 'terminal_failure' | 'unknown'`) |
333
417
 
334
418
  ```ts
335
419
  import { HTTPError, BusinessError } from '@acosmi/sdk-ts';
@@ -482,6 +566,7 @@ client.compliance.getCapabilities(signal?) // 能力闸门列表
482
566
  client.compliance.getFeatureGate(action, signal?) // 单动作能力(便捷,一次网络请求)
483
567
  client.compliance.listOperations(req?, signal?) // 操作投影分页 → PageResult
484
568
  client.compliance.getOperation(id, signal?) // 操作投影详情
569
+ client.compliance.classifyError(err) // BusinessError → ComplianceErrorInfo | null(同顶层 classifyComplianceError,便于在 catch 块上链式调用)
485
570
 
486
571
  client.compliance.listTsaProviders(signal?) // TSA provider 只读列表
487
572
  client.compliance.getTsaStats(signal?) // 时间章统计只读视图
@@ -579,7 +664,8 @@ npm run docs # 经 TypeDoc 生成 API 参考到 docs/api/
579
664
 
580
665
  | 版本 | 状态 | 概要 |
581
666
  | --- | --- | --- |
582
- | 1.5.0 | 当前稳定版 | 沉淀 `src/shared/` 跨域共享 DTO(`PageRequest`/`PageResult` 别名、`OperationId`/`OperationStatus`/`IdempotencyKeyHeader`、`RetryAdvice` 叠加层、`PrincipalRef`/`TenantRef`、`FeatureGateStatus`/`StepUpStatus`/`BillingPreflightResult`)。纯增量;8 个平台控制面占位命名空间仍待后端契约就绪后落地。 |
667
+ | 1.5.1 | 当前稳定版 | **Docs / examples / 源码注释全量复核与修订 — 无 API 变化**。修补 8 项漂移与遗漏:README API 总览补 25+ 漏列方法(Chat 内部方法、Auth 浏览器 Web OAuth 4 原语、Skills/Notifications/Entitlements/Packages 全量、WS `connect/disconnect/isConnected`);重写 §"手动 OAuth" 段对齐 `auth.ts` 真实签名;§"双格式红线" + 三个 chat 示例 `maxTokens` → snake_case `max_tokens`;错误表补 `ModelNotFoundError`;§Agent Runs 补 13 类 stream event 完整表;新增 §`sanitize` 命名空间小节;`docs/compliance.md` 6 处 `Since v1.6/.../1.10` 统一为 `v1.5.0 (originally planned as ...)`;手册 §7 scope 数 12 → 15 + 新增 S1-S6 rollup 段;`examples/compliance-evidence-timestamp.ts` 补 `ScopeComplianceReportsWrite`(v1.3.2 漂移生产 401 隐患);`examples/auth-oauth-flow.ts` + `examples/core-chat.ts` 注释对齐当前契约;`src/index.ts` + `src/browser.ts` + `src/auth/auth.ts` 注释从 Go-port 语义改为"TS 主实现 + Web OAuth 替代品"。`typecheck` / `lint` / `vitest`(214) / `build` / `test:pack` 全绿。 |
668
+ | 1.5.0 | 稳定版 | 沉淀 `src/shared/` 跨域共享 DTO(`PageRequest`/`PageResult` 别名、`OperationId`/`OperationStatus`/`IdempotencyKeyHeader`、`RetryAdvice` 叠加层、`PrincipalRef`/`TenantRef`、`FeatureGateStatus`/`StepUpStatus`/`BillingPreflightResult`)。**同时全量 rollup compliance gateway S1-S6** 能力(原 1.6.0-1.11.0 roadmap,见 [CHANGELOG.md](./CHANGELOG.md)):S1 6 个分页列表、S2 capabilities + operations 投影、S3 TSA 只读视图、S4 envelope 收尾 + void、S5 合同模板全生命周期 + 2 新 scope(`compliance:contract_template:{read,write}`)、S6 用印执行分页(`listSealUses`)。当前 compliance scope 总数 **15** 个(`complianceScopes()` 返回)。纯增量;8 个平台控制面占位命名空间仍待后端契约就绪后落地。 |
583
669
  | 1.4.2 | 稳定版 | `src/` 从扁平 36 文件按业务域重组为 per-domain 目录;公共导出符号集合、`exports`、`dist/` 路径一字未变(纯内部重组)。新增 TypeDoc API 文档。 |
584
670
  | 1.4.1 | 稳定版 | 新增 `Config.browserRefreshMode` / `refreshProxyURL`——浏览器 Web OAuth token 刷新策略(规避 issuer CORS 403)。 |
585
671
  | 1.4.0 | 稳定版 | 新增浏览器 Web OAuth 原语 `discoverWebOAuthMetadata` / `registerWebOAuthClient`(csign `/login` Web OAuth 接入)。 |