@h-ai/ai 0.1.0-alpha.36 → 0.1.0-alpha.38

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.md CHANGED
@@ -18,13 +18,36 @@ AI 能力模块,提供统一的 `ai` 服务对象,覆盖 LLM 对话、工具
18
18
  - `ai.audio`:语音识别(ASR)与语音合成(TTS),支持完整与流式调用,覆盖 OpenAI / MiMo / Qwen / 豆包平台。
19
19
  - `ai.a2a`:Agent-to-Agent 请求处理与远端调用。
20
20
  - `@h-ai/ai/client`:前端轻量客户端(配合 API 服务)。
21
- - `AIStoreProvider`:统一存储抽象;默认 DB Provider 基于 reldb + vecdb。
21
+ - `AIStoreProvider`:统一存储抽象;无数据库时默认使用进程内临时 Store,已初始化 reldb + vecdb 时自动使用持久化 DB Provider
22
22
 
23
23
  更完整的方法清单、错误码与长示例见 [REFERENCE.md](./REFERENCE.md)。
24
24
 
25
25
  ## 快速开始
26
26
 
27
- ### 默认 DB Provider(reldb + vecdb)
27
+ ### LLM-only(零数据库依赖)
28
+
29
+ ```ts
30
+ import { ai } from '@h-ai/ai'
31
+
32
+ const init = await ai.init({
33
+ llm: {
34
+ model: 'gpt-4o-mini',
35
+ apiKey: process.env.HAI_AI_LLM_API_KEY,
36
+ },
37
+ })
38
+ if (!init.success)
39
+ return init
40
+
41
+ const result = await ai.llm.chat({
42
+ messages: [{ role: 'user', content: '你好!' }],
43
+ })
44
+
45
+ await ai.close()
46
+ ```
47
+
48
+ 未初始化 reldb/vecdb 时,AI 使用进程内临时 Store 保存会话等运行时状态;`ai.close()`、进程退出或多实例切换后数据不会保留。需要 Memory、Context、Persona 或会话跨重启持久化时,使用下面的 DB Provider。
49
+
50
+ ### 持久化 DB Provider(reldb + vecdb)
28
51
 
29
52
  ```ts
30
53
  import { ai } from '@h-ai/ai'
@@ -76,9 +99,9 @@ await ai.close()
76
99
 
77
100
  - 对外只通过 `ai` 服务对象和少量独立工厂(如 `createMcpServer`)访问。
78
101
  - 生命周期为 `await ai.init(config, options?)` / `await ai.close()`;关闭会等待自定义 `AIStoreProvider.close()`。
79
- - 公共方法返回 `HaiResult<T>` 或 `Promise<HaiResult<T>>`;业务失败通过 `result.success === false` 和 `result.error.code` 表达。
102
+ - 领域方法返回 `HaiResult<T>` 或 `Promise<HaiResult<T>>`;业务失败通过 `result.success === false` 和 `result.error.code` 表达。流式 `AsyncIterable`、客户端传输和第三方回调在建立或迭代期间可能抛异常。
80
103
  - `ai.tools` 与 `ai.stream` 是纯函数子系统,无需初始化即可使用。
81
- - 默认 DB Provider 需要 reldb/vecdb 已初始化;自定义 Provider 可隐藏其他存储后端。
104
+ - 未初始化 reldb/vecdb 时默认使用进程内临时 Store;两者均已初始化时自动使用 DB Provider。自定义 Provider 可隐藏其他存储后端。
82
105
 
83
106
  ## API 概览
84
107
 
@@ -117,13 +140,29 @@ const temp = await ai.llm.chat({
117
140
  ```ts
118
141
  import { z } from 'zod'
119
142
 
