cartograph-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 (66) hide show
  1. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/.github/workflows/fresh-install.yml +3 -3
  2. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/PKG-INFO +1 -1
  3. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/pyproject.toml +1 -1
  4. cartograph_cli-0.2.2/src/cartograph/_vendor/agent_cli.py +195 -0
  5. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/cli.py +5 -1
  6. cartograph_cli-0.2.2/tests/__init__.py +0 -0
  7. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/.github/workflows/publish.yml +0 -0
  8. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/.github/workflows/test.yml +0 -0
  9. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/.gitignore +0 -0
  10. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/CLAUDE.md +0 -0
  11. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/CONTRIBUTING.md +0 -0
  12. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/LICENSE +0 -0
  13. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/README.md +0 -0
  14. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/cg/infra_agent_cli_python/.validation_stamp.json +0 -0
  15. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/cg/infra_agent_cli_python/examples/example_usage.py +0 -0
  16. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/cg/infra_agent_cli_python/src/__init__.py +0 -0
  17. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/cg/infra_agent_cli_python/src/agent_cli.py +0 -0
  18. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/cg/infra_agent_cli_python/tests/test_agent_cli.py +0 -0
  19. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/cg/infra_agent_cli_python/widget.json +0 -0
  20. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/logo/logo-cartograph-black.svg +0 -0
  21. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/logo/logo-cartograph-white.svg +0 -0
  22. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/logo/logo-cartograph.svg +0 -0
  23. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/pytest.ini +0 -0
  24. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/__init__.py +0 -0
  25. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/__main__.py +0 -0
  26. {cartograph_cli-0.2.0/tests → cartograph_cli-0.2.2/src/cartograph/_vendor}/__init__.py +0 -0
  27. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/auth.py +0 -0
  28. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/checkin.py +0 -0
  29. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/cloud.py +0 -0
  30. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/dashboard.py +0 -0
  31. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/dashboard_ui.py +0 -0
  32. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/engine.py +0 -0
  33. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/inspector.py +0 -0
  34. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/installer.py +0 -0
  35. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/languages/__init__.py +0 -0
  36. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/languages/base.py +0 -0
  37. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/languages/javascript.py +0 -0
  38. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/languages/nim.py +0 -0
  39. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/languages/python.py +0 -0
  40. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/languages/registry.py +0 -0
  41. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/languages/scanners/js_scanner.js +0 -0
  42. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/languages/scanners/nim_scanner.nim +0 -0
  43. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/library_config.json +0 -0
  44. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/scaffolding/__init__.py +0 -0
  45. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/search/__init__.py +0 -0
  46. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/search/base.py +0 -0
  47. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/search/bm25.py +0 -0
  48. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/search/filters.py +0 -0
  49. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/search/hybrid.py +0 -0
  50. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/search/ngram.py +0 -0
  51. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/search/synonyms.json +0 -0
  52. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/trust.py +0 -0
  53. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/validation_stamp.py +0 -0
  54. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/src/cartograph/validator.py +0 -0
  55. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/cloud_health.py +0 -0
  56. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/conftest.py +0 -0
  57. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/fresh_install/Dockerfile +0 -0
  58. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/fresh_install/test_fresh_install.sh +0 -0
  59. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/test_checkin.py +0 -0
  60. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/test_create.py +0 -0
  61. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/test_inspect.py +0 -0
  62. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/test_install.py +0 -0
  63. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/test_language_engines.py +0 -0
  64. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/test_loading.py +0 -0
  65. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/test_search.py +0 -0
  66. {cartograph_cli-0.2.0 → cartograph_cli-0.2.2}/tests/test_validate.py +0 -0
@@ -54,9 +54,9 @@ jobs:
54
54
 
55
55
  - name: Verify widget structure
56
56
  run: |
57
- test -f cartograph/backend-ci-test-python/widget.json
58
- test -d cartograph/backend-ci-test-python/src
59
- test -d cartograph/backend-ci-test-python/tests
57
+ test -f cg/backend-ci-test-python/widget.json
58
+ test -d cg/backend-ci-test-python/src
59
+ test -d cg/backend-ci-test-python/tests
60
60
 
