licos-dev-cli 0.2.16__tar.gz → 0.2.17__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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: licos-dev-cli
3
- Version: 0.2.16
3
+ Version: 0.2.17
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.17
7
+ Requires-Dist: licos-dev-sdk>=0.2.18
@@ -1,19 +1,19 @@
1
- [build-system]
2
- requires = ["hatchling"]
3
- build-backend = "hatchling.build"
4
-
5
- [project]
6
- name = "licos-dev-cli"
7
- version = "0.2.16"
8
- description = "LICOS Dev CLI - generate files and call model capabilities"
9
- requires-python = ">=3.10"
10
- dependencies = [
11
- "licos-dev-sdk>=0.2.17",
12
- "click>=8.1",
13
- ]
14
-
15
- [project.scripts]
16
- licos-dev = "licos_dev_cli.main:cli"
17
-
18
- [tool.hatch.build.targets.wheel]
19
- packages = ["src/licos_dev_cli"]
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "licos-dev-cli"
7
+ version = "0.2.17"
8
+ description = "LICOS Dev CLI - generate files and call model capabilities"
9
+ requires-python = ">=3.10"
10
+ dependencies = [
11
+ "licos-dev-sdk>=0.2.18",
12
+ "click>=8.1",
13
+ ]
14
+
15
+ [project.scripts]
16
+ licos-dev = "licos_dev_cli.main:cli"
17
+
18
+ [tool.hatch.build.targets.wheel]
19
+ packages = ["src/licos_dev_cli"]
@@ -1,42 +1,42 @@
1
- """CLI entry point - wraps licos-dev-sdk functions as click commands."""
2
-
3
- from __future__ import annotations
4
-
1
+ """CLI entry point - wraps licos-dev-sdk functions as click commands."""
2
+
3
+ from __future__ import annotations
4
+
5
5
  import sys
6
6
  import json
7
7
  import os
8
8
  from pathlib import Path
9
9
  import click
10
-
11
- # ── Helpers ──────────────────────────────────────────────────────────────────
12
-
13
- def _read_input(input_path: str | None, content: str | None) -> str:
14
- """Read content from --input file, --content arg, or stdin."""
15
- if input_path:
16
- with open(input_path, "r", encoding="utf-8") as f:
17
- return f.read()
18
- if content:
19
- return content
20
- if not sys.stdin.isatty():
21
- return sys.stdin.read()
22
- raise click.UsageError("Provide --input, --content, or pipe via stdin.")
23
-
24
-
25
- def _read_json(input_path: str | None, content: str | None) -> object:
26
- """Read and parse JSON from input."""
27
- raw = _read_input(input_path, content)
28
- return json.loads(raw)
29
-
30
-
31
- def _json_option(value: str | None, name: str) -> dict | list | None:
32
- if not value:
33
- return None
34
- try:
35
- return json.loads(value)
36
- except json.JSONDecodeError as exc:
37
- raise click.BadParameter(f"{name} must be valid JSON") from exc
38
-
39
-
10
+
11
+ # ── Helpers ──────────────────────────────────────────────────────────────────
12
+
13
+ def _read_input(input_path: str | None, content: str | None) -> str:
14
+ """Read content from --input file, --content arg, or stdin."""
15
+ if input_path:
16
+ with open(input_path, "r", encoding="utf-8") as f:
17
+ return f.read()
18
+ if content:
19
+ return content
20
+ if not sys.stdin.isatty():
21
+ return sys.stdin.read()
22
+ raise click.UsageError("Provide --input, --content, or pipe via stdin.")
23
+
24
+
25
+ def _read_json(input_path: str | None, content: str | None) -> object:
26
+ """Read and parse JSON from input."""
27
+ raw = _read_input(input_path, content)
28
+ return json.loads(raw)
29
+
30
+
31
+ def _json_option(value: str | None, name: str) -> dict | list | None:
32
+ if not value:
33
+ return None
34
+ try:
35
+ return json.loads(value)
36
+ except json.JSONDecodeError as exc:
37
+ raise click.BadParameter(f"{name} must be valid JSON") from exc
38
+
39
+
40
40
  def _echo_json(value: object) -> None:
41
41
  if hasattr(value, "to_dict"):
42
42
  value = value.to_dict()
@@ -88,7 +88,7 @@ def _echo_path(path: object) -> None:
88
88
 
89
89
 
90
90
  # ── CLI Group ────────────────────────────────────────────────────────────────
91
-
91
+
92
92
  @click.group()
93
93
  def cli():
94
94
  """LICOS Dev - file generation and model CLI for AI agents."""
@@ -115,584 +115,584 @@ def credit_check(estimated_points, resource_type, resource_code, request_id):
115
115
 
116
116
 
117
117
  # ── PDF ──────────────────────────────────────────────────────────────────────
118
-
119
- @cli.command()
120
- @click.option("-i", "--input", "input_path", help="Input file (Markdown or HTML)")
121
- @click.option("-c", "--content", help="Direct content")
122
- @click.option("-f", "--filename", required=True, help="Output filename (no extension)")
123
- @click.option("-o", "--output-dir", default=None, help="Output directory")
124
- @click.option("--format", "content_type", default="markdown", help="Content type: markdown|html")
125
- @click.option("--page-size", default="A4", help="Page size: A4|LETTER")
126
- def pdf(input_path, content, filename, output_dir, content_type, page_size):
127
- """Generate PDF from Markdown or HTML."""
118
+
119
+ @cli.command()
120
+ @click.option("-i", "--input", "input_path", help="Input file (Markdown or HTML)")
121
+ @click.option("-c", "--content", help="Direct content")
122
+ @click.option("-f", "--filename", required=True, help="Output filename (no extension)")
123
+ @click.option("-o", "--output-dir", default=None, help="Output directory")
124
+ @click.option("--format", "content_type", default="markdown", help="Content type: markdown|html")
125
+ @click.option("--page-size", default="A4", help="Page size: A4|LETTER")
126
+ def pdf(input_path, content, filename, output_dir, content_type, page_size):
127
+ """Generate PDF from Markdown or HTML."""
128
128
  from licos_dev_sdk import create_pdf
129
129
  text = _read_input(input_path, content)
130
130
  path = create_pdf(text, filename, content_type=content_type, output_dir=output_dir, page_size=page_size)
131
131
  _echo_path(path)