120
- const registry = ai.tools.createRegistry()
121
- registry.register(ai.tools.define({
143
+ const registry = ai.tools.createRegistry({
144
+ // 统一授权在 Zod 校验后、handler 前执行;false/异常均 fail-closed
145
+ authorize: ({ toolName, context }) => canExecuteTool(context.objectId, toolName),
146
+ })
147
+ const registered = registry.register(ai.tools.define({
122
148
  name: 'get_weather',
123
149
  description: '获取天气',
124
150
  parameters: z.object({ city: z.string() }),
125
- handler: async ({ city }) => ({ city, temperature: 20 }),
151
+ // handler 第二参为执行上下文:可响应取消(打断/超时)、感知截止时间与交互主体
152
+ handler: async ({ city }, { signal }) => {
153
+ const res = await fetch(`https://api.example.com/weather?city=${city}`, { signal })
154
+ return res.json()
155
+ },
156
+ timeoutMs: 10_000, // 本工具默认超时(可被 execute 的 deadline / timeoutMs 覆盖)
126
157
  }))
158
+ if (!registered.success)
159
+ return registered
160
+
161
+ // 执行时可传入取消信号 / 超时 / 作用域;取消或超时返回 TOOL_TIMEOUT,且不再等待未响应的 handler
162
+ const result = await registry.execute(toolCall, { signal: controller.signal, objectId: 'user-001', timeoutMs: 30_000 })
163
+
164
+ // 批量调用默认串行,避免副作用工具并发启动;纯读取且确认安全时才显式并行
165
+ const batch = await registry.executeAll(toolCalls)
127
166
 
128
167
  const chat = await ai.llm.chat({ messages, tools: registry.getDefinitions() })
129
168
  ```
@@ -152,6 +191,15 @@ if (!enriched.success) {
152
191
  return enriched
153
192
  }
154
193
 
194
+ // 多租户推荐入口:scoped() 绑定主体与作用域,所有操作自动携带 objectId / scope(含归属校验),杜绝「忘记传 objectId」越权
195
+ const memory = ai.memory.scoped({ objectId: 'user-001', scope: { topicId: 't-1', personaId: 'p-1' } })
196
+ await memory.add({ content: '用户偏好中文', type: 'preference' })
197
+ const recalled = await memory.recall('语言偏好')
198
+
199
+ // clear 拒绝空过滤(防误清全局);全局清空只能显式走管理接口
200
+ await memory.clear({ types: ['event'] }) // 仅清该作用域内的 event
201
+ await ai.memory.admin.clearAll({ confirm: true }) // 危险:清空整个记忆后端,需显式确认
202
+
155
203
  const rag = await ai.rag.query('核心架构是什么?', { sources: ['docs'], topK: 5 })
156
204
 
157
205
  const setup = await ai.knowledge.setup()
@@ -200,7 +248,9 @@ for await (const event of ai.audio.synthesizeStream({
200
248
  instruction: '用轻快的语气',
201
249
  signal: controller.signal,
202
250
  })) {
203
- if (event.type === 'audio')
251
+ if (event.type === 'segment_started')
252
+ prepareDecoder(event.format, event.sampleRate, event.channels) // 真实输出格式来自服务端解析后的 Provider 输出
253
+ else if (event.type === 'audio')
204
254
  await player.write(event.data)
205
255
  else if (event.type === 'segment_done')
206
256
  markSegmentReadyToCommit(event.segmentId)
@@ -211,11 +261,11 @@ const caps = ai.audio.getCapabilities({ operation: 'synthesize', model: 'tts' })
211
261
  if (caps.success && caps.data.synthesize?.streamingAudioOutput) { /* 可实时 TTS */ }
212
262
  ```
213
263
 
214
- > `synthesizeStream` 严格按 `segment_started → audio* → segment_done` 产出事件。播放器只有在对应音频真正播放完成后才应把该段文本计入 `spokenText`;播放状态仍由应用管理。
264
+ > `synthesizeStream` 严格按 `segment_started → audio* → segment_done` 产出事件。`segment_started` 携带服务端解析 Provider 后的**真实输出音频参数**(`format` / `sampleRate` / `channels`),播放器据此正确解码,不应按请求参数猜测格式。播放器只有在对应音频真正播放完成后才应把该段文本计入 `spokenText`;播放状态仍由应用管理。
215
265
 
216
- 取消/超时/连接错误统一为领域错误:`AbortSignal` 触发 → `AUDIO_CANCELLED`(超时 → `AUDIO_TIMEOUT`),连接失败 → `AUDIO_CONNECTION_FAILED`。实时连接时长受 `audio.maxStreamDurationMs`(默认 5 分钟)限制。
266
+ 取消/超时/连接错误统一为领域错误:`AbortSignal` 触发 → `AUDIO_CANCELLED`(超时 → `AUDIO_TIMEOUT`),连接失败或 `end` 前异常断连 → `AUDIO_CONNECTION_FAILED`。实时连接时长受 `audio.maxStreamDurationMs`(默认 5 分钟)限制。
217
267
 
218
- 浏览器 / 移动端通过 `@h-ai/serv` 暴露的统一语音 WebSocket 入口访问,`@h-ai/ai/client` 提供与 Node 端一致的 `audio.*` API(传输细节内部隐藏)。
268
+ 浏览器 / 移动端通过 `@h-ai/serv` 暴露的统一语音 WebSocket 入口访问,`@h-ai/ai/client` 提供与 Node 端一致的 `audio.*` API(传输细节内部隐藏)。浏览器客户端严格区分正常结束、取消(`AUDIO_CANCELLED`)与异常断连(`AUDIO_CONNECTION_FAILED`):取消或在 `end` 前断连会抛出对应领域错误码,`synthesize` 不会把未完成的部分音频当作成功结果返回。
219
269
 
220
270
  ### Context 管理器
221
271
 
@@ -224,13 +274,18 @@ const manager = ai.context.createManager({
224
274
  scope: { objectId: 'user-001', sessionId: 'sess-001' },
225
275
  compress: { auto: true, strategy: 'hybrid', maxTokens: 8000 },
226
276
  memory: { enable: true, enableExtract: true },
277
+ concurrency: 'reject', // 单活动生成(默认):活动生成期间的新 chat 返回 CONTEXT_BUSY;'queue' 则排队
227
278
  })
228
279
  if (manager.success) {
229
280
  const reply = await manager.data.chat('你好')
230
281
  await manager.data.save()
282
+ // reset 生命周期完整:终止活动生成、清空消息/摘要/轮次,默认保留系统提示词
283
+ await manager.data.reset() // 可传 { preserveSystemPrompt, cancelActiveTurn, waitForMemoryTasks }
231
284
  }
232
285
  ```
233
286
 
287
+ 同一管理器默认实行**单活动生成**,避免「上一轮 AI 尚未退出,下一轮 user 消息先写入」导致的消息乱序;`reset()` 现为异步并会终止活动生成、释放并发屏障、清空轮次并默认重新写入 Persona/System Prompt。
288
+
234
289
  #### 真实对话状态(Conversation Commit Layer)
235
290
 
236
291
  默认(`turnCommit: 'auto'`)下,`chat` / `chatStream` 会把**模型生成的完整文本**写入上下文。但在「模型生成 → TTS 合成 → 实际播放」链路中,AI 可能说到一半就被打断——此时进入下一轮所有参与者可见的对话状态,应当是**实际播放出去的部分**,而非模型本想说完的全文。
@@ -266,6 +321,7 @@ const turns = m.getTurns()
266
321
  - `commitTurn(turnId, { text? })` — 提交真实文本(缺省用完整生成文本),状态转 `completed`。
267
322
  - `interruptTurn(turnId, { text? })` — 只写入实际表达出去的部分(缺省视为未表达,不写入),状态转 `interrupted`。
268
323
  - 只有 `committed` 的内容进入上下文与记忆提取;未提交/被打断丢弃的部分不会污染后续轮次。
324
+ - 若轮次在流完成前已被 `interruptTurn` 打断(如主持人抢话,同时上游模型恰好正常结束),`chatStream` **不会再产出 `done`**,避免业务层误判为正常完成后继续提交文本。
269
325
 
270
326
  #### 会话固化(Memory 生命周期)
271
327
 
@@ -356,7 +412,7 @@ memory:
356
412
  ```
357
413
 
358
414
  - **`native`(默认,推荐)**:HAI 原生引擎,复用同一套 vecdb(向量库)、reldb(关系库)、LLM 与 Embedding。`extract` 采用 **Mem0 式批量合并**——一次 LLM 调用对整批抽取事实与相关既有记忆做 ADD / UPDATE / DELETE / NONE 决策,实现增量更新、跨条去重与矛盾删除,并支持 `category` 主题标签。`maxEntriesPerObject`、`maxEntriesGlobal`、`recencyDecay`、`embeddingEnabled`、`writebackRelatedTopK` 均作用于此后端;淘汰按 `objectId` 分区触发,不会因某一主体写入过多而淘汰其他主体的记忆。native 后端的 `scope` 过滤:候选集已被 `objectId` 索引收窄(≤ `maxEntriesPerObject`),PostgreSQL 上还会把 scope 下推为 `data @> '{"scope":...}'::jsonb` 包含查询并命中 JSONB **GIN 索引**(SQLite / MySQL 退回内存匹配,结果一致)。
359
- - **`mem0`(真·mem0ai/oss)**:直接使用 `mem0ai/oss` 的 `Memory` 引擎(嵌入式,无云服务)。LLM / Embedder 从 `llm` 配置提取(OpenAI 兼容,走 `baseUrl` / `apiKey` / 场景模型);向量库从底层 vecdb 后端提取——`qdrant` / `pgvector` 直接复用同一后端,`lancedb` / `chroma`(mem0 TS 不支持)则退回 mem0 自带的 in-memory 存储。历史记录默认禁用。需安装 `mem0ai`(已内置为依赖);复用 qdrant/pgvector 时需对应客户端。
415
+ - **`mem0`(真·mem0ai/oss)**:直接使用 `mem0ai/oss` 的 `Memory` 引擎(嵌入式,无云服务)。LLM / Embedder 从 `llm` 配置提取;`qdrant` / `pgvector` 可复用底层 vecdb。无法映射 `lancedb` / `chroma` 等后端时默认 fail-fast,只有显式设置 `memory.allowEphemeralFallback: true` 才使用 mem0 in-memory,避免重启后静默丢失记忆。历史记录默认禁用。
360
416
 
361
417
  两个 Provider 对外 `ai.memory.*` API 完全一致(`extract` / `recall` / `injectMemories` / `add` / `update` / `get` / `remove` / `list` / `listPage` / `clear`),均支持 `objectId`(主体隔离)与 `scope`(业务作用域 key-value 过滤,如 `{ topicId, personaId }`)。`recall` / `list` / `listPage` / `clear` 均按 `scope` 严格过滤,`clear` 在传入 `types` / `scope` 时仅删除同时匹配项(避免误删)。mem0 后端的 `extract` 在框架层用统一提取器完成分类与打分(honor `types` / `model` / `minImportance` / `systemPrompt`)后以 `infer:false` 写入,保留 `hai_type` / `hai_importance`;`recall` 同样支持 `types` 过滤与 `recencyWeight` 时间衰减——二者行为与 native 一致。一个差异:mem0 后端在 `update` 涉及 type/importance/metadata 时会重建记忆并重新分配 `id`(native 后端保持 id 稳定)。
362
418
 
@@ -1,8 +1,10 @@
1
1
  import * as _h_ai_core from '@h-ai/core';
2
2
  import { HaiResult } from '@h-ai/core';
3
- import { aF as ChatMessage, aQ as InteractionScope, O as MemoryType, bo as RagOptions, bs as ReasoningOptions, bV as ToolRegistryOperations, ba as MemoryEntry, bF as SessionInfo, b6 as LLMOperations, bg as MemoryOperations, bn as RagOperations, br as ReasoningOperations, c as AIConfig, d as AIConfigInput, au as AIStoreProvider, bW as ToolsOperations, bJ as StreamOperations, by as RetrievalOperations, b0 as KnowledgeOperations, ao as A2AOperations, q as AudioOperations, l as AudioFormat } from './ai-reasoning-types-DLLzpn6T.js';
3
+ import { aG as ChatMessage, af as InteractionScope, O as MemoryType, br as RagOptions, bv as ReasoningOptions, c2 as ToolRegistryOperations, bd as MemoryEntry, bK as SessionInfo, b6 as LLMOperations, bj as MemoryOperations, bq as RagOperations, bu as ReasoningOperations, c as AIConfig, d as AIConfigInput, av as AIStoreProvider, c4 as ToolsOperations, bO as StreamOperations, bB as RetrievalOperations, b0 as KnowledgeOperations, ap as A2AOperations, q as AudioOperations, l as AudioFormat } from './ai-reasoning-types-CslaY4xX.js';
4
+ import * as zod from 'zod';
4
5
  import { z } from 'zod';
5
6
  import { Buffer } from 'node:buffer';
7
+ import * as zod_v4_core from 'zod/v4/core';
6
8
 
7
9
  /**
8
10
  * @h-ai/ai — Compress 子功能类型
@@ -279,6 +281,20 @@ interface ContextManagerOptions {
279
281
  * 部分才应进入下一轮所有参与者可见的对话状态,而不是模型本想说完的全文。
280
282
  */
281
283
  turnCommit?: 'auto' | 'manual';
284
+ /**
285
+ * 并发生成策略(默认 `reject`)
286
+ *
287
+ * ContextManager 默认实行**单活动生成**:同一管理器同一时刻只允许一个未完成的
288
+ * `chat` / `chatStream` 轮次,避免「上一轮 AI 尚未退出,下一轮 user 消息先写入」
289
+ * 导致的消息乱序(user1 → user2 → assistant1)。
290
+ *
291
+ * - `reject`:已有活动生成时,新的 `chat` / `chatStream` 立即返回 `CONTEXT_BUSY` 错误。
292
+ * - `queue`:新请求排队,等待前一轮次进入终态(`completed` / `interrupted`)后再开始。
293
+ *
294
+ * `manual` 提交模式下,屏障持续到 `commitTurn` / `interruptTurn` 提交真实文本为止,
295
+ * 因此「打断当前轮次 → 立即发起下一轮」也能保证顺序正确。
296
+ */
297
+ concurrency?: 'reject' | 'queue';
282
298
  /**
283
299
  * 压缩配置(覆盖全局 compress 配置)
284
300
  *
@@ -345,6 +361,32 @@ interface ContextManagerOptions {
345
361
  */
346
362
  maxToolRounds?: number;
347
363
  }
364
+ /**
365
+ * 重置管理器选项(`ContextManager.reset` 使用)
366
+ */
367
+ interface ContextResetOptions {
368
+ /**
369
+ * 是否保留系统提示词(默认 `true`)
370
+ *
371
+ * 系统提示词(Persona / System Prompt)只在创建时追加一次;重置若不保留,
372
+ * 会连同对话历史一起清空。默认重新写入系统提示词,避免 Persona 语义丢失。
373
+ */
374
+ preserveSystemPrompt?: boolean;
375
+ /**
376
+ * 是否终止活动轮次(默认 `true`)
377
+ *
378
+ * 为 `true` 时:中断内部生成信号,使所有非终态轮次进入 `interrupted` 终态,
379
+ * 释放并发屏障,并阻止这些旧轮次在重置后被再次 `commitTurn` / `interruptTurn`。
380
+ */
381
+ cancelActiveTurn?: boolean;
382
+ /**
383
+ * 是否等待后台记忆提取任务完成后再清空(默认 `false`)
384
+ *
385
+ * 为 `true` 时先 `flush()` 等待正在运行的记忆提取写入完成;否则不等待
386
+ * (已在途的提取任务仍会自行写入记忆后端,但其结果不再影响本管理器状态)。
387
+ */
388
+ waitForMemoryTasks?: boolean;
389
+ }
348
390
  /**
349
391
  * 单次 chat/chatStream 请求的覆盖选项
350
392
  */
@@ -507,9 +549,15 @@ interface ContextManager {
507
549
  */
508
550
  readonly pendingMemoryTasks: number;
509
551
  /**
510
- * 重置管理器(清空所有消息和摘要)
552
+ * 重置管理器
553
+ *
554
+ * 默认行为:终止活动轮次(进入终态并释放并发屏障)、清空消息 / 摘要 / 轮次 /
555
+ * 待提交轮次,并重新写入系统提示词。可通过选项调整。
556
+ *
557
+ * @param options - 重置选项(保留系统提示词 / 终止活动轮次 / 等待记忆任务)
558
+ * @returns 成功返回 ok(undefined)
511
559
  */
512
- reset: () => void;
560
+ reset: (options?: ContextResetOptions) => Promise<HaiResult<void>>;
513
561
  /**
514
562
  * 获取对话轮次列表(Conversation Commit Layer)
515
563
  *
@@ -1327,6 +1375,8 @@ declare const HaiAIError: {
1327
1375
  readonly TOOL_VALIDATION_FAILED: _h_ai_core.HaiErrorDef;
1328
1376
  readonly TOOL_EXECUTION_FAILED: _h_ai_core.HaiErrorDef;
1329
1377
  readonly TOOL_TIMEOUT: _h_ai_core.HaiErrorDef;
1378
+ readonly TOOL_ALREADY_REGISTERED: _h_ai_core.HaiErrorDef;
1379
+ readonly TOOL_FORBIDDEN: _h_ai_core.HaiErrorDef;
1330
1380
  readonly REASONING_FAILED: _h_ai_core.HaiErrorDef;
1331
1381
  readonly REASONING_MAX_ROUNDS: _h_ai_core.HaiErrorDef;
1332
1382
  readonly REASONING_STRATEGY_NOT_FOUND: _h_ai_core.HaiErrorDef;
@@ -1368,6 +1418,7 @@ declare const HaiAIError: {
1368
1418
  readonly CONTEXT_BUDGET_EXCEEDED: _h_ai_core.HaiErrorDef;
1369
1419
  readonly CONTEXT_TURN_NOT_FOUND: _h_ai_core.HaiErrorDef;
1370
1420
  readonly CONTEXT_TURN_INVALID_STATE: _h_ai_core.HaiErrorDef;
1421
+ readonly CONTEXT_BUSY: _h_ai_core.HaiErrorDef;
1371
1422
  readonly STORE_FAILED: _h_ai_core.HaiErrorDef;
1372
1423
  readonly STORE_NOT_AVAILABLE: _h_ai_core.HaiErrorDef;
1373
1424
  readonly SESSION_NOT_FOUND: _h_ai_core.HaiErrorDef;
@@ -1388,8 +1439,8 @@ interface AIInitOptions {
1388
1439
  /**
1389
1440
  * 自定义存储 Provider
1390
1441
  *
1391
- * 提供后 AI 模块将使用此 Provider 而非默认的 reldb+vecdb 实现,
1392
- * 此时不需要提前初始化 reldb/vecdb。
1442
+ * 提供后 AI 模块将使用此 Provider,而不采用自动选择的存储实现。
1443
+ * 未提供时:reldb + vecdb 已初始化则使用持久化 DB Provider,否则使用进程内临时 Provider
1393
1444
  */
1394
1445
  storeProvider?: AIStoreProvider;
1395
1446
  }
@@ -1471,15 +1522,6 @@ interface AIFunctions {
1471
1522
  readonly audio: AudioOperations;
1472
1523
  }
1473
1524
 
1474
- /**
1475
- * @h-ai/ai — 统一语音 WebSocket 协议
1476
- *
1477
- * 定义浏览器 / 远程客户端与 `@h-ai/serv` 语音入口之间的统一 WebSocket 消息协议。
1478
- * 客户端与服务端共享此协议,客户端不接收任何厂商原生事件;音频以二进制帧传输,
1479
- * 控制与文本以 JSON 帧传输。
1480
- * @module audio/ai-audio-ws-protocol
1481
- */
1482
-
1483
1525
  /** 统一语音入口的默认路径(相对 API 前缀) */
1484
1526
  declare const AUDIO_WS_PATH = "/ai/audio";
1485
1527
  /**
@@ -1529,6 +1571,74 @@ interface AudioWsDoneMessage {
1529
1571
  }
1530
1572
  /** 客户端 JSON 控制消息(音频输入以二进制帧发送,不走 JSON) */
1531
1573
  type AudioWsClientMessage = AudioWsStartMessage | AudioWsTextMessage | AudioWsDoneMessage;
1574
+ /** 合法音频格式 */
1575
+ declare const AudioFormatSchema: zod.ZodEnum<{
1576
+ pcm16: "pcm16";
1577
+ wav: "wav";
1578
+ mp3: "mp3";
1579
+ opus: "opus";
1580
+ }>;
1581
+ /** 单个字符串控制字段最大长度(model / language / voice / instruction 等) */
1582
+ /** 会话起始帧 Schema */
1583
+ declare const AudioWsStartMessageSchema: zod.ZodObject<{
1584
+ type: zod.ZodLiteral<"start">;
1585
+ operation: zod.ZodEnum<{
1586
+ transcribe: "transcribe";
1587
+ synthesize: "synthesize";
1588
+ }>;
1589
+ stream: zod.ZodOptional<zod.ZodBoolean>;
1590
+ model: zod.ZodOptional<zod.ZodString>;
1591
+ language: zod.ZodOptional<zod.ZodString>;
1592
+ contextHints: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
1593
+ voice: zod.ZodOptional<zod.ZodString>;
1594
+ instruction: zod.ZodOptional<zod.ZodString>;
1595
+ format: zod.ZodOptional<zod.ZodEnum<{
1596
+ pcm16: "pcm16";
1597
+ wav: "wav";
1598
+ mp3: "mp3";
1599
+ opus: "opus";
1600
+ }>>;
1601
+ sampleRate: zod.ZodOptional<zod.ZodNumber>;
1602
+ channels: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodLiteral<1>, zod.ZodLiteral<2>]>>;
1603
+ }, zod_v4_core.$strip>;
1604
+ /** 文本输入帧 Schema(segmentId 非空且长度受限) */
1605
+ declare const AudioWsTextMessageSchema: zod.ZodObject<{
1606
+ type: zod.ZodLiteral<"text">;
1607
+ segmentId: zod.ZodString;
1608
+ text: zod.ZodString;
1609
+ }, zod_v4_core.$strip>;
1610
+ /** 输入结束帧 Schema */
1611
+ declare const AudioWsDoneMessageSchema: zod.ZodObject<{
1612
+ type: zod.ZodLiteral<"done">;
1613
+ }, zod_v4_core.$strip>;
1614
+ /** 客户端 JSON 控制消息 Schema(按 type 判别) */
1615
+ declare const AudioWsClientMessageSchema: zod.ZodDiscriminatedUnion<[zod.ZodObject<{
1616
+ type: zod.ZodLiteral<"start">;
1617
+ operation: zod.ZodEnum<{
1618
+ transcribe: "transcribe";
1619
+ synthesize: "synthesize";
1620
+ }>;
1621
+ stream: zod.ZodOptional<zod.ZodBoolean>;
1622
+ model: zod.ZodOptional<zod.ZodString>;
1623
+ language: zod.ZodOptional<zod.ZodString>;
1624
+ contextHints: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
1625
+ voice: zod.ZodOptional<zod.ZodString>;
1626
+ instruction: zod.ZodOptional<zod.ZodString>;
1627
+ format: zod.ZodOptional<zod.ZodEnum<{
1628
+ pcm16: "pcm16";
1629
+ wav: "wav";
1630
+ mp3: "mp3";
1631
+ opus: "opus";
1632
+ }>>;
1633
+ sampleRate: zod.ZodOptional<zod.ZodNumber>;
1634
+ channels: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodLiteral<1>, zod.ZodLiteral<2>]>>;
1635
+ }, zod_v4_core.$strip>, zod.ZodObject<{
1636
+ type: zod.ZodLiteral<"text">;
1637
+ segmentId: zod.ZodString;
1638
+ text: zod.ZodString;
1639
+ }, zod_v4_core.$strip>, zod.ZodObject<{
1640
+ type: zod.ZodLiteral<"done">;
1641
+ }, zod_v4_core.$strip>], "type">;
1532
1642
  /** 语音起止事件(识别操作时服务端 VAD 检测到语音开始 / 结束) */
