From 9fd6498ba6d11387bb8b10088bbd079dd15fd797 Mon Sep 17 00:00:00 2001 From: chrmc40 Date: Sun, 28 Jun 2026 20:49:04 -0700 Subject: [PATCH] Publish snapshot: v1->v2 character port + accumulated fixes - Tag-builder: port ~1,477 v1 characters into the v2 chip format so the character picker shows 1,486 characters (was 9); 1,390 carry rich per-chip descriptions restructured from each character's own bio. Adds scripts/port_v1_characters_to_v2.py. - Ideogram: rewrite caption to the real Ideogram-4 schema + broaden refusal detection; sampler updates. - Pose-studio, regional-detailer, attention-couple: assorted fixes. - Add validate_templates / test_regions / test_crop_windows scripts. --- build-src/codemirror-entry.mjs | 19 +- core/compiler.py | 77 ++++- core/crop_windows.py | 29 ++ core/pose_api.py | 44 ++- data/tag-builder/tag-builder.db | Bin 42999808 -> 43855872 bytes data/templates/ideogram-t2i-regionbox.json | 2 +- js/codemirror.bundle.js | 8 +- js/lib/model-settings-bridge.js | 40 +-- js/lib/region-highlight.js | 23 +- js/lib/svelte/assets/promptchain-svelte.css | 1 + js/lib/svelte/promptchain-node.js | 53 +++- js/main.js | 2 + js/pose-studio.js | 61 +++- js/region-box.js | 8 +- nodes/attention_couple.py | 30 +- nodes/attention_couple_zimage.py | 4 +- nodes/ideogram_caption.py | 239 +++++++++------ nodes/ideogram_sampler.py | 38 ++- nodes/pose_studio.py | 35 ++- nodes/regional_detailer.py | 37 ++- pyproject.toml | 2 +- scripts/port_v1_characters_to_v2.py | 272 ++++++++++++++++++ scripts/test_crop_windows.py | 94 ++++++ scripts/test_regions.py | 124 ++++++++ scripts/validate_templates.py | 154 ++++++++++ svelte-src/components/node/OutputPanel.svelte | 2 +- .../components/node/PromptOutput.svelte | 32 ++- svelte-src/node-main.svelte.js | 2 + .../pcr_cnaux/depth_anything_v2/__init__.py | 4 +- vendor/pcr_cnaux/teed/__init__.py | 3 +- 30 files changed, 1246 insertions(+), 193 deletions(-) create mode 100644 core/crop_windows.py create mode 100644 scripts/port_v1_characters_to_v2.py create mode 100644 scripts/test_crop_windows.py create mode 100644 scripts/test_regions.py create mode 100644 scripts/validate_templates.py diff --git a/build-src/codemirror-entry.mjs b/build-src/codemirror-entry.mjs index e48995b..06f9fcb 100644 --- a/build-src/codemirror-entry.mjs +++ b/build-src/codemirror-entry.mjs @@ -783,15 +783,26 @@ function formatRegionInner(inner) { } function formatWithRegions(text) { - const OPEN = /\$[A-Za-z]\w*\s*\{/g; + const OPEN = /\$\w+\s*\{/g; // \w+ to match the compiler/binding rule (digit-leading names too) let result = ""; let last = 0; let m; while ((m = OPEN.exec(text)) !== null) { const openBrace = m.index + m[0].length - 1; - const close = text.indexOf("}", openBrace + 1); - if (close === -1) continue; // unterminated — leave it for the linter to flag - const name = m[0].match(/^\$[A-Za-z]\w*/)[0]; + // Find the region's close by brace DEPTH, not the first `}` — otherwise a + // wildcard brace ({a|b}) inside the body ends the region early, spilling the + // rest into the wildcard formatter and splitting a phrase across lines (which + // the newline→comma rule then turns into an unwanted comma). + let depth = 1, j = openBrace + 1; + while (j < text.length && depth > 0) { + const ch = text[j]; + if (ch === "{") depth++; + else if (ch === "}") depth--; + j++; + } + if (depth !== 0) continue; // unterminated — leave it for the linter to flag + const close = j - 1; + const name = m[0].match(/^\$\w+/)[0]; const before = text.slice(last, m.index); if (before.trim()) result += formatPromptText(before).trim() + "\n\n"; const inner = text.slice(openBrace + 1, close); diff --git a/core/compiler.py b/core/compiler.py index d3476bf..3a43dbf 100644 --- a/core/compiler.py +++ b/core/compiler.py @@ -74,8 +74,48 @@ def strip_comments(text: str) -> str: # ============================================================================= # A `$name { body }` group pins `body` to the mannequin identified by `name` # (e.g. $mannequin1). Anything OUTSIDE every group is the shared/global prompt. -# Non-greedy body so adjacent groups don't merge; DOTALL so a group spans lines. -MANNEQUIN_RE = re.compile(r"\$(\w+)\s*\{(.*?)\}", re.DOTALL) +# The close brace is matched by DEPTH (not the first `}`) so a wildcard or +#