mirror of
https://github.com/earendil-works/pi.git
synced 2026-10-02 08:44:38 +08:00
Generation offers active registered tools through positional system entries and hands a tool-calling answer to parallel or sequential pi.tool tasks and a pi.post-tools task that applies addTools/terminate and continues the run. Tool tasks validate, run beforeTool/afterTool, record intent with the replay policy, publish bounded, sanitized, adaptively throttled progress in pi.live.tools, and write results with a rendered diagnostics block. Hook dispatch with conversation and subtree scopes, prepareArguments, HarnessOptions.env, and read/bash/edit/write tools in pi-durable/tools. The env shell now streams raw output and spills past thresholds; its bounded capture and publisher are removed.
49 lines
2.1 KiB
TypeScript
49 lines
2.1 KiB
TypeScript
import { readFile } from "node:fs/promises";
|
|
import { dirname, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const sourceRoot = fileURLToPath(new URL("../src", import.meta.url));
|
|
|
|
async function sourceGraph(entry: string): Promise<Set<string>> {
|
|
const visited = new Set<string>();
|
|
const pending = [resolve(sourceRoot, entry)];
|
|
while (pending.length > 0) {
|
|
const path = pending.pop()!;
|
|
if (visited.has(path)) continue;
|
|
visited.add(path);
|
|
const source = await readFile(path, "utf8");
|
|
expect(source, `${path} imports a Node built-in`).not.toMatch(/(?:from\s+|import\s*)["']node:/);
|
|
// Type-only imports are erased and load nothing.
|
|
for (const match of source.matchAll(/\b(import|export)(\s+type\b)?[^;"']*?(?:from\s*)?["'](\.[^"']+)["']/g)) {
|
|
if (match[2] === undefined) pending.push(resolve(dirname(path), match[3]));
|
|
}
|
|
}
|
|
return visited;
|
|
}
|
|
|
|
describe("durable storage runtime boundaries", () => {
|
|
it("keeps the package root limited to portable core storage", async () => {
|
|
const graph = await sourceGraph("index.ts");
|
|
expect([...graph].some((path) => path.includes("/env/"))).toBe(false);
|
|
expect([...graph].some((path) => path.includes("/storage/jsonl/"))).toBe(false);
|
|
expect([...graph].some((path) => path.includes("/storage/sqlite/"))).toBe(false);
|
|
});
|
|
|
|
it("keeps the portable SQLite subpath free of Node imports", async () => {
|
|
const graph = await sourceGraph("storage/sqlite/index.ts");
|
|
expect([...graph].some((path) => path.endsWith("/storage/sqlite/node.ts"))).toBe(false);
|
|
});
|
|
|
|
it("keeps the portable environment subpath free of Node imports", async () => {
|
|
const graph = await sourceGraph("env/index.ts");
|
|
expect([...graph].some((path) => path.endsWith("/env/node.ts"))).toBe(false);
|
|
});
|
|
|
|
it("keeps the portable JSONL subpath free of Node imports", async () => {
|
|
const graph = await sourceGraph("storage/jsonl/index.ts");
|
|
expect([...graph].some((path) => path.endsWith("/storage/jsonl/node.ts"))).toBe(false);
|
|
expect([...graph].some((path) => path.endsWith("/env/node.ts"))).toBe(false);
|
|
});
|
|
});
|