@acosmi/sdk-ts 2.19.0 → 2.19.2
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 +16 -0
- package/README.md +2 -1
- package/dist/browser/index.mjs +1205 -160
- package/dist/browser/index.mjs.map +1 -1
- package/dist/index.mjs +1205 -160
- package/dist/index.mjs.map +1 -1
- package/dist/node/adapters/anthropic.cjs +2 -0
- 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 +2 -0
- package/dist/node/adapters/anthropic.mjs.map +1 -1
- package/dist/node/adapters/openai.cjs +122 -49
- 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 +122 -49
- package/dist/node/adapters/openai.mjs.map +1 -1
- package/dist/node/{index-C2oh157O.d.cts → index-CqxPqbsl.d.cts} +2 -1
- package/dist/node/{index-C2oh157O.d.ts → index-CqxPqbsl.d.ts} +2 -1
- package/dist/node/index.cjs +1206 -159
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +346 -151
- package/dist/node/index.d.ts +346 -151
- package/dist/node/index.mjs +1205 -160
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/{openai-DR_KhEdM.d.cts → openai-Ce85qh14.d.cts} +30 -3
- package/dist/node/{openai-Cyvi8g6B.d.ts → openai-mkTSir6E.d.ts} +30 -3
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -132,12 +132,13 @@ function parseSettlement(ev) {
|
|
|
132
132
|
callRemaining: s.callRemaining ?? -1
|
|
133
133
|
};
|
|
134
134
|
}
|
|
135
|
-
var BucketClassCommercial, BucketClassGeneric, ThinkingOff, ThinkingHigh, ThinkingMax, ThinkingHighMinMaxTokens, ThinkingMaxFallbackMaxTokens, ServerToolTypeWebSearch;
|
|
135
|
+
var BucketClassCommercial, BucketClassGeneric, ThinkingOff, ThinkingLow, ThinkingHigh, ThinkingMax, ThinkingHighMinMaxTokens, ThinkingMaxFallbackMaxTokens, ServerToolTypeWebSearch;
|
|
136
136
|
var init_types = __esm({
|
|
137
137
|
"src/models/types.ts"() {
|
|
138
138
|
BucketClassCommercial = "COMMERCIAL";
|
|
139
139
|
BucketClassGeneric = "GENERIC";
|
|
140
140
|
ThinkingOff = "off";
|
|
141
|
+
ThinkingLow = "low";
|
|
141
142
|
ThinkingHigh = "high";
|
|
142
143
|
ThinkingMax = "max";
|
|
143
144
|
ThinkingHighMinMaxTokens = 32e3;
|
|
@@ -147,6 +148,55 @@ var init_types = __esm({
|
|
|
147
148
|
});
|
|
148
149
|
|
|
149
150
|
// src/shared/errors.ts
|
|
151
|
+
function nullableID(value) {
|
|
152
|
+
return value === null || typeof value === "string";
|
|
153
|
+
}
|
|
154
|
+
function decodeGatewayErrorContract(value) {
|
|
155
|
+
if (value == null || typeof value !== "object") return null;
|
|
156
|
+
const v = value;
|
|
157
|
+
const version = v.errorContractVersion;
|
|
158
|
+
const domain = v.faultDomain;
|
|
159
|
+
const disposition = v.requestDisposition;
|
|
160
|
+
const errorCode = v.errorCode;
|
|
161
|
+
if (version !== 1 || typeof domain !== "string" || !gatewayFaultDomains.includes(domain)) return null;
|
|
162
|
+
if (typeof errorCode !== "string" || errorCode.length === 0) return null;
|
|
163
|
+
if (disposition !== "not_accepted" && disposition !== "accepted" && disposition !== "unknown") return null;
|
|
164
|
+
if (!nullableID(v.transportRequestId) || !nullableID(v.consumeRequestId) || !nullableID(v.providerRequestId)) return null;
|
|
165
|
+
if (typeof v.retryable !== "boolean") return null;
|
|
166
|
+
return {
|
|
167
|
+
errorContractVersion: 1,
|
|
168
|
+
faultDomain: domain,
|
|
169
|
+
errorCode,
|
|
170
|
+
transportRequestId: v.transportRequestId,
|
|
171
|
+
consumeRequestId: v.consumeRequestId,
|
|
172
|
+
providerRequestId: v.providerRequestId,
|
|
173
|
+
requestDisposition: disposition,
|
|
174
|
+
retryable: v.retryable
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function readGatewayErrorContract(error) {
|
|
178
|
+
const direct = decodeGatewayErrorContract(error);
|
|
179
|
+
if (direct) return direct;
|
|
180
|
+
if (error == null || typeof error !== "object") return null;
|
|
181
|
+
const e = error;
|
|
182
|
+
const axios = decodeGatewayErrorContract(e.response?.data);
|
|
183
|
+
if (axios) return axios;
|
|
184
|
+
if (typeof e.body === "string") {
|
|
185
|
+
try {
|
|
186
|
+
return decodeGatewayErrorContract(JSON.parse(e.body));
|
|
187
|
+
} catch {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
function isUserAccessTokenRejected(error) {
|
|
194
|
+
if (error == null || typeof error !== "object") return false;
|
|
195
|
+
const e = error;
|
|
196
|
+
const status = e.statusCode ?? e.response?.status;
|
|
197
|
+
const contract = readGatewayErrorContract(error);
|
|
198
|
+
return status === 401 && contract?.faultDomain === "user_auth" && contract.errorCode === "USER_ACCESS_TOKEN_INVALID" && contract.requestDisposition === "not_accepted";
|
|
199
|
+
}
|
|
150
200
|
function isWindowLimitError(err) {
|
|
151
201
|
if (!(err instanceof HTTPError)) return false;
|
|
152
202
|
if (err.errorCode === windowLimitErrorCode) return true;
|
|
@@ -174,7 +224,7 @@ function getWindowLimitStreamDetails(err) {
|
|
|
174
224
|
windowOverridable: typeof e.windowOverridable === "boolean" ? e.windowOverridable : void 0
|
|
175
225
|
};
|
|
176
226
|
}
|
|
177
|
-
var RateLimitError, BusinessError, OrderTerminalError, ModelNotFoundError, HTTPError, NetworkError, StreamError, windowLimitErrorCode, windowLimitStreamCode;
|
|
227
|
+
var RateLimitError, BusinessError, OrderTerminalError, ModelNotFoundError, HTTPError, NetworkError, StreamError, gatewayFaultDomains, windowLimitErrorCode, windowLimitStreamCode;
|
|
178
228
|
var init_errors = __esm({
|
|
179
229
|
"src/shared/errors.ts"() {
|
|
180
230
|
RateLimitError = class extends Error {
|
|
@@ -233,6 +283,13 @@ var init_errors = __esm({
|
|
|
233
283
|
* false/缺失 = 周窗/显式禁止/灰度关 (硬等待, 无豁免路径, 老网关不返回时为 undefined)。
|
|
234
284
|
*/
|
|
235
285
|
windowOverridable;
|
|
286
|
+
errorContractVersion;
|
|
287
|
+
faultDomain;
|
|
288
|
+
requestDisposition;
|
|
289
|
+
transportRequestId;
|
|
290
|
+
consumeRequestId;
|
|
291
|
+
providerRequestId;
|
|
292
|
+
retryable;
|
|
236
293
|
constructor(statusCode, opts = {}) {
|
|
237
294
|
let msg;
|
|
238
295
|
if (opts.type) {
|
|
@@ -254,6 +311,13 @@ var init_errors = __esm({
|
|
|
254
311
|
this.windowKind = opts.windowKind;
|
|
255
312
|
this.windowResetAt = opts.windowResetAt;
|
|
256
313
|
this.windowOverridable = opts.windowOverridable;
|
|
314
|
+
this.errorContractVersion = opts.errorContractVersion;
|
|
315
|
+
this.faultDomain = opts.faultDomain;
|
|
316
|
+
this.requestDisposition = opts.requestDisposition;
|
|
317
|
+
this.transportRequestId = opts.transportRequestId;
|
|
318
|
+
this.consumeRequestId = opts.consumeRequestId;
|
|
319
|
+
this.providerRequestId = opts.providerRequestId;
|
|
320
|
+
this.retryable = opts.retryable === true && opts.requestDisposition === "not_accepted";
|
|
257
321
|
}
|
|
258
322
|
};
|
|
259
323
|
NetworkError = class extends Error {
|
|
@@ -264,6 +328,7 @@ var init_errors = __esm({
|
|
|
264
328
|
cause;
|
|
265
329
|
timeout;
|
|
266
330
|
eof;
|
|
331
|
+
requestDisposition = "unknown";
|
|
267
332
|
constructor(op, url, cause, opts = {}) {
|
|
268
333
|
const causeMsg = cause instanceof Error ? cause.message : cause != null ? String(cause) : "network error";
|
|
269
334
|
super(`${op} ${url}: ${causeMsg}`);
|
|
@@ -284,6 +349,8 @@ var init_errors = __esm({
|
|
|
284
349
|
StreamError = class extends Error {
|
|
285
350
|
/** 例: "empty_response" / "rate_limit" / "overloaded" / "" */
|
|
286
351
|
code;
|
|
352
|
+
/** D23 gateway machine code; mirrors the legacy `code` field. */
|
|
353
|
+
errorCode;
|
|
287
354
|
/** 例: "provider" / "settlement" */
|
|
288
355
|
stage;
|
|
289
356
|
/** 用户友好提示 (中文); 历史字段, 与 rawError 区分 */
|
|
@@ -292,23 +359,47 @@ var init_errors = __esm({
|
|
|
292
359
|
rawError;
|
|
293
360
|
/** 客户端是否值得重试 */
|
|
294
361
|
retryable;
|
|
362
|
+
errorContractVersion;
|
|
363
|
+
faultDomain;
|
|
364
|
+
requestDisposition;
|
|
365
|
+
transportRequestId;
|
|
366
|
+
consumeRequestId;
|
|
367
|
+
providerRequestId;
|
|
295
368
|
constructor(opts = {}) {
|
|
296
369
|
const code = opts.code ?? "";
|
|
297
370
|
const stage = opts.stage ?? "";
|
|
298
371
|
const userMessage = opts.message ?? "";
|
|
299
372
|
const rawError = opts.rawError ?? "";
|
|
300
|
-
const retryable = opts.retryable
|
|
373
|
+
const retryable = opts.retryable === true && opts.requestDisposition === "not_accepted";
|
|
301
374
|
const body = rawError !== "" ? rawError : userMessage;
|
|
302
375
|
const msg = stage !== "" ? `stream failed: ${stage}: ${body}` : `stream failed: ${body}`;
|
|
303
376
|
super(msg);
|
|
304
377
|
this.name = "StreamError";
|
|
305
378
|
this.code = code;
|
|
379
|
+
this.errorCode = code;
|
|
306
380
|
this.stage = stage;
|
|
307
381
|
this.userMessage = userMessage;
|
|
308
382
|
this.rawError = rawError;
|
|
309
383
|
this.retryable = retryable;
|
|
384
|
+
this.errorContractVersion = opts.errorContractVersion;
|
|
385
|
+
this.faultDomain = opts.faultDomain;
|
|
386
|
+
this.requestDisposition = opts.requestDisposition;
|
|
387
|
+
this.transportRequestId = opts.transportRequestId;
|
|
388
|
+
this.consumeRequestId = opts.consumeRequestId;
|
|
389
|
+
this.providerRequestId = opts.providerRequestId;
|
|
310
390
|
}
|
|
311
391
|
};
|
|
392
|
+
gatewayFaultDomains = [
|
|
393
|
+
"user_auth",
|
|
394
|
+
"caller_credentials",
|
|
395
|
+
"account_quota",
|
|
396
|
+
"account_permission",
|
|
397
|
+
"provider",
|
|
398
|
+
"gateway",
|
|
399
|
+
"transport",
|
|
400
|
+
"stream_ticket",
|
|
401
|
+
"protocol"
|
|
402
|
+
];
|
|
312
403
|
windowLimitErrorCode = "WINDOW_LIMIT_EXCEEDED";
|
|
313
404
|
windowLimitStreamCode = "window_limit_exceeded";
|
|
314
405
|
}
|
|
@@ -414,6 +505,8 @@ function resolveThinkingLevel(body, req, caps) {
|
|
|
414
505
|
}
|
|
415
506
|
if (caps.supports_effort) {
|
|
416
507
|
let effortLevel = "high";
|
|
508
|
+
if (level === "low") effortLevel = "low";
|
|
509
|
+
if (level === "medium" || level === "xhigh") effortLevel = level;
|
|
417
510
|
if (level === ThinkingMax && caps.supports_max_effort) {
|
|
418
511
|
effortLevel = "max";
|
|
419
512
|
}
|
|
@@ -591,23 +684,28 @@ __export(openai_exports, {
|
|
|
591
684
|
resolveOpenAIReasoningEffort: () => resolveOpenAIReasoningEffort,
|
|
592
685
|
resolveOpenAIResponseFormat: () => resolveOpenAIResponseFormat
|
|
593
686
|
});
|
|
594
|
-
function resolveOpenAIReasoningEffort(req) {
|
|
687
|
+
function resolveOpenAIReasoningEffort(req, supportsMax = false) {
|
|
595
688
|
if (req.effort && req.effort.level !== "") {
|
|
596
689
|
switch (req.effort.level) {
|
|
597
690
|
case "low":
|
|
598
691
|
case "medium":
|
|
599
692
|
case "high":
|
|
693
|
+
case "xhigh":
|
|
600
694
|
return req.effort.level;
|
|
601
695
|
case "max":
|
|
602
|
-
return "high";
|
|
696
|
+
return supportsMax ? "max" : "high";
|
|
603
697
|
}
|
|
604
698
|
}
|
|
605
699
|
if (req.thinking) {
|
|
606
700
|
switch (req.thinking.level) {
|
|
701
|
+
case "low":
|
|
702
|
+
case "medium":
|
|
703
|
+
case "xhigh":
|
|
704
|
+
return req.thinking.level;
|
|
607
705
|
case ThinkingHigh:
|
|
608
706
|
return "high";
|
|
609
707
|
case ThinkingMax:
|
|
610
|
-
return "high";
|
|
708
|
+
return supportsMax ? "max" : "high";
|
|
611
709
|
case ThinkingOff:
|
|
612
710
|
return "";
|
|
613
711
|
}
|
|
@@ -811,10 +909,13 @@ var init_openai = __esm({
|
|
|
811
909
|
if (req.tools != null) {
|
|
812
910
|
body["tools"] = req.tools;
|
|
813
911
|
}
|
|
814
|
-
const eff = resolveOpenAIReasoningEffort(req);
|
|
912
|
+
const eff = resolveOpenAIReasoningEffort(req, _caps.supports_max_effort);
|
|
815
913
|
if (eff !== "") {
|
|
816
914
|
body["reasoning_effort"] = eff;
|
|
817
915
|
}
|
|
916
|
+
if (_caps.supports_thinking && req.thinking?.level === ThinkingOff) {
|
|
917
|
+
body["thinking"] = { type: "disabled" };
|
|
918
|
+
}
|
|
818
919
|
if (req.speed && req.speed !== "") {
|
|
819
920
|
body["speed"] = req.speed;
|
|
820
921
|
}
|
|
@@ -891,16 +992,90 @@ var init_openai = __esm({
|
|
|
891
992
|
* 可能已被 text/tool 推进的 this.blockIndex (否则 content_block_stop 索引错配)。 */
|
|
892
993
|
thinkingBlockIndex = 0;
|
|
893
994
|
textStarted = false;
|
|
894
|
-
/** OpenAI tool_call
|
|
995
|
+
/** OpenAI tool_call 键 → Anthropic block index。键正常是 `tc.index`;上游省略
|
|
996
|
+
* index 时退化为 `id:<tool_call_id>`,两者都没有时沿用上一个键(见
|
|
997
|
+
* {@link resolveToolKey})。 */
|
|
895
998
|
toolBlockIndex = /* @__PURE__ */ new Map();
|
|
896
999
|
blockIndex = 0;
|
|
1000
|
+
/** 每个 tool block 已发出的 `partial_json` 累积,用于识别「每片重发全量参数」
|
|
1001
|
+
* 的上游(见 tool_calls 分支的累计判别)。 */
|
|
1002
|
+
toolArgsAccum = /* @__PURE__ */ new Map();
|
|
1003
|
+
/** 上一次解析出的 tool 键,供缺 index 且缺 id 的后续增量沿用。 */
|
|
1004
|
+
lastToolKey = null;
|
|
1005
|
+
/** 已发出 message_delta/message_stop,避免 finish_reason 与 `[DONE]` 各收一次。 */
|
|
1006
|
+
messageClosed = false;
|
|
1007
|
+
/**
|
|
1008
|
+
* 解析一条 tool_call delta 归属的块键。
|
|
1009
|
+
*
|
|
1010
|
+
* OpenAI 流式规范里 `index` 是必填,但兼容实现常有省略。此前这里直接用
|
|
1011
|
+
* `tc.index` 做 Map 键:两个都省略 index 的 tool_call 会共用键 `undefined`,
|
|
1012
|
+
* 于是只开一个块、两段参数拼进同一条 `partial_json` 流,产出 `{…}{…}` 这种
|
|
1013
|
+
* 必然非法的 JSON。这里按「index → id → 沿用上一个」三级降级,让至少一种
|
|
1014
|
+
* 稳定标识生效。
|
|
1015
|
+
*/
|
|
1016
|
+
resolveToolKey(tc) {
|
|
1017
|
+
if (typeof tc.index === "number" && Number.isFinite(tc.index)) {
|
|
1018
|
+
this.lastToolKey = tc.index;
|
|
1019
|
+
return tc.index;
|
|
1020
|
+
}
|
|
1021
|
+
if (typeof tc.id === "string" && tc.id !== "") {
|
|
1022
|
+
const key = `id:${tc.id}`;
|
|
1023
|
+
this.lastToolKey = key;
|
|
1024
|
+
return key;
|
|
1025
|
+
}
|
|
1026
|
+
if (this.lastToolKey !== null) return this.lastToolKey;
|
|
1027
|
+
this.lastToolKey = 0;
|
|
1028
|
+
return 0;
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* 关闭仍打开的 text / thinking / tool 块,并收口 message。
|
|
1032
|
+
*
|
|
1033
|
+
* 由 `finish_reason` 分支与 `[DONE]` 分支共用:上游断流或只发 `[DONE]` 而不发
|
|
1034
|
+
* `finish_reason` 时,此前一个 `content_block_stop` 都不会发,下游拿到的是一个
|
|
1035
|
+
* 永不闭合的 tool_use 块。
|
|
1036
|
+
*/
|
|
1037
|
+
closeOpenBlocks(events, stopReason) {
|
|
1038
|
+
if (this.messageClosed) return;
|
|
1039
|
+
this.messageClosed = true;
|
|
1040
|
+
if (this.textStarted) {
|
|
1041
|
+
events.push({
|
|
1042
|
+
event: "content_block_stop",
|
|
1043
|
+
data: JSON.stringify({ type: "content_block_stop", index: this.blockIndex })
|
|
1044
|
+
});
|
|
1045
|
+
this.textStarted = false;
|
|
1046
|
+
} else if (this.thinkingStarted && !this.thinkingStopped) {
|
|
1047
|
+
this.thinkingStopped = true;
|
|
1048
|
+
events.push({
|
|
1049
|
+
event: "content_block_stop",
|
|
1050
|
+
data: JSON.stringify({ type: "content_block_stop", index: this.thinkingBlockIndex })
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
1053
|
+
for (const idx of this.toolBlockIndex.values()) {
|
|
1054
|
+
events.push({
|
|
1055
|
+
event: "content_block_stop",
|
|
1056
|
+
data: JSON.stringify({ type: "content_block_stop", index: idx })
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
events.push({
|
|
1060
|
+
event: "message_delta",
|
|
1061
|
+
data: JSON.stringify({ type: "message_delta", delta: { stop_reason: stopReason } })
|
|
1062
|
+
});
|
|
1063
|
+
events.push({
|
|
1064
|
+
event: "message_stop",
|
|
1065
|
+
data: JSON.stringify({ type: "message_stop" })
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
897
1068
|
/**
|
|
898
1069
|
* 将一行 OpenAI SSE data 转换为零或多个 Anthropic 格式 StreamEvent
|
|
899
1070
|
* 返回 { events, done }
|
|
900
1071
|
*/
|
|
901
1072
|
convert(data) {
|
|
902
1073
|
if (data === "[DONE]") {
|
|
903
|
-
|
|
1074
|
+
const events2 = [];
|
|
1075
|
+
if (this.messageStarted) {
|
|
1076
|
+
this.closeOpenBlocks(events2, "end_turn");
|
|
1077
|
+
}
|
|
1078
|
+
return { events: events2, done: true };
|
|
904
1079
|
}
|
|
905
1080
|
let chunk;
|
|
906
1081
|
try {
|
|
@@ -972,7 +1147,9 @@ var init_openai = __esm({
|
|
|
972
1147
|
events.push({ event: "content_block_delta", data: deltaJSON });
|
|
973
1148
|
}
|
|
974
1149
|
for (const tc of choice.delta.tool_calls ?? []) {
|
|
975
|
-
|
|
1150
|
+
const fn = tc.function;
|
|
1151
|
+
const toolKey = this.resolveToolKey(tc);
|
|
1152
|
+
if (!this.toolBlockIndex.has(toolKey)) {
|
|
976
1153
|
if (this.thinkingStarted && !this.thinkingStopped) {
|
|
977
1154
|
this.thinkingStopped = true;
|
|
978
1155
|
const stopJSON = JSON.stringify({
|
|
@@ -991,56 +1168,46 @@ var init_openai = __esm({
|
|
|
991
1168
|
this.blockIndex++;
|
|
992
1169
|
this.textStarted = false;
|
|
993
1170
|
}
|
|
994
|
-
this.toolBlockIndex.set(
|
|
1171
|
+
this.toolBlockIndex.set(toolKey, this.blockIndex);
|
|
995
1172
|
const blockJSON = JSON.stringify({
|
|
996
1173
|
type: "content_block_start",
|
|
997
1174
|
index: this.blockIndex,
|
|
998
1175
|
content_block: {
|
|
999
1176
|
type: "tool_use",
|
|
1000
1177
|
id: tc.id,
|
|
1001
|
-
name:
|
|
1178
|
+
name: fn?.name,
|
|
1002
1179
|
input: {}
|
|
1003
1180
|
}
|
|
1004
1181
|
});
|
|
1005
1182
|
events.push({ event: "content_block_start", data: blockJSON });
|
|
1006
1183
|
this.blockIndex++;
|
|
1007
1184
|
}
|
|
1008
|
-
if (
|
|
1009
|
-
const
|
|
1010
|
-
const
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1185
|
+
if (fn?.arguments !== void 0 && fn.arguments !== null && fn.arguments !== "") {
|
|
1186
|
+
const rawArgs = typeof fn.arguments === "string" ? fn.arguments : JSON.stringify(fn.arguments);
|
|
1187
|
+
const accum = this.toolArgsAccum.get(toolKey) ?? "";
|
|
1188
|
+
let emit = rawArgs;
|
|
1189
|
+
if (accum !== "" && rawArgs.length > accum.length && rawArgs.startsWith(accum)) {
|
|
1190
|
+
emit = rawArgs.slice(accum.length);
|
|
1191
|
+
this.toolArgsAccum.set(toolKey, rawArgs);
|
|
1192
|
+
} else {
|
|
1193
|
+
this.toolArgsAccum.set(toolKey, accum + rawArgs);
|
|
1194
|
+
}
|
|
1195
|
+
if (emit !== "") {
|
|
1196
|
+
const idx = this.toolBlockIndex.get(toolKey);
|
|
1197
|
+
const deltaJSON = JSON.stringify({
|
|
1198
|
+
type: "content_block_delta",
|
|
1199
|
+
index: idx,
|
|
1200
|
+
delta: {
|
|
1201
|
+
type: "input_json_delta",
|
|
1202
|
+
partial_json: emit
|
|
1203
|
+
}
|
|
1204
|
+
});
|
|
1205
|
+
events.push({ event: "content_block_delta", data: deltaJSON });
|
|
1206
|
+
}
|
|
1019
1207
|
}
|
|
1020
1208
|
}
|
|
1021
1209
|
if (choice.finish_reason != null && choice.finish_reason !== "") {
|
|
1022
|
-
|
|
1023
|
-
const stopJSON2 = JSON.stringify({
|
|
1024
|
-
type: "content_block_stop",
|
|
1025
|
-
index: this.blockIndex
|
|
1026
|
-
});
|
|
1027
|
-
events.push({ event: "content_block_stop", data: stopJSON2 });
|
|
1028
|
-
} else if (this.thinkingStarted && !this.thinkingStopped) {
|
|
1029
|
-
this.thinkingStopped = true;
|
|
1030
|
-
const stopJSON2 = JSON.stringify({
|
|
1031
|
-
type: "content_block_stop",
|
|
1032
|
-
index: this.thinkingBlockIndex
|
|
1033
|
-
});
|
|
1034
|
-
events.push({ event: "content_block_stop", data: stopJSON2 });
|
|
1035
|
-
}
|
|
1036
|
-
for (const idx of this.toolBlockIndex.values()) {
|
|
1037
|
-
const stopJSON2 = JSON.stringify({
|
|
1038
|
-
type: "content_block_stop",
|
|
1039
|
-
index: idx
|
|
1040
|
-
});
|
|
1041
|
-
events.push({ event: "content_block_stop", data: stopJSON2 });
|
|
1042
|
-
}
|
|
1043
|
-
let stopReason = "end_turn";
|
|
1210
|
+
let stopReason;
|
|
1044
1211
|
switch (choice.finish_reason) {
|
|
1045
1212
|
case "tool_calls":
|
|
1046
1213
|
stopReason = "tool_use";
|
|
@@ -1048,14 +1215,13 @@ var init_openai = __esm({
|
|
|
1048
1215
|
case "length":
|
|
1049
1216
|
stopReason = "max_tokens";
|
|
1050
1217
|
break;
|
|
1218
|
+
case "stop":
|
|
1219
|
+
stopReason = "end_turn";
|
|
1220
|
+
break;
|
|
1221
|
+
default:
|
|
1222
|
+
stopReason = choice.finish_reason;
|
|
1051
1223
|
}
|
|
1052
|
-
|
|
1053
|
-
type: "message_delta",
|
|
1054
|
-
delta: { stop_reason: stopReason }
|
|
1055
|
-
});
|
|
1056
|
-
events.push({ event: "message_delta", data: deltaJSON });
|
|
1057
|
-
const stopJSON = JSON.stringify({ type: "message_stop" });
|
|
1058
|
-
events.push({ event: "message_stop", data: stopJSON });
|
|
1224
|
+
this.closeOpenBlocks(events, stopReason);
|
|
1059
1225
|
}
|
|
1060
1226
|
return { events, done: false };
|
|
1061
1227
|
}
|
|
@@ -1116,6 +1282,560 @@ var init_adapters = __esm({
|
|
|
1116
1282
|
}
|
|
1117
1283
|
});
|
|
1118
1284
|
|
|
1285
|
+
// src/core/credentials.ts
|
|
1286
|
+
var uuid = () => globalThis.crypto.randomUUID();
|
|
1287
|
+
var pause = () => new Promise((resolve) => setTimeout(resolve, 25));
|
|
1288
|
+
var abort = (signal) => {
|
|
1289
|
+
if (signal?.aborted) throw new Error("aborted");
|
|
1290
|
+
};
|
|
1291
|
+
var sameRequestOwner = (snapshot, expected) => snapshot.storeInstanceId === expected.storeInstanceId && snapshot.authSessionId === expected.authSessionId && snapshot.principal?.issuer === expected.principal?.issuer && snapshot.principal?.subject === expected.principal?.subject && snapshot.principal?.organizationId === expected.principal?.organizationId;
|
|
1292
|
+
var CredentialLifecycle = class {
|
|
1293
|
+
constructor(store, protocol) {
|
|
1294
|
+
this.store = store;
|
|
1295
|
+
this.protocol = protocol;
|
|
1296
|
+
}
|
|
1297
|
+
store;
|
|
1298
|
+
protocol;
|
|
1299
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1300
|
+
notificationKey = "";
|
|
1301
|
+
observations = /* @__PURE__ */ new Map();
|
|
1302
|
+
read(signal) {
|
|
1303
|
+
return this.store.readSnapshot(signal);
|
|
1304
|
+
}
|
|
1305
|
+
subscribe(listener) {
|
|
1306
|
+
this.listeners.add(listener);
|
|
1307
|
+
return () => {
|
|
1308
|
+
this.listeners.delete(listener);
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
async notify(snapshot) {
|
|
1312
|
+
let current;
|
|
1313
|
+
try {
|
|
1314
|
+
current = await this.read();
|
|
1315
|
+
} catch {
|
|
1316
|
+
return;
|
|
1317
|
+
}
|
|
1318
|
+
if (current.storeInstanceId !== snapshot.storeInstanceId || current.revision !== snapshot.revision)
|
|
1319
|
+
return;
|
|
1320
|
+
const projection = {
|
|
1321
|
+
storeInstanceId: snapshot.storeInstanceId,
|
|
1322
|
+
authorityConfig: snapshot.authorityConfig && {
|
|
1323
|
+
serverURL: snapshot.authorityConfig.serverURL,
|
|
1324
|
+
issuer: snapshot.authorityConfig.issuer,
|
|
1325
|
+
oauthProfile: "desktop",
|
|
1326
|
+
authContractVersion: 2,
|
|
1327
|
+
errorContractVersion: 1
|
|
1328
|
+
},
|
|
1329
|
+
revision: snapshot.revision,
|
|
1330
|
+
authSessionId: snapshot.authSessionId,
|
|
1331
|
+
credentialState: snapshot.credentialState,
|
|
1332
|
+
reason: snapshot.reason,
|
|
1333
|
+
principal: snapshot.principal && {
|
|
1334
|
+
issuer: snapshot.principal.issuer,
|
|
1335
|
+
subject: snapshot.principal.subject,
|
|
1336
|
+
organizationId: snapshot.principal.organizationId
|
|
1337
|
+
},
|
|
1338
|
+
refreshOperation: snapshot.refreshOperation && {
|
|
1339
|
+
operationId: snapshot.refreshOperation.operationId,
|
|
1340
|
+
sessionId: snapshot.refreshOperation.sessionId,
|
|
1341
|
+
baseRevision: snapshot.refreshOperation.baseRevision,
|
|
1342
|
+
phase: snapshot.refreshOperation.phase,
|
|
1343
|
+
returnState: snapshot.refreshOperation.returnState,
|
|
1344
|
+
startedAt: snapshot.refreshOperation.startedAt,
|
|
1345
|
+
dispatchedAt: snapshot.refreshOperation.dispatchedAt,
|
|
1346
|
+
deadlineAt: snapshot.refreshOperation.deadlineAt
|
|
1347
|
+
},
|
|
1348
|
+
loginAttempt: snapshot.loginAttempt && {
|
|
1349
|
+
attemptId: snapshot.loginAttempt.attemptId,
|
|
1350
|
+
baseSessionId: snapshot.loginAttempt.baseSessionId,
|
|
1351
|
+
startedAt: snapshot.loginAttempt.startedAt
|
|
1352
|
+
},
|
|
1353
|
+
lastMutation: snapshot.lastMutation && {
|
|
1354
|
+
mutationId: snapshot.lastMutation.mutationId,
|
|
1355
|
+
operationId: snapshot.lastMutation.operationId,
|
|
1356
|
+
resultRevision: snapshot.lastMutation.resultRevision
|
|
1357
|
+
},
|
|
1358
|
+
lastLoginAttemptId: snapshot.lastLoginAttemptId,
|
|
1359
|
+
verifiedIdentity: snapshot.verifiedIdentity && {
|
|
1360
|
+
authSessionId: snapshot.verifiedIdentity.authSessionId,
|
|
1361
|
+
principal: {
|
|
1362
|
+
issuer: snapshot.verifiedIdentity.principal.issuer,
|
|
1363
|
+
subject: snapshot.verifiedIdentity.principal.subject,
|
|
1364
|
+
organizationId: snapshot.verifiedIdentity.principal.organizationId
|
|
1365
|
+
},
|
|
1366
|
+
displayName: snapshot.verifiedIdentity.displayName,
|
|
1367
|
+
avatarUrl: snapshot.verifiedIdentity.avatarUrl,
|
|
1368
|
+
email: snapshot.verifiedIdentity.email,
|
|
1369
|
+
imageUrl: snapshot.verifiedIdentity.imageUrl,
|
|
1370
|
+
accountCreatedAt: snapshot.verifiedIdentity.accountCreatedAt,
|
|
1371
|
+
requiresPhoneBinding: snapshot.verifiedIdentity.requiresPhoneBinding,
|
|
1372
|
+
hasExtraUsageEnabled: snapshot.verifiedIdentity.hasExtraUsageEnabled,
|
|
1373
|
+
billingType: snapshot.verifiedIdentity.billingType,
|
|
1374
|
+
subscriptionCreatedAt: snapshot.verifiedIdentity.subscriptionCreatedAt,
|
|
1375
|
+
rateLimitTier: snapshot.verifiedIdentity.rateLimitTier,
|
|
1376
|
+
organizationName: snapshot.verifiedIdentity.organizationName,
|
|
1377
|
+
verifiedAt: snapshot.verifiedIdentity.verifiedAt
|
|
1378
|
+
}
|
|
1379
|
+
};
|
|
1380
|
+
const key = JSON.stringify({ ...projection, revision: void 0, lastMutation: void 0 });
|
|
1381
|
+
if (key === this.notificationKey) return;
|
|
1382
|
+
this.notificationKey = key;
|
|
1383
|
+
for (const listener of this.listeners) {
|
|
1384
|
+
try {
|
|
1385
|
+
listener(structuredClone(projection));
|
|
1386
|
+
} catch {
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
async reconcile(signal) {
|
|
1391
|
+
const s = await this.read(signal);
|
|
1392
|
+
await this.notify(s);
|
|
1393
|
+
return s;
|
|
1394
|
+
}
|
|
1395
|
+
cas(s, changes, mutationId = uuid(), signal) {
|
|
1396
|
+
return this.store.compareAndSwap(
|
|
1397
|
+
{
|
|
1398
|
+
storeInstanceId: s.storeInstanceId,
|
|
1399
|
+
revision: s.revision,
|
|
1400
|
+
authSessionId: s.authSessionId,
|
|
1401
|
+
state: s.credentialState,
|
|
1402
|
+
operationId: s.refreshOperation?.operationId ?? s.loginAttempt?.attemptId ?? null
|
|
1403
|
+
},
|
|
1404
|
+
{ ...s, ...changes },
|
|
1405
|
+
mutationId,
|
|
1406
|
+
signal
|
|
1407
|
+
);
|
|
1408
|
+
}
|
|
1409
|
+
async commit(s, changes, signal) {
|
|
1410
|
+
const r = await this.cas(s, changes, uuid(), signal);
|
|
1411
|
+
if (r.status === "storage_error") throw new Error("storage_unavailable");
|
|
1412
|
+
if (r.status === "committed") await this.notify(r.snapshot);
|
|
1413
|
+
return r;
|
|
1414
|
+
}
|
|
1415
|
+
async metadata(s, signal) {
|
|
1416
|
+
const m = await this.protocol.metadata(signal);
|
|
1417
|
+
if (m.crabcode_auth_contract_version !== 2 || m.gateway_error_contract_version !== 1 || !m.issuer)
|
|
1418
|
+
throw new Error("auth_contract_unsupported");
|
|
1419
|
+
if (s.authorityConfig && (s.authorityConfig.serverURL !== this.protocol.serverURL || s.authorityConfig.issuer !== m.issuer || s.authorityConfig.oauthProfile !== "desktop" || s.authorityConfig.authContractVersion !== 2 || s.authorityConfig.errorContractVersion !== 1))
|
|
1420
|
+
throw new Error("auth_contract_unsupported");
|
|
1421
|
+
return m;
|
|
1422
|
+
}
|
|
1423
|
+
async reserveLogin(signal) {
|
|
1424
|
+
const attemptId = uuid();
|
|
1425
|
+
let reserved;
|
|
1426
|
+
for (; ; ) {
|
|
1427
|
+
abort(signal);
|
|
1428
|
+
const s = await this.read(signal);
|
|
1429
|
+
if (s.credentialState !== "signed_out") throw new Error("local_logout_required");
|
|
1430
|
+
const r = await this.commit(s, { loginAttempt: { attemptId, baseSessionId: s.authSessionId, startedAt: (/* @__PURE__ */ new Date()).toISOString() } }, signal);
|
|
1431
|
+
if (r.status === "committed") {
|
|
1432
|
+
reserved = r.snapshot;
|
|
1433
|
+
break;
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
try {
|
|
1437
|
+
const m = await this.metadata(reserved, signal);
|
|
1438
|
+
for (; ; ) {
|
|
1439
|
+
abort(signal);
|
|
1440
|
+
const current = await this.read(signal);
|
|
1441
|
+
if (current.storeInstanceId !== reserved.storeInstanceId || current.loginAttempt?.attemptId !== attemptId) throw new Error("superseded");
|
|
1442
|
+
if (current.authorityConfig) return { attemptId, metadata: m };
|
|
1443
|
+
const r = await this.commit(current, { authorityConfig: { serverURL: this.protocol.serverURL, issuer: m.issuer, oauthProfile: "desktop", authContractVersion: 2, errorContractVersion: 1 } }, signal);
|
|
1444
|
+
if (r.status === "committed") return { attemptId, metadata: m };
|
|
1445
|
+
}
|
|
1446
|
+
} catch (error) {
|
|
1447
|
+
await this.cancelLogin(attemptId);
|
|
1448
|
+
throw error;
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
async installLogin(attemptId, tokens, signal) {
|
|
1452
|
+
this.validateTokens(tokens);
|
|
1453
|
+
for (; ; ) {
|
|
1454
|
+
abort(signal);
|
|
1455
|
+
const s = await this.read(signal);
|
|
1456
|
+
if (s.loginAttempt?.attemptId !== attemptId || s.loginAttempt.baseSessionId !== s.authSessionId)
|
|
1457
|
+
throw new Error("superseded");
|
|
1458
|
+
const r = await this.commit(
|
|
1459
|
+
s,
|
|
1460
|
+
{
|
|
1461
|
+
authSessionId: uuid(),
|
|
1462
|
+
tokenSet: tokens,
|
|
1463
|
+
credentialState: "pending_identity",
|
|
1464
|
+
principal: null,
|
|
1465
|
+
verifiedIdentity: null,
|
|
1466
|
+
loginAttempt: null,
|
|
1467
|
+
lastLoginAttemptId: attemptId,
|
|
1468
|
+
reason: "identity_unavailable"
|
|
1469
|
+
},
|
|
1470
|
+
signal
|
|
1471
|
+
);
|
|
1472
|
+
if (r.status === "committed") return this.bindIdentity(r.snapshot.authSessionId, signal);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
async assertLogin(attemptId, signal) {
|
|
1476
|
+
abort(signal);
|
|
1477
|
+
const s = await this.read(signal);
|
|
1478
|
+
if (s.loginAttempt?.attemptId !== attemptId) throw new Error("superseded");
|
|
1479
|
+
}
|
|
1480
|
+
async cancelLogin(attemptId) {
|
|
1481
|
+
const s = await this.read();
|
|
1482
|
+
if (s.loginAttempt?.attemptId === attemptId) await this.commit(s, { loginAttempt: null });
|
|
1483
|
+
}
|
|
1484
|
+
validateTokens(t) {
|
|
1485
|
+
if (!t.access_token?.trim() || !t.refresh_token?.trim() || !t.client_id?.trim() || t.server_url !== this.protocol.serverURL || !Number.isFinite(Date.parse(t.expires_at)) || Date.parse(t.expires_at) <= Date.now())
|
|
1486
|
+
throw new Error("invalid_response");
|
|
1487
|
+
}
|
|
1488
|
+
usable(s) {
|
|
1489
|
+
return !!s.tokenSet && Date.parse(s.tokenSet.expires_at) > Date.now() + 3e5;
|
|
1490
|
+
}
|
|
1491
|
+
async bindIdentity(sessionId, signal) {
|
|
1492
|
+
const s = await this.ensureSnapshot(signal, void 0, true);
|
|
1493
|
+
if (s.authSessionId !== sessionId) throw new Error("superseded");
|
|
1494
|
+
if (s.credentialState === "ready") return s;
|
|
1495
|
+
await this.metadata(s, signal);
|
|
1496
|
+
const beforeProfile = await this.read(signal);
|
|
1497
|
+
if (beforeProfile.storeInstanceId !== s.storeInstanceId || beforeProfile.authSessionId !== sessionId || beforeProfile.revision !== s.revision || beforeProfile.credentialState !== "pending_identity")
|
|
1498
|
+
throw new Error("superseded");
|
|
1499
|
+
let identity;
|
|
1500
|
+
try {
|
|
1501
|
+
identity = await this.protocol.profile(s.tokenSet, signal);
|
|
1502
|
+
} catch (error) {
|
|
1503
|
+
const message = error instanceof Error ? error.message : "";
|
|
1504
|
+
if (message === "invalid_scope" || message === "auth_contract_unsupported")
|
|
1505
|
+
await this.commit(s, { credentialState: "configuration_error", reason: message });
|
|
1506
|
+
throw error;
|
|
1507
|
+
}
|
|
1508
|
+
abort(signal);
|
|
1509
|
+
const current = await this.read(signal);
|
|
1510
|
+
if (current.storeInstanceId !== s.storeInstanceId || current.authSessionId !== sessionId || current.revision !== s.revision)
|
|
1511
|
+
throw new Error("superseded");
|
|
1512
|
+
if (!identity.subject) throw new Error("invalid_response");
|
|
1513
|
+
const principal = {
|
|
1514
|
+
issuer: s.authorityConfig.issuer,
|
|
1515
|
+
subject: identity.subject,
|
|
1516
|
+
organizationId: identity.organizationId
|
|
1517
|
+
};
|
|
1518
|
+
const r = await this.commit(
|
|
1519
|
+
s,
|
|
1520
|
+
{
|
|
1521
|
+
principal,
|
|
1522
|
+
verifiedIdentity: {
|
|
1523
|
+
authSessionId: sessionId,
|
|
1524
|
+
principal,
|
|
1525
|
+
displayName: identity.displayName,
|
|
1526
|
+
avatarUrl: identity.avatarUrl,
|
|
1527
|
+
email: identity.email,
|
|
1528
|
+
imageUrl: identity.imageUrl,
|
|
1529
|
+
accountCreatedAt: identity.accountCreatedAt,
|
|
1530
|
+
requiresPhoneBinding: identity.requiresPhoneBinding,
|
|
1531
|
+
hasExtraUsageEnabled: identity.hasExtraUsageEnabled,
|
|
1532
|
+
billingType: identity.billingType,
|
|
1533
|
+
subscriptionCreatedAt: identity.subscriptionCreatedAt,
|
|
1534
|
+
rateLimitTier: identity.rateLimitTier,
|
|
1535
|
+
organizationName: identity.organizationName,
|
|
1536
|
+
verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1537
|
+
},
|
|
1538
|
+
credentialState: "ready",
|
|
1539
|
+
reason: null
|
|
1540
|
+
},
|
|
1541
|
+
signal
|
|
1542
|
+
);
|
|
1543
|
+
if (r.status !== "committed") throw new Error("superseded");
|
|
1544
|
+
return r.snapshot;
|
|
1545
|
+
}
|
|
1546
|
+
async ensure(signal, rejected, expected) {
|
|
1547
|
+
const snapshot = await this.ensureSnapshot(signal, rejected, false, expected);
|
|
1548
|
+
this.observations.set(snapshot.tokenSet.access_token, snapshot);
|
|
1549
|
+
if (this.observations.size > 128)
|
|
1550
|
+
this.observations.delete(this.observations.keys().next().value);
|
|
1551
|
+
return snapshot.tokenSet.access_token;
|
|
1552
|
+
}
|
|
1553
|
+
async forceRefresh(signal, rejectedToken, expected) {
|
|
1554
|
+
const rejected = rejectedToken ? this.observations.get(rejectedToken) : await this.read(signal);
|
|
1555
|
+
if (rejectedToken && !rejected) throw new Error("credential_observation_unavailable");
|
|
1556
|
+
return this.ensure(signal, rejected, expected);
|
|
1557
|
+
}
|
|
1558
|
+
async ensureSnapshot(signal, rejected, pending = false, expected) {
|
|
1559
|
+
let session;
|
|
1560
|
+
let instance;
|
|
1561
|
+
let initialRevision;
|
|
1562
|
+
let refreshed = false;
|
|
1563
|
+
let initialAccess;
|
|
1564
|
+
for (; ; ) {
|
|
1565
|
+
abort(signal);
|
|
1566
|
+
const s = await this.read(signal);
|
|
1567
|
+
if (expected && !sameRequestOwner(s, expected)) throw new Error("superseded");
|
|
1568
|
+
if (s.authorityConfig && s.authorityConfig.serverURL !== this.protocol.serverURL)
|
|
1569
|
+
throw new Error("auth_contract_unsupported");
|
|
1570
|
+
if (session === void 0) {
|
|
1571
|
+
session = s.authSessionId;
|
|
1572
|
+
instance = s.storeInstanceId;
|
|
1573
|
+
initialRevision = s.revision;
|
|
1574
|
+
initialAccess = s.tokenSet?.access_token;
|
|
1575
|
+
}
|
|
1576
|
+
if (s.storeInstanceId !== instance || s.authSessionId !== session || rejected && (s.authSessionId !== rejected.authSessionId || s.storeInstanceId !== rejected.storeInstanceId))
|
|
1577
|
+
throw new Error("superseded");
|
|
1578
|
+
if (s.credentialState === "refresh_dispatched") {
|
|
1579
|
+
if (Date.now() >= Date.parse(s.refreshOperation.deadlineAt))
|
|
1580
|
+
await this.commit(s, {
|
|
1581
|
+
credentialState: "reauth_required",
|
|
1582
|
+
tokenSet: null,
|
|
1583
|
+
refreshOperation: null,
|
|
1584
|
+
reason: "refresh_outcome_unknown"
|
|
1585
|
+
});
|
|
1586
|
+
else await pause();
|
|
1587
|
+
continue;
|
|
1588
|
+
}
|
|
1589
|
+
if (s.credentialState === "refresh_reserved") {
|
|
1590
|
+
if (Date.now() >= Date.parse(s.refreshOperation.startedAt) + 3e4)
|
|
1591
|
+
await this.commit(s, {
|
|
1592
|
+
credentialState: s.refreshOperation.returnState,
|
|
1593
|
+
refreshOperation: null
|
|
1594
|
+
});
|
|
1595
|
+
else await pause();
|
|
1596
|
+
continue;
|
|
1597
|
+
}
|
|
1598
|
+
if (s.credentialState !== "ready" && !(pending && s.credentialState === "pending_identity"))
|
|
1599
|
+
throw new Error(`credential_unavailable:${s.credentialState}:${s.reason ?? ""}`);
|
|
1600
|
+
const live = !!s.tokenSet && Date.parse(s.tokenSet.expires_at) > Date.now();
|
|
1601
|
+
if (live && (refreshed || s.revision !== (rejected?.revision ?? initialRevision) && (rejected !== void 0 || s.tokenSet.access_token !== initialAccess)))
|
|
1602
|
+
return s;
|
|
1603
|
+
if (this.usable(s) && !rejected) return s;
|
|
1604
|
+
const metadata = await this.metadata(s, signal);
|
|
1605
|
+
abort(signal);
|
|
1606
|
+
const operationId = uuid();
|
|
1607
|
+
const r = await this.commit(
|
|
1608
|
+
s,
|
|
1609
|
+
{
|
|
1610
|
+
credentialState: "refresh_reserved",
|
|
1611
|
+
refreshOperation: {
|
|
1612
|
+
operationId,
|
|
1613
|
+
sessionId: s.authSessionId,
|
|
1614
|
+
baseRevision: s.revision,
|
|
1615
|
+
phase: "reserved",
|
|
1616
|
+
returnState: s.credentialState,
|
|
1617
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1618
|
+
dispatchedAt: null,
|
|
1619
|
+
deadlineAt: null
|
|
1620
|
+
}
|
|
1621
|
+
},
|
|
1622
|
+
signal
|
|
1623
|
+
);
|
|
1624
|
+
if (r.status !== "committed") continue;
|
|
1625
|
+
const owner = this.refresh(r.snapshot, metadata);
|
|
1626
|
+
await this.wait(owner, signal);
|
|
1627
|
+
refreshed = true;
|
|
1628
|
+
rejected = void 0;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
wait(promise, signal) {
|
|
1632
|
+
if (!signal) return promise;
|
|
1633
|
+
return new Promise((resolve, reject) => {
|
|
1634
|
+
const onAbort = () => {
|
|
1635
|
+
signal.removeEventListener("abort", onAbort);
|
|
1636
|
+
reject(new Error("aborted"));
|
|
1637
|
+
};
|
|
1638
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1639
|
+
promise.then(
|
|
1640
|
+
(value) => {
|
|
1641
|
+
signal.removeEventListener("abort", onAbort);
|
|
1642
|
+
resolve(value);
|
|
1643
|
+
},
|
|
1644
|
+
(error) => {
|
|
1645
|
+
signal.removeEventListener("abort", onAbort);
|
|
1646
|
+
reject(error);
|
|
1647
|
+
}
|
|
1648
|
+
);
|
|
1649
|
+
if (signal.aborted) onAbort();
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1652
|
+
async refresh(reserved, metadata) {
|
|
1653
|
+
const dispatchedAt = Date.now();
|
|
1654
|
+
const r = await this.commit(reserved, {
|
|
1655
|
+
credentialState: "refresh_dispatched",
|
|
1656
|
+
refreshOperation: {
|
|
1657
|
+
...reserved.refreshOperation,
|
|
1658
|
+
phase: "dispatched",
|
|
1659
|
+
dispatchedAt: new Date(dispatchedAt).toISOString(),
|
|
1660
|
+
deadlineAt: new Date(dispatchedAt + 3e4).toISOString()
|
|
1661
|
+
}
|
|
1662
|
+
});
|
|
1663
|
+
if (r.status !== "committed") return;
|
|
1664
|
+
const s = r.snapshot;
|
|
1665
|
+
const ctl = new AbortController();
|
|
1666
|
+
const timeout = setTimeout(() => ctl.abort(), 3e4);
|
|
1667
|
+
let tokens;
|
|
1668
|
+
try {
|
|
1669
|
+
const result = await this.wait(
|
|
1670
|
+
(async () => {
|
|
1671
|
+
const response = await this.protocol.fetch(metadata.token_endpoint, {
|
|
1672
|
+
method: "POST",
|
|
1673
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
1674
|
+
body: new URLSearchParams({
|
|
1675
|
+
grant_type: "refresh_token",
|
|
1676
|
+
client_id: s.tokenSet.client_id,
|
|
1677
|
+
refresh_token: s.tokenSet.refresh_token
|
|
1678
|
+
}),
|
|
1679
|
+
signal: ctl.signal
|
|
1680
|
+
});
|
|
1681
|
+
const body2 = await response.json();
|
|
1682
|
+
return { response, body: body2 };
|
|
1683
|
+
})(),
|
|
1684
|
+
ctl.signal
|
|
1685
|
+
);
|
|
1686
|
+
if (!result.response.ok) {
|
|
1687
|
+
const code = result.body.error;
|
|
1688
|
+
let reason = "refresh_outcome_unknown";
|
|
1689
|
+
let state = "reauth_required";
|
|
1690
|
+
if (code === "invalid_grant") reason = code;
|
|
1691
|
+
else if (["invalid_client", "invalid_scope", "unsupported_grant_type"].includes(code)) {
|
|
1692
|
+
reason = code;
|
|
1693
|
+
state = "configuration_error";
|
|
1694
|
+
} else if (result.body.rotationOutcome === "not_committed" && ["temporarily_unavailable", "server_error"].includes(code)) {
|
|
1695
|
+
await this.commit(s, {
|
|
1696
|
+
credentialState: s.refreshOperation.returnState,
|
|
1697
|
+
refreshOperation: null
|
|
1698
|
+
});
|
|
1699
|
+
throw new Error("refresh_temporarily_unavailable");
|
|
1700
|
+
}
|
|
1701
|
+
await this.commit(s, {
|
|
1702
|
+
credentialState: state,
|
|
1703
|
+
tokenSet: null,
|
|
1704
|
+
refreshOperation: null,
|
|
1705
|
+
reason
|
|
1706
|
+
});
|
|
1707
|
+
throw new Error(reason);
|
|
1708
|
+
}
|
|
1709
|
+
const body = result.body;
|
|
1710
|
+
if (!Number.isFinite(body.expires_in) || body.expires_in <= 0)
|
|
1711
|
+
throw new Error("invalid_response");
|
|
1712
|
+
tokens = {
|
|
1713
|
+
...s.tokenSet,
|
|
1714
|
+
access_token: body.access_token,
|
|
1715
|
+
refresh_token: body.refresh_token,
|
|
1716
|
+
expires_at: new Date(Date.now() + body.expires_in * 1e3).toISOString(),
|
|
1717
|
+
scope: body.scope ?? s.tokenSet.scope
|
|
1718
|
+
};
|
|
1719
|
+
this.validateTokens(tokens);
|
|
1720
|
+
} catch (error) {
|
|
1721
|
+
await this.commit(s, {
|
|
1722
|
+
credentialState: "reauth_required",
|
|
1723
|
+
tokenSet: null,
|
|
1724
|
+
refreshOperation: null,
|
|
1725
|
+
reason: "refresh_outcome_unknown"
|
|
1726
|
+
});
|
|
1727
|
+
throw error;
|
|
1728
|
+
} finally {
|
|
1729
|
+
clearTimeout(timeout);
|
|
1730
|
+
}
|
|
1731
|
+
const started = performance.now(), mutationId = uuid();
|
|
1732
|
+
for (; ; ) {
|
|
1733
|
+
if (Date.now() >= Date.parse(s.refreshOperation.deadlineAt)) {
|
|
1734
|
+
await this.commit(s, {
|
|
1735
|
+
credentialState: "reauth_required",
|
|
1736
|
+
tokenSet: null,
|
|
1737
|
+
refreshOperation: null,
|
|
1738
|
+
reason: "refresh_outcome_unknown"
|
|
1739
|
+
});
|
|
1740
|
+
void this.revoke(tokens, metadata);
|
|
1741
|
+
throw new Error("refresh_outcome_unknown");
|
|
1742
|
+
}
|
|
1743
|
+
const result = await this.cas(
|
|
1744
|
+
s,
|
|
1745
|
+
{
|
|
1746
|
+
tokenSet: tokens,
|
|
1747
|
+
credentialState: s.refreshOperation.returnState,
|
|
1748
|
+
refreshOperation: null
|
|
1749
|
+
},
|
|
1750
|
+
mutationId
|
|
1751
|
+
);
|
|
1752
|
+
if (result.status === "committed") {
|
|
1753
|
+
await this.notify(result.snapshot);
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
if (result.status === "superseded") {
|
|
1757
|
+
void this.revoke(tokens, metadata);
|
|
1758
|
+
return;
|
|
1759
|
+
}
|
|
1760
|
+
if (performance.now() - started >= 2e3) throw new Error("credential_persist_failed");
|
|
1761
|
+
await pause();
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
async revoke(tokens, metadata, authority) {
|
|
1765
|
+
const ctl = new AbortController();
|
|
1766
|
+
const timer = setTimeout(() => ctl.abort(), 3e4);
|
|
1767
|
+
try {
|
|
1768
|
+
const m = metadata ?? await this.wait(authority ? this.metadata(authority, ctl.signal) : this.protocol.metadata(ctl.signal), ctl.signal);
|
|
1769
|
+
if (!m.revocation_endpoint) return "unsupported";
|
|
1770
|
+
const response = await this.wait(this.protocol.fetch(m.revocation_endpoint, {
|
|
1771
|
+
method: "POST",
|
|
1772
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
1773
|
+
body: new URLSearchParams({ token: tokens.refresh_token, token_type_hint: "refresh_token" }),
|
|
1774
|
+
signal: ctl.signal
|
|
1775
|
+
}), ctl.signal);
|
|
1776
|
+
return response.ok ? "confirmed" : "failed";
|
|
1777
|
+
} catch {
|
|
1778
|
+
return "failed";
|
|
1779
|
+
} finally {
|
|
1780
|
+
clearTimeout(timer);
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
async logout(signal, expected) {
|
|
1784
|
+
let s = await this.read(signal);
|
|
1785
|
+
if (expected && (s.storeInstanceId !== expected.storeInstanceId || s.authSessionId !== expected.authSessionId)) {
|
|
1786
|
+
return {
|
|
1787
|
+
logoutOperationId: uuid(),
|
|
1788
|
+
expectedAuthSessionId: expected.authSessionId,
|
|
1789
|
+
storeInstanceId: expected.storeInstanceId,
|
|
1790
|
+
revision: s.revision,
|
|
1791
|
+
status: "superseded"
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1794
|
+
const session = s.authSessionId, instance = s.storeInstanceId, started = performance.now(), logoutOperationId = uuid();
|
|
1795
|
+
const receipt = () => ({
|
|
1796
|
+
logoutOperationId,
|
|
1797
|
+
expectedAuthSessionId: session,
|
|
1798
|
+
storeInstanceId: instance,
|
|
1799
|
+
revision: s.revision
|
|
1800
|
+
});
|
|
1801
|
+
for (; ; ) {
|
|
1802
|
+
abort(signal);
|
|
1803
|
+
if (s.storeInstanceId !== instance || s.authSessionId !== session)
|
|
1804
|
+
return { ...receipt(), status: "superseded" };
|
|
1805
|
+
if (s.credentialState === "signed_out" && !s.loginAttempt)
|
|
1806
|
+
return { ...receipt(), status: "already_signed_out" };
|
|
1807
|
+
const r = await this.cas(
|
|
1808
|
+
s,
|
|
1809
|
+
{
|
|
1810
|
+
credentialState: "signed_out",
|
|
1811
|
+
authSessionId: null,
|
|
1812
|
+
principal: null,
|
|
1813
|
+
tokenSet: null,
|
|
1814
|
+
refreshOperation: null,
|
|
1815
|
+
loginAttempt: null,
|
|
1816
|
+
lastLoginAttemptId: null,
|
|
1817
|
+
verifiedIdentity: null,
|
|
1818
|
+
reason: null
|
|
1819
|
+
},
|
|
1820
|
+
logoutOperationId,
|
|
1821
|
+
signal
|
|
1822
|
+
);
|
|
1823
|
+
if (r.status === "committed") {
|
|
1824
|
+
await this.notify(r.snapshot);
|
|
1825
|
+
return {
|
|
1826
|
+
...receipt(),
|
|
1827
|
+
revision: r.snapshot.revision,
|
|
1828
|
+
status: "committed",
|
|
1829
|
+
revocation: s.tokenSet ? this.revoke(s.tokenSet, void 0, s) : Promise.resolve("unsupported")
|
|
1830
|
+
};
|
|
1831
|
+
}
|
|
1832
|
+
if (performance.now() - started >= 2e3) throw new Error("storage_busy");
|
|
1833
|
+
await pause();
|
|
1834
|
+
s = await this.read(signal);
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
};
|
|
1838
|
+
|
|
1119
1839
|
// src/core/client.ts
|
|
1120
1840
|
init_types();
|
|
1121
1841
|
|
|
@@ -1555,33 +2275,35 @@ async function revokeToken(meta, token, signal, fetchImpl = globalThis.fetch) {
|
|
|
1555
2275
|
}
|
|
1556
2276
|
async function postToken(endpoint, data, signal, fetchImpl = globalThis.fetch) {
|
|
1557
2277
|
const ctl = withTimeout(authTimeoutMs, signal);
|
|
1558
|
-
let resp;
|
|
1559
2278
|
try {
|
|
1560
|
-
resp
|
|
1561
|
-
method: "POST",
|
|
1562
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
1563
|
-
body: data,
|
|
1564
|
-
signal: ctl.signal
|
|
1565
|
-
});
|
|
1566
|
-
} catch (e) {
|
|
1567
|
-
throw new Error(`token request: ${e instanceof Error ? e.message : String(e)}`);
|
|
1568
|
-
} finally {
|
|
1569
|
-
ctl.dispose();
|
|
1570
|
-
}
|
|
1571
|
-
if (!resp.ok) {
|
|
1572
|
-
let errBody = {};
|
|
2279
|
+
let resp;
|
|
1573
2280
|
try {
|
|
1574
|
-
|
|
1575
|
-
|
|
2281
|
+
resp = await fetchImpl(endpoint, {
|
|
2282
|
+
method: "POST",
|
|
2283
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
2284
|
+
body: data,
|
|
2285
|
+
signal: ctl.signal
|
|
2286
|
+
});
|
|
2287
|
+
} catch (e) {
|
|
2288
|
+
throw new Error(`token request: ${e instanceof Error ? e.message : String(e)}`);
|
|
1576
2289
|
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
2290
|
+
if (!resp.ok) {
|
|
2291
|
+
let errBody = {};
|
|
2292
|
+
try {
|
|
2293
|
+
errBody = await resp.json();
|
|
2294
|
+
} catch {
|
|
2295
|
+
}
|
|
2296
|
+
const oauthError = typeof errBody.error === "string" ? errBody.error : "";
|
|
2297
|
+
const errorDescription = typeof errBody.error_description === "string" ? errBody.error_description : "";
|
|
2298
|
+
throw new OAuthTokenEndpointError(resp.status, oauthError, errorDescription);
|
|
2299
|
+
}
|
|
2300
|
+
try {
|
|
2301
|
+
return await resp.json();
|
|
2302
|
+
} catch (e) {
|
|
2303
|
+
throw new Error(`token: decode: ${e instanceof Error ? e.message : String(e)}`);
|
|
2304
|
+
}
|
|
2305
|
+
} finally {
|
|
2306
|
+
ctl.dispose();
|
|
1585
2307
|
}
|
|
1586
2308
|
}
|
|
1587
2309
|
function newTokenSet(resp, clientID, serverURL) {
|
|
@@ -2064,10 +2786,31 @@ function parseHTTPErrorWithHeader(statusCode, body, header) {
|
|
|
2064
2786
|
} else if (typeof top.message === "string") {
|
|
2065
2787
|
message = top.message;
|
|
2066
2788
|
}
|
|
2789
|
+
const contractSource = errObj && typeof errObj === "object" ? errObj : top;
|
|
2067
2790
|
if (typeof top.errorCode === "string") errorCode = top.errorCode;
|
|
2791
|
+
else if (typeof contractSource.errorCode === "string") errorCode = contractSource.errorCode;
|
|
2068
2792
|
if (top.windowKind === "FIVE_HOUR" || top.windowKind === "WEEKLY") windowKind = top.windowKind;
|
|
2069
2793
|
if (typeof top.windowResetAt === "string") windowResetAt = top.windowResetAt;
|
|
2070
2794
|
if (typeof top.windowOverridable === "boolean") windowOverridable = top.windowOverridable;
|
|
2795
|
+
const disposition = contractSource.requestDisposition === "not_accepted" || contractSource.requestDisposition === "accepted" || contractSource.requestDisposition === "unknown" ? contractSource.requestDisposition : void 0;
|
|
2796
|
+
const domains = ["user_auth", "caller_credentials", "account_quota", "account_permission", "provider", "gateway", "transport", "stream_ticket", "protocol"];
|
|
2797
|
+
return new HTTPError(statusCode, {
|
|
2798
|
+
type,
|
|
2799
|
+
message,
|
|
2800
|
+
retryAfter,
|
|
2801
|
+
body: bodyStr,
|
|
2802
|
+
errorCode,
|
|
2803
|
+
windowKind,
|
|
2804
|
+
windowResetAt,
|
|
2805
|
+
windowOverridable,
|
|
2806
|
+
errorContractVersion: contractSource.errorContractVersion === 1 ? 1 : void 0,
|
|
2807
|
+
faultDomain: typeof contractSource.faultDomain === "string" && domains.includes(contractSource.faultDomain) ? contractSource.faultDomain : void 0,
|
|
2808
|
+
requestDisposition: disposition,
|
|
2809
|
+
transportRequestId: typeof contractSource.transportRequestId === "string" ? contractSource.transportRequestId : null,
|
|
2810
|
+
consumeRequestId: typeof contractSource.consumeRequestId === "string" ? contractSource.consumeRequestId : null,
|
|
2811
|
+
providerRequestId: typeof contractSource.providerRequestId === "string" ? contractSource.providerRequestId : null,
|
|
2812
|
+
retryable: contractSource.retryable === true
|
|
2813
|
+
});
|
|
2071
2814
|
}
|
|
2072
2815
|
} catch {
|
|
2073
2816
|
}
|
|
@@ -2129,7 +2872,19 @@ function parseStreamError(data) {
|
|
|
2129
2872
|
if (code === "" && errObj.type) code = errObj.type;
|
|
2130
2873
|
}
|
|
2131
2874
|
}
|
|
2132
|
-
return new StreamError({
|
|
2875
|
+
return new StreamError({
|
|
2876
|
+
code,
|
|
2877
|
+
stage,
|
|
2878
|
+
message,
|
|
2879
|
+
rawError,
|
|
2880
|
+
retryable,
|
|
2881
|
+
errorContractVersion: payload.errorContractVersion,
|
|
2882
|
+
faultDomain: payload.faultDomain,
|
|
2883
|
+
requestDisposition: payload.requestDisposition,
|
|
2884
|
+
transportRequestId: payload.transportRequestId,
|
|
2885
|
+
consumeRequestId: payload.consumeRequestId,
|
|
2886
|
+
providerRequestId: payload.providerRequestId
|
|
2887
|
+
});
|
|
2133
2888
|
}
|
|
2134
2889
|
function isOrderSuccess(status) {
|
|
2135
2890
|
switch (status) {
|
|
@@ -2363,6 +3118,13 @@ var Client = class _Client {
|
|
|
2363
3118
|
tokens = null;
|
|
2364
3119
|
/** token 持久化 */
|
|
2365
3120
|
store;
|
|
3121
|
+
credentialMode;
|
|
3122
|
+
versionedCredentialStore;
|
|
3123
|
+
accessTokenProvider;
|
|
3124
|
+
beforeCredentialInstall;
|
|
3125
|
+
credentialAuthority;
|
|
3126
|
+
credentialRequestOwner;
|
|
3127
|
+
lifecycle = null;
|
|
2366
3128
|
/** fetch 实现 (默认 globalThis.fetch) */
|
|
2367
3129
|
fetchImpl;
|
|
2368
3130
|
/** 互斥锁 (TS 用 Promise chain 替代 sync.Mutex) */
|
|
@@ -2393,6 +3155,7 @@ var Client = class _Client {
|
|
|
2393
3155
|
/** V29 系数缓存 (TTL 8s, listCoefficients 内部用) */
|
|
2394
3156
|
coefCacheData = null;
|
|
2395
3157
|
coefCacheTimeMs = 0;
|
|
3158
|
+
credentialOwnerKey = null;
|
|
2396
3159
|
/** 串行化锁 (替代 Go sync.Mutex) */
|
|
2397
3160
|
coefMu = Promise.resolve();
|
|
2398
3161
|
constructor(cfg = {}) {
|
|
@@ -2403,8 +3166,92 @@ var Client = class _Client {
|
|
|
2403
3166
|
this.oauthMetadataProfile = cfg.oauthMetadataProfile ?? "desktop";
|
|
2404
3167
|
this.browserRefreshMode = cfg.browserRefreshMode ?? "direct";
|
|
2405
3168
|
this.refreshProxyURL = cfg.refreshProxyURL ?? null;
|
|
2406
|
-
this.
|
|
3169
|
+
this.credentialMode = cfg.credentialMode ?? "legacy";
|
|
3170
|
+
this.credentialAuthority = new URL(this.serverURL).origin;
|
|
3171
|
+
if (this.credentialMode === "versioned" && !cfg.versionedCredentialStore) {
|
|
3172
|
+
throw new Error("versionedCredentialStore is required for credentialMode=versioned");
|
|
3173
|
+
}
|
|
3174
|
+
if (cfg.credentialRequestOwner && this.credentialMode !== "versioned") {
|
|
3175
|
+
throw new Error("credentialRequestOwner requires credentialMode=versioned");
|
|
3176
|
+
}
|
|
3177
|
+
if (this.credentialMode === "legacy" && cfg.versionedCredentialStore) {
|
|
3178
|
+
throw new Error("credentialMode=versioned is required when versionedCredentialStore is provided");
|
|
3179
|
+
}
|
|
3180
|
+
if (this.credentialMode === "external" && cfg.versionedCredentialStore) {
|
|
3181
|
+
throw new Error("versionedCredentialStore is incompatible with credentialMode=external");
|
|
3182
|
+
}
|
|
3183
|
+
if (this.credentialMode !== "external" && cfg.accessTokenProvider) {
|
|
3184
|
+
throw new Error("accessTokenProvider requires credentialMode=external");
|
|
3185
|
+
}
|
|
3186
|
+
if (this.credentialMode === "external" && !cfg.accessTokenProvider) {
|
|
3187
|
+
throw new Error("accessTokenProvider is required for credentialMode=external");
|
|
3188
|
+
}
|
|
3189
|
+
if (this.credentialMode !== "versioned" && cfg.beforeCredentialInstall) {
|
|
3190
|
+
throw new Error("beforeCredentialInstall requires credentialMode=versioned");
|
|
3191
|
+
}
|
|
3192
|
+
if (this.credentialMode !== "legacy") {
|
|
3193
|
+
const authority = new URL(this.serverURL).origin;
|
|
3194
|
+
for (const [name, override] of [["apiBaseURL", this.apiBaseURL], ["complianceBaseURL", this.complianceBaseURL]]) {
|
|
3195
|
+
if (override && new URL(override).origin !== authority) {
|
|
3196
|
+
throw new Error(`${name} must use the credential authority ${authority}`);
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
this.accessTokenProvider = cfg.accessTokenProvider;
|
|
3201
|
+
this.beforeCredentialInstall = cfg.beforeCredentialInstall;
|
|
3202
|
+
this.credentialRequestOwner = cfg.credentialRequestOwner ? {
|
|
3203
|
+
storeInstanceId: cfg.credentialRequestOwner.storeInstanceId,
|
|
3204
|
+
authSessionId: cfg.credentialRequestOwner.authSessionId,
|
|
3205
|
+
principal: cfg.credentialRequestOwner.principal ? {
|
|
3206
|
+
issuer: cfg.credentialRequestOwner.principal.issuer,
|
|
3207
|
+
subject: cfg.credentialRequestOwner.principal.subject,
|
|
3208
|
+
organizationId: cfg.credentialRequestOwner.principal.organizationId
|
|
3209
|
+
} : null
|
|
3210
|
+
} : null;
|
|
2407
3211
|
this.fetchImpl = cfg.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
3212
|
+
this.versionedCredentialStore = cfg.versionedCredentialStore ?? null;
|
|
3213
|
+
if (this.versionedCredentialStore) this.lifecycle = new CredentialLifecycle(this.versionedCredentialStore, {
|
|
3214
|
+
serverURL: this.serverURL,
|
|
3215
|
+
fetch: this.fetchImpl,
|
|
3216
|
+
metadata: (signal) => discoverWithProfile(this.serverURL, "desktop", signal, this.fetchImpl),
|
|
3217
|
+
profile: async (tokens, signal) => {
|
|
3218
|
+
const gatewayRoot = this.serverURL.replace(/\/api\/v4$/, "");
|
|
3219
|
+
const profileURL = `${gatewayRoot}/api/oauth/profile`;
|
|
3220
|
+
this.assertCredentialURL(profileURL);
|
|
3221
|
+
const response = await this.fetchImpl(profileURL, { headers: { Authorization: `Bearer ${tokens.access_token}` }, signal });
|
|
3222
|
+
if (!response.ok) {
|
|
3223
|
+
const bodyBytes = response.body ? await readLimited(response.body, maxErrorBodySize) : new Uint8Array();
|
|
3224
|
+
const failure = parseHTTPErrorWithHeader(response.status, bodyBytes, response.headers);
|
|
3225
|
+
const contract = readGatewayErrorContract(failure);
|
|
3226
|
+
const code = contract?.errorCode ?? null;
|
|
3227
|
+
if (code === "INVALID_SCOPE") throw new Error("invalid_scope");
|
|
3228
|
+
if (code === "AUTH_CONTRACT_UNSUPPORTED") throw new Error("auth_contract_unsupported");
|
|
3229
|
+
if (code === "ACCOUNT_NOT_FOUND") throw new Error("account_permission");
|
|
3230
|
+
throw new Error("identity_unavailable");
|
|
3231
|
+
}
|
|
3232
|
+
const body = await response.json();
|
|
3233
|
+
const subject = body.account?.uuid;
|
|
3234
|
+
if (typeof subject !== "string" || !subject) throw new Error("invalid_response");
|
|
3235
|
+
const account = body.account;
|
|
3236
|
+
const organization = body.organization;
|
|
3237
|
+
return {
|
|
3238
|
+
subject,
|
|
3239
|
+
organizationId: organization?.uuid || null,
|
|
3240
|
+
...typeof account.display_name === "string" ? { displayName: account.display_name } : {},
|
|
3241
|
+
...[account.avatar_url, account.picture, account.image, body.avatar_url, body.picture, body.image].find((value) => typeof value === "string") !== void 0 ? { avatarUrl: [account.avatar_url, account.picture, account.image, body.avatar_url, body.picture, body.image].find((value) => typeof value === "string") } : {},
|
|
3242
|
+
...typeof account.email === "string" ? { email: account.email } : {},
|
|
3243
|
+
...typeof account.image_url === "string" ? { imageUrl: account.image_url } : {},
|
|
3244
|
+
...typeof account.created_at === "string" ? { accountCreatedAt: account.created_at } : {},
|
|
3245
|
+
...typeof account.requires_phone_binding === "boolean" ? { requiresPhoneBinding: account.requires_phone_binding } : {},
|
|
3246
|
+
...typeof organization?.has_extra_usage_enabled === "boolean" ? { hasExtraUsageEnabled: organization.has_extra_usage_enabled } : {},
|
|
3247
|
+
...typeof organization?.billing_type === "string" ? { billingType: organization.billing_type } : {},
|
|
3248
|
+
...typeof organization?.subscription_created_at === "string" ? { subscriptionCreatedAt: organization.subscription_created_at } : {},
|
|
3249
|
+
...typeof organization?.rate_limit_tier === "string" ? { rateLimitTier: organization.rate_limit_tier } : {},
|
|
3250
|
+
...typeof organization?.name === "string" ? { organizationName: organization.name } : {}
|
|
3251
|
+
};
|
|
3252
|
+
}
|
|
3253
|
+
});
|
|
3254
|
+
this.store = cfg.store ?? defaultTokenStore();
|
|
2408
3255
|
this.retryPolicy = effectivePolicy(cfg.retryPolicy ?? null);
|
|
2409
3256
|
}
|
|
2410
3257
|
/**
|
|
@@ -2413,6 +3260,11 @@ var Client = class _Client {
|
|
|
2413
3260
|
*/
|
|
2414
3261
|
static async create(cfg = {}) {
|
|
2415
3262
|
const c = new _Client(cfg);
|
|
3263
|
+
if (c.credentialMode === "external") return c;
|
|
3264
|
+
if (c.credentialMode === "versioned") {
|
|
3265
|
+
await c.reconcileCredentials();
|
|
3266
|
+
return c;
|
|
3267
|
+
}
|
|
2416
3268
|
try {
|
|
2417
3269
|
const tokens = await c.store.load();
|
|
2418
3270
|
if (tokens) {
|
|
@@ -2426,6 +3278,63 @@ var Client = class _Client {
|
|
|
2426
3278
|
}
|
|
2427
3279
|
return c;
|
|
2428
3280
|
}
|
|
3281
|
+
/** Read the durable authority. Available only in explicit versioned mode. */
|
|
3282
|
+
async getCredentialSnapshot(signal) {
|
|
3283
|
+
if (!this.versionedCredentialStore) {
|
|
3284
|
+
throw new Error("getCredentialSnapshot requires credentialMode=versioned");
|
|
3285
|
+
}
|
|
3286
|
+
return this.versionedCredentialStore.readSnapshot(signal);
|
|
3287
|
+
}
|
|
3288
|
+
/** Reconcile memory from durable state; storage errors never clear confirmed memory. */
|
|
3289
|
+
async reconcileCredentials(signal) {
|
|
3290
|
+
const snapshot = await this.lifecycle.reconcile(signal);
|
|
3291
|
+
this.adoptCredentialOwner(snapshot);
|
|
3292
|
+
this.tokens = snapshot.credentialState === "ready" ? snapshot.tokenSet : null;
|
|
3293
|
+
return snapshot;
|
|
3294
|
+
}
|
|
3295
|
+
ownerKey(snapshot) {
|
|
3296
|
+
return `${snapshot.storeInstanceId}\0${snapshot.authSessionId ?? ""}\0${snapshot.principal?.issuer ?? ""}\0${snapshot.principal?.subject ?? ""}\0${snapshot.principal?.organizationId ?? ""}`;
|
|
3297
|
+
}
|
|
3298
|
+
adoptCredentialOwner(snapshot) {
|
|
3299
|
+
const next = this.ownerKey(snapshot);
|
|
3300
|
+
if (this.credentialOwnerKey !== null && this.credentialOwnerKey !== next) {
|
|
3301
|
+
this.modelCache = [];
|
|
3302
|
+
this.modelCacheTimeMs = 0;
|
|
3303
|
+
this.coefCacheData = null;
|
|
3304
|
+
this.coefCacheTimeMs = 0;
|
|
3305
|
+
}
|
|
3306
|
+
this.credentialOwnerKey = next;
|
|
3307
|
+
}
|
|
3308
|
+
async ensureCredential(signal) {
|
|
3309
|
+
if (!this.lifecycle) return this.ensureToken(signal);
|
|
3310
|
+
const token = await this.lifecycle.ensure(signal, void 0, this.credentialRequestOwner ?? void 0);
|
|
3311
|
+
const snapshot = await this.lifecycle.read(signal);
|
|
3312
|
+
this.adoptCredentialOwner(snapshot);
|
|
3313
|
+
this.tokens = snapshot.credentialState === "ready" ? snapshot.tokenSet : null;
|
|
3314
|
+
return token;
|
|
3315
|
+
}
|
|
3316
|
+
subscribeCredentialState(listener) {
|
|
3317
|
+
if (!this.lifecycle) throw new Error("subscribeCredentialState requires credentialMode=versioned");
|
|
3318
|
+
return this.lifecycle.subscribe(listener);
|
|
3319
|
+
}
|
|
3320
|
+
async retryCredentialIdentity(signal) {
|
|
3321
|
+
const snapshot = await this.getCredentialSnapshot(signal);
|
|
3322
|
+
if (!snapshot.authSessionId) throw new Error("not authorized");
|
|
3323
|
+
const ready = await this.lifecycle.bindIdentity(snapshot.authSessionId, signal);
|
|
3324
|
+
this.adoptCredentialOwner(ready);
|
|
3325
|
+
this.tokens = ready.credentialState === "ready" ? ready.tokenSet : null;
|
|
3326
|
+
return ready;
|
|
3327
|
+
}
|
|
3328
|
+
async logoutCredential(signal, expected) {
|
|
3329
|
+
if (!this.lifecycle) throw new Error("logoutCredential requires credentialMode=versioned");
|
|
3330
|
+
const result = await this.lifecycle.logout(signal, expected);
|
|
3331
|
+
if (result.status === "committed" || result.status === "already_signed_out") {
|
|
3332
|
+
const current = await this.lifecycle.read(signal);
|
|
3333
|
+
this.adoptCredentialOwner(current);
|
|
3334
|
+
this.tokens = null;
|
|
3335
|
+
}
|
|
3336
|
+
return result;
|
|
3337
|
+
}
|
|
2429
3338
|
// ===========================================================================
|
|
2430
3339
|
// 授权生命周期
|
|
2431
3340
|
// ===========================================================================
|
|
@@ -2476,6 +3385,44 @@ var Client = class _Client {
|
|
|
2476
3385
|
return this.loginInternal(appName, scopes, { handler, ...opts }, signal);
|
|
2477
3386
|
}
|
|
2478
3387
|
async loginInternal(appName, scopes, opts, signal) {
|
|
3388
|
+
if (this.lifecycle) {
|
|
3389
|
+
const attempt = await this.lifecycle.reserveLogin(signal);
|
|
3390
|
+
let installHookRejected = false;
|
|
3391
|
+
try {
|
|
3392
|
+
const registration = await register(attempt.metadata, appName, signal, this.fetchImpl);
|
|
3393
|
+
await this.lifecycle.assertLogin(attempt.attemptId, signal);
|
|
3394
|
+
const authorization = await authorize(attempt.metadata, registration.client_id, scopes, { ...opts, handler: opts?.handler ?? void 0, signal });
|
|
3395
|
+
await this.lifecycle.assertLogin(attempt.attemptId, signal);
|
|
3396
|
+
const response = await exchangeCode(attempt.metadata, registration.client_id, authorization.result.code, authorization.result.redirectURI, authorization.verifier, signal, this.fetchImpl);
|
|
3397
|
+
if (!Number.isFinite(response.expires_in) || response.expires_in <= 0) throw new Error("invalid_response");
|
|
3398
|
+
await this.lifecycle.assertLogin(attempt.attemptId, signal);
|
|
3399
|
+
try {
|
|
3400
|
+
await this.beforeCredentialInstall?.({
|
|
3401
|
+
accessToken: response.access_token,
|
|
3402
|
+
attemptId: attempt.attemptId,
|
|
3403
|
+
serverURL: this.serverURL,
|
|
3404
|
+
clientId: registration.client_id
|
|
3405
|
+
}, signal);
|
|
3406
|
+
} catch (error) {
|
|
3407
|
+
installHookRejected = true;
|
|
3408
|
+
throw error;
|
|
3409
|
+
}
|
|
3410
|
+
await this.lifecycle.assertLogin(attempt.attemptId, signal);
|
|
3411
|
+
const ready = await this.lifecycle.installLogin(attempt.attemptId, newTokenSet(response, registration.client_id, this.serverURL), signal);
|
|
3412
|
+
const current = await this.getCredentialSnapshot(signal);
|
|
3413
|
+
if (current.revision !== ready.revision || current.authSessionId !== ready.authSessionId) throw new Error("superseded");
|
|
3414
|
+
this.tokens = ready.tokenSet;
|
|
3415
|
+
opts?.handler?.({ type: EventComplete, attemptId: attempt.attemptId });
|
|
3416
|
+
} catch (error) {
|
|
3417
|
+
const current = await this.getCredentialSnapshot();
|
|
3418
|
+
if (current.loginAttempt?.attemptId === attempt.attemptId || current.lastLoginAttemptId === attempt.attemptId) {
|
|
3419
|
+
opts?.handler?.(installHookRejected ? { type: EventError, attemptId: attempt.attemptId, err_code: "credential_install_rejected", error: "credential_install_rejected" } : { type: EventError, attemptId: attempt.attemptId, error: "credential_login_failed" });
|
|
3420
|
+
}
|
|
3421
|
+
await this.lifecycle.cancelLogin(attempt.attemptId);
|
|
3422
|
+
throw error;
|
|
3423
|
+
}
|
|
3424
|
+
return;
|
|
3425
|
+
}
|
|
2479
3426
|
const handler = opts?.handler ?? void 0;
|
|
2480
3427
|
const emit = (e) => {
|
|
2481
3428
|
if (handler) handler(e);
|
|
@@ -2584,6 +3531,11 @@ var Client = class _Client {
|
|
|
2584
3531
|
}
|
|
2585
3532
|
/** 吊销 token 并清除本地存储 */
|
|
2586
3533
|
async logout(signal) {
|
|
3534
|
+
if (this.lifecycle) {
|
|
3535
|
+
await this.logoutCredential(signal);
|
|
3536
|
+
await this.reconcileCredentials(signal);
|
|
3537
|
+
return;
|
|
3538
|
+
}
|
|
2587
3539
|
const tokens = this.tokens;
|
|
2588
3540
|
let meta = this.meta;
|
|
2589
3541
|
this.tokens = null;
|
|
@@ -2621,6 +3573,13 @@ var Client = class _Client {
|
|
|
2621
3573
|
* 避免应用启动期 "login + 多个 API 调用" 并发场景下 4+ 条 "not authorized" 误报.
|
|
2622
3574
|
*/
|
|
2623
3575
|
async ensureToken(signal) {
|
|
3576
|
+
if (this.credentialMode === "external") {
|
|
3577
|
+
if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
|
|
3578
|
+
const token = await this.accessTokenProvider(signal);
|
|
3579
|
+
if (typeof token !== "string" || token.length === 0) throw new Error("external access token unavailable");
|
|
3580
|
+
return token;
|
|
3581
|
+
}
|
|
3582
|
+
if (this.lifecycle) return this.lifecycle.ensure(signal, void 0, this.credentialRequestOwner ?? void 0);
|
|
2624
3583
|
let tokens = this.tokens;
|
|
2625
3584
|
const ready = this.tokenReady.promise;
|
|
2626
3585
|
const inFlight = this.loginInFlight;
|
|
@@ -2668,7 +3627,14 @@ var Client = class _Client {
|
|
|
2668
3627
|
);
|
|
2669
3628
|
}
|
|
2670
3629
|
/** 强制刷新 token (用于 401 重试) */
|
|
2671
|
-
async forceRefresh(signal) {
|
|
3630
|
+
async forceRefresh(signal, rejectedToken) {
|
|
3631
|
+
if (this.credentialMode === "external") throw new Error("external credentials cannot be refreshed by the SDK");
|
|
3632
|
+
if (this.lifecycle) {
|
|
3633
|
+
await this.lifecycle.forceRefresh(signal, rejectedToken, this.credentialRequestOwner ?? void 0);
|
|
3634
|
+
const snapshot = await this.lifecycle.read(signal);
|
|
3635
|
+
this.tokens = snapshot.credentialState === "ready" ? snapshot.tokenSet : null;
|
|
3636
|
+
return;
|
|
3637
|
+
}
|
|
2672
3638
|
return this.withMu(
|
|
2673
3639
|
() => this.storeWithLock(async () => {
|
|
2674
3640
|
await this.syncFromDisk();
|
|
@@ -2863,6 +3829,7 @@ var Client = class _Client {
|
|
|
2863
3829
|
*/
|
|
2864
3830
|
async listModelsWithStatus(signal, opts) {
|
|
2865
3831
|
const includeLocked = opts?.includeLocked === true;
|
|
3832
|
+
const requestOwner = this.lifecycle ? this.ownerKey(await this.getCredentialSnapshot(signal)) : null;
|
|
2866
3833
|
const path = includeLocked ? "/managed-models?picker=1" : "/managed-models";
|
|
2867
3834
|
const { result, headers } = await this.doJSONFull(
|
|
2868
3835
|
"GET",
|
|
@@ -2871,6 +3838,11 @@ var Client = class _Client {
|
|
|
2871
3838
|
signal
|
|
2872
3839
|
);
|
|
2873
3840
|
const normalized = normalizeInputModalities(result.data);
|
|
3841
|
+
if (requestOwner !== null) {
|
|
3842
|
+
const current = await this.getCredentialSnapshot(signal);
|
|
3843
|
+
if (this.ownerKey(current) !== requestOwner) throw new Error("superseded");
|
|
3844
|
+
this.adoptCredentialOwner(current);
|
|
3845
|
+
}
|
|
2874
3846
|
if (!includeLocked) {
|
|
2875
3847
|
this.modelCache = normalized;
|
|
2876
3848
|
this.modelCacheTimeMs = Date.now();
|
|
@@ -3290,12 +4262,11 @@ var Client = class _Client {
|
|
|
3290
4262
|
throw classifyTransport("POST " + endpoint, url, e);
|
|
3291
4263
|
}
|
|
3292
4264
|
if (resp.status === 401 && !retried) {
|
|
4265
|
+
const bodyBytes = resp.body ? await readLimited(resp.body, maxErrorBodySize) : new Uint8Array();
|
|
4266
|
+
const authError = parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
4267
|
+
if (!isUserAccessTokenRejected(authError)) throw authError;
|
|
3293
4268
|
try {
|
|
3294
|
-
await
|
|
3295
|
-
} catch {
|
|
3296
|
-
}
|
|
3297
|
-
try {
|
|
3298
|
-
await this.forceRefresh(signal);
|
|
4269
|
+
await this.forceRefresh(signal, token);
|
|
3299
4270
|
} catch (refreshErr) {
|
|
3300
4271
|
throw new Error(
|
|
3301
4272
|
`stream: unauthorized and refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}`
|
|
@@ -3361,12 +4332,11 @@ var Client = class _Client {
|
|
|
3361
4332
|
throw classifyTransport("POST " + endpoint, url, e);
|
|
3362
4333
|
}
|
|
3363
4334
|
if (resp.status === 401 && !retried) {
|
|
4335
|
+
const bodyBytes = resp.body ? await readLimited(resp.body, maxErrorBodySize) : new Uint8Array();
|
|
4336
|
+
const authError = parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
4337
|
+
if (!isUserAccessTokenRejected(authError)) throw authError;
|
|
3364
4338
|
try {
|
|
3365
|
-
await
|
|
3366
|
-
} catch {
|
|
3367
|
-
}
|
|
3368
|
-
try {
|
|
3369
|
-
await this.forceRefresh(signal);
|
|
4339
|
+
await this.forceRefresh(signal, token);
|
|
3370
4340
|
} catch (refreshErr) {
|
|
3371
4341
|
throw new Error(
|
|
3372
4342
|
`messages stream: unauthorized and refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}`
|
|
@@ -3456,7 +4426,9 @@ var Client = class _Client {
|
|
|
3456
4426
|
if (!base.endsWith("/api/v4")) {
|
|
3457
4427
|
base += "/api/v4";
|
|
3458
4428
|
}
|
|
3459
|
-
|
|
4429
|
+
const url = base + path;
|
|
4430
|
+
this.assertCredentialURL(url);
|
|
4431
|
+
return url;
|
|
3460
4432
|
}
|
|
3461
4433
|
/**
|
|
3462
4434
|
* Compliance API URL 拼接。
|
|
@@ -3469,7 +4441,14 @@ var Client = class _Client {
|
|
|
3469
4441
|
*/
|
|
3470
4442
|
complianceURL(path) {
|
|
3471
4443
|
const base = this.complianceBaseURL ?? this.serverURL + "/admin-api";
|
|
3472
|
-
|
|
4444
|
+
const url = base + path;
|
|
4445
|
+
this.assertCredentialURL(url);
|
|
4446
|
+
return url;
|
|
4447
|
+
}
|
|
4448
|
+
assertCredentialURL(url) {
|
|
4449
|
+
if (this.credentialMode !== "legacy" && new URL(url).origin !== this.credentialAuthority) {
|
|
4450
|
+
throw new Error("credential request authority changed");
|
|
4451
|
+
}
|
|
3473
4452
|
}
|
|
3474
4453
|
/** GET/POST/... 通用 JSON 调用 (返回 result 已 typed) */
|
|
3475
4454
|
async doJSON(method, path, body, signal) {
|
|
@@ -3498,12 +4477,11 @@ var Client = class _Client {
|
|
|
3498
4477
|
ctl.signal
|
|
3499
4478
|
);
|
|
3500
4479
|
if (resp.status === 401 && !retried) {
|
|
4480
|
+
const bodyBytes = resp.body ? await readLimited(resp.body, maxErrorBodySize) : new Uint8Array();
|
|
4481
|
+
const authError = parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
4482
|
+
if (!isUserAccessTokenRejected(authError)) throw authError;
|
|
3501
4483
|
try {
|
|
3502
|
-
await
|
|
3503
|
-
} catch {
|
|
3504
|
-
}
|
|
3505
|
-
try {
|
|
3506
|
-
await this.forceRefresh(ctl.signal);
|
|
4484
|
+
await this.forceRefresh(ctl.signal, token);
|
|
3507
4485
|
} catch (refreshErr) {
|
|
3508
4486
|
throw new Error(
|
|
3509
4487
|
`unauthorized and refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}`
|
|
@@ -3568,12 +4546,11 @@ var Client = class _Client {
|
|
|
3568
4546
|
ctl.signal
|
|
3569
4547
|
);
|
|
3570
4548
|
if (resp.status === 401 && !retried) {
|
|
4549
|
+
const bodyBytes = resp.body ? await readLimited(resp.body, maxErrorBodySize) : new Uint8Array();
|
|
4550
|
+
const authError = parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
4551
|
+
if (!isUserAccessTokenRejected(authError)) throw authError;
|
|
3571
4552
|
try {
|
|
3572
|
-
await
|
|
3573
|
-
} catch {
|
|
3574
|
-
}
|
|
3575
|
-
try {
|
|
3576
|
-
await this.forceRefresh(ctl.signal);
|
|
4553
|
+
await this.forceRefresh(ctl.signal, token);
|
|
3577
4554
|
} catch (refreshErr) {
|
|
3578
4555
|
throw new Error(
|
|
3579
4556
|
`unauthorized and refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}`
|
|
@@ -3648,6 +4625,7 @@ var Client = class _Client {
|
|
|
3648
4625
|
* 6 处原始 fetch() 全部走此 helper
|
|
3649
4626
|
*/
|
|
3650
4627
|
async doRequest(req, signal) {
|
|
4628
|
+
if (new Headers(req.headers).has("Authorization")) this.assertCredentialURL(req.url);
|
|
3651
4629
|
try {
|
|
3652
4630
|
return await this.fetchImpl(req.url, {
|
|
3653
4631
|
method: req.method,
|
|
@@ -4645,12 +5623,11 @@ async function uploadSkillInternal(c, zipData, scope, intent, retried, signal) {
|
|
|
4645
5623
|
throw classifyTransport("POST /skill-store/upload", url, e);
|
|
4646
5624
|
}
|
|
4647
5625
|
if (resp.status === 401 && !retried) {
|
|
5626
|
+
const bodyBytes = resp.body ? await readLimited(resp.body, maxErrorBodySize) : new Uint8Array();
|
|
5627
|
+
const authError = parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
5628
|
+
if (!isUserAccessTokenRejected(authError)) throw authError;
|
|
4648
5629
|
try {
|
|
4649
|
-
await
|
|
4650
|
-
} catch {
|
|
4651
|
-
}
|
|
4652
|
-
try {
|
|
4653
|
-
await c.forceRefresh(ctl.signal);
|
|
5630
|
+
await c.forceRefresh(ctl.signal, token);
|
|
4654
5631
|
} catch (refreshErr) {
|
|
4655
5632
|
throw new Error(
|
|
4656
5633
|
`upload: unauthorized and refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}`
|
|
@@ -4821,9 +5798,7 @@ Client.prototype.updateNotificationPreference = async function(typeCode, pref, s
|
|
|
4821
5798
|
|
|
4822
5799
|
// src/notifications/ws.ts
|
|
4823
5800
|
Client.prototype.connect = async function(cfg, signal) {
|
|
4824
|
-
|
|
4825
|
-
await this.disconnect();
|
|
4826
|
-
}
|
|
5801
|
+
const oldDisconnect = this.ws ? this.disconnect() : Promise.resolve();
|
|
4827
5802
|
const noop = () => {
|
|
4828
5803
|
};
|
|
4829
5804
|
const filledCfg = {
|
|
@@ -4839,21 +5814,31 @@ Client.prototype.connect = async function(cfg, signal) {
|
|
|
4839
5814
|
const done = new Promise((r) => {
|
|
4840
5815
|
resolveDone = r;
|
|
4841
5816
|
});
|
|
4842
|
-
const
|
|
5817
|
+
const abort2 = new AbortController();
|
|
4843
5818
|
if (signal) {
|
|
4844
|
-
if (signal.aborted)
|
|
4845
|
-
else signal.addEventListener("abort", () =>
|
|
5819
|
+
if (signal.aborted) abort2.abort();
|
|
5820
|
+
else signal.addEventListener("abort", () => abort2.abort());
|
|
4846
5821
|
}
|
|
4847
5822
|
const ws = {
|
|
4848
5823
|
conn: null,
|
|
4849
5824
|
cfg: filledCfg,
|
|
4850
|
-
abort,
|
|
5825
|
+
abort: abort2,
|
|
4851
5826
|
done,
|
|
4852
5827
|
doneResolve: resolveDone,
|
|
4853
|
-
connected: false
|
|
5828
|
+
connected: false,
|
|
5829
|
+
owner: null
|
|
4854
5830
|
};
|
|
4855
|
-
await wsConnectOnce(this, ws);
|
|
4856
5831
|
this.ws = ws;
|
|
5832
|
+
try {
|
|
5833
|
+
await oldDisconnect;
|
|
5834
|
+
await assertCurrent(this, ws);
|
|
5835
|
+
await wsConnectOnce(this, ws);
|
|
5836
|
+
} catch (error) {
|
|
5837
|
+
ws.abort.abort();
|
|
5838
|
+
if (this.ws === ws) this.ws = null;
|
|
5839
|
+
ws.doneResolve();
|
|
5840
|
+
throw error;
|
|
5841
|
+
}
|
|
4857
5842
|
void wsLoop(this, ws);
|
|
4858
5843
|
};
|
|
4859
5844
|
Client.prototype.disconnect = async function() {
|
|
@@ -4891,15 +5876,47 @@ function getWebSocketCtor() {
|
|
|
4891
5876
|
}
|
|
4892
5877
|
return WSCtor;
|
|
4893
5878
|
}
|
|
5879
|
+
function sameOwner(a, b) {
|
|
5880
|
+
return a?.storeInstanceId === b?.storeInstanceId && a?.authSessionId === b?.authSessionId && a?.principal?.issuer === b?.principal?.issuer && a?.principal?.subject === b?.principal?.subject && a?.principal?.organizationId === b?.principal?.organizationId;
|
|
5881
|
+
}
|
|
5882
|
+
async function readOwner(c, signal) {
|
|
5883
|
+
if (c.credentialMode !== "versioned") return null;
|
|
5884
|
+
const snapshot = await c.getCredentialSnapshot(signal);
|
|
5885
|
+
return {
|
|
5886
|
+
storeInstanceId: snapshot.storeInstanceId,
|
|
5887
|
+
authSessionId: snapshot.authSessionId,
|
|
5888
|
+
principal: snapshot.principal
|
|
5889
|
+
};
|
|
5890
|
+
}
|
|
5891
|
+
async function assertCurrent(c, ws) {
|
|
5892
|
+
if (ws.abort.signal.aborted || c.ws !== ws) throw new Error("websocket connection superseded");
|
|
5893
|
+
if (ws.owner !== null && !sameOwner(ws.owner, await readOwner(c, ws.abort.signal))) {
|
|
5894
|
+
ws.abort.abort();
|
|
5895
|
+
throw new Error("websocket credential owner changed");
|
|
5896
|
+
}
|
|
5897
|
+
}
|
|
4894
5898
|
async function wsConnectOnce(c, ws) {
|
|
5899
|
+
const observedOwner = await readOwner(c, ws.abort.signal);
|
|
5900
|
+
if (ws.owner === null) ws.owner = observedOwner;
|
|
5901
|
+
else if (!sameOwner(ws.owner, observedOwner)) throw new Error("websocket credential owner changed");
|
|
5902
|
+
await assertCurrent(c, ws);
|
|
4895
5903
|
const url = wsURL(c);
|
|
4896
5904
|
const WSCtor = getWebSocketCtor();
|
|
4897
|
-
const
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
5905
|
+
const token = await c.ensureToken(ws.abort.signal);
|
|
5906
|
+
await assertCurrent(c, ws);
|
|
5907
|
+
const ticketURL = c.apiURL("/ws/stream-ticket");
|
|
5908
|
+
await assertCurrent(c, ws);
|
|
5909
|
+
const ticketHTTP = await c.doRequest({
|
|
5910
|
+
method: "POST",
|
|
5911
|
+
url: ticketURL,
|
|
5912
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
5913
|
+
}, ws.abort.signal);
|
|
5914
|
+
if (!ticketHTTP.ok) {
|
|
5915
|
+
const body = ticketHTTP.body ? await readLimited(ticketHTTP.body, maxErrorBodySize) : new Uint8Array();
|
|
5916
|
+
throw parseHTTPErrorWithHeader(ticketHTTP.status, body, ticketHTTP.headers);
|
|
5917
|
+
}
|
|
5918
|
+
const ticketResp = await ticketHTTP.json();
|
|
5919
|
+
await assertCurrent(c, ws);
|
|
4903
5920
|
const ticket = ticketResp.data.ticket;
|
|
4904
5921
|
const u = new URL(url);
|
|
4905
5922
|
u.searchParams.set("ticket", ticket);
|
|
@@ -4920,11 +5937,28 @@ async function wsConnectOnce(c, ws) {
|
|
|
4920
5937
|
reject(new Error("dial: handshake timeout"));
|
|
4921
5938
|
}
|
|
4922
5939
|
}, 3e4);
|
|
5940
|
+
const abortHandshake = () => {
|
|
5941
|
+
clearTimeout(handshakeTimer);
|
|
5942
|
+
try {
|
|
5943
|
+
conn.close();
|
|
5944
|
+
} catch {
|
|
5945
|
+
}
|
|
5946
|
+
reject(new Error("websocket connection aborted"));
|
|
5947
|
+
};
|
|
5948
|
+
ws.abort.signal.addEventListener("abort", abortHandshake, { once: true });
|
|
4923
5949
|
conn.addEventListener("open", () => {
|
|
5950
|
+
if (ws.abort.signal.aborted || c.ws !== ws) {
|
|
5951
|
+
try {
|
|
5952
|
+
conn.close();
|
|
5953
|
+
} catch {
|
|
5954
|
+
}
|
|
5955
|
+
return;
|
|
5956
|
+
}
|
|
4924
5957
|
opened = true;
|
|
4925
5958
|
});
|
|
4926
5959
|
conn.addEventListener("error", (e) => {
|
|
4927
5960
|
clearTimeout(handshakeTimer);
|
|
5961
|
+
ws.abort.signal.removeEventListener("abort", abortHandshake);
|
|
4928
5962
|
reject(new Error(`dial: ${e.message ?? "connection error"}`));
|
|
4929
5963
|
});
|
|
4930
5964
|
conn.addEventListener("message", (e) => {
|
|
@@ -4933,6 +5967,7 @@ async function wsConnectOnce(c, ws) {
|
|
|
4933
5967
|
const welcome = JSON.parse(msg);
|
|
4934
5968
|
if (welcome.type !== "welcome") {
|
|
4935
5969
|
clearTimeout(handshakeTimer);
|
|
5970
|
+
ws.abort.signal.removeEventListener("abort", abortHandshake);
|
|
4936
5971
|
try {
|
|
4937
5972
|
conn.close();
|
|
4938
5973
|
} catch {
|
|
@@ -4940,31 +5975,34 @@ async function wsConnectOnce(c, ws) {
|
|
|
4940
5975
|
reject(new Error(`unexpected first message: ${welcome.type}`));
|
|
4941
5976
|
return;
|
|
4942
5977
|
}
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
JSON.stringify({
|
|
4950
|
-
type: "subscribe",
|
|
4951
|
-
topics: ws.cfg.topics
|
|
4952
|
-
})
|
|
4953
|
-
);
|
|
4954
|
-
} catch (sendErr) {
|
|
4955
|
-
ws.conn = null;
|
|
4956
|
-
ws.connected = false;
|
|
5978
|
+
void assertCurrent(c, ws).then(() => {
|
|
5979
|
+
clearTimeout(handshakeTimer);
|
|
5980
|
+
ws.abort.signal.removeEventListener("abort", abortHandshake);
|
|
5981
|
+
ws.conn = conn;
|
|
5982
|
+
ws.connected = true;
|
|
5983
|
+
if (ws.cfg.topics.length > 0) {
|
|
4957
5984
|
try {
|
|
4958
|
-
conn.
|
|
4959
|
-
|
|
5985
|
+
conn.send(
|
|
5986
|
+
JSON.stringify({
|
|
5987
|
+
type: "subscribe",
|
|
5988
|
+
topics: ws.cfg.topics
|
|
5989
|
+
})
|
|
5990
|
+
);
|
|
5991
|
+
} catch (sendErr) {
|
|
5992
|
+
ws.conn = null;
|
|
5993
|
+
ws.connected = false;
|
|
5994
|
+
try {
|
|
5995
|
+
conn.close();
|
|
5996
|
+
} catch {
|
|
5997
|
+
}
|
|
5998
|
+
reject(new Error(`send subscribe: ${sendErr instanceof Error ? sendErr.message : String(sendErr)}`));
|
|
5999
|
+
return;
|
|
4960
6000
|
}
|
|
4961
|
-
reject(new Error(`send subscribe: ${sendErr instanceof Error ? sendErr.message : String(sendErr)}`));
|
|
4962
|
-
return;
|
|
4963
6001
|
}
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
6002
|
+
ws.cfg.onConnect();
|
|
6003
|
+
console.log(`[acosmi-sdk] websocket connected, connId=${welcome.connId ?? ""}`);
|
|
6004
|
+
resolve();
|
|
6005
|
+
}).catch(reject);
|
|
4968
6006
|
} catch (parseErr) {
|
|
4969
6007
|
clearTimeout(handshakeTimer);
|
|
4970
6008
|
try {
|
|
@@ -4979,7 +6017,7 @@ async function wsConnectOnce(c, ws) {
|
|
|
4979
6017
|
async function wsLoop(c, ws) {
|
|
4980
6018
|
try {
|
|
4981
6019
|
while (true) {
|
|
4982
|
-
await wsReadLoop(ws);
|
|
6020
|
+
await wsReadLoop(c, ws);
|
|
4983
6021
|
if (ws.abort.signal.aborted) return;
|
|
4984
6022
|
if (ws.conn) {
|
|
4985
6023
|
try {
|
|
@@ -5010,7 +6048,7 @@ async function wsLoop(c, ws) {
|
|
|
5010
6048
|
ws.doneResolve();
|
|
5011
6049
|
}
|
|
5012
6050
|
}
|
|
5013
|
-
async function wsReadLoop(ws) {
|
|
6051
|
+
async function wsReadLoop(c, ws) {
|
|
5014
6052
|
const conn = ws.conn;
|
|
5015
6053
|
if (!conn) return;
|
|
5016
6054
|
return new Promise((resolve) => {
|
|
@@ -5018,10 +6056,17 @@ async function wsReadLoop(ws) {
|
|
|
5018
6056
|
try {
|
|
5019
6057
|
const data = e.data;
|
|
5020
6058
|
const event = JSON.parse(data);
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
6059
|
+
void assertCurrent(c, ws).then(() => {
|
|
6060
|
+
try {
|
|
6061
|
+
ws.cfg.onEvent(event);
|
|
6062
|
+
} catch {
|
|
6063
|
+
}
|
|
6064
|
+
}).catch(() => {
|
|
6065
|
+
try {
|
|
6066
|
+
conn.close();
|
|
6067
|
+
} catch {
|
|
6068
|
+
}
|
|
6069
|
+
});
|
|
5025
6070
|
} catch {
|
|
5026
6071
|
}
|
|
5027
6072
|
};
|
|
@@ -5234,6 +6279,7 @@ function isTerminalRemoteEvent(ev) {
|
|
|
5234
6279
|
}
|
|
5235
6280
|
|
|
5236
6281
|
// src/agent-runs/client.ts
|
|
6282
|
+
init_errors();
|
|
5237
6283
|
var agentRunsByClient = /* @__PURE__ */ new WeakMap();
|
|
5238
6284
|
Object.defineProperty(Client.prototype, "agentRuns", {
|
|
5239
6285
|
configurable: true,
|
|
@@ -5613,11 +6659,10 @@ var AgentRunsClient = class {
|
|
|
5613
6659
|
}
|
|
5614
6660
|
const resp = await this.client.doRequest({ method, url, headers, body: bodyStr }, signal);
|
|
5615
6661
|
if (resp.status === 401 && opts.retryOn401 && !retried) {
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
await this.client.forceRefresh(signal);
|
|
6662
|
+
const bodyBytes = resp.body ? await readLimited(resp.body, maxErrorBodySize) : new Uint8Array();
|
|
6663
|
+
const authError = parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
6664
|
+
if (!isUserAccessTokenRejected(authError)) throw authError;
|
|
6665
|
+
await this.client.forceRefresh(signal, token);
|
|
5621
6666
|
return this.requestRawInner(method, path, body, signal, opts, true);
|
|
5622
6667
|
}
|
|
5623
6668
|
if (resp.status < 200 || resp.status >= 300) {
|
|
@@ -6244,6 +7289,7 @@ function isComplianceBusinessError(err) {
|
|
|
6244
7289
|
}
|
|
6245
7290
|
|
|
6246
7291
|
// src/compliance/client.ts
|
|
7292
|
+
init_errors();
|
|
6247
7293
|
var cache = /* @__PURE__ */ new WeakMap();
|
|
6248
7294
|
Object.defineProperty(Client.prototype, "compliance", {
|
|
6249
7295
|
configurable: true,
|
|
@@ -7060,11 +8106,10 @@ var ComplianceClient = class {
|
|
|
7060
8106
|
}
|
|
7061
8107
|
const resp = await this.client.doRequest({ method, url, headers, body: bodyStr }, signal);
|
|
7062
8108
|
if (resp.status === 401 && opts.retryOn401 && !retried) {
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
await this.client.forceRefresh(signal);
|
|
8109
|
+
const bodyBytes = resp.body ? await readLimited(resp.body, maxErrorBodySize) : new Uint8Array();
|
|
8110
|
+
const authError = parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
8111
|
+
if (!isUserAccessTokenRejected(authError)) throw authError;
|
|
8112
|
+
await this.client.forceRefresh(signal, token);
|
|
7068
8113
|
return this.executeJsonInner(method, path, body, signal, opts, true);
|
|
7069
8114
|
}
|
|
7070
8115
|
if (resp.status < 200 || resp.status >= 300) {
|
|
@@ -7835,6 +8880,6 @@ function brandCredential(c) {
|
|
|
7835
8880
|
return c;
|
|
7836
8881
|
}
|
|
7837
8882
|
|
|
7838
|
-
export { AGENT_RUN_META_TITLE, AGENT_RUN_META_WORKSPACE, ALL_INTEGRATION_STATUS, ALL_PLATFORMS, ALL_REGIONS, AgentRunStreamError, AgentRunsClient, AnthropicAdapter, AudienceEnum, BillingModeEnum, BucketClassCommercial, BucketClassGeneric, BusinessError, CHAT_REQUEST_TIMEOUT_MS, ChatBridgeClient, Client, ComplianceClient, CompliancePollError, CrabCodeByokClient, DEFAULT_API_TIMEOUT_MS, DEFAULT_GATEWAY_BASE_URL, DefaultRetryPolicy, ErrAuthDenied, ErrBillingCallbackCannotCommit, ErrBillingCommitRequiresLocalVerify, ErrBillingS2sForbidden, ErrBrowserOpen, ErrComplianceStepUpRequired, ErrDiscovery, ErrEnvelopeGateClosed, ErrOAuthCORSBlocked, ErrProviderNotConfigured, ErrProviderUnknownNoRetry, ErrRefreshProxyFailed, ErrRegistration, ErrSSLProxy, ErrSealApprovalContractHashMismatch, ErrSealApprovalExpired, ErrSealApprovalLocationMismatch, ErrSealApprovalNonceUsed, ErrSealApprovalNotApproved, ErrSealApprovalSealMismatch, ErrSealApprovalTransactorMismatch, ErrSealUseAlreadyConsumed, ErrStateMismatch, ErrTimeout, ErrTokenExchange, ErrTokenExpired, EventAuthURL, EventComplete, EventError, FileTokenStore, FilterStatusAdminBypass, FilterStatusDisabledByFlag, FilterStatusFallbackMissingUser, FilterStatusFallbackNoBuckets, FilterStatusFallbackTkdistError, FilterStatusFallbackTkdistSkew, FilterStatusInternalBypass, FilterStatusOK, FilterStatusUnknown, GATEWAY_REQUEST_ID_HEADER, HTTPError, IdempotencyKeyHeader, InMemoryTokenStore, LocalStorageTokenStore, ModelNotFoundError, NetworkError, OAuthTokenEndpointError, OpenAIAdapter, OrderTerminalError, ProductFamilyEnum, ProviderFormat, RETRY_ADVICE_REASONS, RateLimitError, RegionScopeEnum, ScopeAI, ScopeAccount, ScopeAgentAccessManage, ScopeChatBridge, ScopeChatBridgeRead, ScopeChatBridgeRotate, ScopeChatBridgeWrite, ScopeComplianceContractSigningRead, ScopeComplianceContractSigningWrite, ScopeComplianceContractTemplateRead, ScopeComplianceContractTemplateWrite, ScopeComplianceEvidenceRead, ScopeComplianceEvidenceWrite, ScopeComplianceReportsPublish, ScopeComplianceReportsRead, ScopeComplianceReportsWrite, ScopeComplianceSealApprovalApprove, ScopeComplianceSealApprovalRequest, ScopeComplianceSealManage, ScopeComplianceSealUseExecute, ScopeComplianceTimestampIssue, ScopeComplianceTimestampVerify, ScopeEntitlements, ScopeModels, ScopeModelsChat, ScopeProfile, ScopeRemoteControl, ScopeRemoteControlAgentRun, ScopeRemoteControlPermissionResponse, ScopeRemoteControlSessionControl, ScopeSkillStore, ScopeSkills, ScopeTokenPackages, ScopeTools, ScopeToolsExecute, ScopeWallet, ScopeWalletReadonly, ServerToolTypeWebSearch, StreamError, ThinkingHigh, ThinkingHighMinMaxTokens, ThinkingMax, ThinkingMaxFallbackMaxTokens, ThinkingOff, agentAccessScopes, allScopes, anthropicResponseTextContent, anthropicResponseThinkingContent, anthropicResponseToolUseBlocks, apiResponseBusinessError, apiResponseGetMessage, asCredentialRef, authorize, bucketInfoIsCommercial, bucketRowIsCommercial, buildBetas, chatBridgeScopes, classifyComplianceError, classifySourcesEvent, commerceScopes, completeWebAuthorizationRequest, complianceErrorToRetryAdvice, complianceScopes, computeBackoff, createWebAuthorizationRequest, defaultRetryable, defaultSafeToRetry, discover, discoverWebOAuthMetadata, discoverWithProfile, effectivePolicy, exchangeCode, extractAnthropicBlockMeta, fileLockDefaults, findDesktopVisualUnderstandingModel, findFirstModelByInputModality, generateState, getAdapter, getAdapterForModel, getWindowLimitStreamDetails, isBillingConfirmable, isChannelInboundEvent, isComplianceBusinessError, isComplianceTerminalError, isContinuableWindowLimitError, isIntegrationStatus, isInvalidGrantError, isPlatform, isRegion, isSSECommentLine, isSSLError, isTerminalRemoteEvent, isValidTokenSet, isWindowLimitError, isWindowLimitStreamError, maxEndUserIdLength, modelScopes, modelSupportsImageInput, modelSupportsInputModality, newFileTokenStore, newThinkingConfig, newTokenSet, newWebSearchTool, normalizeGatewayBaseURL, normalizeOverrideBaseURL, parseNotificationEvent, parseRemoteControlEvent, parseSettlement, parseSourcesEvent, refreshToken, register, registerWebOAuthClient, remoteControlScopes, retryReasonForComplianceKey, retryReasonForOAuthError, revokeToken, sanitize_exports as sanitize, skillScopes, tokenSetIsExpired, uniqueMerge, validateEndUserId };
|
|
8883
|
+
export { AGENT_RUN_META_TITLE, AGENT_RUN_META_WORKSPACE, ALL_INTEGRATION_STATUS, ALL_PLATFORMS, ALL_REGIONS, AgentRunStreamError, AgentRunsClient, AnthropicAdapter, AudienceEnum, BillingModeEnum, BucketClassCommercial, BucketClassGeneric, BusinessError, CHAT_REQUEST_TIMEOUT_MS, ChatBridgeClient, Client, ComplianceClient, CompliancePollError, CrabCodeByokClient, DEFAULT_API_TIMEOUT_MS, DEFAULT_GATEWAY_BASE_URL, DefaultRetryPolicy, ErrAuthDenied, ErrBillingCallbackCannotCommit, ErrBillingCommitRequiresLocalVerify, ErrBillingS2sForbidden, ErrBrowserOpen, ErrComplianceStepUpRequired, ErrDiscovery, ErrEnvelopeGateClosed, ErrOAuthCORSBlocked, ErrProviderNotConfigured, ErrProviderUnknownNoRetry, ErrRefreshProxyFailed, ErrRegistration, ErrSSLProxy, ErrSealApprovalContractHashMismatch, ErrSealApprovalExpired, ErrSealApprovalLocationMismatch, ErrSealApprovalNonceUsed, ErrSealApprovalNotApproved, ErrSealApprovalSealMismatch, ErrSealApprovalTransactorMismatch, ErrSealUseAlreadyConsumed, ErrStateMismatch, ErrTimeout, ErrTokenExchange, ErrTokenExpired, EventAuthURL, EventComplete, EventError, FileTokenStore, FilterStatusAdminBypass, FilterStatusDisabledByFlag, FilterStatusFallbackMissingUser, FilterStatusFallbackNoBuckets, FilterStatusFallbackTkdistError, FilterStatusFallbackTkdistSkew, FilterStatusInternalBypass, FilterStatusOK, FilterStatusUnknown, GATEWAY_REQUEST_ID_HEADER, HTTPError, IdempotencyKeyHeader, InMemoryTokenStore, LocalStorageTokenStore, ModelNotFoundError, NetworkError, OAuthTokenEndpointError, OpenAIAdapter, OrderTerminalError, ProductFamilyEnum, ProviderFormat, RETRY_ADVICE_REASONS, RateLimitError, RegionScopeEnum, ScopeAI, ScopeAccount, ScopeAgentAccessManage, ScopeChatBridge, ScopeChatBridgeRead, ScopeChatBridgeRotate, ScopeChatBridgeWrite, ScopeComplianceContractSigningRead, ScopeComplianceContractSigningWrite, ScopeComplianceContractTemplateRead, ScopeComplianceContractTemplateWrite, ScopeComplianceEvidenceRead, ScopeComplianceEvidenceWrite, ScopeComplianceReportsPublish, ScopeComplianceReportsRead, ScopeComplianceReportsWrite, ScopeComplianceSealApprovalApprove, ScopeComplianceSealApprovalRequest, ScopeComplianceSealManage, ScopeComplianceSealUseExecute, ScopeComplianceTimestampIssue, ScopeComplianceTimestampVerify, ScopeEntitlements, ScopeModels, ScopeModelsChat, ScopeProfile, ScopeRemoteControl, ScopeRemoteControlAgentRun, ScopeRemoteControlPermissionResponse, ScopeRemoteControlSessionControl, ScopeSkillStore, ScopeSkills, ScopeTokenPackages, ScopeTools, ScopeToolsExecute, ScopeWallet, ScopeWalletReadonly, ServerToolTypeWebSearch, StreamError, ThinkingHigh, ThinkingHighMinMaxTokens, ThinkingLow, ThinkingMax, ThinkingMaxFallbackMaxTokens, ThinkingOff, agentAccessScopes, allScopes, anthropicResponseTextContent, anthropicResponseThinkingContent, anthropicResponseToolUseBlocks, apiResponseBusinessError, apiResponseGetMessage, asCredentialRef, authorize, bucketInfoIsCommercial, bucketRowIsCommercial, buildBetas, chatBridgeScopes, classifyComplianceError, classifySourcesEvent, commerceScopes, completeWebAuthorizationRequest, complianceErrorToRetryAdvice, complianceScopes, computeBackoff, createWebAuthorizationRequest, defaultRetryable, defaultSafeToRetry, discover, discoverWebOAuthMetadata, discoverWithProfile, effectivePolicy, exchangeCode, extractAnthropicBlockMeta, fileLockDefaults, findDesktopVisualUnderstandingModel, findFirstModelByInputModality, generateState, getAdapter, getAdapterForModel, getWindowLimitStreamDetails, isBillingConfirmable, isChannelInboundEvent, isComplianceBusinessError, isComplianceTerminalError, isContinuableWindowLimitError, isIntegrationStatus, isInvalidGrantError, isPlatform, isRegion, isSSECommentLine, isSSLError, isTerminalRemoteEvent, isUserAccessTokenRejected, isValidTokenSet, isWindowLimitError, isWindowLimitStreamError, maxEndUserIdLength, modelScopes, modelSupportsImageInput, modelSupportsInputModality, newFileTokenStore, newThinkingConfig, newTokenSet, newWebSearchTool, normalizeGatewayBaseURL, normalizeOverrideBaseURL, parseNotificationEvent, parseRemoteControlEvent, parseSettlement, parseSourcesEvent, readGatewayErrorContract, refreshToken, register, registerWebOAuthClient, remoteControlScopes, retryReasonForComplianceKey, retryReasonForOAuthError, revokeToken, sanitize_exports as sanitize, skillScopes, tokenSetIsExpired, uniqueMerge, validateEndUserId };
|
|
7839
8884
|
//# sourceMappingURL=index.mjs.map
|
|
7840
8885
|
//# sourceMappingURL=index.mjs.map
|