Files
ComfyAssets-ComfyUI_PromptM…/tests/js/support/generation-params-oracle.mjs
Vito Sansevero b83c3556d8 feat(parse): port the browser generation-parameter parser to Python
Adds utils/generation_params.py, a line-for-line port of
extractGenerationParams in web/js/comfy-metadata.js, the parser behind
the gallery, admin and metadata pages. The scan and live monitor can use
it so every surface reads prompts the same way. The JavaScript parser is
unchanged.

The port reproduces the JavaScript value semantics the result depends on
(property order, truthiness, String(), trim(), strict equality, Map keys,
JSON.parse number rounding, and the inputs on which it throws), and runs
its recursive tracing on an explicit stack so crafted graphs cannot
exhaust the Python stack.

Tests:
- behaviour tests for each tracing rule, with JavaScript results as
  expected values, including the visit-limit boundary;
- golden vectors of the JavaScript parser's results for every named case
  and every PNG fixture, so the comparison runs without Node;
- a live comparison against the JavaScript parser when Node is present;
- a randomized differential test over 9,000 generated graphs and
  workflows, coherent and corrupted, including inputs where the
  JavaScript throws.

Five deliberate porting mistakes (trim, truthiness, prepend handling,
visit limit, pair slot) each fail the tests. On a 38,602-file output
folder, all 18,491 files with a workflow give identical results.
2026-10-19 20:22:53 -07:00

33 lines
1.5 KiB
JavaScript

// Runs the legacy browser parser (comfy-metadata.js extractGenerationParams) on
// one JSON case per input line and prints one JSON result per line. The Python
// port (utils/generation_params.py) must produce the same results.
//
// Input line: {"prompt": <text or null>, "workflow": <text or null>}
// Each present record is parsed with JSON.parse; a record that fails
// to parse is treated as absent, as the browser pages do.
// Output line: {"ok": true, "result": {...}} or {"ok": false} when the parser throws.
import path from 'node:path';
import fs from 'node:fs';
import { createRequire } from 'node:module';
import { fileURLToPath } from 'node:url';
const here = path.dirname(fileURLToPath(import.meta.url));
const require = createRequire(import.meta.url);
const { extractGenerationParams } = require(path.join(here, '..', '..', '..', 'web', 'js', 'comfy-metadata.js'));
function parsed(text) {
if (typeof text !== 'string') return undefined;
try { return JSON.parse(text); } catch { return undefined; }
}
for (const line of fs.readFileSync(0, 'utf8').split('\n')) {
if (!line.trim()) continue;
const item = JSON.parse(line), data = {};
const prompt = parsed(item.prompt), workflow = parsed(item.workflow);
if (prompt !== undefined) data.prompt = prompt;
if (workflow !== undefined) data.workflow = workflow;
let out;
try { out = { ok: true, result: extractGenerationParams(data) }; } catch { out = { ok: false }; }
process.stdout.write(JSON.stringify(out) + '\n');
}