@yolk-sdk/sandbox 0.1.0-canary.76 → 0.1.0-canary.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,11 +5,11 @@ Effect-native sandbox execution contracts, an agent tool, testing fakes, and a V
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- pnpm add @yolk-sdk/sandbox@canary @yolk-sdk/agent@canary effect@4.0.0-beta.80
8
+ pnpm add @yolk-sdk/sandbox@canary @yolk-sdk/agent@canary effect@4.0.0-rc.115
9
9
  ```
10
10
 
11
11
  Canary APIs are unstable. Keep all `@yolk-sdk/*` packages on the same version.
12
- Use the SDK's matching Effect version (`4.0.0-beta.80`) in host code.
12
+ Use the SDK's matching Effect version (`4.0.0-rc.115`) in host code.
13
13
  Published package metadata requires Node.js 22+; `@yolk-sdk/sandbox/vercel` is server-only.
14
14
 
15
15
  ## Subpaths
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.mts","names":[],"sources":["../src/agent.ts"],"mappings":";;;;;;;;cAuBa,eAAA;AAAA,cAEP,iBAAA,EAAiB,MAAA,CAAA,MAAA;EAAA;;;;;;KAsCX,iBAAA,UAA2B,iBAAA,CAAkB,IAAI;AAAA,KAEjD,wBAAA;EAAA,SACD,YAAA,GAAe,aAAA;EAAA,SACf,oBAAA;EAAA,SACA,oBAAA;EAAA,SACA,YAAA,GAAe,aAAA;EAAA,SACf,SAAA,IAAa,OAAA,EAAS,OAAA,KAAY,MAAA,CAAO,MAAA,UAAgB,iBAAA;AAAA;AAAA,KAG/D,sBAAA;EAAA,SACM,IAAA;EAAA,SACA,GAAG;AAAA;AAAA,KAGT,iBAAA;EAAA,SACM,IAAA;EAAA,SACA,IAAA;EAAA,SACA,WAAA;EAAA,SACA,YAAA;EAAA,SACA,WAAA;EAAA,SACA,cAAA;AAAA;AAAA,KAGC,4BAAA;EAAA,SACD,QAAA;EAAA,SACA,UAAA;EAAA,SACA,QAAA;EAAA,SACA,SAAA;EAAA,SACA,cAAA;EAAA,SACA,YAAA;EAAA,SACA,WAAA,EAAa,aAAA,CAAc,sBAAA;EAAA,SAC3B,KAAA,EAAO,iBAAA;AAAA;AAAA,cAkKL,qBAAA,GAAyB,KAAA;EAAA,SAC3B,MAAA;EAAA,SACA,MAAA,EAAQ,oBAAA;AAAA,MAClB,UAUA;AAAA,cA2BY,4BAAA,YACX,OAAA,EAAS,UAAA,EACT,OAAA,GAAS,wBAAA,CAAyB,OAAA,MACjC,UAAA,CAAW,OAAA;AAAA,cAyCD,qBAAA,YACX,OAAA,GAAS,wBAAA,CAAyB,OAAA,MACjC,MAAA,CAAO,MAAA,CAAO,UAAA,CAAW,OAAA,UAAiB,OAAA;AAAA,KAMjC,yBAAA;EAAA,SACD,IAAA,EAAM,QAAA;EAAA,SACN,OAAA,EAAS,OAAA;EAAA,SACT,MAAA,EAAQ,iBAAA;AAAA"}
1
+ {"version":3,"file":"agent.d.mts","names":[],"sources":["../src/agent.ts"],"mappings":";;;;;;;;cAuBa,eAAA;AAAA,cAEP,iBAAA,EAAiB,MAAA,CAAA,MAAA;EAAA;;;;;;KA4CX,iBAAA,UAA2B,iBAAA,CAAkB,IAAI;AAAA,KAEjD,wBAAA;EAAA,SACD,YAAA,GAAe,aAAA;EAAA,SACf,oBAAA;EAAA,SACA,oBAAA;EAAA,SACA,YAAA,GAAe,aAAA;EAAA,SACf,SAAA,IAAa,OAAA,EAAS,OAAA,KAAY,MAAA,CAAO,MAAA,UAAgB,iBAAA;AAAA;AAAA,KAG/D,sBAAA;EAAA,SACM,IAAA;EAAA,SACA,GAAG;AAAA;AAAA,KAGT,iBAAA;EAAA,SACM,IAAA;EAAA,SACA,IAAA;EAAA,SACA,WAAA;EAAA,SACA,YAAA;EAAA,SACA,WAAA;EAAA,SACA,cAAA;AAAA;AAAA,KAGC,4BAAA;EAAA,SACD,QAAA;EAAA,SACA,UAAA;EAAA,SACA,QAAA;EAAA,SACA,SAAA;EAAA,SACA,cAAA;EAAA,SACA,YAAA;EAAA,SACA,WAAA,EAAa,aAAA,CAAc,sBAAA;EAAA,SAC3B,KAAA,EAAO,iBAAA;AAAA;AAAA,cAoLL,qBAAA,GAAyB,KAAA;EAAA,SAC3B,MAAA;EAAA,SACA,MAAA,EAAQ,oBAAA;AAAA,MAClB,UAUA;AAAA,cA4BY,4BAAA,YACX,OAAA,EAAS,UAAA,EACT,OAAA,GAAS,wBAAA,CAAyB,OAAA,MACjC,UAAA,CAAW,OAAA;AAAA,cA0CD,qBAAA,YACX,OAAA,GAAS,wBAAA,CAAyB,OAAA,MACjC,MAAA,CAAO,MAAA,CAAO,UAAA,CAAW,OAAA,UAAiB,OAAA;AAAA,KAOjC,yBAAA;EAAA,SACD,IAAA,EAAM,QAAA;EAAA,SACN,OAAA,EAAS,OAAA;EAAA,SACT,MAAA,EAAQ,iBAAA;AAAA"}
package/dist/agent.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { maxSandboxCommandTimeoutMs, normalizeWorkspaceCwd, sandboxCommandTimeoutMs, sandboxToolOutputLimit, validateSandboxCommand } from "./lifecycle.mjs";
2
2
  import { Sandbox } from "./service.mjs";
3
- import { Effect } from "effect";
3
+ import { Effect, Match } from "effect";
4
4
  import * as Schema from "effect/Schema";
5
5
  import { ToolError } from "@yolk-sdk/agent/loop";
6
6
  import { ToolResult } from "@yolk-sdk/agent/protocol";
@@ -20,29 +20,25 @@ const toolError = (message, cause) => new ToolError({
20
20
  message,
21
21
  cause
22
22
  });
23
- const modelVisibleSandboxError = (error) => {
24
- switch (error._tag) {
25
- case "SandboxInputError": return modelVisibleToolError({
26
- tool: sandboxToolName,
27
- message: error.message,
28
- reason: "invalid_input"
29
- });
30
- case "SandboxExpiredError": return modelVisibleToolError({
31
- tool: sandboxToolName,
32
- message: error.message,
33
- reason: "unavailable",
34
- details: { expiredAtMs: error.expiredAtMs }
35
- });
36
- }
37
- };
38
- const sandboxInfraToolError = (error) => {
39
- switch (error._tag) {
40
- case "SandboxConfigError": return toolError(error.message, "invalid_input");
41
- case "SandboxProviderError": return toolError(error.message, "execution");
42
- case "SandboxStateError":
43
- case "SandboxStateStoreError": return toolError(error.message, "unavailable");
44
- }
45
- };
23
+ const modelVisibleSandboxError = (error) => Match.value(error).pipe(Match.tagsExhaustive({
24
+ SandboxInputError: (inputError) => modelVisibleToolError({
25
+ tool: sandboxToolName,
26
+ message: inputError.message,
27
+ reason: "invalid_input"
28
+ }),
29
+ SandboxExpiredError: (expiredError) => modelVisibleToolError({
30
+ tool: sandboxToolName,
31
+ message: expiredError.message,
32
+ reason: "unavailable",
33
+ details: { expiredAtMs: expiredError.expiredAtMs }
34
+ })
35
+ }));
36
+ const sandboxInfraToolError = (error) => Match.value(error).pipe(Match.tagsExhaustive({
37
+ SandboxConfigError: (configError) => toolError(configError.message, "invalid_input"),
38
+ SandboxProviderError: (providerError) => toolError(providerError.message, "execution"),
39
+ SandboxStateError: (stateError) => toolError(stateError.message, "unavailable"),
40
+ SandboxStateStoreError: (storeError) => toolError(storeError.message, "unavailable")
41
+ }));
46
42
  const normalizeTimeoutMs = (timeoutSeconds) => {
47
43
  const value = nullToUndefined(timeoutSeconds);
48
44
  if (value === void 0) return Effect.succeed(sandboxCommandTimeoutMs(void 0));
@@ -100,28 +96,29 @@ const plainSandboxPreviewUrl = (previewUrl) => ({
100
96
  port: previewUrl.port,
101
97
  url: previewUrl.url
102
98
  });
103
- const plainSandboxState = (state) => {
104
- switch (state._tag) {
105
- case "Vercel": return {
106
- _tag: state._tag,
107
- name: state.name,
108
- createdAtMs: state.createdAtMs,
109
- lastUsedAtMs: state.lastUsedAtMs,
110
- expiresAtMs: state.expiresAtMs,
111
- maxExpiresAtMs: state.maxExpiresAtMs
112
- };
113
- }
99
+ const plainSandboxState = (state) => Match.value(state._tag).pipe(Match.when("Vercel", () => ({
100
+ _tag: state._tag,
101
+ name: state.name,
102
+ createdAtMs: state.createdAtMs,
103
+ lastUsedAtMs: state.lastUsedAtMs,
104
+ expiresAtMs: state.expiresAtMs,
105
+ maxExpiresAtMs: state.maxExpiresAtMs
106
+ })), Match.exhaustive);
107
+ const structuredContent = (result, truncated) => {
108
+ const content = {
109
+ exitCode: result.exitCode,
110
+ durationMs: result.durationMs,
111
+ timedOut: result.timedOut,
112
+ truncated,
113
+ workspaceReset: result.workspaceReset
114
+ };
115
+ if (result.backgroundId !== void 0) content.backgroundId = result.backgroundId;
116
+ return {
117
+ ...content,
118
+ previewUrls: result.previewUrls.map(plainSandboxPreviewUrl),
119
+ state: plainSandboxState(result.state)
120
+ };
114
121
  };
115
- const structuredContent = (result, truncated) => ({
116
- exitCode: result.exitCode,
117
- durationMs: result.durationMs,
118
- timedOut: result.timedOut,
119
- truncated,
120
- workspaceReset: result.workspaceReset,
121
- ...result.backgroundId === void 0 ? {} : { backgroundId: result.backgroundId },
122
- previewUrls: result.previewUrls.map(plainSandboxPreviewUrl),
123
- state: plainSandboxState(result.state)
124
- });
125
122
  const makeSandboxToolResult = (input) => {
126
123
  const output = truncateOutputs(input.result.stdout, input.result.stderr, sandboxToolOutputLimit);
127
124
  return ToolResult.make({
@@ -163,16 +160,14 @@ const makeSandboxToolModuleFromApi = (sandbox, options = {}) => ({
163
160
  execute: ({ call, params }) => Effect.gen(function* () {
164
161
  if (call.name !== "sandbox") return yield* Effect.fail(toolError(`Tool is not configured: ${call.name}`, "not_found"));
165
162
  const normalized = yield* normalizeToolParams(params);
166
- const result = yield* sandbox.run(normalized).pipe(Effect.mapError((error) => {
167
- switch (error._tag) {
168
- case "SandboxInputError":
169
- case "SandboxExpiredError": return modelVisibleSandboxError(error);
170
- case "SandboxConfigError":
171
- case "SandboxProviderError":
172
- case "SandboxStateError":
173
- case "SandboxStateStoreError": return sandboxInfraToolError(error);
174
- }
175
- }));
163
+ const result = yield* sandbox.run(normalized).pipe(Effect.mapError((error) => Match.value(error).pipe(Match.tagsExhaustive({
164
+ SandboxInputError: (inputError) => modelVisibleSandboxError(inputError),
165
+ SandboxExpiredError: (expiredError) => modelVisibleSandboxError(expiredError),
166
+ SandboxConfigError: (configError) => sandboxInfraToolError(configError),
167
+ SandboxProviderError: (providerError) => sandboxInfraToolError(providerError),
168
+ SandboxStateError: (stateError) => sandboxInfraToolError(stateError),
169
+ SandboxStateStoreError: (storeError) => sandboxInfraToolError(storeError)
170
+ }))));
176
171
  return makeSandboxToolResult({
177
172
  callId: call.id,
178
173
  result
@@ -1 +1 @@
1
- {"version":3,"file":"agent.mjs","names":[],"sources":["../src/agent.ts"],"sourcesContent":["import { Effect } from 'effect'\nimport * as Schema from 'effect/Schema'\nimport { ToolError } from '@yolk-sdk/agent/loop'\nimport { ToolResult, type ToolCall } from '@yolk-sdk/agent/protocol'\nimport {\n makeTool,\n modelVisibleToolError,\n type ModelVisibleToolError,\n type ToolModule,\n type ToolRegistryError\n} from '@yolk-sdk/agent/tools'\nimport {\n maxSandboxCommandTimeoutMs,\n normalizeWorkspaceCwd,\n sandboxCommandTimeoutMs,\n sandboxToolOutputLimit,\n validateSandboxCommand\n} from './lifecycle.ts'\nimport type { SandboxError, SandboxExpiredError, SandboxInputError } from './errors.ts'\nimport type { SandboxApi } from './service.ts'\nimport { Sandbox } from './service.ts'\nimport type { SandboxCommandResult } from './model.ts'\n\nexport const sandboxToolName = 'sandbox'\n\nconst SandboxToolParams = Schema.Struct({\n command: Schema.String.pipe(\n Schema.annotate({ description: 'Shell command to run. Multiline commands are allowed.' })\n ),\n cwd: Schema.optional(\n Schema.NullOr(\n Schema.String.pipe(\n Schema.annotate({\n description: 'Workspace-relative working directory. Absolute paths are rejected.'\n })\n )\n )\n ),\n stdin: Schema.optional(\n Schema.NullOr(\n Schema.String.pipe(\n Schema.annotate({ description: 'Optional stdin text passed to the command.' })\n )\n )\n ),\n timeoutSeconds: Schema.optional(\n Schema.NullOr(\n Schema.Number.pipe(\n Schema.annotate({ description: 'Foreground timeout in seconds. Default 120, max 600.' })\n )\n )\n ),\n background: Schema.optional(\n Schema.NullOr(\n Schema.Boolean.pipe(\n Schema.annotate({\n description: 'Start command in background and return after a quick probe.'\n })\n )\n )\n )\n})\n\nexport type SandboxToolParams = typeof SandboxToolParams.Type\n\nexport type SandboxToolModuleOptions<Context> = {\n readonly capabilities?: ReadonlyArray<string>\n readonly workspaceDescription?: string\n readonly lifecycleDescription?: string\n readonly previewPorts?: ReadonlyArray<number>\n readonly isEnabled?: (context: Context) => Effect.Effect<boolean, ToolRegistryError>\n}\n\ntype PlainSandboxPreviewUrl = {\n readonly port: number\n readonly url: string\n}\n\ntype PlainSandboxState = {\n readonly _tag: 'Vercel'\n readonly name: string\n readonly createdAtMs: number\n readonly lastUsedAtMs: number\n readonly expiresAtMs: number\n readonly maxExpiresAtMs: number\n}\n\nexport type SandboxToolStructuredContent = {\n readonly exitCode: number | null\n readonly durationMs: number\n readonly timedOut: boolean\n readonly truncated: boolean\n readonly workspaceReset: boolean\n readonly backgroundId?: string\n readonly previewUrls: ReadonlyArray<PlainSandboxPreviewUrl>\n readonly state: PlainSandboxState\n}\n\ntype OutputSlice = {\n readonly stdout: string\n readonly stderr: string\n readonly truncated: boolean\n}\n\nconst nullToUndefined = <A>(value: A | null | undefined) => (value === null ? undefined : value)\n\nconst toolError = (message: string, cause: ToolError['cause']) =>\n new ToolError({\n tool: sandboxToolName,\n message,\n cause\n })\n\nconst modelVisibleSandboxError = (\n error: SandboxInputError | SandboxExpiredError\n): ModelVisibleToolError => {\n switch (error._tag) {\n case 'SandboxInputError':\n return modelVisibleToolError({\n tool: sandboxToolName,\n message: error.message,\n reason: 'invalid_input'\n })\n case 'SandboxExpiredError':\n return modelVisibleToolError({\n tool: sandboxToolName,\n message: error.message,\n reason: 'unavailable',\n details: { expiredAtMs: error.expiredAtMs }\n })\n }\n}\n\nconst sandboxInfraToolError = (\n error: Exclude<SandboxError, SandboxInputError | SandboxExpiredError>\n) => {\n switch (error._tag) {\n case 'SandboxConfigError':\n return toolError(error.message, 'invalid_input')\n case 'SandboxProviderError':\n return toolError(error.message, 'execution')\n case 'SandboxStateError':\n case 'SandboxStateStoreError':\n return toolError(error.message, 'unavailable')\n }\n}\n\nconst normalizeTimeoutMs = (timeoutSeconds: number | null | undefined) => {\n const value = nullToUndefined(timeoutSeconds)\n\n if (value === undefined) {\n return Effect.succeed(sandboxCommandTimeoutMs(undefined))\n }\n\n if (!Number.isFinite(value) || value <= 0) {\n return Effect.fail(\n modelVisibleToolError({\n tool: sandboxToolName,\n message: 'timeoutSeconds must be greater than 0',\n reason: 'invalid_input'\n })\n )\n }\n\n return Effect.succeed(sandboxCommandTimeoutMs(Math.floor(value * 1_000)))\n}\n\nconst normalizeToolParams = (params: SandboxToolParams) =>\n Effect.gen(function* () {\n const command = yield* validateSandboxCommand(params.command).pipe(\n Effect.mapError(modelVisibleSandboxError)\n )\n const cwd = yield* normalizeWorkspaceCwd(params.cwd).pipe(\n Effect.mapError(modelVisibleSandboxError)\n )\n const timeoutMs = yield* normalizeTimeoutMs(params.timeoutSeconds)\n\n return {\n command,\n cwd,\n stdin: nullToUndefined(params.stdin),\n timeoutMs,\n background: nullToUndefined(params.background)\n }\n })\n\nconst truncateOutputs = (stdout: string, stderr: string, limit: number): OutputSlice => {\n if (stdout.length + stderr.length <= limit) {\n return { stdout, stderr, truncated: false }\n }\n\n const initialStderrBudget = Math.min(stderr.length, Math.floor(limit / 2))\n const initialStdoutBudget = Math.min(stdout.length, limit - initialStderrBudget)\n const unused = limit - initialStdoutBudget - initialStderrBudget\n const stdoutBudget = Math.min(stdout.length, initialStdoutBudget + unused)\n const stderrBudget = Math.min(stderr.length, limit - stdoutBudget)\n\n return {\n stdout: stdout.slice(0, stdoutBudget),\n stderr: stderr.slice(0, stderrBudget),\n truncated: true\n }\n}\n\nconst formatSandboxToolContent = (result: SandboxCommandResult, output: OutputSlice) =>\n [\n `exit_code: ${result.exitCode === null ? 'null' : String(result.exitCode)}`,\n `duration_ms: ${result.durationMs}`,\n `truncated: ${output.truncated}`,\n `timed_out: ${result.timedOut}`,\n `workspace_reset: ${result.workspaceReset}`,\n result.backgroundId === undefined ? undefined : `background_id: ${result.backgroundId}`,\n '<stdout>',\n output.stdout,\n '</stdout>',\n '<stderr>',\n output.stderr,\n '</stderr>'\n ]\n .filter(line => line !== undefined)\n .join('\\n')\n\nconst plainSandboxPreviewUrl = (\n previewUrl: SandboxCommandResult['previewUrls'][number]\n): PlainSandboxPreviewUrl => ({\n port: previewUrl.port,\n url: previewUrl.url\n})\n\nconst plainSandboxState = (state: SandboxCommandResult['state']): PlainSandboxState => {\n switch (state._tag) {\n case 'Vercel':\n return {\n _tag: state._tag,\n name: state.name,\n createdAtMs: state.createdAtMs,\n lastUsedAtMs: state.lastUsedAtMs,\n expiresAtMs: state.expiresAtMs,\n maxExpiresAtMs: state.maxExpiresAtMs\n }\n }\n}\n\nconst structuredContent = (\n result: SandboxCommandResult,\n truncated: boolean\n): SandboxToolStructuredContent => ({\n exitCode: result.exitCode,\n durationMs: result.durationMs,\n timedOut: result.timedOut,\n truncated,\n workspaceReset: result.workspaceReset,\n ...(result.backgroundId === undefined ? {} : { backgroundId: result.backgroundId }),\n previewUrls: result.previewUrls.map(plainSandboxPreviewUrl),\n state: plainSandboxState(result.state)\n})\n\nexport const makeSandboxToolResult = (input: {\n readonly callId: string\n readonly result: SandboxCommandResult\n}) => {\n const output = truncateOutputs(input.result.stdout, input.result.stderr, sandboxToolOutputLimit)\n\n return ToolResult.make({\n toolCallId: input.callId,\n content: formatSandboxToolContent(input.result, output),\n isError:\n input.result.timedOut || (input.result.exitCode !== null && input.result.exitCode !== 0),\n structuredContent: structuredContent(input.result, output.truncated)\n })\n}\n\nconst sandboxToolDescription = <Context>(options: SandboxToolModuleOptions<Context>) => {\n const capabilities = options.capabilities ?? [\n 'run project commands such as typechecks, lint, tests, and builds',\n 'edit files with shell tools such as apply_patch when available',\n 'start dev servers and use preview ports',\n 'run browser checks through agent-browser when available'\n ]\n const ports = options.previewPorts ?? []\n\n return [\n 'Run one non-interactive bash command inside a real sandbox workspace.',\n options.workspaceDescription ?? 'The working directory is the sandbox workspace root.',\n options.lifecycleDescription ??\n 'The sandbox is disposable and may reset after idle or max lifetime expiry.',\n `Foreground timeout defaults to 120s and is capped at ${Math.floor(maxSandboxCommandTimeoutMs / 1_000)}s.`,\n 'Use workspace-relative cwd only; absolute paths and workspace escapes are rejected.',\n 'Use stdin for large patches, scripts, or data.',\n 'Set background=true for long-running servers; the tool returns after a quick probe.',\n ports.length === 0\n ? 'Preview URLs are returned when configured by the host.'\n : `Preview ports: ${ports.join(', ')}.`,\n `Available capabilities:\\n${capabilities.map(capability => `- ${capability}`).join('\\n')}`\n ].join('\\n\\n')\n}\n\nexport const makeSandboxToolModuleFromApi = <Context>(\n sandbox: SandboxApi,\n options: SandboxToolModuleOptions<Context> = {}\n): ToolModule<Context> => ({\n id: 'sandbox',\n tools: [\n makeTool({\n name: sandboxToolName,\n description: sandboxToolDescription(options),\n parameters: SandboxToolParams,\n access: 'destructive',\n isEnabled: options.isEnabled,\n invalidParamsMessage: error =>\n `Invalid sandbox arguments: ${error instanceof Error ? error.message : String(error)}`,\n execute: ({ call, params }) =>\n Effect.gen(function* () {\n if (call.name !== sandboxToolName) {\n return yield* Effect.fail(\n toolError(`Tool is not configured: ${call.name}`, 'not_found')\n )\n }\n\n const normalized = yield* normalizeToolParams(params)\n const result = yield* sandbox.run(normalized).pipe(\n Effect.mapError(error => {\n switch (error._tag) {\n case 'SandboxInputError':\n case 'SandboxExpiredError':\n return modelVisibleSandboxError(error)\n case 'SandboxConfigError':\n case 'SandboxProviderError':\n case 'SandboxStateError':\n case 'SandboxStateStoreError':\n return sandboxInfraToolError(error)\n }\n })\n )\n\n return makeSandboxToolResult({ callId: call.id, result })\n })\n })\n ]\n})\n\nexport const makeSandboxToolModule = <Context>(\n options: SandboxToolModuleOptions<Context> = {}\n): Effect.Effect<ToolModule<Context>, never, Sandbox> =>\n Effect.gen(function* () {\n const sandbox = yield* Sandbox\n return makeSandboxToolModuleFromApi(sandbox, options)\n })\n\nexport type SandboxToolExecutionInput<Context> = {\n readonly call: ToolCall\n readonly context: Context\n readonly params: SandboxToolParams\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agent.mjs","names":[],"sources":["../src/agent.ts"],"sourcesContent":["import { Effect, Match } from 'effect'\nimport * as Schema from 'effect/Schema'\nimport { ToolError } from '@yolk-sdk/agent/loop'\nimport { ToolResult, type ToolCall } from '@yolk-sdk/agent/protocol'\nimport {\n makeTool,\n modelVisibleToolError,\n type ModelVisibleToolError,\n type ToolModule,\n type ToolRegistryError\n} from '@yolk-sdk/agent/tools'\nimport {\n maxSandboxCommandTimeoutMs,\n normalizeWorkspaceCwd,\n sandboxCommandTimeoutMs,\n sandboxToolOutputLimit,\n validateSandboxCommand\n} from './lifecycle.ts'\nimport type { SandboxError, SandboxExpiredError, SandboxInputError } from './errors.ts'\nimport type { SandboxApi } from './service.ts'\nimport { Sandbox } from './service.ts'\nimport type { SandboxCommandResult } from './model.ts'\n\nexport const sandboxToolName = 'sandbox'\n\nconst SandboxToolParams = Schema.Struct({\n command: Schema.String.pipe(\n Schema.annotate({\n description: 'Shell command to run. Multiline commands are allowed.'\n })\n ),\n cwd: Schema.optional(\n Schema.NullOr(\n Schema.String.pipe(\n Schema.annotate({\n description: 'Workspace-relative working directory. Absolute paths are rejected.'\n })\n )\n )\n ),\n stdin: Schema.optional(\n Schema.NullOr(\n Schema.String.pipe(\n Schema.annotate({\n description: 'Optional stdin text passed to the command.'\n })\n )\n )\n ),\n timeoutSeconds: Schema.optional(\n Schema.NullOr(\n Schema.Number.pipe(\n Schema.annotate({\n description: 'Foreground timeout in seconds. Default 120, max 600.'\n })\n )\n )\n ),\n background: Schema.optional(\n Schema.NullOr(\n Schema.Boolean.pipe(\n Schema.annotate({\n description: 'Start command in background and return after a quick probe.'\n })\n )\n )\n )\n})\n\nexport type SandboxToolParams = typeof SandboxToolParams.Type\n\nexport type SandboxToolModuleOptions<Context> = {\n readonly capabilities?: ReadonlyArray<string>\n readonly workspaceDescription?: string\n readonly lifecycleDescription?: string\n readonly previewPorts?: ReadonlyArray<number>\n readonly isEnabled?: (context: Context) => Effect.Effect<boolean, ToolRegistryError>\n}\n\ntype PlainSandboxPreviewUrl = {\n readonly port: number\n readonly url: string\n}\n\ntype PlainSandboxState = {\n readonly _tag: 'Vercel'\n readonly name: string\n readonly createdAtMs: number\n readonly lastUsedAtMs: number\n readonly expiresAtMs: number\n readonly maxExpiresAtMs: number\n}\n\nexport type SandboxToolStructuredContent = {\n readonly exitCode: number | null\n readonly durationMs: number\n readonly timedOut: boolean\n readonly truncated: boolean\n readonly workspaceReset: boolean\n readonly backgroundId?: string\n readonly previewUrls: ReadonlyArray<PlainSandboxPreviewUrl>\n readonly state: PlainSandboxState\n}\n\ntype OutputSlice = {\n readonly stdout: string\n readonly stderr: string\n readonly truncated: boolean\n}\n\nconst nullToUndefined = <A>(value: A | null | undefined) => (value === null ? undefined : value)\n\nconst toolError = (message: string, cause: ToolError['cause']) =>\n new ToolError({\n tool: sandboxToolName,\n message,\n cause\n })\n\nconst modelVisibleSandboxError = (\n error: SandboxInputError | SandboxExpiredError\n): ModelVisibleToolError =>\n Match.value(error).pipe(\n Match.tagsExhaustive({\n SandboxInputError: inputError =>\n modelVisibleToolError({\n tool: sandboxToolName,\n message: inputError.message,\n reason: 'invalid_input'\n }),\n SandboxExpiredError: expiredError =>\n modelVisibleToolError({\n tool: sandboxToolName,\n message: expiredError.message,\n reason: 'unavailable',\n details: { expiredAtMs: expiredError.expiredAtMs }\n })\n })\n )\n\nconst sandboxInfraToolError = (\n error: Exclude<SandboxError, SandboxInputError | SandboxExpiredError>\n) =>\n Match.value(error).pipe(\n Match.tagsExhaustive({\n SandboxConfigError: configError => toolError(configError.message, 'invalid_input'),\n SandboxProviderError: providerError => toolError(providerError.message, 'execution'),\n SandboxStateError: stateError => toolError(stateError.message, 'unavailable'),\n SandboxStateStoreError: storeError => toolError(storeError.message, 'unavailable')\n })\n )\n\nconst normalizeTimeoutMs = (timeoutSeconds: number | null | undefined) => {\n const value = nullToUndefined(timeoutSeconds)\n\n if (value === undefined) {\n return Effect.succeed(sandboxCommandTimeoutMs(undefined))\n }\n\n if (!Number.isFinite(value) || value <= 0) {\n return Effect.fail(\n modelVisibleToolError({\n tool: sandboxToolName,\n message: 'timeoutSeconds must be greater than 0',\n reason: 'invalid_input'\n })\n )\n }\n\n return Effect.succeed(sandboxCommandTimeoutMs(Math.floor(value * 1_000)))\n}\n\nconst normalizeToolParams = (params: SandboxToolParams) =>\n Effect.gen(function* () {\n const command = yield* validateSandboxCommand(params.command).pipe(\n Effect.mapError(modelVisibleSandboxError)\n )\n\n const cwd = yield* normalizeWorkspaceCwd(params.cwd).pipe(\n Effect.mapError(modelVisibleSandboxError)\n )\n\n const timeoutMs = yield* normalizeTimeoutMs(params.timeoutSeconds)\n\n return {\n command,\n cwd,\n stdin: nullToUndefined(params.stdin),\n timeoutMs,\n background: nullToUndefined(params.background)\n }\n })\n\nconst truncateOutputs = (stdout: string, stderr: string, limit: number): OutputSlice => {\n if (stdout.length + stderr.length <= limit) {\n return { stdout, stderr, truncated: false }\n }\n\n const initialStderrBudget = Math.min(stderr.length, Math.floor(limit / 2))\n const initialStdoutBudget = Math.min(stdout.length, limit - initialStderrBudget)\n const unused = limit - initialStdoutBudget - initialStderrBudget\n const stdoutBudget = Math.min(stdout.length, initialStdoutBudget + unused)\n const stderrBudget = Math.min(stderr.length, limit - stdoutBudget)\n\n return {\n stdout: stdout.slice(0, stdoutBudget),\n stderr: stderr.slice(0, stderrBudget),\n truncated: true\n }\n}\n\nconst formatSandboxToolContent = (result: SandboxCommandResult, output: OutputSlice) =>\n [\n `exit_code: ${result.exitCode === null ? 'null' : String(result.exitCode)}`,\n `duration_ms: ${result.durationMs}`,\n `truncated: ${output.truncated}`,\n `timed_out: ${result.timedOut}`,\n `workspace_reset: ${result.workspaceReset}`,\n result.backgroundId === undefined ? undefined : `background_id: ${result.backgroundId}`,\n '<stdout>',\n output.stdout,\n '</stdout>',\n '<stderr>',\n output.stderr,\n '</stderr>'\n ]\n .filter(line => line !== undefined)\n .join('\\n')\n\nconst plainSandboxPreviewUrl = (\n previewUrl: SandboxCommandResult['previewUrls'][number]\n): PlainSandboxPreviewUrl => ({\n port: previewUrl.port,\n url: previewUrl.url\n})\n\nconst plainSandboxState = (state: SandboxCommandResult['state']): PlainSandboxState =>\n Match.value(state._tag).pipe(\n Match.when('Vercel', () => ({\n _tag: state._tag,\n name: state.name,\n createdAtMs: state.createdAtMs,\n lastUsedAtMs: state.lastUsedAtMs,\n expiresAtMs: state.expiresAtMs,\n maxExpiresAtMs: state.maxExpiresAtMs\n })),\n Match.exhaustive\n )\n\ntype SandboxToolStructuredContentFields = {\n readonly exitCode: number | null\n readonly durationMs: number\n readonly timedOut: boolean\n readonly truncated: boolean\n readonly workspaceReset: boolean\n backgroundId?: string\n}\n\nconst structuredContent = (\n result: SandboxCommandResult,\n truncated: boolean\n): SandboxToolStructuredContent => {\n const content: SandboxToolStructuredContentFields = {\n exitCode: result.exitCode,\n durationMs: result.durationMs,\n timedOut: result.timedOut,\n truncated,\n workspaceReset: result.workspaceReset\n }\n\n if (result.backgroundId !== undefined) {\n content.backgroundId = result.backgroundId\n }\n\n return {\n ...content,\n previewUrls: result.previewUrls.map(plainSandboxPreviewUrl),\n state: plainSandboxState(result.state)\n }\n}\n\nexport const makeSandboxToolResult = (input: {\n readonly callId: string\n readonly result: SandboxCommandResult\n}) => {\n const output = truncateOutputs(input.result.stdout, input.result.stderr, sandboxToolOutputLimit)\n\n return ToolResult.make({\n toolCallId: input.callId,\n content: formatSandboxToolContent(input.result, output),\n isError:\n input.result.timedOut || (input.result.exitCode !== null && input.result.exitCode !== 0),\n structuredContent: structuredContent(input.result, output.truncated)\n })\n}\n\nconst sandboxToolDescription = <Context>(options: SandboxToolModuleOptions<Context>) => {\n const capabilities = options.capabilities ?? [\n 'run project commands such as typechecks, lint, tests, and builds',\n 'edit files with shell tools such as apply_patch when available',\n 'start dev servers and use preview ports',\n 'run browser checks through agent-browser when available'\n ]\n\n const ports = options.previewPorts ?? []\n\n return [\n 'Run one non-interactive bash command inside a real sandbox workspace.',\n options.workspaceDescription ?? 'The working directory is the sandbox workspace root.',\n options.lifecycleDescription ??\n 'The sandbox is disposable and may reset after idle or max lifetime expiry.',\n `Foreground timeout defaults to 120s and is capped at ${Math.floor(maxSandboxCommandTimeoutMs / 1_000)}s.`,\n 'Use workspace-relative cwd only; absolute paths and workspace escapes are rejected.',\n 'Use stdin for large patches, scripts, or data.',\n 'Set background=true for long-running servers; the tool returns after a quick probe.',\n ports.length === 0\n ? 'Preview URLs are returned when configured by the host.'\n : `Preview ports: ${ports.join(', ')}.`,\n `Available capabilities:\\n${capabilities.map(capability => `- ${capability}`).join('\\n')}`\n ].join('\\n\\n')\n}\n\nexport const makeSandboxToolModuleFromApi = <Context>(\n sandbox: SandboxApi,\n options: SandboxToolModuleOptions<Context> = {}\n): ToolModule<Context> => ({\n id: 'sandbox',\n tools: [\n makeTool({\n name: sandboxToolName,\n description: sandboxToolDescription(options),\n parameters: SandboxToolParams,\n access: 'destructive',\n isEnabled: options.isEnabled,\n invalidParamsMessage: error =>\n `Invalid sandbox arguments: ${error instanceof Error ? error.message : String(error)}`,\n execute: ({ call, params }) =>\n Effect.gen(function* () {\n if (call.name !== sandboxToolName) {\n return yield* Effect.fail(\n toolError(`Tool is not configured: ${call.name}`, 'not_found')\n )\n }\n\n const normalized = yield* normalizeToolParams(params)\n\n const result = yield* sandbox.run(normalized).pipe(\n Effect.mapError(error =>\n Match.value(error).pipe(\n Match.tagsExhaustive({\n SandboxInputError: inputError => modelVisibleSandboxError(inputError),\n SandboxExpiredError: expiredError => modelVisibleSandboxError(expiredError),\n SandboxConfigError: configError => sandboxInfraToolError(configError),\n SandboxProviderError: providerError => sandboxInfraToolError(providerError),\n SandboxStateError: stateError => sandboxInfraToolError(stateError),\n SandboxStateStoreError: storeError => sandboxInfraToolError(storeError)\n })\n )\n )\n )\n\n return makeSandboxToolResult({ callId: call.id, result })\n })\n })\n ]\n})\n\nexport const makeSandboxToolModule = <Context>(\n options: SandboxToolModuleOptions<Context> = {}\n): Effect.Effect<ToolModule<Context>, never, Sandbox> =>\n Effect.gen(function* () {\n const sandbox = yield* Sandbox\n\n return makeSandboxToolModuleFromApi(sandbox, options)\n })\n\nexport type SandboxToolExecutionInput<Context> = {\n readonly call: ToolCall\n readonly context: Context\n readonly params: SandboxToolParams\n}\n"],"mappings":"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"}
package/dist/errors.d.mts CHANGED
@@ -38,7 +38,6 @@ declare const SandboxProviderError_base: Schema.Class<SandboxProviderError, Sche
38
38
  }>, import("effect/Cause").YieldableError>;
39
39
  declare class SandboxProviderError extends SandboxProviderError_base {}
40
40
  type SandboxError = SandboxInputError | SandboxConfigError | SandboxExpiredError | SandboxStateError | SandboxStateStoreError | SandboxProviderError;
41
- declare const unknownToMessage: (error: unknown) => string;
42
41
  //#endregion
43
- export { SandboxConfigError, SandboxError, SandboxExpiredError, SandboxInputError, SandboxInputErrorCause, SandboxProviderError, SandboxStateError, SandboxStateStoreError, unknownToMessage };
42
+ export { SandboxConfigError, SandboxError, SandboxExpiredError, SandboxInputError, SandboxInputErrorCause, SandboxProviderError, SandboxStateError, SandboxStateStoreError };
44
43
  //# sourceMappingURL=errors.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.mts","names":[],"sources":["../src/errors.ts"],"mappings":";;;cAEa,sBAAA,EAAsB,MAAA,CAAA,QAAA;AAAA,KAKvB,sBAAA,UAAgC,sBAAA,CAAuB,IAAI;AAAA,cAAA,sBAAA;;;;cAE1D,iBAAA,SAA0B,sBAMtC;AAAA,cAAG,uBAAA;;;;cAES,kBAAA,SAA2B,uBAMvC;AAAA,cAAG,wBAAA;;;;cAES,mBAAA,SAA4B,wBAMxC;AAAA,cAAG,sBAAA;;;;;cAES,iBAAA,SAA0B,sBAOtC;AAAA,cAAG,2BAAA;;;;;cAES,sBAAA,SAA+B,2BAO3C;AAAA,cAAG,yBAAA;;;;;;cAES,oBAAA,SAA6B,yBAQzC;AAAA,KAEW,YAAA,GACR,iBAAA,GACA,kBAAA,GACA,mBAAA,GACA,iBAAA,GACA,sBAAA,GACA,oBAAA;AAAA,cAES,gBAAA,GAAoB,KAAc"}
1
+ {"version":3,"file":"errors.d.mts","names":[],"sources":["../src/errors.ts"],"mappings":";;;cAEa,sBAAA,EAAsB,MAAA,CAAA,QAAA;AAAA,KAMvB,sBAAA,UAAgC,sBAAA,CAAuB,IAAI;AAAA,cAAA,sBAAA;;;;cAE1D,iBAAA,SAA0B,sBAMtC;AAAA,cAAG,uBAAA;;;;cAES,kBAAA,SAA2B,uBAMvC;AAAA,cAAG,wBAAA;;;;cAES,mBAAA,SAA4B,wBAMxC;AAAA,cAAG,sBAAA;;;;;cAES,iBAAA,SAA0B,sBAOtC;AAAA,cAAG,2BAAA;;;;;cAES,sBAAA,SAA+B,2BAO3C;AAAA,cAAG,yBAAA;;;;;;cAES,oBAAA,SAA6B,yBAQzC;AAAA,KAEW,YAAA,GACR,iBAAA,GACA,kBAAA,GACA,mBAAA,GACA,iBAAA,GACA,sBAAA,GACA,oBAAA"}
package/dist/errors.mjs CHANGED
@@ -5,36 +5,35 @@ const SandboxInputErrorCause = Schema.Literals([
5
5
  "invalid_cwd",
6
6
  "invalid_timeout"
7
7
  ]);
8
- var SandboxInputError = class extends Schema.TaggedErrorClass()("SandboxInputError", {
8
+ var SandboxInputError = class extends Schema.TaggedError()("SandboxInputError", {
9
9
  cause: SandboxInputErrorCause,
10
10
  message: Schema.String
11
11
  }) {};
12
- var SandboxConfigError = class extends Schema.TaggedErrorClass()("SandboxConfigError", {
12
+ var SandboxConfigError = class extends Schema.TaggedError()("SandboxConfigError", {
13
13
  message: Schema.String,
14
14
  cause: Schema.String
15
15
  }) {};
16
- var SandboxExpiredError = class extends Schema.TaggedErrorClass()("SandboxExpiredError", {
16
+ var SandboxExpiredError = class extends Schema.TaggedError()("SandboxExpiredError", {
17
17
  message: Schema.String,
18
18
  expiredAtMs: Schema.Number
19
19
  }) {};
20
- var SandboxStateError = class extends Schema.TaggedErrorClass()("SandboxStateError", {
20
+ var SandboxStateError = class extends Schema.TaggedError()("SandboxStateError", {
21
21
  message: Schema.String,
22
22
  cause: Schema.String,
23
23
  underlying: Schema.optional(Schema.Unknown)
24
24
  }) {};
25
- var SandboxStateStoreError = class extends Schema.TaggedErrorClass()("SandboxStateStoreError", {
25
+ var SandboxStateStoreError = class extends Schema.TaggedError()("SandboxStateStoreError", {
26
26
  message: Schema.String,
27
27
  operation: Schema.String,
28
28
  underlying: Schema.optional(Schema.Unknown)
29
29
  }) {};
30
- var SandboxProviderError = class extends Schema.TaggedErrorClass()("SandboxProviderError", {
30
+ var SandboxProviderError = class extends Schema.TaggedError()("SandboxProviderError", {
31
31
  provider: Schema.Literal("vercel"),
32
32
  operation: Schema.String,
33
33
  message: Schema.String,
34
34
  underlying: Schema.optional(Schema.Unknown)
35
35
  }) {};
36
- const unknownToMessage = (error) => error instanceof Error ? error.message : String(error);
37
36
  //#endregion
38
- export { SandboxConfigError, SandboxExpiredError, SandboxInputError, SandboxInputErrorCause, SandboxProviderError, SandboxStateError, SandboxStateStoreError, unknownToMessage };
37
+ export { SandboxConfigError, SandboxExpiredError, SandboxInputError, SandboxInputErrorCause, SandboxProviderError, SandboxStateError, SandboxStateStoreError };
39
38
 
40
39
  //# sourceMappingURL=errors.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import * as Schema from 'effect/Schema'\n\nexport const SandboxInputErrorCause = Schema.Literals([\n 'empty_command',\n 'invalid_cwd',\n 'invalid_timeout'\n])\nexport type SandboxInputErrorCause = typeof SandboxInputErrorCause.Type\n\nexport class SandboxInputError extends Schema.TaggedErrorClass<SandboxInputError>()(\n 'SandboxInputError',\n {\n cause: SandboxInputErrorCause,\n message: Schema.String\n }\n) {}\n\nexport class SandboxConfigError extends Schema.TaggedErrorClass<SandboxConfigError>()(\n 'SandboxConfigError',\n {\n message: Schema.String,\n cause: Schema.String\n }\n) {}\n\nexport class SandboxExpiredError extends Schema.TaggedErrorClass<SandboxExpiredError>()(\n 'SandboxExpiredError',\n {\n message: Schema.String,\n expiredAtMs: Schema.Number\n }\n) {}\n\nexport class SandboxStateError extends Schema.TaggedErrorClass<SandboxStateError>()(\n 'SandboxStateError',\n {\n message: Schema.String,\n cause: Schema.String,\n underlying: Schema.optional(Schema.Unknown)\n }\n) {}\n\nexport class SandboxStateStoreError extends Schema.TaggedErrorClass<SandboxStateStoreError>()(\n 'SandboxStateStoreError',\n {\n message: Schema.String,\n operation: Schema.String,\n underlying: Schema.optional(Schema.Unknown)\n }\n) {}\n\nexport class SandboxProviderError extends Schema.TaggedErrorClass<SandboxProviderError>()(\n 'SandboxProviderError',\n {\n provider: Schema.Literal('vercel'),\n operation: Schema.String,\n message: Schema.String,\n underlying: Schema.optional(Schema.Unknown)\n }\n) {}\n\nexport type SandboxError =\n | SandboxInputError\n | SandboxConfigError\n | SandboxExpiredError\n | SandboxStateError\n | SandboxStateStoreError\n | SandboxProviderError\n\nexport const unknownToMessage = (error: unknown) =>\n error instanceof Error ? error.message : String(error)\n"],"mappings":";;AAEA,MAAa,yBAAyB,OAAO,SAAS;CACpD;CACA;CACA;AACF,CAAC;AAGD,IAAa,oBAAb,cAAuC,OAAO,iBAAoC,EAChF,qBACA;CACE,OAAO;CACP,SAAS,OAAO;AAClB,CACF,EAAE,CAAC;AAEH,IAAa,qBAAb,cAAwC,OAAO,iBAAqC,EAClF,sBACA;CACE,SAAS,OAAO;CAChB,OAAO,OAAO;AAChB,CACF,EAAE,CAAC;AAEH,IAAa,sBAAb,cAAyC,OAAO,iBAAsC,EACpF,uBACA;CACE,SAAS,OAAO;CAChB,aAAa,OAAO;AACtB,CACF,EAAE,CAAC;AAEH,IAAa,oBAAb,cAAuC,OAAO,iBAAoC,EAChF,qBACA;CACE,SAAS,OAAO;CAChB,OAAO,OAAO;CACd,YAAY,OAAO,SAAS,OAAO,OAAO;AAC5C,CACF,EAAE,CAAC;AAEH,IAAa,yBAAb,cAA4C,OAAO,iBAAyC,EAC1F,0BACA;CACE,SAAS,OAAO;CAChB,WAAW,OAAO;CAClB,YAAY,OAAO,SAAS,OAAO,OAAO;AAC5C,CACF,EAAE,CAAC;AAEH,IAAa,uBAAb,cAA0C,OAAO,iBAAuC,EACtF,wBACA;CACE,UAAU,OAAO,QAAQ,QAAQ;CACjC,WAAW,OAAO;CAClB,SAAS,OAAO;CAChB,YAAY,OAAO,SAAS,OAAO,OAAO;AAC5C,CACF,EAAE,CAAC;AAUH,MAAa,oBAAoB,UAC/B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK"}
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import * as Schema from 'effect/Schema'\n\nexport const SandboxInputErrorCause = Schema.Literals([\n 'empty_command',\n 'invalid_cwd',\n 'invalid_timeout'\n])\n\nexport type SandboxInputErrorCause = typeof SandboxInputErrorCause.Type\n\nexport class SandboxInputError extends Schema.TaggedError<SandboxInputError>()(\n 'SandboxInputError',\n {\n cause: SandboxInputErrorCause,\n message: Schema.String\n }\n) {}\n\nexport class SandboxConfigError extends Schema.TaggedError<SandboxConfigError>()(\n 'SandboxConfigError',\n {\n message: Schema.String,\n cause: Schema.String\n }\n) {}\n\nexport class SandboxExpiredError extends Schema.TaggedError<SandboxExpiredError>()(\n 'SandboxExpiredError',\n {\n message: Schema.String,\n expiredAtMs: Schema.Number\n }\n) {}\n\nexport class SandboxStateError extends Schema.TaggedError<SandboxStateError>()(\n 'SandboxStateError',\n {\n message: Schema.String,\n cause: Schema.String,\n underlying: Schema.optional(Schema.Unknown)\n }\n) {}\n\nexport class SandboxStateStoreError extends Schema.TaggedError<SandboxStateStoreError>()(\n 'SandboxStateStoreError',\n {\n message: Schema.String,\n operation: Schema.String,\n underlying: Schema.optional(Schema.Unknown)\n }\n) {}\n\nexport class SandboxProviderError extends Schema.TaggedError<SandboxProviderError>()(\n 'SandboxProviderError',\n {\n provider: Schema.Literal('vercel'),\n operation: Schema.String,\n message: Schema.String,\n underlying: Schema.optional(Schema.Unknown)\n }\n) {}\n\nexport type SandboxError =\n | SandboxInputError\n | SandboxConfigError\n | SandboxExpiredError\n | SandboxStateError\n | SandboxStateStoreError\n | SandboxProviderError\n"],"mappings":";;AAEA,MAAa,yBAAyB,OAAO,SAAS;CACpD;CACA;CACA;AACF,CAAC;AAID,IAAa,oBAAb,cAAuC,OAAO,YAA+B,EAC3E,qBACA;CACE,OAAO;CACP,SAAS,OAAO;AAClB,CACF,EAAE,CAAC;AAEH,IAAa,qBAAb,cAAwC,OAAO,YAAgC,EAC7E,sBACA;CACE,SAAS,OAAO;CAChB,OAAO,OAAO;AAChB,CACF,EAAE,CAAC;AAEH,IAAa,sBAAb,cAAyC,OAAO,YAAiC,EAC/E,uBACA;CACE,SAAS,OAAO;CAChB,aAAa,OAAO;AACtB,CACF,EAAE,CAAC;AAEH,IAAa,oBAAb,cAAuC,OAAO,YAA+B,EAC3E,qBACA;CACE,SAAS,OAAO;CAChB,OAAO,OAAO;CACd,YAAY,OAAO,SAAS,OAAO,OAAO;AAC5C,CACF,EAAE,CAAC;AAEH,IAAa,yBAAb,cAA4C,OAAO,YAAoC,EACrF,0BACA;CACE,SAAS,OAAO;CAChB,WAAW,OAAO;CAClB,YAAY,OAAO,SAAS,OAAO,OAAO;AAC5C,CACF,EAAE,CAAC;AAEH,IAAa,uBAAb,cAA0C,OAAO,YAAkC,EACjF,wBACA;CACE,UAAU,OAAO,QAAQ,QAAQ;CACjC,WAAW,OAAO;CAClB,SAAS,OAAO;CAChB,YAAY,OAAO,SAAS,OAAO,OAAO;AAC5C,CACF,EAAE,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { SandboxInputError } from "./errors.mjs";
2
2
  import { DisposableSandboxLifecycle, EmptySandboxInitialSource, SandboxInitialSource, SandboxLifecycle, SandboxState, VercelSandboxState } from "./model.mjs";
3
3
  import { Effect, Option } from "effect";
4
+ import * as Schema from "effect/Schema";
4
5
 
5
6
  //#region src/lifecycle.d.ts
6
7
  declare const defaultSandboxIdleTtlMs: number;
@@ -14,14 +15,14 @@ declare const defaultSandboxWorkspaceRoot = "/vercel/sandbox";
14
15
  declare const defaultSandboxLifecycle: DisposableSandboxLifecycle;
15
16
  declare const defaultSandboxInitialSource: EmptySandboxInitialSource;
16
17
  type SandboxRecreateReason = 'idle_expired' | 'max_expired' | 'name_mismatch';
18
+ declare const SandboxCreateDecision: Schema.TaggedStruct<"Create", {
19
+ readonly workspaceReset: Schema.Boolean;
20
+ readonly reason: Schema.optionalKey<Schema.Literals<readonly ["idle_expired", "max_expired", "name_mismatch"]>>;
21
+ }>;
17
22
  type SandboxStateDecision = {
18
23
  readonly _tag: 'UseExisting';
19
24
  readonly state: SandboxState;
20
- } | {
21
- readonly _tag: 'Create';
22
- readonly workspaceReset: boolean;
23
- readonly reason?: SandboxRecreateReason;
24
- };
25
+ } | typeof SandboxCreateDecision.Type;
25
26
  declare const sandboxLifecycleOrDefault: (lifecycle?: SandboxLifecycle) => SandboxLifecycle;
26
27
  declare const sandboxSourceOrDefault: (source?: SandboxInitialSource) => SandboxInitialSource;
27
28
  declare const sandboxCommandTimeoutMs: (timeoutMs?: number) => number;
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.d.mts","names":[],"sources":["../src/lifecycle.ts"],"mappings":";;;;;cAWa,uBAAA;AAAA,cACA,2BAAA;AAAA,cACA,8BAAA;AAAA,cACA,0BAAA;AAAA,cACA,wBAAA;AAAA,cACA,sBAAA;AAAA,cACA,mBAAA,EAAqB,aAAa;AAAA,cAClC,2BAAA;AAAA,cAEA,uBAAA,EAAuB,0BAGlC;AAAA,cAEW,2BAAA,EAA2B,yBAAqC;AAAA,KAEjE,qBAAA;AAAA,KAEA,oBAAA;EAAA,SAEG,IAAA;EAAA,SACA,KAAA,EAAO,YAAA;AAAA;EAAA,SAGP,IAAA;EAAA,SACA,cAAA;EAAA,SACA,MAAA,GAAS,qBAAqB;AAAA;AAAA,cAMhC,yBAAA,GAA6B,SAAA,GAAY,gBAAA,KAAmB,gBACnC;AAAA,cAEzB,sBAAA,GAA0B,MAAA,GAAS,oBAAA,KAAuB,oBAChC;AAAA,cAE1B,uBAAA,GAA2B,SAAkB;AAAA,cAG7C,sBAAA,GAA0B,OAAA,aAAe,MAAA,CAAA,MAAA,QAAA,iBAAA,WAAA,MAAA,CAAA,MAAA;AAAA,cAazC,qBAAA,GACX,GAAA,qBACC,MAAA,CAAO,MAAM,SAAS,iBAAA;AAAA,cA0CZ,kBAAA,GAAsB,aAAA,UAAuB,aAAqB;AAAA,cAGlE,mBAAA,GAAuB,KAAA;EAAA,SACzB,IAAA;EAAA,SACA,KAAA;EAAA,SACA,SAAA,EAAW,gBAAA;AAAA,MACrB,kBAmBA;AAAA,cAEY,iBAAA,GAAqB,KAAA;EAAA,SACvB,KAAA,EAAO,YAAA;EAAA,SACP,KAAA;EAAA,SACA,SAAA,EAAW,gBAAA;AAAA,MACrB,kBAAA;AAAA,cAiBY,2BAAA,GAA+B,KAAA;EAAA,SACjC,MAAA,EAAQ,YAAA;EAAA,SACR,KAAA,EAAO,YAAY;AAAA;AAAA,cAGjB,oBAAA,GAAwB,KAAA;EAAA,SAC1B,KAAA,EAAO,MAAA,CAAO,MAAA,CAAO,YAAA;EAAA,SACrB,IAAA;EAAA,SACA,KAAA;EAAA,SACA,SAAA,EAAW,gBAAA;AAAA,MAClB,oBAAA"}
1
+ {"version":3,"file":"lifecycle.d.mts","names":[],"sources":["../src/lifecycle.ts"],"mappings":";;;;;;cAYa,uBAAA;AAAA,cAEA,2BAAA;AAAA,cAEA,8BAAA;AAAA,cAEA,0BAAA;AAAA,cAEA,wBAAA;AAAA,cAEA,sBAAA;AAAA,cAEA,mBAAA,EAAqB,aAAa;AAAA,cAElC,2BAAA;AAAA,cAEA,uBAAA,EAAuB,0BAGlC;AAAA,cAEW,2BAAA,EAA2B,yBAAqC;AAAA,KAEjE,qBAAA;AAAA,cAMN,qBAAA,EAAqB,MAAA,CAAA,YAAA;EAAA;;;KAKf,oBAAA;EAAA,SAEG,IAAA;EAAA,SACA,KAAA,EAAO,YAAA;AAAA,WAEX,qBAAA,CAAsB,IAAI;AAAA,cAUxB,yBAAA,GAA6B,SAAA,GAAY,gBAAA,KAAmB,gBACnC;AAAA,cAEzB,sBAAA,GAA0B,MAAA,GAAS,oBAAA,KAAuB,oBAChC;AAAA,cAE1B,uBAAA,GAA2B,SAAkB;AAAA,cAG7C,sBAAA,GAA0B,OAAA,aAAe,MAAA,CAAA,MAAA,QAAA,iBAAA,WAAA,MAAA,CAAA,MAAA;AAAA,cAazC,qBAAA,GACX,GAAA,qBACC,MAAA,CAAO,MAAM,SAAS,iBAAA;AAAA,cA4CZ,kBAAA,GAAsB,aAAA,UAAuB,aAAqB;AAAA,cAGlE,mBAAA,GAAuB,KAAA;EAAA,SACzB,IAAA;EAAA,SACA,KAAA;EAAA,SACA,SAAA,EAAW,gBAAA;AAAA,MACrB,kBAsBE;AAAA,cAEU,iBAAA,GAAqB,KAAA;EAAA,SACvB,KAAA,EAAO,YAAA;EAAA,SACP,KAAA;EAAA,SACA,SAAA,EAAW,gBAAA;AAAA,MACrB,kBAAA;AAAA,cAoBY,2BAAA,GAA+B,KAAA;EAAA,SACjC,MAAA,EAAQ,YAAA;EAAA,SACR,KAAA,EAAO,YAAY;AAAA;AAAA,cAGjB,oBAAA,GAAwB,KAAA;EAAA,SAC1B,KAAA,EAAO,MAAA,CAAO,MAAA,CAAO,YAAA;EAAA,SACrB,IAAA;EAAA,SACA,KAAA;EAAA,SACA,SAAA,EAAW,gBAAA;AAAA,MAClB,oBAAA"}
@@ -1,6 +1,7 @@
1
1
  import { SandboxInputError } from "./errors.mjs";
2
2
  import { DisposableSandboxLifecycle, EmptySandboxInitialSource, VercelSandboxState } from "./model.mjs";
3
- import { Effect, Option } from "effect";
3
+ import { Effect, Match, Option, Predicate } from "effect";
4
+ import * as Schema from "effect/Schema";
4
5
  //#region src/lifecycle.ts
5
6
  const defaultSandboxIdleTtlMs = 30 * 6e4;
6
7
  const defaultSandboxMaxLifetimeMs = 45 * 6e4;
@@ -20,6 +21,19 @@ const defaultSandboxLifecycle = DisposableSandboxLifecycle.make({
20
21
  maxLifetimeMs: defaultSandboxMaxLifetimeMs
21
22
  });
22
23
  const defaultSandboxInitialSource = EmptySandboxInitialSource.make({});
24
+ const SandboxUseExistingDecision = Schema.TaggedStruct("UseExisting", { state: Schema.Unknown });
25
+ const SandboxCreateDecision = Schema.TaggedStruct("Create", {
26
+ workspaceReset: Schema.Boolean,
27
+ reason: Schema.optionalKey(Schema.Literals([
28
+ "idle_expired",
29
+ "max_expired",
30
+ "name_mismatch"
31
+ ]))
32
+ });
33
+ const existingSandboxStateDecision = (state) => ({
34
+ ...SandboxUseExistingDecision.make({ state }),
35
+ state
36
+ });
23
37
  const positiveOr = (value, fallback) => value === void 0 || !Number.isFinite(value) || value <= 0 ? fallback : Math.floor(value);
24
38
  const sandboxLifecycleOrDefault = (lifecycle) => lifecycle ?? defaultSandboxLifecycle;
25
39
  const sandboxSourceOrDefault = (source) => source ?? defaultSandboxInitialSource;
@@ -53,68 +67,46 @@ const normalizeWorkspaceCwd = (cwd) => {
53
67
  return Effect.succeed(parts.length === 0 ? "." : parts.join("/"));
54
68
  };
55
69
  const absoluteSandboxCwd = (workspaceRoot, normalizedCwd) => normalizedCwd === "." ? workspaceRoot : `${workspaceRoot}/${normalizedCwd}`;
56
- const initialSandboxState = (input) => {
57
- switch (input.lifecycle._tag) {
58
- case "Disposable": return VercelSandboxState.make({
59
- name: input.name,
60
- createdAtMs: input.nowMs,
61
- lastUsedAtMs: input.nowMs,
62
- expiresAtMs: input.nowMs + input.lifecycle.idleTtlMs,
63
- maxExpiresAtMs: input.nowMs + input.lifecycle.maxLifetimeMs
64
- });
65
- case "Persistent": return VercelSandboxState.make({
66
- name: input.name,
67
- createdAtMs: input.nowMs,
68
- lastUsedAtMs: input.nowMs,
69
- expiresAtMs: input.nowMs + input.lifecycle.idleTtlMs,
70
- maxExpiresAtMs: Number.MAX_SAFE_INTEGER
71
- });
72
- }
73
- };
74
- const touchSandboxState = (input) => {
75
- switch (input.lifecycle._tag) {
76
- case "Disposable": return VercelSandboxState.make({
77
- ...input.state,
78
- lastUsedAtMs: input.nowMs,
79
- expiresAtMs: Math.min(input.nowMs + input.lifecycle.idleTtlMs, input.state.maxExpiresAtMs)
80
- });
81
- case "Persistent": return VercelSandboxState.make({
82
- ...input.state,
83
- lastUsedAtMs: input.nowMs,
84
- expiresAtMs: input.nowMs + input.lifecycle.idleTtlMs
85
- });
86
- }
87
- };
70
+ const initialSandboxState = (input) => Match.value(input.lifecycle).pipe(Match.withReturnType(), Match.tag("Disposable", (lifecycle) => VercelSandboxState.make({
71
+ name: input.name,
72
+ createdAtMs: input.nowMs,
73
+ lastUsedAtMs: input.nowMs,
74
+ expiresAtMs: input.nowMs + lifecycle.idleTtlMs,
75
+ maxExpiresAtMs: input.nowMs + lifecycle.maxLifetimeMs
76
+ })), Match.tag("Persistent", (lifecycle) => VercelSandboxState.make({
77
+ name: input.name,
78
+ createdAtMs: input.nowMs,
79
+ lastUsedAtMs: input.nowMs,
80
+ expiresAtMs: input.nowMs + lifecycle.idleTtlMs,
81
+ maxExpiresAtMs: Number.MAX_SAFE_INTEGER
82
+ })), Match.exhaustive);
83
+ const touchSandboxState = (input) => Match.value(input.lifecycle).pipe(Match.withReturnType(), Match.tag("Disposable", (lifecycle) => VercelSandboxState.make({
84
+ ...input.state,
85
+ lastUsedAtMs: input.nowMs,
86
+ expiresAtMs: Math.min(input.nowMs + lifecycle.idleTtlMs, input.state.maxExpiresAtMs)
87
+ })), Match.tag("Persistent", (lifecycle) => VercelSandboxState.make({
88
+ ...input.state,
89
+ lastUsedAtMs: input.nowMs,
90
+ expiresAtMs: input.nowMs + lifecycle.idleTtlMs
91
+ })), Match.exhaustive);
88
92
  const sandboxTimeoutExtendDeltaMs = (input) => Math.max(0, input.after.expiresAtMs - input.before.expiresAtMs);
89
93
  const sandboxStateDecision = (input) => {
90
- if (Option.isNone(input.state)) return {
91
- _tag: "Create",
92
- workspaceReset: false
93
- };
94
+ if (Option.isNone(input.state)) return SandboxCreateDecision.make({ workspaceReset: false });
94
95
  const state = input.state.value;
95
- if (state.name !== input.name) return {
96
- _tag: "Create",
96
+ if (state.name !== input.name) return SandboxCreateDecision.make({
97
97
  workspaceReset: true,
98
98
  reason: "name_mismatch"
99
- };
100
- if (input.lifecycle._tag === "Persistent") return {
101
- _tag: "UseExisting",
102
- state
103
- };
104
- if (input.nowMs >= state.maxExpiresAtMs) return {
105
- _tag: "Create",
99
+ });
100
+ if (Predicate.isTagged(input.lifecycle, "Persistent")) return existingSandboxStateDecision(state);
101
+ if (input.nowMs >= state.maxExpiresAtMs) return SandboxCreateDecision.make({
106
102
  workspaceReset: true,
107
103
  reason: "max_expired"
108
- };
109
- if (input.nowMs >= state.expiresAtMs) return {
110
- _tag: "Create",
104
+ });
105
+ if (input.nowMs >= state.expiresAtMs) return SandboxCreateDecision.make({
111
106
  workspaceReset: true,
112
107
  reason: "idle_expired"
113
- };
114
- return {
115
- _tag: "UseExisting",
116
- state
117
- };
108
+ });
109
+ return existingSandboxStateDecision(state);
118
110
  };
119
111
  //#endregion
120
112
  export { absoluteSandboxCwd, backgroundSandboxProbeMs, defaultSandboxCommandTimeoutMs, defaultSandboxIdleTtlMs, defaultSandboxInitialSource, defaultSandboxLifecycle, defaultSandboxMaxLifetimeMs, defaultSandboxPorts, defaultSandboxWorkspaceRoot, initialSandboxState, maxSandboxCommandTimeoutMs, normalizeWorkspaceCwd, sandboxCommandTimeoutMs, sandboxLifecycleOrDefault, sandboxSourceOrDefault, sandboxStateDecision, sandboxTimeoutExtendDeltaMs, sandboxToolOutputLimit, touchSandboxState, validateSandboxCommand };
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.mjs","names":[],"sources":["../src/lifecycle.ts"],"sourcesContent":["import { Effect, Option } from 'effect'\nimport { SandboxInputError } from './errors.ts'\nimport {\n DisposableSandboxLifecycle,\n EmptySandboxInitialSource,\n type SandboxInitialSource,\n type SandboxLifecycle,\n type SandboxState,\n VercelSandboxState\n} from './model.ts'\n\nexport const defaultSandboxIdleTtlMs = 30 * 60_000\nexport const defaultSandboxMaxLifetimeMs = 45 * 60_000\nexport const defaultSandboxCommandTimeoutMs = 120_000\nexport const maxSandboxCommandTimeoutMs = 600_000\nexport const backgroundSandboxProbeMs = 2_000\nexport const sandboxToolOutputLimit = 50_000\nexport const defaultSandboxPorts: ReadonlyArray<number> = [3000, 5173, 4321, 8000]\nexport const defaultSandboxWorkspaceRoot = '/vercel/sandbox'\n\nexport const defaultSandboxLifecycle = DisposableSandboxLifecycle.make({\n idleTtlMs: defaultSandboxIdleTtlMs,\n maxLifetimeMs: defaultSandboxMaxLifetimeMs\n})\n\nexport const defaultSandboxInitialSource = EmptySandboxInitialSource.make({})\n\nexport type SandboxRecreateReason = 'idle_expired' | 'max_expired' | 'name_mismatch'\n\nexport type SandboxStateDecision =\n | {\n readonly _tag: 'UseExisting'\n readonly state: SandboxState\n }\n | {\n readonly _tag: 'Create'\n readonly workspaceReset: boolean\n readonly reason?: SandboxRecreateReason\n }\n\nconst positiveOr = (value: number | undefined, fallback: number) =>\n value === undefined || !Number.isFinite(value) || value <= 0 ? fallback : Math.floor(value)\n\nexport const sandboxLifecycleOrDefault = (lifecycle?: SandboxLifecycle): SandboxLifecycle =>\n lifecycle ?? defaultSandboxLifecycle\n\nexport const sandboxSourceOrDefault = (source?: SandboxInitialSource): SandboxInitialSource =>\n source ?? defaultSandboxInitialSource\n\nexport const sandboxCommandTimeoutMs = (timeoutMs?: number) =>\n Math.min(maxSandboxCommandTimeoutMs, positiveOr(timeoutMs, defaultSandboxCommandTimeoutMs))\n\nexport const validateSandboxCommand = (command: string) => {\n if (command.trim().length === 0) {\n return Effect.fail(\n new SandboxInputError({\n cause: 'empty_command',\n message: 'Sandbox command must not be empty'\n })\n )\n }\n\n return Effect.succeed(command)\n}\n\nexport const normalizeWorkspaceCwd = (\n cwd?: string | null\n): Effect.Effect<string, SandboxInputError> => {\n if (cwd === undefined || cwd === null || cwd.trim().length === 0) {\n return Effect.succeed('.')\n }\n\n const trimmed = cwd.trim()\n\n if (trimmed.startsWith('/') || trimmed.includes('\\0')) {\n return Effect.fail(\n new SandboxInputError({\n cause: 'invalid_cwd',\n message: 'cwd must be workspace-relative'\n })\n )\n }\n\n const parts: Array<string> = []\n\n for (const segment of trimmed.split('/')) {\n if (segment.length === 0 || segment === '.') {\n continue\n }\n\n if (segment === '..') {\n const previous = parts.pop()\n if (previous === undefined) {\n return Effect.fail(\n new SandboxInputError({\n cause: 'invalid_cwd',\n message: 'cwd must not escape the workspace'\n })\n )\n }\n continue\n }\n\n parts.push(segment)\n }\n\n return Effect.succeed(parts.length === 0 ? '.' : parts.join('/'))\n}\n\nexport const absoluteSandboxCwd = (workspaceRoot: string, normalizedCwd: string) =>\n normalizedCwd === '.' ? workspaceRoot : `${workspaceRoot}/${normalizedCwd}`\n\nexport const initialSandboxState = (input: {\n readonly name: string\n readonly nowMs: number\n readonly lifecycle: SandboxLifecycle\n}) => {\n switch (input.lifecycle._tag) {\n case 'Disposable':\n return VercelSandboxState.make({\n name: input.name,\n createdAtMs: input.nowMs,\n lastUsedAtMs: input.nowMs,\n expiresAtMs: input.nowMs + input.lifecycle.idleTtlMs,\n maxExpiresAtMs: input.nowMs + input.lifecycle.maxLifetimeMs\n })\n case 'Persistent':\n return VercelSandboxState.make({\n name: input.name,\n createdAtMs: input.nowMs,\n lastUsedAtMs: input.nowMs,\n expiresAtMs: input.nowMs + input.lifecycle.idleTtlMs,\n maxExpiresAtMs: Number.MAX_SAFE_INTEGER\n })\n }\n}\n\nexport const touchSandboxState = (input: {\n readonly state: SandboxState\n readonly nowMs: number\n readonly lifecycle: SandboxLifecycle\n}) => {\n switch (input.lifecycle._tag) {\n case 'Disposable':\n return VercelSandboxState.make({\n ...input.state,\n lastUsedAtMs: input.nowMs,\n expiresAtMs: Math.min(input.nowMs + input.lifecycle.idleTtlMs, input.state.maxExpiresAtMs)\n })\n case 'Persistent':\n return VercelSandboxState.make({\n ...input.state,\n lastUsedAtMs: input.nowMs,\n expiresAtMs: input.nowMs + input.lifecycle.idleTtlMs\n })\n }\n}\n\nexport const sandboxTimeoutExtendDeltaMs = (input: {\n readonly before: SandboxState\n readonly after: SandboxState\n}) => Math.max(0, input.after.expiresAtMs - input.before.expiresAtMs)\n\nexport const sandboxStateDecision = (input: {\n readonly state: Option.Option<SandboxState>\n readonly name: string\n readonly nowMs: number\n readonly lifecycle: SandboxLifecycle\n}): SandboxStateDecision => {\n if (Option.isNone(input.state)) {\n return { _tag: 'Create', workspaceReset: false }\n }\n\n const state = input.state.value\n\n if (state.name !== input.name) {\n return { _tag: 'Create', workspaceReset: true, reason: 'name_mismatch' }\n }\n\n if (input.lifecycle._tag === 'Persistent') {\n return { _tag: 'UseExisting', state }\n }\n\n if (input.nowMs >= state.maxExpiresAtMs) {\n return { _tag: 'Create', workspaceReset: true, reason: 'max_expired' }\n }\n\n if (input.nowMs >= state.expiresAtMs) {\n return { _tag: 'Create', workspaceReset: true, reason: 'idle_expired' }\n }\n\n return { _tag: 'UseExisting', state }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecycle.mjs","names":[],"sources":["../src/lifecycle.ts"],"sourcesContent":["import { Effect, Match, Option, Predicate } from 'effect'\nimport * as Schema from 'effect/Schema'\nimport { SandboxInputError } from './errors.ts'\nimport {\n DisposableSandboxLifecycle,\n EmptySandboxInitialSource,\n type SandboxInitialSource,\n type SandboxLifecycle,\n type SandboxState,\n VercelSandboxState\n} from './model.ts'\n\nexport const defaultSandboxIdleTtlMs = 30 * 60_000\n\nexport const defaultSandboxMaxLifetimeMs = 45 * 60_000\n\nexport const defaultSandboxCommandTimeoutMs = 120_000\n\nexport const maxSandboxCommandTimeoutMs = 600_000\n\nexport const backgroundSandboxProbeMs = 2_000\n\nexport const sandboxToolOutputLimit = 50_000\n\nexport const defaultSandboxPorts: ReadonlyArray<number> = [3000, 5173, 4321, 8000]\n\nexport const defaultSandboxWorkspaceRoot = '/vercel/sandbox'\n\nexport const defaultSandboxLifecycle = DisposableSandboxLifecycle.make({\n idleTtlMs: defaultSandboxIdleTtlMs,\n maxLifetimeMs: defaultSandboxMaxLifetimeMs\n})\n\nexport const defaultSandboxInitialSource = EmptySandboxInitialSource.make({})\n\nexport type SandboxRecreateReason = 'idle_expired' | 'max_expired' | 'name_mismatch'\n\nconst SandboxUseExistingDecision = Schema.TaggedStruct('UseExisting', {\n state: Schema.Unknown\n})\n\nconst SandboxCreateDecision = Schema.TaggedStruct('Create', {\n workspaceReset: Schema.Boolean,\n reason: Schema.optionalKey(Schema.Literals(['idle_expired', 'max_expired', 'name_mismatch']))\n})\n\nexport type SandboxStateDecision =\n | {\n readonly _tag: 'UseExisting'\n readonly state: SandboxState\n }\n | typeof SandboxCreateDecision.Type\n\nconst existingSandboxStateDecision = (state: SandboxState): SandboxStateDecision => ({\n ...SandboxUseExistingDecision.make({ state }),\n state\n})\n\nconst positiveOr = (value: number | undefined, fallback: number) =>\n value === undefined || !Number.isFinite(value) || value <= 0 ? fallback : Math.floor(value)\n\nexport const sandboxLifecycleOrDefault = (lifecycle?: SandboxLifecycle): SandboxLifecycle =>\n lifecycle ?? defaultSandboxLifecycle\n\nexport const sandboxSourceOrDefault = (source?: SandboxInitialSource): SandboxInitialSource =>\n source ?? defaultSandboxInitialSource\n\nexport const sandboxCommandTimeoutMs = (timeoutMs?: number) =>\n Math.min(maxSandboxCommandTimeoutMs, positiveOr(timeoutMs, defaultSandboxCommandTimeoutMs))\n\nexport const validateSandboxCommand = (command: string) => {\n if (command.trim().length === 0) {\n return Effect.fail(\n new SandboxInputError({\n cause: 'empty_command',\n message: 'Sandbox command must not be empty'\n })\n )\n }\n\n return Effect.succeed(command)\n}\n\nexport const normalizeWorkspaceCwd = (\n cwd?: string | null\n): Effect.Effect<string, SandboxInputError> => {\n if (cwd === undefined || cwd === null || cwd.trim().length === 0) {\n return Effect.succeed('.')\n }\n\n const trimmed = cwd.trim()\n\n if (trimmed.startsWith('/') || trimmed.includes('\\0')) {\n return Effect.fail(\n new SandboxInputError({\n cause: 'invalid_cwd',\n message: 'cwd must be workspace-relative'\n })\n )\n }\n\n const parts: Array<string> = []\n\n for (const segment of trimmed.split('/')) {\n if (segment.length === 0 || segment === '.') {\n continue\n }\n\n if (segment === '..') {\n const previous = parts.pop()\n\n if (previous === undefined) {\n return Effect.fail(\n new SandboxInputError({\n cause: 'invalid_cwd',\n message: 'cwd must not escape the workspace'\n })\n )\n }\n\n continue\n }\n\n parts.push(segment)\n }\n\n return Effect.succeed(parts.length === 0 ? '.' : parts.join('/'))\n}\n\nexport const absoluteSandboxCwd = (workspaceRoot: string, normalizedCwd: string) =>\n normalizedCwd === '.' ? workspaceRoot : `${workspaceRoot}/${normalizedCwd}`\n\nexport const initialSandboxState = (input: {\n readonly name: string\n readonly nowMs: number\n readonly lifecycle: SandboxLifecycle\n}) =>\n Match.value(input.lifecycle).pipe(\n Match.withReturnType<SandboxState>(),\n Match.tag('Disposable', lifecycle =>\n VercelSandboxState.make({\n name: input.name,\n createdAtMs: input.nowMs,\n lastUsedAtMs: input.nowMs,\n expiresAtMs: input.nowMs + lifecycle.idleTtlMs,\n maxExpiresAtMs: input.nowMs + lifecycle.maxLifetimeMs\n })\n ),\n Match.tag('Persistent', lifecycle =>\n VercelSandboxState.make({\n name: input.name,\n createdAtMs: input.nowMs,\n lastUsedAtMs: input.nowMs,\n expiresAtMs: input.nowMs + lifecycle.idleTtlMs,\n maxExpiresAtMs: Number.MAX_SAFE_INTEGER\n })\n ),\n Match.exhaustive\n )\n\nexport const touchSandboxState = (input: {\n readonly state: SandboxState\n readonly nowMs: number\n readonly lifecycle: SandboxLifecycle\n}) =>\n Match.value(input.lifecycle).pipe(\n Match.withReturnType<SandboxState>(),\n Match.tag('Disposable', lifecycle =>\n VercelSandboxState.make({\n ...input.state,\n lastUsedAtMs: input.nowMs,\n expiresAtMs: Math.min(input.nowMs + lifecycle.idleTtlMs, input.state.maxExpiresAtMs)\n })\n ),\n Match.tag('Persistent', lifecycle =>\n VercelSandboxState.make({\n ...input.state,\n lastUsedAtMs: input.nowMs,\n expiresAtMs: input.nowMs + lifecycle.idleTtlMs\n })\n ),\n Match.exhaustive\n )\n\nexport const sandboxTimeoutExtendDeltaMs = (input: {\n readonly before: SandboxState\n readonly after: SandboxState\n}) => Math.max(0, input.after.expiresAtMs - input.before.expiresAtMs)\n\nexport const sandboxStateDecision = (input: {\n readonly state: Option.Option<SandboxState>\n readonly name: string\n readonly nowMs: number\n readonly lifecycle: SandboxLifecycle\n}): SandboxStateDecision => {\n if (Option.isNone(input.state)) {\n return SandboxCreateDecision.make({ workspaceReset: false })\n }\n\n const state = input.state.value\n\n if (state.name !== input.name) {\n return SandboxCreateDecision.make({ workspaceReset: true, reason: 'name_mismatch' })\n }\n\n if (Predicate.isTagged(input.lifecycle, 'Persistent')) {\n return existingSandboxStateDecision(state)\n }\n\n if (input.nowMs >= state.maxExpiresAtMs) {\n return SandboxCreateDecision.make({ workspaceReset: true, reason: 'max_expired' })\n }\n\n if (input.nowMs >= state.expiresAtMs) {\n return SandboxCreateDecision.make({ workspaceReset: true, reason: 'idle_expired' })\n }\n\n return existingSandboxStateDecision(state)\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.mts","names":[],"sources":["../src/model.ts"],"mappings":";;;cAAuC,wBAAA;;;;;;;cAQ1B,mBAAA,SAA4B,wBAMvC;AAAA,cAAG,sBAAA;;;;cAEQ,iBAAA,SAA0B,sBAGrC;AAAA,cAAG,uBAAA;;;;;;;cAEQ,kBAAA,SAA2B,uBAMtC;AAAA,cAEW,YAAA,EAAY,MAAA,CAAA,KAAA,kBAAA,kBAAA;AAAA,KACb,YAAA,UAAsB,YAAA,CAAa,IAAI;AAAA,cAAA,yBAAA;;;;;;;;;;;cAEtC,oBAAA,SAA6B,yBAYxC;AAAA,cAAG,+BAAA;;;;cAEQ,0BAAA,SAAmC,+BAM/C;AAAA,cAAG,6BAAA;;;;;cAES,wBAAA,SAAiC,6BAM5C;AAAA,cAAG,+BAAA;;;;;cAEQ,0BAAA,SAAmC,+BAO/C;AAAA,cAEY,gBAAA,EAAgB,MAAA,CAAA,KAAA,kBAAA,0BAAA,SAAA,0BAAA;AAAA,KAIjB,gBAAA,UAA0B,gBAAA,CAAiB,IAAI;AAAA,cAAA,8BAAA;cAE9C,yBAAA,SAAkC,8BAG9C;AAAA,cAAG,iCAAA;;;cAES,4BAAA,SAAqC,iCAKjD;AAAA,cAAG,wBAAA;;;;cAES,mBAAA,SAA4B,wBAGvC;AAAA,cAAG,4BAAA;;;;;;cAEQ,uBAAA,SAAgC,4BAK3C;AAAA,cAAG,gCAAA;;;cAEQ,2BAAA,SAAoC,gCAKhD;AAAA,cAEY,oBAAA,EAAoB,MAAA,CAAA,KAAA,kBAAA,yBAAA,SAAA,4BAAA,SAAA,uBAAA,SAAA,2BAAA;AAAA,KAMrB,oBAAA,UAA8B,oBAAA,CAAqB,IAAI;AAAA,cAAA,qBAAA;;;cAEtD,gBAAA,SAAyB,qBAEpC"}
1
+ {"version":3,"file":"model.d.mts","names":[],"sources":["../src/model.ts"],"mappings":";;;cAAuC,wBAAA;;;;;;;cAY1B,mBAAA,SAA4B,wBAMvC;AAAA,cAAG,sBAAA;;;;cAEQ,iBAAA,SAA0B,sBAGrC;AAAA,cAAG,uBAAA;;;;;;;cAEQ,kBAAA,SAA2B,uBAMtC;AAAA,cAEW,YAAA,EAAY,MAAA,CAAA,KAAA,kBAAA,kBAAA;AAAA,KAEb,YAAA,UAAsB,YAAA,CAAa,IAAI;AAAA,cAAA,yBAAA;;;;;;;;;;;cAEtC,oBAAA,SAA6B,yBAYxC;AAAA,cAAG,+BAAA;;;;cAEQ,0BAAA,SAAmC,+BAM/C;AAAA,cAAG,6BAAA;;;;;cAES,wBAAA,SAAiC,6BAM5C;AAAA,cAAG,+BAAA;;;;;cAEQ,0BAAA,SAAmC,+BAO/C;AAAA,cAEY,gBAAA,EAAgB,MAAA,CAAA,KAAA,kBAAA,0BAAA,SAAA,0BAAA;AAAA,KAKjB,gBAAA,UAA0B,gBAAA,CAAiB,IAAI;AAAA,cAAA,8BAAA;cAE9C,yBAAA,SAAkC,8BAG9C;AAAA,cAAG,iCAAA;;;cAES,4BAAA,SAAqC,iCAKjD;AAAA,cAAG,wBAAA;;;;cAES,mBAAA,SAA4B,wBAGvC;AAAA,cAAG,4BAAA;;;;;;cAEQ,uBAAA,SAAgC,4BAK3C;AAAA,cAAG,gCAAA;;;cAEQ,2BAAA,SAAoC,gCAKhD;AAAA,cAEY,oBAAA,EAAoB,MAAA,CAAA,KAAA,kBAAA,yBAAA,SAAA,4BAAA,SAAA,uBAAA,SAAA,2BAAA;AAAA,KAOrB,oBAAA,UAA8B,oBAAA,CAAqB,IAAI;AAAA,cAAA,qBAAA;;;cAEtD,gBAAA,SAAyB,qBAEpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"model.mjs","names":[],"sources":["../src/model.ts"],"sourcesContent":["import * as Schema from 'effect/Schema'\n\nconst NonEmptyTrimmedString = Schema.Trimmed.pipe(Schema.check(Schema.isNonEmpty()))\nconst NonNegativeInteger = Schema.Int.pipe(Schema.check(Schema.isGreaterThanOrEqualTo(0)))\nconst PositiveInteger = Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0)))\nconst PositiveNumber = Schema.Number.pipe(Schema.check(Schema.isGreaterThan(0)))\nconst SnapshotRetentionCount = PositiveInteger.pipe(Schema.check(Schema.isLessThanOrEqualTo(10)))\n\nexport class SandboxCommandInput extends Schema.Class<SandboxCommandInput>('SandboxCommandInput')({\n command: Schema.String,\n cwd: Schema.optional(Schema.String),\n stdin: Schema.optional(Schema.String),\n timeoutMs: Schema.optional(PositiveInteger),\n background: Schema.optional(Schema.Boolean)\n}) {}\n\nexport class SandboxPreviewUrl extends Schema.Class<SandboxPreviewUrl>('SandboxPreviewUrl')({\n port: PositiveInteger,\n url: NonEmptyTrimmedString\n}) {}\n\nexport class VercelSandboxState extends Schema.TaggedClass<VercelSandboxState>()('Vercel', {\n name: NonEmptyTrimmedString,\n createdAtMs: NonNegativeInteger,\n lastUsedAtMs: NonNegativeInteger,\n expiresAtMs: NonNegativeInteger,\n maxExpiresAtMs: NonNegativeInteger\n}) {}\n\nexport const SandboxState = Schema.Union([VercelSandboxState])\nexport type SandboxState = typeof SandboxState.Type\n\nexport class SandboxCommandResult extends Schema.Class<SandboxCommandResult>(\n 'SandboxCommandResult'\n)({\n exitCode: Schema.NullOr(Schema.Int),\n stdout: Schema.String,\n stderr: Schema.String,\n durationMs: NonNegativeInteger,\n timedOut: Schema.Boolean,\n workspaceReset: Schema.Boolean,\n backgroundId: Schema.optional(NonEmptyTrimmedString),\n previewUrls: Schema.Array(SandboxPreviewUrl),\n state: SandboxState\n}) {}\n\nexport class DisposableSandboxLifecycle extends Schema.TaggedClass<DisposableSandboxLifecycle>()(\n 'Disposable',\n {\n idleTtlMs: PositiveInteger,\n maxLifetimeMs: PositiveInteger\n }\n) {}\n\nexport class SandboxSnapshotRetention extends Schema.Class<SandboxSnapshotRetention>(\n 'SandboxSnapshotRetention'\n)({\n count: SnapshotRetentionCount,\n expirationMs: Schema.optional(NonNegativeInteger),\n deleteEvicted: Schema.optional(Schema.Boolean)\n}) {}\n\nexport class PersistentSandboxLifecycle extends Schema.TaggedClass<PersistentSandboxLifecycle>()(\n 'Persistent',\n {\n idleTtlMs: PositiveInteger,\n snapshotExpirationMs: Schema.optional(NonNegativeInteger),\n keepLastSnapshots: Schema.optional(SandboxSnapshotRetention)\n }\n) {}\n\nexport const SandboxLifecycle = Schema.Union([\n DisposableSandboxLifecycle,\n PersistentSandboxLifecycle\n])\nexport type SandboxLifecycle = typeof SandboxLifecycle.Type\n\nexport class EmptySandboxInitialSource extends Schema.TaggedClass<EmptySandboxInitialSource>()(\n 'Empty',\n {}\n) {}\n\nexport class SnapshotSandboxInitialSource extends Schema.TaggedClass<SnapshotSandboxInitialSource>()(\n 'Snapshot',\n {\n snapshotId: NonEmptyTrimmedString\n }\n) {}\n\nexport class GitSandboxBasicAuth extends Schema.Class<GitSandboxBasicAuth>('GitSandboxBasicAuth')({\n username: NonEmptyTrimmedString,\n password: NonEmptyTrimmedString\n}) {}\n\nexport class GitSandboxInitialSource extends Schema.TaggedClass<GitSandboxInitialSource>()('Git', {\n url: NonEmptyTrimmedString,\n auth: Schema.optional(GitSandboxBasicAuth),\n depth: Schema.optional(PositiveInteger),\n revision: Schema.optional(NonEmptyTrimmedString)\n}) {}\n\nexport class TarballSandboxInitialSource extends Schema.TaggedClass<TarballSandboxInitialSource>()(\n 'Tarball',\n {\n url: NonEmptyTrimmedString\n }\n) {}\n\nexport const SandboxInitialSource = Schema.Union([\n EmptySandboxInitialSource,\n SnapshotSandboxInitialSource,\n GitSandboxInitialSource,\n TarballSandboxInitialSource\n])\nexport type SandboxInitialSource = typeof SandboxInitialSource.Type\n\nexport class SandboxResources extends Schema.Class<SandboxResources>('SandboxResources')({\n vcpus: PositiveNumber\n}) {}\n"],"mappings":"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"}
1
+ {"version":3,"file":"model.mjs","names":[],"sources":["../src/model.ts"],"sourcesContent":["import * as Schema from 'effect/Schema'\n\nconst NonEmptyTrimmedString = Schema.Trimmed.pipe(Schema.check(Schema.isNonEmpty()))\n\nconst NonNegativeInteger = Schema.Int.pipe(Schema.check(Schema.isGreaterThanOrEqualTo(0)))\n\nconst PositiveInteger = Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0)))\n\nconst PositiveNumber = Schema.Number.pipe(Schema.check(Schema.isGreaterThan(0)))\n\nconst SnapshotRetentionCount = PositiveInteger.pipe(Schema.check(Schema.isLessThanOrEqualTo(10)))\n\nexport class SandboxCommandInput extends Schema.Class<SandboxCommandInput>('SandboxCommandInput')({\n command: Schema.String,\n cwd: Schema.optional(Schema.String),\n stdin: Schema.optional(Schema.String),\n timeoutMs: Schema.optional(PositiveInteger),\n background: Schema.optional(Schema.Boolean)\n}) {}\n\nexport class SandboxPreviewUrl extends Schema.Class<SandboxPreviewUrl>('SandboxPreviewUrl')({\n port: PositiveInteger,\n url: NonEmptyTrimmedString\n}) {}\n\nexport class VercelSandboxState extends Schema.TaggedClass<VercelSandboxState>()('Vercel', {\n name: NonEmptyTrimmedString,\n createdAtMs: NonNegativeInteger,\n lastUsedAtMs: NonNegativeInteger,\n expiresAtMs: NonNegativeInteger,\n maxExpiresAtMs: NonNegativeInteger\n}) {}\n\nexport const SandboxState = Schema.Union([VercelSandboxState])\n\nexport type SandboxState = typeof SandboxState.Type\n\nexport class SandboxCommandResult extends Schema.Class<SandboxCommandResult>(\n 'SandboxCommandResult'\n)({\n exitCode: Schema.NullOr(Schema.Int),\n stdout: Schema.String,\n stderr: Schema.String,\n durationMs: NonNegativeInteger,\n timedOut: Schema.Boolean,\n workspaceReset: Schema.Boolean,\n backgroundId: Schema.optional(NonEmptyTrimmedString),\n previewUrls: Schema.Array(SandboxPreviewUrl),\n state: SandboxState\n}) {}\n\nexport class DisposableSandboxLifecycle extends Schema.TaggedClass<DisposableSandboxLifecycle>()(\n 'Disposable',\n {\n idleTtlMs: PositiveInteger,\n maxLifetimeMs: PositiveInteger\n }\n) {}\n\nexport class SandboxSnapshotRetention extends Schema.Class<SandboxSnapshotRetention>(\n 'SandboxSnapshotRetention'\n)({\n count: SnapshotRetentionCount,\n expirationMs: Schema.optional(NonNegativeInteger),\n deleteEvicted: Schema.optional(Schema.Boolean)\n}) {}\n\nexport class PersistentSandboxLifecycle extends Schema.TaggedClass<PersistentSandboxLifecycle>()(\n 'Persistent',\n {\n idleTtlMs: PositiveInteger,\n snapshotExpirationMs: Schema.optional(NonNegativeInteger),\n keepLastSnapshots: Schema.optional(SandboxSnapshotRetention)\n }\n) {}\n\nexport const SandboxLifecycle = Schema.Union([\n DisposableSandboxLifecycle,\n PersistentSandboxLifecycle\n])\n\nexport type SandboxLifecycle = typeof SandboxLifecycle.Type\n\nexport class EmptySandboxInitialSource extends Schema.TaggedClass<EmptySandboxInitialSource>()(\n 'Empty',\n {}\n) {}\n\nexport class SnapshotSandboxInitialSource extends Schema.TaggedClass<SnapshotSandboxInitialSource>()(\n 'Snapshot',\n {\n snapshotId: NonEmptyTrimmedString\n }\n) {}\n\nexport class GitSandboxBasicAuth extends Schema.Class<GitSandboxBasicAuth>('GitSandboxBasicAuth')({\n username: NonEmptyTrimmedString,\n password: NonEmptyTrimmedString\n}) {}\n\nexport class GitSandboxInitialSource extends Schema.TaggedClass<GitSandboxInitialSource>()('Git', {\n url: NonEmptyTrimmedString,\n auth: Schema.optional(GitSandboxBasicAuth),\n depth: Schema.optional(PositiveInteger),\n revision: Schema.optional(NonEmptyTrimmedString)\n}) {}\n\nexport class TarballSandboxInitialSource extends Schema.TaggedClass<TarballSandboxInitialSource>()(\n 'Tarball',\n {\n url: NonEmptyTrimmedString\n }\n) {}\n\nexport const SandboxInitialSource = Schema.Union([\n EmptySandboxInitialSource,\n SnapshotSandboxInitialSource,\n GitSandboxInitialSource,\n TarballSandboxInitialSource\n])\n\nexport type SandboxInitialSource = typeof SandboxInitialSource.Type\n\nexport class SandboxResources extends Schema.Class<SandboxResources>('SandboxResources')({\n vcpus: PositiveNumber\n}) {}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"name.d.mts","names":[],"sources":["../src/name.ts"],"mappings":";cAqBa,qBAAA,GAAyB,gBAAwB"}
1
+ {"version":3,"file":"name.d.mts","names":[],"sources":["../src/name.ts"],"mappings":";cAsBa,qBAAA,GAAyB,gBAAwB"}
package/dist/name.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"name.mjs","names":[],"sources":["../src/name.ts"],"sourcesContent":["const fnvOffsetBasis32 = 0x811c9dc5\nconst fnvPrime32 = 0x01000193\n\nconst fnv1a32 = (value: string, seed: number) => {\n let hash = seed\n\n for (const character of value) {\n hash ^= character.codePointAt(0) ?? 0\n hash = Math.imul(hash, fnvPrime32)\n }\n\n return (hash >>> 0).toString(36).padStart(7, '0')\n}\n\nconst stableHash = (value: string) => {\n const first = fnv1a32(value, fnvOffsetBasis32)\n const second = fnv1a32([...value].reverse().join(''), fnvOffsetBasis32 ^ 0x9e3779b9)\n\n return `${first}${second}`\n}\n\nexport const makeVercelSandboxName = (sandboxSessionId: string) =>\n `sandbox-${stableHash(sandboxSessionId)}`\n"],"mappings":";AAAA,MAAM,mBAAmB;AACzB,MAAM,aAAa;AAEnB,MAAM,WAAW,OAAe,SAAiB;CAC/C,IAAI,OAAO;CAEX,KAAK,MAAM,aAAa,OAAO;EAC7B,QAAQ,UAAU,YAAY,CAAC,KAAK;EACpC,OAAO,KAAK,KAAK,MAAM,UAAU;CACnC;CAEA,QAAQ,SAAS,GAAG,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAClD;AAEA,MAAM,cAAc,UAAkB;CAIpC,OAAO,GAHO,QAAQ,OAAO,gBAGf,IAFC,QAAQ,CAAC,GAAG,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,mBAAmB,UAElD;AACzB;AAEA,MAAa,yBAAyB,qBACpC,WAAW,WAAW,gBAAgB"}
1
+ {"version":3,"file":"name.mjs","names":[],"sources":["../src/name.ts"],"sourcesContent":["const fnvOffsetBasis32 = 0x811c9dc5\n\nconst fnvPrime32 = 0x01000193\n\nconst fnv1a32 = (value: string, seed: number) => {\n let hash = seed\n\n for (const character of value) {\n hash ^= character.codePointAt(0) ?? 0\n hash = Math.imul(hash, fnvPrime32)\n }\n\n return (hash >>> 0).toString(36).padStart(7, '0')\n}\n\nconst stableHash = (value: string) => {\n const first = fnv1a32(value, fnvOffsetBasis32)\n const second = fnv1a32([...value].reverse().join(''), fnvOffsetBasis32 ^ 0x9e3779b9)\n\n return `${first}${second}`\n}\n\nexport const makeVercelSandboxName = (sandboxSessionId: string) =>\n `sandbox-${stableHash(sandboxSessionId)}`\n"],"mappings":";AAAA,MAAM,mBAAmB;AAEzB,MAAM,aAAa;AAEnB,MAAM,WAAW,OAAe,SAAiB;CAC/C,IAAI,OAAO;CAEX,KAAK,MAAM,aAAa,OAAO;EAC7B,QAAQ,UAAU,YAAY,CAAC,KAAK;EACpC,OAAO,KAAK,KAAK,MAAM,UAAU;CACnC;CAEA,QAAQ,SAAS,GAAG,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAClD;AAEA,MAAM,cAAc,UAAkB;CAIpC,OAAO,GAHO,QAAQ,OAAO,gBAGf,IAFC,QAAQ,CAAC,GAAG,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,mBAAmB,UAElD;AACzB;AAEA,MAAa,yBAAyB,qBACpC,WAAW,WAAW,gBAAgB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/testing/index.ts"],"sourcesContent":["import { Effect, Layer, Option, Ref } from 'effect'\nimport type { SandboxCommandInput, SandboxCommandResult, SandboxState } from '../model.ts'\nimport { Sandbox } from '../service.ts'\nimport { SandboxStateStore } from '../state-store.ts'\nimport type { SandboxError } from '../errors.ts'\n\nexport type FakeSandboxRun = (\n input: SandboxCommandInput\n) => Effect.Effect<SandboxCommandResult, SandboxError>\n\nexport type FakeSandboxOptions = {\n readonly run: FakeSandboxRun\n readonly initialState?: SandboxState\n}\n\nexport const makeFakeSandboxLayer = (options: FakeSandboxOptions) =>\n Layer.effect(\n Sandbox,\n Ref.make(Option.fromNullishOr(options.initialState)).pipe(\n Effect.map(stateRef =>\n Sandbox.of({\n run: input =>\n options\n .run(input)\n .pipe(Effect.tap(result => Ref.set(stateRef, Option.some(result.state)))),\n currentState: Ref.get(stateRef),\n delete: Ref.set(stateRef, Option.none())\n })\n )\n )\n )\n\nexport type InMemorySandboxStateStoreEntry = {\n readonly sandboxSessionId: string\n readonly state: SandboxState\n}\n\nexport const makeInMemorySandboxStateStoreLayer = (\n initial: ReadonlyArray<InMemorySandboxStateStoreEntry> = []\n) =>\n Layer.effect(\n SandboxStateStore,\n Effect.gen(function* () {\n const states = yield* Ref.make(\n new Map(initial.map(entry => [entry.sandboxSessionId, entry.state]))\n )\n\n return SandboxStateStore.of({\n load: sandboxSessionId =>\n Ref.get(states).pipe(\n Effect.map(current => Option.fromNullishOr(current.get(sandboxSessionId)))\n ),\n save: input =>\n Ref.update(\n states,\n current => new Map([...current, [input.sandboxSessionId, input.state]])\n ),\n clear: sandboxSessionId =>\n Ref.update(states, current => {\n const next = new Map(current)\n next.delete(sandboxSessionId)\n return next\n })\n })\n })\n )\n"],"mappings":";;;;AAeA,MAAa,wBAAwB,YACnC,MAAM,OACJ,SACA,IAAI,KAAK,OAAO,cAAc,QAAQ,YAAY,CAAC,EAAE,KACnD,OAAO,KAAI,aACT,QAAQ,GAAG;CACT,MAAK,UACH,QACG,IAAI,KAAK,EACT,KAAK,OAAO,KAAI,WAAU,IAAI,IAAI,UAAU,OAAO,KAAK,OAAO,KAAK,CAAC,CAAC,CAAC;CAC5E,cAAc,IAAI,IAAI,QAAQ;CAC9B,QAAQ,IAAI,IAAI,UAAU,OAAO,KAAK,CAAC;AACzC,CAAC,CACH,CACF,CACF;AAOF,MAAa,sCACX,UAAyD,CAAC,MAE1D,MAAM,OACJ,mBACA,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO,IAAI,KACxB,IAAI,IAAI,QAAQ,KAAI,UAAS,CAAC,MAAM,kBAAkB,MAAM,KAAK,CAAC,CAAC,CACrE;CAEA,OAAO,kBAAkB,GAAG;EAC1B,OAAM,qBACJ,IAAI,IAAI,MAAM,EAAE,KACd,OAAO,KAAI,YAAW,OAAO,cAAc,QAAQ,IAAI,gBAAgB,CAAC,CAAC,CAC3E;EACF,OAAM,UACJ,IAAI,OACF,SACA,YAAW,IAAI,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,kBAAkB,MAAM,KAAK,CAAC,CAAC,CACxE;EACF,QAAO,qBACL,IAAI,OAAO,SAAQ,YAAW;GAC5B,MAAM,OAAO,IAAI,IAAI,OAAO;GAC5B,KAAK,OAAO,gBAAgB;GAC5B,OAAO;EACT,CAAC;CACL,CAAC;AACH,CAAC,CACH"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/testing/index.ts"],"sourcesContent":["import { Effect, Layer, Option, Ref } from 'effect'\nimport type { SandboxCommandInput, SandboxCommandResult, SandboxState } from '../model.ts'\nimport { Sandbox } from '../service.ts'\nimport { SandboxStateStore } from '../state-store.ts'\nimport type { SandboxError } from '../errors.ts'\n\nexport type FakeSandboxRun = (\n input: SandboxCommandInput\n) => Effect.Effect<SandboxCommandResult, SandboxError>\n\nexport type FakeSandboxOptions = {\n readonly run: FakeSandboxRun\n readonly initialState?: SandboxState\n}\n\nexport const makeFakeSandboxLayer = (options: FakeSandboxOptions) =>\n Layer.effect(\n Sandbox,\n Ref.make(Option.fromNullishOr(options.initialState)).pipe(\n Effect.map(stateRef =>\n Sandbox.of({\n run: input =>\n options\n .run(input)\n .pipe(Effect.tap(result => Ref.set(stateRef, Option.some(result.state)))),\n currentState: Ref.get(stateRef),\n delete: Ref.set(stateRef, Option.none())\n })\n )\n )\n )\n\nexport type InMemorySandboxStateStoreEntry = {\n readonly sandboxSessionId: string\n readonly state: SandboxState\n}\n\nexport const makeInMemorySandboxStateStoreLayer = (\n initial: ReadonlyArray<InMemorySandboxStateStoreEntry> = []\n) =>\n Layer.effect(\n SandboxStateStore,\n Effect.gen(function* () {\n const states = yield* Ref.make(\n new Map(initial.map(entry => [entry.sandboxSessionId, entry.state]))\n )\n\n return SandboxStateStore.of({\n load: sandboxSessionId =>\n Ref.get(states).pipe(\n Effect.map(current => Option.fromNullishOr(current.get(sandboxSessionId)))\n ),\n save: input =>\n Ref.update(\n states,\n current => new Map([...current, [input.sandboxSessionId, input.state]])\n ),\n clear: sandboxSessionId =>\n Ref.update(states, current => {\n const next = new Map(current)\n next.delete(sandboxSessionId)\n\n return next\n })\n })\n })\n )\n"],"mappings":";;;;AAeA,MAAa,wBAAwB,YACnC,MAAM,OACJ,SACA,IAAI,KAAK,OAAO,cAAc,QAAQ,YAAY,CAAC,EAAE,KACnD,OAAO,KAAI,aACT,QAAQ,GAAG;CACT,MAAK,UACH,QACG,IAAI,KAAK,EACT,KAAK,OAAO,KAAI,WAAU,IAAI,IAAI,UAAU,OAAO,KAAK,OAAO,KAAK,CAAC,CAAC,CAAC;CAC5E,cAAc,IAAI,IAAI,QAAQ;CAC9B,QAAQ,IAAI,IAAI,UAAU,OAAO,KAAK,CAAC;AACzC,CAAC,CACH,CACF,CACF;AAOF,MAAa,sCACX,UAAyD,CAAC,MAE1D,MAAM,OACJ,mBACA,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO,IAAI,KACxB,IAAI,IAAI,QAAQ,KAAI,UAAS,CAAC,MAAM,kBAAkB,MAAM,KAAK,CAAC,CAAC,CACrE;CAEA,OAAO,kBAAkB,GAAG;EAC1B,OAAM,qBACJ,IAAI,IAAI,MAAM,EAAE,KACd,OAAO,KAAI,YAAW,OAAO,cAAc,QAAQ,IAAI,gBAAgB,CAAC,CAAC,CAC3E;EACF,OAAM,UACJ,IAAI,OACF,SACA,YAAW,IAAI,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,kBAAkB,MAAM,KAAK,CAAC,CAAC,CACxE;EACF,QAAO,qBACL,IAAI,OAAO,SAAQ,YAAW;GAC5B,MAAM,OAAO,IAAI,IAAI,OAAO;GAC5B,KAAK,OAAO,gBAAgB;GAE5B,OAAO;EACT,CAAC;CACL,CAAC;AACH,CAAC,CACH"}