61
61
  - name: cartograph stats
62
62
  run: cartograph stats
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cartograph-cli
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Widget library manager for AI agents — CLI
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cartograph-cli"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "Widget library manager for AI agents — CLI"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -0,0 +1,195 @@
1
+ """
2
+ Agent CLI - a declarative CLI framework for LLM/agent-driven tools.
3
+
4
+ Design principles:
5
+ - All output is JSON (structured, parseable by agents)
6
+ - No interactive prompts (agents can't answer y/n)
7
+ - Grouped help text (readable by humans and agents)
8
+ - Commands are plain functions that receive parsed args
9
+ - Declarative: define commands as dicts, get argparse wiring for free
10
+
11
+ Usage:
12
+
13
+ from agent_cli import AgentCLI, out, err
14
+
15
+ def cmd_greet(args):
16
+ return {"message": f"hello {args.name}"}
17
+
18
+ cli = AgentCLI(
19
+ prog="mytool",
20
+ description="My agent-friendly tool",
21
+ version="1.0.0",
22
+ )
23
+ cli.add_commands("Basics", [
24
+ {
25
+ "name": "greet",
26
+ "help": "Say hello",
27
+ "handler": cmd_greet,
28
+ "args": [
29
+ {"name": "name", "help": "Who to greet"},
30
+ ],
31
+ },
32
+ ])
33
+ cli.run()
34
+ """
35
+
36
+ import argparse
37
+ import json
38
+ import sys
39
+
40
+
41
+ def out(result: dict) -> None:
42
+ """Write a JSON result to stdout."""
43
+ sys.stdout.write(json.dumps(result, indent=2) + "\n")
44
+
45
+
46
+ def err(result: dict, code: int = 1) -> None:
47
+ """Write a JSON error to stdout and exit."""
48
+ out(result)
49
+ sys.exit(code)
50
+
51
+
52
+ def ok(message: str = "success", **extra) -> dict:
53
+ """Build a success result dict."""
54
+ return {"status": "ok", "message": message, **extra}
55
+
56
+
57
+ def fail(message: str, **extra) -> dict:
58
+ """Build an error result dict."""
59
+ return {"status": "error", "message": message, **extra}
60
+
61
+
62
+ class AgentCLI:
63
+ """Declarative CLI builder that produces agent-friendly JSON output."""
64
+
65
+ def __init__(self, prog: str, description: str = "", version: str = ""):
66
+ self.prog = prog
67
+ self.description = description
68
+ self.version = version
69
+ self._groups: list[tuple[str, list[dict]]] = []
70
+
71
+ def add_commands(self, group_name: str, commands: list[dict]) -> None:
72
+ """Register a group of commands.
73
+
74
+ Each command dict has:
75
+ name: str - subcommand name (use "parent child" for nested)
76
+ help: str - one-line description
77
+ handler: callable - function(args) -> dict or None
78
+ args: list[dict] - argument specs (see _add_arg)
79
+ """
80
+ self._groups.append((group_name, commands))
81
+
82
+ def build_parser(self) -> argparse.ArgumentParser:
83
+ """Build the argparse parser from declared command groups."""
84
+ parser = argparse.ArgumentParser(
85
+ prog=self.prog,
86
+ description=self.description,
87
+ usage=argparse.SUPPRESS,
88
+ add_help=False,
89
+ )
90
+ parser.add_argument("-h", "--help", action="store_true", default=False)
91
+ if self.version:
92
+ parser.add_argument(
93
+ "-v", "--version", action="version",
94
+ version=f"{self.prog} {self.version}",
95
+ )
96
+
97
+ sub = parser.add_subparsers(dest="command", metavar="<command>")
98
+ self._nested_parsers = {}
99
+
100
+ for _group_name, commands in self._groups:
101
+ for cmd in commands:
102
+ name = cmd["name"]
103
+ parts = name.split()
104
+ handler = cmd.get("handler")
105
+
106
+ if len(parts) == 2:
107
+ parent, child = parts
108
+ if parent not in self._nested_parsers:
109
+ parent_parser = sub.add_parser(parent, help=f"{parent} operations")
110
+ parent_sub = parent_parser.add_subparsers(dest=f"{parent}_command")
111
+ self._nested_parsers[parent] = (parent_parser, parent_sub)
112
+ _, parent_sub = self._nested_parsers[parent]
113
+ p = parent_sub.add_parser(child, help=cmd.get("help", ""))
114
+ else:
115
+ p = sub.add_parser(name, help=cmd.get("help", ""))
116
+
117
+ for arg_spec in cmd.get("args", []):
118
+ self._add_arg(p, arg_spec)
119
+
120
+ if handler:
121
+ p.set_defaults(func=handler)
122
+
123
+ for parent, (parent_parser, _) in self._nested_parsers.items():
124
+ parent_parser.set_defaults(func=lambda args, pp=parent_parser: pp.print_help())
125
+
126
+ return parser
127
+
128
+ def grouped_help(self) -> str:
129
+ """Render grouped help text with optional color."""
130
+ use_color = sys.stdout.isatty()
131
+ if use_color:
132
+ g, r = "\033[32m", "\033[0m"
133
+ else:
134
+ g, r = "", ""
135
+
136
+ lines = ["", f"usage: {self.prog} <command> [options]", ""]
137
+ for group_name, commands in self._groups:
138
+ lines.append(f" {group_name}:")
139
+ for cmd in commands:
140
+ name = cmd["name"]
141
+ desc = cmd.get("help", "")
142
+ lines.append(f" {g}{name:<16s}{r} {desc}")
143
+ lines.append("")
144
+ lines.append(f" Run '{g}{self.prog} <command> -h{r}' for command-specific help.")
145
+ lines.append("")
146
+ return "\n".join(lines)
147
+
148
+ def run(self, argv: list[str] = None) -> None:
149
+ """Parse args and dispatch to the handler.
150
+
151
+ If the handler returns a dict, it is printed as JSON.
152
+ Handlers can also call out()/err() directly for more control.
153
+ """
154
+ parser = self.build_parser()
155
+ args = parser.parse_args(argv)
156
+
157
+ if args.help or not args.command:
158
+ sys.stdout.write(self.grouped_help())
159
+ sys.exit(0)
160
+
161
+ handler = getattr(args, "func", None)
162
+ if not handler:
163
+ sys.stdout.write(self.grouped_help())
164
+ sys.exit(0)
165
+
166
+ result = handler(args)
167
+ if isinstance(result, dict):
168
+ out(result)
169
+
170
+ @staticmethod
171
+ def _add_arg(parser: argparse.ArgumentParser, spec: dict) -> None:
172
+ """Add an argument to a parser from a spec dict.
173
+
174
+ Spec keys:
175
+ name: str - positional arg name or --flag name
176
+ help: str - help text
177
+ required: bool - for optional args
178
+ default: any - default value
179
+ type: type - int, float, str, etc.
180
+ choices: list - valid values
181
+ action: str - "store_true", "store_false", etc.
182
+ nargs: str - "?", "*", "+", etc.
183
+ dest: str - attribute name on the parsed args
184
+ """
185
+ name = spec["name"]
186
+ kwargs = {}
187
+ for key in ("help", "required", "default", "type", "choices", "action", "nargs", "dest"):
188
+ if key in spec:
189
+ kwargs[key] = spec[key]
190
+
191
+ if name.startswith("-"):
192
+ parser.add_argument(name, **kwargs)
193
+ else:
194
+ kwargs.pop("required", None)
195
+ parser.add_argument(name, **kwargs)
@@ -13,7 +13,11 @@ import urllib.parse
13
13
  import zipfile
14
14
  from io import BytesIO
15
15
 
16
- from cg.infra_agent_cli_python.src.agent_cli import AgentCLI, out, err
16
+ try:
17
+ from cg.infra_agent_cli_python.src.agent_cli import AgentCLI, out, err
18
+ except ImportError:
19
+ # Fallback for pip installs where cg/ isn't available
20
+ from cartograph._vendor.agent_cli import AgentCLI, out, err
17
21
 
18
22
 
19
23
  def _check_and_prompt_tos():
File without changes
File without changes
File without changes
File without changes