opsiom-cli 1.2.1__tar.gz → 1.2.3__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.
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/PKG-INFO +1 -1
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/pyproject.toml +1 -1
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/src/opsiom_cli/cli.py +15 -15
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/src/opsiom_cli.egg-info/PKG-INFO +1 -1
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/README.md +0 -0
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/setup.cfg +0 -0
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/src/opsiom_cli/__init__.py +0 -0
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/src/opsiom_cli.egg-info/SOURCES.txt +0 -0
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/src/opsiom_cli.egg-info/dependency_links.txt +0 -0
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/src/opsiom_cli.egg-info/entry_points.txt +0 -0
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/src/opsiom_cli.egg-info/requires.txt +0 -0
- {opsiom_cli-1.2.1 → opsiom_cli-1.2.3}/src/opsiom_cli.egg-info/top_level.txt +0 -0
|
@@ -40,7 +40,7 @@ try:
|
|
|
40
40
|
except ImportError:
|
|
41
41
|
readline = None # absent par défaut sur certains Windows (pyreadline3 comble le manque)
|
|
42
42
|
|
|
43
|
-
VERSION = "1.
|
|
43
|
+
VERSION = "1.1.5"
|
|
44
44
|
CONFIG_PATH = Path.home() / ".config" / "opsiom" / "config.json"
|
|
45
45
|
HISTORY_PATH = Path.home() / ".local" / "share" / "opsiom" / "history"
|
|
46
46
|
TRANSCRIPTS_DIR = Path.home() / "opsiom-conversations"
|
|
@@ -234,7 +234,7 @@ def save_transcript(transcript, filename=None):
|
|
|
234
234
|
else:
|
|
235
235
|
lines.append(f"**Opsiom ({entry['model']}) :** {entry['text']} _({entry['elapsed_ms']} ms)_")
|
|
236
236
|
lines.append("")
|
|
237
|
-
path.write_text("
|
|
237
|
+
path.write_text("\n".join(lines), encoding="utf-8")
|
|
238
238
|
return path
|
|
239
239
|
|
|
240
240
|
|
|
@@ -263,7 +263,7 @@ def prompt_for_config():
|
|
|
263
263
|
api_key = input(" Clé API (vide si aucune) : ").strip()
|
|
264
264
|
save = input(muted(" Sauvegarder localement pour la prochaine fois ? [O/n] ")).strip().lower()
|
|
265
265
|
config = {"url": url, "api_key": api_key}
|
|
266
|
-
if save in ("
|
|
266
|
+
if save in ("", "o", "oui", "y", "yes"):
|
|
267
267
|
save_config(config)
|
|
268
268
|
print(muted(f" → enregistré dans {CONFIG_PATH} "))
|
|
269
269
|
return config
|
|
@@ -411,12 +411,12 @@ def print_error(text, detail=None):
|
|
|
411
411
|
|
|
412
412
|
def choose_default_model(models_payload):
|
|
413
413
|
default = models_payload.get("default")
|
|
414
|
-
models = models_payload.get("models
|
|
414
|
+
models = models_payload.get("models", [])
|
|
415
415
|
return default or (models[0]["id"] if models else None)
|
|
416
416
|
|
|
417
417
|
|
|
418
418
|
def print_models(models_payload, current_model):
|
|
419
|
-
for i, m in enumerate(models_payload.get("models
|
|
419
|
+
for i, m in enumerate(models_payload.get("models", []), start=1):
|
|
420
420
|
is_current = m["id"] == current_model
|
|
421
421
|
marker = accent("›") if is_current else " "
|
|
422
422
|
label = accent(m["label"], bold=True) if is_current else m["label"]
|
|
@@ -438,7 +438,7 @@ def resolve_model_choice(choice, models):
|
|
|
438
438
|
|
|
439
439
|
|
|
440
440
|
def select_model_interactively(models_payload, current_model):
|
|
441
|
-
models = models_payload.get("models
|
|
441
|
+
models = models_payload.get("models", [])
|
|
442
442
|
if not models:
|
|
443
443
|
print_error("aucun modèle disponible côté serveur.")
|
|
444
444
|
return current_model
|
|
@@ -458,7 +458,7 @@ def print_assistant_message(text, elapsed_ms):
|
|
|
458
458
|
width = max(term_width() - 4, 30)
|
|
459
459
|
wrapped = textwrap.fill(text, width=width)
|
|
460
460
|
print()
|
|
461
|
-
for line in wrapped.split("
|
|
461
|
+
for line in wrapped.split("\n"):
|
|
462
462
|
print(f" {line}")
|
|
463
463
|
print(f" {muted(format_elapsed(elapsed_ms))}")
|
|
464
464
|
|
|
@@ -475,7 +475,7 @@ def run_chat(client: OpsiomClient, url, api_key):
|
|
|
475
475
|
try:
|
|
476
476
|
health = client.health()
|
|
477
477
|
connected = health.get("status") == "ok"
|
|
478
|
-
models_loaded = health.get("models_loaded
|
|
478
|
+
models_loaded = health.get("models_loaded", [])
|
|
479
479
|
except requests.HTTPError as e:
|
|
480
480
|
connected = False
|
|
481
481
|
invalid_key = e.response is not None and e.response.status_code in (401, 403)
|
|
@@ -509,7 +509,7 @@ def run_chat(client: OpsiomClient, url, api_key):
|
|
|
509
509
|
arg = rest[0].strip() if rest else ""
|
|
510
510
|
cmd = cmd.lower()
|
|
511
511
|
|
|
512
|
-
if cmd in ("quit
|
|
512
|
+
if cmd in ("quit", "exit"):
|
|
513
513
|
break
|
|
514
514
|
elif cmd == "help":
|
|
515
515
|
print(muted(HELP_TEXT))
|
|
@@ -537,7 +537,7 @@ def run_chat(client: OpsiomClient, url, api_key):
|
|
|
537
537
|
if not arg:
|
|
538
538
|
current_model = select_model_interactively(models_payload, current_model)
|
|
539
539
|
else:
|
|
540
|
-
resolved = resolve_model_choice(arg, models_payload.get("models
|
|
540
|
+
resolved = resolve_model_choice(arg, models_payload.get("models", [])) or arg
|
|
541
541
|
current_model = resolved
|
|
542
542
|
print(f" {accent('→')} modèle actif : {accent(resolved, bold=True)}")
|
|
543
543
|
else:
|
|
@@ -554,7 +554,7 @@ def run_chat(client: OpsiomClient, url, api_key):
|
|
|
554
554
|
print()
|
|
555
555
|
continue
|
|
556
556
|
|
|
557
|
-
transcript.append({"role": "user
|
|
557
|
+
transcript.append({"role": "user", "text": user_input})
|
|
558
558
|
|
|
559
559
|
spinner = Spinner(label="Réflexion")
|
|
560
560
|
spinner.start()
|
|
@@ -583,8 +583,8 @@ def run_chat(client: OpsiomClient, url, api_key):
|
|
|
583
583
|
spinner.stop()
|
|
584
584
|
elapsed_ms = int((time.perf_counter() - start_time) * 1000)
|
|
585
585
|
|
|
586
|
-
response_text = result.get("response
|
|
587
|
-
used_model = result.get("model
|
|
586
|
+
response_text = result.get("response", "(réponse vide)")
|
|
587
|
+
used_model = result.get("model", current_model or "?")
|
|
588
588
|
print_assistant_message(response_text, elapsed_ms)
|
|
589
589
|
|
|
590
590
|
tokens_used = result.get("tokens_used") or (estimate_tokens(user_input) + estimate_tokens(response_text))
|
|
@@ -592,7 +592,7 @@ def run_chat(client: OpsiomClient, url, api_key):
|
|
|
592
592
|
_, remaining_quota = get_quota_state(api_key)
|
|
593
593
|
print(f" {muted(f'{remaining_quota} tokens restants aujourd’hui')}")
|
|
594
594
|
print()
|
|
595
|
-
transcript.append({"role": "assistant
|
|
595
|
+
transcript.append({"role": "assistant", "text": response_text, "model": used_model, "elapsed_ms": elapsed_ms})
|
|
596
596
|
|
|
597
597
|
save_history()
|
|
598
598
|
|
|
@@ -625,4 +625,4 @@ def main():
|
|
|
625
625
|
|
|
626
626
|
|
|
627
627
|
if __name__ == "__main__":
|
|
628
|
-
main()
|
|
628
|
+
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|