owui-cli 0.5.0__tar.gz → 0.5.2__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.
- {owui_cli-0.5.0 → owui_cli-0.5.2}/PKG-INFO +2 -2
- {owui_cli-0.5.0 → owui_cli-0.5.2}/pyproject.toml +1 -1
- owui_cli-0.5.2/src/owui_cli/__init__.py +1 -0
- {owui_cli-0.5.0 → owui_cli-0.5.2}/src/owui_cli/cli.py +93 -24
- {owui_cli-0.5.0 → owui_cli-0.5.2}/uv.lock +1 -1
- owui_cli-0.5.0/src/owui_cli/__init__.py +0 -1
- {owui_cli-0.5.0 → owui_cli-0.5.2}/.github/workflows/publish.yml +0 -0
- {owui_cli-0.5.0 → owui_cli-0.5.2}/.gitignore +0 -0
- {owui_cli-0.5.0 → owui_cli-0.5.2}/AGENTS.md +0 -0
- {owui_cli-0.5.0 → owui_cli-0.5.2}/LICENSE +0 -0
- {owui_cli-0.5.0 → owui_cli-0.5.2}/README.md +0 -0
- {owui_cli-0.5.0 → owui_cli-0.5.2}/src/owui_cli/data/api-schema.json +0 -0
- {owui_cli-0.5.0 → owui_cli-0.5.2}/update-schema.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: owui-cli
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: Admin CLI for Open WebUI instances
|
|
5
5
|
Project-URL: Homepage, https://github.com/rndmcnlly/owui-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/rndmcnlly/owui-cli
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.5.2"
|
|
@@ -444,6 +444,23 @@ def functions_valves_user_set_field(url, token, item_id, key, value):_valves_set
|
|
|
444
444
|
def functions_valves_user_unset_field(url, token, item_id, key): _valves_unset_field(url, token, "functions", item_id, key, "/user")
|
|
445
445
|
|
|
446
446
|
|
|
447
|
+
# ── functions toggle (activate / deactivate, and global) ─────────────
|
|
448
|
+
|
|
449
|
+
def functions_toggle(url, token, item_id):
|
|
450
|
+
"""Toggle a function's is_active flag."""
|
|
451
|
+
with httpx.Client(timeout=TIMEOUT) as c:
|
|
452
|
+
r = _post(c, url, f"/api/v1/functions/id/{item_id}/toggle", token)
|
|
453
|
+
f = r.json()
|
|
454
|
+
out(f"{item_id} {'active' if f.get('is_active') else 'inactive'}")
|
|
455
|
+
|
|
456
|
+
def functions_toggle_global(url, token, item_id):
|
|
457
|
+
"""Toggle a function's is_global flag (applies to all models)."""
|
|
458
|
+
with httpx.Client(timeout=TIMEOUT) as c:
|
|
459
|
+
r = _post(c, url, f"/api/v1/functions/id/{item_id}/toggle/global", token)
|
|
460
|
+
f = r.json()
|
|
461
|
+
out(f"{item_id} {'global' if f.get('is_global') else 'not global'}")
|
|
462
|
+
|
|
463
|
+
|
|
447
464
|
class SkillsResource(Resource):
|
|
448
465
|
"""Skills use frontmatter and have grant/revoke commands."""
|
|
449
466
|
|
|
@@ -573,33 +590,68 @@ def models_show(url, token, model_id):
|
|
|
573
590
|
if JSON_OUTPUT:
|
|
574
591
|
out(m)
|
|
575
592
|
return
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
params = info.get("params") or {}
|
|
593
|
+
meta = m.get("meta") or {}
|
|
594
|
+
params = m.get("params") or {}
|
|
579
595
|
pairs = [("id", m.get("id","")), ("name", m.get("name","")),
|
|
580
|
-
("base",
|
|
581
|
-
("active", str(
|
|
596
|
+
("base", m.get("base_model_id","(none)") or "(none)"),
|
|
597
|
+
("active", str(m.get("is_active","?"))),
|
|
582
598
|
("tools", ", ".join(meta.get("toolIds") or []) or "(none)"),
|
|
583
|
-
("filters", ", ".join(
|
|
599
|
+
("filters", ", ".join(meta.get("filterIds") or []) or "(none)"),
|
|
584
600
|
("knowledge", ", ".join(k.get("name","?") for k in (meta.get("knowledge") or [])) or "(none)"),
|
|
585
|
-
("system", f"{len(params.get('system'
|
|
586
|
-
("grants", str(len(
|
|
601
|
+
("system", f"{len(params.get('system') or '')} chars"),
|
|
602
|
+
("grants", str(len(m.get("access_grants") or [])))]
|
|
587
603
|
out_kv(pairs)
|
|
588
604
|
|
|
605
|
+
_MIME_BY_EXT = {
|
|
606
|
+
"png": "image/png",
|
|
607
|
+
"jpg": "image/jpeg",
|
|
608
|
+
"jpeg": "image/jpeg",
|
|
609
|
+
"gif": "image/gif",
|
|
610
|
+
"webp": "image/webp",
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
def _inline_sibling_images(json_path: str, payload: dict) -> list[str]:
|
|
615
|
+
"""Replace bare sibling-image references in meta.profile_image_url with data URIs.
|
|
616
|
+
|
|
617
|
+
The repo convention stores the icon as a sibling file referenced by bare
|
|
618
|
+
filename (e.g. "profile.png"). OWUI's stored-model validator (utils/validate.py)
|
|
619
|
+
rejects bare filenames and silently clears them to null, so push must inline
|
|
620
|
+
the sibling image instead — the mirror of models_pull_all's extraction.
|
|
621
|
+
Returns the list of inlined filenames.
|
|
622
|
+
"""
|
|
623
|
+
inlined = []
|
|
624
|
+
meta = payload.get("meta") if isinstance(payload, dict) else None
|
|
625
|
+
ref = (meta or {}).get("profile_image_url")
|
|
626
|
+
if not isinstance(ref, str) or not ref or ref.startswith(("data:", "http://", "https://", "/")):
|
|
627
|
+
return inlined
|
|
628
|
+
image_path = os.path.join(os.path.dirname(os.path.abspath(json_path)), ref)
|
|
629
|
+
ext = os.path.splitext(ref)[1].lstrip(".").lower()
|
|
630
|
+
mime = _MIME_BY_EXT.get(ext)
|
|
631
|
+
if mime and os.path.isfile(image_path):
|
|
632
|
+
with open(image_path, "rb") as f:
|
|
633
|
+
b64 = base64.b64encode(f.read()).decode()
|
|
634
|
+
payload["meta"]["profile_image_url"] = f"data:{mime};base64,{b64}"
|
|
635
|
+
inlined.append(ref)
|
|
636
|
+
return inlined
|
|
637
|
+
|
|
638
|
+
|
|
589
639
|
def models_create(url, token, json_path):
|
|
590
640
|
with open(json_path) as f:
|
|
591
641
|
payload = json.load(f)
|
|
642
|
+
inlined = _inline_sibling_images(json_path, payload)
|
|
592
643
|
with httpx.Client(timeout=TIMEOUT) as c:
|
|
593
644
|
r = _post(c, url, "/api/v1/models/create", token, payload)
|
|
594
645
|
m = r.json()
|
|
595
|
-
out(f"created {m.get('id')}")
|
|
646
|
+
out(f"created {m.get('id')}" + (f" (inlined {', '.join(inlined)})" if inlined else ""))
|
|
596
647
|
|
|
597
648
|
def models_update(url, token, json_path):
|
|
598
649
|
with open(json_path) as f:
|
|
599
650
|
payload = json.load(f)
|
|
651
|
+
inlined = _inline_sibling_images(json_path, payload)
|
|
600
652
|
with httpx.Client(timeout=TIMEOUT) as c:
|
|
601
653
|
r = _post(c, url, "/api/v1/models/model/update", token, payload)
|
|
602
|
-
out(f"updated {r.json().get('id')}")
|
|
654
|
+
out(f"updated {r.json().get('id')}" + (f" (inlined {', '.join(inlined)})" if inlined else ""))
|
|
603
655
|
|
|
604
656
|
def models_delete(url, token, model_id):
|
|
605
657
|
with httpx.Client(timeout=TIMEOUT) as c:
|
|
@@ -607,23 +659,38 @@ def models_delete(url, token, model_id):
|
|
|
607
659
|
out(f"deleted {model_id}")
|
|
608
660
|
|
|
609
661
|
def _models_fetch(c, url, token, model_id):
|
|
610
|
-
"""Fetch a model by ID, returning the parsed JSON."""
|
|
662
|
+
"""Fetch a model by ID, returning the parsed JSON (flat ModelModel shape)."""
|
|
611
663
|
r = _get(c, url, f"/api/v1/models/model?id={model_id}", token)
|
|
612
664
|
return r.json()
|
|
613
665
|
|
|
666
|
+
def _models_form(model):
|
|
667
|
+
"""Build a ModelForm update payload from a fetched flat model.
|
|
668
|
+
|
|
669
|
+
OWUI's Model schema is flat: top-level `meta`, `params`, `base_model_id`,
|
|
670
|
+
`name`, `is_active`, `access_grants`. The /model/update endpoint accepts a
|
|
671
|
+
ModelForm of the same shape (extra keys ignored). Rebuilding explicitly
|
|
672
|
+
avoids leaking response-only fields (user, write_access, timestamps) and
|
|
673
|
+
ensures `meta`/`params` round-trip intact.
|
|
674
|
+
"""
|
|
675
|
+
return {
|
|
676
|
+
"id": model.get("id"),
|
|
677
|
+
"base_model_id": model.get("base_model_id"),
|
|
678
|
+
"name": model.get("name", model.get("id", "")),
|
|
679
|
+
"meta": model.get("meta") or {},
|
|
680
|
+
"params": model.get("params") or {},
|
|
681
|
+
"access_grants": model.get("access_grants") or [],
|
|
682
|
+
"is_active": model.get("is_active", True),
|
|
683
|
+
}
|
|
684
|
+
|
|
614
685
|
def models_set_tools(url, token, model_id, *tool_ids):
|
|
615
686
|
"""Set the tool bindings for a workspace model (pass no IDs to clear)."""
|
|
616
687
|
with httpx.Client(timeout=TIMEOUT) as c:
|
|
617
688
|
model = _models_fetch(c, url, token, model_id)
|
|
618
|
-
|
|
619
|
-
meta = info.setdefault("meta", {})
|
|
620
|
-
params = info.setdefault("params", {})
|
|
689
|
+
form = _models_form(model)
|
|
621
690
|
ids = list(tool_ids)
|
|
622
|
-
meta
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
model["info"] = info
|
|
626
|
-
r = _post(c, url, "/api/v1/models/model/update", token, model)
|
|
691
|
+
# OWUI binds per-model tools via meta.toolIds.
|
|
692
|
+
form["meta"]["toolIds"] = ids
|
|
693
|
+
r = _post(c, url, "/api/v1/models/model/update", token, form)
|
|
627
694
|
label = ", ".join(ids) if ids else "(none)"
|
|
628
695
|
out(f"tools for {model_id}: {label}")
|
|
629
696
|
|
|
@@ -631,12 +698,12 @@ def models_set_filters(url, token, model_id, *filter_ids):
|
|
|
631
698
|
"""Set the filter bindings for a workspace model (pass no IDs to clear)."""
|
|
632
699
|
with httpx.Client(timeout=TIMEOUT) as c:
|
|
633
700
|
model = _models_fetch(c, url, token, model_id)
|
|
634
|
-
|
|
635
|
-
params = info.setdefault("params", {})
|
|
701
|
+
form = _models_form(model)
|
|
636
702
|
ids = list(filter_ids)
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
703
|
+
# OWUI reads per-model filters from meta.filterIds
|
|
704
|
+
# (see backend/open_webui/utils/filter.py).
|
|
705
|
+
form["meta"]["filterIds"] = ids
|
|
706
|
+
r = _post(c, url, "/api/v1/models/model/update", token, form)
|
|
640
707
|
label = ", ".join(ids) if ids else "(none)"
|
|
641
708
|
out(f"filters for {model_id}: {label}")
|
|
642
709
|
|
|
@@ -1156,6 +1223,8 @@ COMMANDS.update({
|
|
|
1156
1223
|
("functions", "valves-user-set"): (functions_valves_user_set, "<id> <valves.json>", (2, 2)),
|
|
1157
1224
|
("functions", "valves-user-set-field"): (functions_valves_user_set_field, "<id> <key> <value>", (3, 3)),
|
|
1158
1225
|
("functions", "valves-user-unset-field"):(functions_valves_user_unset_field, "<id> <key>", (2, 2)),
|
|
1226
|
+
("functions", "toggle"): (functions_toggle, "<id>", (1, 1)),
|
|
1227
|
+
("functions", "toggle-global"): (functions_toggle_global, "<id>", (1, 1)),
|
|
1159
1228
|
("models", "list"): (models_list, "", (0, 0)),
|
|
1160
1229
|
("models", "show"): (models_show, "<id>", (1, 1)),
|
|
1161
1230
|
("models", "create"): (models_create, "<model.json>", (1, 1)),
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.5.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|