licos-dev-cli 0.2.13__tar.gz → 0.2.15__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.
@@ -12,6 +12,7 @@ packages/*/dist/
12
12
  .vscode/
13
13
  *.swp
14
14
  *.swo
15
+ *.pyc
15
16
 
16
17
  # OS
17
18
  .DS_Store
@@ -33,13 +34,16 @@ crates/industrial/industrial-stack.env
33
34
  # Build
34
35
  *.log
35
36
  *.pid
36
- crates/industrial/bin/
37
37
  .licos
38
38
  .tmp
39
39
  .playwright-cli
40
40
 
41
41
  /tmp
42
+ crates/industrial/bin/
43
+
42
44
  tools/android-sdk-cache/*.zip
45
+ tools/codegraph-cache/*.tgz
46
+ tools/codegraph-cache/*.tgz
43
47
 
44
48
  *.codex-*
45
49
 
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: licos-dev-cli
3
- Version: 0.2.13
3
+ Version: 0.2.15
4
4
  Summary: LICOS Dev CLI - generate files and call model capabilities
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: click>=8.1
7
- Requires-Dist: licos-dev-sdk>=0.2.14
7
+ Requires-Dist: licos-dev-sdk>=0.2.16
@@ -4,11 +4,11 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "licos-dev-cli"
7
- version = "0.2.13"
7
+ version = "0.2.15"
8
8
  description = "LICOS Dev CLI - generate files and call model capabilities"
9
9
  requires-python = ">=3.10"
10
10
  dependencies = [
11
- "licos-dev-sdk>=0.2.14",
11
+ "licos-dev-sdk>=0.2.16",
12
12
  "click>=8.1",
13
13
  ]
14
14
 
@@ -2,9 +2,11 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import sys
6
- import json
7
- import click
5
+ import sys
6
+ import json
7
+ import os
8
+ from pathlib import Path
9
+ import click
8
10
 
9
11
  # ── Helpers ──────────────────────────────────────────────────────────────────
10
12
 
@@ -35,21 +37,84 @@ def _json_option(value: str | None, name: str) -> dict | list | None:
35
37
  raise click.BadParameter(f"{name} must be valid JSON") from exc
36
38
 
37
39
 
38
- def _echo_json(value: object) -> None:
39
- if hasattr(value, "to_dict"):
40
- value = value.to_dict()
41
- click.echo(json.dumps(value, ensure_ascii=False, indent=2))
42
-
43
-
44
- # ── CLI Group ────────────────────────────────────────────────────────────────
45
-
46
- @click.group()
47
- def cli():
48
- """LICOS Dev - file generation and model CLI for AI agents."""
49
- pass
50
-
51
-
52
- # ── PDF ──────────────────────────────────────────────────────────────────────
40
+ def _echo_json(value: object) -> None:
41
+ if hasattr(value, "to_dict"):
42
+ value = value.to_dict()
43
+ click.echo(json.dumps(value, ensure_ascii=False, indent=2))
44
+
45
+
46
+ def _path_to_cli_output(path: object) -> str:
47
+ raw = str(path)
48
+ if not raw:
49
+ return raw
50
+
51
+ normalized = raw.replace("\\", "/")
52
+ string_roots = [
53
+ os.environ.get("LICOS_PROJECT_PATH"),
54
+ (os.path.join(os.environ["LICOS_WORKSPACE_PATH"], "projects") if os.environ.get("LICOS_WORKSPACE_PATH") else None),
55
+ "/workspace/projects",
56
+ ]
57
+ for root in string_roots:
58
+ if not root:
59
+ continue
60
+ prefix = root.replace("\\", "/").rstrip("/")
61
+ if normalized == prefix:
62
+ return "."
63
+ if normalized.startswith(f"{prefix}/"):
64
+ return normalized[len(prefix) + 1 :]
65
+
66
+ p = Path(raw)
67
+ if not p.is_absolute():
68
+ return normalized
69
+
70
+ path_roots = [
71
+ os.environ.get("LICOS_PROJECT_PATH"),
72
+ (os.path.join(os.environ["LICOS_WORKSPACE_PATH"], "projects") if os.environ.get("LICOS_WORKSPACE_PATH") else None),
73
+ str(Path.cwd()),
74
+ ]
75
+ for root in path_roots:
76
+ if not root:
77
+ continue
78
+ try:
79
+ return p.resolve().relative_to(Path(root).resolve()).as_posix()
80
+ except (OSError, RuntimeError, ValueError):
81
+ continue
82
+
83
+ return normalized
84
+
85
+
86
+ def _echo_path(path: object) -> None:
87
+ click.echo(_path_to_cli_output(path))
88
+
89
+
90
+ # ── CLI Group ────────────────────────────────────────────────────────────────
91
+
92
+ @click.group()
93
+ def cli():
94
+ """LICOS Dev - file generation and model CLI for AI agents."""
95
+ pass
96
+
97
+
98
+ @cli.command("credit-check")
99
+ @click.option("--estimated-points", default=1, type=click.IntRange(min=1), show_default=True)
100
+ @click.option("--resource-type", default="MODEL_TOOL", show_default=True)
101
+ @click.option("--resource-code", default="MANUAL_CHECK", show_default=True)
102
+ @click.option("--request-id", default=None)
103
+ def credit_check(estimated_points, resource_type, resource_code, request_id):
104
+ """Check whether the current SDK identity can execute a billed operation."""
105
+ from licos_dev_sdk import check_credit_availability
106
+
107
+ _echo_json(
108
+ check_credit_availability(
109
+ estimated_points=estimated_points,
110
+ resource_type=resource_type,
111
+ resource_code=resource_code,
112
+ request_id=request_id,
113
+ )
114
+ )
115
+
116
+
117
+ # ── PDF ──────────────────────────────────────────────────────────────────────
53
118
 
54
119
  @cli.command()
55
120
  @click.option("-i", "--input", "input_path", help="Input file (Markdown or HTML)")
@@ -60,10 +125,10 @@ def cli():
60
125
  @click.option("--page-size", default="A4", help="Page size: A4|LETTER")
61
126
  def pdf(input_path, content, filename, output_dir, content_type, page_size):
62
127
  """Generate PDF from Markdown or HTML."""
63
- from licos_dev_sdk import create_pdf
64
- text = _read_input(input_path, content)
65
- path = create_pdf(text, filename, content_type=content_type, output_dir=output_dir, page_size=page_size)
66
- click.echo(path)
128
+ from licos_dev_sdk import create_pdf
129
+ text = _read_input(input_path, content)
130
+ path = create_pdf(text, filename, content_type=content_type, output_dir=output_dir, page_size=page_size)
131
+ _echo_path(path)
67
132
 
68
133
 
69
134
  # ── DOCX ─────────────────────────────────────────────────────────────────────
@@ -78,10 +143,10 @@ def pdf(input_path, content, filename, output_dir, content_type, page_size):
78
143
  @click.option("--font-size", default=11, type=int)
79
144
  def docx(input_path, content, filename, output_dir, content_type, font, font_size):
80
145
  """Generate DOCX from Markdown or HTML."""
81
- from licos_dev_sdk import create_docx
82
- text = _read_input(input_path, content)
83
- path = create_docx(text, filename, content_type=content_type, output_dir=output_dir, font_name=font, font_size=font_size)
84
- click.echo(path)
146
+ from licos_dev_sdk import create_docx
147
+ text = _read_input(input_path, content)
148
+ path = create_docx(text, filename, content_type=content_type, output_dir=output_dir, font_name=font, font_size=font_size)
149
+ _echo_path(path)
85
150
 
86
151
 
87
152
  @cli.command("docx-template")
@@ -94,10 +159,10 @@ def docx_template(template_path, input_path, data_content, filename, output_dir)
94
159
  """Generate DOCX by rendering a DOCX template with JSON data."""
95
160
  from licos_dev_sdk import create_docx_from_template
96
161
  data = _read_json(input_path, data_content)
97
- if not isinstance(data, dict):
98
- raise click.BadParameter("template data must be a JSON object")
99
- path = create_docx_from_template(template_path, data, filename, output_dir=output_dir)
100
- click.echo(path)
162
+ if not isinstance(data, dict):
163
+ raise click.BadParameter("template data must be a JSON object")
164
+ path = create_docx_from_template(template_path, data, filename, output_dir=output_dir)
165
+ _echo_path(path)
101
166
 
102
167
 
103
168
  # ── XLSX ─────────────────────────────────────────────────────────────────────
@@ -111,10 +176,10 @@ def docx_template(template_path, input_path, data_content, filename, output_dir)
111
176
  @click.option("--header-color", default="4472C4")
112
177
  def xlsx(input_path, content, filename, output_dir, sheet_name, header_color):
113
178
  """Generate XLSX from JSON data."""
114
- from licos_dev_sdk import create_xlsx
115
- data = _read_json(input_path, content)
116
- path = create_xlsx(data, filename, output_dir=output_dir, sheet_name=sheet_name, header_color=header_color)
117
- click.echo(path)
179
+ from licos_dev_sdk import create_xlsx
180
+ data = _read_json(input_path, content)
181
+ path = create_xlsx(data, filename, output_dir=output_dir, sheet_name=sheet_name, header_color=header_color)
182
+ _echo_path(path)
118
183
 
119
184
 
120
185
  @cli.command("xlsx-workbook")
@@ -134,10 +199,10 @@ def xlsx_workbook(input_path, content, filename, output_dir, header_color, freez
134
199
  filename,
135
200
  output_dir=output_dir,
136
201
  header_color=header_color,
137
- freeze_header=freeze_header,
138
- autofilter=autofilter,
139
- )
140
- click.echo(path)
202
+ freeze_header=freeze_header,
203
+ autofilter=autofilter,
204
+ )
205
+ _echo_path(path)
141
206
 
142
207
 
143
208
  # ── CSV ──────────────────────────────────────────────────────────────────────
@@ -149,10 +214,10 @@ def xlsx_workbook(input_path, content, filename, output_dir, header_color, freez
149
214
  @click.option("-o", "--output-dir", default=None)
150
215
  def csv(input_path, content, filename, output_dir):
151
216
  """Generate CSV from JSON data."""
152
- from licos_dev_sdk import create_csv
153
- data = _read_json(input_path, content)
154
- path = create_csv(data, filename, output_dir=output_dir)
155
- click.echo(path)
217
+ from licos_dev_sdk import create_csv
218
+ data = _read_json(input_path, content)
219
+ path = create_csv(data, filename, output_dir=output_dir)
220
+ _echo_path(path)
156
221
 
157
222
 
158
223
  # ── PPTX ─────────────────────────────────────────────────────────────────────
@@ -165,10 +230,10 @@ def csv(input_path, content, filename, output_dir):
165
230
  @click.option("--format", "content_type", default="markdown")
166
231
  def pptx(input_path, content, filename, output_dir, content_type):
167
232
  """Generate PPTX from Markdown."""
168
- from licos_dev_sdk import create_pptx
169
- text = _read_input(input_path, content)
170
- path = create_pptx(text, filename, content_type=content_type, output_dir=output_dir)
171
- click.echo(path)
233
+ from licos_dev_sdk import create_pptx
234
+ text = _read_input(input_path, content)
235
+ path = create_pptx(text, filename, content_type=content_type, output_dir=output_dir)
236
+ _echo_path(path)
172
237
 
173
238
 
174
239
  # ── Chart ────────────────────────────────────────────────────────────────────
@@ -185,10 +250,10 @@ def pptx(input_path, content, filename, output_dir, content_type):
185
250
  @click.option("--height", default=600, type=int)
186
251
  def chart(input_path, content, filename, output_dir, chart_type, fmt, title, width, height):
187
252
  """Generate chart image from JSON data."""
188
- from licos_dev_sdk import create_chart
189
- data = _read_json(input_path, content)
190
- path = create_chart(chart_type, data, filename, output_dir=output_dir, format=fmt, title=title, width=width, height=height)
191
- click.echo(path)
253
+ from licos_dev_sdk import create_chart
254
+ data = _read_json(input_path, content)
255
+ path = create_chart(chart_type, data, filename, output_dir=output_dir, format=fmt, title=title, width=width, height=height)
256
+ _echo_path(path)
192
257
 
193
258
 
194
259
  # ── Diagram ──────────────────────────────────────────────────────────────────
@@ -201,10 +266,10 @@ def chart(input_path, content, filename, output_dir, chart_type, fmt, title, wid
201
266
  @click.option("--format", "fmt", default="png", help="png|svg|pdf")
202
267
  def diagram(input_path, content, filename, output_dir, fmt):
203
268
  """Generate diagram from Graphviz DOT source."""
204
- from licos_dev_sdk import create_diagram
205
- text = _read_input(input_path, content)
206
- path = create_diagram(text, filename, output_dir=output_dir, format=fmt)
207
- click.echo(path)
269
+ from licos_dev_sdk import create_diagram
270
+ text = _read_input(input_path, content)
271
+ path = create_diagram(text, filename, output_dir=output_dir, format=fmt)
272
+ _echo_path(path)
208
273
 
209
274
 
210
275
  # ── QR Code ──────────────────────────────────────────────────────────────────
@@ -216,9 +281,9 @@ def diagram(input_path, content, filename, output_dir, fmt):
216
281
  @click.option("--size", default=300, type=int)
217
282
  def qrcode(data, filename, output_dir, size):
218
283
  """Generate QR code PNG image."""
219
- from licos_dev_sdk import create_qrcode
220
- path = create_qrcode(data, filename, output_dir=output_dir, size=size)
221
- click.echo(path)
284
+ from licos_dev_sdk import create_qrcode
285
+ path = create_qrcode(data, filename, output_dir=output_dir, size=size)
286
+ _echo_path(path)
222
287
 
223
288
 
224
289
  # ── Barcode ──────────────────────────────────────────────────────────────────
@@ -230,9 +295,9 @@ def qrcode(data, filename, output_dir, size):
230
295
  @click.option("--type", "barcode_type", default="code128", help="code128|ean13|ean8|isbn13|upc")
231
296
  def barcode(data, filename, output_dir, barcode_type):
232
297
  """Generate barcode PNG image."""
233
- from licos_dev_sdk import create_barcode
234
- path = create_barcode(data, filename, output_dir=output_dir, barcode_type=barcode_type)
235
- click.echo(path)
298
+ from licos_dev_sdk import create_barcode
299
+ path = create_barcode(data, filename, output_dir=output_dir, barcode_type=barcode_type)
300
+ _echo_path(path)
236
301
 
237
302
 
238
303
  # ── ZIP ──────────────────────────────────────────────────────────────────────
@@ -243,10 +308,10 @@ def barcode(data, filename, output_dir, barcode_type):
243
308
  @click.option("-o", "--output-dir", default=None)
244
309
  def zip_cmd(paths, filename, output_dir):
245
310
  """Create ZIP archive."""
246
- from licos_dev_sdk import create_zip
247
- source_paths = [p.strip() for p in paths.split(",")]
248
- path = create_zip(source_paths, filename, output_dir=output_dir)
249
- click.echo(path)
311
+ from licos_dev_sdk import create_zip
312
+ source_paths = [p.strip() for p in paths.split(",")]
313
+ path = create_zip(source_paths, filename, output_dir=output_dir)
314
+ _echo_path(path)
250
315
 
251
316
 
252
317
  # ── TAR.GZ ───────────────────────────────────────────────────────────────────
@@ -257,10 +322,10 @@ def zip_cmd(paths, filename, output_dir):
257
322
  @click.option("-o", "--output-dir", default=None)
258
323
  def tar_cmd(paths, filename, output_dir):
259
324
  """Create TAR.GZ archive."""
260
- from licos_dev_sdk import create_tar_gz
261
- source_paths = [p.strip() for p in paths.split(",")]
262
- path = create_tar_gz(source_paths, filename, output_dir=output_dir)
263
- click.echo(path)
325
+ from licos_dev_sdk import create_tar_gz
326
+ source_paths = [p.strip() for p in paths.split(",")]
327
+ path = create_tar_gz(source_paths, filename, output_dir=output_dir)
328
+ _echo_path(path)
264
329
 
265
330
 
266
331
  # ── JSON ─────────────────────────────────────────────────────────────────────
@@ -276,11 +341,11 @@ def json_cmd(input_path, content, filename, output_dir):
276
341
  raw = _read_input(input_path, content)
277
342
  try:
278
343
  data = json.loads(raw)
279
- except json.JSONDecodeError:
280
- import yaml
281
- data = yaml.safe_load(raw)
282
- path = create_json(data, filename, output_dir=output_dir)
283
- click.echo(path)
344
+ except json.JSONDecodeError:
345
+ import yaml
346
+ data = yaml.safe_load(raw)
347
+ path = create_json(data, filename, output_dir=output_dir)
348
+ _echo_path(path)
284
349
 
285
350
 
286
351
  # ── YAML ─────────────────────────────────────────────────────────────────────
@@ -297,10 +362,10 @@ def yaml_cmd(input_path, content, filename, output_dir):
297
362
  raw = _read_input(input_path, content)
298
363
  try:
299
364
  data = json.loads(raw)
300
- except json.JSONDecodeError:
301
- data = yaml_lib.safe_load(raw)
302
- path = create_yaml(data, filename, output_dir=output_dir)
303
- click.echo(path)
365
+ except json.JSONDecodeError:
366
+ data = yaml_lib.safe_load(raw)
367
+ path = create_yaml(data, filename, output_dir=output_dir)
368
+ _echo_path(path)
304
369
 
305
370
 
306
371
  # ── XML ──────────────────────────────────────────────────────────────────────
@@ -313,10 +378,10 @@ def yaml_cmd(input_path, content, filename, output_dir):
313
378
  @click.option("--root-tag", default="root")
314
379
  def xml_cmd(input_path, content, filename, output_dir, root_tag):
315
380
  """Generate XML file from JSON data."""
316
- from licos_dev_sdk import create_xml
317
- data = _read_json(input_path, content)
318
- path = create_xml(data, filename, output_dir=output_dir, root_tag=root_tag)
319
- click.echo(path)
381
+ from licos_dev_sdk import create_xml
382
+ data = _read_json(input_path, content)
383
+ path = create_xml(data, filename, output_dir=output_dir, root_tag=root_tag)
384
+ _echo_path(path)
320
385
 
321
386
 
322
387
  # ── HTML ─────────────────────────────────────────────────────────────────────
@@ -329,10 +394,10 @@ def xml_cmd(input_path, content, filename, output_dir, root_tag):
329
394
  @click.option("--format", "content_type", default="markdown", help="markdown|html")
330
395
  def html_cmd(input_path, content, filename, output_dir, content_type):
331
396
  """Generate HTML file from Markdown or raw HTML."""
332
- from licos_dev_sdk import create_html
333
- text = _read_input(input_path, content)
334
- path = create_html(text, filename, output_dir=output_dir, content_type=content_type)
335
- click.echo(path)
397
+ from licos_dev_sdk import create_html
398
+ text = _read_input(input_path, content)
399
+ path = create_html(text, filename, output_dir=output_dir, content_type=content_type)
400
+ _echo_path(path)
336
401
 
337
402
 
338
403
  # ── Model Catalog ────────────────────────────────────────────────────────────
@@ -0,0 +1,33 @@
1
+ import os
2
+ from pathlib import Path
3
+
4
+ from licos_dev_cli.main import _path_to_cli_output
5
+
6
+
7
+ def test_project_absolute_path_is_printed_relative(tmp_path, monkeypatch):
8
+ project = tmp_path / "projects"
9
+ monkeypatch.setenv("LICOS_PROJECT_PATH", str(project))
10
+
11
+ assert _path_to_cli_output(project / "reports" / "demo.docx") == "reports/demo.docx"
12
+
13
+
14
+ def test_project_root_is_printed_as_dot(tmp_path, monkeypatch):
15
+ project = tmp_path / "projects"
16
+ monkeypatch.setenv("LICOS_PROJECT_PATH", str(project))
17
+
18
+ assert _path_to_cli_output(project) == "."
19
+
20
+
21
+ def test_external_absolute_path_is_not_trimmed(tmp_path, monkeypatch):
22
+ project = tmp_path / "projects"
23
+ external = tmp_path / "other" / "demo.docx"
24
+ monkeypatch.setenv("LICOS_PROJECT_PATH", str(project))
25
+
26
+ assert _path_to_cli_output(external) == external.as_posix()
27
+
28
+
29
+ def test_agent_default_project_path_is_printed_relative(monkeypatch):
30
+ monkeypatch.delenv("LICOS_PROJECT_PATH", raising=False)
31
+ monkeypatch.delenv("LICOS_WORKSPACE_PATH", raising=False)
32
+
33
+ assert _path_to_cli_output("/workspace/projects/output/demo.docx") == "output/demo.docx"
@@ -0,0 +1,39 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from unittest import mock
5
+
6
+ from click.testing import CliRunner
7
+
8
+ from licos_dev_cli.main import cli
9
+
10
+
11
+ def test_credit_check_forwards_structured_options() -> None:
12
+ availability = {"allowed": True, "availableBalance": 100}
13
+ with mock.patch(
14
+ "licos_dev_sdk.check_credit_availability",
15
+ return_value=availability,
16
+ ) as check:
17
+ result = CliRunner().invoke(
18
+ cli,
19
+ [
20
+ "credit-check",
21
+ "--estimated-points",
22
+ "2",
23
+ "--resource-type",
24
+ "MODEL_TOOL",
25
+ "--resource-code",
26
+ "IMAGE_GENERATE",
27
+ "--request-id",
28
+ "request-1",
29
+ ],
30
+ )
31
+
32
+ assert result.exit_code == 0
33
+ assert json.loads(result.output) == availability
34
+ check.assert_called_once_with(
35
+ estimated_points=2,
36
+ resource_type="MODEL_TOOL",
37
+ resource_code="IMAGE_GENERATE",
38
+ request_id="request-1",
39
+ )