diff options
| author | Agando <roduccomm@gmail.com> | 2026-10-17 20:17:28 +0200 |
|---|---|---|
| committer | Agando <roduccomm@gmail.com> | 2026-10-17 20:17:28 +0200 |
| commit | 526c420f4591f0a58f805b473fa76d3da2981eae (patch) | |
| tree | 9c8f3bb3bf5f329b81647f064d6c87554850d196 /scripts/gen-floating-designer-registry.py | |
| parent | c3f89abb448021ecf894b27692dba0a7dc2ff8e3 (diff) | |
newos4: floating-ui-designer v3 — repair 12 escape-mangled JS sites, rebuild 344-cmd registry (124->344), quoting/import/preset UX fixes; add Node harness + registry generator; floating-ui skill JSON de-piped
Diffstat (limited to 'scripts/gen-floating-designer-registry.py')
| -rw-r--r-- | scripts/gen-floating-designer-registry.py | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/scripts/gen-floating-designer-registry.py b/scripts/gen-floating-designer-registry.py new file mode 100644 index 0000000..1b150d6 --- /dev/null +++ b/scripts/gen-floating-designer-registry.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +"""gen-floating-designer-registry.py — Task 4 of the v2->v3 repair plan. (v2) + +Rebuilds the floating-ui-designer CMDS registry from ground truth: + * union of `commands['X']` registrations in modules/core + modules/ext + (bundle/worker files skipped), and + * terminal.js dispatch builtins (`cmd === 'x'`). + +Emits /tmp/fui_cmds_snippet.txt with one JS line per command: + ['name','desc','cat',1], +Descriptions are re-escaped safely: apostrophes -> \u2019, backslashes -> \u005C +(no raw backslash pairs ever enter the page). Prints acceptance diagnostics. +""" +import os, re +from collections import Counter + +BASE = '/var/www/webx11.duckdns.org/spaces/newos4' +OUT = '/tmp/fui_cmds_snippet.txt' + +files = [] +for d in ('modules/core', 'modules/ext'): + dd = os.path.join(BASE, d) + for f in sorted(os.listdir(dd)): + if not f.endswith('.js'): + continue + if 'bundle' in f or 'worker' in f: + continue + files.append(os.path.join(d, f)) + +texts = {} +for rel in files: + try: + texts[rel] = open(os.path.join(BASE, rel), encoding='utf-8', errors='replace').read() + except Exception as e: + print('skip', rel, e) + +cmd_re = re.compile(r"commands\['([^']+)'\]\s*=") +src_of = {} +for rel, txt in texts.items(): + for name in cmd_re.findall(txt): + src_of.setdefault(name, set()).add(rel) + +disp = set() +t = texts.get('modules/core/terminal.js', '') +for m in re.finditer(r"cmd === '([a-z0-9-]+)'", t): + disp.add(m.group(1)) +for n in disp: + src_of.setdefault(n, set()).add('modules/core/terminal.js') + +ALL = sorted(src_of.keys()) + +def cat_for(rels): + joined = ' '.join(rels) + rules = [ + (('aiassist', 'aiasm', 'smartctx', 'chatstudio', 'ollama'), 'ai'), + (('agent-registry', 'orchestrator', 'leases', 'memory-graph', 'world-model'), 'agents'), + (('module-fs', 'busybox', 'shell', 'filemgr', 'editor', 'finder', 'diff', 'neural-vfs', 'cryptogzip'), 'files'), + (('searxng', 'fetcher', 'webdav'), 'network'), + (('calc', 'mindmap', 'three', 'media', 'voice', 'wpm', 'tutorial', 'console'), 'tools'), + (('floating', 'theme', 'kanban'), 'ui'), + (('system', 'config', 'modmgr', 'debug-supervisor', 'predictor', 'servermon', 'sandbox', 'secret-vault', 'terminal'), 'system'), + ] + for keys, cat in rules: + if any(k in joined for k in keys): + return cat + return 'system' + +DESC_FALLBACK = 'Terminal command' + +def desc_for(name): + pat = re.compile(r"'" + re.escape(name) + r"'\s*:\s*'((?:[^'\\]|\\.){1,200})'") + for rel in sorted(texts.keys()): + m = pat.search(texts[rel]) + if not m: + continue + raw = m.group(1) + # unescape source-level escaping: \\ -> placeholder, \' and \" -> quote + raw = raw.replace('\\\\', '\x01') + raw = raw.replace("\\'", "'").replace('\\"', '"') + raw = raw.replace('\x01', '\\') + # strip control chars + raw = ''.join(' ' if ord(c) < 32 else c for c in raw) + if '\u2014' in raw: + raw = raw.split('\u2014', 1)[1].strip() + if not raw or raw.lower() == name: + continue + if len(raw) > 90: + raw = raw[:87].rstrip() + '...' + return raw + return DESC_FALLBACK + +entries = [] +for n in ALL: + d = desc_for(n) + d = d.replace('\\', '\\u005C').replace("'", '\\u2019') + entries.append((cat_for(src_of[n]), n, d)) + +entries.sort(key=lambda e: (e[0], e[1])) + +cnt = Counter(c for c, _, _ in entries) +print('total=%d' % len(entries)) +for k in sorted(cnt): + print(' %-8s %d' % (k, cnt[k])) + +want = ['session-new', 'health-check', 'doctor', 'uptime', 'ai-stop', 'kanban', 'webdav-browser', 'vfs-export', 'fetch'] +bad = ['new-session', 'clipboard-history', 'web', 'save', 'load', 'import', 'svg'] +have = set(e[1] for e in entries) +print('missing:', [w for w in want if w not in have]) +print('excluded-present:', [b for b in bad if b in have]) +print('no-desc fallback count:', sum(1 for _, _, d in entries if d == DESC_FALLBACK)) + +assert len(entries) >= 330, 'TOO FEW COMMANDS: %d' % len(entries) + +with open(OUT, 'w', encoding='utf-8') as f: + for cat, n, d in entries: + f.write("['%s','%s','%s',1],\n" % (n, d, cat)) +print('WROTE', OUT) |