@openclaw/ai 2026.7.2-beta.7 → 2026.7.34
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/README.md +5 -6
- package/dist/{anthropic-CH4UUnZr.mjs → anthropic-Bcdbq-l5.mjs} +467 -100
- package/dist/{api-registry-DlMgPR39.d.mts → api-registry-BXYnCOIR.d.mts} +2 -1
- package/dist/{azure-openai-responses-CImcwB83.mjs → azure-openai-responses-2xhpNPWg.mjs} +13 -11
- package/dist/{azure-openai-responses-client-compat-C7K7QfUE.mjs → azure-openai-responses-client-compat-a_O_GVQV.mjs} +2 -23
- package/dist/{env-api-keys-DrgeBuva.mjs → env-api-keys-CtMlqaQ4.mjs} +4 -5
- package/dist/{event-stream-YjaPW20U.d.mts → event-stream-0nZeBKl2.d.mts} +1 -1
- package/dist/{event-stream-D8n2uFee.mjs → event-stream-ReMmOTzX.mjs} +6 -14
- package/dist/event-stream.d.mts +1 -1
- package/dist/event-stream.mjs +1 -1
- package/dist/{github-copilot-headers-NCJtz9i0.mjs → github-copilot-headers-BsH5cqGj.mjs} +12 -1
- package/dist/{google-CtSg0iTS.mjs → google-C6P31moq.mjs} +5 -5
- package/dist/{google-shared-DNBz5rcD.mjs → google-shared-BeyXFAcf.mjs} +26 -34
- package/dist/{google-vertex-31f1uS9L.mjs → google-vertex--9_gT74B.mjs} +19 -6
- package/dist/host-4t713IeR.mjs +37 -0
- package/dist/{anthropic-SrGtwsJu.d.mts → index-CGDEoorl.d.mts} +2 -6
- package/dist/index.d.mts +50 -7
- package/dist/index.mjs +5 -5
- package/dist/internal/anthropic.d.mts +61 -21
- package/dist/internal/anthropic.mjs +4 -5
- package/dist/internal/openai.d.mts +89 -98
- package/dist/internal/openai.mjs +6 -8
- package/dist/internal/runtime.d.mts +34 -13
- package/dist/internal/runtime.mjs +14 -26
- package/dist/internal/shared.d.mts +9 -26
- package/dist/internal/shared.mjs +2 -6
- package/dist/{json-parse-BvXNt1-7.mjs → json-parse-DzNSIQBq.mjs} +6 -4
- package/dist/{llm-request-activity-BjtkplhG.mjs → llm-request-activity-CehVkZP-.mjs} +19 -1
- package/dist/{mistral-CWmpvWYh.mjs → mistral-CBm3OQWD.mjs} +39 -141
- package/dist/model-utils-Cn9KAz3z.mjs +69 -0
- package/dist/{openai-chatgpt-responses-B84Ibtrd.mjs → openai-chatgpt-responses-M2RVpycr.mjs} +154 -101
- package/dist/{openai-completions-DsOxhOD1.mjs → openai-completions-BUlMEeBc.mjs} +295 -81
- package/dist/{openai-responses-BT7A3sLu.mjs → openai-responses-DW61C22l.mjs} +9 -14
- package/dist/openai-responses-shared-BhYsVkwW.mjs +1949 -0
- package/dist/{openai-tool-projection-OhX64DoP.mjs → openai-tool-projection-g4HuxD26.mjs} +20 -31
- package/dist/providers.d.mts +2 -3
- package/dist/providers.mjs +10 -11
- package/dist/reasoning-tag-text-partitioner-axhAdUwg.mjs +394 -0
- package/dist/{src-QkygScBs.mjs → src-CjOfhrH3.mjs} +6 -17
- package/dist/{stream-first-event-timeout-BBys9hSb.mjs → stream-first-event-timeout-RjWszj8c.mjs} +22 -2
- package/dist/transform-messages-DoWx35pj.mjs +509 -0
- package/dist/{types-bzp5k29J.d.mts → types-DRgdPqaZ.d.mts} +0 -19
- package/dist/types.d.mts +5 -5
- package/dist/types.mjs +4 -4
- package/dist/{validation-B-j7cOYp.d.mts → validation-BDMWOr8d.d.mts} +1 -1
- package/dist/{validation-DAa_yFOM.mjs → validation-FrchoOlv.mjs} +7 -2
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/npm-shrinkwrap.json +645 -0
- package/package.json +11 -36
- package/dist/anthropic-usage-DWU-x8MI.mjs +0 -459
- package/dist/cache-retention-0x979a5V.mjs +0 -12
- package/dist/deferred-event-buffer-DAvyP7qA.mjs +0 -19
- package/dist/error-coercion-DgxlWC0n.mjs +0 -15
- package/dist/host-B9GUmcra.d.mts +0 -173
- package/dist/host-Dog2WQiR.mjs +0 -369
- package/dist/index-BVVgDSdq.d.mts +0 -1
- package/dist/internal/retry-after.d.mts +0 -5
- package/dist/internal/retry-after.mjs +0 -101
- package/dist/number-coercion-DvG7SNMg.mjs +0 -129
- package/dist/openai-completions-compat-DBWjXoMZ.d.mts +0 -43
- package/dist/openai-prompt-cache-2uo_1OR1.d.mts +0 -7
- package/dist/openai-prompt-cache-mZTCdRPo.mjs +0 -12
- package/dist/openai-reasoning-compat-YgeLncHw.mjs +0 -396
- package/dist/openai-responses-shared-pXl6Wd8S.mjs +0 -392
- package/dist/openai-responses-stream-internal-Cw5txaGW.mjs +0 -2964
- package/dist/prompt-cache-stability-Cwcjv_fx.d.mts +0 -13
- package/dist/provider-error-CAEvRjry.mjs +0 -47
- package/dist/provider-options-D8bB3z9b.d.mts +0 -144
- package/dist/reasoning-tag-text-partitioner-CGDyLWUR.mjs +0 -12209
- package/dist/simple-options-9lhRrN73.mjs +0 -50
- package/dist/stream-first-event-timeout-DvDeSucC.d.mts +0 -29
- package/dist/tls-certificate-errors-DXSpluKI.mjs +0 -93
- package/dist/tool-result-text-CTpIRbYd.mjs +0 -225
- package/dist/transform-messages-C8mBqZxF.mjs +0 -2
- package/dist/transport-stream-shared-D81p90xq.mjs +0 -297
- package/dist/transports.d.mts +0 -573
- package/dist/transports.mjs +0 -4110
package/dist/host-B9GUmcra.d.mts
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import { E as Model, L as StreamFn, n as Api, u as Context } from "./types-bzp5k29J.mjs";
|
|
2
|
-
import { n as ApiRegistry } from "./api-registry-DlMgPR39.mjs";
|
|
3
|
-
|
|
4
|
-
//#region packages/ai/src/host.d.ts
|
|
5
|
-
/** Provider capability facts needed by the package-owned transports. */
|
|
6
|
-
interface AiProviderRequestCapabilities {
|
|
7
|
-
endpointClass: string;
|
|
8
|
-
knownProviderFamily: string;
|
|
9
|
-
supportsNativeStreamingUsageCompat: boolean;
|
|
10
|
-
supportsOpenAICompletionsStreamingUsageCompat: boolean;
|
|
11
|
-
usesExplicitProxyLikeEndpoint: boolean;
|
|
12
|
-
allowsAnthropicServiceTier: boolean;
|
|
13
|
-
}
|
|
14
|
-
/** Transport-safe provider policy input kept independent of OpenClaw config types. */
|
|
15
|
-
interface AiProviderRequestPolicyInput {
|
|
16
|
-
provider?: string;
|
|
17
|
-
api?: string;
|
|
18
|
-
baseUrl?: string;
|
|
19
|
-
capability?: "llm" | "audio" | "image" | "video" | "other";
|
|
20
|
-
transport?: "stream" | "websocket" | "http" | "media-understanding";
|
|
21
|
-
modelId?: string | null;
|
|
22
|
-
compat?: unknown;
|
|
23
|
-
}
|
|
24
|
-
/** Context shared by plugin-owned provider stream hooks. */
|
|
25
|
-
interface AiProviderStreamHookContext {
|
|
26
|
-
config?: unknown;
|
|
27
|
-
agentDir?: string;
|
|
28
|
-
workspaceDir?: string;
|
|
29
|
-
provider: string;
|
|
30
|
-
modelId: string;
|
|
31
|
-
model: Model;
|
|
32
|
-
}
|
|
33
|
-
/** Narrow plugin-runtime port used by package-owned transports. */
|
|
34
|
-
interface AiTransportPluginHost {
|
|
35
|
-
resolveProviderStream(this: void, params: {
|
|
36
|
-
provider: string;
|
|
37
|
-
config?: unknown;
|
|
38
|
-
workspaceDir?: string;
|
|
39
|
-
env?: NodeJS.ProcessEnv;
|
|
40
|
-
allowRuntimePluginLoad?: boolean;
|
|
41
|
-
context: AiProviderStreamHookContext;
|
|
42
|
-
}): StreamFn | undefined;
|
|
43
|
-
resolveTransportTurnState(this: void, params: {
|
|
44
|
-
provider: string;
|
|
45
|
-
modelId?: string | null;
|
|
46
|
-
config?: unknown;
|
|
47
|
-
workspaceDir?: string;
|
|
48
|
-
env?: NodeJS.ProcessEnv;
|
|
49
|
-
allowRuntimePluginLoad?: boolean;
|
|
50
|
-
context: {
|
|
51
|
-
provider: string;
|
|
52
|
-
modelId: string;
|
|
53
|
-
model?: Model;
|
|
54
|
-
sessionId?: string;
|
|
55
|
-
turnId: string;
|
|
56
|
-
attempt: number;
|
|
57
|
-
transport: "stream" | "websocket";
|
|
58
|
-
};
|
|
59
|
-
}): {
|
|
60
|
-
headers?: Record<string, string>;
|
|
61
|
-
metadata?: Record<string, string>;
|
|
62
|
-
} | undefined;
|
|
63
|
-
wrapSimpleCompletionStream(this: void, params: {
|
|
64
|
-
provider: string;
|
|
65
|
-
config?: unknown;
|
|
66
|
-
context: AiProviderStreamHookContext & {
|
|
67
|
-
streamFn: StreamFn;
|
|
68
|
-
};
|
|
69
|
-
}): StreamFn | undefined;
|
|
70
|
-
createAnthropicVertexStream(this: void, model: Pick<Model, "baseUrl">, env?: NodeJS.ProcessEnv): StreamFn;
|
|
71
|
-
}
|
|
72
|
-
/** Host-owned transcript normalization contract used immediately before provider projection. */
|
|
73
|
-
type AiTransformTransportMessages = (messages: Context["messages"], model: Model, normalizeToolCallId?: (id: string, targetModel: Model, source: {
|
|
74
|
-
provider: string;
|
|
75
|
-
api: Api;
|
|
76
|
-
model: string;
|
|
77
|
-
}) => string, options?: {
|
|
78
|
-
normalizeSameModelToolCallIds?: boolean;
|
|
79
|
-
preserveCrossModelToolCallThoughtSignature?: boolean;
|
|
80
|
-
}) => Context["messages"];
|
|
81
|
-
/** Strict-tool policy inputs for OpenAI-compatible routes. */
|
|
82
|
-
interface OpenAIStrictToolSettingOptions {
|
|
83
|
-
transport?: "stream" | "websocket";
|
|
84
|
-
supportsStrictMode?: boolean;
|
|
85
|
-
}
|
|
86
|
-
type AiInlineTextBlock = {
|
|
87
|
-
type: "text";
|
|
88
|
-
text: string;
|
|
89
|
-
};
|
|
90
|
-
type AiInlineImageBlock = {
|
|
91
|
-
type: "image";
|
|
92
|
-
data: string;
|
|
93
|
-
mimeType: string;
|
|
94
|
-
};
|
|
95
|
-
type AiInlineContentBlock = AiInlineTextBlock | AiInlineImageBlock;
|
|
96
|
-
type AnthropicInlineContentNormalizer = (content: readonly AiInlineContentBlock[]) => Promise<AiInlineContentBlock[]>;
|
|
97
|
-
/** Narrow host ports consumed by the built-in provider adapters. */
|
|
98
|
-
interface AiTransportHost {
|
|
99
|
-
/**
|
|
100
|
-
* Builds a policy-guarded fetch for one model request.
|
|
101
|
-
* Returning undefined keeps the provider SDK's default fetch.
|
|
102
|
-
*/
|
|
103
|
-
buildModelFetch(model: Model, timeoutMs?: number, options?: {
|
|
104
|
-
sanitizeSse?: boolean;
|
|
105
|
-
}): typeof fetch | undefined;
|
|
106
|
-
/** Resolves host-owned process-local secret sentinel substrings immediately before egress. */
|
|
107
|
-
resolveSecretSentinel(value: string): string;
|
|
108
|
-
/** Redacts secrets inside structured tool-result payloads. */
|
|
109
|
-
redactSecrets<T>(value: T): T;
|
|
110
|
-
/** Redacts secret-bearing text in tool payload strings. */
|
|
111
|
-
redactToolPayloadText(text: string): string;
|
|
112
|
-
/** Normalizes Anthropic inline image blocks before provider payload construction. */
|
|
113
|
-
normalizeAnthropicInlineContentBlocks?: AnthropicInlineContentNormalizer;
|
|
114
|
-
/**
|
|
115
|
-
* Resolves the host strict-tool default for OpenAI-compatible routes.
|
|
116
|
-
* undefined lets the request omit the strict flag entirely.
|
|
117
|
-
*/
|
|
118
|
-
resolveOpenAIStrictToolSetting(model: Pick<Model, "provider" | "api" | "baseUrl" | "id"> & {
|
|
119
|
-
compat?: unknown;
|
|
120
|
-
}, options?: OpenAIStrictToolSettingOptions): boolean | undefined;
|
|
121
|
-
/** Provider-plugin operations required by the generic package transports. */
|
|
122
|
-
plugin: AiTransportPluginHost;
|
|
123
|
-
/** Builds provider-owned Copilot compatibility headers for one message turn. */
|
|
124
|
-
buildCopilotDynamicHeaders(messages: Context["messages"]): Record<string, string>;
|
|
125
|
-
/** Resolves endpoint classification without importing core provider registries. */
|
|
126
|
-
resolveProviderEndpointClass(baseUrl?: string): string;
|
|
127
|
-
/** Resolves provider capability flags used by payload compatibility policy. */
|
|
128
|
-
resolveProviderRequestCapabilities(input: AiProviderRequestPolicyInput): AiProviderRequestCapabilities;
|
|
129
|
-
/** Merges host-owned provider request headers and attribution policy. */
|
|
130
|
-
resolveProviderRequestHeaders(input: {
|
|
131
|
-
provider?: string;
|
|
132
|
-
api?: string;
|
|
133
|
-
baseUrl?: string;
|
|
134
|
-
providerHeaders?: Record<string, string>;
|
|
135
|
-
callerHeaders?: Record<string, string>;
|
|
136
|
-
precedence?: "caller-wins" | "defaults-win";
|
|
137
|
-
}): Record<string, string> | undefined;
|
|
138
|
-
/** Returns the host-configured request timeout attached to a model. */
|
|
139
|
-
resolveModelRequestTimeoutMs(model: Model): number | undefined;
|
|
140
|
-
/** Reports whether the model carries host-managed proxy, TLS, or local-service state. */
|
|
141
|
-
requiresManagedTransport(model: Model): boolean;
|
|
142
|
-
/** Copies host-owned managed-transport state onto a projected model. */
|
|
143
|
-
inheritManagedTransport(source: Model, target: Model): Model;
|
|
144
|
-
/** Applies host-owned transcript replay and pairing rules. */
|
|
145
|
-
transformTransportMessages: AiTransformTransportMessages;
|
|
146
|
-
/** Registers a custom transport API with the host's stream error bridge. */
|
|
147
|
-
registerCustomApi(registry: ApiRegistry, api: Api, streamFn: StreamFn): boolean;
|
|
148
|
-
/** Prepares the provider-owned Google simple-completion alias when needed. */
|
|
149
|
-
prepareGoogleSimpleCompletionModel(registry: ApiRegistry, model: Model): Model;
|
|
150
|
-
/**
|
|
151
|
-
* Emits one transport diagnostic; build runs only when the host logs it and
|
|
152
|
-
* may return null to suppress the entry (e.g. de-duplication).
|
|
153
|
-
*/
|
|
154
|
-
logDebug(subsystem: string, build: () => {
|
|
155
|
-
message: string;
|
|
156
|
-
data?: Record<string, unknown>;
|
|
157
|
-
} | null): void;
|
|
158
|
-
/** Emits an informational transport diagnostic through the host logger. */
|
|
159
|
-
logInfo(subsystem: string, message: string, data?: Record<string, unknown>): void;
|
|
160
|
-
/** Emits a warning through the host logger. */
|
|
161
|
-
logWarn(subsystem: string, message: string, data?: Record<string, unknown>): void;
|
|
162
|
-
}
|
|
163
|
-
type ActiveAiTransportHost = Omit<AiTransportHost, "normalizeAnthropicInlineContentBlocks"> & {
|
|
164
|
-
normalizeAnthropicInlineContentBlocks: AnthropicInlineContentNormalizer;
|
|
165
|
-
};
|
|
166
|
-
/** Installs host implementations for the transport policy ports. */
|
|
167
|
-
declare function configureAiTransportHost(host: Partial<AiTransportHost>): void;
|
|
168
|
-
/** Returns the active transport host (inert defaults unless configured). */
|
|
169
|
-
declare function getAiTransportHost(): ActiveAiTransportHost;
|
|
170
|
-
/** Resolves sentinel substrings in custom headers at a no-fetch adapter boundary. */
|
|
171
|
-
declare function resolveAiTransportHeaderSentinels(headers: Record<string, string> | undefined): Record<string, string> | undefined;
|
|
172
|
-
//#endregion
|
|
173
|
-
export { AiProviderRequestPolicyInput as a, AiTransportHost as c, configureAiTransportHost as d, getAiTransportHost as f, AiProviderRequestCapabilities as i, AiTransportPluginHost as l, AiInlineImageBlock as n, AiProviderStreamHookContext as o, resolveAiTransportHeaderSentinels as p, AiInlineTextBlock as r, AiTransformTransportMessages as s, AiInlineContentBlock as t, OpenAIStrictToolSettingOptions as u };
|
package/dist/host-Dog2WQiR.mjs
DELETED
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
import { a as requiresClaudeMandatoryAdaptiveThinking, c as resolveClaudeMythos5ModelIdentity, d as resolveClaudeSonnet5ModelIdentity, i as requiresClaudeDefaultSampling, o as resolveClaudeFable5ModelIdentity, u as resolveClaudeOpus5ModelIdentity } from "./src-QkygScBs.mjs";
|
|
2
|
-
//#region packages/normalization-core/src/record-coerce.ts
|
|
3
|
-
/** Type guard for non-array object records at browser-safe boundaries. */
|
|
4
|
-
function isRecord(value) {
|
|
5
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6
|
-
}
|
|
7
|
-
//#endregion
|
|
8
|
-
//#region packages/normalization-core/src/string-coerce.ts
|
|
9
|
-
/** Reads a value only when it is already a string, preserving whitespace. */
|
|
10
|
-
function readStringValue(value) {
|
|
11
|
-
return typeof value === "string" ? value : void 0;
|
|
12
|
-
}
|
|
13
|
-
/** Trims string input and returns null for non-strings or empty strings. */
|
|
14
|
-
function normalizeNullableString(value) {
|
|
15
|
-
if (typeof value !== "string") return null;
|
|
16
|
-
const trimmed = value.trim();
|
|
17
|
-
return trimmed ? trimmed : null;
|
|
18
|
-
}
|
|
19
|
-
/** Trims string input and returns undefined for non-strings or empty strings. */
|
|
20
|
-
function normalizeOptionalString(value) {
|
|
21
|
-
return normalizeNullableString(value) ?? void 0;
|
|
22
|
-
}
|
|
23
|
-
/** Lowercases a normalized optional string. */
|
|
24
|
-
function normalizeOptionalLowercaseString(value) {
|
|
25
|
-
return normalizeOptionalString(value)?.toLowerCase();
|
|
26
|
-
}
|
|
27
|
-
/** Lowercases a normalized string or returns an empty string when absent. */
|
|
28
|
-
function normalizeLowercaseStringOrEmpty(value) {
|
|
29
|
-
return normalizeOptionalLowercaseString(value) ?? "";
|
|
30
|
-
}
|
|
31
|
-
/** Type guard for strings that remain non-empty after trimming. */
|
|
32
|
-
function hasNonEmptyString(value) {
|
|
33
|
-
return normalizeOptionalString(value) !== void 0;
|
|
34
|
-
}
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region packages/ai/src/providers/anthropic-model-contract.ts
|
|
37
|
-
function normalizeModelId(modelId) {
|
|
38
|
-
const normalized = normalizeLowercaseStringOrEmpty(modelId);
|
|
39
|
-
return (normalized.startsWith("anthropic/") ? normalized.slice(10) : normalized).replace(/[._\s]+/g, "-");
|
|
40
|
-
}
|
|
41
|
-
function normalizeApi(api) {
|
|
42
|
-
const normalized = normalizeLowercaseStringOrEmpty(api);
|
|
43
|
-
return normalized === "openclaw-anthropic-messages-transport" ? "anthropic-messages" : normalized;
|
|
44
|
-
}
|
|
45
|
-
function hasConcreteResponseModel(ref) {
|
|
46
|
-
const responseModelId = normalizeModelId(ref.responseModelId);
|
|
47
|
-
return responseModelId.length > 0 && responseModelId !== normalizeModelId(ref.modelId);
|
|
48
|
-
}
|
|
49
|
-
function usesClaudeFable5MessagesContract(model) {
|
|
50
|
-
return normalizeApi(model.api) === "anthropic-messages" && resolveClaudeFable5ModelIdentity(model) !== void 0;
|
|
51
|
-
}
|
|
52
|
-
/** Return whether streamed output must wait for the terminal refusal decision. */
|
|
53
|
-
function usesClaudeStreamingRefusalContract(model) {
|
|
54
|
-
if (normalizeApi(model.api) !== "anthropic-messages") return false;
|
|
55
|
-
return resolveClaudeFable5ModelIdentity(model) !== void 0 || resolveClaudeMythos5ModelIdentity(model) !== void 0 || resolveClaudeOpus5ModelIdentity(model) !== void 0 || resolveClaudeSonnet5ModelIdentity(model) !== void 0;
|
|
56
|
-
}
|
|
57
|
-
function requiresClaudeAdaptiveThinking(model) {
|
|
58
|
-
if (normalizeApi(model.api) !== "anthropic-messages") return false;
|
|
59
|
-
return requiresClaudeMandatoryAdaptiveThinking(model);
|
|
60
|
-
}
|
|
61
|
-
/** Return whether omitted thinking should default to adaptive/high. */
|
|
62
|
-
function defaultsClaudeAdaptiveThinking(model) {
|
|
63
|
-
return requiresClaudeAdaptiveThinking(model) || normalizeApi(model.api) === "anthropic-messages" && (resolveClaudeOpus5ModelIdentity(model) !== void 0 || resolveClaudeSonnet5ModelIdentity(model) !== void 0);
|
|
64
|
-
}
|
|
65
|
-
/** Remove unsupported assistant prefills while preserving completed tool-use turns. */
|
|
66
|
-
function prepareClaudeNoPrefillRequestContext(model, context) {
|
|
67
|
-
if (!resolveClaudeOpus5ModelIdentity(model) && !resolveClaudeSonnet5ModelIdentity(model)) return context;
|
|
68
|
-
let end = context.messages.length;
|
|
69
|
-
while (end > 0) {
|
|
70
|
-
const message = context.messages[end - 1];
|
|
71
|
-
if (message?.role !== "assistant" || Array.isArray(message.content) && message.content.some((block) => block.type === "toolCall")) break;
|
|
72
|
-
end -= 1;
|
|
73
|
-
}
|
|
74
|
-
return end === context.messages.length ? context : {
|
|
75
|
-
...context,
|
|
76
|
-
messages: context.messages.slice(0, end)
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
function applyClaudeRequestContract(params, model) {
|
|
80
|
-
if (normalizeApi(model.api) !== "anthropic-messages") return;
|
|
81
|
-
const opus5 = resolveClaudeOpus5ModelIdentity(model) !== void 0;
|
|
82
|
-
const sonnet5 = resolveClaudeSonnet5ModelIdentity(model) !== void 0;
|
|
83
|
-
if (!requiresClaudeDefaultSampling(model) && !opus5 && !sonnet5) return;
|
|
84
|
-
delete params.temperature;
|
|
85
|
-
delete params.top_p;
|
|
86
|
-
delete params.top_k;
|
|
87
|
-
if (opus5 || sonnet5) delete params.service_tier;
|
|
88
|
-
}
|
|
89
|
-
function resolveReplayModelBoundIdentity(ref) {
|
|
90
|
-
if (normalizeApi(ref.api) !== "anthropic-messages") return;
|
|
91
|
-
const modelRef = hasConcreteResponseModel(ref) ? { id: ref.responseModelId } : {
|
|
92
|
-
id: ref.modelId,
|
|
93
|
-
params: ref.modelParams
|
|
94
|
-
};
|
|
95
|
-
const fableIdentity = resolveClaudeFable5ModelIdentity(modelRef);
|
|
96
|
-
if (fableIdentity) return `fable:${fableIdentity}`;
|
|
97
|
-
const mythosIdentity = resolveClaudeMythos5ModelIdentity(modelRef);
|
|
98
|
-
if (mythosIdentity) return `mythos:${mythosIdentity}`;
|
|
99
|
-
const opusIdentity = resolveClaudeOpus5ModelIdentity(modelRef);
|
|
100
|
-
if (opusIdentity) return `opus:${opusIdentity}`;
|
|
101
|
-
const sonnetIdentity = resolveClaudeSonnet5ModelIdentity(modelRef);
|
|
102
|
-
return sonnetIdentity ? `sonnet:${sonnetIdentity}` : void 0;
|
|
103
|
-
}
|
|
104
|
-
function resolveModelBoundThinkingReplayMode(params) {
|
|
105
|
-
const sourceApi = normalizeApi(params.source.api);
|
|
106
|
-
const targetApi = normalizeApi(params.target.api);
|
|
107
|
-
const sourceIdentity = resolveReplayModelBoundIdentity(params.source);
|
|
108
|
-
const targetIdentity = resolveReplayModelBoundIdentity(params.target);
|
|
109
|
-
const sameRoute = normalizeLowercaseStringOrEmpty(params.source.provider) === normalizeLowercaseStringOrEmpty(params.target.provider) && sourceApi === targetApi && normalizeModelId(params.source.modelId) === normalizeModelId(params.target.modelId);
|
|
110
|
-
if (!sourceIdentity && !targetIdentity) return "default";
|
|
111
|
-
if (!sourceIdentity && !hasConcreteResponseModel(params.source) && targetIdentity && sameRoute) return "preserve";
|
|
112
|
-
return sourceApi === targetApi && sourceIdentity === targetIdentity ? "preserve" : "drop";
|
|
113
|
-
}
|
|
114
|
-
//#endregion
|
|
115
|
-
//#region packages/ai/src/transcript-transform.ts
|
|
116
|
-
const NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
117
|
-
const NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
|
|
118
|
-
function isImageWithMediaPayload(block) {
|
|
119
|
-
return isRecord(block) && block.type === "image" && typeof block.data === "string" && block.data.trim().length > 0;
|
|
120
|
-
}
|
|
121
|
-
function replaceImagesWithPlaceholder(content, placeholder) {
|
|
122
|
-
const result = [];
|
|
123
|
-
let previousWasPlaceholder = false;
|
|
124
|
-
for (const block of content) {
|
|
125
|
-
if (block.type === "image") {
|
|
126
|
-
if (!isImageWithMediaPayload(block)) continue;
|
|
127
|
-
if (!previousWasPlaceholder) result.push({
|
|
128
|
-
type: "text",
|
|
129
|
-
text: placeholder
|
|
130
|
-
});
|
|
131
|
-
previousWasPlaceholder = true;
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
result.push(block);
|
|
135
|
-
previousWasPlaceholder = block.text === placeholder;
|
|
136
|
-
}
|
|
137
|
-
return result;
|
|
138
|
-
}
|
|
139
|
-
function downgradeUnsupportedImages(messages, model) {
|
|
140
|
-
if (model.input.includes("image")) return messages;
|
|
141
|
-
return messages.map((msg) => {
|
|
142
|
-
if (msg.role === "user" && Array.isArray(msg.content)) return {
|
|
143
|
-
...msg,
|
|
144
|
-
content: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER)
|
|
145
|
-
};
|
|
146
|
-
if (msg.role === "toolResult") return {
|
|
147
|
-
...msg,
|
|
148
|
-
content: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER)
|
|
149
|
-
};
|
|
150
|
-
return msg;
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Normalize tool call ID for cross-provider compatibility.
|
|
155
|
-
* OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
|
|
156
|
-
* Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).
|
|
157
|
-
*/
|
|
158
|
-
function transformMessages(messages, model, normalizeToolCallId) {
|
|
159
|
-
const toolCallIdMap = /* @__PURE__ */ new Map();
|
|
160
|
-
const transformed = downgradeUnsupportedImages(messages.map((msg) => msg.content == null ? {
|
|
161
|
-
...msg,
|
|
162
|
-
content: []
|
|
163
|
-
} : msg), model).map((msg) => {
|
|
164
|
-
if (msg.role === "user") return msg;
|
|
165
|
-
if (msg.role === "toolResult") {
|
|
166
|
-
const normalizedId = toolCallIdMap.get(msg.toolCallId);
|
|
167
|
-
if (normalizedId && normalizedId !== msg.toolCallId) return Object.assign({}, msg, { toolCallId: normalizedId });
|
|
168
|
-
return msg;
|
|
169
|
-
}
|
|
170
|
-
if (msg.role === "assistant") {
|
|
171
|
-
const assistantMsg = msg;
|
|
172
|
-
const modelBoundThinkingReplayMode = resolveModelBoundThinkingReplayMode({
|
|
173
|
-
source: {
|
|
174
|
-
provider: assistantMsg.provider,
|
|
175
|
-
api: assistantMsg.api,
|
|
176
|
-
modelId: assistantMsg.model,
|
|
177
|
-
responseModelId: assistantMsg.responseModel
|
|
178
|
-
},
|
|
179
|
-
target: {
|
|
180
|
-
provider: model.provider,
|
|
181
|
-
api: model.api,
|
|
182
|
-
modelId: model.id,
|
|
183
|
-
modelParams: model.params
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
const isSameModel = modelBoundThinkingReplayMode === "preserve" || assistantMsg.provider === model.provider && assistantMsg.api === model.api && assistantMsg.model === model.id;
|
|
187
|
-
const transformedContent = (typeof assistantMsg.content === "string" ? [{
|
|
188
|
-
type: "text",
|
|
189
|
-
text: assistantMsg.content
|
|
190
|
-
}] : assistantMsg.content).flatMap((block) => {
|
|
191
|
-
if (block.type === "thinking") {
|
|
192
|
-
if (modelBoundThinkingReplayMode === "drop") return [];
|
|
193
|
-
if (block.redacted) return isSameModel ? block : [];
|
|
194
|
-
if (isSameModel && block.thinkingSignature) return block;
|
|
195
|
-
if (!block.thinking || block.thinking.trim() === "") return [];
|
|
196
|
-
if (isSameModel) return block;
|
|
197
|
-
return {
|
|
198
|
-
type: "text",
|
|
199
|
-
text: block.thinking
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
if (block.type === "text") {
|
|
203
|
-
if (isSameModel) return block;
|
|
204
|
-
return {
|
|
205
|
-
type: "text",
|
|
206
|
-
text: block.text
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
if (block.type === "toolCall") {
|
|
210
|
-
const toolCall = block;
|
|
211
|
-
let normalizedToolCall = toolCall;
|
|
212
|
-
if (!isSameModel && toolCall.thoughtSignature) {
|
|
213
|
-
normalizedToolCall = Object.assign({}, toolCall);
|
|
214
|
-
delete normalizedToolCall.thoughtSignature;
|
|
215
|
-
}
|
|
216
|
-
if (!isSameModel && normalizeToolCallId) {
|
|
217
|
-
const normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);
|
|
218
|
-
if (normalizedId !== toolCall.id) {
|
|
219
|
-
toolCallIdMap.set(toolCall.id, normalizedId);
|
|
220
|
-
normalizedToolCall = Object.assign({}, normalizedToolCall, { id: normalizedId });
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
return normalizedToolCall;
|
|
224
|
-
}
|
|
225
|
-
return block;
|
|
226
|
-
});
|
|
227
|
-
return Object.assign({}, assistantMsg, { content: transformedContent });
|
|
228
|
-
}
|
|
229
|
-
return msg;
|
|
230
|
-
});
|
|
231
|
-
const result = [];
|
|
232
|
-
let pendingToolCalls = [];
|
|
233
|
-
let existingToolResultIds = /* @__PURE__ */ new Set();
|
|
234
|
-
const insertSyntheticToolResults = () => {
|
|
235
|
-
if (pendingToolCalls.length > 0) {
|
|
236
|
-
for (const tc of pendingToolCalls) if (!existingToolResultIds.has(tc.id)) result.push({
|
|
237
|
-
role: "toolResult",
|
|
238
|
-
toolCallId: tc.id,
|
|
239
|
-
toolName: tc.name,
|
|
240
|
-
content: [{
|
|
241
|
-
type: "text",
|
|
242
|
-
text: "No result provided"
|
|
243
|
-
}],
|
|
244
|
-
isError: true,
|
|
245
|
-
timestamp: Date.now()
|
|
246
|
-
});
|
|
247
|
-
pendingToolCalls = [];
|
|
248
|
-
existingToolResultIds = /* @__PURE__ */ new Set();
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
|
-
for (const msg of transformed) if (msg.role === "assistant") {
|
|
252
|
-
insertSyntheticToolResults();
|
|
253
|
-
const assistantMsg = msg;
|
|
254
|
-
if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") continue;
|
|
255
|
-
const toolCalls = assistantMsg.content.filter((b) => b.type === "toolCall");
|
|
256
|
-
if (toolCalls.length > 0) {
|
|
257
|
-
pendingToolCalls = toolCalls;
|
|
258
|
-
existingToolResultIds = /* @__PURE__ */ new Set();
|
|
259
|
-
}
|
|
260
|
-
result.push(msg);
|
|
261
|
-
} else if (msg.role === "toolResult") {
|
|
262
|
-
existingToolResultIds.add(msg.toolCallId);
|
|
263
|
-
result.push(msg);
|
|
264
|
-
} else if (msg.role === "user") {
|
|
265
|
-
insertSyntheticToolResults();
|
|
266
|
-
result.push(msg);
|
|
267
|
-
} else result.push(msg);
|
|
268
|
-
insertSyntheticToolResults();
|
|
269
|
-
return result;
|
|
270
|
-
}
|
|
271
|
-
//#endregion
|
|
272
|
-
//#region packages/ai/src/host.ts
|
|
273
|
-
const MAX_PENDING_CUSTOM_API_REGISTRATIONS = 32;
|
|
274
|
-
const pendingCustomApiRegistrations = [];
|
|
275
|
-
function queueCustomApiRegistration(registry, api, streamFn) {
|
|
276
|
-
const existing = pendingCustomApiRegistrations.find((registration) => registration.registry === registry && registration.api === api);
|
|
277
|
-
if (existing) {
|
|
278
|
-
existing.streamFn = streamFn;
|
|
279
|
-
return false;
|
|
280
|
-
}
|
|
281
|
-
if (pendingCustomApiRegistrations.length >= MAX_PENDING_CUSTOM_API_REGISTRATIONS) throw new Error("Too many custom transport APIs were registered before host configuration");
|
|
282
|
-
pendingCustomApiRegistrations.push({
|
|
283
|
-
registry,
|
|
284
|
-
api,
|
|
285
|
-
streamFn
|
|
286
|
-
});
|
|
287
|
-
return false;
|
|
288
|
-
}
|
|
289
|
-
const inertAiTransportHost = {
|
|
290
|
-
buildModelFetch: () => void 0,
|
|
291
|
-
resolveSecretSentinel: (value) => value,
|
|
292
|
-
redactSecrets: (value) => value,
|
|
293
|
-
redactToolPayloadText: (text) => text,
|
|
294
|
-
normalizeAnthropicInlineContentBlocks: async (content) => [...content],
|
|
295
|
-
resolveOpenAIStrictToolSetting: (_model, options) => options?.supportsStrictMode ? false : void 0,
|
|
296
|
-
plugin: {
|
|
297
|
-
resolveProviderStream: () => void 0,
|
|
298
|
-
resolveTransportTurnState: () => void 0,
|
|
299
|
-
wrapSimpleCompletionStream: () => void 0,
|
|
300
|
-
createAnthropicVertexStream: () => {
|
|
301
|
-
throw new Error("Anthropic Vertex transport is not configured by the embedding host");
|
|
302
|
-
}
|
|
303
|
-
},
|
|
304
|
-
buildCopilotDynamicHeaders: () => ({}),
|
|
305
|
-
resolveProviderEndpointClass: () => "default",
|
|
306
|
-
resolveProviderRequestCapabilities: () => ({
|
|
307
|
-
endpointClass: "default",
|
|
308
|
-
knownProviderFamily: "",
|
|
309
|
-
supportsNativeStreamingUsageCompat: false,
|
|
310
|
-
supportsOpenAICompletionsStreamingUsageCompat: false,
|
|
311
|
-
usesExplicitProxyLikeEndpoint: false,
|
|
312
|
-
allowsAnthropicServiceTier: false
|
|
313
|
-
}),
|
|
314
|
-
resolveProviderRequestHeaders: ({ providerHeaders, callerHeaders, precedence }) => ({
|
|
315
|
-
...precedence === "caller-wins" ? providerHeaders : callerHeaders,
|
|
316
|
-
...precedence === "caller-wins" ? callerHeaders : providerHeaders
|
|
317
|
-
}),
|
|
318
|
-
resolveModelRequestTimeoutMs: () => void 0,
|
|
319
|
-
requiresManagedTransport: () => false,
|
|
320
|
-
inheritManagedTransport: (_source, target) => target,
|
|
321
|
-
transformTransportMessages: (messages, model, normalizeToolCallId) => transformMessages(messages, model, normalizeToolCallId),
|
|
322
|
-
registerCustomApi: queueCustomApiRegistration,
|
|
323
|
-
prepareGoogleSimpleCompletionModel: (_registry, model) => model,
|
|
324
|
-
logDebug: () => {},
|
|
325
|
-
logInfo: () => {},
|
|
326
|
-
logWarn: () => {}
|
|
327
|
-
};
|
|
328
|
-
let activeAiTransportHost = inertAiTransportHost;
|
|
329
|
-
/** Installs host implementations for the transport policy ports. */
|
|
330
|
-
function configureAiTransportHost(host) {
|
|
331
|
-
activeAiTransportHost = {
|
|
332
|
-
...inertAiTransportHost,
|
|
333
|
-
...host,
|
|
334
|
-
normalizeAnthropicInlineContentBlocks: host.normalizeAnthropicInlineContentBlocks ?? inertAiTransportHost.normalizeAnthropicInlineContentBlocks,
|
|
335
|
-
plugin: {
|
|
336
|
-
...inertAiTransportHost.plugin,
|
|
337
|
-
...host.plugin
|
|
338
|
-
}
|
|
339
|
-
};
|
|
340
|
-
const transportHost = activeAiTransportHost;
|
|
341
|
-
if (transportHost.registerCustomApi === inertAiTransportHost.registerCustomApi || pendingCustomApiRegistrations.length === 0) return;
|
|
342
|
-
const pending = pendingCustomApiRegistrations.splice(0);
|
|
343
|
-
for (const [index, registration] of pending.entries()) try {
|
|
344
|
-
transportHost.registerCustomApi(registration.registry, registration.api, registration.streamFn);
|
|
345
|
-
} catch (error) {
|
|
346
|
-
pendingCustomApiRegistrations.unshift(...pending.slice(index));
|
|
347
|
-
throw error;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
/** Returns the active transport host (inert defaults unless configured). */
|
|
351
|
-
function getAiTransportHost() {
|
|
352
|
-
return activeAiTransportHost;
|
|
353
|
-
}
|
|
354
|
-
/** Resolves sentinel substrings in custom headers at a no-fetch adapter boundary. */
|
|
355
|
-
function resolveAiTransportHeaderSentinels(headers) {
|
|
356
|
-
if (!headers) return;
|
|
357
|
-
const host = getAiTransportHost();
|
|
358
|
-
let resolvedHeaders;
|
|
359
|
-
for (const [name, value] of Object.entries(headers)) {
|
|
360
|
-
const resolved = host.resolveSecretSentinel(value);
|
|
361
|
-
if (resolved !== value) {
|
|
362
|
-
resolvedHeaders ??= { ...headers };
|
|
363
|
-
resolvedHeaders[name] = resolved;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
return resolvedHeaders ?? headers;
|
|
367
|
-
}
|
|
368
|
-
//#endregion
|
|
369
|
-
export { applyClaudeRequestContract as a, requiresClaudeAdaptiveThinking as c, usesClaudeStreamingRefusalContract as d, hasNonEmptyString as f, isRecord as g, readStringValue as h, transformMessages as i, resolveModelBoundThinkingReplayMode as l, normalizeOptionalString as m, getAiTransportHost as n, defaultsClaudeAdaptiveThinking as o, normalizeLowercaseStringOrEmpty as p, resolveAiTransportHeaderSentinels as r, prepareClaudeNoPrefillRequestContext as s, configureAiTransportHost as t, usesClaudeFable5MessagesContract as u };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { };
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
//#region packages/ai/src/internal/retry-after.d.ts
|
|
2
|
-
/** Parses the three HTTP-date forms accepted for Retry-After without Date.parse normalization. */
|
|
3
|
-
declare function parseRetryAfterHttpDateMs(value: string, nowMs?: number): number | undefined;
|
|
4
|
-
//#endregion
|
|
5
|
-
export { parseRetryAfterHttpDateMs };
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
//#region packages/ai/src/internal/retry-after.ts
|
|
2
|
-
const HTTP_DATE_MONTH_INDEX = new Map([
|
|
3
|
-
"Jan",
|
|
4
|
-
"Feb",
|
|
5
|
-
"Mar",
|
|
6
|
-
"Apr",
|
|
7
|
-
"May",
|
|
8
|
-
"Jun",
|
|
9
|
-
"Jul",
|
|
10
|
-
"Aug",
|
|
11
|
-
"Sep",
|
|
12
|
-
"Oct",
|
|
13
|
-
"Nov",
|
|
14
|
-
"Dec"
|
|
15
|
-
].map((month, index) => [month, index]));
|
|
16
|
-
const HTTP_DATE_SHORT_WEEKDAY_INDEX = new Map([
|
|
17
|
-
"Sun",
|
|
18
|
-
"Mon",
|
|
19
|
-
"Tue",
|
|
20
|
-
"Wed",
|
|
21
|
-
"Thu",
|
|
22
|
-
"Fri",
|
|
23
|
-
"Sat"
|
|
24
|
-
].map((weekday, index) => [weekday, index]));
|
|
25
|
-
const HTTP_DATE_LONG_WEEKDAY_INDEX = new Map([
|
|
26
|
-
"Sunday",
|
|
27
|
-
"Monday",
|
|
28
|
-
"Tuesday",
|
|
29
|
-
"Wednesday",
|
|
30
|
-
"Thursday",
|
|
31
|
-
"Friday",
|
|
32
|
-
"Saturday"
|
|
33
|
-
].map((weekday, index) => [weekday, index]));
|
|
34
|
-
const IMF_FIXDATE_RE = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d{2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{2}):(\d{2}):(\d{2}) GMT$/;
|
|
35
|
-
const OBSOLETE_RFC850_DATE_RE = /^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (\d{2})-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d{2}) (\d{2}):(\d{2}):(\d{2}) GMT$/;
|
|
36
|
-
const OBSOLETE_ASCTIME_DATE_RE = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{2}| \d) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/;
|
|
37
|
-
/** Parses the three HTTP-date forms accepted for Retry-After without Date.parse normalization. */
|
|
38
|
-
function parseRetryAfterHttpDateMs(value, nowMs = Date.now()) {
|
|
39
|
-
const imfFixdate = IMF_FIXDATE_RE.exec(value);
|
|
40
|
-
if (imfFixdate) return parseHttpDateComponentsMs({
|
|
41
|
-
weekday: HTTP_DATE_SHORT_WEEKDAY_INDEX.get(imfFixdate[1] ?? ""),
|
|
42
|
-
year: Number.parseInt(imfFixdate[4] ?? "", 10),
|
|
43
|
-
month: HTTP_DATE_MONTH_INDEX.get(imfFixdate[3] ?? ""),
|
|
44
|
-
day: Number.parseInt(imfFixdate[2] ?? "", 10),
|
|
45
|
-
hours: Number.parseInt(imfFixdate[5] ?? "", 10),
|
|
46
|
-
minutes: Number.parseInt(imfFixdate[6] ?? "", 10),
|
|
47
|
-
seconds: Number.parseInt(imfFixdate[7] ?? "", 10)
|
|
48
|
-
});
|
|
49
|
-
const rfc850Date = OBSOLETE_RFC850_DATE_RE.exec(value);
|
|
50
|
-
if (rfc850Date) {
|
|
51
|
-
const now = new Date(nowMs);
|
|
52
|
-
if (Number.isNaN(now.getTime())) return;
|
|
53
|
-
const shortYear = Number.parseInt(rfc850Date[4] ?? "", 10);
|
|
54
|
-
const candidateYear = Math.floor(now.getUTCFullYear() / 100) * 100 + shortYear;
|
|
55
|
-
const components = {
|
|
56
|
-
weekday: HTTP_DATE_LONG_WEEKDAY_INDEX.get(rfc850Date[1] ?? ""),
|
|
57
|
-
month: HTTP_DATE_MONTH_INDEX.get(rfc850Date[3] ?? ""),
|
|
58
|
-
day: Number.parseInt(rfc850Date[2] ?? "", 10),
|
|
59
|
-
hours: Number.parseInt(rfc850Date[5] ?? "", 10),
|
|
60
|
-
minutes: Number.parseInt(rfc850Date[6] ?? "", 10),
|
|
61
|
-
seconds: Number.parseInt(rfc850Date[7] ?? "", 10)
|
|
62
|
-
};
|
|
63
|
-
const candidate = parseHttpDateCalendarMs({
|
|
64
|
-
year: candidateYear,
|
|
65
|
-
...components
|
|
66
|
-
});
|
|
67
|
-
if (candidate === void 0) return;
|
|
68
|
-
return parseHttpDateComponentsMs({
|
|
69
|
-
year: candidate > Date.UTC(now.getUTCFullYear() + 50, now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), now.getUTCMilliseconds()) ? candidateYear - 100 : candidateYear,
|
|
70
|
-
...components
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
const asctimeDate = OBSOLETE_ASCTIME_DATE_RE.exec(value);
|
|
74
|
-
if (asctimeDate) return parseHttpDateComponentsMs({
|
|
75
|
-
weekday: HTTP_DATE_SHORT_WEEKDAY_INDEX.get(asctimeDate[1] ?? ""),
|
|
76
|
-
year: Number.parseInt(asctimeDate[7] ?? "", 10),
|
|
77
|
-
month: HTTP_DATE_MONTH_INDEX.get(asctimeDate[2] ?? ""),
|
|
78
|
-
day: Number.parseInt((asctimeDate[3] ?? "").trim(), 10),
|
|
79
|
-
hours: Number.parseInt(asctimeDate[4] ?? "", 10),
|
|
80
|
-
minutes: Number.parseInt(asctimeDate[5] ?? "", 10),
|
|
81
|
-
seconds: Number.parseInt(asctimeDate[6] ?? "", 10)
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
function parseHttpDateComponentsMs(components) {
|
|
85
|
-
const timestamp = parseHttpDateCalendarMs(components);
|
|
86
|
-
if (timestamp === void 0) return;
|
|
87
|
-
const weekdayTimestamp = components.seconds === 60 ? timestamp - 1e3 : timestamp;
|
|
88
|
-
if (new Date(weekdayTimestamp).getUTCDay() !== components.weekday) return;
|
|
89
|
-
return timestamp;
|
|
90
|
-
}
|
|
91
|
-
function parseHttpDateCalendarMs(components) {
|
|
92
|
-
const { year, month, day, hours, minutes, seconds } = components;
|
|
93
|
-
if (month === void 0 || !Number.isInteger(year) || year < 1900 || !Number.isInteger(day) || day < 1 || day > 31 || !Number.isInteger(hours) || hours < 0 || hours > 23 || !Number.isInteger(minutes) || minutes < 0 || minutes > 59 || !Number.isInteger(seconds) || seconds < 0 || seconds > 60) return;
|
|
94
|
-
const calendarSecond = Math.min(seconds, 59);
|
|
95
|
-
const timestamp = Date.UTC(year, month, day, hours, minutes, calendarSecond);
|
|
96
|
-
const parsedDate = new Date(timestamp);
|
|
97
|
-
if (parsedDate.getUTCFullYear() !== year || parsedDate.getUTCMonth() !== month || parsedDate.getUTCDate() !== day || parsedDate.getUTCHours() !== hours || parsedDate.getUTCMinutes() !== minutes || parsedDate.getUTCSeconds() !== calendarSecond) return;
|
|
98
|
-
return seconds === 60 ? timestamp + 1e3 : timestamp;
|
|
99
|
-
}
|
|
100
|
-
//#endregion
|
|
101
|
-
export { parseRetryAfterHttpDateMs };
|