@apifuse/provider-sdk 2.2.0-beta.62 → 2.2.0-beta.64
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/AUTHORING.md +367 -9
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/bin/apifuse-check.ts +84 -2
- package/bin/apifuse-dev.ts +11 -31
- package/bin/apifuse-migrate-deployment.ts +200 -0
- package/bin/apifuse-pack-check.ts +11 -4
- package/bin/apifuse-pack-types.ts +187 -4
- package/bin/apifuse-record.ts +44 -32
- package/bin/apifuse-submit-check.ts +9 -5
- package/bin/apifuse-test.ts +3 -1
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/commands.js +11 -0
- package/dist/cli/deployment-intent.d.ts +178 -0
- package/dist/cli/deployment-intent.js +277 -0
- package/dist/cli/migrate-deployment-intent.d.ts +132 -0
- package/dist/cli/migrate-deployment-intent.js +1552 -0
- package/dist/cli/migrate-provider-shape.d.ts +5 -1
- package/dist/cli/migrate-provider-shape.js +4 -2
- package/dist/cli/resolver-runtime.d.ts +21 -0
- package/dist/cli/resolver-runtime.js +31 -0
- package/dist/define.d.ts +3 -0
- package/dist/define.js +5 -0
- package/dist/dev.d.ts +3 -1
- package/dist/dev.js +6 -1
- package/dist/engine.d.ts +35 -1
- package/dist/engine.js +21 -2
- package/dist/error-resolution.d.ts +1 -0
- package/dist/error-resolution.js +54 -0
- package/dist/errors.d.ts +39 -1
- package/dist/errors.js +50 -0
- package/dist/handle-meta.d.ts +36 -1
- package/dist/handle-meta.js +16 -0
- package/dist/handle.d.ts +23 -5
- package/dist/handle.js +54 -8
- package/dist/health-scenario.d.ts +38 -0
- package/dist/i18n/error-messages.d.ts +86 -0
- package/dist/i18n/error-messages.js +192 -0
- package/dist/i18n/index.d.ts +1 -0
- package/dist/i18n/index.js +1 -0
- package/dist/i18n/keys.d.ts +12 -0
- package/dist/i18n/keys.js +76 -5
- package/dist/index.d.ts +11 -3
- package/dist/index.js +9 -1
- package/dist/lint.d.ts +15 -0
- package/dist/lint.js +469 -82
- package/dist/provider.d.ts +6 -6
- package/dist/provider.js +3 -3
- package/dist/runtime/browser-telemetry-binding.d.ts +5 -0
- package/dist/runtime/browser-telemetry-binding.js +83 -0
- package/dist/runtime/browser-telemetry.d.ts +76 -0
- package/dist/runtime/browser-telemetry.js +165 -0
- package/dist/runtime/browser.d.ts +3 -0
- package/dist/runtime/browser.js +208 -47
- package/dist/runtime/cache-telemetry.d.ts +71 -0
- package/dist/runtime/cache-telemetry.js +177 -0
- package/dist/runtime/cache.js +67 -7
- package/dist/runtime/capability-response.d.ts +3 -0
- package/dist/runtime/capability-response.js +56 -0
- package/dist/runtime/capability-telemetry.d.ts +46 -0
- package/dist/runtime/capability-telemetry.js +68 -0
- package/dist/runtime/diagnostic-env.d.ts +3 -0
- package/dist/runtime/diagnostic-env.js +10 -1
- package/dist/runtime/engine-mode.d.ts +74 -0
- package/dist/runtime/engine-mode.js +152 -0
- package/dist/runtime/handle.js +9 -1
- package/dist/runtime/http-telemetry-guard.d.ts +10 -0
- package/dist/runtime/http-telemetry-guard.js +62 -10
- package/dist/runtime/http.js +141 -35
- package/dist/runtime/instrumentation.js +92 -13
- package/dist/runtime/ocr-telemetry.d.ts +82 -0
- package/dist/runtime/ocr-telemetry.js +192 -0
- package/dist/runtime/ocr.js +35 -8
- package/dist/runtime/request-telemetry.d.ts +2 -0
- package/dist/runtime/request-telemetry.js +2 -1
- package/dist/runtime/resolver-runtime-options.d.ts +14 -0
- package/dist/runtime/resolver-runtime-options.js +33 -0
- package/dist/runtime/resolver-shared.d.ts +3 -2
- package/dist/runtime/resolver-shared.js +4 -4
- package/dist/runtime/resolver-telemetry.d.ts +1 -0
- package/dist/runtime/resolver-telemetry.js +1 -1
- package/dist/runtime/resolver-vendors/browser.d.ts +2 -0
- package/dist/runtime/resolver-vendors/browser.js +46 -0
- package/dist/runtime/resolver-vendors/hosts.d.ts +21 -0
- package/dist/runtime/resolver-vendors/hosts.js +35 -0
- package/dist/runtime/resolver-vendors/hypersolutions.js +2 -2
- package/dist/runtime/resolver-vendors/types.d.ts +5 -4
- package/dist/runtime/resolver.d.ts +4 -1
- package/dist/runtime/resolver.js +46 -13
- package/dist/runtime/state-telemetry.d.ts +79 -0
- package/dist/runtime/state-telemetry.js +194 -0
- package/dist/runtime/state.d.ts +3 -0
- package/dist/runtime/state.js +26 -7
- package/dist/runtime/stealth-cookies.d.ts +5 -1
- package/dist/runtime/stealth-cookies.js +21 -1
- package/dist/runtime/stealth-owned-headers.d.ts +26 -0
- package/dist/runtime/stealth-owned-headers.js +37 -0
- package/dist/runtime/stealth-telemetry.d.ts +92 -0
- package/dist/runtime/stealth-telemetry.js +179 -0
- package/dist/runtime/stealth.d.ts +4 -1
- package/dist/runtime/stealth.js +228 -85
- package/dist/runtime/stt-telemetry.d.ts +77 -0
- package/dist/runtime/stt-telemetry.js +176 -0
- package/dist/runtime/stt.js +15 -6
- package/dist/runtime-boundary-lint.d.ts +132 -0
- package/dist/runtime-boundary-lint.js +586 -0
- package/dist/server/error-stack-frames.d.ts +35 -0
- package/dist/server/error-stack-frames.js +219 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.js +4 -0
- package/dist/server/sdk-version.d.ts +3 -0
- package/dist/server/sdk-version.js +19 -0
- package/dist/server/self-test.js +1 -18
- package/dist/server/sensitive-values.d.ts +1 -1
- package/dist/server/sensitive-values.js +9 -0
- package/dist/server/serve-implementation.d.ts +51 -2
- package/dist/server/serve-implementation.js +337 -90
- package/dist/server/types.d.ts +1 -0
- package/dist/server/types.js +7 -0
- package/dist/stateful/stateful-provider-owner-forwarder.js +22 -0
- package/dist/stateful/stateful-provider-runtime-context.d.ts +3 -0
- package/dist/stateful/stateful-provider-runtime-context.js +1 -0
- package/dist/types.d.ts +123 -1
- package/dist/typescript-module.d.ts +39 -0
- package/dist/typescript-module.js +72 -0
- package/package.json +6 -1
- package/src/cli/commands.ts +14 -0
- package/src/cli/deployment-intent.ts +364 -0
- package/src/cli/migrate-deployment-intent.ts +1908 -0
- package/src/cli/migrate-provider-shape.ts +10 -4
- package/src/cli/resolver-runtime.ts +72 -0
- package/src/define.ts +13 -0
- package/src/dev.ts +9 -2
- package/src/engine.ts +38 -2
- package/src/error-resolution.ts +58 -0
- package/src/errors.ts +77 -1
- package/src/handle-meta.ts +51 -1
- package/src/handle.ts +92 -10
- package/src/health-scenario.ts +38 -0
- package/src/i18n/error-messages.ts +255 -0
- package/src/i18n/index.ts +1 -0
- package/src/i18n/keys.ts +80 -6
- package/src/index.ts +86 -0
- package/src/lint.ts +604 -91
- package/src/provider.ts +12 -0
- package/src/runtime/browser-telemetry-binding.ts +92 -0
- package/src/runtime/browser-telemetry.ts +289 -0
- package/src/runtime/browser.ts +249 -65
- package/src/runtime/cache-telemetry.ts +247 -0
- package/src/runtime/cache.ts +68 -17
- package/src/runtime/capability-response.ts +53 -0
- package/src/runtime/capability-telemetry.ts +101 -0
- package/src/runtime/diagnostic-env.ts +11 -1
- package/src/runtime/engine-mode.ts +233 -0
- package/src/runtime/handle.ts +9 -1
- package/src/runtime/http-telemetry-guard.ts +66 -13
- package/src/runtime/http.ts +168 -37
- package/src/runtime/instrumentation.ts +105 -16
- package/src/runtime/ocr-telemetry.ts +308 -0
- package/src/runtime/ocr.ts +114 -74
- package/src/runtime/request-telemetry.ts +2 -1
- package/src/runtime/resolver-runtime-options.ts +50 -0
- package/src/runtime/resolver-shared.ts +9 -4
- package/src/runtime/resolver-telemetry.ts +1 -1
- package/src/runtime/resolver-vendors/browser.ts +65 -7
- package/src/runtime/resolver-vendors/hosts.ts +43 -0
- package/src/runtime/resolver-vendors/hypersolutions.ts +2 -2
- package/src/runtime/resolver-vendors/types.ts +5 -4
- package/src/runtime/resolver.ts +64 -21
- package/src/runtime/state-telemetry.ts +298 -0
- package/src/runtime/state.ts +46 -45
- package/src/runtime/stealth-cookies.ts +24 -1
- package/src/runtime/stealth-owned-headers.ts +41 -0
- package/src/runtime/stealth-telemetry.ts +304 -0
- package/src/runtime/stealth.ts +355 -150
- package/src/runtime/stt-telemetry.ts +282 -0
- package/src/runtime/stt.ts +93 -71
- package/src/runtime-boundary-lint.ts +703 -0
- package/src/server/error-stack-frames.ts +214 -0
- package/src/server/index.ts +53 -0
- package/src/server/sdk-version.ts +22 -0
- package/src/server/self-test.ts +1 -21
- package/src/server/sensitive-values.ts +14 -0
- package/src/server/serve-implementation.ts +569 -108
- package/src/server/types.ts +7 -0
- package/src/stateful/stateful-provider-owner-forwarder.ts +23 -0
- package/src/stateful/stateful-provider-runtime-context.ts +4 -0
- package/src/types.ts +128 -1
- package/src/typescript-module.ts +100 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +0 -10
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-a.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-b.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-barrel.ts.txt +0 -2
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-computed.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-a.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-b.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-barrel.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-catalog.ts.txt +0 -19
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-docs.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-stores.ts.txt +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-indirect-config.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-nonstatic.ts.txt +0 -4
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-package-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-leaf.ts.txt +0 -10
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-one.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-two.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-one.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-two.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-mixed-index.ts.txt +0 -14
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-registry.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-barrel.ts.txt +0 -2
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-leaf.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-hoisted-array-spread.ts.txt +0 -15
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-imported-array-spread.ts.txt +0 -9
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-kebab-operation-id.ts.txt +0 -17
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt +0 -24
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +0 -16
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-snake-operation-id.ts.txt +0 -21
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-duplicate-provider.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-id-unresolved.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-many.ts.txt +0 -18
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-one.ts.txt +0 -13
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +0 -31
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +0 -21
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +0 -14
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-en.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ja.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ko.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-existing-operation-namespace-en.json +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-binding-ambiguous.ts.txt +0 -12
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported-other.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-key-ambiguous.ts.txt +0 -19
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-shorthand.ts.txt +0 -9
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-typed.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-unrelated.ts.txt +0 -13
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +0 -15
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +0 -4
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +0 -12
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import type { OcrContext } from "../types.js";
|
|
2
|
+
import {
|
|
3
|
+
add,
|
|
4
|
+
capabilityErrorText,
|
|
5
|
+
capabilityFacts,
|
|
6
|
+
capabilityMetadata,
|
|
7
|
+
capabilityText,
|
|
8
|
+
inputBytes,
|
|
9
|
+
integer,
|
|
10
|
+
observeCapability,
|
|
11
|
+
registerCapabilityInput,
|
|
12
|
+
} from "./capability-telemetry.js";
|
|
13
|
+
import {
|
|
14
|
+
type ClosedEnum,
|
|
15
|
+
closedEnum,
|
|
16
|
+
type SpanIndex,
|
|
17
|
+
type TelemetryContributor,
|
|
18
|
+
} from "./request-telemetry.js";
|
|
19
|
+
export type OcrTelemetryBackend =
|
|
20
|
+
| "cloudflare-workers-ai"
|
|
21
|
+
| "openai-compatible"
|
|
22
|
+
| "custom"
|
|
23
|
+
| "unavailable";
|
|
24
|
+
export type OcrTelemetryEngine = "workers-ai" | "openai-compatible" | "custom";
|
|
25
|
+
export type OcrTelemetryErrorCode =
|
|
26
|
+
| "OCR_UNAVAILABLE"
|
|
27
|
+
| "UNSUPPORTED_OCR_BACKEND"
|
|
28
|
+
| "OCR_UPSTREAM_FAILED"
|
|
29
|
+
| "OCR_INCOMPLETE_RESPONSE"
|
|
30
|
+
| "transport_network_error"
|
|
31
|
+
| "transport_timeout"
|
|
32
|
+
| "other";
|
|
33
|
+
export type OcrTelemetryModel =
|
|
34
|
+
| "gemma-4-26b-a4b-it"
|
|
35
|
+
| "glm-ocr"
|
|
36
|
+
| "moondream3.1-9B-A2B"
|
|
37
|
+
| "kimi-k2.7-code";
|
|
38
|
+
export type OcrTelemetryFinishReason =
|
|
39
|
+
| "stop"
|
|
40
|
+
| "length"
|
|
41
|
+
| "content_filter"
|
|
42
|
+
| "tool_calls"
|
|
43
|
+
| "function_call"
|
|
44
|
+
| "error"
|
|
45
|
+
| "unknown";
|
|
46
|
+
const ERROR_CODES: ReadonlySet<string> = new Set([
|
|
47
|
+
"OCR_UNAVAILABLE",
|
|
48
|
+
"UNSUPPORTED_OCR_BACKEND",
|
|
49
|
+
"OCR_UPSTREAM_FAILED",
|
|
50
|
+
"OCR_INCOMPLETE_RESPONSE",
|
|
51
|
+
"transport_network_error",
|
|
52
|
+
"transport_timeout",
|
|
53
|
+
"other",
|
|
54
|
+
]);
|
|
55
|
+
const MODELS = new Map<string, OcrTelemetryModel>([
|
|
56
|
+
["@cf/google/gemma-4-26b-a4b-it", "gemma-4-26b-a4b-it"],
|
|
57
|
+
["zai-org/GLM-OCR", "glm-ocr"],
|
|
58
|
+
["@cf/moondream/moondream3.1-9B-A2B", "moondream3.1-9B-A2B"],
|
|
59
|
+
["@cf/moonshotai/kimi-k2.7-code", "kimi-k2.7-code"],
|
|
60
|
+
]);
|
|
61
|
+
function errorCode(error: unknown): OcrTelemetryErrorCode {
|
|
62
|
+
const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
|
|
63
|
+
return typeof code === "string" && ERROR_CODES.has(code)
|
|
64
|
+
? (code as OcrTelemetryErrorCode)
|
|
65
|
+
: "other";
|
|
66
|
+
}
|
|
67
|
+
function finishReason(value: string | undefined, failed: boolean): OcrTelemetryFinishReason {
|
|
68
|
+
switch (value) {
|
|
69
|
+
case "stop":
|
|
70
|
+
case "length":
|
|
71
|
+
case "content_filter":
|
|
72
|
+
case "tool_calls":
|
|
73
|
+
case "function_call":
|
|
74
|
+
return value;
|
|
75
|
+
default:
|
|
76
|
+
return value === undefined ? (failed ? "error" : "stop") : "unknown";
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export type OcrTelemetryEvent = {
|
|
80
|
+
backend: OcrTelemetryBackend;
|
|
81
|
+
engine: OcrTelemetryEngine;
|
|
82
|
+
model?: string;
|
|
83
|
+
ms: number;
|
|
84
|
+
status?: number;
|
|
85
|
+
bytesIn?: number;
|
|
86
|
+
bytesOut?: number;
|
|
87
|
+
candidates?: number;
|
|
88
|
+
warnings?: number;
|
|
89
|
+
errorCode?: OcrTelemetryErrorCode;
|
|
90
|
+
diagnostics?: string;
|
|
91
|
+
finishReason?: OcrTelemetryFinishReason;
|
|
92
|
+
};
|
|
93
|
+
export interface OcrTelemetrySink {
|
|
94
|
+
record(event: OcrTelemetryEvent): void;
|
|
95
|
+
markTelemetryFailed?(): void;
|
|
96
|
+
}
|
|
97
|
+
export type OcrTelemetryLogPayload = {
|
|
98
|
+
telemetryFailed?: true;
|
|
99
|
+
diagnostics?: string[];
|
|
100
|
+
backend: OcrTelemetryBackend;
|
|
101
|
+
engine: OcrTelemetryEngine;
|
|
102
|
+
model?: string;
|
|
103
|
+
ms: number;
|
|
104
|
+
status?: number;
|
|
105
|
+
bytesIn: number;
|
|
106
|
+
bytesOut: number;
|
|
107
|
+
candidates: number;
|
|
108
|
+
warnings: number;
|
|
109
|
+
lastErrorCode?: OcrTelemetryErrorCode;
|
|
110
|
+
finishReason?: OcrTelemetryFinishReason;
|
|
111
|
+
samples?: Array<Omit<OcrTelemetryEvent, "backend" | "engine" | "model" | "diagnostics">>;
|
|
112
|
+
samplesDropped?: number;
|
|
113
|
+
};
|
|
114
|
+
export type OcrTelemetryHeaderPayload = {
|
|
115
|
+
backend: ClosedEnum<OcrTelemetryBackend>;
|
|
116
|
+
engine: ClosedEnum<OcrTelemetryEngine>;
|
|
117
|
+
model?: ClosedEnum<OcrTelemetryModel>;
|
|
118
|
+
ms: number;
|
|
119
|
+
status?: number;
|
|
120
|
+
bytesIn: number;
|
|
121
|
+
bytesOut: number;
|
|
122
|
+
candidates: number;
|
|
123
|
+
warnings: number;
|
|
124
|
+
lastErrorCode?: ClosedEnum<OcrTelemetryErrorCode>;
|
|
125
|
+
finishReason?: ClosedEnum<OcrTelemetryFinishReason>;
|
|
126
|
+
samples?: Array<{
|
|
127
|
+
ms: number;
|
|
128
|
+
status?: number;
|
|
129
|
+
bytesIn?: number;
|
|
130
|
+
bytesOut?: number;
|
|
131
|
+
candidates?: number;
|
|
132
|
+
warnings?: number;
|
|
133
|
+
errorCode?: ClosedEnum<OcrTelemetryErrorCode>;
|
|
134
|
+
finishReason?: ClosedEnum<OcrTelemetryFinishReason>;
|
|
135
|
+
}>;
|
|
136
|
+
samplesDropped?: number;
|
|
137
|
+
};
|
|
138
|
+
export class OcrTelemetryCollector
|
|
139
|
+
implements
|
|
140
|
+
OcrTelemetrySink,
|
|
141
|
+
TelemetryContributor<OcrTelemetryLogPayload, OcrTelemetryHeaderPayload>
|
|
142
|
+
{
|
|
143
|
+
readonly key = "ocr" as const;
|
|
144
|
+
readonly #redact?: (text: string) => string;
|
|
145
|
+
#samples: NonNullable<OcrTelemetryLogPayload["samples"]> = [];
|
|
146
|
+
#summary: Omit<OcrTelemetryLogPayload, "samples" | "samplesDropped"> | undefined;
|
|
147
|
+
#diagnostics: string[] = [];
|
|
148
|
+
#dropped = 0;
|
|
149
|
+
#failed = false;
|
|
150
|
+
constructor(options: { redact?: (text: string) => string } = {}) {
|
|
151
|
+
this.#redact = options.redact;
|
|
152
|
+
}
|
|
153
|
+
markTelemetryFailed(): void {
|
|
154
|
+
this.#failed = true;
|
|
155
|
+
this.#summary ??= {
|
|
156
|
+
backend: "custom",
|
|
157
|
+
engine: "custom",
|
|
158
|
+
ms: 0,
|
|
159
|
+
bytesIn: 0,
|
|
160
|
+
bytesOut: 0,
|
|
161
|
+
candidates: 0,
|
|
162
|
+
warnings: 0,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
record(event: OcrTelemetryEvent): void {
|
|
166
|
+
const sample = {
|
|
167
|
+
ms: integer(event.ms),
|
|
168
|
+
...(event.status === undefined ? {} : { status: integer(event.status) }),
|
|
169
|
+
...(event.bytesIn === undefined ? {} : { bytesIn: integer(event.bytesIn) }),
|
|
170
|
+
...(event.bytesOut === undefined ? {} : { bytesOut: integer(event.bytesOut) }),
|
|
171
|
+
...(event.candidates === undefined ? {} : { candidates: integer(event.candidates) }),
|
|
172
|
+
...(event.warnings === undefined ? {} : { warnings: integer(event.warnings) }),
|
|
173
|
+
...(event.errorCode ? { errorCode: event.errorCode } : {}),
|
|
174
|
+
...(event.finishReason ? { finishReason: event.finishReason } : {}),
|
|
175
|
+
...(event.diagnostics === undefined
|
|
176
|
+
? {}
|
|
177
|
+
: { diagnostics: capabilityText(event.diagnostics, this.#redact, true) }),
|
|
178
|
+
};
|
|
179
|
+
const prior = this.#summary;
|
|
180
|
+
this.#summary = {
|
|
181
|
+
backend: event.backend,
|
|
182
|
+
engine: event.engine,
|
|
183
|
+
...(event.model === undefined ? {} : { model: capabilityText(event.model, this.#redact) }),
|
|
184
|
+
ms: add(prior?.ms ?? 0, sample.ms),
|
|
185
|
+
...(sample.status === undefined ? {} : { status: sample.status }),
|
|
186
|
+
bytesIn: add(prior?.bytesIn ?? 0, sample.bytesIn ?? 0),
|
|
187
|
+
bytesOut: add(prior?.bytesOut ?? 0, sample.bytesOut ?? 0),
|
|
188
|
+
candidates: add(prior?.candidates ?? 0, sample.candidates ?? 0),
|
|
189
|
+
warnings: add(prior?.warnings ?? 0, sample.warnings ?? 0),
|
|
190
|
+
...(event.errorCode ? { lastErrorCode: event.errorCode } : {}),
|
|
191
|
+
...(event.finishReason ? { finishReason: event.finishReason } : {}),
|
|
192
|
+
};
|
|
193
|
+
if (this.#samples.length < 24) {
|
|
194
|
+
const { diagnostics, ...closedSample } = sample;
|
|
195
|
+
this.#samples.push(closedSample);
|
|
196
|
+
if (diagnostics !== undefined) this.#diagnostics.push(diagnostics);
|
|
197
|
+
} else this.#dropped = add(this.#dropped, 1);
|
|
198
|
+
}
|
|
199
|
+
toLogPayload(_spans: SpanIndex): OcrTelemetryLogPayload | undefined {
|
|
200
|
+
if (!this.#summary) return undefined;
|
|
201
|
+
return {
|
|
202
|
+
...this.#summary,
|
|
203
|
+
...(this.#diagnostics.length ? { diagnostics: [...this.#diagnostics] } : {}),
|
|
204
|
+
...(this.#failed ? { telemetryFailed: true as const } : {}),
|
|
205
|
+
samples: this.#samples.map((s) => ({ ...s })),
|
|
206
|
+
...(this.#dropped ? { samplesDropped: this.#dropped } : {}),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
toHeaderPayload(log: OcrTelemetryLogPayload): OcrTelemetryHeaderPayload {
|
|
210
|
+
return {
|
|
211
|
+
backend: closedEnum(log.backend),
|
|
212
|
+
engine: closedEnum(log.engine),
|
|
213
|
+
...(log.model && MODELS.has(log.model) ? { model: closedEnum(MODELS.get(log.model)!) } : {}),
|
|
214
|
+
ms: log.ms,
|
|
215
|
+
...(log.status === undefined ? {} : { status: log.status }),
|
|
216
|
+
bytesIn: log.bytesIn,
|
|
217
|
+
bytesOut: log.bytesOut,
|
|
218
|
+
candidates: log.candidates,
|
|
219
|
+
warnings: log.warnings,
|
|
220
|
+
...(log.lastErrorCode ? { lastErrorCode: closedEnum(log.lastErrorCode) } : {}),
|
|
221
|
+
...(log.finishReason ? { finishReason: closedEnum(log.finishReason) } : {}),
|
|
222
|
+
...(log.samples
|
|
223
|
+
? {
|
|
224
|
+
samples: log.samples.map((s) => ({
|
|
225
|
+
ms: s.ms,
|
|
226
|
+
...(s.status === undefined ? {} : { status: s.status }),
|
|
227
|
+
...(s.bytesIn === undefined ? {} : { bytesIn: s.bytesIn }),
|
|
228
|
+
...(s.bytesOut === undefined ? {} : { bytesOut: s.bytesOut }),
|
|
229
|
+
...(s.candidates === undefined ? {} : { candidates: s.candidates }),
|
|
230
|
+
...(s.warnings === undefined ? {} : { warnings: s.warnings }),
|
|
231
|
+
...(s.errorCode ? { errorCode: closedEnum(s.errorCode) } : {}),
|
|
232
|
+
...(s.finishReason ? { finishReason: closedEnum(s.finishReason) } : {}),
|
|
233
|
+
})),
|
|
234
|
+
}
|
|
235
|
+
: {}),
|
|
236
|
+
...(log.samplesDropped ? { samplesDropped: log.samplesDropped } : {}),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
export function bindOcrTelemetry(
|
|
241
|
+
context: OcrContext,
|
|
242
|
+
sink: OcrTelemetrySink,
|
|
243
|
+
options: { backend?: OcrTelemetryBackend; engine?: OcrTelemetryEngine; model?: string } = {},
|
|
244
|
+
): OcrContext {
|
|
245
|
+
const metadata = capabilityMetadata(context);
|
|
246
|
+
const backend =
|
|
247
|
+
options.backend ?? (metadata?.backend as OcrTelemetryBackend | undefined) ?? "custom";
|
|
248
|
+
const engine = options.engine ?? (metadata?.engine as OcrTelemetryEngine | undefined) ?? "custom";
|
|
249
|
+
const model = options.model ?? metadata?.model;
|
|
250
|
+
async function run<
|
|
251
|
+
T extends {
|
|
252
|
+
text: string;
|
|
253
|
+
model: string;
|
|
254
|
+
candidates?: readonly unknown[];
|
|
255
|
+
warnings?: readonly unknown[];
|
|
256
|
+
},
|
|
257
|
+
>(input: { kind: string; data?: string; url?: string }, operation: () => Promise<T>): Promise<T> {
|
|
258
|
+
const started = performance.now();
|
|
259
|
+
const facts: { status?: number; finishReason?: string; diagnostics?: string } = {};
|
|
260
|
+
observeCapability(sink, () => registerCapabilityInput(input));
|
|
261
|
+
let result: T;
|
|
262
|
+
try {
|
|
263
|
+
result = await capabilityFacts.run(facts, operation);
|
|
264
|
+
} catch (error) {
|
|
265
|
+
observeCapability(sink, () => {
|
|
266
|
+
const status =
|
|
267
|
+
error &&
|
|
268
|
+
typeof error === "object" &&
|
|
269
|
+
"status" in error &&
|
|
270
|
+
typeof error.status === "number"
|
|
271
|
+
? error.status
|
|
272
|
+
: undefined;
|
|
273
|
+
return sink.record({
|
|
274
|
+
backend,
|
|
275
|
+
engine,
|
|
276
|
+
model,
|
|
277
|
+
ms: performance.now() - started,
|
|
278
|
+
status: facts.status ?? status,
|
|
279
|
+
bytesIn: inputBytes(input),
|
|
280
|
+
errorCode: errorCode(error),
|
|
281
|
+
finishReason: finishReason(facts.finishReason, true),
|
|
282
|
+
diagnostics: `${capabilityErrorText(error)} ${facts.diagnostics ?? ""}`,
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
throw error;
|
|
286
|
+
}
|
|
287
|
+
observeCapability(sink, () =>
|
|
288
|
+
sink.record({
|
|
289
|
+
backend,
|
|
290
|
+
engine,
|
|
291
|
+
model: result.model,
|
|
292
|
+
ms: performance.now() - started,
|
|
293
|
+
status: facts.status,
|
|
294
|
+
bytesIn: inputBytes(input),
|
|
295
|
+
bytesOut: Buffer.byteLength(result.text),
|
|
296
|
+
candidates: result.candidates?.length ?? 0,
|
|
297
|
+
finishReason: finishReason(facts.finishReason, false),
|
|
298
|
+
warnings: result.warnings?.length ?? 0,
|
|
299
|
+
}),
|
|
300
|
+
);
|
|
301
|
+
return result;
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
...context,
|
|
305
|
+
recognize: (request) => run(request.image, () => context.recognize(request)),
|
|
306
|
+
extractCaptchaText: (image, opts) => run(image, () => context.extractCaptchaText(image, opts)),
|
|
307
|
+
};
|
|
308
|
+
}
|
package/src/runtime/ocr.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { readDiagnosticEnv } from "./diagnostic-env.js";
|
|
2
1
|
import { ProviderError, TransportError } from "../errors.js";
|
|
3
2
|
import type {
|
|
4
3
|
OcrCaptchaCandidate,
|
|
@@ -10,6 +9,13 @@ import type {
|
|
|
10
9
|
OcrResult,
|
|
11
10
|
ProviderOcrConfig,
|
|
12
11
|
} from "../types.js";
|
|
12
|
+
import { readCapabilityErrorBody } from "./capability-response.js";
|
|
13
|
+
import {
|
|
14
|
+
captureCapability,
|
|
15
|
+
registerCapabilityInput,
|
|
16
|
+
tagCapability,
|
|
17
|
+
} from "./capability-telemetry.js";
|
|
18
|
+
import { readDiagnosticEnv, registerDiagnosticValue } from "./diagnostic-env.js";
|
|
13
19
|
import { CLOUDFLARE_ACCOUNT_ID_ENV } from "./stt.js";
|
|
14
20
|
import { createTimeoutController, isTimeoutLikeError } from "./timeout.js";
|
|
15
21
|
|
|
@@ -78,14 +84,21 @@ function createErrorOcrClient(options: ErrorOcrClientOptions): OcrContext {
|
|
|
78
84
|
fix: options.fix,
|
|
79
85
|
});
|
|
80
86
|
};
|
|
81
|
-
return
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
return tagCapability(
|
|
88
|
+
{
|
|
89
|
+
// Own data property: `bindOcrTelemetry` re-spreads the context, so a
|
|
90
|
+
// getter or prototype member would silently vanish before reaching
|
|
91
|
+
// provider code.
|
|
92
|
+
available: false,
|
|
93
|
+
async recognize() {
|
|
94
|
+
return unavailable();
|
|
95
|
+
},
|
|
96
|
+
async extractCaptchaText() {
|
|
97
|
+
return unavailable();
|
|
98
|
+
},
|
|
87
99
|
},
|
|
88
|
-
|
|
100
|
+
{ backend: "unavailable", engine: "custom" },
|
|
101
|
+
);
|
|
89
102
|
}
|
|
90
103
|
|
|
91
104
|
export function createUnsupportedOcrClient(reason?: string): OcrContext {
|
|
@@ -249,6 +262,8 @@ function responseContent(payload: unknown, cloudflare: boolean, model: string):
|
|
|
249
262
|
const choices = root?.choices;
|
|
250
263
|
if (!Array.isArray(choices)) return undefined;
|
|
251
264
|
const choice = unknownRecord(choices[0]);
|
|
265
|
+
if (typeof choice?.finish_reason === "string")
|
|
266
|
+
captureCapability({ finishReason: choice.finish_reason });
|
|
252
267
|
if (typeof choice?.finish_reason === "string" && choice.finish_reason !== "stop") {
|
|
253
268
|
throw incompleteResponseError(model, choice.finish_reason);
|
|
254
269
|
}
|
|
@@ -305,7 +320,11 @@ function moondreamSseContent(body: string, model: string): string | undefined {
|
|
|
305
320
|
terminalFinishReason = chunk.finish_reason;
|
|
306
321
|
}
|
|
307
322
|
}
|
|
308
|
-
if (finalAnswer)
|
|
323
|
+
if (finalAnswer) {
|
|
324
|
+
captureCapability({ finishReason: "stop" });
|
|
325
|
+
return finalAnswer;
|
|
326
|
+
}
|
|
327
|
+
if (terminalFinishReason) captureCapability({ finishReason: terminalFinishReason });
|
|
309
328
|
if (terminalFinishReason) throw incompleteResponseError(model, terminalFinishReason);
|
|
310
329
|
if (firstDecodingFailure) throw malformedResponseError(model, firstDecodingFailure);
|
|
311
330
|
return finalAnswer;
|
|
@@ -340,6 +359,7 @@ function createOcrClient(
|
|
|
340
359
|
recognize: (request: OcrRecognizeRequest) => Promise<OcrResult>,
|
|
341
360
|
): OcrContext {
|
|
342
361
|
return {
|
|
362
|
+
available: true,
|
|
343
363
|
recognize,
|
|
344
364
|
async extractCaptchaText(image, options = {}): Promise<OcrCaptchaResult> {
|
|
345
365
|
const result = await recognize({ image, hint: "captcha" });
|
|
@@ -361,48 +381,57 @@ export function createCloudflareWorkersAiOcrClient(
|
|
|
361
381
|
): OcrContext {
|
|
362
382
|
const model = options.model ?? DEFAULT_CLOUDFLARE_WORKERS_AI_OCR_MODEL;
|
|
363
383
|
const runFetch = options.fetch ?? fetch;
|
|
364
|
-
return
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
384
|
+
return tagCapability(
|
|
385
|
+
createOcrClient(model, async (request) => {
|
|
386
|
+
registerCapabilityInput(request.image);
|
|
387
|
+
registerDiagnosticValue(options.apiToken);
|
|
388
|
+
registerDiagnosticValue(`Bearer ${options.apiToken}`);
|
|
389
|
+
const timeout = createTimeoutController(request.timeoutMs ?? DEFAULT_OCR_TIMEOUT_MS);
|
|
368
390
|
try {
|
|
369
|
-
response
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
391
|
+
let response: Response;
|
|
392
|
+
try {
|
|
393
|
+
response = await runFetch(
|
|
394
|
+
`https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(options.accountId)}/ai/run/${model}`,
|
|
395
|
+
{
|
|
396
|
+
method: "POST",
|
|
397
|
+
headers: {
|
|
398
|
+
Authorization: `Bearer ${options.apiToken}`,
|
|
399
|
+
"Content-Type": "application/json",
|
|
400
|
+
},
|
|
401
|
+
body: JSON.stringify(
|
|
402
|
+
isMoondreamModel(model)
|
|
403
|
+
? moondreamPayload(request)
|
|
404
|
+
: cloudflareMessagesPayload(request, model),
|
|
405
|
+
),
|
|
406
|
+
signal: timeout.controller.signal,
|
|
376
407
|
},
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
408
|
+
);
|
|
409
|
+
} catch (error) {
|
|
410
|
+
throw toOcrTransportError(error);
|
|
411
|
+
}
|
|
412
|
+
captureCapability({ status: response.status });
|
|
413
|
+
if (!response.ok) {
|
|
414
|
+
const echoed = await readCapabilityErrorBody(response, timeout.controller.signal);
|
|
415
|
+
captureCapability({ diagnostics: echoed });
|
|
416
|
+
throw new TransportError("OCR upstream request failed", {
|
|
417
|
+
code: "OCR_UPSTREAM_FAILED",
|
|
418
|
+
status: response.status,
|
|
419
|
+
upstreamStatus: response.status,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
const text = isMoondreamModel(model)
|
|
423
|
+
? moondreamSseContent(await response.text(), model)
|
|
424
|
+
: responseContent(await responseJson(response, model), true, model);
|
|
425
|
+
if (!text) throw emptyResponseError(model);
|
|
426
|
+
return { text, model };
|
|
385
427
|
} catch (error) {
|
|
386
428
|
throw toOcrTransportError(error);
|
|
429
|
+
} finally {
|
|
430
|
+
timeout.clear();
|
|
387
431
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
status: response.status,
|
|
392
|
-
upstreamStatus: response.status,
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
const text = isMoondreamModel(model)
|
|
396
|
-
? moondreamSseContent(await response.text(), model)
|
|
397
|
-
: responseContent(await responseJson(response, model), true, model);
|
|
398
|
-
if (!text) throw emptyResponseError(model);
|
|
399
|
-
return { text, model };
|
|
400
|
-
} catch (error) {
|
|
401
|
-
throw toOcrTransportError(error);
|
|
402
|
-
} finally {
|
|
403
|
-
timeout.clear();
|
|
404
|
-
}
|
|
405
|
-
});
|
|
432
|
+
}),
|
|
433
|
+
{ backend: "cloudflare-workers-ai", engine: "workers-ai", model },
|
|
434
|
+
);
|
|
406
435
|
}
|
|
407
436
|
|
|
408
437
|
export function createOpenAiCompatibleOcrClient(
|
|
@@ -410,38 +439,49 @@ export function createOpenAiCompatibleOcrClient(
|
|
|
410
439
|
): OcrContext {
|
|
411
440
|
const model = options.model;
|
|
412
441
|
const runFetch = options.fetch ?? fetch;
|
|
413
|
-
return
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
442
|
+
return tagCapability(
|
|
443
|
+
createOcrClient(model, async (request) => {
|
|
444
|
+
registerCapabilityInput(request.image);
|
|
445
|
+
if (options.apiKey) {
|
|
446
|
+
registerDiagnosticValue(options.apiKey);
|
|
447
|
+
registerDiagnosticValue(`Bearer ${options.apiKey}`);
|
|
448
|
+
}
|
|
449
|
+
const headers: Record<string, string> = { "Content-Type": "application/json" };
|
|
450
|
+
if (options.apiKey) headers.Authorization = `Bearer ${options.apiKey}`;
|
|
451
|
+
const timeout = createTimeoutController(request.timeoutMs ?? DEFAULT_OCR_TIMEOUT_MS);
|
|
419
452
|
try {
|
|
420
|
-
response
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
453
|
+
let response: Response;
|
|
454
|
+
try {
|
|
455
|
+
response = await runFetch(`${options.baseUrl.replace(/\/+$/u, "")}/chat/completions`, {
|
|
456
|
+
method: "POST",
|
|
457
|
+
headers,
|
|
458
|
+
body: JSON.stringify(messagesPayload(request, model)),
|
|
459
|
+
signal: timeout.controller.signal,
|
|
460
|
+
});
|
|
461
|
+
} catch (error) {
|
|
462
|
+
throw toOcrTransportError(error);
|
|
463
|
+
}
|
|
464
|
+
captureCapability({ status: response.status });
|
|
465
|
+
if (!response.ok) {
|
|
466
|
+
const echoed = await readCapabilityErrorBody(response, timeout.controller.signal);
|
|
467
|
+
captureCapability({ diagnostics: echoed });
|
|
468
|
+
throw new TransportError("OCR upstream request failed", {
|
|
469
|
+
code: "OCR_UPSTREAM_FAILED",
|
|
470
|
+
status: response.status,
|
|
471
|
+
upstreamStatus: response.status,
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
const text = responseContent(await responseJson(response, model), false, model);
|
|
475
|
+
if (!text) throw emptyResponseError(model);
|
|
476
|
+
return { text, model };
|
|
426
477
|
} catch (error) {
|
|
427
478
|
throw toOcrTransportError(error);
|
|
479
|
+
} finally {
|
|
480
|
+
timeout.clear();
|
|
428
481
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
status: response.status,
|
|
433
|
-
upstreamStatus: response.status,
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
const text = responseContent(await responseJson(response, model), false, model);
|
|
437
|
-
if (!text) throw emptyResponseError(model);
|
|
438
|
-
return { text, model };
|
|
439
|
-
} catch (error) {
|
|
440
|
-
throw toOcrTransportError(error);
|
|
441
|
-
} finally {
|
|
442
|
-
timeout.clear();
|
|
443
|
-
}
|
|
444
|
-
});
|
|
482
|
+
}),
|
|
483
|
+
{ backend: "openai-compatible", engine: "openai-compatible", model },
|
|
484
|
+
);
|
|
445
485
|
}
|
|
446
486
|
|
|
447
487
|
function cleanCaptchaText(text: string): string {
|
|
@@ -140,7 +140,8 @@ const MAX_INGESTIBLE_ARRAY_LENGTH = 64;
|
|
|
140
140
|
const MAX_INGESTIBLE_OBJECT_KEYS = 32;
|
|
141
141
|
const MAX_INGESTIBLE_DEPTH = 4;
|
|
142
142
|
const INGESTIBLE_TOKEN = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,63}$/;
|
|
143
|
-
|
|
143
|
+
/** @internal */
|
|
144
|
+
export const HEADER_PRIORITY = [
|
|
144
145
|
"proxy",
|
|
145
146
|
"resolver",
|
|
146
147
|
"native",
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ProviderCache, ProviderDefinition, ProviderProxyPolicy } from "../types.js";
|
|
2
|
+
import type { ResolverRuntimeOptions } from "./resolver.js";
|
|
3
|
+
import type { ResolverTelemetrySink } from "./resolver-telemetry.js";
|
|
4
|
+
import type { BrowserTelemetrySink } from "./browser-telemetry.js";
|
|
5
|
+
|
|
6
|
+
/** Normalize the `proxy` declaration shorthand (`true`/`false`) into the policy object the resolver chain consumes. */
|
|
7
|
+
export function resolveNativeProxyPolicy(
|
|
8
|
+
provider: ProviderDefinition,
|
|
9
|
+
): ProviderProxyPolicy | undefined {
|
|
10
|
+
if (typeof provider.proxy === "object") return provider.proxy;
|
|
11
|
+
if (provider.proxy === true) return { mode: "optional" };
|
|
12
|
+
if (provider.proxy === false) return { mode: "disabled" };
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* One option set for every SDK-built resolver chain — the server's ctx.resolver and automatic
|
|
18
|
+
* SBSD solve, and the CLI helper contexts — so they share allowed hosts, cache, identity scope,
|
|
19
|
+
* proxy intent, and the telemetry sink. `identityScope` is server-owned; CLI contexts pass none.
|
|
20
|
+
*/
|
|
21
|
+
export function createResolverRuntimeOptions(
|
|
22
|
+
provider: ProviderDefinition,
|
|
23
|
+
cache: ProviderCache,
|
|
24
|
+
identityScope: string | undefined,
|
|
25
|
+
proxyPolicy: ProviderProxyPolicy | undefined,
|
|
26
|
+
proxyClientOptions: Omit<
|
|
27
|
+
NonNullable<ResolverRuntimeOptions["proxyIntent"]>,
|
|
28
|
+
"mode" | "userAgent"
|
|
29
|
+
>,
|
|
30
|
+
stealthProfile: { readonly userAgent: string } | undefined,
|
|
31
|
+
telemetry: ResolverTelemetrySink,
|
|
32
|
+
browserTelemetry?: BrowserTelemetrySink,
|
|
33
|
+
): ResolverRuntimeOptions {
|
|
34
|
+
return {
|
|
35
|
+
allowedHosts: provider.allowedHosts,
|
|
36
|
+
cache,
|
|
37
|
+
telemetry,
|
|
38
|
+
browserTelemetry,
|
|
39
|
+
...(identityScope === undefined ? {} : { identityScope }),
|
|
40
|
+
...(proxyPolicy
|
|
41
|
+
? {
|
|
42
|
+
proxyIntent: {
|
|
43
|
+
mode: proxyPolicy.mode,
|
|
44
|
+
...proxyClientOptions,
|
|
45
|
+
...(stealthProfile ? { userAgent: stealthProfile.userAgent } : {}),
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
: {}),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -2,8 +2,12 @@ import { ProviderError } from "../errors.js";
|
|
|
2
2
|
import type { ChallengeSolution, ProviderChallenge, ResolverContext } from "../types.js";
|
|
3
3
|
import type { TraceRecorder } from "./trace.js";
|
|
4
4
|
import type { ResolverTelemetryOutcome, ResolverTelemetrySink } from "./resolver-telemetry.js";
|
|
5
|
+
import type { BrowserTelemetrySink } from "./browser-telemetry.js";
|
|
5
6
|
|
|
6
|
-
type ResolverTelemetryBinding = (
|
|
7
|
+
type ResolverTelemetryBinding = (
|
|
8
|
+
sink: ResolverTelemetrySink,
|
|
9
|
+
browserSink?: BrowserTelemetrySink,
|
|
10
|
+
) => ResolverContext;
|
|
7
11
|
const telemetryBindings = new WeakMap<ResolverContext, ResolverTelemetryBinding>();
|
|
8
12
|
|
|
9
13
|
/** Internal contract: reconstruct a chain with a new request sink, without mutating the host chain. */
|
|
@@ -27,6 +31,7 @@ export function inheritResolverTelemetryBinding(
|
|
|
27
31
|
export function bindResolverTelemetry(
|
|
28
32
|
resolver: ResolverContext,
|
|
29
33
|
sink: ResolverTelemetrySink | undefined,
|
|
34
|
+
browserSink?: BrowserTelemetrySink,
|
|
30
35
|
): ResolverContext {
|
|
31
36
|
if (!sink) return resolver;
|
|
32
37
|
const metadata = (
|
|
@@ -34,9 +39,9 @@ export function bindResolverTelemetry(
|
|
|
34
39
|
readonly [RESOLVER_INSTRUMENTATION_METADATA]?: { readonly target: ResolverContext };
|
|
35
40
|
}
|
|
36
41
|
)[RESOLVER_INSTRUMENTATION_METADATA];
|
|
37
|
-
if (metadata) return bindResolverTelemetry(metadata.target, sink);
|
|
42
|
+
if (metadata) return bindResolverTelemetry(metadata.target, sink, browserSink);
|
|
38
43
|
const bind = telemetryBindings.get(resolver);
|
|
39
|
-
if (bind) return bind(sink);
|
|
44
|
+
if (bind) return bind(sink, browserSink);
|
|
40
45
|
const wrapper: ResolverSolveWithRecorder = {
|
|
41
46
|
async solve(challenge, signal, recorder) {
|
|
42
47
|
const startedAt = Date.now();
|
|
@@ -74,7 +79,7 @@ export function bindResolverTelemetry(
|
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
function createOpaqueResolverTelemetryBinding(resolver: ResolverContext): ResolverTelemetryBinding {
|
|
77
|
-
return (sink) => bindResolverTelemetry(resolver, sink);
|
|
82
|
+
return (sink, browserSink) => bindResolverTelemetry(resolver, sink, browserSink);
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
export const RESOLVER_INSTRUMENTATION_METADATA = Symbol.for(
|
|
@@ -147,7 +147,7 @@ function boundedInteger(value: number): number {
|
|
|
147
147
|
return Math.max(0, Math.floor(Number.isFinite(value) ? value : 0));
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
function boundedText(value: string, redact?: (text: string) => string): string {
|
|
150
|
+
export function boundedText(value: string, redact?: (text: string) => string): string {
|
|
151
151
|
let result = value;
|
|
152
152
|
try {
|
|
153
153
|
result = redact?.(value) ?? value;
|