@h-ai/ai 0.1.0-alpha.35 → 0.1.0-alpha.36
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 +48 -17
- package/dist/{ai-audio-ws-protocol-C-V8N8YL.d.ts → ai-audio-ws-protocol-CsmuWetO.d.ts} +33 -9
- package/dist/{ai-reasoning-types-BGf-x2Qj.d.ts → ai-reasoning-types-DLLzpn6T.d.ts} +101 -42
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +2 -2
- package/dist/{chunk-AXIZBZMV.js → chunk-535CQURK.js} +36 -17
- package/dist/chunk-535CQURK.js.map +1 -0
- package/dist/{chunk-URXCNMJW.js → chunk-UROBPUCF.js} +15 -2
- package/dist/chunk-UROBPUCF.js.map +1 -0
- package/dist/client/index.d.ts +6 -6
- package/dist/client/index.js +1 -1
- package/dist/index.d.ts +34 -4
- package/dist/index.js +574 -420
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/dist/chunk-AXIZBZMV.js.map +0 -1
- package/dist/chunk-URXCNMJW.js.map +0 -1
|
@@ -119,11 +119,11 @@ function openBrowserWs(url, signal) {
|
|
|
119
119
|
}
|
|
120
120
|
function createAudioClient(config) {
|
|
121
121
|
async function buildUrl() {
|
|
122
|
-
const
|
|
123
|
-
if (!
|
|
124
|
-
|
|
122
|
+
const ticket = await config.getTicket();
|
|
123
|
+
if (!ticket)
|
|
124
|
+
throw new Error("Audio WebSocket ticket is required");
|
|
125
125
|
const separator = config.url.includes("?") ? "&" : "?";
|
|
126
|
-
return `${config.url}${separator}
|
|
126
|
+
return `${config.url}${separator}ticket=${encodeURIComponent(ticket)}`;
|
|
127
127
|
}
|
|
128
128
|
function startMessage(operation, extra) {
|
|
129
129
|
return JSON.stringify({ type: "start", operation, ...extra });
|
|
@@ -196,30 +196,41 @@ function createAudioClient(config) {
|
|
|
196
196
|
try {
|
|
197
197
|
conn.send(startMessage("synthesize", { model: request.model, voice: request.voice, instruction: request.instruction, format: request.format, sampleRate: request.sampleRate }));
|
|
198
198
|
const sendText = (async () => {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
for await (const part of request.text)
|
|
203
|
-
conn.send(JSON.stringify({ type: "text", text: part }));
|
|
204
|
-
}
|
|
199
|
+
const segments = isSynthesisTextSegment(request.text) ? singleSegment(request.text) : request.text;
|
|
200
|
+
for await (const segment of segments)
|
|
201
|
+
conn.send(JSON.stringify({ type: "text", segmentId: segment.id, text: segment.text }));
|
|
205
202
|
conn.send(JSON.stringify({ type: "done" }));
|
|
206
203
|
})();
|
|
207
204
|
let sendError;
|
|
208
205
|
sendText.catch((e) => {
|
|
209
206
|
sendError = e;
|
|
210
207
|
});
|
|
208
|
+
let activeSegmentId;
|
|
211
209
|
for await (const message of conn.messages()) {
|
|
212
210
|
if (message.isBinary && message.binary) {
|
|
213
|
-
|
|
211
|
+
if (!activeSegmentId)
|
|
212
|
+
throw new Error("Audio frame received outside a synthesis segment");
|
|
213
|
+
yield { type: "audio", segmentId: activeSegmentId, data: message.binary };
|
|
214
214
|
continue;
|
|
215
215
|
}
|
|
216
216
|
if (!message.text)
|
|
217
217
|
continue;
|
|
218
218
|
const event = JSON.parse(message.text);
|
|
219
|
-
if (event.type === "
|
|
219
|
+
if (event.type === "segment_started") {
|
|
220
|
+
if (activeSegmentId)
|
|
221
|
+
throw new Error("Synthesis segment started before the previous segment completed");
|
|
222
|
+
activeSegmentId = event.segmentId;
|
|
223
|
+
yield event;
|
|
224
|
+
} else if (event.type === "segment_done") {
|
|
225
|
+
if (activeSegmentId !== event.segmentId)
|
|
226
|
+
throw new Error("Synthesis segment completion does not match the active segment");
|
|
227
|
+
yield event;
|
|
228
|
+
activeSegmentId = void 0;
|
|
229
|
+
} else if (event.type === "error") {
|
|
220
230
|
throw new Error(`${event.code}: ${event.message}`);
|
|
221
|
-
else if (event.type === "end")
|
|
231
|
+
} else if (event.type === "end") {
|
|
222
232
|
break;
|
|
233
|
+
}
|
|
223
234
|
}
|
|
224
235
|
if (sendError)
|
|
225
236
|
throw sendError;
|
|
@@ -229,8 +240,10 @@ function createAudioClient(config) {
|
|
|
229
240
|
}
|
|
230
241
|
async function synthesize(request) {
|
|
231
242
|
const chunks = [];
|
|
232
|
-
for await (const
|
|
233
|
-
|
|
243
|
+
for await (const event of synthesizeStream({ ...request, text: { id: "synthesis", text: request.text } })) {
|
|
244
|
+
if (event.type === "audio")
|
|
245
|
+
chunks.push(event.data);
|
|
246
|
+
}
|
|
234
247
|
const total = chunks.reduce((sum, c) => sum + c.length, 0);
|
|
235
248
|
const data = new Uint8Array(total);
|
|
236
249
|
let offset = 0;
|
|
@@ -243,6 +256,12 @@ function createAudioClient(config) {
|
|
|
243
256
|
}
|
|
244
257
|
return { transcribe, transcribeStream, synthesize, synthesizeStream };
|
|
245
258
|
}
|
|
259
|
+
function isSynthesisTextSegment(value) {
|
|
260
|
+
return typeof value === "object" && value !== null && "id" in value && "text" in value;
|
|
261
|
+
}
|
|
262
|
+
async function* singleSegment(segment) {
|
|
263
|
+
yield segment;
|
|
264
|
+
}
|
|
246
265
|
function createUnconfiguredAudioClient() {
|
|
247
266
|
const message = "Audio client not configured. Provide `audio` in createAIClient() config.";
|
|
248
267
|
return {
|
|
@@ -533,5 +552,5 @@ async function collectStreamContent(stream) {
|
|
|
533
552
|
}
|
|
534
553
|
|
|
535
554
|
export { collectStreamContent, createA2AClient, createAIClient, createAudioClient, createUnconfiguredAudioClient, parseSSE };
|
|
536
|
-
//# sourceMappingURL=chunk-
|
|
537
|
-
//# sourceMappingURL=chunk-
|
|
555
|
+
//# sourceMappingURL=chunk-535CQURK.js.map
|
|
556
|
+
//# sourceMappingURL=chunk-535CQURK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/ai-a2a-client.ts","../src/client/ai-audio-client.ts","../src/client/ai-client.ts"],"names":[],"mappings":"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","file":"chunk-535CQURK.js","sourcesContent":["/**\n * @h-ai/ai — 前端 A2A 客户端\n *\n * 浏览器端 A2A 操作客户端,通过 API 服务调用后端 A2A 能力。\n * @module ai-a2a-client\n */\n\nimport type {\n A2AAgentCardConfig,\n A2ACallResult,\n A2AMessageRecord,\n} from '../a2a/ai-a2a-types.js'\nimport type { StorePage } from '../store/ai-store-types.js'\nimport type { AIApiAdapter } from './ai-client.js'\n\n// ─── A2A 客户端接口 ───\n\n/**\n * A2A 客户端接口\n *\n * 提供浏览器端调用后端 A2A API 的能力。\n */\nexport interface A2AClientOperations {\n /** 获取当前 Agent Card 配置 */\n getAgentCard: () => Promise<A2AAgentCardConfig>\n /** 查询 A2A 消息记录 */\n listMessages: (filter?: { contextId?: string, status?: string, limit?: number, offset?: number }) => Promise<StorePage<A2AMessageRecord>>\n /** 作为客户端调用远端 Agent */\n callRemoteAgent: (remoteUrl: string, message: string, options?: { timeout?: number }) => Promise<A2ACallResult>\n}\n\n// ─── A2A API 路径 ───\n\nconst A2A_PATH = {\n agentCard: '/a2a/agent-card',\n messages: '/a2a/messages',\n callRemote: '/a2a/call',\n} as const\n\n// ─── 工厂函数 ───\n\n/**\n * 创建 A2A 客户端\n *\n * @param api - API 适配器(来自 @h-ai/api-client)\n * @returns A2A 客户端操作实例\n */\nexport function createA2AClient(api: AIApiAdapter): A2AClientOperations {\n return {\n async getAgentCard(): Promise<A2AAgentCardConfig> {\n const result = await api.post<A2AAgentCardConfig>(A2A_PATH.agentCard)\n if (!result.success) {\n throw new Error(`A2A get agent card failed: ${result.error.message}`)\n }\n return result.data\n },\n\n async listMessages(filter?: { contextId?: string, status?: string, limit?: number, offset?: number }): Promise<StorePage<A2AMessageRecord>> {\n const result = await api.post<StorePage<A2AMessageRecord>>(A2A_PATH.messages, filter ?? {})\n if (!result.success) {\n throw new Error(`A2A list messages failed: ${result.error.message}`)\n }\n return result.data\n },\n\n async callRemoteAgent(remoteUrl: string, message: string, options?: { timeout?: number }): Promise<A2ACallResult> {\n const result = await api.post<A2ACallResult>(A2A_PATH.callRemote, {\n remoteUrl,\n message,\n ...options,\n })\n if (!result.success) {\n throw new Error(`A2A remote call failed: ${result.error.message}`)\n }\n return result.data\n },\n }\n}\n","/**\n * @h-ai/ai/client — 浏览器语音客户端\n *\n * 通过统一 WebSocket 连接 `@h-ai/serv` 的语音入口,向浏览器暴露与 Node 端一致的\n * `ai.audio.*` 业务 API。WebSocket 建立、消息编解码等传输细节在此内部完成,\n * 调用方不接触任何厂商原生事件。\n * @module client/ai-audio-client\n */\n\nimport type {\n SynthesisEvent,\n SynthesisRequest,\n SynthesisResult,\n SynthesisStreamRequest,\n SynthesisTextSegment,\n TranscriptionEvent,\n TranscriptionRequest,\n TranscriptionResult,\n TranscriptionStreamRequest,\n} from '../audio/ai-audio-types.js'\nimport type { AudioWsServerMessage, AudioWsStartMessage } from '../audio/ai-audio-ws-protocol.js'\n\n// ─── 客户端配置 ───\n\n/** 浏览器语音客户端配置 */\nexport interface AudioClientConfig {\n /** 语音 WebSocket 完整 URL(如 `wss://host/api/v1/ai/audio`) */\n url: string\n /**\n * 获取短期、一次性的 Audio WebSocket ticket\n *\n * ticket 应由已登录 HTTP 请求签发,并在服务端首次校验时原子消费。\n */\n getTicket: () => string | Promise<string>\n}\n\n/**\n * 浏览器语音操作接口\n *\n * 与 Node 端 `AudioOperations` 业务形态一致;出错时抛出异常(浏览器 Client 约定)。\n */\nexport interface AudioClientOperations {\n /** 将完整音频识别为完整文本 */\n transcribe: (request: TranscriptionRequest) => Promise<TranscriptionResult>\n /** 持续输入音频或增量返回识别文本(含语音起止事件) */\n transcribeStream: (request: TranscriptionStreamRequest) => AsyncIterable<TranscriptionEvent>\n /** 将完整文本合成为完整音频 */\n synthesize: (request: SynthesisRequest) => Promise<SynthesisResult>\n /** 持续输入文本段并按段输出结构化音频事件 */\n synthesizeStream: (request: SynthesisStreamRequest) => AsyncIterable<SynthesisEvent>\n}\n\n// ─── 浏览器 WebSocket 辅助 ───\n\n/** WebSocket 收到的消息 */\ninterface BrowserWsMessage {\n text?: string\n binary?: Uint8Array\n isBinary: boolean\n}\n\n/** 浏览器 WebSocket 连接封装 */\ninterface BrowserWsConnection {\n send: (data: string | Uint8Array) => void\n messages: () => AsyncIterableIterator<BrowserWsMessage>\n close: () => void\n}\n\n/** 建立浏览器 WebSocket 连接(内部消息队列 → 异步迭代) */\nfunction openBrowserWs(url: string, signal?: AbortSignal): Promise<BrowserWsConnection> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(url)\n ws.binaryType = 'arraybuffer'\n\n const queue: BrowserWsMessage[] = []\n let waiting: ((result: IteratorResult<BrowserWsMessage>) => void) | null = null\n let closed = false\n let opened = false\n let failure: Error | null = null\n\n const onAbort = (): void => ws.close()\n\n function settleClosed(): void {\n if (closed)\n return\n closed = true\n signal?.removeEventListener('abort', onAbort)\n if (waiting) {\n const w = waiting\n waiting = null\n w({ value: undefined, done: true })\n }\n }\n\n function push(message: BrowserWsMessage): void {\n if (waiting) {\n const w = waiting\n waiting = null\n w({ value: message, done: false })\n }\n else {\n queue.push(message)\n }\n }\n\n ws.onmessage = (event: MessageEvent): void => {\n if (typeof event.data === 'string')\n push({ isBinary: false, text: event.data })\n else\n push({ isBinary: true, binary: new Uint8Array(event.data as ArrayBuffer) })\n }\n ws.onerror = (): void => {\n if (!opened) {\n failure = new Error('Audio WebSocket connection failed')\n settleClosed()\n reject(failure)\n }\n }\n ws.onclose = (): void => settleClosed()\n\n if (signal) {\n if (signal.aborted)\n onAbort()\n else\n signal.addEventListener('abort', onAbort, { once: true })\n }\n\n ws.onopen = (): void => {\n opened = true\n resolve({\n // DOM WebSocket.send 的 BufferSource 泛型限定为 ArrayBuffer,Uint8Array 需显式收窄\n send: data => ws.send(data as string | Uint8Array<ArrayBuffer>),\n async* messages() {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift() as BrowserWsMessage\n continue\n }\n if (closed) {\n if (failure)\n throw failure\n return\n }\n const next = await new Promise<IteratorResult<BrowserWsMessage>>((res) => {\n waiting = res\n })\n if (next.done) {\n if (failure)\n throw failure\n return\n }\n yield next.value\n }\n },\n close: () => ws.close(),\n })\n }\n })\n}\n\n// ─── 客户端实现 ───\n\n/**\n * 创建浏览器语音客户端\n *\n * @param config - 语音客户端配置\n * @returns 浏览器语音操作接口\n */\nexport function createAudioClient(config: AudioClientConfig): AudioClientOperations {\n async function buildUrl(): Promise<string> {\n const ticket = await config.getTicket()\n if (!ticket)\n throw new Error('Audio WebSocket ticket is required')\n const separator = config.url.includes('?') ? '&' : '?'\n return `${config.url}${separator}ticket=${encodeURIComponent(ticket)}`\n }\n\n function startMessage(operation: 'transcribe' | 'synthesize', extra: Partial<AudioWsStartMessage>): string {\n return JSON.stringify({ type: 'start', operation, ...extra } satisfies AudioWsStartMessage)\n }\n\n async function* transcribeStream(request: TranscriptionStreamRequest): AsyncIterable<TranscriptionEvent> {\n const conn = await openBrowserWs(await buildUrl(), request.signal)\n try {\n const format = request.audio.format\n const sampleRate = request.audio.sampleRate\n conn.send(startMessage('transcribe', { stream: true, model: request.model, language: request.language, contextHints: request.contextHints, format, sampleRate, channels: request.audio.channels }))\n\n const sendAudio = (async () => {\n if ('chunks' in request.audio) {\n for await (const part of request.audio.chunks)\n conn.send(part)\n }\n else {\n conn.send(request.audio.data)\n }\n conn.send(JSON.stringify({ type: 'done' }))\n })()\n let sendError: unknown\n sendAudio.catch((e: unknown) => {\n sendError = e\n })\n\n for await (const message of conn.messages()) {\n if (message.isBinary || !message.text)\n continue\n const event = JSON.parse(message.text) as AudioWsServerMessage\n if (event.type === 'transcript')\n yield { type: 'transcript', text: event.text, final: event.final }\n else if (event.type === 'speech_started')\n yield { type: 'speech_started' }\n else if (event.type === 'speech_stopped')\n yield { type: 'speech_stopped' }\n else if (event.type === 'error')\n throw new Error(`${event.code}: ${event.message}`)\n else if (event.type === 'end')\n break\n }\n if (sendError)\n throw sendError\n }\n finally {\n conn.close()\n }\n }\n\n async function transcribe(request: TranscriptionRequest): Promise<TranscriptionResult> {\n // 完整识别:服务端缓冲全部音频后返回单条最终结果\n const conn = await openBrowserWs(await buildUrl(), request.signal)\n try {\n conn.send(startMessage('transcribe', { stream: false, model: request.model, language: request.language, contextHints: request.contextHints, format: request.audio.format, sampleRate: request.audio.sampleRate, channels: request.audio.channels }))\n conn.send(request.audio.data)\n conn.send(JSON.stringify({ type: 'done' }))\n\n let text = ''\n for await (const message of conn.messages()) {\n if (message.isBinary || !message.text)\n continue\n const event = JSON.parse(message.text) as AudioWsServerMessage\n if (event.type === 'transcript')\n text = event.text\n else if (event.type === 'error')\n throw new Error(`${event.code}: ${event.message}`)\n else if (event.type === 'end')\n break\n }\n return { text }\n }\n finally {\n conn.close()\n }\n }\n\n async function* synthesizeStream(request: SynthesisStreamRequest): AsyncIterable<SynthesisEvent> {\n const conn = await openBrowserWs(await buildUrl(), request.signal)\n try {\n conn.send(startMessage('synthesize', { model: request.model, voice: request.voice, instruction: request.instruction, format: request.format, sampleRate: request.sampleRate }))\n\n const sendText = (async () => {\n const segments = isSynthesisTextSegment(request.text) ? singleSegment(request.text) : request.text\n for await (const segment of segments)\n conn.send(JSON.stringify({ type: 'text', segmentId: segment.id, text: segment.text }))\n conn.send(JSON.stringify({ type: 'done' }))\n })()\n let sendError: unknown\n sendText.catch((e: unknown) => {\n sendError = e\n })\n\n let activeSegmentId: string | undefined\n for await (const message of conn.messages()) {\n if (message.isBinary && message.binary) {\n if (!activeSegmentId)\n throw new Error('Audio frame received outside a synthesis segment')\n yield { type: 'audio', segmentId: activeSegmentId, data: message.binary }\n continue\n }\n if (!message.text)\n continue\n const event = JSON.parse(message.text) as AudioWsServerMessage\n if (event.type === 'segment_started') {\n if (activeSegmentId)\n throw new Error('Synthesis segment started before the previous segment completed')\n activeSegmentId = event.segmentId\n yield event\n }\n else if (event.type === 'segment_done') {\n if (activeSegmentId !== event.segmentId)\n throw new Error('Synthesis segment completion does not match the active segment')\n yield event\n activeSegmentId = undefined\n }\n else if (event.type === 'error') {\n throw new Error(`${event.code}: ${event.message}`)\n }\n else if (event.type === 'end') {\n break\n }\n }\n if (sendError)\n throw sendError\n }\n finally {\n conn.close()\n }\n }\n\n async function synthesize(request: SynthesisRequest): Promise<SynthesisResult> {\n const chunks: Uint8Array[] = []\n for await (const event of synthesizeStream({ ...request, text: { id: 'synthesis', text: request.text } })) {\n if (event.type === 'audio')\n chunks.push(event.data)\n }\n const total = chunks.reduce((sum, c) => sum + c.length, 0)\n const data = new Uint8Array(total)\n let offset = 0\n for (const chunk of chunks) {\n data.set(chunk, offset)\n offset += chunk.length\n }\n const outFormat = request.format ?? 'pcm16'\n return { data, format: outFormat, sampleRate: outFormat === 'pcm16' ? (request.sampleRate ?? 24000) : undefined, channels: 1 }\n }\n\n return { transcribe, transcribeStream, synthesize, synthesizeStream }\n}\n\nfunction isSynthesisTextSegment(value: SynthesisStreamRequest['text']): value is SynthesisTextSegment {\n return typeof value === 'object' && value !== null && 'id' in value && 'text' in value\n}\n\nasync function* singleSegment(segment: SynthesisTextSegment): AsyncIterable<SynthesisTextSegment> {\n yield segment\n}\n\n/** 未配置语音入口时的占位实现(调用即抛出,提示需配置 audio) */\nexport function createUnconfiguredAudioClient(): AudioClientOperations {\n const message = 'Audio client not configured. Provide `audio` in createAIClient() config.'\n return {\n transcribe: () => Promise.reject(new Error(message)),\n async* transcribeStream() { throw new Error(message) },\n synthesize: () => Promise.reject(new Error(message)),\n async* synthesizeStream() { throw new Error(message) },\n }\n}\n","/**\n * @h-ai/ai — 前端 AI 客户端\n *\n * 基于 @h-ai/api-client 的 AI 领域客户端。\n * 通过 `createAIClient()` 工厂函数创建,消除自建 HTTP 层,\n * 复用 api-client 提供的 Token 管理、超时、拦截器等基础能力。\n * @module ai-client\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { KnowledgeAskResult, KnowledgeDocumentInfo, KnowledgeIngestResult, KnowledgeRetrieveResult } from '../knowledge/ai-knowledge-types.js'\nimport type {\n ChatCompletionChunk,\n ChatCompletionRequest,\n ChatCompletionResponse,\n ChatMessage,\n ChatRecord,\n} from '../llm/ai-llm-types.js'\nimport type { MemoryEntry, MemoryEntryInput, MemoryUpdateInput } from '../memory/ai-memory-types.js'\nimport type { RagResult } from '../rag/ai-rag-types.js'\nimport type { ReasoningResult } from '../reasoning/ai-reasoning-types.js'\nimport type { SessionInfo, StorePage } from '../store/ai-store-types.js'\nimport type { AudioClientConfig, AudioClientOperations } from './ai-audio-client.js'\n\nimport { createAudioClient, createUnconfiguredAudioClient } from './ai-audio-client.js'\n\n// ─── API 适配器接口 ───\n\n/**\n * AI 客户端所需的 API 调用能力\n *\n * 结构兼容 `@h-ai/api-client` 的 `apiClient` 默认单例(鸭子类型)。\n * 传入 `apiClient` 默认单例即可,无需额外适配。\n */\nexport interface AIApiAdapter {\n /** POST 请求(返回 HaiResult) */\n post: <T>(path: string, body?: unknown) => Promise<HaiResult<T>>\n /** 流式请求(返回 SSE data 行的 AsyncIterable) */\n stream: (path: string, body?: unknown) => AsyncIterable<string>\n}\n\n// ─── 客户端配置 ───\n\n/**\n * AI 客户端配置\n *\n * @example\n * ```ts\n * import { apiClient } from '@h-ai/api-client'\n * import { createAIClient } from '@h-ai/ai/client'\n *\n * await apiClient.init({ baseUrl: '/api', auth: { ... } })\n * const aiClient = createAIClient({ api: apiClient })\n * ```\n */\nexport interface AIClientConfig {\n /**\n * API 调用适配器\n *\n * 传入 `apiClient` 默认单例(初始化后)。\n * baseUrl、Token 管理、超时等通过 api-client 配置。\n */\n api: AIApiAdapter\n /**\n * 语音 WebSocket 配置(可选)\n *\n * 提供后 `client.audio.*` 通过统一 WebSocket 连接 `@h-ai/serv` 语音入口;\n * 未提供时调用 `client.audio.*` 抛出「未配置」错误。\n */\n audio?: AudioClientConfig\n}\n\n/** 流式响应进度(`onProgress` 回调参数) */\nexport interface StreamProgress {\n /** 当前累积的文本内容 */\n content: string\n /** 是否已完成 */\n done: boolean\n /** 完成原因(仅 `done=true` 时有值,如 `'stop'`) */\n finishReason?: string\n}\n\n/** 流式响应选项 */\nexport interface StreamOptions {\n /** 进度回调(每次收到 chunk 时触发) */\n onProgress?: (progress: StreamProgress) => void\n}\n\n// ─── 客户端接口 ───\n\n/**\n * AI 客户端接口\n *\n * 提供浏览器端调用 AI API 的能力,HTTP 基础设施委托给 @h-ai/api-client。\n */\nexport interface AIClient {\n // ─── LLM ───\n /** 发送对话请求(非流式) */\n chat: (request: ChatCompletionRequest) => Promise<ChatCompletionResponse>\n /** 发送流式对话请求,返回异步迭代器 */\n chatStream: (request: ChatCompletionRequest, options?: StreamOptions) => AsyncIterable<ChatCompletionChunk>\n /** 便捷方法:发送纯文本消息并返回回复文本 */\n sendMessage: (message: string, systemPrompt?: string) => Promise<string>\n /** 便捷方法:流式发送纯文本消息并返回完整回复 */\n sendMessageStream: (message: string, options?: StreamOptions, systemPrompt?: string) => Promise<string>\n /** 简单问答(单轮,自动构造 messages) */\n ask: (question: string, options?: { systemPrompt?: string, model?: string }) => Promise<string>\n /** 流式简单问答,返回异步文本流 */\n askStream: (question: string, options?: { systemPrompt?: string, model?: string }) => AsyncIterable<string>\n\n // ─── Knowledge ───\n /** 知识检索(向量 + 实体增强) */\n knowledgeRetrieve: (query: string, options?: { topK?: number, collection?: string }) => Promise<KnowledgeRetrieveResult>\n /** 知识问答(RAG + 信源) */\n knowledgeAsk: (query: string, options?: { model?: string, collection?: string }) => Promise<KnowledgeAskResult>\n /** 导入文档 */\n knowledgeIngest: (input: { documentId: string, content: string, title?: string, collection?: string, metadata?: Record<string, unknown> }) => Promise<KnowledgeIngestResult>\n /** 列出已导入文档 */\n knowledgeListDocuments: (options?: { collection?: string, offset?: number, limit?: number }) => Promise<KnowledgeDocumentInfo[]>\n /** 删除已导入文档 */\n knowledgeRemoveDocument: (documentId: string, options?: { collection?: string }) => Promise<void>\n\n // ─── Memory ───\n /** 检索相关记忆 */\n recallMemories: (query: string, options?: { topK?: number, types?: string[], minImportance?: number, objectId?: string }) => Promise<MemoryEntry[]>\n /** 列出记忆(分页) */\n listMemories: (options?: { types?: string[], objectId?: string, offset?: number, limit?: number }) => Promise<StorePage<MemoryEntry>>\n /** 添加记忆 */\n addMemory: (entry: MemoryEntryInput) => Promise<MemoryEntry>\n /** 更新记忆 */\n updateMemory: (memoryId: string, updates: MemoryUpdateInput) => Promise<MemoryEntry>\n /** 删除记忆 */\n removeMemory: (memoryId: string) => Promise<void>\n\n // ─── Session ───\n /** 列出会话 */\n listSessions: (objectId: string) => Promise<SessionInfo[]>\n /** 重命名会话 */\n renameSession: (sessionId: string, title: string) => Promise<void>\n /** 删除会话 */\n removeSession: (sessionId: string) => Promise<void>\n /** 获取对话历史 */\n chatHistory: (objectId: string, sessionId: string, options?: { limit?: number, order?: 'asc' | 'desc' }) => Promise<ChatRecord[]>\n\n // ─── RAG ───\n /** RAG 查询(检索 + 生成) */\n ragQuery: (query: string, options?: { collection?: string, topK?: number, model?: string }) => Promise<RagResult>\n /** RAG 流式查询,返回 SSE 数据行 */\n ragQueryStream: (query: string, options?: { collection?: string, topK?: number, model?: string }) => AsyncIterable<string>\n\n // ─── Reasoning ───\n /** 推理(多步思考) */\n reasoningRun: (query: string, options?: { model?: string, maxSteps?: number }) => Promise<ReasoningResult>\n /** 推理流式,返回 SSE 数据行 */\n reasoningRunStream: (query: string, options?: { model?: string, maxSteps?: number }) => AsyncIterable<string>\n\n // ─── Token ───\n /** 估算文本的 Token 数 */\n estimateTokens: (text: string) => Promise<{ tokens: number }>\n\n // ─── Audio ───\n /** 语音操作(识别 / 合成),需在 createAIClient 配置 `audio` */\n audio: AudioClientOperations\n}\n\n// ─── AI API 路径(与 ai-api-contract 保持一致) ───\n\nconst AI_PATH = {\n // LLM\n chat: '/ai/chat',\n chatStream: '/ai/chat/stream',\n chatHistory: '/ai/chat/history',\n ask: '/ai/ask',\n askStream: '/ai/ask/stream',\n // Knowledge\n knowledgeRetrieve: '/ai/knowledge/retrieve',\n knowledgeAsk: '/ai/knowledge/ask',\n knowledgeIngest: '/ai/knowledge/ingest',\n knowledgeDocuments: '/ai/knowledge/documents',\n knowledgeRemoveDocument: '/ai/knowledge/documents/remove',\n // Memory\n memoryRecall: '/ai/memory/recall',\n memoryList: '/ai/memory/list',\n memoryAdd: '/ai/memory/add',\n memoryUpdate: '/ai/memory/update',\n memoryRemove: '/ai/memory/remove',\n // Session\n sessions: '/ai/sessions',\n sessionRename: '/ai/sessions/rename',\n sessionRemove: '/ai/sessions/remove',\n // RAG\n ragQuery: '/ai/rag/query',\n ragQueryStream: '/ai/rag/query/stream',\n // Reasoning\n reasoningRun: '/ai/reasoning/run',\n reasoningRunStream: '/ai/reasoning/run/stream',\n // Token\n tokenEstimate: '/ai/token/estimate',\n} as const\n\n// ─── 工厂函数 ───\n\n/**\n * 创建 AI 客户端\n *\n * 通过 @h-ai/api-client 的 ApiClient 实例调用后端 AI API。\n * HTTP 层(Token、超时、拦截器)全部复用 api-client,本模块仅负责:\n * - 非流式 / 流式 ChatCompletion 协议适配\n * - SSE 解析与 ChatCompletionChunk 类型化\n * - onProgress 进度回调\n *\n * @param config - 客户端配置\n * @returns AI 客户端实例\n *\n * @example\n * ```ts\n * import { apiClient } from '@h-ai/api-client'\n * import { createAIClient } from '@h-ai/ai/client'\n *\n * await apiClient.init({ baseUrl: '/api' })\n * const client = createAIClient({ api: apiClient })\n * const reply = await client.sendMessage('你好')\n * ```\n */\nexport function createAIClient(config: AIClientConfig): AIClient {\n const { api } = config\n const audio = config.audio ? createAudioClient(config.audio) : createUnconfiguredAudioClient()\n\n return {\n async chat(req: ChatCompletionRequest): Promise<ChatCompletionResponse> {\n const result = await api.post<ChatCompletionResponse>(AI_PATH.chat, { ...req, stream: false })\n if (!result.success) {\n throw new Error(`AI chat request failed: ${result.error.message}`)\n }\n return result.data\n },\n\n async* chatStream(\n req: ChatCompletionRequest,\n options?: StreamOptions,\n ): AsyncIterable<ChatCompletionChunk> {\n let content = ''\n\n for await (const data of api.stream(AI_PATH.chatStream, { ...req, stream: true })) {\n try {\n const chunk: ChatCompletionChunk = JSON.parse(data)\n const delta = chunk.choices[0]?.delta?.content\n if (delta) {\n content += delta\n }\n const finishReason = chunk.choices[0]?.finish_reason\n if (finishReason) {\n options?.onProgress?.({ content, done: true, finishReason })\n }\n else {\n options?.onProgress?.({ content, done: false })\n }\n yield chunk\n }\n catch {\n // 忽略解析错误的行\n }\n }\n },\n\n async sendMessage(message: string, systemPrompt?: string): Promise<string> {\n const messages: ChatMessage[] = []\n if (systemPrompt) {\n messages.push({ role: 'system', content: systemPrompt })\n }\n messages.push({ role: 'user', content: message })\n const response = await this.chat({ messages })\n return response.choices[0]?.message?.content ?? ''\n },\n\n async sendMessageStream(\n message: string,\n options?: StreamOptions,\n systemPrompt?: string,\n ): Promise<string> {\n const messages: ChatMessage[] = []\n if (systemPrompt) {\n messages.push({ role: 'system', content: systemPrompt })\n }\n messages.push({ role: 'user', content: message })\n\n let content = ''\n for await (const chunk of this.chatStream({ messages }, options)) {\n const delta = chunk.choices[0]?.delta?.content\n if (delta) {\n content += delta\n }\n }\n return content\n },\n\n async recallMemories(query: string, options?: { topK?: number, types?: string[], minImportance?: number, objectId?: string }): Promise<MemoryEntry[]> {\n const result = await api.post<{ items: MemoryEntry[] }>(AI_PATH.memoryRecall, { query, ...options })\n if (!result.success) {\n throw new Error(`Memory recall failed: ${result.error.message}`)\n }\n return result.data.items\n },\n\n async listMemories(options?: { types?: string[], objectId?: string, offset?: number, limit?: number }): Promise<StorePage<MemoryEntry>> {\n const result = await api.post<StorePage<MemoryEntry>>(AI_PATH.memoryList, options ?? {})\n if (!result.success) {\n throw new Error(`Memory list failed: ${result.error.message}`)\n }\n return result.data\n },\n\n async listSessions(objectId: string): Promise<SessionInfo[]> {\n const result = await api.post<{ items: SessionInfo[] }>(AI_PATH.sessions, { objectId })\n if (!result.success) {\n throw new Error(`Session list failed: ${result.error.message}`)\n }\n return result.data.items\n },\n\n async chatHistory(objectId: string, sessionId: string, options?: { limit?: number, order?: 'asc' | 'desc' }): Promise<ChatRecord[]> {\n const result = await api.post<{ items: ChatRecord[] }>(AI_PATH.chatHistory, { objectId, sessionId, ...options })\n if (!result.success) {\n throw new Error(`Chat history failed: ${result.error.message}`)\n }\n return result.data.items\n },\n\n // ─── LLM ask/askStream ───\n\n async ask(question: string, options?: { systemPrompt?: string, model?: string }): Promise<string> {\n const result = await api.post<{ text: string }>(AI_PATH.ask, { question, ...options })\n if (!result.success) {\n throw new Error(`AI ask failed: ${result.error.message}`)\n }\n return result.data.text\n },\n\n async* askStream(question: string, options?: { systemPrompt?: string, model?: string }): AsyncIterable<string> {\n for await (const data of api.stream(AI_PATH.askStream, { question, ...options })) {\n yield data\n }\n },\n\n // ─── Knowledge ───\n\n async knowledgeRetrieve(query: string, options?: { topK?: number, collection?: string }): Promise<KnowledgeRetrieveResult> {\n const result = await api.post<KnowledgeRetrieveResult>(AI_PATH.knowledgeRetrieve, { query, ...options })\n if (!result.success) {\n throw new Error(`Knowledge retrieve failed: ${result.error.message}`)\n }\n return result.data\n },\n\n async knowledgeAsk(query: string, options?: { model?: string, collection?: string }): Promise<KnowledgeAskResult> {\n const result = await api.post<KnowledgeAskResult>(AI_PATH.knowledgeAsk, { query, ...options })\n if (!result.success) {\n throw new Error(`Knowledge ask failed: ${result.error.message}`)\n }\n return result.data\n },\n\n async knowledgeIngest(input: { documentId: string, content: string, title?: string, collection?: string, metadata?: Record<string, unknown> }): Promise<KnowledgeIngestResult> {\n const result = await api.post<KnowledgeIngestResult>(AI_PATH.knowledgeIngest, input)\n if (!result.success) {\n throw new Error(`Knowledge ingest failed: ${result.error.message}`)\n }\n return result.data\n },\n\n async knowledgeListDocuments(options?: { collection?: string, offset?: number, limit?: number }): Promise<KnowledgeDocumentInfo[]> {\n const result = await api.post<{ items: KnowledgeDocumentInfo[] }>(AI_PATH.knowledgeDocuments, options ?? {})\n if (!result.success) {\n throw new Error(`Knowledge list documents failed: ${result.error.message}`)\n }\n return result.data.items\n },\n\n async knowledgeRemoveDocument(documentId: string, options?: { collection?: string }): Promise<void> {\n const result = await api.post<void>(AI_PATH.knowledgeRemoveDocument, { documentId, ...options })\n if (!result.success) {\n throw new Error(`Knowledge remove document failed: ${result.error.message}`)\n }\n },\n\n // ─── Memory (extended) ───\n\n async addMemory(entry: MemoryEntryInput): Promise<MemoryEntry> {\n const result = await api.post<MemoryEntry>(AI_PATH.memoryAdd, entry)\n if (!result.success) {\n throw new Error(`Memory add failed: ${result.error.message}`)\n }\n return result.data\n },\n\n async updateMemory(memoryId: string, updates: MemoryUpdateInput): Promise<MemoryEntry> {\n const result = await api.post<MemoryEntry>(AI_PATH.memoryUpdate, { memoryId, ...updates })\n if (!result.success) {\n throw new Error(`Memory update failed: ${result.error.message}`)\n }\n return result.data\n },\n\n async removeMemory(memoryId: string): Promise<void> {\n const result = await api.post<void>(AI_PATH.memoryRemove, { memoryId })\n if (!result.success) {\n throw new Error(`Memory remove failed: ${result.error.message}`)\n }\n },\n\n // ─── Session (extended) ───\n\n async renameSession(sessionId: string, title: string): Promise<void> {\n const result = await api.post<void>(AI_PATH.sessionRename, { sessionId, title })\n if (!result.success) {\n throw new Error(`Session rename failed: ${result.error.message}`)\n }\n },\n\n async removeSession(sessionId: string): Promise<void> {\n const result = await api.post<void>(AI_PATH.sessionRemove, { sessionId })\n if (!result.success) {\n throw new Error(`Session remove failed: ${result.error.message}`)\n }\n },\n\n // ─── RAG ───\n\n async ragQuery(query: string, options?: { collection?: string, topK?: number, model?: string }): Promise<RagResult> {\n const result = await api.post<RagResult>(AI_PATH.ragQuery, { query, ...options })\n if (!result.success) {\n throw new Error(`RAG query failed: ${result.error.message}`)\n }\n return result.data\n },\n\n async* ragQueryStream(query: string, options?: { collection?: string, topK?: number, model?: string }): AsyncIterable<string> {\n for await (const data of api.stream(AI_PATH.ragQueryStream, { query, ...options })) {\n yield data\n }\n },\n\n // ─── Reasoning ───\n\n async reasoningRun(query: string, options?: { model?: string, maxSteps?: number }): Promise<ReasoningResult> {\n const result = await api.post<ReasoningResult>(AI_PATH.reasoningRun, { query, ...options })\n if (!result.success) {\n throw new Error(`Reasoning run failed: ${result.error.message}`)\n }\n return result.data\n },\n\n async* reasoningRunStream(query: string, options?: { model?: string, maxSteps?: number }): AsyncIterable<string> {\n for await (const data of api.stream(AI_PATH.reasoningRunStream, { query, ...options })) {\n yield data\n }\n },\n\n // ─── Token ───\n\n async estimateTokens(text: string): Promise<{ tokens: number }> {\n const result = await api.post<{ tokens: number }>(AI_PATH.tokenEstimate, { text })\n if (!result.success) {\n throw new Error(`Token estimate failed: ${result.error.message}`)\n }\n return result.data\n },\n\n // ─── Audio ───\n\n audio,\n }\n}\n\n// ─── SSE 解析工具 ───\n\n/**\n * 从 fetch Response 中解析 SSE data 字段\n *\n * 自动处理分片缓冲和 `[DONE]` 结束标记。\n *\n * @param response - fetch 响应对象\n * @yields SSE data 字符串(不含 `[DONE]`)\n *\n * @example\n * ```ts\n * const resp = await fetch('/api/chat', { method: 'POST', body })\n * for await (const data of parseSSE(resp)) {\n * const chunk = JSON.parse(data) // ChatCompletionChunk\n * }\n * ```\n */\nexport async function* parseSSE(response: Response): AsyncIterable<string> {\n const reader = response.body?.getReader()\n if (!reader) {\n throw new Error('Response body is not readable')\n }\n\n const decoder = new TextDecoder()\n let buffer = ''\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done)\n break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6)\n if (data !== '[DONE]') {\n yield data\n }\n }\n }\n }\n }\n finally {\n reader.releaseLock()\n }\n}\n\n/**\n * 收集流式响应的完整文本内容\n *\n * 完整消费流并拼接所有 `delta.content` 片段。\n *\n * @param stream - 聊天响应块流\n * @returns 完整文本\n *\n * @example\n * ```ts\n * const client = createAIClient({ api })\n * const stream = client.chatStream({ messages })\n * const fullText = await collectStreamContent(stream)\n * ```\n */\nexport async function collectStreamContent(\n stream: AsyncIterable<ChatCompletionChunk>,\n): Promise<string> {\n let content = ''\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta?.content\n if (delta) {\n content += delta\n }\n }\n return content\n}\n"]}
|
|
@@ -528,6 +528,12 @@ var AudioModelEntrySchema = z.object({
|
|
|
528
528
|
provider: AudioProviderSchema,
|
|
529
529
|
/** 厂商模型名(传给厂商 API 的实际模型名) */
|
|
530
530
|
model: z.string(),
|
|
531
|
+
/** 模型允许执行的操作;解析模型时会在调用厂商前校验 */
|
|
532
|
+
operations: z.union([
|
|
533
|
+
z.tuple([z.literal("transcribe")]),
|
|
534
|
+
z.tuple([z.literal("synthesize")]),
|
|
535
|
+
z.tuple([z.literal("transcribe"), z.literal("synthesize")])
|
|
536
|
+
]),
|
|
531
537
|
/** API Key 覆盖(未提供时回退对应平台环境变量) */
|
|
532
538
|
apiKey: z.string().optional(),
|
|
533
539
|
/** HTTP / WebSocket 端点覆盖(未提供时使用平台默认端点) */
|
|
@@ -583,6 +589,13 @@ function resolveAudioModel(audioConfig, operation, explicit) {
|
|
|
583
589
|
const entry = audioConfig.models?.find((m) => m.id === targetId || m.model === targetId);
|
|
584
590
|
if (!entry)
|
|
585
591
|
return err(HaiAIError.AUDIO_MODEL_NOT_FOUND, aiM("ai_audioModelNotFound", { params: { model: targetId } }));
|
|
592
|
+
const operations = entry.operations;
|
|
593
|
+
if (!operations.includes(operation)) {
|
|
594
|
+
return err(
|
|
595
|
+
HaiAIError.AUDIO_UNSUPPORTED_INPUT,
|
|
596
|
+
aiM("ai_audioUnsupportedInput", { params: { provider: entry.provider, reason: `model ${entry.id} does not support ${operation}` } })
|
|
597
|
+
);
|
|
598
|
+
}
|
|
586
599
|
const apiKey = entry.apiKey ?? audioProviderEnvApiKey(entry.provider);
|
|
587
600
|
const hasDoubaoLegacy = Boolean(entry.appKey && entry.accessKey);
|
|
588
601
|
if (!apiKey && !(entry.provider === "doubao" && hasDoubaoLegacy))
|
|
@@ -638,5 +651,5 @@ var AIConfigSchema = z.object({
|
|
|
638
651
|
var AUDIO_WS_PATH = "/ai/audio";
|
|
639
652
|
|
|
640
653
|
export { A2AConfigSchema, A2ASkillConfigSchema, AIConfigSchema, AUDIO_WS_PATH, ApiTypeSchema, AudioConfigSchema, AudioModelEntrySchema, AudioProviderSchema, CompressConfigSchema, CompressionStrategySchema, EmbeddingConfigSchema, EntityTypeSchema, FileConfigSchema, HaiAIError, KnowledgeConfigSchema, LLMConfigSchema, MCPConfigSchema, MCPServerCapabilitiesSchema, MCPServerConfigSchema, MemoryConfigSchema, MemoryTypeSchema, ModelEntrySchema, ModelScenarioSchema, RetrievalConfigSchema, RetrievalSourceSchema, SummaryConfigSchema, TokenConfigSchema, aiM, resolveAudioModel, resolveModelApi, resolveModelEntry };
|
|
641
|
-
//# sourceMappingURL=chunk-
|
|
642
|
-
//# sourceMappingURL=chunk-
|
|
654
|
+
//# sourceMappingURL=chunk-UROBPUCF.js.map
|
|
655
|
+
//# sourceMappingURL=chunk-UROBPUCF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ai-types.ts","../src/compress/ai-compress-types.ts","../src/knowledge/ai-knowledge-types.ts","../src/memory/ai-memory-types.ts","../messages/en-US.json","../messages/zh-CN.json","../src/ai-i18n.ts","../src/ai-config.ts","../src/audio/ai-audio-ws-protocol.ts"],"names":["z","core"],"mappings":"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","file":"chunk-UROBPUCF.js","sourcesContent":["/**\n * @h-ai/ai — 公共类型定义\n *\n * 聚合导出模块根类型和子功能类型,供外部通过 `@h-ai/ai` 一站式引入。\n * @module ai-types\n */\n\nimport type { ErrorInfo, HaiResult } from '@h-ai/core'\nimport type { A2AOperations } from './a2a/ai-a2a-types.js'\n\nimport type { AIConfig, AIConfigInput } from './ai-config.js'\nimport type { AudioOperations } from './audio/ai-audio-types.js'\nimport type { CompressOperations } from './compress/ai-compress-types.js'\nimport type { ContextOperations } from './context/ai-context-types.js'\nimport type { EmbeddingOperations } from './embedding/ai-embedding-types.js'\nimport type { FileOperations } from './file/ai-file-types.js'\nimport type { KnowledgeOperations } from './knowledge/ai-knowledge-types.js'\nimport type { LLMOperations, StreamOperations, ToolsOperations } from './llm/ai-llm-types.js'\nimport type { MCPOperations } from './mcp/ai-mcp-types.js'\nimport type { MemoryOperations } from './memory/ai-memory-types.js'\nimport type { PersonaOperations } from './persona/ai-persona-types.js'\nimport type { RagOperations } from './rag/ai-rag-types.js'\nimport type { ReasoningOperations } from './reasoning/ai-reasoning-types.js'\nimport type { RerankOperations } from './rerank/ai-rerank-types.js'\nimport type { RetrievalOperations } from './retrieval/ai-retrieval-types.js'\nimport type { AIStoreProvider } from './store/ai-store-types.js'\nimport type { SummaryOperations } from './summary/ai-summary-types.js'\nimport type { TokenOperations } from './token/ai-token-types.js'\nimport { core } from '@h-ai/core'\n\n// ─── 错误定义(照 @h-ai/core 范式) ───\n\n/**\n * AI 错误信息映射(错误码:HTTP状态码)。\n *\n * 错误码采用 3 位数字格式(000-999),HTTP 状态码遵循标准 HTTP 规范。\n * 完整错误码将自动生成为:`hai:ai:NNN`\n */\nconst AIErrorInfo = {\n // 通用 (000-009)\n INTERNAL_ERROR: '000:500',\n\n // 初始化 (010-019)\n NOT_INITIALIZED: '010:500',\n CONFIGURATION_ERROR: '011:500',\n INIT_IN_PROGRESS: '012:500',\n RERANK_API_ERROR: '020:502',\n RERANK_INVALID_REQUEST: '021:400',\n\n // LLM (100-199)\n API_ERROR: '100:502',\n INVALID_REQUEST: '101:400',\n RATE_LIMITED: '102:429',\n TIMEOUT: '103:504',\n MODEL_NOT_FOUND: '104:404',\n CONTEXT_LENGTH_EXCEEDED: '105:400',\n LLM_RECORD_FAILED: '106:500',\n LLM_HISTORY_FAILED: '107:500',\n\n // MCP (200-299)\n MCP_CONNECTION_ERROR: '200:502',\n MCP_PROTOCOL_ERROR: '201:502',\n MCP_TOOL_ERROR: '202:500',\n MCP_RESOURCE_ERROR: '203:500',\n MCP_SERVER_ERROR: '204:502',\n\n // Embedding (300-399)\n EMBEDDING_API_ERROR: '300:502',\n EMBEDDING_MODEL_NOT_FOUND: '301:404',\n EMBEDDING_INPUT_TOO_LONG: '302:400',\n\n // 工具 (400-499)\n TOOL_NOT_FOUND: '400:404',\n TOOL_VALIDATION_FAILED: '401:400',\n TOOL_EXECUTION_FAILED: '402:500',\n TOOL_TIMEOUT: '403:504',\n\n // Reasoning (500-599)\n REASONING_FAILED: '500:500',\n REASONING_MAX_ROUNDS: '501:400',\n REASONING_STRATEGY_NOT_FOUND: '502:404',\n\n // Retrieval (600-699)\n RETRIEVAL_FAILED: '600:500',\n RETRIEVAL_SOURCE_NOT_FOUND: '601:404',\n\n // RAG (700-799)\n RAG_FAILED: '700:500',\n RAG_CONTEXT_BUILD_FAILED: '701:500',\n\n // Knowledge (800-899)\n KNOWLEDGE_SETUP_FAILED: '800:500',\n KNOWLEDGE_INGEST_FAILED: '801:500',\n KNOWLEDGE_RETRIEVE_FAILED: '802:500',\n KNOWLEDGE_ENTITY_EXTRACT_FAILED: '803:500',\n KNOWLEDGE_NOT_SETUP: '804:500',\n KNOWLEDGE_COLLECTION_NOT_FOUND: '805:404',\n\n // Memory (900-949)\n MEMORY_EXTRACT_FAILED: '900:500',\n MEMORY_STORE_FAILED: '901:500',\n MEMORY_RECALL_FAILED: '902:500',\n MEMORY_NOT_FOUND: '903:404',\n MEMORY_ENRICH_FAILED: '904:500',\n MEMORY_PROMOTE_FAILED: '905:500',\n\n // Persona (910-919)\n PERSONA_NOT_FOUND: '910:404',\n PERSONA_SAVE_FAILED: '911:500',\n\n // File (030-049)\n FILE_PARSE_FAILED: '030:500',\n FILE_UNSUPPORTED_FORMAT: '031:400',\n FILE_OCR_FAILED: '032:500',\n FILE_INVALID_CONTENT: '033:400',\n\n // Audio (050-059)\n AUDIO_INVALID_REQUEST: '050:400',\n AUDIO_MODEL_NOT_FOUND: '051:404',\n AUDIO_PROVIDER_NOT_FOUND: '052:404',\n AUDIO_UNSUPPORTED_INPUT: '053:400',\n AUDIO_UPSTREAM_ERROR: '054:502',\n AUDIO_PROTOCOL_ERROR: '055:502',\n AUDIO_CONNECTION_FAILED: '056:502',\n AUDIO_TIMEOUT: '057:504',\n AUDIO_INPUT_TOO_LARGE: '058:413',\n AUDIO_CANCELLED: '059:499',\n\n // Context (950-999)\n CONTEXT_COMPRESS_FAILED: '950:500',\n CONTEXT_SUMMARIZE_FAILED: '951:500',\n CONTEXT_TOKEN_ESTIMATE_FAILED: '952:500',\n CONTEXT_BUDGET_EXCEEDED: '953:400',\n CONTEXT_TURN_NOT_FOUND: '954:404',\n CONTEXT_TURN_INVALID_STATE: '955:409',\n\n // Store (960-969)\n STORE_FAILED: '960:500',\n STORE_NOT_AVAILABLE: '961:503',\n\n // Session (970-979)\n SESSION_NOT_FOUND: '970:404',\n SESSION_FAILED: '971:500',\n\n // A2A (980-999)\n A2A_NOT_CONFIGURED: '980:500',\n A2A_HANDLE_FAILED: '981:500',\n A2A_REMOTE_CALL_FAILED: '982:502',\n A2A_AUTH_FAILED: '983:401',\n A2A_LIST_MESSAGES_FAILED: '984:500',\n} as const satisfies ErrorInfo\n\n/**\n * AI 模块标准错误定义对象。\n *\n * 通过 `HaiAIError.ERROR_CODE_NAME` 访问具体错误定义,如:\n * ```ts\n * const def = HaiAIError.NOT_INITIALIZED\n * // => { code: 'hai:ai:010', httpStatus: 500, system: 'hai', module: 'ai' }\n * ```\n */\nexport const HaiAIError = core.error.buildHaiErrorsDef('ai', AIErrorInfo)\n\n// ─── 初始化选项 ───\n\n/**\n * AI 初始化运行时选项\n *\n * 用于传入运行时对象(如自定义 StoreProvider),\n * 这些对象无法通过 Zod 配置 Schema 传递。\n */\nexport interface AIInitOptions {\n /**\n * 自定义存储 Provider\n *\n * 提供后 AI 模块将使用此 Provider 而非默认的 reldb+vecdb 实现,\n * 此时不需要提前初始化 reldb/vecdb。\n */\n storeProvider?: AIStoreProvider\n}\n\n// ─── AIFunctions 接口 ───\n\n/**\n * AI 服务接口(通过 `ai` 对象访问)\n *\n * 所有 AI 功能的统一入口,需先调用 `init()` 初始化后才能使用 `llm`、`mcp` 操作。\n * `tools` 和 `stream` 为纯函数,无需初始化即可使用。\n *\n * @example\n * ```ts\n * import { ai } from '@h-ai/ai'\n *\n * await ai.init({ llm: { model: 'gpt-4o-mini' } })\n * const result = await ai.llm.chat({ messages: [{ role: 'user', content: '你好' }] })\n * await ai.close()\n * ```\n */\nexport interface AIFunctions {\n /**\n * 初始化 AI 服务\n *\n * 使用 Zod Schema 校验配置,失败返回 `CONFIGURATION_ERROR`。\n * 重复调用会先关闭旧实例再重新初始化。\n *\n * @param config - AI 配置(可选,默认使用空对象并应用 Schema 默认值)\n * @param options - 运行时选项(可选,用于传入自定义 StoreProvider 等运行时对象)\n * @returns 成功返回 `ok(undefined)`;配置校验失败返回 `err(HaiAIError.CONFIGURATION_ERROR)`\n */\n init: (config?: AIConfigInput, options?: AIInitOptions) => Promise<HaiResult<void>>\n /**\n * 关闭 AI 服务,释放内部状态\n *\n * 关闭后 `llm`、`mcp` 操作将返回 `NOT_INITIALIZED` 错误。\n * 重复关闭不会报错。\n */\n close: () => Promise<void>\n /** 当前脱敏后的配置快照(未初始化时为 `null`) */\n readonly config: AIConfig | null\n /** 是否已初始化(`init()` 成功后为 `true`,`close()` 后为 `false`) */\n readonly isInitialized: boolean\n /** LLM 操作(聊天、流式、模型列表),需要先调用 `init()` */\n readonly llm: LLMOperations\n /** MCP 操作(工具/资源/提示词注册与调用),需要先调用 `init()` */\n readonly mcp: MCPOperations\n /** 工具操作(定义工具与注册表),纯函数,无需初始化 */\n readonly tools: ToolsOperations\n /** 流处理操作(流处理器、SSE 编解码),纯函数,无需初始化 */\n readonly stream: StreamOperations\n /** Embedding 操作(向量嵌入),需要先调用 `init()` */\n readonly embedding: EmbeddingOperations\n /** 推理操作(ReAct / CoT / Plan-Execute),需要先调用 `init()` */\n readonly reasoning: ReasoningOperations\n /** 检索操作(向量检索),需要先调用 `init()` */\n readonly retrieval: RetrievalOperations\n /** RAG 操作(检索增强生成),需要先调用 `init()` */\n readonly rag: RagOperations\n /** Knowledge 操作(知识库管理与检索),需要先调用 `init()` 和 `knowledge.setup()` */\n readonly knowledge: KnowledgeOperations\n /** Memory 操作(记忆提取、存储、检索、注入),需要先调用 `init()` */\n readonly memory: MemoryOperations\n /** Persona 操作(AI 角色人格档案与系统提示词组合),需要先调用 `init()` */\n readonly persona: PersonaOperations\n /** Token 操作(Token 估算),需要先调用 `init()` */\n readonly token: TokenOperations\n /** Summary 操作(消息摘要生成),需要先调用 `init()` */\n readonly summary: SummaryOperations\n /** Compress 操作(上下文压缩),需要先调用 `init()` */\n readonly compress: CompressOperations\n /** Context 操作(有状态上下文管理器,编排 LLM + Memory + RAG + Reasoning),需要先调用 `init()` */\n readonly context: ContextOperations\n /** Rerank 操作(文档重排序),需要先调用 `init()` */\n readonly rerank: RerankOperations\n /** File 操作(文件内容解析),需要先调用 `init()` */\n readonly file: FileOperations\n /** A2A 操作(Agent-to-Agent 协议),需要先调用 `init()` 并配置 `a2a` */\n readonly a2a: A2AOperations\n /** Audio 操作(语音识别 / 语音合成),需要先调用 `init()` 并配置 `audio` */\n readonly audio: AudioOperations\n}\n","/**\n * @h-ai/ai — Compress 子功能类型\n *\n * 定义上下文压缩操作的类型接口:滑动窗口、摘要、混合三种策略。\n * 在对话超出模型上下文窗口时,自动压缩历史消息以保持对话连续性。\n * @module ai-compress-types\n */\n\nimport type { HaiResult } from '@h-ai/core'\n\nimport type { ChatMessage } from '../llm/ai-llm-types.js'\n\nimport { z } from 'zod'\n\n// ─── 压缩策略枚举 ───\n\n/** 压缩策略枚举 */\nexport const CompressionStrategySchema = z.enum(['summary', 'sliding-window', 'hybrid'])\n\n/** 压缩策略类型 */\nexport type CompressionStrategy = z.infer<typeof CompressionStrategySchema>\n\n// ─── 压缩选项与结果 ───\n\n/**\n * 上下文压缩选项\n */\nexport interface CompressOptions {\n /** 压缩策略(默认使用配置的 defaultStrategy) */\n strategy?: CompressionStrategy\n /** 目标 token 数(默认使用配置的 defaultMaxTokens,0 表示取模型 maxTokens 的 80%) */\n maxTokens?: number\n /** 保留 system 消息(默认 true) */\n preserveSystem?: boolean\n /** 保留最近 N 条消息不压缩(默认使用配置的 preserveLastN) */\n preserveLastN?: number\n /** 摘要用的模型 */\n summaryModel?: string\n}\n\n/**\n * 上下文压缩结果\n */\nexport interface CompressResult {\n /** 压缩后的消息列表 */\n messages: ChatMessage[]\n /** 原始消息的估算 token 数 */\n originalTokens: number\n /** 压缩后的估算 token 数 */\n compressedTokens: number\n /** 被移除/合并的消息数 */\n removedCount: number\n /** 生成的摘要文本(仅 summary/hybrid 策略有值) */\n summary?: string\n}\n\n// ─── Compress 操作接口 ───\n\n/**\n * Compress 操作接口\n *\n * 管理对话消息的压缩,支持三种策略:\n * - `sliding-window`:移除最旧的消息,保留最近 N 条\n * - `summary`:使用 LLM 生成摘要替换旧消息\n * - `hybrid`:先滑动窗口,不够则回退到摘要\n *\n * @example\n * ```ts\n * const result = await compressOps.tryCompress(messages, {\n * strategy: 'hybrid',\n * maxTokens: 4000,\n * })\n * if (result.success) {\n * const compressed = result.data.messages\n * }\n * ```\n */\nexport interface CompressOperations {\n /**\n * 尝试压缩消息列表,使其不超过指定 Token 预算\n *\n * 如果当前 token 数未超限则直接返回(不压缩),因此命名为 tryCompress。\n *\n * @param messages - 消息列表\n * @param options - 压缩选项\n * @returns 压缩结果\n */\n tryCompress: (messages: ChatMessage[], options?: CompressOptions) => Promise<HaiResult<CompressResult>>\n}\n","/**\n * @h-ai/ai — Knowledge 子功能类型\n *\n * 定义知识库操作的类型接口:文档导入、实体索引、信源追踪检索。\n * @module ai-knowledge-types\n */\n\nimport type { HaiError, HaiResult } from '@h-ai/core'\nimport type { ChunkOptionsInput, CleanOptionsInput } from '@h-ai/datapipe'\n\nimport type { ChatMessage } from '../llm/ai-llm-types.js'\nimport type { Citation } from '../retrieval/ai-retrieval-types.js'\n\nimport { z } from 'zod'\n\n// ─── 实体类型枚举 ───\n\n/**\n * 内置实体类型枚举(预设值,可通过配置 `entityTypes` 扩展)\n */\nexport const EntityTypeSchema = z.enum(['person', 'project', 'concept', 'organization', 'location', 'event', 'other'])\n\n/** 实体类型(字符串,支持内置类型及用户自定义类型) */\nexport type EntityType = string\n\n// ─── 实体 ───\n\n/**\n * 知识实体\n *\n * 表示从文档中提取的命名实体(人名、项目名、概念等),\n * 存储在 KnowledgeStore 中用于倒排索引查询。\n *\n * @example\n * ```ts\n * const entity: KnowledgeEntity = {\n * id: 'ent-001',\n * name: '张三',\n * type: 'person',\n * aliases: ['小张', 'Zhang San'],\n * }\n * ```\n */\nexport interface KnowledgeEntity {\n /** 实体唯一标识 */\n id: string\n /** 实体名称 */\n name: string\n /** 实体类型 */\n type: EntityType\n /** 别名列表(可选) */\n aliases?: string[]\n /** 描述(可选) */\n description?: string\n /** 创建时间 */\n createdAt?: string\n /** 更新时间 */\n updatedAt?: string\n}\n\n/**\n * 文档-实体关联记录\n *\n * 倒排索引中的一条记录,记录实体与文档/分块的关联关系。\n */\nexport interface EntityDocumentRelation {\n /** 实体 ID */\n entityId: string\n /** 文档 ID(对应向量存储中的 documentId) */\n documentId: string\n /** 分块 ID(对应向量存储中的向量记录 ID) */\n chunkId?: string\n /** 集合名 */\n collection: string\n /** 关联强度 [0, 1](默认 1.0) */\n relevance?: number\n /** 实体在该文档中的上下文片段(可选) */\n context?: string\n /** 创建时间 */\n createdAt?: string\n}\n\n// ─── 知识库操作输入/输出 ───\n\n/**\n * 知识库初始化选项\n */\nexport interface KnowledgeSetupOptions {\n /** 集合名(可选,默认使用配置中的 collection) */\n collection?: string\n /** 向量维度(可选,默认使用配置中的 dimension) */\n dimension?: number\n}\n\n/**\n * 文档导入输入\n *\n * @example\n * ```ts\n * const input: KnowledgeIngestInput = {\n * documentId: 'doc-001',\n * content: '# 项目文档\\n\\n张三负责了核心模块...',\n * title: '项目文档',\n * url: 'https://docs.example.com/project',\n * metadata: { author: '李四' },\n * }\n * ```\n */\nexport interface KnowledgeIngestInput {\n /** 文档唯一标识(必填,用于关联信源和实体) */\n documentId: string\n /** 文档原始内容文本 */\n content: string\n /** 文档标题(可选,存入 metadata 用于信源展示) */\n title?: string\n /** 文档 URL / 路径(可选,存入 metadata 用于信源展示) */\n url?: string\n /** 集合名(可选,默认使用配置中的 collection) */\n collection?: string\n /** 附加元数据(可选,合并到每个 chunk 的 metadata 中) */\n metadata?: Record<string, unknown>\n /** 是否启用实体提取(可选,覆盖全局配置) */\n enableEntityExtraction?: boolean\n /**\n * 文本清洗选项(可选,覆盖全局配置默认值)\n *\n * 字段含义与 @h-ai/datapipe CleanOptionsInput 完全一致,\n * 支持 removeHtml、removeUrls、normalizeWhitespace、customReplacements 等。\n */\n cleanOptions?: CleanOptionsInput\n /**\n * 分块选项(可选,覆盖全局配置默认值)\n *\n * 字段含义与 @h-ai/datapipe ChunkOptionsInput 完全一致,\n * 支持 mode、maxSize、overlap、separator、markdownMinLevel 等完整选项。\n */\n chunkOptions?: ChunkOptionsInput\n}\n\n/**\n * 文档导入结果\n */\nexport interface KnowledgeIngestResult {\n /** 文档 ID */\n documentId: string\n /** 生成的分块数量 */\n chunkCount: number\n /** 提取的实体列表(未启用实体提取时为空数组) */\n entities: KnowledgeEntity[]\n /** 处理耗时(毫秒) */\n duration: number\n}\n\n/**\n * 知识检索选项\n */\nexport interface KnowledgeRetrieveOptions {\n /** 集合名(可选,默认使用配置中的 collection) */\n collection?: string\n /** 返回的最大结果数(默认 10) */\n topK?: number\n /** 最低相似度(默认无限制) */\n minScore?: number\n /** 是否启用实体增强检索(默认 true) */\n enableEntityBoost?: boolean\n /** 元数据过滤条件 */\n filter?: Record<string, unknown>\n}\n\n/**\n * 知识检索结果项\n */\nexport interface KnowledgeRetrieveItem {\n /** 分块 ID */\n id: string\n /** 分块内容 */\n content: string\n /** 综合得分(向量相似度 + 实体加权) */\n score: number\n /** 结构化信源引用 */\n citation: Citation\n /** 元数据 */\n metadata?: Record<string, unknown>\n /** 命中的实体名称列表(实体增强检索时填充) */\n matchedEntities?: string[]\n}\n\n/**\n * 知识检索结果\n */\nexport interface KnowledgeRetrieveResult {\n /** 检索结果列表(按综合分数降序) */\n items: KnowledgeRetrieveItem[]\n /** 去重后的信源引用列表 */\n citations: Citation[]\n /** 查询文本 */\n query: string\n /** 查询耗时(毫秒) */\n duration: number\n}\n\n/**\n * 知识问答选项\n */\nexport interface KnowledgeAskOptions extends KnowledgeRetrieveOptions {\n /** LLM 模型名称覆盖 */\n model?: string\n /** 系统提示词覆盖 */\n systemPrompt?: string\n /** 温度覆盖 */\n temperature?: number\n /** 消息历史(多轮对话) */\n messages?: ChatMessage[]\n}\n\n/**\n * 知识问答结果\n */\nexport interface KnowledgeAskResult {\n /** LLM 生成的回答 */\n answer: string\n /** 使用的上下文 */\n context: KnowledgeRetrieveItem[]\n /** 去重后的信源引用列表 */\n citations: Citation[]\n /** 查询文本 */\n query: string\n /** 使用的模型 */\n model: string\n /** Token 使用统计 */\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n }\n}\n\n/**\n * 实体查询选项\n */\nexport interface EntityQueryOptions {\n /** 集合名(可选,默认使用配置中的 collection) */\n collection?: string\n /** 实体类型过滤 */\n type?: EntityType\n}\n\n/**\n * 实体关联文档结果\n */\nexport interface EntityDocumentResult {\n /** 实体信息 */\n entity: KnowledgeEntity\n /** 关联文档列表 */\n documents: Array<{\n documentId: string\n chunkId?: string\n collection: string\n relevance: number\n context?: string\n }>\n}\n\n/**\n * 实体列表查询选项\n */\nexport interface EntityListOptions {\n /** 集合名过滤(不指定则返回所有 collection 的实体) */\n collection?: string\n /** 实体类型过滤 */\n type?: EntityType\n /** 关键词搜索(模糊匹配实体名称和别名) */\n keyword?: string\n /** 最大返回数 */\n limit?: number\n}\n\n// ─── 文件导入类型 ───\n\n/**\n * 文件导入输入(从文件路径读取内容后自动 ingest)\n *\n * 仅 Node.js 端可用。\n *\n * @example\n * ```ts\n * await knowledge.ingestFile({\n * filePath: '/data/docs/README.md',\n * documentId: 'readme',\n * })\n * ```\n */\nexport interface KnowledgeIngestFileInput {\n /** 文件路径(绝对路径或相对路径) */\n filePath: string\n /** 文档唯一标识(可选,默认从文件名派生) */\n documentId?: string\n /** 文档标题(可选,默认为文件名) */\n title?: string\n /** 文件编码(默认 'utf-8') */\n encoding?: BufferEncoding\n /** 集合名(可选,默认使用配置中的 collection) */\n collection?: string\n /** 附加元数据 */\n metadata?: Record<string, unknown>\n /** 是否启用实体提取 */\n enableEntityExtraction?: boolean\n /** 清洗选项 */\n cleanOptions?: CleanOptionsInput\n /** 分块选项 */\n chunkOptions?: ChunkOptionsInput\n}\n\n// ─── 文档管理类型 ───\n\n/**\n * 文档信息(列表展示用)\n */\nexport interface KnowledgeDocumentInfo {\n /** 文档 ID */\n documentId: string\n /** 文档标题 */\n title?: string\n /** 文档来源 URL / 路径 */\n url?: string\n /** 分块数量 */\n chunkCount: number\n /** 关联实体数 */\n entityCount: number\n /** 创建时间(Unix 毫秒) */\n createdAt: number\n}\n\n/**\n * 文档列表查询选项\n */\nexport interface KnowledgeDocumentListOptions {\n /** 集合名覆盖(不指定则使用配置中的 default) */\n collection?: string\n /** 偏移量 */\n offset?: number\n /** 每页数量(默认 20) */\n limit?: number\n}\n\n/**\n * 文档删除选项\n */\nexport interface KnowledgeDocumentRemoveOptions {\n /** 集合名覆盖 */\n collection?: string\n}\n\n// ─── 批量导入类型 ───\n\n/**\n * 批量导入进度回调参数\n */\nexport interface KnowledgeIngestBatchProgress {\n /** 已完成数量 */\n completed: number\n /** 总数量 */\n total: number\n /** 当前文档 ID */\n currentDocumentId: string\n /** 当前文档导入结果(失败时为 undefined) */\n result?: KnowledgeIngestResult\n /** 当前文档导入错误(成功时为 undefined) */\n error?: HaiError\n}\n\n/**\n * 批量导入结果\n */\nexport interface KnowledgeIngestBatchResult {\n /** 成功导入的文档数 */\n successCount: number\n /** 失败的文档数 */\n failureCount: number\n /** 各文档导入结果 */\n results: Array<{ documentId: string, result?: KnowledgeIngestResult, error?: HaiError }>\n /** 总耗时(毫秒) */\n duration: number\n}\n\n// ─── Knowledge 操作接口 ───\n\n/**\n * Knowledge 操作接口(通过 `ai.knowledge` 访问)\n *\n * 知识库管理与检索的统一入口,编排 datapipe + KnowledgeStore + embedding + LLM。\n *\n * ## 生命周期\n *\n * 每个 collection 在使用前必须先调用 `setup()`,支持多次调用以初始化不同分区:\n *\n * ```ts\n * await ai.knowledge.setup() // 使用配置默认 collection\n * await ai.knowledge.setup({ collection: 'kb-prod' }) // 初始化额外分区\n * ```\n *\n * ## 单 collection 示例\n *\n * ```ts\n * // 初始化\n * await ai.knowledge.setup()\n *\n * // 导入文档\n * await ai.knowledge.ingest({\n * documentId: 'doc-001',\n * content: markdownContent,\n * title: '项目文档',\n * })\n *\n * // 查询(带信源追踪)\n * const result = await ai.knowledge.retrieve('张三负责了哪些模块?')\n *\n * // 问答(RAG + 信源引用)\n * const answer = await ai.knowledge.ask('张三负责了哪些模块?')\n * ```\n *\n * ## 多 collection(多分区)示例\n *\n * ```ts\n * // 分别初始化两个知识库分区\n * await ai.knowledge.setup({ collection: 'kb-product' })\n * await ai.knowledge.setup({ collection: 'kb-support' })\n *\n * // 写入不同分区\n * await ai.knowledge.ingest({ documentId: 'p-001', content: '...', collection: 'kb-product' })\n * await ai.knowledge.ingest({ documentId: 's-001', content: '...', collection: 'kb-support' })\n *\n * // 从指定分区检索(对未 setup 的 collection 发起任何操作都会返回 KNOWLEDGE_NOT_SETUP 错误)\n * const result = await ai.knowledge.retrieve('query', { collection: 'kb-support' })\n * ```\n */\nexport interface KnowledgeOperations {\n /**\n * 初始化知识库(幂等,支持多次调用以初始化不同 collection)\n *\n * 创建向量集合和实体表。每个 collection 需独立调用本方法,\n * 未 setup 的 collection 执行以下操作时均会返回 `KNOWLEDGE_NOT_SETUP` 错误:\n * `ingest` / `ingestFile` / `ingestBatch` / `retrieve` / `ask` /\n * `findByEntity` / `listDocuments` / `removeDocument`。\n *\n * @param options - 初始化选项(collection 名称、向量维度)\n * @returns 成功返回 ok(undefined)\n */\n setup: (options?: KnowledgeSetupOptions) => Promise<HaiResult<void>>\n\n /**\n * 导入文档\n *\n * 执行流程:clean → chunk → embed → 向量存储 → 实体提取 → 实体存储\n *\n * @param input - 文档导入输入\n * @returns 导入结果(分块数、实体列表等)\n */\n ingest: (input: KnowledgeIngestInput) => Promise<HaiResult<KnowledgeIngestResult>>\n\n /**\n * 知识检索(带实体增强 + 信源追踪)\n *\n * @param query - 查询文本\n * @param options - 检索选项\n * @returns 检索结果(带 citations)\n */\n retrieve: (query: string, options?: KnowledgeRetrieveOptions) => Promise<HaiResult<KnowledgeRetrieveResult>>\n\n /**\n * 知识问答(RAG + 信源引用)\n *\n * @param query - 用户问题\n * @param options - 问答选项\n * @returns 问答结果(回答 + 信源)\n */\n ask: (query: string, options?: KnowledgeAskOptions) => Promise<HaiResult<KnowledgeAskResult>>\n\n /**\n * 按实体查询关联文档\n *\n * @param entityName - 实体名称\n * @param options - 查询选项\n * @returns 实体关联文档列表\n */\n findByEntity: (entityName: string, options?: EntityQueryOptions) => Promise<HaiResult<EntityDocumentResult[]>>\n\n /**\n * 列出所有实体\n *\n * @param options - 列表选项\n * @returns 实体列表\n */\n listEntities: (options?: EntityListOptions) => Promise<HaiResult<KnowledgeEntity[]>>\n\n /**\n * 列出已导入的文档列表\n *\n * @param options - 列表选项\n * @returns 文档信息列表\n */\n listDocuments: (options?: KnowledgeDocumentListOptions) => Promise<HaiResult<KnowledgeDocumentInfo[]>>\n\n /**\n * 删除已导入的文档(同时删除向量和实体关联)\n *\n * @param documentId - 文档 ID\n * @param options - 删除选项\n * @returns 成功返回 ok(undefined)\n */\n removeDocument: (documentId: string, options?: KnowledgeDocumentRemoveOptions) => Promise<HaiResult<void>>\n\n /**\n * 从文件路径导入文档(仅 Node.js 端可用)\n *\n * 读取文件内容后自动调用 ingest() 完成导入。\n *\n * @param input - 文件导入输入\n * @returns 导入结果\n */\n ingestFile: (input: KnowledgeIngestFileInput) => Promise<HaiResult<KnowledgeIngestResult>>\n\n /**\n * 批量导入文档\n *\n * 依次执行 ingest(),通过 onProgress 回调报告进度,单个文档失败不中断整体流程。\n *\n * @param inputs - 文档导入输入列表\n * @param onProgress - 每完成一个文档后的回调\n * @returns 批量导入汇总结果\n */\n ingestBatch: (\n inputs: KnowledgeIngestInput[],\n onProgress?: (progress: KnowledgeIngestBatchProgress) => void,\n ) => Promise<HaiResult<KnowledgeIngestBatchResult>>\n\n /**\n * 删除整个 collection(幂等)\n *\n * 同时清除:vecdb 向量集合、实体-文档关联、文档元数据、collection 注册记录。\n * 删除后 collection 需重新执行 `setup` 才可使用。\n *\n * @param collection - 要删除的 collection 名称,默认使用 config.collection\n * @returns 成功返回 ok(undefined);store 不可用时返回 `KNOWLEDGE_SETUP_FAILED`\n */\n deleteCollection: (collection?: string) => Promise<HaiResult<void>>\n}\n","/**\n * @h-ai/ai — Memory 子功能类型\n *\n * 定义记忆管理操作的类型接口:提取、存储、检索、注入。\n * 支持从对话中自动提取关键事实、偏好、事件等记忆,并在后续对话中检索注入。\n * @module ai-memory-types\n */\n\nimport type { HaiResult } from '@h-ai/core'\n\nimport type { ChatMessage, TempModelConfig } from '../llm/ai-llm-types.js'\nimport type { StorePage } from '../store/ai-store-types.js'\n\nimport { z } from 'zod'\n\n// ─── 记忆类型枚举 ───\n\n/**\n * 记忆类型枚举 Schema\n *\n * 定义系统支持的五种记忆类型,用于对提取和存储的记忆进行分类:\n * - `fact` — 客观事实(如「用户是后端工程师」「项目使用 TypeScript」)\n * - `preference` — 用户偏好(如「喜欢简洁的代码风格」「偏好中文回复」)\n * - `event` — 事件/时间线信息(如「上周部署了 v2.0」「昨天修复了登录 Bug」)\n * - `entity` — 命名实体(如人名、产品名、组织名等,便于后续实体关联)\n * - `instruction` — 用户给出的持久指令(如「以后都用函数式写法」「回复不超过 200 字」)\n *\n * @example\n * ```ts\n * import { MemoryTypeSchema } from '@h-ai/ai'\n *\n * // 校验字符串是否为合法记忆类型\n * const result = MemoryTypeSchema.safeParse('preference') // { success: true }\n *\n * // 用于配置或过滤\n * await ai.memory.recall('编程语言', { types: ['preference', 'fact'] })\n * ```\n */\nexport const MemoryTypeSchema = z.enum(['fact', 'preference', 'event', 'entity', 'instruction'])\n\n/** 记忆类型 */\nexport type MemoryType = z.infer<typeof MemoryTypeSchema>\n\n// ─── 记忆条目 ───\n\n/**\n * 记忆条目输入(手动添加时使用)\n *\n * @example\n * ```ts\n * const input: MemoryEntryInput = {\n * content: '用户偏好使用中文回复',\n * type: 'preference',\n * importance: 0.8,\n * objectId: 'user-001',\n * }\n * ```\n */\nexport interface MemoryEntryInput {\n /** 记忆内容 */\n content: string\n /** 记忆类型 */\n type: MemoryType\n /** 重要性评分 [0, 1](可选,默认 0.5) */\n importance?: number\n /** 所属主体 ID(不指定时为全局记忆) */\n objectId?: string\n /** 作用域(JSON 对象,key-value 匹配过滤。用于子 session 记忆隔离等场景) */\n scope?: Record<string, unknown>\n /** 附加元数据 */\n metadata?: Record<string, unknown>\n}\n\n/**\n * 完整的记忆条目\n */\nexport interface MemoryEntry {\n /** 记忆唯一标识 */\n id: string\n /** 记忆内容 */\n content: string\n /** 记忆类型 */\n type: MemoryType\n /** 重要性评分 [0, 1] */\n importance: number\n /** 所属主体 ID */\n objectId?: string\n /** 作用域(JSON 对象,key-value 匹配过滤。用于子 session 记忆隔离等场景) */\n scope?: Record<string, unknown>\n /** 附加元数据 */\n metadata?: Record<string, unknown>\n /** 向量(embedding 已计算时填充) */\n vector?: number[]\n /** 创建时间(Unix 毫秒) */\n createdAt: number\n /** 最近访问时间(Unix 毫秒) */\n lastAccessedAt: number\n /** 被检索次数 */\n accessCount: number\n}\n\n// ─── 提取选项 ───\n\n/**\n * 记忆提取选项\n */\nexport interface MemoryExtractOptions {\n /** 只提取指定类型 */\n types?: MemoryType[]\n /** 指定提取用的模型 */\n model?: string\n /** 自定义提取 systemPrompt(覆盖模块配置与内置默认提示词) */\n systemPrompt?: string\n /** 过滤低重要性条目(默认 0) */\n minImportance?: number\n /** 所属主体 ID(关联到提取结果) */\n objectId?: string\n /** 作用域(JSON 对象,提取的记忆将关联此 scope) */\n scope?: Record<string, unknown>\n /**\n * 临时模型配置(携带凭据的模型请求)。\n *\n * 用于传递运行时解析的 apiKey / baseUrl 等凭证,\n * 避免回退到全局 .env 配置。优先级高于全局 config.models 查找。\n */\n tempModel?: TempModelConfig\n}\n\n// ─── 检索选项 ───\n\n/**\n * 记忆检索选项\n */\nexport interface MemoryRecallOptions {\n /** 返回数量(默认使用配置的 defaultTopK) */\n topK?: number\n /**\n * 候选池倍数(覆盖配置的 candidateMultiplier)\n *\n * 检索时先取回 `topK × candidateMultiplier` 条候选再按 scope / 类型 / 重要性过滤,\n * 最后截取 topK。scope 过滤较严(如按 topic / persona 隔离)时应调大,避免漏召回。\n */\n candidateMultiplier?: number\n /** 过滤类型 */\n types?: MemoryType[]\n /** 最低重要性 */\n minImportance?: number\n /** 时间衰减权重 [0, 1](0 = 不考虑时间,1 = 仅按时间排序) */\n recencyWeight?: number\n /** 限定主体 ID */\n objectId?: string\n /** 限定作用域(key-value 匹配过滤,用于子 session 记忆隔离等场景) */\n scope?: Record<string, unknown>\n}\n\n// ─── 注入选项 ───\n\n/**\n * 记忆注入选项(`injectMemories` 使用)\n *\n * 控制记忆注入行为:检索数量、Token 预算、注入位置等。\n */\nexport interface MemoryInjectionOptions {\n /** 注入的记忆数量(默认 5) */\n topK?: number\n /**\n * 候选池倍数(覆盖配置的 candidateMultiplier)\n *\n * 透传给底层 `recall`,scope 过滤较严时应调大以避免漏召回。\n */\n candidateMultiplier?: number\n /** 记忆占用的最大 token 预算(默认不限) */\n maxTokens?: number\n /** 注入位置:system = 追加到 system 消息末尾,before-last = 插入在最后一条用户消息之前 */\n position?: 'system' | 'before-last'\n /** 限定主体 ID */\n objectId?: string\n /** 限定作用域(key-value 匹配过滤,用于子 session 记忆隔离等场景) */\n scope?: Record<string, unknown>\n /** 限定记忆类型 */\n types?: MemoryType[]\n /** 最低重要性阈值 */\n minImportance?: number\n}\n\n// ─── 列表与清空选项 ───\n\n/**\n * 记忆列表选项\n */\nexport interface MemoryListOptions {\n /** 过滤类型 */\n types?: MemoryType[]\n /** 限定主体 ID */\n objectId?: string\n /** 限定作用域(key-value 匹配过滤,用于子 session / 主题 / 角色记忆隔离等场景) */\n scope?: Record<string, unknown>\n /** 最大返回数 */\n limit?: number\n}\n\n/**\n * 记忆分页选项\n */\nexport interface MemoryListPageOptions {\n /** 过滤类型 */\n types?: MemoryType[]\n /** 限定主体 ID */\n objectId?: string\n /** 限定作用域(key-value 匹配过滤,用于子 session / 主题 / 角色记忆隔离等场景) */\n scope?: Record<string, unknown>\n /** 偏移量 */\n offset?: number\n /** 每页数量(默认 20) */\n limit?: number\n}\n\n/**\n * 记忆清空选项\n *\n * 安全语义:未传任何过滤条件时清空全部;传入 objectId / types / scope 时\n * 仅删除同时匹配所有给定条件的记忆,避免误删其他主体或类型的记忆。\n */\nexport interface MemoryClearOptions {\n /** 仅清空指定类型 */\n types?: MemoryType[]\n /** 仅清空指定主体 */\n objectId?: string\n /** 仅清空匹配指定作用域的记忆(key-value 匹配过滤) */\n scope?: Record<string, unknown>\n}\n\n/**\n * 记忆条目更新输入\n *\n * 所有字段均为可选,仅传入需要更新的字段。\n */\nexport interface MemoryUpdateInput {\n /** 更新记忆内容(同时重新计算向量) */\n content?: string\n /** 更新记忆类型 */\n type?: MemoryType\n /** 更新重要性 */\n importance?: number\n /** 更新元数据 */\n metadata?: Record<string, unknown>\n}\n\n// ─── Memory 操作接口 ───\n\n/**\n * Memory 操作接口(通过 `ai.memory` 访问)\n *\n * 管理对话中产生的关键事实、用户偏好、长期知识的提取、存储与检索。\n * 需要先调用 `ai.init()` 初始化后使用。\n *\n * @example\n * ```ts\n * // 从对话中自动提取记忆\n * const extracted = await ai.memory.extract(messages, {\n * objectId: 'user-001',\n * systemPrompt: 'Only extract durable user preferences and explicit long-term instructions.',\n * })\n *\n * // 手动添加记忆\n * await ai.memory.add({ content: '用户偏好中文', type: 'preference', objectId: 'user-001' })\n *\n * // 检索相关记忆\n * const memories = await ai.memory.recall('用户的语言偏好', { objectId: 'user-001' })\n *\n * // 将记忆注入消息列表\n * const enriched = await ai.memory.injectMemories(newMessages, { objectId: 'user-001' })\n * const response = await ai.llm.chat({ messages: enriched.value })\n * ```\n */\n\n/**\n * 按 ID 访问单条记忆(get / update / remove)时的归属校验作用域。\n *\n * 传入后,Provider 先读取记忆再校验:`entry.objectId` 必须等于 `objectId`,且 `entry.scope`\n * 包含 `scope` 的全部 key-value;不匹配时统一返回 `MEMORY_NOT_FOUND`(避免通过错误差异\n * 枚举其他主体的记忆)。不传时不做归属校验(向后兼容);处理不可信输入的 memoryId 时必须传入。\n */\nexport interface MemoryAccessScope {\n /** 归属主体 ID(必须与记忆 entry.objectId 一致) */\n objectId: string\n /** 业务作用域(entry.scope 必须包含这些 key-value) */\n scope?: Record<string, unknown>\n}\n\nexport interface MemoryOperations {\n /**\n * 从对话消息中自动提取记忆条目\n *\n * 使用 LLM 分析对话内容,提取值得记住的事实、偏好、事件等。\n * 提取的记忆会自动持久化到 Store(含向量计算)。\n *\n * @param messages - 对话消息列表\n * @param options - 提取选项\n * @returns 提取到的记忆条目列表\n */\n extract: (messages: ChatMessage[], options?: MemoryExtractOptions) => Promise<HaiResult<MemoryEntry[]>>\n\n /**\n * 根据查询检索最相关的记忆\n *\n * 综合向量相似度、重要性、时间衰减进行排序。\n *\n * @param query - 查询文本\n * @param options - 检索选项\n * @returns 相关记忆列表\n */\n recall: (query: string, options?: MemoryRecallOptions) => Promise<HaiResult<MemoryEntry[]>>\n\n /**\n * 将相关记忆注入到消息列表中\n *\n * 工作流程:\n * 1. 从消息列表中提取最后一条用户消息作为检索查询\n * 2. 调用 `recall` 检索最相关的记忆条目\n * 3. 将记忆格式化为文本块,按指定位置注入消息列表\n *\n * @param messages - 原始消息列表\n * @param options - 注入选项(数量、位置、Token 预算等)\n * @returns 注入记忆后的新消息列表(不修改原数组)\n */\n injectMemories: (messages: ChatMessage[], options?: MemoryInjectionOptions) => Promise<HaiResult<ChatMessage[]>>\n\n /**\n * 手动添加一条记忆\n *\n * 记忆会自动持久化到 Store(含向量计算)。\n *\n * @param entry - 记忆条目输入\n * @returns 存储后的完整记忆条目\n */\n add: (entry: MemoryEntryInput) => Promise<HaiResult<MemoryEntry>>\n\n /**\n * 更新一条已有记忆\n *\n * 仅更新传入的字段,其余字段保持不变。\n * 若 content 被更新,会重新计算向量。\n * 更新结果自动持久化到 Store。\n *\n * @param memoryId - 记忆 ID\n * @param updates - 需要更新的字段\n * @param accessScope - 可选归属校验(不匹配返回 MEMORY_NOT_FOUND)\n * @returns 更新后的完整记忆条目\n */\n update: (memoryId: string, updates: MemoryUpdateInput, accessScope?: MemoryAccessScope) => Promise<HaiResult<MemoryEntry>>\n\n /**\n * 按 ID 获取单条记忆\n *\n * @param memoryId - 记忆 ID\n * @param accessScope - 可选归属校验(不匹配返回 MEMORY_NOT_FOUND)\n * @returns 记忆条目,不存在时返回 MEMORY_NOT_FOUND\n */\n get: (memoryId: string, accessScope?: MemoryAccessScope) => Promise<HaiResult<MemoryEntry>>\n\n /**\n * 删除单条记忆\n *\n * 同时从 Store 中移除持久化数据。\n *\n * @param memoryId - 记忆 ID\n * @param accessScope - 可选归属校验(不匹配返回 MEMORY_NOT_FOUND)\n * @returns 成功返回 ok(undefined)\n */\n remove: (memoryId: string, accessScope?: MemoryAccessScope) => Promise<HaiResult<void>>\n\n /**\n * 获取记忆列表\n *\n * @param options - 列表选项\n * @returns 记忆条目列表\n */\n list: (options?: MemoryListOptions) => Promise<HaiResult<MemoryEntry[]>>\n\n /**\n * 分页获取记忆列表\n *\n * @param options - 分页选项\n * @returns 分页结果\n */\n listPage: (options?: MemoryListPageOptions) => Promise<HaiResult<StorePage<MemoryEntry>>>\n\n /**\n * 清空记忆\n *\n * 同时从 Store 中移除持久化数据。\n *\n * @param options - 清空选项(可按类型/主体过滤)\n */\n clear: (options?: MemoryClearOptions) => Promise<HaiResult<void>>\n}\n","{\n \"$schema\": \"https://inlang.com/schema/inlang-message-format\",\n\n \"ai_notInitialized\": \"AI service not initialized. Call ai.init() first.\",\n \"ai_initFailed\": \"Failed to initialize AI service: {error}\",\n \"ai_initInProgress\": \"AI service initialization is already in progress.\",\n\n \"ai_requestTimeout\": \"Request timeout\",\n \"ai_internalError\": \"Internal error: {error}\",\n\n \"ai_mcpToolNotFound\": \"MCP tool '{name}' not found\",\n \"ai_mcpToolFailed\": \"MCP tool '{name}' execution failed: {error}\",\n \"ai_mcpResourceNotFound\": \"MCP resource '{uri}' not found\",\n \"ai_mcpResourceFailed\": \"MCP resource '{uri}' read failed: {error}\",\n \"ai_mcpPromptNotFound\": \"MCP prompt '{name}' not found\",\n \"ai_mcpPromptMissingArg\": \"MCP prompt '{name}' missing required argument '{arg}'\",\n \"ai_mcpPromptFailed\": \"MCP prompt '{name}' execution failed: {error}\",\n\n \"ai_toolNotFound\": \"Tool '{name}' not found\",\n \"ai_toolInvalidJson\": \"Invalid JSON in tool call arguments\",\n \"ai_configError\": \"AI config validation failed: {error}\",\n\n \"ai_llmRecordFailed\": \"Chat record save failed: {error}\",\n \"ai_llmHistoryFailed\": \"Chat history query failed: {error}\",\n\n \"ai_generateObjectFailed\": \"Structured output parsing failed: {error}\",\n \"ai_generateObjectRepair\": \"The previous output could not be parsed into the required structure ({error}). Output only JSON conforming to the schema, with no extra text.\",\n\n \"ai_embeddingApiFailed\": \"Embedding API call failed: {error}\",\n \"ai_embeddingModelNotFound\": \"Embedding model '{model}' not found\",\n \"ai_embeddingInputTooLong\": \"Embedding input text exceeds maximum length\",\n\n \"ai_reasoningFailed\": \"Reasoning execution failed: {error}\",\n \"ai_reasoningMaxRounds\": \"Reasoning rounds limit reached ({rounds} rounds)\",\n \"ai_reasoningStrategyNotFound\": \"Reasoning strategy '{strategy}' not found\",\n\n \"ai_retrievalFailed\": \"Retrieval execution failed: {error}\",\n \"ai_retrievalSourceNotFound\": \"Retrieval source '{source}' not configured\",\n\n \"ai_ragFailed\": \"RAG execution failed: {error}\",\n \"ai_ragContextBuildFailed\": \"RAG context build failed: {error}\",\n\n \"ai_knowledgeSetupFailed\": \"Knowledge base setup failed: {error}\",\n \"ai_knowledgeIngestFailed\": \"Knowledge ingestion failed: {error}\",\n \"ai_knowledgeRetrieveFailed\": \"Knowledge retrieval failed: {error}\",\n \"ai_knowledgeEntityExtractFailed\": \"Entity extraction failed: {error}\",\n \"ai_knowledgeNotSetup\": \"Knowledge base not initialized. Call ai.knowledge.setup() first.\",\n \"ai_knowledgeCollectionNotFound\": \"Knowledge collection '{collection}' not found\",\n\n \"ai_memoryExtractFailed\": \"Memory extraction failed: {error}\",\n \"ai_memoryStoreFailed\": \"Memory storage failed: {error}\",\n \"ai_memoryRecallFailed\": \"Memory recall failed: {error}\",\n \"ai_memoryNotFound\": \"Memory entry '{id}' not found\",\n \"ai_memoryEnrichFailed\": \"Memory enrichment failed: {error}\",\n \"ai_memoryPromoteFailed\": \"Memory promotion (long-term consolidation) failed: {error}\",\n\n \"ai_personaNotFound\": \"Persona '{id}' not found\",\n \"ai_personaSaveFailed\": \"Persona save failed: {error}\",\n\n \"ai_contextCompressFailed\": \"Context compression failed: {error}\",\n \"ai_contextSummarizeFailed\": \"Context summarization failed: {error}\",\n \"ai_contextTokenEstimateFailed\": \"Token estimation failed: {error}\",\n \"ai_turnNotFound\": \"Conversation turn '{turnId}' not found\",\n \"ai_turnInvalidState\": \"Conversation turn '{turnId}' is already committed\",\n\n \"ai_storeFailed\": \"Store operation failed: {error}\",\n \"ai_storeNotAvailable\": \"Store backend not available, degraded to memory mode\",\n \"ai_sessionNotFound\": \"Session '{id}' not found\",\n \"ai_sessionFailed\": \"Session operation failed: {error}\",\n\n \"ai_rerankApiFailed\": \"Rerank API call failed: {error}\",\n \"ai_rerankInvalidRequest\": \"Invalid rerank request: {reason}\",\n \"ai_fileParseFailed\": \"File parsing failed: {error}\",\n \"ai_fileUnsupportedFormat\": \"Unsupported file format: {mimeType}\",\n \"ai_fileOcrFailed\": \"OCR recognition failed: {error}\",\n \"ai_fileInvalidContent\": \"Invalid file content: {reason}\",\n \"ai_configMissingApiKey\": \"API Key is required for scenario '{scenario}'\",\n\n \"ai_audioNotInitialized\": \"Audio service not initialized. Call ai.init() first.\",\n \"ai_audioInvalidRequest\": \"Invalid audio request: {reason}\",\n \"ai_audioModelNotFound\": \"Audio model '{model}' not found. Register it in audio.models of ai.init().\",\n \"ai_audioMissingApiKey\": \"Audio provider '{provider}' is missing credentials (API Key or App/Access Key).\",\n \"ai_audioUnsupportedInput\": \"Provider '{provider}' does not support this input mode: {reason}\",\n \"ai_audioUpstreamError\": \"Audio upstream service error: {error}\",\n \"ai_audioProtocolError\": \"Audio protocol error: {error}\",\n \"ai_audioConnectionFailed\": \"Audio connection failed: {error}\",\n \"ai_audioTimeout\": \"Audio request timed out\",\n \"ai_audioInputTooLarge\": \"Input audio exceeds size limit ({limit} bytes)\",\n \"ai_audioCancelled\": \"Audio request was cancelled\",\n\n \"ai_a2aNotConfigured\": \"A2A service not configured. Provide 'a2a' config in ai.init().\",\n \"ai_a2aHandleFailed\": \"A2A request handling failed: {error}\",\n \"ai_a2aRemoteCallFailed\": \"A2A remote call to '{url}' failed: {error}\",\n \"ai_a2aAuthFailed\": \"A2A authentication failed: {error}\",\n \"ai_a2aListMessagesFailed\": \"A2A message listing failed: {error}\"\n}\n","{\n \"$schema\": \"https://inlang.com/schema/inlang-message-format\",\n\n \"ai_notInitialized\": \"AI 服务未初始化,请先调用 ai.init()\",\n \"ai_initFailed\": \"AI 服务初始化失败:{error}\",\n \"ai_initInProgress\": \"AI 服务正在初始化中,请勿重复调用。\",\n\n \"ai_requestTimeout\": \"请求超时\",\n \"ai_internalError\": \"内部错误:{error}\",\n\n \"ai_mcpToolNotFound\": \"MCP 工具 '{name}' 未找到\",\n \"ai_mcpToolFailed\": \"MCP 工具 '{name}' 执行失败:{error}\",\n \"ai_mcpResourceNotFound\": \"MCP 资源 '{uri}' 未找到\",\n \"ai_mcpResourceFailed\": \"MCP 资源 '{uri}' 读取失败:{error}\",\n \"ai_mcpPromptNotFound\": \"MCP 提示词 '{name}' 未找到\",\n \"ai_mcpPromptMissingArg\": \"MCP 提示词 '{name}' 缺少必需参数 '{arg}'\",\n \"ai_mcpPromptFailed\": \"MCP 提示词 '{name}' 执行失败:{error}\",\n\n \"ai_toolNotFound\": \"工具 '{name}' 未找到\",\n \"ai_toolInvalidJson\": \"工具调用参数 JSON 格式无效\",\n \"ai_configError\": \"AI 配置校验失败:{error}\",\n\n \"ai_llmRecordFailed\": \"对话记录保存失败:{error}\",\n \"ai_llmHistoryFailed\": \"对话历史查询失败:{error}\",\n\n \"ai_generateObjectFailed\": \"结构化输出解析失败:{error}\",\n \"ai_generateObjectRepair\": \"上一次输出无法解析为要求的结构({error})。请只输出符合 schema 的 JSON,不要包含额外文本。\",\n\n \"ai_embeddingApiFailed\": \"Embedding API 调用失败:{error}\",\n \"ai_embeddingModelNotFound\": \"Embedding 模型 '{model}' 未找到\",\n \"ai_embeddingInputTooLong\": \"Embedding 输入文本超过最大长度限制\",\n\n \"ai_reasoningFailed\": \"推理执行失败:{error}\",\n \"ai_reasoningMaxRounds\": \"推理轮次已达上限({rounds} 轮)\",\n \"ai_reasoningStrategyNotFound\": \"推理策略 '{strategy}' 不存在\",\n\n \"ai_retrievalFailed\": \"检索执行失败:{error}\",\n \"ai_retrievalSourceNotFound\": \"检索源 '{source}' 未配置\",\n\n \"ai_ragFailed\": \"RAG 执行失败:{error}\",\n \"ai_ragContextBuildFailed\": \"RAG 上下文构建失败:{error}\",\n\n \"ai_knowledgeSetupFailed\": \"知识库初始化失败:{error}\",\n \"ai_knowledgeIngestFailed\": \"知识入库失败:{error}\",\n \"ai_knowledgeRetrieveFailed\": \"知识检索失败:{error}\",\n \"ai_knowledgeEntityExtractFailed\": \"实体提取失败:{error}\",\n \"ai_knowledgeNotSetup\": \"知识库未初始化,请先调用 ai.knowledge.setup()\",\n \"ai_knowledgeCollectionNotFound\": \"知识集合 '{collection}' 不存在\",\n\n \"ai_memoryExtractFailed\": \"记忆提取失败:{error}\",\n \"ai_memoryStoreFailed\": \"记忆存储失败:{error}\",\n \"ai_memoryRecallFailed\": \"记忆召回失败:{error}\",\n \"ai_memoryNotFound\": \"记忆条目 '{id}' 不存在\",\n \"ai_memoryEnrichFailed\": \"记忆注入失败:{error}\",\n \"ai_memoryPromoteFailed\": \"记忆固化(长期化)失败:{error}\",\n\n \"ai_personaNotFound\": \"角色 '{id}' 不存在\",\n \"ai_personaSaveFailed\": \"角色保存失败:{error}\",\n\n \"ai_contextCompressFailed\": \"上下文压缩失败:{error}\",\n \"ai_contextSummarizeFailed\": \"上下文总结失败:{error}\",\n \"ai_contextTokenEstimateFailed\": \"Token 估算失败:{error}\",\n \"ai_turnNotFound\": \"对话轮次 '{turnId}' 不存在\",\n \"ai_turnInvalidState\": \"对话轮次 '{turnId}' 已提交,无法重复提交\",\n\n \"ai_storeFailed\": \"存储操作失败:{error}\",\n \"ai_storeNotAvailable\": \"存储后端不可用,已降级为内存模式\",\n \"ai_sessionNotFound\": \"会话 '{id}' 不存在\",\n \"ai_sessionFailed\": \"会话操作失败:{error}\",\n\n \"ai_rerankApiFailed\": \"Rerank API 调用失败:{error}\",\n \"ai_rerankInvalidRequest\": \"Rerank 请求参数无效:{reason}\",\n \"ai_fileParseFailed\": \"文件解析失败:{error}\",\n \"ai_fileUnsupportedFormat\": \"不支持的文件格式:{mimeType}\",\n \"ai_fileOcrFailed\": \"OCR 识别失败:{error}\",\n \"ai_fileInvalidContent\": \"文件内容无效:{reason}\",\n \"ai_configMissingApiKey\": \"场景 '{scenario}' 需要提供 API Key\",\n\n \"ai_audioNotInitialized\": \"Audio 服务未初始化,请先调用 ai.init()\",\n \"ai_audioInvalidRequest\": \"语音请求参数无效:{reason}\",\n \"ai_audioModelNotFound\": \"语音模型 '{model}' 未找到,请在 ai.init() 的 audio.models 中注册\",\n \"ai_audioMissingApiKey\": \"语音平台 '{provider}' 缺少凭据(API Key 或 App/Access Key)\",\n \"ai_audioUnsupportedInput\": \"平台 '{provider}' 不支持此输入方式:{reason}\",\n \"ai_audioUpstreamError\": \"语音上游服务错误:{error}\",\n \"ai_audioProtocolError\": \"语音协议错误:{error}\",\n \"ai_audioConnectionFailed\": \"语音连接失败:{error}\",\n \"ai_audioTimeout\": \"语音请求超时\",\n \"ai_audioInputTooLarge\": \"输入音频超过大小上限({limit} 字节)\",\n \"ai_audioCancelled\": \"语音请求已取消\",\n\n \"ai_a2aNotConfigured\": \"A2A 服务未配置,请在 ai.init() 中提供 'a2a' 配置。\",\n \"ai_a2aHandleFailed\": \"A2A 请求处理失败:{error}\",\n \"ai_a2aRemoteCallFailed\": \"A2A 远端调用 '{url}' 失败:{error}\",\n \"ai_a2aAuthFailed\": \"A2A 认证失败:{error}\",\n \"ai_a2aListMessagesFailed\": \"A2A 消息查询失败:{error}\"\n}\n","/**\n * @h-ai/ai — i18n 消息获取器\n *\n * 模块内部使用,不对外导出。\n *\n * @internal\n * @module ai-i18n\n */\n\nimport { core } from '@h-ai/core'\nimport messagesEnUS from '../messages/en-US.json'\nimport messagesZhCN from '../messages/zh-CN.json'\n\ntype AiMessageKey = keyof typeof messagesZhCN\n\n/**\n * 获取 AI 模块本地化文案\n *\n * @internal\n */\nexport const aiM = core.i18n.createMessageGetter<AiMessageKey>({\n 'zh-CN': messagesZhCN,\n 'en-US': messagesEnUS,\n})\n","/**\n * @h-ai/ai — 错误码 + 配置 Schema\n *\n * 定义 AI 模块的错误码常量、Zod Schema 和配置类型。\n * @module ai-config\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport process from 'node:process'\nimport { err, ok } from '@h-ai/core'\nimport { ChunkOptionsSchema, CleanOptionsSchema } from '@h-ai/datapipe'\nimport { z } from 'zod'\nimport { aiM } from './ai-i18n.js'\n\nimport { HaiAIError } from './ai-types.js'\nimport { CompressionStrategySchema } from './compress/ai-compress-types.js'\n\n// ─── LLM 配置 Schema ───\n\n// ─── 多模型配置 ───\n\n/**\n * 模型场景枚举\n *\n * 预定义的模型使用场景,用于自动选择合适的模型。\n *\n * - `default` — 默认场景(兜底)\n * - `chat` — 对话场景\n * - `reasoning` — 推理场景(ReAct、CoT,需要强逻辑能力)\n * - `plan` — Plan-Execute 规划阶段(需要强推理)\n * - `execute` — Plan-Execute 执行阶段(需要工具调用能力)\n * - `extraction` — 信息提取场景(记忆提取、实体抽取)\n * - `summary` — 摘要/压缩场景(上下文摘要)\n * - `embedding` — 向量嵌入场景\n * - `rerank` — 文档重排序场景\n * - `ocr` — 图片 OCR 识别场景(视觉模型)\n * - `fast` — 快速响应场景(低延迟优先)\n */\nexport const ModelScenarioSchema = z.enum(['default', 'chat', 'reasoning', 'plan', 'execute', 'extraction', 'summary', 'embedding', 'rerank', 'ocr', 'fast'])\n\n/** 模型场景类型 */\nexport type ModelScenario = z.infer<typeof ModelScenarioSchema>\n\n/**\n * LLM API 协议枚举\n *\n * 决定底层通过哪种 API 协议与模型交互(对使用方透明,公共请求/响应形状保持一致):\n *\n * - `chat` — OpenAI Chat Completions API(`/v1/chat/completions`,默认,兼容绝大多数厂商)\n * - `responses` — OpenAI Responses API(`/v1/responses`,新一代有状态接口)\n * - `anthropic` — Anthropic Messages API(Claude 原生协议,需安装 `@anthropic-ai/sdk`)\n */\nexport const ApiTypeSchema = z.enum(['chat', 'responses', 'anthropic'])\n\n/** LLM API 协议类型 */\nexport type ApiType = z.infer<typeof ApiTypeSchema>\n\n/**\n * 模型条目 Schema\n *\n * 定义单个模型的配置信息,包含唯一 ID、模型名称和可选参数覆盖。\n *\n * @example\n * ```ts\n * const model = {\n * id: 'gpt-4o',\n * model: 'gpt-4o',\n * maxTokens: 8192,\n * temperature: 0.3,\n * }\n * ```\n */\nexport const ModelEntrySchema = z.object({\n /** 模型唯一标识(用于 ModelResolver 解析) */\n id: z.string(),\n /** 模型名称(传给 API 的实际模型名) */\n model: z.string(),\n /** API 协议(可选,未指定时回退全局 `api`,再回退 `chat`;决定走 Chat Completions / Responses / Anthropic) */\n api: ApiTypeSchema.optional(),\n /** API Key 覆盖(可选,未提供时使用全局配置) */\n apiKey: z.string().optional(),\n /** Base URL 覆盖(可选) */\n baseUrl: z.url().optional(),\n /** 最大 Token 数覆盖(可选) */\n maxTokens: z.number().positive().optional(),\n /** 温度覆盖(可选) */\n temperature: z.number().min(0).max(2).optional(),\n /** 超时覆盖(可选,毫秒) */\n timeout: z.number().positive().optional(),\n})\n\n/** 模型条目类型 */\nexport type ModelEntry = z.infer<typeof ModelEntrySchema>\n\n/**\n * LLM 配置 Schema\n *\n * 配置大模型调用参数:模型名称、API Key、Base URL、温度等。\n * 支持多模型注册和场景映射。\n *\n * 顶层 `apiKey`、`baseUrl`、`maxTokens`、`temperature`、`timeout` 作为全局默认值,\n * 当 `models` 条目中未指定对应字段时,自动回退到这些全局默认值。\n * 通过 `resolveModelEntry()` 统一解析。\n *\n * @example\n * ```ts\n * const llmConfig = {\n * // 全局默认值(各模型未指定时回退到此处)\n * apiKey: 'sk-xxx',\n * baseUrl: 'https://api.openai.com/v1',\n * model: 'gpt-4o-mini',\n * maxTokens: 4096,\n * temperature: 0.7,\n * timeout: 60000,\n * // 多模型注册(各字段可选,未指定时回退到全局默认值)\n * models: [\n * { id: 'fast', model: 'gpt-4o-mini', temperature: 0.3 },\n * { id: 'strong', model: 'gpt-4o', maxTokens: 8192 },\n * { id: 'rerank', model: 'rerank-english-v3.0', baseUrl: 'https://api.cohere.com' },\n * ],\n * // 场景映射(场景名 → 模型 ID 或模型名称)\n * scenarios: { chat: 'fast', reasoning: 'strong', rerank: 'rerank' },\n * }\n * ```\n */\nexport const LLMConfigSchema = z.object({\n /** 全局 API Key(各模型 fallback;未提供时回退到 `process.env.HAI_AI_LLM_API_KEY` 或 `process.env.OPENAI_API_KEY`) */\n apiKey: z.string().optional(),\n /** 全局 API 基础 URL(各模型 fallback;未提供时回退到 `process.env.HAI_AI_LLM_BASE_URL` 或 `process.env.OPENAI_BASE_URL`) */\n baseUrl: z.url().optional(),\n /** 默认模型名称(默认 `'gpt-4o-mini'`) */\n model: z.string().optional().default('gpt-4o-mini'),\n /** 全局 API 协议(各模型 fallback,默认 `'chat'`;可选 `chat` / `responses` / `anthropic`) */\n api: ApiTypeSchema.optional().default('chat'),\n /** 全局最大 Token 数(各模型 fallback,默认 `4096`) */\n maxTokens: z.number().positive().optional().default(4096),\n /** 全局采样温度(各模型 fallback,范围 `[0, 2]`,默认 `0.7`) */\n temperature: z.number().min(0).max(2).optional().default(0.7),\n /** 全局请求超时时间(各模型 fallback,毫秒,默认 `60000`) */\n timeout: z.number().positive().optional().default(60000),\n /** 临时模型客户端缓存存活时间(毫秒,默认 `600000` = 10 分钟;超时后临时模型客户端实例失效并重建) */\n tempModelCacheTtl: z.number().positive().optional().default(600000),\n /** 多模型配置列表(各字段可选,未指定时回退到全局默认值) */\n models: z.array(ModelEntrySchema).optional(),\n /** 场景模型映射(场景名 → 模型 ID 或直接模型名称,各场景均可选) */\n scenarios: z.object(Object.fromEntries(ModelScenarioSchema.options.map(k => [k, z.string().optional()])) as Record<ModelScenario, z.ZodOptional<z.ZodString>>).optional(),\n})\n\n/** LLM 配置类型 */\nexport type LLMConfig = z.infer<typeof LLMConfigSchema>\n\n/**\n * 已解析的模型配置\n *\n * 由 `resolveModelEntry()` 返回,包含模型名称和完整的参数配置(已合并全局默认值和环境变量)。\n */\nexport interface ResolvedModelConfig {\n /** 模型名称(传给 API 的实际模型名) */\n model: string\n /** API 协议(模型条目 > 全局配置 > `chat`) */\n api: ApiType\n /** API Key(模型条目 > 全局配置 > 环境变量) */\n apiKey: string | undefined\n /** API 基础 URL(模型条目 > 全局配置 > 环境变量 > 默认 OpenAI) */\n baseUrl: string\n /** 最大 Token 数(模型条目 > 全局配置) */\n maxTokens: number\n /** 采样温度(模型条目 > 全局配置) */\n temperature: number\n /** 请求超时时间(毫秒)(模型条目 > 全局配置) */\n timeout: number\n}\n\n/**\n * 必需模型解析选项\n */\nexport interface ResolveRequiredModelEntryOptions {\n /** 缺少 API Key 时的自定义错误消息 */\n missingApiKeyMessage?: string\n}\n\n/**\n * 根据场景解析完整模型配置,并要求必须存在 API Key\n *\n * 用于需要访问远程模型 API 的场景,避免各子模块重复编写\n * `if (!resolved.apiKey)` 之类的配置校验逻辑。\n *\n * @param llmConfig - LLM 配置\n * @param scenario - 使用场景\n * @param explicit - 调用方显式指定的模型名称(最高优先级)\n * @param options - 必需校验选项\n * @returns 成功返回已解析模型配置,失败返回 `CONFIGURATION_ERROR`\n */\nexport function resolveModelEntry(\n llmConfig: LLMConfig,\n scenario: ModelScenario,\n explicit?: string,\n options?: ResolveRequiredModelEntryOptions,\n): HaiResult<ResolvedModelConfig> {\n let entry: ModelEntry | undefined\n let modelName: string\n\n if (explicit) {\n // 显式指定的模型名,尝试匹配 models 条目\n entry = llmConfig.models?.find(m => m.id === explicit || m.model === explicit)\n modelName = entry?.model ?? explicit\n }\n else {\n // 从场景映射查找\n const modelId = llmConfig.scenarios?.[scenario] ?? llmConfig.scenarios?.default\n if (modelId) {\n entry = llmConfig.models?.find(m => m.id === modelId)\n modelName = entry?.model ?? modelId\n }\n else {\n modelName = llmConfig.model ?? 'gpt-4o-mini'\n }\n }\n\n const resolved: ResolvedModelConfig = {\n model: modelName,\n api: entry?.api ?? llmConfig.api ?? 'chat',\n apiKey: entry?.apiKey ?? llmConfig.apiKey ?? process.env.HAI_AI_LLM_API_KEY ?? process.env.OPENAI_API_KEY,\n baseUrl: entry?.baseUrl ?? llmConfig.baseUrl ?? process.env.HAI_AI_LLM_BASE_URL ?? process.env.OPENAI_BASE_URL ?? 'https://api.openai.com/v1',\n maxTokens: entry?.maxTokens ?? llmConfig.maxTokens ?? 4096,\n temperature: entry?.temperature ?? llmConfig.temperature ?? 0.7,\n timeout: entry?.timeout ?? llmConfig.timeout ?? 60000,\n }\n\n if (!resolved.apiKey) {\n return err(HaiAIError.CONFIGURATION_ERROR, options?.missingApiKeyMessage ?? aiM('ai_configMissingApiKey', { params: { scenario } }))\n }\n\n return ok(resolved)\n}\n\n/**\n * 解析某次 chat 请求应使用的 API 协议(不校验 API Key)\n *\n * 供 LLM Provider 路由层选择底层实现使用:优先取显式模型条目的 `api`,\n * 其次全局 `api`,最后回退 `chat`。临时模型的 `api` 由调用方单独传入优先。\n *\n * @param llmConfig - LLM 配置\n * @param explicitModel - 显式指定的模型名/ID(可选)\n * @param tempApi - 临时模型显式指定的 API 协议(可选,最高优先级)\n * @returns 解析出的 API 协议\n */\nexport function resolveModelApi(llmConfig: LLMConfig, explicitModel?: string, tempApi?: ApiType): ApiType {\n if (tempApi)\n return tempApi\n const entry = explicitModel\n ? llmConfig.models?.find(m => m.id === explicitModel || m.model === explicitModel)\n : undefined\n return entry?.api ?? llmConfig.api ?? 'chat'\n}\n\n// ─── MCP 配置 Schema ───\n\n/** MCP 服务器能力 Schema */\nexport const MCPServerCapabilitiesSchema = z.object({\n /** 是否支持工具调用(默认 `true`) */\n tools: z.boolean().optional().default(true),\n /** 是否支持资源访问(默认 `true`) */\n resources: z.boolean().optional().default(true),\n /** 是否支持提示词模板(默认 `true`) */\n prompts: z.boolean().optional().default(true),\n})\n\n/** MCP 服务器能力类型 */\nexport type MCPServerCapabilities = z.infer<typeof MCPServerCapabilitiesSchema>\n\n/** MCP 服务器配置 Schema */\nexport const MCPServerConfigSchema = z.object({\n /** 服务器名称 */\n name: z.string(),\n /** 服务器版本(默认 `'1.0.0'`) */\n version: z.string().optional().default('1.0.0'),\n /** 服务器能力声明 */\n capabilities: MCPServerCapabilitiesSchema.optional(),\n})\n\n/** MCP 服务器配置类型 */\nexport type MCPServerConfig = z.infer<typeof MCPServerConfigSchema>\n\n/**\n * MCP 配置 Schema\n *\n * 配置 MCP(Model Context Protocol)服务器参数。\n *\n * @example\n * ```ts\n * const mcpConfig = {\n * server: {\n * name: 'my-app',\n * version: '1.0.0',\n * capabilities: { tools: true, resources: true, prompts: true },\n * },\n * }\n * ```\n */\nexport const MCPConfigSchema = z.object({\n /** 服务器配置 */\n server: MCPServerConfigSchema.optional(),\n})\n\n/** MCP 配置类型 */\nexport type MCPConfig = z.infer<typeof MCPConfigSchema>\n\n// ─── 统一 AI 配置 ───\n\n/**\n * Embedding 配置 Schema\n *\n * 配置文本向量化参数。\n * 模型通过 LLMConfigSchema.scenarios.embedding 解析,\n * apiKey / baseUrl 统一使用 LLM 配置。\n *\n * @example\n * ```ts\n * const embeddingConfig = {\n * dimensions: 1536,\n * batchSize: 100,\n * }\n * ```\n */\nexport const EmbeddingConfigSchema = z.object({\n /** 向量维度(可选,部分模型支持指定维度) */\n dimensions: z.number().int().positive().optional(),\n /** 批量大小(单次请求最多处理的文本数,默认 100) */\n batchSize: z.number().int().positive().default(100),\n})\n\n/** Embedding 配置类型 */\nexport type EmbeddingConfig = z.infer<typeof EmbeddingConfigSchema>\n\n// ─── Knowledge 配置 Schema ───\n\nexport { CompressionStrategySchema } from './compress/ai-compress-types.js'\nexport type { CompressionStrategy } from './compress/ai-compress-types.js'\n\n/**\n * Knowledge 配置 Schema\n *\n * 配置知识库管理参数:向量集合、分块策略、实体提取等。\n * 模型通过 LLMConfigSchema.scenarios 解析,\n * apiKey / baseUrl 统一使用 LLM 配置。\n *\n * @example\n * ```ts\n * const knowledgeConfig = {\n * collection: 'my-knowledge',\n * dimension: 1536,\n * enableEntityExtraction: true\n * }\n * ```\n */\nexport const KnowledgeConfigSchema = z.object({\n /** 默认向量集合名(默认 'hai_ai_knowledge') */\n collection: z.string().default('hai_ai_knowledge'),\n /** 向量维度(默认 1536,需与 embedding 模型匹配) */\n dimension: z.number().int().positive().default(1536),\n /** 是否启用实体提取(默认 true) */\n enableEntityExtraction: z.boolean().default(true),\n /**\n * 默认文本清洗选项\n *\n * 字段含义与 @h-ai/datapipe CleanOptionsInput 完全一致,\n * 支持 removeHtml、removeUrls、normalizeWhitespace、customReplacements 等。\n */\n cleanOptions: CleanOptionsSchema.default(CleanOptionsSchema.parse({})),\n /**\n * 默认分块选项\n *\n * 字段含义与 @h-ai/datapipe ChunkOptionsInput 完全一致,\n * 支持 mode、maxSize、overlap、separator、markdownMinLevel 等完整选项。\n */\n chunkOptions: ChunkOptionsSchema.default(ChunkOptionsSchema.parse({\n mode: 'markdown',\n maxSize: 1500,\n overlap: 200,\n })),\n /** 实体查询命中的额外加权系数(默认 0.15,叠加到向量分数上) */\n entityBoostWeight: z.number().min(0).max(1).default(0.15),\n /** 自定义实体类型列表(不指定时使用内置默认类型) */\n entityTypes: z.array(z.string()).optional(),\n /** 自定义实体提取系统提示词(不指定时使用内置默认提示词) */\n systemPrompt: z.string().optional(),\n})\n\n/** Knowledge 配置类型 */\nexport type KnowledgeConfig = z.infer<typeof KnowledgeConfigSchema>\n\n// ─── Memory 配置 Schema ───\n\n// EntityTypeSchema / EntityType 定义在 knowledge/ai-knowledge-types.ts 中\nexport { EntityTypeSchema } from './knowledge/ai-knowledge-types.js'\nexport type { EntityType } from './knowledge/ai-knowledge-types.js'\n\n/**\n * Memory 配置 Schema\n *\n * 配置对话记忆的提取、存储与检索参数。两种 provider 均为嵌入式,复用同一套\n * vecdb / reldb / LLM / Embedding;模型通过 LLMConfigSchema.scenarios.extraction\n * 解析,apiKey / baseUrl 统一使用 LLM 配置。\n *\n * @example\n * ```ts\n * const memoryConfig = {\n * provider: 'native',\n * maxEntriesPerObject: 1000,\n * maxEntriesGlobal: 100000,\n * embeddingEnabled: true,\n * recencyDecay: 0.95,\n * defaultTopK: 10,\n * }\n * ```\n */\nexport const MemoryConfigSchema = z.object({\n /** 记忆后端:native = 逐条写回;mem0 = 批量 ADD/UPDATE/DELETE 合并(均为嵌入式,复用 HAI 组件) */\n provider: z.enum(['native', 'mem0']).default('native'),\n /**\n * 单个主体(objectId)的最大记忆条数(默认 1000)\n *\n * native 淘汰按 objectId 分区触发:某个主体写入超过此上限时,只淘汰该主体自身\n * 最低优先级的条目,不会波及其他主体的记忆。\n */\n maxEntriesPerObject: z.number().int().positive().default(1000),\n /**\n * 全局最大记忆条数(默认 100000)\n *\n * 跨所有主体的总量上限,作为整体保护阈值;超过时淘汰全局最低优先级条目。\n */\n maxEntriesGlobal: z.number().int().positive().default(100000),\n /** 自定义记忆提取 systemPrompt(可选,覆盖内置默认提示词) */\n systemPrompt: z.string().optional(),\n /** 时间衰减系数(默认 0.95,每次检索乘以此系数调整 recency 权重) */\n recencyDecay: z.number().min(0).max(1).default(0.95),\n /** 是否启用向量检索(默认 true,关闭则仅使用关键词匹配) */\n embeddingEnabled: z.boolean().default(true),\n /** 检索时默认返回数量(默认 10) */\n defaultTopK: z.number().int().positive().default(10),\n /**\n * 候选池倍数(默认 5)\n *\n * 检索时先从向量后端取回 `topK × candidateMultiplier` 条候选,再按 scope / 重要性等\n * 条件在内存中过滤,最后截取 topK。用于修正「向量后端仅返回 topK,随后被 scope 过滤\n * 掉大部分、导致同一主体下特定主题/角色记忆漏召回」的问题:候选池越大,scope 命中越充分。\n *\n * native provider 会对全部候选评分,故此值仅影响向量预取宽度;mem0 provider 无法下推\n * scope,必须依赖更大的候选池才能保证 scope 内记忆被召回。\n */\n candidateMultiplier: z.number().int().positive().default(5),\n /** 写回 / 合并时检索相关记忆的数量(native 与 mem0 共用,默认 20) */\n writebackRelatedTopK: z.number().int().positive().default(20),\n})\n\n/** Memory 配置类型 */\nexport type MemoryConfig = z.infer<typeof MemoryConfigSchema>\n// MemoryTypeSchema / MemoryType 定义在 memory/ai-memory-types.ts 中\nexport { MemoryTypeSchema } from './memory/ai-memory-types.js'\nexport type { MemoryType } from './memory/ai-memory-types.js'\n\n/**\n * Token 配置 Schema\n *\n * 配置 Token 估算参数。\n *\n * @example\n * ```ts\n * const tokenConfig = { tokenRatio: 0.25 }\n * ```\n */\nexport const TokenConfigSchema = z.object({\n /** Token 估算每字符系数(默认 0.25,即 4 字符 ≈ 1 token) */\n tokenRatio: z.number().positive().default(0.25),\n})\n\n/** Token 配置类型 */\nexport type TokenConfig = z.infer<typeof TokenConfigSchema>\n\n/**\n * Summary 配置 Schema\n *\n * 配置摘要生成参数。\n * 模型通过 LLMConfigSchema.scenarios.summary 解析,\n * apiKey / baseUrl 统一使用 LLM 配置。\n *\n * @example\n * ```ts\n * const summaryConfig = { systemPrompt: 'You are a summarizer.' }\n * ```\n */\nexport const SummaryConfigSchema = z.object({\n /** 自定义摘要 systemPrompt(可选,覆盖内置默认提示词) */\n systemPrompt: z.string().optional(),\n})\n\n/** Summary 配置类型 */\nexport type SummaryConfig = z.infer<typeof SummaryConfigSchema>\n\n/**\n * Compress 配置 Schema\n *\n * 配置上下文压缩参数:压缩策略、Token 预算、保留消息数。\n *\n * @example\n * ```ts\n * const compressConfig = {\n * defaultStrategy: 'hybrid',\n * defaultMaxTokens: 4000,\n * preserveLastN: 4,\n * }\n * ```\n */\nexport const CompressConfigSchema = z.object({\n /** 默认压缩策略(默认 'hybrid') */\n defaultStrategy: CompressionStrategySchema.default('hybrid'),\n /** 默认 Token 预算(默认 0 表示取模型上限的 80%) */\n defaultMaxTokens: z.number().int().min(0).default(0),\n /** 默认保留最近消息数(默认 4) */\n preserveLastN: z.number().int().min(0).default(4),\n})\n\n/** Compress 配置类型 */\nexport type CompressConfig = z.infer<typeof CompressConfigSchema>\n\n// ─── File 配置 Schema ───\n\n/**\n * File 配置 Schema\n *\n * 配置文件解析参数:OCR 提示词。\n * OCR 使用的视觉模型通过 `llm.scenarios.ocr` 指定。\n */\nexport const FileConfigSchema = z.object({\n /** OCR 系统提示词(可选,覆盖内置默认提示词) */\n systemPrompt: z.string().optional(),\n})\n\n/** File 配置类型 */\nexport type FileConfig = z.infer<typeof FileConfigSchema>\n\n// ─── Retrieval 配置 Schema ───\n\n/**\n * 检索源配置 Schema\n *\n * 与 `RetrievalSource` 接口字段对齐,支持在 `ai.init()` 中预注册检索源。\n */\nexport const RetrievalSourceSchema = z.object({\n /** 来源唯一标识 */\n id: z.string(),\n /** vecdb collection 名称 */\n collection: z.string(),\n /** 信源显示名 */\n name: z.string().optional(),\n /** 信源 URL / 路径 */\n url: z.string().optional(),\n /** 最大返回条数(默认 5) */\n topK: z.number().int().positive().optional(),\n /** 最低相似度 0~1(低于此值的结果被过滤) */\n minScore: z.number().min(0).max(1).optional(),\n /** 元数据过滤条件 */\n filter: z.record(z.string(), z.unknown()).optional(),\n})\n\n/** 检索源配置类型 */\nexport type RetrievalSourceConfig = z.infer<typeof RetrievalSourceSchema>\n\n/**\n * Retrieval 配置 Schema\n *\n * 在 `ai.init()` 时预注册检索源,等价于初始化后逐条调用 `ai.retrieval.addSource()`。\n *\n * @example\n * ```ts\n * ai.init({\n * llm: { apiKey: 'sk-xxx', model: 'gpt-4o-mini' },\n * retrieval: {\n * sources: [\n * { id: 'docs', collection: 'documentation', name: '产品文档', topK: 5, minScore: 0.7 },\n * { id: 'faq', collection: 'faq', name: '常见问题' },\n * ],\n * },\n * })\n * ```\n */\nexport const RetrievalConfigSchema = z.object({\n /** 预注册检索源列表 */\n sources: z.array(RetrievalSourceSchema).optional(),\n})\n\n/** Retrieval 配置类型 */\nexport type RetrievalConfig = z.infer<typeof RetrievalConfigSchema>\n\n// ─── A2A 配置 Schema ───\n\n/** A2A Agent Skill 配置 Schema */\nexport const A2ASkillConfigSchema = z.object({\n /** 技能 ID */\n id: z.string(),\n /** 技能名称 */\n name: z.string(),\n /** 技能描述 */\n description: z.string().optional(),\n /** 标签列表 */\n tags: z.array(z.string()).optional(),\n})\n\n/**\n * A2A 配置 Schema\n *\n * 配置 Agent-to-Agent 协议参数:Agent Card、认证等。\n *\n * @example\n * ```ts\n * ai.init({\n * llm: { apiKey: 'sk-xxx', model: 'gpt-4o-mini' },\n * a2a: {\n * agentCard: {\n * name: 'my-agent',\n * description: 'An example agent',\n * url: 'https://example.com',\n * skills: [{ id: 'chat', name: 'General Chat' }],\n * },\n * },\n * })\n * ```\n */\nexport const A2AConfigSchema = z.object({\n /** Agent Card 配置 */\n agentCard: z.object({\n /** Agent 名称 */\n name: z.string(),\n /** Agent 描述 */\n description: z.string().optional(),\n /** Agent 对外 URL */\n url: z.string(),\n /** Agent 版本 */\n version: z.string().optional(),\n /** Agent 技能列表 */\n skills: z.array(A2ASkillConfigSchema).optional(),\n }),\n /** A2A 安全认证配置 */\n security: z.object({\n /** API Key 认证(通过 IAM apiKey.verifyApiKey 验证) */\n apiKey: z.object({\n /** API Key 的传递位置(默认 header) */\n in: z.enum(['header', 'query']).default('header'),\n /** 参数名(默认 x-api-key) */\n name: z.string().default('x-api-key'),\n }).optional(),\n }).optional(),\n})\n\n/** A2A 配置类型 */\nexport type A2AConfig = z.infer<typeof A2AConfigSchema>\n\n// ─── Audio 配置 Schema ───\n\n/**\n * 语音平台枚举\n *\n * 决定 `ai.audio` 底层调用哪个厂商(对使用方透明,公共请求/响应形状保持一致):\n *\n * - `openai` — OpenAI Audio API(transcriptions / speech)\n * - `mimo` — 小米 MiMo(Chat Completions 风格 ASR / TTS)\n * - `qwen` — 阿里云百炼 Qwen Realtime(DashScope WebSocket ASR / TTS)\n * - `doubao` — 火山引擎豆包语音(二进制 WebSocket ASR / TTS)\n */\nexport const AudioProviderSchema = z.enum(['openai', 'mimo', 'qwen', 'doubao'])\n\n/** 语音平台类型 */\nexport type AudioProviderName = z.infer<typeof AudioProviderSchema>\n\n/**\n * 语音模型条目 Schema\n *\n * 定义单个语音模型:唯一 ID、所属平台、厂商模型名及凭据。凭据未提供时回退到对应平台的环境变量。\n *\n * @example\n * ```ts\n * const model = { id: 'asr', provider: 'qwen', model: 'qwen3-asr-flash-realtime', operations: ['transcribe'] }\n * ```\n */\nexport const AudioModelEntrySchema = z.object({\n /** 模型唯一标识(用于场景解析与请求显式指定) */\n id: z.string(),\n /** 所属语音平台 */\n provider: AudioProviderSchema,\n /** 厂商模型名(传给厂商 API 的实际模型名) */\n model: z.string(),\n /** 模型允许执行的操作;解析模型时会在调用厂商前校验 */\n operations: z.union([\n z.tuple([z.literal('transcribe')]),\n z.tuple([z.literal('synthesize')]),\n z.tuple([z.literal('transcribe'), z.literal('synthesize')]),\n ]),\n /** API Key 覆盖(未提供时回退对应平台环境变量) */\n apiKey: z.string().optional(),\n /** HTTP / WebSocket 端点覆盖(未提供时使用平台默认端点) */\n baseUrl: z.string().optional(),\n /** 火山引擎 App Key(`X-Api-App-Key`,旧版控制台 ASR 需要) */\n appKey: z.string().optional(),\n /** 火山引擎 Access Key(`X-Api-Access-Key`,旧版控制台 ASR 需要) */\n accessKey: z.string().optional(),\n /** 火山引擎资源 ID(`X-Api-Resource-Id`;未提供时使用平台默认资源 ID) */\n resourceId: z.string().optional(),\n /** 阿里云百炼业务空间 ID(`X-DashScope-WorkSpace`,可选) */\n workspaceId: z.string().optional(),\n /** 请求超时(毫秒,默认 60000) */\n timeout: z.number().positive().optional(),\n})\n\n/** 语音模型条目类型 */\nexport type AudioModelEntry = z.infer<typeof AudioModelEntrySchema>\n\n/**\n * Audio 配置 Schema\n *\n * 注册语音模型并映射默认识别 / 合成模型。调用方通常无需指定模型,仅在临时切换时通过 `request.model` 覆盖。\n *\n * @example\n * ```ts\n * ai.init({\n * audio: {\n * models: [\n * { id: 'asr', provider: 'qwen', model: 'qwen3-asr-flash-realtime', operations: ['transcribe'] },\n * { id: 'tts', provider: 'qwen', model: 'qwen3-tts-flash-realtime', operations: ['synthesize'] },\n * ],\n * transcribeModel: 'asr',\n * synthesizeModel: 'tts',\n * },\n * })\n * ```\n */\nexport const AudioConfigSchema = z.object({\n /** 注册的语音模型列表 */\n models: z.array(AudioModelEntrySchema).optional(),\n /** 默认识别模型 ID(`ai.audio.transcribe*` 未指定 model 时使用) */\n transcribeModel: z.string().optional(),\n /** 默认合成模型 ID(`ai.audio.synthesize*` 未指定 model 时使用) */\n synthesizeModel: z.string().optional(),\n /** 单次音频字节上限(默认 10 MiB,防止资源耗尽) */\n maxAudioBytes: z.number().int().positive().default(10 * 1024 * 1024),\n /** 实时连接最长持续时间(毫秒,默认 5 分钟) */\n maxStreamDurationMs: z.number().int().positive().default(5 * 60 * 1000),\n})\n\n/** Audio 配置类型 */\nexport type AudioConfig = z.infer<typeof AudioConfigSchema>\n\n/**\n * 已解析的语音模型配置\n *\n * 由 `resolveAudioModel()` 返回,凭据已合并环境变量、端点已应用平台默认值。\n */\nexport interface ResolvedAudioModel {\n /** 模型条目 ID */\n id: string\n /** 所属平台 */\n provider: AudioProviderName\n /** 厂商模型名 */\n model: string\n /** API Key(条目 > 平台环境变量) */\n apiKey: string | undefined\n /** 端点(条目 > 平台默认) */\n baseUrl: string\n /** 火山引擎 App Key */\n appKey: string | undefined\n /** 火山引擎 Access Key */\n accessKey: string | undefined\n /** 火山引擎资源 ID(条目 > 平台默认) */\n resourceId: string\n /** 阿里云百炼业务空间 ID */\n workspaceId: string | undefined\n /** 请求超时(毫秒) */\n timeout: number\n}\n\n/** 各平台默认端点 */\nconst AUDIO_PROVIDER_DEFAULT_BASE_URL: Record<AudioProviderName, string> = {\n openai: 'https://api.openai.com/v1',\n mimo: 'https://api.xiaomimimo.com/v1',\n qwen: 'wss://dashscope.aliyuncs.com/api-ws/v1/realtime',\n doubao: 'wss://openspeech.bytedance.com',\n}\n\n/** 火山引擎默认资源 ID(按操作类型区分 ASR / TTS) */\nfunction doubaoDefaultResourceId(operation: 'transcribe' | 'synthesize'): string {\n return operation === 'transcribe' ? 'volc.bigasr.sauc.duration' : 'seed-tts-2.0'\n}\n\n/** 读取指定平台的 API Key 环境变量(凭据未在配置中提供时的回退) */\nfunction audioProviderEnvApiKey(provider: AudioProviderName): string | undefined {\n switch (provider) {\n case 'openai':\n return process.env.HAI_AI_AUDIO_OPENAI_API_KEY ?? process.env.OPENAI_API_KEY\n case 'mimo':\n return process.env.HAI_AI_AUDIO_MIMO_API_KEY ?? process.env.MIMO_API_KEY\n case 'qwen':\n return process.env.HAI_AI_AUDIO_QWEN_API_KEY ?? process.env.DASHSCOPE_API_KEY\n case 'doubao':\n return process.env.HAI_AI_AUDIO_DOUBAO_API_KEY ?? process.env.VOLC_API_KEY\n }\n}\n\n/**\n * 解析语音操作应使用的模型配置\n *\n * 解析优先级:请求显式 `model` > 场景默认(transcribe/synthesize);凭据回退到平台环境变量。\n *\n * @param audioConfig - Audio 配置\n * @param operation - 操作类型(识别 / 合成),决定使用哪个默认模型\n * @param explicit - 请求显式指定的模型 ID(最高优先级)\n * @returns 成功返回已解析模型;无匹配模型返回 `AUDIO_MODEL_NOT_FOUND`;缺少凭据返回 `CONFIGURATION_ERROR`\n */\nexport function resolveAudioModel(\n audioConfig: AudioConfig,\n operation: 'transcribe' | 'synthesize',\n explicit?: string,\n): HaiResult<ResolvedAudioModel> {\n const targetId = explicit ?? (operation === 'transcribe' ? audioConfig.transcribeModel : audioConfig.synthesizeModel)\n if (!targetId)\n return err(HaiAIError.AUDIO_MODEL_NOT_FOUND, aiM('ai_audioModelNotFound', { params: { model: `<${operation}>` } }))\n\n const entry = audioConfig.models?.find(m => m.id === targetId || m.model === targetId)\n if (!entry)\n return err(HaiAIError.AUDIO_MODEL_NOT_FOUND, aiM('ai_audioModelNotFound', { params: { model: targetId } }))\n\n const operations: readonly string[] = entry.operations\n if (!operations.includes(operation)) {\n return err(\n HaiAIError.AUDIO_UNSUPPORTED_INPUT,\n aiM('ai_audioUnsupportedInput', { params: { provider: entry.provider, reason: `model ${entry.id} does not support ${operation}` } }),\n )\n }\n\n const apiKey = entry.apiKey ?? audioProviderEnvApiKey(entry.provider)\n const hasDoubaoLegacy = Boolean(entry.appKey && entry.accessKey)\n if (!apiKey && !(entry.provider === 'doubao' && hasDoubaoLegacy))\n return err(HaiAIError.CONFIGURATION_ERROR, aiM('ai_audioMissingApiKey', { params: { provider: entry.provider } }))\n\n return ok({\n id: entry.id,\n provider: entry.provider,\n model: entry.model,\n apiKey,\n baseUrl: entry.baseUrl ?? AUDIO_PROVIDER_DEFAULT_BASE_URL[entry.provider],\n appKey: entry.appKey ?? process.env.VOLC_APP_KEY,\n accessKey: entry.accessKey ?? process.env.VOLC_ACCESS_KEY,\n resourceId: entry.resourceId ?? (entry.provider === 'doubao' ? doubaoDefaultResourceId(operation) : ''),\n workspaceId: entry.workspaceId,\n timeout: entry.timeout ?? 60000,\n })\n}\n\n/**\n * AI 配置 Schema\n *\n * 统一 AI 模块配置:LLM、MCP、Embedding、Knowledge、Retrieval、Memory、Token、Summary、Compress、File。\n * 模型通过 LLM.scenarios 映射场景,子系统不再独立配置 apiKey / baseUrl / model。\n *\n * @example\n * ```ts\n * ai.init({\n * llm: {\n * apiKey: 'sk-xxx',\n * model: 'gpt-4o-mini',\n * maxTokens: 4096,\n * models: [\n * { id: 'rerank', model: 'rerank-english-v3.0', baseUrl: 'https://api.cohere.com' },\n * ],\n * scenarios: {\n * extraction: 'gpt-4o',\n * summary: 'gpt-4o-mini',\n * embedding: 'text-embedding-3-small',\n * rerank: 'rerank',\n * ocr: 'gpt-4o',\n * },\n * },\n * embedding: { dimensions: 1536 },\n * knowledge: {\n * collection: 'docs',\n * enableEntityExtraction: true,\n * cleanOptions: { removeHtml: true },\n * chunkOptions: { mode: 'markdown', maxSize: 1500, overlap: 200 },\n * },\n * retrieval: {\n * sources: [\n * { id: 'docs', collection: 'documentation', name: '产品文档', topK: 5, minScore: 0.7 },\n * ],\n * },\n * memory: { maxEntriesPerObject: 500, embeddingEnabled: true },\n * token: { tokenRatio: 0.25 },\n * summary: { systemPrompt: 'You are a summarizer.' },\n * compress: { defaultStrategy: 'hybrid', preserveLastN: 4 },\n * })\n * ```\n */\nexport const AIConfigSchema = z.object({\n /** LLM 配置(可选,所有字段有默认值) */\n llm: LLMConfigSchema.default({\n model: 'gpt-4o-mini',\n api: 'chat',\n maxTokens: 4096,\n temperature: 0.7,\n timeout: 60000,\n tempModelCacheTtl: 600000,\n }),\n /** MCP 配置 */\n mcp: MCPConfigSchema.optional(),\n /** Embedding 配置 */\n embedding: EmbeddingConfigSchema.optional(),\n /** Knowledge 配置 */\n knowledge: KnowledgeConfigSchema.optional(),\n /** Memory 配置 */\n memory: MemoryConfigSchema.optional(),\n /** Token 配置 */\n token: TokenConfigSchema.optional(),\n /** Summary 配置 */\n summary: SummaryConfigSchema.optional(),\n /** Compress 配置 */\n compress: CompressConfigSchema.optional(),\n /** Retrieval 配置(预注册检索源) */\n retrieval: RetrievalConfigSchema.optional(),\n /** File 解析配置 */\n file: FileConfigSchema.optional(),\n /** A2A 配置(Agent-to-Agent 协议) */\n a2a: A2AConfigSchema.optional(),\n /** Audio 配置(语音识别 / 语音合成) */\n audio: AudioConfigSchema.optional(),\n})\n\n/** AI 配置类型(校验后的完整类型) */\nexport type AIConfig = z.infer<typeof AIConfigSchema>\n\n/** AI 配置输入类型(允许部分字段) */\nexport type AIConfigInput = z.input<typeof AIConfigSchema>\n","/**\n * @h-ai/ai — 统一语音 WebSocket 协议\n *\n * 定义浏览器 / 远程客户端与 `@h-ai/serv` 语音入口之间的统一 WebSocket 消息协议。\n * 客户端与服务端共享此协议,客户端不接收任何厂商原生事件;音频以二进制帧传输,\n * 控制与文本以 JSON 帧传输。\n * @module audio/ai-audio-ws-protocol\n */\n\nimport type { AudioFormat } from './ai-audio-types.js'\n\n/** 统一语音入口的默认路径(相对 API 前缀) */\nexport const AUDIO_WS_PATH = '/ai/audio'\n\n// ─── 客户端 → 服务端 ───\n\n/**\n * 会话起始消息(客户端首个 JSON 帧)\n *\n * 表达本次语音操作:识别或合成,及可选的模型 / 语言 / 音色 / 格式等参数。\n */\nexport interface AudioWsStartMessage {\n type: 'start'\n /** 操作类型 */\n operation: 'transcribe' | 'synthesize'\n /**\n * 是否流式返回增量结果\n *\n * 识别操作:`true` 时服务端桥接为持续音频输入并流式返回临时结果;\n * `false`(默认)时服务端缓冲完整音频后返回单条最终结果。\n */\n stream?: boolean\n /** 模型 ID(不传时使用服务端默认模型) */\n model?: string\n /** 识别语言提示 */\n language?: string\n /** 领域提示词 / 热词(识别) */\n contextHints?: string[]\n /** 合成音色 */\n voice?: string\n /** 合成自然语言风格指令 */\n instruction?: string\n /** 音频格式(识别时为输入格式,合成时为输出格式) */\n format?: AudioFormat\n /** 采样率 */\n sampleRate?: number\n /** 声道数 */\n channels?: 1 | 2\n}\n\n/** 文本输入帧(合成操作时携带待合成文本) */\nexport interface AudioWsTextMessage {\n type: 'text'\n /** 调用方分配的稳定文本段 ID */\n segmentId: string\n /** 待合成文本片段 */\n text: string\n}\n\n/** 输入结束帧(音频 / 文本输入全部发送完毕) */\nexport interface AudioWsDoneMessage {\n type: 'done'\n}\n\n/** 客户端 JSON 控制消息(音频输入以二进制帧发送,不走 JSON) */\nexport type AudioWsClientMessage = AudioWsStartMessage | AudioWsTextMessage | AudioWsDoneMessage\n\n// ─── 服务端 → 客户端 ───\n\n/** 语音起止事件(识别操作时服务端 VAD 检测到语音开始 / 结束) */\nexport interface AudioWsSpeechMessage {\n type: 'speech_started' | 'speech_stopped'\n}\n\n/** 识别结果帧(识别操作时返回当前语句的完整文本) */\nexport interface AudioWsTranscriptMessage {\n type: 'transcript'\n /** 当前语句的完整识别文本 */\n text: string\n /** 是否为该语句的最终结果 */\n final: boolean\n}\n\n/** 合成文本段开始;后续二进制帧均属于该段,直到收到对应的 `segment_done`。 */\nexport interface AudioWsSegmentStartedMessage {\n type: 'segment_started'\n segmentId: string\n text: string\n}\n\n/** 合成文本段的音频已全部发送。 */\nexport interface AudioWsSegmentDoneMessage {\n type: 'segment_done'\n segmentId: string\n}\n\n/** 错误帧(领域语义错误码,不暴露厂商协议细节) */\nexport interface AudioWsErrorMessage {\n type: 'error'\n /** 领域错误码(如 `hai:ai:054`) */\n code: string\n /** 错误消息 */\n message: string\n}\n\n/** 结束帧(服务端已发送全部结果,随后关闭连接) */\nexport interface AudioWsEndMessage {\n type: 'end'\n}\n\n/** 服务端 JSON 消息(合成音频以二进制帧返回,不走 JSON) */\nexport type AudioWsServerMessage\n = | AudioWsSpeechMessage\n | AudioWsTranscriptMessage\n | AudioWsSegmentStartedMessage\n | AudioWsSegmentDoneMessage\n | AudioWsErrorMessage\n | AudioWsEndMessage\n"]}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a9 as TranscriptionRequest, aa as TranscriptionResult, ab as TranscriptionStreamRequest, a8 as TranscriptionEvent, a2 as SynthesisRequest, a3 as SynthesisResult, a4 as SynthesisStreamRequest, a1 as SynthesisEvent, aC as ChatCompletionRequest, aD as ChatCompletionResponse, aA as ChatCompletionChunk, b3 as KnowledgeRetrieveResult, aS as KnowledgeAskResult, a$ as KnowledgeIngestResult, aT as KnowledgeDocumentInfo, ba as MemoryEntry, bH as StorePage, bb as MemoryEntryInput, bi as MemoryUpdateInput, bF as SessionInfo, aG as ChatRecord, bp as RagResult, bt as ReasoningResult, af as A2AAgentCardConfig, an as A2AMessageRecord, aj as A2ACallResult } from '../ai-reasoning-types-DLLzpn6T.js';
|
|
2
2
|
import { HaiResult } from '@h-ai/core';
|
|
3
3
|
import '@a2a-js/sdk/server';
|
|
4
4
|
import '@h-ai/datapipe';
|
|
@@ -19,11 +19,11 @@ interface AudioClientConfig {
|
|
|
19
19
|
/** 语音 WebSocket 完整 URL(如 `wss://host/api/v1/ai/audio`) */
|
|
20
20
|
url: string;
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* 获取短期、一次性的 Audio WebSocket ticket
|
|
23
23
|
*
|
|
24
|
-
*
|
|
24
|
+
* ticket 应由已登录 HTTP 请求签发,并在服务端首次校验时原子消费。
|
|
25
25
|
*/
|
|
26
|
-
|
|
26
|
+
getTicket: () => string | Promise<string>;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* 浏览器语音操作接口
|
|
@@ -37,8 +37,8 @@ interface AudioClientOperations {
|
|
|
37
37
|
transcribeStream: (request: TranscriptionStreamRequest) => AsyncIterable<TranscriptionEvent>;
|
|
38
38
|
/** 将完整文本合成为完整音频 */
|
|
39
39
|
synthesize: (request: SynthesisRequest) => Promise<SynthesisResult>;
|
|
40
|
-
/**
|
|
41
|
-
synthesizeStream: (request: SynthesisStreamRequest) => AsyncIterable<
|
|
40
|
+
/** 持续输入文本段并按段输出结构化音频事件 */
|
|
41
|
+
synthesizeStream: (request: SynthesisStreamRequest) => AsyncIterable<SynthesisEvent>;
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* 创建浏览器语音客户端
|
package/dist/client/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { collectStreamContent, createA2AClient, createAIClient, createAudioClient, createUnconfiguredAudioClient, parseSSE } from '../chunk-
|
|
1
|
+
export { collectStreamContent, createA2AClient, createAIClient, createAudioClient, createUnconfiguredAudioClient, parseSSE } from '../chunk-535CQURK.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|