@fungi.computer/mycelium 0.0.0-stage → 0.0.1

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.
Files changed (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +303 -2
  3. package/THIRD_PARTY_NOTICES +2 -0
  4. package/dist/access.d.ts +129 -0
  5. package/dist/access.js +166 -0
  6. package/dist/capability-source.d.ts +44 -0
  7. package/dist/capability-source.js +1 -0
  8. package/dist/compiler.d.ts +28 -0
  9. package/dist/compiler.js +221 -0
  10. package/dist/define.d.ts +8 -0
  11. package/dist/define.js +7 -0
  12. package/dist/effect.d.ts +89 -0
  13. package/dist/effect.js +42 -0
  14. package/dist/errors.d.ts +48 -0
  15. package/dist/errors.js +62 -0
  16. package/dist/execute-tool.d.ts +22 -0
  17. package/dist/execute-tool.js +163 -0
  18. package/dist/image-collector.d.ts +47 -0
  19. package/dist/image-collector.js +39 -0
  20. package/dist/index.d.ts +149 -0
  21. package/dist/index.js +22 -0
  22. package/dist/internal/build-identity.d.ts +1 -0
  23. package/dist/internal/build-identity.js +15 -0
  24. package/dist/internal/build-identity.node.d.ts +1 -0
  25. package/dist/internal/build-identity.node.js +42 -0
  26. package/dist/internal/execution-lifecycle.d.ts +44 -0
  27. package/dist/internal/execution-lifecycle.js +328 -0
  28. package/dist/internal/mcp-principal.d.ts +14 -0
  29. package/dist/internal/mcp-principal.js +17 -0
  30. package/dist/mcp-catalog.d.ts +23 -0
  31. package/dist/mcp-catalog.js +110 -0
  32. package/dist/mcp.d.ts +92 -0
  33. package/dist/mcp.js +250 -0
  34. package/dist/operation-schema.d.ts +47 -0
  35. package/dist/operation-schema.js +50 -0
  36. package/dist/promise-facade.d.ts +3 -0
  37. package/dist/promise-facade.js +82 -0
  38. package/dist/registration.d.ts +74 -0
  39. package/dist/registration.js +157 -0
  40. package/dist/remote.d.ts +33 -0
  41. package/dist/remote.js +126 -0
  42. package/dist/runtime.d.ts +51 -0
  43. package/dist/runtime.js +159 -0
  44. package/dist/sandbox-boundary.d.ts +44 -0
  45. package/dist/sandbox-boundary.js +325 -0
  46. package/dist/sandbox-failure-event.d.ts +15 -0
  47. package/dist/sandbox-failure-event.js +34 -0
  48. package/dist/sandbox-failure.d.ts +128 -0
  49. package/dist/sandbox-failure.js +161 -0
  50. package/dist/sandbox-guest.d.ts +34 -0
  51. package/dist/sandbox-guest.js +131 -0
  52. package/dist/sandbox-wire.d.ts +76 -0
  53. package/dist/sandbox-wire.js +190 -0
  54. package/dist/sandbox.d.ts +41 -0
  55. package/dist/sandbox.js +1 -0
  56. package/dist/semaphore-transition.d.ts +7 -0
  57. package/dist/semaphore-transition.js +9 -0
  58. package/dist/source-runtime.d.ts +28 -0
  59. package/dist/source-runtime.js +162 -0
  60. package/dist/testing.d.ts +11 -0
  61. package/dist/testing.js +19 -0
  62. package/dist/workers/index.d.ts +9 -0
  63. package/dist/workers/index.js +90 -0
  64. package/docs/api/README.md +25 -0
  65. package/docs/api/define.md +20 -0
  66. package/docs/api/effect.md +245 -0
  67. package/docs/api/index.md +1081 -0
  68. package/docs/api/mcp.md +239 -0
  69. package/docs/api/remote.md +108 -0
  70. package/docs/api/sandbox-boundary.md +325 -0
  71. package/docs/api/sandbox-failure.md +1133 -0
  72. package/docs/api/sandbox-guest.md +191 -0
  73. package/docs/api/sandbox-wire.md +117 -0
  74. package/docs/api/sandbox.md +81 -0
  75. package/docs/api/semaphore-transition.md +40 -0
  76. package/docs/api/testing.md +72 -0
  77. package/docs/api/workers.md +55 -0
  78. package/package.json +132 -3
@@ -0,0 +1,325 @@
1
+ import { nanoid } from "@fungi.computer/cairn";
2
+ import { ForageError } from "@fungi.computer/forage";
3
+ import * as Result from "effect/Result";
4
+ import * as Schema from "effect/Schema";
5
+ import { z } from "zod";
6
+ import { InvalidOperationInput } from "./errors.js";
7
+ import { SourceInvalid, GuestThrew, DeadlineExceeded, Cancelled, DispatchLost, SandboxCrashed, BadResponse, ResultTooLarge, ResultNotJson, CapabilityFailed, Unknown, referenceSandboxFailure, sandboxFailureMessage, } from "./sandbox-failure.js";
8
+ const ownedFailureSchema = z.union([
9
+ z.instanceof(SourceInvalid),
10
+ z.instanceof(GuestThrew),
11
+ z.instanceof(DeadlineExceeded),
12
+ z.instanceof(Cancelled),
13
+ z.instanceof(DispatchLost),
14
+ z.instanceof(SandboxCrashed),
15
+ z.instanceof(BadResponse),
16
+ z.instanceof(ResultTooLarge),
17
+ z.instanceof(ResultNotJson),
18
+ z.instanceof(CapabilityFailed),
19
+ z.instanceof(Unknown),
20
+ ]);
21
+ /** The one interpretation boundary for foreign in-process values and rejections. */
22
+ const foreignValueSchema = z
23
+ .unknown()
24
+ .pipe(z.union([
25
+ z
26
+ .instanceof(Error)
27
+ .transform((value) => ({ kind: "error", value })),
28
+ z.null().transform((value) => ({ kind: "null", value })),
29
+ z
30
+ .undefined()
31
+ .transform((value) => ({ kind: "undefined", value })),
32
+ z.string().transform((value) => ({ kind: "string", value })),
33
+ z.boolean().transform((value) => ({ kind: "boolean", value })),
34
+ z
35
+ .union([z.number(), z.nan(), z.literal(Infinity), z.literal(-Infinity)])
36
+ .transform((value) => ({ kind: "number", value })),
37
+ z.bigint().transform((value) => ({ kind: "bigint", value })),
38
+ z.symbol().transform((value) => ({ kind: "symbol", value })),
39
+ z
40
+ .instanceof(Function)
41
+ .transform((value) => ({ kind: "function", value })),
42
+ z
43
+ .array(z.unknown())
44
+ .transform((value) => ({ kind: "array", value })),
45
+ z
46
+ .union([z.instanceof(Object), z.record(z.string(), z.unknown())])
47
+ .transform((value) => ({ kind: "object", value })),
48
+ z.unknown().transform(() => ({ kind: "opaque" })),
49
+ ]));
50
+ /** Admit only errors constructed by the sandbox owner, using the maintained decoder. */
51
+ export function isSandboxFailure(cause) {
52
+ return ownedFailureSchema.safeParse(cause).success;
53
+ }
54
+ /** Foreign throws stay private until an owner admits a diagnostic. */
55
+ export function sandboxFailure(cause) {
56
+ const owned = ownedFailureSchema.safeParse(cause);
57
+ return owned.success ? owned.data : new Unknown({ rawCause: cause });
58
+ }
59
+ /** Label a rejected JSON value without caller-owned reflection. */
60
+ export function sandboxValueKind(value) {
61
+ const decoded = foreignValueSchema.parse(value);
62
+ switch (decoded.kind) {
63
+ case "error":
64
+ case "array":
65
+ case "null":
66
+ return "object";
67
+ default:
68
+ return decoded.kind;
69
+ }
70
+ }
71
+ const bindingInputSchema = z.json().optional();
72
+ /** Decode the RPC argument before any capability callback observes it. */
73
+ export function sandboxBindingInput(value) {
74
+ return bindingInputSchema.parse(value);
75
+ }
76
+ /** Full operator representation, including nested errors, aggregates and cycles. */
77
+ export function sandboxOperatorValue(cause) {
78
+ return operatorValue(cause, new Set());
79
+ }
80
+ function operatorValue(cause, seen) {
81
+ const decoded = foreignValueSchema.parse(cause);
82
+ switch (decoded.kind) {
83
+ case "null":
84
+ case "undefined":
85
+ return null;
86
+ case "string":
87
+ case "boolean":
88
+ return decoded.value;
89
+ case "number":
90
+ return Number.isFinite(decoded.value)
91
+ ? decoded.value
92
+ : String(decoded.value);
93
+ case "bigint":
94
+ case "symbol":
95
+ return String(decoded.value);
96
+ case "function":
97
+ return { kind: "function", name: decoded.value.name };
98
+ case "opaque":
99
+ return { kind: "opaque" };
100
+ case "error":
101
+ case "array":
102
+ case "object": {
103
+ const value = decoded.value;
104
+ // Zod copies arrays and records. Track their original input identities,
105
+ // retaining references only for this traversal's active ancestors.
106
+ if (seen.has(cause))
107
+ return { kind: "circular_reference" };
108
+ seen.add(cause);
109
+ try {
110
+ if (decoded.kind === "array")
111
+ return decoded.value.map((item) => operatorValue(item, seen));
112
+ const fields = Object.fromEntries(Object.entries(value).map(([key, item]) => [
113
+ key,
114
+ operatorValue(item, seen),
115
+ ]));
116
+ if (decoded.kind === "error") {
117
+ const error = decoded.value;
118
+ fields.name = error.name;
119
+ fields.message = error.message;
120
+ if (error.stack !== undefined)
121
+ fields.stack = error.stack;
122
+ if (error.cause !== undefined)
123
+ fields.cause = operatorValue(error.cause, seen);
124
+ if (error instanceof AggregateError)
125
+ fields.errors = operatorValue(error.errors, seen);
126
+ }
127
+ return fields;
128
+ }
129
+ finally {
130
+ seen.delete(cause);
131
+ }
132
+ }
133
+ }
134
+ }
135
+ const missingVariable = z
136
+ .object({
137
+ name: z.literal("ReferenceError"),
138
+ message: z
139
+ .string()
140
+ .regex(/^[\p{ID_Start}_$][\p{ID_Continue}$]* is not defined$/u),
141
+ })
142
+ .transform((value) => ({
143
+ ...value,
144
+ missingVariable: value.message.slice(0, -" is not defined".length),
145
+ }));
146
+ const guestDiagnosticSchema = z
147
+ .union([missingVariable, z.object({ name: z.string(), message: z.string() })])
148
+ .and(z.object({ transportMessage: z.string().max(512).optional() }));
149
+ /** Decode the engine's guest-owned diagnostic once; renderers receive typed fields. */
150
+ export function sandboxGuestFailure(cause, bindings = {}) {
151
+ const diagnostic = guestDiagnosticSchema.parse(cause);
152
+ if ("missingVariable" in diagnostic) {
153
+ for (const [namespace, operations] of Object.entries(bindings))
154
+ for (const operation of Object.keys(operations))
155
+ if (`${namespace}_${operation}` === diagnostic.missingVariable)
156
+ return new GuestThrew({
157
+ name: diagnostic.name,
158
+ message: `${diagnostic.message}. Call the operation as a method: ${namespace}.${operation}(...).`,
159
+ });
160
+ }
161
+ return new GuestThrew(diagnostic);
162
+ }
163
+ const transportEnvelopeSchema = z.strictObject({
164
+ v: z.literal(1),
165
+ kind: z.literal("sandbox_failure"),
166
+ tag: z.enum([
167
+ "SourceInvalid",
168
+ "GuestThrew",
169
+ "DeadlineExceeded",
170
+ "Cancelled",
171
+ "DispatchLost",
172
+ "SandboxCrashed",
173
+ "BadResponse",
174
+ "ResultTooLarge",
175
+ "ResultNotJson",
176
+ "CapabilityFailed",
177
+ "Unknown",
178
+ ]),
179
+ ref: z.string().min(1).max(32),
180
+ message: z.string().max(160),
181
+ });
182
+ const decodeJsonText = Schema.decodeUnknownResult(Schema.fromJsonString(Schema.Unknown));
183
+ const jsonTextSchema = z.string().transform((text, context) => {
184
+ const decoded = decodeJsonText(text);
185
+ if (Result.isFailure(decoded)) {
186
+ context.addIssue({
187
+ code: "custom",
188
+ message: "Invalid sandbox transport JSON",
189
+ });
190
+ return z.NEVER;
191
+ }
192
+ return decoded.success;
193
+ });
194
+ const transportMessageSchema = jsonTextSchema.pipe(transportEnvelopeSchema);
195
+ const returnedOperationFailure = z.strictObject({
196
+ error: transportMessageSchema,
197
+ });
198
+ /** Error.message is the SDK's wire carrier; only this safe, bounded envelope crosses it. */
199
+ export function sandboxTransportMessage(failure, ref) {
200
+ const envelope = transportEnvelopeSchema.parse({
201
+ v: 1,
202
+ kind: "sandbox_failure",
203
+ tag: failure._tag,
204
+ ref,
205
+ message: sandboxFailureMessage(failure, false)
206
+ .replace(/\p{Cc}|\p{Cf}/gu, " ")
207
+ .slice(0, 160),
208
+ });
209
+ return JSON.stringify(envelope);
210
+ }
211
+ /** Recovery uses the decoded identity, never a match against diagnostic text. */
212
+ export function recoverSandboxFailure(failure, failures) {
213
+ if (failure._tag !== "GuestThrew")
214
+ return failure;
215
+ const decoded = transportMessageSchema.safeParse(failure.transportMessage ?? failure.message);
216
+ if (!decoded.success)
217
+ return failure;
218
+ const original = failures.get(decoded.data.ref);
219
+ return original?._tag === decoded.data.tag ? original : failure;
220
+ }
221
+ const executorFailureSchema = z
222
+ .unknown()
223
+ .pipe(z.union([
224
+ z
225
+ .literal("Execution timed out")
226
+ .transform(() => ({ kind: "deadline" })),
227
+ z
228
+ .unknown()
229
+ .transform((rawCause) => ({ kind: "bad_response", rawCause })),
230
+ ]));
231
+ /** Decode Codemode's documented error carrier before adapters choose a failure. */
232
+ export function sandboxExecutorFailure(cause, limitMs, elapsedMs) {
233
+ const decoded = executorFailureSchema.parse(cause);
234
+ return decoded.kind === "deadline"
235
+ ? new DeadlineExceeded({ limitMs, elapsedMs })
236
+ : new BadResponse({
237
+ reason: "executor failed outside guest handler",
238
+ rawCause: decoded.rawCause,
239
+ });
240
+ }
241
+ /** Decode a transport-owned errno without reflecting on a foreign throw in adapters. */
242
+ export function sandboxTransportErrno(cause) {
243
+ const error = z.instanceof(Error).safeParse(cause);
244
+ if (!error.success)
245
+ return undefined;
246
+ const decoded = z.object({ code: z.string() }).safeParse(error.data);
247
+ return decoded.success ? decoded.data.code : undefined;
248
+ }
249
+ /** Admit Acorn's documented offset from a syntax exception at this boundary. */
250
+ export function sandboxSourceError(cause) {
251
+ const error = z.instanceof(SyntaxError).safeParse(cause);
252
+ if (!error.success)
253
+ return undefined;
254
+ const decoded = z
255
+ .object({ pos: z.number().int().nonnegative() })
256
+ .safeParse(error.data);
257
+ return decoded.success ? { pos: decoded.data.pos } : undefined;
258
+ }
259
+ /** Capability owners supply an admission schema; decoding and foreign fallback stay here. */
260
+ export function sandboxCapabilityFailure(cause, namespace, operation, admitted = z.never()) {
261
+ const diagnostic = (fields) => new CapabilityFailed({
262
+ namespace,
263
+ operation,
264
+ cause: fields,
265
+ rawCause: cause,
266
+ });
267
+ return z
268
+ .unknown()
269
+ .pipe(z.union([
270
+ ownedFailureSchema,
271
+ admitted.transform(diagnostic),
272
+ z
273
+ .instanceof(ForageError)
274
+ .transform((error) => diagnostic({ kind: "Forage", message: error.message })),
275
+ z.instanceof(InvalidOperationInput).transform((error) => diagnostic({
276
+ kind: "InvalidInput",
277
+ message: `Invalid operation input: ${z.prettifyError({ issues: error.issues })}; use forage.describe`,
278
+ })),
279
+ z.unknown().transform((rawCause) => new Unknown({ rawCause })),
280
+ ]))
281
+ .parse(cause);
282
+ }
283
+ const maximumRecordedFailures = 128;
284
+ /** One boundary owns RPC decoding, safe transport and invocation-scoped recovery. */
285
+ export function sandboxBindingBoundary(bindings) {
286
+ const failures = new Map();
287
+ const capture = (failure) => {
288
+ if (failures.size >= maximumRecordedFailures)
289
+ throw new Error("Too many failed capability calls; split this execute call");
290
+ const ref = nanoid();
291
+ const referenced = referenceSandboxFailure(failure, ref);
292
+ failures.set(ref, referenced);
293
+ return sandboxTransportMessage(referenced, ref);
294
+ };
295
+ // Store the original cause in this invocation before constructing the safe
296
+ // guest carrier. It must never become an Error.cause exposed to the guest.
297
+ const captureError = (failure) => new Error(capture(failure));
298
+ return Object.freeze({
299
+ capture,
300
+ bindings: Object.freeze(Object.fromEntries(Object.entries(bindings).map(([namespace, operations]) => [
301
+ namespace,
302
+ Object.freeze(Object.fromEntries(Object.entries(operations).map(([operation, invoke]) => {
303
+ const call = async (input) => {
304
+ if (failures.size >= maximumRecordedFailures)
305
+ throw new Error("Too many failed capability calls; split this execute call");
306
+ try {
307
+ return await invoke(sandboxBindingInput(input));
308
+ }
309
+ catch (rawCause) {
310
+ throw captureError(sandboxCapabilityFailure(rawCause, namespace, operation));
311
+ }
312
+ };
313
+ return [operation, call];
314
+ }))),
315
+ ]))),
316
+ recover: (failure) => recoverSandboxFailure(failure, failures),
317
+ returnedFailure: (value) => {
318
+ const decoded = returnedOperationFailure.safeParse(value);
319
+ if (!decoded.success)
320
+ return undefined;
321
+ const original = failures.get(decoded.data.error.ref);
322
+ return original?._tag === decoded.data.error.tag ? original : undefined;
323
+ },
324
+ });
325
+ }
@@ -0,0 +1,15 @@
1
+ import * as Schema from "effect/Schema";
2
+ import type { z } from "zod";
3
+ /** Shared structural grammar for durable operator facts and client inspection. */
4
+ export declare const SandboxFailureEventSchema: Schema.Struct<{
5
+ readonly kind: Schema.Literal<"sandbox_failure">;
6
+ readonly ref: Schema.String;
7
+ readonly executionId: Schema.String;
8
+ readonly adapter: Schema.String;
9
+ readonly buildSha: Schema.NullOr<Schema.String>;
10
+ readonly tag: Schema.Literals<readonly ["SourceInvalid", "GuestThrew", "DeadlineExceeded", "Cancelled", "DispatchLost", "SandboxCrashed", "BadResponse", "ResultTooLarge", "ResultNotJson", "CapabilityFailed", "Unknown"]>;
11
+ readonly fields: Schema.$Record<Schema.String, Schema.Codec<z.core.util.JSONType, z.core.util.JSONType, never, never>>;
12
+ readonly healthAlert: Schema.Boolean;
13
+ }>;
14
+ /** Full operator diagnostics, excluded from model conversation and default reads. */
15
+ export type SandboxFailureEvent = typeof SandboxFailureEventSchema.Type;
@@ -0,0 +1,34 @@
1
+ import * as Schema from "effect/Schema";
2
+ const operatorJsonValue = Schema.suspend(() => Schema.Union([
3
+ Schema.Null,
4
+ Schema.Boolean,
5
+ Schema.Finite,
6
+ Schema.String,
7
+ Schema.mutable(Schema.Array(operatorJsonValue)),
8
+ Schema.mutableKey(Schema.Record(Schema.String, operatorJsonValue)),
9
+ ]));
10
+ const reference = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(256));
11
+ const identity = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(128));
12
+ /** Shared structural grammar for durable operator facts and client inspection. */
13
+ export const SandboxFailureEventSchema = Schema.Struct({
14
+ kind: Schema.Literal("sandbox_failure"),
15
+ ref: reference,
16
+ executionId: reference,
17
+ adapter: identity,
18
+ buildSha: Schema.NullOr(identity),
19
+ tag: Schema.Literals([
20
+ "SourceInvalid",
21
+ "GuestThrew",
22
+ "DeadlineExceeded",
23
+ "Cancelled",
24
+ "DispatchLost",
25
+ "SandboxCrashed",
26
+ "BadResponse",
27
+ "ResultTooLarge",
28
+ "ResultNotJson",
29
+ "CapabilityFailed",
30
+ "Unknown",
31
+ ]),
32
+ fields: Schema.Record(Schema.String, operatorJsonValue),
33
+ healthAlert: Schema.Boolean,
34
+ });
@@ -0,0 +1,128 @@
1
+ /** Optional source reference carried by sandbox failures. */
2
+ export type SandboxFailureReference = {
3
+ readonly ref?: string | undefined;
4
+ };
5
+ declare const SourceInvalid_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
6
+ readonly _tag: "SourceInvalid";
7
+ } & Readonly<A>;
8
+ /** A location in the submitted program, never in the host's source. */
9
+ export declare class SourceInvalid extends SourceInvalid_base<SandboxFailureReference & {
10
+ readonly line: number;
11
+ readonly column: number;
12
+ readonly excerpt: string;
13
+ }> {
14
+ }
15
+ declare const GuestThrew_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
16
+ readonly _tag: "GuestThrew";
17
+ } & Readonly<A>;
18
+ /** Text captured inside the guest's own exception handler. */
19
+ export declare class GuestThrew extends GuestThrew_base<SandboxFailureReference & {
20
+ readonly name: string;
21
+ readonly message: string;
22
+ readonly missingVariable?: string | undefined;
23
+ /** Safe provider envelope carried in the guest exception's cause, never model text. */
24
+ readonly transportMessage?: string | undefined;
25
+ }> {
26
+ }
27
+ declare const DeadlineExceeded_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
28
+ readonly _tag: "DeadlineExceeded";
29
+ } & Readonly<A>;
30
+ /** The invocation owner decided its execution budget was spent. */
31
+ export declare class DeadlineExceeded extends DeadlineExceeded_base<SandboxFailureReference & {
32
+ readonly limitMs: number;
33
+ readonly elapsedMs: number;
34
+ readonly acknowledged?: boolean | undefined;
35
+ }> {
36
+ }
37
+ declare const Cancelled_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
38
+ readonly _tag: "Cancelled";
39
+ } & Readonly<A>;
40
+ /** The invocation owner accepted cancellation. */
41
+ export declare class Cancelled extends Cancelled_base<SandboxFailureReference & {
42
+ readonly by: "caller" | "operator";
43
+ readonly acknowledged?: boolean | undefined;
44
+ }> {
45
+ }
46
+ declare const DispatchLost_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
47
+ readonly _tag: "DispatchLost";
48
+ } & Readonly<A>;
49
+ /** Dispatch started, but its transport did not deliver an answer. */
50
+ export declare class DispatchLost extends DispatchLost_base<SandboxFailureReference & {
51
+ readonly elapsedMs: number;
52
+ readonly transport: string;
53
+ readonly errno?: string | undefined;
54
+ readonly rawCause: unknown;
55
+ }> {
56
+ }
57
+ declare const SandboxCrashed_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
58
+ readonly _tag: "SandboxCrashed";
59
+ } & Readonly<A>;
60
+ /** The sandbox process could not start or stopped before answering. */
61
+ export declare class SandboxCrashed extends SandboxCrashed_base<SandboxFailureReference & {
62
+ readonly exit?: number | undefined;
63
+ readonly errno?: string | undefined;
64
+ readonly rawCause: unknown;
65
+ }> {
66
+ }
67
+ declare const BadResponse_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
68
+ readonly _tag: "BadResponse";
69
+ } & Readonly<A>;
70
+ /** A received envelope could not be decoded. Its reason is operator only. */
71
+ export declare class BadResponse extends BadResponse_base<SandboxFailureReference & {
72
+ readonly reason: string;
73
+ readonly rawCause: unknown;
74
+ }> {
75
+ }
76
+ declare const ResultTooLarge_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
77
+ readonly _tag: "ResultTooLarge";
78
+ } & Readonly<A>;
79
+ /** A JSON result exceeded Mycelium's output budget. */
80
+ export declare class ResultTooLarge extends ResultTooLarge_base<SandboxFailureReference & {
81
+ readonly size: number;
82
+ }> {
83
+ }
84
+ declare const ResultNotJson_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
85
+ readonly _tag: "ResultNotJson";
86
+ } & Readonly<A>;
87
+ /** A result could not be represented as JSON. */
88
+ export declare class ResultNotJson extends ResultNotJson_base<SandboxFailureReference & {
89
+ readonly kind: string;
90
+ readonly rawCause?: unknown;
91
+ }> {
92
+ }
93
+ /** A capability owner explicitly admits this bounded diagnostic as safe. */
94
+ export type CapabilityDiagnostic = Readonly<{
95
+ kind: "Files" | "Forage" | "InvalidInput" | "Unavailable" | "OperationFailed";
96
+ message: string;
97
+ }>;
98
+ /** Fields admitted by a capability owner, with the original cause kept private. */
99
+ export type CapabilityFailureFields = {
100
+ readonly ref?: string;
101
+ readonly namespace: string;
102
+ readonly operation: string;
103
+ readonly cause: CapabilityDiagnostic;
104
+ readonly rawCause?: unknown;
105
+ };
106
+ declare const CapabilityFailed_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
107
+ readonly _tag: "CapabilityFailed";
108
+ } & Readonly<A>;
109
+ /** Failure at a named capability boundary, with an owner-admitted diagnostic. */
110
+ export declare class CapabilityFailed extends CapabilityFailed_base<CapabilityFailureFields> {
111
+ /** Retain the admitted diagnostic for ordinary Error consumers through the same safe projection. */
112
+ constructor(fields: CapabilityFailureFields);
113
+ }
114
+ declare const Unknown_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
115
+ readonly _tag: "Unknown";
116
+ } & Readonly<A>;
117
+ /** A foreign throw violated the typed adapter contract. */
118
+ export declare class Unknown extends Unknown_base<SandboxFailureReference & {
119
+ readonly rawCause: unknown;
120
+ }> {
121
+ }
122
+ /** Closed error channel shared by sandbox adapters and the invocation owner. */
123
+ export type SandboxFailure = SourceInvalid | GuestThrew | DeadlineExceeded | Cancelled | DispatchLost | SandboxCrashed | BadResponse | ResultTooLarge | ResultNotJson | CapabilityFailed | Unknown;
124
+ /** Copy the failure to correlate one execution without mutating shared host errors. */
125
+ export declare function referenceSandboxFailure(failure: SandboxFailure, ref: string): SandboxFailure;
126
+ /** The sole model projection. Transport, parser and raw cause fields stay private. */
127
+ export declare function sandboxFailureMessage(failure: SandboxFailure, includeReference?: boolean): string;
128
+ export {};
@@ -0,0 +1,161 @@
1
+ import * as Data from "effect/Data";
2
+ /** A location in the submitted program, never in the host's source. */
3
+ export class SourceInvalid extends Data.TaggedError("SourceInvalid") {
4
+ }
5
+ /** Text captured inside the guest's own exception handler. */
6
+ export class GuestThrew extends Data.TaggedError("GuestThrew") {
7
+ }
8
+ /** The invocation owner decided its execution budget was spent. */
9
+ export class DeadlineExceeded extends Data.TaggedError("DeadlineExceeded") {
10
+ }
11
+ /** The invocation owner accepted cancellation. */
12
+ export class Cancelled extends Data.TaggedError("Cancelled") {
13
+ }
14
+ /** Dispatch started, but its transport did not deliver an answer. */
15
+ export class DispatchLost extends Data.TaggedError("DispatchLost") {
16
+ }
17
+ /** The sandbox process could not start or stopped before answering. */
18
+ export class SandboxCrashed extends Data.TaggedError("SandboxCrashed") {
19
+ }
20
+ /** A received envelope could not be decoded. Its reason is operator only. */
21
+ export class BadResponse extends Data.TaggedError("BadResponse") {
22
+ }
23
+ /** A JSON result exceeded Mycelium's output budget. */
24
+ export class ResultTooLarge extends Data.TaggedError("ResultTooLarge") {
25
+ }
26
+ /** A result could not be represented as JSON. */
27
+ export class ResultNotJson extends Data.TaggedError("ResultNotJson") {
28
+ }
29
+ /** Failure at a named capability boundary, with an owner-admitted diagnostic. */
30
+ export class CapabilityFailed extends Data.TaggedError("CapabilityFailed") {
31
+ /** Retain the admitted diagnostic for ordinary Error consumers through the same safe projection. */
32
+ constructor(fields) {
33
+ super(fields);
34
+ this.message = sandboxFailureMessage(this);
35
+ }
36
+ }
37
+ /** A foreign throw violated the typed adapter contract. */
38
+ export class Unknown extends Data.TaggedError("Unknown") {
39
+ }
40
+ /** Copy the failure to correlate one execution without mutating shared host errors. */
41
+ export function referenceSandboxFailure(failure, ref) {
42
+ switch (failure._tag) {
43
+ case "SourceInvalid":
44
+ return new SourceInvalid({
45
+ line: failure.line,
46
+ column: failure.column,
47
+ excerpt: failure.excerpt,
48
+ ref,
49
+ });
50
+ case "GuestThrew":
51
+ return new GuestThrew({
52
+ name: failure.name,
53
+ message: failure.message,
54
+ missingVariable: failure.missingVariable,
55
+ transportMessage: failure.transportMessage,
56
+ ref,
57
+ });
58
+ case "DeadlineExceeded":
59
+ return new DeadlineExceeded({
60
+ limitMs: failure.limitMs,
61
+ elapsedMs: failure.elapsedMs,
62
+ acknowledged: failure.acknowledged,
63
+ ref,
64
+ });
65
+ case "Cancelled":
66
+ return new Cancelled({
67
+ by: failure.by,
68
+ acknowledged: failure.acknowledged,
69
+ ref,
70
+ });
71
+ case "DispatchLost":
72
+ return new DispatchLost({
73
+ elapsedMs: failure.elapsedMs,
74
+ transport: failure.transport,
75
+ errno: failure.errno,
76
+ rawCause: failure.rawCause,
77
+ ref,
78
+ });
79
+ case "SandboxCrashed":
80
+ return new SandboxCrashed({
81
+ exit: failure.exit,
82
+ errno: failure.errno,
83
+ rawCause: failure.rawCause,
84
+ ref,
85
+ });
86
+ case "BadResponse":
87
+ return new BadResponse({
88
+ reason: failure.reason,
89
+ rawCause: failure.rawCause,
90
+ ref,
91
+ });
92
+ case "ResultTooLarge":
93
+ return new ResultTooLarge({ size: failure.size, ref });
94
+ case "ResultNotJson":
95
+ return new ResultNotJson({
96
+ kind: failure.kind,
97
+ rawCause: failure.rawCause,
98
+ ref,
99
+ });
100
+ case "CapabilityFailed":
101
+ return new CapabilityFailed({
102
+ namespace: failure.namespace,
103
+ operation: failure.operation,
104
+ cause: failure.cause,
105
+ rawCause: failure.rawCause,
106
+ ref,
107
+ });
108
+ case "Unknown":
109
+ return new Unknown({ rawCause: failure.rawCause, ref });
110
+ }
111
+ }
112
+ /** The sole model projection. Transport, parser and raw cause fields stay private. */
113
+ export function sandboxFailureMessage(failure, includeReference = true) {
114
+ let text;
115
+ switch (failure._tag) {
116
+ case "SourceInvalid":
117
+ text = `SyntaxError in submitted source line ${String(failure.line)}, column ${String(failure.column)}: ${failure.excerpt.slice(0, 160)}. Nothing ran. Fix quote/heredoc nesting: quote multi-line shell text with a JavaScript template literal or \\n escapes; escape backticks and \${ inside it. If a nested heredoc is hard to quote, write the script with Files, then execute it.`;
118
+ break;
119
+ case "GuestThrew": {
120
+ const name = failure.name.slice(0, 80);
121
+ const message = failure.message.slice(0, 512);
122
+ const missing = failure.missingVariable;
123
+ text = `${name}: ${message}${missing === undefined ? "" : `. Declare ${missing} with const or let before assigning it; this sandbox does not create implicit globals. Each execute call has its own variables.`}`;
124
+ break;
125
+ }
126
+ case "DeadlineExceeded":
127
+ text = `execute hit its ${String(failure.limitMs)} ms deadline after ${String(failure.elapsedMs)} ms; split the work or persist progress${failure.acknowledged === false ? "; sandbox did not acknowledge cancellation" : ""}`;
128
+ break;
129
+ case "Cancelled":
130
+ text =
131
+ failure.acknowledged === false
132
+ ? "Sandbox did not acknowledge cancellation"
133
+ : "Execution was cancelled";
134
+ break;
135
+ case "DispatchLost":
136
+ text = `The sandbox lost contact after ${String(failure.elapsedMs)} ms; a running command may still be running; check its effects before retrying`;
137
+ break;
138
+ case "SandboxCrashed":
139
+ text =
140
+ "The sandbox process stopped before answering; check effects before retrying";
141
+ break;
142
+ case "BadResponse":
143
+ text =
144
+ "The sandbox returned an unreadable result; retry once, split the call if it recurs";
145
+ break;
146
+ case "ResultTooLarge":
147
+ text = "Sandbox result exceeds 256 KiB";
148
+ break;
149
+ case "ResultNotJson":
150
+ text = "Sandbox returned non-JSON data";
151
+ break;
152
+ case "CapabilityFailed":
153
+ text = failure.cause.message.slice(0, 1000);
154
+ break;
155
+ case "Unknown":
156
+ return `The sandbox failed for an unrecognized reason${includeReference ? ` (ref ${failure.ref ?? "unavailable"})` : ""}`;
157
+ }
158
+ return !includeReference || failure.ref === undefined
159
+ ? text
160
+ : `${text} (ref ${failure.ref})`;
161
+ }