@remixmate/cli 0.9.63 → 0.9.65
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/dist/cli.js +13 -0
- package/dist/handlers/index.js +2 -0
- package/dist/handlers/template-init.d.ts +10 -0
- package/dist/handlers/template-init.js +21 -0
- package/dist/manifest.json +53 -3
- package/dist/template/args.d.ts +25 -0
- package/dist/template/args.js +69 -0
- package/dist/template/check.d.ts +23 -0
- package/dist/template/check.js +25 -0
- package/dist/template/commands.d.ts +25 -0
- package/dist/template/commands.js +146 -0
- package/dist/template/constants.d.ts +25 -0
- package/dist/template/constants.js +32 -0
- package/dist/template/init.d.ts +22 -0
- package/dist/template/init.js +115 -0
- package/dist/template/list.d.ts +23 -0
- package/dist/template/list.js +46 -0
- package/dist/template/preview.d.ts +60 -0
- package/dist/template/preview.js +318 -0
- package/dist/template/proc.d.ts +26 -0
- package/dist/template/proc.js +43 -0
- package/dist/template/project.d.ts +37 -0
- package/dist/template/project.js +110 -0
- package/dist/template/publish.d.ts +43 -0
- package/dist/template/publish.js +182 -0
- package/dist/template/render-client.d.ts +39 -0
- package/dist/template/render-client.js +79 -0
- package/package.json +1 -1
- package/skills/template-authoring/SKILL.md +69 -0
- package/skills/template-authoring/skill.json +32 -0
- package/skills/template-authoring/version.json +7 -0
- package/skills/template-registry/SKILL.md +2 -2
- package/skills/template-registry/scripts/list_templates.py +46 -13
- package/skills/template-registry/scripts/registry_loader.py +17 -0
- package/skills/template-registry/skill.json +1 -1
|
@@ -72,9 +72,10 @@ Flags:
|
|
|
72
72
|
(samples, layouts); also opens the browser
|
|
73
73
|
when stdout is an interactive terminal
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
Links & samples: list and detail views add each template's web detail-page
|
|
76
|
+
link (registry document-level ``pageUrls``, falling back to the samples
|
|
77
|
+
endpoint) and sample count (showcase_loader.py) when ab-api serves them; when
|
|
78
|
+
it does not, the views are unchanged apart from one stderr warning.
|
|
78
79
|
"""
|
|
79
80
|
|
|
80
81
|
from __future__ import annotations
|
|
@@ -94,6 +95,7 @@ from registry_loader import ( # noqa: E402
|
|
|
94
95
|
RegistryUnreachableError,
|
|
95
96
|
get_template,
|
|
96
97
|
list_templates as load_visible_templates,
|
|
98
|
+
registry_page_urls,
|
|
97
99
|
)
|
|
98
100
|
from showcase_loader import load_showcases, summarize_group # noqa: E402
|
|
99
101
|
|
|
@@ -198,6 +200,23 @@ def _open_in_browser(url: str) -> None:
|
|
|
198
200
|
pass
|
|
199
201
|
|
|
200
202
|
|
|
203
|
+
def _page_url(template_id: object, page_urls: dict[str, str], groups: dict | None) -> str | None:
|
|
204
|
+
"""Web detail page link for one template.
|
|
205
|
+
|
|
206
|
+
The registry's document-level ``pageUrls`` comes first: it rides on the call
|
|
207
|
+
every list makes anyway, so the link survives the samples endpoint being
|
|
208
|
+
down. The samples group's ``pageUrl`` is the fallback (same URL, built by
|
|
209
|
+
the same backend helper).
|
|
210
|
+
"""
|
|
211
|
+
if not isinstance(template_id, str):
|
|
212
|
+
return None
|
|
213
|
+
if page_urls.get(template_id):
|
|
214
|
+
return page_urls[template_id]
|
|
215
|
+
group = (groups or {}).get(template_id)
|
|
216
|
+
url = group.get("pageUrl") if isinstance(group, dict) else None
|
|
217
|
+
return url if isinstance(url, str) and url else None
|
|
218
|
+
|
|
219
|
+
|
|
201
220
|
def _report_unknown_ids(missing: list[str], templates: list[dict]) -> None:
|
|
202
221
|
for tid in missing:
|
|
203
222
|
# Distinguish "gated out by status" from "does not exist" —
|
|
@@ -459,6 +478,7 @@ def main() -> None:
|
|
|
459
478
|
sys.exit(1)
|
|
460
479
|
|
|
461
480
|
by_id = {t.get("templateId"): t for t in templates}
|
|
481
|
+
page_urls = registry_page_urls()
|
|
462
482
|
|
|
463
483
|
# ----- open mode (--open) -------------------------------------------------
|
|
464
484
|
#
|
|
@@ -468,8 +488,9 @@ def main() -> None:
|
|
|
468
488
|
if args.open_id not in by_id:
|
|
469
489
|
_report_unknown_ids([args.open_id], templates)
|
|
470
490
|
sys.exit(1)
|
|
471
|
-
|
|
472
|
-
|
|
491
|
+
page_url = _page_url(args.open_id, page_urls, None)
|
|
492
|
+
if not page_url:
|
|
493
|
+
page_url = _page_url(args.open_id, {}, load_showcases([args.open_id], 1))
|
|
473
494
|
if not page_url:
|
|
474
495
|
print(
|
|
475
496
|
"❌ No web detail page link for this template: the backend does not "
|
|
@@ -520,9 +541,16 @@ def main() -> None:
|
|
|
520
541
|
# chars), which alone pushed the plain call past the tool-result cap and
|
|
521
542
|
# got it spilled to a file the agent cannot read. Humans can `| jq`.
|
|
522
543
|
detail: dict = {"templates": picked}
|
|
523
|
-
# Samples sit beside the definitions, never inside them: the
|
|
524
|
-
# is the template's authoring contract,
|
|
544
|
+
# Samples and links sit beside the definitions, never inside them: the
|
|
545
|
+
# definition is the template's authoring contract, these are web content.
|
|
525
546
|
groups = load_showcases([str(t.get("templateId")) for t in picked], _DETAIL_SHOWCASES)
|
|
547
|
+
links = {
|
|
548
|
+
str(t.get("templateId")): url
|
|
549
|
+
for t in picked
|
|
550
|
+
if (url := _page_url(t.get("templateId"), page_urls, groups))
|
|
551
|
+
}
|
|
552
|
+
if links:
|
|
553
|
+
detail["pageUrls"] = links
|
|
526
554
|
if groups is not None:
|
|
527
555
|
detail["showcases"] = {
|
|
528
556
|
tid: summarize_group(g, _DETAIL_SHOWCASES) for tid, g in groups.items()
|
|
@@ -554,6 +582,8 @@ def main() -> None:
|
|
|
554
582
|
summaries = []
|
|
555
583
|
for t in visible:
|
|
556
584
|
s = _summarize(t)
|
|
585
|
+
if url := _page_url(t.get("templateId"), page_urls, groups):
|
|
586
|
+
s["pageUrl"] = url
|
|
557
587
|
# Absent (not null) when the endpoint is unavailable, so a consumer
|
|
558
588
|
# never mistakes "unknown" for "zero samples".
|
|
559
589
|
if groups is not None and t.get("templateId") in groups:
|
|
@@ -576,6 +606,7 @@ def main() -> None:
|
|
|
576
606
|
return
|
|
577
607
|
|
|
578
608
|
groups = load_showcases([str(t.get("templateId")) for t in visible], _LIST_SHOWCASES)
|
|
609
|
+
any_link = False
|
|
579
610
|
|
|
580
611
|
header = (
|
|
581
612
|
f"\n{'Template ID':<22} {'Name':<18} {'Aspect':<12} "
|
|
@@ -596,12 +627,14 @@ def main() -> None:
|
|
|
596
627
|
hint = _truncate(tpl.get("llmHint"), _SUMMARY_HINT_CHARS)
|
|
597
628
|
if hint:
|
|
598
629
|
print(f"{' ' * 22} ↳ {hint}")
|
|
630
|
+
# Two lines, link on its own: an agent summarizing the table keeps a
|
|
631
|
+
# labelled `detail:` line, a URL trailing a count reads as an aside.
|
|
599
632
|
group = (groups or {}).get(tpl.get("templateId"))
|
|
600
633
|
if group is not None:
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
634
|
+
print(f"{' ' * 22} ↳ samples: {int(group.get('showcaseCount') or 0)}")
|
|
635
|
+
if url := _page_url(tpl.get("templateId"), page_urls, groups):
|
|
636
|
+
print(f"{' ' * 22} ↳ detail: {url}")
|
|
637
|
+
any_link = True
|
|
605
638
|
|
|
606
639
|
print(f"\n{len(visible)} template(s) shown")
|
|
607
640
|
first_id = str(visible[0].get("templateId", "<templateId>"))
|
|
@@ -609,8 +642,8 @@ def main() -> None:
|
|
|
609
642
|
f"Full definition of one template: --template-id {first_id} --json-output "
|
|
610
643
|
"(llmHint / customPayloadSchema / slideSchemas / slotMapping / variants)",
|
|
611
644
|
)
|
|
612
|
-
if
|
|
613
|
-
print(f"Watch samples in the browser: --open {first_id}")
|
|
645
|
+
if any_link:
|
|
646
|
+
print(f"Watch samples / layouts in the browser: open a detail link, or --open {first_id}")
|
|
614
647
|
|
|
615
648
|
|
|
616
649
|
if __name__ == "__main__":
|
|
@@ -306,6 +306,23 @@ def load_registry_data(
|
|
|
306
306
|
return _load_from_url(url, ttl=ttl_seconds, timeout=http_timeout)
|
|
307
307
|
|
|
308
308
|
|
|
309
|
+
def registry_page_urls() -> dict[str, str]:
|
|
310
|
+
"""Document-level ``pageUrls`` (templateId → web detail page), built by ab-api.
|
|
311
|
+
|
|
312
|
+
Kept beside ``templates`` rather than inside each definition: a definition is
|
|
313
|
+
the template's authoring contract, a link is site information. Absent on
|
|
314
|
+
older backends, offline registries, or when the backend has no site address
|
|
315
|
+
configured — returns ``{}`` then (never raises: it is display-only).
|
|
316
|
+
"""
|
|
317
|
+
try:
|
|
318
|
+
raw = load_registry_data().get("pageUrls")
|
|
319
|
+
except Exception: # noqa: BLE001 — the caller already loaded the registry once
|
|
320
|
+
return {}
|
|
321
|
+
if not isinstance(raw, dict):
|
|
322
|
+
return {}
|
|
323
|
+
return {k: v for k, v in raw.items() if isinstance(k, str) and isinstance(v, str) and v}
|
|
324
|
+
|
|
325
|
+
|
|
309
326
|
# ════════════════════════════════════════════════════════════════════════════
|
|
310
327
|
# Indexed views — O(1) template-id lookup + status / beta gating
|
|
311
328
|
#
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"filter_aspect": { "type": "string", "description": "Show only templates that declare this aspect ratio. E.g. '9:16' / '16:9' / '1:1'." },
|
|
20
20
|
"filter_language": { "type": "string", "description": "Show only templates whose contentLanguage includes this code ('zh' or 'en'). Templates with no declared language are always shown (treated as language-agnostic)." },
|
|
21
21
|
"include_beta": { "type": "boolean", "description": "Also list templates with status='beta'. Default off (only 'stable' shows). The ENABLE_BETA_TEMPLATES env var has the same effect process-wide." },
|
|
22
|
-
"json_output": { "type": "boolean", "description": "Emit a JSON result instead of the human-readable table: { templates: [...] } — summaries, or full definitions when template_id / full is set — or { examples: [...] }.
|
|
22
|
+
"json_output": { "type": "boolean", "description": "Emit a JSON result instead of the human-readable table: { templates: [...] } — summaries, or full definitions when template_id / full is set — or { examples: [...] }. List summaries carry pageUrl (the template's web detail page — show it to the user as a link) and, when the backend serves samples, showcases { count, pageUrl, items }; the template_id view carries top-level pageUrls / showcases maps." },
|
|
23
23
|
"open": { "type": "string", "description": "Print the web detail page URL of <templateId> (playable samples, layouts, copy-ready prompt) and open it in the browser when run from an interactive terminal. Relay the printed URL to the user." }
|
|
24
24
|
},
|
|
25
25
|
"required": []
|