soliplex 0.78__tar.gz → 0.78.1__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.
- {soliplex-0.78/src/soliplex.egg-info → soliplex-0.78.1}/PKG-INFO +1 -1
- {soliplex-0.78 → soliplex-0.78.1}/pyproject.toml +1 -1
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/cli/audit.py +75 -41
- {soliplex-0.78 → soliplex-0.78.1/src/soliplex.egg-info}/PKG-INFO +1 -1
- {soliplex-0.78 → soliplex-0.78.1}/LICENSE +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/MANIFEST.in +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/README.md +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/example/skills/bare-bones/SKILL.md +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/example/skills/stanzas/SKILL.md +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/setup.cfg +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/skills/soliplex-docs/SKILL.md +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/agents.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/agui/__init__.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/agui/parser.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/agui/persistence.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/agui/schema.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/agui/util.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/authn.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/authz/__init__.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/authz/persistence.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/authz/schema.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/capabilities/filesystem.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/capabilities/rag_audit.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/cli/admin_users.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/cli/ask.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/cli/cli_util.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/cli/main.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/cli/ollama.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/cli/room_authz.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/cli/serve.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/cli/types.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/completions.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/__init__.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/_utils.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/agents.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/agui.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/authsystem.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/completions.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/exceptions.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/installation.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/logfire.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/meta.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/middleware.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/quizzes.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/rag.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/rooms.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/routing.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/secrets.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/skills.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/config/tools.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/examples.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/installation.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/log_ingest.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/loggers.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/main.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/mcp_auth.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/mcp_client.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/mcp_server.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/models.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/ollama.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/quizzes.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/rag_audit.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/sandbox_audit.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/secrets.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/skills/bwrap_sandbox/SKILL.md +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/skills/bwrap_sandbox/__init__.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/titles.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/tools/__init__.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/tools/agui_run_feedback.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/tools/file_uploads.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/tools/rag.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/tui/cli.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/tui/main.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/tui/rest_api.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/tui/serve.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/util.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/__init__.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/agui.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/authn.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/authz.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/completions.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/installation.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/log_ingest.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/quizzes.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/room_file_uploads.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/rooms.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/sandbox_workdirs.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/stats.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/streaming.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex/views/thread_file_uploads.py +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex.egg-info/SOURCES.txt +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex.egg-info/dependency_links.txt +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex.egg-info/entry_points.txt +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex.egg-info/requires.txt +0 -0
- {soliplex-0.78 → soliplex-0.78.1}/src/soliplex.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: soliplex
|
|
3
|
-
Version: 0.78
|
|
3
|
+
Version: 0.78.1
|
|
4
4
|
Summary: An AI-powered Retrieval-Augmented Generation (RAG) system with a modern web interface.
|
|
5
5
|
Author-email: Enfold <info@enfoldsystems.net>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "soliplex"
|
|
7
|
-
version = "0.78"
|
|
7
|
+
version = "0.78.1"
|
|
8
8
|
description = "An AI-powered Retrieval-Augmented Generation (RAG) system with a modern web interface."
|
|
9
9
|
authors = [{ name = "Enfold", email = "info@enfoldsystems.net" }]
|
|
10
10
|
readme = "README.md"
|
|
@@ -568,22 +568,39 @@ async def _list_admin_discriminators(dburi):
|
|
|
568
568
|
return await policy.list_admin_user_discriminators()
|
|
569
569
|
|
|
570
570
|
|
|
571
|
-
def
|
|
572
|
-
"""
|
|
573
|
-
|
|
571
|
+
def _room_policies(the_installation) -> tuple[list, str | None]:
|
|
572
|
+
"""Return ``(policies, error)`` for the stored room policies.
|
|
573
|
+
|
|
574
|
+
``policies`` holds the unchecked policy models read via
|
|
575
|
+
'RoomAuthorizationPolicy.list_room_policies' and ``error`` is ``None``
|
|
576
|
+
on success. A RAM-based authz DB can hold no persisted rows, so it
|
|
577
|
+
short-circuits to ``([], None)`` without touching the database.
|
|
578
|
+
|
|
579
|
+
When the database itself cannot be reached -- e.g. its DBURI names a
|
|
580
|
+
Postgres server that isn't listening -- ``policies`` is empty and
|
|
581
|
+
``error`` carries the exception message, so the audit can report the
|
|
582
|
+
unreachable DB instead of dying on the traceback.
|
|
583
|
+
"""
|
|
574
584
|
dburi = the_installation.authorization_dburi_async
|
|
575
585
|
|
|
576
586
|
if dburi in cli_util._RAM_DBURIS:
|
|
577
|
-
return
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
}
|
|
587
|
+
return [], None
|
|
588
|
+
|
|
589
|
+
try:
|
|
590
|
+
return list(asyncio.run(_list_room_policies(dburi))), None
|
|
591
|
+
except Exception as exc:
|
|
592
|
+
return [], f"{type(exc).__name__}: {exc}"
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
def _room_authz_groups(the_installation, room_policies):
|
|
596
|
+
"""Bucket configured rooms by authorization state; collect stale rows.
|
|
597
|
+
|
|
598
|
+
``room_policies`` is the policy list from '_room_policies'.
|
|
599
|
+
"""
|
|
600
|
+
configured = sorted(the_installation._config.room_configs)
|
|
583
601
|
|
|
584
602
|
policies = {
|
|
585
|
-
policy.room_id: policy.default_allow_deny
|
|
586
|
-
for policy in asyncio.run(_list_room_policies(dburi))
|
|
603
|
+
policy.room_id: policy.default_allow_deny for policy in room_policies
|
|
587
604
|
}
|
|
588
605
|
|
|
589
606
|
configured_set = set(configured)
|
|
@@ -606,26 +623,21 @@ def _room_authz_groups(the_installation):
|
|
|
606
623
|
}
|
|
607
624
|
|
|
608
625
|
|
|
609
|
-
def _invalid_acl_json_paths(
|
|
626
|
+
def _invalid_acl_json_paths(room_policies) -> dict:
|
|
610
627
|
"""Collect ACL entries whose stored 'json_path' fails to validate.
|
|
611
628
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
629
|
+
``room_policies`` is the policy list from '_room_policies' -- the
|
|
630
|
+
unchecked models, which tolerate entries that would fail
|
|
631
|
+
'policy.as_model'. Each surfaced 'json_path' is re-validated against
|
|
632
|
+
the currently-loaded JSONPath environment. Typically an entry lands
|
|
633
|
+
here when it was authored under a meta-config that registered filter
|
|
634
|
+
functions which are no longer present.
|
|
618
635
|
|
|
619
636
|
Returns a dict mapping 'room_id' to a list of '(json_path, error)'
|
|
620
|
-
pairs.
|
|
637
|
+
pairs.
|
|
621
638
|
"""
|
|
622
|
-
dburi = the_installation.authorization_dburi_async
|
|
623
|
-
|
|
624
|
-
if dburi in cli_util._RAM_DBURIS:
|
|
625
|
-
return {}
|
|
626
|
-
|
|
627
639
|
invalid: dict = {}
|
|
628
|
-
for policy in
|
|
640
|
+
for policy in room_policies:
|
|
629
641
|
for entry in policy.acl_entries:
|
|
630
642
|
if entry.json_path is None:
|
|
631
643
|
continue
|
|
@@ -651,7 +663,13 @@ def _audit_room_authz_section(
|
|
|
651
663
|
tc_rule("Configured rooms by authorization state")
|
|
652
664
|
tc_line()
|
|
653
665
|
|
|
654
|
-
|
|
666
|
+
room_policies, db_error = _room_policies(the_installation)
|
|
667
|
+
if db_error is not None:
|
|
668
|
+
tc_print(f"ERROR: authorization database unreachable: {db_error}")
|
|
669
|
+
tc_line()
|
|
670
|
+
return {"room_authz": {"unreachable": db_error}}
|
|
671
|
+
|
|
672
|
+
groups = _room_authz_groups(the_installation, room_policies)
|
|
655
673
|
|
|
656
674
|
for label, room_ids in (
|
|
657
675
|
(
|
|
@@ -677,7 +695,7 @@ def _audit_room_authz_section(
|
|
|
677
695
|
tc_print(" (none)")
|
|
678
696
|
tc_line()
|
|
679
697
|
|
|
680
|
-
invalid_acls = _invalid_acl_json_paths(
|
|
698
|
+
invalid_acls = _invalid_acl_json_paths(room_policies)
|
|
681
699
|
tc_print("ACL entries with invalid JSONPath:")
|
|
682
700
|
if invalid_acls:
|
|
683
701
|
for room_id in sorted(invalid_acls):
|
|
@@ -699,36 +717,47 @@ def _audit_room_authz_section(
|
|
|
699
717
|
return errors
|
|
700
718
|
|
|
701
719
|
|
|
702
|
-
def _admin_user_json_paths(
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
720
|
+
def _admin_user_json_paths(
|
|
721
|
+
the_installation,
|
|
722
|
+
) -> tuple[list[str], str | None]:
|
|
723
|
+
"""Return ``(json_paths, error)`` for the stored admin rows.
|
|
724
|
+
|
|
725
|
+
``json_paths`` holds every stored 'AdminUser.json_path', in insertion
|
|
726
|
+
order, read via 'AdminUserPolicy.list_admin_user_discriminators';
|
|
727
|
+
``error`` is ``None`` on success. A RAM-based authz DB can hold no
|
|
728
|
+
persisted rows, so it short-circuits to ``([], None)`` without
|
|
729
|
+
touching the database.
|
|
730
|
+
|
|
731
|
+
When the database itself cannot be reached -- e.g. its DBURI names a
|
|
732
|
+
Postgres server that isn't listening -- ``json_paths`` is empty and
|
|
733
|
+
``error`` carries the exception message, so the audit can report the
|
|
734
|
+
unreachable DB instead of dying on the traceback.
|
|
709
735
|
"""
|
|
710
736
|
dburi = the_installation.authorization_dburi_async
|
|
711
737
|
|
|
712
738
|
if dburi in cli_util._RAM_DBURIS:
|
|
713
|
-
return []
|
|
739
|
+
return [], None
|
|
714
740
|
|
|
715
|
-
|
|
741
|
+
try:
|
|
742
|
+
return list(asyncio.run(_list_admin_discriminators(dburi))), None
|
|
743
|
+
except Exception as exc:
|
|
744
|
+
return [], f"{type(exc).__name__}: {exc}"
|
|
716
745
|
|
|
717
746
|
|
|
718
747
|
def _invalid_admin_user_json_paths(
|
|
719
|
-
|
|
748
|
+
json_paths,
|
|
720
749
|
) -> list[tuple[str, str]]:
|
|
721
750
|
"""Collect admin entries whose 'json_path' fails to validate.
|
|
722
751
|
|
|
723
752
|
Same intent as '_invalid_acl_json_paths' but for the 'AdminUser'
|
|
724
753
|
table: a row typically lands here when it was authored under a
|
|
725
754
|
meta-config that registered filter functions which are no longer
|
|
726
|
-
present.
|
|
755
|
+
present. ``json_paths`` is the list from '_admin_user_json_paths'.
|
|
727
756
|
|
|
728
757
|
Returns a list of '(json_path, error)' pairs.
|
|
729
758
|
"""
|
|
730
759
|
invalid: list[tuple[str, str]] = []
|
|
731
|
-
for json_path in
|
|
760
|
+
for json_path in json_paths:
|
|
732
761
|
try:
|
|
733
762
|
authz.validate_json_path(json_path)
|
|
734
763
|
except authz.InvalidJSONPath as exc:
|
|
@@ -749,7 +778,12 @@ def _audit_admin_users_section(
|
|
|
749
778
|
tc_rule("Configured admin users")
|
|
750
779
|
tc_line()
|
|
751
780
|
|
|
752
|
-
json_paths = _admin_user_json_paths(the_installation)
|
|
781
|
+
json_paths, db_error = _admin_user_json_paths(the_installation)
|
|
782
|
+
if db_error is not None:
|
|
783
|
+
tc_print(f"ERROR: authorization database unreachable: {db_error}")
|
|
784
|
+
tc_line()
|
|
785
|
+
return {"admin_users": {"unreachable": db_error}}
|
|
786
|
+
|
|
753
787
|
tc_print(f"Admin users ({len(json_paths)}):")
|
|
754
788
|
if json_paths:
|
|
755
789
|
for json_path in json_paths:
|
|
@@ -763,7 +797,7 @@ def _audit_admin_users_section(
|
|
|
763
797
|
tc_print(" (none)")
|
|
764
798
|
tc_line()
|
|
765
799
|
|
|
766
|
-
invalid = _invalid_admin_user_json_paths(
|
|
800
|
+
invalid = _invalid_admin_user_json_paths(json_paths)
|
|
767
801
|
tc_print("Admin users with invalid JSONPath:")
|
|
768
802
|
if invalid:
|
|
769
803
|
for json_path, error in invalid:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: soliplex
|
|
3
|
-
Version: 0.78
|
|
3
|
+
Version: 0.78.1
|
|
4
4
|
Summary: An AI-powered Retrieval-Augmented Generation (RAG) system with a modern web interface.
|
|
5
5
|
Author-email: Enfold <info@enfoldsystems.net>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|