llms-py 2.0.4__py3-none-any.whl → 2.0.5__py3-none-any.whl

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.
Files changed (31) hide show
  1. llms.py +170 -40
  2. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/app.css +1 -0
  3. {llms_py-2.0.4.dist-info → llms_py-2.0.5.dist-info}/METADATA +1 -1
  4. llms_py-2.0.5.dist-info/RECORD +30 -0
  5. llms_py-2.0.4.dist-info/RECORD +0 -30
  6. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/index.html +0 -0
  7. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/llms.json +0 -0
  8. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/requirements.txt +0 -0
  9. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/App.mjs +0 -0
  10. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/ChatPrompt.mjs +0 -0
  11. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/Main.mjs +0 -0
  12. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/Recents.mjs +0 -0
  13. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/Sidebar.mjs +0 -0
  14. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/fav.svg +0 -0
  15. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/lib/highlight.min.mjs +0 -0
  16. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/lib/idb.min.mjs +0 -0
  17. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/lib/marked.min.mjs +0 -0
  18. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/lib/servicestack-client.min.mjs +0 -0
  19. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/lib/servicestack-vue.min.mjs +0 -0
  20. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/lib/vue-router.min.mjs +0 -0
  21. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/lib/vue.min.mjs +0 -0
  22. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/markdown.mjs +0 -0
  23. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/tailwind.input.css +0 -0
  24. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/threadStore.mjs +0 -0
  25. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/typography.css +0 -0
  26. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui/utils.mjs +0 -0
  27. {llms_py-2.0.4.data → llms_py-2.0.5.data}/data/ui.json +0 -0
  28. {llms_py-2.0.4.dist-info → llms_py-2.0.5.dist-info}/WHEEL +0 -0
  29. {llms_py-2.0.4.dist-info → llms_py-2.0.5.dist-info}/entry_points.txt +0 -0
  30. {llms_py-2.0.4.dist-info → llms_py-2.0.5.dist-info}/licenses/LICENSE +0 -0
  31. {llms_py-2.0.4.dist-info → llms_py-2.0.5.dist-info}/top_level.txt +0 -0
llms.py CHANGED
@@ -12,6 +12,8 @@ import subprocess
12
12
  import base64
13
13
  import mimetypes
14
14
  import traceback
15
+ import sys
16
+ import site
15
17
 
16
18
  import aiohttp
17
19
  from aiohttp import web
@@ -19,7 +21,8 @@ from aiohttp import web
19
21
  from pathlib import Path
20
22
  from importlib import resources # Py≥3.9 (pip install importlib_resources for 3.7/3.8)
21
23
 
22
- VERSION = "2.0.4"
24
+ VERSION = "2.0.5"
25
+ _ROOT = None
23
26
  g_config_path = None
24
27
  g_ui_path = None
25
28
  g_config = None
@@ -785,9 +788,117 @@ def disable_provider(provider):
785
788
  save_config(g_config)
786
789
  init_llms(g_config)
787
790
 
