UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

61 lines (60 loc) • 2.2 kB
import { homeViewsOf } from "./read-deny-home.js"; export const DIRECTORY_LISTING_MAX_ENTRIES = 1000; export function createEntryDenyJudge(env, deny, signal) { const views = homeViewsOf(env, deny, signal); return async (path, leaf) => { const hit = deny.matchPath(path); if (hit) return hit; const view = await views.of(path, leaf !== undefined ? { leaf } : undefined); return view !== undefined ? deny.matchPath(view) : null; }; } export async function enumerateDirectory(env, dir, judge, signal) { const listing = await env.listDir(dir, signal); if (!listing.ok) return listing; const infos = [...listing.value].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0)); const kept = []; let omitted = 0; const omittedPatterns = []; let incomplete = false; for (const info of infos) { if (signal?.aborted) { incomplete = true; break; } const hit = judge === undefined ? null : await judge(info.path, info.kind === "directory" ? undefined : "file"); if (hit) { omitted++; if (!omittedPatterns.includes(hit.pattern)) omittedPatterns.push(hit.pattern); continue; } kept.push({ name: info.name, kind: info.kind }); } return { ok: true, value: { entries: kept.slice(0, DIRECTORY_LISTING_MAX_ENTRIES), more: Math.max(0, kept.length - DIRECTORY_LISTING_MAX_ENTRIES), omitted, omittedPatterns, incomplete, }, }; } const LABEL_UNSAFE = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u; export function quoteDataLabel(label) { let out = ""; for (const ch of JSON.stringify(label)) { out += LABEL_UNSAFE.test(ch) ? `\\u${ch.codePointAt(0).toString(16).padStart(4, "0")}` : ch; } return out; } export function renderDirectoryListing(l) { const lines = l.entries.map((e) => `${LABEL_UNSAFE.test(e.name) ? quoteDataLabel(e.name) : e.name}${e.kind === "directory" ? "/" : ""}`); if (l.more > 0) lines.push(`… and ${l.more} more entries`); return lines.join("\n"); }