@yolk-sdk/sandbox 0.1.0-canary.39 → 0.1.0-canary.41

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.
@@ -1,5 +1,5 @@
1
1
  import { SandboxInitialSource, SandboxResources, SandboxSnapshotRetention } from "../model.mjs";
2
- import { Context, Layer } from "effect";
2
+ import { Context, Effect, Layer } from "effect";
3
3
  import { NetworkPolicy } from "@vercel/sandbox";
4
4
 
5
5
  //#region src/vercel/client.d.ts
@@ -13,14 +13,14 @@ type VercelCommandSignal = 'SIGTERM' | 'SIGKILL';
13
13
  type VercelFinishedCommand = {
14
14
  readonly id: string;
15
15
  readonly exitCode: number;
16
- readonly output: () => Promise<VercelCommandOutput>;
16
+ readonly output: Effect.Effect<VercelCommandOutput, unknown>;
17
17
  };
18
18
  type VercelDetachedCommand = {
19
19
  readonly id: string;
20
20
  readonly exitCode: number | null;
21
- readonly wait: () => Promise<VercelFinishedCommand>;
22
- readonly kill: (signal: VercelCommandSignal) => Promise<void>;
23
- readonly output: () => Promise<VercelCommandOutput>;
21
+ readonly wait: Effect.Effect<VercelFinishedCommand, unknown>;
22
+ readonly kill: (signal: VercelCommandSignal) => Effect.Effect<void, unknown>;
23
+ readonly output: Effect.Effect<VercelCommandOutput, unknown>;
24
24
  };
25
25
  type VercelSandboxFile = {
26
26
  readonly path: string;
@@ -50,16 +50,16 @@ type VercelSandboxGetInput = {
50
50
  };
51
51
  type VercelSandboxHandle = {
52
52
  readonly name: string;
53
- readonly writeFiles: (files: ReadonlyArray<VercelSandboxFile>) => Promise<void>;
54
- readonly runDetachedCommand: (input: VercelRunCommandInput) => Promise<VercelDetachedCommand>;
55
- readonly getCommand: (id: string) => Promise<VercelDetachedCommand>;
56
- readonly extendTimeout: (durationMs: number) => Promise<void>;
57
- readonly delete: () => Promise<void>;
53
+ readonly writeFiles: (files: ReadonlyArray<VercelSandboxFile>) => Effect.Effect<void, unknown>;
54
+ readonly runDetachedCommand: (input: VercelRunCommandInput) => Effect.Effect<VercelDetachedCommand, unknown>;
55
+ readonly getCommand: (id: string) => Effect.Effect<VercelDetachedCommand, unknown>;
56
+ readonly extendTimeout: (durationMs: number) => Effect.Effect<void, unknown>;
57
+ readonly delete: Effect.Effect<void, unknown>;
58
58
  readonly domain: (port: number) => string;
59
59
  };
60
60
  type VercelSandboxClientApi = {
61
- readonly get: (input: VercelSandboxGetInput) => Promise<VercelSandboxHandle | null>;
62
- readonly create: (input: VercelSandboxCreateInput) => Promise<VercelSandboxHandle>;
61
+ readonly get: (input: VercelSandboxGetInput) => Effect.Effect<VercelSandboxHandle | null, unknown>;
62
+ readonly create: (input: VercelSandboxCreateInput) => Effect.Effect<VercelSandboxHandle, unknown>;
63
63
  };
64
64
  declare const VercelSandboxClient_base: Context.ServiceClass<VercelSandboxClient, "@yolk-sdk/sandbox/vercel/VercelSandboxClient", VercelSandboxClientApi>;
65
65
  declare class VercelSandboxClient extends VercelSandboxClient_base {}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.mts","names":[],"sources":["../../src/vercel/client.ts"],"mappings":";;;;;KAUY,oBAAA;AAAA,KACA,mBAAA,GAAsB,aAAa;AAAA,KAEnC,mBAAA;EAAA,SACD,MAAA;EAAA,SACA,MAAM;AAAA;AAAA,KAGL,mBAAA;AAAA,KAEA,qBAAA;EAAA,SACD,EAAA;EAAA,SACA,QAAA;EAAA,SACA,MAAA,QAAc,OAAO,CAAC,mBAAA;AAAA;AAAA,KAGrB,qBAAA;EAAA,SACD,EAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA,QAAY,OAAA,CAAQ,qBAAA;EAAA,SACpB,IAAA,GAAO,MAAA,EAAQ,mBAAA,KAAwB,OAAA;EAAA,SACvC,MAAA,QAAc,OAAA,CAAQ,mBAAA;AAAA;AAAA,KAGrB,iBAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA;EAAA,SACA,IAAA;AAAA;AAAA,KAGC,qBAAA;EAAA,SACD,GAAA;EAAA,SACA,IAAA,GAAO,aAAa;EAAA,SACpB,GAAA;AAAA;AAAA,KAGC,wBAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,oBAAA;EAAA,SACR,KAAA,EAAO,aAAA;EAAA,SACP,SAAA;EAAA,SACA,SAAA,EAAW,gBAAA;EAAA,SACX,OAAA,EAAS,oBAAA;EAAA,SACT,GAAA,GAAM,QAAA,CAAS,MAAA;EAAA,SACf,UAAA;EAAA,SACA,oBAAA;EAAA,SACA,iBAAA,GAAoB,wBAAA;EAAA,SACpB,aAAA,GAAgB,mBAAA;AAAA;AAAA,KAGf,qBAAA;EAAA,SACD,IAAI;AAAA;AAAA,KAGH,mBAAA;EAAA,SACD,IAAA;EAAA,SACA,UAAA,GAAa,KAAA,EAAO,aAAA,CAAc,iBAAA,MAAuB,OAAA;EAAA,SACzD,kBAAA,GAAqB,KAAA,EAAO,qBAAA,KAA0B,OAAA,CAAQ,qBAAA;EAAA,SAC9D,UAAA,GAAa,EAAA,aAAe,OAAA,CAAQ,qBAAA;EAAA,SACpC,aAAA,GAAgB,UAAA,aAAuB,OAAA;EAAA,SACvC,MAAA,QAAc,OAAA;EAAA,SACd,MAAA,GAAS,IAAA;AAAA;AAAA,KAGR,sBAAA;EAAA,SACD,GAAA,GAAM,KAAA,EAAO,qBAAA,KAA0B,OAAA,CAAQ,mBAAA;EAAA,SAC/C,MAAA,GAAS,KAAA,EAAO,wBAAA,KAA6B,OAAA,CAAQ,mBAAA;AAAA;AAAA,cAC/D,wBAAA;cAEY,mBAAA,SAA4B,wBAGU;AAAA,cAEtC,2BAAA,GAA+B,KAAc;AAAA,cAwI7C,uBAAA,EAAuB,KAAA,CAAA,KAAA,CAAA,mBAAA"}
1
+ {"version":3,"file":"client.d.mts","names":[],"sources":["../../src/vercel/client.ts"],"mappings":";;;;;KAUY,oBAAA;AAAA,KACA,mBAAA,GAAsB,aAAa;AAAA,KAEnC,mBAAA;EAAA,SACD,MAAA;EAAA,SACA,MAAM;AAAA;AAAA,KAGL,mBAAA;AAAA,KAEA,qBAAA;EAAA,SACD,EAAA;EAAA,SACA,QAAA;EAAA,SACA,MAAA,EAAQ,MAAA,CAAO,MAAM,CAAC,mBAAA;AAAA;AAAA,KAGrB,qBAAA;EAAA,SACD,EAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA,EAAM,MAAA,CAAO,MAAA,CAAO,qBAAA;EAAA,SACpB,IAAA,GAAO,MAAA,EAAQ,mBAAA,KAAwB,MAAA,CAAO,MAAA;EAAA,SAC9C,MAAA,EAAQ,MAAA,CAAO,MAAA,CAAO,mBAAA;AAAA;AAAA,KAGrB,iBAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA;EAAA,SACA,IAAA;AAAA;AAAA,KAGC,qBAAA;EAAA,SACD,GAAA;EAAA,SACA,IAAA,GAAO,aAAa;EAAA,SACpB,GAAA;AAAA;AAAA,KAGC,wBAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,oBAAA;EAAA,SACR,KAAA,EAAO,aAAA;EAAA,SACP,SAAA;EAAA,SACA,SAAA,EAAW,gBAAA;EAAA,SACX,OAAA,EAAS,oBAAA;EAAA,SACT,GAAA,GAAM,QAAA,CAAS,MAAA;EAAA,SACf,UAAA;EAAA,SACA,oBAAA;EAAA,SACA,iBAAA,GAAoB,wBAAA;EAAA,SACpB,aAAA,GAAgB,mBAAA;AAAA;AAAA,KAGf,qBAAA;EAAA,SACD,IAAI;AAAA;AAAA,KAGH,mBAAA;EAAA,SACD,IAAA;EAAA,SACA,UAAA,GAAa,KAAA,EAAO,aAAA,CAAc,iBAAA,MAAuB,MAAA,CAAO,MAAA;EAAA,SAChE,kBAAA,GACP,KAAA,EAAO,qBAAA,KACJ,MAAA,CAAO,MAAA,CAAO,qBAAA;EAAA,SACV,UAAA,GAAa,EAAA,aAAe,MAAA,CAAO,MAAA,CAAO,qBAAA;EAAA,SAC1C,aAAA,GAAgB,UAAA,aAAuB,MAAA,CAAO,MAAA;EAAA,SAC9C,MAAA,EAAQ,MAAA,CAAO,MAAA;EAAA,SACf,MAAA,GAAS,IAAA;AAAA;AAAA,KAGR,sBAAA;EAAA,SACD,GAAA,GAAM,KAAA,EAAO,qBAAA,KAA0B,MAAA,CAAO,MAAA,CAAO,mBAAA;EAAA,SACrD,MAAA,GAAS,KAAA,EAAO,wBAAA,KAA6B,MAAA,CAAO,MAAA,CAAO,mBAAA;AAAA;AAAA,cACrE,wBAAA;cAEY,mBAAA,SAA4B,wBAGU;AAAA,cAEtC,2BAAA,GAA+B,KAAc;AAAA,cAoJ7C,uBAAA,EAAuB,KAAA,CAAA,KAAA,CAAA,mBAAA"}
@@ -1,40 +1,44 @@
1
- import { Context, Layer } from "effect";
1
+ import { Context, Effect, Layer } from "effect";
2
2
  import { APIError, Sandbox } from "@vercel/sandbox";
3
3
  //#region src/vercel/client.ts
4
4
  var VercelSandboxClient = class extends Context.Service()("@yolk-sdk/sandbox/vercel/VercelSandboxClient") {};
5
5
  const isVercelMissingSandboxError = (error) => error instanceof APIError && (error.response.status === 404 || error.response.status === 410);
6
- const commandOutput = (command) => Promise.all([command.stdout(), command.stderr()]).then(([stdout, stderr]) => ({
7
- stdout,
8
- stderr
9
- }));
6
+ const tryVercelPromise = (body) => Effect.tryPromise({
7
+ try: body,
8
+ catch: (error) => error
9
+ });
10
+ const commandOutput = (command) => Effect.all({
11
+ stdout: tryVercelPromise(() => command.stdout()),
12
+ stderr: tryVercelPromise(() => command.stderr())
13
+ });
10
14
  const toFinishedCommand = (command) => ({
11
15
  id: command.cmdId,
12
16
  exitCode: command.exitCode,
13
- output: () => commandOutput(command)
17
+ output: commandOutput(command)
14
18
  });
15
19
  const toDetachedCommand = (command) => ({
16
20
  id: command.cmdId,
17
21
  exitCode: command.exitCode,
18
- wait: () => command.wait().then(toFinishedCommand),
19
- kill: (signal) => command.kill(signal),
20
- output: () => commandOutput(command)
22
+ wait: tryVercelPromise(() => command.wait()).pipe(Effect.map(toFinishedCommand)),
23
+ kill: (signal) => tryVercelPromise(() => command.kill(signal)),
24
+ output: commandOutput(command)
21
25
  });
22
26
  const toHandle = (sandbox) => ({
23
27
  name: sandbox.name,
24
- writeFiles: (files) => sandbox.writeFiles(files.map((file) => ({
28
+ writeFiles: (files) => tryVercelPromise(() => sandbox.writeFiles(files.map((file) => ({
25
29
  path: file.path,
26
30
  content: file.content,
27
31
  ...file.mode === void 0 ? {} : { mode: file.mode }
28
- }))),
29
- runDetachedCommand: (input) => sandbox.runCommand({
32
+ })))),
33
+ runDetachedCommand: (input) => tryVercelPromise(() => sandbox.runCommand({
30
34
  cmd: input.cmd,
31
35
  args: input.args === void 0 ? [] : [...input.args],
32
36
  ...input.cwd === void 0 ? {} : { cwd: input.cwd },
33
37
  detached: true
34
- }).then(toDetachedCommand),
35
- getCommand: (id) => sandbox.getCommand(id).then(toDetachedCommand),
36
- extendTimeout: (durationMs) => sandbox.extendTimeout(durationMs).then(() => void 0),
37
- delete: () => sandbox.delete().then(() => void 0),
38
+ })).pipe(Effect.map(toDetachedCommand)),
39
+ getCommand: (id) => tryVercelPromise(() => sandbox.getCommand(id)).pipe(Effect.map(toDetachedCommand)),
40
+ extendTimeout: (durationMs) => tryVercelPromise(() => sandbox.extendTimeout(durationMs)).pipe(Effect.asVoid),
41
+ delete: tryVercelPromise(() => sandbox.delete()).pipe(Effect.asVoid),
38
42
  domain: (port) => sandbox.domain(port)
39
43
  });
40
44
  const envObject = (env) => env === void 0 ? void 0 : Object.fromEntries(Object.entries(env));
@@ -101,11 +105,11 @@ const createSandbox = (input) => {
101
105
  }
102
106
  };
