diff --git a/.changeset/desktop-environment.md b/.changeset/desktop-environment.md
new file mode 100644
index 000000000..80aa00105
--- /dev/null
+++ b/.changeset/desktop-environment.md
@@ -0,0 +1,13 @@
+---
+'@cloudflare/sandbox': patch
+---
+
+Add desktop environment support for AI computer-use workflows.
+
+Start a full Linux desktop (Xvfb + XFCE4 + x11vnc + noVNC) inside the
+sandbox and control it programmatically via `sandbox.desktop.*` methods.
+Supports screenshots, mouse clicks, keyboard input, and live browser
+streaming via noVNC preview URLs.
+
+Enable with `sandbox.desktop.start()`. Requires the desktop container
+image variant.
diff --git a/examples/desktop/.gitignore b/examples/desktop/.gitignore
new file mode 100644
index 000000000..2fbb0d2d1
--- /dev/null
+++ b/examples/desktop/.gitignore
@@ -0,0 +1,26 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+.wrangler
+.turbo
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/examples/desktop/Dockerfile b/examples/desktop/Dockerfile
new file mode 100644
index 000000000..a50416672
--- /dev/null
+++ b/examples/desktop/Dockerfile
@@ -0,0 +1,8 @@
+FROM sandbox-desktop:local
+EXPOSE 6080
+
+# Cloudflare-branded desktop wallpaper
+COPY assets/wallpaper.png /usr/share/backgrounds/cloudflare.png
+COPY assets/set-wallpaper.sh /usr/local/bin/set-wallpaper.sh
+RUN chmod +x /usr/local/bin/set-wallpaper.sh
+COPY assets/set-wallpaper.desktop /etc/xdg/autostart/set-wallpaper.desktop
diff --git a/examples/desktop/assets/set-wallpaper.desktop b/examples/desktop/assets/set-wallpaper.desktop
new file mode 100644
index 000000000..a8fca841f
--- /dev/null
+++ b/examples/desktop/assets/set-wallpaper.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Type=Application
+Name=Set Wallpaper
+Exec=/usr/local/bin/set-wallpaper.sh
+Hidden=false
+NoDisplay=true
+X-GNOME-Autostart-enabled=true
diff --git a/examples/desktop/assets/set-wallpaper.sh b/examples/desktop/assets/set-wallpaper.sh
new file mode 100644
index 000000000..2543b602b
--- /dev/null
+++ b/examples/desktop/assets/set-wallpaper.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Set the Cloudflare wallpaper for whatever monitor XFCE detects.
+# Runs as an XFCE autostart entry after xfdesktop initializes.
+sleep 2
+for prop in $(xfconf-query -c xfce4-desktop -l 2>/dev/null | grep last-image); do
+ xfconf-query -c xfce4-desktop -p "$prop" -s "/usr/share/backgrounds/cloudflare.png"
+done
diff --git a/examples/desktop/assets/wallpaper.png b/examples/desktop/assets/wallpaper.png
new file mode 100644
index 000000000..68df7f3a4
Binary files /dev/null and b/examples/desktop/assets/wallpaper.png differ
diff --git a/examples/desktop/index.html b/examples/desktop/index.html
new file mode 100644
index 000000000..ff202499b
--- /dev/null
+++ b/examples/desktop/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Cloudflare Sandbox Desktop
+
+
+
+
+
+
diff --git a/examples/desktop/package.json b/examples/desktop/package.json
new file mode 100644
index 000000000..a609ef1e9
--- /dev/null
+++ b/examples/desktop/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "@cloudflare/sandbox-desktop-example",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "deploy": "vite build && wrangler deploy",
+ "typecheck": "tsc -b",
+ "cf-typegen": "wrangler types"
+ },
+ "dependencies": {
+ "@cloudflare/kumo": "^1.8.0",
+ "@phosphor-icons/react": "^2.1.10",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0"
+ },
+ "devDependencies": {
+ "@cloudflare/sandbox": "*",
+ "@cloudflare/vite-plugin": "^1.15.2",
+ "@tailwindcss/vite": "^4.2.1",
+ "@types/react": "^19.2.7",
+ "@types/react-dom": "^19.2.3",
+ "@vitejs/plugin-react": "^5.1.1",
+ "tailwindcss": "^4.1.17",
+ "typescript": "^5.9.3",
+ "vite": "^7.2.4",
+ "wrangler": "^4.63.0"
+ }
+}
diff --git a/examples/desktop/src/App.tsx b/examples/desktop/src/App.tsx
new file mode 100644
index 000000000..f60521cde
--- /dev/null
+++ b/examples/desktop/src/App.tsx
@@ -0,0 +1,44 @@
+import { useRef } from 'react';
+import { DesktopViewer } from './components/DesktopViewer';
+import { Header } from './components/Header';
+import { useDesktop } from './hooks/useDesktop';
+
+export default function App() {
+ const { isRunning, isStarting, streamUrl, error, start, stop } = useDesktop();
+ const viewerRef = useRef(null);
+
+ const handleStart = () => {
+ const el = viewerRef.current;
+ if (el) {
+ // Measure the available space and start the desktop at that resolution
+ start([el.clientWidth, el.clientHeight]);
+ } else {
+ start();
+ }
+ };
+
+ return (
+
+
+
+ {error && (
+
+ {error}
+
+ )}
+
+
+
+
+
+ );
+}
diff --git a/examples/desktop/src/api/client.ts b/examples/desktop/src/api/client.ts
new file mode 100644
index 000000000..4a561dfe8
--- /dev/null
+++ b/examples/desktop/src/api/client.ts
@@ -0,0 +1,31 @@
+interface DesktopStatus {
+ status: 'active' | 'partial' | 'inactive';
+ processes: Record<
+ string,
+ { running: boolean; pid?: number; uptime?: number }
+ >;
+ resolution: [number, number] | null;
+ dpi: number | null;
+}
+async function json(input: RequestInfo, init?: RequestInit): Promise {
+ const res = await fetch(input, init);
+ if (!res.ok) {
+ const body = await res.text();
+ throw new Error(body || res.statusText);
+ }
+ return res.json() as Promise;
+}
+
+export const api = {
+ startDesktop: (resolution?: [number, number]) =>
+ json<{ success: boolean }>('/api/start', {
+ method: 'POST',
+ headers: resolution ? { 'Content-Type': 'application/json' } : undefined,
+ body: resolution ? JSON.stringify({ resolution }) : undefined
+ }),
+ stopDesktop: () =>
+ json<{ success: boolean }>('/api/stop', { method: 'POST' }),
+ getStatus: () => json('/api/status'),
+ getStreamUrl: () =>
+ json<{ url: string }>('/api/stream-url', { method: 'POST' })
+};
diff --git a/examples/desktop/src/components/DesktopViewer.tsx b/examples/desktop/src/components/DesktopViewer.tsx
new file mode 100644
index 000000000..f42f65d40
--- /dev/null
+++ b/examples/desktop/src/components/DesktopViewer.tsx
@@ -0,0 +1,54 @@
+interface DesktopViewerProps {
+ isRunning: boolean;
+ isStarting: boolean;
+ streamUrl: string | null;
+}
+
+export function DesktopViewer({
+ isRunning,
+ isStarting,
+ streamUrl
+}: DesktopViewerProps) {
+ if (isStarting) {
+ return (
+
+
+
Starting desktop environment…
+
This may take a few seconds
+
+
+ );
+ }
+
+ if (!isRunning) {
+ return (
+
+
+
Desktop is stopped
+
+ Click "Start Desktop" to begin
+
+
+
+ );
+ }
+
+ if (!streamUrl) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+}
diff --git a/examples/desktop/src/components/Header.tsx b/examples/desktop/src/components/Header.tsx
new file mode 100644
index 000000000..38c2034f7
--- /dev/null
+++ b/examples/desktop/src/components/Header.tsx
@@ -0,0 +1,54 @@
+import { Badge } from '@cloudflare/kumo/components/badge';
+import { Button } from '@cloudflare/kumo/components/button';
+import { Camera } from '@phosphor-icons/react';
+
+interface HeaderProps {
+ isRunning: boolean;
+ isStarting: boolean;
+ onStart: () => void;
+ onStop: () => void;
+}
+
+export function Header({
+ isRunning,
+ isStarting,
+ onStart,
+ onStop
+}: HeaderProps) {
+ return (
+
+
+
+ Desktop Environment
+
+
+ {isStarting ? 'Starting…' : isRunning ? 'Running' : 'Stopped'}
+
+
+
+ {isRunning && (
+
+ )}
+ {isRunning ? (
+
+ ) : (
+
+ )}
+
+
+ );
+}
diff --git a/examples/desktop/src/hooks/useDesktop.ts b/examples/desktop/src/hooks/useDesktop.ts
new file mode 100644
index 000000000..28c9fe312
--- /dev/null
+++ b/examples/desktop/src/hooks/useDesktop.ts
@@ -0,0 +1,78 @@
+import { useCallback, useEffect, useRef, useState } from 'react';
+import { api } from '../api/client';
+
+export function useDesktop() {
+ const [isRunning, setIsRunning] = useState(false);
+ const [isStarting, setIsStarting] = useState(false);
+ const [streamUrl, setStreamUrl] = useState(null);
+ const [error, setError] = useState(null);
+
+ const statusTimer = useRef(0);
+ const fetchingUrl = useRef(false);
+
+ const refreshStatus = useCallback(async () => {
+ try {
+ const status = await api.getStatus();
+ const running = status.status === 'active' || status.status === 'partial';
+ setIsRunning(running);
+
+ if (!running) {
+ setStreamUrl(null);
+ fetchingUrl.current = false;
+ }
+ } catch {
+ // Transient errors during polling are expected
+ }
+ }, []);
+
+ // Fetch stream URL when desktop becomes running and we don't have one
+ useEffect(() => {
+ if (!isRunning || streamUrl || fetchingUrl.current) return;
+
+ fetchingUrl.current = true;
+ api
+ .getStreamUrl()
+ .then(({ url }) => setStreamUrl(url))
+ .catch(() => {
+ fetchingUrl.current = false;
+ });
+ }, [isRunning, streamUrl]);
+
+ const start = async (resolution?: [number, number]) => {
+ setError(null);
+ setIsStarting(true);
+ try {
+ await api.startDesktop(resolution);
+ await refreshStatus();
+ // getDesktopStreamUrl waits for the platform to detect port 6080
+ // (via the Containers runtime's getTcpPort polling) before returning.
+ const { url } = await api.getStreamUrl();
+ setStreamUrl(url);
+ } catch (err: unknown) {
+ setError(err instanceof Error ? err.message : 'Failed to start desktop');
+ } finally {
+ setIsStarting(false);
+ }
+ };
+
+ const stop = async () => {
+ setError(null);
+ try {
+ await api.stopDesktop();
+ setStreamUrl(null);
+ fetchingUrl.current = false;
+ await refreshStatus();
+ } catch (err: unknown) {
+ setError(err instanceof Error ? err.message : 'Failed to stop desktop');
+ }
+ };
+
+ // Poll status every 3s
+ useEffect(() => {
+ refreshStatus();
+ statusTimer.current = window.setInterval(refreshStatus, 3000);
+ return () => clearInterval(statusTimer.current);
+ }, [refreshStatus]);
+
+ return { isRunning, isStarting, streamUrl, error, start, stop };
+}
diff --git a/examples/desktop/src/index.css b/examples/desktop/src/index.css
new file mode 100644
index 000000000..aeace3095
--- /dev/null
+++ b/examples/desktop/src/index.css
@@ -0,0 +1,3 @@
+@source "../node_modules/@cloudflare/kumo/dist/**/*.{js,jsx,ts,tsx}";
+@import "@cloudflare/kumo/styles/tailwind";
+@import "tailwindcss";
diff --git a/examples/desktop/src/main.tsx b/examples/desktop/src/main.tsx
new file mode 100644
index 000000000..2339d59cf
--- /dev/null
+++ b/examples/desktop/src/main.tsx
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import App from './App';
+import './index.css';
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+
+);
diff --git a/examples/desktop/tsconfig.app.json b/examples/desktop/tsconfig.app.json
new file mode 100644
index 000000000..a9b5a59ca
--- /dev/null
+++ b/examples/desktop/tsconfig.app.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2022",
+ "useDefineForClassFields": true,
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "types": ["vite/client"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["src"]
+}
diff --git a/examples/desktop/tsconfig.json b/examples/desktop/tsconfig.json
new file mode 100644
index 000000000..fbbbb94e6
--- /dev/null
+++ b/examples/desktop/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.worker.json" }
+ ]
+}
diff --git a/examples/desktop/tsconfig.worker.json b/examples/desktop/tsconfig.worker.json
new file mode 100644
index 000000000..dae99c0f5
--- /dev/null
+++ b/examples/desktop/tsconfig.worker.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "lib": ["ES2022", "DOM"],
+ "types": [],
+ "strict": true,
+ "skipLibCheck": true,
+ "noEmit": true
+ },
+ "include": ["workers/**/*", "worker-configuration.d.ts"]
+}
diff --git a/examples/desktop/vite.config.ts b/examples/desktop/vite.config.ts
new file mode 100644
index 000000000..fa248c207
--- /dev/null
+++ b/examples/desktop/vite.config.ts
@@ -0,0 +1,8 @@
+import { cloudflare } from '@cloudflare/vite-plugin';
+import tailwindcss from '@tailwindcss/vite';
+import react from '@vitejs/plugin-react';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ plugins: [react(), tailwindcss(), cloudflare()]
+});
diff --git a/examples/desktop/worker-configuration.d.ts b/examples/desktop/worker-configuration.d.ts
new file mode 100644
index 000000000..ae5a881ff
--- /dev/null
+++ b/examples/desktop/worker-configuration.d.ts
@@ -0,0 +1,10920 @@
+/* eslint-disable */
+// Generated by Wrangler by running `wrangler types` (hash: bed9e415af21dbee23f72fe0ef640aef)
+// Runtime types generated with workerd@1.20260210.0 2025-11-15 nodejs_compat
+declare namespace Cloudflare {
+ interface GlobalProps {
+ mainModule: typeof import("./workers/app");
+ durableNamespaces: "Sandbox";
+ }
+ interface Env {
+ ASSETS: Fetcher;
+ Sandbox: DurableObjectNamespace;
+ }
+}
+interface Env extends Cloudflare.Env {}
+
+// Begin runtime types
+/*! *****************************************************************************
+Copyright (c) Cloudflare. All rights reserved.
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+this file except in compliance with the License. You may obtain a copy of the
+License at http://www.apache.org/licenses/LICENSE-2.0
+THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
+WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+MERCHANTABLITY OR NON-INFRINGEMENT.
+See the Apache Version 2.0 License for specific language governing permissions
+and limitations under the License.
+***************************************************************************** */
+/* eslint-disable */
+// noinspection JSUnusedGlobalSymbols
+declare var onmessage: never;
+/**
+ * The **`DOMException`** interface represents an abnormal event (called an **exception**) that occurs as a result of calling a method or accessing a property of a web API.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMException)
+ */
+declare class DOMException extends Error {
+ constructor(message?: string, name?: string);
+ /**
+ * The **`message`** read-only property of the a message or description associated with the given error name.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMException/message)
+ */
+ readonly message: string;
+ /**
+ * The **`name`** read-only property of the one of the strings associated with an error name.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMException/name)
+ */
+ readonly name: string;
+ /**
+ * The **`code`** read-only property of the DOMException interface returns one of the legacy error code constants, or `0` if none match.
+ * @deprecated
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMException/code)
+ */
+ readonly code: number;
+ static readonly INDEX_SIZE_ERR: number;
+ static readonly DOMSTRING_SIZE_ERR: number;
+ static readonly HIERARCHY_REQUEST_ERR: number;
+ static readonly WRONG_DOCUMENT_ERR: number;
+ static readonly INVALID_CHARACTER_ERR: number;
+ static readonly NO_DATA_ALLOWED_ERR: number;
+ static readonly NO_MODIFICATION_ALLOWED_ERR: number;
+ static readonly NOT_FOUND_ERR: number;
+ static readonly NOT_SUPPORTED_ERR: number;
+ static readonly INUSE_ATTRIBUTE_ERR: number;
+ static readonly INVALID_STATE_ERR: number;
+ static readonly SYNTAX_ERR: number;
+ static readonly INVALID_MODIFICATION_ERR: number;
+ static readonly NAMESPACE_ERR: number;
+ static readonly INVALID_ACCESS_ERR: number;
+ static readonly VALIDATION_ERR: number;
+ static readonly TYPE_MISMATCH_ERR: number;
+ static readonly SECURITY_ERR: number;
+ static readonly NETWORK_ERR: number;
+ static readonly ABORT_ERR: number;
+ static readonly URL_MISMATCH_ERR: number;
+ static readonly QUOTA_EXCEEDED_ERR: number;
+ static readonly TIMEOUT_ERR: number;
+ static readonly INVALID_NODE_TYPE_ERR: number;
+ static readonly DATA_CLONE_ERR: number;
+ get stack(): any;
+ set stack(value: any);
+}
+type WorkerGlobalScopeEventMap = {
+ fetch: FetchEvent;
+ scheduled: ScheduledEvent;
+ queue: QueueEvent;
+ unhandledrejection: PromiseRejectionEvent;
+ rejectionhandled: PromiseRejectionEvent;
+};
+declare abstract class WorkerGlobalScope extends EventTarget {
+ EventTarget: typeof EventTarget;
+}
+/* The **`console`** object provides access to the debugging console (e.g., the Web console in Firefox). *
+ * The **`console`** object provides access to the debugging console (e.g., the Web console in Firefox).
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console)
+ */
+interface Console {
+ "assert"(condition?: boolean, ...data: any[]): void;
+ /**
+ * The **`console.clear()`** static method clears the console if possible.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/clear_static)
+ */
+ clear(): void;
+ /**
+ * The **`console.count()`** static method logs the number of times that this particular call to `count()` has been called.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/count_static)
+ */
+ count(label?: string): void;
+ /**
+ * The **`console.countReset()`** static method resets counter used with console/count_static.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/countReset_static)
+ */
+ countReset(label?: string): void;
+ /**
+ * The **`console.debug()`** static method outputs a message to the console at the 'debug' log level.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/debug_static)
+ */
+ debug(...data: any[]): void;
+ /**
+ * The **`console.dir()`** static method displays a list of the properties of the specified JavaScript object.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/dir_static)
+ */
+ dir(item?: any, options?: any): void;
+ /**
+ * The **`console.dirxml()`** static method displays an interactive tree of the descendant elements of the specified XML/HTML element.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/dirxml_static)
+ */
+ dirxml(...data: any[]): void;
+ /**
+ * The **`console.error()`** static method outputs a message to the console at the 'error' log level.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/error_static)
+ */
+ error(...data: any[]): void;
+ /**
+ * The **`console.group()`** static method creates a new inline group in the Web console log, causing any subsequent console messages to be indented by an additional level, until console/groupEnd_static is called.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/group_static)
+ */
+ group(...data: any[]): void;
+ /**
+ * The **`console.groupCollapsed()`** static method creates a new inline group in the console.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupCollapsed_static)
+ */
+ groupCollapsed(...data: any[]): void;
+ /**
+ * The **`console.groupEnd()`** static method exits the current inline group in the console.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupEnd_static)
+ */
+ groupEnd(): void;
+ /**
+ * The **`console.info()`** static method outputs a message to the console at the 'info' log level.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/info_static)
+ */
+ info(...data: any[]): void;
+ /**
+ * The **`console.log()`** static method outputs a message to the console.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)
+ */
+ log(...data: any[]): void;
+ /**
+ * The **`console.table()`** static method displays tabular data as a table.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/table_static)
+ */
+ table(tabularData?: any, properties?: string[]): void;
+ /**
+ * The **`console.time()`** static method starts a timer you can use to track how long an operation takes.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/time_static)
+ */
+ time(label?: string): void;
+ /**
+ * The **`console.timeEnd()`** static method stops a timer that was previously started by calling console/time_static.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeEnd_static)
+ */
+ timeEnd(label?: string): void;
+ /**
+ * The **`console.timeLog()`** static method logs the current value of a timer that was previously started by calling console/time_static.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeLog_static)
+ */
+ timeLog(label?: string, ...data: any[]): void;
+ timeStamp(label?: string): void;
+ /**
+ * The **`console.trace()`** static method outputs a stack trace to the console.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/trace_static)
+ */
+ trace(...data: any[]): void;
+ /**
+ * The **`console.warn()`** static method outputs a warning message to the console at the 'warning' log level.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/warn_static)
+ */
+ warn(...data: any[]): void;
+}
+declare const console: Console;
+type BufferSource = ArrayBufferView | ArrayBuffer;
+type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array;
+declare namespace WebAssembly {
+ class CompileError extends Error {
+ constructor(message?: string);
+ }
+ class RuntimeError extends Error {
+ constructor(message?: string);
+ }
+ type ValueType = "anyfunc" | "externref" | "f32" | "f64" | "i32" | "i64" | "v128";
+ interface GlobalDescriptor {
+ value: ValueType;
+ mutable?: boolean;
+ }
+ class Global {
+ constructor(descriptor: GlobalDescriptor, value?: any);
+ value: any;
+ valueOf(): any;
+ }
+ type ImportValue = ExportValue | number;
+ type ModuleImports = Record;
+ type Imports = Record;
+ type ExportValue = Function | Global | Memory | Table;
+ type Exports = Record;
+ class Instance {
+ constructor(module: Module, imports?: Imports);
+ readonly exports: Exports;
+ }
+ interface MemoryDescriptor {
+ initial: number;
+ maximum?: number;
+ shared?: boolean;
+ }
+ class Memory {
+ constructor(descriptor: MemoryDescriptor);
+ readonly buffer: ArrayBuffer;
+ grow(delta: number): number;
+ }
+ type ImportExportKind = "function" | "global" | "memory" | "table";
+ interface ModuleExportDescriptor {
+ kind: ImportExportKind;
+ name: string;
+ }
+ interface ModuleImportDescriptor {
+ kind: ImportExportKind;
+ module: string;
+ name: string;
+ }
+ abstract class Module {
+ static customSections(module: Module, sectionName: string): ArrayBuffer[];
+ static exports(module: Module): ModuleExportDescriptor[];
+ static imports(module: Module): ModuleImportDescriptor[];
+ }
+ type TableKind = "anyfunc" | "externref";
+ interface TableDescriptor {
+ element: TableKind;
+ initial: number;
+ maximum?: number;
+ }
+ class Table {
+ constructor(descriptor: TableDescriptor, value?: any);
+ readonly length: number;
+ get(index: number): any;
+ grow(delta: number, value?: any): number;
+ set(index: number, value?: any): void;
+ }
+ function instantiate(module: Module, imports?: Imports): Promise;
+ function validate(bytes: BufferSource): boolean;
+}
+/**
+ * The **`ServiceWorkerGlobalScope`** interface of the Service Worker API represents the global execution context of a service worker.
+ * Available only in secure contexts.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/ServiceWorkerGlobalScope)
+ */
+interface ServiceWorkerGlobalScope extends WorkerGlobalScope {
+ DOMException: typeof DOMException;
+ WorkerGlobalScope: typeof WorkerGlobalScope;
+ btoa(data: string): string;
+ atob(data: string): string;
+ setTimeout(callback: (...args: any[]) => void, msDelay?: number): number;
+ setTimeout(callback: (...args: Args) => void, msDelay?: number, ...args: Args): number;
+ clearTimeout(timeoutId: number | null): void;
+ setInterval(callback: (...args: any[]) => void, msDelay?: number): number;
+ setInterval(callback: (...args: Args) => void, msDelay?: number, ...args: Args): number;
+ clearInterval(timeoutId: number | null): void;
+ queueMicrotask(task: Function): void;
+ structuredClone(value: T, options?: StructuredSerializeOptions): T;
+ reportError(error: any): void;
+ fetch(input: RequestInfo | URL, init?: RequestInit): Promise;
+ self: ServiceWorkerGlobalScope;
+ crypto: Crypto;
+ caches: CacheStorage;
+ scheduler: Scheduler;
+ performance: Performance;
+ Cloudflare: Cloudflare;
+ readonly origin: string;
+ Event: typeof Event;
+ ExtendableEvent: typeof ExtendableEvent;
+ CustomEvent: typeof CustomEvent;
+ PromiseRejectionEvent: typeof PromiseRejectionEvent;
+ FetchEvent: typeof FetchEvent;
+ TailEvent: typeof TailEvent;
+ TraceEvent: typeof TailEvent;
+ ScheduledEvent: typeof ScheduledEvent;
+ MessageEvent: typeof MessageEvent;
+ CloseEvent: typeof CloseEvent;
+ ReadableStreamDefaultReader: typeof ReadableStreamDefaultReader;
+ ReadableStreamBYOBReader: typeof ReadableStreamBYOBReader;
+ ReadableStream: typeof ReadableStream;
+ WritableStream: typeof WritableStream;
+ WritableStreamDefaultWriter: typeof WritableStreamDefaultWriter;
+ TransformStream: typeof TransformStream;
+ ByteLengthQueuingStrategy: typeof ByteLengthQueuingStrategy;
+ CountQueuingStrategy: typeof CountQueuingStrategy;
+ ErrorEvent: typeof ErrorEvent;
+ MessageChannel: typeof MessageChannel;
+ MessagePort: typeof MessagePort;
+ EventSource: typeof EventSource;
+ ReadableStreamBYOBRequest: typeof ReadableStreamBYOBRequest;
+ ReadableStreamDefaultController: typeof ReadableStreamDefaultController;
+ ReadableByteStreamController: typeof ReadableByteStreamController;
+ WritableStreamDefaultController: typeof WritableStreamDefaultController;
+ TransformStreamDefaultController: typeof TransformStreamDefaultController;
+ CompressionStream: typeof CompressionStream;
+ DecompressionStream: typeof DecompressionStream;
+ TextEncoderStream: typeof TextEncoderStream;
+ TextDecoderStream: typeof TextDecoderStream;
+ Headers: typeof Headers;
+ Body: typeof Body;
+ Request: typeof Request;
+ Response: typeof Response;
+ WebSocket: typeof WebSocket;
+ WebSocketPair: typeof WebSocketPair;
+ WebSocketRequestResponsePair: typeof WebSocketRequestResponsePair;
+ AbortController: typeof AbortController;
+ AbortSignal: typeof AbortSignal;
+ TextDecoder: typeof TextDecoder;
+ TextEncoder: typeof TextEncoder;
+ navigator: Navigator;
+ Navigator: typeof Navigator;
+ URL: typeof URL;
+ URLSearchParams: typeof URLSearchParams;
+ URLPattern: typeof URLPattern;
+ Blob: typeof Blob;
+ File: typeof File;
+ FormData: typeof FormData;
+ Crypto: typeof Crypto;
+ SubtleCrypto: typeof SubtleCrypto;
+ CryptoKey: typeof CryptoKey;
+ CacheStorage: typeof CacheStorage;
+ Cache: typeof Cache;
+ FixedLengthStream: typeof FixedLengthStream;
+ IdentityTransformStream: typeof IdentityTransformStream;
+ HTMLRewriter: typeof HTMLRewriter;
+}
+declare function addEventListener(type: Type, handler: EventListenerOrEventListenerObject, options?: EventTargetAddEventListenerOptions | boolean): void;
+declare function removeEventListener(type: Type, handler: EventListenerOrEventListenerObject, options?: EventTargetEventListenerOptions | boolean): void;
+/**
+ * The **`dispatchEvent()`** method of the EventTarget sends an Event to the object, (synchronously) invoking the affected event listeners in the appropriate order.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/dispatchEvent)
+ */
+declare function dispatchEvent(event: WorkerGlobalScopeEventMap[keyof WorkerGlobalScopeEventMap]): boolean;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/btoa) */
+declare function btoa(data: string): string;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/atob) */
+declare function atob(data: string): string;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setTimeout) */
+declare function setTimeout(callback: (...args: any[]) => void, msDelay?: number): number;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setTimeout) */
+declare function setTimeout(callback: (...args: Args) => void, msDelay?: number, ...args: Args): number;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/clearTimeout) */
+declare function clearTimeout(timeoutId: number | null): void;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setInterval) */
+declare function setInterval(callback: (...args: any[]) => void, msDelay?: number): number;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setInterval) */
+declare function setInterval(callback: (...args: Args) => void, msDelay?: number, ...args: Args): number;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/clearInterval) */
+declare function clearInterval(timeoutId: number | null): void;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/queueMicrotask) */
+declare function queueMicrotask(task: Function): void;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/structuredClone) */
+declare function structuredClone(value: T, options?: StructuredSerializeOptions): T;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/reportError) */
+declare function reportError(error: any): void;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/fetch) */
+declare function fetch(input: RequestInfo | URL, init?: RequestInit): Promise;
+declare const self: ServiceWorkerGlobalScope;
+/**
+* The Web Crypto API provides a set of low-level functions for common cryptographic tasks.
+* The Workers runtime implements the full surface of this API, but with some differences in
+* the [supported algorithms](https://developers.cloudflare.com/workers/runtime-apis/web-crypto/#supported-algorithms)
+* compared to those implemented in most browsers.
+*
+* [Cloudflare Docs Reference](https://developers.cloudflare.com/workers/runtime-apis/web-crypto/)
+*/
+declare const crypto: Crypto;
+/**
+* The Cache API allows fine grained control of reading and writing from the Cloudflare global network cache.
+*
+* [Cloudflare Docs Reference](https://developers.cloudflare.com/workers/runtime-apis/cache/)
+*/
+declare const caches: CacheStorage;
+declare const scheduler: Scheduler;
+/**
+* The Workers runtime supports a subset of the Performance API, used to measure timing and performance,
+* as well as timing of subrequests and other operations.
+*
+* [Cloudflare Docs Reference](https://developers.cloudflare.com/workers/runtime-apis/performance/)
+*/
+declare const performance: Performance;
+declare const Cloudflare: Cloudflare;
+declare const origin: string;
+declare const navigator: Navigator;
+interface TestController {
+}
+interface ExecutionContext {
+ waitUntil(promise: Promise): void;
+ passThroughOnException(): void;
+ readonly props: Props;
+}
+type ExportedHandlerFetchHandler = (request: Request>, env: Env, ctx: ExecutionContext) => Response | Promise;
+type ExportedHandlerTailHandler = (events: TraceItem[], env: Env, ctx: ExecutionContext) => void | Promise;
+type ExportedHandlerTraceHandler = (traces: TraceItem[], env: Env, ctx: ExecutionContext) => void | Promise;
+type ExportedHandlerTailStreamHandler = (event: TailStream.TailEvent, env: Env, ctx: ExecutionContext) => TailStream.TailEventHandlerType | Promise;
+type ExportedHandlerScheduledHandler = (controller: ScheduledController, env: Env, ctx: ExecutionContext) => void | Promise;
+type ExportedHandlerQueueHandler = (batch: MessageBatch, env: Env, ctx: ExecutionContext) => void | Promise;
+type ExportedHandlerTestHandler = (controller: TestController, env: Env, ctx: ExecutionContext) => void | Promise;
+interface ExportedHandler {
+ fetch?: ExportedHandlerFetchHandler;
+ tail?: ExportedHandlerTailHandler;
+ trace?: ExportedHandlerTraceHandler;
+ tailStream?: ExportedHandlerTailStreamHandler;
+ scheduled?: ExportedHandlerScheduledHandler;
+ test?: ExportedHandlerTestHandler;
+ email?: EmailExportedHandler;
+ queue?: ExportedHandlerQueueHandler;
+}
+interface StructuredSerializeOptions {
+ transfer?: any[];
+}
+declare abstract class Navigator {
+ sendBeacon(url: string, body?: BodyInit): boolean;
+ readonly userAgent: string;
+ readonly hardwareConcurrency: number;
+ readonly language: string;
+ readonly languages: string[];
+}
+interface AlarmInvocationInfo {
+ readonly isRetry: boolean;
+ readonly retryCount: number;
+}
+interface Cloudflare {
+ readonly compatibilityFlags: Record;
+}
+interface DurableObject {
+ fetch(request: Request): Response | Promise;
+ alarm?(alarmInfo?: AlarmInvocationInfo): void | Promise;
+ webSocketMessage?(ws: WebSocket, message: string | ArrayBuffer): void | Promise;
+ webSocketClose?(ws: WebSocket, code: number, reason: string, wasClean: boolean): void | Promise;
+ webSocketError?(ws: WebSocket, error: unknown): void | Promise;
+}
+type DurableObjectStub = Fetcher & {
+ readonly id: DurableObjectId;
+ readonly name?: string;
+};
+interface DurableObjectId {
+ toString(): string;
+ equals(other: DurableObjectId): boolean;
+ readonly name?: string;
+}
+declare abstract class DurableObjectNamespace {
+ newUniqueId(options?: DurableObjectNamespaceNewUniqueIdOptions): DurableObjectId;
+ idFromName(name: string): DurableObjectId;
+ idFromString(id: string): DurableObjectId;
+ get(id: DurableObjectId, options?: DurableObjectNamespaceGetDurableObjectOptions): DurableObjectStub;
+ getByName(name: string, options?: DurableObjectNamespaceGetDurableObjectOptions): DurableObjectStub;
+ jurisdiction(jurisdiction: DurableObjectJurisdiction): DurableObjectNamespace;
+}
+type DurableObjectJurisdiction = "eu" | "fedramp" | "fedramp-high";
+interface DurableObjectNamespaceNewUniqueIdOptions {
+ jurisdiction?: DurableObjectJurisdiction;
+}
+type DurableObjectLocationHint = "wnam" | "enam" | "sam" | "weur" | "eeur" | "apac" | "oc" | "afr" | "me";
+type DurableObjectRoutingMode = "primary-only";
+interface DurableObjectNamespaceGetDurableObjectOptions {
+ locationHint?: DurableObjectLocationHint;
+ routingMode?: DurableObjectRoutingMode;
+}
+interface DurableObjectClass<_T extends Rpc.DurableObjectBranded | undefined = undefined> {
+}
+interface DurableObjectState {
+ waitUntil(promise: Promise): void;
+ readonly props: Props;
+ readonly id: DurableObjectId;
+ readonly storage: DurableObjectStorage;
+ container?: Container;
+ blockConcurrencyWhile(callback: () => Promise): Promise;
+ acceptWebSocket(ws: WebSocket, tags?: string[]): void;
+ getWebSockets(tag?: string): WebSocket[];
+ setWebSocketAutoResponse(maybeReqResp?: WebSocketRequestResponsePair): void;
+ getWebSocketAutoResponse(): WebSocketRequestResponsePair | null;
+ getWebSocketAutoResponseTimestamp(ws: WebSocket): Date | null;
+ setHibernatableWebSocketEventTimeout(timeoutMs?: number): void;
+ getHibernatableWebSocketEventTimeout(): number | null;
+ getTags(ws: WebSocket): string[];
+ abort(reason?: string): void;
+}
+interface DurableObjectTransaction {
+ get(key: string, options?: DurableObjectGetOptions): Promise;
+ get(keys: string[], options?: DurableObjectGetOptions): Promise