791
+ def resolve_root():
792
+ # Try to find the resource root directory
793
+ # When installed as a package, static files may be in different locations
794
+
795
+ # Method 1: Try importlib.resources for package data (Python 3.9+)
796
+ try:
797
+ try:
798
+ # Try to access the package resources
799
+ pkg_files = resources.files("llms")
800
+ # Check if ui directory exists in package resources
801
+ if hasattr(pkg_files, 'is_dir') and (pkg_files / "ui").is_dir():
802
+ _log(f"RESOURCE ROOT (package): {pkg_files}")
803
+ return pkg_files
804
+ except (FileNotFoundError, AttributeError, TypeError):
805
+ # Package doesn't have the resources, try other methods
806
+ pass
807
+ except ImportError:
808
+ # importlib.resources not available (Python < 3.9)
809
+ pass
810
+
811
+ # Method 2: Try to find data files in sys.prefix (where data_files are installed)
812
+ # Get all possible installation directories
813
+ possible_roots = [
814
+ Path(sys.prefix), # Standard installation
815
+ Path(sys.prefix) / "share", # Some distributions
816
+ Path(sys.base_prefix), # Virtual environments
817
+ Path(sys.base_prefix) / "share",
818
+ ]
819
+
820
+ # Add site-packages directories
821
+ for site_dir in site.getsitepackages():
822
+ possible_roots.extend([
823
+ Path(site_dir),
824
+ Path(site_dir).parent,
825
+ Path(site_dir).parent / "share",
826
+ ])
827
+
828
+ # Add user site directory
829
+ try:
830
+ user_site = site.getusersitepackages()
831
+ if user_site:
832
+ possible_roots.extend([
833
+ Path(user_site),
834
+ Path(user_site).parent,
835
+ Path(user_site).parent / "share",
836
+ ])
837
+ except AttributeError:
838
+ pass
839
+
840
+ for root in possible_roots:
841
+ try:
842
+ if root.exists() and (root / "index.html").exists() and (root / "ui").is_dir():
843
+ _log(f"RESOURCE ROOT (data files): {root}")
844
+ return root
845
+ except (OSError, PermissionError):
846
+ continue
847
+
848
+ # Method 3: Development mode - look relative to this file
849
+ # __file__ is *this* module; look in same directory first, then parent
850
+ dev_roots = [
851
+ Path(__file__).resolve().parent, # Same directory as llms.py
852
+ Path(__file__).resolve().parent.parent, # Parent directory (repo root)
853
+ ]
854
+
855
+ for root in dev_roots:
856
+ try:
857
+ if (root / "index.html").exists() and (root / "ui").is_dir():
858
+ _log(f"RESOURCE ROOT (development): {root}")
859
+ return root
860
+ except (OSError, PermissionError):
861
+ continue
862
+
863
+ # Fallback: use the directory containing this file
864
+ from_file = Path(__file__).resolve().parent
865
+ _log(f"RESOURCE ROOT (fallback): {from_file}")
866
+ return from_file
867
+
868
+ def resource_exists(resource_path):
869
+ # Check if resource files exist (handle both Path and Traversable objects)
870
+ try:
871
+ if hasattr(resource_path, 'is_file'):
872
+ return resource_path.is_file()
873
+ else:
874
+ return os.path.exists(resource_path)
875
+ except (OSError, AttributeError):
876
+ pass
877
+
878
+ def read_resource_text(resource_path):
879
+ if hasattr(resource_path, 'read_text'):
880
+ return resource_path.read_text()
881
+ else:
882
+ with open(resource_path, "r") as f:
883
+ return f.read()
884
+
885
+ def read_resource_file_bytes(resource_file):
886
+ try:
887
+ if hasattr(_ROOT, 'joinpath'):
888
+ # importlib.resources Traversable
889
+ index_resource = _ROOT.joinpath(resource_file)
890
+ if index_resource.is_file():
891
+ return index_resource.read_bytes()
892
+ else:
893
+ # Regular Path object
894
+ index_path = _ROOT / resource_file
895
+ if index_path.exists():
896
+ return index_path.read_bytes()
897
+ except (OSError, PermissionError, AttributeError) as e:
898
+ _log(f"Error reading resource bytes: {e}")
788
899
 
789
900
  def main():
790
- global g_verbose, g_default_model, g_logprefix, g_config_path, g_ui_path
901
+ global _ROOT, g_verbose, g_default_model, g_logprefix, g_config_path, g_ui_path
791
902
 
792
903
  parser = argparse.ArgumentParser(description=f"llms v{VERSION}")
793
904
  parser.add_argument('--config', default=None, help='Path to config file', metavar='FILE')
@@ -827,20 +938,14 @@ def main():
827
938
  if cli_args.config is not None:
828
939
  g_config_path = os.path.join(os.path.dirname(__file__), cli_args.config)
829
940
 
830
- try:
831
- from importlib.resources import files
832
- _ROOT = files("llms-py")
833
- _log(f"RESOURCE ROOT: {_ROOT}")
834
- except ModuleNotFoundError:
835
- # package not installed
836
- # __file__ is *this* module; climb two levels to repo root
837
- _ROOT = Path(__file__).resolve().parent.parent / "llms"
838
- _log(f"__file__: {Path(__file__).resolve()}")
839
- _log(f"PATH ROOT: {_ROOT}")
840
-
941
+ _ROOT = resolve_root()
841
942
  if cli_args.root:
842
943
  _ROOT = Path(cli_args.root)
843
944
 