132
-
133
-
134
- # ── DOCX ─────────────────────────────────────────────────────────────────────
135
-
136
- @cli.command()
137
- @click.option("-i", "--input", "input_path")
138
- @click.option("-c", "--content")
139
- @click.option("-f", "--filename", required=True)
140
- @click.option("-o", "--output-dir", default=None)
141
- @click.option("--format", "content_type", default="markdown")
142
- @click.option("--font", default="Arial")
143
- @click.option("--font-size", default=11, type=int)
144
- def docx(input_path, content, filename, output_dir, content_type, font, font_size):
145
- """Generate DOCX from Markdown or HTML."""
132
+
133
+
134
+ # ── DOCX ─────────────────────────────────────────────────────────────────────
135
+
136
+ @cli.command()
137
+ @click.option("-i", "--input", "input_path")
138
+ @click.option("-c", "--content")
139
+ @click.option("-f", "--filename", required=True)
140
+ @click.option("-o", "--output-dir", default=None)
141
+ @click.option("--format", "content_type", default="markdown")
142
+ @click.option("--font", default="Arial")
143
+ @click.option("--font-size", default=11, type=int)
144
+ def docx(input_path, content, filename, output_dir, content_type, font, font_size):
145
+ """Generate DOCX from Markdown or HTML."""
146
146
  from licos_dev_sdk import create_docx
147
147
  text = _read_input(input_path, content)
148
148
  path = create_docx(text, filename, content_type=content_type, output_dir=output_dir, font_name=font, font_size=font_size)
149
149
  _echo_path(path)
150
-
151
-
152
- @cli.command("docx-template")
153
- @click.option("-t", "--template", "template_path", required=True, help="DOCX template path")
154
- @click.option("-i", "--input", "input_path", help="JSON data file")
155
- @click.option("-d", "--data", "data_content", help="JSON data")
156
- @click.option("-f", "--filename", required=True)
157
- @click.option("-o", "--output-dir", default=None)
158
- def docx_template(template_path, input_path, data_content, filename, output_dir):
159
- """Generate DOCX by rendering a DOCX template with JSON data."""
160
- from licos_dev_sdk import create_docx_from_template
161
- data = _read_json(input_path, data_content)
150
+
151
+
152
+ @cli.command("docx-template")
153
+ @click.option("-t", "--template", "template_path", required=True, help="DOCX template path")
154
+ @click.option("-i", "--input", "input_path", help="JSON data file")
155
+ @click.option("-d", "--data", "data_content", help="JSON data")
156
+ @click.option("-f", "--filename", required=True)
157
+ @click.option("-o", "--output-dir", default=None)
158
+ def docx_template(template_path, input_path, data_content, filename, output_dir):
159
+ """Generate DOCX by rendering a DOCX template with JSON data."""
160
+ from licos_dev_sdk import create_docx_from_template
161
+ data = _read_json(input_path, data_content)
162
162
  if not isinstance(data, dict):
163
163
  raise click.BadParameter("template data must be a JSON object")
164
164
  path = create_docx_from_template(template_path, data, filename, output_dir=output_dir)
165
165
  _echo_path(path)
166
-
167
-
168
- # ── XLSX ─────────────────────────────────────────────────────────────────────
169
-
170
- @cli.command()
171
- @click.option("-i", "--input", "input_path")
172
- @click.option("-c", "--content", help="JSON data")
173
- @click.option("-f", "--filename", required=True)
174
- @click.option("-o", "--output-dir", default=None)
175
- @click.option("--sheet-name", default="Sheet1")
176
- @click.option("--header-color", default="4472C4")
177
- def xlsx(input_path, content, filename, output_dir, sheet_name, header_color):
178
- """Generate XLSX from JSON data."""
166
+
167
+
168
+ # ── XLSX ─────────────────────────────────────────────────────────────────────
169
+
170
+ @cli.command()
171
+ @click.option("-i", "--input", "input_path")
172
+ @click.option("-c", "--content", help="JSON data")
173
+ @click.option("-f", "--filename", required=True)
174
+ @click.option("-o", "--output-dir", default=None)
175
+ @click.option("--sheet-name", default="Sheet1")
176
+ @click.option("--header-color", default="4472C4")
177
+ def xlsx(input_path, content, filename, output_dir, sheet_name, header_color):
178
+ """Generate XLSX from JSON data."""
179
179
  from licos_dev_sdk import create_xlsx
180
180
  data = _read_json(input_path, content)
181
181
  path = create_xlsx(data, filename, output_dir=output_dir, sheet_name=sheet_name, header_color=header_color)
182
182
  _echo_path(path)
