INTEGRITY Dokumentace

Terminály

Vytvářejte a ovládejte interaktivní terminály PTY v aktuálním kontejneru sandboxu.

Vysvětlení principu fungování a postup připojení prohlížeče najdete v Terminály.

createTerminal()

Spusťte terminál z argv (obvykle shell). Vyřeší se ve chvíli, kdy je vytvořen prostředek terminálu. Platí stejná pravidla jako pro proces exec: žádné implicitní obalení shellem a položky argv nejsou escapované pro shell.

createTerminal(options: CreateTerminalOptions): Promise<Terminal>

CreateTerminalOptions

Pole Typ Popis
command SandboxCommand Argv, které se má spustit pod PTY. Povinné. Příklad: ['bash'] nebo ['/bin/bash'].
cwd string Pracovní adresář procesu terminálu.
env Record<string, string> Překrytí prostředí pro tento terminál. Neovlivní pozdější spuštění.
cols number Počáteční šířka ve sloupcích.
rows number Počáteční výška v řádcích.
bufferSize number Velikost výstupní vyrovnávací paměti pro přehrávání (pokud to runtime podporuje).

SandboxCommand je stejný typ argv jako proces exec: readonly [executable: string, ...args: string[]].

Vrací

Promise<Terminal> : handle pro terminál v aktuální kontejner.

const terminal = await sandbox.createTerminal({
	command: ["bash"],
	cwd: "/workspace",
	env: { TERM: "xterm-256color" },
	cols: 120,
	rows: 40,
});

console.log(terminal.id);
const terminal = await sandbox.createTerminal({
	command: ["bash"],
	cwd: "/workspace",
	env: { TERM: "xterm-256color" },
	cols: 120,
	rows: 40,
});

console.log(terminal.id);

getTerminal()

Vrátí popisovač terminálu v aktuální kontejner, nebo null.

Pokud neběží žádný kontejner, nespustí nový. Vrátí null když neběží žádný kontejner, když je ID terminálu v aktuálním kontejneru neznámé nebo když daný terminál patřil předchozímu kontejneru se stejným ID sandboxu.

getTerminal(id: string): Promise<Terminal | null>

listTerminals()

Vypíše terminály v aktuálním kontejneru tohoto sandboxu. Pokud žádný kontejner neběží, nespustí ho. Pokud žádný kontejner neběží, vrátí prázdný seznam.

listTerminals(): Promise<Terminal[]>

Terminal

Člen Popis
id ID terminálu v aktuálním kontejneru.
getSnapshot() Aktuální snímek (running / exited / error).
write(data) Zapíše bajty do PTY (stdin).
resize(cols, rows) Změní velikost PTY.
output(options?) Proud výstupních událostí založený na kurzoru.
waitForExit(options?) Počkejte, až terminál dokončí činnost.
interrupt() Odešlete přerušení relaci terminálu (například sémantiku Ctrl-C).
terminate() Ukončí prostředek terminálu.
connect(request, opts?) Přijměte upgrade prohlížeče na WebSocket a připojte jej k tomuto terminálu.

getSnapshot()

interface TerminalSnapshot {
	id: string;
	pid?: number;
	command: SandboxCommand;
	cwd?: string;
	status: "running" | "exited" | "error";
	exit?: ProcessExit;
	error?: ProcessFailure;
}

write()

write(data: Uint8Array): Promise<void>

Zapíše bajty do PTY. Stisky kláves z prohlížeče obvykle přicházejí přes connect() místo toho.

resize()

resize(cols: number, rows: number): Promise<void>

output()

output(options?: TerminalOutputOptions): Promise<ReadableStream<TerminalOutputEvent>>

TerminalOutputOptions

Pole Typ Popis
since string Neprůhledný kurzor; pokračuje po předchozí události.
replay boolean Při obnovení zahrne historii uloženou ve vyrovnávací paměti.
follow boolean Udržujte stream otevřený pro živý výstup.
signal AbortSignal Zrušte pouze tento odběr. Terminál poběží dál.

TerminalOutputEvent

type TerminalOutputEvent =
	| {
			type: "data";
			terminalId: string;
			cursor: string;
			timestamp: string;
			data: Uint8Array;
	  }
	| {
			type: "terminal";
			terminalId: string;
			cursor: string;
			timestamp: string;
			state: "exited";
			exit: ProcessExit;
	  }
	| {
			type: "terminal";
			terminalId: string;
			cursor: string;
			timestamp: string;
			state: "error";
			error: ProcessFailure;
	  }
	| {
			type: "truncated";
			terminalId: string;
			cursor?: string;
			timestamp: string;
	  };