945
+ if not _ROOT:
946
+ print("Resource root not found")
947
+ exit(1)
948
+
844
949
  g_config_path = os.path.join(os.path.dirname(__file__), cli_args.config) if cli_args.config else get_config_path()
845
950
  g_ui_path = get_ui_path()
846
951
 
@@ -865,21 +970,32 @@ def main():
865
970
 
866
971
  if not g_config_path or not os.path.exists(g_config_path):
867
972
  # copy llms.json and ui.json to llms_home
868
- if not os.path.exists(home_config_path) and os.path.exists(resource_config_path):
973
+
974
+ if not os.path.exists(home_config_path) and resource_exists(resource_config_path):
869
975
  llms_home = os.path.dirname(home_config_path)
870
976
  os.makedirs(llms_home, exist_ok=True)
871
- with open(resource_config_path, "r") as f:
872
- config_json = f.read()
977
+
978
+ # Read config from resource (handle both Path and Traversable objects)
979
+ try:
980
+ config_json = read_resource_text(resource_config_path)
873
981
  with open(home_config_path, "w") as f:
874
982
  f.write(config_json)
875
983
  _log(f"Created default config at {home_config_path}")
876
-
877
- if not os.path.exists(home_ui_path) and os.path.exists(resource_ui_path):
878
- with open(resource_ui_path, "r") as f:
879
- ui_json = f.read()
984
+ except (OSError, AttributeError) as e:
985
+ _log(f"Error reading resource config: {e}")
986
+
987
+ # Read UI config from resource
988
+ if not os.path.exists(home_ui_path) and resource_exists(resource_ui_path):
989
+ try:
990
+ ui_json = read_resource_text(resource_ui_path)
880
991
  with open(home_ui_path, "w") as f:
881
992
  f.write(ui_json)
882
993
  _log(f"Created default ui config at {home_ui_path}")
994
+ except (OSError, AttributeError) as e:
995
+ _log(f"Error reading resource ui config: {e}")
996
+
997
+ # Update g_config_path to point to the copied file
998
+ g_config_path = home_config_path
883
999
  else:
884
1000
  print("Config file not found. Create one with --init or use --config <path>")
885
1001
  exit(1)
@@ -964,17 +1080,32 @@ def main():
964
1080
 
965
1081
  async def ui_static(request: web.Request) -> web.Response:
966
1082
  path = Path(request.match_info["path"])
967
- resource = _ROOT / "ui" / path
968
- if not resource.is_file():
969
- raise web.HTTPNotFound
1083
+
970
1084
  try:
971
- resource.relative_to(Path(_ROOT)) # basic directory-traversal guard
972
- except ValueError:
973
- raise web.HTTPBadRequest(text="Invalid path")
974
- content_type, _ = mimetypes.guess_type(resource.name)
975
- if content_type is None:
976
- content_type = "application/octet-stream"
977
- return web.Response(body=resource.read_bytes(), content_type=content_type)
1085
+ # Handle both Path objects and importlib.resources Traversable objects
1086
+ if hasattr(_ROOT, 'joinpath'):
1087
+ # importlib.resources Traversable
1088
+ resource = _ROOT.joinpath("ui").joinpath(str(path))
1089
+ if not resource.is_file():
1090
+ raise web.HTTPNotFound
1091
+ content = resource.read_bytes()
1092
+ else:
1093
+ # Regular Path object
1094
+ resource = _ROOT / "ui" / path
1095
+ if not resource.is_file():
1096
+ raise web.HTTPNotFound
1097
+ try:
1098
+ resource.relative_to(Path(_ROOT)) # basic directory-traversal guard
1099
+ except ValueError:
1100
+ raise web.HTTPBadRequest(text="Invalid path")
1101
+ content = resource.read_bytes()
1102
+
1103
+ content_type, _ = mimetypes.guess_type(str(path))
1104
+ if content_type is None:
1105
+ content_type = "application/octet-stream"
1106
+ return web.Response(body=content, content_type=content_type)
1107
+ except (OSError, PermissionError, AttributeError):
1108
+ raise web.HTTPNotFound
978
1109
 
979
1110
  app.router.add_get("/ui/{path:.*}", ui_static, name="ui_static")
980
1111
 
@@ -983,16 +1114,15 @@ def main():
983
1114
  app.router.add_get('/favicon.ico', not_found_handler)
984
1115
 
985
1116
  # Serve index.html from root
