licos-dev-cli 0.1.0__tar.gz → 0.2.0__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.1.0 → licos_dev_cli-0.2.0}/.gitignore +10 -5
- licos_dev_cli-0.2.0/PKG-INFO +7 -0
- {licos_dev_cli-0.1.0 → licos_dev_cli-0.2.0}/pyproject.toml +3 -3
- {licos_dev_cli-0.1.0 → licos_dev_cli-0.2.0}/src/licos_dev_cli/main.py +239 -2
- licos_dev_cli-0.1.0/PKG-INFO +0 -7
- {licos_dev_cli-0.1.0 → licos_dev_cli-0.2.0}/src/licos_dev_cli/__init__.py +0 -0
|
@@ -31,14 +31,19 @@ Thumbs.db
|
|
|
31
31
|
|
|
32
32
|
# Build
|
|
33
33
|
*.log
|
|
34
|
+
*.pid
|
|
34
35
|
.licos
|
|
36
|
+
.tmp
|
|
37
|
+
.playwright-cli
|
|
35
38
|
|
|
36
39
|
/tmp
|
|
37
|
-
|
|
38
|
-
/Docs/hermes-agent
|
|
39
|
-
/Docs/OpenCode
|
|
40
|
-
/Docs/平台API
|
|
40
|
+
tools/android-sdk-cache/*.zip
|
|
41
41
|
|
|
42
42
|
*.codex-*
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
dist
|
|
45
|
+
logs
|
|
46
|
+
|
|
47
|
+
source
|
|
48
|
+
|
|
49
|
+
平台API
|
|
@@ -4,11 +4,11 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "licos-dev-cli"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "LICOS Dev CLI
|
|
7
|
+
version = "0.2.0"
|
|
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.
|
|
11
|
+
"licos-dev-sdk>=0.2.0",
|
|
12
12
|
"click>=8.1",
|
|
13
13
|
]
|
|
14
14
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""CLI entry point
|
|
1
|
+
"""CLI entry point - wraps licos-dev-sdk functions as click commands."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -26,11 +26,26 @@ def _read_json(input_path: str | None, content: str | None) -> object:
|
|
|
26
26
|
return json.loads(raw)
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
def _json_option(value: str | None, name: str) -> dict | list | None:
|
|
30
|
+
if not value:
|
|
31
|
+
return None
|
|
32
|
+
try:
|
|
33
|
+
return json.loads(value)
|
|
34
|
+
except json.JSONDecodeError as exc:
|
|
35
|
+
raise click.BadParameter(f"{name} must be valid JSON") from exc
|
|
36
|
+
|
|
37
|
+
|
|
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
|
+
|
|
29
44
|
# ── CLI Group ────────────────────────────────────────────────────────────────
|
|
30
45
|
|
|
31
46
|
@click.group()
|
|
32
47
|
def cli():
|
|
33
|
-
"""LICOS Dev
|
|
48
|
+
"""LICOS Dev - file generation and model CLI for AI agents."""
|
|
34
49
|
pass
|
|
35
50
|
|
|
36
51
|
|
|
@@ -281,5 +296,227 @@ def html_cmd(input_path, content, filename, output_dir, content_type):
|
|
|
281
296
|
click.echo(path)
|
|
282
297
|
|
|
283
298
|
|
|
299
|
+
# ── Model Catalog ────────────────────────────────────────────────────────────
|
|
300
|
+
|
|
301
|
+
@cli.command("model-catalog")
|
|
302
|
+
@click.option("--refresh", is_flag=True, help="Bypass local catalog cache")
|
|
303
|
+
def model_catalog(refresh):
|
|
304
|
+
"""Print platform model capability catalog."""
|
|
305
|
+
from licos_dev_sdk import fetch_model_catalogs
|
|
306
|
+
|
|
307
|
+
_echo_json(fetch_model_catalogs(refresh=refresh))
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
# ── LLM ──────────────────────────────────────────────────────────────────────
|
|
311
|
+
|
|
312
|
+
@cli.group("llm")
|
|
313
|
+
def llm_group():
|
|
314
|
+
"""Call chat/text model capabilities."""
|
|
315
|
+
pass
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
@llm_group.command("invoke")
|
|
319
|
+
@click.option("-p", "--prompt", help="User prompt. If omitted, --messages or stdin is used.")
|
|
320
|
+
@click.option("--messages", help="OpenAI-style messages JSON array")
|
|
321
|
+
@click.option("--model", default=None)
|
|
322
|
+
@click.option("--temperature", default=None, type=float)
|
|
323
|
+
@click.option("--max-completion-tokens", default=None, type=int)
|
|
324
|
+
@click.option("--extra", default=None, help="Extra request fields as JSON object")
|
|
325
|
+
def llm_invoke(prompt, messages, model, temperature, max_completion_tokens, extra):
|
|
326
|
+
"""Run a non-streaming chat completion."""
|
|
327
|
+
from licos_dev_sdk import LLMClient
|
|
328
|
+
|
|
329
|
+
if messages:
|
|
330
|
+
message_payload = _json_option(messages, "--messages")
|
|
331
|
+
else:
|
|
332
|
+
message_payload = prompt if prompt is not None else _read_input(None, None)
|
|
333
|
+
extra_payload = _json_option(extra, "--extra") or {}
|
|
334
|
+
if not isinstance(extra_payload, dict):
|
|
335
|
+
raise click.BadParameter("--extra must be a JSON object")
|
|
336
|
+
result = LLMClient().invoke(
|
|
337
|
+
message_payload,
|
|
338
|
+
model=model,
|
|
339
|
+
temperature=temperature,
|
|
340
|
+
max_completion_tokens=max_completion_tokens,
|
|
341
|
+
**extra_payload,
|
|
342
|
+
)
|
|
343
|
+
_echo_json(result)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
@llm_group.command("stream")
|
|
347
|
+
@click.option("-p", "--prompt", help="User prompt. If omitted, --messages or stdin is used.")
|
|
348
|
+
@click.option("--messages", help="OpenAI-style messages JSON array")
|
|
349
|
+
@click.option("--model", default=None)
|
|
350
|
+
@click.option("--temperature", default=None, type=float)
|
|
351
|
+
@click.option("--max-completion-tokens", default=None, type=int)
|
|
352
|
+
@click.option("--extra", default=None, help="Extra request fields as JSON object")
|
|
353
|
+
def llm_stream(prompt, messages, model, temperature, max_completion_tokens, extra):
|
|
354
|
+
"""Run a streaming chat completion and print text chunks."""
|
|
355
|
+
from licos_dev_sdk import LLMClient
|
|
356
|
+
|
|
357
|
+
if messages:
|
|
358
|
+
message_payload = _json_option(messages, "--messages")
|
|
359
|
+
else:
|
|
360
|
+
message_payload = prompt if prompt is not None else _read_input(None, None)
|
|
361
|
+
extra_payload = _json_option(extra, "--extra") or {}
|
|
362
|
+
if not isinstance(extra_payload, dict):
|
|
363
|
+
raise click.BadParameter("--extra must be a JSON object")
|
|
364
|
+
for chunk in LLMClient().stream(
|
|
365
|
+
message_payload,
|
|
366
|
+
model=model,
|
|
367
|
+
temperature=temperature,
|
|
368
|
+
max_completion_tokens=max_completion_tokens,
|
|
369
|
+
**extra_payload,
|
|
370
|
+
):
|
|
371
|
+
click.echo(chunk, nl=False)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
# ── Vision ───────────────────────────────────────────────────────────────────
|
|
375
|
+
|
|
376
|
+
@cli.group("vision")
|
|
377
|
+
def vision_group():
|
|
378
|
+
"""Call chat vision model capabilities."""
|
|
379
|
+
pass
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
@vision_group.command("understand")
|
|
383
|
+
@click.option("--image-url", multiple=True, help="Image URL. Can be repeated.")
|
|
384
|
+
@click.option("-p", "--prompt", default="Describe this image.")
|
|
385
|
+
@click.option("--model", default=None)
|
|
386
|
+
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
387
|
+
def vision_understand(image_url, prompt, model, raw_request):
|
|
388
|
+
"""Understand one or more images with the catalog vision model."""
|
|
389
|
+
from licos_dev_sdk import VisionClient
|
|
390
|
+
|
|
391
|
+
raw_payload = _json_option(raw_request, "--raw-request")
|
|
392
|
+
if raw_payload is not None and not isinstance(raw_payload, dict):
|
|
393
|
+
raise click.BadParameter("--raw-request must be a JSON object")
|
|
394
|
+
if raw_payload is None and not image_url:
|
|
395
|
+
raise click.UsageError("Provide --image-url or --raw-request.")
|
|
396
|
+
result = VisionClient().understand(
|
|
397
|
+
image_urls=list(image_url),
|
|
398
|
+
prompt=prompt,
|
|
399
|
+
model=model,
|
|
400
|
+
raw_request=raw_payload,
|
|
401
|
+
)
|
|
402
|
+
_echo_json(result)
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
# ── Image Generation ─────────────────────────────────────────────────────────
|
|
406
|
+
|
|
407
|
+
@cli.group("image-generation")
|
|
408
|
+
def image_generation_group():
|
|
409
|
+
"""Call image generation model capabilities."""
|
|
410
|
+
pass
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
@image_generation_group.command("generate")
|
|
414
|
+
@click.option("-p", "--prompt")
|
|
415
|
+
@click.option("--negative-prompt", default=None)
|
|
416
|
+
@click.option("--count", default=1, type=int)
|
|
417
|
+
@click.option("--size", default=None)
|
|
418
|
+
@click.option("--model", default=None)
|
|
419
|
+
@click.option("--parameters", default=None, help="Parameters JSON object")
|
|
420
|
+
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
421
|
+
@click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
|
|
422
|
+
def image_generate(prompt, negative_prompt, count, size, model, parameters, raw_request, no_wait):
|
|
423
|
+
"""Generate images from a text prompt."""
|
|
424
|
+
from licos_dev_sdk import ImageGenerationClient
|
|
425
|
+
|
|
426
|
+
parameter_payload = _json_option(parameters, "--parameters") or {}
|
|
427
|
+
raw_payload = _json_option(raw_request, "--raw-request")
|
|
428
|
+
if not isinstance(parameter_payload, dict):
|
|
429
|
+
raise click.BadParameter("--parameters must be a JSON object")
|
|
430
|
+
if raw_payload is not None and not isinstance(raw_payload, dict):
|
|
431
|
+
raise click.BadParameter("--raw-request must be a JSON object")
|
|
432
|
+
if raw_payload is None and not prompt:
|
|
433
|
+
raise click.UsageError("Provide --prompt or --raw-request.")
|
|
434
|
+
result = ImageGenerationClient().generate(
|
|
435
|
+
prompt or "",
|
|
436
|
+
negative_prompt=negative_prompt,
|
|
437
|
+
count=count,
|
|
438
|
+
size=size,
|
|
439
|
+
model=model,
|
|
440
|
+
parameters=parameter_payload,
|
|
441
|
+
raw_request=raw_payload,
|
|
442
|
+
wait=not no_wait,
|
|
443
|
+
)
|
|
444
|
+
_echo_json(result)
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
# ── Video Generation ─────────────────────────────────────────────────────────
|
|
448
|
+
|
|
449
|
+
@cli.group("video-generation")
|
|
450
|
+
def video_generation_group():
|
|
451
|
+
"""Call video generation model capabilities."""
|
|
452
|
+
pass
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
@video_generation_group.command("generate")
|
|
456
|
+
@click.option("-p", "--prompt")
|
|
457
|
+
@click.option("--image-url", default=None)
|
|
458
|
+
@click.option("--model", default=None)
|
|
459
|
+
@click.option("--parameters", default=None, help="Parameters JSON object")
|
|
460
|
+
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
461
|
+
@click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
|
|
462
|
+
def video_generate(prompt, image_url, model, parameters, raw_request, no_wait):
|
|
463
|
+
"""Generate a video from a text prompt and optional first-frame image."""
|
|
464
|
+
from licos_dev_sdk import VideoGenerationClient
|
|
465
|
+
|
|
466
|
+
parameter_payload = _json_option(parameters, "--parameters") or {}
|
|
467
|
+
raw_payload = _json_option(raw_request, "--raw-request")
|
|
468
|
+
if not isinstance(parameter_payload, dict):
|
|
469
|
+
raise click.BadParameter("--parameters must be a JSON object")
|
|
470
|
+
if raw_payload is not None and not isinstance(raw_payload, dict):
|
|
471
|
+
raise click.BadParameter("--raw-request must be a JSON object")
|
|
472
|
+
if raw_payload is None and not prompt:
|
|
473
|
+
raise click.UsageError("Provide --prompt or --raw-request.")
|
|
474
|
+
result = VideoGenerationClient().generate(
|
|
475
|
+
prompt or "",
|
|
476
|
+
image_url=image_url,
|
|
477
|
+
model=model,
|
|
478
|
+
parameters=parameter_payload,
|
|
479
|
+
raw_request=raw_payload,
|
|
480
|
+
wait=not no_wait,
|
|
481
|
+
)
|
|
482
|
+
_echo_json(result)
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
# ── Audio / ASR ──────────────────────────────────────────────────────────────
|
|
486
|
+
|
|
487
|
+
@cli.group("audio")
|
|
488
|
+
def audio_group():
|
|
489
|
+
"""Call audio model capabilities."""
|
|
490
|
+
pass
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
@audio_group.command("recognize")
|
|
494
|
+
@click.option("--audio-url", multiple=True, help="Audio URL. Can be repeated.")
|
|
495
|
+
@click.option("--model", default=None)
|
|
496
|
+
@click.option("--parameters", default=None, help="Parameters JSON object")
|
|
497
|
+
@click.option("--raw-request", default=None, help="Raw JSON request body")
|
|
498
|
+
@click.option("--no-wait", is_flag=True, help="Return submit response without polling async tasks")
|
|
499
|
+
def audio_recognize(audio_url, model, parameters, raw_request, no_wait):
|
|
500
|
+
"""Recognize speech from one or more audio URLs."""
|
|
501
|
+
from licos_dev_sdk import SpeechRecognitionClient
|
|
502
|
+
|
|
503
|
+
parameter_payload = _json_option(parameters, "--parameters") or {}
|
|
504
|
+
raw_payload = _json_option(raw_request, "--raw-request")
|
|
505
|
+
if not isinstance(parameter_payload, dict):
|
|
506
|
+
raise click.BadParameter("--parameters must be a JSON object")
|
|
507
|
+
if raw_payload is not None and not isinstance(raw_payload, dict):
|
|
508
|
+
raise click.BadParameter("--raw-request must be a JSON object")
|
|
509
|
+
if raw_payload is None and not audio_url:
|
|
510
|
+
raise click.UsageError("Provide --audio-url or --raw-request.")
|
|
511
|
+
result = SpeechRecognitionClient().recognize(
|
|
512
|
+
audio_urls=list(audio_url),
|
|
513
|
+
model=model,
|
|
514
|
+
parameters=parameter_payload,
|
|
515
|
+
raw_request=raw_payload,
|
|
516
|
+
wait=not no_wait,
|
|
517
|
+
)
|
|
518
|
+
_echo_json(result)
|
|
519
|
+
|
|
520
|
+
|
|
284
521
|
if __name__ == "__main__":
|
|
285
522
|
cli()
|
licos_dev_cli-0.1.0/PKG-INFO
DELETED
|
File without changes
|