@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
168 lines • 6.15 kB
JavaScript
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
if (typeof path === "string" && /^\.\.?\//.test(path)) {
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
});
}
return path;
};
/**
* The browser storage: no task isolation, one frame stack per storage.
*
* `getStore` answers the newest live frame, so a read that interleaves
* with another task's bind can still see that task's store — only real
* isolation fixes that, which is what `liveStores` exists to route
* around. What the stack does fix is the slot's two worse failures: a
* settle removes its own frame rather than blind-restoring a saved
* value, so an out-of-order settle can neither wipe a binding that is
* still live nor strand a stale one after every run has finished.
*
* Exported for the fallback-mode tests, which mock `createAsyncContext`
* with this class so the browser branch runs under node's test runner.
*/
export class FallbackStorage {
frames = [];
run(s, fn) {
return this.withFrame(s, fn);
}
withFrame(s, fn) {
const frame = { store: s };
this.frames.push(frame);
const drop = () => {
const at = this.frames.indexOf(frame);
if (at >= 0)
this.frames.splice(at, 1);
};
try {
const result = fn();
if (result instanceof Promise) {
return result.finally(drop);
}
drop();
return result;
}
catch (err) {
drop();
throw err;
}
}
getStore() {
return this.frames.length === 0 ? undefined : this.frames[this.frames.length - 1]?.store;
}
liveStores() {
return this.frames
.map((frame) => frame.store)
.filter((store) => store !== undefined);
}
capture() {
const frames = this.frames.length === 0 ? [undefined] : this.frames.map((frame) => frame.store);
return (fn) => {
const enter = (at) => at === frames.length ? fn() : this.withFrame(frames[at], () => enter(at + 1));
return enter(0);
};
}
}
class IsolatedStorage {
tasks;
constructor(ctor) {
this.tasks = new ctor();
}
run(store, fn) {
return this.tasks.run(store, fn);
}
getStore() {
return this.tasks.getStore();
}
liveStores() {
const store = this.tasks.getStore();
return store === undefined ? [] : [store];
}
capture() {
const store = this.tasks.getStore();
return (fn) => this.tasks.run(store, fn);
}
}
async function resolveCtor() {
const g = globalThis;
if (g.AsyncLocalStorage !== undefined)
return g.AsyncLocalStorage;
if (g.process?.versions?.node !== undefined) {
try {
const modName = 'node:async_hooks';
const mod = (await import(__rewriteRelativeImportExtension(/* @vite-ignore */ modName)));
return mod.AsyncLocalStorage;
}
catch {
return null;
}
}
return null;
}
/**
* Whether `ctor` actually isolates overlapping tasks.
*
* Constructor identity is not proof: a bundler's `AsyncLocalStorage`
* shim on `globalThis` is typically a single slot, and trusting it
* would disarm every fallback hardening while behaving exactly like
* the fallback. So the claim is tested: two runs overlap across a
* microtask and each must read back its own store. A ctor that throws
* anywhere in the probe is answering the same question.
*/
async function isolates(ctor) {
try {
const probe = new ctor();
const reads = await Promise.all([
probe.run(1, async () => {
await Promise.resolve();
return probe.getStore();
}),
probe.run(2, async () => {
await Promise.resolve();
return probe.getStore();
}),
]);
return reads[0] === 1 && reads[1] === 2;
}
catch {
return false;
}
}
const resolved = await resolveCtor();
/**
* Whether the storage isolates concurrent tasks, verified behaviorally
* at module load rather than assumed from where the constructor came
* from.
*
* `AsyncLocalStorage` gives every task its own store. The fallback is
* one frame stack whose top a concurrent task can shadow, so a caller
* that binds a store for concurrent work has to know which it got.
*/
export const asyncContextIsolatesTasks = resolved !== null && (await isolates(resolved));
const verifiedCtor = asyncContextIsolatesTasks ? resolved : null;
const unbound = verifiedCtor?.snapshot?.() ?? null;
/**
* Run `fn` with no store bound, as this module loaded: for work a line
* starts that outlives it and must not carry the line's state, such as
* a sandbox's SFTP server. Without task isolation there is nothing to
* leave, so `fn` runs as called.
*/
export function runDetached(fn) {
return unbound === null ? fn() : unbound(fn);
}
export function createAsyncContext() {
return verifiedCtor === null ? new FallbackStorage() : new IsolatedStorage(verifiedCtor);
}
//# sourceMappingURL=async_context.js.map