@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
73 lines • 2.79 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. =========
import { createAsyncContext } from "../utils/async_context.js";
import { MemoryExhausted } from "./errors.js";
/**
* The max_memory a workspace runs under when it names none: with the 32 MB
* read cache, 64 MB a workspace, 32 of them on a 2 GiB machine. Mirrors
* Python's MAX_MEMORY.
*/
export const MAX_MEMORY = 32 * 1024 * 1024;
/**
* A workspace's `max_memory` and the bytes its stores hold.
*
* What the workspace stores is counted exactly, by the stores themselves,
* and `held` sums it when asked, so nothing is charged or released here and
* the count cannot drift. An object a command builds while it runs must fit
* in what is left (`room`). Mirrors Python's `MemoryBudget`.
*/
export class MemoryBudget {
limit;
held;
constructor(limit, held) {
this.limit = limit;
this.held = held;
}
/** The bytes left under the limit, never below 0. */
room() {
return Math.max(this.limit - this.held(), 0);
}
}
// The budget of the workspace a line or an op runs in, null for no cap.
const budget = createAsyncContext();
/**
* `fn` run under a workspace's memory budget, which what it stores and every
* object it builds are checked against. Mirrors Python's `run_with_memory`.
*/
export function runWithMemory(memory, fn) {
return Promise.resolve(budget.run(memory, fn));
}
/**
* The bytes left in the running workspace's budget, null for no cap. A
* browser cannot tell one task's binding from another's, so there it is the
* least any live budget has left. Mirrors Python's `memory_room`.
*/
export function memoryRoom() {
let room = null;
for (const live of budget.liveStores()) {
if (live !== null)
room = Math.min(room ?? Infinity, live.room());
}
return room;
}
/**
* Refuse an object that grew to `size` bytes past what the running
* workspace's budget has left. Mirrors Python's `check_memory`.
*/
export function checkMemory(size) {
const room = memoryRoom();
if (room !== null && size > room)
throw new MemoryExhausted();
}
//# sourceMappingURL=memory.js.map