lokuma-cli 1.3.5 → 1.3.7

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/README.md CHANGED
@@ -68,7 +68,7 @@ Options:
68
68
  `lokuma-cli` installs two files into your project:
69
69
 
70
70
  1. **SKILL.md** — tells your AI assistant how to use Lokuma
71
- 2. **search.py** — a lightweight cloud client that calls the Lokuma API
71
+ 2. **design.py** — a lightweight cloud client that calls the Lokuma API
72
72
 
73
73
  No local data files. No Python dependencies. Just set your API key and go.
74
74
 
package/assets/design.py CHANGED
@@ -106,6 +106,20 @@ def _post(endpoint: str, payload: dict) -> dict:
106
106
  sys.exit(1)
107
107
 
108
108
 
109
+ # ─────────────────────────────────────────────
110
+ # Image reminder (appended to every recommendation)
111
+ # ─────────────────────────────────────────────
112
+
113
+ IMAGE_REMINDER = (
114
+ "\n\n---\n"
115
+ "> **Image requirement:** Always include real images when generating UI. "
116
+ "Use high-quality placeholder sources such as Unsplash (`https://source.unsplash.com/...`) "
117
+ "or Picsum (`https://picsum.photos/...`). "
118
+ "Every hero section, card, and media slot must have an actual `<img>` tag or CSS background image. "
119
+ "Do not leave image areas empty, use placeholder boxes, or skip images entirely."
120
+ )
121
+
122
+
109
123
  # ─────────────────────────────────────────────
110
124
  # Output formatting
111
125
  # ─────────────────────────────────────────────
@@ -114,11 +128,50 @@ def _format_output(result: dict, fmt: str) -> str:
114
128
  if "error" in result:
115
129
  return f"Error: {result['error']}"
116
130
 
117
- # design-system response (has "output" key for ascii/markdown)
131
+ # ── Print low-balance warning if present ──────────────────────────────────
132
+ warning = result.get("warning")
133
+ if warning:
134
+ print(f"\n⚠️ {warning}\n", file=sys.stderr)
135
+
136
+ # ── New /v1/design response: domains + recommendation ─────────────────────
137
+ if "recommendation" in result:
138
+ if fmt == "json":
139
+ return json.dumps(result, indent=2, ensure_ascii=False)
140
+
141
+ lines = []
142
+ project = result.get("project_name")
143
+ if project:
144
+ lines.append(f"# {project}\n")
145
+
146
+ # Per-domain matches summary
147
+ domains = result.get("domains", {})
148
+ if domains:
149
+ lines.append("## Domain Matches\n")
150
+ for domain, data in domains.items():
151
+ match = data.get("match", {}) if isinstance(data, dict) else {}
152
+ # pick a representative label from the match
153
+ label = (
154
+ match.get("name") or match.get("Font Pairing Name") or
155
+ match.get("Pattern Name") or match.get("Product Type") or
156
+ match.get("Category") or match.get("family") or
157
+ next(iter(match.values()), "") if match else ""
158
+ )
159
+ lines.append(f"- **{domain}**: {label}")
160
+ lines.append("")
161
+
162
+ # Main recommendation
163
+ lines.append(result["recommendation"])
164
+
165
+ # Append image reminder
166
+ lines.append(IMAGE_REMINDER)
167
+
168
+ return "\n".join(lines)
169
+
170
+ # ── Legacy: design-system response (has "output" key) ────────────────────
118
171
  if "output" in result:
119
- return result["output"]
172
+ return result["output"] + IMAGE_REMINDER
120
173
 
121
- # design-system json response
174
+ # ── Legacy: design-system json response ──────────────────────────────────
122
175
  if "design_system" in result:
123
176
  ds = result["design_system"]
124
177
  if fmt == "json":
@@ -134,13 +187,13 @@ def _format_output(result: dict, fmt: str) -> str:
134
187
  else:
135
188
  lines.append(str(data))
136
189
  lines.append("")
137
- return "\n".join(lines)
190
+ return "\n".join(lines) + IMAGE_REMINDER
138
191
 
139
- # multi-domain response
192
+ # ── Legacy: multi-domain response ────────────────────────────────────────
140
193
  if result.get("strategy") == "multi":
141
194
  if fmt == "json":
142
195
  return json.dumps(result, indent=2, ensure_ascii=False)
143
- lines = [f"## Lokuma Design Results\n"]
196
+ lines = ["## Lokuma Design Results\n"]
144
197
  for r in result.get("results", []):
145
198
  domain = r.get("domain", "")
146
199
  lines.append(f"### {domain.title()}")
@@ -149,9 +202,9 @@ def _format_output(result: dict, fmt: str) -> str:
149
202
  f"{k}: {str(v)[:100]}" for k, v in list(row.items())[:4]
150
203
  ))
151
204
  lines.append("")
152
- return "\n".join(lines)
205
+ return "\n".join(lines) + IMAGE_REMINDER
153
206
 
154
- # single-domain response
207
+ # ── Legacy: single-domain response ───────────────────────────────────────
155
208
  if fmt == "json":
156
209
  return json.dumps(result, indent=2, ensure_ascii=False)
157
210
 
@@ -165,7 +218,7 @@ def _format_output(result: dict, fmt: str) -> str:
165
218
  v = v[:300] + "..."
166
219
  lines.append(f"- **{key}:** {v}")
167
220
  lines.append("")
168
- return "\n".join(lines)
221
+ return "\n".join(lines) + IMAGE_REMINDER
169
222
 
170
223
 
171
224
  # ─────────────────────────────────────────────
package/dist/index.js CHANGED
@@ -54,22 +54,22 @@ var AI_DISPLAY_NAMES = {
54
54
  all: "All assistants"
55
55
  };
