tzero-mcp 10.7.0 → 10.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +589 -0
- package/CONTRIBUTING.md +71 -0
- package/README.md +25 -17
- package/bin/postinstall.js +34 -0
- package/bin/tzero-mcp.js +16 -19
- package/bin/tzero.js +14 -19
- package/index.d.ts +24 -0
- package/index.js +7 -3
- package/package.json +24 -2
- package/src/addmcp.py +1194 -0
- package/src/main.py +60 -0
- package/src/siber_akademi_icon.py +77 -0
- package/src/tzero/jarvis/semantic_compressor.py +373 -0
- package/src/tzero.py +58 -0
- package/src/tzero_benchmark.py +475 -0
- package/src/tzero_bridge.py +362 -0
- package/src/tzero_ci.py +153 -0
- package/src/tzero_commit.py +192 -0
- package/src/tzero_cost.py +163 -0
- package/src/tzero_dashboard.py +1448 -0
- package/src/tzero_deps.py +287 -0
- package/src/tzero_drift.py +208 -0
- package/src/tzero_explain.py +240 -0
- package/src/tzero_features.py +3022 -0
- package/src/tzero_fix.py +228 -0
- package/src/tzero_fixer/__init__.py +63 -0
- package/src/tzero_fixer/amalgamation.py +334 -0
- package/src/tzero_fixer/ast_syntax_healer.py +464 -0
- package/src/tzero_fixer/ast_type_modernizer.py +288 -0
- package/src/tzero_fixer/async_io_modernizer.py +127 -0
- package/src/tzero_fixer/automated_regression_suite.py +600 -0
- package/src/tzero_fixer/benchmarks_and_diagnostics.py +174 -0
- package/src/tzero_fixer/ci_cd_self_healing_gate.py +246 -0
- package/src/tzero_fixer/code_duplicity_and_refactorer.py +151 -0
- package/src/tzero_fixer/code_smells_healer.py +260 -0
- package/src/tzero_fixer/cwe_remediator.py +171 -0
- package/src/tzero_fixer/dead_code_eliminator.py +150 -0
- package/src/tzero_fixer/dependency_vulnerability_auditor.py +309 -0
- package/src/tzero_fixer/git_advanced_surgeon.py +280 -0
- package/src/tzero_fixer/hardware_and_disk_doctor.py +325 -0
- package/src/tzero_fixer/import_graph_healer.py +412 -0
- package/src/tzero_fixer/interactive_tui.py +91 -0
- package/src/tzero_fixer/knowledge_base.py +295 -0
- package/src/tzero_fixer/knowledge_base_extended.py +940 -0
- package/src/tzero_fixer/linters_and_static_analyzer.py +307 -0
- package/src/tzero_fixer/mcp_server.py +447 -0
- package/src/tzero_fixer/models.py +385 -0
- package/src/tzero_fixer/orchestrator.py +375 -0
- package/src/tzero_fixer/os_doctor.py +502 -0
- package/src/tzero_fixer/packaging_abi_surgeon.py +323 -0
- package/src/tzero_fixer/pc_fixer_doctor.py +599 -0
- package/src/tzero_fixer/performance_and_memory_profiler.py +274 -0
- package/src/tzero_fixer/polyglot_ast_parsers.py +313 -0
- package/src/tzero_fixer/polyglot_build_healer.py +364 -0
- package/src/tzero_fixer/polyglot_config_healer.py +318 -0
- package/src/tzero_fixer/polyglot_doctor.py +372 -0
- package/src/tzero_fixer/polyglot_linters.py +619 -0
- package/src/tzero_fixer/polyglot_schema_validator.py +305 -0
- package/src/tzero_fixer/security_cwe_database.py +444 -0
- package/src/tzero_fixer/security_deep_rules.py +114 -0
- package/src/tzero_fixer/security_rules_catalog.py +110 -0
- package/src/tzero_fixer/security_zero_leak.py +326 -0
- package/src/tzero_fixer/smart_patch_recommender.py +223 -0
- package/src/tzero_fixer/synthetic_workspace_generator.py +220 -0
- package/src/tzero_fixer/system_diagnostics_extended.py +493 -0
- package/src/tzero_fixer/system_repair_recipes.py +447 -0
- package/src/tzero_fixer/venv_doctor.py +309 -0
- package/src/tzero_gateway.py +885 -0
- package/src/tzero_guard.py +243 -0
- package/src/tzero_infra.py +274 -0
- package/src/tzero_jarvis/__init__.py +124 -0
- package/src/tzero_jarvis/causal_graph.py +310 -0
- package/src/tzero_jarvis/graph_visualizer.py +395 -0
- package/src/tzero_jarvis/hybrid_search.py +214 -0
- package/src/tzero_jarvis/latent_press.py +137 -0
- package/src/tzero_jarvis/memory_consolidation.py +212 -0
- package/src/tzero_jarvis/minhash_lsh.py +184 -0
- package/src/tzero_jarvis/orchestrator.py +335 -0
- package/src/tzero_jarvis/self_healing.py +308 -0
- package/src/tzero_jarvis/semantic_compressor.py +887 -0
- package/src/tzero_jarvis/swarm.py +261 -0
- package/src/tzero_jarvis/swarm_bft.py +144 -0
- package/src/tzero_jarvis/workspace_orchestrator.py +1167 -0
- package/src/tzero_jarvis/zero_key_router.py +173 -0
- package/src/tzero_mcp.py +4858 -0
- package/src/tzero_neural_cortex.py +1425 -0
- package/src/tzero_packer.py +370 -0
- package/src/tzero_patch.py +624 -0
- package/src/tzero_pc_fixer.py +12657 -0
- package/src/tzero_pipe.py +95 -0
- package/src/tzero_polyglot.py +422 -0
- package/src/tzero_reachability.py +272 -0
- package/src/tzero_replay.py +141 -0
- package/src/tzero_security.py +570 -0
- package/src/tzero_snapshot.py +258 -0
- package/src/tzero_stubs.py +313 -0
- package/src/tzero_superdesign.py +774 -0
- package/src/tzero_sync.py +241 -0
- package/src/tzero_task_benchmark.py +363 -0
- package/src/tzero_tui.py +244 -0
- package/src/tzero_v3.py +9435 -0
|
@@ -0,0 +1,774 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""Siber Akademi T-Zero — Superdesign MCP Orchestrator Module.
|
|
3
|
+
|
|
4
|
+
Brings the open-source Superdesign AI design orchestrator capabilities natively to
|
|
5
|
+
MCP clients (Claude Code, Cursor, Antigravity IDE, Windsurf).
|
|
6
|
+
|
|
7
|
+
Operates as a design orchestrator providing structured specifications, design system
|
|
8
|
+
extraction, iterative refinement, and interactive HTML galleries without requiring
|
|
9
|
+
external API keys or cloud dependencies.
|
|
10
|
+
|
|
11
|
+
Developer: Toprak Ahmet Aydoğmuş (Siber Akademi)
|
|
12
|
+
License: MIT
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import html
|
|
18
|
+
import json
|
|
19
|
+
import os
|
|
20
|
+
import re
|
|
21
|
+
import time
|
|
22
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
23
|
+
|
|
24
|
+
VALID_DESIGN_TYPES = {"ui", "wireframe", "component", "logo", "icon"}
|
|
25
|
+
VALID_FRAMEWORKS = {"html", "react", "vue"}
|
|
26
|
+
|
|
27
|
+
DEFAULT_DESIGN_SYSTEM = {
|
|
28
|
+
"$schema": "https://superdesign.dev/schema/design-system.json",
|
|
29
|
+
"name": "T-Zero Modern Design System",
|
|
30
|
+
"version": "1.0.0",
|
|
31
|
+
"theme": "dark",
|
|
32
|
+
"colors": {
|
|
33
|
+
"background": {
|
|
34
|
+
"canvas": "#090d16",
|
|
35
|
+
"surface": "#0f172a",
|
|
36
|
+
"surface_hover": "#1e293b",
|
|
37
|
+
"surface_active": "#334155"
|
|
38
|
+
},
|
|
39
|
+
"border": {
|
|
40
|
+
"subtle": "#1e293b",
|
|
41
|
+
"strong": "#334155",
|
|
42
|
+
"focus": "#6366f1"
|
|
43
|
+
},
|
|
44
|
+
"text": {
|
|
45
|
+
"primary": "#f8fafc",
|
|
46
|
+
"secondary": "#94a3b8",
|
|
47
|
+
"tertiary": "#64748b",
|
|
48
|
+
"inverse": "#090d16"
|
|
49
|
+
},
|
|
50
|
+
"accent": {
|
|
51
|
+
"primary": "#38bdf8",
|
|
52
|
+
"primary_hover": "#0ea5e9",
|
|
53
|
+
"secondary": "#818cf8",
|
|
54
|
+
"success": "#34d399",
|
|
55
|
+
"warning": "#fbbf24",
|
|
56
|
+
"danger": "#f87171"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"typography": {
|
|
60
|
+
"fonts": {
|
|
61
|
+
"ui": "Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
|
62
|
+
"mono": "'Fira Code', 'Geist Mono', Consolas, Monaco, monospace",
|
|
63
|
+
"heading": "Inter, -apple-system, BlinkMacSystemFont, sans-serif"
|
|
64
|
+
},
|
|
65
|
+
"scale": {
|
|
66
|
+
"xs": "0.75rem",
|
|
67
|
+
"sm": "0.875rem",
|
|
68
|
+
"base": "1rem",
|
|
69
|
+
"lg": "1.125rem",
|
|
70
|
+
"xl": "1.25rem",
|
|
71
|
+
"2xl": "1.5rem",
|
|
72
|
+
"3xl": "1.875rem",
|
|
73
|
+
"4xl": "2.25rem"
|
|
74
|
+
},
|
|
75
|
+
"weights": {
|
|
76
|
+
"normal": "400",
|
|
77
|
+
"medium": "500",
|
|
78
|
+
"semibold": "600",
|
|
79
|
+
"bold": "700"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"spacing": {
|
|
83
|
+
"1": "0.25rem",
|
|
84
|
+
"2": "0.5rem",
|
|
85
|
+
"3": "0.75rem",
|
|
86
|
+
"4": "1rem",
|
|
87
|
+
"6": "1.5rem",
|
|
88
|
+
"8": "2rem",
|
|
89
|
+
"12": "3rem",
|
|
90
|
+
"16": "4rem"
|
|
91
|
+
},
|
|
92
|
+
"radii": {
|
|
93
|
+
"sm": "0.25rem",
|
|
94
|
+
"md": "0.5rem",
|
|
95
|
+
"lg": "0.75rem",
|
|
96
|
+
"xl": "1rem",
|
|
97
|
+
"full": "9999px"
|
|
98
|
+
},
|
|
99
|
+
"shadows": {
|
|
100
|
+
"sm": "0 1px 2px 0 rgba(0, 0, 0, 0.4)",
|
|
101
|
+
"md": "0 4px 6px -1px rgba(0, 0, 0, 0.5), 0 2px 4px -2px rgba(0, 0, 0, 0.5)",
|
|
102
|
+
"lg": "0 10px 15px -3px rgba(0, 0, 0, 0.6), 0 4px 6px -4px rgba(0, 0, 0, 0.6)"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _slugify(text: str) -> str:
|
|
108
|
+
"""Converts a descriptive string to a filesystem-friendly slug."""
|
|
109
|
+
text = text.lower().strip()
|
|
110
|
+
text = re.sub(r"[^\w\s-]", "", text)
|
|
111
|
+
text = re.sub(r"[\s_-]+", "_", text)
|
|
112
|
+
return text[:36].strip("_") or "design"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _ensure_superdesign_dirs(workspace_path: str = ".") -> Tuple[str, str]:
|
|
116
|
+
"""Ensures that superdesign/design_iterations and superdesign/design_system exist."""
|
|
117
|
+
base_dir = os.path.join(workspace_path, "superdesign")
|
|
118
|
+
iterations_dir = os.path.join(base_dir, "design_iterations")
|
|
119
|
+
systems_dir = os.path.join(base_dir, "design_system")
|
|
120
|
+
os.makedirs(iterations_dir, exist_ok=True)
|
|
121
|
+
os.makedirs(systems_dir, exist_ok=True)
|
|
122
|
+
return iterations_dir, systems_dir
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def superdesign_generate(
|
|
126
|
+
prompt: str,
|
|
127
|
+
design_type: str = "ui",
|
|
128
|
+
variations: int = 3,
|
|
129
|
+
framework: str = "html",
|
|
130
|
+
workspace_path: str = ".",
|
|
131
|
+
) -> Dict[str, Any]:
|
|
132
|
+
"""Generates structured specifications and guidelines for the LLM to create designs."""
|
|
133
|
+
d_type = (design_type or "ui").lower().strip()
|
|
134
|
+
if d_type not in VALID_DESIGN_TYPES:
|
|
135
|
+
return {
|
|
136
|
+
"success": False,
|
|
137
|
+
"error": f"Invalid design_type '{design_type}'. Must be one of: {sorted(list(VALID_DESIGN_TYPES))}",
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
fw = (framework or "html").lower().strip()
|
|
141
|
+
if fw not in VALID_FRAMEWORKS:
|
|
142
|
+
fw = "html"
|
|
143
|
+
|
|
144
|
+
variations = max(1, min(int(variations or 3), 5))
|
|
145
|
+
iterations_dir, _ = _ensure_superdesign_dirs(workspace_path)
|
|
146
|
+
slug = _slugify(prompt)
|
|
147
|
+
|
|
148
|
+
ext_map = {
|
|
149
|
+
"ui": ".html",
|
|
150
|
+
"wireframe": ".html",
|
|
151
|
+
"component": ".html" if fw == "html" else (".tsx" if fw == "react" else ".vue"),
|
|
152
|
+
"logo": ".svg",
|
|
153
|
+
"icon": ".svg",
|
|
154
|
+
}
|
|
155
|
+
ext = ext_map.get(d_type, ".html")
|
|
156
|
+
|
|
157
|
+
files_to_create = []
|
|
158
|
+
for i in range(1, variations + 1):
|
|
159
|
+
filename = f"{d_type}_{slug}_v{i}{ext}"
|
|
160
|
+
rel_path = os.path.join("superdesign", "design_iterations", filename).replace("\\", "/")
|
|
161
|
+
files_to_create.append({
|
|
162
|
+
"variation": i,
|
|
163
|
+
"filename": filename,
|
|
164
|
+
"file_path": rel_path,
|
|
165
|
+
"full_path": os.path.abspath(os.path.join(iterations_dir, filename)),
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
guidelines = [
|
|
169
|
+
"1. Avoid generic AI aesthetics (neon glow spam, wall-of-emojis, tacky cyberpunk badges).",
|
|
170
|
+
"2. Use curated, accessible color palettes: slate/zinc neutral surfaces (#090d16, #0f172a, #1e293b).",
|
|
171
|
+
"3. Typography: Prioritize modern clean typefaces (Inter, Geist, Fira Code monospace).",
|
|
172
|
+
"4. Layout: Implement responsive mobile-first flexbox/grid with clear visual hierarchy.",
|
|
173
|
+
"5. Self-Contained: Include all CSS and necessary SVG icons inline so each file opens standalone in any browser.",
|
|
174
|
+
]
|
|
175
|
+
if d_type == "wireframe":
|
|
176
|
+
guidelines.append("6. Wireframe Mode: Strictly monochrome (black, white, greys) with wire-box indicators for imagery.")
|
|
177
|
+
elif d_type in {"logo", "icon"}:
|
|
178
|
+
guidelines.append("6. Vector SVG: Use viewBox='0 0 24 24' (or 100 100), clean paths, stroke-width=2, and semantic layers.")
|
|
179
|
+
|
|
180
|
+
specifications = {
|
|
181
|
+
"design_orchestrator": "Superdesign MCP v1.0 (T-Zero Edition)",
|
|
182
|
+
"prompt": prompt,
|
|
183
|
+
"design_type": d_type,
|
|
184
|
+
"framework": fw,
|
|
185
|
+
"variations_requested": variations,
|
|
186
|
+
"design_system_reference": "superdesign/design_system/tzero_design_system.json",
|
|
187
|
+
"core_guidelines": guidelines,
|
|
188
|
+
"instructions_for_claude": (
|
|
189
|
+
f"Generate {variations} complete, production-ready, beautiful variations of the requested {d_type}. "
|
|
190
|
+
f"Write the output code directly into the target files listed under 'files_to_create'. "
|
|
191
|
+
"Ensure the visual presentation feels high-end, crisp, and completely free of AI slop."
|
|
192
|
+
),
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
"success": True,
|
|
197
|
+
"design_type": d_type,
|
|
198
|
+
"framework": fw,
|
|
199
|
+
"variations": variations,
|
|
200
|
+
"files_to_create": files_to_create,
|
|
201
|
+
"specifications": specifications,
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def superdesign_iterate(
|
|
206
|
+
design_file: str,
|
|
207
|
+
feedback: str,
|
|
208
|
+
variations: int = 1,
|
|
209
|
+
workspace_path: str = ".",
|
|
210
|
+
) -> Dict[str, Any]:
|
|
211
|
+
"""Generates structured iteration instructions to refine an existing design file."""
|
|
212
|
+
if not design_file or not os.path.exists(design_file):
|
|
213
|
+
return {
|
|
214
|
+
"success": False,
|
|
215
|
+
"error": f"Design file '{design_file}' was not found. Please provide an existing design file path.",
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
variations = max(1, min(int(variations or 1), 5))
|
|
219
|
+
iterations_dir, _ = _ensure_superdesign_dirs(workspace_path)
|
|
220
|
+
|
|
221
|
+
base_name = os.path.basename(design_file)
|
|
222
|
+
name_no_ext, ext = os.path.splitext(base_name)
|
|
223
|
+
# Detect version tag or append _iter
|
|
224
|
+
v_match = re.search(r"_v(\d+)$", name_no_ext)
|
|
225
|
+
current_ver = int(v_match.group(1)) if v_match else 1
|
|
226
|
+
|
|
227
|
+
target_files = []
|
|
228
|
+
for i in range(1, variations + 1):
|
|
229
|
+
next_ver = current_ver + i
|
|
230
|
+
if v_match:
|
|
231
|
+
new_name = re.sub(r"_v\d+$", f"_v{next_ver}", name_no_ext) + ext
|
|
232
|
+
else:
|
|
233
|
+
new_name = f"{name_no_ext}_v{next_ver}{ext}"
|
|
234
|
+
rel_path = os.path.join("superdesign", "design_iterations", new_name).replace("\\", "/")
|
|
235
|
+
target_files.append({
|
|
236
|
+
"variation": i,
|
|
237
|
+
"target_path": rel_path,
|
|
238
|
+
"full_path": os.path.abspath(os.path.join(iterations_dir, new_name)),
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
try:
|
|
242
|
+
with open(design_file, "r", encoding="utf-8", errors="ignore") as f:
|
|
243
|
+
original_code = f.read()
|
|
244
|
+
except Exception as e:
|
|
245
|
+
original_code = f"<!-- Error reading original file: {e} -->"
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
"success": True,
|
|
249
|
+
"design_file": design_file,
|
|
250
|
+
"feedback": feedback,
|
|
251
|
+
"variations": variations,
|
|
252
|
+
"target_files": target_files,
|
|
253
|
+
"original_code_snippet": original_code[:1200] + ("..." if len(original_code) > 1200 else ""),
|
|
254
|
+
"iteration_instructions": {
|
|
255
|
+
"goal": "Refine the original design incorporating the user feedback while preserving core layout integrity.",
|
|
256
|
+
"feedback_to_apply": feedback,
|
|
257
|
+
"superdesign_principles": [
|
|
258
|
+
"Preserve component consistency and spacing rhythm (4px/8px grid).",
|
|
259
|
+
"Ensure contrast ratios meet WCAG AA standards.",
|
|
260
|
+
"Polish micro-interactions, hover states, and smooth CSS transitions.",
|
|
261
|
+
"Avoid introducing visual clutter or artificial AI tropes.",
|
|
262
|
+
],
|
|
263
|
+
"execution_note": "Write the improved code into the target files specified in 'target_files'.",
|
|
264
|
+
},
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def superdesign_extract_system(
|
|
269
|
+
input_path_or_description: str,
|
|
270
|
+
system_name: str = "custom",
|
|
271
|
+
workspace_path: str = ".",
|
|
272
|
+
) -> Dict[str, Any]:
|
|
273
|
+
"""Extracts or initializes a structured JSON design system with modern tokens."""
|
|
274
|
+
_, systems_dir = _ensure_superdesign_dirs(workspace_path)
|
|
275
|
+
clean_name = _slugify(system_name) or "design_system"
|
|
276
|
+
system_file = os.path.join(systems_dir, f"{clean_name}.json")
|
|
277
|
+
|
|
278
|
+
tokens = json.loads(json.dumps(DEFAULT_DESIGN_SYSTEM))
|
|
279
|
+
tokens["name"] = f"Superdesign System: {system_name.replace('_', ' ').title()}"
|
|
280
|
+
tokens["description"] = f"Extracted design system for: {input_path_or_description}"
|
|
281
|
+
tokens["extracted_at"] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
|
282
|
+
|
|
283
|
+
with open(system_file, "w", encoding="utf-8") as f:
|
|
284
|
+
json.dump(tokens, f, indent=2, ensure_ascii=False)
|
|
285
|
+
|
|
286
|
+
return {
|
|
287
|
+
"success": True,
|
|
288
|
+
"system_name": clean_name,
|
|
289
|
+
"file_path": system_file.replace("\\", "/"),
|
|
290
|
+
"design_system": tokens,
|
|
291
|
+
"usage_instructions": (
|
|
292
|
+
f"Design system tokens saved to '{system_file}'. "
|
|
293
|
+
"Reference these CSS custom properties in your HTML, React, and Vue components."
|
|
294
|
+
),
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def superdesign_list(workspace_path: str = ".") -> Dict[str, Any]:
|
|
299
|
+
"""Enumerates all Superdesign creations and extracted design systems."""
|
|
300
|
+
iterations_dir, systems_dir = _ensure_superdesign_dirs(workspace_path)
|
|
301
|
+
|
|
302
|
+
iterations = []
|
|
303
|
+
if os.path.isdir(iterations_dir):
|
|
304
|
+
for fname in sorted(os.listdir(iterations_dir)):
|
|
305
|
+
full_p = os.path.join(iterations_dir, fname)
|
|
306
|
+
if os.path.isfile(full_p):
|
|
307
|
+
ext = os.path.splitext(fname)[1].lower()
|
|
308
|
+
dtype = "ui"
|
|
309
|
+
if fname.startswith("wireframe_"):
|
|
310
|
+
dtype = "wireframe"
|
|
311
|
+
elif fname.startswith("component_"):
|
|
312
|
+
dtype = "component"
|
|
313
|
+
elif fname.startswith("logo_"):
|
|
314
|
+
dtype = "logo"
|
|
315
|
+
elif fname.startswith("icon_"):
|
|
316
|
+
dtype = "icon"
|
|
317
|
+
|
|
318
|
+
iterations.append({
|
|
319
|
+
"filename": fname,
|
|
320
|
+
"design_type": dtype,
|
|
321
|
+
"extension": ext,
|
|
322
|
+
"relative_path": os.path.join("superdesign", "design_iterations", fname).replace("\\", "/"),
|
|
323
|
+
"size_bytes": os.path.getsize(full_p),
|
|
324
|
+
"modified_time": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getmtime(full_p))),
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
systems = []
|
|
328
|
+
if os.path.isdir(systems_dir):
|
|
329
|
+
for fname in sorted(os.listdir(systems_dir)):
|
|
330
|
+
full_p = os.path.join(systems_dir, fname)
|
|
331
|
+
if os.path.isfile(full_p) and fname.endswith(".json"):
|
|
332
|
+
systems.append({
|
|
333
|
+
"filename": fname,
|
|
334
|
+
"relative_path": os.path.join("superdesign", "design_system", fname).replace("\\", "/"),
|
|
335
|
+
"size_bytes": os.path.getsize(full_p),
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
return {
|
|
339
|
+
"success": True,
|
|
340
|
+
"total_iterations": len(iterations),
|
|
341
|
+
"total_design_systems": len(systems),
|
|
342
|
+
"iterations": iterations,
|
|
343
|
+
"design_systems": systems,
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def superdesign_gallery(workspace_path: str = ".") -> Dict[str, Any]:
|
|
348
|
+
"""Builds a responsive, interactive HTML gallery previewing all designs in superdesign/."""
|
|
349
|
+
iterations_dir, _ = _ensure_superdesign_dirs(workspace_path)
|
|
350
|
+
gallery_file = os.path.join(workspace_path, "superdesign", "gallery.html")
|
|
351
|
+
|
|
352
|
+
list_data = superdesign_list(workspace_path=workspace_path)
|
|
353
|
+
items = list_data.get("iterations", [])
|
|
354
|
+
|
|
355
|
+
cards_html = []
|
|
356
|
+
for idx, item in enumerate(items):
|
|
357
|
+
fn = html.escape(item["filename"])
|
|
358
|
+
dtype = html.escape(item["design_type"].upper())
|
|
359
|
+
mod = html.escape(item["modified_time"])
|
|
360
|
+
rel_p = html.escape(f"design_iterations/{item['filename']}")
|
|
361
|
+
ext = item["extension"]
|
|
362
|
+
|
|
363
|
+
if ext == ".svg":
|
|
364
|
+
# Read inline SVG for instant preview
|
|
365
|
+
svg_path = os.path.join(iterations_dir, item["filename"])
|
|
366
|
+
try:
|
|
367
|
+
with open(svg_path, "r", encoding="utf-8", errors="ignore") as sf:
|
|
368
|
+
svg_raw = sf.read()
|
|
369
|
+
# Strip xml header if present
|
|
370
|
+
svg_raw = re.sub(r"<\?xml.*?\?>", "", svg_raw).strip()
|
|
371
|
+
except Exception:
|
|
372
|
+
svg_raw = "<div style='color:#ef4444;'>Failed to load SVG</div>"
|
|
373
|
+
preview_content = f"<div class='svg-frame'>{svg_raw}</div>"
|
|
374
|
+
else:
|
|
375
|
+
preview_content = f"<iframe src='{rel_p}' loading='lazy' class='preview-iframe' title='{fn}'></iframe>"
|
|
376
|
+
|
|
377
|
+
card = f"""
|
|
378
|
+
<div class="gallery-card" data-type="{item['design_type']}">
|
|
379
|
+
<div class="card-preview">
|
|
380
|
+
{preview_content}
|
|
381
|
+
<div class="preview-overlay">
|
|
382
|
+
<button class="btn-action" onclick="openModal('{rel_p}', '{fn}')">Preview Full</button>
|
|
383
|
+
</div>
|
|
384
|
+
</div>
|
|
385
|
+
<div class="card-meta">
|
|
386
|
+
<div class="card-header">
|
|
387
|
+
<span class="badge badge-{item['design_type']}">{dtype}</span>
|
|
388
|
+
<span class="card-date">{mod}</span>
|
|
389
|
+
</div>
|
|
390
|
+
<div class="card-title" title="{fn}">{fn}</div>
|
|
391
|
+
<div class="card-footer">
|
|
392
|
+
<button class="btn-copy" onclick="copyPath('{item['relative_path']}', this)">Copy Path</button>
|
|
393
|
+
<a href="{rel_p}" target="_blank" class="btn-link">Open ↗</a>
|
|
394
|
+
</div>
|
|
395
|
+
</div>
|
|
396
|
+
</div>
|
|
397
|
+
"""
|
|
398
|
+
cards_html.append(card)
|
|
399
|
+
|
|
400
|
+
cards_joined = "\n".join(cards_html) if cards_html else (
|
|
401
|
+
"<div class='empty-state'>"
|
|
402
|
+
"<h3>No Designs Yet</h3>"
|
|
403
|
+
"<p>Run <code>superdesign_generate</code> to create your first clean UI, wireframe, or component.</p>"
|
|
404
|
+
"</div>"
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
gallery_html_content = f"""<!DOCTYPE html>
|
|
408
|
+
<html lang="en">
|
|
409
|
+
<head>
|
|
410
|
+
<meta charset="UTF-8">
|
|
411
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
412
|
+
<title>Superdesign Gallery — T-Zero Design Canvas</title>
|
|
413
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
414
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
415
|
+
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
416
|
+
<style>
|
|
417
|
+
:root {{
|
|
418
|
+
--bg: #090d16;
|
|
419
|
+
--surface: #0f172a;
|
|
420
|
+
--surface-elevated: #1e293b;
|
|
421
|
+
--border: #1e293b;
|
|
422
|
+
--border-focus: #38bdf8;
|
|
423
|
+
--text: #f8fafc;
|
|
424
|
+
--text-muted: #94a3b8;
|
|
425
|
+
--accent: #38bdf8;
|
|
426
|
+
--accent-indigo: #818cf8;
|
|
427
|
+
--radius: 10px;
|
|
428
|
+
}}
|
|
429
|
+
* {{ box-sizing: border-box; margin: 0; padding: 0; }}
|
|
430
|
+
body {{
|
|
431
|
+
background: var(--bg);
|
|
432
|
+
color: var(--text);
|
|
433
|
+
font-family: 'Inter', -apple-system, sans-serif;
|
|
434
|
+
min-height: 100vh;
|
|
435
|
+
display: flex;
|
|
436
|
+
flex-direction: column;
|
|
437
|
+
}}
|
|
438
|
+
header {{
|
|
439
|
+
padding: 20px 36px;
|
|
440
|
+
border-bottom: 1px solid var(--border);
|
|
441
|
+
background: rgba(15, 23, 42, 0.85);
|
|
442
|
+
backdrop-filter: blur(16px);
|
|
443
|
+
position: sticky;
|
|
444
|
+
top: 0;
|
|
445
|
+
z-index: 50;
|
|
446
|
+
display: flex;
|
|
447
|
+
justify-content: space-between;
|
|
448
|
+
align-items: center;
|
|
449
|
+
}}
|
|
450
|
+
.brand {{
|
|
451
|
+
display: flex;
|
|
452
|
+
align-items: center;
|
|
453
|
+
gap: 12px;
|
|
454
|
+
}}
|
|
455
|
+
.brand-logo {{
|
|
456
|
+
width: 32px;
|
|
457
|
+
height: 32px;
|
|
458
|
+
background: linear-gradient(135deg, var(--accent), var(--accent-indigo));
|
|
459
|
+
border-radius: 8px;
|
|
460
|
+
display: flex;
|
|
461
|
+
align-items: center;
|
|
462
|
+
justify-content: center;
|
|
463
|
+
font-weight: 700;
|
|
464
|
+
color: #090d16;
|
|
465
|
+
}}
|
|
466
|
+
.brand-title {{
|
|
467
|
+
font-size: 18px;
|
|
468
|
+
font-weight: 700;
|
|
469
|
+
letter-spacing: -0.02em;
|
|
470
|
+
}}
|
|
471
|
+
.filter-bar {{
|
|
472
|
+
display: flex;
|
|
473
|
+
gap: 8px;
|
|
474
|
+
}}
|
|
475
|
+
.filter-btn {{
|
|
476
|
+
background: var(--surface);
|
|
477
|
+
border: 1px solid var(--border);
|
|
478
|
+
color: var(--text-muted);
|
|
479
|
+
padding: 6px 14px;
|
|
480
|
+
border-radius: 6px;
|
|
481
|
+
font-size: 13px;
|
|
482
|
+
font-weight: 500;
|
|
483
|
+
cursor: pointer;
|
|
484
|
+
transition: all 0.15s ease;
|
|
485
|
+
}}
|
|
486
|
+
.filter-btn:hover, .filter-btn.active {{
|
|
487
|
+
background: var(--surface-elevated);
|
|
488
|
+
color: var(--text);
|
|
489
|
+
border-color: var(--accent);
|
|
490
|
+
}}
|
|
491
|
+
main {{
|
|
492
|
+
flex: 1;
|
|
493
|
+
padding: 36px;
|
|
494
|
+
max-width: 1440px;
|
|
495
|
+
margin: 0 auto;
|
|
496
|
+
width: 100%;
|
|
497
|
+
}}
|
|
498
|
+
.gallery-grid {{
|
|
499
|
+
display: grid;
|
|
500
|
+
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
|
|
501
|
+
gap: 24px;
|
|
502
|
+
}}
|
|
503
|
+
.gallery-card {{
|
|
504
|
+
background: var(--surface);
|
|
505
|
+
border: 1px solid var(--border);
|
|
506
|
+
border-radius: var(--radius);
|
|
507
|
+
overflow: hidden;
|
|
508
|
+
display: flex;
|
|
509
|
+
flex-direction: column;
|
|
510
|
+
transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
|
|
511
|
+
}}
|
|
512
|
+
.gallery-card:hover {{
|
|
513
|
+
transform: translateY(-3px);
|
|
514
|
+
border-color: #334155;
|
|
515
|
+
box-shadow: 0 12px 24px -10px rgba(0, 0, 0, 0.6);
|
|
516
|
+
}}
|
|
517
|
+
.card-preview {{
|
|
518
|
+
height: 220px;
|
|
519
|
+
background: #060910;
|
|
520
|
+
position: relative;
|
|
521
|
+
overflow: hidden;
|
|
522
|
+
display: flex;
|
|
523
|
+
align-items: center;
|
|
524
|
+
justify-content: center;
|
|
525
|
+
border-bottom: 1px solid var(--border);
|
|
526
|
+
}}
|
|
527
|
+
.preview-iframe {{
|
|
528
|
+
width: 200%;
|
|
529
|
+
height: 200%;
|
|
530
|
+
transform: scale(0.5);
|
|
531
|
+
transform-origin: top left;
|
|
532
|
+
border: none;
|
|
533
|
+
pointer-events: none;
|
|
534
|
+
}}
|
|
535
|
+
.svg-frame {{
|
|
536
|
+
width: 100%;
|
|
537
|
+
height: 100%;
|
|
538
|
+
display: flex;
|
|
539
|
+
align-items: center;
|
|
540
|
+
justify-content: center;
|
|
541
|
+
padding: 24px;
|
|
542
|
+
}}
|
|
543
|
+
.svg-frame svg {{
|
|
544
|
+
max-width: 100%;
|
|
545
|
+
max-height: 100%;
|
|
546
|
+
}}
|
|
547
|
+
.preview-overlay {{
|
|
548
|
+
position: absolute;
|
|
549
|
+
inset: 0;
|
|
550
|
+
background: rgba(9, 13, 22, 0.7);
|
|
551
|
+
backdrop-filter: blur(4px);
|
|
552
|
+
display: flex;
|
|
553
|
+
align-items: center;
|
|
554
|
+
justify-content: center;
|
|
555
|
+
opacity: 0;
|
|
556
|
+
transition: opacity 0.2s ease;
|
|
557
|
+
}}
|
|
558
|
+
.card-preview:hover .preview-overlay {{
|
|
559
|
+
opacity: 1;
|
|
560
|
+
}}
|
|
561
|
+
.btn-action {{
|
|
562
|
+
background: var(--accent);
|
|
563
|
+
color: #090d16;
|
|
564
|
+
border: none;
|
|
565
|
+
padding: 8px 16px;
|
|
566
|
+
border-radius: 6px;
|
|
567
|
+
font-weight: 600;
|
|
568
|
+
font-size: 13px;
|
|
569
|
+
cursor: pointer;
|
|
570
|
+
}}
|
|
571
|
+
.card-meta {{
|
|
572
|
+
padding: 16px;
|
|
573
|
+
display: flex;
|
|
574
|
+
flex-direction: column;
|
|
575
|
+
gap: 8px;
|
|
576
|
+
}}
|
|
577
|
+
.card-header {{
|
|
578
|
+
display: flex;
|
|
579
|
+
justify-content: space-between;
|
|
580
|
+
align-items: center;
|
|
581
|
+
}}
|
|
582
|
+
.badge {{
|
|
583
|
+
font-size: 11px;
|
|
584
|
+
font-weight: 600;
|
|
585
|
+
padding: 3px 8px;
|
|
586
|
+
border-radius: 4px;
|
|
587
|
+
text-transform: uppercase;
|
|
588
|
+
letter-spacing: 0.05em;
|
|
589
|
+
}}
|
|
590
|
+
.badge-ui {{ background: rgba(56, 189, 248, 0.15); color: #38bdf8; }}
|
|
591
|
+
.badge-wireframe {{ background: rgba(148, 163, 184, 0.15); color: #94a3b8; }}
|
|
592
|
+
.badge-component {{ background: rgba(129, 140, 248, 0.15); color: #818cf8; }}
|
|
593
|
+
.badge-logo, .badge-icon {{ background: rgba(52, 211, 153, 0.15); color: #34d399; }}
|
|
594
|
+
.card-date {{
|
|
595
|
+
font-size: 11px;
|
|
596
|
+
color: var(--text-muted);
|
|
597
|
+
font-family: 'Fira Code', monospace;
|
|
598
|
+
}}
|
|
599
|
+
.card-title {{
|
|
600
|
+
font-size: 14px;
|
|
601
|
+
font-weight: 600;
|
|
602
|
+
overflow: hidden;
|
|
603
|
+
text-overflow: ellipsis;
|
|
604
|
+
white-space: nowrap;
|
|
605
|
+
}}
|
|
606
|
+
.card-footer {{
|
|
607
|
+
display: flex;
|
|
608
|
+
justify-content: space-between;
|
|
609
|
+
align-items: center;
|
|
610
|
+
margin-top: 4px;
|
|
611
|
+
padding-top: 10px;
|
|
612
|
+
border-top: 1px solid var(--border);
|
|
613
|
+
}}
|
|
614
|
+
.btn-copy {{
|
|
615
|
+
background: transparent;
|
|
616
|
+
border: 1px solid var(--border);
|
|
617
|
+
color: var(--text-muted);
|
|
618
|
+
padding: 4px 10px;
|
|
619
|
+
border-radius: 4px;
|
|
620
|
+
font-size: 12px;
|
|
621
|
+
cursor: pointer;
|
|
622
|
+
}}
|
|
623
|
+
.btn-copy:hover {{
|
|
624
|
+
color: var(--text);
|
|
625
|
+
border-color: #334155;
|
|
626
|
+
}}
|
|
627
|
+
.btn-link {{
|
|
628
|
+
color: var(--accent);
|
|
629
|
+
text-decoration: none;
|
|
630
|
+
font-size: 13px;
|
|
631
|
+
font-weight: 500;
|
|
632
|
+
}}
|
|
633
|
+
.empty-state {{
|
|
634
|
+
grid-column: 1 / -1;
|
|
635
|
+
text-align: center;
|
|
636
|
+
padding: 80px 20px;
|
|
637
|
+
color: var(--text-muted);
|
|
638
|
+
}}
|
|
639
|
+
.empty-state h3 {{
|
|
640
|
+
color: var(--text);
|
|
641
|
+
font-size: 20px;
|
|
642
|
+
margin-bottom: 8px;
|
|
643
|
+
}}
|
|
644
|
+
/* Modal */
|
|
645
|
+
.modal-backdrop {{
|
|
646
|
+
position: fixed;
|
|
647
|
+
inset: 0;
|
|
648
|
+
background: rgba(9, 13, 22, 0.85);
|
|
649
|
+
backdrop-filter: blur(8px);
|
|
650
|
+
z-index: 1000;
|
|
651
|
+
display: none;
|
|
652
|
+
align-items: center;
|
|
653
|
+
justify-content: center;
|
|
654
|
+
padding: 24px;
|
|
655
|
+
}}
|
|
656
|
+
.modal-backdrop.open {{ display: flex; }}
|
|
657
|
+
.modal-container {{
|
|
658
|
+
background: var(--surface);
|
|
659
|
+
border: 1px solid var(--border);
|
|
660
|
+
border-radius: var(--radius);
|
|
661
|
+
width: 90vw;
|
|
662
|
+
height: 85vh;
|
|
663
|
+
display: flex;
|
|
664
|
+
flex-direction: column;
|
|
665
|
+
overflow: hidden;
|
|
666
|
+
}}
|
|
667
|
+
.modal-header {{
|
|
668
|
+
padding: 14px 20px;
|
|
669
|
+
border-bottom: 1px solid var(--border);
|
|
670
|
+
display: flex;
|
|
671
|
+
justify-content: space-between;
|
|
672
|
+
align-items: center;
|
|
673
|
+
}}
|
|
674
|
+
.modal-body {{
|
|
675
|
+
flex: 1;
|
|
676
|
+
background: #fff;
|
|
677
|
+
}}
|
|
678
|
+
.modal-body iframe {{
|
|
679
|
+
width: 100%;
|
|
680
|
+
height: 100%;
|
|
681
|
+
border: none;
|
|
682
|
+
}}
|
|
683
|
+
.btn-close {{
|
|
684
|
+
background: none;
|
|
685
|
+
border: none;
|
|
686
|
+
color: var(--text-muted);
|
|
687
|
+
font-size: 22px;
|
|
688
|
+
cursor: pointer;
|
|
689
|
+
}}
|
|
690
|
+
.btn-close:hover {{ color: var(--text); }}
|
|
691
|
+
</style>
|
|
692
|
+
</head>
|
|
693
|
+
<body>
|
|
694
|
+
<header>
|
|
695
|
+
<div class="brand">
|
|
696
|
+
<div class="brand-logo">Σ</div>
|
|
697
|
+
<div class="brand-title">Superdesign Canvas</div>
|
|
698
|
+
</div>
|
|
699
|
+
<div class="filter-bar">
|
|
700
|
+
<button class="filter-btn active" onclick="filterGallery('all')">All</button>
|
|
701
|
+
<button class="filter-btn" onclick="filterGallery('ui')">UI</button>
|
|
702
|
+
<button class="filter-btn" onclick="filterGallery('component')">Components</button>
|
|
703
|
+
<button class="filter-btn" onclick="filterGallery('wireframe')">Wireframes</button>
|
|
704
|
+
<button class="filter-btn" onclick="filterGallery('logo')">Logos & Icons</button>
|
|
705
|
+
</div>
|
|
706
|
+
</header>
|
|
707
|
+
<main>
|
|
708
|
+
<div class="gallery-grid" id="gallery-grid">
|
|
709
|
+
{cards_joined}
|
|
710
|
+
</div>
|
|
711
|
+
</main>
|
|
712
|
+
|
|
713
|
+
<div class="modal-backdrop" id="preview-modal" onclick="closeModal(event)">
|
|
714
|
+
<div class="modal-container" onclick="event.stopPropagation()">
|
|
715
|
+
<div class="modal-header">
|
|
716
|
+
<span id="modal-title" style="font-weight:600;font-size:14px;"></span>
|
|
717
|
+
<button class="btn-close" onclick="closeModalDirect()">×</button>
|
|
718
|
+
</div>
|
|
719
|
+
<div class="modal-body">
|
|
720
|
+
<iframe id="modal-frame" src="about:blank"></iframe>
|
|
721
|
+
</div>
|
|
722
|
+
</div>
|
|
723
|
+
</div>
|
|
724
|
+
|
|
725
|
+
<script>
|
|
726
|
+
function filterGallery(type) {{
|
|
727
|
+
document.querySelectorAll('.filter-btn').forEach(btn => btn.classList.remove('active'));
|
|
728
|
+
event.target.classList.add('active');
|
|
729
|
+
const cards = document.querySelectorAll('.gallery-card');
|
|
730
|
+
cards.forEach(card => {{
|
|
731
|
+
if (type === 'all' || card.dataset.type === type || (type === 'logo' && (card.dataset.type === 'logo' || card.dataset.type === 'icon'))) {{
|
|
732
|
+
card.style.display = 'flex';
|
|
733
|
+
}} else {{
|
|
734
|
+
card.style.display = 'none';
|
|
735
|
+
}}
|
|
736
|
+
}});
|
|
737
|
+
}}
|
|
738
|
+
function openModal(src, title) {{
|
|
739
|
+
document.getElementById('modal-title').textContent = title;
|
|
740
|
+
document.getElementById('modal-frame').src = src;
|
|
741
|
+
document.getElementById('preview-modal').classList.add('open');
|
|
742
|
+
}}
|
|
743
|
+
function closeModal(e) {{
|
|
744
|
+
if (e.target.id === 'preview-modal') {{
|
|
745
|
+
closeModalDirect();
|
|
746
|
+
}}
|
|
747
|
+
}}
|
|
748
|
+
function closeModalDirect() {{
|
|
749
|
+
document.getElementById('preview-modal').classList.remove('open');
|
|
750
|
+
document.getElementById('modal-frame').src = 'about:blank';
|
|
751
|
+
}}
|
|
752
|
+
document.addEventListener('keydown', (e) => {{
|
|
753
|
+
if (e.key === 'Escape') closeModalDirect();
|
|
754
|
+
}});
|
|
755
|
+
function copyPath(text, btn) {{
|
|
756
|
+
navigator.clipboard.writeText(text).then(() => {{
|
|
757
|
+
const original = btn.textContent;
|
|
758
|
+
btn.textContent = 'Copied!';
|
|
759
|
+
setTimeout(() => {{ btn.textContent = original; }}, 1500);
|
|
760
|
+
}});
|
|
761
|
+
}}
|
|
762
|
+
</script>
|
|
763
|
+
</body>
|
|
764
|
+
</html>"""
|
|
765
|
+
|
|
766
|
+
with open(gallery_file, "w", encoding="utf-8") as gf:
|
|
767
|
+
gf.write(gallery_html_content)
|
|
768
|
+
|
|
769
|
+
return {
|
|
770
|
+
"success": True,
|
|
771
|
+
"gallery_file": gallery_file.replace("\\", "/"),
|
|
772
|
+
"total_items": len(items),
|
|
773
|
+
"url_hint": f"Open file://{os.path.abspath(gallery_file)} in any browser to inspect all designs.",
|
|
774
|
+
}
|