@acosmi/sdk-ts 2.14.0 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +65 -3
- package/dist/browser/index.mjs +125 -16
- package/dist/browser/index.mjs.map +1 -1
- package/dist/index.mjs +125 -16
- package/dist/index.mjs.map +1 -1
- package/dist/node/adapters/anthropic.cjs.map +1 -1
- package/dist/node/adapters/anthropic.d.cts +1 -1
- package/dist/node/adapters/anthropic.d.ts +1 -1
- package/dist/node/adapters/anthropic.mjs.map +1 -1
- package/dist/node/adapters/openai.cjs.map +1 -1
- package/dist/node/adapters/openai.d.cts +2 -2
- package/dist/node/adapters/openai.d.ts +2 -2
- package/dist/node/adapters/openai.mjs.map +1 -1
- package/dist/node/{index-BoxWrEq0.d.cts → index-yOZUFtNQ.d.cts} +29 -2
- package/dist/node/{index-BoxWrEq0.d.ts → index-yOZUFtNQ.d.ts} +29 -2
- package/dist/node/index.cjs +126 -15
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +51 -8
- package/dist/node/index.d.ts +51 -8
- package/dist/node/index.mjs +125 -16
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/{openai-BRreM1fK.d.cts → openai-B6mz3cyj.d.cts} +1 -1
- package/dist/node/{openai-Dpz9QgEJ.d.ts → openai-DuQHy2AA.d.ts} +1 -1
- package/docs//345/274/200/345/217/221/344/270/216/345/217/221/345/270/203/346/211/213/345/206/214.md +80 -33
- package/package.json +1 -1
package/dist/node/index.cjs
CHANGED
|
@@ -43,6 +43,57 @@ function newWebSearchTool(cfg) {
|
|
|
43
43
|
}
|
|
44
44
|
return st;
|
|
45
45
|
}
|
|
46
|
+
function classifySourcesEvent(ev) {
|
|
47
|
+
let parsed;
|
|
48
|
+
try {
|
|
49
|
+
parsed = JSON.parse(ev.data);
|
|
50
|
+
} catch {
|
|
51
|
+
return ev.event === "sources" ? { kind: "malformed_sources", code: "invalid_json" } : { kind: "not_sources" };
|
|
52
|
+
}
|
|
53
|
+
const wrapper = typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
|
|
54
|
+
if (wrapper?.type !== "sources" && ev.event !== "sources") {
|
|
55
|
+
return { kind: "not_sources" };
|
|
56
|
+
}
|
|
57
|
+
if (!wrapper || !Object.prototype.hasOwnProperty.call(wrapper, "sources")) {
|
|
58
|
+
return { kind: "malformed_sources", code: "missing_sources" };
|
|
59
|
+
}
|
|
60
|
+
if (Object.prototype.hasOwnProperty.call(wrapper, "session_id") && wrapper.session_id !== void 0 && typeof wrapper.session_id !== "string") {
|
|
61
|
+
return { kind: "malformed_sources", code: "session_id_invalid" };
|
|
62
|
+
}
|
|
63
|
+
if (!Array.isArray(wrapper.sources)) {
|
|
64
|
+
return { kind: "malformed_sources", code: "sources_not_array" };
|
|
65
|
+
}
|
|
66
|
+
const sessionID = typeof wrapper.session_id === "string" ? wrapper.session_id : void 0;
|
|
67
|
+
if (wrapper.sources.length === 0) {
|
|
68
|
+
return {
|
|
69
|
+
kind: "empty_sources",
|
|
70
|
+
...sessionID === void 0 ? {} : { session_id: sessionID }
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
for (const source of wrapper.sources) {
|
|
74
|
+
if (typeof source !== "object" || source === null || Array.isArray(source)) {
|
|
75
|
+
return { kind: "malformed_sources", code: "source_not_object" };
|
|
76
|
+
}
|
|
77
|
+
const item = source;
|
|
78
|
+
if (typeof item.title !== "string") {
|
|
79
|
+
return { kind: "malformed_sources", code: "source_title_invalid" };
|
|
80
|
+
}
|
|
81
|
+
if (typeof item.url !== "string") {
|
|
82
|
+
return { kind: "malformed_sources", code: "source_url_invalid" };
|
|
83
|
+
}
|
|
84
|
+
if (Object.prototype.hasOwnProperty.call(item, "snippet") && item.snippet !== void 0 && typeof item.snippet !== "string") {
|
|
85
|
+
return { kind: "malformed_sources", code: "source_snippet_invalid" };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
kind: "sources",
|
|
90
|
+
value: {
|
|
91
|
+
...wrapper,
|
|
92
|
+
sources: wrapper.sources,
|
|
93
|
+
...sessionID === void 0 ? {} : { session_id: sessionID }
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
46
97
|
function parseSourcesEvent(ev) {
|
|
47
98
|
let wrapper;
|
|
48
99
|
try {
|
|
@@ -2239,6 +2290,13 @@ var ErrOAuthCORSBlocked = "oauth_cors_blocked";
|
|
|
2239
2290
|
var ErrRefreshProxyFailed = "refresh_proxy_failed";
|
|
2240
2291
|
var ErrTokenExpired = "token_expired";
|
|
2241
2292
|
var CHAT_REQUEST_TIMEOUT_MS = 11 * 60 * 1e3;
|
|
2293
|
+
function notifyUpstreamActivity(cb) {
|
|
2294
|
+
if (!cb) return;
|
|
2295
|
+
try {
|
|
2296
|
+
cb();
|
|
2297
|
+
} catch {
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2242
2300
|
var DEFAULT_API_TIMEOUT_MS = 6e4;
|
|
2243
2301
|
function newDeferred() {
|
|
2244
2302
|
let resolve;
|
|
@@ -2952,7 +3010,13 @@ var Client = class _Client {
|
|
|
2952
3010
|
try {
|
|
2953
3011
|
const { body, adapter } = await this.buildChatRequest(modelID, r, ctl.signal);
|
|
2954
3012
|
const endpoint = `/managed-models/${encodeURIComponent(modelID)}${adapter.endpointSuffix()}`;
|
|
2955
|
-
const { result, headers } = await this.doJSONFullRaw(
|
|
3013
|
+
const { result, headers } = await this.doJSONFullRaw(
|
|
3014
|
+
"POST",
|
|
3015
|
+
endpoint,
|
|
3016
|
+
body,
|
|
3017
|
+
ctl.signal,
|
|
3018
|
+
CHAT_REQUEST_TIMEOUT_MS
|
|
3019
|
+
);
|
|
2956
3020
|
const resp = adapter.parseResponse(result);
|
|
2957
3021
|
const v1 = headers.get("X-Token-Remaining");
|
|
2958
3022
|
if (v1) {
|
|
@@ -3017,7 +3081,13 @@ var Client = class _Client {
|
|
|
3017
3081
|
*/
|
|
3018
3082
|
async generateVideo(modelID, req, signal) {
|
|
3019
3083
|
const endpoint = `/managed-models/${encodeURIComponent(modelID)}/videos/generations`;
|
|
3020
|
-
const { result } = await this.doJSONFullRaw(
|
|
3084
|
+
const { result } = await this.doJSONFullRaw(
|
|
3085
|
+
"POST",
|
|
3086
|
+
endpoint,
|
|
3087
|
+
req,
|
|
3088
|
+
signal,
|
|
3089
|
+
CHAT_REQUEST_TIMEOUT_MS
|
|
3090
|
+
);
|
|
3021
3091
|
return this.unwrapAPIResponse(result);
|
|
3022
3092
|
}
|
|
3023
3093
|
/**
|
|
@@ -3086,7 +3156,8 @@ var Client = class _Client {
|
|
|
3086
3156
|
"POST",
|
|
3087
3157
|
`/managed-models/${encodeURIComponent(modelID)}/anthropic`,
|
|
3088
3158
|
data,
|
|
3089
|
-
ctl.signal
|
|
3159
|
+
ctl.signal,
|
|
3160
|
+
CHAT_REQUEST_TIMEOUT_MS
|
|
3090
3161
|
);
|
|
3091
3162
|
const rawStr = new TextDecoder().decode(result);
|
|
3092
3163
|
try {
|
|
@@ -3120,7 +3191,13 @@ var Client = class _Client {
|
|
|
3120
3191
|
const body = adapter.buildRequestBody(caps, r);
|
|
3121
3192
|
const data = JSON.stringify(body);
|
|
3122
3193
|
const endpoint = `/managed-models/${encodeURIComponent(modelID)}${adapter.endpointSuffix()}`;
|
|
3123
|
-
const { result } = await this.doJSONFullRaw(
|
|
3194
|
+
const { result } = await this.doJSONFullRaw(
|
|
3195
|
+
"POST",
|
|
3196
|
+
endpoint,
|
|
3197
|
+
data,
|
|
3198
|
+
ctl.signal,
|
|
3199
|
+
CHAT_REQUEST_TIMEOUT_MS
|
|
3200
|
+
);
|
|
3124
3201
|
const { parseOpenAIResponseToAnthropic: parseOpenAIResponseToAnthropic2 } = await Promise.resolve().then(() => (init_openai(), openai_exports));
|
|
3125
3202
|
return parseOpenAIResponseToAnthropic2(result);
|
|
3126
3203
|
} finally {
|
|
@@ -3130,23 +3207,27 @@ var Client = class _Client {
|
|
|
3130
3207
|
/**
|
|
3131
3208
|
* 流式聊天 (SSE), 通过 async generator 返回事件
|
|
3132
3209
|
* v0.5.0: 根据 adapter 路由端点
|
|
3210
|
+
*
|
|
3211
|
+
* @param onUpstreamActivity 见 {@link UpstreamActivityCallback}
|
|
3133
3212
|
*/
|
|
3134
|
-
chatStream(modelID, req, signal) {
|
|
3213
|
+
chatStream(modelID, req, signal, onUpstreamActivity) {
|
|
3135
3214
|
return {
|
|
3136
|
-
[Symbol.asyncIterator]: () => this.chatStreamGen(modelID, req, signal, false)
|
|
3215
|
+
[Symbol.asyncIterator]: () => this.chatStreamGen(modelID, req, signal, false, onUpstreamActivity)
|
|
3137
3216
|
};
|
|
3138
3217
|
}
|
|
3139
3218
|
/**
|
|
3140
3219
|
* Anthropic 原生格式流式聊天 (SSE)
|
|
3141
3220
|
* 调用 POST /managed-models/:id/anthropic, SSE 事件为 Anthropic 协议格式
|
|
3142
3221
|
* 无 started/settled/failed 自定义事件, 无 data: [DONE], message_stop 为自然结束
|
|
3222
|
+
*
|
|
3223
|
+
* @param onUpstreamActivity 见 {@link UpstreamActivityCallback}
|
|
3143
3224
|
*/
|
|
3144
|
-
chatMessagesStream(modelID, req, signal) {
|
|
3225
|
+
chatMessagesStream(modelID, req, signal, onUpstreamActivity) {
|
|
3145
3226
|
return {
|
|
3146
|
-
[Symbol.asyncIterator]: () => this.chatMessagesStreamGen(modelID, req, signal, false)
|
|
3227
|
+
[Symbol.asyncIterator]: () => this.chatMessagesStreamGen(modelID, req, signal, false, onUpstreamActivity)
|
|
3147
3228
|
};
|
|
3148
3229
|
}
|
|
3149
|
-
async *chatStreamGen(modelID, req, signal, retried) {
|
|
3230
|
+
async *chatStreamGen(modelID, req, signal, retried, onUpstreamActivity) {
|
|
3150
3231
|
const r = { ...req, stream: true };
|
|
3151
3232
|
const { body, adapter } = await this.buildChatRequest(modelID, r, signal);
|
|
3152
3233
|
const token = await this.ensureToken(signal);
|
|
@@ -3179,7 +3260,7 @@ var Client = class _Client {
|
|
|
3179
3260
|
`stream: unauthorized and refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}`
|
|
3180
3261
|
);
|
|
3181
3262
|
}
|
|
3182
|
-
yield* this.chatStreamGen(modelID, req, signal, true);
|
|
3263
|
+
yield* this.chatStreamGen(modelID, req, signal, true, onUpstreamActivity);
|
|
3183
3264
|
return;
|
|
3184
3265
|
}
|
|
3185
3266
|
if (!resp.ok) {
|
|
@@ -3195,6 +3276,7 @@ var Client = class _Client {
|
|
|
3195
3276
|
}
|
|
3196
3277
|
let currentEvent = "";
|
|
3197
3278
|
for await (const line of iterSSELines(resp.body)) {
|
|
3279
|
+
notifyUpstreamActivity(onUpstreamActivity);
|
|
3198
3280
|
if (isSSECommentLine(line)) continue;
|
|
3199
3281
|
if (line.startsWith("event:")) {
|
|
3200
3282
|
currentEvent = line.slice("event:".length).trim();
|
|
@@ -3215,7 +3297,7 @@ var Client = class _Client {
|
|
|
3215
3297
|
}
|
|
3216
3298
|
}
|
|
3217
3299
|
}
|
|
3218
|
-
async *chatMessagesStreamGen(modelID, req, signal, retried) {
|
|
3300
|
+
async *chatMessagesStreamGen(modelID, req, signal, retried, onUpstreamActivity) {
|
|
3219
3301
|
const r = { ...req, stream: true };
|
|
3220
3302
|
const { body, adapter } = await this.buildChatRequest(modelID, r, signal);
|
|
3221
3303
|
const token = await this.ensureToken(signal);
|
|
@@ -3248,7 +3330,7 @@ var Client = class _Client {
|
|
|
3248
3330
|
`messages stream: unauthorized and refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}`
|
|
3249
3331
|
);
|
|
3250
3332
|
}
|
|
3251
|
-
yield* this.chatMessagesStreamGen(modelID, req, signal, true);
|
|
3333
|
+
yield* this.chatMessagesStreamGen(modelID, req, signal, true, onUpstreamActivity);
|
|
3252
3334
|
return;
|
|
3253
3335
|
}
|
|
3254
3336
|
if (!resp.ok) {
|
|
@@ -3261,6 +3343,7 @@ var Client = class _Client {
|
|
|
3261
3343
|
if (adapter.format() === 1 /* OpenAI */) {
|
|
3262
3344
|
const converter = newOpenAIStreamConverter();
|
|
3263
3345
|
for await (const line of iterSSELines(resp.body)) {
|
|
3346
|
+
notifyUpstreamActivity(onUpstreamActivity);
|
|
3264
3347
|
if (isSSECommentLine(line)) continue;
|
|
3265
3348
|
if (line.startsWith("event:")) {
|
|
3266
3349
|
line.slice("event:".length).trim();
|
|
@@ -3275,6 +3358,7 @@ var Client = class _Client {
|
|
|
3275
3358
|
const blockTypeMap = /* @__PURE__ */ new Map();
|
|
3276
3359
|
let currentEvent = "";
|
|
3277
3360
|
for await (const line of iterSSELines(resp.body)) {
|
|
3361
|
+
notifyUpstreamActivity(onUpstreamActivity);
|
|
3278
3362
|
if (isSSECommentLine(line)) continue;
|
|
3279
3363
|
if (line.startsWith("event:")) {
|
|
3280
3364
|
currentEvent = line.slice("event:".length).trim();
|
|
@@ -3407,7 +3491,19 @@ var Client = class _Client {
|
|
|
3407
3491
|
ctl.dispose();
|
|
3408
3492
|
}
|
|
3409
3493
|
}
|
|
3410
|
-
/**
|
|
3494
|
+
/**
|
|
3495
|
+
* doJSONFull 的 raw bytes 变体 (chat 用, 不立即 JSON.parse)
|
|
3496
|
+
*
|
|
3497
|
+
* ⚠️ 契约 (2026-08-06): `timeoutMs` 的 30s 默认值只适用于**控制面**端点 (列目录 /
|
|
3498
|
+
* 查配额 / 取任务状态)。凡走**模型推理或生成**的端点 —— chat / anthropic /
|
|
3499
|
+
* embeddings / rerank / images / videos —— 一律必须显式传入 `CHAT_REQUEST_TIMEOUT_MS`,
|
|
3500
|
+
* 哪怕调用方已经用 `withRequestTimeout` 建了外层预算: 外层只约束 `signal`, 内层
|
|
3501
|
+
* 会**另建**一个 `timeoutMs` 计时器, 30s 恒先于任何更长的外层预算触发。
|
|
3502
|
+
*
|
|
3503
|
+
* 这不是假设 —— 2026-08-06 事故里 chat 路径正因漏传本参数而被恒定钉死在 30s,
|
|
3504
|
+
* 且上方 v1.6.0 的注释还声称它已是 11min。回归闸门见
|
|
3505
|
+
* `tests/chat-timeout-budget.test.ts`。
|
|
3506
|
+
*/
|
|
3411
3507
|
async doJSONFullRaw(method, path, body, signal, timeoutMs = 3e4) {
|
|
3412
3508
|
return this.doJSONFullRawInternal(method, path, body, signal, false, timeoutMs);
|
|
3413
3509
|
}
|
|
@@ -7068,6 +7164,15 @@ function sleep2(ms, signal) {
|
|
|
7068
7164
|
}
|
|
7069
7165
|
|
|
7070
7166
|
// src/support/bug-report.ts
|
|
7167
|
+
function unwrapBugReport(raw, op, isComplete) {
|
|
7168
|
+
if (raw && isComplete(raw)) return raw;
|
|
7169
|
+
const inner = raw?.data;
|
|
7170
|
+
if (inner && isComplete(inner)) return inner;
|
|
7171
|
+
const keys = raw && typeof raw === "object" ? Object.keys(raw) : [];
|
|
7172
|
+
throw new Error(
|
|
7173
|
+
`acosmi: ${op}: gateway accepted the request but the response is missing required fields (observed keys: ${keys.length > 0 ? keys.join(",") : "<none>"})`
|
|
7174
|
+
);
|
|
7175
|
+
}
|
|
7071
7176
|
Client.prototype.submitBugReport = async function(reportData, signal) {
|
|
7072
7177
|
if (reportData == null) {
|
|
7073
7178
|
throw new Error("acosmi: reportData required");
|
|
@@ -7084,7 +7189,11 @@ Client.prototype.submitBugReport = async function(reportData, signal) {
|
|
|
7084
7189
|
{ content: contentStr },
|
|
7085
7190
|
signal
|
|
7086
7191
|
);
|
|
7087
|
-
return
|
|
7192
|
+
return unwrapBugReport(
|
|
7193
|
+
result,
|
|
7194
|
+
"submitBugReport",
|
|
7195
|
+
(r) => typeof r.feedback_id === "string" && r.feedback_id.length > 0
|
|
7196
|
+
);
|
|
7088
7197
|
};
|
|
7089
7198
|
Client.prototype.getBugReport = async function(bugID, signal) {
|
|
7090
7199
|
const trimmed = bugID.trim();
|
|
@@ -7097,7 +7206,7 @@ Client.prototype.getBugReport = async function(bugID, signal) {
|
|
|
7097
7206
|
null,
|
|
7098
7207
|
signal
|
|
7099
7208
|
);
|
|
7100
|
-
return resp.
|
|
7209
|
+
return unwrapBugReport(resp, "getBugReport", (r) => typeof r.id === "string");
|
|
7101
7210
|
};
|
|
7102
7211
|
|
|
7103
7212
|
// src/subscription/client.ts
|
|
@@ -7688,6 +7797,7 @@ exports.AgentRunStreamError = AgentRunStreamError;
|
|
|
7688
7797
|
exports.AgentRunsClient = AgentRunsClient;
|
|
7689
7798
|
exports.AudienceEnum = AudienceEnum;
|
|
7690
7799
|
exports.BillingModeEnum = BillingModeEnum;
|
|
7800
|
+
exports.CHAT_REQUEST_TIMEOUT_MS = CHAT_REQUEST_TIMEOUT_MS;
|
|
7691
7801
|
exports.ChatBridgeClient = ChatBridgeClient;
|
|
7692
7802
|
exports.Client = Client;
|
|
7693
7803
|
exports.ComplianceClient = ComplianceClient;
|
|
@@ -7791,6 +7901,7 @@ exports.bucketRowIsCommercial = bucketRowIsCommercial;
|
|
|
7791
7901
|
exports.buildBetas = buildBetas;
|
|
7792
7902
|
exports.chatBridgeScopes = chatBridgeScopes;
|
|
7793
7903
|
exports.classifyComplianceError = classifyComplianceError;
|
|
7904
|
+
exports.classifySourcesEvent = classifySourcesEvent;
|
|
7794
7905
|
exports.commerceScopes = commerceScopes;
|
|
7795
7906
|
exports.completeWebAuthorizationRequest = completeWebAuthorizationRequest;
|
|
7796
7907
|
exports.complianceErrorToRetryAdvice = complianceErrorToRetryAdvice;
|