@acosmi/sdk-ts 2.19.4 → 2.19.6
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 +14 -0
- package/README.md +33 -3
- package/dist/browser/index.mjs +119 -24
- package/dist/browser/index.mjs.map +1 -1
- package/dist/index.mjs +119 -24
- 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/{format-DWA12pVT.d.cts → format-CKpXSSqY.d.cts} +22 -0
- package/dist/node/{format-DWA12pVT.d.ts → format-CKpXSSqY.d.ts} +22 -0
- package/dist/node/index.cjs +119 -23
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +84 -12
- package/dist/node/index.d.ts +84 -12
- package/dist/node/index.mjs +119 -24
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/{openai-Cuu_DPxM.d.cts → openai-ByUO-cSR.d.cts} +1 -1
- package/dist/node/{openai-DsbJUOOW.d.ts → openai-CH0wnJXv.d.ts} +1 -1
- package/package.json +1 -1
package/dist/node/index.cjs
CHANGED
|
@@ -150,6 +150,14 @@ var init_types = __esm({
|
|
|
150
150
|
});
|
|
151
151
|
|
|
152
152
|
// src/shared/errors.ts
|
|
153
|
+
function finiteNonNegative(value) {
|
|
154
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
155
|
+
}
|
|
156
|
+
function isStreamError(err) {
|
|
157
|
+
if (err == null || typeof err !== "object") return false;
|
|
158
|
+
const e = err;
|
|
159
|
+
return e.name === "StreamError" && typeof e.errorCode === "string";
|
|
160
|
+
}
|
|
153
161
|
function nullableID(value) {
|
|
154
162
|
return value === null || typeof value === "string";
|
|
155
163
|
}
|
|
@@ -359,8 +367,23 @@ var init_errors = __esm({
|
|
|
359
367
|
userMessage;
|
|
360
368
|
/** gateway 原始 error 字符串 */
|
|
361
369
|
rawError;
|
|
362
|
-
/** 客户端是否值得重试 */
|
|
370
|
+
/** 客户端是否值得重试 (= 服务端 `retryable` **且** `requestDisposition === 'not_accepted'`) */
|
|
363
371
|
retryable;
|
|
372
|
+
/**
|
|
373
|
+
* 服务端在帧上声明的 `retryable` **原值** (2.19.5 起) —— 不与 requestDisposition 合取,
|
|
374
|
+
* 缺席即 undefined。
|
|
375
|
+
*
|
|
376
|
+
* 为什么要并列存一份: 上面的 `retryable` 是两个判据的合取, 网关的流内错误帧并不总是
|
|
377
|
+
* 下发 `requestDisposition`, 于是"服务端明说可重试"会被合取成 false —— 两端各自正确,
|
|
378
|
+
* 合起来恒否。消费方要区分**「服务端明说不可重试」**(false, 一票否决) 与**「服务端没说」**
|
|
379
|
+
* (undefined, 回落到自己的本地分类表) 时, 只能读这个原值; 读 `retryable` 两种情形不可分。
|
|
380
|
+
*/
|
|
381
|
+
serverRetryable;
|
|
382
|
+
/**
|
|
383
|
+
* 服务端建议的等待秒数 (2.19.5 起)。**有限非负数**才收, 其余 (null / 负数 /
|
|
384
|
+
* NaN / Infinity / 非数字) 一律 undefined —— 宁可不给, 绝不编造等待时间。
|
|
385
|
+
*/
|
|
386
|
+
retryAfterSecs;
|
|
364
387
|
errorContractVersion;
|
|
365
388
|
faultDomain;
|
|
366
389
|
requestDisposition;
|
|
@@ -383,6 +406,8 @@ var init_errors = __esm({
|
|
|
383
406
|
this.userMessage = userMessage;
|
|
384
407
|
this.rawError = rawError;
|
|
385
408
|
this.retryable = retryable;
|
|
409
|
+
this.serverRetryable = opts.retryable;
|
|
410
|
+
this.retryAfterSecs = finiteNonNegative(opts.retryAfterSecs);
|
|
386
411
|
this.errorContractVersion = opts.errorContractVersion;
|
|
387
412
|
this.faultDomain = opts.faultDomain;
|
|
388
413
|
this.requestDisposition = opts.requestDisposition;
|
|
@@ -2197,7 +2222,10 @@ var FileTokenStore = class {
|
|
|
2197
2222
|
/**
|
|
2198
2223
|
* 跨进程临界区. 用 sidecar `<path>.lock` 文件 + O_EXCL 创建语义实现互斥:
|
|
2199
2224
|
* - 创建成功 = 持有锁; 写入 pid+timestamp 便于诊断
|
|
2200
|
-
* - 创建失败 (EEXIST) = 别的进程持锁, backoff 重试
|
|
2225
|
+
* - 创建失败 (EEXIST) = 别的进程持锁, stale 检测后 backoff 重试
|
|
2226
|
+
* - 创建失败 (Windows 的 EPERM / EBUSY) = 前一持有者的 unlink 处于 delete-pending,
|
|
2227
|
+
* 同属争用; 跳过 stale 检测直接 backoff 重试 (见 catch 内注释)。EACCES 不在其中 —
|
|
2228
|
+
* 它是真权限错误, 立即抛
|
|
2201
2229
|
* - 锁文件 mtime > staleMs = 进程崩溃残留, unlink 后重试
|
|
2202
2230
|
* - acquireTimeoutMs 超时 = 抛错 (caller 应作为 transient error 处理, 上层 retry)
|
|
2203
2231
|
*
|
|
@@ -2226,25 +2254,29 @@ ${Date.now()}
|
|
|
2226
2254
|
release = async () => {
|
|
2227
2255
|
try {
|
|
2228
2256
|
await fs.unlink(lockPath);
|
|
2229
|
-
} catch {
|
|
2257
|
+
} catch (e) {
|
|
2258
|
+
warnLockCleanupFailed("release", lockPath, e);
|
|
2230
2259
|
}
|
|
2231
2260
|
};
|
|
2232
2261
|
break;
|
|
2233
2262
|
} catch (e) {
|
|
2234
|
-
if (!
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
const st = await fs.stat(lockPath);
|
|
2238
|
-
if (Date.now() - st.mtimeMs > fileLockDefaults.staleMs) stale = true;
|
|
2239
|
-
} catch {
|
|
2240
|
-
continue;
|
|
2241
|
-
}
|
|
2242
|
-
if (stale) {
|
|
2263
|
+
if (!isLockContendedError(e)) throw e;
|
|
2264
|
+
if (!isWindowsLockBusyError(e)) {
|
|
2265
|
+
let stale = false;
|
|
2243
2266
|
try {
|
|
2244
|
-
await fs.
|
|
2267
|
+
const st = await fs.stat(lockPath);
|
|
2268
|
+
if (Date.now() - st.mtimeMs > fileLockDefaults.staleMs) stale = true;
|
|
2245
2269
|
} catch {
|
|
2270
|
+
continue;
|
|
2271
|
+
}
|
|
2272
|
+
if (stale) {
|
|
2273
|
+
try {
|
|
2274
|
+
await fs.unlink(lockPath);
|
|
2275
|
+
} catch (e2) {
|
|
2276
|
+
warnLockCleanupFailed("stale-break", lockPath, e2);
|
|
2277
|
+
}
|
|
2278
|
+
continue;
|
|
2246
2279
|
}
|
|
2247
|
-
continue;
|
|
2248
2280
|
}
|
|
2249
2281
|
if (Date.now() - startMs > fileLockDefaults.acquireTimeoutMs) {
|
|
2250
2282
|
throw new Error(
|
|
@@ -2344,12 +2376,27 @@ ${Date.now()}
|
|
|
2344
2376
|
});
|
|
2345
2377
|
}
|
|
2346
2378
|
};
|
|
2379
|
+
function warnLockCleanupFailed(stage, lockPath, e) {
|
|
2380
|
+
if (isNotExistError(e)) return;
|
|
2381
|
+
console.warn(
|
|
2382
|
+
`[acosmi-sdk] warning: unlink token file lock (${stage}) failed: ${lockPath}: ${e instanceof Error ? e.message : String(e)}`
|
|
2383
|
+
);
|
|
2384
|
+
}
|
|
2347
2385
|
function isNotExistError(e) {
|
|
2348
2386
|
if (typeof e === "object" && e !== null && "code" in e) {
|
|
2349
2387
|
return e.code === "ENOENT";
|
|
2350
2388
|
}
|
|
2351
2389
|
return false;
|
|
2352
2390
|
}
|
|
2391
|
+
function isWindowsLockBusyError(e) {
|
|
2392
|
+
if (typeof process === "undefined" || process.platform !== "win32") return false;
|
|
2393
|
+
if (typeof e !== "object" || e === null || !("code" in e)) return false;
|
|
2394
|
+
const code = e.code;
|
|
2395
|
+
return code === "EPERM" || code === "EBUSY";
|
|
2396
|
+
}
|
|
2397
|
+
function isLockContendedError(e) {
|
|
2398
|
+
return isAlreadyExistsError(e) || isWindowsLockBusyError(e);
|
|
2399
|
+
}
|
|
2353
2400
|
function isAlreadyExistsError(e) {
|
|
2354
2401
|
if (typeof e === "object" && e !== null && "code" in e) {
|
|
2355
2402
|
return e.code === "EEXIST";
|
|
@@ -2943,7 +2990,7 @@ function parseStreamError(data) {
|
|
|
2943
2990
|
let code = payload.errorCode ?? "";
|
|
2944
2991
|
const stage = payload.stage ?? "";
|
|
2945
2992
|
let message = payload.message ?? "";
|
|
2946
|
-
const retryable = payload.retryable
|
|
2993
|
+
const retryable = payload.retryable;
|
|
2947
2994
|
let rawError = "";
|
|
2948
2995
|
if (payload.error != null) {
|
|
2949
2996
|
if (typeof payload.error === "string") {
|
|
@@ -2961,6 +3008,7 @@ function parseStreamError(data) {
|
|
|
2961
3008
|
message,
|
|
2962
3009
|
rawError,
|
|
2963
3010
|
retryable,
|
|
3011
|
+
retryAfterSecs: payload.retryAfterSecs,
|
|
2964
3012
|
errorContractVersion: payload.errorContractVersion,
|
|
2965
3013
|
faultDomain: payload.faultDomain,
|
|
2966
3014
|
requestDisposition: payload.requestDisposition,
|
|
@@ -3171,6 +3219,25 @@ function notifyGatewayRequestID(cb, headers) {
|
|
|
3171
3219
|
} catch {
|
|
3172
3220
|
}
|
|
3173
3221
|
}
|
|
3222
|
+
function notifyResponseHeaders(cb, headers) {
|
|
3223
|
+
if (!cb) return;
|
|
3224
|
+
try {
|
|
3225
|
+
cb(headers);
|
|
3226
|
+
} catch {
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
function armStreamRequestTimeout(opts, parent) {
|
|
3230
|
+
const ms = opts?.requestTimeoutMs;
|
|
3231
|
+
if (typeof ms !== "number" || !Number.isFinite(ms) || ms <= 0) return void 0;
|
|
3232
|
+
return withRequestTimeout(ms, parent);
|
|
3233
|
+
}
|
|
3234
|
+
async function* disposeTimeoutWhenSettled(inner, ctl) {
|
|
3235
|
+
try {
|
|
3236
|
+
yield* inner;
|
|
3237
|
+
} finally {
|
|
3238
|
+
ctl.dispose();
|
|
3239
|
+
}
|
|
3240
|
+
}
|
|
3174
3241
|
var DEFAULT_API_TIMEOUT_MS = 6e4;
|
|
3175
3242
|
function newDeferred() {
|
|
3176
3243
|
let resolve;
|
|
@@ -4304,10 +4371,23 @@ var Client = class _Client {
|
|
|
4304
4371
|
*
|
|
4305
4372
|
* @param onUpstreamActivity 见 {@link UpstreamActivityCallback}
|
|
4306
4373
|
* @param onGatewayRequestID 见 {@link GatewayRequestIDCallback}
|
|
4374
|
+
* @param opts 见 {@link ChatStreamOptions} (2.19.5 起)
|
|
4307
4375
|
*/
|
|
4308
|
-
chatStream(modelID, req, signal, onUpstreamActivity, onGatewayRequestID) {
|
|
4376
|
+
chatStream(modelID, req, signal, onUpstreamActivity, onGatewayRequestID, opts) {
|
|
4309
4377
|
return {
|
|
4310
|
-
[Symbol.asyncIterator]: () =>
|
|
4378
|
+
[Symbol.asyncIterator]: () => {
|
|
4379
|
+
const ctl = armStreamRequestTimeout(opts, signal);
|
|
4380
|
+
const inner = this.chatStreamGen(
|
|
4381
|
+
modelID,
|
|
4382
|
+
req,
|
|
4383
|
+
ctl?.signal ?? signal,
|
|
4384
|
+
false,
|
|
4385
|
+
onUpstreamActivity,
|
|
4386
|
+
onGatewayRequestID,
|
|
4387
|
+
opts?.onResponseHeaders
|
|
4388
|
+
);
|
|
4389
|
+
return ctl ? disposeTimeoutWhenSettled(inner, ctl) : inner;
|
|
4390
|
+
}
|
|
4311
4391
|
};
|
|
4312
4392
|
}
|
|
4313
4393
|
/**
|
|
@@ -4317,13 +4397,26 @@ var Client = class _Client {
|
|
|
4317
4397
|
*
|
|
4318
4398
|
* @param onUpstreamActivity 见 {@link UpstreamActivityCallback}
|
|
4319
4399
|
* @param onGatewayRequestID 见 {@link GatewayRequestIDCallback}
|
|
4400
|
+
* @param opts 见 {@link ChatStreamOptions} (2.19.5 起)
|
|
4320
4401
|
*/
|
|
4321
|
-
chatMessagesStream(modelID, req, signal, onUpstreamActivity, onGatewayRequestID) {
|
|
4402
|
+
chatMessagesStream(modelID, req, signal, onUpstreamActivity, onGatewayRequestID, opts) {
|
|
4322
4403
|
return {
|
|
4323
|
-
[Symbol.asyncIterator]: () =>
|
|
4404
|
+
[Symbol.asyncIterator]: () => {
|
|
4405
|
+
const ctl = armStreamRequestTimeout(opts, signal);
|
|
4406
|
+
const inner = this.chatMessagesStreamGen(
|
|
4407
|
+
modelID,
|
|
4408
|
+
req,
|
|
4409
|
+
ctl?.signal ?? signal,
|
|
4410
|
+
false,
|
|
4411
|
+
onUpstreamActivity,
|
|
4412
|
+
onGatewayRequestID,
|
|
4413
|
+
opts?.onResponseHeaders
|
|
4414
|
+
);
|
|
4415
|
+
return ctl ? disposeTimeoutWhenSettled(inner, ctl) : inner;
|
|
4416
|
+
}
|
|
4324
4417
|
};
|
|
4325
4418
|
}
|
|
4326
|
-
async *chatStreamGen(modelID, req, signal, retried, onUpstreamActivity, onGatewayRequestID) {
|
|
4419
|
+
async *chatStreamGen(modelID, req, signal, retried, onUpstreamActivity, onGatewayRequestID, onResponseHeaders) {
|
|
4327
4420
|
const r = { ...req, stream: true };
|
|
4328
4421
|
const { body, adapter } = await this.buildChatRequest(modelID, r, signal);
|
|
4329
4422
|
const token = await this.ensureToken(signal);
|
|
@@ -4355,10 +4448,11 @@ var Client = class _Client {
|
|
|
4355
4448
|
`stream: unauthorized and refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}`
|
|
4356
4449
|
);
|
|
4357
4450
|
}
|
|
4358
|
-
yield* this.chatStreamGen(modelID, req, signal, true, onUpstreamActivity, onGatewayRequestID);
|
|
4451
|
+
yield* this.chatStreamGen(modelID, req, signal, true, onUpstreamActivity, onGatewayRequestID, onResponseHeaders);
|
|
4359
4452
|
return;
|
|
4360
4453
|
}
|
|
4361
4454
|
notifyGatewayRequestID(onGatewayRequestID, resp.headers);
|
|
4455
|
+
notifyResponseHeaders(onResponseHeaders, resp.headers);
|
|
4362
4456
|
if (!resp.ok) {
|
|
4363
4457
|
const bodyBytes = await readLimited(resp.body, maxErrorBodySize);
|
|
4364
4458
|
throw parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
@@ -4393,7 +4487,7 @@ var Client = class _Client {
|
|
|
4393
4487
|
}
|
|
4394
4488
|
}
|
|
4395
4489
|
}
|
|
4396
|
-
async *chatMessagesStreamGen(modelID, req, signal, retried, onUpstreamActivity, onGatewayRequestID) {
|
|
4490
|
+
async *chatMessagesStreamGen(modelID, req, signal, retried, onUpstreamActivity, onGatewayRequestID, onResponseHeaders) {
|
|
4397
4491
|
const r = { ...req, stream: true };
|
|
4398
4492
|
const { body, adapter } = await this.buildChatRequest(modelID, r, signal);
|
|
4399
4493
|
const token = await this.ensureToken(signal);
|
|
@@ -4425,10 +4519,11 @@ var Client = class _Client {
|
|
|
4425
4519
|
`messages stream: unauthorized and refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}`
|
|
4426
4520
|
);
|
|
4427
4521
|
}
|
|
4428
|
-
yield* this.chatMessagesStreamGen(modelID, req, signal, true, onUpstreamActivity, onGatewayRequestID);
|
|
4522
|
+
yield* this.chatMessagesStreamGen(modelID, req, signal, true, onUpstreamActivity, onGatewayRequestID, onResponseHeaders);
|
|
4429
4523
|
return;
|
|
4430
4524
|
}
|
|
4431
4525
|
notifyGatewayRequestID(onGatewayRequestID, resp.headers);
|
|
4526
|
+
notifyResponseHeaders(onResponseHeaders, resp.headers);
|
|
4432
4527
|
if (!resp.ok) {
|
|
4433
4528
|
const bodyBytes = await readLimited(resp.body, maxErrorBodySize);
|
|
4434
4529
|
throw parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
@@ -9114,6 +9209,7 @@ exports.isPlatform = isPlatform;
|
|
|
9114
9209
|
exports.isRegion = isRegion;
|
|
9115
9210
|
exports.isSSECommentLine = isSSECommentLine;
|
|
9116
9211
|
exports.isSSLError = isSSLError;
|
|
9212
|
+
exports.isStreamError = isStreamError;
|
|
9117
9213
|
exports.isTerminalRemoteEvent = isTerminalRemoteEvent;
|
|
9118
9214
|
exports.isUserAccessTokenRejected = isUserAccessTokenRejected;
|
|
9119
9215
|
exports.isValidTokenSet = isValidTokenSet;
|