@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
64 lines • 2.8 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 { mountedPath } from "../../utils/key_prefix.js";
import { rstripSlash, stripSlash } from "../../utils/slash.js";
import { searchFiles } from "./api.js";
import { DropboxApiError } from "./client.js";
import { checkPath, dropboxPathOf } from "./paths.js";
/**
* The files under `under` Dropbox search returns. Hits are
* kept inside each scope on `path_lower` (Dropbox paths are case-insensitive)
* and keyed from `path_display`. Null whenever the answer may miss a match:
* an API failure, the 10,000-match ceiling, or no hit at all, since Dropbox
* indexes a write some time after it lands.
*
* Dropbox searches the text it extracted, not the bytes grep reads, so the
* answer can leave out a file that holds the text: an office file, PDF or
* archive, the end of a large file, a word Dropbox splits differently
* (`foo.bar`), or a recent write.
*
* Mirrors Python's `files_containing`.
*/
export async function filesContaining(accessor, text, under) {
const root = accessor.rootPath;
const found = [];
for (const p of under) {
await checkPath(accessor, p);
const scopeApi = dropboxPathOf(accessor, p);
let results;
try {
const out = await searchFiles(accessor.tokenManager, text, { path: scopeApi });
if (out.truncated)
return null;
results = out.paths;
}
catch (err) {
if (!(err instanceof DropboxApiError))
throw err;
console.debug(`dropbox search failed (${String(err)}); reading every file`);
return null;
}
const scopeLower = scopeApi.toLowerCase();
const scopePrefix = rstripSlash(scopeLower) + '/';
for (const [lower, display] of results) {
if (lower !== scopeLower && !lower.startsWith(scopePrefix))
continue;
const key = stripSlash(display.slice(root.length));
if (key)
found.push(mountedPath(p, `/${key}`));
}
}
return found.length > 0 ? found : null;
}
//# sourceMappingURL=search.js.map