@acosmi/sdk-ts 1.4.1 → 1.4.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 +28 -0
- package/README.md +8 -3
- package/dist/browser/index.mjs +1920 -1898
- package/dist/browser/index.mjs.map +1 -1
- package/dist/index.mjs +1920 -1898
- package/dist/index.mjs.map +1 -1
- package/dist/node/adapters/anthropic.cjs +6 -4
- 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 +6 -4
- package/dist/node/adapters/anthropic.mjs.map +1 -1
- package/dist/node/adapters/openai.cjs +4 -2
- package/dist/node/adapters/openai.cjs.map +1 -1
- package/dist/node/adapters/openai.d.cts +2 -64
- package/dist/node/adapters/openai.d.ts +2 -64
- package/dist/node/adapters/openai.mjs +4 -2
- package/dist/node/adapters/openai.mjs.map +1 -1
- package/dist/node/index-DEA6LXw6.d.cts +409 -0
- package/dist/node/index-DEA6LXw6.d.ts +409 -0
- package/dist/node/index.cjs +1920 -1898
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +1439 -866
- package/dist/node/index.d.ts +1439 -866
- package/dist/node/index.mjs +1920 -1898
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/openai-BDodfhsG.d.cts +125 -0
- package/dist/node/openai-vfUUgdvL.d.ts +125 -0
- package/examples/agent-runs-stream.ts +118 -0
- package/examples/auth-oauth-flow.ts +97 -0
- package/examples/core-chat.ts +85 -0
- package/package.json +5 -2
- package/dist/node/index-CbG9NqE-.d.cts +0 -1027
- package/dist/node/index-CbG9NqE-.d.ts +0 -1027
package/dist/index.mjs
CHANGED
|
@@ -8,11 +8,7 @@ var __export = (target, all) => {
|
|
|
8
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
// src/types.ts
|
|
12
|
-
function tokenSetIsExpired(t) {
|
|
13
|
-
const expiresAt = new Date(t.expires_at).getTime();
|
|
14
|
-
return Date.now() > expiresAt - 3e4;
|
|
15
|
-
}
|
|
11
|
+
// src/models/types.ts
|
|
16
12
|
function bucketInfoIsCommercial(b) {
|
|
17
13
|
if (!b) return false;
|
|
18
14
|
return b.bucketClass.toLowerCase() === BucketClassCommercial.toLowerCase();
|
|
@@ -60,23 +56,6 @@ function parseSourcesEvent(ev) {
|
|
|
60
56
|
}
|
|
61
57
|
return { sources: wrapper.sources, session_id: wrapper.session_id };
|
|
62
58
|
}
|
|
63
|
-
function anthropicResponseTextContent(r) {
|
|
64
|
-
const parts = [];
|
|
65
|
-
for (const b of r.content) {
|
|
66
|
-
if (b.type === "text" && b.text) parts.push(b.text);
|
|
67
|
-
}
|
|
68
|
-
return parts.join("");
|
|
69
|
-
}
|
|
70
|
-
function anthropicResponseThinkingContent(r) {
|
|
71
|
-
const parts = [];
|
|
72
|
-
for (const b of r.content) {
|
|
73
|
-
if (b.type === "thinking" && b.thinking) parts.push(b.thinking);
|
|
74
|
-
}
|
|
75
|
-
return parts.join("");
|
|
76
|
-
}
|
|
77
|
-
function anthropicResponseToolUseBlocks(r) {
|
|
78
|
-
return r.content.filter((b) => b.type === "tool_use");
|
|
79
|
-
}
|
|
80
59
|
function parseSettlement(ev) {
|
|
81
60
|
if (ev.event !== "settled" && ev.event !== "pending_settle") {
|
|
82
61
|
return null;
|
|
@@ -97,36 +76,9 @@ function parseSettlement(ev) {
|
|
|
97
76
|
callRemaining: s.callRemaining ?? -1
|
|
98
77
|
};
|
|
99
78
|
}
|
|
100
|
-
|
|
101
|
-
return r.message ?? r.msg ?? "";
|
|
102
|
-
}
|
|
103
|
-
function apiResponseBusinessError(r) {
|
|
104
|
-
if (r.code !== 0) {
|
|
105
|
-
return new BusinessError(r.code, apiResponseGetMessage(r));
|
|
106
|
-
}
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
function parseNotificationEvent(ev) {
|
|
110
|
-
if (ev.type !== "event" || ev.topic !== "system") {
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
if (ev.data == null) return null;
|
|
114
|
-
let n;
|
|
115
|
-
try {
|
|
116
|
-
if (typeof ev.data === "string") {
|
|
117
|
-
n = JSON.parse(ev.data);
|
|
118
|
-
} else {
|
|
119
|
-
n = ev.data;
|
|
120
|
-
}
|
|
121
|
-
} catch {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
if (!n.id) return null;
|
|
125
|
-
return n;
|
|
126
|
-
}
|
|
127
|
-
var BucketClassCommercial, BucketClassGeneric, ThinkingOff, ThinkingHigh, ThinkingMax, ThinkingHighMinMaxTokens, ThinkingMaxFallbackMaxTokens, ServerToolTypeWebSearch, RateLimitError, BusinessError, OrderTerminalError, ModelNotFoundError, HTTPError, NetworkError, StreamError;
|
|
79
|
+
var BucketClassCommercial, BucketClassGeneric, ThinkingOff, ThinkingHigh, ThinkingMax, ThinkingHighMinMaxTokens, ThinkingMaxFallbackMaxTokens, ServerToolTypeWebSearch;
|
|
128
80
|
var init_types = __esm({
|
|
129
|
-
"src/types.ts"() {
|
|
81
|
+
"src/models/types.ts"() {
|
|
130
82
|
BucketClassCommercial = "COMMERCIAL";
|
|
131
83
|
BucketClassGeneric = "GENERIC";
|
|
132
84
|
ThinkingOff = "off";
|
|
@@ -135,6 +87,13 @@ var init_types = __esm({
|
|
|
135
87
|
ThinkingHighMinMaxTokens = 32e3;
|
|
136
88
|
ThinkingMaxFallbackMaxTokens = 128e3;
|
|
137
89
|
ServerToolTypeWebSearch = "web_search_20250305";
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// src/shared/errors.ts
|
|
94
|
+
var RateLimitError, BusinessError, OrderTerminalError, ModelNotFoundError, HTTPError, NetworkError, StreamError;
|
|
95
|
+
var init_errors = __esm({
|
|
96
|
+
"src/shared/errors.ts"() {
|
|
138
97
|
RateLimitError = class extends Error {
|
|
139
98
|
retryAfter;
|
|
140
99
|
raw;
|
|
@@ -254,7 +213,7 @@ var init_types = __esm({
|
|
|
254
213
|
}
|
|
255
214
|
});
|
|
256
215
|
|
|
257
|
-
// src/betas.ts
|
|
216
|
+
// src/models/betas.ts
|
|
258
217
|
function buildBetas(caps, req) {
|
|
259
218
|
const betas = [];
|
|
260
219
|
if (caps.supports_isp) {
|
|
@@ -301,7 +260,7 @@ function uniqueMerge(base, extra) {
|
|
|
301
260
|
}
|
|
302
261
|
var betaInterleavedThinking, betaContext1M, betaContextManagement, betaStructuredOutputs, betaAdvancedToolUse, betaEffort, betaPromptCachingScope, betaFastMode, betaRedactThinking, betaTokenEfficientTools;
|
|
303
262
|
var init_betas = __esm({
|
|
304
|
-
"src/betas.ts"() {
|
|
263
|
+
"src/models/betas.ts"() {
|
|
305
264
|
init_types();
|
|
306
265
|
betaInterleavedThinking = "interleaved-thinking-2025-05-14";
|
|
307
266
|
betaContext1M = "context-1m-2025-08-07";
|
|
@@ -316,7 +275,7 @@ var init_betas = __esm({
|
|
|
316
275
|
}
|
|
317
276
|
});
|
|
318
277
|
|
|
319
|
-
// src/adapters/anthropic.ts
|
|
278
|
+
// src/models/adapters/anthropic.ts
|
|
320
279
|
function resolveThinkingLevel(body, req, caps) {
|
|
321
280
|
const level = req.thinking?.level ?? "";
|
|
322
281
|
if (level === ThinkingOff) {
|
|
@@ -363,8 +322,9 @@ function resolveThinkingLevel(body, req, caps) {
|
|
|
363
322
|
}
|
|
364
323
|
var AnthropicAdapter;
|
|
365
324
|
var init_anthropic = __esm({
|
|
366
|
-
"src/adapters/anthropic.ts"() {
|
|
325
|
+
"src/models/adapters/anthropic.ts"() {
|
|
367
326
|
init_types();
|
|
327
|
+
init_errors();
|
|
368
328
|
init_betas();
|
|
369
329
|
init_adapters();
|
|
370
330
|
AnthropicAdapter = class {
|
|
@@ -498,7 +458,7 @@ var init_anthropic = __esm({
|
|
|
498
458
|
}
|
|
499
459
|
});
|
|
500
460
|
|
|
501
|
-
// src/adapters/openai.ts
|
|
461
|
+
// src/models/adapters/openai.ts
|
|
502
462
|
var openai_exports = {};
|
|
503
463
|
__export(openai_exports, {
|
|
504
464
|
OpenAIAdapter: () => OpenAIAdapter,
|
|
@@ -693,8 +653,9 @@ function newOpenAIStreamConverter() {
|
|
|
693
653
|
}
|
|
694
654
|
var OpenAIAdapter, OpenAIStreamConverter;
|
|
695
655
|
var init_openai = __esm({
|
|
696
|
-
"src/adapters/openai.ts"() {
|
|
656
|
+
"src/models/adapters/openai.ts"() {
|
|
697
657
|
init_types();
|
|
658
|
+
init_errors();
|
|
698
659
|
init_adapters();
|
|
699
660
|
OpenAIAdapter = class {
|
|
700
661
|
format() {
|
|
@@ -962,7 +923,7 @@ var init_openai = __esm({
|
|
|
962
923
|
}
|
|
963
924
|
});
|
|
964
925
|
|
|
965
|
-
// src/adapters/index.ts
|
|
926
|
+
// src/models/adapters/index.ts
|
|
966
927
|
function getAdapter(provider) {
|
|
967
928
|
const a = adapterRegistry[provider.toLowerCase()];
|
|
968
929
|
if (a) return a;
|
|
@@ -994,7 +955,7 @@ function getAdapterForModel(m) {
|
|
|
994
955
|
}
|
|
995
956
|
var ProviderFormat, adapterRegistry, defaultOpenAIAdapter;
|
|
996
957
|
var init_adapters = __esm({
|
|
997
|
-
"src/adapters/index.ts"() {
|
|
958
|
+
"src/models/adapters/index.ts"() {
|
|
998
959
|
init_anthropic();
|
|
999
960
|
init_openai();
|
|
1000
961
|
ProviderFormat = /* @__PURE__ */ ((ProviderFormat2) => {
|
|
@@ -1011,50 +972,31 @@ var init_adapters = __esm({
|
|
|
1011
972
|
}
|
|
1012
973
|
});
|
|
1013
974
|
|
|
1014
|
-
// src/
|
|
975
|
+
// src/core/client.ts
|
|
1015
976
|
init_types();
|
|
1016
977
|
|
|
1017
|
-
// src/
|
|
1018
|
-
function
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
if (!Array.isArray(mods)) return false;
|
|
1022
|
-
return mods.includes(modality);
|
|
978
|
+
// src/auth/types.ts
|
|
979
|
+
function tokenSetIsExpired(t) {
|
|
980
|
+
const expiresAt = new Date(t.expires_at).getTime();
|
|
981
|
+
return Date.now() > expiresAt - 3e4;
|
|
1023
982
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
983
|
+
|
|
984
|
+
// src/core/client.ts
|
|
985
|
+
init_errors();
|
|
986
|
+
|
|
987
|
+
// src/shared/api-response.ts
|
|
988
|
+
init_errors();
|
|
989
|
+
function apiResponseGetMessage(r) {
|
|
990
|
+
return r.message ?? r.msg ?? "";
|
|
1026
991
|
}
|
|
1027
|
-
function
|
|
1028
|
-
if (
|
|
1029
|
-
|
|
1030
|
-
if (!m) continue;
|
|
1031
|
-
if (m.isEnabled === false) continue;
|
|
1032
|
-
if (!modelSupportsInputModality(m, modality)) continue;
|
|
1033
|
-
return m;
|
|
992
|
+
function apiResponseBusinessError(r) {
|
|
993
|
+
if (r.code !== 0) {
|
|
994
|
+
return new BusinessError(r.code, apiResponseGetMessage(r));
|
|
1034
995
|
}
|
|
1035
996
|
return null;
|
|
1036
997
|
}
|
|
1037
|
-
function findDesktopVisualUnderstandingModel(models) {
|
|
1038
|
-
if (!Array.isArray(models)) return null;
|
|
1039
|
-
const candidates = [];
|
|
1040
|
-
for (const m of models) {
|
|
1041
|
-
if (!m) continue;
|
|
1042
|
-
if (m.isEnabled === false) continue;
|
|
1043
|
-
if (m.capabilities?.supports_desktop_visual_understanding !== true) continue;
|
|
1044
|
-
if (!modelSupportsInputModality(m, "image")) continue;
|
|
1045
|
-
candidates.push(m);
|
|
1046
|
-
}
|
|
1047
|
-
if (candidates.length === 0) return null;
|
|
1048
|
-
for (const m of candidates) {
|
|
1049
|
-
if (m.isDefault === true) return m;
|
|
1050
|
-
}
|
|
1051
|
-
return candidates[0];
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
// src/index.ts
|
|
1055
|
-
init_adapters();
|
|
1056
998
|
|
|
1057
|
-
// src/auth.ts
|
|
999
|
+
// src/auth/auth.ts
|
|
1058
1000
|
var authTimeoutMs = 3e4;
|
|
1059
1001
|
async function discoverWithProfile(serverURL, profile, signal) {
|
|
1060
1002
|
let parsed;
|
|
@@ -1504,251 +1446,29 @@ function withTimeout(ms, parent) {
|
|
|
1504
1446
|
};
|
|
1505
1447
|
}
|
|
1506
1448
|
|
|
1507
|
-
// src/
|
|
1508
|
-
var
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
var
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
var ScopeComplianceSealUseExecute = "compliance:seal_use:execute";
|
|
1531
|
-
var ScopeComplianceReportsRead = "compliance:reports:read";
|
|
1532
|
-
var ScopeComplianceReportsWrite = "compliance:reports:write";
|
|
1533
|
-
var ScopeComplianceReportsPublish = "compliance:reports:publish";
|
|
1534
|
-
function allScopes() {
|
|
1535
|
-
return [ScopeAI, ScopeSkills, ScopeAccount];
|
|
1536
|
-
}
|
|
1537
|
-
function complianceScopes() {
|
|
1538
|
-
return [
|
|
1539
|
-
ScopeComplianceEvidenceRead,
|
|
1540
|
-
ScopeComplianceEvidenceWrite,
|
|
1541
|
-
ScopeComplianceTimestampIssue,
|
|
1542
|
-
ScopeComplianceTimestampVerify,
|
|
1543
|
-
ScopeComplianceContractSigningRead,
|
|
1544
|
-
ScopeComplianceContractSigningWrite,
|
|
1545
|
-
ScopeComplianceSealManage,
|
|
1546
|
-
ScopeComplianceSealApprovalRequest,
|
|
1547
|
-
ScopeComplianceSealApprovalApprove,
|
|
1548
|
-
ScopeComplianceSealUseExecute,
|
|
1549
|
-
ScopeComplianceReportsRead,
|
|
1550
|
-
ScopeComplianceReportsWrite,
|
|
1551
|
-
ScopeComplianceReportsPublish
|
|
1552
|
-
];
|
|
1553
|
-
}
|
|
1554
|
-
function modelScopes() {
|
|
1555
|
-
return [ScopeAI];
|
|
1556
|
-
}
|
|
1557
|
-
function commerceScopes() {
|
|
1558
|
-
return [ScopeAI, ScopeAccount];
|
|
1559
|
-
}
|
|
1560
|
-
function skillScopes() {
|
|
1561
|
-
return [ScopeSkills];
|
|
1562
|
-
}
|
|
1563
|
-
|
|
1564
|
-
// src/compliance-status.ts
|
|
1565
|
-
var ErrComplianceStepUpRequired = "COMPLIANCE_STEP_UP_REQUIRED";
|
|
1566
|
-
var ErrEnvelopeGateClosed = "ENVELOPE_GATE_CLOSED";
|
|
1567
|
-
var ErrProviderNotConfigured = "PROVIDER_NOT_CONFIGURED";
|
|
1568
|
-
var ErrProviderUnknownNoRetry = "PROVIDER_REQUEST_UNKNOWN_NO_RETRY";
|
|
1569
|
-
var ErrBillingCallbackCannotCommit = "BILLING_CALLBACK_CANNOT_COMMIT";
|
|
1570
|
-
var ErrBillingCommitRequiresLocalVerify = "BILLING_COMMIT_REQUIRES_LOCAL_VERIFY";
|
|
1571
|
-
var ErrBillingS2sForbidden = "BILLING_S2S_FORBIDDEN";
|
|
1572
|
-
var ErrSealApprovalNotApproved = "SEAL_APPROVAL_STATE_NOT_APPROVED";
|
|
1573
|
-
var ErrSealApprovalExpired = "SEAL_APPROVAL_EXPIRED";
|
|
1574
|
-
var ErrSealApprovalNonceUsed = "SEAL_APPROVAL_NONCE_USED";
|
|
1575
|
-
var ErrSealApprovalContractHashMismatch = "SEAL_APPROVAL_CONTRACT_HASH_MISMATCH";
|
|
1576
|
-
var ErrSealApprovalSealMismatch = "SEAL_APPROVAL_SEAL_MISMATCH";
|
|
1577
|
-
var ErrSealApprovalLocationMismatch = "SEAL_APPROVAL_LOCATION_MISMATCH";
|
|
1578
|
-
var ErrSealApprovalTransactorMismatch = "SEAL_APPROVAL_TRANSACTOR_MISMATCH";
|
|
1579
|
-
var ErrSealUseAlreadyConsumed = "SEAL_USE_ALREADY_CONSUMED";
|
|
1580
|
-
function isComplianceTerminalError(code) {
|
|
1581
|
-
switch (code) {
|
|
1582
|
-
case ErrEnvelopeGateClosed:
|
|
1583
|
-
case ErrProviderNotConfigured:
|
|
1584
|
-
case ErrProviderUnknownNoRetry:
|
|
1585
|
-
case ErrBillingCallbackCannotCommit:
|
|
1586
|
-
case ErrBillingCommitRequiresLocalVerify:
|
|
1587
|
-
case ErrBillingS2sForbidden:
|
|
1588
|
-
case ErrSealApprovalNonceUsed:
|
|
1589
|
-
case ErrSealApprovalExpired:
|
|
1590
|
-
case ErrSealApprovalContractHashMismatch:
|
|
1591
|
-
case ErrSealApprovalSealMismatch:
|
|
1592
|
-
case ErrSealApprovalLocationMismatch:
|
|
1593
|
-
case ErrSealApprovalTransactorMismatch:
|
|
1594
|
-
case ErrSealUseAlreadyConsumed:
|
|
1595
|
-
return true;
|
|
1596
|
-
default:
|
|
1597
|
-
return false;
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
function isBillingConfirmable(providerStatus, billingStatus) {
|
|
1601
|
-
return providerStatus === "success" && billingStatus === "committed";
|
|
1602
|
-
}
|
|
1603
|
-
|
|
1604
|
-
// src/compliance-errors.ts
|
|
1605
|
-
var CODE_TO_KEY = {
|
|
1606
|
-
// 通用 / token / scope (1-031-000-xxx)
|
|
1607
|
-
1031000001: "COMPLIANCE_UNAUTHORIZED",
|
|
1608
|
-
1031000002: "COMPLIANCE_TOKEN_INVALID",
|
|
1609
|
-
1031000003: "COMPLIANCE_TOKEN_INVALID",
|
|
1610
|
-
1031000004: "COMPLIANCE_TOKEN_INVALID",
|
|
1611
|
-
1031000005: "COMPLIANCE_TOKEN_INVALID",
|
|
1612
|
-
1031000006: "COMPLIANCE_TOKEN_INVALID",
|
|
1613
|
-
1031000007: "COMPLIANCE_TOKEN_INVALID",
|
|
1614
|
-
1031000008: "COMPLIANCE_TOKEN_INVALID",
|
|
1615
|
-
1031000009: "COMPLIANCE_TOKEN_INVALID",
|
|
1616
|
-
1031000010: "COMPLIANCE_TOKEN_INVALID",
|
|
1617
|
-
1031000011: "COMPLIANCE_TOKEN_INVALID",
|
|
1618
|
-
1031000012: "COMPLIANCE_INSUFFICIENT_SCOPE",
|
|
1619
|
-
1031000013: "COMPLIANCE_STEP_UP_REQUIRED",
|
|
1620
|
-
// Subject snapshot (1-031-001-xxx)
|
|
1621
|
-
1031001001: "SUBJECT_SNAPSHOT_NOT_FOUND",
|
|
1622
|
-
1031001002: "SUBJECT_SNAPSHOT_TENANT_MISMATCH",
|
|
1623
|
-
1031001003: "SUBJECT_SNAPSHOT_REQUIRED",
|
|
1624
|
-
// Evidence / Timestamp / Package / Report (1-031-002-xxx)
|
|
1625
|
-
1031002001: "EVIDENCE_ASSET_NOT_FOUND",
|
|
1626
|
-
1031002002: "SUBJECT_SNAPSHOT_TENANT_MISMATCH",
|
|
1627
|
-
1031002003: "EVIDENCE_ASSET_HASH_MISMATCH",
|
|
1628
|
-
1031002004: "EVIDENCE_ASSET_PAYLOAD_REQUIRED",
|
|
1629
|
-
1031002005: "EVIDENCE_ASSET_PAYLOAD_REQUIRED",
|
|
1630
|
-
1031002006: "TIMESTAMP_TOKEN_NOT_FOUND",
|
|
1631
|
-
1031002007: "TIMESTAMP_PROVIDER_FAILED",
|
|
1632
|
-
1031002008: "TIMESTAMP_PROVIDER_UNKNOWN",
|
|
1633
|
-
1031002009: "TIMESTAMP_LOCAL_VERIFY_FAILED",
|
|
1634
|
-
1031002010: "TIMESTAMP_PROVIDER_NOT_AVAILABLE",
|
|
1635
|
-
1031002011: "EVIDENCE_PACKAGE_NOT_FOUND",
|
|
1636
|
-
1031002012: "EVIDENCE_PACKAGE_TIMESTAMP_REQUIRED",
|
|
1637
|
-
1031002013: "EVIDENCE_PACKAGE_MANIFEST_HASH_MISMATCH",
|
|
1638
|
-
1031002014: "REPORT_NOT_FOUND",
|
|
1639
|
-
1031002015: "REPORT_ALREADY_PUBLISHED",
|
|
1640
|
-
1031002016: "REPORT_DRAFT_REQUIRED",
|
|
1641
|
-
1031002017: "EVIDENCE_VERIFY_TARGET_REQUIRED",
|
|
1642
|
-
1031002018: "EVIDENCE_VERIFY_TARGET_NOT_FOUND",
|
|
1643
|
-
// Provider request (1-031-003-xxx)
|
|
1644
|
-
1031003001: "PROVIDER_REQUEST_UNKNOWN_NO_RETRY",
|
|
1645
|
-
1031003002: "PROVIDER_CALLBACK_SOURCE_INVALID",
|
|
1646
|
-
1031003003: "PROVIDER_NOT_CONFIGURED",
|
|
1647
|
-
1031003010: "PROVIDER_REQUEST_NOT_FOUND",
|
|
1648
|
-
1031003011: "PROVIDER_REQUEST_IDEMPOTENCY_REQUIRED",
|
|
1649
|
-
1031003012: "PROVIDER_REQUEST_STATUS_NOT_TERMINAL",
|
|
1650
|
-
// Envelope (1-031-004-xxx)
|
|
1651
|
-
1031004001: "ENVELOPE_NOT_FOUND",
|
|
1652
|
-
1031004002: "ENVELOPE_TENANT_MISMATCH",
|
|
1653
|
-
1031004003: "ENVELOPE_STATE_NOT_ALLOWED",
|
|
1654
|
-
1031004004: "ENVELOPE_GATE_CLOSED",
|
|
1655
|
-
1031004005: "CONTRACT_NOT_FOUND",
|
|
1656
|
-
1031004006: "CONTRACT_HASH_MISMATCH",
|
|
1657
|
-
1031004007: "CONTRACT_NOT_FOUND",
|
|
1658
|
-
1031004008: "PROVIDER_AUTHORIZATION_NOT_CONFIRMED",
|
|
1659
|
-
1031004009: "PROVIDER_AUTHORIZATION_NOT_CONFIRMED",
|
|
1660
|
-
1031004010: "ENVELOPE_EVIDENCE_NOT_READY",
|
|
1661
|
-
// Seal approval / use (1-031-005-xxx)
|
|
1662
|
-
1031005001: "SEAL_ASSET_NOT_FOUND",
|
|
1663
|
-
1031005010: "SEAL_APPROVAL_NOT_FOUND",
|
|
1664
|
-
1031005011: "SEAL_APPROVAL_NOT_FOUND",
|
|
1665
|
-
1031005012: "SEAL_APPROVAL_STATE_NOT_APPROVED",
|
|
1666
|
-
1031005013: "SEAL_APPROVAL_EXPIRED",
|
|
1667
|
-
1031005014: "SEAL_APPROVAL_ALREADY_USED",
|
|
1668
|
-
1031005015: "SEAL_APPROVAL_NONCE_USED",
|
|
1669
|
-
1031005016: "SEAL_APPROVAL_SEAL_MISMATCH",
|
|
1670
|
-
1031005017: "SEAL_APPROVAL_LOCATION_MISMATCH",
|
|
1671
|
-
1031005018: "SEAL_APPROVAL_TRANSACTOR_MISMATCH",
|
|
1672
|
-
1031005019: "SEAL_APPROVAL_CONTRACT_HASH_MISMATCH",
|
|
1673
|
-
1031005020: "SEAL_APPROVAL_INVALID_TRANSITION",
|
|
1674
|
-
1031005030: "SEAL_USE_ALREADY_CONSUMED",
|
|
1675
|
-
// Billing (1-031-006-xxx)
|
|
1676
|
-
1031006004: "BILLING_COMMIT_REQUIRES_LOCAL_VERIFY",
|
|
1677
|
-
1031006005: "BILLING_COMMIT_REQUIRES_PROVIDER_SUCCESS",
|
|
1678
|
-
1031006007: "BILLING_CALLBACK_CANNOT_COMMIT",
|
|
1679
|
-
1031006008: "BILLING_PROVIDER_UNKNOWN_NOT_COMMITTABLE",
|
|
1680
|
-
1031006009: "BILLING_S2S_FORBIDDEN",
|
|
1681
|
-
// Audit (1-031-007-xxx)
|
|
1682
|
-
1031007011: "AUDIT_CHAIN_TAMPER_DETECTED"
|
|
1683
|
-
};
|
|
1684
|
-
var STEP_UP_KEYS = /* @__PURE__ */ new Set(["COMPLIANCE_STEP_UP_REQUIRED"]);
|
|
1685
|
-
var TERMINAL_KEYS = /* @__PURE__ */ new Set([
|
|
1686
|
-
"ENVELOPE_GATE_CLOSED",
|
|
1687
|
-
"PROVIDER_NOT_CONFIGURED",
|
|
1688
|
-
"PROVIDER_REQUEST_UNKNOWN_NO_RETRY",
|
|
1689
|
-
"BILLING_CALLBACK_CANNOT_COMMIT",
|
|
1690
|
-
"BILLING_COMMIT_REQUIRES_LOCAL_VERIFY",
|
|
1691
|
-
"BILLING_COMMIT_REQUIRES_PROVIDER_SUCCESS",
|
|
1692
|
-
"BILLING_PROVIDER_UNKNOWN_NOT_COMMITTABLE",
|
|
1693
|
-
"BILLING_S2S_FORBIDDEN",
|
|
1694
|
-
"SEAL_APPROVAL_NONCE_USED",
|
|
1695
|
-
"SEAL_APPROVAL_EXPIRED",
|
|
1696
|
-
"SEAL_APPROVAL_CONTRACT_HASH_MISMATCH",
|
|
1697
|
-
"SEAL_APPROVAL_SEAL_MISMATCH",
|
|
1698
|
-
"SEAL_APPROVAL_LOCATION_MISMATCH",
|
|
1699
|
-
"SEAL_APPROVAL_TRANSACTOR_MISMATCH",
|
|
1700
|
-
"SEAL_USE_ALREADY_CONSUMED",
|
|
1701
|
-
"CONTRACT_HASH_MISMATCH",
|
|
1702
|
-
"TIMESTAMP_LOCAL_VERIFY_FAILED",
|
|
1703
|
-
"EVIDENCE_PACKAGE_MANIFEST_HASH_MISMATCH",
|
|
1704
|
-
"AUDIT_CHAIN_TAMPER_DETECTED",
|
|
1705
|
-
"PROVIDER_REQUEST_NOT_FOUND",
|
|
1706
|
-
"EVIDENCE_ASSET_HASH_MISMATCH",
|
|
1707
|
-
"EVIDENCE_VERIFY_TARGET_NOT_FOUND",
|
|
1708
|
-
"REPORT_ALREADY_PUBLISHED"
|
|
1709
|
-
]);
|
|
1710
|
-
var RETRYABLE_KEYS = /* @__PURE__ */ new Set([]);
|
|
1711
|
-
function classifyComplianceError(err) {
|
|
1712
|
-
const key = CODE_TO_KEY[err.code] ?? "UNKNOWN_COMPLIANCE_ERROR";
|
|
1713
|
-
return {
|
|
1714
|
-
code: err.code,
|
|
1715
|
-
message: err.message,
|
|
1716
|
-
key,
|
|
1717
|
-
retryable: RETRYABLE_KEYS.has(key),
|
|
1718
|
-
terminal: TERMINAL_KEYS.has(key),
|
|
1719
|
-
stepUpRequired: STEP_UP_KEYS.has(key)
|
|
1720
|
-
};
|
|
1721
|
-
}
|
|
1722
|
-
function isComplianceBusinessError(err) {
|
|
1723
|
-
return err.code >= 1031e6 && err.code <= 1031999999;
|
|
1724
|
-
}
|
|
1725
|
-
|
|
1726
|
-
// src/client.ts
|
|
1727
|
-
init_types();
|
|
1728
|
-
|
|
1729
|
-
// src/store.ts
|
|
1730
|
-
var fileLockDefaults = {
|
|
1731
|
-
/** 获取锁的超时上限 (毫秒). refresh 流程含网络 < 30s, 30s 已远超正常完成时间. */
|
|
1732
|
-
acquireTimeoutMs: 3e4,
|
|
1733
|
-
/** 旧锁判定阈值 (毫秒). 锁文件 mtime 早于此值视为 stale 进程崩溃残留, 自动 break. */
|
|
1734
|
-
staleMs: 6e4,
|
|
1735
|
-
/** 重试间隔基数 (毫秒). 真实间隔 = base + random(0, jitter). */
|
|
1736
|
-
retryBaseMs: 30,
|
|
1737
|
-
retryJitterMs: 70
|
|
1738
|
-
};
|
|
1739
|
-
var FileTokenStore = class {
|
|
1740
|
-
path;
|
|
1741
|
-
/** 进程内串行化 (Promise chain) — 与跨进程 flock 配合, 避免单进程内并发持锁产生死锁式互等. */
|
|
1742
|
-
chain = Promise.resolve();
|
|
1743
|
-
constructor(path) {
|
|
1744
|
-
if (typeof process === "undefined" || !process.versions || !process.versions.node) {
|
|
1745
|
-
throw new Error("FileTokenStore requires Node.js environment; use LocalStorageTokenStore or InMemoryTokenStore in browser");
|
|
1746
|
-
}
|
|
1747
|
-
if (path && path !== "") {
|
|
1748
|
-
this.path = path;
|
|
1749
|
-
} else {
|
|
1750
|
-
this.path = "";
|
|
1751
|
-
}
|
|
1449
|
+
// src/core/store.ts
|
|
1450
|
+
var fileLockDefaults = {
|
|
1451
|
+
/** 获取锁的超时上限 (毫秒). refresh 流程含网络 < 30s, 30s 已远超正常完成时间. */
|
|
1452
|
+
acquireTimeoutMs: 3e4,
|
|
1453
|
+
/** 旧锁判定阈值 (毫秒). 锁文件 mtime 早于此值视为 stale 进程崩溃残留, 自动 break. */
|
|
1454
|
+
staleMs: 6e4,
|
|
1455
|
+
/** 重试间隔基数 (毫秒). 真实间隔 = base + random(0, jitter). */
|
|
1456
|
+
retryBaseMs: 30,
|
|
1457
|
+
retryJitterMs: 70
|
|
1458
|
+
};
|
|
1459
|
+
var FileTokenStore = class {
|
|
1460
|
+
path;
|
|
1461
|
+
/** 进程内串行化 (Promise chain) — 与跨进程 flock 配合, 避免单进程内并发持锁产生死锁式互等. */
|
|
1462
|
+
chain = Promise.resolve();
|
|
1463
|
+
constructor(path) {
|
|
1464
|
+
if (typeof process === "undefined" || !process.versions || !process.versions.node) {
|
|
1465
|
+
throw new Error("FileTokenStore requires Node.js environment; use LocalStorageTokenStore or InMemoryTokenStore in browser");
|
|
1466
|
+
}
|
|
1467
|
+
if (path && path !== "") {
|
|
1468
|
+
this.path = path;
|
|
1469
|
+
} else {
|
|
1470
|
+
this.path = "";
|
|
1471
|
+
}
|
|
1752
1472
|
}
|
|
1753
1473
|
async resolvePath() {
|
|
1754
1474
|
if (this.path && this.path !== "") return this.path;
|
|
@@ -1945,8 +1665,8 @@ var InMemoryTokenStore = class {
|
|
|
1945
1665
|
}
|
|
1946
1666
|
};
|
|
1947
1667
|
|
|
1948
|
-
// src/retry.ts
|
|
1949
|
-
|
|
1668
|
+
// src/core/retry.ts
|
|
1669
|
+
init_errors();
|
|
1950
1670
|
var DefaultRetryPolicy = {
|
|
1951
1671
|
maxAttempts: 2,
|
|
1952
1672
|
backoffMs: 200,
|
|
@@ -2001,10 +1721,10 @@ function computeBackoff(p, attempt, err) {
|
|
|
2001
1721
|
return d;
|
|
2002
1722
|
}
|
|
2003
1723
|
|
|
2004
|
-
// src/client.ts
|
|
1724
|
+
// src/core/client.ts
|
|
2005
1725
|
init_adapters();
|
|
2006
1726
|
|
|
2007
|
-
// src/stream-meta.ts
|
|
1727
|
+
// src/models/stream-meta.ts
|
|
2008
1728
|
function extractAnthropicBlockMeta(eventType, data, blockTypeMap) {
|
|
2009
1729
|
switch (eventType) {
|
|
2010
1730
|
case "content_block_start": {
|
|
@@ -2050,11 +1770,11 @@ function extractAnthropicBlockMeta(eventType, data, blockTypeMap) {
|
|
|
2050
1770
|
}
|
|
2051
1771
|
}
|
|
2052
1772
|
|
|
2053
|
-
// src/client.ts
|
|
1773
|
+
// src/core/client.ts
|
|
2054
1774
|
init_openai();
|
|
2055
1775
|
|
|
2056
|
-
// src/
|
|
2057
|
-
|
|
1776
|
+
// src/core/http.ts
|
|
1777
|
+
init_errors();
|
|
2058
1778
|
var maxDownloadSize = 50 * 1024 * 1024;
|
|
2059
1779
|
var maxErrorBodySize = 1 * 1024 * 1024;
|
|
2060
1780
|
var maxSSELineSize = 1 * 1024 * 1024;
|
|
@@ -2230,7 +1950,7 @@ async function readLimitedText(body, maxBytes) {
|
|
|
2230
1950
|
return new TextDecoder("utf-8").decode(buf);
|
|
2231
1951
|
}
|
|
2232
1952
|
|
|
2233
|
-
// src/client.ts
|
|
1953
|
+
// src/core/client.ts
|
|
2234
1954
|
var FilterStatusOK = "ok";
|
|
2235
1955
|
var FilterStatusAdminBypass = "admin-bypass";
|
|
2236
1956
|
var FilterStatusInternalBypass = "internal-bypass";
|
|
@@ -3445,860 +3165,1235 @@ async function sleep(ms, signal) {
|
|
|
3445
3165
|
});
|
|
3446
3166
|
}
|
|
3447
3167
|
|
|
3448
|
-
// src/
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3168
|
+
// src/sanitize/index.ts
|
|
3169
|
+
var sanitize_exports = {};
|
|
3170
|
+
__export(sanitize_exports, {
|
|
3171
|
+
BlockCodeExecutionToolResult: () => BlockCodeExecutionToolResult,
|
|
3172
|
+
BlockContainerUpload: () => BlockContainerUpload,
|
|
3173
|
+
BlockDeniedError: () => BlockDeniedError,
|
|
3174
|
+
BlockDocument: () => BlockDocument,
|
|
3175
|
+
BlockImage: () => BlockImage,
|
|
3176
|
+
BlockMCPToolResult: () => BlockMCPToolResult,
|
|
3177
|
+
BlockMCPToolUse: () => BlockMCPToolUse,
|
|
3178
|
+
BlockRedactedThinking: () => BlockRedactedThinking,
|
|
3179
|
+
BlockSearchResult: () => BlockSearchResult,
|
|
3180
|
+
BlockServerToolUse: () => BlockServerToolUse,
|
|
3181
|
+
BlockText: () => BlockText,
|
|
3182
|
+
BlockThinking: () => BlockThinking,
|
|
3183
|
+
BlockToolReference: () => BlockToolReference,
|
|
3184
|
+
BlockToolResult: () => BlockToolResult,
|
|
3185
|
+
BlockToolUse: () => BlockToolUse,
|
|
3186
|
+
BlockVideo: () => BlockVideo,
|
|
3187
|
+
BlockWebSearchToolResult: () => BlockWebSearchToolResult,
|
|
3188
|
+
DeltaCitations: () => DeltaCitations,
|
|
3189
|
+
DeltaInputJSON: () => DeltaInputJSON,
|
|
3190
|
+
DeltaSignature: () => DeltaSignature,
|
|
3191
|
+
DeltaText: () => DeltaText,
|
|
3192
|
+
DeltaThinking: () => DeltaThinking,
|
|
3193
|
+
EphemeralMarkerField: () => EphemeralMarkerField,
|
|
3194
|
+
ErrBlockDenied: () => ErrBlockDenied,
|
|
3195
|
+
ErrHistoryTooDeep: () => ErrHistoryTooDeep,
|
|
3196
|
+
HistoryTooDeepError: () => HistoryTooDeepError,
|
|
3197
|
+
SizeError: () => SizeError,
|
|
3198
|
+
dropBlocks: () => dropBlocks,
|
|
3199
|
+
sanitize: () => sanitize,
|
|
3200
|
+
stripEphemeral: () => stripEphemeral
|
|
3462
3201
|
});
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3202
|
+
|
|
3203
|
+
// src/sanitize/types.ts
|
|
3204
|
+
var BlockText = "text";
|
|
3205
|
+
var BlockImage = "image";
|
|
3206
|
+
var BlockVideo = "video";
|
|
3207
|
+
var BlockDocument = "document";
|
|
3208
|
+
var BlockSearchResult = "search_result";
|
|
3209
|
+
var BlockThinking = "thinking";
|
|
3210
|
+
var BlockRedactedThinking = "redacted_thinking";
|
|
3211
|
+
var BlockToolUse = "tool_use";
|
|
3212
|
+
var BlockToolResult = "tool_result";
|
|
3213
|
+
var BlockToolReference = "tool_reference";
|
|
3214
|
+
var BlockServerToolUse = "server_tool_use";
|
|
3215
|
+
var BlockWebSearchToolResult = "web_search_tool_result";
|
|
3216
|
+
var BlockCodeExecutionToolResult = "code_execution_tool_result";
|
|
3217
|
+
var BlockMCPToolUse = "mcp_tool_use";
|
|
3218
|
+
var BlockMCPToolResult = "mcp_tool_result";
|
|
3219
|
+
var BlockContainerUpload = "container_upload";
|
|
3220
|
+
var DeltaText = "text_delta";
|
|
3221
|
+
var DeltaInputJSON = "input_json_delta";
|
|
3222
|
+
var DeltaThinking = "thinking_delta";
|
|
3223
|
+
var DeltaSignature = "signature_delta";
|
|
3224
|
+
var DeltaCitations = "citations_delta";
|
|
3225
|
+
var EphemeralMarkerField = "acosmi_ephemeral";
|
|
3226
|
+
|
|
3227
|
+
// src/sanitize/config.ts
|
|
3228
|
+
var HistoryTooDeepError = class extends Error {
|
|
3229
|
+
constructor() {
|
|
3230
|
+
super("sanitize: messages history exceeds configured depth");
|
|
3231
|
+
this.name = "HistoryTooDeepError";
|
|
3232
|
+
}
|
|
3468
3233
|
};
|
|
3469
|
-
var
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
super(message);
|
|
3474
|
-
this.name = "CompliancePollError";
|
|
3475
|
-
this.kind = kind;
|
|
3476
|
-
this.lastInfo = lastInfo;
|
|
3234
|
+
var BlockDeniedError = class extends Error {
|
|
3235
|
+
constructor() {
|
|
3236
|
+
super("sanitize: block type permanently denied");
|
|
3237
|
+
this.name = "BlockDeniedError";
|
|
3477
3238
|
}
|
|
3478
3239
|
};
|
|
3479
|
-
var
|
|
3480
|
-
|
|
3481
|
-
|
|
3240
|
+
var SizeError = class extends Error {
|
|
3241
|
+
blockType;
|
|
3242
|
+
actual;
|
|
3243
|
+
limit;
|
|
3244
|
+
constructor(blockType, actual, limit) {
|
|
3245
|
+
super(`sanitize: ${blockType} base64 size ${actual} exceeds limit ${limit}`);
|
|
3246
|
+
this.name = "SizeError";
|
|
3247
|
+
this.blockType = blockType;
|
|
3248
|
+
this.actual = actual;
|
|
3249
|
+
this.limit = limit;
|
|
3482
3250
|
}
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3251
|
+
};
|
|
3252
|
+
var ErrHistoryTooDeep = new HistoryTooDeepError();
|
|
3253
|
+
var ErrBlockDenied = new BlockDeniedError();
|
|
3254
|
+
|
|
3255
|
+
// src/sanitize/history.ts
|
|
3256
|
+
function dropBlocks(messages, pred) {
|
|
3257
|
+
const droppedToolUseIDs = collectDroppedToolUseIDs(messages, pred);
|
|
3258
|
+
const out = [];
|
|
3259
|
+
for (const msg of messages) {
|
|
3260
|
+
if (!isPlainObject(msg)) {
|
|
3261
|
+
out.push(msg);
|
|
3262
|
+
continue;
|
|
3263
|
+
}
|
|
3264
|
+
const content = msg["content"];
|
|
3265
|
+
if (!Array.isArray(content)) {
|
|
3266
|
+
out.push(msg);
|
|
3267
|
+
continue;
|
|
3268
|
+
}
|
|
3269
|
+
const { kept, changed } = filterBlocks(content, pred, droppedToolUseIDs);
|
|
3270
|
+
if (!changed) {
|
|
3271
|
+
out.push(msg);
|
|
3272
|
+
continue;
|
|
3273
|
+
}
|
|
3274
|
+
if (kept.length === 0) {
|
|
3275
|
+
continue;
|
|
3276
|
+
}
|
|
3277
|
+
const newMsg = { ...msg };
|
|
3278
|
+
newMsg["content"] = kept;
|
|
3279
|
+
out.push(newMsg);
|
|
3495
3280
|
}
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
);
|
|
3281
|
+
return out;
|
|
3282
|
+
}
|
|
3283
|
+
function collectDroppedToolUseIDs(messages, pred) {
|
|
3284
|
+
const ids = /* @__PURE__ */ new Set();
|
|
3285
|
+
for (const msg of messages) {
|
|
3286
|
+
if (!isPlainObject(msg)) continue;
|
|
3287
|
+
const content = msg["content"];
|
|
3288
|
+
if (!Array.isArray(content)) continue;
|
|
3289
|
+
for (const raw of content) {
|
|
3290
|
+
if (!isPlainObject(raw)) continue;
|
|
3291
|
+
if (!pred(raw)) continue;
|
|
3292
|
+
const t = raw["type"];
|
|
3293
|
+
if (typeof t !== "string") continue;
|
|
3294
|
+
if (t === "tool_use" || t === "server_tool_use" || t === "mcp_tool_use") {
|
|
3295
|
+
const id = raw["id"];
|
|
3296
|
+
if (typeof id === "string" && id !== "") ids.add(id);
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3504
3299
|
}
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
if (
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3300
|
+
return ids;
|
|
3301
|
+
}
|
|
3302
|
+
function filterBlocks(content, pred, droppedToolUseIDs) {
|
|
3303
|
+
const kept = [];
|
|
3304
|
+
let changed = false;
|
|
3305
|
+
for (const raw of content) {
|
|
3306
|
+
if (!isPlainObject(raw)) {
|
|
3307
|
+
kept.push(raw);
|
|
3308
|
+
continue;
|
|
3309
|
+
}
|
|
3310
|
+
if (pred(raw)) {
|
|
3311
|
+
changed = true;
|
|
3312
|
+
continue;
|
|
3313
|
+
}
|
|
3314
|
+
if (droppedToolUseIDs.size > 0) {
|
|
3315
|
+
const t = raw["type"];
|
|
3316
|
+
if (t === "tool_result" || t === "mcp_tool_result") {
|
|
3317
|
+
const id = raw["tool_use_id"];
|
|
3318
|
+
if (typeof id === "string" && id !== "" && droppedToolUseIDs.has(id)) {
|
|
3319
|
+
changed = true;
|
|
3320
|
+
continue;
|
|
3321
|
+
}
|
|
3322
|
+
}
|
|
3323
|
+
}
|
|
3324
|
+
kept.push(raw);
|
|
3523
3325
|
}
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3326
|
+
return { kept, changed };
|
|
3327
|
+
}
|
|
3328
|
+
function stripEphemeral(messages) {
|
|
3329
|
+
return dropBlocks(messages, (b) => {
|
|
3330
|
+
const t = b["type"];
|
|
3331
|
+
if (t === "thinking" || t === "redacted_thinking") {
|
|
3332
|
+
return false;
|
|
3333
|
+
}
|
|
3334
|
+
const v = b[EphemeralMarkerField];
|
|
3335
|
+
return v === true;
|
|
3336
|
+
});
|
|
3337
|
+
}
|
|
3338
|
+
function isPlainObject(v) {
|
|
3339
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3340
|
+
}
|
|
3341
|
+
|
|
3342
|
+
// src/sanitize/defensive.ts
|
|
3343
|
+
function sanitize(messages, cfg) {
|
|
3344
|
+
if ((cfg.maxMessagesTurns ?? 0) > 0 && messages.length > cfg.maxMessagesTurns) {
|
|
3345
|
+
throw ErrHistoryTooDeep;
|
|
3530
3346
|
}
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
return this.write(
|
|
3534
|
-
"POST",
|
|
3535
|
-
`/compliance/evidence/assets/${encodeURIComponent(assetId)}/timestamp`,
|
|
3536
|
-
null,
|
|
3537
|
-
writeCtx(opts)
|
|
3538
|
-
);
|
|
3347
|
+
if ((cfg.maxImageBytes ?? 0) > 0 || (cfg.maxVideoBytes ?? 0) > 0 || (cfg.maxPDFBytes ?? 0) > 0) {
|
|
3348
|
+
checkMediaSizes(messages, cfg);
|
|
3539
3349
|
}
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
);
|
|
3350
|
+
if (cfg.permanentDenyBlocks && cfg.permanentDenyBlocks.length > 0) {
|
|
3351
|
+
const denySet = /* @__PURE__ */ new Set();
|
|
3352
|
+
for (const bt of cfg.permanentDenyBlocks) denySet.add(bt);
|
|
3353
|
+
messages = dropBlocks(messages, (b) => {
|
|
3354
|
+
const t = b["type"];
|
|
3355
|
+
return typeof t === "string" && denySet.has(t);
|
|
3356
|
+
});
|
|
3548
3357
|
}
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
)
|
|
3358
|
+
return messages;
|
|
3359
|
+
}
|
|
3360
|
+
function checkMediaSizes(messages, cfg) {
|
|
3361
|
+
for (const msg of messages) {
|
|
3362
|
+
if (!isPlainObject2(msg)) continue;
|
|
3363
|
+
const content = msg["content"];
|
|
3364
|
+
if (!Array.isArray(content)) continue;
|
|
3365
|
+
for (const raw of content) {
|
|
3366
|
+
if (!isPlainObject2(raw)) continue;
|
|
3367
|
+
const bt = raw["type"];
|
|
3368
|
+
if (typeof bt !== "string") continue;
|
|
3369
|
+
let limit = 0;
|
|
3370
|
+
switch (bt) {
|
|
3371
|
+
case "image":
|
|
3372
|
+
limit = cfg.maxImageBytes ?? 0;
|
|
3373
|
+
break;
|
|
3374
|
+
case "video":
|
|
3375
|
+
limit = cfg.maxVideoBytes ?? 0;
|
|
3376
|
+
break;
|
|
3377
|
+
case "document":
|
|
3378
|
+
limit = cfg.maxPDFBytes ?? 0;
|
|
3379
|
+
break;
|
|
3380
|
+
default:
|
|
3381
|
+
continue;
|
|
3382
|
+
}
|
|
3383
|
+
if (limit <= 0) continue;
|
|
3384
|
+
const data = extractBase64Data(raw);
|
|
3385
|
+
if (data === "") continue;
|
|
3386
|
+
const actual = base64DecodedLen(data);
|
|
3387
|
+
if (actual > limit) {
|
|
3388
|
+
throw new SizeError(bt, actual, limit);
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3557
3391
|
}
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
opts
|
|
3570
|
-
);
|
|
3392
|
+
}
|
|
3393
|
+
function extractBase64Data(block) {
|
|
3394
|
+
const src = block["source"];
|
|
3395
|
+
if (!isPlainObject2(src)) return "";
|
|
3396
|
+
if (src["type"] !== "base64") return "";
|
|
3397
|
+
const dataRaw = src["data"];
|
|
3398
|
+
if (typeof dataRaw !== "string") return "";
|
|
3399
|
+
let data = dataRaw;
|
|
3400
|
+
const i = data.indexOf("base64,");
|
|
3401
|
+
if (i >= 0) {
|
|
3402
|
+
data = data.slice(i + "base64,".length);
|
|
3571
3403
|
}
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3404
|
+
return data;
|
|
3405
|
+
}
|
|
3406
|
+
function base64DecodedLen(b64) {
|
|
3407
|
+
const n = b64.length;
|
|
3408
|
+
let pad = 0;
|
|
3409
|
+
if (n >= 1 && b64[n - 1] === "=") pad++;
|
|
3410
|
+
if (n >= 2 && b64[n - 2] === "=") pad++;
|
|
3411
|
+
return Math.floor(n * 3 / 4) - pad;
|
|
3412
|
+
}
|
|
3413
|
+
function isPlainObject2(v) {
|
|
3414
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3415
|
+
}
|
|
3416
|
+
|
|
3417
|
+
// src/core/sanitize-bridge.ts
|
|
3418
|
+
Client.prototype.setDefensiveSanitize = function(cfg) {
|
|
3419
|
+
this.defensiveCfg = cfg;
|
|
3420
|
+
};
|
|
3421
|
+
Client.prototype.setAutoStripEphemeralHistory = function(on) {
|
|
3422
|
+
this.autoStripEphemeral = on;
|
|
3423
|
+
};
|
|
3424
|
+
Client.prototype.applyRequestSanitizers = function(req) {
|
|
3425
|
+
const cfg = this.defensiveCfg;
|
|
3426
|
+
const strip = this.autoStripEphemeral;
|
|
3427
|
+
if (cfg == null && !strip) return;
|
|
3428
|
+
if (req.rawMessages != null) {
|
|
3429
|
+
let msgs;
|
|
3430
|
+
try {
|
|
3431
|
+
msgs = normalizeRawMessages(req.rawMessages);
|
|
3432
|
+
} catch (e) {
|
|
3433
|
+
throw new Error(
|
|
3434
|
+
`sanitize: normalize raw messages: ${e instanceof Error ? e.message : String(e)}`
|
|
3435
|
+
);
|
|
3436
|
+
}
|
|
3437
|
+
if (cfg) {
|
|
3438
|
+
msgs = sanitize(msgs, cfg);
|
|
3439
|
+
}
|
|
3440
|
+
if (strip) {
|
|
3441
|
+
msgs = stripEphemeral(msgs);
|
|
3442
|
+
}
|
|
3443
|
+
req.rawMessages = msgs;
|
|
3444
|
+
return;
|
|
3584
3445
|
}
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
// =========================================================================
|
|
3588
|
-
/** 创建证据报告(写)。 */
|
|
3589
|
-
createReport(req, opts = {}) {
|
|
3590
|
-
return this.write("POST", "/compliance/reports", req, writeCtx(opts));
|
|
3446
|
+
if (cfg && (cfg.maxMessagesTurns ?? 0) > 0 && (req.messages?.length ?? 0) > cfg.maxMessagesTurns) {
|
|
3447
|
+
throw ErrHistoryTooDeep;
|
|
3591
3448
|
}
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
);
|
|
3449
|
+
};
|
|
3450
|
+
function normalizeRawMessages(rm) {
|
|
3451
|
+
if (Array.isArray(rm)) return rm;
|
|
3452
|
+
let s;
|
|
3453
|
+
try {
|
|
3454
|
+
s = JSON.parse(JSON.stringify(rm));
|
|
3455
|
+
} catch (e) {
|
|
3456
|
+
throw new Error(`raw messages: ${e instanceof Error ? e.message : String(e)}`);
|
|
3600
3457
|
}
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
*
|
|
3604
|
-
* `@status gated` — step-up 闸门未闭合前服务端会一致返回
|
|
3605
|
-
* `COMPLIANCE_STEP_UP_REQUIRED`(数值码 1031000013)。SDK 不会自动重试、不伪成功;
|
|
3606
|
-
* 调用方需要引导用户重新做 OAuth introspection 或重新登录后再次调用本方法
|
|
3607
|
-
*(使用同一 idempotency-key)。方法状态分级见 `docs/compliance.md` Method Status。
|
|
3608
|
-
*/
|
|
3609
|
-
publishReport(id, opts = {}) {
|
|
3610
|
-
return this.write(
|
|
3611
|
-
"POST",
|
|
3612
|
-
`/compliance/reports/${encodeURIComponent(id)}/publish`,
|
|
3613
|
-
null,
|
|
3614
|
-
writeCtx(opts)
|
|
3615
|
-
);
|
|
3616
|
-
}
|
|
3617
|
-
/**
|
|
3618
|
-
* 下载报告(读)。返回 {@link ReportDownload}:报告 hash + 资产 hash + 证据包 hash +
|
|
3619
|
-
* 时间章 serial/genTime,足以离线复核。
|
|
3620
|
-
* 不返回 bodyCanonicalJson / storage key / subject snapshot id。
|
|
3621
|
-
*/
|
|
3622
|
-
downloadReport(id, signal) {
|
|
3623
|
-
return this.read(
|
|
3624
|
-
"GET",
|
|
3625
|
-
`/compliance/reports/${encodeURIComponent(id)}/download`,
|
|
3626
|
-
null,
|
|
3627
|
-
signal
|
|
3628
|
-
);
|
|
3458
|
+
if (!Array.isArray(s)) {
|
|
3459
|
+
throw new Error("raw messages must be a JSON array");
|
|
3629
3460
|
}
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3461
|
+
return s;
|
|
3462
|
+
}
|
|
3463
|
+
|
|
3464
|
+
// src/shared/index.ts
|
|
3465
|
+
init_errors();
|
|
3466
|
+
|
|
3467
|
+
// src/auth/scopes.ts
|
|
3468
|
+
var ScopeAI = "ai";
|
|
3469
|
+
var ScopeSkills = "skills";
|
|
3470
|
+
var ScopeAccount = "account";
|
|
3471
|
+
var ScopeModels = "models";
|
|
3472
|
+
var ScopeModelsChat = "models:chat";
|
|
3473
|
+
var ScopeEntitlements = "entitlements";
|
|
3474
|
+
var ScopeTokenPackages = "token-packages";
|
|
3475
|
+
var ScopeSkillStore = "skill_store";
|
|
3476
|
+
var ScopeTools = "tools";
|
|
3477
|
+
var ScopeToolsExecute = "tools:execute";
|
|
3478
|
+
var ScopeWallet = "wallet";
|
|
3479
|
+
var ScopeWalletReadonly = "wallet:readonly";
|
|
3480
|
+
var ScopeProfile = "profile";
|
|
3481
|
+
function allScopes() {
|
|
3482
|
+
return [ScopeAI, ScopeSkills, ScopeAccount];
|
|
3483
|
+
}
|
|
3484
|
+
function modelScopes() {
|
|
3485
|
+
return [ScopeAI];
|
|
3486
|
+
}
|
|
3487
|
+
function commerceScopes() {
|
|
3488
|
+
return [ScopeAI, ScopeAccount];
|
|
3489
|
+
}
|
|
3490
|
+
function skillScopes() {
|
|
3491
|
+
return [ScopeSkills];
|
|
3492
|
+
}
|
|
3493
|
+
|
|
3494
|
+
// src/models/index.ts
|
|
3495
|
+
init_types();
|
|
3496
|
+
|
|
3497
|
+
// src/models/wire-anthropic.ts
|
|
3498
|
+
function anthropicResponseTextContent(r) {
|
|
3499
|
+
const parts = [];
|
|
3500
|
+
for (const b of r.content) {
|
|
3501
|
+
if (b.type === "text" && b.text) parts.push(b.text);
|
|
3641
3502
|
}
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
signal
|
|
3649
|
-
);
|
|
3503
|
+
return parts.join("");
|
|
3504
|
+
}
|
|
3505
|
+
function anthropicResponseThinkingContent(r) {
|
|
3506
|
+
const parts = [];
|
|
3507
|
+
for (const b of r.content) {
|
|
3508
|
+
if (b.type === "thinking" && b.thinking) parts.push(b.thinking);
|
|
3650
3509
|
}
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3510
|
+
return parts.join("");
|
|
3511
|
+
}
|
|
3512
|
+
function anthropicResponseToolUseBlocks(r) {
|
|
3513
|
+
return r.content.filter((b) => b.type === "tool_use");
|
|
3514
|
+
}
|
|
3515
|
+
|
|
3516
|
+
// src/models/model-helpers.ts
|
|
3517
|
+
function modelSupportsInputModality(model, modality) {
|
|
3518
|
+
if (!model) return false;
|
|
3519
|
+
const mods = model.inputModalities;
|
|
3520
|
+
if (!Array.isArray(mods)) return false;
|
|
3521
|
+
return mods.includes(modality);
|
|
3522
|
+
}
|
|
3523
|
+
function modelSupportsImageInput(model) {
|
|
3524
|
+
return modelSupportsInputModality(model, "image");
|
|
3525
|
+
}
|
|
3526
|
+
function findFirstModelByInputModality(models, modality) {
|
|
3527
|
+
if (!Array.isArray(models)) return null;
|
|
3528
|
+
for (const m of models) {
|
|
3529
|
+
if (!m) continue;
|
|
3530
|
+
if (m.isEnabled === false) continue;
|
|
3531
|
+
if (!modelSupportsInputModality(m, modality)) continue;
|
|
3532
|
+
return m;
|
|
3664
3533
|
}
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
);
|
|
3534
|
+
return null;
|
|
3535
|
+
}
|
|
3536
|
+
function findDesktopVisualUnderstandingModel(models) {
|
|
3537
|
+
if (!Array.isArray(models)) return null;
|
|
3538
|
+
const candidates = [];
|
|
3539
|
+
for (const m of models) {
|
|
3540
|
+
if (!m) continue;
|
|
3541
|
+
if (m.isEnabled === false) continue;
|
|
3542
|
+
if (m.capabilities?.supports_desktop_visual_understanding !== true) continue;
|
|
3543
|
+
if (!modelSupportsInputModality(m, "image")) continue;
|
|
3544
|
+
candidates.push(m);
|
|
3677
3545
|
}
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
return
|
|
3681
|
-
"POST",
|
|
3682
|
-
`/compliance/signing-envelopes/${encodeURIComponent(envelopeId)}/sync-provider-status`,
|
|
3683
|
-
null,
|
|
3684
|
-
writeCtx(opts)
|
|
3685
|
-
);
|
|
3546
|
+
if (candidates.length === 0) return null;
|
|
3547
|
+
for (const m of candidates) {
|
|
3548
|
+
if (m.isDefault === true) return m;
|
|
3686
3549
|
}
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3550
|
+
return candidates[0];
|
|
3551
|
+
}
|
|
3552
|
+
|
|
3553
|
+
// src/models/index.ts
|
|
3554
|
+
init_adapters();
|
|
3555
|
+
init_betas();
|
|
3556
|
+
|
|
3557
|
+
// src/billing/entitlements.ts
|
|
3558
|
+
Client.prototype.getBalance = async function(signal) {
|
|
3559
|
+
const resp = await this.doJSON(
|
|
3560
|
+
"GET",
|
|
3561
|
+
"/entitlements/balance",
|
|
3562
|
+
null,
|
|
3563
|
+
signal
|
|
3564
|
+
);
|
|
3565
|
+
return resp.data;
|
|
3566
|
+
};
|
|
3567
|
+
Client.prototype.getBalanceDetail = async function(signal) {
|
|
3568
|
+
const resp = await this.doJSON(
|
|
3569
|
+
"GET",
|
|
3570
|
+
"/entitlements/balance-detail",
|
|
3571
|
+
null,
|
|
3572
|
+
signal
|
|
3573
|
+
);
|
|
3574
|
+
return resp.data;
|
|
3575
|
+
};
|
|
3576
|
+
Client.prototype.listEntitlements = async function(status, signal) {
|
|
3577
|
+
let path = "/entitlements";
|
|
3578
|
+
if (status !== "") {
|
|
3579
|
+
path += `?status=${encodeURIComponent(status)}`;
|
|
3704
3580
|
}
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3581
|
+
const resp = await this.doJSON("GET", path, null, signal);
|
|
3582
|
+
return resp.data;
|
|
3583
|
+
};
|
|
3584
|
+
Client.prototype.listConsumeRecords = async function(page, pageSize, signal) {
|
|
3585
|
+
const path = `/entitlements/consume-records?page=${page}&pageSize=${pageSize}`;
|
|
3586
|
+
const resp = await this.doJSON("GET", path, null, signal);
|
|
3587
|
+
return resp.data;
|
|
3588
|
+
};
|
|
3589
|
+
Client.prototype.claimMonthlyFree = async function(signal) {
|
|
3590
|
+
const resp = await this.doJSON(
|
|
3591
|
+
"POST",
|
|
3592
|
+
"/entitlements/claim-monthly",
|
|
3593
|
+
null,
|
|
3594
|
+
signal
|
|
3595
|
+
);
|
|
3596
|
+
return resp.data;
|
|
3597
|
+
};
|
|
3598
|
+
Client.prototype.getByModel = async function(modelID, signal) {
|
|
3599
|
+
if (modelID === "") throw new Error("modelID required");
|
|
3600
|
+
const path = `/entitlements/by-model?modelId=${encodeURIComponent(modelID)}`;
|
|
3601
|
+
const resp = await this.doJSON("GET", path, null, signal);
|
|
3602
|
+
return resp.data;
|
|
3603
|
+
};
|
|
3604
|
+
Client.prototype.listBuckets = async function(signal) {
|
|
3605
|
+
const resp = await this.doJSON(
|
|
3606
|
+
"GET",
|
|
3607
|
+
"/entitlements/buckets",
|
|
3608
|
+
null,
|
|
3609
|
+
signal
|
|
3610
|
+
);
|
|
3611
|
+
return resp.data;
|
|
3612
|
+
};
|
|
3613
|
+
Client.prototype.listCoefficients = async function(signal) {
|
|
3614
|
+
if (this.coefCacheData && Date.now() - this.coefCacheTimeMs < coefCacheTTLMs) {
|
|
3615
|
+
return [...this.coefCacheData];
|
|
3722
3616
|
}
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
listPendingSealApprovals(signal) {
|
|
3746
|
-
return this.read(
|
|
3747
|
-
"GET",
|
|
3748
|
-
"/compliance/seal-approvals/pending",
|
|
3749
|
-
null,
|
|
3750
|
-
signal
|
|
3751
|
-
);
|
|
3752
|
-
}
|
|
3753
|
-
getSealApproval(id, signal) {
|
|
3754
|
-
return this.read(
|
|
3755
|
-
"GET",
|
|
3756
|
-
`/compliance/seal-approvals/${encodeURIComponent(id)}`,
|
|
3757
|
-
null,
|
|
3758
|
-
signal
|
|
3759
|
-
);
|
|
3760
|
-
}
|
|
3761
|
-
// =========================================================================
|
|
3762
|
-
// Provider Request (read-only)
|
|
3763
|
-
// =========================================================================
|
|
3764
|
-
getProviderRequest(id, signal) {
|
|
3765
|
-
return this.read(
|
|
3766
|
-
"GET",
|
|
3767
|
-
`/compliance/provider-requests/${encodeURIComponent(id)}`,
|
|
3768
|
-
null,
|
|
3769
|
-
signal
|
|
3770
|
-
);
|
|
3771
|
-
}
|
|
3772
|
-
/**
|
|
3773
|
-
* 轮询 provider request 到 SUCCESS / FAILED 终态。
|
|
3774
|
-
* - SUCCESS / FAILED → 返回最后视图;
|
|
3775
|
-
* - UNKNOWN / RETRYING / PENDING → 继续轮询;
|
|
3776
|
-
* - timeout → 抛 {@link CompliancePollError} kind='timeout',不自动重发原 provider 请求。
|
|
3777
|
-
*
|
|
3778
|
-
* SUCCESS 不代表 billing 已 commit;调用方仍需通过业务侧 envelope / asset 终态判断。
|
|
3779
|
-
*/
|
|
3780
|
-
async waitForProviderRequestTerminal(id, opts = {}) {
|
|
3781
|
-
return this.poll(
|
|
3782
|
-
() => this.getProviderRequest(id, opts.signal),
|
|
3783
|
-
(v) => classifyProviderStatus(v.status),
|
|
3784
|
-
opts
|
|
3785
|
-
);
|
|
3786
|
-
}
|
|
3787
|
-
// =========================================================================
|
|
3788
|
-
// Error classification (re-export for convenience)
|
|
3789
|
-
// =========================================================================
|
|
3790
|
-
classifyError(err) {
|
|
3791
|
-
if (!isBusinessErrorLike(err)) return null;
|
|
3792
|
-
if (!isComplianceBusinessError(err)) return null;
|
|
3793
|
-
return classifyComplianceError(err);
|
|
3617
|
+
const resp = await this.doJSON(
|
|
3618
|
+
"GET",
|
|
3619
|
+
"/entitlements/coefficients",
|
|
3620
|
+
null,
|
|
3621
|
+
signal
|
|
3622
|
+
);
|
|
3623
|
+
this.coefCacheData = [...resp.data];
|
|
3624
|
+
this.coefCacheTimeMs = Date.now();
|
|
3625
|
+
return resp.data;
|
|
3626
|
+
};
|
|
3627
|
+
Client.prototype.invalidateCoefficientCache = function() {
|
|
3628
|
+
this.coefCacheData = null;
|
|
3629
|
+
this.coefCacheTimeMs = 0;
|
|
3630
|
+
};
|
|
3631
|
+
|
|
3632
|
+
// src/billing/packages.ts
|
|
3633
|
+
init_errors();
|
|
3634
|
+
Client.prototype.listTokenPackages = async function(signal) {
|
|
3635
|
+
const raw = await this.doJSON("GET", "/token-packages", null, signal);
|
|
3636
|
+
if (raw.data && typeof raw.data === "object" && "list" in raw.data) {
|
|
3637
|
+
const page = raw.data;
|
|
3638
|
+
if (Array.isArray(page.list)) return page.list;
|
|
3794
3639
|
}
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3640
|
+
if (Array.isArray(raw.data)) return raw.data;
|
|
3641
|
+
throw new Error("decode token packages: unexpected shape");
|
|
3642
|
+
};
|
|
3643
|
+
Client.prototype.getTokenPackageDetail = async function(packageID, signal) {
|
|
3644
|
+
const resp = await this.doJSON(
|
|
3645
|
+
"GET",
|
|
3646
|
+
`/token-packages/${encodeURIComponent(packageID)}`,
|
|
3647
|
+
null,
|
|
3648
|
+
signal
|
|
3649
|
+
);
|
|
3650
|
+
return resp.data;
|
|
3651
|
+
};
|
|
3652
|
+
Client.prototype.buyTokenPackage = async function(packageID, payload, signal) {
|
|
3653
|
+
const body = payload ?? null;
|
|
3654
|
+
const resp = await this.doJSON(
|
|
3655
|
+
"POST",
|
|
3656
|
+
`/token-packages/${encodeURIComponent(packageID)}/buy`,
|
|
3657
|
+
body,
|
|
3658
|
+
signal
|
|
3659
|
+
);
|
|
3660
|
+
return resp.data;
|
|
3661
|
+
};
|
|
3662
|
+
Client.prototype.getOrderStatus = async function(orderID, signal) {
|
|
3663
|
+
const resp = await this.doJSON(
|
|
3664
|
+
"GET",
|
|
3665
|
+
`/token-packages/orders/${encodeURIComponent(orderID)}/status`,
|
|
3666
|
+
null,
|
|
3667
|
+
signal
|
|
3668
|
+
);
|
|
3669
|
+
return resp.data;
|
|
3670
|
+
};
|
|
3671
|
+
Client.prototype.listMyOrders = async function(signal) {
|
|
3672
|
+
const raw = await this.doJSON("GET", "/token-packages/my", null, signal);
|
|
3673
|
+
if (raw.data && typeof raw.data === "object" && "list" in raw.data) {
|
|
3674
|
+
const page = raw.data;
|
|
3675
|
+
if (Array.isArray(page.list)) return page.list;
|
|
3807
3676
|
}
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
*/
|
|
3819
|
-
async publicRead(method, path, signal) {
|
|
3820
|
-
let token = "";
|
|
3821
|
-
try {
|
|
3822
|
-
token = await this.client.ensureToken(signal);
|
|
3823
|
-
} catch {
|
|
3824
|
-
}
|
|
3825
|
-
const url = this.client.complianceURL(path);
|
|
3826
|
-
const headers = { Accept: "application/json" };
|
|
3827
|
-
if (token) headers.Authorization = `Bearer ${token}`;
|
|
3828
|
-
const resp = await this.client.doRequest({ method, url, headers }, signal);
|
|
3829
|
-
if (resp.status < 200 || resp.status >= 300) {
|
|
3830
|
-
const bodyBytes = resp.body ? await readLimited(resp.body, maxErrorBodySize) : new Uint8Array();
|
|
3831
|
-
throw parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
3677
|
+
if (Array.isArray(raw.data)) return raw.data;
|
|
3678
|
+
throw new Error("decode orders: unexpected shape");
|
|
3679
|
+
};
|
|
3680
|
+
Client.prototype.waitForPayment = async function(orderID, pollIntervalMs, signal) {
|
|
3681
|
+
if (pollIntervalMs <= 0) pollIntervalMs = 2e3;
|
|
3682
|
+
while (true) {
|
|
3683
|
+
const status = await this.getOrderStatus(orderID, signal);
|
|
3684
|
+
if (isOrderTerminal(status.status)) {
|
|
3685
|
+
if (isOrderSuccess(status.status)) return status;
|
|
3686
|
+
throw new OrderTerminalError(orderID, status.status);
|
|
3832
3687
|
}
|
|
3833
|
-
|
|
3834
|
-
if (!text) return void 0;
|
|
3835
|
-
const parsed = JSON.parse(text);
|
|
3836
|
-
const bizErr = apiResponseBusinessError(parsed);
|
|
3837
|
-
if (bizErr) throw bizErr;
|
|
3838
|
-
return parsed.data;
|
|
3839
|
-
}
|
|
3840
|
-
/**
|
|
3841
|
-
* 写路径:POST。
|
|
3842
|
-
* - 发送前 ensureToken 一次确保 token fresh。
|
|
3843
|
-
* - 不自动 401 重放:401 → 抛 HTTPError;调用方必须自己刷新 token 后用同一
|
|
3844
|
-
* idempotency-key 重新发起,避免 provider 侧重复请求。
|
|
3845
|
-
* - 不走 doRequestWithRetry:写操作不允许 5xx/timeout 自动重试。
|
|
3846
|
-
*/
|
|
3847
|
-
async write(method, path, body, ctx) {
|
|
3848
|
-
const headers = { ...ctx.extraHeaders ?? {} };
|
|
3849
|
-
if (ctx.idempotencyKey) headers["Idempotency-Key"] = ctx.idempotencyKey;
|
|
3850
|
-
return this.executeJson(method, path, body, ctx.signal, {
|
|
3851
|
-
retryOn401: false,
|
|
3852
|
-
extraHeaders: headers
|
|
3853
|
-
});
|
|
3688
|
+
await sleepWithSignal(pollIntervalMs, signal);
|
|
3854
3689
|
}
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
} catch {
|
|
3873
|
-
}
|
|
3874
|
-
await this.client.forceRefresh(signal);
|
|
3875
|
-
return this.executeJson(method, path, body, signal, opts, true);
|
|
3876
|
-
}
|
|
3877
|
-
if (resp.status < 200 || resp.status >= 300) {
|
|
3878
|
-
const bodyBytes = resp.body ? await readLimited(resp.body, maxErrorBodySize) : new Uint8Array();
|
|
3879
|
-
throw parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
3690
|
+
};
|
|
3691
|
+
async function sleepWithSignal(ms, signal) {
|
|
3692
|
+
if (ms <= 0) return;
|
|
3693
|
+
if (signal && signal.aborted) throw new Error("aborted");
|
|
3694
|
+
return new Promise((resolve, reject) => {
|
|
3695
|
+
const t = setTimeout(() => {
|
|
3696
|
+
if (signal && abortHandler) signal.removeEventListener("abort", abortHandler);
|
|
3697
|
+
resolve();
|
|
3698
|
+
}, ms);
|
|
3699
|
+
let abortHandler;
|
|
3700
|
+
if (signal) {
|
|
3701
|
+
abortHandler = () => {
|
|
3702
|
+
clearTimeout(t);
|
|
3703
|
+
signal.removeEventListener("abort", abortHandler);
|
|
3704
|
+
reject(new Error("aborted"));
|
|
3705
|
+
};
|
|
3706
|
+
signal.addEventListener("abort", abortHandler);
|
|
3880
3707
|
}
|
|
3881
|
-
const text = await resp.text();
|
|
3882
|
-
if (!text) return void 0;
|
|
3883
|
-
const parsed = JSON.parse(text);
|
|
3884
|
-
const bizErr = apiResponseBusinessError(parsed);
|
|
3885
|
-
if (bizErr) throw bizErr;
|
|
3886
|
-
return parsed.data;
|
|
3887
|
-
}
|
|
3888
|
-
async poll(fetcher, classify, opts) {
|
|
3889
|
-
const cfg = {
|
|
3890
|
-
timeoutMs: opts.timeoutMs ?? DEFAULT_POLL.timeoutMs,
|
|
3891
|
-
initialIntervalMs: opts.initialIntervalMs ?? DEFAULT_POLL.initialIntervalMs,
|
|
3892
|
-
maxIntervalMs: opts.maxIntervalMs ?? DEFAULT_POLL.maxIntervalMs,
|
|
3893
|
-
multiplier: opts.multiplier ?? DEFAULT_POLL.multiplier
|
|
3894
|
-
};
|
|
3895
|
-
const deadline = Date.now() + cfg.timeoutMs;
|
|
3896
|
-
let interval = cfg.initialIntervalMs;
|
|
3897
|
-
let lastValue;
|
|
3898
|
-
while (Date.now() < deadline) {
|
|
3899
|
-
if (opts.signal?.aborted) {
|
|
3900
|
-
throw new CompliancePollError("compliance poll aborted", "unknown");
|
|
3901
|
-
}
|
|
3902
|
-
lastValue = await fetcher();
|
|
3903
|
-
const decision = classify(lastValue);
|
|
3904
|
-
if (decision === "done") return lastValue;
|
|
3905
|
-
if (decision === "failed") {
|
|
3906
|
-
throw new CompliancePollError(
|
|
3907
|
-
"compliance poll observed terminal failure",
|
|
3908
|
-
"terminal_failure"
|
|
3909
|
-
);
|
|
3910
|
-
}
|
|
3911
|
-
const sleepMs = Math.min(interval, deadline - Date.now());
|
|
3912
|
-
if (sleepMs <= 0) break;
|
|
3913
|
-
await sleep2(sleepMs, opts.signal);
|
|
3914
|
-
interval = Math.min(Math.floor(interval * cfg.multiplier), cfg.maxIntervalMs);
|
|
3915
|
-
}
|
|
3916
|
-
throw new CompliancePollError("compliance poll timed out", "timeout");
|
|
3917
|
-
}
|
|
3918
|
-
};
|
|
3919
|
-
function classifyTimestamp(status) {
|
|
3920
|
-
switch (status) {
|
|
3921
|
-
case "VERIFIED":
|
|
3922
|
-
return "done";
|
|
3923
|
-
case "FAILED":
|
|
3924
|
-
case "LOCAL_VERIFY_FAILED":
|
|
3925
|
-
return "failed";
|
|
3926
|
-
case "PENDING":
|
|
3927
|
-
case "UNKNOWN":
|
|
3928
|
-
case "RETRYING":
|
|
3929
|
-
default:
|
|
3930
|
-
return "continue";
|
|
3931
|
-
}
|
|
3932
|
-
}
|
|
3933
|
-
function classifyProviderStatus(status) {
|
|
3934
|
-
switch (status) {
|
|
3935
|
-
case "SUCCESS":
|
|
3936
|
-
return "done";
|
|
3937
|
-
case "FAILED":
|
|
3938
|
-
return "failed";
|
|
3939
|
-
case "PENDING":
|
|
3940
|
-
case "UNKNOWN":
|
|
3941
|
-
case "RETRYING":
|
|
3942
|
-
default:
|
|
3943
|
-
return "continue";
|
|
3944
|
-
}
|
|
3945
|
-
}
|
|
3946
|
-
function writeCtx(opts, extraHeaders = {}) {
|
|
3947
|
-
return {
|
|
3948
|
-
idempotencyKey: opts.idempotencyKey,
|
|
3949
|
-
signal: opts.signal,
|
|
3950
|
-
extraHeaders
|
|
3951
|
-
};
|
|
3952
|
-
}
|
|
3953
|
-
function isBusinessErrorLike(err) {
|
|
3954
|
-
if (err == null || typeof err !== "object") return false;
|
|
3955
|
-
return typeof err.code === "number";
|
|
3956
|
-
}
|
|
3957
|
-
function sleep2(ms, signal) {
|
|
3958
|
-
return new Promise((resolve, reject) => {
|
|
3959
|
-
if (signal?.aborted) {
|
|
3960
|
-
reject(new CompliancePollError("compliance poll aborted", "unknown"));
|
|
3961
|
-
return;
|
|
3962
|
-
}
|
|
3963
|
-
const timer = setTimeout(() => {
|
|
3964
|
-
signal?.removeEventListener("abort", onAbort);
|
|
3965
|
-
resolve();
|
|
3966
|
-
}, ms);
|
|
3967
|
-
const onAbort = () => {
|
|
3968
|
-
clearTimeout(timer);
|
|
3969
|
-
signal?.removeEventListener("abort", onAbort);
|
|
3970
|
-
reject(new CompliancePollError("compliance poll aborted", "unknown"));
|
|
3971
|
-
};
|
|
3972
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
3973
3708
|
});
|
|
3974
3709
|
}
|
|
3975
3710
|
|
|
3976
|
-
// src/
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
BlockThinking: () => BlockThinking,
|
|
3991
|
-
BlockToolReference: () => BlockToolReference,
|
|
3992
|
-
BlockToolResult: () => BlockToolResult,
|
|
3993
|
-
BlockToolUse: () => BlockToolUse,
|
|
3994
|
-
BlockVideo: () => BlockVideo,
|
|
3995
|
-
BlockWebSearchToolResult: () => BlockWebSearchToolResult,
|
|
3996
|
-
DeltaCitations: () => DeltaCitations,
|
|
3997
|
-
DeltaInputJSON: () => DeltaInputJSON,
|
|
3998
|
-
DeltaSignature: () => DeltaSignature,
|
|
3999
|
-
DeltaText: () => DeltaText,
|
|
4000
|
-
DeltaThinking: () => DeltaThinking,
|
|
4001
|
-
EphemeralMarkerField: () => EphemeralMarkerField,
|
|
4002
|
-
ErrBlockDenied: () => ErrBlockDenied,
|
|
4003
|
-
ErrHistoryTooDeep: () => ErrHistoryTooDeep,
|
|
4004
|
-
HistoryTooDeepError: () => HistoryTooDeepError,
|
|
4005
|
-
SizeError: () => SizeError,
|
|
4006
|
-
dropBlocks: () => dropBlocks,
|
|
4007
|
-
sanitize: () => sanitize,
|
|
4008
|
-
stripEphemeral: () => stripEphemeral
|
|
4009
|
-
});
|
|
4010
|
-
|
|
4011
|
-
// src/sanitize/types.ts
|
|
4012
|
-
var BlockText = "text";
|
|
4013
|
-
var BlockImage = "image";
|
|
4014
|
-
var BlockVideo = "video";
|
|
4015
|
-
var BlockDocument = "document";
|
|
4016
|
-
var BlockSearchResult = "search_result";
|
|
4017
|
-
var BlockThinking = "thinking";
|
|
4018
|
-
var BlockRedactedThinking = "redacted_thinking";
|
|
4019
|
-
var BlockToolUse = "tool_use";
|
|
4020
|
-
var BlockToolResult = "tool_result";
|
|
4021
|
-
var BlockToolReference = "tool_reference";
|
|
4022
|
-
var BlockServerToolUse = "server_tool_use";
|
|
4023
|
-
var BlockWebSearchToolResult = "web_search_tool_result";
|
|
4024
|
-
var BlockCodeExecutionToolResult = "code_execution_tool_result";
|
|
4025
|
-
var BlockMCPToolUse = "mcp_tool_use";
|
|
4026
|
-
var BlockMCPToolResult = "mcp_tool_result";
|
|
4027
|
-
var BlockContainerUpload = "container_upload";
|
|
4028
|
-
var DeltaText = "text_delta";
|
|
4029
|
-
var DeltaInputJSON = "input_json_delta";
|
|
4030
|
-
var DeltaThinking = "thinking_delta";
|
|
4031
|
-
var DeltaSignature = "signature_delta";
|
|
4032
|
-
var DeltaCitations = "citations_delta";
|
|
4033
|
-
var EphemeralMarkerField = "acosmi_ephemeral";
|
|
3711
|
+
// src/billing/wallet.ts
|
|
3712
|
+
Client.prototype.getWalletStats = async function(signal) {
|
|
3713
|
+
const resp = await this.doJSON("GET", "/wallet/stats", null, signal);
|
|
3714
|
+
return resp.data;
|
|
3715
|
+
};
|
|
3716
|
+
Client.prototype.getWalletTransactions = async function(signal) {
|
|
3717
|
+
const resp = await this.doJSON(
|
|
3718
|
+
"GET",
|
|
3719
|
+
"/wallet/transactions",
|
|
3720
|
+
null,
|
|
3721
|
+
signal
|
|
3722
|
+
);
|
|
3723
|
+
return resp.data;
|
|
3724
|
+
};
|
|
4034
3725
|
|
|
4035
|
-
// src/
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
3726
|
+
// src/skills/skills.ts
|
|
3727
|
+
init_errors();
|
|
3728
|
+
Client.prototype.browseSkillStore = async function(query, signal) {
|
|
3729
|
+
const resp = await this.browseSkills(
|
|
3730
|
+
1,
|
|
3731
|
+
50,
|
|
3732
|
+
query.category ?? "",
|
|
3733
|
+
query.keyword ?? "",
|
|
3734
|
+
query.tag ?? "",
|
|
3735
|
+
"",
|
|
3736
|
+
signal
|
|
3737
|
+
);
|
|
3738
|
+
return resp.items;
|
|
4041
3739
|
};
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
3740
|
+
Client.prototype.browseSkills = async function(page, pageSize, category, keyword, tag, source, signal) {
|
|
3741
|
+
const qv = new URLSearchParams();
|
|
3742
|
+
qv.set("page", String(page));
|
|
3743
|
+
qv.set("pageSize", String(pageSize));
|
|
3744
|
+
if (category) qv.set("category", category);
|
|
3745
|
+
if (keyword) qv.set("keyword", keyword);
|
|
3746
|
+
if (tag) qv.set("tag", tag);
|
|
3747
|
+
if (source) qv.set("source", source);
|
|
3748
|
+
const resp = await this.doPublicJSON(
|
|
3749
|
+
"GET",
|
|
3750
|
+
`/skill-store?${qv.toString()}`,
|
|
3751
|
+
null,
|
|
3752
|
+
signal
|
|
3753
|
+
);
|
|
3754
|
+
return resp.data;
|
|
4047
3755
|
};
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
3756
|
+
Client.prototype.browseSkillsList = async function(page, pageSize, category, keyword, tag, source, signal) {
|
|
3757
|
+
const qv = new URLSearchParams();
|
|
3758
|
+
qv.set("page", String(page));
|
|
3759
|
+
qv.set("pageSize", String(pageSize));
|
|
3760
|
+
qv.set("fields", "minimal");
|
|
3761
|
+
if (category) qv.set("category", category);
|
|
3762
|
+
if (keyword) qv.set("keyword", keyword);
|
|
3763
|
+
if (tag) qv.set("tag", tag);
|
|
3764
|
+
if (source) qv.set("source", source);
|
|
3765
|
+
const resp = await this.doPublicJSON(
|
|
3766
|
+
"GET",
|
|
3767
|
+
`/skill-store?${qv.toString()}`,
|
|
3768
|
+
null,
|
|
3769
|
+
signal
|
|
3770
|
+
);
|
|
3771
|
+
return resp.data;
|
|
4059
3772
|
};
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
3773
|
+
Client.prototype.getSkillDetail = async function(skillID, signal) {
|
|
3774
|
+
const resp = await this.doPublicJSON(
|
|
3775
|
+
"GET",
|
|
3776
|
+
`/skill-store/${encodeURIComponent(skillID)}`,
|
|
3777
|
+
null,
|
|
3778
|
+
signal
|
|
3779
|
+
);
|
|
3780
|
+
return resp.data;
|
|
3781
|
+
};
|
|
3782
|
+
Client.prototype.resolveSkill = async function(key, signal) {
|
|
3783
|
+
const resp = await this.doPublicJSON(
|
|
3784
|
+
"GET",
|
|
3785
|
+
`/skill-store/resolve/${encodeURIComponent(key)}`,
|
|
3786
|
+
null,
|
|
3787
|
+
signal
|
|
3788
|
+
);
|
|
3789
|
+
return resp.data;
|
|
3790
|
+
};
|
|
3791
|
+
Client.prototype.installSkill = async function(skillID, signal) {
|
|
3792
|
+
const resp = await this.doJSON(
|
|
3793
|
+
"POST",
|
|
3794
|
+
`/skill-store/${encodeURIComponent(skillID)}/install`,
|
|
3795
|
+
null,
|
|
3796
|
+
signal
|
|
3797
|
+
);
|
|
3798
|
+
return resp.data;
|
|
3799
|
+
};
|
|
3800
|
+
Client.prototype.downloadSkill = async function(skillID, signal) {
|
|
3801
|
+
const ctl = new AbortController();
|
|
3802
|
+
const timer = setTimeout(() => ctl.abort(), 5 * 60 * 1e3);
|
|
3803
|
+
let parentHandler;
|
|
3804
|
+
if (signal) {
|
|
3805
|
+
if (signal.aborted) ctl.abort();
|
|
3806
|
+
else {
|
|
3807
|
+
parentHandler = () => ctl.abort();
|
|
3808
|
+
signal.addEventListener("abort", parentHandler);
|
|
4071
3809
|
}
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
continue;
|
|
3810
|
+
}
|
|
3811
|
+
try {
|
|
3812
|
+
const url = this.apiURL(`/skill-store/${encodeURIComponent(skillID)}/download`);
|
|
3813
|
+
const headers = {};
|
|
3814
|
+
let token = "";
|
|
3815
|
+
try {
|
|
3816
|
+
token = await this.ensureToken(ctl.signal);
|
|
3817
|
+
} catch {
|
|
4081
3818
|
}
|
|
4082
|
-
if (
|
|
4083
|
-
|
|
3819
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
3820
|
+
let resp;
|
|
3821
|
+
try {
|
|
3822
|
+
resp = await this.fetchImpl(url, { method: "GET", headers, signal: ctl.signal });
|
|
3823
|
+
} catch (e) {
|
|
3824
|
+
throw classifyTransport(`GET /skill-store/${skillID}/download`, url, e);
|
|
4084
3825
|
}
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
}
|
|
4089
|
-
return out;
|
|
4090
|
-
}
|
|
4091
|
-
function collectDroppedToolUseIDs(messages, pred) {
|
|
4092
|
-
const ids = /* @__PURE__ */ new Set();
|
|
4093
|
-
for (const msg of messages) {
|
|
4094
|
-
if (!isPlainObject(msg)) continue;
|
|
4095
|
-
const content = msg["content"];
|
|
4096
|
-
if (!Array.isArray(content)) continue;
|
|
4097
|
-
for (const raw of content) {
|
|
4098
|
-
if (!isPlainObject(raw)) continue;
|
|
4099
|
-
if (!pred(raw)) continue;
|
|
4100
|
-
const t = raw["type"];
|
|
4101
|
-
if (typeof t !== "string") continue;
|
|
4102
|
-
if (t === "tool_use" || t === "server_tool_use" || t === "mcp_tool_use") {
|
|
4103
|
-
const id = raw["id"];
|
|
4104
|
-
if (typeof id === "string" && id !== "") ids.add(id);
|
|
4105
|
-
}
|
|
3826
|
+
if (resp.status === 429) {
|
|
3827
|
+
const bodyText = await readLimitedText(resp.body, maxErrorBodySize);
|
|
3828
|
+
throw new RateLimitError("\u533F\u540D\u4E0B\u8F7D\u5DF2\u8FBE\u9650\u5236", resp.headers.get("Retry-After") ?? "", bodyText);
|
|
4106
3829
|
}
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
let changed = false;
|
|
4113
|
-
for (const raw of content) {
|
|
4114
|
-
if (!isPlainObject(raw)) {
|
|
4115
|
-
kept.push(raw);
|
|
4116
|
-
continue;
|
|
3830
|
+
if (!resp.ok) {
|
|
3831
|
+
const bodyBytes = await readLimited(resp.body, maxErrorBodySize);
|
|
3832
|
+
throw new Error(
|
|
3833
|
+
`download skill: ${parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers).message}`
|
|
3834
|
+
);
|
|
4117
3835
|
}
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
3836
|
+
const data = await readLimited(resp.body, maxDownloadSize + 1);
|
|
3837
|
+
if (data.byteLength > maxDownloadSize) {
|
|
3838
|
+
throw new Error(`download skill: response exceeds ${maxDownloadSize >> 20}MB limit`);
|
|
4121
3839
|
}
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
3840
|
+
let filename = "skill.zip";
|
|
3841
|
+
const cd = resp.headers.get("Content-Disposition");
|
|
3842
|
+
if (cd) {
|
|
3843
|
+
const idx = cd.indexOf("filename");
|
|
3844
|
+
if (idx !== -1) {
|
|
3845
|
+
const parts = cd.slice(idx).split("=", 2);
|
|
3846
|
+
if (parts.length === 2) {
|
|
3847
|
+
filename = parts[1].trim().replace(/^["' ]+|["' ]+$/g, "");
|
|
4129
3848
|
}
|
|
4130
3849
|
}
|
|
4131
3850
|
}
|
|
4132
|
-
|
|
3851
|
+
return { data, filename };
|
|
3852
|
+
} finally {
|
|
3853
|
+
clearTimeout(timer);
|
|
3854
|
+
if (parentHandler && signal) signal.removeEventListener("abort", parentHandler);
|
|
4133
3855
|
}
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
3856
|
+
};
|
|
3857
|
+
Client.prototype.uploadSkill = async function(zipData, scope, intent, signal) {
|
|
3858
|
+
return uploadSkillInternal(this, zipData, scope, intent, false, signal);
|
|
3859
|
+
};
|
|
3860
|
+
async function uploadSkillInternal(c, zipData, scope, intent, retried, signal) {
|
|
3861
|
+
const ctl = new AbortController();
|
|
3862
|
+
const timer = setTimeout(() => ctl.abort(), 5 * 60 * 1e3);
|
|
3863
|
+
let parentHandler;
|
|
3864
|
+
if (signal) {
|
|
3865
|
+
if (signal.aborted) ctl.abort();
|
|
3866
|
+
else {
|
|
3867
|
+
parentHandler = () => ctl.abort();
|
|
3868
|
+
signal.addEventListener("abort", parentHandler);
|
|
4141
3869
|
}
|
|
4142
|
-
const v = b[EphemeralMarkerField];
|
|
4143
|
-
return v === true;
|
|
4144
|
-
});
|
|
4145
|
-
}
|
|
4146
|
-
function isPlainObject(v) {
|
|
4147
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
4148
|
-
}
|
|
4149
|
-
|
|
4150
|
-
// src/sanitize/defensive.ts
|
|
4151
|
-
function sanitize(messages, cfg) {
|
|
4152
|
-
if ((cfg.maxMessagesTurns ?? 0) > 0 && messages.length > cfg.maxMessagesTurns) {
|
|
4153
|
-
throw ErrHistoryTooDeep;
|
|
4154
|
-
}
|
|
4155
|
-
if ((cfg.maxImageBytes ?? 0) > 0 || (cfg.maxVideoBytes ?? 0) > 0 || (cfg.maxPDFBytes ?? 0) > 0) {
|
|
4156
|
-
checkMediaSizes(messages, cfg);
|
|
4157
|
-
}
|
|
4158
|
-
if (cfg.permanentDenyBlocks && cfg.permanentDenyBlocks.length > 0) {
|
|
4159
|
-
const denySet = /* @__PURE__ */ new Set();
|
|
4160
|
-
for (const bt of cfg.permanentDenyBlocks) denySet.add(bt);
|
|
4161
|
-
messages = dropBlocks(messages, (b) => {
|
|
4162
|
-
const t = b["type"];
|
|
4163
|
-
return typeof t === "string" && denySet.has(t);
|
|
4164
|
-
});
|
|
4165
3870
|
}
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
const
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
continue;
|
|
3871
|
+
try {
|
|
3872
|
+
const token = await c.ensureToken(ctl.signal);
|
|
3873
|
+
const form = new FormData();
|
|
3874
|
+
form.append("scope", scope);
|
|
3875
|
+
form.append("intent", intent);
|
|
3876
|
+
const blob = new Blob([zipData], { type: "application/zip" });
|
|
3877
|
+
form.append("file", blob, "skill.zip");
|
|
3878
|
+
const url = c.apiURL("/skill-store/upload");
|
|
3879
|
+
let resp;
|
|
3880
|
+
try {
|
|
3881
|
+
resp = await c.fetchImpl(url, {
|
|
3882
|
+
method: "POST",
|
|
3883
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
3884
|
+
body: form,
|
|
3885
|
+
signal: ctl.signal
|
|
3886
|
+
});
|
|
3887
|
+
} catch (e) {
|
|
3888
|
+
throw classifyTransport("POST /skill-store/upload", url, e);
|
|
3889
|
+
}
|
|
3890
|
+
if (resp.status === 401 && !retried) {
|
|
3891
|
+
try {
|
|
3892
|
+
await resp.body?.cancel();
|
|
3893
|
+
} catch {
|
|
4190
3894
|
}
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
3895
|
+
try {
|
|
3896
|
+
await c.forceRefresh(ctl.signal);
|
|
3897
|
+
} catch (refreshErr) {
|
|
3898
|
+
throw new Error(
|
|
3899
|
+
`upload: unauthorized and refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}`
|
|
3900
|
+
);
|
|
4197
3901
|
}
|
|
3902
|
+
return uploadSkillInternal(c, zipData, scope, intent, true, signal);
|
|
4198
3903
|
}
|
|
3904
|
+
if (resp.status < 200 || resp.status >= 300) {
|
|
3905
|
+
const bodyBytes = await readLimited(resp.body, maxErrorBodySize);
|
|
3906
|
+
throw new Error(
|
|
3907
|
+
`upload: ${parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers).message}`
|
|
3908
|
+
);
|
|
3909
|
+
}
|
|
3910
|
+
const text = await resp.text();
|
|
3911
|
+
const result = JSON.parse(text);
|
|
3912
|
+
return result.data.skill;
|
|
3913
|
+
} finally {
|
|
3914
|
+
clearTimeout(timer);
|
|
3915
|
+
if (parentHandler && signal) signal.removeEventListener("abort", parentHandler);
|
|
4199
3916
|
}
|
|
4200
3917
|
}
|
|
4201
|
-
function
|
|
4202
|
-
const
|
|
4203
|
-
|
|
4204
|
-
if (src["type"] !== "base64") return "";
|
|
4205
|
-
const dataRaw = src["data"];
|
|
4206
|
-
if (typeof dataRaw !== "string") return "";
|
|
4207
|
-
let data = dataRaw;
|
|
4208
|
-
const i = data.indexOf("base64,");
|
|
4209
|
-
if (i >= 0) {
|
|
4210
|
-
data = data.slice(i + "base64,".length);
|
|
4211
|
-
}
|
|
4212
|
-
return data;
|
|
4213
|
-
}
|
|
4214
|
-
function base64DecodedLen(b64) {
|
|
4215
|
-
const n = b64.length;
|
|
4216
|
-
let pad = 0;
|
|
4217
|
-
if (n >= 1 && b64[n - 1] === "=") pad++;
|
|
4218
|
-
if (n >= 2 && b64[n - 2] === "=") pad++;
|
|
4219
|
-
return Math.floor(n * 3 / 4) - pad;
|
|
4220
|
-
}
|
|
4221
|
-
function isPlainObject2(v) {
|
|
4222
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
4223
|
-
}
|
|
4224
|
-
|
|
4225
|
-
// src/agent-runs-types.ts
|
|
4226
|
-
var AgentRunStreamError = class extends Error {
|
|
4227
|
-
event;
|
|
4228
|
-
code;
|
|
4229
|
-
stage;
|
|
4230
|
-
retryable;
|
|
4231
|
-
constructor(event) {
|
|
4232
|
-
const err = event.error;
|
|
4233
|
-
super(err.stage ? `agent run failed: ${err.stage}: ${err.message}` : `agent run failed: ${err.message}`);
|
|
4234
|
-
this.name = "AgentRunStreamError";
|
|
4235
|
-
this.event = event;
|
|
4236
|
-
this.code = err.code ?? "";
|
|
4237
|
-
this.stage = err.stage ?? "";
|
|
4238
|
-
this.retryable = err.retryable ?? false;
|
|
4239
|
-
}
|
|
3918
|
+
Client.prototype.getSkillSummary = async function(signal) {
|
|
3919
|
+
const resp = await this.doJSON("GET", "/skills/summary", null, signal);
|
|
3920
|
+
return resp.data;
|
|
4240
3921
|
};
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
3922
|
+
Client.prototype.certifySkill = async function(skillID, signal) {
|
|
3923
|
+
await this.doJSON(
|
|
3924
|
+
"POST",
|
|
3925
|
+
`/skill-store/${encodeURIComponent(skillID)}/certify`,
|
|
3926
|
+
null,
|
|
3927
|
+
signal
|
|
3928
|
+
);
|
|
3929
|
+
};
|
|
3930
|
+
Client.prototype.getCertificationStatus = async function(skillID, signal) {
|
|
3931
|
+
const resp = await this.doJSON(
|
|
3932
|
+
"GET",
|
|
3933
|
+
`/skill-store/${encodeURIComponent(skillID)}/certification`,
|
|
3934
|
+
null,
|
|
3935
|
+
signal
|
|
3936
|
+
);
|
|
3937
|
+
return resp.data;
|
|
3938
|
+
};
|
|
3939
|
+
Client.prototype.generateSkill = async function(req, signal) {
|
|
3940
|
+
const resp = await this.doJSON(
|
|
3941
|
+
"POST",
|
|
3942
|
+
"/skill-generator/generate",
|
|
3943
|
+
req,
|
|
3944
|
+
signal
|
|
3945
|
+
);
|
|
3946
|
+
return resp.data;
|
|
3947
|
+
};
|
|
3948
|
+
Client.prototype.optimizeSkill = async function(req, signal) {
|
|
3949
|
+
const resp = await this.doJSON(
|
|
3950
|
+
"POST",
|
|
3951
|
+
"/skill-generator/optimize",
|
|
3952
|
+
req,
|
|
3953
|
+
signal
|
|
3954
|
+
);
|
|
3955
|
+
return resp.data;
|
|
3956
|
+
};
|
|
3957
|
+
Client.prototype.validateSkill = async function(skillName, signal) {
|
|
3958
|
+
await this.doJSON(
|
|
3959
|
+
"POST",
|
|
3960
|
+
"/skill-generator/validate",
|
|
3961
|
+
{ skillName },
|
|
3962
|
+
signal
|
|
3963
|
+
);
|
|
3964
|
+
};
|
|
3965
|
+
|
|
3966
|
+
// src/skills/tools.ts
|
|
3967
|
+
Client.prototype.listTools = async function(signal) {
|
|
3968
|
+
const resp = await this.doJSON("GET", "/tools", null, signal);
|
|
3969
|
+
return resp.data.skills;
|
|
3970
|
+
};
|
|
3971
|
+
Client.prototype.getTool = async function(toolID, signal) {
|
|
3972
|
+
const resp = await this.doJSON(
|
|
3973
|
+
"GET",
|
|
3974
|
+
`/tools/${encodeURIComponent(toolID)}`,
|
|
3975
|
+
null,
|
|
3976
|
+
signal
|
|
3977
|
+
);
|
|
3978
|
+
return resp.data;
|
|
3979
|
+
};
|
|
3980
|
+
|
|
3981
|
+
// src/notifications/types.ts
|
|
3982
|
+
function parseNotificationEvent(ev) {
|
|
3983
|
+
if (ev.type !== "event" || ev.topic !== "system") {
|
|
3984
|
+
return null;
|
|
4255
3985
|
}
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
3986
|
+
if (ev.data == null) return null;
|
|
3987
|
+
let n;
|
|
3988
|
+
try {
|
|
3989
|
+
if (typeof ev.data === "string") {
|
|
3990
|
+
n = JSON.parse(ev.data);
|
|
3991
|
+
} else {
|
|
3992
|
+
n = ev.data;
|
|
3993
|
+
}
|
|
3994
|
+
} catch {
|
|
3995
|
+
return null;
|
|
4260
3996
|
}
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
3997
|
+
if (!n.id) return null;
|
|
3998
|
+
return n;
|
|
3999
|
+
}
|
|
4000
|
+
|
|
4001
|
+
// src/notifications/notifications.ts
|
|
4002
|
+
Client.prototype.listNotifications = async function(page, pageSize, typeFilter, signal) {
|
|
4003
|
+
let path = `/notifications?page=${page}&pageSize=${pageSize}`;
|
|
4004
|
+
if (typeFilter) path += `&type=${encodeURIComponent(typeFilter)}`;
|
|
4005
|
+
const resp = await this.doJSON("GET", path, null, signal);
|
|
4006
|
+
return resp.data;
|
|
4007
|
+
};
|
|
4008
|
+
Client.prototype.getUnreadCount = async function(signal) {
|
|
4009
|
+
const resp = await this.doJSON(
|
|
4010
|
+
"GET",
|
|
4011
|
+
"/notifications/unread-count",
|
|
4012
|
+
null,
|
|
4013
|
+
signal
|
|
4014
|
+
);
|
|
4015
|
+
return resp.data.unreadCount;
|
|
4016
|
+
};
|
|
4017
|
+
Client.prototype.markNotificationRead = async function(id, signal) {
|
|
4018
|
+
await this.doJSON(
|
|
4019
|
+
"PUT",
|
|
4020
|
+
`/notifications/${encodeURIComponent(id)}/read`,
|
|
4021
|
+
null,
|
|
4022
|
+
signal
|
|
4023
|
+
);
|
|
4024
|
+
};
|
|
4025
|
+
Client.prototype.markAllNotificationsRead = async function(signal) {
|
|
4026
|
+
await this.doJSON("PUT", "/notifications/read-all", null, signal);
|
|
4027
|
+
};
|
|
4028
|
+
Client.prototype.deleteNotification = async function(id, signal) {
|
|
4029
|
+
await this.doJSON(
|
|
4030
|
+
"DELETE",
|
|
4031
|
+
`/notifications/${encodeURIComponent(id)}`,
|
|
4032
|
+
null,
|
|
4033
|
+
signal
|
|
4034
|
+
);
|
|
4035
|
+
};
|
|
4036
|
+
Client.prototype.registerDevice = async function(reg, signal) {
|
|
4037
|
+
await this.doJSON("POST", "/devices/register", reg, signal);
|
|
4038
|
+
};
|
|
4039
|
+
Client.prototype.unregisterDevice = async function(token, signal) {
|
|
4040
|
+
await this.doJSON(
|
|
4041
|
+
"DELETE",
|
|
4042
|
+
`/devices/${encodeURIComponent(token)}`,
|
|
4043
|
+
null,
|
|
4044
|
+
signal
|
|
4045
|
+
);
|
|
4046
|
+
};
|
|
4047
|
+
Client.prototype.listNotificationPreferences = async function(signal) {
|
|
4048
|
+
const resp = await this.doJSON(
|
|
4049
|
+
"GET",
|
|
4050
|
+
"/notification-preferences",
|
|
4051
|
+
null,
|
|
4052
|
+
signal
|
|
4053
|
+
);
|
|
4054
|
+
return resp.data;
|
|
4055
|
+
};
|
|
4056
|
+
Client.prototype.updateNotificationPreference = async function(typeCode, pref, signal) {
|
|
4057
|
+
await this.doJSON(
|
|
4058
|
+
"PUT",
|
|
4059
|
+
`/notification-preferences/${encodeURIComponent(typeCode)}`,
|
|
4060
|
+
pref,
|
|
4061
|
+
signal
|
|
4062
|
+
);
|
|
4063
|
+
};
|
|
4064
|
+
|
|
4065
|
+
// src/notifications/ws.ts
|
|
4066
|
+
Client.prototype.connect = async function(cfg, signal) {
|
|
4067
|
+
const noop = () => {
|
|
4068
|
+
};
|
|
4069
|
+
const filledCfg = {
|
|
4070
|
+
onEvent: cfg.onEvent ?? noop,
|
|
4071
|
+
onConnect: cfg.onConnect ?? noop,
|
|
4072
|
+
onDisconnect: cfg.onDisconnect ?? noop,
|
|
4073
|
+
topics: cfg.topics ?? [],
|
|
4074
|
+
reconnectMinMs: cfg.reconnectMinMs ?? 2e3,
|
|
4075
|
+
reconnectMaxMs: cfg.reconnectMaxMs ?? 6e4,
|
|
4076
|
+
autoReconnect: cfg.autoReconnect ?? true
|
|
4077
|
+
};
|
|
4078
|
+
let resolveDone;
|
|
4079
|
+
const done = new Promise((r) => {
|
|
4080
|
+
resolveDone = r;
|
|
4081
|
+
});
|
|
4082
|
+
const abort = new AbortController();
|
|
4083
|
+
if (signal) {
|
|
4084
|
+
if (signal.aborted) abort.abort();
|
|
4085
|
+
else signal.addEventListener("abort", () => abort.abort());
|
|
4271
4086
|
}
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4087
|
+
const ws = {
|
|
4088
|
+
conn: null,
|
|
4089
|
+
cfg: filledCfg,
|
|
4090
|
+
abort,
|
|
4091
|
+
done,
|
|
4092
|
+
doneResolve: resolveDone,
|
|
4093
|
+
connected: false
|
|
4094
|
+
};
|
|
4095
|
+
await wsConnectOnce(this, ws);
|
|
4096
|
+
this.ws = ws;
|
|
4097
|
+
void wsLoop(this, ws);
|
|
4098
|
+
};
|
|
4099
|
+
Client.prototype.disconnect = async function() {
|
|
4100
|
+
const ws = this.ws;
|
|
4101
|
+
this.ws = null;
|
|
4102
|
+
if (!ws) return;
|
|
4103
|
+
ws.abort.abort();
|
|
4104
|
+
ws.connected = false;
|
|
4105
|
+
if (ws.conn) {
|
|
4106
|
+
try {
|
|
4107
|
+
ws.conn.close(1e3, "");
|
|
4108
|
+
} catch {
|
|
4109
|
+
}
|
|
4280
4110
|
}
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4111
|
+
await Promise.race([
|
|
4112
|
+
ws.done,
|
|
4113
|
+
new Promise((resolve) => setTimeout(resolve, 5e3))
|
|
4114
|
+
]);
|
|
4115
|
+
};
|
|
4116
|
+
Client.prototype.isConnected = function() {
|
|
4117
|
+
const ws = this.ws;
|
|
4118
|
+
if (!ws) return false;
|
|
4119
|
+
return ws.connected;
|
|
4120
|
+
};
|
|
4121
|
+
function wsURL(c) {
|
|
4122
|
+
const base = c.apiURL("/ws");
|
|
4123
|
+
return base.replace(/^http:\/\//, "ws://").replace(/^https:\/\//, "wss://");
|
|
4124
|
+
}
|
|
4125
|
+
function getWebSocketCtor() {
|
|
4126
|
+
const WSCtor = globalThis.WebSocket;
|
|
4127
|
+
if (!WSCtor) {
|
|
4128
|
+
throw new Error(
|
|
4129
|
+
'WebSocket not available \u2014 on Node \u226421 set globalThis.WebSocket = require("ws") before connect'
|
|
4130
|
+
);
|
|
4285
4131
|
}
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4132
|
+
return WSCtor;
|
|
4133
|
+
}
|
|
4134
|
+
async function wsConnectOnce(c, ws) {
|
|
4135
|
+
const token = await c.ensureToken(ws.abort.signal);
|
|
4136
|
+
const url = wsURL(c);
|
|
4137
|
+
const WSCtor = getWebSocketCtor();
|
|
4138
|
+
const u = new URL(url);
|
|
4139
|
+
u.searchParams.set("token", token);
|
|
4140
|
+
let conn;
|
|
4141
|
+
try {
|
|
4142
|
+
conn = new WSCtor(u.toString());
|
|
4143
|
+
} catch (e) {
|
|
4144
|
+
throw new Error(`dial: ${e instanceof Error ? e.message : String(e)}`);
|
|
4294
4145
|
}
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4146
|
+
await new Promise((resolve, reject) => {
|
|
4147
|
+
let opened = false;
|
|
4148
|
+
const handshakeTimer = setTimeout(() => {
|
|
4149
|
+
if (!opened) {
|
|
4150
|
+
try {
|
|
4151
|
+
conn.close();
|
|
4152
|
+
} catch {
|
|
4153
|
+
}
|
|
4154
|
+
reject(new Error("dial: handshake timeout"));
|
|
4155
|
+
}
|
|
4156
|
+
}, 3e4);
|
|
4157
|
+
conn.addEventListener("open", () => {
|
|
4158
|
+
opened = true;
|
|
4159
|
+
});
|
|
4160
|
+
conn.addEventListener("error", (e) => {
|
|
4161
|
+
clearTimeout(handshakeTimer);
|
|
4162
|
+
reject(new Error(`dial: ${e.message ?? "connection error"}`));
|
|
4163
|
+
});
|
|
4164
|
+
conn.addEventListener("message", (e) => {
|
|
4165
|
+
try {
|
|
4166
|
+
const msg = e.data;
|
|
4167
|
+
const welcome = JSON.parse(msg);
|
|
4168
|
+
if (welcome.type !== "welcome") {
|
|
4169
|
+
clearTimeout(handshakeTimer);
|
|
4170
|
+
try {
|
|
4171
|
+
conn.close();
|
|
4172
|
+
} catch {
|
|
4173
|
+
}
|
|
4174
|
+
reject(new Error(`unexpected first message: ${welcome.type}`));
|
|
4175
|
+
return;
|
|
4176
|
+
}
|
|
4177
|
+
clearTimeout(handshakeTimer);
|
|
4178
|
+
ws.conn = conn;
|
|
4179
|
+
ws.connected = true;
|
|
4180
|
+
if (ws.cfg.topics.length > 0) {
|
|
4181
|
+
try {
|
|
4182
|
+
conn.send(
|
|
4183
|
+
JSON.stringify({
|
|
4184
|
+
type: "subscribe",
|
|
4185
|
+
topics: ws.cfg.topics
|
|
4186
|
+
})
|
|
4187
|
+
);
|
|
4188
|
+
} catch (sendErr) {
|
|
4189
|
+
ws.conn = null;
|
|
4190
|
+
ws.connected = false;
|
|
4191
|
+
try {
|
|
4192
|
+
conn.close();
|
|
4193
|
+
} catch {
|
|
4194
|
+
}
|
|
4195
|
+
reject(new Error(`send subscribe: ${sendErr instanceof Error ? sendErr.message : String(sendErr)}`));
|
|
4196
|
+
return;
|
|
4197
|
+
}
|
|
4198
|
+
}
|
|
4199
|
+
ws.cfg.onConnect();
|
|
4200
|
+
console.log(`[acosmi-sdk] websocket connected, connId=${welcome.connId ?? ""}`);
|
|
4201
|
+
resolve();
|
|
4202
|
+
} catch (parseErr) {
|
|
4203
|
+
clearTimeout(handshakeTimer);
|
|
4204
|
+
try {
|
|
4205
|
+
conn.close();
|
|
4206
|
+
} catch {
|
|
4207
|
+
}
|
|
4208
|
+
reject(new Error(`parse welcome: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`));
|
|
4209
|
+
}
|
|
4210
|
+
}, { once: true });
|
|
4211
|
+
});
|
|
4212
|
+
}
|
|
4213
|
+
async function wsLoop(c, ws) {
|
|
4214
|
+
try {
|
|
4215
|
+
while (true) {
|
|
4216
|
+
await wsReadLoop(ws);
|
|
4217
|
+
if (ws.abort.signal.aborted) return;
|
|
4218
|
+
if (ws.conn) {
|
|
4219
|
+
try {
|
|
4220
|
+
ws.conn.close();
|
|
4221
|
+
} catch {
|
|
4222
|
+
}
|
|
4223
|
+
ws.conn = null;
|
|
4224
|
+
}
|
|
4225
|
+
ws.connected = false;
|
|
4226
|
+
if (!ws.cfg.autoReconnect) return;
|
|
4227
|
+
let delay = ws.cfg.reconnectMinMs;
|
|
4228
|
+
while (true) {
|
|
4229
|
+
if (ws.abort.signal.aborted) return;
|
|
4230
|
+
await sleepWithSignal2(delay, ws.abort.signal).catch(() => {
|
|
4231
|
+
});
|
|
4232
|
+
if (ws.abort.signal.aborted) return;
|
|
4233
|
+
console.log(`[acosmi-sdk] websocket reconnecting (delay=${delay}ms)...`);
|
|
4234
|
+
try {
|
|
4235
|
+
await wsConnectOnce(c, ws);
|
|
4236
|
+
break;
|
|
4237
|
+
} catch (err) {
|
|
4238
|
+
console.log(`[acosmi-sdk] websocket reconnect failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4239
|
+
delay = Math.min(delay * 2, ws.cfg.reconnectMaxMs);
|
|
4240
|
+
}
|
|
4241
|
+
}
|
|
4242
|
+
}
|
|
4243
|
+
} finally {
|
|
4244
|
+
ws.doneResolve();
|
|
4245
|
+
}
|
|
4246
|
+
}
|
|
4247
|
+
async function wsReadLoop(ws) {
|
|
4248
|
+
const conn = ws.conn;
|
|
4249
|
+
if (!conn) return;
|
|
4250
|
+
return new Promise((resolve) => {
|
|
4251
|
+
const handleMessage = (e) => {
|
|
4252
|
+
try {
|
|
4253
|
+
const data = e.data;
|
|
4254
|
+
const event = JSON.parse(data);
|
|
4255
|
+
try {
|
|
4256
|
+
ws.cfg.onEvent(event);
|
|
4257
|
+
} catch {
|
|
4258
|
+
}
|
|
4259
|
+
} catch {
|
|
4260
|
+
}
|
|
4261
|
+
};
|
|
4262
|
+
const handleClose = (e) => {
|
|
4263
|
+
conn.removeEventListener("message", handleMessage);
|
|
4264
|
+
conn.removeEventListener("close", handleClose);
|
|
4265
|
+
conn.removeEventListener("error", handleError);
|
|
4266
|
+
try {
|
|
4267
|
+
ws.cfg.onDisconnect(new Error(`closed: code=${e.code} reason=${e.reason}`));
|
|
4268
|
+
} catch {
|
|
4269
|
+
}
|
|
4270
|
+
resolve();
|
|
4271
|
+
};
|
|
4272
|
+
const handleError = (e) => {
|
|
4273
|
+
conn.removeEventListener("message", handleMessage);
|
|
4274
|
+
conn.removeEventListener("close", handleClose);
|
|
4275
|
+
conn.removeEventListener("error", handleError);
|
|
4276
|
+
try {
|
|
4277
|
+
ws.cfg.onDisconnect(e);
|
|
4278
|
+
} catch {
|
|
4279
|
+
}
|
|
4280
|
+
resolve();
|
|
4281
|
+
};
|
|
4282
|
+
conn.addEventListener("message", handleMessage);
|
|
4283
|
+
conn.addEventListener("close", handleClose);
|
|
4284
|
+
conn.addEventListener("error", handleError);
|
|
4285
|
+
if (ws.abort.signal.aborted) {
|
|
4286
|
+
try {
|
|
4287
|
+
conn.close();
|
|
4288
|
+
} catch {
|
|
4289
|
+
}
|
|
4290
|
+
} else {
|
|
4291
|
+
ws.abort.signal.addEventListener(
|
|
4292
|
+
"abort",
|
|
4293
|
+
() => {
|
|
4294
|
+
try {
|
|
4295
|
+
conn.close();
|
|
4296
|
+
} catch {
|
|
4297
|
+
}
|
|
4298
|
+
},
|
|
4299
|
+
{ once: true }
|
|
4300
|
+
);
|
|
4301
|
+
}
|
|
4302
|
+
});
|
|
4303
|
+
}
|
|
4304
|
+
async function sleepWithSignal2(ms, signal) {
|
|
4305
|
+
if (ms <= 0) return;
|
|
4306
|
+
if (signal.aborted) throw new Error("aborted");
|
|
4307
|
+
return new Promise((resolve, reject) => {
|
|
4308
|
+
const t = setTimeout(() => {
|
|
4309
|
+
signal.removeEventListener("abort", abortHandler);
|
|
4310
|
+
resolve();
|
|
4311
|
+
}, ms);
|
|
4312
|
+
const abortHandler = () => {
|
|
4313
|
+
clearTimeout(t);
|
|
4314
|
+
signal.removeEventListener("abort", abortHandler);
|
|
4315
|
+
reject(new Error("aborted"));
|
|
4316
|
+
};
|
|
4317
|
+
signal.addEventListener("abort", abortHandler);
|
|
4318
|
+
});
|
|
4319
|
+
}
|
|
4320
|
+
|
|
4321
|
+
// src/agent-runs/types.ts
|
|
4322
|
+
var AgentRunStreamError = class extends Error {
|
|
4323
|
+
event;
|
|
4324
|
+
code;
|
|
4325
|
+
stage;
|
|
4326
|
+
retryable;
|
|
4327
|
+
constructor(event) {
|
|
4328
|
+
const err = event.error;
|
|
4329
|
+
super(err.stage ? `agent run failed: ${err.stage}: ${err.message}` : `agent run failed: ${err.message}`);
|
|
4330
|
+
this.name = "AgentRunStreamError";
|
|
4331
|
+
this.event = event;
|
|
4332
|
+
this.code = err.code ?? "";
|
|
4333
|
+
this.stage = err.stage ?? "";
|
|
4334
|
+
this.retryable = err.retryable ?? false;
|
|
4335
|
+
}
|
|
4336
|
+
};
|
|
4337
|
+
|
|
4338
|
+
// src/agent-runs/client.ts
|
|
4339
|
+
var agentRunsByClient = /* @__PURE__ */ new WeakMap();
|
|
4340
|
+
Object.defineProperty(Client.prototype, "agentRuns", {
|
|
4341
|
+
configurable: true,
|
|
4342
|
+
enumerable: false,
|
|
4343
|
+
get() {
|
|
4344
|
+
let existing = agentRunsByClient.get(this);
|
|
4345
|
+
if (!existing) {
|
|
4346
|
+
existing = new AgentRunsClient(this);
|
|
4347
|
+
agentRunsByClient.set(this, existing);
|
|
4348
|
+
}
|
|
4349
|
+
return existing;
|
|
4350
|
+
}
|
|
4351
|
+
});
|
|
4352
|
+
var AgentRunsClient = class {
|
|
4353
|
+
constructor(client) {
|
|
4354
|
+
this.client = client;
|
|
4355
|
+
}
|
|
4356
|
+
client;
|
|
4357
|
+
async create(req, signal) {
|
|
4358
|
+
const resp = await this.requestAPI(
|
|
4359
|
+
"POST",
|
|
4360
|
+
"/agent-runs",
|
|
4361
|
+
toWireCreateRequest(req),
|
|
4362
|
+
signal,
|
|
4363
|
+
{ retryOn401: false }
|
|
4364
|
+
);
|
|
4365
|
+
return fromWireCreateResponse(resp);
|
|
4366
|
+
}
|
|
4367
|
+
get(runId, signal) {
|
|
4368
|
+
return this.requestAPI(
|
|
4369
|
+
"GET",
|
|
4370
|
+
`/agent-runs/${encodeURIComponent(runId)}`,
|
|
4371
|
+
null,
|
|
4372
|
+
signal,
|
|
4373
|
+
{ retryOn401: true }
|
|
4374
|
+
).then(fromWireRun);
|
|
4375
|
+
}
|
|
4376
|
+
stream(runId, opts = {}, signal) {
|
|
4377
|
+
return {
|
|
4378
|
+
[Symbol.asyncIterator]: () => this.streamGen(runId, opts, signal)
|
|
4379
|
+
};
|
|
4380
|
+
}
|
|
4381
|
+
cancel(runId, signal) {
|
|
4382
|
+
return this.requestAPI(
|
|
4383
|
+
"POST",
|
|
4384
|
+
`/agent-runs/${encodeURIComponent(runId)}/cancel`,
|
|
4385
|
+
{},
|
|
4386
|
+
signal,
|
|
4387
|
+
{ retryOn401: false }
|
|
4388
|
+
).then(fromWireRun);
|
|
4389
|
+
}
|
|
4390
|
+
listArtifacts(runId, signal) {
|
|
4391
|
+
return this.requestAPI(
|
|
4392
|
+
"GET",
|
|
4393
|
+
`/agent-runs/${encodeURIComponent(runId)}/artifacts`,
|
|
4394
|
+
null,
|
|
4395
|
+
signal,
|
|
4396
|
+
{ retryOn401: true }
|
|
4302
4397
|
).then((r) => (r.artifacts ?? []).map(fromWireArtifact));
|
|
4303
4398
|
}
|
|
4304
4399
|
async downloadArtifact(runId, artifactId, signal) {
|
|
@@ -4718,801 +4813,728 @@ function errorMessage(e) {
|
|
|
4718
4813
|
return e instanceof Error ? e.message : String(e);
|
|
4719
4814
|
}
|
|
4720
4815
|
|
|
4721
|
-
// src/
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4816
|
+
// src/compliance/scopes.ts
|
|
4817
|
+
var ScopeComplianceEvidenceRead = "compliance:evidence:read";
|
|
4818
|
+
var ScopeComplianceEvidenceWrite = "compliance:evidence:write";
|
|
4819
|
+
var ScopeComplianceTimestampIssue = "compliance:timestamp:issue";
|
|
4820
|
+
var ScopeComplianceTimestampVerify = "compliance:timestamp:verify";
|
|
4821
|
+
var ScopeComplianceContractSigningRead = "compliance:contract_signing:read";
|
|
4822
|
+
var ScopeComplianceContractSigningWrite = "compliance:contract_signing:write";
|
|
4823
|
+
var ScopeComplianceSealManage = "compliance:seal:manage";
|
|
4824
|
+
var ScopeComplianceSealApprovalRequest = "compliance:seal_approval:request";
|
|
4825
|
+
var ScopeComplianceSealApprovalApprove = "compliance:seal_approval:approve";
|
|
4826
|
+
var ScopeComplianceSealUseExecute = "compliance:seal_use:execute";
|
|
4827
|
+
var ScopeComplianceReportsRead = "compliance:reports:read";
|
|
4828
|
+
var ScopeComplianceReportsWrite = "compliance:reports:write";
|
|
4829
|
+
var ScopeComplianceReportsPublish = "compliance:reports:publish";
|
|
4830
|
+
function complianceScopes() {
|
|
4831
|
+
return [
|
|
4832
|
+
ScopeComplianceEvidenceRead,
|
|
4833
|
+
ScopeComplianceEvidenceWrite,
|
|
4834
|
+
ScopeComplianceTimestampIssue,
|
|
4835
|
+
ScopeComplianceTimestampVerify,
|
|
4836
|
+
ScopeComplianceContractSigningRead,
|
|
4837
|
+
ScopeComplianceContractSigningWrite,
|
|
4838
|
+
ScopeComplianceSealManage,
|
|
4839
|
+
ScopeComplianceSealApprovalRequest,
|
|
4840
|
+
ScopeComplianceSealApprovalApprove,
|
|
4841
|
+
ScopeComplianceSealUseExecute,
|
|
4842
|
+
ScopeComplianceReportsRead,
|
|
4843
|
+
ScopeComplianceReportsWrite,
|
|
4844
|
+
ScopeComplianceReportsPublish
|
|
4845
|
+
];
|
|
4846
|
+
}
|
|
4847
|
+
|
|
4848
|
+
// src/compliance/status.ts
|
|
4849
|
+
var ErrComplianceStepUpRequired = "COMPLIANCE_STEP_UP_REQUIRED";
|
|
4850
|
+
var ErrEnvelopeGateClosed = "ENVELOPE_GATE_CLOSED";
|
|
4851
|
+
var ErrProviderNotConfigured = "PROVIDER_NOT_CONFIGURED";
|
|
4852
|
+
var ErrProviderUnknownNoRetry = "PROVIDER_REQUEST_UNKNOWN_NO_RETRY";
|
|
4853
|
+
var ErrBillingCallbackCannotCommit = "BILLING_CALLBACK_CANNOT_COMMIT";
|
|
4854
|
+
var ErrBillingCommitRequiresLocalVerify = "BILLING_COMMIT_REQUIRES_LOCAL_VERIFY";
|
|
4855
|
+
var ErrBillingS2sForbidden = "BILLING_S2S_FORBIDDEN";
|
|
4856
|
+
var ErrSealApprovalNotApproved = "SEAL_APPROVAL_STATE_NOT_APPROVED";
|
|
4857
|
+
var ErrSealApprovalExpired = "SEAL_APPROVAL_EXPIRED";
|
|
4858
|
+
var ErrSealApprovalNonceUsed = "SEAL_APPROVAL_NONCE_USED";
|
|
4859
|
+
var ErrSealApprovalContractHashMismatch = "SEAL_APPROVAL_CONTRACT_HASH_MISMATCH";
|
|
4860
|
+
var ErrSealApprovalSealMismatch = "SEAL_APPROVAL_SEAL_MISMATCH";
|
|
4861
|
+
var ErrSealApprovalLocationMismatch = "SEAL_APPROVAL_LOCATION_MISMATCH";
|
|
4862
|
+
var ErrSealApprovalTransactorMismatch = "SEAL_APPROVAL_TRANSACTOR_MISMATCH";
|
|
4863
|
+
var ErrSealUseAlreadyConsumed = "SEAL_USE_ALREADY_CONSUMED";
|
|
4864
|
+
function isComplianceTerminalError(code) {
|
|
4865
|
+
switch (code) {
|
|
4866
|
+
case ErrEnvelopeGateClosed:
|
|
4867
|
+
case ErrProviderNotConfigured:
|
|
4868
|
+
case ErrProviderUnknownNoRetry:
|
|
4869
|
+
case ErrBillingCallbackCannotCommit:
|
|
4870
|
+
case ErrBillingCommitRequiresLocalVerify:
|
|
4871
|
+
case ErrBillingS2sForbidden:
|
|
4872
|
+
case ErrSealApprovalNonceUsed:
|
|
4873
|
+
case ErrSealApprovalExpired:
|
|
4874
|
+
case ErrSealApprovalContractHashMismatch:
|
|
4875
|
+
case ErrSealApprovalSealMismatch:
|
|
4876
|
+
case ErrSealApprovalLocationMismatch:
|
|
4877
|
+
case ErrSealApprovalTransactorMismatch:
|
|
4878
|
+
case ErrSealUseAlreadyConsumed:
|
|
4879
|
+
return true;
|
|
4880
|
+
default:
|
|
4881
|
+
return false;
|
|
4747
4882
|
}
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4883
|
+
}
|
|
4884
|
+
function isBillingConfirmable(providerStatus, billingStatus) {
|
|
4885
|
+
return providerStatus === "success" && billingStatus === "committed";
|
|
4886
|
+
}
|
|
4887
|
+
|
|
4888
|
+
// src/compliance/errors.ts
|
|
4889
|
+
var CODE_TO_KEY = {
|
|
4890
|
+
// 通用 / token / scope (1-031-000-xxx)
|
|
4891
|
+
1031000001: "COMPLIANCE_UNAUTHORIZED",
|
|
4892
|
+
1031000002: "COMPLIANCE_TOKEN_INVALID",
|
|
4893
|
+
1031000003: "COMPLIANCE_TOKEN_INVALID",
|
|
4894
|
+
1031000004: "COMPLIANCE_TOKEN_INVALID",
|
|
4895
|
+
1031000005: "COMPLIANCE_TOKEN_INVALID",
|
|
4896
|
+
1031000006: "COMPLIANCE_TOKEN_INVALID",
|
|
4897
|
+
1031000007: "COMPLIANCE_TOKEN_INVALID",
|
|
4898
|
+
1031000008: "COMPLIANCE_TOKEN_INVALID",
|
|
4899
|
+
1031000009: "COMPLIANCE_TOKEN_INVALID",
|
|
4900
|
+
1031000010: "COMPLIANCE_TOKEN_INVALID",
|
|
4901
|
+
1031000011: "COMPLIANCE_TOKEN_INVALID",
|
|
4902
|
+
1031000012: "COMPLIANCE_INSUFFICIENT_SCOPE",
|
|
4903
|
+
1031000013: "COMPLIANCE_STEP_UP_REQUIRED",
|
|
4904
|
+
// Subject snapshot (1-031-001-xxx)
|
|
4905
|
+
1031001001: "SUBJECT_SNAPSHOT_NOT_FOUND",
|
|
4906
|
+
1031001002: "SUBJECT_SNAPSHOT_TENANT_MISMATCH",
|
|
4907
|
+
1031001003: "SUBJECT_SNAPSHOT_REQUIRED",
|
|
4908
|
+
// Evidence / Timestamp / Package / Report (1-031-002-xxx)
|
|
4909
|
+
1031002001: "EVIDENCE_ASSET_NOT_FOUND",
|
|
4910
|
+
1031002002: "SUBJECT_SNAPSHOT_TENANT_MISMATCH",
|
|
4911
|
+
1031002003: "EVIDENCE_ASSET_HASH_MISMATCH",
|
|
4912
|
+
1031002004: "EVIDENCE_ASSET_PAYLOAD_REQUIRED",
|
|
4913
|
+
1031002005: "EVIDENCE_ASSET_PAYLOAD_REQUIRED",
|
|
4914
|
+
1031002006: "TIMESTAMP_TOKEN_NOT_FOUND",
|
|
4915
|
+
1031002007: "TIMESTAMP_PROVIDER_FAILED",
|
|
4916
|
+
1031002008: "TIMESTAMP_PROVIDER_UNKNOWN",
|
|
4917
|
+
1031002009: "TIMESTAMP_LOCAL_VERIFY_FAILED",
|
|
4918
|
+
1031002010: "TIMESTAMP_PROVIDER_NOT_AVAILABLE",
|
|
4919
|
+
1031002011: "EVIDENCE_PACKAGE_NOT_FOUND",
|
|
4920
|
+
1031002012: "EVIDENCE_PACKAGE_TIMESTAMP_REQUIRED",
|
|
4921
|
+
1031002013: "EVIDENCE_PACKAGE_MANIFEST_HASH_MISMATCH",
|
|
4922
|
+
1031002014: "REPORT_NOT_FOUND",
|
|
4923
|
+
1031002015: "REPORT_ALREADY_PUBLISHED",
|
|
4924
|
+
1031002016: "REPORT_DRAFT_REQUIRED",
|
|
4925
|
+
1031002017: "EVIDENCE_VERIFY_TARGET_REQUIRED",
|
|
4926
|
+
1031002018: "EVIDENCE_VERIFY_TARGET_NOT_FOUND",
|
|
4927
|
+
// Provider request (1-031-003-xxx)
|
|
4928
|
+
1031003001: "PROVIDER_REQUEST_UNKNOWN_NO_RETRY",
|
|
4929
|
+
1031003002: "PROVIDER_CALLBACK_SOURCE_INVALID",
|
|
4930
|
+
1031003003: "PROVIDER_NOT_CONFIGURED",
|
|
4931
|
+
1031003010: "PROVIDER_REQUEST_NOT_FOUND",
|
|
4932
|
+
1031003011: "PROVIDER_REQUEST_IDEMPOTENCY_REQUIRED",
|
|
4933
|
+
1031003012: "PROVIDER_REQUEST_STATUS_NOT_TERMINAL",
|
|
4934
|
+
// Envelope (1-031-004-xxx)
|
|
4935
|
+
1031004001: "ENVELOPE_NOT_FOUND",
|
|
4936
|
+
1031004002: "ENVELOPE_TENANT_MISMATCH",
|
|
4937
|
+
1031004003: "ENVELOPE_STATE_NOT_ALLOWED",
|
|
4938
|
+
1031004004: "ENVELOPE_GATE_CLOSED",
|
|
4939
|
+
1031004005: "CONTRACT_NOT_FOUND",
|
|
4940
|
+
1031004006: "CONTRACT_HASH_MISMATCH",
|
|
4941
|
+
1031004007: "CONTRACT_NOT_FOUND",
|
|
4942
|
+
1031004008: "PROVIDER_AUTHORIZATION_NOT_CONFIRMED",
|
|
4943
|
+
1031004009: "PROVIDER_AUTHORIZATION_NOT_CONFIRMED",
|
|
4944
|
+
1031004010: "ENVELOPE_EVIDENCE_NOT_READY",
|
|
4945
|
+
// Seal approval / use (1-031-005-xxx)
|
|
4946
|
+
1031005001: "SEAL_ASSET_NOT_FOUND",
|
|
4947
|
+
1031005010: "SEAL_APPROVAL_NOT_FOUND",
|
|
4948
|
+
1031005011: "SEAL_APPROVAL_NOT_FOUND",
|
|
4949
|
+
1031005012: "SEAL_APPROVAL_STATE_NOT_APPROVED",
|
|
4950
|
+
1031005013: "SEAL_APPROVAL_EXPIRED",
|
|
4951
|
+
1031005014: "SEAL_APPROVAL_ALREADY_USED",
|
|
4952
|
+
1031005015: "SEAL_APPROVAL_NONCE_USED",
|
|
4953
|
+
1031005016: "SEAL_APPROVAL_SEAL_MISMATCH",
|
|
4954
|
+
1031005017: "SEAL_APPROVAL_LOCATION_MISMATCH",
|
|
4955
|
+
1031005018: "SEAL_APPROVAL_TRANSACTOR_MISMATCH",
|
|
4956
|
+
1031005019: "SEAL_APPROVAL_CONTRACT_HASH_MISMATCH",
|
|
4957
|
+
1031005020: "SEAL_APPROVAL_INVALID_TRANSITION",
|
|
4958
|
+
1031005030: "SEAL_USE_ALREADY_CONSUMED",
|
|
4959
|
+
// Billing (1-031-006-xxx)
|
|
4960
|
+
1031006004: "BILLING_COMMIT_REQUIRES_LOCAL_VERIFY",
|
|
4961
|
+
1031006005: "BILLING_COMMIT_REQUIRES_PROVIDER_SUCCESS",
|
|
4962
|
+
1031006007: "BILLING_CALLBACK_CANNOT_COMMIT",
|
|
4963
|
+
1031006008: "BILLING_PROVIDER_UNKNOWN_NOT_COMMITTABLE",
|
|
4964
|
+
1031006009: "BILLING_S2S_FORBIDDEN",
|
|
4965
|
+
// Audit (1-031-007-xxx)
|
|
4966
|
+
1031007011: "AUDIT_CHAIN_TAMPER_DETECTED"
|
|
4779
4967
|
};
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4968
|
+
var STEP_UP_KEYS = /* @__PURE__ */ new Set(["COMPLIANCE_STEP_UP_REQUIRED"]);
|
|
4969
|
+
var TERMINAL_KEYS = /* @__PURE__ */ new Set([
|
|
4970
|
+
"ENVELOPE_GATE_CLOSED",
|
|
4971
|
+
"PROVIDER_NOT_CONFIGURED",
|
|
4972
|
+
"PROVIDER_REQUEST_UNKNOWN_NO_RETRY",
|
|
4973
|
+
"BILLING_CALLBACK_CANNOT_COMMIT",
|
|
4974
|
+
"BILLING_COMMIT_REQUIRES_LOCAL_VERIFY",
|
|
4975
|
+
"BILLING_COMMIT_REQUIRES_PROVIDER_SUCCESS",
|
|
4976
|
+
"BILLING_PROVIDER_UNKNOWN_NOT_COMMITTABLE",
|
|
4977
|
+
"BILLING_S2S_FORBIDDEN",
|
|
4978
|
+
"SEAL_APPROVAL_NONCE_USED",
|
|
4979
|
+
"SEAL_APPROVAL_EXPIRED",
|
|
4980
|
+
"SEAL_APPROVAL_CONTRACT_HASH_MISMATCH",
|
|
4981
|
+
"SEAL_APPROVAL_SEAL_MISMATCH",
|
|
4982
|
+
"SEAL_APPROVAL_LOCATION_MISMATCH",
|
|
4983
|
+
"SEAL_APPROVAL_TRANSACTOR_MISMATCH",
|
|
4984
|
+
"SEAL_USE_ALREADY_CONSUMED",
|
|
4985
|
+
"CONTRACT_HASH_MISMATCH",
|
|
4986
|
+
"TIMESTAMP_LOCAL_VERIFY_FAILED",
|
|
4987
|
+
"EVIDENCE_PACKAGE_MANIFEST_HASH_MISMATCH",
|
|
4988
|
+
"AUDIT_CHAIN_TAMPER_DETECTED",
|
|
4989
|
+
"PROVIDER_REQUEST_NOT_FOUND",
|
|
4990
|
+
"EVIDENCE_ASSET_HASH_MISMATCH",
|
|
4991
|
+
"EVIDENCE_VERIFY_TARGET_NOT_FOUND",
|
|
4992
|
+
"REPORT_ALREADY_PUBLISHED"
|
|
4993
|
+
]);
|
|
4994
|
+
var RETRYABLE_KEYS = /* @__PURE__ */ new Set([]);
|
|
4995
|
+
function classifyComplianceError(err) {
|
|
4996
|
+
const key = CODE_TO_KEY[err.code] ?? "UNKNOWN_COMPLIANCE_ERROR";
|
|
4997
|
+
return {
|
|
4998
|
+
code: err.code,
|
|
4999
|
+
message: err.message,
|
|
5000
|
+
key,
|
|
5001
|
+
retryable: RETRYABLE_KEYS.has(key),
|
|
5002
|
+
terminal: TERMINAL_KEYS.has(key),
|
|
5003
|
+
stepUpRequired: STEP_UP_KEYS.has(key)
|
|
5004
|
+
};
|
|
5005
|
+
}
|
|
5006
|
+
function isComplianceBusinessError(err) {
|
|
5007
|
+
return err.code >= 1031e6 && err.code <= 1031999999;
|
|
5008
|
+
}
|
|
5009
|
+
|
|
5010
|
+
// src/compliance/client.ts
|
|
5011
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
5012
|
+
Object.defineProperty(Client.prototype, "compliance", {
|
|
5013
|
+
configurable: true,
|
|
5014
|
+
enumerable: false,
|
|
5015
|
+
get() {
|
|
5016
|
+
let existing = cache.get(this);
|
|
5017
|
+
if (!existing) {
|
|
5018
|
+
existing = new ComplianceClient(this);
|
|
5019
|
+
cache.set(this, existing);
|
|
5020
|
+
}
|
|
5021
|
+
return existing;
|
|
4783
5022
|
}
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
this.coefCacheData = [...resp.data];
|
|
4791
|
-
this.coefCacheTimeMs = Date.now();
|
|
4792
|
-
return resp.data;
|
|
5023
|
+
});
|
|
5024
|
+
var DEFAULT_POLL = {
|
|
5025
|
+
timeoutMs: 6e4,
|
|
5026
|
+
initialIntervalMs: 1e3,
|
|
5027
|
+
maxIntervalMs: 5e3,
|
|
5028
|
+
multiplier: 1.5
|
|
4793
5029
|
};
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
5030
|
+
var CompliancePollError = class extends Error {
|
|
5031
|
+
kind;
|
|
5032
|
+
lastInfo;
|
|
5033
|
+
constructor(message, kind, lastInfo) {
|
|
5034
|
+
super(message);
|
|
5035
|
+
this.name = "CompliancePollError";
|
|
5036
|
+
this.kind = kind;
|
|
5037
|
+
this.lastInfo = lastInfo;
|
|
5038
|
+
}
|
|
4797
5039
|
};
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
5040
|
+
var ComplianceClient = class {
|
|
5041
|
+
constructor(client) {
|
|
5042
|
+
this.client = client;
|
|
5043
|
+
}
|
|
5044
|
+
client;
|
|
5045
|
+
// =========================================================================
|
|
5046
|
+
// Evidence Asset
|
|
5047
|
+
// =========================================================================
|
|
5048
|
+
/** 创建证据资产(写)。 */
|
|
5049
|
+
createEvidenceAsset(req, opts = {}) {
|
|
5050
|
+
return this.write(
|
|
5051
|
+
"POST",
|
|
5052
|
+
"/compliance/evidence/assets",
|
|
5053
|
+
req,
|
|
5054
|
+
writeCtx(opts)
|
|
5055
|
+
);
|
|
5056
|
+
}
|
|
5057
|
+
/** 读 — 证据资产详情。 */
|
|
5058
|
+
getEvidenceAsset(id, signal) {
|
|
5059
|
+
return this.read(
|
|
5060
|
+
"GET",
|
|
5061
|
+
`/compliance/evidence/assets/${encodeURIComponent(id)}`,
|
|
5062
|
+
null,
|
|
5063
|
+
signal
|
|
5064
|
+
);
|
|
5065
|
+
}
|
|
5066
|
+
/**
|
|
5067
|
+
* 公开 verify。隐私边界:返回字段不含 PII / 合同原文 / storage / provider raw。
|
|
5068
|
+
*
|
|
5069
|
+
* 匿名可调用:未 login 时走匿名请求,不会抛 `not authorized, call login() first`。
|
|
5070
|
+
* 已 login / 已持有 token 时附带 `Authorization` 以保留审计上下文。public 端点不
|
|
5071
|
+
* 应要求认证 — 收到 401 直接抛 HTTPError,不触发 `forceRefresh`,也不做 refresh
|
|
5072
|
+
* replay。
|
|
5073
|
+
*/
|
|
5074
|
+
verifyEvidencePublic(params, signal) {
|
|
5075
|
+
const q = new URLSearchParams();
|
|
5076
|
+
if (params.evidenceNo) q.set("evidenceNo", params.evidenceNo);
|
|
5077
|
+
if (params.publicVerifyCode) q.set("publicVerifyCode", params.publicVerifyCode);
|
|
5078
|
+
const qs = q.toString();
|
|
5079
|
+
return this.publicRead(
|
|
5080
|
+
"GET",
|
|
5081
|
+
`/compliance/evidence/verify${qs ? "?" + qs : ""}`,
|
|
5082
|
+
signal
|
|
5083
|
+
);
|
|
5084
|
+
}
|
|
5085
|
+
// =========================================================================
|
|
5086
|
+
// Timestamp
|
|
5087
|
+
// =========================================================================
|
|
5088
|
+
/** 申请时间章(写)。SDK 永远不传 provider 字段。 */
|
|
5089
|
+
issueTimestamp(req, opts = {}) {
|
|
5090
|
+
return this.write("POST", "/compliance/timestamps", req, writeCtx(opts));
|
|
5091
|
+
}
|
|
5092
|
+
/** 给已有资产申请时间章。SDK 永远不传 provider 字段。 */
|
|
5093
|
+
issueTimestampForAsset(assetId, opts = {}) {
|
|
5094
|
+
return this.write(
|
|
5095
|
+
"POST",
|
|
5096
|
+
`/compliance/evidence/assets/${encodeURIComponent(assetId)}/timestamp`,
|
|
5097
|
+
null,
|
|
5098
|
+
writeCtx(opts)
|
|
5099
|
+
);
|
|
5100
|
+
}
|
|
5101
|
+
/** 读 — 时间章 token 详情。 */
|
|
5102
|
+
getTimestamp(id, signal) {
|
|
5103
|
+
return this.read(
|
|
5104
|
+
"GET",
|
|
5105
|
+
`/compliance/timestamps/${encodeURIComponent(id)}`,
|
|
5106
|
+
null,
|
|
5107
|
+
signal
|
|
5108
|
+
);
|
|
5109
|
+
}
|
|
5110
|
+
/** verify — 本地离线校验已申请的时间章。 */
|
|
5111
|
+
verifyTimestamp(req, opts = {}) {
|
|
5112
|
+
return this.write(
|
|
5113
|
+
"POST",
|
|
5114
|
+
"/compliance/timestamps/verify",
|
|
5115
|
+
req,
|
|
5116
|
+
writeCtx(opts)
|
|
5117
|
+
);
|
|
5118
|
+
}
|
|
5119
|
+
/**
|
|
5120
|
+
* 轮询到 VERIFIED 终态。
|
|
5121
|
+
* - VERIFIED → 返回 token;
|
|
5122
|
+
* - FAILED / LOCAL_VERIFY_FAILED → 抛 {@link CompliancePollError} kind='terminal_failure';
|
|
5123
|
+
* - UNKNOWN / RETRYING / PENDING → 继续轮询直到 timeout;
|
|
5124
|
+
* - timeout → 抛 {@link CompliancePollError} kind='timeout'。
|
|
5125
|
+
*/
|
|
5126
|
+
async waitForTimestampVerified(id, opts = {}) {
|
|
5127
|
+
return this.poll(
|
|
5128
|
+
() => this.getTimestamp(id, opts.signal),
|
|
5129
|
+
(t) => classifyTimestamp(t.verificationStatus),
|
|
5130
|
+
opts
|
|
5131
|
+
);
|
|
5132
|
+
}
|
|
5133
|
+
// =========================================================================
|
|
5134
|
+
// Evidence Package
|
|
5135
|
+
// =========================================================================
|
|
5136
|
+
/** 构建证据包(写)。 */
|
|
5137
|
+
buildEvidencePackage(assetId, timestampTokenId, opts = {}) {
|
|
5138
|
+
const tsParam = timestampTokenId == null ? "" : "?timestampTokenId=" + encodeURIComponent(timestampTokenId);
|
|
5139
|
+
return this.write(
|
|
5140
|
+
"POST",
|
|
5141
|
+
`/compliance/evidence/assets/${encodeURIComponent(assetId)}/packages${tsParam}`,
|
|
5142
|
+
null,
|
|
5143
|
+
writeCtx(opts)
|
|
5144
|
+
);
|
|
5145
|
+
}
|
|
5146
|
+
// =========================================================================
|
|
5147
|
+
// Report
|
|
5148
|
+
// =========================================================================
|
|
5149
|
+
/** 创建证据报告(写)。 */
|
|
5150
|
+
createReport(req, opts = {}) {
|
|
5151
|
+
return this.write("POST", "/compliance/reports", req, writeCtx(opts));
|
|
4806
5152
|
}
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
signal
|
|
4816
|
-
);
|
|
4817
|
-
return resp.data;
|
|
4818
|
-
};
|
|
4819
|
-
Client.prototype.buyTokenPackage = async function(packageID, payload, signal) {
|
|
4820
|
-
const body = payload ?? null;
|
|
4821
|
-
const resp = await this.doJSON(
|
|
4822
|
-
"POST",
|
|
4823
|
-
`/token-packages/${encodeURIComponent(packageID)}/buy`,
|
|
4824
|
-
body,
|
|
4825
|
-
signal
|
|
4826
|
-
);
|
|
4827
|
-
return resp.data;
|
|
4828
|
-
};
|
|
4829
|
-
Client.prototype.getOrderStatus = async function(orderID, signal) {
|
|
4830
|
-
const resp = await this.doJSON(
|
|
4831
|
-
"GET",
|
|
4832
|
-
`/token-packages/orders/${encodeURIComponent(orderID)}/status`,
|
|
4833
|
-
null,
|
|
4834
|
-
signal
|
|
4835
|
-
);
|
|
4836
|
-
return resp.data;
|
|
4837
|
-
};
|
|
4838
|
-
Client.prototype.listMyOrders = async function(signal) {
|
|
4839
|
-
const raw = await this.doJSON("GET", "/token-packages/my", null, signal);
|
|
4840
|
-
if (raw.data && typeof raw.data === "object" && "list" in raw.data) {
|
|
4841
|
-
const page = raw.data;
|
|
4842
|
-
if (Array.isArray(page.list)) return page.list;
|
|
5153
|
+
/** 读 — 报告详情。 */
|
|
5154
|
+
getReport(id, signal) {
|
|
5155
|
+
return this.read(
|
|
5156
|
+
"GET",
|
|
5157
|
+
`/compliance/reports/${encodeURIComponent(id)}`,
|
|
5158
|
+
null,
|
|
5159
|
+
signal
|
|
5160
|
+
);
|
|
4843
5161
|
}
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
5162
|
+
/**
|
|
5163
|
+
* 发布报告(写,step-up 必须)。
|
|
5164
|
+
*
|
|
5165
|
+
* `@status gated` — step-up 闸门未闭合前服务端会一致返回
|
|
5166
|
+
* `COMPLIANCE_STEP_UP_REQUIRED`(数值码 1031000013)。SDK 不会自动重试、不伪成功;
|
|
5167
|
+
* 调用方需要引导用户重新做 OAuth introspection 或重新登录后再次调用本方法
|
|
5168
|
+
*(使用同一 idempotency-key)。方法状态分级见 `docs/compliance.md` Method Status。
|
|
5169
|
+
*/
|
|
5170
|
+
publishReport(id, opts = {}) {
|
|
5171
|
+
return this.write(
|
|
5172
|
+
"POST",
|
|
5173
|
+
`/compliance/reports/${encodeURIComponent(id)}/publish`,
|
|
5174
|
+
null,
|
|
5175
|
+
writeCtx(opts)
|
|
5176
|
+
);
|
|
4856
5177
|
}
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
clearTimeout(t);
|
|
4870
|
-
signal.removeEventListener("abort", abortHandler);
|
|
4871
|
-
reject(new Error("aborted"));
|
|
4872
|
-
};
|
|
4873
|
-
signal.addEventListener("abort", abortHandler);
|
|
4874
|
-
}
|
|
4875
|
-
});
|
|
4876
|
-
}
|
|
4877
|
-
|
|
4878
|
-
// src/client/wallet.ts
|
|
4879
|
-
Client.prototype.getWalletStats = async function(signal) {
|
|
4880
|
-
const resp = await this.doJSON("GET", "/wallet/stats", null, signal);
|
|
4881
|
-
return resp.data;
|
|
4882
|
-
};
|
|
4883
|
-
Client.prototype.getWalletTransactions = async function(signal) {
|
|
4884
|
-
const resp = await this.doJSON(
|
|
4885
|
-
"GET",
|
|
4886
|
-
"/wallet/transactions",
|
|
4887
|
-
null,
|
|
4888
|
-
signal
|
|
4889
|
-
);
|
|
4890
|
-
return resp.data;
|
|
4891
|
-
};
|
|
4892
|
-
|
|
4893
|
-
// src/client/skills.ts
|
|
4894
|
-
init_types();
|
|
4895
|
-
Client.prototype.browseSkillStore = async function(query, signal) {
|
|
4896
|
-
const resp = await this.browseSkills(
|
|
4897
|
-
1,
|
|
4898
|
-
50,
|
|
4899
|
-
query.category ?? "",
|
|
4900
|
-
query.keyword ?? "",
|
|
4901
|
-
query.tag ?? "",
|
|
4902
|
-
"",
|
|
4903
|
-
signal
|
|
4904
|
-
);
|
|
4905
|
-
return resp.items;
|
|
4906
|
-
};
|
|
4907
|
-
Client.prototype.browseSkills = async function(page, pageSize, category, keyword, tag, source, signal) {
|
|
4908
|
-
const qv = new URLSearchParams();
|
|
4909
|
-
qv.set("page", String(page));
|
|
4910
|
-
qv.set("pageSize", String(pageSize));
|
|
4911
|
-
if (category) qv.set("category", category);
|
|
4912
|
-
if (keyword) qv.set("keyword", keyword);
|
|
4913
|
-
if (tag) qv.set("tag", tag);
|
|
4914
|
-
if (source) qv.set("source", source);
|
|
4915
|
-
const resp = await this.doPublicJSON(
|
|
4916
|
-
"GET",
|
|
4917
|
-
`/skill-store?${qv.toString()}`,
|
|
4918
|
-
null,
|
|
4919
|
-
signal
|
|
4920
|
-
);
|
|
4921
|
-
return resp.data;
|
|
4922
|
-
};
|
|
4923
|
-
Client.prototype.browseSkillsList = async function(page, pageSize, category, keyword, tag, source, signal) {
|
|
4924
|
-
const qv = new URLSearchParams();
|
|
4925
|
-
qv.set("page", String(page));
|
|
4926
|
-
qv.set("pageSize", String(pageSize));
|
|
4927
|
-
qv.set("fields", "minimal");
|
|
4928
|
-
if (category) qv.set("category", category);
|
|
4929
|
-
if (keyword) qv.set("keyword", keyword);
|
|
4930
|
-
if (tag) qv.set("tag", tag);
|
|
4931
|
-
if (source) qv.set("source", source);
|
|
4932
|
-
const resp = await this.doPublicJSON(
|
|
4933
|
-
"GET",
|
|
4934
|
-
`/skill-store?${qv.toString()}`,
|
|
4935
|
-
null,
|
|
4936
|
-
signal
|
|
4937
|
-
);
|
|
4938
|
-
return resp.data;
|
|
4939
|
-
};
|
|
4940
|
-
Client.prototype.getSkillDetail = async function(skillID, signal) {
|
|
4941
|
-
const resp = await this.doPublicJSON(
|
|
4942
|
-
"GET",
|
|
4943
|
-
`/skill-store/${encodeURIComponent(skillID)}`,
|
|
4944
|
-
null,
|
|
4945
|
-
signal
|
|
4946
|
-
);
|
|
4947
|
-
return resp.data;
|
|
4948
|
-
};
|
|
4949
|
-
Client.prototype.resolveSkill = async function(key, signal) {
|
|
4950
|
-
const resp = await this.doPublicJSON(
|
|
4951
|
-
"GET",
|
|
4952
|
-
`/skill-store/resolve/${encodeURIComponent(key)}`,
|
|
4953
|
-
null,
|
|
4954
|
-
signal
|
|
4955
|
-
);
|
|
4956
|
-
return resp.data;
|
|
4957
|
-
};
|
|
4958
|
-
Client.prototype.installSkill = async function(skillID, signal) {
|
|
4959
|
-
const resp = await this.doJSON(
|
|
4960
|
-
"POST",
|
|
4961
|
-
`/skill-store/${encodeURIComponent(skillID)}/install`,
|
|
4962
|
-
null,
|
|
4963
|
-
signal
|
|
4964
|
-
);
|
|
4965
|
-
return resp.data;
|
|
4966
|
-
};
|
|
4967
|
-
Client.prototype.downloadSkill = async function(skillID, signal) {
|
|
4968
|
-
const ctl = new AbortController();
|
|
4969
|
-
const timer = setTimeout(() => ctl.abort(), 5 * 60 * 1e3);
|
|
4970
|
-
let parentHandler;
|
|
4971
|
-
if (signal) {
|
|
4972
|
-
if (signal.aborted) ctl.abort();
|
|
4973
|
-
else {
|
|
4974
|
-
parentHandler = () => ctl.abort();
|
|
4975
|
-
signal.addEventListener("abort", parentHandler);
|
|
4976
|
-
}
|
|
5178
|
+
/**
|
|
5179
|
+
* 下载报告(读)。返回 {@link ReportDownload}:报告 hash + 资产 hash + 证据包 hash +
|
|
5180
|
+
* 时间章 serial/genTime,足以离线复核。
|
|
5181
|
+
* 不返回 bodyCanonicalJson / storage key / subject snapshot id。
|
|
5182
|
+
*/
|
|
5183
|
+
downloadReport(id, signal) {
|
|
5184
|
+
return this.read(
|
|
5185
|
+
"GET",
|
|
5186
|
+
`/compliance/reports/${encodeURIComponent(id)}/download`,
|
|
5187
|
+
null,
|
|
5188
|
+
signal
|
|
5189
|
+
);
|
|
4977
5190
|
}
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
resp = await this.fetchImpl(url, { method: "GET", headers, signal: ctl.signal });
|
|
4990
|
-
} catch (e) {
|
|
4991
|
-
throw classifyTransport(`GET /skill-store/${skillID}/download`, url, e);
|
|
4992
|
-
}
|
|
4993
|
-
if (resp.status === 429) {
|
|
4994
|
-
const bodyText = await readLimitedText(resp.body, maxErrorBodySize);
|
|
4995
|
-
throw new RateLimitError("\u533F\u540D\u4E0B\u8F7D\u5DF2\u8FBE\u9650\u5236", resp.headers.get("Retry-After") ?? "", bodyText);
|
|
4996
|
-
}
|
|
4997
|
-
if (!resp.ok) {
|
|
4998
|
-
const bodyBytes = await readLimited(resp.body, maxErrorBodySize);
|
|
4999
|
-
throw new Error(
|
|
5000
|
-
`download skill: ${parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers).message}`
|
|
5001
|
-
);
|
|
5002
|
-
}
|
|
5003
|
-
const data = await readLimited(resp.body, maxDownloadSize + 1);
|
|
5004
|
-
if (data.byteLength > maxDownloadSize) {
|
|
5005
|
-
throw new Error(`download skill: response exceeds ${maxDownloadSize >> 20}MB limit`);
|
|
5006
|
-
}
|
|
5007
|
-
let filename = "skill.zip";
|
|
5008
|
-
const cd = resp.headers.get("Content-Disposition");
|
|
5009
|
-
if (cd) {
|
|
5010
|
-
const idx = cd.indexOf("filename");
|
|
5011
|
-
if (idx !== -1) {
|
|
5012
|
-
const parts = cd.slice(idx).split("=", 2);
|
|
5013
|
-
if (parts.length === 2) {
|
|
5014
|
-
filename = parts[1].trim().replace(/^["' ]+|["' ]+$/g, "");
|
|
5015
|
-
}
|
|
5016
|
-
}
|
|
5017
|
-
}
|
|
5018
|
-
return { data, filename };
|
|
5019
|
-
} finally {
|
|
5020
|
-
clearTimeout(timer);
|
|
5021
|
-
if (parentHandler && signal) signal.removeEventListener("abort", parentHandler);
|
|
5191
|
+
// =========================================================================
|
|
5192
|
+
// Signing Envelope
|
|
5193
|
+
// =========================================================================
|
|
5194
|
+
/** 创建 envelope(写)。返回 envelope id。 */
|
|
5195
|
+
createSigningEnvelope(req, opts = {}) {
|
|
5196
|
+
return this.write(
|
|
5197
|
+
"POST",
|
|
5198
|
+
"/compliance/signing-envelopes",
|
|
5199
|
+
req,
|
|
5200
|
+
writeCtx(opts)
|
|
5201
|
+
);
|
|
5022
5202
|
}
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
if (signal) {
|
|
5032
|
-
if (signal.aborted) ctl.abort();
|
|
5033
|
-
else {
|
|
5034
|
-
parentHandler = () => ctl.abort();
|
|
5035
|
-
signal.addEventListener("abort", parentHandler);
|
|
5036
|
-
}
|
|
5203
|
+
/** 读 — envelope 详情。租户由服务端从 compliance token principal 推导。 */
|
|
5204
|
+
getSigningEnvelope(envelopeId, signal) {
|
|
5205
|
+
return this.read(
|
|
5206
|
+
"GET",
|
|
5207
|
+
`/compliance/signing-envelopes/${encodeURIComponent(envelopeId)}`,
|
|
5208
|
+
null,
|
|
5209
|
+
signal
|
|
5210
|
+
);
|
|
5037
5211
|
}
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
body: form,
|
|
5052
|
-
signal: ctl.signal
|
|
5053
|
-
});
|
|
5054
|
-
} catch (e) {
|
|
5055
|
-
throw classifyTransport("POST /skill-store/upload", url, e);
|
|
5056
|
-
}
|
|
5057
|
-
if (resp.status === 401 && !retried) {
|
|
5058
|
-
try {
|
|
5059
|
-
await resp.body?.cancel();
|
|
5060
|
-
} catch {
|
|
5061
|
-
}
|
|
5062
|
-
try {
|
|
5063
|
-
await c.forceRefresh(ctl.signal);
|
|
5064
|
-
} catch (refreshErr) {
|
|
5065
|
-
throw new Error(
|
|
5066
|
-
`upload: unauthorized and refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}`
|
|
5067
|
-
);
|
|
5068
|
-
}
|
|
5069
|
-
return uploadSkillInternal(c, zipData, scope, intent, true, signal);
|
|
5070
|
-
}
|
|
5071
|
-
if (resp.status < 200 || resp.status >= 300) {
|
|
5072
|
-
const bodyBytes = await readLimited(resp.body, maxErrorBodySize);
|
|
5073
|
-
throw new Error(
|
|
5074
|
-
`upload: ${parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers).message}`
|
|
5075
|
-
);
|
|
5076
|
-
}
|
|
5077
|
-
const text = await resp.text();
|
|
5078
|
-
const result = JSON.parse(text);
|
|
5079
|
-
return result.data.skill;
|
|
5080
|
-
} finally {
|
|
5081
|
-
clearTimeout(timer);
|
|
5082
|
-
if (parentHandler && signal) signal.removeEventListener("abort", parentHandler);
|
|
5212
|
+
/**
|
|
5213
|
+
* 正式签署(写,step-up 必须)。
|
|
5214
|
+
*
|
|
5215
|
+
* `@status gated` — 服务端闸门关闭时会一致返回 `ENVELOPE_GATE_CLOSED` (1031004004)。
|
|
5216
|
+
* SDK 不重试、不伪成功;调用方应该将该错误展示为"功能未开放"。
|
|
5217
|
+
*/
|
|
5218
|
+
signEnvelope(envelopeId, req, opts = {}) {
|
|
5219
|
+
return this.write(
|
|
5220
|
+
"POST",
|
|
5221
|
+
`/compliance/signing-envelopes/${encodeURIComponent(envelopeId)}/sign`,
|
|
5222
|
+
req,
|
|
5223
|
+
writeCtx(opts)
|
|
5224
|
+
);
|
|
5083
5225
|
}
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
};
|
|
5097
|
-
Client.prototype.getCertificationStatus = async function(skillID, signal) {
|
|
5098
|
-
const resp = await this.doJSON(
|
|
5099
|
-
"GET",
|
|
5100
|
-
`/skill-store/${encodeURIComponent(skillID)}/certification`,
|
|
5101
|
-
null,
|
|
5102
|
-
signal
|
|
5103
|
-
);
|
|
5104
|
-
return resp.data;
|
|
5105
|
-
};
|
|
5106
|
-
Client.prototype.generateSkill = async function(req, signal) {
|
|
5107
|
-
const resp = await this.doJSON(
|
|
5108
|
-
"POST",
|
|
5109
|
-
"/skill-generator/generate",
|
|
5110
|
-
req,
|
|
5111
|
-
signal
|
|
5112
|
-
);
|
|
5113
|
-
return resp.data;
|
|
5114
|
-
};
|
|
5115
|
-
Client.prototype.optimizeSkill = async function(req, signal) {
|
|
5116
|
-
const resp = await this.doJSON(
|
|
5117
|
-
"POST",
|
|
5118
|
-
"/skill-generator/optimize",
|
|
5119
|
-
req,
|
|
5120
|
-
signal
|
|
5121
|
-
);
|
|
5122
|
-
return resp.data;
|
|
5123
|
-
};
|
|
5124
|
-
Client.prototype.validateSkill = async function(skillName, signal) {
|
|
5125
|
-
await this.doJSON(
|
|
5126
|
-
"POST",
|
|
5127
|
-
"/skill-generator/validate",
|
|
5128
|
-
{ skillName },
|
|
5129
|
-
signal
|
|
5130
|
-
);
|
|
5131
|
-
};
|
|
5132
|
-
|
|
5133
|
-
// src/client/tools.ts
|
|
5134
|
-
Client.prototype.listTools = async function(signal) {
|
|
5135
|
-
const resp = await this.doJSON("GET", "/tools", null, signal);
|
|
5136
|
-
return resp.data.skills;
|
|
5137
|
-
};
|
|
5138
|
-
Client.prototype.getTool = async function(toolID, signal) {
|
|
5139
|
-
const resp = await this.doJSON(
|
|
5140
|
-
"GET",
|
|
5141
|
-
`/tools/${encodeURIComponent(toolID)}`,
|
|
5142
|
-
null,
|
|
5143
|
-
signal
|
|
5144
|
-
);
|
|
5145
|
-
return resp.data;
|
|
5146
|
-
};
|
|
5147
|
-
|
|
5148
|
-
// src/client/notifications.ts
|
|
5149
|
-
Client.prototype.listNotifications = async function(page, pageSize, typeFilter, signal) {
|
|
5150
|
-
let path = `/notifications?page=${page}&pageSize=${pageSize}`;
|
|
5151
|
-
if (typeFilter) path += `&type=${encodeURIComponent(typeFilter)}`;
|
|
5152
|
-
const resp = await this.doJSON("GET", path, null, signal);
|
|
5153
|
-
return resp.data;
|
|
5154
|
-
};
|
|
5155
|
-
Client.prototype.getUnreadCount = async function(signal) {
|
|
5156
|
-
const resp = await this.doJSON(
|
|
5157
|
-
"GET",
|
|
5158
|
-
"/notifications/unread-count",
|
|
5159
|
-
null,
|
|
5160
|
-
signal
|
|
5161
|
-
);
|
|
5162
|
-
return resp.data.unreadCount;
|
|
5163
|
-
};
|
|
5164
|
-
Client.prototype.markNotificationRead = async function(id, signal) {
|
|
5165
|
-
await this.doJSON(
|
|
5166
|
-
"PUT",
|
|
5167
|
-
`/notifications/${encodeURIComponent(id)}/read`,
|
|
5168
|
-
null,
|
|
5169
|
-
signal
|
|
5170
|
-
);
|
|
5171
|
-
};
|
|
5172
|
-
Client.prototype.markAllNotificationsRead = async function(signal) {
|
|
5173
|
-
await this.doJSON("PUT", "/notifications/read-all", null, signal);
|
|
5174
|
-
};
|
|
5175
|
-
Client.prototype.deleteNotification = async function(id, signal) {
|
|
5176
|
-
await this.doJSON(
|
|
5177
|
-
"DELETE",
|
|
5178
|
-
`/notifications/${encodeURIComponent(id)}`,
|
|
5179
|
-
null,
|
|
5180
|
-
signal
|
|
5181
|
-
);
|
|
5182
|
-
};
|
|
5183
|
-
Client.prototype.registerDevice = async function(reg, signal) {
|
|
5184
|
-
await this.doJSON("POST", "/devices/register", reg, signal);
|
|
5185
|
-
};
|
|
5186
|
-
Client.prototype.unregisterDevice = async function(token, signal) {
|
|
5187
|
-
await this.doJSON(
|
|
5188
|
-
"DELETE",
|
|
5189
|
-
`/devices/${encodeURIComponent(token)}`,
|
|
5190
|
-
null,
|
|
5191
|
-
signal
|
|
5192
|
-
);
|
|
5193
|
-
};
|
|
5194
|
-
Client.prototype.listNotificationPreferences = async function(signal) {
|
|
5195
|
-
const resp = await this.doJSON(
|
|
5196
|
-
"GET",
|
|
5197
|
-
"/notification-preferences",
|
|
5198
|
-
null,
|
|
5199
|
-
signal
|
|
5200
|
-
);
|
|
5201
|
-
return resp.data;
|
|
5202
|
-
};
|
|
5203
|
-
Client.prototype.updateNotificationPreference = async function(typeCode, pref, signal) {
|
|
5204
|
-
await this.doJSON(
|
|
5205
|
-
"PUT",
|
|
5206
|
-
`/notification-preferences/${encodeURIComponent(typeCode)}`,
|
|
5207
|
-
pref,
|
|
5208
|
-
signal
|
|
5209
|
-
);
|
|
5210
|
-
};
|
|
5211
|
-
|
|
5212
|
-
// src/sanitize-bridge.ts
|
|
5213
|
-
Client.prototype.setDefensiveSanitize = function(cfg) {
|
|
5214
|
-
this.defensiveCfg = cfg;
|
|
5215
|
-
};
|
|
5216
|
-
Client.prototype.setAutoStripEphemeralHistory = function(on) {
|
|
5217
|
-
this.autoStripEphemeral = on;
|
|
5218
|
-
};
|
|
5219
|
-
Client.prototype.applyRequestSanitizers = function(req) {
|
|
5220
|
-
const cfg = this.defensiveCfg;
|
|
5221
|
-
const strip = this.autoStripEphemeral;
|
|
5222
|
-
if (cfg == null && !strip) return;
|
|
5223
|
-
if (req.rawMessages != null) {
|
|
5224
|
-
let msgs;
|
|
5225
|
-
try {
|
|
5226
|
-
msgs = normalizeRawMessages(req.rawMessages);
|
|
5227
|
-
} catch (e) {
|
|
5228
|
-
throw new Error(
|
|
5229
|
-
`sanitize: normalize raw messages: ${e instanceof Error ? e.message : String(e)}`
|
|
5230
|
-
);
|
|
5231
|
-
}
|
|
5232
|
-
if (cfg) {
|
|
5233
|
-
msgs = sanitize(msgs, cfg);
|
|
5234
|
-
}
|
|
5235
|
-
if (strip) {
|
|
5236
|
-
msgs = stripEphemeral(msgs);
|
|
5237
|
-
}
|
|
5238
|
-
req.rawMessages = msgs;
|
|
5239
|
-
return;
|
|
5226
|
+
/**
|
|
5227
|
+
* 创建 H5 签署短链(写,step-up 必须)。
|
|
5228
|
+
*
|
|
5229
|
+
* `@status gated` — 同 {@link signEnvelope}:服务端闸门关闭时 SDK 不重试、不伪成功。
|
|
5230
|
+
*/
|
|
5231
|
+
createH5SigningUrl(envelopeId, req, opts = {}) {
|
|
5232
|
+
return this.write(
|
|
5233
|
+
"POST",
|
|
5234
|
+
`/compliance/signing-envelopes/${encodeURIComponent(envelopeId)}/h5-url`,
|
|
5235
|
+
req,
|
|
5236
|
+
writeCtx(opts)
|
|
5237
|
+
);
|
|
5240
5238
|
}
|
|
5241
|
-
|
|
5242
|
-
|
|
5239
|
+
/** 同步 provider 状态(写但只读对账,不创建新 provider 请求)。 */
|
|
5240
|
+
syncSigningEnvelopeStatus(envelopeId, opts = {}) {
|
|
5241
|
+
return this.write(
|
|
5242
|
+
"POST",
|
|
5243
|
+
`/compliance/signing-envelopes/${encodeURIComponent(envelopeId)}/sync-provider-status`,
|
|
5244
|
+
null,
|
|
5245
|
+
writeCtx(opts)
|
|
5246
|
+
);
|
|
5243
5247
|
}
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5248
|
+
// =========================================================================
|
|
5249
|
+
// Seal Approval
|
|
5250
|
+
// =========================================================================
|
|
5251
|
+
/**
|
|
5252
|
+
* 提交用印审批申请(写)。
|
|
5253
|
+
*
|
|
5254
|
+
* `@status production-ready` — 服务端以 `Idempotency-Key` + 业务请求指纹做重放保护:
|
|
5255
|
+
* 同 key + 同请求 → 返回原审批 id;同 key + 不同请求 → 拒绝复用幂等键。强烈建议调用方
|
|
5256
|
+
* 持久化 `idempotencyKey`,网络重试 / 任务恢复时复用,避免重复创建审批单。
|
|
5257
|
+
*/
|
|
5258
|
+
submitSealApproval(req, opts = {}) {
|
|
5259
|
+
return this.write(
|
|
5260
|
+
"POST",
|
|
5261
|
+
"/compliance/seal-approvals",
|
|
5262
|
+
req,
|
|
5263
|
+
writeCtx(opts)
|
|
5264
|
+
);
|
|
5252
5265
|
}
|
|
5253
|
-
|
|
5254
|
-
|
|
5266
|
+
/**
|
|
5267
|
+
* 审批通过用印申请(写,step-up 必须)。
|
|
5268
|
+
*
|
|
5269
|
+
* `@status gated` — step-up 未闭合前服务端会返回 `COMPLIANCE_STEP_UP_REQUIRED`。
|
|
5270
|
+
* SDK 不重试、不伪成功。方法状态分级见 `docs/compliance.md` Method Status。
|
|
5271
|
+
*/
|
|
5272
|
+
approveSealApproval(id, query, opts = {}) {
|
|
5273
|
+
const q = new URLSearchParams();
|
|
5274
|
+
if (query.expiresAt) q.set("expiresAt", query.expiresAt);
|
|
5275
|
+
if (query.note) q.set("note", query.note);
|
|
5276
|
+
const qs = q.toString();
|
|
5277
|
+
return this.write(
|
|
5278
|
+
"POST",
|
|
5279
|
+
`/compliance/seal-approvals/${encodeURIComponent(id)}/approve${qs ? "?" + qs : ""}`,
|
|
5280
|
+
null,
|
|
5281
|
+
writeCtx(opts)
|
|
5282
|
+
);
|
|
5255
5283
|
}
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
onDisconnect: cfg.onDisconnect ?? noop,
|
|
5267
|
-
topics: cfg.topics ?? [],
|
|
5268
|
-
reconnectMinMs: cfg.reconnectMinMs ?? 2e3,
|
|
5269
|
-
reconnectMaxMs: cfg.reconnectMaxMs ?? 6e4,
|
|
5270
|
-
autoReconnect: cfg.autoReconnect ?? true
|
|
5271
|
-
};
|
|
5272
|
-
let resolveDone;
|
|
5273
|
-
const done = new Promise((r) => {
|
|
5274
|
-
resolveDone = r;
|
|
5275
|
-
});
|
|
5276
|
-
const abort = new AbortController();
|
|
5277
|
-
if (signal) {
|
|
5278
|
-
if (signal.aborted) abort.abort();
|
|
5279
|
-
else signal.addEventListener("abort", () => abort.abort());
|
|
5284
|
+
rejectSealApproval(id, query, opts = {}) {
|
|
5285
|
+
const q = new URLSearchParams();
|
|
5286
|
+
if (query.reason) q.set("reason", query.reason);
|
|
5287
|
+
const qs = q.toString();
|
|
5288
|
+
return this.write(
|
|
5289
|
+
"POST",
|
|
5290
|
+
`/compliance/seal-approvals/${encodeURIComponent(id)}/reject${qs ? "?" + qs : ""}`,
|
|
5291
|
+
null,
|
|
5292
|
+
writeCtx(opts)
|
|
5293
|
+
);
|
|
5280
5294
|
}
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
void wsLoop(this, ws);
|
|
5292
|
-
};
|
|
5293
|
-
Client.prototype.disconnect = async function() {
|
|
5294
|
-
const ws = this.ws;
|
|
5295
|
-
this.ws = null;
|
|
5296
|
-
if (!ws) return;
|
|
5297
|
-
ws.abort.abort();
|
|
5298
|
-
ws.connected = false;
|
|
5299
|
-
if (ws.conn) {
|
|
5300
|
-
try {
|
|
5301
|
-
ws.conn.close(1e3, "");
|
|
5302
|
-
} catch {
|
|
5303
|
-
}
|
|
5295
|
+
cancelSealApproval(id, query, opts = {}) {
|
|
5296
|
+
const q = new URLSearchParams();
|
|
5297
|
+
if (query.reason) q.set("reason", query.reason);
|
|
5298
|
+
const qs = q.toString();
|
|
5299
|
+
return this.write(
|
|
5300
|
+
"POST",
|
|
5301
|
+
`/compliance/seal-approvals/${encodeURIComponent(id)}/cancel${qs ? "?" + qs : ""}`,
|
|
5302
|
+
null,
|
|
5303
|
+
writeCtx(opts)
|
|
5304
|
+
);
|
|
5304
5305
|
}
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
const ws = this.ws;
|
|
5312
|
-
if (!ws) return false;
|
|
5313
|
-
return ws.connected;
|
|
5314
|
-
};
|
|
5315
|
-
function wsURL(c) {
|
|
5316
|
-
const base = c.apiURL("/ws");
|
|
5317
|
-
return base.replace(/^http:\/\//, "ws://").replace(/^https:\/\//, "wss://");
|
|
5318
|
-
}
|
|
5319
|
-
function getWebSocketCtor() {
|
|
5320
|
-
const WSCtor = globalThis.WebSocket;
|
|
5321
|
-
if (!WSCtor) {
|
|
5322
|
-
throw new Error(
|
|
5323
|
-
'WebSocket not available \u2014 on Node \u226421 set globalThis.WebSocket = require("ws") before connect'
|
|
5306
|
+
listPendingSealApprovals(signal) {
|
|
5307
|
+
return this.read(
|
|
5308
|
+
"GET",
|
|
5309
|
+
"/compliance/seal-approvals/pending",
|
|
5310
|
+
null,
|
|
5311
|
+
signal
|
|
5324
5312
|
);
|
|
5325
5313
|
}
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
u.searchParams.set("token", token);
|
|
5334
|
-
let conn;
|
|
5335
|
-
try {
|
|
5336
|
-
conn = new WSCtor(u.toString());
|
|
5337
|
-
} catch (e) {
|
|
5338
|
-
throw new Error(`dial: ${e instanceof Error ? e.message : String(e)}`);
|
|
5314
|
+
getSealApproval(id, signal) {
|
|
5315
|
+
return this.read(
|
|
5316
|
+
"GET",
|
|
5317
|
+
`/compliance/seal-approvals/${encodeURIComponent(id)}`,
|
|
5318
|
+
null,
|
|
5319
|
+
signal
|
|
5320
|
+
);
|
|
5339
5321
|
}
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
}
|
|
5404
|
-
}, { once: true });
|
|
5405
|
-
});
|
|
5406
|
-
}
|
|
5407
|
-
async function wsLoop(c, ws) {
|
|
5408
|
-
try {
|
|
5409
|
-
while (true) {
|
|
5410
|
-
await wsReadLoop(ws);
|
|
5411
|
-
if (ws.abort.signal.aborted) return;
|
|
5412
|
-
if (ws.conn) {
|
|
5413
|
-
try {
|
|
5414
|
-
ws.conn.close();
|
|
5415
|
-
} catch {
|
|
5416
|
-
}
|
|
5417
|
-
ws.conn = null;
|
|
5418
|
-
}
|
|
5419
|
-
ws.connected = false;
|
|
5420
|
-
if (!ws.cfg.autoReconnect) return;
|
|
5421
|
-
let delay = ws.cfg.reconnectMinMs;
|
|
5422
|
-
while (true) {
|
|
5423
|
-
if (ws.abort.signal.aborted) return;
|
|
5424
|
-
await sleepWithSignal2(delay, ws.abort.signal).catch(() => {
|
|
5425
|
-
});
|
|
5426
|
-
if (ws.abort.signal.aborted) return;
|
|
5427
|
-
console.log(`[acosmi-sdk] websocket reconnecting (delay=${delay}ms)...`);
|
|
5428
|
-
try {
|
|
5429
|
-
await wsConnectOnce(c, ws);
|
|
5430
|
-
break;
|
|
5431
|
-
} catch (err) {
|
|
5432
|
-
console.log(`[acosmi-sdk] websocket reconnect failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
5433
|
-
delay = Math.min(delay * 2, ws.cfg.reconnectMaxMs);
|
|
5434
|
-
}
|
|
5435
|
-
}
|
|
5322
|
+
// =========================================================================
|
|
5323
|
+
// Provider Request (read-only)
|
|
5324
|
+
// =========================================================================
|
|
5325
|
+
getProviderRequest(id, signal) {
|
|
5326
|
+
return this.read(
|
|
5327
|
+
"GET",
|
|
5328
|
+
`/compliance/provider-requests/${encodeURIComponent(id)}`,
|
|
5329
|
+
null,
|
|
5330
|
+
signal
|
|
5331
|
+
);
|
|
5332
|
+
}
|
|
5333
|
+
/**
|
|
5334
|
+
* 轮询 provider request 到 SUCCESS / FAILED 终态。
|
|
5335
|
+
* - SUCCESS / FAILED → 返回最后视图;
|
|
5336
|
+
* - UNKNOWN / RETRYING / PENDING → 继续轮询;
|
|
5337
|
+
* - timeout → 抛 {@link CompliancePollError} kind='timeout',不自动重发原 provider 请求。
|
|
5338
|
+
*
|
|
5339
|
+
* SUCCESS 不代表 billing 已 commit;调用方仍需通过业务侧 envelope / asset 终态判断。
|
|
5340
|
+
*/
|
|
5341
|
+
async waitForProviderRequestTerminal(id, opts = {}) {
|
|
5342
|
+
return this.poll(
|
|
5343
|
+
() => this.getProviderRequest(id, opts.signal),
|
|
5344
|
+
(v) => classifyProviderStatus(v.status),
|
|
5345
|
+
opts
|
|
5346
|
+
);
|
|
5347
|
+
}
|
|
5348
|
+
// =========================================================================
|
|
5349
|
+
// Error classification (re-export for convenience)
|
|
5350
|
+
// =========================================================================
|
|
5351
|
+
classifyError(err) {
|
|
5352
|
+
if (!isBusinessErrorLike(err)) return null;
|
|
5353
|
+
if (!isComplianceBusinessError(err)) return null;
|
|
5354
|
+
return classifyComplianceError(err);
|
|
5355
|
+
}
|
|
5356
|
+
// =========================================================================
|
|
5357
|
+
// Internal helpers
|
|
5358
|
+
// =========================================================================
|
|
5359
|
+
/**
|
|
5360
|
+
* 读路径:GET / 公开 verify。允许 401 单次刷新后重放(GET 幂等安全)。
|
|
5361
|
+
* 与 client.doJSONFullInternal 行为一致;不复用其代码因为 base URL 不同。
|
|
5362
|
+
*/
|
|
5363
|
+
async read(method, path, body, signal, extraHeaders = {}) {
|
|
5364
|
+
return this.executeJson(method, path, body, signal, {
|
|
5365
|
+
retryOn401: true,
|
|
5366
|
+
extraHeaders
|
|
5367
|
+
});
|
|
5368
|
+
}
|
|
5369
|
+
/**
|
|
5370
|
+
* 公开读路径:public verify。
|
|
5371
|
+
*
|
|
5372
|
+
* 与 {@link read} 的区别 — public 端点不应要求认证:
|
|
5373
|
+
* - 无 token 时匿名请求:ensureToken 抛 `not authorized` 会被吞掉,继续匿名发送。
|
|
5374
|
+
* - 有 token 时附带 `Authorization`,保留后端审计上下文。
|
|
5375
|
+
* - 不做 401 refresh replay:401 直接抛 HTTPError,不触发 `forceRefresh`。
|
|
5376
|
+
*
|
|
5377
|
+
* URL 仍走 `client.complianceURL(path)`,不复用 `/api/v4`;底层复用
|
|
5378
|
+
* `client.doRequest`,不新增 fetch/axios 直连。
|
|
5379
|
+
*/
|
|
5380
|
+
async publicRead(method, path, signal) {
|
|
5381
|
+
let token = "";
|
|
5382
|
+
try {
|
|
5383
|
+
token = await this.client.ensureToken(signal);
|
|
5384
|
+
} catch {
|
|
5436
5385
|
}
|
|
5437
|
-
|
|
5438
|
-
|
|
5386
|
+
const url = this.client.complianceURL(path);
|
|
5387
|
+
const headers = { Accept: "application/json" };
|
|
5388
|
+
if (token) headers.Authorization = `Bearer ${token}`;
|
|
5389
|
+
const resp = await this.client.doRequest({ method, url, headers }, signal);
|
|
5390
|
+
if (resp.status < 200 || resp.status >= 300) {
|
|
5391
|
+
const bodyBytes = resp.body ? await readLimited(resp.body, maxErrorBodySize) : new Uint8Array();
|
|
5392
|
+
throw parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
5393
|
+
}
|
|
5394
|
+
const text = await resp.text();
|
|
5395
|
+
if (!text) return void 0;
|
|
5396
|
+
const parsed = JSON.parse(text);
|
|
5397
|
+
const bizErr = apiResponseBusinessError(parsed);
|
|
5398
|
+
if (bizErr) throw bizErr;
|
|
5399
|
+
return parsed.data;
|
|
5439
5400
|
}
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5401
|
+
/**
|
|
5402
|
+
* 写路径:POST。
|
|
5403
|
+
* - 发送前 ensureToken 一次确保 token fresh。
|
|
5404
|
+
* - 不自动 401 重放:401 → 抛 HTTPError;调用方必须自己刷新 token 后用同一
|
|
5405
|
+
* idempotency-key 重新发起,避免 provider 侧重复请求。
|
|
5406
|
+
* - 不走 doRequestWithRetry:写操作不允许 5xx/timeout 自动重试。
|
|
5407
|
+
*/
|
|
5408
|
+
async write(method, path, body, ctx) {
|
|
5409
|
+
const headers = { ...ctx.extraHeaders ?? {} };
|
|
5410
|
+
if (ctx.idempotencyKey) headers["Idempotency-Key"] = ctx.idempotencyKey;
|
|
5411
|
+
return this.executeJson(method, path, body, ctx.signal, {
|
|
5412
|
+
retryOn401: false,
|
|
5413
|
+
extraHeaders: headers
|
|
5414
|
+
});
|
|
5415
|
+
}
|
|
5416
|
+
async executeJson(method, path, body, signal, opts, retried = false) {
|
|
5417
|
+
const token = await this.client.ensureToken(signal);
|
|
5418
|
+
const url = this.client.complianceURL(path);
|
|
5419
|
+
const headers = {
|
|
5420
|
+
Authorization: `Bearer ${token}`,
|
|
5421
|
+
Accept: "application/json",
|
|
5422
|
+
...opts.extraHeaders
|
|
5455
5423
|
};
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5424
|
+
let bodyStr;
|
|
5425
|
+
if (body != null) {
|
|
5426
|
+
bodyStr = typeof body === "string" ? body : JSON.stringify(body);
|
|
5427
|
+
headers["Content-Type"] = "application/json";
|
|
5428
|
+
}
|
|
5429
|
+
const resp = await this.client.doRequest({ method, url, headers, body: bodyStr }, signal);
|
|
5430
|
+
if (resp.status === 401 && opts.retryOn401 && !retried) {
|
|
5460
5431
|
try {
|
|
5461
|
-
|
|
5432
|
+
await resp.body?.cancel();
|
|
5462
5433
|
} catch {
|
|
5463
5434
|
}
|
|
5464
|
-
|
|
5435
|
+
await this.client.forceRefresh(signal);
|
|
5436
|
+
return this.executeJson(method, path, body, signal, opts, true);
|
|
5437
|
+
}
|
|
5438
|
+
if (resp.status < 200 || resp.status >= 300) {
|
|
5439
|
+
const bodyBytes = resp.body ? await readLimited(resp.body, maxErrorBodySize) : new Uint8Array();
|
|
5440
|
+
throw parseHTTPErrorWithHeader(resp.status, bodyBytes, resp.headers);
|
|
5441
|
+
}
|
|
5442
|
+
const text = await resp.text();
|
|
5443
|
+
if (!text) return void 0;
|
|
5444
|
+
const parsed = JSON.parse(text);
|
|
5445
|
+
const bizErr = apiResponseBusinessError(parsed);
|
|
5446
|
+
if (bizErr) throw bizErr;
|
|
5447
|
+
return parsed.data;
|
|
5448
|
+
}
|
|
5449
|
+
async poll(fetcher, classify, opts) {
|
|
5450
|
+
const cfg = {
|
|
5451
|
+
timeoutMs: opts.timeoutMs ?? DEFAULT_POLL.timeoutMs,
|
|
5452
|
+
initialIntervalMs: opts.initialIntervalMs ?? DEFAULT_POLL.initialIntervalMs,
|
|
5453
|
+
maxIntervalMs: opts.maxIntervalMs ?? DEFAULT_POLL.maxIntervalMs,
|
|
5454
|
+
multiplier: opts.multiplier ?? DEFAULT_POLL.multiplier
|
|
5465
5455
|
};
|
|
5466
|
-
const
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
} catch {
|
|
5456
|
+
const deadline = Date.now() + cfg.timeoutMs;
|
|
5457
|
+
let interval = cfg.initialIntervalMs;
|
|
5458
|
+
let lastValue;
|
|
5459
|
+
while (Date.now() < deadline) {
|
|
5460
|
+
if (opts.signal?.aborted) {
|
|
5461
|
+
throw new CompliancePollError("compliance poll aborted", "unknown");
|
|
5473
5462
|
}
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
} catch {
|
|
5463
|
+
lastValue = await fetcher();
|
|
5464
|
+
const decision = classify(lastValue);
|
|
5465
|
+
if (decision === "done") return lastValue;
|
|
5466
|
+
if (decision === "failed") {
|
|
5467
|
+
throw new CompliancePollError(
|
|
5468
|
+
"compliance poll observed terminal failure",
|
|
5469
|
+
"terminal_failure"
|
|
5470
|
+
);
|
|
5483
5471
|
}
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
try {
|
|
5489
|
-
conn.close();
|
|
5490
|
-
} catch {
|
|
5491
|
-
}
|
|
5492
|
-
},
|
|
5493
|
-
{ once: true }
|
|
5494
|
-
);
|
|
5472
|
+
const sleepMs = Math.min(interval, deadline - Date.now());
|
|
5473
|
+
if (sleepMs <= 0) break;
|
|
5474
|
+
await sleep2(sleepMs, opts.signal);
|
|
5475
|
+
interval = Math.min(Math.floor(interval * cfg.multiplier), cfg.maxIntervalMs);
|
|
5495
5476
|
}
|
|
5496
|
-
|
|
5477
|
+
throw new CompliancePollError("compliance poll timed out", "timeout");
|
|
5478
|
+
}
|
|
5479
|
+
};
|
|
5480
|
+
function classifyTimestamp(status) {
|
|
5481
|
+
switch (status) {
|
|
5482
|
+
case "VERIFIED":
|
|
5483
|
+
return "done";
|
|
5484
|
+
case "FAILED":
|
|
5485
|
+
case "LOCAL_VERIFY_FAILED":
|
|
5486
|
+
return "failed";
|
|
5487
|
+
case "PENDING":
|
|
5488
|
+
case "UNKNOWN":
|
|
5489
|
+
case "RETRYING":
|
|
5490
|
+
default:
|
|
5491
|
+
return "continue";
|
|
5492
|
+
}
|
|
5497
5493
|
}
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5494
|
+
function classifyProviderStatus(status) {
|
|
5495
|
+
switch (status) {
|
|
5496
|
+
case "SUCCESS":
|
|
5497
|
+
return "done";
|
|
5498
|
+
case "FAILED":
|
|
5499
|
+
return "failed";
|
|
5500
|
+
case "PENDING":
|
|
5501
|
+
case "UNKNOWN":
|
|
5502
|
+
case "RETRYING":
|
|
5503
|
+
default:
|
|
5504
|
+
return "continue";
|
|
5505
|
+
}
|
|
5506
|
+
}
|
|
5507
|
+
function writeCtx(opts, extraHeaders = {}) {
|
|
5508
|
+
return {
|
|
5509
|
+
idempotencyKey: opts.idempotencyKey,
|
|
5510
|
+
signal: opts.signal,
|
|
5511
|
+
extraHeaders
|
|
5512
|
+
};
|
|
5513
|
+
}
|
|
5514
|
+
function isBusinessErrorLike(err) {
|
|
5515
|
+
if (err == null || typeof err !== "object") return false;
|
|
5516
|
+
return typeof err.code === "number";
|
|
5517
|
+
}
|
|
5518
|
+
function sleep2(ms, signal) {
|
|
5501
5519
|
return new Promise((resolve, reject) => {
|
|
5502
|
-
|
|
5503
|
-
|
|
5520
|
+
if (signal?.aborted) {
|
|
5521
|
+
reject(new CompliancePollError("compliance poll aborted", "unknown"));
|
|
5522
|
+
return;
|
|
5523
|
+
}
|
|
5524
|
+
const timer = setTimeout(() => {
|
|
5525
|
+
signal?.removeEventListener("abort", onAbort);
|
|
5504
5526
|
resolve();
|
|
5505
5527
|
}, ms);
|
|
5506
|
-
const
|
|
5507
|
-
clearTimeout(
|
|
5508
|
-
signal
|
|
5509
|
-
reject(new
|
|
5528
|
+
const onAbort = () => {
|
|
5529
|
+
clearTimeout(timer);
|
|
5530
|
+
signal?.removeEventListener("abort", onAbort);
|
|
5531
|
+
reject(new CompliancePollError("compliance poll aborted", "unknown"));
|
|
5510
5532
|
};
|
|
5511
|
-
signal
|
|
5533
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
5512
5534
|
});
|
|
5513
5535
|
}
|
|
5514
5536
|
|
|
5515
|
-
// src/bug-report.ts
|
|
5537
|
+
// src/support/bug-report.ts
|
|
5516
5538
|
Client.prototype.submitBugReport = async function(reportData, signal) {
|
|
5517
5539
|
if (reportData == null) {
|
|
5518
5540
|
throw new Error("acosmi: reportData required");
|