@h-ai/ai 0.1.0-alpha.50 → 0.1.0-alpha.53
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 +1 -1
- package/dist/index.js +46 -17
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -316,7 +316,7 @@ return playable.data
|
|
|
316
316
|
|
|
317
317
|
浏览器 / 移动端通过 `@h-ai/serv` 暴露的统一语音 WebSocket 入口访问,`@h-ai/ai/client` 提供与 Node 端一致的 `audio.*` API(传输细节内部隐藏)。浏览器客户端严格区分正常结束、取消(`AUDIO_CANCELLED`)与异常断连(`AUDIO_CONNECTION_FAILED`):取消或在 `end` 前断连会抛出对应领域错误码,`synthesize` 不会把未完成的部分音频当作成功结果返回。
|
|
318
318
|
|
|
319
|
-
> 自托管模型服务(faster-whisper / IndexTTS / Qwen3-4B 的 CPU/GPU Docker 镜像、权重下载与离线打包)见 [`models/`](./models/README.md)。镜像与权重下载优先使用 ModelScope
|
|
319
|
+
> 自托管模型服务(faster-whisper / IndexTTS / Qwen3-4B 的 CPU/GPU Docker 镜像、权重下载与离线打包)见 [`models/`](./models/README.md)。镜像与权重下载优先使用 ModelScope,自动回退 HuggingFace 镜像。
|
|
320
320
|
|
|
321
321
|
### 文生图(Image)
|
|
322
322
|
|
package/dist/index.js
CHANGED
|
@@ -9,10 +9,10 @@ import { DefaultExecutionEventBusManager, DefaultRequestHandler, JsonRpcTranspor
|
|
|
9
9
|
import { Buffer } from 'buffer';
|
|
10
10
|
import { gunzipSync } from 'zlib';
|
|
11
11
|
import WebSocket from 'ws';
|
|
12
|
+
import process2 from 'process';
|
|
12
13
|
import OpenAI3, { toFile } from 'openai';
|
|
13
14
|
import { nanoid } from 'nanoid';
|
|
14
15
|
import { z } from 'zod';
|
|
15
|
-
import process from 'process';
|
|
16
16
|
import { reldb } from '@h-ai/reldb';
|
|
17
17
|
import { vecdb } from '@h-ai/vecdb';
|
|
18
18
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
@@ -873,16 +873,23 @@ function createIndexTtsAudioProvider() {
|
|
|
873
873
|
const headers = {};
|
|
874
874
|
if (model.apiKey)
|
|
875
875
|
headers.Authorization = `Bearer ${model.apiKey}`;
|
|
876
|
-
const
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
876
|
+
const dispatcher = await createNodeDispatcher(model.timeout);
|
|
877
|
+
try {
|
|
878
|
+
const requestInit = {
|
|
879
|
+
method: "POST",
|
|
880
|
+
headers,
|
|
881
|
+
body: form,
|
|
882
|
+
signal: combineSignal(signal, model.timeout),
|
|
883
|
+
...dispatcher ? { dispatcher } : {}
|
|
884
|
+
};
|
|
885
|
+
const response = await fetch(`${model.baseUrl.replace(/\/$/, "")}/audio/speech`, requestInit);
|
|
886
|
+
if (!response.ok)
|
|
887
|
+
return err(HaiAIError.AUDIO_UPSTREAM_ERROR, aiM("ai_audioUpstreamError", { params: { error: await describeHttpError(response) } }));
|
|
888
|
+
const data = new Uint8Array(await response.arrayBuffer());
|
|
889
|
+
return ok(buildSynthesisResult(data, out, response.headers));
|
|
890
|
+
} finally {
|
|
891
|
+
await dispatcher?.close();
|
|
892
|
+
}
|
|
886
893
|
} catch (error) {
|
|
887
894
|
logger4.debug("IndexTTS synthesize failed", { error: errorMessage(error) });
|
|
888
895
|
return toAudioErrorResult(error, signal);
|
|
@@ -893,6 +900,16 @@ function createIndexTtsAudioProvider() {
|
|
|
893
900
|
getCapabilities: () => INDEX_TTS_CAPABILITIES
|
|
894
901
|
};
|
|
895
902
|
}
|
|
903
|
+
async function createNodeDispatcher(timeout) {
|
|
904
|
+
if (typeof process2 === "undefined" || !process2.versions?.node)
|
|
905
|
+
return void 0;
|
|
906
|
+
const { Agent } = await import('undici');
|
|
907
|
+
return new Agent({
|
|
908
|
+
connectTimeout: Math.min(timeout, 3e4),
|
|
909
|
+
headersTimeout: timeout,
|
|
910
|
+
bodyTimeout: timeout
|
|
911
|
+
});
|
|
912
|
+
}
|
|
896
913
|
function resolveSynthesisOutput2(request) {
|
|
897
914
|
const format = request.format ?? "wav";
|
|
898
915
|
return { format, sampleRate: format === "pcm16" ? request.sampleRate ?? 24e3 : void 0, channels: 1 };
|
|
@@ -4820,10 +4837,10 @@ function createAnthropicProvider(deps) {
|
|
|
4820
4837
|
function resolveAnthropic(requestModel, tempModel) {
|
|
4821
4838
|
const entry = requestModel ? config.llm.models?.find((m) => m.id === requestModel || m.model === requestModel) : void 0;
|
|
4822
4839
|
const model = tempModel?.model ?? entry?.model ?? requestModel ?? config.llm.model ?? "claude-3-5-sonnet-latest";
|
|
4823
|
-
const apiKey = tempModel?.apiKey ?? entry?.apiKey ?? config.llm.apiKey ??
|
|
4840
|
+
const apiKey = tempModel?.apiKey ?? entry?.apiKey ?? config.llm.apiKey ?? process2.env.HAI_AI_ANTHROPIC_API_KEY ?? process2.env.ANTHROPIC_API_KEY;
|
|
4824
4841
|
if (!apiKey)
|
|
4825
4842
|
return err(HaiAIError.CONFIGURATION_ERROR, aiM("ai_configError", { params: { error: "API Key is required for Anthropic" } }));
|
|
4826
|
-
const baseUrl = (tempModel?.baseUrl ?? entry?.baseUrl ??
|
|
4843
|
+
const baseUrl = (tempModel?.baseUrl ?? entry?.baseUrl ?? process2.env.HAI_AI_ANTHROPIC_BASE_URL ?? process2.env.ANTHROPIC_BASE_URL ?? DEFAULT_ANTHROPIC_BASE_URL).replace(/\/+$/, "");
|
|
4827
4844
|
return ok({
|
|
4828
4845
|
apiKey,
|
|
4829
4846
|
baseUrl,
|
|
@@ -5182,10 +5199,10 @@ function createOpenAIProvider(deps) {
|
|
|
5182
5199
|
return ok({ client: getClient(apiKey ?? "", baseUrl ?? "https://api.openai.com/v1", timeout), model, api: resolvedApi });
|
|
5183
5200
|
}
|
|
5184
5201
|
function resolveTempClient(tempModel) {
|
|
5185
|
-
const apiKey = tempModel.apiKey ?? config.llm.apiKey ??
|
|
5202
|
+
const apiKey = tempModel.apiKey ?? config.llm.apiKey ?? process2.env.HAI_AI_LLM_API_KEY ?? process2.env.OPENAI_API_KEY;
|
|
5186
5203
|
if (!apiKey)
|
|
5187
5204
|
return err(HaiAIError.CONFIGURATION_ERROR, aiM("ai_configError", { params: { error: "API Key is required for temp model" } }));
|
|
5188
|
-
const baseUrl = tempModel.baseUrl ?? config.llm.baseUrl ??
|
|
5205
|
+
const baseUrl = tempModel.baseUrl ?? config.llm.baseUrl ?? process2.env.HAI_AI_LLM_BASE_URL ?? process2.env.OPENAI_BASE_URL ?? "https://api.openai.com/v1";
|
|
5189
5206
|
const timeout = tempModel.timeout ?? config.llm.timeout ?? 6e4;
|
|
5190
5207
|
const api = (tempModel.api ?? config.llm.api) === "responses" ? "responses" : "chat";
|
|
5191
5208
|
return ok({
|
|
@@ -7927,6 +7944,12 @@ async function createAISubsystems(config, deps) {
|
|
|
7927
7944
|
}
|
|
7928
7945
|
var logger30 = core.logger.child({ module: "ai", scope: "store-provider-db" });
|
|
7929
7946
|
var MAX_BATCH_SQL_PARAMS = 900;
|
|
7947
|
+
function dataTimestamp(data, field, fallback) {
|
|
7948
|
+
if (typeof data !== "object" || data === null)
|
|
7949
|
+
return fallback;
|
|
7950
|
+
const value = data[field];
|
|
7951
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
7952
|
+
}
|
|
7930
7953
|
var ReldbAIRelStore = class {
|
|
7931
7954
|
sql;
|
|
7932
7955
|
table;
|
|
@@ -7982,6 +8005,8 @@ var ReldbAIRelStore = class {
|
|
|
7982
8005
|
async save(id, data, scope) {
|
|
7983
8006
|
const now = Date.now();
|
|
7984
8007
|
const json = JSON.stringify(data);
|
|
8008
|
+
const createdAt = dataTimestamp(data, "createdAt", now);
|
|
8009
|
+
const updatedAt = dataTimestamp(data, "updatedAt", now);
|
|
7985
8010
|
const colNames = ["id"];
|
|
7986
8011
|
const values = [id];
|
|
7987
8012
|
const placeholders = ["?"];
|
|
@@ -8006,7 +8031,7 @@ var ReldbAIRelStore = class {
|
|
|
8006
8031
|
placeholders.push("?");
|
|
8007
8032
|
}
|
|
8008
8033
|
colNames.push("data", "created_at", "updated_at");
|
|
8009
|
-
values.push(json,
|
|
8034
|
+
values.push(json, createdAt, updatedAt);
|
|
8010
8035
|
placeholders.push("?", "?", "?");
|
|
8011
8036
|
if (this.dbType === "mysql") {
|
|
8012
8037
|
const updateParts = ["data = VALUES(data)", "updated_at = VALUES(updated_at)"];
|
|
@@ -8140,7 +8165,11 @@ var ReldbAIRelStore = class {
|
|
|
8140
8165
|
values.push(scope?.status ?? null);
|
|
8141
8166
|
if (this.hasRefId)
|
|
8142
8167
|
values.push(scope?.refId ?? null);
|
|
8143
|
-
values.push(
|
|
8168
|
+
values.push(
|
|
8169
|
+
JSON.stringify(data),
|
|
8170
|
+
dataTimestamp(data, "createdAt", now),
|
|
8171
|
+
dataTimestamp(data, "updatedAt", now)
|
|
8172
|
+
);
|
|
8144
8173
|
return values;
|
|
8145
8174
|
}
|
|
8146
8175
|
/** 构造跨数据库 upsert 更新片段;列名来自内部白名单,不接受外部输入。 */
|