183
-
184
-
185
- @cli.command("xlsx-workbook")
186
- @click.option("-i", "--input", "input_path")
187
- @click.option("-c", "--content", help="JSON workbook data")
188
- @click.option("-f", "--filename", required=True)
189
- @click.option("-o", "--output-dir", default=None)
190
- @click.option("--header-color", default="4472C4")
191
- @click.option("--freeze-header/--no-freeze-header", default=True)
192
- @click.option("--autofilter/--no-autofilter", default=True)
193
- def xlsx_workbook(input_path, content, filename, output_dir, header_color, freeze_header, autofilter):
194
- """Generate multi-sheet XLSX from JSON workbook data."""
195
- from licos_dev_sdk import create_xlsx_workbook
196
- data = _read_json(input_path, content)
197
- path = create_xlsx_workbook(
198
- data,
199
- filename,
200
- output_dir=output_dir,
201
- header_color=header_color,
183
+
184
+
185
+ @cli.command("xlsx-workbook")
186
+ @click.option("-i", "--input", "input_path")
187
+ @click.option("-c", "--content", help="JSON workbook data")
188
+ @click.option("-f", "--filename", required=True)
189
+ @click.option("-o", "--output-dir", default=None)
190
+ @click.option("--header-color", default="4472C4")
191
+ @click.option("--freeze-header/--no-freeze-header", default=True)
192
+ @click.option("--autofilter/--no-autofilter", default=True)
193
+ def xlsx_workbook(input_path, content, filename, output_dir, header_color, freeze_header, autofilter):
194
+ """Generate multi-sheet XLSX from JSON workbook data."""
195
+ from licos_dev_sdk import create_xlsx_workbook
196
+ data = _read_json(input_path, content)
197
+ path = create_xlsx_workbook(
198
+ data,
199
+ filename,
200
+ output_dir=output_dir,
201
+ header_color=header_color,
202
202
  freeze_header=freeze_header,
203
203
  autofilter=autofilter,
204
204
  )
205
205
  _echo_path(path)
206
-
207
-
208
- # ── CSV ──────────────────────────────────────────────────────────────────────
209
-
210
- @cli.command()
211
- @click.option("-i", "--input", "input_path")
212
- @click.option("-c", "--content", help="JSON data")
213
- @click.option("-f", "--filename", required=True)
214
- @click.option("-o", "--output-dir", default=None)
215
- def csv(input_path, content, filename, output_dir):
216
- """Generate CSV from JSON data."""
206
+
207
+
208
+ # ── CSV ──────────────────────────────────────────────────────────────────────
209
+
210
+ @cli.command()
211
+ @click.option("-i", "--input", "input_path")
212
+ @click.option("-c", "--content", help="JSON data")
213
+ @click.option("-f", "--filename", required=True)
214
+ @click.option("-o", "--output-dir", default=None)
215
+ def csv(input_path, content, filename, output_dir):
216
+ """Generate CSV from JSON data."""
217
217
  from licos_dev_sdk import create_csv
218
218
  data = _read_json(input_path, content)
219
219
  path = create_csv(data, filename, output_dir=output_dir)
220
220
  _echo_path(path)
221
-
222
-
223
- # ── PPTX ─────────────────────────────────────────────────────────────────────
224
-
225
- @cli.command()
226
- @click.option("-i", "--input", "input_path")
227
- @click.option("-c", "--content")
228
- @click.option("-f", "--filename", required=True)
229
- @click.option("-o", "--output-dir", default=None)
230
- @click.option("--format", "content_type", default="markdown")
231
- def pptx(input_path, content, filename, output_dir, content_type):
232
- """Generate PPTX from Markdown."""
221
+
222
+
223
+ # ── PPTX ─────────────────────────────────────────────────────────────────────
224
+
225
+ @cli.command()
226
+ @click.option("-i", "--input", "input_path")
227
+ @click.option("-c", "--content")
228
+ @click.option("-f", "--filename", required=True)
229
+ @click.option("-o", "--output-dir", default=None)
230
+ @click.option("--format", "content_type", default="markdown")
231
+ def pptx(input_path, content, filename, output_dir, content_type):
232
+ """Generate PPTX from Markdown."""
233
233
  from licos_dev_sdk import create_pptx
234
234
  text = _read_input(input_path, content)
235
235
  path = create_pptx(text, filename, content_type=content_type, output_dir=output_dir)
236
236
  _echo_path(path)
237
-
238
-
239
- # ── Chart ────────────────────────────────────────────────────────────────────
240
-
241
- @cli.command()
242
- @click.option("-i", "--input", "input_path")
243
- @click.option("-c", "--content", help="JSON chart data")
244
- @click.option("-f", "--filename", required=True)
245
- @click.option("-o", "--output-dir", default=None)
246
- @click.option("--type", "chart_type", required=True, help="bar|line|pie|scatter|heatmap")
247
- @click.option("--format", "fmt", default="png", help="png|svg")
248
- @click.option("--title", default="")
249
- @click.option("--width", default=800, type=int)
250
- @click.option("--height", default=600, type=int)
251
- def chart(input_path, content, filename, output_dir, chart_type, fmt, title, width, height):
252
- """Generate chart image from JSON data."""
237
+
238
+
239
+ # ── Chart ────────────────────────────────────────────────────────────────────
240
+
241
+ @cli.command()
242
+ @click.option("-i", "--input", "input_path")
243
+ @click.option("-c", "--content", help="JSON chart data")
244
+ @click.option("-f", "--filename", required=True)
245
+ @click.option("-o", "--output-dir", default=None)
246
+ @click.option("--type", "chart_type", required=True, help="bar|line|pie|scatter|heatmap")
247
+ @click.option("--format", "fmt", default="png", help="png|svg")
248
+ @click.option("--title", default="")
249
+ @click.option("--width", default=800, type=int)
250
+ @click.option("--height", default=600, type=int)
251
+ def chart(input_path, content, filename, output_dir, chart_type, fmt, title, width, height):
252
+ """Generate chart image from JSON data."""
253
253
  from licos_dev_sdk import create_chart
254
254
  data = _read_json(input_path, content)
255
255
  path = create_chart(chart_type, data, filename, output_dir=output_dir, format=fmt, title=title, width=width, height=height)
256
256
  _echo_path(path)
257
-
258
-
259
- # ── Diagram ──────────────────────────────────────────────────────────────────
260
-
261
- @cli.command()
262
- @click.option("-i", "--input", "input_path")
263
- @click.option("-c", "--content", help="DOT source")
264
- @click.option("-f", "--filename", required=True)
265
- @click.option("-o", "--output-dir", default=None)
266
- @click.option("--format", "fmt", default="png", help="png|svg|pdf")
267
- def diagram(input_path, content, filename, output_dir, fmt):
268
- """Generate diagram from Graphviz DOT source."""
257
+
258
+
259
+ # ── Diagram ──────────────────────────────────────────────────────────────────
260
+
261
+ @cli.command()
262
+ @click.option("-i", "--input", "input_path")
263
+ @click.option("-c", "--content", help="DOT source")
264
+ @click.option("-f", "--filename", required=True)
265
+ @click.option("-o", "--output-dir", default=None)
266
+ @click.option("--format", "fmt", default="png", help="png|svg|pdf")
267
+ def diagram(input_path, content, filename, output_dir, fmt):
268
+ """Generate diagram from Graphviz DOT source."""
269
269
  from licos_dev_sdk import create_diagram
270
270
  text = _read_input(input_path, content)
271
271
  path = create_diagram(text, filename, output_dir=output_dir, format=fmt)
272
272
  _echo_path(path)
273
-
274
-
275
- # ── QR Code ──────────────────────────────────────────────────────────────────
276
-
277
- @cli.command()
278
- @click.option("-d", "--data", required=True, help="Data to encode")
279
- @click.option("-f", "--filename", required=True)
280
- @click.option("-o", "--output-dir", default=None)
281
- @click.option("--size", default=300, type=int)
282
- def qrcode(data, filename, output_dir, size):
283
- """Generate QR code PNG image."""
273
+
274
+
275
+ # ── QR Code ──────────────────────────────────────────────────────────────────
276
+
277
+ @cli.command()
278
+ @click.option("-d", "--data", required=True, help="Data to encode")
279
+ @click.option("-f", "--filename", required=True)
280
+ @click.option("-o", "--output-dir", default=None)
281
+ @click.option("--size", default=300, type=int)
282
+ def qrcode(data, filename, output_dir, size):
283
+ """Generate QR code PNG image."""
284
284
  from licos_dev_sdk import create_qrcode
285
285
  path = create_qrcode(data, filename, output_dir=output_dir, size=size)
286
286
  _echo_path(path)
287
-
288
-
289
- # ── Barcode ──────────────────────────────────────────────────────────────────
290
-
291
- @cli.command()
292
- @click.option("-d", "--data", required=True, help="Data to encode")
293
- @click.option("-f", "--filename", required=True)
294
- @click.option("-o", "--output-dir", default=None)
295
- @click.option("--type", "barcode_type", default="code128", help="code128|ean13|ean8|isbn13|upc")
296
- def barcode(data, filename, output_dir, barcode_type):
297
- """Generate barcode PNG image."""
287
+
288
+
289
+ # ── Barcode ──────────────────────────────────────────────────────────────────
290
+
291
+ @cli.command()
292
+ @click.option("-d", "--data", required=True, help="Data to encode")
293
+ @click.option("-f", "--filename", required=True)
294
+ @click.option("-o", "--output-dir", default=None)
295
+ @click.option("--type", "barcode_type", default="code128", help="code128|ean13|ean8|isbn13|upc")
296
+ def barcode(data, filename, output_dir, barcode_type):
297
+ """Generate barcode PNG image."""
298
298
  from licos_dev_sdk import create_barcode
299
299
  path = create_barcode(data, filename, output_dir=output_dir, barcode_type=barcode_type)
300
300
  _echo_path(path)
301
-
302
-
303
- # ── ZIP ──────────────────────────────────────────────────────────────────────
304
-
305
- @cli.command("zip")
306
- @click.option("-p", "--paths", required=True, help="Comma-separated file/dir paths")
307
- @click.option("-f", "--filename", required=True)
308
- @click.option("-o", "--output-dir", default=None)
309
- def zip_cmd(paths, filename, output_dir):
310
- """Create ZIP archive."""
301
+
302
+
303
+ # ── ZIP ──────────────────────────────────────────────────────────────────────
304
+
305
+ @cli.command("zip")
306
+ @click.option("-p", "--paths", required=True, help="Comma-separated file/dir paths")
307
+ @click.option("-f", "--filename", required=True)
308
+ @click.option("-o", "--output-dir", default=None)
309
+ def zip_cmd(paths, filename, output_dir):
310
+ """Create ZIP archive."""
311
311
  from licos_dev_sdk import create_zip
312
312
  source_paths = [p.strip() for p in paths.split(",")]
313
313
  path = create_zip(source_paths, filename, output_dir=output_dir)
314
314
  _echo_path(path)
315
-
316
-
317
- # ── TAR.GZ ───────────────────────────────────────────────────────────────────
318
-
319
- @cli.command("tar")
320
- @click.option("-p", "--paths", required=True, help="Comma-separated file/dir paths")
321
- @click.option("-f", "--filename", required=True)
322
- @click.option("-o", "--output-dir", default=None)
323
- def tar_cmd(paths, filename, output_dir):
324
- """Create TAR.GZ archive."""
315
+
316
+
317
+ # ── TAR.GZ ───────────────────────────────────────────────────────────────────
318
+
319
+ @cli.command("tar")
320
+ @click.option("-p", "--paths", required=True, help="Comma-separated file/dir paths")
321
+ @click.option("-f", "--filename", required=True)
322
+ @click.option("-o", "--output-dir", default=None)
323
+ def tar_cmd(paths, filename, output_dir):
324
+ """Create TAR.GZ archive."""
325
325
  from licos_dev_sdk import create_tar_gz
326
326
  source_paths = [p.strip() for p in paths.split(",")]
327
327
  path = create_tar_gz(source_paths, filename, output_dir=output_dir)
328
328
  _echo_path(path)
329
-
330
-
331
- # ── JSON ─────────────────────────────────────────────────────────────────────
332
-
333
- @cli.command("json")
334
- @click.option("-i", "--input", "input_path")
335
- @click.option("-c", "--content", help="JSON or YAML content")
336
- @click.option("-f", "--filename", required=True)
337
- @click.option("-o", "--output-dir", default=None)
338
- def json_cmd(input_path, content, filename, output_dir):
339
- """Generate JSON file (accepts JSON or YAML input)."""
340
- from licos_dev_sdk import create_json
341
- raw = _read_input(input_path, content)
342
- try:
343
- data = json.loads(raw)
329
+
330
+
331
+ # ── JSON ─────────────────────────────────────────────────────────────────────
332
+
333
+ @cli.command("json")
334
+ @click.option("-i", "--input", "input_path")
335
+ @click.option("-c", "--content", help="JSON or YAML content")
336
+ @click.option("-f", "--filename", required=True)
337
+ @click.option("-o", "--output-dir", default=None)
338
+ def json_cmd(input_path, content, filename, output_dir):
339
+ """Generate JSON file (accepts JSON or YAML input)."""
340
+ from licos_dev_sdk import create_json
341
+ raw = _read_input(input_path, content)
342
+ try:
343
+ data = json.loads(raw)
344
344
  except json.JSONDecodeError:
345
345
  import yaml
346
346
  data = yaml.safe_load(raw)
347
347
  path = create_json(data, filename, output_dir=output_dir)
348
348
  _echo_path(path)
349
-
350
-
351
- # ── YAML ─────────────────────────────────────────────────────────────────────
352
-
353
- @cli.command("yaml")
354
- @click.option("-i", "--input", "input_path")
355
- @click.option("-c", "--content", help="JSON or YAML content")
356
- @click.option("-f", "--filename", required=True)
357
- @click.option("-o", "--output-dir", default=None)
358
- def yaml_cmd(input_path, content, filename, output_dir):
359
- """Generate YAML file (accepts JSON or YAML input)."""
360
- from licos_dev_sdk import create_yaml
361
- import yaml as yaml_lib
362
- raw = _read_input(input_path, content)
363
- try:
364
- data = json.loads(raw)
349
+
350
+
351
+ # ── YAML ─────────────────────────────────────────────────────────────────────
352
+
353
+ @cli.command("yaml")
354
+ @click.option("-i", "--input", "input_path")
355
+ @click.option("-c", "--content", help="JSON or YAML content")
356
+ @click.option("-f", "--filename", required=True)
357
+ @click.option("-o", "--output-dir", default=None)
358
+ def yaml_cmd(input_path, content, filename, output_dir):
359
+ """Generate YAML file (accepts JSON or YAML input)."""
360
+ from licos_dev_sdk import create_yaml
361
+ import yaml as yaml_lib
362
+ raw = _read_input(input_path, content)
363
+ try:
364
+ data = json.loads(raw)
365
365
  except json.JSONDecodeError:
366
366
  data = yaml_lib.safe_load(raw)
367
367
  path = create_yaml(data, filename, output_dir=output_dir)
368
368
  _echo_path(path)
369
-
370
-
371
- # ── XML ──────────────────────────────────────────────────────────────────────
372
-
373
- @cli.command("xml")
374
- @click.option("-i", "--input", "input_path")
375
- @click.option("-c", "--content", help="JSON content")
376
- @click.option("-f", "--filename", required=True)
377
- @click.option("-o", "--output-dir", default=None)
378
- @click.option("--root-tag", default="root")
379
- def xml_cmd(input_path, content, filename, output_dir, root_tag):
380
- """Generate XML file from JSON data."""
369
+
370
+
371
+ # ── XML ──────────────────────────────────────────────────────────────────────
372
+
373
+ @cli.command("xml")
374
+ @click.option("-i", "--input", "input_path")
375
+ @click.option("-c", "--content", help="JSON content")
376
+ @click.option("-f", "--filename", required=True)
377
+ @click.option("-o", "--output-dir", default=None)
378
+ @click.option("--root-tag", default="root")
379
+ def xml_cmd(input_path, content, filename, output_dir, root_tag):
380
+ """Generate XML file from JSON data."""
381
381
  from licos_dev_sdk import create_xml
382
382
  data = _read_json(input_path, content)
383
383
  path = create_xml(data, filename, output_dir=output_dir, root_tag=root_tag)
384
384
  _echo_path(path)
385
-
386
-
387
- # ── HTML ─────────────────────────────────────────────────────────────────────
388
-
389
- @cli.command("html")
390
- @click.option("-i", "--input", "input_path")
391
- @click.option("-c", "--content")
392
- @click.option("-f", "--filename", required=True)
393
- @click.option("-o", "--output-dir", default=None)
394
- @click.option("--format", "content_type", default="markdown", help="markdown|html")
395
- def html_cmd(input_path, content, filename, output_dir, content_type):
396
- """Generate HTML file from Markdown or raw HTML."""
385
+
386
+
387
+ # ── HTML ─────────────────────────────────────────────────────────────────────
388
+
389
+ @cli.command("html")
390
+ @click.option("-i", "--input", "input_path")
391
+ @click.option("-c", "--content")
392
+ @click.option("-f", "--filename", required=True)
393
+ @click.option("-o", "--output-dir", default=None)
394
+ @click.option("--format", "content_type", default="markdown", help="markdown|html")
395
+ def html_cmd(input_path, content, filename, output_dir, content_type):
396
+ """Generate HTML file from Markdown or raw HTML."""
397
397
  from licos_dev_sdk import create_html
398
398
  text = _read_input(input_path, content)
399
399
  path = create_html(text, filename, output_dir=output_dir, content_type=content_type)
400
400
  _echo_path(path)
401
-
402
-
403
- # ── Model Catalog ────────────────────────────────────────────────────────────
404
-
405
- @cli.command("model-catalog")
406
- @click.option("--refresh", is_flag=True, help="Bypass local catalog cache")
407
- @click.option("--workspace-id", default=None, help="Workspace id; defaults to runtime workspace")
408
- @click.option("--input-capabilities", default=None, help="Optional input capabilities filter, for example text or image")
409
- @click.option(
410
- "--category-code",
411
- default="llm",
412
- help="Model category code, for example llm, vision_llm, image_generation",
413
- )
414
- def model_catalog(refresh, workspace_id, input_capabilities, category_code):
415
- """Print platform model capability catalog."""
416
- from licos_dev_sdk import fetch_model_catalogs
417
-
418
- _echo_json(
419
- fetch_model_catalogs(
420
- refresh=refresh,
421
- workspace_id=workspace_id,
422
- category_code=category_code,
423
- input_capabilities=input_capabilities,
424
- )
425
- )
426
-
427
-
428
- # ── LLM ──────────────────────────────────────────────────────────────────────
429
-
430
- @cli.group("llm")
431
- def llm_group():
432
- """Call chat/text model capabilities."""
433
- pass
434
-
435
-
436
- @llm_group.command("invoke")
437
- @click.option("-p", "--prompt", help="User prompt. If omitted, --messages or stdin is used.")
438
- @click.option("--messages", help="OpenAI-style messages JSON array")
439
- @click.option("--model", default=None)
440
- @click.option("--temperature", default=None, type=float)
441
- @click.option("--max-completion-tokens", default=None, type=int)
442
- @click.option("--extra", default=None, help="Extra request fields as JSON object")
443
- def llm_invoke(prompt, messages, model, temperature, max_completion_tokens, extra):
444
- """Run a non-streaming chat completion."""
445
- from licos_dev_sdk import LLMClient
446
-
447
- if messages:
448
- message_payload = _json_option(messages, "--messages")
449
- else:
450
- message_payload = prompt if prompt is not None else _read_input(None, None)
451
- extra_payload = _json_option(extra, "--extra") or {}
452
- if not isinstance(extra_payload, dict):
453
- raise click.BadParameter("--extra must be a JSON object")
454
- result = LLMClient().invoke(
455
- message_payload,
456
- model=model,
457
- temperature=temperature,
458
- max_completion_tokens=max_completion_tokens,
459
- **extra_payload,
460
- )
461
- _echo_json(result)
462
-
463
-
464
- @llm_group.command("stream")
465
- @click.option("-p", "--prompt", help="User prompt. If omitted, --messages or stdin is used.")
466
- @click.option("--messages", help="OpenAI-style messages JSON array")
467
- @click.option("--model", default=None)
468
- @click.option("--temperature", default=None, type=float)
469
- @click.option("--max-completion-tokens", default=None, type=int)
470
- @click.option("--extra", default=None, help="Extra request fields as JSON object")
471
- def llm_stream(prompt, messages, model, temperature, max_completion_tokens, extra):
472
- """Run a streaming chat completion and print text chunks."""
473
- from licos_dev_sdk import LLMClient
474
-
475
- if messages:
476
- message_payload = _json_option(messages, "--messages")
477
- else:
478
- message_payload = prompt if prompt is not None else _read_input(None, None)
479
- extra_payload = _json_option(extra, "--extra") or {}
480
- if not isinstance(extra_payload, dict):
481
- raise click.BadParameter("--extra must be a JSON object")
482
- for chunk in LLMClient().stream(
483
- message_payload,
484
- model=model,
485
- temperature=temperature,
486
- max_completion_tokens=max_completion_tokens,
487
- **extra_payload,
488
- ):
489
- click.echo(chunk, nl=False)
490
-
491
-
492
- # ── Vision ───────────────────────────────────────────────────────────────────
493
-
494
- @cli.group("vision")
495
- def vision_group():
496
- """Call chat vision model capabilities."""
497
- pass
498
-
499
-
500
- @vision_group.command("understand")
501
- @click.option("--image", "image", multiple=True, help="Image URL, Base64 data URI, or plain Base64 image data. Can be repeated.")
502
- @click.option("--image-url", "image_url", multiple=True, help="Alias for --image. Can be repeated.")
503
- @click.option("--file-path", "file_path", multiple=True, help="Local image file path. Can be repeated.")
504
- @click.option("-p", "--prompt", default="Describe this image.")
505
- @click.option("--model", default=None)
506
- @click.option("--mime-type", default=None, help="MIME type for plain Base64 image inputs. Defaults to image/png.")
507
- @click.option("--raw-request", default=None, help="Raw JSON request body")
508
- def vision_understand(image, image_url, file_path, prompt, model, mime_type, raw_request):
509
- """Understand one or more images with the catalog vision model."""
510
- from licos_dev_sdk import VisionClient
511
-
512
- raw_payload = _json_option(raw_request, "--raw-request")
513
- if raw_payload is not None and not isinstance(raw_payload, dict):
514
- raise click.BadParameter("--raw-request must be a JSON object")
515
- if raw_payload is None and not image_url and not image and not file_path:
516
- raise click.UsageError("Provide --image, --image-url, --file-path, or --raw-request.")
517
- result = VisionClient().understand(
518
- images=[*image, *image_url],
519
- file_paths=list(file_path),
520
- prompt=prompt,
521
- model=model,
522
- mime_type=mime_type,
523
- raw_request=raw_payload,
524
- )
525
- _echo_json(result)
526
-
527
-
528
- # ── Image Generation ─────────────────────────────────────────────────────────
529
-
530
- @cli.group("image-generation")
531
- def image_generation_group():
532
- """Call image generation model capabilities."""
533
- pass
534
-
535
-
536
- @image_generation_group.command("generate")
537
- @click.option("-p", "--prompt")
538
- @click.option("--image", "image", multiple=True, help="Source/reference image URL or Base64 data URI")
539
- @click.option("--image-url", "image_url", multiple=True, help="Alias for --image")
540
- @click.option("--reference-image", default=None, help="Alias for --image")
541
- @click.option("--file-path", "file_path", multiple=True, help="Local source/reference image path")
542
- @click.option("--input-capabilities", default=None, help="Override image model input filter: text or image")
543
- @click.option("--negative-prompt", default=None)
544
- @click.option("--count", default=1, type=int)
545
- @click.option("--size", default=None)
546
- @click.option("--model", default=None)
547
- @click.option("--parameters", default=None, help="Parameters JSON object")
548
- @click.option("--raw-request", default=None, help="Raw JSON request body")
549
- @click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
550
- def image_generate(
551
- prompt,
552
- image,
553
- image_url,
554
- reference_image,
555
- file_path,
556
- input_capabilities,
557
- negative_prompt,
558
- count,
559
- size,
560
- model,
561
- parameters,
562
- raw_request,
563
- no_wait,
564
- ):
565
- """Generate images from text, image URLs/Base64, or local image files."""
566
- from licos_dev_sdk import ImageGenerationClient
567
-
568
- parameter_payload = _json_option(parameters, "--parameters") or {}
569
- raw_payload = _json_option(raw_request, "--raw-request")
570
- if not isinstance(parameter_payload, dict):
571
- raise click.BadParameter("--parameters must be a JSON object")
572
- if raw_payload is not None and not isinstance(raw_payload, dict):
573
- raise click.BadParameter("--raw-request must be a JSON object")
574
- if raw_payload is None and not prompt:
575
- raise click.UsageError("Provide --prompt or --raw-request.")
576
- result = ImageGenerationClient().generate(
577
- prompt or "",
578
- negative_prompt=negative_prompt,
579
- count=count,
580
- size=size,
581
- images=[*image, *image_url],
582
- reference_image=reference_image,
583
- file_paths=list(file_path),
584
- input_capabilities=input_capabilities,
585
- model=model,
586
- parameters=parameter_payload,
587
- raw_request=raw_payload,
588
- wait=not no_wait,
589
- )
590
- _echo_json(result)
591
-
592
-
593
- # ── Video Generation ─────────────────────────────────────────────────────────
594
-
595
- @cli.group("video-generation")
596
- def video_generation_group():
597
- """Call video generation model capabilities."""
598
- pass
599
-
600
-
601
- @video_generation_group.command("generate")
602
- @click.option("-p", "--prompt")
603
- @click.option("--image", default=None, help="Source/reference image URL, Base64 data URI, or plain Base64 image data")
604
- @click.option("--image-url", default=None, help="Alias for --image")
605
- @click.option("--reference-image", default=None, help="Alias for --image")
606
- @click.option("--first-frame-url", default=None, help="Alias for --image")
607
- @click.option("--file-path", default=None, help="Local source/reference image path")
608
- @click.option("--model", default=None)
609
- @click.option("--input-capabilities", default=None, help="Override video model input filter: text or image")
610
- @click.option("--mime-type", default=None, help="MIME type for plain Base64 image inputs. Defaults to image/png.")
611
- @click.option("--parameters", default=None, help="Parameters JSON object")
612
- @click.option("--raw-request", default=None, help="Raw JSON request body")
613
- @click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
614
- def video_generate(
615
- prompt,
616
- image,
617
- image_url,
618
- reference_image,
619
- first_frame_url,
620
- file_path,
621
- model,
622
- input_capabilities,
623
- mime_type,
624
- parameters,
625
- raw_request,
626
- no_wait,
627
- ):
628
- """Generate a video from a text prompt and optional first-frame image."""
629
- from licos_dev_sdk import VideoGenerationClient
630
-
631
- parameter_payload = _json_option(parameters, "--parameters") or {}
632
- raw_payload = _json_option(raw_request, "--raw-request")
633
- if not isinstance(parameter_payload, dict):
634
- raise click.BadParameter("--parameters must be a JSON object")
635
- if raw_payload is not None and not isinstance(raw_payload, dict):
636
- raise click.BadParameter("--raw-request must be a JSON object")
637
- if raw_payload is None and not prompt:
638
- raise click.UsageError("Provide --prompt or --raw-request.")
639
- result = VideoGenerationClient().generate(
640
- prompt or "",
641
- image=image,
642
- image_url=image_url,
643
- reference_image=reference_image,
644
- first_frame_url=first_frame_url,
645
- file_path=file_path,
646
- model=model,
647
- input_capabilities=input_capabilities,
648
- mime_type=mime_type,
649
- parameters=parameter_payload,
650
- raw_request=raw_payload,
651
- wait=not no_wait,
652
- )
653
- _echo_json(result)
654
-
655
-
656
- # ── Audio / ASR ──────────────────────────────────────────────────────────────
657
-
658
- @cli.group("audio")
659
- def audio_group():
660
- """Call audio model capabilities."""
661
- pass
662
-
663
-
664
- @audio_group.command("recognize")
665
- @click.option("--audio", "audio", multiple=True, help="Audio URL, Base64 data URI, or plain Base64 audio data. Can be repeated.")
666
- @click.option("--audio-url", "audio_url", multiple=True, help="Alias for --audio. Can be repeated.")
667
- @click.option("--file-path", "file_path", multiple=True, help="Local audio file path. Can be repeated.")
668
- @click.option("--model", default=None)
669
- @click.option("--mime-type", default=None, help="MIME type for plain Base64 audio inputs. Defaults to audio/wav.")
670
- @click.option("--parameters", default=None, help="Parameters JSON object")
671
- @click.option("--raw-request", default=None, help="Raw JSON request body")
672
- @click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
673
- def audio_recognize(audio, audio_url, file_path, model, mime_type, parameters, raw_request, no_wait):
674
- """Recognize speech from one or more audio inputs."""
675
- from licos_dev_sdk import SpeechRecognitionClient
676
-
677
- parameter_payload = _json_option(parameters, "--parameters") or {}
678
- raw_payload = _json_option(raw_request, "--raw-request")
679
- if not isinstance(parameter_payload, dict):
680
- raise click.BadParameter("--parameters must be a JSON object")
681
- if raw_payload is not None and not isinstance(raw_payload, dict):
682
- raise click.BadParameter("--raw-request must be a JSON object")
683
- if raw_payload is None and not audio and not audio_url and not file_path:
684
- raise click.UsageError("Provide --audio, --audio-url, --file-path, or --raw-request.")
685
- result = SpeechRecognitionClient().recognize(
686
- audios=[*audio, *audio_url],
687
- file_paths=list(file_path),
688
- model=model,
689
- mime_type=mime_type,
690
- parameters=parameter_payload,
691
- raw_request=raw_payload,
692
- wait=not no_wait,
693
- )
694
- _echo_json(result)
695
-
696
-
697
- if __name__ == "__main__":
698
- cli()
401
+
402
+
403
+ # ── Model Catalog ────────────────────────────────────────────────────────────
404
+
405
+ @cli.command("model-catalog")
406
+ @click.option("--refresh", is_flag=True, help="Bypass local catalog cache")
407
+ @click.option("--workspace-id", default=None, help="Workspace id; defaults to runtime workspace")
408
+ @click.option("--input-capabilities", default=None, help="Optional input capabilities filter, for example text or image")
409
+ @click.option(
410
+ "--category-code",
411
+ default="llm",
412
+ help="Model category code, for example llm, vision_llm, image_generation",
413
+ )
414
+ def model_catalog(refresh, workspace_id, input_capabilities, category_code):
415
+ """Print platform model capability catalog."""
416
+ from licos_dev_sdk import fetch_model_catalogs
417
+
418
+ _echo_json(
419
+ fetch_model_catalogs(
420
+ refresh=refresh,
421
+ workspace_id=workspace_id,
422
+ category_code=category_code,
423
+ input_capabilities=input_capabilities,
424
+ )
425
+ )
426
+
427
+
428
+ # ── LLM ──────────────────────────────────────────────────────────────────────
429
+
430
+ @cli.group("llm")
431
+ def llm_group():
432
+ """Call chat/text model capabilities."""
433
+ pass
434
+
435
+
436
+ @llm_group.command("invoke")
437
+ @click.option("-p", "--prompt", help="User prompt. If omitted, --messages or stdin is used.")
438
+ @click.option("--messages", help="OpenAI-style messages JSON array")
439
+ @click.option("--model", default=None)
440
+ @click.option("--temperature", default=None, type=float)
441
+ @click.option("--max-completion-tokens", default=None, type=int)
442
+ @click.option("--extra", default=None, help="Extra request fields as JSON object")
443
+ def llm_invoke(prompt, messages, model, temperature, max_completion_tokens, extra):
444
+ """Run a non-streaming chat completion."""
445
+ from licos_dev_sdk import LLMClient
446
+
447
+ if messages:
448
+ message_payload = _json_option(messages, "--messages")
449
+ else:
450
+ message_payload = prompt if prompt is not None else _read_input(None, None)
451
+ extra_payload = _json_option(extra, "--extra") or {}
452
+ if not isinstance(extra_payload, dict):
453
+ raise click.BadParameter("--extra must be a JSON object")
454
+ result = LLMClient().invoke(
455
+ message_payload,
456
+ model=model,
457
+ temperature=temperature,
458
+ max_completion_tokens=max_completion_tokens,
459
+ **extra_payload,
460
+ )
461
+ _echo_json(result)
462
+
463
+
464
+ @llm_group.command("stream")
465
+ @click.option("-p", "--prompt", help="User prompt. If omitted, --messages or stdin is used.")
466
+ @click.option("--messages", help="OpenAI-style messages JSON array")
467
+ @click.option("--model", default=None)
468
+ @click.option("--temperature", default=None, type=float)
469
+ @click.option("--max-completion-tokens", default=None, type=int)
470
+ @click.option("--extra", default=None, help="Extra request fields as JSON object")
471
+ def llm_stream(prompt, messages, model, temperature, max_completion_tokens, extra):
472
+ """Run a streaming chat completion and print text chunks."""
473
+ from licos_dev_sdk import LLMClient
474
+
475
+ if messages:
476
+ message_payload = _json_option(messages, "--messages")
477
+ else:
478
+ message_payload = prompt if prompt is not None else _read_input(None, None)
479
+ extra_payload = _json_option(extra, "--extra") or {}
480
+ if not isinstance(extra_payload, dict):
481
+ raise click.BadParameter("--extra must be a JSON object")
482
+ for chunk in LLMClient().stream(
483
+ message_payload,
484
+ model=model,
485
+ temperature=temperature,
486
+ max_completion_tokens=max_completion_tokens,
487
+ **extra_payload,
488
+ ):
489
+ click.echo(chunk, nl=False)
490
+
491
+
492
+ # ── Vision ───────────────────────────────────────────────────────────────────
493
+
494
+ @cli.group("vision")
495
+ def vision_group():
496
+ """Call chat vision model capabilities."""
497
+ pass
498
+
499
+
500
+ @vision_group.command("understand")
501
+ @click.option("--image", "image", multiple=True, help="Image URL, Base64 data URI, or plain Base64 image data. Can be repeated.")
502
+ @click.option("--image-url", "image_url", multiple=True, help="Alias for --image. Can be repeated.")
503
+ @click.option("--file-path", "file_path", multiple=True, help="Local image file path. Can be repeated.")
504
+ @click.option("-p", "--prompt", default="Describe this image.")
505
+ @click.option("--model", default=None)
506
+ @click.option("--mime-type", default=None, help="MIME type for plain Base64 image inputs. Defaults to image/png.")
507
+ @click.option("--raw-request", default=None, help="Raw JSON request body")
508
+ def vision_understand(image, image_url, file_path, prompt, model, mime_type, raw_request):
509
+ """Understand one or more images with the catalog vision model."""
510
+ from licos_dev_sdk import VisionClient
511
+
512
+ raw_payload = _json_option(raw_request, "--raw-request")
513
+ if raw_payload is not None and not isinstance(raw_payload, dict):
514
+ raise click.BadParameter("--raw-request must be a JSON object")
515
+ if raw_payload is None and not image_url and not image and not file_path:
516
+ raise click.UsageError("Provide --image, --image-url, --file-path, or --raw-request.")
517
+ result = VisionClient().understand(
518
+ images=[*image, *image_url],
519
+ file_paths=list(file_path),
520
+ prompt=prompt,
521
+ model=model,
522
+ mime_type=mime_type,
523
+ raw_request=raw_payload,
524
+ )
525
+ _echo_json(result)
526
+
527
+
528
+ # ── Image Generation ─────────────────────────────────────────────────────────
529
+
530
+ @cli.group("image-generation")
531
+ def image_generation_group():
532
+ """Call image generation model capabilities."""
533
+ pass
534
+
535
+
536
+ @image_generation_group.command("generate")
537
+ @click.option("-p", "--prompt")
538
+ @click.option("--image", "image", multiple=True, help="Source/reference image URL or Base64 data URI")
539
+ @click.option("--image-url", "image_url", multiple=True, help="Alias for --image")
540
+ @click.option("--reference-image", default=None, help="Alias for --image")
541
+ @click.option("--file-path", "file_path", multiple=True, help="Local source/reference image path")
542
+ @click.option("--input-capabilities", default=None, help="Override image model input filter: text or image")
543
+ @click.option("--negative-prompt", default=None)
544
+ @click.option("--count", default=1, type=int)
545
+ @click.option("--size", default=None)
546
+ @click.option("--model", default=None)
547
+ @click.option("--parameters", default=None, help="Parameters JSON object")
548
+ @click.option("--raw-request", default=None, help="Raw JSON request body")
549
+ @click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
550
+ def image_generate(
551
+ prompt,
552
+ image,
553
+ image_url,
554
+ reference_image,
555
+ file_path,
556
+ input_capabilities,
557
+ negative_prompt,
558
+ count,
559
+ size,
560
+ model,
561
+ parameters,
562
+ raw_request,
563
+ no_wait,
564
+ ):
565
+ """Generate images from text, image URLs/Base64, or local image files."""
566
+ from licos_dev_sdk import ImageGenerationClient
567
+
568
+ parameter_payload = _json_option(parameters, "--parameters") or {}
569
+ raw_payload = _json_option(raw_request, "--raw-request")
570
+ if not isinstance(parameter_payload, dict):
571
+ raise click.BadParameter("--parameters must be a JSON object")
572
+ if raw_payload is not None and not isinstance(raw_payload, dict):
573
+ raise click.BadParameter("--raw-request must be a JSON object")
574
+ if raw_payload is None and not prompt:
575
+ raise click.UsageError("Provide --prompt or --raw-request.")
576
+ result = ImageGenerationClient().generate(
577
+ prompt or "",
578
+ negative_prompt=negative_prompt,
579
+ count=count,
580
+ size=size,
581
+ images=[*image, *image_url],
582
+ reference_image=reference_image,
583
+ file_paths=list(file_path),
584
+ input_capabilities=input_capabilities,
585
+ model=model,
586
+ parameters=parameter_payload,
587
+ raw_request=raw_payload,
588
+ wait=not no_wait,
589
+ )
590
+ _echo_json(result)
591
+
592
+
593
+ # ── Video Generation ─────────────────────────────────────────────────────────
594
+
595
+ @cli.group("video-generation")
596
+ def video_generation_group():
597
+ """Call video generation model capabilities."""
598
+ pass
599
+
600
+
601
+ @video_generation_group.command("generate")
602
+ @click.option("-p", "--prompt")
603
+ @click.option("--image", default=None, help="Source/reference image URL, Base64 data URI, or plain Base64 image data")
604
+ @click.option("--image-url", default=None, help="Alias for --image")
605
+ @click.option("--reference-image", default=None, help="Alias for --image")
606
+ @click.option("--first-frame-url", default=None, help="Alias for --image")
607
+ @click.option("--file-path", default=None, help="Local source/reference image path")
608
+ @click.option("--model", default=None)
609
+ @click.option("--input-capabilities", default=None, help="Override video model input filter: text or image")
610
+ @click.option("--mime-type", default=None, help="MIME type for plain Base64 image inputs. Defaults to image/png.")
611
+ @click.option("--parameters", default=None, help="Parameters JSON object")
612
+ @click.option("--raw-request", default=None, help="Raw JSON request body")
613
+ @click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
614
+ def video_generate(
615
+ prompt,
616
+ image,
617
+ image_url,
618
+ reference_image,
619
+ first_frame_url,
620
+ file_path,
621
+ model,
622
+ input_capabilities,
623
+ mime_type,
624
+ parameters,
625
+ raw_request,
626
+ no_wait,
627
+ ):
628
+ """Generate a video from a text prompt and optional first-frame image."""
629
+ from licos_dev_sdk import VideoGenerationClient
630
+
631
+ parameter_payload = _json_option(parameters, "--parameters") or {}
632
+ raw_payload = _json_option(raw_request, "--raw-request")
633
+ if not isinstance(parameter_payload, dict):
634
+ raise click.BadParameter("--parameters must be a JSON object")
635
+ if raw_payload is not None and not isinstance(raw_payload, dict):
636
+ raise click.BadParameter("--raw-request must be a JSON object")
637
+ if raw_payload is None and not prompt:
638
+ raise click.UsageError("Provide --prompt or --raw-request.")
639
+ result = VideoGenerationClient().generate(
640
+ prompt or "",
641
+ image=image,
642
+ image_url=image_url,
643
+ reference_image=reference_image,
644
+ first_frame_url=first_frame_url,
645
+ file_path=file_path,
646
+ model=model,
647
+ input_capabilities=input_capabilities,
648
+ mime_type=mime_type,
649
+ parameters=parameter_payload,
650
+ raw_request=raw_payload,
651
+ wait=not no_wait,
652
+ )
653
+ _echo_json(result)
654
+
655
+
656
+ # ── Audio / ASR ──────────────────────────────────────────────────────────────
657
+
658
+ @cli.group("audio")
659
+ def audio_group():
660
+ """Call audio model capabilities."""
661
+ pass
662
+
663
+
664
+ @audio_group.command("recognize")
665
+ @click.option("--audio", "audio", multiple=True, help="Audio URL, Base64 data URI, or plain Base64 audio data. Can be repeated.")
666
+ @click.option("--audio-url", "audio_url", multiple=True, help="Alias for --audio. Can be repeated.")
667
+ @click.option("--file-path", "file_path", multiple=True, help="Local audio file path. Can be repeated.")
668
+ @click.option("--model", default=None)
669
+ @click.option("--mime-type", default=None, help="MIME type for plain Base64 audio inputs. Defaults to audio/wav.")
670
+ @click.option("--parameters", default=None, help="Parameters JSON object")
671
+ @click.option("--raw-request", default=None, help="Raw JSON request body")
672
+ @click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
673
+ def audio_recognize(audio, audio_url, file_path, model, mime_type, parameters, raw_request, no_wait):
674
+ """Recognize speech from one or more audio inputs."""
675
+ from licos_dev_sdk import SpeechRecognitionClient
676
+
677
+ parameter_payload = _json_option(parameters, "--parameters") or {}
678
+ raw_payload = _json_option(raw_request, "--raw-request")
679
+ if not isinstance(parameter_payload, dict):
680
+ raise click.BadParameter("--parameters must be a JSON object")
681
+ if raw_payload is not None and not isinstance(raw_payload, dict):
682
+ raise click.BadParameter("--raw-request must be a JSON object")
683
+ if raw_payload is None and not audio and not audio_url and not file_path:
684
+ raise click.UsageError("Provide --audio, --audio-url, --file-path, or --raw-request.")
685
+ result = SpeechRecognitionClient().recognize(
686
+ audios=[*audio, *audio_url],
687
+ file_paths=list(file_path),
688
+ model=model,
689
+ mime_type=mime_type,
690
+ parameters=parameter_payload,
691
+ raw_request=raw_payload,
692
+ wait=not no_wait,
693
+ )
694
+ _echo_json(result)
695
+
696
+
697
+ if __name__ == "__main__":
698
+ cli()