A file chosen on the Inspect page now shows the prompts and resolution the server's inspector gives the same records: buildLocalPayload takes its roles from the local resolver instead of the interim open roles, so the legacy fill applies exactly where it does for Images. The resolver reads the server's own node table. The page fetches web/js/inspection-semantics.json once through the API client as it mounts, before any selection; the static route serves that one JSON file by exact path (every other JSON stays forbidden). A table that cannot be fetched answers "The inspector's node table is unavailable." as the server does, and a later selection asks again. The Copy settings summary deviation is numbered D117.
44 lines
2.4 KiB
JavaScript
44 lines
2.4 KiB
JavaScript
// web/js/workspace/local-semantics.mjs (#249 local Inspect, PR L3 Task 10): the node table local Inspect resolves
|
|
// with is the server's own web/js/inspection-semantics.json, fetched once through the API client before a file is
|
|
// chosen. A table that cannot be fetched or used answers as the server does when its table is unusable.
|
|
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
|
|
const TABLE = fs.readFileSync(new URL("../../web/js/inspection-semantics.json", import.meta.url), "utf8");
|
|
let instance = 0;
|
|
/** A fresh module instance (its cache is per page) with `fetch` and the API client stubbed. */
|
|
async function load(respond) {
|
|
const calls = [];
|
|
globalThis.window = { ApiClient: { resolveUrl: (path) => `/proxy${path}` } };
|
|
globalThis.fetch = async (url, init) => { calls.push([url, init]); return respond(); };
|
|
const module = await import(`../../web/js/workspace/local-semantics.mjs?instance=${++instance}`);
|
|
return { module, calls };
|
|
}
|
|
test.after(() => { delete globalThis.window; delete globalThis.fetch; });
|
|
|
|
test("the table is fetched once through the API client and compiled", async () => {
|
|
const { module, calls } = await load(() => new Response(TABLE, { status: 200 }));
|
|
const [first, second] = await Promise.all([module.loadInspectionSemantics(), module.loadInspectionSemantics()]);
|
|
assert.equal(first, second);
|
|
assert.ok(first.samplers.has("KSampler"));
|
|
assert.equal(await module.loadInspectionSemantics(), first);
|
|
assert.deepEqual(calls, [["/proxy/prompt_manager/js/inspection-semantics.json", { credentials: "same-origin" }]]);
|
|
});
|
|
|
|
test("a failed or unusable table is null, and a later selection asks again", async () => {
|
|
for (const respond of [() => new Response("nope", { status: 404 }), () => new Response("{\"schema\": 2}", { status: 200 }), () => { throw new TypeError("offline"); }]) {
|
|
const { module, calls } = await load(respond);
|
|
assert.equal(await module.loadInspectionSemantics(), null);
|
|
assert.equal(await module.loadInspectionSemantics(), null);
|
|
assert.equal(calls.length, 2);
|
|
}
|
|
});
|
|
|
|
test("without the API client nothing is fetched", async () => {
|
|
const { module, calls } = await load(() => new Response(TABLE));
|
|
delete globalThis.window;
|
|
assert.equal(await module.loadInspectionSemantics(), null);
|
|
assert.deepEqual(calls, []);
|
|
});
|