56
56
  var AI_SKILL_PATHS = {
57
- claude: { root: ".claude", skillMd: ".claude/skills/lokuma/SKILL.md", scriptPy: ".claude/skills/lokuma/scripts/search.py" },
58
- cursor: { root: ".cursor", skillMd: ".cursor/rules/lokuma.mdc", scriptPy: ".cursor/rules/lokuma/scripts/search.py" },
59
- windsurf: { root: ".windsurf", skillMd: ".windsurf/rules/lokuma.md", scriptPy: ".windsurf/rules/lokuma/scripts/search.py" },
60
- copilot: { root: ".github", skillMd: ".github/instructions/lokuma.instructions.md", scriptPy: ".github/instructions/lokuma/scripts/search.py" },
61
- kiro: { root: ".kiro", skillMd: ".kiro/steering/lokuma.md", scriptPy: ".kiro/steering/lokuma/scripts/search.py" },
62
- roocode: { root: ".roo", skillMd: ".roo/rules/lokuma.md", scriptPy: ".roo/rules/lokuma/scripts/search.py" },
63
- codex: { root: ".codex", skillMd: ".codex/instructions.md", scriptPy: ".codex/lokuma/scripts/search.py" },
64
- qoder: { root: ".qoder", skillMd: ".qoder/rules/lokuma.md", scriptPy: ".qoder/rules/lokuma/scripts/search.py" },
65
- gemini: { root: ".gemini", skillMd: ".gemini/GEMINI.md", scriptPy: ".gemini/lokuma/scripts/search.py" },
66
- trae: { root: ".trae", skillMd: ".trae/rules/lokuma.md", scriptPy: ".trae/rules/lokuma/scripts/search.py" },
67
- opencode: { root: ".opencode", skillMd: ".opencode/OPENCODE.md", scriptPy: ".opencode/lokuma/scripts/search.py" },
68
- continue: { root: ".continue", skillMd: ".continue/lokuma/SKILL.md", scriptPy: ".continue/lokuma/scripts/search.py" },
69
- codebuddy: { root: ".codebuddy", skillMd: ".codebuddy/lokuma/SKILL.md", scriptPy: ".codebuddy/lokuma/scripts/search.py" },
70
- droid: { root: ".factory", skillMd: ".factory/skills/lokuma/SKILL.md", scriptPy: ".factory/skills/lokuma/scripts/search.py" },
57
+ claude: { root: ".claude", skillMd: ".claude/skills/lokuma/SKILL.md", scriptPy: ".claude/skills/lokuma/scripts/design.py" },
58
+ cursor: { root: ".cursor", skillMd: ".cursor/rules/lokuma.mdc", scriptPy: ".cursor/rules/lokuma/scripts/design.py" },
59
+ windsurf: { root: ".windsurf", skillMd: ".windsurf/rules/lokuma.md", scriptPy: ".windsurf/rules/lokuma/scripts/design.py" },
60
+ copilot: { root: ".github", skillMd: ".github/instructions/lokuma.instructions.md", scriptPy: ".github/instructions/lokuma/scripts/design.py" },
61
+ kiro: { root: ".kiro", skillMd: ".kiro/steering/lokuma.md", scriptPy: ".kiro/steering/lokuma/scripts/design.py" },
62
+ roocode: { root: ".roo", skillMd: ".roo/rules/lokuma.md", scriptPy: ".roo/rules/lokuma/scripts/design.py" },
63
+ codex: { root: ".codex", skillMd: ".codex/instructions.md", scriptPy: ".codex/lokuma/scripts/design.py" },
64
+ qoder: { root: ".qoder", skillMd: ".qoder/rules/lokuma.md", scriptPy: ".qoder/rules/lokuma/scripts/design.py" },
65
+ gemini: { root: ".gemini", skillMd: ".gemini/GEMINI.md", scriptPy: ".gemini/lokuma/scripts/design.py" },
66
+ trae: { root: ".trae", skillMd: ".trae/rules/lokuma.md", scriptPy: ".trae/rules/lokuma/scripts/design.py" },
67
+ opencode: { root: ".opencode", skillMd: ".opencode/OPENCODE.md", scriptPy: ".opencode/lokuma/scripts/design.py" },
68
+ continue: { root: ".continue", skillMd: ".continue/lokuma/SKILL.md", scriptPy: ".continue/lokuma/scripts/design.py" },
69
+ codebuddy: { root: ".codebuddy", skillMd: ".codebuddy/lokuma/SKILL.md", scriptPy: ".codebuddy/lokuma/scripts/design.py" },
70
+ droid: { root: ".factory", skillMd: ".factory/skills/lokuma/SKILL.md", scriptPy: ".factory/skills/lokuma/scripts/design.py" },
71
71
  // OpenClaw installs to a fixed absolute path (not relative to cwd)
72
- openclaw: { root: "~/.openclaw/workspace/skills/lokuma", skillMd: "~/.openclaw/workspace/skills/lokuma/SKILL.md", scriptPy: "~/.openclaw/workspace/skills/lokuma/scripts/search.py" }
72
+ openclaw: { root: "~/.openclaw/workspace/skills/lokuma", skillMd: "~/.openclaw/workspace/skills/lokuma/SKILL.md", scriptPy: "~/.openclaw/workspace/skills/lokuma/scripts/design.py" }
73
73
  };
74
74
 
75
75
  // src/commands/init.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lokuma-cli",
3
- "version": "1.3.5",
3
+ "version": "1.3.7",
4
4
  "description": "CLI to install Lokuma design intelligence skill for AI coding assistants",
5
5
  "type": "module",
6
6
  "bin": {