986
- index_path = os.path.join(_ROOT, 'index.html')
987
- if os.path.exists(index_path):
988
- async def index_handler(request):
989
- return web.FileResponse(index_path)
990
- app.router.add_get('/', index_handler)
991
-
992
- # Serve index.html as fallback route (SPA routing)
993
- async def fallback_route_handler(request):
994
- return web.FileResponse(index_path)
995
- app.router.add_route('*', '/{tail:.*}', fallback_route_handler)
1117
+ async def index_handler(request):
1118
+ index_content = read_resource_file_bytes("index.html")
1119
+ if index_content is None:
1120
+ raise web.HTTPNotFound
1121
+ return web.Response(body=index_content, content_type='text/html')
1122
+ app.router.add_get('/', index_handler)
1123
+
1124
+ # Serve index.html as fallback route (SPA routing)
1125
+ app.router.add_route('*', '/{tail:.*}', index_handler)
996
1126
 
997
1127
  if os.path.exists(g_ui_path):
998
1128
  async def ui_json_handler(request):
@@ -135,6 +135,7 @@
135
135
  --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
136
136
  --default-font-family: var(--font-sans);
137
137
  --default-mono-font-family: var(--font-mono);
138
+ --default-ring-color: hsl(var(--ring));
138
139
  }
139
140
  }