103
107
  const VercelSandboxClientLive = Layer.succeed(VercelSandboxClient, VercelSandboxClient.of({
104
- get: (input) => Sandbox.get({ name: input.name }).then(toHandle).catch((error) => {
105
- if (isVercelMissingSandboxError(error)) return null;
106
- throw error;
107
- }),
108
- create: (input) => createSandbox(input).then(toHandle)
108
+ get: (input) => tryVercelPromise(() => Sandbox.get({ name: input.name })).pipe(Effect.map(toHandle), Effect.catch((error) => {
109
+ if (isVercelMissingSandboxError(error)) return Effect.succeed(null);
110
+ return Effect.fail(error);
111
+ })),
112
+ create: (input) => tryVercelPromise(() => createSandbox(input)).pipe(Effect.map(toHandle))
109
113
  }));
110
114
  //#endregion
111
115
  export { VercelSandboxClient, VercelSandboxClientLive, isVercelMissingSandboxError };
@@ -1 +1 @@
1
- {"version":3,"file":"client.mjs","names":["VercelSdkSandbox"],"sources":["../../src/vercel/client.ts"],"sourcesContent":["import { Context, Layer } from 'effect'\nimport {\n APIError,\n Sandbox as VercelSdkSandbox,\n type Command,\n type CommandFinished,\n type NetworkPolicy\n} from '@vercel/sandbox'\nimport type { SandboxInitialSource, SandboxResources, SandboxSnapshotRetention } from '../model.ts'\n\nexport type VercelSandboxRuntime = 'node22' | 'node24' | 'node26' | 'python3.13'\nexport type VercelNetworkPolicy = NetworkPolicy\n\nexport type VercelCommandOutput = {\n readonly stdout: string\n readonly stderr: string\n}\n\nexport type VercelCommandSignal = 'SIGTERM' | 'SIGKILL'\n\nexport type VercelFinishedCommand = {\n readonly id: string\n readonly exitCode: number\n readonly output: () => Promise<VercelCommandOutput>\n}\n\nexport type VercelDetachedCommand = {\n readonly id: string\n readonly exitCode: number | null\n readonly wait: () => Promise<VercelFinishedCommand>\n readonly kill: (signal: VercelCommandSignal) => Promise<void>\n readonly output: () => Promise<VercelCommandOutput>\n}\n\nexport type VercelSandboxFile = {\n readonly path: string\n readonly content: string\n readonly mode?: number\n}\n\nexport type VercelRunCommandInput = {\n readonly cmd: string\n readonly args?: ReadonlyArray<string>\n readonly cwd?: string\n}\n\nexport type VercelSandboxCreateInput = {\n readonly name: string\n readonly source: SandboxInitialSource\n readonly ports: ReadonlyArray<number>\n readonly timeoutMs: number\n readonly resources: SandboxResources\n readonly runtime: VercelSandboxRuntime\n readonly env?: Readonly<Record<string, string>>\n readonly persistent: boolean\n readonly snapshotExpirationMs?: number\n readonly keepLastSnapshots?: SandboxSnapshotRetention\n readonly networkPolicy?: VercelNetworkPolicy\n}\n\nexport type VercelSandboxGetInput = {\n readonly name: string\n}\n\nexport type VercelSandboxHandle = {\n readonly name: string\n readonly writeFiles: (files: ReadonlyArray<VercelSandboxFile>) => Promise<void>\n readonly runDetachedCommand: (input: VercelRunCommandInput) => Promise<VercelDetachedCommand>\n readonly getCommand: (id: string) => Promise<VercelDetachedCommand>\n readonly extendTimeout: (durationMs: number) => Promise<void>\n readonly delete: () => Promise<void>\n readonly domain: (port: number) => string\n}\n\nexport type VercelSandboxClientApi = {\n readonly get: (input: VercelSandboxGetInput) => Promise<VercelSandboxHandle | null>\n readonly create: (input: VercelSandboxCreateInput) => Promise<VercelSandboxHandle>\n}\n\nexport class VercelSandboxClient extends Context.Service<\n VercelSandboxClient,\n VercelSandboxClientApi\n>()('@yolk-sdk/sandbox/vercel/VercelSandboxClient') {}\n\nexport const isVercelMissingSandboxError = (error: unknown) =>\n error instanceof APIError && (error.response.status === 404 || error.response.status === 410)\n\nconst commandOutput = (command: Command | CommandFinished): Promise<VercelCommandOutput> =>\n Promise.all([command.stdout(), command.stderr()]).then(([stdout, stderr]) => ({ stdout, stderr }))\n\nconst toFinishedCommand = (command: CommandFinished): VercelFinishedCommand => ({\n id: command.cmdId,\n exitCode: command.exitCode,\n output: () => commandOutput(command)\n})\n\nconst toDetachedCommand = (command: Command): VercelDetachedCommand => ({\n id: command.cmdId,\n exitCode: command.exitCode,\n wait: () => command.wait().then(toFinishedCommand),\n kill: signal => command.kill(signal),\n output: () => commandOutput(command)\n})\n\nconst toHandle = (sandbox: VercelSdkSandbox): VercelSandboxHandle => ({\n name: sandbox.name,\n writeFiles: files =>\n sandbox.writeFiles(\n files.map(file => ({\n path: file.path,\n content: file.content,\n ...(file.mode === undefined ? {} : { mode: file.mode })\n }))\n ),\n runDetachedCommand: input =>\n sandbox\n .runCommand({\n cmd: input.cmd,\n args: input.args === undefined ? [] : [...input.args],\n ...(input.cwd === undefined ? {} : { cwd: input.cwd }),\n detached: true\n })\n .then(toDetachedCommand),\n getCommand: id => sandbox.getCommand(id).then(toDetachedCommand),\n extendTimeout: durationMs => sandbox.extendTimeout(durationMs).then(() => undefined),\n delete: () => sandbox.delete().then(() => undefined),\n domain: port => sandbox.domain(port)\n})\n\nconst envObject = (env?: Readonly<Record<string, string>>) =>\n env === undefined ? undefined : Object.fromEntries(Object.entries(env))\n\nconst retentionObject = (retention?: SandboxSnapshotRetention) =>\n retention === undefined\n ? undefined\n : {\n count: retention.count,\n ...(retention.expirationMs === undefined ? {} : { expiration: retention.expirationMs }),\n ...(retention.deleteEvicted === undefined ? {} : { deleteEvicted: retention.deleteEvicted })\n }\n\ntype AnonymousGitSource = {\n readonly type: 'git'\n readonly url: string\n readonly depth?: number\n readonly revision?: string\n}\n\ntype BasicAuthGitSource = AnonymousGitSource & {\n readonly username: string\n readonly password: string\n}\n\nconst commonCreateOptions = (input: VercelSandboxCreateInput) => ({\n name: input.name,\n ports: [...input.ports],\n timeout: input.timeoutMs,\n resources: { vcpus: input.resources.vcpus },\n env: envObject(input.env),\n persistent: input.persistent,\n networkPolicy: input.networkPolicy,\n snapshotExpiration: input.snapshotExpirationMs,\n keepLastSnapshots: retentionObject(input.keepLastSnapshots)\n})\n\nconst gitSource = (\n source: Extract<SandboxInitialSource, { readonly _tag: 'Git' }>\n): AnonymousGitSource | BasicAuthGitSource => {\n if ((source.username === undefined) !== (source.password === undefined)) {\n throw new Error('Vercel git source requires both username and password when using basic auth')\n }\n\n if (source.username !== undefined && source.password !== undefined) {\n return {\n type: 'git',\n url: source.url,\n username: source.username,\n password: source.password,\n ...(source.depth === undefined ? {} : { depth: source.depth }),\n ...(source.revision === undefined ? {} : { revision: source.revision })\n }\n }\n\n return {\n type: 'git',\n url: source.url,\n ...(source.depth === undefined ? {} : { depth: source.depth }),\n ...(source.revision === undefined ? {} : { revision: source.revision })\n }\n}\n\nconst createSandbox = (input: VercelSandboxCreateInput) => {\n const common = commonCreateOptions(input)\n\n switch (input.source._tag) {\n case 'Empty':\n return VercelSdkSandbox.create({\n ...common,\n runtime: input.runtime\n })\n case 'Snapshot':\n return VercelSdkSandbox.create({\n ...common,\n source: { type: 'snapshot', snapshotId: input.source.snapshotId }\n })\n case 'Git':\n return VercelSdkSandbox.create({\n ...common,\n runtime: input.runtime,\n source: gitSource(input.source)\n })\n case 'Tarball':\n return VercelSdkSandbox.create({\n ...common,\n runtime: input.runtime,\n source: { type: 'tarball', url: input.source.url }\n })\n }\n}\n\nexport const VercelSandboxClientLive = Layer.succeed(\n VercelSandboxClient,\n VercelSandboxClient.of({\n get: input =>\n VercelSdkSandbox.get({ name: input.name })\n .then(toHandle)\n .catch(error => {\n if (isVercelMissingSandboxError(error)) {\n return null\n }\n\n throw error\n }),\n create: input => createSandbox(input).then(toHandle)\n })\n)\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.mjs","names":["VercelSdkSandbox"],"sources":["../../src/vercel/client.ts"],"sourcesContent":["import { Context, Effect, Layer } from 'effect'\nimport {\n APIError,\n Sandbox as VercelSdkSandbox,\n type Command,\n type CommandFinished,\n type NetworkPolicy\n} from '@vercel/sandbox'\nimport type { SandboxInitialSource, SandboxResources, SandboxSnapshotRetention } from '../model.ts'\n\nexport type VercelSandboxRuntime = 'node22' | 'node24' | 'node26' | 'python3.13'\nexport type VercelNetworkPolicy = NetworkPolicy\n\nexport type VercelCommandOutput = {\n readonly stdout: string\n readonly stderr: string\n}\n\nexport type VercelCommandSignal = 'SIGTERM' | 'SIGKILL'\n\nexport type VercelFinishedCommand = {\n readonly id: string\n readonly exitCode: number\n readonly output: Effect.Effect<VercelCommandOutput, unknown>\n}\n\nexport type VercelDetachedCommand = {\n readonly id: string\n readonly exitCode: number | null\n readonly wait: Effect.Effect<VercelFinishedCommand, unknown>\n readonly kill: (signal: VercelCommandSignal) => Effect.Effect<void, unknown>\n readonly output: Effect.Effect<VercelCommandOutput, unknown>\n}\n\nexport type VercelSandboxFile = {\n readonly path: string\n readonly content: string\n readonly mode?: number\n}\n\nexport type VercelRunCommandInput = {\n readonly cmd: string\n readonly args?: ReadonlyArray<string>\n readonly cwd?: string\n}\n\nexport type VercelSandboxCreateInput = {\n readonly name: string\n readonly source: SandboxInitialSource\n readonly ports: ReadonlyArray<number>\n readonly timeoutMs: number\n readonly resources: SandboxResources\n readonly runtime: VercelSandboxRuntime\n readonly env?: Readonly<Record<string, string>>\n readonly persistent: boolean\n readonly snapshotExpirationMs?: number\n readonly keepLastSnapshots?: SandboxSnapshotRetention\n readonly networkPolicy?: VercelNetworkPolicy\n}\n\nexport type VercelSandboxGetInput = {\n readonly name: string\n}\n\nexport type VercelSandboxHandle = {\n readonly name: string\n readonly writeFiles: (files: ReadonlyArray<VercelSandboxFile>) => Effect.Effect<void, unknown>\n readonly runDetachedCommand: (\n input: VercelRunCommandInput\n ) => Effect.Effect<VercelDetachedCommand, unknown>\n readonly getCommand: (id: string) => Effect.Effect<VercelDetachedCommand, unknown>\n readonly extendTimeout: (durationMs: number) => Effect.Effect<void, unknown>\n readonly delete: Effect.Effect<void, unknown>\n readonly domain: (port: number) => string\n}\n\nexport type VercelSandboxClientApi = {\n readonly get: (input: VercelSandboxGetInput) => Effect.Effect<VercelSandboxHandle | null, unknown>\n readonly create: (input: VercelSandboxCreateInput) => Effect.Effect<VercelSandboxHandle, unknown>\n}\n\nexport class VercelSandboxClient extends Context.Service<\n VercelSandboxClient,\n VercelSandboxClientApi\n>()('@yolk-sdk/sandbox/vercel/VercelSandboxClient') {}\n\nexport const isVercelMissingSandboxError = (error: unknown) =>\n error instanceof APIError && (error.response.status === 404 || error.response.status === 410)\n\nconst tryVercelPromise = <A>(body: () => Promise<A>) =>\n Effect.tryPromise({\n try: body,\n catch: error => error\n })\n\nconst commandOutput = (command: Command | CommandFinished): Effect.Effect<VercelCommandOutput, unknown> =>\n Effect.all({\n stdout: tryVercelPromise(() => command.stdout()),\n stderr: tryVercelPromise(() => command.stderr())\n })\n\nconst toFinishedCommand = (command: CommandFinished): VercelFinishedCommand => ({\n id: command.cmdId,\n exitCode: command.exitCode,\n output: commandOutput(command)\n})\n\nconst toDetachedCommand = (command: Command): VercelDetachedCommand => ({\n id: command.cmdId,\n exitCode: command.exitCode,\n wait: tryVercelPromise(() => command.wait()).pipe(Effect.map(toFinishedCommand)),\n kill: signal => tryVercelPromise(() => command.kill(signal)),\n output: commandOutput(command)\n})\n\nconst toHandle = (sandbox: VercelSdkSandbox): VercelSandboxHandle => ({\n name: sandbox.name,\n writeFiles: files =>\n tryVercelPromise(() =>\n sandbox.writeFiles(\n files.map(file => ({\n path: file.path,\n content: file.content,\n ...(file.mode === undefined ? {} : { mode: file.mode })\n }))\n )\n ),\n runDetachedCommand: input =>\n tryVercelPromise(() =>\n sandbox.runCommand({\n cmd: input.cmd,\n args: input.args === undefined ? [] : [...input.args],\n ...(input.cwd === undefined ? {} : { cwd: input.cwd }),\n detached: true\n })\n ).pipe(Effect.map(toDetachedCommand)),\n getCommand: id => tryVercelPromise(() => sandbox.getCommand(id)).pipe(Effect.map(toDetachedCommand)),\n extendTimeout: durationMs =>\n tryVercelPromise(() => sandbox.extendTimeout(durationMs)).pipe(Effect.asVoid),\n delete: tryVercelPromise(() => sandbox.delete()).pipe(Effect.asVoid),\n domain: port => sandbox.domain(port)\n})\n\nconst envObject = (env?: Readonly<Record<string, string>>) =>\n env === undefined ? undefined : Object.fromEntries(Object.entries(env))\n\nconst retentionObject = (retention?: SandboxSnapshotRetention) =>\n retention === undefined\n ? undefined\n : {\n count: retention.count,\n ...(retention.expirationMs === undefined ? {} : { expiration: retention.expirationMs }),\n ...(retention.deleteEvicted === undefined ? {} : { deleteEvicted: retention.deleteEvicted })\n }\n\ntype AnonymousGitSource = {\n readonly type: 'git'\n readonly url: string\n readonly depth?: number\n readonly revision?: string\n}\n\ntype BasicAuthGitSource = AnonymousGitSource & {\n readonly username: string\n readonly password: string\n}\n\nconst commonCreateOptions = (input: VercelSandboxCreateInput) => ({\n name: input.name,\n ports: [...input.ports],\n timeout: input.timeoutMs,\n resources: { vcpus: input.resources.vcpus },\n env: envObject(input.env),\n persistent: input.persistent,\n networkPolicy: input.networkPolicy,\n snapshotExpiration: input.snapshotExpirationMs,\n keepLastSnapshots: retentionObject(input.keepLastSnapshots)\n})\n\nconst gitSource = (\n source: Extract<SandboxInitialSource, { readonly _tag: 'Git' }>\n): AnonymousGitSource | BasicAuthGitSource => {\n if ((source.username === undefined) !== (source.password === undefined)) {\n throw new Error('Vercel git source requires both username and password when using basic auth')\n }\n\n if (source.username !== undefined && source.password !== undefined) {\n return {\n type: 'git',\n url: source.url,\n username: source.username,\n password: source.password,\n ...(source.depth === undefined ? {} : { depth: source.depth }),\n ...(source.revision === undefined ? {} : { revision: source.revision })\n }\n }\n\n return {\n type: 'git',\n url: source.url,\n ...(source.depth === undefined ? {} : { depth: source.depth }),\n ...(source.revision === undefined ? {} : { revision: source.revision })\n }\n}\n\nconst createSandbox = (input: VercelSandboxCreateInput) => {\n const common = commonCreateOptions(input)\n\n switch (input.source._tag) {\n case 'Empty':\n return VercelSdkSandbox.create({\n ...common,\n runtime: input.runtime\n })\n case 'Snapshot':\n return VercelSdkSandbox.create({\n ...common,\n source: { type: 'snapshot', snapshotId: input.source.snapshotId }\n })\n case 'Git':\n return VercelSdkSandbox.create({\n ...common,\n runtime: input.runtime,\n source: gitSource(input.source)\n })\n case 'Tarball':\n return VercelSdkSandbox.create({\n ...common,\n runtime: input.runtime,\n source: { type: 'tarball', url: input.source.url }\n })\n }\n}\n\nexport const VercelSandboxClientLive = Layer.succeed(\n VercelSandboxClient,\n VercelSandboxClient.of({\n get: input =>\n tryVercelPromise(() => VercelSdkSandbox.get({ name: input.name })).pipe(\n Effect.map(toHandle),\n Effect.catch((error: unknown) => {\n if (isVercelMissingSandboxError(error)) {\n return Effect.succeed(null)\n }\n\n return Effect.fail(error)\n })\n ),\n create: input => tryVercelPromise(() => createSandbox(input)).pipe(Effect.map(toHandle))\n })\n)\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"layer.d.mts","names":[],"sources":["../../src/vercel/layer.ts"],"mappings":";;;;;;;KAuCY,wBAAA;EAAA,SACD,gBAAA;EAAA,SACA,SAAA,GAAY,gBAAA;EAAA,SACZ,MAAA,GAAS,oBAAA;EAAA,SACT,GAAA,GAAM,QAAA,CAAS,MAAA;EAAA,SACf,KAAA,GAAQ,aAAA;EAAA,SACR,SAAA,GAAY,gBAAA;EAAA,SACZ,OAAA,GAAU,oBAAA;EAAA,SACV,aAAA,GAAgB,mBAAA;EAAA,SAChB,aAAA;AAAA;AAAA,cAoLE,gCAAA,GAAoC,MAAA,EAAQ,wBAAA,KAAwB,KAAA,CAAA,KAAA,CAAA,OAAA,SAAA,iBAAA,GAAA,mBAAA;AAAA,cAwMpE,sBAAA,GAA0B,MAAA,EAAQ,wBAAA,KAAwB,KAAA,CAAA,KAAA,CAAA,OAAA,SAAA,iBAAA"}
1
+ {"version":3,"file":"layer.d.mts","names":[],"sources":["../../src/vercel/layer.ts"],"mappings":";;;;;;;KAuCY,wBAAA;EAAA,SACD,gBAAA;EAAA,SACA,SAAA,GAAY,gBAAA;EAAA,SACZ,MAAA,GAAS,oBAAA;EAAA,SACT,GAAA,GAAM,QAAA,CAAS,MAAA;EAAA,SACf,KAAA,GAAQ,aAAA;EAAA,SACR,SAAA,GAAY,gBAAA;EAAA,SACZ,OAAA,GAAU,oBAAA;EAAA,SACV,aAAA,GAAgB,mBAAA;EAAA,SAChB,aAAA;AAAA;AAAA,cAiLE,gCAAA,GAAoC,MAAA,EAAQ,wBAAA,KAAwB,KAAA,CAAA,KAAA,CAAA,OAAA,SAAA,iBAAA,GAAA,mBAAA;AAAA,cA0MpE,sBAAA,GAA0B,MAAA,EAAQ,wBAAA,KAAwB,KAAA,CAAA,KAAA,CAAA,OAAA,SAAA,iBAAA"}
@@ -15,10 +15,7 @@ const providerError = (operation, error) => new SandboxProviderError({
15
15
  message: `Vercel Sandbox ${operation} failed: ${unknownToMessage(error)}`,
16
16
  underlying: error
17
17
  });
18
- const tryProvider = (operation, body) => Effect.tryPromise({
19
- try: body,
20
- catch: (error) => providerError(operation, error)
21
- });
18
+ const tryProvider = (operation, effect) => effect.pipe(Effect.mapError((error) => providerError(operation, error)));
22
19
  const lifecycleTimeoutMs = (lifecycle) => {
23
20
  switch (lifecycle._tag) {
24
21
  case "Disposable": return Math.min(lifecycle.idleTtlMs, lifecycle.maxLifetimeMs);
@@ -54,7 +51,7 @@ const waitForegroundCommand = (command, timeoutMs) => tryProvider("command.wait"
54
51
  })))), Effect.timeoutOrElse({
55
52
  duration: Duration.millis(timeoutMs),
56
53
  orElse: () => Effect.gen(function* () {
57
- yield* tryProvider("command.kill", () => command.kill("SIGKILL")).pipe(Effect.catchTag("SandboxProviderError", () => Effect.void));
54
+ yield* tryProvider("command.kill", command.kill("SIGKILL")).pipe(Effect.catchTag("SandboxProviderError", () => Effect.void));
58
55
  const output = yield* commandOutputOrEmpty(command);
59
56
  return {
60
57
  exitCode: null,
@@ -64,7 +61,7 @@ const waitForegroundCommand = (command, timeoutMs) => tryProvider("command.wait"
64
61
  };
65
62
  })
66
63
  }));
67
- const probeBackgroundCommand = (handle, command) => Effect.sleep(Duration.millis(backgroundSandboxProbeMs)).pipe(Effect.flatMap(() => tryProvider("command.get", () => handle.getCommand(command.id))), Effect.flatMap((current) => {
64
+ const probeBackgroundCommand = (handle, command) => Effect.sleep(Duration.millis(backgroundSandboxProbeMs)).pipe(Effect.flatMap(() => tryProvider("command.get", handle.getCommand(command.id))), Effect.flatMap((current) => {
68
65
  if (current.exitCode === null) return Effect.succeed({
69
66
  exitCode: null,
70
67
  stdout: "",
@@ -116,9 +113,9 @@ const makeVercelSandboxLayerWithClient = (config) => Layer.effect(Sandbox, Effec
116
113
  const runtime = config.runtime ?? defaultVercelRuntime;
117
114
  const workspaceRoot = config.workspaceRoot ?? "/vercel/sandbox";
118
115
  const name = makeVercelSandboxName(config.sandboxSessionId);
119
- const deleteNamedSandbox = (sandboxName) => tryProvider("get", () => client.get({ name: sandboxName })).pipe(Effect.flatMap((handle) => handle === null ? Effect.void : tryProvider("delete", () => handle.delete())));
116
+ const deleteNamedSandbox = (sandboxName) => tryProvider("get", client.get({ name: sandboxName })).pipe(Effect.flatMap((handle) => handle === null ? Effect.void : tryProvider("delete", handle.delete)));
120
117
  const createSandbox = (input) => Effect.gen(function* () {
121
- const handle = yield* tryProvider("create", () => client.create({
118
+ const handle = yield* tryProvider("create", client.create({
122
119
  name,
123
120
  source,
124
121
  ports,
@@ -163,7 +160,7 @@ const makeVercelSandboxLayerWithClient = (config) => Layer.effect(Sandbox, Effec
163
160
  };
164
161
  });
165
162
  const attachOrCreateSandbox = (input) => Effect.gen(function* () {
166
- const handle = yield* tryProvider("get", () => client.get({ name }));
163
+ const handle = yield* tryProvider("get", client.get({ name }));
167
164
  if (handle !== null) return yield* attachExistingSandbox({
168
165
  handle,
169
166
  nowMs: input.nowMs
@@ -180,7 +177,7 @@ const makeVercelSandboxLayerWithClient = (config) => Layer.effect(Sandbox, Effec
180
177
  before: input.state,
181
178
  after: touched
182
179
  });
183
- if (deltaMs > 0) yield* tryProvider("extendTimeout", () => input.handle.extendTimeout(deltaMs));
180
+ if (deltaMs > 0) yield* tryProvider("extendTimeout", input.handle.extendTimeout(deltaMs));
184
181
  yield* store.save({
185
182
  sandboxSessionId: config.sandboxSessionId,
186
183
  state: touched
@@ -212,7 +209,7 @@ const makeVercelSandboxLayerWithClient = (config) => Layer.effect(Sandbox, Effec
212
209
  workspaceReset: decision.workspaceReset
213
210
  });
214
211
  }
215
- const handle = yield* tryProvider("get", () => client.get({ name }));
212
+ const handle = yield* tryProvider("get", client.get({ name }));
216
213
  if (handle === null) {
217
214
  yield* store.clear(config.sandboxSessionId);
218
215
  return yield* createSandbox({
@@ -239,9 +236,9 @@ const makeVercelSandboxLayerWithClient = (config) => Layer.effect(Sandbox, Effec
239
236
  command: input.command,
240
237
  stdin: input.stdin
241
238
  });
242
- yield* tryProvider("writeFiles", () => active.handle.writeFiles(commandFiles.files));
239
+ yield* tryProvider("writeFiles", active.handle.writeFiles(commandFiles.files));
243
240
  const startedAtMs = yield* Clock.currentTimeMillis;
244
- const command = yield* tryProvider("runCommand", () => active.handle.runDetachedCommand({
241
+ const command = yield* tryProvider("runCommand", active.handle.runDetachedCommand({
245
242
  cmd: "bash",
246
243
  args: [commandFiles.wrapperPath],
247
244
  cwd: absoluteSandboxCwd(workspaceRoot, normalizedCwd)
@@ -1 +1 @@
1
- {"version":3,"file":"layer.mjs","names":["Arr"],"sources":["../../src/vercel/layer.ts"],"sourcesContent":["import { Array as Arr, Clock, Duration, Effect, Layer, Option, Ref, Semaphore } from 'effect'\nimport {\n absoluteSandboxCwd,\n backgroundSandboxProbeMs,\n defaultSandboxPorts,\n defaultSandboxWorkspaceRoot,\n initialSandboxState,\n normalizeWorkspaceCwd,\n sandboxCommandTimeoutMs,\n sandboxLifecycleOrDefault,\n sandboxSourceOrDefault,\n sandboxStateDecision,\n sandboxTimeoutExtendDeltaMs,\n touchSandboxState,\n validateSandboxCommand\n} from '../lifecycle.ts'\nimport { makeVercelSandboxName } from '../name.ts'\nimport {\n SandboxCommandResult,\n type SandboxCommandInput,\n SandboxPreviewUrl,\n SandboxResources,\n type SandboxInitialSource,\n type SandboxLifecycle,\n type SandboxState\n} from '../model.ts'\nimport { Sandbox } from '../service.ts'\nimport { SandboxStateStore } from '../state-store.ts'\nimport { SandboxProviderError, unknownToMessage } from '../errors.ts'\nimport type { SandboxError } from '../errors.ts'\nimport {\n VercelSandboxClient,\n VercelSandboxClientLive,\n type VercelDetachedCommand,\n type VercelNetworkPolicy,\n type VercelSandboxHandle,\n type VercelSandboxRuntime\n} from './client.ts'\n\nexport type VercelSandboxLayerConfig = {\n readonly sandboxSessionId: string\n readonly lifecycle?: SandboxLifecycle\n readonly source?: SandboxInitialSource\n readonly env?: Readonly<Record<string, string>>\n readonly ports?: ReadonlyArray<number>\n readonly resources?: SandboxResources\n readonly runtime?: VercelSandboxRuntime\n readonly networkPolicy?: VercelNetworkPolicy\n readonly workspaceRoot?: string\n}\n\ntype ActiveSandbox = {\n readonly handle: VercelSandboxHandle\n readonly state: SandboxState\n readonly workspaceReset: boolean\n}\n\ntype CommandRunOutput = {\n readonly exitCode: number | null\n readonly stdout: string\n readonly stderr: string\n readonly timedOut: boolean\n readonly backgroundId?: string\n}\n\nconst defaultVercelResources = SandboxResources.make({ vcpus: 2 })\nconst defaultVercelRuntime: VercelSandboxRuntime = 'node24'\n\nconst providerError = (operation: string, error: unknown) =>\n new SandboxProviderError({\n provider: 'vercel',\n operation,\n message: `Vercel Sandbox ${operation} failed: ${unknownToMessage(error)}`,\n underlying: error\n })\n\nconst tryProvider = <A>(operation: string, body: () => Promise<A>) =>\n Effect.tryPromise({\n try: body,\n catch: error => providerError(operation, error)\n })\n\nconst lifecycleTimeoutMs = (lifecycle: SandboxLifecycle) => {\n switch (lifecycle._tag) {\n case 'Disposable':\n return Math.min(lifecycle.idleTtlMs, lifecycle.maxLifetimeMs)\n case 'Persistent':\n return lifecycle.idleTtlMs\n }\n}\n\nconst persistentFlag = (lifecycle: SandboxLifecycle) => lifecycle._tag === 'Persistent'\n\nconst snapshotExpirationMs = (lifecycle: SandboxLifecycle) =>\n lifecycle._tag === 'Persistent' ? lifecycle.snapshotExpirationMs : undefined\n\nconst keepLastSnapshots = (lifecycle: SandboxLifecycle) =>\n lifecycle._tag === 'Persistent' ? lifecycle.keepLastSnapshots : undefined\n\nconst previewUrls = (handle: VercelSandboxHandle, ports: ReadonlyArray<number>) =>\n Effect.forEach(ports, port =>\n Effect.try({\n try: () => handle.domain(port),\n catch: error => error\n }).pipe(\n Effect.match({\n onFailure: () => Option.none<SandboxPreviewUrl>(),\n onSuccess: url => Option.some(SandboxPreviewUrl.make({ port, url }))\n })\n )\n ).pipe(Effect.map(Arr.getSomes))\n\nconst commandOutputOrEmpty = (command: VercelDetachedCommand) =>\n tryProvider('command.output', command.output).pipe(\n Effect.catchTag('SandboxProviderError', error =>\n Effect.succeed({\n stdout: '',\n stderr: error.message\n })\n )\n )\n\nconst finishedCommandOutputOrEmpty = (command: {\n readonly output: () => Promise<{ readonly stdout: string; readonly stderr: string }>\n}) =>\n tryProvider('command.output', command.output).pipe(\n Effect.catchTag('SandboxProviderError', error =>\n Effect.succeed({\n stdout: '',\n stderr: error.message\n })\n )\n )\n\nconst waitForegroundCommand = (\n command: VercelDetachedCommand,\n timeoutMs: number\n): Effect.Effect<CommandRunOutput, SandboxProviderError> =>\n tryProvider('command.wait', command.wait).pipe(\n Effect.flatMap(finished =>\n finishedCommandOutputOrEmpty(finished).pipe(\n Effect.map(output => ({\n exitCode: finished.exitCode,\n stdout: output.stdout,\n stderr: output.stderr,\n timedOut: false\n }))\n )\n ),\n Effect.timeoutOrElse({\n duration: Duration.millis(timeoutMs),\n orElse: () =>\n Effect.gen(function* () {\n yield* tryProvider('command.kill', () => command.kill('SIGKILL')).pipe(\n Effect.catchTag('SandboxProviderError', () => Effect.void)\n )\n const output = yield* commandOutputOrEmpty(command)\n\n return {\n exitCode: null,\n stdout: output.stdout,\n stderr: output.stderr,\n timedOut: true\n }\n })\n })\n )\n\nconst probeBackgroundCommand = (\n handle: VercelSandboxHandle,\n command: VercelDetachedCommand\n): Effect.Effect<CommandRunOutput, SandboxProviderError> =>\n Effect.sleep(Duration.millis(backgroundSandboxProbeMs)).pipe(\n Effect.flatMap(() => tryProvider('command.get', () => handle.getCommand(command.id))),\n Effect.flatMap(current => {\n if (current.exitCode === null) {\n return Effect.succeed({\n exitCode: null,\n stdout: '',\n stderr: '',\n timedOut: false,\n backgroundId: command.id\n })\n }\n\n return commandOutputOrEmpty(current).pipe(\n Effect.map(output => ({\n exitCode: current.exitCode,\n stdout: output.stdout,\n stderr: output.stderr,\n timedOut: false\n }))\n )\n })\n )\n\nconst createCommandFiles = (input: {\n readonly commandId: string\n readonly workspaceRoot: string\n readonly command: string\n readonly stdin?: string\n}) => {\n const commandDir = `${input.workspaceRoot}/.yolk/commands/${input.commandId}`\n const commandPath = `${commandDir}/command.sh`\n const stdinPath = `${commandDir}/stdin.txt`\n const wrapperPath = `${commandDir}/wrapper.sh`\n\n return {\n wrapperPath,\n files: [\n {\n path: commandPath,\n content: `#!/usr/bin/env bash\\n${input.command}\\n`,\n mode: 0o755\n },\n {\n path: stdinPath,\n content: input.stdin ?? ''\n },\n {\n path: wrapperPath,\n content: `#!/usr/bin/env bash\\nbash ${JSON.stringify(commandPath)} < ${JSON.stringify(stdinPath)}\\n`,\n mode: 0o755\n }\n ]\n }\n}\n\nexport const makeVercelSandboxLayerWithClient = (config: VercelSandboxLayerConfig) =>\n Layer.effect(\n Sandbox,\n Effect.gen(function* () {\n const store = yield* SandboxStateStore\n const client = yield* VercelSandboxClient\n const semaphore = yield* Semaphore.make(1)\n const commandCounter = yield* Ref.make(0)\n const lifecycle = sandboxLifecycleOrDefault(config.lifecycle)\n const source = sandboxSourceOrDefault(config.source)\n const ports = config.ports ?? defaultSandboxPorts\n const resources = config.resources ?? defaultVercelResources\n const runtime = config.runtime ?? defaultVercelRuntime\n const workspaceRoot = config.workspaceRoot ?? defaultSandboxWorkspaceRoot\n const name = makeVercelSandboxName(config.sandboxSessionId)\n\n const deleteNamedSandbox = (sandboxName: string) =>\n tryProvider('get', () => client.get({ name: sandboxName })).pipe(\n Effect.flatMap(handle =>\n handle === null ? Effect.void : tryProvider('delete', () => handle.delete())\n )\n )\n\n const createSandbox = (input: { readonly nowMs: number; readonly workspaceReset: boolean }) =>\n Effect.gen(function* () {\n const handle = yield* tryProvider('create', () =>\n client.create({\n name,\n source,\n ports,\n timeoutMs: lifecycleTimeoutMs(lifecycle),\n resources,\n runtime,\n env: config.env,\n persistent: persistentFlag(lifecycle),\n snapshotExpirationMs: snapshotExpirationMs(lifecycle),\n keepLastSnapshots: keepLastSnapshots(lifecycle),\n networkPolicy: config.networkPolicy\n })\n )\n const state = initialSandboxState({ name, nowMs: input.nowMs, lifecycle })\n yield* store.save({ sandboxSessionId: config.sandboxSessionId, state })\n\n return { handle, state, workspaceReset: input.workspaceReset }\n })\n\n const attachExistingSandbox = (input: {\n readonly handle: VercelSandboxHandle\n readonly nowMs: number\n }) =>\n Effect.gen(function* () {\n const state = initialSandboxState({ name, nowMs: input.nowMs, lifecycle })\n yield* store.save({ sandboxSessionId: config.sandboxSessionId, state })\n\n return {\n handle: input.handle,\n state,\n workspaceReset: false\n }\n })\n\n const attachOrCreateSandbox = (input: {\n readonly nowMs: number\n readonly workspaceReset: boolean\n }) =>\n Effect.gen(function* () {\n const handle = yield* tryProvider('get', () => client.get({ name }))\n\n if (handle !== null) {\n return yield* attachExistingSandbox({ handle, nowMs: input.nowMs })\n }\n\n return yield* createSandbox(input)\n })\n\n const touchExistingSandbox = (input: {\n readonly handle: VercelSandboxHandle\n readonly state: SandboxState\n readonly nowMs: number\n readonly workspaceReset: boolean\n }) =>\n Effect.gen(function* () {\n const touched = touchSandboxState({\n state: input.state,\n nowMs: input.nowMs,\n lifecycle\n })\n const deltaMs = sandboxTimeoutExtendDeltaMs({ before: input.state, after: touched })\n\n if (deltaMs > 0) {\n yield* tryProvider('extendTimeout', () => input.handle.extendTimeout(deltaMs))\n }\n\n yield* store.save({ sandboxSessionId: config.sandboxSessionId, state: touched })\n\n return {\n handle: input.handle,\n state: touched,\n workspaceReset: input.workspaceReset\n }\n })\n\n const ensureSandbox = (nowMs: number): Effect.Effect<ActiveSandbox, SandboxError> =>\n Effect.gen(function* () {\n const loaded = yield* store.load(config.sandboxSessionId)\n const decision = sandboxStateDecision({ state: loaded, name, nowMs })\n\n if (decision._tag === 'Create') {\n if (Option.isNone(loaded)) {\n return yield* attachOrCreateSandbox({\n nowMs,\n workspaceReset: decision.workspaceReset\n })\n }\n\n if (Option.isSome(loaded) && decision.workspaceReset) {\n yield* deleteNamedSandbox(loaded.value.name)\n yield* store.clear(config.sandboxSessionId)\n }\n\n return yield* createSandbox({ nowMs, workspaceReset: decision.workspaceReset })\n }\n\n const handle = yield* tryProvider('get', () => client.get({ name }))\n\n if (handle === null) {\n yield* store.clear(config.sandboxSessionId)\n return yield* createSandbox({ nowMs, workspaceReset: true })\n }\n\n return yield* touchExistingSandbox({\n handle,\n state: decision.state,\n nowMs,\n workspaceReset: false\n })\n })\n\n const nextCommandId = Ref.updateAndGet(commandCounter, value => value + 1).pipe(\n Effect.map(value => `command-${value}`)\n )\n\n const runUnlocked = (input: SandboxCommandInput) =>\n Effect.gen(function* () {\n yield* validateSandboxCommand(input.command)\n const normalizedCwd = yield* normalizeWorkspaceCwd(input.cwd)\n const timeoutMs = sandboxCommandTimeoutMs(input.timeoutMs)\n const nowMs = yield* Clock.currentTimeMillis\n const active = yield* ensureSandbox(nowMs)\n const id = yield* nextCommandId\n const commandFiles = createCommandFiles({\n commandId: id,\n workspaceRoot,\n command: input.command,\n stdin: input.stdin\n })\n\n yield* tryProvider('writeFiles', () => active.handle.writeFiles(commandFiles.files))\n\n const startedAtMs = yield* Clock.currentTimeMillis\n const command = yield* tryProvider('runCommand', () =>\n active.handle.runDetachedCommand({\n cmd: 'bash',\n args: [commandFiles.wrapperPath],\n cwd: absoluteSandboxCwd(workspaceRoot, normalizedCwd)\n })\n )\n const output = yield* input.background === true\n ? probeBackgroundCommand(active.handle, command)\n : waitForegroundCommand(command, timeoutMs)\n const endedAtMs = yield* Clock.currentTimeMillis\n const urls = yield* previewUrls(active.handle, ports)\n\n return SandboxCommandResult.make({\n exitCode: output.exitCode,\n stdout: output.stdout,\n stderr: output.stderr,\n durationMs: Math.max(0, endedAtMs - startedAtMs),\n timedOut: output.timedOut,\n workspaceReset: active.workspaceReset,\n ...(output.backgroundId === undefined ? {} : { backgroundId: output.backgroundId }),\n previewUrls: urls,\n state: active.state\n })\n })\n\n return Sandbox.of({\n run: input => semaphore.withPermits(1)(runUnlocked(input)),\n currentState: store.load(config.sandboxSessionId),\n delete: Effect.gen(function* () {\n const loaded = yield* store.load(config.sandboxSessionId)\n if (Option.isSome(loaded)) {\n yield* deleteNamedSandbox(loaded.value.name)\n }\n yield* store.clear(config.sandboxSessionId)\n })\n })\n })\n )\n\nexport const makeVercelSandboxLayer = (config: VercelSandboxLayerConfig) =>\n makeVercelSandboxLayerWithClient(config).pipe(Layer.provide(VercelSandboxClientLive))\n"],"mappings":"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"}
1
+ {"version":3,"file":"layer.mjs","names":["Arr"],"sources":["../../src/vercel/layer.ts"],"sourcesContent":["import { Array as Arr, Clock, Duration, Effect, Layer, Option, Ref, Semaphore } from 'effect'\nimport {\n absoluteSandboxCwd,\n backgroundSandboxProbeMs,\n defaultSandboxPorts,\n defaultSandboxWorkspaceRoot,\n initialSandboxState,\n normalizeWorkspaceCwd,\n sandboxCommandTimeoutMs,\n sandboxLifecycleOrDefault,\n sandboxSourceOrDefault,\n sandboxStateDecision,\n sandboxTimeoutExtendDeltaMs,\n touchSandboxState,\n validateSandboxCommand\n} from '../lifecycle.ts'\nimport { makeVercelSandboxName } from '../name.ts'\nimport {\n SandboxCommandResult,\n type SandboxCommandInput,\n SandboxPreviewUrl,\n SandboxResources,\n type SandboxInitialSource,\n type SandboxLifecycle,\n type SandboxState\n} from '../model.ts'\nimport { Sandbox } from '../service.ts'\nimport { SandboxStateStore } from '../state-store.ts'\nimport { SandboxProviderError, unknownToMessage } from '../errors.ts'\nimport type { SandboxError } from '../errors.ts'\nimport {\n VercelSandboxClient,\n VercelSandboxClientLive,\n type VercelDetachedCommand,\n type VercelNetworkPolicy,\n type VercelSandboxHandle,\n type VercelSandboxRuntime\n} from './client.ts'\n\nexport type VercelSandboxLayerConfig = {\n readonly sandboxSessionId: string\n readonly lifecycle?: SandboxLifecycle\n readonly source?: SandboxInitialSource\n readonly env?: Readonly<Record<string, string>>\n readonly ports?: ReadonlyArray<number>\n readonly resources?: SandboxResources\n readonly runtime?: VercelSandboxRuntime\n readonly networkPolicy?: VercelNetworkPolicy\n readonly workspaceRoot?: string\n}\n\ntype ActiveSandbox = {\n readonly handle: VercelSandboxHandle\n readonly state: SandboxState\n readonly workspaceReset: boolean\n}\n\ntype CommandRunOutput = {\n readonly exitCode: number | null\n readonly stdout: string\n readonly stderr: string\n readonly timedOut: boolean\n readonly backgroundId?: string\n}\n\nconst defaultVercelResources = SandboxResources.make({ vcpus: 2 })\nconst defaultVercelRuntime: VercelSandboxRuntime = 'node24'\n\nconst providerError = (operation: string, error: unknown) =>\n new SandboxProviderError({\n provider: 'vercel',\n operation,\n message: `Vercel Sandbox ${operation} failed: ${unknownToMessage(error)}`,\n underlying: error\n })\n\nconst tryProvider = <A>(operation: string, effect: Effect.Effect<A, unknown>) =>\n effect.pipe(Effect.mapError(error => providerError(operation, error)))\n\nconst lifecycleTimeoutMs = (lifecycle: SandboxLifecycle) => {\n switch (lifecycle._tag) {\n case 'Disposable':\n return Math.min(lifecycle.idleTtlMs, lifecycle.maxLifetimeMs)\n case 'Persistent':\n return lifecycle.idleTtlMs\n }\n}\n\nconst persistentFlag = (lifecycle: SandboxLifecycle) => lifecycle._tag === 'Persistent'\n\nconst snapshotExpirationMs = (lifecycle: SandboxLifecycle) =>\n lifecycle._tag === 'Persistent' ? lifecycle.snapshotExpirationMs : undefined\n\nconst keepLastSnapshots = (lifecycle: SandboxLifecycle) =>\n lifecycle._tag === 'Persistent' ? lifecycle.keepLastSnapshots : undefined\n\nconst previewUrls = (handle: VercelSandboxHandle, ports: ReadonlyArray<number>) =>\n Effect.forEach(ports, port =>\n Effect.try({\n try: () => handle.domain(port),\n catch: error => error\n }).pipe(\n Effect.match({\n onFailure: () => Option.none<SandboxPreviewUrl>(),\n onSuccess: url => Option.some(SandboxPreviewUrl.make({ port, url }))\n })\n )\n ).pipe(Effect.map(Arr.getSomes))\n\nconst commandOutputOrEmpty = (command: VercelDetachedCommand) =>\n tryProvider('command.output', command.output).pipe(\n Effect.catchTag('SandboxProviderError', error =>\n Effect.succeed({\n stdout: '',\n stderr: error.message\n })\n )\n )\n\nconst finishedCommandOutputOrEmpty = (command: {\n readonly output: Effect.Effect<{ readonly stdout: string; readonly stderr: string }, unknown>\n}) =>\n tryProvider('command.output', command.output).pipe(\n Effect.catchTag('SandboxProviderError', error =>\n Effect.succeed({\n stdout: '',\n stderr: error.message\n })\n )\n )\n\nconst waitForegroundCommand = (\n command: VercelDetachedCommand,\n timeoutMs: number\n): Effect.Effect<CommandRunOutput, SandboxProviderError> =>\n tryProvider('command.wait', command.wait).pipe(\n Effect.flatMap(finished =>\n finishedCommandOutputOrEmpty(finished).pipe(\n Effect.map(output => ({\n exitCode: finished.exitCode,\n stdout: output.stdout,\n stderr: output.stderr,\n timedOut: false\n }))\n )\n ),\n Effect.timeoutOrElse({\n duration: Duration.millis(timeoutMs),\n orElse: () =>\n Effect.gen(function* () {\n yield* tryProvider('command.kill', command.kill('SIGKILL')).pipe(\n Effect.catchTag('SandboxProviderError', () => Effect.void)\n )\n const output = yield* commandOutputOrEmpty(command)\n\n return {\n exitCode: null,\n stdout: output.stdout,\n stderr: output.stderr,\n timedOut: true\n }\n })\n })\n )\n\nconst probeBackgroundCommand = (\n handle: VercelSandboxHandle,\n command: VercelDetachedCommand\n): Effect.Effect<CommandRunOutput, SandboxProviderError> =>\n Effect.sleep(Duration.millis(backgroundSandboxProbeMs)).pipe(\n Effect.flatMap(() => tryProvider('command.get', handle.getCommand(command.id))),\n Effect.flatMap(current => {\n if (current.exitCode === null) {\n return Effect.succeed({\n exitCode: null,\n stdout: '',\n stderr: '',\n timedOut: false,\n backgroundId: command.id\n })\n }\n\n return commandOutputOrEmpty(current).pipe(\n Effect.map(output => ({\n exitCode: current.exitCode,\n stdout: output.stdout,\n stderr: output.stderr,\n timedOut: false\n }))\n )\n })\n )\n\nconst createCommandFiles = (input: {\n readonly commandId: string\n readonly workspaceRoot: string\n readonly command: string\n readonly stdin?: string\n}) => {\n const commandDir = `${input.workspaceRoot}/.yolk/commands/${input.commandId}`\n const commandPath = `${commandDir}/command.sh`\n const stdinPath = `${commandDir}/stdin.txt`\n const wrapperPath = `${commandDir}/wrapper.sh`\n\n return {\n wrapperPath,\n files: [\n {\n path: commandPath,\n content: `#!/usr/bin/env bash\\n${input.command}\\n`,\n mode: 0o755\n },\n {\n path: stdinPath,\n content: input.stdin ?? ''\n },\n {\n path: wrapperPath,\n content: `#!/usr/bin/env bash\\nbash ${JSON.stringify(commandPath)} < ${JSON.stringify(stdinPath)}\\n`,\n mode: 0o755\n }\n ]\n }\n}\n\nexport const makeVercelSandboxLayerWithClient = (config: VercelSandboxLayerConfig) =>\n Layer.effect(\n Sandbox,\n Effect.gen(function* () {\n const store = yield* SandboxStateStore\n const client = yield* VercelSandboxClient\n const semaphore = yield* Semaphore.make(1)\n const commandCounter = yield* Ref.make(0)\n const lifecycle = sandboxLifecycleOrDefault(config.lifecycle)\n const source = sandboxSourceOrDefault(config.source)\n const ports = config.ports ?? defaultSandboxPorts\n const resources = config.resources ?? defaultVercelResources\n const runtime = config.runtime ?? defaultVercelRuntime\n const workspaceRoot = config.workspaceRoot ?? defaultSandboxWorkspaceRoot\n const name = makeVercelSandboxName(config.sandboxSessionId)\n\n const deleteNamedSandbox = (sandboxName: string) =>\n tryProvider('get', client.get({ name: sandboxName })).pipe(\n Effect.flatMap(handle =>\n handle === null ? Effect.void : tryProvider('delete', handle.delete)\n )\n )\n\n const createSandbox = (input: { readonly nowMs: number; readonly workspaceReset: boolean }) =>\n Effect.gen(function* () {\n const handle = yield* tryProvider(\n 'create',\n client.create({\n name,\n source,\n ports,\n timeoutMs: lifecycleTimeoutMs(lifecycle),\n resources,\n runtime,\n env: config.env,\n persistent: persistentFlag(lifecycle),\n snapshotExpirationMs: snapshotExpirationMs(lifecycle),\n keepLastSnapshots: keepLastSnapshots(lifecycle),\n networkPolicy: config.networkPolicy\n })\n )\n const state = initialSandboxState({ name, nowMs: input.nowMs, lifecycle })\n yield* store.save({ sandboxSessionId: config.sandboxSessionId, state })\n\n return { handle, state, workspaceReset: input.workspaceReset }\n })\n\n const attachExistingSandbox = (input: {\n readonly handle: VercelSandboxHandle\n readonly nowMs: number\n }) =>\n Effect.gen(function* () {\n const state = initialSandboxState({ name, nowMs: input.nowMs, lifecycle })\n yield* store.save({ sandboxSessionId: config.sandboxSessionId, state })\n\n return {\n handle: input.handle,\n state,\n workspaceReset: false\n }\n })\n\n const attachOrCreateSandbox = (input: {\n readonly nowMs: number\n readonly workspaceReset: boolean\n }) =>\n Effect.gen(function* () {\n const handle = yield* tryProvider('get', client.get({ name }))\n\n if (handle !== null) {\n return yield* attachExistingSandbox({ handle, nowMs: input.nowMs })\n }\n\n return yield* createSandbox(input)\n })\n\n const touchExistingSandbox = (input: {\n readonly handle: VercelSandboxHandle\n readonly state: SandboxState\n readonly nowMs: number\n readonly workspaceReset: boolean\n }) =>\n Effect.gen(function* () {\n const touched = touchSandboxState({\n state: input.state,\n nowMs: input.nowMs,\n lifecycle\n })\n const deltaMs = sandboxTimeoutExtendDeltaMs({ before: input.state, after: touched })\n\n if (deltaMs > 0) {\n yield* tryProvider('extendTimeout', input.handle.extendTimeout(deltaMs))\n }\n\n yield* store.save({ sandboxSessionId: config.sandboxSessionId, state: touched })\n\n return {\n handle: input.handle,\n state: touched,\n workspaceReset: input.workspaceReset\n }\n })\n\n const ensureSandbox = (nowMs: number): Effect.Effect<ActiveSandbox, SandboxError> =>\n Effect.gen(function* () {\n const loaded = yield* store.load(config.sandboxSessionId)\n const decision = sandboxStateDecision({ state: loaded, name, nowMs })\n\n if (decision._tag === 'Create') {\n if (Option.isNone(loaded)) {\n return yield* attachOrCreateSandbox({\n nowMs,\n workspaceReset: decision.workspaceReset\n })\n }\n\n if (Option.isSome(loaded) && decision.workspaceReset) {\n yield* deleteNamedSandbox(loaded.value.name)\n yield* store.clear(config.sandboxSessionId)\n }\n\n return yield* createSandbox({ nowMs, workspaceReset: decision.workspaceReset })\n }\n\n const handle = yield* tryProvider('get', client.get({ name }))\n\n if (handle === null) {\n yield* store.clear(config.sandboxSessionId)\n return yield* createSandbox({ nowMs, workspaceReset: true })\n }\n\n return yield* touchExistingSandbox({\n handle,\n state: decision.state,\n nowMs,\n workspaceReset: false\n })\n })\n\n const nextCommandId = Ref.updateAndGet(commandCounter, value => value + 1).pipe(\n Effect.map(value => `command-${value}`)\n )\n\n const runUnlocked = (input: SandboxCommandInput) =>\n Effect.gen(function* () {\n yield* validateSandboxCommand(input.command)\n const normalizedCwd = yield* normalizeWorkspaceCwd(input.cwd)\n const timeoutMs = sandboxCommandTimeoutMs(input.timeoutMs)\n const nowMs = yield* Clock.currentTimeMillis\n const active = yield* ensureSandbox(nowMs)\n const id = yield* nextCommandId\n const commandFiles = createCommandFiles({\n commandId: id,\n workspaceRoot,\n command: input.command,\n stdin: input.stdin\n })\n\n yield* tryProvider('writeFiles', active.handle.writeFiles(commandFiles.files))\n\n const startedAtMs = yield* Clock.currentTimeMillis\n const command = yield* tryProvider(\n 'runCommand',\n active.handle.runDetachedCommand({\n cmd: 'bash',\n args: [commandFiles.wrapperPath],\n cwd: absoluteSandboxCwd(workspaceRoot, normalizedCwd)\n })\n )\n const output = yield* input.background === true\n ? probeBackgroundCommand(active.handle, command)\n : waitForegroundCommand(command, timeoutMs)\n const endedAtMs = yield* Clock.currentTimeMillis\n const urls = yield* previewUrls(active.handle, ports)\n\n return SandboxCommandResult.make({\n exitCode: output.exitCode,\n stdout: output.stdout,\n stderr: output.stderr,\n durationMs: Math.max(0, endedAtMs - startedAtMs),\n timedOut: output.timedOut,\n workspaceReset: active.workspaceReset,\n ...(output.backgroundId === undefined ? {} : { backgroundId: output.backgroundId }),\n previewUrls: urls,\n state: active.state\n })\n })\n\n return Sandbox.of({\n run: input => semaphore.withPermits(1)(runUnlocked(input)),\n currentState: store.load(config.sandboxSessionId),\n delete: Effect.gen(function* () {\n const loaded = yield* store.load(config.sandboxSessionId)\n if (Option.isSome(loaded)) {\n yield* deleteNamedSandbox(loaded.value.name)\n }\n yield* store.clear(config.sandboxSessionId)\n })\n })\n })\n )\n\nexport const makeVercelSandboxLayer = (config: VercelSandboxLayerConfig) =>\n makeVercelSandboxLayerWithClient(config).pipe(Layer.provide(VercelSandboxClientLive))\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yolk-sdk/sandbox",
3
- "version": "0.1.0-canary.39",
3
+ "version": "0.1.0-canary.41",
4
4
  "description": "Effect-native sandbox execution plane primitives and Vercel Sandbox adapter for Yolk agents.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -61,7 +61,7 @@
61
61
  "dependencies": {
62
62
  "@vercel/sandbox": "2.2.1",
63
63
  "effect": "4.0.0-beta.65",
64
- "@yolk-sdk/agent": "^0.1.0-canary.39"
64
+ "@yolk-sdk/agent": "^0.1.0-canary.41"
65
65
  },
66
66
  "scripts": {
67
67
  "build": "tsdown",
@@ -1,4 +1,4 @@
1
- import { Context, Layer } from 'effect'
1
+ import { Context, Effect, Layer } from 'effect'
2
2
  import {
3
3
  APIError,
4
4
  Sandbox as VercelSdkSandbox,
@@ -21,15 +21,15 @@ export type VercelCommandSignal = 'SIGTERM' | 'SIGKILL'
21
21
  export type VercelFinishedCommand = {
22
22
  readonly id: string
23
23
  readonly exitCode: number
24
- readonly output: () => Promise<VercelCommandOutput>
24
+ readonly output: Effect.Effect<VercelCommandOutput, unknown>
25
25
  }
26
26
 
27
27
  export type VercelDetachedCommand = {
28
28
  readonly id: string
29
29
  readonly exitCode: number | null
30
- readonly wait: () => Promise<VercelFinishedCommand>
31
- readonly kill: (signal: VercelCommandSignal) => Promise<void>
32
- readonly output: () => Promise<VercelCommandOutput>
30
+ readonly wait: Effect.Effect<VercelFinishedCommand, unknown>
31
+ readonly kill: (signal: VercelCommandSignal) => Effect.Effect<void, unknown>
32
+ readonly output: Effect.Effect<VercelCommandOutput, unknown>
33
33
  }
34
34
 
35
35
  export type VercelSandboxFile = {
@@ -64,17 +64,19 @@ export type VercelSandboxGetInput = {
64
64
 
65
65
  export type VercelSandboxHandle = {
66
66
  readonly name: string
67
- readonly writeFiles: (files: ReadonlyArray<VercelSandboxFile>) => Promise<void>
68
- readonly runDetachedCommand: (input: VercelRunCommandInput) => Promise<VercelDetachedCommand>
69
- readonly getCommand: (id: string) => Promise<VercelDetachedCommand>
70
- readonly extendTimeout: (durationMs: number) => Promise<void>
71
- readonly delete: () => Promise<void>
67
+ readonly writeFiles: (files: ReadonlyArray<VercelSandboxFile>) => Effect.Effect<void, unknown>
68
+ readonly runDetachedCommand: (
69
+ input: VercelRunCommandInput
70
+ ) => Effect.Effect<VercelDetachedCommand, unknown>
71
+ readonly getCommand: (id: string) => Effect.Effect<VercelDetachedCommand, unknown>
72
+ readonly extendTimeout: (durationMs: number) => Effect.Effect<void, unknown>
73
+ readonly delete: Effect.Effect<void, unknown>
72
74
  readonly domain: (port: number) => string
73
75
  }
74
76
 
75
77
  export type VercelSandboxClientApi = {
76
- readonly get: (input: VercelSandboxGetInput) => Promise<VercelSandboxHandle | null>
77
- readonly create: (input: VercelSandboxCreateInput) => Promise<VercelSandboxHandle>
78
+ readonly get: (input: VercelSandboxGetInput) => Effect.Effect<VercelSandboxHandle | null, unknown>
79
+ readonly create: (input: VercelSandboxCreateInput) => Effect.Effect<VercelSandboxHandle, unknown>
78
80
  }
79
81
 
80
82
  export class VercelSandboxClient extends Context.Service<
@@ -85,45 +87,57 @@ export class VercelSandboxClient extends Context.Service<
85
87
  export const isVercelMissingSandboxError = (error: unknown) =>
86
88
  error instanceof APIError && (error.response.status === 404 || error.response.status === 410)
87
89
 
88
- const commandOutput = (command: Command | CommandFinished): Promise<VercelCommandOutput> =>
89
- Promise.all([command.stdout(), command.stderr()]).then(([stdout, stderr]) => ({ stdout, stderr }))
90
+ const tryVercelPromise = <A>(body: () => Promise<A>) =>
91
+ Effect.tryPromise({
92
+ try: body,
93
+ catch: error => error
94
+ })
95
+
96
+ const commandOutput = (command: Command | CommandFinished): Effect.Effect<VercelCommandOutput, unknown> =>
97
+ Effect.all({
98
+ stdout: tryVercelPromise(() => command.stdout()),
99
+ stderr: tryVercelPromise(() => command.stderr())
100
+ })
90
101
 
91
102
  const toFinishedCommand = (command: CommandFinished): VercelFinishedCommand => ({
92
103
  id: command.cmdId,
93
104
  exitCode: command.exitCode,
94
- output: () => commandOutput(command)
105
+ output: commandOutput(command)
95
106
  })
96
107
 
97
108
  const toDetachedCommand = (command: Command): VercelDetachedCommand => ({
98
109
  id: command.cmdId,
99
110
  exitCode: command.exitCode,
100
- wait: () => command.wait().then(toFinishedCommand),
101
- kill: signal => command.kill(signal),
102
- output: () => commandOutput(command)
111
+ wait: tryVercelPromise(() => command.wait()).pipe(Effect.map(toFinishedCommand)),
112
+ kill: signal => tryVercelPromise(() => command.kill(signal)),
113
+ output: commandOutput(command)
103
114
  })
104
115
 
105
116
  const toHandle = (sandbox: VercelSdkSandbox): VercelSandboxHandle => ({
106
117
  name: sandbox.name,
107
118
  writeFiles: files =>
108
- sandbox.writeFiles(
109
- files.map(file => ({
110
- path: file.path,
111
- content: file.content,
112
- ...(file.mode === undefined ? {} : { mode: file.mode })
113
- }))
119
+ tryVercelPromise(() =>
120
+ sandbox.writeFiles(
121
+ files.map(file => ({
122
+ path: file.path,
123
+ content: file.content,
124
+ ...(file.mode === undefined ? {} : { mode: file.mode })
125
+ }))
126
+ )
114
127
  ),
115
128
  runDetachedCommand: input =>
116
- sandbox
117
- .runCommand({
129
+ tryVercelPromise(() =>
130
+ sandbox.runCommand({
118
131
  cmd: input.cmd,
119
132
  args: input.args === undefined ? [] : [...input.args],
120
133
  ...(input.cwd === undefined ? {} : { cwd: input.cwd }),
121
134
  detached: true
122
135
  })
123
- .then(toDetachedCommand),
124
- getCommand: id => sandbox.getCommand(id).then(toDetachedCommand),
125
- extendTimeout: durationMs => sandbox.extendTimeout(durationMs).then(() => undefined),
126
- delete: () => sandbox.delete().then(() => undefined),
136
+ ).pipe(Effect.map(toDetachedCommand)),
137
+ getCommand: id => tryVercelPromise(() => sandbox.getCommand(id)).pipe(Effect.map(toDetachedCommand)),
138
+ extendTimeout: durationMs =>
139
+ tryVercelPromise(() => sandbox.extendTimeout(durationMs)).pipe(Effect.asVoid),
140
+ delete: tryVercelPromise(() => sandbox.delete()).pipe(Effect.asVoid),
127
141
  domain: port => sandbox.domain(port)
128
142
  })
129
143
 
@@ -222,15 +236,16 @@ export const VercelSandboxClientLive = Layer.succeed(
222
236
  VercelSandboxClient,
223
237
  VercelSandboxClient.of({
224
238
  get: input =>
225
- VercelSdkSandbox.get({ name: input.name })
226
- .then(toHandle)
227
- .catch(error => {
239
+ tryVercelPromise(() => VercelSdkSandbox.get({ name: input.name })).pipe(
240
+ Effect.map(toHandle),
241
+ Effect.catch((error: unknown) => {
228
242
  if (isVercelMissingSandboxError(error)) {
229
- return null
243
+ return Effect.succeed(null)
230
244
  }
231
245
 
232
- throw error
233
- }),
234
- create: input => createSandbox(input).then(toHandle)
246
+ return Effect.fail(error)
247
+ })
248
+ ),
249
+ create: input => tryVercelPromise(() => createSandbox(input)).pipe(Effect.map(toHandle))
235
250
  })
236
251
  )
@@ -74,11 +74,8 @@ const providerError = (operation: string, error: unknown) =>
74
74
  underlying: error
75
75
  })
76
76
 
77
- const tryProvider = <A>(operation: string, body: () => Promise<A>) =>
78
- Effect.tryPromise({
79
- try: body,
80
- catch: error => providerError(operation, error)
81
- })
77
+ const tryProvider = <A>(operation: string, effect: Effect.Effect<A, unknown>) =>
78
+ effect.pipe(Effect.mapError(error => providerError(operation, error)))
82
79
 
83
80
  const lifecycleTimeoutMs = (lifecycle: SandboxLifecycle) => {
84
81
  switch (lifecycle._tag) {
@@ -121,7 +118,7 @@ const commandOutputOrEmpty = (command: VercelDetachedCommand) =>
121
118
  )
122
119
 
123
120
  const finishedCommandOutputOrEmpty = (command: {
124
- readonly output: () => Promise<{ readonly stdout: string; readonly stderr: string }>
121
+ readonly output: Effect.Effect<{ readonly stdout: string; readonly stderr: string }, unknown>
125
122
  }) =>
126
123
  tryProvider('command.output', command.output).pipe(
127
124
  Effect.catchTag('SandboxProviderError', error =>
@@ -151,7 +148,7 @@ const waitForegroundCommand = (
151
148
  duration: Duration.millis(timeoutMs),
152
149
  orElse: () =>
153
150
  Effect.gen(function* () {
154
- yield* tryProvider('command.kill', () => command.kill('SIGKILL')).pipe(
151
+ yield* tryProvider('command.kill', command.kill('SIGKILL')).pipe(
155
152
  Effect.catchTag('SandboxProviderError', () => Effect.void)
156
153
  )
157
154
  const output = yield* commandOutputOrEmpty(command)
@@ -171,7 +168,7 @@ const probeBackgroundCommand = (
171
168
  command: VercelDetachedCommand
172
169
  ): Effect.Effect<CommandRunOutput, SandboxProviderError> =>
173
170
  Effect.sleep(Duration.millis(backgroundSandboxProbeMs)).pipe(
174
- Effect.flatMap(() => tryProvider('command.get', () => handle.getCommand(command.id))),
171
+ Effect.flatMap(() => tryProvider('command.get', handle.getCommand(command.id))),
175
172
  Effect.flatMap(current => {
176
173
  if (current.exitCode === null) {
177
174
  return Effect.succeed({
@@ -243,15 +240,16 @@ export const makeVercelSandboxLayerWithClient = (config: VercelSandboxLayerConfi
243
240
  const name = makeVercelSandboxName(config.sandboxSessionId)
244
241
 
245
242
  const deleteNamedSandbox = (sandboxName: string) =>
246
- tryProvider('get', () => client.get({ name: sandboxName })).pipe(
243
+ tryProvider('get', client.get({ name: sandboxName })).pipe(
247
244
  Effect.flatMap(handle =>
248
- handle === null ? Effect.void : tryProvider('delete', () => handle.delete())
245
+ handle === null ? Effect.void : tryProvider('delete', handle.delete)
249
246
  )
250
247
  )
251
248
 
252
249
  const createSandbox = (input: { readonly nowMs: number; readonly workspaceReset: boolean }) =>
253
250
  Effect.gen(function* () {
254
- const handle = yield* tryProvider('create', () =>
251
+ const handle = yield* tryProvider(
252
+ 'create',
255
253
  client.create({
256
254
  name,
257
255
  source,
@@ -292,7 +290,7 @@ export const makeVercelSandboxLayerWithClient = (config: VercelSandboxLayerConfi
292
290
  readonly workspaceReset: boolean
293
291
  }) =>
294
292
  Effect.gen(function* () {
295
- const handle = yield* tryProvider('get', () => client.get({ name }))
293
+ const handle = yield* tryProvider('get', client.get({ name }))
296
294
 
297
295
  if (handle !== null) {
298
296
  return yield* attachExistingSandbox({ handle, nowMs: input.nowMs })
@@ -316,7 +314,7 @@ export const makeVercelSandboxLayerWithClient = (config: VercelSandboxLayerConfi
316
314
  const deltaMs = sandboxTimeoutExtendDeltaMs({ before: input.state, after: touched })
317
315
 
318
316
  if (deltaMs > 0) {
319
- yield* tryProvider('extendTimeout', () => input.handle.extendTimeout(deltaMs))
317
+ yield* tryProvider('extendTimeout', input.handle.extendTimeout(deltaMs))
320
318
  }
321
319
 
322
320
  yield* store.save({ sandboxSessionId: config.sandboxSessionId, state: touched })
@@ -349,7 +347,7 @@ export const makeVercelSandboxLayerWithClient = (config: VercelSandboxLayerConfi
349
347
  return yield* createSandbox({ nowMs, workspaceReset: decision.workspaceReset })
350
348
  }
351
349
 
352
- const handle = yield* tryProvider('get', () => client.get({ name }))
350
+ const handle = yield* tryProvider('get', client.get({ name }))
353
351
 
354
352
  if (handle === null) {
355
353
  yield* store.clear(config.sandboxSessionId)
@@ -383,10 +381,11 @@ export const makeVercelSandboxLayerWithClient = (config: VercelSandboxLayerConfi
383
381
  stdin: input.stdin
384
382
  })
385
383
 
386
- yield* tryProvider('writeFiles', () => active.handle.writeFiles(commandFiles.files))
384
+ yield* tryProvider('writeFiles', active.handle.writeFiles(commandFiles.files))
387
385
 
388
386
  const startedAtMs = yield* Clock.currentTimeMillis
389
- const command = yield* tryProvider('runCommand', () =>
387
+ const command = yield* tryProvider(
388
+ 'runCommand',
390
389
  active.handle.runDetachedCommand({
391
390
  cmd: 'bash',
392
391
  args: [commandFiles.wrapperPath],