airgen-cli 0.17.0 → 0.17.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.
@@ -18,15 +18,14 @@ function sanitizeId(id) {
18
18
  }
19
19
  function mermaidNodeShape(block) {
20
20
  const id = sanitizeId(block.id);
21
- const label = block.name.replace(/"/g, "'");
22
- const stereo = block.stereotype?.replace(/[«»<>]/g, "") ?? block.kind ?? "block";
23
- const display = `"<<${stereo}>><br/>${label}"`;
21
+ const label = block.name.replace(/"/g, "'").replace(/[<>]/g, "");
22
+ const stereo = block.stereotype?.replace(/[«»<>]/g, "") ?? block.kind ?? "";
23
+ // Use Mermaid-safe label: stereotype on separate line via <br>, no << >> delimiters
24
+ const display = stereo ? `"${stereo}<br>${label}"` : `"${label}"`;
25
+ // Use only universally supported shapes: [] for most, {} for interface
24
26
  switch (block.kind) {
25
- case "system": return `${id}[${display}]`;
26
- case "subsystem": return `${id}[${display}]`;
27
- case "actor": return `${id}([${display}])`;
28
- case "external": return `${id}[${display}]`;
29
- case "interface": return `${id}{{${display}}}`;
27
+ case "actor": return `${id}[${display}]`;
28
+ case "interface": return `${id}[${display}]`;
30
29
  default: return `${id}[${display}]`;
31
30
  }
32
31
  }
@@ -187,7 +186,7 @@ function renderMermaid(blocks, connectors, direction) {
187
186
  const tgt = sanitizeId(c.target);
188
187
  const arrow = mermaidArrow(c.kind);
189
188
  if (c.label) {
190
- const edgeLabel = c.label.replace(/"/g, "'");
189
+ const edgeLabel = c.label.replace(/"/g, "'").replace(/[<>|]/g, "");
191
190
  lines.push(` ${src} ${arrow}|${edgeLabel}| ${tgt}`);
192
191
  }
193
192
  else {
@@ -290,7 +289,10 @@ export function registerDiagramCommands(program, client) {
290
289
  rendered = rendered
291
290
  .split("\n")
292
291
  .filter(l => !l.trim().startsWith("classDef ") && !l.trim().startsWith("class ") && !l.trim().startsWith("style "))
293
- .map(l => l.replace(/<<[^>]+>><br\/>/g, "")) // Strip <<stereotype>><br/> from node labels
292
+ .map(l => l
293
+ .replace(/<<[^>]+>><br\/?>/g, "") // Strip <<stereotype>><br> or <<stereotype>><br/>
294
+ .replace(/[a-z]+<br>/gi, (m) => m) // Keep stereo<br>label (valid Mermaid)
295
+ )
294
296
  .join("\n");
295
297
  }
296
298
  if (isJsonMode()) {
@@ -147,7 +147,7 @@ export function registerProjectCommands(program, client) {
147
147
  });
148
148
  cmd
149
149
  .command("delete")
150
- .description("Delete a project")
150
+ .description("Delete a project by slug")
151
151
  .argument("<tenant>", "Tenant slug")
152
152
  .argument("<project>", "Project slug")
153
153
  .action(async (tenant, project) => {
@@ -51,6 +51,7 @@ export declare class UhtClient {
51
51
  private request;
52
52
  classify(entity: string): Promise<UhtClassification>;
53
53
  batchCompare(entity: string, candidates: string[]): Promise<UhtBatchResult>;
54
- /** Look up an entity by name in a Substrate namespace. Returns null if not found. */
54
+ /** Look up an entity by name in a Substrate namespace. Returns null if not found.
55
+ * Only returns exact name matches (case-insensitive) — no fuzzy fallback. */
55
56
  lookupEntity(name: string, namespace: string): Promise<UhtEntityRecord | null>;
56
57
  }
@@ -76,11 +76,11 @@ export class UhtClient {
76
76
  async batchCompare(entity, candidates) {
77
77
  return this.request("POST", "/batch-compare", { entity, candidates });
78
78
  }
79
- /** Look up an entity by name in a Substrate namespace. Returns null if not found. */
79
+ /** Look up an entity by name in a Substrate namespace. Returns null if not found.
80
+ * Only returns exact name matches (case-insensitive) — no fuzzy fallback. */
80
81
  async lookupEntity(name, namespace) {
81
82
  const data = await this.request("GET", `/entities?namespace=${encodeURIComponent(namespace)}&name=${encodeURIComponent(name)}&limit=10`);
82
- // Prefer exact match (case-insensitive), fall back to first result
83
- const exact = data.entities.find(e => e.name.toLowerCase() === name.toLowerCase());
84
- return exact ?? data.entities[0] ?? null;
83
+ // Exact match only — the API does substring filtering, so we must check
84
+ return data.entities.find(e => e.name.toLowerCase() === name.toLowerCase()) ?? null;
85
85
  }
86
86
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "airgen-cli",
3
- "version": "0.17.0",
3
+ "version": "0.17.2",
4
4
  "description": "AIRGen CLI — requirements engineering from the command line",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",