@fungi.computer/mycelium 0.0.0-stage → 0.0.2

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,162 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Exit from "effect/Exit";
3
+ import * as Scope from "effect/Scope";
4
+ import { z } from "zod";
5
+ import { compileSurface, } from "./compiler.js";
6
+ import { MyceliumDefinitionError, MyceliumSourceError, } from "./errors.js";
7
+ import { createExecuteDoor } from "./execute-tool.js";
8
+ function compareCodeUnits(left, right) {
9
+ return left < right ? -1 : left > right ? 1 : 0;
10
+ }
11
+ const maximumCapabilitySources = 128;
12
+ const sourceIdSchema = z.string().min(1).max(160);
13
+ const sourceSnapshotSchema = z.object({
14
+ version: z.string().min(1).max(160),
15
+ modules: z.array(z.unknown()),
16
+ });
17
+ const maximumCandidateModules = 1_000;
18
+ function validateSources(input) {
19
+ if (input.length > maximumCapabilitySources) {
20
+ throw new MyceliumDefinitionError("Capability source count exceeds bound");
21
+ }
22
+ const sources = [...input].sort((left, right) => compareCodeUnits(left.id, right.id));
23
+ const ids = new Set();
24
+ for (const source of sources) {
25
+ if (!sourceIdSchema.safeParse(source.id).success) {
26
+ throw new MyceliumDefinitionError("Capability source id must be non-empty and bounded");
27
+ }
28
+ if (ids.has(source.id)) {
29
+ throw new MyceliumDefinitionError(`Duplicate capability source id: ${source.id}`);
30
+ }
31
+ ids.add(source.id);
32
+ }
33
+ return sources;
34
+ }
35
+ function validateCandidateModuleCount(count) {
36
+ if (count > maximumCandidateModules) {
37
+ throw new MyceliumDefinitionError("Candidate module count exceeds bound");
38
+ }
39
+ }
40
+ function validateSourceSnapshot(snapshot, existingModuleCount) {
41
+ const parsed = sourceSnapshotSchema.safeParse(snapshot);
42
+ if (!parsed.success) {
43
+ throw new MyceliumDefinitionError("Capability source snapshot must have a non-empty bounded version");
44
+ }
45
+ validateCandidateModuleCount(existingModuleCount + parsed.data.modules.length);
46
+ }
47
+ function acquireSourceIntoScope(source, candidateScope, cleanupFailures, invalidate, session) {
48
+ return Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
49
+ const release = (acquired) => Effect.tryPromise({
50
+ try: () => acquired.release(),
51
+ catch: () => new MyceliumSourceError(source.id, "release"),
52
+ }).pipe(Effect.catch((failure) => Effect.sync(() => {
53
+ cleanupFailures.push(failure);
54
+ })));
55
+ const state = yield* Effect.try({
56
+ try: () => {
57
+ const controller = new AbortController();
58
+ return {
59
+ controller,
60
+ outcome: source
61
+ .acquire(session === undefined
62
+ ? { signal: controller.signal, invalidate }
63
+ : { signal: controller.signal, invalidate, session })
64
+ .then((acquired) => Exit.succeed(acquired), () => Exit.fail(new MyceliumSourceError(source.id, "acquire"))),
65
+ };
66
+ },
67
+ catch: () => new MyceliumSourceError(source.id, "acquire"),
68
+ });
69
+ yield* Scope.addFinalizer(candidateScope, Effect.promise(() => state.outcome).pipe(Effect.flatMap((outcome) => Exit.isSuccess(outcome) ? release(outcome.value) : Effect.void)));
70
+ const outcome = yield* restore(Effect.promise(() => state.outcome)).pipe(Effect.onInterrupt(() => Effect.sync(() => {
71
+ state.controller.abort();
72
+ })));
73
+ if (Exit.isFailure(outcome)) {
74
+ return yield* Effect.failCause(outcome.cause);
75
+ }
76
+ return outcome.value;
77
+ }));
78
+ }
79
+ /** Acquire one complete candidate attempt without mutating installed state. */
80
+ function acquireCandidateAttempt(options) {
81
+ return Effect.gen(function* () {
82
+ const sources = yield* Effect.try({
83
+ try: () => validateSources(options.sources),
84
+ catch: (cause) => cause instanceof MyceliumDefinitionError
85
+ ? cause
86
+ : new MyceliumDefinitionError("Capability sources are invalid"),
87
+ });
88
+ yield* Effect.try({
89
+ try: () => {
90
+ validateCandidateModuleCount(options.modules.length);
91
+ },
92
+ catch: (cause) => cause instanceof MyceliumDefinitionError
93
+ ? cause
94
+ : new MyceliumDefinitionError("Static capability modules are invalid"),
95
+ });
96
+ const candidateScope = yield* Scope.make();
97
+ const cleanupFailures = [];
98
+ let stale = false;
99
+ const modules = [...options.modules];
100
+ const sourceFrames = [];
101
+ const acquireAll = Effect.gen(function* () {
102
+ for (const source of sources) {
103
+ const acquired = yield* acquireSourceIntoScope(source, candidateScope, cleanupFailures, () => {
104
+ stale = true;
105
+ }, options.session);
106
+ yield* Effect.try({
107
+ try: () => {
108
+ validateSourceSnapshot(acquired.snapshot, modules.length);
109
+ },
110
+ catch: (cause) => cause instanceof MyceliumDefinitionError
111
+ ? cause
112
+ : new MyceliumDefinitionError("Capability source snapshot is invalid"),
113
+ });
114
+ modules.push(...acquired.snapshot.modules);
115
+ sourceFrames.push({
116
+ id: source.id,
117
+ version: acquired.snapshot.version,
118
+ });
119
+ }
120
+ const compiled = options.precompiled ??
121
+ (yield* Effect.try({
122
+ try: () => compileSurface(modules, sourceFrames),
123
+ catch: (cause) => cause instanceof MyceliumDefinitionError
124
+ ? cause
125
+ : new MyceliumDefinitionError("Capability compilation failed"),
126
+ }));
127
+ const backingWork = options.backingWork.createGroup();
128
+ const executeDoor = createExecuteDoor(compiled.operations, compiled.catalog, options.sandbox, backingWork, compiled.moduleAliases, compiled.namespacePaths, options.session?.sessionId ?? null, options.access);
129
+ let closed = false;
130
+ const close = () => Effect.gen(function* () {
131
+ if (!closed) {
132
+ closed = true;
133
+ yield* backingWork.awaitIdle;
134
+ yield* Scope.close(candidateScope, Exit.void);
135
+ }
136
+ const cleanupFailure = cleanupFailures[0];
137
+ if (cleanupFailure !== undefined)
138
+ yield* Effect.fail(cleanupFailure);
139
+ });
140
+ return Object.freeze({
141
+ compiled,
142
+ executeDoor,
143
+ isStale: () => stale,
144
+ close,
145
+ });
146
+ });
147
+ return yield* acquireAll.pipe(Effect.onExit((exit) => Exit.isSuccess(exit) ? Effect.void : Scope.close(candidateScope, exit)));
148
+ });
149
+ }
150
+ const maximumCandidateAttempts = 2;
151
+ /** Acquire one non-stale candidate or fail after one bounded retry. */
152
+ export function acquireSourceCandidate(options) {
153
+ return Effect.gen(function* () {
154
+ for (let attempt = 0; attempt < maximumCandidateAttempts; attempt += 1) {
155
+ const candidate = yield* acquireCandidateAttempt(options);
156
+ if (!candidate.isStale())
157
+ return candidate;
158
+ yield* candidate.close();
159
+ }
160
+ return yield* Effect.fail(new MyceliumSourceError(undefined, "stale"));
161
+ });
162
+ }
@@ -0,0 +1,11 @@
1
+ import type { Sandbox, SandboxRequest, SandboxValue } from "./index.js";
2
+ /** A test callback receives the admitted bindings and cancellation. */
3
+ export type DirectSandboxCallback = (bindings: SandboxRequest["bindings"], signal: AbortSignal) => Promise<SandboxValue>;
4
+ /**
5
+ * Dispatch a known-binding callback directly in this process. NOT isolation:
6
+ * submitted code is ignored, and the callback retains all host privileges.
7
+ * Use only trusted tests and examples, never model-authored code execution.
8
+ */
9
+ export declare function directSandbox(callback: DirectSandboxCallback): Sandbox;
10
+ /** A test transport that always refuses execution with the supplied message. */
11
+ export declare function rejectingSandbox(message: string): Sandbox;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Dispatch a known-binding callback directly in this process. NOT isolation:
3
+ * submitted code is ignored, and the callback retains all host privileges.
4
+ * Use only trusted tests and examples, never model-authored code execution.
5
+ */
6
+ export function directSandbox(callback) {
7
+ return {
8
+ execute: async (request, signal) => {
9
+ signal.throwIfAborted();
10
+ const result = await callback(request.bindings, signal);
11
+ signal.throwIfAborted();
12
+ return result;
13
+ },
14
+ };
15
+ }
16
+ /** A test transport that always refuses execution with the supplied message. */
17
+ export function rejectingSandbox(message) {
18
+ return directSandbox(() => Promise.reject(new Error(message)));
19
+ }
@@ -0,0 +1,9 @@
1
+ import type { Sandbox } from "@fungi.computer/mycelium";
2
+ /** The Worker Loader binding Codemode runs guests on. */
3
+ export type CodemodeLoader = WorkerLoader;
4
+ /** Local development facts supplied by the host, never by guest code. */
5
+ export type CodemodeSandboxOptions = Readonly<{
6
+ localDevUnenforcedLimits?: readonly ("cpu" | "memory" | "output" | "cancel")[];
7
+ }>;
8
+ /** Construct a network-isolated Codemode sandbox over a Worker Loader. */
9
+ export declare function createCodemodeSandbox(loader: CodemodeLoader, adapter?: string, options?: CodemodeSandboxOptions): Sandbox;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * A Mycelium sandbox over Cloudflare Codemode: each `execute` call runs the
3
+ * model's program in a fresh Dynamic Worker (Worker Loader) with no network,
4
+ * and the bound operations are its only way out. For Workers hosts.
5
+ */
6
+ import { DynamicWorkerExecutor, normalizeCode } from "@cloudflare/codemode";
7
+ import { BadResponse, Cancelled, DispatchLost, SourceInvalid, } from "@fungi.computer/mycelium/sandbox-failure";
8
+ import { sandboxBindingNames, sandboxGuestProgram, sandboxGuestResultSchema, sandboxProviderOperationName, submittedSourceLocation, } from "@fungi.computer/mycelium/sandbox-guest";
9
+ import { isSandboxFailure, sandboxBindingBoundary, sandboxExecutorFailure, sandboxGuestFailure, } from "@fungi.computer/mycelium/sandbox-boundary";
10
+ const unenforcedLimitMessages = {
11
+ cpu: "CPU limits are not enforced in local dev",
12
+ memory: "Memory limits are not enforced in local dev",
13
+ output: "Output limits are not enforced in local dev",
14
+ cancel: "Cancellation limits are not enforced in local dev",
15
+ };
16
+ const reportedUnenforcedLimits = new Set();
17
+ /** Construct a network-isolated Codemode sandbox over a Worker Loader. */
18
+ export function createCodemodeSandbox(loader, adapter = "codemode-workerd", options = {}) {
19
+ for (const limit of options.localDevUnenforcedLimits ?? []) {
20
+ const message = unenforcedLimitMessages[limit];
21
+ if (!reportedUnenforcedLimits.has(message)) {
22
+ reportedUnenforcedLimits.add(message);
23
+ console.warn(message);
24
+ }
25
+ }
26
+ return {
27
+ adapter,
28
+ async execute(request, signal) {
29
+ const startedAt = Date.now();
30
+ try {
31
+ signal.throwIfAborted();
32
+ const normalized = normalizeCode(request.code);
33
+ const location = submittedSourceLocation(normalized, request.code);
34
+ if (location !== null)
35
+ throw new SourceInvalid(location);
36
+ const boundary = sandboxBindingBoundary(request.bindings);
37
+ const withCpuBudget = (definition) => ({
38
+ ...definition,
39
+ limits: {
40
+ ...definition.limits,
41
+ cpuMs: Math.min(request.timeoutMs, definition.limits?.cpuMs ?? request.timeoutMs),
42
+ },
43
+ });
44
+ const executor = new DynamicWorkerExecutor({
45
+ loader: {
46
+ load: (definition) => loader.load(withCpuBudget(definition)),
47
+ get: (name, getCode) => loader.get(name, async () => withCpuBudget(await getCode())),
48
+ },
49
+ timeout: request.timeoutMs,
50
+ globalOutbound: null,
51
+ });
52
+ // Codemode has no cancellation API; keep its promise until it settles
53
+ // so Mycelium owns the cancellation grace.
54
+ const output = await executor.execute(sandboxGuestProgram(normalized, sandboxBindingNames(boundary.bindings), request.namespacePaths, sandboxProviderOperationName), Object.entries(boundary.bindings).map(([name, operations]) => ({
55
+ name,
56
+ fns: Object.fromEntries(Object.entries(operations).map(([operation, binding]) => [
57
+ sandboxProviderOperationName(operation),
58
+ binding,
59
+ ])),
60
+ })));
61
+ signal.throwIfAborted();
62
+ if (output.error !== undefined)
63
+ throw sandboxExecutorFailure(output.error, request.timeoutMs, Date.now() - startedAt);
64
+ const decoded = sandboxGuestResultSchema.safeParse(output.result);
65
+ if (!decoded.success)
66
+ throw new BadResponse({
67
+ reason: "invalid guest envelope",
68
+ rawCause: decoded.error,
69
+ });
70
+ if (!decoded.data.ok)
71
+ throw boundary.recover(sandboxGuestFailure(decoded.data.error, request.bindings));
72
+ const returned = boundary.returnedFailure(decoded.data.value);
73
+ if (returned !== undefined)
74
+ throw returned;
75
+ return decoded.data.value;
76
+ }
77
+ catch (cause) {
78
+ if (signal.aborted)
79
+ throw new Cancelled({ by: "caller" });
80
+ if (isSandboxFailure(cause))
81
+ throw cause;
82
+ throw new DispatchLost({
83
+ elapsedMs: Date.now() - startedAt,
84
+ transport: adapter,
85
+ rawCause: cause,
86
+ });
87
+ }
88
+ },
89
+ };
90
+ }
@@ -0,0 +1,25 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ **@fungi.computer/mycelium**
4
+
5
+ ---
6
+
7
+ # @fungi.computer/mycelium
8
+
9
+ ## Modules
10
+
11
+ | Module | Description |
12
+ | ----------------------------------------------- | ----------- |
13
+ | [define](define.md) | - |
14
+ | [effect](effect.md) | - |
15
+ | [index](index.md) | - |
16
+ | [mcp](mcp.md) | - |
17
+ | [remote](remote.md) | - |
18
+ | [sandbox-boundary](sandbox-boundary.md) | - |
19
+ | [sandbox-failure](sandbox-failure.md) | - |
20
+ | [sandbox-guest](sandbox-guest.md) | - |
21
+ | [sandbox-wire](sandbox-wire.md) | - |
22
+ | [sandbox](sandbox.md) | - |
23
+ | [semaphore-transition](semaphore-transition.md) | - |
24
+ | [testing](testing.md) | - |
25
+ | [workers](workers.md) | - |
@@ -0,0 +1,20 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ [**@fungi.computer/mycelium**](README.md)
4
+
5
+ ---
6
+
7
+ [@fungi.computer/mycelium](README.md) / define
8
+
9
+ # define
10
+
11
+ ## Variables
12
+
13
+ ### Mycelium
14
+
15
+ ```ts
16
+ const Mycelium: Pick<MyceliumApi, "module" | "operation" | "gate">;
17
+ ```
18
+
19
+ The authoring half of [MyceliumApi](index.md#myceliumapi); registrations are the
20
+ same handles.
@@ -0,0 +1,245 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ [**@fungi.computer/mycelium**](README.md)
4
+
5
+ ---
6
+
7
+ [@fungi.computer/mycelium](README.md) / effect
8
+
9
+ # effect
10
+
11
+ ## Type Aliases
12
+
13
+ ### Sandbox
14
+
15
+ ```ts
16
+ type Sandbox = Readonly<{
17
+ execute: (request, signal) => Effect.Effect<SandboxValue, SandboxFailure>;
18
+ adapter?: string;
19
+ buildSha?: string;
20
+ }>;
21
+ ```
22
+
23
+ Effect-native host seam for sandbox execution.
24
+
25
+ Interrupting `execute` must not complete until the backing work has actually
26
+ settled. Mycelium bounds that wait by the acknowledgement grace and reports
27
+ `abort_unacknowledged` when it expires, keeping the work's source revision alive
28
+ until it exits. A host with Promise-shaped work adapts it with
29
+ [fromTypedSandbox](#fromtypedsandbox); `Effect.tryPromise` alone completes
30
+ interruption without awaiting the Promise and so breaks that settlement law.
31
+
32
+ ---
33
+
34
+ ### MyceliumOptions
35
+
36
+ ```ts
37
+ type MyceliumOptions = Readonly<{
38
+ modules?: readonly ModuleRegistration[];
39
+ sources?: readonly CapabilitySource[];
40
+ session?: CapabilitySession;
41
+ execution?: ExecutionOptions;
42
+ sandbox: Sandbox;
43
+ onSandboxFailure?: (event) => Effect.Effect<void>;
44
+ tools?: readonly LabelledTool[];
45
+ access?: AccessOptions;
46
+ }>;
47
+ ```
48
+
49
+ Inputs used to construct the canonical Effect runtime.
50
+
51
+ ---
52
+
53
+ ### Lease
54
+
55
+ ```ts
56
+ type Lease = Readonly<{
57
+ revision: string;
58
+ catalog: ForageCatalog;
59
+ executeTool: MuleTool;
60
+ tools: readonly MuleTool[];
61
+ release: () => Effect.Effect<void, MyceliumError>;
62
+ }>;
63
+ ```
64
+
65
+ One immutable Effect-facing capability revision.
66
+
67
+ ---
68
+
69
+ ### Runtime
70
+
71
+ ```ts
72
+ type Runtime = Readonly<{
73
+ acquire: () => Effect.Effect<Lease, MyceliumError, Scope.Scope>;
74
+ close: () => Effect.Effect<void, MyceliumError>;
75
+ }>;
76
+ ```
77
+
78
+ Warm Effect lifecycle for acquiring scope-owned run leases.
79
+
80
+ ## Functions
81
+
82
+ ### fromTypedSandbox()
83
+
84
+ ```ts
85
+ function fromTypedSandbox(sandbox): Sandbox;
86
+ ```
87
+
88
+ Adapt a Promise-shaped sandbox to the Effect seam. This is Mycelium's one
89
+ Promise sandbox conversion: interruption waits for the host Promise to settle,
90
+ while cancellation reaches the host through the abort signal.
91
+
92
+ #### Parameters
93
+
94
+ | Parameter | Type |
95
+ | --------- | ------------------------------- |
96
+ | `sandbox` | [`Sandbox`](sandbox.md#sandbox) |
97
+
98
+ #### Returns
99
+
100
+ [`Sandbox`](#sandbox)
101
+
102
+ ---
103
+
104
+ ### make()
105
+
106
+ ```ts
107
+ function make(options): Effect<
108
+ Readonly<{
109
+ acquire: () => Effect<
110
+ Readonly<{
111
+ revision: string;
112
+ catalog: ForageCatalog;
113
+ executeTool: MuleTool;
114
+ tools: readonly MuleTool[];
115
+ release: () => Effect<void, MyceliumError>;
116
+ }>,
117
+ MyceliumError,
118
+ Scope
119
+ >;
120
+ close: () => Effect<void, MyceliumError>;
121
+ }>,
122
+ MyceliumError,
123
+ Scope
124
+ >;
125
+ ```
126
+
127
+ Construct the canonical scoped Effect runtime.
128
+
129
+ #### Parameters
130
+
131
+ | Parameter | Type |
132
+ | --------- | ------------------------------------- |
133
+ | `options` | [`MyceliumOptions`](#myceliumoptions) |
134
+
135
+ #### Returns
136
+
137
+ `Effect`\<`Readonly`\<\{ `acquire`: () => `Effect`\<`Readonly`\<\{ `revision`:
138
+ `string`; `catalog`: `ForageCatalog`; `executeTool`: `MuleTool`; `tools`:
139
+ readonly `MuleTool`[]; `release`: () => `Effect`\<`void`,
140
+ [`MyceliumError`](index.md#myceliumerror)\>; \}\>,
141
+ [`MyceliumError`](index.md#myceliumerror), `Scope`\>; `close`: () =>
142
+ `Effect`\<`void`, [`MyceliumError`](index.md#myceliumerror)\>; \}\>,
143
+ [`MyceliumError`](index.md#myceliumerror), `Scope`\>
144
+
145
+ ## References
146
+
147
+ ### CapabilitySession
148
+
149
+ Re-exports [CapabilitySession](index.md#capabilitysession)
150
+
151
+ ---
152
+
153
+ ### CapabilitySource
154
+
155
+ Re-exports [CapabilitySource](index.md#capabilitysource)
156
+
157
+ ---
158
+
159
+ ### ModuleRegistration
160
+
161
+ Re-exports [ModuleRegistration](index.md#moduleregistration)
162
+
163
+ ---
164
+
165
+ ### SandboxBinding
166
+
167
+ Re-exports [SandboxBinding](sandbox.md#sandboxbinding)
168
+
169
+ ---
170
+
171
+ ### SandboxRequest
172
+
173
+ Re-exports [SandboxRequest](sandbox.md#sandboxrequest)
174
+
175
+ ---
176
+
177
+ ### ExecutionOptions
178
+
179
+ Re-exports [ExecutionOptions](index.md#executionoptions)
180
+
181
+ ---
182
+
183
+ ### Access
184
+
185
+ Re-exports [Access](index.md#access)
186
+
187
+ ---
188
+
189
+ ### AccessContext
190
+
191
+ Re-exports [AccessContext](index.md#accesscontext)
192
+
193
+ ---
194
+
195
+ ### AccessLabel
196
+
197
+ Re-exports [AccessLabel](index.md#accesslabel)
198
+
199
+ ---
200
+
201
+ ### AccessOptions
202
+
203
+ Re-exports [AccessOptions](index.md#accessoptions)
204
+
205
+ ---
206
+
207
+ ### AccessRefusal
208
+
209
+ Re-exports [AccessRefusal](index.md#accessrefusal)
210
+
211
+ ---
212
+
213
+ ### AccessRefusalReason
214
+
215
+ Re-exports [AccessRefusalReason](index.md#accessrefusalreason)
216
+
217
+ ---
218
+
219
+ ### ConfirmRequest
220
+
221
+ Re-exports [ConfirmRequest](index.md#confirmrequest)
222
+
223
+ ---
224
+
225
+ ### Grant
226
+
227
+ Re-exports [Grant](index.md#grant)
228
+
229
+ ---
230
+
231
+ ### Grants
232
+
233
+ Re-exports [Grants](index.md#grants)
234
+
235
+ ---
236
+
237
+ ### LabelledTool
238
+
239
+ Re-exports [LabelledTool](index.md#labelledtool)
240
+
241
+ ---
242
+
243
+ ### ToolPolicy
244
+
245
+ Re-exports [ToolPolicy](index.md#toolpolicy)