140
141
  @layer base {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llms-py
3
- Version: 2.0.4
3
+ Version: 2.0.5
4
4
  Summary: A lightweight CLI tool and OpenAI-compatible server for querying multiple Large Language Model (LLM) providers
5
5
  Home-page: https://github.com/ServiceStack/llms
6
6
  Author: ServiceStack
@@ -0,0 +1,30 @@
1
+ llms.py,sha256=PDRwX-IQYJbIXLGEkzm5J5UOkd26m02ofzQKYt9tmXU,51990
2
+ llms_py-2.0.5.data/data/index.html,sha256=nOgYc7t9QjlbRoy35-W6HpQbEEuD0-O1rkA8j-IYhZ4,2276
3
+ llms_py-2.0.5.data/data/llms.json,sha256=nw9g63Ht15V5h2A9ynx8_1KLLboNrzUN5PTPhPV1lAY,18365
4
+ llms_py-2.0.5.data/data/requirements.txt,sha256=iv-JIaacmTl-hSho3QmphcKnbRRYx1st47yjz_178Ro,8
5
+ llms_py-2.0.5.data/data/ui.json,sha256=iBOmpNeD5-o8AgUa51ymS-KemovJ7bm9J1fnL0nf8jk,134025
6
+ llms_py-2.0.5.data/data/ui/App.mjs,sha256=hXtUjaL3GrcIHieEK3BzIG72OVzrorBBS4RkE1DOGc4,439
7
+ llms_py-2.0.5.data/data/ui/ChatPrompt.mjs,sha256=S_p2h6CJUDMvuetMgauJzS0MkACDw-bWw0FR-YXre_w,17163
8
+ llms_py-2.0.5.data/data/ui/Main.mjs,sha256=8RdjDDCQSwk4wjRolJIkbWvHZHRf1GB9Qj8zN1lyuHo,26714
9
+ llms_py-2.0.5.data/data/ui/Recents.mjs,sha256=cA9njbuOXeTWWagiArmswwgXuAV36ExhXGPE6sZrffY,7459
10
+ llms_py-2.0.5.data/data/ui/Sidebar.mjs,sha256=TUyicSr8MRpLoUZoQ6neBG0PwhFcz2BhIQVwdaKSuo8,10870
11
+ llms_py-2.0.5.data/data/ui/app.css,sha256=uNXiu7lQ_1pmqK4ElFKuRAoxjNJE6WN91Ob63NvbG-c,92485
12
+ llms_py-2.0.5.data/data/ui/fav.svg,sha256=_R6MFeXl6wBFT0lqcUxYQIDWgm246YH_3hSTW0oO8qw,734
13
+ llms_py-2.0.5.data/data/ui/markdown.mjs,sha256=YeOnS7bPM0oyXHMVsgwobLYKgqzRNjrmBJ8NIrhU9Z8,6096
14
+ llms_py-2.0.5.data/data/ui/tailwind.input.css,sha256=31O3JLwvf8qPoEmKAGMPXEOgVRNcP7i7Y0DH_xw6qsg,10612
15
+ llms_py-2.0.5.data/data/ui/threadStore.mjs,sha256=bL-yPx1ShU7lBJrzgMHI7K-ZtzcuWDSjtSf--nn0DVk,7199
16
+ llms_py-2.0.5.data/data/ui/typography.css,sha256=XtIOwBvWujwTOSOuF-zs5x3xEJLnmg27q2lmv4JyLm4,16127
17
+ llms_py-2.0.5.data/data/ui/utils.mjs,sha256=exyN-YohPvcGSR-IrjYUj0t3_RDIrnaJgSvkHA2bIRk,4016
18
+ llms_py-2.0.5.data/data/ui/lib/highlight.min.mjs,sha256=sG7wq8bF-IKkfie7S4QSyh5DdHBRf0NqQxMOEH8-MT0,127458
19
+ llms_py-2.0.5.data/data/ui/lib/idb.min.mjs,sha256=CeTXyV4I_pB5vnibvJuyXdMs0iVF2ZL0Z7cdm3w_QaI,3853
20
+ llms_py-2.0.5.data/data/ui/lib/marked.min.mjs,sha256=QRHb_VZugcBJRD2EP6gYlVFEsJw5C2fQ8ImMf_pA2_s,39488
21
+ llms_py-2.0.5.data/data/ui/lib/servicestack-client.min.mjs,sha256=UVafVbzhJ_0N2lzv7rlzIbzwnWpoqXxGk3N3FSKgOOc,54534
22
+ llms_py-2.0.5.data/data/ui/lib/servicestack-vue.min.mjs,sha256=oqeaDTgQxCi4gLt9X0J8UwIJgW9FWCV0d-Iiak6k-qI,218926
23
+ llms_py-2.0.5.data/data/ui/lib/vue-router.min.mjs,sha256=fR30GHoXI1u81zyZ26YEU105pZgbbAKSXbpnzFKIxls,30418
24
+ llms_py-2.0.5.data/data/ui/lib/vue.min.mjs,sha256=iXh97m5hotl0eFllb3aoasQTImvp7mQoRJ_0HoxmZkw,163811
25
+ llms_py-2.0.5.dist-info/licenses/LICENSE,sha256=rRryrddGfVftpde-rmAZpW0R8IJihqJ8t8wpfDXoKiQ,1549
26
+ llms_py-2.0.5.dist-info/METADATA,sha256=LRw_cBuhHltQJO6xEPpyENSUm1nE0ckfK1RqRU0jsNI,23652
27
+ llms_py-2.0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
+ llms_py-2.0.5.dist-info/entry_points.txt,sha256=svUoTt28bIJeo6Mb1ffDBLyzhD90DWtFbfp0ShyRCgU,35
29
+ llms_py-2.0.5.dist-info/top_level.txt,sha256=gC7hk9BKSeog8gyg-EM_g2gxm1mKHwFRfK-10BxOsa4,5
30
+ llms_py-2.0.5.dist-info/RECORD,,
@@ -1,30 +0,0 @@
1
- llms.py,sha256=ia7cCcAEXBpBu484lyKilPHiZNbPE4ob8REHXMbQ9NM,47266
2
- llms_py-2.0.4.data/data/index.html,sha256=nOgYc7t9QjlbRoy35-W6HpQbEEuD0-O1rkA8j-IYhZ4,2276
3
- llms_py-2.0.4.data/data/llms.json,sha256=nw9g63Ht15V5h2A9ynx8_1KLLboNrzUN5PTPhPV1lAY,18365
4
- llms_py-2.0.4.data/data/requirements.txt,sha256=iv-JIaacmTl-hSho3QmphcKnbRRYx1st47yjz_178Ro,8
5
- llms_py-2.0.4.data/data/ui.json,sha256=iBOmpNeD5-o8AgUa51ymS-KemovJ7bm9J1fnL0nf8jk,134025
6
- llms_py-2.0.4.data/data/ui/App.mjs,sha256=hXtUjaL3GrcIHieEK3BzIG72OVzrorBBS4RkE1DOGc4,439
7
- llms_py-2.0.4.data/data/ui/ChatPrompt.mjs,sha256=S_p2h6CJUDMvuetMgauJzS0MkACDw-bWw0FR-YXre_w,17163
8
- llms_py-2.0.4.data/data/ui/Main.mjs,sha256=8RdjDDCQSwk4wjRolJIkbWvHZHRf1GB9Qj8zN1lyuHo,26714
9
- llms_py-2.0.4.data/data/ui/Recents.mjs,sha256=cA9njbuOXeTWWagiArmswwgXuAV36ExhXGPE6sZrffY,7459
10
- llms_py-2.0.4.data/data/ui/Sidebar.mjs,sha256=TUyicSr8MRpLoUZoQ6neBG0PwhFcz2BhIQVwdaKSuo8,10870
11
- llms_py-2.0.4.data/data/ui/app.css,sha256=E_UzowGq5lYcvSnHy-KgSsQV_LB6HPr989lpp6YHlug,92441
12
- llms_py-2.0.4.data/data/ui/fav.svg,sha256=_R6MFeXl6wBFT0lqcUxYQIDWgm246YH_3hSTW0oO8qw,734
13
- llms_py-2.0.4.data/data/ui/markdown.mjs,sha256=YeOnS7bPM0oyXHMVsgwobLYKgqzRNjrmBJ8NIrhU9Z8,6096
14
- llms_py-2.0.4.data/data/ui/tailwind.input.css,sha256=31O3JLwvf8qPoEmKAGMPXEOgVRNcP7i7Y0DH_xw6qsg,10612
15
- llms_py-2.0.4.data/data/ui/threadStore.mjs,sha256=bL-yPx1ShU7lBJrzgMHI7K-ZtzcuWDSjtSf--nn0DVk,7199
16
- llms_py-2.0.4.data/data/ui/typography.css,sha256=XtIOwBvWujwTOSOuF-zs5x3xEJLnmg27q2lmv4JyLm4,16127
17
- llms_py-2.0.4.data/data/ui/utils.mjs,sha256=exyN-YohPvcGSR-IrjYUj0t3_RDIrnaJgSvkHA2bIRk,4016
18
- llms_py-2.0.4.data/data/ui/lib/highlight.min.mjs,sha256=sG7wq8bF-IKkfie7S4QSyh5DdHBRf0NqQxMOEH8-MT0,127458
19
- llms_py-2.0.4.data/data/ui/lib/idb.min.mjs,sha256=CeTXyV4I_pB5vnibvJuyXdMs0iVF2ZL0Z7cdm3w_QaI,3853
20
- llms_py-2.0.4.data/data/ui/lib/marked.min.mjs,sha256=QRHb_VZugcBJRD2EP6gYlVFEsJw5C2fQ8ImMf_pA2_s,39488
21
- llms_py-2.0.4.data/data/ui/lib/servicestack-client.min.mjs,sha256=UVafVbzhJ_0N2lzv7rlzIbzwnWpoqXxGk3N3FSKgOOc,54534
22
- llms_py-2.0.4.data/data/ui/lib/servicestack-vue.min.mjs,sha256=oqeaDTgQxCi4gLt9X0J8UwIJgW9FWCV0d-Iiak6k-qI,218926
23
- llms_py-2.0.4.data/data/ui/lib/vue-router.min.mjs,sha256=fR30GHoXI1u81zyZ26YEU105pZgbbAKSXbpnzFKIxls,30418
24
- llms_py-2.0.4.data/data/ui/lib/vue.min.mjs,sha256=iXh97m5hotl0eFllb3aoasQTImvp7mQoRJ_0HoxmZkw,163811
25
- llms_py-2.0.4.dist-info/licenses/LICENSE,sha256=rRryrddGfVftpde-rmAZpW0R8IJihqJ8t8wpfDXoKiQ,1549
26
- llms_py-2.0.4.dist-info/METADATA,sha256=RNRMepk75YiBKVOMATos5VPgXGWkdpfGSu4eqA1hR14,23652
27
- llms_py-2.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
- llms_py-2.0.4.dist-info/entry_points.txt,sha256=svUoTt28bIJeo6Mb1ffDBLyzhD90DWtFbfp0ShyRCgU,35
29
- llms_py-2.0.4.dist-info/top_level.txt,sha256=gC7hk9BKSeog8gyg-EM_g2gxm1mKHwFRfK-10BxOsa4,5
30
- llms_py-2.0.4.dist-info/RECORD,,
File without changes