licos-dev-cli 0.2.12__tar.gz → 0.2.14__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.
- {licos_dev_cli-0.2.12 → licos_dev_cli-0.2.14}/PKG-INFO +2 -2
- {licos_dev_cli-0.2.12 → licos_dev_cli-0.2.14}/pyproject.toml +2 -2
- {licos_dev_cli-0.2.12 → licos_dev_cli-0.2.14}/src/licos_dev_cli/main.py +253 -207
- licos_dev_cli-0.2.14/tests/test_cli_output_paths.py +33 -0
- {licos_dev_cli-0.2.12 → licos_dev_cli-0.2.14}/.gitignore +0 -0
- {licos_dev_cli-0.2.12 → licos_dev_cli-0.2.14}/src/licos_dev_cli/__init__.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: licos-dev-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.14
|
|
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.
|
|
7
|
+
Requires-Dist: licos-dev-sdk>=0.2.14
|
|
@@ -4,11 +4,11 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "licos-dev-cli"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.14"
|
|
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.
|
|
11
|
+
"licos-dev-sdk>=0.2.14",
|
|
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
|
|
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,13 +37,57 @@ 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
|
-
|
|
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 ────────────────────────────────────────────────────────────────
|
|
45
91
|
|
|
46
92
|
@click.group()
|
|
47
93
|
def cli():
|
|
@@ -60,10 +106,10 @@ def cli():
|
|
|
60
106
|
@click.option("--page-size", default="A4", help="Page size: A4|LETTER")
|
|
61
107
|
def pdf(input_path, content, filename, output_dir, content_type, page_size):
|
|
62
108
|
"""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
|
-
|
|
109
|
+
from licos_dev_sdk import create_pdf
|
|
110
|
+
text = _read_input(input_path, content)
|
|
111
|
+
path = create_pdf(text, filename, content_type=content_type, output_dir=output_dir, page_size=page_size)
|
|
112
|
+
_echo_path(path)
|
|
67
113
|
|
|
68
114
|
|
|
69
115
|
# ── DOCX ─────────────────────────────────────────────────────────────────────
|
|
@@ -78,10 +124,10 @@ def pdf(input_path, content, filename, output_dir, content_type, page_size):
|
|
|
78
124
|
@click.option("--font-size", default=11, type=int)
|
|
79
125
|
def docx(input_path, content, filename, output_dir, content_type, font, font_size):
|
|
80
126
|
"""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
|
-
|
|
127
|
+
from licos_dev_sdk import create_docx
|
|
128
|
+
text = _read_input(input_path, content)
|
|
129
|
+
path = create_docx(text, filename, content_type=content_type, output_dir=output_dir, font_name=font, font_size=font_size)
|
|
130
|
+
_echo_path(path)
|
|
85
131
|
|
|
86
132
|
|
|
87
133
|
@cli.command("docx-template")
|
|
@@ -94,10 +140,10 @@ def docx_template(template_path, input_path, data_content, filename, output_dir)
|
|
|
94
140
|
"""Generate DOCX by rendering a DOCX template with JSON data."""
|
|
95
141
|
from licos_dev_sdk import create_docx_from_template
|
|
96
142
|
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
|
-
|
|
143
|
+
if not isinstance(data, dict):
|
|
144
|
+
raise click.BadParameter("template data must be a JSON object")
|
|
145
|
+
path = create_docx_from_template(template_path, data, filename, output_dir=output_dir)
|
|
146
|
+
_echo_path(path)
|
|
101
147
|
|
|
102
148
|
|
|
103
149
|
# ── XLSX ─────────────────────────────────────────────────────────────────────
|
|
@@ -111,10 +157,10 @@ def docx_template(template_path, input_path, data_content, filename, output_dir)
|
|
|
111
157
|
@click.option("--header-color", default="4472C4")
|
|
112
158
|
def xlsx(input_path, content, filename, output_dir, sheet_name, header_color):
|
|
113
159
|
"""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
|
-
|
|
160
|
+
from licos_dev_sdk import create_xlsx
|
|
161
|
+
data = _read_json(input_path, content)
|
|
162
|
+
path = create_xlsx(data, filename, output_dir=output_dir, sheet_name=sheet_name, header_color=header_color)
|
|
163
|
+
_echo_path(path)
|
|
118
164
|
|
|
119
165
|
|
|
120
166
|
@cli.command("xlsx-workbook")
|
|
@@ -134,10 +180,10 @@ def xlsx_workbook(input_path, content, filename, output_dir, header_color, freez
|
|
|
134
180
|
filename,
|
|
135
181
|
output_dir=output_dir,
|
|
136
182
|
header_color=header_color,
|
|
137
|
-
freeze_header=freeze_header,
|
|
138
|
-
autofilter=autofilter,
|
|
139
|
-
)
|
|
140
|
-
|
|
183
|
+
freeze_header=freeze_header,
|
|
184
|
+
autofilter=autofilter,
|
|
185
|
+
)
|
|
186
|
+
_echo_path(path)
|
|
141
187
|
|
|
142
188
|
|
|
143
189
|
# ── CSV ──────────────────────────────────────────────────────────────────────
|
|
@@ -149,10 +195,10 @@ def xlsx_workbook(input_path, content, filename, output_dir, header_color, freez
|
|
|
149
195
|
@click.option("-o", "--output-dir", default=None)
|
|
150
196
|
def csv(input_path, content, filename, output_dir):
|
|
151
197
|
"""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
|
-
|
|
198
|
+
from licos_dev_sdk import create_csv
|
|
199
|
+
data = _read_json(input_path, content)
|
|
200
|
+
path = create_csv(data, filename, output_dir=output_dir)
|
|
201
|
+
_echo_path(path)
|
|
156
202
|
|
|
157
203
|
|
|
158
204
|
# ── PPTX ─────────────────────────────────────────────────────────────────────
|
|
@@ -165,10 +211,10 @@ def csv(input_path, content, filename, output_dir):
|
|
|
165
211
|
@click.option("--format", "content_type", default="markdown")
|
|
166
212
|
def pptx(input_path, content, filename, output_dir, content_type):
|
|
167
213
|
"""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
|
-
|
|
214
|
+
from licos_dev_sdk import create_pptx
|
|
215
|
+
text = _read_input(input_path, content)
|
|
216
|
+
path = create_pptx(text, filename, content_type=content_type, output_dir=output_dir)
|
|
217
|
+
_echo_path(path)
|
|
172
218
|
|
|
173
219
|
|
|
174
220
|
# ── Chart ────────────────────────────────────────────────────────────────────
|
|
@@ -185,10 +231,10 @@ def pptx(input_path, content, filename, output_dir, content_type):
|
|
|
185
231
|
@click.option("--height", default=600, type=int)
|
|
186
232
|
def chart(input_path, content, filename, output_dir, chart_type, fmt, title, width, height):
|
|
187
233
|
"""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
|
-
|
|
234
|
+
from licos_dev_sdk import create_chart
|
|
235
|
+
data = _read_json(input_path, content)
|
|
236
|
+
path = create_chart(chart_type, data, filename, output_dir=output_dir, format=fmt, title=title, width=width, height=height)
|
|
237
|
+
_echo_path(path)
|
|
192
238
|
|
|
193
239
|
|
|
194
240
|
# ── Diagram ──────────────────────────────────────────────────────────────────
|
|
@@ -201,10 +247,10 @@ def chart(input_path, content, filename, output_dir, chart_type, fmt, title, wid
|
|
|
201
247
|
@click.option("--format", "fmt", default="png", help="png|svg|pdf")
|
|
202
248
|
def diagram(input_path, content, filename, output_dir, fmt):
|
|
203
249
|
"""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
|
-
|
|
250
|
+
from licos_dev_sdk import create_diagram
|
|
251
|
+
text = _read_input(input_path, content)
|
|
252
|
+
path = create_diagram(text, filename, output_dir=output_dir, format=fmt)
|
|
253
|
+
_echo_path(path)
|
|
208
254
|
|
|
209
255
|
|
|
210
256
|
# ── QR Code ──────────────────────────────────────────────────────────────────
|
|
@@ -216,9 +262,9 @@ def diagram(input_path, content, filename, output_dir, fmt):
|
|
|
216
262
|
@click.option("--size", default=300, type=int)
|
|
217
263
|
def qrcode(data, filename, output_dir, size):
|
|
218
264
|
"""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
|
-
|
|
265
|
+
from licos_dev_sdk import create_qrcode
|
|
266
|
+
path = create_qrcode(data, filename, output_dir=output_dir, size=size)
|
|
267
|
+
_echo_path(path)
|
|
222
268
|
|
|
223
269
|
|
|
224
270
|
# ── Barcode ──────────────────────────────────────────────────────────────────
|
|
@@ -230,9 +276,9 @@ def qrcode(data, filename, output_dir, size):
|
|
|
230
276
|
@click.option("--type", "barcode_type", default="code128", help="code128|ean13|ean8|isbn13|upc")
|
|
231
277
|
def barcode(data, filename, output_dir, barcode_type):
|
|
232
278
|
"""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
|
-
|
|
279
|
+
from licos_dev_sdk import create_barcode
|
|
280
|
+
path = create_barcode(data, filename, output_dir=output_dir, barcode_type=barcode_type)
|
|
281
|
+
_echo_path(path)
|
|
236
282
|
|
|
237
283
|
|
|
238
284
|
# ── ZIP ──────────────────────────────────────────────────────────────────────
|
|
@@ -243,10 +289,10 @@ def barcode(data, filename, output_dir, barcode_type):
|
|
|
243
289
|
@click.option("-o", "--output-dir", default=None)
|
|
244
290
|
def zip_cmd(paths, filename, output_dir):
|
|
245
291
|
"""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
|
-
|
|
292
|
+
from licos_dev_sdk import create_zip
|
|
293
|
+
source_paths = [p.strip() for p in paths.split(",")]
|
|
294
|
+
path = create_zip(source_paths, filename, output_dir=output_dir)
|
|
295
|
+
_echo_path(path)
|
|
250
296
|
|
|
251
297
|
|
|
252
298
|
# ── TAR.GZ ───────────────────────────────────────────────────────────────────
|
|
@@ -257,10 +303,10 @@ def zip_cmd(paths, filename, output_dir):
|
|
|
257
303
|
@click.option("-o", "--output-dir", default=None)
|
|
258
304
|
def tar_cmd(paths, filename, output_dir):
|
|
259
305
|
"""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
|
-
|
|
306
|
+
from licos_dev_sdk import create_tar_gz
|
|
307
|
+
source_paths = [p.strip() for p in paths.split(",")]
|
|
308
|
+
path = create_tar_gz(source_paths, filename, output_dir=output_dir)
|
|
309
|
+
_echo_path(path)
|
|
264
310
|
|
|
265
311
|
|
|
266
312
|
# ── JSON ─────────────────────────────────────────────────────────────────────
|
|
@@ -276,11 +322,11 @@ def json_cmd(input_path, content, filename, output_dir):
|
|
|
276
322
|
raw = _read_input(input_path, content)
|
|
277
323
|
try:
|
|
278
324
|
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
|
-
|
|
325
|
+
except json.JSONDecodeError:
|
|
326
|
+
import yaml
|
|
327
|
+
data = yaml.safe_load(raw)
|
|
328
|
+
path = create_json(data, filename, output_dir=output_dir)
|
|
329
|
+
_echo_path(path)
|
|
284
330
|
|
|
285
331
|
|
|
286
332
|
# ── YAML ─────────────────────────────────────────────────────────────────────
|
|
@@ -297,10 +343,10 @@ def yaml_cmd(input_path, content, filename, output_dir):
|
|
|
297
343
|
raw = _read_input(input_path, content)
|
|
298
344
|
try:
|
|
299
345
|
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
|
-
|
|
346
|
+
except json.JSONDecodeError:
|
|
347
|
+
data = yaml_lib.safe_load(raw)
|
|
348
|
+
path = create_yaml(data, filename, output_dir=output_dir)
|
|
349
|
+
_echo_path(path)
|
|
304
350
|
|
|
305
351
|
|
|
306
352
|
# ── XML ──────────────────────────────────────────────────────────────────────
|
|
@@ -313,10 +359,10 @@ def yaml_cmd(input_path, content, filename, output_dir):
|
|
|
313
359
|
@click.option("--root-tag", default="root")
|
|
314
360
|
def xml_cmd(input_path, content, filename, output_dir, root_tag):
|
|
315
361
|
"""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
|
-
|
|
362
|
+
from licos_dev_sdk import create_xml
|
|
363
|
+
data = _read_json(input_path, content)
|
|
364
|
+
path = create_xml(data, filename, output_dir=output_dir, root_tag=root_tag)
|
|
365
|
+
_echo_path(path)
|
|
320
366
|
|
|
321
367
|
|
|
322
368
|
# ── HTML ─────────────────────────────────────────────────────────────────────
|
|
@@ -329,10 +375,10 @@ def xml_cmd(input_path, content, filename, output_dir, root_tag):
|
|
|
329
375
|
@click.option("--format", "content_type", default="markdown", help="markdown|html")
|
|
330
376
|
def html_cmd(input_path, content, filename, output_dir, content_type):
|
|
331
377
|
"""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
|
-
|
|
378
|
+
from licos_dev_sdk import create_html
|
|
379
|
+
text = _read_input(input_path, content)
|
|
380
|
+
path = create_html(text, filename, output_dir=output_dir, content_type=content_type)
|
|
381
|
+
_echo_path(path)
|
|
336
382
|
|
|
337
383
|
|
|
338
384
|
# ── Model Catalog ────────────────────────────────────────────────────────────
|
|
@@ -432,32 +478,32 @@ def vision_group():
|
|
|
432
478
|
pass
|
|
433
479
|
|
|
434
480
|
|
|
435
|
-
@vision_group.command("understand")
|
|
436
|
-
@click.option("--image", "image", multiple=True, help="Image URL, Base64 data URI, or plain Base64 image data. Can be repeated.")
|
|
437
|
-
@click.option("--image-url", "image_url", multiple=True, help="Alias for --image. Can be repeated.")
|
|
438
|
-
@click.option("--file-path", "file_path", multiple=True, help="Local image file path. Can be repeated.")
|
|
439
|
-
@click.option("-p", "--prompt", default="Describe this image.")
|
|
440
|
-
@click.option("--model", default=None)
|
|
441
|
-
@click.option("--mime-type", default=None, help="MIME type for plain Base64 image inputs. Defaults to image/png.")
|
|
442
|
-
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
443
|
-
def vision_understand(image, image_url, file_path, prompt, model, mime_type, raw_request):
|
|
444
|
-
"""Understand one or more images with the catalog vision model."""
|
|
445
|
-
from licos_dev_sdk import VisionClient
|
|
446
|
-
|
|
447
|
-
raw_payload = _json_option(raw_request, "--raw-request")
|
|
448
|
-
if raw_payload is not None and not isinstance(raw_payload, dict):
|
|
449
|
-
raise click.BadParameter("--raw-request must be a JSON object")
|
|
450
|
-
if raw_payload is None and not image_url and not image and not file_path:
|
|
451
|
-
raise click.UsageError("Provide --image, --image-url, --file-path, or --raw-request.")
|
|
452
|
-
result = VisionClient().understand(
|
|
453
|
-
images=[*image, *image_url],
|
|
454
|
-
file_paths=list(file_path),
|
|
455
|
-
prompt=prompt,
|
|
456
|
-
model=model,
|
|
457
|
-
mime_type=mime_type,
|
|
458
|
-
raw_request=raw_payload,
|
|
459
|
-
)
|
|
460
|
-
_echo_json(result)
|
|
481
|
+
@vision_group.command("understand")
|
|
482
|
+
@click.option("--image", "image", multiple=True, help="Image URL, Base64 data URI, or plain Base64 image data. Can be repeated.")
|
|
483
|
+
@click.option("--image-url", "image_url", multiple=True, help="Alias for --image. Can be repeated.")
|
|
484
|
+
@click.option("--file-path", "file_path", multiple=True, help="Local image file path. Can be repeated.")
|
|
485
|
+
@click.option("-p", "--prompt", default="Describe this image.")
|
|
486
|
+
@click.option("--model", default=None)
|
|
487
|
+
@click.option("--mime-type", default=None, help="MIME type for plain Base64 image inputs. Defaults to image/png.")
|
|
488
|
+
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
489
|
+
def vision_understand(image, image_url, file_path, prompt, model, mime_type, raw_request):
|
|
490
|
+
"""Understand one or more images with the catalog vision model."""
|
|
491
|
+
from licos_dev_sdk import VisionClient
|
|
492
|
+
|
|
493
|
+
raw_payload = _json_option(raw_request, "--raw-request")
|
|
494
|
+
if raw_payload is not None and not isinstance(raw_payload, dict):
|
|
495
|
+
raise click.BadParameter("--raw-request must be a JSON object")
|
|
496
|
+
if raw_payload is None and not image_url and not image and not file_path:
|
|
497
|
+
raise click.UsageError("Provide --image, --image-url, --file-path, or --raw-request.")
|
|
498
|
+
result = VisionClient().understand(
|
|
499
|
+
images=[*image, *image_url],
|
|
500
|
+
file_paths=list(file_path),
|
|
501
|
+
prompt=prompt,
|
|
502
|
+
model=model,
|
|
503
|
+
mime_type=mime_type,
|
|
504
|
+
raw_request=raw_payload,
|
|
505
|
+
)
|
|
506
|
+
_echo_json(result)
|
|
461
507
|
|
|
462
508
|
|
|
463
509
|
# ── Image Generation ─────────────────────────────────────────────────────────
|
|
@@ -469,35 +515,35 @@ def image_generation_group():
|
|
|
469
515
|
|
|
470
516
|
|
|
471
517
|
@image_generation_group.command("generate")
|
|
472
|
-
@click.option("-p", "--prompt")
|
|
473
|
-
@click.option("--image", "image", multiple=True, help="Source/reference image URL or Base64 data URI")
|
|
474
|
-
@click.option("--image-url", "image_url", multiple=True, help="Alias for --image")
|
|
475
|
-
@click.option("--reference-image", default=None, help="Alias for --image")
|
|
476
|
-
@click.option("--file-path", "file_path", multiple=True, help="Local source/reference image path")
|
|
477
|
-
@click.option("--input-capabilities", default=None, help="Override image model input filter: text or image")
|
|
478
|
-
@click.option("--negative-prompt", default=None)
|
|
479
|
-
@click.option("--count", default=1, type=int)
|
|
480
|
-
@click.option("--size", default=None)
|
|
518
|
+
@click.option("-p", "--prompt")
|
|
519
|
+
@click.option("--image", "image", multiple=True, help="Source/reference image URL or Base64 data URI")
|
|
520
|
+
@click.option("--image-url", "image_url", multiple=True, help="Alias for --image")
|
|
521
|
+
@click.option("--reference-image", default=None, help="Alias for --image")
|
|
522
|
+
@click.option("--file-path", "file_path", multiple=True, help="Local source/reference image path")
|
|
523
|
+
@click.option("--input-capabilities", default=None, help="Override image model input filter: text or image")
|
|
524
|
+
@click.option("--negative-prompt", default=None)
|
|
525
|
+
@click.option("--count", default=1, type=int)
|
|
526
|
+
@click.option("--size", default=None)
|
|
481
527
|
@click.option("--model", default=None)
|
|
482
|
-
@click.option("--parameters", default=None, help="Parameters JSON object")
|
|
483
|
-
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
484
|
-
@click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
|
|
485
|
-
def image_generate(
|
|
486
|
-
prompt,
|
|
487
|
-
image,
|
|
488
|
-
image_url,
|
|
489
|
-
reference_image,
|
|
490
|
-
file_path,
|
|
491
|
-
input_capabilities,
|
|
492
|
-
negative_prompt,
|
|
493
|
-
count,
|
|
494
|
-
size,
|
|
495
|
-
model,
|
|
496
|
-
parameters,
|
|
497
|
-
raw_request,
|
|
498
|
-
no_wait,
|
|
499
|
-
):
|
|
500
|
-
"""Generate images from text, image URLs/Base64, or local image files."""
|
|
528
|
+
@click.option("--parameters", default=None, help="Parameters JSON object")
|
|
529
|
+
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
530
|
+
@click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
|
|
531
|
+
def image_generate(
|
|
532
|
+
prompt,
|
|
533
|
+
image,
|
|
534
|
+
image_url,
|
|
535
|
+
reference_image,
|
|
536
|
+
file_path,
|
|
537
|
+
input_capabilities,
|
|
538
|
+
negative_prompt,
|
|
539
|
+
count,
|
|
540
|
+
size,
|
|
541
|
+
model,
|
|
542
|
+
parameters,
|
|
543
|
+
raw_request,
|
|
544
|
+
no_wait,
|
|
545
|
+
):
|
|
546
|
+
"""Generate images from text, image URLs/Base64, or local image files."""
|
|
501
547
|
from licos_dev_sdk import ImageGenerationClient
|
|
502
548
|
|
|
503
549
|
parameter_payload = _json_option(parameters, "--parameters") or {}
|
|
@@ -510,16 +556,16 @@ def image_generate(
|
|
|
510
556
|
raise click.UsageError("Provide --prompt or --raw-request.")
|
|
511
557
|
result = ImageGenerationClient().generate(
|
|
512
558
|
prompt or "",
|
|
513
|
-
negative_prompt=negative_prompt,
|
|
514
|
-
count=count,
|
|
515
|
-
size=size,
|
|
516
|
-
images=[*image, *image_url],
|
|
517
|
-
reference_image=reference_image,
|
|
518
|
-
file_paths=list(file_path),
|
|
519
|
-
input_capabilities=input_capabilities,
|
|
520
|
-
model=model,
|
|
521
|
-
parameters=parameter_payload,
|
|
522
|
-
raw_request=raw_payload,
|
|
559
|
+
negative_prompt=negative_prompt,
|
|
560
|
+
count=count,
|
|
561
|
+
size=size,
|
|
562
|
+
images=[*image, *image_url],
|
|
563
|
+
reference_image=reference_image,
|
|
564
|
+
file_paths=list(file_path),
|
|
565
|
+
input_capabilities=input_capabilities,
|
|
566
|
+
model=model,
|
|
567
|
+
parameters=parameter_payload,
|
|
568
|
+
raw_request=raw_payload,
|
|
523
569
|
wait=not no_wait,
|
|
524
570
|
)
|
|
525
571
|
_echo_json(result)
|
|
@@ -533,36 +579,36 @@ def video_generation_group():
|
|
|
533
579
|
pass
|
|
534
580
|
|
|
535
581
|
|
|
536
|
-
@video_generation_group.command("generate")
|
|
537
|
-
@click.option("-p", "--prompt")
|
|
538
|
-
@click.option("--image", default=None, help="Source/reference image URL, Base64 data URI, or plain Base64 image data")
|
|
539
|
-
@click.option("--image-url", default=None, help="Alias for --image")
|
|
540
|
-
@click.option("--reference-image", default=None, help="Alias for --image")
|
|
541
|
-
@click.option("--first-frame-url", default=None, help="Alias for --image")
|
|
542
|
-
@click.option("--file-path", default=None, help="Local source/reference image path")
|
|
543
|
-
@click.option("--model", default=None)
|
|
544
|
-
@click.option("--input-capabilities", default=None, help="Override video model input filter: text or image")
|
|
545
|
-
@click.option("--mime-type", default=None, help="MIME type for plain Base64 image inputs. Defaults to image/png.")
|
|
546
|
-
@click.option("--parameters", default=None, help="Parameters JSON object")
|
|
547
|
-
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
548
|
-
@click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
|
|
549
|
-
def video_generate(
|
|
550
|
-
prompt,
|
|
551
|
-
image,
|
|
552
|
-
image_url,
|
|
553
|
-
reference_image,
|
|
554
|
-
first_frame_url,
|
|
555
|
-
file_path,
|
|
556
|
-
model,
|
|
557
|
-
input_capabilities,
|
|
558
|
-
mime_type,
|
|
559
|
-
parameters,
|
|
560
|
-
raw_request,
|
|
561
|
-
no_wait,
|
|
562
|
-
):
|
|
563
|
-
"""Generate a video from a text prompt and optional first-frame image."""
|
|
564
|
-
from licos_dev_sdk import VideoGenerationClient
|
|
565
|
-
|
|
582
|
+
@video_generation_group.command("generate")
|
|
583
|
+
@click.option("-p", "--prompt")
|
|
584
|
+
@click.option("--image", default=None, help="Source/reference image URL, Base64 data URI, or plain Base64 image data")
|
|
585
|
+
@click.option("--image-url", default=None, help="Alias for --image")
|
|
586
|
+
@click.option("--reference-image", default=None, help="Alias for --image")
|
|
587
|
+
@click.option("--first-frame-url", default=None, help="Alias for --image")
|
|
588
|
+
@click.option("--file-path", default=None, help="Local source/reference image path")
|
|
589
|
+
@click.option("--model", default=None)
|
|
590
|
+
@click.option("--input-capabilities", default=None, help="Override video model input filter: text or image")
|
|
591
|
+
@click.option("--mime-type", default=None, help="MIME type for plain Base64 image inputs. Defaults to image/png.")
|
|
592
|
+
@click.option("--parameters", default=None, help="Parameters JSON object")
|
|
593
|
+
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
594
|
+
@click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
|
|
595
|
+
def video_generate(
|
|
596
|
+
prompt,
|
|
597
|
+
image,
|
|
598
|
+
image_url,
|
|
599
|
+
reference_image,
|
|
600
|
+
first_frame_url,
|
|
601
|
+
file_path,
|
|
602
|
+
model,
|
|
603
|
+
input_capabilities,
|
|
604
|
+
mime_type,
|
|
605
|
+
parameters,
|
|
606
|
+
raw_request,
|
|
607
|
+
no_wait,
|
|
608
|
+
):
|
|
609
|
+
"""Generate a video from a text prompt and optional first-frame image."""
|
|
610
|
+
from licos_dev_sdk import VideoGenerationClient
|
|
611
|
+
|
|
566
612
|
parameter_payload = _json_option(parameters, "--parameters") or {}
|
|
567
613
|
raw_payload = _json_option(raw_request, "--raw-request")
|
|
568
614
|
if not isinstance(parameter_payload, dict):
|
|
@@ -571,19 +617,19 @@ def video_generate(
|
|
|
571
617
|
raise click.BadParameter("--raw-request must be a JSON object")
|
|
572
618
|
if raw_payload is None and not prompt:
|
|
573
619
|
raise click.UsageError("Provide --prompt or --raw-request.")
|
|
574
|
-
result = VideoGenerationClient().generate(
|
|
575
|
-
prompt or "",
|
|
576
|
-
image=image,
|
|
577
|
-
image_url=image_url,
|
|
578
|
-
reference_image=reference_image,
|
|
579
|
-
first_frame_url=first_frame_url,
|
|
580
|
-
file_path=file_path,
|
|
581
|
-
model=model,
|
|
582
|
-
input_capabilities=input_capabilities,
|
|
583
|
-
mime_type=mime_type,
|
|
584
|
-
parameters=parameter_payload,
|
|
585
|
-
raw_request=raw_payload,
|
|
586
|
-
wait=not no_wait,
|
|
620
|
+
result = VideoGenerationClient().generate(
|
|
621
|
+
prompt or "",
|
|
622
|
+
image=image,
|
|
623
|
+
image_url=image_url,
|
|
624
|
+
reference_image=reference_image,
|
|
625
|
+
first_frame_url=first_frame_url,
|
|
626
|
+
file_path=file_path,
|
|
627
|
+
model=model,
|
|
628
|
+
input_capabilities=input_capabilities,
|
|
629
|
+
mime_type=mime_type,
|
|
630
|
+
parameters=parameter_payload,
|
|
631
|
+
raw_request=raw_payload,
|
|
632
|
+
wait=not no_wait,
|
|
587
633
|
)
|
|
588
634
|
_echo_json(result)
|
|
589
635
|
|
|
@@ -596,35 +642,35 @@ def audio_group():
|
|
|
596
642
|
pass
|
|
597
643
|
|
|
598
644
|
|
|
599
|
-
@audio_group.command("recognize")
|
|
600
|
-
@click.option("--audio", "audio", multiple=True, help="Audio URL, Base64 data URI, or plain Base64 audio data. Can be repeated.")
|
|
601
|
-
@click.option("--audio-url", "audio_url", multiple=True, help="Alias for --audio. Can be repeated.")
|
|
602
|
-
@click.option("--file-path", "file_path", multiple=True, help="Local audio file path. Can be repeated.")
|
|
603
|
-
@click.option("--model", default=None)
|
|
604
|
-
@click.option("--mime-type", default=None, help="MIME type for plain Base64 audio inputs. Defaults to audio/wav.")
|
|
605
|
-
@click.option("--parameters", default=None, help="Parameters JSON object")
|
|
606
|
-
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
607
|
-
@click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
|
|
608
|
-
def audio_recognize(audio, audio_url, file_path, model, mime_type, parameters, raw_request, no_wait):
|
|
609
|
-
"""Recognize speech from one or more audio inputs."""
|
|
610
|
-
from licos_dev_sdk import SpeechRecognitionClient
|
|
611
|
-
|
|
645
|
+
@audio_group.command("recognize")
|
|
646
|
+
@click.option("--audio", "audio", multiple=True, help="Audio URL, Base64 data URI, or plain Base64 audio data. Can be repeated.")
|
|
647
|
+
@click.option("--audio-url", "audio_url", multiple=True, help="Alias for --audio. Can be repeated.")
|
|
648
|
+
@click.option("--file-path", "file_path", multiple=True, help="Local audio file path. Can be repeated.")
|
|
649
|
+
@click.option("--model", default=None)
|
|
650
|
+
@click.option("--mime-type", default=None, help="MIME type for plain Base64 audio inputs. Defaults to audio/wav.")
|
|
651
|
+
@click.option("--parameters", default=None, help="Parameters JSON object")
|
|
652
|
+
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
653
|
+
@click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
|
|
654
|
+
def audio_recognize(audio, audio_url, file_path, model, mime_type, parameters, raw_request, no_wait):
|
|
655
|
+
"""Recognize speech from one or more audio inputs."""
|
|
656
|
+
from licos_dev_sdk import SpeechRecognitionClient
|
|
657
|
+
|
|
612
658
|
parameter_payload = _json_option(parameters, "--parameters") or {}
|
|
613
659
|
raw_payload = _json_option(raw_request, "--raw-request")
|
|
614
660
|
if not isinstance(parameter_payload, dict):
|
|
615
661
|
raise click.BadParameter("--parameters must be a JSON object")
|
|
616
662
|
if raw_payload is not None and not isinstance(raw_payload, dict):
|
|
617
663
|
raise click.BadParameter("--raw-request must be a JSON object")
|
|
618
|
-
if raw_payload is None and not audio and not audio_url and not file_path:
|
|
619
|
-
raise click.UsageError("Provide --audio, --audio-url, --file-path, or --raw-request.")
|
|
620
|
-
result = SpeechRecognitionClient().recognize(
|
|
621
|
-
audios=[*audio, *audio_url],
|
|
622
|
-
file_paths=list(file_path),
|
|
623
|
-
model=model,
|
|
624
|
-
mime_type=mime_type,
|
|
625
|
-
parameters=parameter_payload,
|
|
626
|
-
raw_request=raw_payload,
|
|
627
|
-
wait=not no_wait,
|
|
664
|
+
if raw_payload is None and not audio and not audio_url and not file_path:
|
|
665
|
+
raise click.UsageError("Provide --audio, --audio-url, --file-path, or --raw-request.")
|
|
666
|
+
result = SpeechRecognitionClient().recognize(
|
|
667
|
+
audios=[*audio, *audio_url],
|
|
668
|
+
file_paths=list(file_path),
|
|
669
|
+
model=model,
|
|
670
|
+
mime_type=mime_type,
|
|
671
|
+
parameters=parameter_payload,
|
|
672
|
+
raw_request=raw_payload,
|
|
673
|
+
wait=not no_wait,
|
|
628
674
|
)
|
|
629
675
|
_echo_json(result)
|
|
630
676
|
|
|
@@ -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"
|
|
File without changes
|
|
File without changes
|