Ponechte nejnovější cursor z doručených událostí, pokud se znovu připojíte nebo zavoláte output({ since, replay: true }) později na stejný terminál v stejný kontejner.

waitForExit()

waitForExit(options?: {
	timeout?: number;
	signal?: AbortSignal;
}): Promise<ProcessExit>

Lokální timeout / signal zruší pouze čekání. Terminál tím neukončí. Zavolejte terminate() nebo interrupt() když ho hodláte zastavit.

interrupt() a terminate()

interrupt(): Promise<void>
terminate(): Promise<void>

Jde o řídicí operace terminálu. Nejde o totéž jako process kill(signal) na exec handle.

connect()

Připojte k tomuto terminálu požadavek na upgrade WebSocket z prohlížeče (nebo jiného zdroje).

connect(
	request: Request,
	options?: {
		cursor?: string;
		cols?: number;
		rows?: number;
	},
): Promise<Response>

Vrátí WebSocket upgrade Response by měl váš Worker vrátit klientovi.

const url = new URL(request.url);
const terminalId = url.searchParams.get("terminalId");
if (!terminalId) {
	return new Response("terminalId is required", { status: 400 });
}

const terminal = await sandbox.getTerminal(terminalId);
if (!terminal) {
	return new Response("Terminal not found", { status: 404 });
}

return terminal.connect(request, {
	cursor: url.searchParams.get("cursor") ?? undefined,
	cols: 120,
	rows: 40,
});
const url = new URL(request.url);
const terminalId = url.searchParams.get("terminalId");
if (!terminalId) {
	return new Response("terminalId is required", { status: 400 });
}

const terminal = await sandbox.getTerminal(terminalId);
if (!terminal) {
	return new Response("Terminal not found", { status: 404 });
}

return terminal.connect(request, {
	cursor: url.searchParams.get("cursor") ?? undefined,
	cols: 120,
	rows: 40,
});

Úplný postup s Worker + xterm.js najdete v Terminály.

Pomocník klienta: @cloudflare/sandbox/xterm

SandboxAddon integruje xterm.js ↗ s náhledovými terminály.

import { SandboxAddon } from "@cloudflare/sandbox/xterm";

const addon = new SandboxAddon({
	// `origin` is already a WebSocket origin (`wss://` or `ws://`).
	getWebSocketUrl: ({ sandboxId, terminalId, cursor, origin }) => {
		const params = new URLSearchParams({ sandboxId });
		if (terminalId) params.set("terminalId", terminalId);
		if (cursor) params.set("cursor", cursor);
		return `${origin}/ws/terminal?${params}`;
	},
	reconnect: true,
	onStateChange: (state, error) => {
		/* update UI */
	},
});
import { SandboxAddon } from "@cloudflare/sandbox/xterm";

const addon = new SandboxAddon({
	// `origin` is already a WebSocket origin (`wss://` or `ws://`).
	getWebSocketUrl: ({ sandboxId, terminalId, cursor, origin }) => {
		const params = new URLSearchParams({ sandboxId });
		if (terminalId) params.set("terminalId", terminalId);
		if (cursor) params.set("cursor", cursor);
		return `${origin}/ws/terminal?${params}`;
	},
	reconnect: true,
	onStateChange: (state, error) => {
		/* update UI */
	},
});
Položka Podrobnosti náhledu
Cíl připojení { sandboxId, terminalId? }
getWebSocketUrl parametry sandboxId, terminalId?, cursor?, origin
Vlastnosti state, sandboxId, terminalId

@xterm/xterm je volitelná peer dependency balíčku preview.

Časté chyby

Situace Třída / výsledek
Neznámé ID terminálu v aktuálním kontejneru TerminalNotFoundError
getTerminal / listTerminals zatímco neběží žádný kontejner null / [] (nejde o chybu; nespouští kontejner)
Handle nebo ID terminálu z předchozího kontejneru StaleTerminalHandleError
Neplatný pracovní adresář při vytvoření InvalidTerminalCwdError
Neplatný kurzor výstupu InvalidTerminalCursorError
Řídicí operace se nezdařila TerminalControlError

Pokyny k obnovení: Chyby a zotavení. Úplný katalog: API chyb. Životnost: Jak dlouho proces žije.