cloudwright-ai-cli 0.2.0__tar.gz → 0.2.2__tar.gz

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.
Files changed (36) hide show
  1. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/PKG-INFO +1 -1
  2. cloudwright_ai_cli-0.2.2/cloudwright_cli/__init__.py +1 -0
  3. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/analyze_cmd.py +8 -0
  4. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/catalog_cmd.py +32 -13
  5. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/design.py +7 -1
  6. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/modify_cmd.py +6 -1
  7. cloudwright_ai_cli-0.2.0/cloudwright_cli/__init__.py +0 -1
  8. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/.gitignore +0 -0
  9. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/CLAUDE.md +0 -0
  10. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/README.md +0 -0
  11. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/__main__.py +0 -0
  12. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/__init__.py +0 -0
  13. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/chat.py +0 -0
  14. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/compare.py +0 -0
  15. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/cost.py +0 -0
  16. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/diff.py +0 -0
  17. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/drift_cmd.py +0 -0
  18. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/export.py +0 -0
  19. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/import_cmd.py +0 -0
  20. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/init_cmd.py +0 -0
  21. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/lint_cmd.py +0 -0
  22. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/policy.py +0 -0
  23. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/refresh_cmd.py +0 -0
  24. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/score_cmd.py +0 -0
  25. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/commands/validate.py +0 -0
  26. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/main.py +0 -0
  27. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/project.py +0 -0
  28. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/py.typed +0 -0
  29. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/cloudwright_cli/utils.py +0 -0
  30. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/pyproject.toml +0 -0
  31. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/tests/__init__.py +0 -0
  32. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/tests/test_cli.py +0 -0
  33. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/tests/test_drift_cmd.py +0 -0
  34. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/tests/test_init.py +0 -0
  35. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/tests/test_modify_cmd.py +0 -0
  36. {cloudwright_ai_cli-0.2.0 → cloudwright_ai_cli-0.2.2}/tests/test_project.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudwright-ai-cli
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: CLI for Cloudwright architecture intelligence
5
5
  Project-URL: Homepage, https://github.com/xmpuspus/cloudwright
6
6
  Project-URL: Repository, https://github.com/xmpuspus/cloudwright
@@ -0,0 +1 @@
1
+ __version__ = "0.2.2"
@@ -27,6 +27,14 @@ def analyze(
27
27
  from cloudwright.analyzer import Analyzer
28
28
 
29
29
  spec = ArchSpec.from_file(spec_file)
30
+
31
+ if component:
32
+ valid_ids = {c.id for c in spec.components}
33
+ if component not in valid_ids:
34
+ console.print(f"[red]Error:[/red] Component '{component}' not found in spec.")
35
+ console.print(f"[dim]Available components: {', '.join(sorted(valid_ids))}[/dim]")
36
+ raise typer.Exit(1)
37
+
30
38
  analyzer = Analyzer()
31
39
  result = analyzer.analyze(spec, component_id=component)
32
40
 
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import re
3
4
  from typing import Annotated
4
5
 
5
6
  import typer
@@ -34,16 +35,33 @@ def catalog_search(
34
35
  memory: Annotated[float | None, typer.Option(help="Minimum memory in GB")] = None,
35
36
  ) -> None:
36
37
  """Search the cloud service catalog."""
37
- filters: dict = {}
38
- if provider:
39
- filters["provider"] = provider.lower()
40
- if vcpus is not None:
41
- filters["min_vcpus"] = vcpus
42
- if memory is not None:
43
- filters["min_memory_gb"] = memory
38
+ # Extract structured filters from natural language query
39
+ parsed_vcpus = vcpus
40
+ parsed_memory = memory
41
+ text_query = query
42
+
43
+ if parsed_vcpus is None:
44
+ m = re.search(r"(\d+)\s*vcpu", query, re.IGNORECASE)
45
+ if m:
46
+ parsed_vcpus = int(m.group(1))
47
+ text_query = re.sub(r"\d+\s*vcpus?\s*", "", text_query, flags=re.IGNORECASE).strip()
48
+
49
+ if parsed_memory is None:
50
+ m = re.search(r"(\d+(?:\.\d+)?)\s*(?:gb|gib)\s*(?:memory|ram)?", query, re.IGNORECASE)
51
+ if m:
52
+ parsed_memory = float(m.group(1))
53
+ text_query = re.sub(r"\d+(?:\.\d+)?\s*(?:gb|gib)\s*(?:memory|ram)?\s*", "", text_query, flags=re.IGNORECASE).strip()
54
+
55
+ # Clean up leftover whitespace/empty query
56
+ text_query = text_query.strip() or None
44
57
 
45
58
  with console.status("Searching catalog..."):
46
- results = Catalog().search(query, **filters)
59
+ results = Catalog().search(
60
+ query=text_query,
61
+ vcpus=parsed_vcpus,
62
+ memory_gb=parsed_memory,
63
+ provider=provider,
64
+ )
47
65
 
48
66
  # Resolve ctx.obj through parent chain when invoked via sub-app
49
67
  obj = ctx.obj or (ctx.parent.obj if ctx.parent else None)
@@ -67,14 +85,15 @@ def catalog_search(
67
85
  table.add_column("Notes", style="dim")
68
86
 
69
87
  for item in results:
88
+ price = item.get("price_per_hour")
70
89
  table.add_row(
71
- item.get("service", ""),
72
- item.get("provider", ""),
73
- item.get("label", ""),
90
+ item.get("name", ""),
91
+ item.get("provider_id", ""),
92
+ item.get("family", ""),
74
93
  str(item.get("vcpus", "-")),
75
94
  str(item.get("memory_gb", "-")),
76
- f"${item['hourly']:.4f}" if item.get("hourly") else "-",
77
- item.get("notes", ""),
95
+ f"${price:.4f}" if price else "-",
96
+ item.get("description", ""),
78
97
  )
79
98
 
80
99
  console.print(table)
@@ -35,8 +35,14 @@ def design(
35
35
  compliance=compliance or [],
36
36
  )
37
37
 
38
+ try:
39
+ architect = Architect()
40
+ except RuntimeError as e:
41
+ console.print(f"[red]Error:[/red] {e}")
42
+ raise typer.Exit(1) from None
43
+
38
44
  with console.status("Designing architecture..."):
39
- spec = Architect().design(description, constraints=constraints)
45
+ spec = architect.design(description, constraints=constraints)
40
46
  # Set provider/region from CLI args if not overridden by LLM
41
47
  if spec.provider == "aws" and provider != "aws":
42
48
  spec = spec.model_copy(update={"provider": provider})
@@ -40,8 +40,13 @@ def modify(
40
40
 
41
41
  console.print(f"Modifying [cyan]{spec_file}[/cyan]: [yellow]{instruction}[/yellow]\n")
42
42
 
43
- with console.status("Applying modification..."):
43
+ try:
44
44
  architect = Architect()
45
+ except RuntimeError as e:
46
+ console.print(f"[red]Error:[/red] {e}")
47
+ raise typer.Exit(1) from None
48
+
49
+ with console.status("Applying modification..."):
45
50
  modified = architect.modify(original, instruction)
46
51
 
47
52
  # Price both versions; ignore errors (catalog may not have all services)
@@ -1 +0,0 @@
1
- __version__ = "0.2.0"