1533
1643
  interface AudioWsSpeechMessage {
1534
1644
  type: 'speech_started' | 'speech_stopped';
@@ -1541,11 +1651,21 @@ interface AudioWsTranscriptMessage {
1541
1651
  /** 是否为该语句的最终结果 */
1542
1652
  final: boolean;
1543
1653
  }
1544
- /** 合成文本段开始;后续二进制帧均属于该段,直到收到对应的 `segment_done`。 */
1654
+ /**
1655
+ * 合成文本段开始;后续二进制帧均属于该段,直到收到对应的 `segment_done`。
1656
+ *
1657
+ * 携带服务端解析 Provider 后的真实输出音频参数,供浏览器正确标注音频格式。
1658
+ */
1545
1659
  interface AudioWsSegmentStartedMessage {
1546
1660
  type: 'segment_started';
1547
1661
  segmentId: string;
1548
1662
  text: string;
1663
+ /** 真实输出音频格式(来自服务端解析后的 Provider 输出,非客户端请求参数) */
1664
+ format: AudioFormat;
1665
+ /** 采样率(Hz);pcm16 等裸音频必填 */
1666
+ sampleRate?: number;
1667
+ /** 声道数(默认单声道) */
1668
+ channels?: 1 | 2;
1549
1669
  }
1550
1670
  /** 合成文本段的音频已全部发送。 */
1551
1671
  interface AudioWsSegmentDoneMessage {
@@ -1567,4 +1687,4 @@ interface AudioWsEndMessage {
1567
1687
  /** 服务端 JSON 消息(合成音频以二进制帧返回,不走 JSON) */
1568
1688
  type AudioWsServerMessage = AudioWsSpeechMessage | AudioWsTranscriptMessage | AudioWsSegmentStartedMessage | AudioWsSegmentDoneMessage | AudioWsErrorMessage | AudioWsEndMessage;
1569
1689
 
1570
- export { type MCPToolDefinition as $, type AIFunctions as A, type ContextOperations as B, type CompressionStrategy as C, type ContextStreamEvent as D, type ConversationTurn as E, type ConversationTurnStatus as F, type EmbeddingItem as G, HaiAIError as H, type EmbeddingOperations as I, type EmbeddingProvider as J, type EmbeddingRequest as K, type EmbeddingResponse as L, type McpServerOptions as M, type FileOperations as N, type FileParseMethod as O, type FileParseOptions as P, type FileParseRequest as Q, type FileParseResult as R, type MCPContext as S, type MCPOperations as T, type MCPPrompt as U, type MCPPromptArgument as V, type MCPPromptContent as W, type MCPPromptMessage as X, type MCPProvider as Y, type MCPResource as Z, type MCPResourceContent as _, type AIInitOptions as a, type MCPToolHandler as a0, type OutputFormat as a1, type PersonaOperations as a2, type PersonaProfile as a3, type PersonaProfileInput as a4, type PersonaProfileUpdate as a5, type PersonaScopeOptions as a6, type RerankDocument as a7, type RerankItem as a8, type RerankOperations as a9, type RerankRequest as aa, type RerankResponse as ab, type SummaryOperations as ac, type SummaryOptions as ad, type SummaryResult as ae, type TokenOperations as af, AUDIO_WS_PATH as b, type AudioWsClientMessage as c, type AudioWsDoneMessage as d, type AudioWsEndMessage as e, type AudioWsErrorMessage as f, type AudioWsSegmentDoneMessage as g, type AudioWsSegmentStartedMessage as h, type AudioWsServerMessage as i, type AudioWsSpeechMessage as j, type AudioWsStartMessage as k, type AudioWsTextMessage as l, type AudioWsTranscriptMessage as m, CompressionStrategySchema as n, type AIMCPFunctionsDeps as o, type CommitTurnInput as p, type CompressOperations as q, type CompressOptions as r, type CompressResult as s, type ConsolidateOptions as t, type ConsolidateResult as u, type ContextChatOptions as v, type ContextChatResult as w, type ContextDeps as x, type ContextManager as y, type ContextManagerOptions as z };
1690
+ export { type MCPPromptArgument as $, type AIFunctions as A, type ContextChatOptions as B, type CompressionStrategy as C, type ContextChatResult as D, type ContextDeps as E, type ContextManager as F, type ContextManagerOptions as G, HaiAIError as H, type ContextOperations as I, type ContextResetOptions as J, type ContextStreamEvent as K, type ConversationTurn as L, type McpServerOptions as M, type ConversationTurnStatus as N, type EmbeddingItem as O, type EmbeddingOperations as P, type EmbeddingProvider as Q, type EmbeddingRequest as R, type EmbeddingResponse as S, type FileOperations as T, type FileParseMethod as U, type FileParseOptions as V, type FileParseRequest as W, type FileParseResult as X, type MCPContext as Y, type MCPOperations as Z, type MCPPrompt as _, type AIInitOptions as a, type MCPPromptContent as a0, type MCPPromptMessage as a1, type MCPProvider as a2, type MCPResource as a3, type MCPResourceContent as a4, type MCPToolDefinition as a5, type MCPToolHandler as a6, type OutputFormat as a7, type PersonaOperations as a8, type PersonaProfile as a9, type PersonaProfileInput as aa, type PersonaProfileUpdate as ab, type PersonaScopeOptions as ac, type RerankDocument as ad, type RerankItem as ae, type RerankOperations as af, type RerankRequest as ag, type RerankResponse as ah, type SummaryOperations as ai, type SummaryOptions as aj, type SummaryResult as ak, type TokenOperations as al, AUDIO_WS_PATH as b, AudioFormatSchema as c, type AudioWsClientMessage as d, AudioWsClientMessageSchema as e, type AudioWsDoneMessage as f, AudioWsDoneMessageSchema as g, type AudioWsEndMessage as h, type AudioWsErrorMessage as i, type AudioWsSegmentDoneMessage as j, type AudioWsSegmentStartedMessage as k, type AudioWsServerMessage as l, type AudioWsSpeechMessage as m, type AudioWsStartMessage as n, AudioWsStartMessageSchema as o, type AudioWsTextMessage as p, AudioWsTextMessageSchema as q, type AudioWsTranscriptMessage as r, CompressionStrategySchema as s, type AIMCPFunctionsDeps as t, type CommitTurnInput as u, type CompressOperations as v, type CompressOptions as w, type CompressResult as x, type ConsolidateOptions as y, type ConsolidateResult as z };