UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

55 lines • 2.82 kB
// ========= 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 { ContentType } from "../../types.js"; import { NAME_MAX_BYTES, byteLength, sanitizeLabel } from "../../utils/sanitize.js"; import { Slot, Scope } from "../hierarchy/scope.js"; import { CORPUS } from "./constants.js"; const TITLE_MAX_CHARS = 100; export const DATE_LEN = 10; const sanitizeTitle = (title, maxBytes) => sanitizeLabel(title, { fallback: 'Untitled', maxLen: TITLE_MAX_CHARS, maxBytes }); /** * The tree of a Google app mount: its corpora and their files. One * description per app: readdir, stat, read and unlink all classify through * it, so the file surface and the write surface cannot disagree about what a * path means. Sheets, Docs and Slides differ only in the codec of a file * name. The name splits on its first `__`: the title is sanitized and holds * none, and a Drive file id can. Mirrors Python's `app_scopes`. */ export function appScopes(fileName) { return [ new Scope({ kind: 'corpus', segments: [new Slot('corpus', CORPUS)], probed: false }), new Scope({ kind: 'file', segments: [new Slot('corpus', CORPUS), new Slot('name', fileName, 'file_id', false, 'first')], leaf: true, filetype: ContentType.JSON, }), ]; } /** * Build an app file's name from its title, id and modified date. * * The title takes whatever of the 255-byte NAME_MAX the date, the id and the * suffix leave, rather than a flat character count: those are the same number * only for ASCII, and a 100-character CJK title rendered a name ext4 and APFS * reject outright. The id never gives, so the name keeps addressing the file * -- same rule as gcal's event filenames. Sheets, Docs and Slides differ only * in the suffix. Mirrors Python's `app_filename`. */ export function appFilename(title, fileId, modifiedTime, suffix) { const lead = modifiedTime.length >= DATE_LEN ? `${modifiedTime.slice(0, DATE_LEN)}_` : ''; const fixed = byteLength(lead) + 2 + byteLength(fileId) + suffix.length; return `${lead}${sanitizeTitle(title, NAME_MAX_BYTES - fixed)}__${fileId}${suffix}`; } //# sourceMappingURL=scope.js.map