owui-cli 0.3.0__tar.gz → 0.5.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.
- {owui_cli-0.3.0 → owui_cli-0.5.0}/.gitignore +1 -0
- owui_cli-0.5.0/AGENTS.md +49 -0
- {owui_cli-0.3.0 → owui_cli-0.5.0}/PKG-INFO +1 -1
- {owui_cli-0.3.0 → owui_cli-0.5.0}/pyproject.toml +1 -1
- owui_cli-0.5.0/src/owui_cli/__init__.py +1 -0
- {owui_cli-0.3.0 → owui_cli-0.5.0}/src/owui_cli/cli.py +133 -9
- owui_cli-0.5.0/uv.lock +91 -0
- owui_cli-0.3.0/src/owui_cli/__init__.py +0 -1
- {owui_cli-0.3.0 → owui_cli-0.5.0}/.github/workflows/publish.yml +0 -0
- {owui_cli-0.3.0 → owui_cli-0.5.0}/LICENSE +0 -0
- {owui_cli-0.3.0 → owui_cli-0.5.0}/README.md +0 -0
- {owui_cli-0.3.0 → owui_cli-0.5.0}/src/owui_cli/data/api-schema.json +0 -0
- {owui_cli-0.3.0 → owui_cli-0.5.0}/update-schema.py +0 -0
owui_cli-0.5.0/AGENTS.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# AGENTS.md — owui-cli
|
|
2
|
+
|
|
3
|
+
## Version management
|
|
4
|
+
|
|
5
|
+
The version number appears in two places and **must be kept in sync**:
|
|
6
|
+
|
|
7
|
+
- `pyproject.toml` → `version = "X.Y.Z"`
|
|
8
|
+
- `src/owui_cli/__init__.py` → `__version__ = "X.Y.Z"`
|
|
9
|
+
|
|
10
|
+
Bump both when cutting a release.
|
|
11
|
+
|
|
12
|
+
## Publishing
|
|
13
|
+
|
|
14
|
+
Every push to `main` auto-publishes to PyPI via GitHub Actions trusted publishing. Bump the version before pushing, and don't push broken code to main.
|
|
15
|
+
|
|
16
|
+
## Local development install
|
|
17
|
+
|
|
18
|
+
After making changes, reinstall locally with `uv tool install --force .` so your modified `owui-cli` is the one on your PATH.
|
|
19
|
+
|
|
20
|
+
## Testing before committing
|
|
21
|
+
|
|
22
|
+
Always verify changes work against a **production Open WebUI server** before committing. Set `OWUI_URL` and `OWUI_TOKEN` and run the relevant commands to confirm they succeed with real API responses — don't rely on local-only reasoning.
|
|
23
|
+
|
|
24
|
+
## Architecture
|
|
25
|
+
|
|
26
|
+
Single-file CLI in `src/owui_cli/cli.py`. The `Resource` base class handles generic CRUD (list, show, deploy, pull, pull-all, delete) for tools, functions, and skills. Special resources (models, knowledge, files, groups, users, chats, configs, prompts) use standalone functions. All commands are registered in the `COMMANDS` dispatch table at the bottom of the file.
|
|
27
|
+
|
|
28
|
+
## API endpoint patterns
|
|
29
|
+
|
|
30
|
+
The Open WebUI API is not fully consistent across resources:
|
|
31
|
+
|
|
32
|
+
- **Tools/functions/skills:** `/api/v1/{resource}/id/{id}`
|
|
33
|
+
- **Models:** `/api/v1/models/model?id={id}`
|
|
34
|
+
- **Knowledge/users:** `/api/v1/{resource}/{id}`
|
|
35
|
+
- **Groups:** `/api/v1/groups/id/{id}`
|
|
36
|
+
|
|
37
|
+
Always verify the actual endpoint against a running instance when adding new commands.
|
|
38
|
+
|
|
39
|
+
## Output conventions
|
|
40
|
+
|
|
41
|
+
All commands support `--json` for machine-readable output. New commands should use the existing output helpers which handle JSON mode automatically:
|
|
42
|
+
|
|
43
|
+
- `out(data)` — generic output (JSON in `--json` mode, pretty-printed otherwise)
|
|
44
|
+
- `out_table(rows, cols)` — aligned columnar table
|
|
45
|
+
- `out_kv(pairs)` — key-value display
|
|
46
|
+
|
|
47
|
+
## Schema updates
|
|
48
|
+
|
|
49
|
+
`update-schema.py` fetches OWUI router sources from GitHub and generates a prompt to feed an LLM. The LLM output goes in `src/owui_cli/data/api-schema.json`. See the script header for the full workflow.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.5.0"
|
|
@@ -43,8 +43,8 @@ def _api(url: str, path: str) -> str:
|
|
|
43
43
|
return f"{url}{path}"
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
def _get(c: httpx.Client, url: str, path: str, token: str) -> httpx.Response:
|
|
47
|
-
r = c.get(_api(url, path), headers=_headers(token))
|
|
46
|
+
def _get(c: httpx.Client, url: str, path: str, token: str, params=None) -> httpx.Response:
|
|
47
|
+
r = c.get(_api(url, path), headers=_headers(token), params=params)
|
|
48
48
|
r.raise_for_status()
|
|
49
49
|
return r
|
|
50
50
|
|
|
@@ -369,6 +369,81 @@ functions_res = Resource("functions", "/api/v1/functions",
|
|
|
369
369
|
workspace_path="/workspace/functions")
|
|
370
370
|
|
|
371
371
|
|
|
372
|
+
# ── valves (admin/global and per-user, for tools and functions) ──────
|
|
373
|
+
#
|
|
374
|
+
# OWUI plugins can declare two valve schemas:
|
|
375
|
+
# class Valves(BaseModel) -> /api/v1/{kind}/id/{id}/valves[/spec|/update]
|
|
376
|
+
# class UserValves(BaseModel) -> /api/v1/{kind}/id/{id}/valves/user[/spec|/update]
|
|
377
|
+
#
|
|
378
|
+
# The unprefixed `valves*` commands target the admin/global path (most common
|
|
379
|
+
# case: an admin-set API key). The `valves-user*` commands target the per-user
|
|
380
|
+
# path (the calling user's personal valves on the plugin).
|
|
381
|
+
|
|
382
|
+
def _valves_get(url, token, kind, item_id, scope=""):
|
|
383
|
+
with httpx.Client(timeout=TIMEOUT) as c:
|
|
384
|
+
r = _get(c, url, f"/api/v1/{kind}/id/{item_id}/valves{scope}", token)
|
|
385
|
+
out(r.json())
|
|
386
|
+
|
|
387
|
+
def _valves_spec(url, token, kind, item_id, scope=""):
|
|
388
|
+
with httpx.Client(timeout=TIMEOUT) as c:
|
|
389
|
+
r = _get(c, url, f"/api/v1/{kind}/id/{item_id}/valves{scope}/spec", token)
|
|
390
|
+
out(r.json())
|
|
391
|
+
|
|
392
|
+
def _valves_set(url, token, kind, item_id, json_path, scope=""):
|
|
393
|
+
with open(json_path) as f:
|
|
394
|
+
payload = json.load(f)
|
|
395
|
+
with httpx.Client(timeout=TIMEOUT) as c:
|
|
396
|
+
r = _post(c, url, f"/api/v1/{kind}/id/{item_id}/valves{scope}/update", token, payload)
|
|
397
|
+
out(r.json())
|
|
398
|
+
|
|
399
|
+
def _valves_set_field(url, token, kind, item_id, key, value, scope=""):
|
|
400
|
+
"""Set a single field. Value is parsed as JSON; falls back to string."""
|
|
401
|
+
try:
|
|
402
|
+
parsed = json.loads(value)
|
|
403
|
+
except (json.JSONDecodeError, ValueError):
|
|
404
|
+
parsed = value
|
|
405
|
+
with httpx.Client(timeout=TIMEOUT) as c:
|
|
406
|
+
current = _get(c, url, f"/api/v1/{kind}/id/{item_id}/valves{scope}", token).json()
|
|
407
|
+
current[key] = parsed
|
|
408
|
+
r = _post(c, url, f"/api/v1/{kind}/id/{item_id}/valves{scope}/update", token, current)
|
|
409
|
+
out(r.json())
|
|
410
|
+
|
|
411
|
+
def _valves_unset_field(url, token, kind, item_id, key, scope=""):
|
|
412
|
+
with httpx.Client(timeout=TIMEOUT) as c:
|
|
413
|
+
current = _get(c, url, f"/api/v1/{kind}/id/{item_id}/valves{scope}", token).json()
|
|
414
|
+
if key not in current:
|
|
415
|
+
die(f"key '{key}' not found in valves")
|
|
416
|
+
del current[key]
|
|
417
|
+
r = _post(c, url, f"/api/v1/{kind}/id/{item_id}/valves{scope}/update", token, current)
|
|
418
|
+
out(r.json())
|
|
419
|
+
|
|
420
|
+
# Wrappers — admin/global valves (unprefixed: the common case)
|
|
421
|
+
def tools_valves_get(url, token, item_id): _valves_get(url, token, "tools", item_id)
|
|
422
|
+
def tools_valves_spec(url, token, item_id): _valves_spec(url, token, "tools", item_id)
|
|
423
|
+
def tools_valves_set(url, token, item_id, json_path): _valves_set(url, token, "tools", item_id, json_path)
|
|
424
|
+
def tools_valves_set_field(url, token, item_id, key, value):_valves_set_field(url, token, "tools", item_id, key, value)
|
|
425
|
+
def tools_valves_unset_field(url, token, item_id, key): _valves_unset_field(url, token, "tools", item_id, key)
|
|
426
|
+
|
|
427
|
+
def functions_valves_get(url, token, item_id): _valves_get(url, token, "functions", item_id)
|
|
428
|
+
def functions_valves_spec(url, token, item_id): _valves_spec(url, token, "functions", item_id)
|
|
429
|
+
def functions_valves_set(url, token, item_id, json_path): _valves_set(url, token, "functions", item_id, json_path)
|
|
430
|
+
def functions_valves_set_field(url, token, item_id, key, value):_valves_set_field(url, token, "functions", item_id, key, value)
|
|
431
|
+
def functions_valves_unset_field(url, token, item_id, key): _valves_unset_field(url, token, "functions", item_id, key)
|
|
432
|
+
|
|
433
|
+
# Wrappers — per-user valves (`valves-user*`)
|
|
434
|
+
def tools_valves_user_get(url, token, item_id): _valves_get(url, token, "tools", item_id, "/user")
|
|
435
|
+
def tools_valves_user_spec(url, token, item_id): _valves_spec(url, token, "tools", item_id, "/user")
|
|
436
|
+
def tools_valves_user_set(url, token, item_id, json_path): _valves_set(url, token, "tools", item_id, json_path, "/user")
|
|
437
|
+
def tools_valves_user_set_field(url, token, item_id, key, value):_valves_set_field(url, token, "tools", item_id, key, value, "/user")
|
|
438
|
+
def tools_valves_user_unset_field(url, token, item_id, key): _valves_unset_field(url, token, "tools", item_id, key, "/user")
|
|
439
|
+
|
|
440
|
+
def functions_valves_user_get(url, token, item_id): _valves_get(url, token, "functions", item_id, "/user")
|
|
441
|
+
def functions_valves_user_spec(url, token, item_id): _valves_spec(url, token, "functions", item_id, "/user")
|
|
442
|
+
def functions_valves_user_set(url, token, item_id, json_path): _valves_set(url, token, "functions", item_id, json_path, "/user")
|
|
443
|
+
def functions_valves_user_set_field(url, token, item_id, key, value):_valves_set_field(url, token, "functions", item_id, key, value, "/user")
|
|
444
|
+
def functions_valves_user_unset_field(url, token, item_id, key): _valves_unset_field(url, token, "functions", item_id, key, "/user")
|
|
445
|
+
|
|
446
|
+
|
|
372
447
|
class SkillsResource(Resource):
|
|
373
448
|
"""Skills use frontmatter and have grant/revoke commands."""
|
|
374
449
|
|
|
@@ -614,9 +689,20 @@ def models_pull_all(url, token, out_dir="."):
|
|
|
614
689
|
# ── knowledge (special: files subresource, file/remove is destructive) ─
|
|
615
690
|
|
|
616
691
|
def knowledge_list(url, token):
|
|
692
|
+
kbs = []
|
|
693
|
+
page = 1
|
|
617
694
|
with httpx.Client(timeout=TIMEOUT) as c:
|
|
618
|
-
|
|
619
|
-
|
|
695
|
+
while True:
|
|
696
|
+
data = _get(c, url, "/api/v1/knowledge/", token, params={"page": page}).json()
|
|
697
|
+
batch = data["items"] if isinstance(data, dict) else data
|
|
698
|
+
if not batch:
|
|
699
|
+
break
|
|
700
|
+
kbs.extend(batch)
|
|
701
|
+
if isinstance(data, dict):
|
|
702
|
+
if len(kbs) >= data.get("total", 0): break
|
|
703
|
+
else:
|
|
704
|
+
break
|
|
705
|
+
page += 1
|
|
620
706
|
rows = [{"id": k.get("id",""), "name": k.get("name",""),
|
|
621
707
|
"desc": (k.get("description") or "")[:50]}
|
|
622
708
|
for k in sorted(kbs, key=lambda k: k.get("name",""))]
|
|
@@ -667,12 +753,25 @@ def knowledge_remove_file(url, token, kb_id, file_id):
|
|
|
667
753
|
# ── files ─────────────────────────────────────────────────────────────
|
|
668
754
|
|
|
669
755
|
def files_list(url, token):
|
|
756
|
+
rows = []
|
|
757
|
+
page = 1
|
|
670
758
|
with httpx.Client(timeout=TIMEOUT) as c:
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
759
|
+
while True:
|
|
760
|
+
data = _get(c, url, "/api/v1/files/", token,
|
|
761
|
+
params={"page": page, "content": "false"}).json()
|
|
762
|
+
# OWUI >= 0.9 returns {items, total}; older versions return a bare list.
|
|
763
|
+
batch = data["items"] if isinstance(data, dict) else data
|
|
764
|
+
if not batch:
|
|
765
|
+
break
|
|
766
|
+
rows.extend({"id": f.get("id",""),
|
|
767
|
+
"name": (f.get("meta") or {}).get("name") or f.get("filename",""),
|
|
768
|
+
"size": str((f.get("meta") or {}).get("size","?"))}
|
|
769
|
+
for f in batch)
|
|
770
|
+
if isinstance(data, dict):
|
|
771
|
+
if len(rows) >= data.get("total", 0): break
|
|
772
|
+
else:
|
|
773
|
+
break # bare-list response is unpaginated
|
|
774
|
+
page += 1
|
|
676
775
|
out_table(rows, [("FILE_ID","id",36), ("NAME","name",30), ("SIZE","size",8)])
|
|
677
776
|
|
|
678
777
|
def files_show(url, token, file_id):
|
|
@@ -1037,6 +1136,26 @@ for res in [tools_res, functions_res, skills_res]:
|
|
|
1037
1136
|
|
|
1038
1137
|
# Register special resources
|
|
1039
1138
|
COMMANDS.update({
|
|
1139
|
+
("tools", "valves"): (tools_valves_get, "<id>", (1, 1)),
|
|
1140
|
+
("tools", "valves-spec"): (tools_valves_spec, "<id>", (1, 1)),
|
|
1141
|
+
("tools", "valves-set"): (tools_valves_set, "<id> <valves.json>", (2, 2)),
|
|
1142
|
+
("tools", "valves-set-field"): (tools_valves_set_field, "<id> <key> <value>", (3, 3)),
|
|
1143
|
+
("tools", "valves-unset-field"):(tools_valves_unset_field, "<id> <key>", (2, 2)),
|
|
1144
|
+
("tools", "valves-user"): (tools_valves_user_get, "<id>", (1, 1)),
|
|
1145
|
+
("tools", "valves-user-spec"): (tools_valves_user_spec, "<id>", (1, 1)),
|
|
1146
|
+
("tools", "valves-user-set"): (tools_valves_user_set, "<id> <valves.json>", (2, 2)),
|
|
1147
|
+
("tools", "valves-user-set-field"): (tools_valves_user_set_field, "<id> <key> <value>", (3, 3)),
|
|
1148
|
+
("tools", "valves-user-unset-field"):(tools_valves_user_unset_field, "<id> <key>", (2, 2)),
|
|
1149
|
+
("functions", "valves"): (functions_valves_get, "<id>", (1, 1)),
|
|
1150
|
+
("functions", "valves-spec"): (functions_valves_spec, "<id>", (1, 1)),
|
|
1151
|
+
("functions", "valves-set"): (functions_valves_set, "<id> <valves.json>", (2, 2)),
|
|
1152
|
+
("functions", "valves-set-field"): (functions_valves_set_field, "<id> <key> <value>", (3, 3)),
|
|
1153
|
+
("functions", "valves-unset-field"):(functions_valves_unset_field, "<id> <key>", (2, 2)),
|
|
1154
|
+
("functions", "valves-user"): (functions_valves_user_get, "<id>", (1, 1)),
|
|
1155
|
+
("functions", "valves-user-spec"): (functions_valves_user_spec, "<id>", (1, 1)),
|
|
1156
|
+
("functions", "valves-user-set"): (functions_valves_user_set, "<id> <valves.json>", (2, 2)),
|
|
1157
|
+
("functions", "valves-user-set-field"): (functions_valves_user_set_field, "<id> <key> <value>", (3, 3)),
|
|
1158
|
+
("functions", "valves-user-unset-field"):(functions_valves_user_unset_field, "<id> <key>", (2, 2)),
|
|
1040
1159
|
("models", "list"): (models_list, "", (0, 0)),
|
|
1041
1160
|
("models", "show"): (models_show, "<id>", (1, 1)),
|
|
1042
1161
|
("models", "create"): (models_create, "<model.json>", (1, 1)),
|
|
@@ -1130,7 +1249,12 @@ def main():
|
|
|
1130
1249
|
resource, command = args[0], args[1]
|
|
1131
1250
|
key = (resource, command)
|
|
1132
1251
|
|
|
1252
|
+
# Subcommands are plural (chats, models, etc.) to mirror the OWUI API
|
|
1253
|
+
# paths (/api/v1/chats/, /api/v1/models, ...), not typical CLI convention.
|
|
1133
1254
|
if key not in COMMANDS:
|
|
1255
|
+
plural = resource + "s"
|
|
1256
|
+
if (plural, command) in COMMANDS:
|
|
1257
|
+
die(f"resources are plural: use '{plural} {command}' not '{resource} {command}'")
|
|
1134
1258
|
die(f"unknown: {resource} {command}")
|
|
1135
1259
|
|
|
1136
1260
|
fn, arg_spec, (min_args, max_args) = COMMANDS[key]
|
owui_cli-0.5.0/uv.lock
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 2
|
|
3
|
+
requires-python = ">=3.11"
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "anyio"
|
|
7
|
+
version = "4.13.0"
|
|
8
|
+
source = { registry = "https://pypi.org/simple" }
|
|
9
|
+
dependencies = [
|
|
10
|
+
{ name = "idna" },
|
|
11
|
+
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
|
12
|
+
]
|
|
13
|
+
sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622, upload-time = "2026-03-24T12:59:09.671Z" }
|
|
14
|
+
wheels = [
|
|
15
|
+
{ url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" },
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[[package]]
|
|
19
|
+
name = "certifi"
|
|
20
|
+
version = "2026.2.25"
|
|
21
|
+
source = { registry = "https://pypi.org/simple" }
|
|
22
|
+
sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" }
|
|
23
|
+
wheels = [
|
|
24
|
+
{ url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" },
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[[package]]
|
|
28
|
+
name = "h11"
|
|
29
|
+
version = "0.16.0"
|
|
30
|
+
source = { registry = "https://pypi.org/simple" }
|
|
31
|
+
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
|
|
32
|
+
wheels = [
|
|
33
|
+
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[[package]]
|
|
37
|
+
name = "httpcore"
|
|
38
|
+
version = "1.0.9"
|
|
39
|
+
source = { registry = "https://pypi.org/simple" }
|
|
40
|
+
dependencies = [
|
|
41
|
+
{ name = "certifi" },
|
|
42
|
+
{ name = "h11" },
|
|
43
|
+
]
|
|
44
|
+
sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
|
|
45
|
+
wheels = [
|
|
46
|
+
{ url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[[package]]
|
|
50
|
+
name = "httpx"
|
|
51
|
+
version = "0.28.1"
|
|
52
|
+
source = { registry = "https://pypi.org/simple" }
|
|
53
|
+
dependencies = [
|
|
54
|
+
{ name = "anyio" },
|
|
55
|
+
{ name = "certifi" },
|
|
56
|
+
{ name = "httpcore" },
|
|
57
|
+
{ name = "idna" },
|
|
58
|
+
]
|
|
59
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
|
|
60
|
+
wheels = [
|
|
61
|
+
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[[package]]
|
|
65
|
+
name = "idna"
|
|
66
|
+
version = "3.11"
|
|
67
|
+
source = { registry = "https://pypi.org/simple" }
|
|
68
|
+
sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" }
|
|
69
|
+
wheels = [
|
|
70
|
+
{ url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[[package]]
|
|
74
|
+
name = "owui-cli"
|
|
75
|
+
version = "0.2.0"
|
|
76
|
+
source = { editable = "." }
|
|
77
|
+
dependencies = [
|
|
78
|
+
{ name = "httpx" },
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
[package.metadata]
|
|
82
|
+
requires-dist = [{ name = "httpx", specifier = ">=0.27" }]
|
|
83
|
+
|
|
84
|
+
[[package]]
|
|
85
|
+
name = "typing-extensions"
|
|
86
|
+
version = "4.15.0"
|
|
87
|
+
source = { registry = "https://pypi.org/simple" }
|
|
88
|
+
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
|
89
|
+
wheels = [
|
|
90
|
+
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
|
91
|
+
]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|