@beachside/freestyle 0.0.0 → 0.12.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.
@@ -0,0 +1,72 @@
1
+ import { type NativeProcess, type ProcessStartContext, type ProcessStartInput, type ReadContext } from "@beachside/adapter";
2
+ import { z } from "zod";
3
+ /**
4
+ * Freestyle's `exec-await` returns only after a command ends, and its terminal sessions merge
5
+ * stdout and stderr through a TTY. A Beachside process therefore runs as a detached job in
6
+ * the guest: stdout and stderr go to private files, the exit status is written last, and the
7
+ * adapter reads new bytes from both files (base64, so they survive the lossy UTF-8 text
8
+ * channel) until the exit status appears and both files are drained. Pipe stdin is a FIFO
9
+ * kept open by a holder process; closing stdin, or the job's exit, stops the holder.
10
+ */
11
+ export declare const PROCESS_RECORD = "BEACHSIDE-PROC-1";
12
+ /** Bytes read from each stream per poll. */
13
+ export declare const POLL_BYTES: number;
14
+ /** Largest stdin chunk written per request (Freestyle's native stdin bound). */
15
+ export declare const MAX_WRITE_BYTES = 1048576;
16
+ export declare const ProcessReference: z.ZodObject<{
17
+ version: z.ZodLiteral<1>;
18
+ kind: z.ZodLiteral<"freestyle-job">;
19
+ sandbox: z.ZodString;
20
+ directory: z.ZodString;
21
+ stdin: z.ZodEnum<{
22
+ closed: "closed";
23
+ pipe: "pipe";
24
+ }>;
25
+ }, z.core.$strict>;
26
+ export type ProcessReference = z.infer<typeof ProcessReference>;
27
+ /** Runs one guest command and returns its stdout text; throws an AdapterError otherwise. */
28
+ export type GuestRunner = (command: string, ctx: ReadContext, stdin?: Uint8Array) => Promise<string>;
29
+ export type JobOptions = {
30
+ run: GuestRunner;
31
+ /** Delay between polls while the job is quiet. */
32
+ pollMs: number;
33
+ /** Bound for one poll or control request. */
34
+ requestSeconds: number;
35
+ /**
36
+ * True while this client is pausing the VM or holds it paused. Every poll is a guest command,
37
+ * which keeps the VM busy and would wake it, so observation waits instead of polling.
38
+ */
39
+ held?: () => Promise<boolean>;
40
+ };
41
+ /** The guest launcher: a private directory, the detached job, then one record line. */
42
+ export declare function launcherScript(input: ProcessStartInput): string;
43
+ /** One poll: exit status (or `-`), both sizes, then new bytes of each stream as base64. */
44
+ export declare function pollScript(directory: string, offsets: {
45
+ stdout: number;
46
+ stderr: number;
47
+ }): string;
48
+ type Poll = {
49
+ gone: true;
50
+ } | {
51
+ gone: false;
52
+ exit: number | undefined;
53
+ sizes: {
54
+ stdout: number;
55
+ stderr: number;
56
+ };
57
+ stdout: Uint8Array;
58
+ stderr: Uint8Array;
59
+ };
60
+ export declare function parsePoll(text: string): Poll | null;
61
+ /** Start or reattach to a guest job and observe it until exit or detach. */
62
+ export declare function observeJob(options: JobOptions, reference: ProcessReference, input: {
63
+ format: "text" | "bytes";
64
+ capture?: {
65
+ maxBytes: number;
66
+ };
67
+ /** Reopened jobs report output written from now on, not output delivered before. */
68
+ fromEnd: boolean;
69
+ }, ctx: ProcessStartContext): Promise<NativeProcess>;
70
+ /** Parse the launcher record: the job directory. */
71
+ export declare function parseLauncher(text: string): string | null;
72
+ export {};
@@ -0,0 +1,51 @@
1
+ import { type NativeProcess, type ProcessStartContext, type ReadContext, type TerminalDimensions } from "@beachside/adapter";
2
+ import type { PtySessionEvents, PtySessionInfo } from "freestyle";
3
+ import { z } from "zod";
4
+ /** The part of the SDK's `PtySession` a terminal uses. */
5
+ export type PtyHandle = {
6
+ write(data: Uint8Array): void;
7
+ resize(options: {
8
+ cols: number;
9
+ rows: number;
10
+ }): void;
11
+ signal(signal: "sigint" | "sigkill"): void;
12
+ detach(): void;
13
+ };
14
+ /** Freestyle terminal sessions (`vm.pty`); tests inject a deterministic stand-in. */
15
+ export type PtyDriver = {
16
+ open(vmId: string, options: {
17
+ exec: string;
18
+ cols: number;
19
+ rows: number;
20
+ slug: string;
21
+ } & PtySessionEvents): Promise<PtyHandle>;
22
+ attach(vmId: string, options: {
23
+ session: string;
24
+ } & PtySessionEvents): Promise<PtyHandle>;
25
+ list(vmId: string, ctx: ReadContext): Promise<PtySessionInfo[]>;
26
+ };
27
+ export declare const TerminalReference: z.ZodObject<{
28
+ version: z.ZodLiteral<1>;
29
+ kind: z.ZodLiteral<"freestyle-pty">;
30
+ sandbox: z.ZodString;
31
+ session: z.ZodString;
32
+ }, z.core.$strict>;
33
+ export type TerminalReference = z.infer<typeof TerminalReference>;
34
+ export declare function terminalSlug(): string;
35
+ /**
36
+ * A Beachside terminal on a named Freestyle PTY session. Output is the TTY's byte stream on
37
+ * stdout; a reattach skips the scrollback Freestyle replays first, so only new output is
38
+ * reported. Connections never reconnect on their own: a lost connection fails observation,
39
+ * and the terminal keeps running for a reopen.
40
+ */
41
+ export declare function openTerminal(driver: PtyDriver, input: {
42
+ vmId: string;
43
+ /** A new session's shell command line; absent to reattach to `reference`. */
44
+ command?: string;
45
+ terminal?: TerminalDimensions;
46
+ reference: TerminalReference;
47
+ format: "text" | "bytes";
48
+ capture?: {
49
+ maxBytes: number;
50
+ };
51
+ }, ctx: ProcessStartContext): Promise<NativeProcess>;
@@ -0,0 +1,48 @@
1
+ import { AdapterError } from "@beachside/adapter";
2
+ import { Freestyle } from "freestyle";
3
+ /** Fixed Freestyle public API origin; it is not a project-controlled setting. */
4
+ export declare const FREESTYLE_API = "https://api.freestyle.sh";
5
+ /** Largest native response body the adapter accepts, before decoding. */
6
+ export declare const MAX_RESPONSE_BYTES: number;
7
+ /**
8
+ * Code of the synthetic response a cancelled operation hands the SDK's background poll. The
9
+ * poll keeps retrying ordinary fetch failures for minutes; an API error ends it at once.
10
+ */
11
+ export declare const CANCELLED = "BEACHSIDE_CANCELLED";
12
+ /**
13
+ * Code of the synthetic error that replaces a poll-level failure of a background request. A
14
+ * stored result carries the request id header; a failure without it (such as a 404 for an
15
+ * unknown or expired result) says nothing about the operation itself, which may have run.
16
+ */
17
+ export declare const RESULT_LOST = "BACKGROUND_RESULT_LOST";
18
+ /**
19
+ * A request the adapter's fetch refused or stopped reading. It deliberately has no `code`
20
+ * property: the SDK would otherwise read it as a connection failure and replay a read.
21
+ */
22
+ export declare class FetchRefused extends Error {
23
+ readonly reason: "bound" | "origin";
24
+ constructor(reason: "bound" | "origin", message: string);
25
+ }
26
+ /** The fetch signature the adapter accepts and hands to the SDK. */
27
+ export type NativeFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
28
+ export type NativeFailure = {
29
+ /** HTTP status, or undefined when no response arrived. */
30
+ status?: number;
31
+ code?: string;
32
+ error: AdapterError;
33
+ };
34
+ /** Normalize an SDK throw into a redacted AdapterError plus the native status and code. */
35
+ export declare function nativeFailure(error: unknown, secrets: readonly string[]): NativeFailure;
36
+ /** True only when Freestyle answered with a refusal that proves the request had no effect. */
37
+ export declare function refusedBeforeEffect(failure: NativeFailure): boolean;
38
+ /**
39
+ * The `fetch` handed to the official SDK for one adapter call. It sends each request exactly
40
+ * once (the SDK itself replays only bodyless reads), refuses redirects so the API key stays on
41
+ * the Freestyle origin, ties every request to the call's signal and bounds every body.
42
+ *
43
+ * The SDK backgrounds slow requests and polls their result without a cancellation hook; once
44
+ * the call is cancelled, a poll is answered locally with an API error so the SDK stops polling.
45
+ */
46
+ export declare function callFetch(base: NativeFetch, signal: AbortSignal, limit?: number): typeof fetch;
47
+ /** A Freestyle SDK client whose every request belongs to one adapter call. */
48
+ export declare function createFreestyleClient(apiKey: string, base: NativeFetch, signal: AbortSignal, limit?: number): Freestyle;
package/package.json CHANGED
@@ -1,16 +1,46 @@
1
1
  {
2
2
  "name": "@beachside/freestyle",
3
- "version": "0.0.0",
4
- "description": "Placeholder for @beachside/freestyle. Install a published Beachside release instead.",
3
+ "version": "0.12.0",
4
+ "private": false,
5
+ "files": [
6
+ "dist",
7
+ "README.md",
8
+ "LICENSE"
9
+ ],
10
+ "type": "module",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ }
16
+ },
17
+ "scripts": {
18
+ "check": "tsc -p tsconfig.json",
19
+ "build": "rm -rf dist && bun build src/index.ts --target node --format esm --outdir dist --external @beachside/adapter --external freestyle --external zod && tsc -p tsconfig.build.json --noEmit false --declaration --emitDeclarationOnly --outDir dist && bun ../../../scripts/rewrite-declarations.mjs"
20
+ },
21
+ "dependencies": {
22
+ "freestyle": "0.2.21",
23
+ "zod": "4.6.6",
24
+ "@beachside/adapter": "0.12.0"
25
+ },
26
+ "devDependencies": {
27
+ "beachside": "0.12.0"
28
+ },
5
29
  "license": "Apache-2.0",
6
30
  "repository": {
7
31
  "type": "git",
8
32
  "url": "git+https://github.com/pandemicsyn/beachside.git",
9
33
  "directory": "packages/providers/freestyle"
10
34
  },
11
- "homepage": "https://github.com/pandemicsyn/beachside#readme",
12
- "files": [
13
- "README.md",
14
- "LICENSE"
15
- ]
35
+ "description": "Experimental Freestyle VMs sandbox provider adapter for Beachside.",
36
+ "bugs": {
37
+ "url": "https://github.com/pandemicsyn/beachside/issues"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "types": "./dist/index.d.ts",
43
+ "engines": {
44
+ "node": ">=20"
45
+ }
16
46
  }