@screenshotscout/mcp 0.1.0
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/LICENSE +21 -0
- package/README.md +194 -0
- package/SECURITY.md +21 -0
- package/dist/core/capture-input.d.ts +85 -0
- package/dist/core/capture-input.js +332 -0
- package/dist/core/capture-tool.d.ts +25 -0
- package/dist/core/capture-tool.js +135 -0
- package/dist/core/client.d.ts +18 -0
- package/dist/core/client.js +16 -0
- package/dist/core/errors.d.ts +20 -0
- package/dist/core/errors.js +166 -0
- package/dist/core/image.d.ts +67 -0
- package/dist/core/image.js +387 -0
- package/dist/core/redaction.d.ts +15 -0
- package/dist/core/redaction.js +185 -0
- package/dist/core/result.d.ts +43 -0
- package/dist/core/result.js +140 -0
- package/dist/core/tool-metadata.d.ts +10 -0
- package/dist/core/tool-metadata.js +10 -0
- package/dist/http.d.ts +30 -0
- package/dist/http.js +458 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +10 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.js +16 -0
- package/dist/stdio.js +157 -0
- package/llms-install.md +114 -0
- package/package.json +103 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { CaptureHttpMethod } from "@screenshotscout/sdk";
|
|
2
|
+
import { captureScreenshotInputSchema, mapCaptureInputToSdk, } from "./capture-input.js";
|
|
3
|
+
import { formatScreenshotScoutError } from "./errors.js";
|
|
4
|
+
import { evaluateInlineImage, normalizeMimeType, resolveImageDimensions, } from "./image.js";
|
|
5
|
+
import { captureResultMetadataSchema, formatCaptureSuccess, } from "./result.js";
|
|
6
|
+
import { CAPTURE_SCREENSHOT_TOOL_ANNOTATIONS, CAPTURE_SCREENSHOT_TOOL_DESCRIPTION, CAPTURE_SCREENSHOT_TOOL_NAME, CAPTURE_SCREENSHOT_TOOL_TITLE, } from "./tool-metadata.js";
|
|
7
|
+
/**
|
|
8
|
+
* Invokes the official Screenshot Scout SDK after MCP schema validation.
|
|
9
|
+
* Result-content branching remains in the shared result layer.
|
|
10
|
+
*/
|
|
11
|
+
export async function invokeCaptureScreenshot(input, dependencies, context = {}) {
|
|
12
|
+
const configuredSensitiveValues = dependencies.sensitiveValues ?? [];
|
|
13
|
+
try {
|
|
14
|
+
const mappedRequest = mapCaptureInputToSdk(input);
|
|
15
|
+
const response = await dependencies.client.capture(mappedRequest.targetUrl, mappedRequest.captureOptions, {
|
|
16
|
+
method: CaptureHttpMethod.POST,
|
|
17
|
+
...(context.signal === undefined ? {} : { signal: context.signal }),
|
|
18
|
+
});
|
|
19
|
+
const mimeType = normalizeMimeType(response.rawResponse.contentType);
|
|
20
|
+
const baseMetadata = {
|
|
21
|
+
...(response.screenshotUrl === undefined
|
|
22
|
+
? {}
|
|
23
|
+
: { screenshotUrl: response.screenshotUrl }),
|
|
24
|
+
...(response.screenshotUrlExpiresAt === undefined
|
|
25
|
+
? {}
|
|
26
|
+
: { screenshotUrlExpiresAt: response.screenshotUrlExpiresAt }),
|
|
27
|
+
...(response.cacheStatus === undefined
|
|
28
|
+
? {}
|
|
29
|
+
: { cacheStatus: response.cacheStatus }),
|
|
30
|
+
format: input.format,
|
|
31
|
+
...(mimeType === undefined ? {} : { mimeType }),
|
|
32
|
+
inlineImageIncluded: false,
|
|
33
|
+
};
|
|
34
|
+
if (input.format === "pdf") {
|
|
35
|
+
const resourceLink = createPdfResourceLink(response.screenshotUrl, mimeType, response.bytes.byteLength);
|
|
36
|
+
return formatCaptureSuccess({
|
|
37
|
+
metadata: baseMetadata,
|
|
38
|
+
...(resourceLink === undefined
|
|
39
|
+
? {}
|
|
40
|
+
: { additionalContent: [resourceLink] }),
|
|
41
|
+
sensitiveValues: configuredSensitiveValues,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const dimensions = resolveImageDimensions(response.bytes, mimeType, undefined);
|
|
45
|
+
const evaluation = evaluateInlineImage({
|
|
46
|
+
format: input.format,
|
|
47
|
+
resultMode: mappedRequest.resultMode,
|
|
48
|
+
mimeType,
|
|
49
|
+
bytes: response.bytes,
|
|
50
|
+
...(dimensions === undefined
|
|
51
|
+
? {}
|
|
52
|
+
: {
|
|
53
|
+
trustedDimensions: {
|
|
54
|
+
imageWidth: dimensions.width,
|
|
55
|
+
imageHeight: dimensions.height,
|
|
56
|
+
},
|
|
57
|
+
}),
|
|
58
|
+
...(dependencies.maxSerializedResultBytes === undefined
|
|
59
|
+
? {}
|
|
60
|
+
: {
|
|
61
|
+
serializedSizeLimitBytes: dependencies.maxSerializedResultBytes,
|
|
62
|
+
}),
|
|
63
|
+
clientSupportsInlineImage: dependencies.clientSupportsInlineImage ?? (() => false),
|
|
64
|
+
buildSerializedResult: (image, measuredDimensions) => formatCaptureSuccess({
|
|
65
|
+
metadata: buildImageMetadata(baseMetadata, measuredDimensions, true),
|
|
66
|
+
additionalContent: [image],
|
|
67
|
+
sensitiveValues: configuredSensitiveValues,
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
if (evaluation.included) {
|
|
71
|
+
return formatCaptureSuccess({
|
|
72
|
+
metadata: buildImageMetadata(baseMetadata, evaluation.dimensions, true),
|
|
73
|
+
additionalContent: [evaluation.image],
|
|
74
|
+
sensitiveValues: configuredSensitiveValues,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return formatCaptureSuccess({
|
|
78
|
+
metadata: {
|
|
79
|
+
...buildImageMetadata(baseMetadata, dimensions, false),
|
|
80
|
+
inlineImageOmissionReason: evaluation.reason,
|
|
81
|
+
},
|
|
82
|
+
sensitiveValues: configuredSensitiveValues,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
// MCP cancellation reasons may be strings, but error mapping expects the
|
|
87
|
+
// standard AbortError shape and must not report cancellations as faults.
|
|
88
|
+
const captureError = context.signal?.aborted === true
|
|
89
|
+
? new DOMException("The screenshot capture was cancelled.", "AbortError")
|
|
90
|
+
: error;
|
|
91
|
+
return formatScreenshotScoutError(captureError, {
|
|
92
|
+
sensitiveValues: [input.url, ...configuredSensitiveValues],
|
|
93
|
+
...(dependencies.onUnexpectedError === undefined
|
|
94
|
+
? {}
|
|
95
|
+
: { onUnexpectedError: dependencies.onUnexpectedError }),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Registers the one approved tool on a transport-neutral MCP server.
|
|
101
|
+
*/
|
|
102
|
+
export function registerCaptureScreenshotTool(server, dependencies) {
|
|
103
|
+
return server.registerTool(CAPTURE_SCREENSHOT_TOOL_NAME, {
|
|
104
|
+
title: CAPTURE_SCREENSHOT_TOOL_TITLE,
|
|
105
|
+
description: CAPTURE_SCREENSHOT_TOOL_DESCRIPTION,
|
|
106
|
+
inputSchema: captureScreenshotInputSchema,
|
|
107
|
+
outputSchema: captureResultMetadataSchema,
|
|
108
|
+
annotations: CAPTURE_SCREENSHOT_TOOL_ANNOTATIONS,
|
|
109
|
+
}, (input, extra) => invokeCaptureScreenshot(input, dependencies, { signal: extra.signal }));
|
|
110
|
+
}
|
|
111
|
+
function buildImageMetadata(baseMetadata, dimensions, inlineImageIncluded) {
|
|
112
|
+
return {
|
|
113
|
+
...baseMetadata,
|
|
114
|
+
...(dimensions === undefined
|
|
115
|
+
? {}
|
|
116
|
+
: {
|
|
117
|
+
imageWidth: dimensions.width,
|
|
118
|
+
imageHeight: dimensions.height,
|
|
119
|
+
}),
|
|
120
|
+
inlineImageIncluded,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function createPdfResourceLink(screenshotUrl, mimeType, rawBytes) {
|
|
124
|
+
if (screenshotUrl === undefined)
|
|
125
|
+
return undefined;
|
|
126
|
+
return {
|
|
127
|
+
type: "resource_link",
|
|
128
|
+
uri: screenshotUrl,
|
|
129
|
+
name: "screenshot-scout-capture.pdf",
|
|
130
|
+
title: "Screenshot Scout PDF capture",
|
|
131
|
+
description: "Temporary PDF capture generated by Screenshot Scout.",
|
|
132
|
+
mimeType: mimeType ?? "application/pdf",
|
|
133
|
+
size: rawBytes,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type BinaryCaptureOptions, type BinaryCaptureResponse, type CaptureRequestOptions, type ScreenshotScoutClientOptions, type ScreenshotScoutFetch } from "@screenshotscout/sdk";
|
|
2
|
+
export type ScreenshotScoutCredentials = {
|
|
3
|
+
readonly accessKey: string;
|
|
4
|
+
readonly secretKey?: string;
|
|
5
|
+
};
|
|
6
|
+
export interface ScreenshotScoutCaptureClient {
|
|
7
|
+
capture(targetUrl: string, captureOptions?: BinaryCaptureOptions | null, captureRequestOptions?: CaptureRequestOptions | null): Promise<BinaryCaptureResponse>;
|
|
8
|
+
}
|
|
9
|
+
export type ScreenshotScoutClientFactory = (options: ScreenshotScoutClientOptions) => ScreenshotScoutCaptureClient;
|
|
10
|
+
export type ScreenshotScoutClientDependencies = {
|
|
11
|
+
readonly clientFactory?: ScreenshotScoutClientFactory;
|
|
12
|
+
readonly fetch?: ScreenshotScoutFetch;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Constructs the official SDK client from credentials supplied by the caller.
|
|
16
|
+
* Environment, transport, and tool layers remain outside this core.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createScreenshotScoutClient(credentials: ScreenshotScoutCredentials, dependencies?: ScreenshotScoutClientDependencies): ScreenshotScoutCaptureClient;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ScreenshotScoutClient, } from "@screenshotscout/sdk";
|
|
2
|
+
const defaultClientFactory = (options) => new ScreenshotScoutClient(options);
|
|
3
|
+
/**
|
|
4
|
+
* Constructs the official SDK client from credentials supplied by the caller.
|
|
5
|
+
* Environment, transport, and tool layers remain outside this core.
|
|
6
|
+
*/
|
|
7
|
+
export function createScreenshotScoutClient(credentials, dependencies = {}) {
|
|
8
|
+
const options = {
|
|
9
|
+
accessKey: credentials.accessKey,
|
|
10
|
+
...(credentials.secretKey === undefined
|
|
11
|
+
? {}
|
|
12
|
+
: { secretKey: credentials.secretKey }),
|
|
13
|
+
...(dependencies.fetch === undefined ? {} : { fetch: dependencies.fetch }),
|
|
14
|
+
};
|
|
15
|
+
return (dependencies.clientFactory ?? defaultClientFactory)(options);
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { type RedactedDiagnostic } from "./redaction.js";
|
|
3
|
+
export type SafeOptionError = {
|
|
4
|
+
readonly option: string;
|
|
5
|
+
readonly message: string;
|
|
6
|
+
};
|
|
7
|
+
export type SafeScreenshotScoutError = {
|
|
8
|
+
readonly category: "api" | "cancelled" | "configuration" | "response" | "serialization" | "transport" | "unexpected" | "unsafe_result";
|
|
9
|
+
readonly message: string;
|
|
10
|
+
readonly status?: number;
|
|
11
|
+
readonly code?: string;
|
|
12
|
+
readonly optionErrors?: readonly SafeOptionError[];
|
|
13
|
+
readonly remediation?: string;
|
|
14
|
+
};
|
|
15
|
+
export type ErrorMappingOptions = {
|
|
16
|
+
readonly sensitiveValues?: readonly (string | null | undefined)[];
|
|
17
|
+
readonly onUnexpectedError?: (diagnostic: RedactedDiagnostic) => void;
|
|
18
|
+
};
|
|
19
|
+
export declare function mapScreenshotScoutError(error: unknown, options?: ErrorMappingOptions): SafeScreenshotScoutError;
|
|
20
|
+
export declare function formatScreenshotScoutError(error: unknown, options?: ErrorMappingOptions): CallToolResult;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { ScreenshotScoutApiError, ScreenshotScoutConfigurationError, ScreenshotScoutResponseDecodingError, ScreenshotScoutSerializationError, ScreenshotScoutTransportError, } from "@screenshotscout/sdk";
|
|
2
|
+
import { redactText, toRedactedDiagnostic, } from "./redaction.js";
|
|
3
|
+
import { UnsafeCaptureResultError } from "./result.js";
|
|
4
|
+
export function mapScreenshotScoutError(error, options = {}) {
|
|
5
|
+
try {
|
|
6
|
+
return mapScreenshotScoutErrorInternal(error, options);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
reportUnexpectedError(error, options);
|
|
10
|
+
return {
|
|
11
|
+
category: "unexpected",
|
|
12
|
+
message: "An unexpected Screenshot Scout MCP error occurred. Retry the request, and contact support if it continues.",
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function mapScreenshotScoutErrorInternal(error, options) {
|
|
17
|
+
const sensitiveValues = options.sensitiveValues ?? [];
|
|
18
|
+
if (error instanceof ScreenshotScoutApiError) {
|
|
19
|
+
const code = error.errorCode === undefined
|
|
20
|
+
? undefined
|
|
21
|
+
: safeErrorText(error.errorCode, sensitiveValues, 100);
|
|
22
|
+
const message = safeErrorText(error.errorMessage ??
|
|
23
|
+
`Screenshot Scout API request failed with status ${error.status}.`, sensitiveValues, 1_000);
|
|
24
|
+
const optionErrors = readSafeOptionErrors(error.errors, sensitiveValues);
|
|
25
|
+
const remediation = code === "signature_required"
|
|
26
|
+
? "This API key requires signed requests. Use local stdio or MCPB with the secret key, or use a dedicated key with signed requests disabled. Never send the secret key to a hosted MCP endpoint."
|
|
27
|
+
: undefined;
|
|
28
|
+
return {
|
|
29
|
+
category: "api",
|
|
30
|
+
message,
|
|
31
|
+
status: error.status,
|
|
32
|
+
...(code === undefined ? {} : { code }),
|
|
33
|
+
...(optionErrors.length === 0 ? {} : { optionErrors }),
|
|
34
|
+
...(remediation === undefined ? {} : { remediation }),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (error instanceof ScreenshotScoutConfigurationError) {
|
|
38
|
+
return {
|
|
39
|
+
category: "configuration",
|
|
40
|
+
message: "Screenshot Scout client configuration is invalid. Check the configured access key and local signing settings.",
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (error instanceof ScreenshotScoutSerializationError) {
|
|
44
|
+
const option = error.option === undefined
|
|
45
|
+
? undefined
|
|
46
|
+
: safeErrorText(error.option, sensitiveValues, 100);
|
|
47
|
+
return {
|
|
48
|
+
category: "serialization",
|
|
49
|
+
message: option === undefined
|
|
50
|
+
? "The screenshot request options could not be serialized safely."
|
|
51
|
+
: `The screenshot request option "${option}" could not be serialized safely.`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (error instanceof ScreenshotScoutTransportError) {
|
|
55
|
+
return {
|
|
56
|
+
category: "transport",
|
|
57
|
+
message: "Screenshot Scout could not be reached before a response was received. Retry the capture.",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (error instanceof ScreenshotScoutResponseDecodingError) {
|
|
61
|
+
return {
|
|
62
|
+
category: "response",
|
|
63
|
+
message: "Screenshot Scout returned an unexpected response that could not be handled safely.",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (error instanceof UnsafeCaptureResultError) {
|
|
67
|
+
return {
|
|
68
|
+
category: "unsafe_result",
|
|
69
|
+
message: "Screenshot Scout returned result metadata that could not be exposed safely.",
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (isAbortError(error)) {
|
|
73
|
+
return {
|
|
74
|
+
category: "cancelled",
|
|
75
|
+
message: "The screenshot capture was cancelled.",
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
reportUnexpectedError(error, options);
|
|
79
|
+
return {
|
|
80
|
+
category: "unexpected",
|
|
81
|
+
message: "An unexpected Screenshot Scout MCP error occurred. Retry the request, and contact support if it continues.",
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export function formatScreenshotScoutError(error, options = {}) {
|
|
85
|
+
const safeError = mapScreenshotScoutError(error, options);
|
|
86
|
+
const lines = ["Screenshot Scout capture failed."];
|
|
87
|
+
if (safeError.status !== undefined) {
|
|
88
|
+
lines.push(`HTTP status: ${safeError.status}`);
|
|
89
|
+
}
|
|
90
|
+
if (safeError.code !== undefined) {
|
|
91
|
+
lines.push(`Error code: ${safeError.code}`);
|
|
92
|
+
}
|
|
93
|
+
lines.push(`Message: ${safeError.message}`);
|
|
94
|
+
if (safeError.optionErrors !== undefined &&
|
|
95
|
+
safeError.optionErrors.length > 0) {
|
|
96
|
+
lines.push("Option errors:");
|
|
97
|
+
for (const optionError of safeError.optionErrors) {
|
|
98
|
+
lines.push(`- ${optionError.option}: ${optionError.message}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (safeError.remediation !== undefined) {
|
|
102
|
+
lines.push(`How to resolve: ${safeError.remediation}`);
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
106
|
+
isError: true,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function readSafeOptionErrors(errors, sensitiveValues) {
|
|
110
|
+
if (errors === undefined)
|
|
111
|
+
return [];
|
|
112
|
+
const output = [];
|
|
113
|
+
for (const value of errors.slice(0, 25)) {
|
|
114
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
let option;
|
|
118
|
+
let message;
|
|
119
|
+
try {
|
|
120
|
+
option = Reflect.get(value, "option");
|
|
121
|
+
message = Reflect.get(value, "message");
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (typeof option !== "string" || typeof message !== "string")
|
|
127
|
+
continue;
|
|
128
|
+
output.push({
|
|
129
|
+
option: safeErrorText(option, sensitiveValues, 100),
|
|
130
|
+
message: safeErrorText(message, sensitiveValues, 500),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return output;
|
|
134
|
+
}
|
|
135
|
+
function safeErrorText(value, sensitiveValues, maxLength) {
|
|
136
|
+
return redactText(value, {
|
|
137
|
+
sensitiveValues,
|
|
138
|
+
redactUrls: true,
|
|
139
|
+
maxLength,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
function reportUnexpectedError(error, options) {
|
|
143
|
+
try {
|
|
144
|
+
if (options.onUnexpectedError === undefined)
|
|
145
|
+
return;
|
|
146
|
+
options.onUnexpectedError(toRedactedDiagnostic(error, {
|
|
147
|
+
...(options.sensitiveValues === undefined
|
|
148
|
+
? {}
|
|
149
|
+
: { sensitiveValues: options.sensitiveValues }),
|
|
150
|
+
redactUrls: true,
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// Diagnostics must never replace the safe tool error.
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function isAbortError(error) {
|
|
158
|
+
if (typeof error !== "object" || error === null)
|
|
159
|
+
return false;
|
|
160
|
+
try {
|
|
161
|
+
return Reflect.get(error, "name") === "AbortError";
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ImageContent } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type { CaptureResultMode, CaptureScreenshotInput } from "./capture-input.js";
|
|
3
|
+
export declare const MAX_INLINE_IMAGE_DIMENSION = 8000;
|
|
4
|
+
export declare const MAX_INLINE_IMAGE_RAW_BYTES: number;
|
|
5
|
+
export declare const DEFAULT_MAX_SERIALIZED_RESULT_BYTES = 128000;
|
|
6
|
+
export declare const DEFAULT_MAX_IMAGE_HEADER_BYTES: number;
|
|
7
|
+
export declare const INLINE_IMAGE_MIME_TYPES: readonly ["image/png", "image/jpeg", "image/webp", "image/gif"];
|
|
8
|
+
export type InlineImageMimeType = (typeof INLINE_IMAGE_MIME_TYPES)[number];
|
|
9
|
+
export type CaptureFormat = CaptureScreenshotInput["format"];
|
|
10
|
+
export declare const INLINE_IMAGE_OMISSION_REASONS: {
|
|
11
|
+
readonly RESULT_MODE_URL_ONLY: "result_mode_url_only";
|
|
12
|
+
readonly FORMAT_NOT_INLINE_ELIGIBLE: "format_not_inline_eligible";
|
|
13
|
+
readonly UNSUPPORTED_MIME_TYPE: "unsupported_mime_type";
|
|
14
|
+
readonly MIME_TYPE_MISMATCH: "mime_type_mismatch";
|
|
15
|
+
readonly RAW_SIZE_EXCEEDS_LIMIT: "raw_size_exceeds_limit";
|
|
16
|
+
readonly DIMENSIONS_UNAVAILABLE: "dimensions_unavailable";
|
|
17
|
+
readonly DIMENSIONS_EXCEED_LIMIT: "dimensions_exceed_limit";
|
|
18
|
+
readonly CLIENT_NOT_COMPATIBLE: "client_not_compatible";
|
|
19
|
+
readonly SERIALIZED_SIZE_UNAVAILABLE: "serialized_size_unavailable";
|
|
20
|
+
readonly SERIALIZED_SIZE_EXCEEDS_LIMIT: "serialized_size_exceeds_limit";
|
|
21
|
+
};
|
|
22
|
+
export type InlineImageOmissionReason = (typeof INLINE_IMAGE_OMISSION_REASONS)[keyof typeof INLINE_IMAGE_OMISSION_REASONS];
|
|
23
|
+
export type ImageDimensions = {
|
|
24
|
+
readonly width: number;
|
|
25
|
+
readonly height: number;
|
|
26
|
+
};
|
|
27
|
+
export type TrustedImageDimensions = {
|
|
28
|
+
readonly imageWidth?: number;
|
|
29
|
+
readonly imageHeight?: number;
|
|
30
|
+
};
|
|
31
|
+
export type InlineImageIncluded = {
|
|
32
|
+
readonly included: true;
|
|
33
|
+
readonly image: ImageContent;
|
|
34
|
+
readonly dimensions: ImageDimensions;
|
|
35
|
+
readonly rawBytes: number;
|
|
36
|
+
readonly serializedBytes: number;
|
|
37
|
+
readonly serializedSizeLimitBytes: number;
|
|
38
|
+
};
|
|
39
|
+
export type InlineImageOmitted = {
|
|
40
|
+
readonly included: false;
|
|
41
|
+
readonly reason: InlineImageOmissionReason;
|
|
42
|
+
readonly dimensions?: ImageDimensions;
|
|
43
|
+
readonly rawBytes: number;
|
|
44
|
+
readonly serializedSizeLimitBytes: number;
|
|
45
|
+
};
|
|
46
|
+
export type InlineImageEvaluation = InlineImageIncluded | InlineImageOmitted;
|
|
47
|
+
export type InlineImageCandidate = {
|
|
48
|
+
readonly format: CaptureFormat;
|
|
49
|
+
readonly resultMode: CaptureResultMode;
|
|
50
|
+
readonly mimeType: string | null | undefined;
|
|
51
|
+
readonly bytes: Uint8Array;
|
|
52
|
+
readonly trustedDimensions?: TrustedImageDimensions;
|
|
53
|
+
readonly serializedSizeLimitBytes?: number;
|
|
54
|
+
readonly clientSupportsInlineImage: (mimeType: InlineImageMimeType) => boolean;
|
|
55
|
+
readonly buildSerializedResult: (image: ImageContent, dimensions: ImageDimensions) => unknown;
|
|
56
|
+
readonly stringify?: (value: unknown) => string | undefined;
|
|
57
|
+
};
|
|
58
|
+
export declare function normalizeMimeType(value: string | null | undefined): string | undefined;
|
|
59
|
+
export declare function asInlineImageMimeType(value: string | null | undefined): InlineImageMimeType | undefined;
|
|
60
|
+
export declare function resolveImageDimensions(bytes: Uint8Array, mimeType: string | null | undefined, trustedDimensions: TrustedImageDimensions | undefined, maxHeaderBytes?: number): ImageDimensions | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Reads only bounded format headers. It does not decode pixels or transform
|
|
63
|
+
* the payload.
|
|
64
|
+
*/
|
|
65
|
+
export declare function inspectImageDimensions(bytes: Uint8Array, mimeType: string | null | undefined, maxHeaderBytes?: number): ImageDimensions | undefined;
|
|
66
|
+
export declare function evaluateInlineImage(candidate: InlineImageCandidate): InlineImageEvaluation;
|
|
67
|
+
export declare function resolveSerializedSizeLimit(requestedLimitBytes: number | undefined): number;
|