@openclaw/ai 2026.8.1-beta.1 → 2026.8.1-beta.3
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/dist/{anthropic-CE-7SkF6.mjs → anthropic-B8KwTtlb.mjs} +62 -37
- package/dist/{anthropic-SrGtwsJu.d.mts → anthropic-BECQCNdF.d.mts} +0 -2
- package/dist/{src-QkygScBs.mjs → anthropic-BQXQudmA.mjs} +0 -2
- package/dist/{anthropic-usage-Ma4iX6uG.mjs → anthropic-compaction-replay-4Zx7-aCr.mjs} +225 -103
- package/dist/anthropic-payload-policy-CSx7MoKH.d.mts +50 -0
- package/dist/{api-registry-EpJoVwM1.d.mts → api-registry-DFxSnFqG.d.mts} +1 -1
- package/dist/{azure-openai-responses-Cc_kasye.mjs → azure-openai-responses-Aa4mVcYG.mjs} +23 -29
- package/dist/diagnostics.d.mts +24 -1
- package/dist/diagnostics.mjs +2 -1
- package/dist/event-stream-BVVgDSdq.d.mts +1 -0
- package/dist/{event-stream-DRmDMRHH.d.mts → event-stream-D91-ohD_.d.mts} +3 -1
- package/dist/{event-stream-CEV9t6da.mjs → event-stream-uSMZJ3FA.mjs} +16 -3
- package/dist/event-stream.d.mts +1 -1
- package/dist/event-stream.mjs +1 -1
- package/dist/{google-shared-Cq2UKx1l.mjs → google-shared-M1dl64nz.mjs} +17 -19
- package/dist/google-thinking-level-C-V3tecN.mjs +9 -0
- package/dist/{google-vertex-CusxWzvE.mjs → google-vertex-DCJHM_a5.mjs} +5 -4
- package/dist/{google-CGQu21aw.mjs → google-yDRnipeq.mjs} +4 -4
- package/dist/host-DF_yxOsA.mjs +477 -0
- package/dist/{host-Dn4_SZI2.d.mts → host-DJq_FGcz.d.mts} +13 -8
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +7 -5
- package/dist/internal/anthropic.d.mts +21 -7
- package/dist/internal/anthropic.mjs +5 -5
- package/dist/internal/openai-responses-payload-policy.d.mts +3 -0
- package/dist/internal/openai-responses-payload-policy.mjs +3 -0
- package/dist/internal/openai.d.mts +6 -6
- package/dist/internal/openai.mjs +9 -7
- package/dist/internal/runtime.d.mts +19 -5
- package/dist/internal/runtime.mjs +85 -72
- package/dist/internal/shared.d.mts +17 -8
- package/dist/internal/shared.mjs +4 -5
- package/dist/{json-parse-BvXNt1-7.mjs → json-parse-CDnesDM_.mjs} +4 -6
- package/dist/{mistral-Dx6VzNjf.mjs → mistral-D6hRXI7A.mjs} +67 -72
- package/dist/{number-coercion-1Miyb5MO.mjs → number-coercion-H9qHik3g.mjs} +7 -2
- package/dist/openai-chatgpt-jwt-KWcgd0d_.mjs +19 -0
- package/dist/{openai-chatgpt-responses-SC9m0FSf.mjs → openai-chatgpt-responses-C339VIfT.mjs} +235 -146
- package/dist/{openai-completions-BaIpl93j.mjs → openai-completions-D88orSJ9.mjs} +88 -67
- package/dist/openai-completions-compat-B0KTleXp.d.mts +43 -0
- package/dist/{openai-responses-Bdx3V_Yu.mjs → openai-responses-BXEcr-Tp.mjs} +17 -24
- package/dist/openai-responses-contracts-CD75pQ0m.d.mts +68 -0
- package/dist/openai-responses-contracts-DvILoqBk.mjs +247 -0
- package/dist/openai-responses-payload-policy-BDo8CQsx.mjs +208 -0
- package/dist/openai-responses-payload-policy-CNGFT9zr.d.mts +41 -0
- package/dist/{openai-responses-prompt-observer-internal-DDZPxRfr.mjs → openai-responses-prompt-observer-internal-BG-1AsBI.mjs} +2 -3
- package/dist/{openai-responses-stream-internal-Bl8YyVtF.mjs → openai-responses-shared-Cvt5MgEm.mjs} +1287 -1039
- package/dist/{openai-reasoning-compat-DKebnIBL.mjs → openai-stop-reason-9OONKyAm.mjs} +222 -180
- package/dist/{openai-transport-shared-Cipt7egQ.mjs → openai-tool-projection-CHGLt03m.mjs} +239 -128
- package/dist/provider-error-C8mBRJDl.mjs +424 -0
- package/dist/provider-error-CzNw4BWX.d.mts +12 -0
- package/dist/provider-options-AvldWZt8.mjs +21 -0
- package/dist/{provider-options-C5kYML7i.d.mts → provider-options-Cc5ZQ6Aa.d.mts} +19 -3
- package/dist/provider-transcript-transform--gtf0ZbR.mjs +32 -0
- package/dist/provider-types.d.mts +31 -0
- package/dist/provider-types.mjs +8 -0
- package/dist/providers.d.mts +1 -1
- package/dist/providers.mjs +17 -19
- package/dist/{reasoning-tag-text-partitioner-CGDyLWUR.mjs → reasoning-tag-text-partitioner-5ygO2rZc.mjs} +17 -8
- package/dist/record-coerce-DdXsgUd_.mjs +23 -0
- package/dist/{model-utils-Dau5dlgm.mjs → sanitize-unicode-BP7HLLZn.mjs} +28 -2
- package/dist/session-resources-CkR4WWy1.mjs +21 -0
- package/dist/simple-options-oqsXB6U3.mjs +450 -0
- package/dist/src-D2H6yKkH.mjs +2 -0
- package/dist/{stream-first-event-timeout-BIBomOGq.mjs → stream-first-event-timeout-MK28puvq.mjs} +2 -2
- package/dist/string-coerce-fsri9iCu.mjs +34 -0
- package/dist/{tool-schema-json-projection-B1b-XCn5.mjs → tool-schema-json-projection-FEr-jOoZ.mjs} +20 -13
- package/dist/transport-utils-Bv0FHkd0.mjs +138 -0
- package/dist/transports.d.mts +199 -209
- package/dist/transports.mjs +1842 -1364
- package/dist/types-BDdaOVi2.mjs +6 -0
- package/dist/{types-CH7ReIcU.d.mts → types-DTAP49HF.d.mts} +35 -2
- package/dist/types.d.mts +5 -5
- package/dist/types.mjs +6 -4
- package/dist/utf16-slice-CvGodqok.mjs +29 -0
- package/dist/{validation-DAa_yFOM.mjs → validation-B61OhAio.mjs} +6 -6
- package/dist/{validation-CcPcuEbR.d.mts → validation-DYNNrU9u.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +15 -1
- package/dist/host-Bl7Kgddo.mjs +0 -407
- package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +0 -39
- package/dist/openai-responses-contracts-BBKBfAqR.d.mts +0 -116
- package/dist/openai-responses-shared-CCyMvg7M.mjs +0 -403
- package/dist/provider-error-DI0Ts28U.mjs +0 -47
- package/dist/sanitize-unicode-DT5o51ur.mjs +0 -26
- package/dist/tool-result-text-Dvkp2Dus.mjs +0 -274
- package/dist/transform-messages-DfjpNXNQ.mjs +0 -2
- package/dist/transport-stream-shared-CPNv7A3r.mjs +0 -297
package/dist/providers.mjs
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { t as AssistantMessageEventStream } from "./event-stream-
|
|
1
|
+
import { t as AssistantMessageEventStream } from "./event-stream-uSMZJ3FA.mjs";
|
|
2
|
+
import { n as projectProviderError } from "./provider-error-C8mBRJDl.mjs";
|
|
2
3
|
import { n as clampOpenAIPromptCacheKey, t as OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH } from "./openai-prompt-cache-mZTCdRPo.mjs";
|
|
3
4
|
//#region packages/ai/src/providers/register-builtins.ts
|
|
4
5
|
/** Source id used for built-in API provider registrations. */
|
|
5
6
|
const BUILT_IN_API_PROVIDER_SOURCE_ID = "core:built-in";
|
|
6
|
-
function forwardStream(target, source) {
|
|
7
|
-
(
|
|
8
|
-
|
|
9
|
-
target.end();
|
|
10
|
-
})();
|
|
7
|
+
async function forwardStream(target, source) {
|
|
8
|
+
for await (const event of source) target.push(event);
|
|
9
|
+
target.end();
|
|
11
10
|
}
|
|
12
|
-
function createLazyLoadErrorMessage(model, error) {
|
|
11
|
+
function createLazyLoadErrorMessage(model, error, signal) {
|
|
13
12
|
return {
|
|
14
13
|
role: "assistant",
|
|
15
14
|
content: [],
|
|
@@ -30,8 +29,7 @@ function createLazyLoadErrorMessage(model, error) {
|
|
|
30
29
|
total: 0
|
|
31
30
|
}
|
|
32
31
|
},
|
|
33
|
-
|
|
34
|
-
errorMessage: error instanceof Error ? error.message : String(error),
|
|
32
|
+
...projectProviderError(error, signal),
|
|
35
33
|
timestamp: Date.now()
|
|
36
34
|
};
|
|
37
35
|
}
|
|
@@ -39,10 +37,10 @@ function createLazyStream(load, select) {
|
|
|
39
37
|
return (model, context, options) => {
|
|
40
38
|
const outer = new AssistantMessageEventStream();
|
|
41
39
|
load().then((streams) => forwardStream(outer, select(streams)(model, context, options))).catch((error) => {
|
|
42
|
-
const message = createLazyLoadErrorMessage(model, error);
|
|
40
|
+
const message = createLazyLoadErrorMessage(model, error, options?.signal);
|
|
43
41
|
outer.push({
|
|
44
42
|
type: "error",
|
|
45
|
-
reason:
|
|
43
|
+
reason: message.stopReason,
|
|
46
44
|
error: message
|
|
47
45
|
});
|
|
48
46
|
outer.end(message);
|
|
@@ -64,35 +62,35 @@ function createLazyRegistration(api, importModule, select) {
|
|
|
64
62
|
};
|
|
65
63
|
}
|
|
66
64
|
const registerBuiltIns = [
|
|
67
|
-
createLazyRegistration("anthropic-messages", () => import("./anthropic-
|
|
65
|
+
createLazyRegistration("anthropic-messages", () => import("./anthropic-B8KwTtlb.mjs").then((n) => n.t), (module) => ({
|
|
68
66
|
stream: module.streamAnthropic,
|
|
69
67
|
streamSimple: module.streamSimpleAnthropic
|
|
70
68
|
})),
|
|
71
|
-
createLazyRegistration("openai-completions", () => import("./openai-completions-
|
|
69
|
+
createLazyRegistration("openai-completions", () => import("./openai-completions-D88orSJ9.mjs").then((n) => n.t), (module) => ({
|
|
72
70
|
stream: module.streamOpenAICompletions,
|
|
73
71
|
streamSimple: module.streamSimpleOpenAICompletions
|
|
74
72
|
})),
|
|
75
|
-
createLazyRegistration("mistral-conversations", () => import("./mistral-
|
|
73
|
+
createLazyRegistration("mistral-conversations", () => import("./mistral-D6hRXI7A.mjs"), (module) => ({
|
|
76
74
|
stream: module.streamMistral,
|
|
77
75
|
streamSimple: module.streamSimpleMistral
|
|
78
76
|
})),
|
|
79
|
-
createLazyRegistration("openai-responses", () => import("./openai-responses-
|
|
77
|
+
createLazyRegistration("openai-responses", () => import("./openai-responses-BXEcr-Tp.mjs").then((n) => n.t), (module) => ({
|
|
80
78
|
stream: module.streamOpenAIResponses,
|
|
81
79
|
streamSimple: module.streamSimpleOpenAIResponses
|
|
82
80
|
})),
|
|
83
|
-
createLazyRegistration("azure-openai-responses", () => import("./azure-openai-responses-
|
|
81
|
+
createLazyRegistration("azure-openai-responses", () => import("./azure-openai-responses-Aa4mVcYG.mjs"), (module) => ({
|
|
84
82
|
stream: module.streamAzureOpenAIResponses,
|
|
85
83
|
streamSimple: module.streamSimpleAzureOpenAIResponses
|
|
86
84
|
})),
|
|
87
|
-
createLazyRegistration("openai-chatgpt-responses", () => import("./openai-chatgpt-responses-
|
|
85
|
+
createLazyRegistration("openai-chatgpt-responses", () => import("./openai-chatgpt-responses-C339VIfT.mjs"), (module) => ({
|
|
88
86
|
stream: module.streamOpenAICodexResponses,
|
|
89
87
|
streamSimple: module.streamSimpleOpenAICodexResponses
|
|
90
88
|
})),
|
|
91
|
-
createLazyRegistration("google-generative-ai", () => import("./google-
|
|
89
|
+
createLazyRegistration("google-generative-ai", () => import("./google-yDRnipeq.mjs"), (module) => ({
|
|
92
90
|
stream: module.streamGoogle,
|
|
93
91
|
streamSimple: module.streamSimpleGoogle
|
|
94
92
|
})),
|
|
95
|
-
createLazyRegistration("google-vertex", () => import("./google-vertex-
|
|
93
|
+
createLazyRegistration("google-vertex", () => import("./google-vertex-DCJHM_a5.mjs"), (module) => ({
|
|
96
94
|
stream: module.streamGoogleVertex,
|
|
97
95
|
streamSimple: module.streamSimpleGoogleVertex
|
|
98
96
|
}))
|
|
@@ -11573,6 +11573,7 @@ const REASONING_TAG_NAMES = [
|
|
|
11573
11573
|
"thinking",
|
|
11574
11574
|
"thought",
|
|
11575
11575
|
"reasoning",
|
|
11576
|
+
"internal",
|
|
11576
11577
|
"antthinking",
|
|
11577
11578
|
"antml:think",
|
|
11578
11579
|
"antml:thinking",
|
|
@@ -11645,7 +11646,8 @@ function parseReasoningTagAt(text, start, final) {
|
|
|
11645
11646
|
index: start,
|
|
11646
11647
|
text: text.slice(start, end),
|
|
11647
11648
|
isClose,
|
|
11648
|
-
isSelfClosing: !isClose && lastSignificant === "/"
|
|
11649
|
+
isSelfClosing: !isClose && lastSignificant === "/",
|
|
11650
|
+
isPrivate: partialName === "internal"
|
|
11649
11651
|
}
|
|
11650
11652
|
};
|
|
11651
11653
|
}
|
|
@@ -11748,16 +11750,18 @@ function reduceReasoningText(text, codeSpans, state, options) {
|
|
|
11748
11750
|
index: scannedTag.index + start,
|
|
11749
11751
|
isClose: scannedTag.isClose,
|
|
11750
11752
|
isSelfClosing: scannedTag.isSelfClosing,
|
|
11753
|
+
isPrivate: scannedTag.isPrivate,
|
|
11751
11754
|
text: scannedTag.text
|
|
11752
11755
|
};
|
|
11753
11756
|
if (!isInsideCode(tag.index, codeSpans)) tags.push(tag);
|
|
11754
11757
|
}
|
|
11755
|
-
const
|
|
11758
|
+
const mustParseRemainder = [];
|
|
11756
11759
|
if (options.scope === "leading") {
|
|
11757
|
-
let
|
|
11760
|
+
let mustParse = false;
|
|
11758
11761
|
for (let index = tags.length - 1; index >= 0; index -= 1) {
|
|
11759
|
-
|
|
11760
|
-
|
|
11762
|
+
mustParse ||= tags[index]?.isPrivate === true;
|
|
11763
|
+
mustParseRemainder[index] = mustParse;
|
|
11764
|
+
mustParse ||= tags[index]?.isClose === true;
|
|
11761
11765
|
}
|
|
11762
11766
|
}
|
|
11763
11767
|
let cursor = start;
|
|
@@ -11777,17 +11781,19 @@ function reduceReasoningText(text, codeSpans, state, options) {
|
|
|
11777
11781
|
continue;
|
|
11778
11782
|
}
|
|
11779
11783
|
if (!tag.isClose) {
|
|
11780
|
-
if (state.depth === 0 && options.scope === "leading" && state.visibleEver && !
|
|
11784
|
+
if (state.depth === 0 && options.scope === "leading" && state.visibleEver && !mustParseRemainder[tagIndex]) {
|
|
11781
11785
|
emit("text", text.slice(tag.index));
|
|
11782
11786
|
cursor = text.length;
|
|
11783
11787
|
break;
|
|
11784
11788
|
}
|
|
11785
11789
|
if (state.depth === 0) state.pending = {
|
|
11786
11790
|
content: "",
|
|
11791
|
+
containsPrivate: tag.isPrivate,
|
|
11787
11792
|
openTag: tag.text,
|
|
11788
11793
|
protectedClose: false,
|
|
11789
11794
|
visibleBefore: state.visibleEver
|
|
11790
11795
|
};
|
|
11796
|
+
else if (state.pending) state.pending.containsPrivate ||= tag.isPrivate;
|
|
11791
11797
|
state.depth += 1;
|
|
11792
11798
|
cursor = tagEnd;
|
|
11793
11799
|
continue;
|
|
@@ -11795,7 +11801,7 @@ function reduceReasoningText(text, codeSpans, state, options) {
|
|
|
11795
11801
|
if (state.depth > 0) {
|
|
11796
11802
|
state.depth -= 1;
|
|
11797
11803
|
if (state.depth === 0 && state.pending) {
|
|
11798
|
-
emit("thinking", state.pending.content);
|
|
11804
|
+
if (!state.pending.containsPrivate) emit("thinking", state.pending.content);
|
|
11799
11805
|
state.pending = void 0;
|
|
11800
11806
|
} else if (state.pending) state.pending.protectedClose = true;
|
|
11801
11807
|
cursor = tagEnd;
|
|
@@ -11815,7 +11821,7 @@ function reduceReasoningText(text, codeSpans, state, options) {
|
|
|
11815
11821
|
append(text.slice(cursor));
|
|
11816
11822
|
if (options.final && state.depth > 0 && state.pending) {
|
|
11817
11823
|
const pending = state.pending;
|
|
11818
|
-
if (options.mode === "static-preserve" || options.mode === "static-strict" && !pending.visibleBefore && !pending.protectedClose || options.mode === "visible" && !pending.protectedClose) emit("text", options.mode === "visible" && pending.visibleBefore ? pending.openTag + pending.content : pending.content);
|
|
11824
|
+
if (!pending.containsPrivate) if (options.mode === "static-preserve" || options.mode === "static-strict" && !pending.visibleBefore && !pending.protectedClose || options.mode === "visible" && !pending.protectedClose) emit("text", options.mode === "visible" && pending.visibleBefore ? pending.openTag + pending.content : pending.content);
|
|
11819
11825
|
else emit("thinking", pending.content);
|
|
11820
11826
|
state.depth = 0;
|
|
11821
11827
|
state.pending = void 0;
|
|
@@ -12200,6 +12206,9 @@ function createReasoningTagTextPartitioner() {
|
|
|
12200
12206
|
hasPending() {
|
|
12201
12207
|
return holdStart !== void 0 && holdStart < source.length || reduction.depth > 0 || emitted < source.length;
|
|
12202
12208
|
},
|
|
12209
|
+
hasPendingSyntax() {
|
|
12210
|
+
return pendingTagProbe !== void 0 || heldBacktickStart !== void 0 || reduction.depth > 0;
|
|
12211
|
+
},
|
|
12203
12212
|
isInsideReasoning() {
|
|
12204
12213
|
return reduction.depth > 0;
|
|
12205
12214
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region packages/normalization-core/src/record-coerce.ts
|
|
2
|
+
/** Type guard for non-array object records at browser-safe boundaries. */
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
/** Returns a non-array record or undefined. */
|
|
7
|
+
function asOptionalRecord(value) {
|
|
8
|
+
return isRecord(value) ? value : void 0;
|
|
9
|
+
}
|
|
10
|
+
/** Returns a non-array record or a fresh ordinary empty record. */
|
|
11
|
+
function asNonArrayRecord(value) {
|
|
12
|
+
return asOptionalRecord(value) ?? {};
|
|
13
|
+
}
|
|
14
|
+
/** Returns a non-array record or null. */
|
|
15
|
+
function asNullableRecord(value) {
|
|
16
|
+
return isRecord(value) ? value : null;
|
|
17
|
+
}
|
|
18
|
+
/** Returns any object-backed record, including arrays, or undefined. */
|
|
19
|
+
function asOptionalObjectRecord(value) {
|
|
20
|
+
return value && typeof value === "object" ? value : void 0;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { isRecord as a, asOptionalRecord as i, asNullableRecord as n, asOptionalObjectRecord as r, asNonArrayRecord as t };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { a as requiresClaudeMandatoryAdaptiveThinking, l as resolveClaudeNativeThinkingLevelMap } from "./
|
|
1
|
+
import { a as requiresClaudeMandatoryAdaptiveThinking, l as resolveClaudeNativeThinkingLevelMap } from "./anthropic-BQXQudmA.mjs";
|
|
2
|
+
import "./src-D2H6yKkH.mjs";
|
|
2
3
|
//#region packages/ai/src/model-utils.ts
|
|
3
4
|
/** Calculates and stores model cost fields from token usage and per-million pricing. */
|
|
4
5
|
function calculateCost(model, usage) {
|
|
@@ -61,4 +62,29 @@ function modelsAreEqual(a, b) {
|
|
|
61
62
|
return a.id === b.id && a.provider === b.provider;
|
|
62
63
|
}
|
|
63
64
|
//#endregion
|
|
64
|
-
|
|
65
|
+
//#region packages/ai/src/utils/sanitize-unicode.ts
|
|
66
|
+
/**
|
|
67
|
+
* Removes unpaired Unicode surrogate characters from a string.
|
|
68
|
+
*
|
|
69
|
+
* Unpaired surrogates (high surrogates 0xD800-0xDBFF without matching low surrogates 0xDC00-0xDFFF,
|
|
70
|
+
* or vice versa) cause JSON serialization errors in many API providers.
|
|
71
|
+
*
|
|
72
|
+
* Valid emoji and other characters outside the Basic Multilingual Plane use properly paired
|
|
73
|
+
* surrogates and will NOT be affected by this function.
|
|
74
|
+
*
|
|
75
|
+
* @param text - The text to sanitize
|
|
76
|
+
* @returns The sanitized text with unpaired surrogates removed
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // Valid emoji (properly paired surrogates) are preserved
|
|
80
|
+
* sanitizeSurrogates("Hello 🙈 World") // => "Hello 🙈 World"
|
|
81
|
+
*
|
|
82
|
+
* // Unpaired high surrogate is removed
|
|
83
|
+
* const unpaired = String.fromCharCode(0xD83D); // high surrogate without low
|
|
84
|
+
* sanitizeSurrogates(`Text ${unpaired} here`) // => "Text here"
|
|
85
|
+
*/
|
|
86
|
+
function sanitizeSurrogates(text) {
|
|
87
|
+
return text.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "");
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
export { getSupportedThinkingLevels as a, clampThinkingLevel as i, applyProviderReportedUsageCost as n, modelsAreEqual as o, calculateCost as r, sanitizeSurrogates as t };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region packages/ai/src/session-resources.ts
|
|
2
|
+
const sessionResourceCleanups = /* @__PURE__ */ new Set();
|
|
3
|
+
/** Registers a session-resource cleanup hook and returns an unregister function. */
|
|
4
|
+
function registerSessionResourceCleanup(cleanup) {
|
|
5
|
+
sessionResourceCleanups.add(cleanup);
|
|
6
|
+
return () => {
|
|
7
|
+
sessionResourceCleanups.delete(cleanup);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/** Runs all registered cleanup hooks, aggregating failures after every hook has run. */
|
|
11
|
+
function cleanupSessionResources(sessionId) {
|
|
12
|
+
const errors = [];
|
|
13
|
+
for (const cleanup of sessionResourceCleanups) try {
|
|
14
|
+
cleanup(sessionId);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
errors.push(error);
|
|
17
|
+
}
|
|
18
|
+
if (errors.length > 0) throw new AggregateError(errors, "Failed to cleanup session resources");
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { registerSessionResourceCleanup as n, cleanupSessionResources as t };
|