soliplex 0.78.2__tar.gz → 0.79__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.2/src/soliplex.egg-info → soliplex-0.79}/PKG-INFO +3 -3
- {soliplex-0.78.2 → soliplex-0.79}/pyproject.toml +11 -6
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/agui/persistence.py +0 -3
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/agui/util.py +1 -1
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/authz/__init__.py +9 -7
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/authz/schema.py +1 -1
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/cli/audit.py +45 -6
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/agents.py +8 -5
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/authsystem.py +5 -2
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/completions.py +6 -2
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/installation.py +35 -36
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/logfire.py +5 -2
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/quizzes.py +6 -2
- soliplex-0.79/src/soliplex/config/rag.py +508 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/rooms.py +25 -27
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/secrets.py +8 -5
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/skills.py +13 -16
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/tools.py +25 -17
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/examples.py +1 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/loggers.py +59 -4
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/models.py +7 -2
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/quizzes.py +5 -3
- soliplex-0.79/src/soliplex/sandbox_audit.py +164 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/secrets.py +8 -4
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/skills/bwrap_sandbox/__init__.py +125 -85
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/tools/agui_run_feedback.py +1 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/tools/rag.py +5 -5
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/tui/main.py +10 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/log_ingest.py +2 -1
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/rooms.py +31 -6
- {soliplex-0.78.2 → soliplex-0.79/src/soliplex.egg-info}/PKG-INFO +3 -3
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex.egg-info/requires.txt +1 -1
- soliplex-0.78.2/src/soliplex/config/rag.py +0 -198
- soliplex-0.78.2/src/soliplex/sandbox_audit.py +0 -65
- {soliplex-0.78.2 → soliplex-0.79}/LICENSE +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/MANIFEST.in +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/README.md +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/example/skills/bare-bones/SKILL.md +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/example/skills/stanzas/SKILL.md +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/setup.cfg +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/skills/soliplex-docs/SKILL.md +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/agents.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/agui/__init__.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/agui/parser.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/agui/schema.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/authn.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/authz/persistence.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/capabilities/filesystem.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/capabilities/rag_audit.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/cli/admin_users.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/cli/ask.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/cli/cli_util.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/cli/main.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/cli/ollama.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/cli/room_authz.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/cli/serve.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/cli/types.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/completions.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/__init__.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/_utils.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/agui.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/exceptions.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/meta.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/middleware.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/config/routing.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/installation.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/log_ingest.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/main.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/mcp_auth.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/mcp_client.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/mcp_server.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/ollama.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/rag_audit.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/skills/bwrap_sandbox/SKILL.md +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/titles.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/tools/__init__.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/tools/file_uploads.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/tui/cli.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/tui/rest_api.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/tui/serve.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/util.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/__init__.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/agui.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/authn.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/authz.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/completions.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/installation.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/quizzes.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/room_file_uploads.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/sandbox_workdirs.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/stats.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/streaming.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex/views/thread_file_uploads.py +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex.egg-info/SOURCES.txt +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex.egg-info/dependency_links.txt +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex.egg-info/entry_points.txt +0 -0
- {soliplex-0.78.2 → soliplex-0.79}/src/soliplex.egg-info/top_level.txt +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: soliplex
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.79
|
|
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
|
|
7
7
|
Classifier: Operating System :: OS Independent
|
|
8
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.13
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Requires-Dist: ag-ui-protocol<0.1.19,>=0.1.18
|
|
@@ -19,7 +19,7 @@ Requires-Dist: fastapi
|
|
|
19
19
|
Requires-Dist: fastmcp<3.4,>=3.3.0
|
|
20
20
|
Requires-Dist: fakeredis!=2.35.0
|
|
21
21
|
Requires-Dist: greenlet
|
|
22
|
-
Requires-Dist: haiku.rag-slim<0.
|
|
22
|
+
Requires-Dist: haiku.rag-slim<0.83,>=0.82.0
|
|
23
23
|
Requires-Dist: idna>=3.15
|
|
24
24
|
Requires-Dist: itsdangerous
|
|
25
25
|
Requires-Dist: joserfc<1.7,>=1.6.7
|
|
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "soliplex"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.79"
|
|
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"
|
|
11
|
-
requires-python = ">=3.
|
|
11
|
+
requires-python = ">=3.13"
|
|
12
12
|
classifiers = [
|
|
13
13
|
"Programming Language :: Python :: 3",
|
|
14
14
|
"Operating System :: OS Independent",
|
|
@@ -25,7 +25,7 @@ dependencies = [
|
|
|
25
25
|
"fastmcp >= 3.3.0, < 3.4",
|
|
26
26
|
"fakeredis != 2.35.0", # brownbag
|
|
27
27
|
"greenlet",
|
|
28
|
-
"haiku.rag-slim >= 0.
|
|
28
|
+
"haiku.rag-slim >= 0.82.0, < 0.83",
|
|
29
29
|
"idna >= 3.15",
|
|
30
30
|
"itsdangerous",
|
|
31
31
|
"joserfc >= 1.6.7, < 1.7", # CVE-2026-48990
|
|
@@ -84,7 +84,13 @@ pythonpath = [".", "tests/unit"]
|
|
|
84
84
|
python_files = "test_*.py"
|
|
85
85
|
# skip 'tests/functional' by default
|
|
86
86
|
testpaths = ["tests/unit"]
|
|
87
|
-
|
|
87
|
+
# 'src/soliplex' (a path), not 'soliplex' (the importable name):
|
|
88
|
+
# 'soliplex' is a namespace package, and coverage cannot enumerate one
|
|
89
|
+
# by walking the filesystem, so a package-name target silently measures
|
|
90
|
+
# only the modules some test happened to import. A path target reports
|
|
91
|
+
# never-imported modules at 0%, which is what makes 'omit' below the
|
|
92
|
+
# single place that decides what is exempt.
|
|
93
|
+
addopts = "--cov=src/soliplex --cov=tests/unit --cov=scripts --cov=skills/soliplex-docs/scripts --cov-branch --cov-fail-under=100"
|
|
88
94
|
filterwarnings = [
|
|
89
95
|
# "ignore::DeprecationWarning:<source-package>",
|
|
90
96
|
]
|
|
@@ -95,8 +101,7 @@ markers = [
|
|
|
95
101
|
[tool.coverage.run]
|
|
96
102
|
omit = [
|
|
97
103
|
"scripts/lint_textio.py", # runs its own '--self-test' during lint
|
|
98
|
-
"src/soliplex/
|
|
99
|
-
"src/soliplex/tui.py",
|
|
104
|
+
"src/soliplex/tui/*", # the TUI is deliberately untested
|
|
100
105
|
]
|
|
101
106
|
|
|
102
107
|
[tool.coverage.report]
|
|
@@ -16,9 +16,6 @@ from soliplex.agui import persistence as agui_persistence
|
|
|
16
16
|
from soliplex.agui import schema as agui_schema
|
|
17
17
|
from soliplex.agui import util as agui_util
|
|
18
18
|
|
|
19
|
-
# Temporary backward-compatibility: to be removed in 'v0.45'
|
|
20
|
-
from soliplex.agui.schema import * # noqa F403
|
|
21
|
-
|
|
22
19
|
FeedbackReviewStatus = agui.FeedbackReviewStatus
|
|
23
20
|
|
|
24
21
|
|
|
@@ -9,7 +9,9 @@ import typing
|
|
|
9
9
|
import jsonpath
|
|
10
10
|
|
|
11
11
|
# Avoid circular import when only used for typing
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
if typing.TYPE_CHECKING: # avoid an import cycle at runtime
|
|
14
|
+
from soliplex import models
|
|
13
15
|
|
|
14
16
|
UserToken = dict[str, typing.Any]
|
|
15
17
|
|
|
@@ -249,14 +251,14 @@ class RoomAuthorizationPolicy(abc.ABC):
|
|
|
249
251
|
async def get_room_policy(
|
|
250
252
|
self,
|
|
251
253
|
room_id: str,
|
|
252
|
-
) -> models.RoomPolicy | None:
|
|
254
|
+
) -> models.RoomPolicy | None:
|
|
253
255
|
"""Return the authorization policy for the room"""
|
|
254
256
|
|
|
255
257
|
@abc.abstractmethod
|
|
256
258
|
async def update_room_policy(
|
|
257
259
|
self,
|
|
258
260
|
room_id: str,
|
|
259
|
-
room_policy: models.RoomPolicy,
|
|
261
|
+
room_policy: models.RoomPolicy,
|
|
260
262
|
) -> None:
|
|
261
263
|
"""Update the authorization policy for the room"""
|
|
262
264
|
|
|
@@ -271,13 +273,13 @@ class RoomAuthorizationPolicy(abc.ABC):
|
|
|
271
273
|
async def get_room_policy_unchecked(
|
|
272
274
|
self,
|
|
273
275
|
room_id: str,
|
|
274
|
-
) -> models.RoomPolicyUnchecked | None:
|
|
276
|
+
) -> models.RoomPolicyUnchecked | None:
|
|
275
277
|
"""Return the room policy, tolerating non-compiling 'json_path's."""
|
|
276
278
|
|
|
277
279
|
@abc.abstractmethod
|
|
278
280
|
async def list_room_policies(
|
|
279
281
|
self,
|
|
280
|
-
) -> list[models.RoomPolicyUnchecked]:
|
|
282
|
+
) -> list[models.RoomPolicyUnchecked]:
|
|
281
283
|
"""List every stored room policy as an unchecked model.
|
|
282
284
|
|
|
283
285
|
Each policy is returned as the unchecked model -- the analogue
|
|
@@ -298,7 +300,7 @@ class RoomAuthorizationPolicy(abc.ABC):
|
|
|
298
300
|
async def add_acl_entry(
|
|
299
301
|
self,
|
|
300
302
|
room_id: str,
|
|
301
|
-
entry: models.ACLEntry,
|
|
303
|
+
entry: models.ACLEntry,
|
|
302
304
|
) -> None:
|
|
303
305
|
"""Add an ACL entry to the room's policy, replacing any entry with
|
|
304
306
|
the same discriminator."""
|
|
@@ -307,7 +309,7 @@ class RoomAuthorizationPolicy(abc.ABC):
|
|
|
307
309
|
async def remove_acl_entry(
|
|
308
310
|
self,
|
|
309
311
|
room_id: str,
|
|
310
|
-
entry: models.ACLEntryUnchecked,
|
|
312
|
+
entry: models.ACLEntryUnchecked,
|
|
311
313
|
) -> None:
|
|
312
314
|
"""Remove the matching ACL entry from the room's policy."""
|
|
313
315
|
|
|
@@ -23,7 +23,7 @@ relationship = sqla_orm.relationship
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def _timestamp() -> datetime.datetime:
|
|
26
|
-
return datetime.datetime.now(datetime.
|
|
26
|
+
return datetime.datetime.now(datetime.UTC)
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
# Recommended naming convention used by Alembic, as various different database
|
|
@@ -408,6 +408,24 @@ def _iter_room_rag_candidates(room_config):
|
|
|
408
408
|
yield f"tool:{tool_config.tool_name}", tool_config
|
|
409
409
|
|
|
410
410
|
|
|
411
|
+
def _rag_db_probes(source, cfg):
|
|
412
|
+
"""Yield ``(label, cfg)`` for each database a config names.
|
|
413
|
+
|
|
414
|
+
A probe checks a path this config places, so a config deferring
|
|
415
|
+
placement to its haiku.rag config yields nothing: opening it for the
|
|
416
|
+
document count is what checks it. A candidate is only known to expose
|
|
417
|
+
``haiku_rag_config``, so one that cannot place a database at all yields
|
|
418
|
+
itself and reports its own error from inside the caller's ``try``.
|
|
419
|
+
"""
|
|
420
|
+
rag_databases = getattr(cfg, "rag_databases", None)
|
|
421
|
+
|
|
422
|
+
if rag_databases:
|
|
423
|
+
for entry in rag_databases:
|
|
424
|
+
yield f"{source}#{entry.name}", entry
|
|
425
|
+
elif getattr(cfg, "names_own_databases", True):
|
|
426
|
+
yield source, cfg
|
|
427
|
+
|
|
428
|
+
|
|
411
429
|
def _invalid_room_agui_features(
|
|
412
430
|
the_installation: installation.Installation,
|
|
413
431
|
) -> dict:
|
|
@@ -438,9 +456,18 @@ def _invalid_room_rag_dbs(
|
|
|
438
456
|
|
|
439
457
|
for source, cfg in _iter_room_rag_candidates(room_config):
|
|
440
458
|
try:
|
|
441
|
-
cfg.
|
|
459
|
+
_ = cfg.haiku_rag_config # property raises
|
|
442
460
|
except Exception as exc:
|
|
461
|
+
# A config that will not build says why; what it
|
|
462
|
+
# names is unanswerable until that is fixed.
|
|
443
463
|
per_room[source] = str(exc)
|
|
464
|
+
continue
|
|
465
|
+
|
|
466
|
+
for label, probe in _rag_db_probes(source, cfg):
|
|
467
|
+
try:
|
|
468
|
+
_ = probe.rag_lancedb_path # property raises
|
|
469
|
+
except Exception as exc:
|
|
470
|
+
per_room[label] = str(exc)
|
|
444
471
|
|
|
445
472
|
if per_room:
|
|
446
473
|
rag_errors[room_config.id] = per_room
|
|
@@ -505,12 +532,24 @@ def _audit_rooms_section(
|
|
|
505
532
|
tc_print()
|
|
506
533
|
tc_print(" Haiku Rag DBs")
|
|
507
534
|
for source, cfg in candidates:
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
535
|
+
# A config that will not build is recorded under its own
|
|
536
|
+
# source, which the per-database labels never match.
|
|
537
|
+
if source in per_room_rag:
|
|
538
|
+
failed = (source, per_room_rag[source])
|
|
539
|
+
else:
|
|
540
|
+
failed = next(
|
|
541
|
+
(
|
|
542
|
+
(label, per_room_rag[label])
|
|
543
|
+
for label, _ in _rag_db_probes(source, cfg)
|
|
544
|
+
if label in per_room_rag
|
|
545
|
+
),
|
|
546
|
+
None,
|
|
547
|
+
)
|
|
548
|
+
if failed is not None:
|
|
549
|
+
failed_label, exc = failed
|
|
550
|
+
tc_print(f" - {failed_label:20}: ERROR: {exc}")
|
|
511
551
|
else:
|
|
512
552
|
rag = hr_client.HaikuRAG(
|
|
513
|
-
db_path=cfg.rag_lancedb_path,
|
|
514
553
|
config=cfg.haiku_rag_config,
|
|
515
554
|
read_only=True,
|
|
516
555
|
)
|
|
@@ -522,7 +561,7 @@ def _audit_rooms_section(
|
|
|
522
561
|
room_rag_errors[source] = count_error
|
|
523
562
|
tc_print(
|
|
524
563
|
f" - {source:20}: "
|
|
525
|
-
f"{
|
|
564
|
+
f"{cfg.rag_db_audit_path:30} {count_display}"
|
|
526
565
|
)
|
|
527
566
|
tc_print()
|
|
528
567
|
tc_line()
|
|
@@ -21,6 +21,9 @@ from pydantic_ai.providers import openai as openai_providers
|
|
|
21
21
|
from . import _utils
|
|
22
22
|
from . import exceptions
|
|
23
23
|
|
|
24
|
+
if typing.TYPE_CHECKING: # avoid an import cycle at runtime
|
|
25
|
+
from . import installation as config_installation
|
|
26
|
+
|
|
24
27
|
_no_repr_no_compare_none = _utils._no_repr_no_compare_none
|
|
25
28
|
_default_dict_field = _utils._default_dict_field
|
|
26
29
|
_default_list_field = _utils._default_list_field
|
|
@@ -186,7 +189,7 @@ class AgentConfig:
|
|
|
186
189
|
agui_feature_names: tuple[str] = ()
|
|
187
190
|
|
|
188
191
|
# Set by `from_yaml` factory
|
|
189
|
-
_installation_config: InstallationConfig = (
|
|
192
|
+
_installation_config: config_installation.InstallationConfig = (
|
|
190
193
|
_no_repr_no_compare_none()
|
|
191
194
|
)
|
|
192
195
|
_config_path: pathlib.Path = None
|
|
@@ -207,7 +210,7 @@ class AgentConfig:
|
|
|
207
210
|
@classmethod
|
|
208
211
|
def from_yaml(
|
|
209
212
|
cls,
|
|
210
|
-
installation_config: InstallationConfig,
|
|
213
|
+
installation_config: config_installation.InstallationConfig,
|
|
211
214
|
config_path: pathlib.Path,
|
|
212
215
|
config_dict: dict,
|
|
213
216
|
):
|
|
@@ -362,7 +365,7 @@ class FactoryAgentConfig:
|
|
|
362
365
|
_factory: AgentFactory = None
|
|
363
366
|
|
|
364
367
|
# Set by `from_yaml` factory
|
|
365
|
-
_installation_config: InstallationConfig = (
|
|
368
|
+
_installation_config: config_installation.InstallationConfig = (
|
|
366
369
|
_no_repr_no_compare_none()
|
|
367
370
|
)
|
|
368
371
|
_config_path: pathlib.Path = None
|
|
@@ -394,7 +397,7 @@ class FactoryAgentConfig:
|
|
|
394
397
|
@classmethod
|
|
395
398
|
def from_yaml(
|
|
396
399
|
cls,
|
|
397
|
-
installation_config: InstallationConfig,
|
|
400
|
+
installation_config: config_installation.InstallationConfig,
|
|
398
401
|
config_path: pathlib.Path,
|
|
399
402
|
config_dict: dict,
|
|
400
403
|
):
|
|
@@ -449,7 +452,7 @@ AgentConfigMap = dict[str, AgentConfigTypes]
|
|
|
449
452
|
|
|
450
453
|
|
|
451
454
|
def extract_agent_config(
|
|
452
|
-
installation_config: InstallationConfig,
|
|
455
|
+
installation_config: config_installation.InstallationConfig,
|
|
453
456
|
config_path: pathlib.Path,
|
|
454
457
|
config_dict: dict,
|
|
455
458
|
) -> AgentConfig: # or subclass
|
|
@@ -8,6 +8,9 @@ import typing
|
|
|
8
8
|
from . import _utils
|
|
9
9
|
from . import exceptions as config_exc
|
|
10
10
|
|
|
11
|
+
if typing.TYPE_CHECKING: # avoid an import cycle at runtime
|
|
12
|
+
from . import installation as config_installation
|
|
13
|
+
|
|
11
14
|
_no_repr_no_compare_none = _utils._no_repr_no_compare_none
|
|
12
15
|
|
|
13
16
|
|
|
@@ -31,7 +34,7 @@ class OIDCAuthSystemConfig:
|
|
|
31
34
|
oidc_client_pem_path: pathlib.Path = None
|
|
32
35
|
|
|
33
36
|
# Set in 'from_yaml' below
|
|
34
|
-
_installation_config: InstallationConfig = (
|
|
37
|
+
_installation_config: config_installation.InstallationConfig = (
|
|
35
38
|
_no_repr_no_compare_none()
|
|
36
39
|
)
|
|
37
40
|
_config_path: pathlib.Path = None
|
|
@@ -39,7 +42,7 @@ class OIDCAuthSystemConfig:
|
|
|
39
42
|
@classmethod
|
|
40
43
|
def from_yaml(
|
|
41
44
|
cls,
|
|
42
|
-
installation_config: InstallationConfig,
|
|
45
|
+
installation_config: config_installation.InstallationConfig,
|
|
43
46
|
config_path: pathlib.Path,
|
|
44
47
|
config_dict: dict[str, typing.Any],
|
|
45
48
|
):
|
|
@@ -2,11 +2,15 @@ from __future__ import annotations # forward refs in typing decls
|
|
|
2
2
|
|
|
3
3
|
import dataclasses
|
|
4
4
|
import pathlib
|
|
5
|
+
import typing
|
|
5
6
|
|
|
6
7
|
from . import _utils
|
|
7
8
|
from . import agents as config_agents
|
|
8
9
|
from . import tools as config_tools
|
|
9
10
|
|
|
11
|
+
if typing.TYPE_CHECKING: # avoid an import cycle at runtime
|
|
12
|
+
from . import installation as config_installation
|
|
13
|
+
|
|
10
14
|
_no_repr_no_compare_none = _utils._no_repr_no_compare_none
|
|
11
15
|
_default_dict_field = _utils._default_dict_field
|
|
12
16
|
|
|
@@ -36,7 +40,7 @@ class CompletionConfig:
|
|
|
36
40
|
)
|
|
37
41
|
|
|
38
42
|
# Set by `from_yaml` factory
|
|
39
|
-
_installation_config: InstallationConfig = (
|
|
43
|
+
_installation_config: config_installation.InstallationConfig = (
|
|
40
44
|
_no_repr_no_compare_none()
|
|
41
45
|
)
|
|
42
46
|
_config_path: pathlib.Path = None
|
|
@@ -44,7 +48,7 @@ class CompletionConfig:
|
|
|
44
48
|
@classmethod
|
|
45
49
|
def from_yaml(
|
|
46
50
|
cls,
|
|
47
|
-
installation_config: InstallationConfig,
|
|
51
|
+
installation_config: config_installation.InstallationConfig,
|
|
48
52
|
config_path: pathlib.Path,
|
|
49
53
|
config_dict: dict,
|
|
50
54
|
):
|
|
@@ -7,7 +7,6 @@ import itertools
|
|
|
7
7
|
import os
|
|
8
8
|
import pathlib
|
|
9
9
|
import re
|
|
10
|
-
import sys
|
|
11
10
|
import typing
|
|
12
11
|
|
|
13
12
|
import dotenv
|
|
@@ -148,10 +147,28 @@ def _find_configs_yaml(
|
|
|
148
147
|
yield sub_config, _load_config_yaml(sub_config)
|
|
149
148
|
except config_exc.NoSuchConfig:
|
|
150
149
|
continue
|
|
151
|
-
else:
|
|
150
|
+
else:
|
|
152
151
|
pass
|
|
153
152
|
|
|
154
153
|
|
|
154
|
+
def _resolved_tokens(value, split_re, resolve):
|
|
155
|
+
"""Yield 'value' tokenized on 'split_re', resolving the markers.
|
|
156
|
+
|
|
157
|
+
'split_re' has a single capturing group, so 'split' alternates literal
|
|
158
|
+
text with captured marker names. Batching the tokens in pairs makes
|
|
159
|
+
the second element of each pair (when present) the marker to resolve.
|
|
160
|
+
"""
|
|
161
|
+
tokens = split_re.split(value)
|
|
162
|
+
|
|
163
|
+
batch = itertools.batched(tokens, 2, strict=False)
|
|
164
|
+
|
|
165
|
+
for two_or_one in batch:
|
|
166
|
+
yield two_or_one[0]
|
|
167
|
+
|
|
168
|
+
if len(two_or_one) == 2:
|
|
169
|
+
yield resolve(two_or_one[1])
|
|
170
|
+
|
|
171
|
+
|
|
155
172
|
_find_room_configs = functools.partial(
|
|
156
173
|
_find_configs_yaml,
|
|
157
174
|
filename_yaml="room_config.yaml",
|
|
@@ -443,22 +460,13 @@ class InstallationConfig:
|
|
|
443
460
|
|
|
444
461
|
The marker pattern may appear zero or more times.
|
|
445
462
|
"""
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
batch = itertools.batched(tokens, 2) # noqa: B911
|
|
454
|
-
|
|
455
|
-
for two_or_one in batch:
|
|
456
|
-
yield two_or_one[0]
|
|
457
|
-
|
|
458
|
-
if len(two_or_one) == 2:
|
|
459
|
-
yield self._resolve_secret(two_or_one[1])
|
|
460
|
-
|
|
461
|
-
return "".join(resolved_tokens(value))
|
|
463
|
+
return "".join(
|
|
464
|
+
_resolved_tokens(
|
|
465
|
+
value,
|
|
466
|
+
config_secrets.SECRET_RE,
|
|
467
|
+
self._resolve_secret,
|
|
468
|
+
)
|
|
469
|
+
)
|
|
462
470
|
|
|
463
471
|
#
|
|
464
472
|
# Map values similar to 'os.environ'.
|
|
@@ -489,7 +497,7 @@ class InstallationConfig:
|
|
|
489
497
|
|
|
490
498
|
if from_dotenv is not None:
|
|
491
499
|
result.append(ES(EST.DOT_ENV, from_dotenv))
|
|
492
|
-
else:
|
|
500
|
+
else:
|
|
493
501
|
pass
|
|
494
502
|
|
|
495
503
|
from_osenv = os.getenv(key)
|
|
@@ -540,23 +548,14 @@ class InstallationConfig:
|
|
|
540
548
|
|
|
541
549
|
The marker pattern may appear zero or more times.
|
|
542
550
|
"""
|
|
543
|
-
|
|
544
|
-
def resolved_tokens(value):
|
|
545
|
-
tokens = ENVIRONMENT_RE.split(value)
|
|
546
|
-
|
|
547
|
-
if sys.version_info >= (3, 13): # noqa: UP036
|
|
548
|
-
batch = itertools.batched(tokens, 2, strict=False)
|
|
549
|
-
else: # pragma: NO COVER
|
|
550
|
-
batch = itertools.batched(tokens, 2) # noqa: B911
|
|
551
|
-
|
|
552
|
-
for two_or_one in batch:
|
|
553
|
-
yield two_or_one[0]
|
|
554
|
-
|
|
555
|
-
if len(two_or_one) == 2:
|
|
556
|
-
yield self._resolve_environment_var(two_or_one[1])
|
|
557
|
-
|
|
558
551
|
if isinstance(value, str):
|
|
559
|
-
return "".join(
|
|
552
|
+
return "".join(
|
|
553
|
+
_resolved_tokens(
|
|
554
|
+
value,
|
|
555
|
+
ENVIRONMENT_RE,
|
|
556
|
+
self._resolve_environment_var,
|
|
557
|
+
)
|
|
558
|
+
)
|
|
560
559
|
else:
|
|
561
560
|
return value
|
|
562
561
|
|
|
@@ -962,7 +961,7 @@ class InstallationConfig:
|
|
|
962
961
|
|
|
963
962
|
return cls(**config_dict)
|
|
964
963
|
|
|
965
|
-
except config_exc.FromYamlException:
|
|
964
|
+
except config_exc.FromYamlException:
|
|
966
965
|
raise
|
|
967
966
|
|
|
968
967
|
except Exception as exc:
|
|
@@ -9,6 +9,9 @@ import logfire
|
|
|
9
9
|
from . import _utils
|
|
10
10
|
from . import exceptions as config_exc
|
|
11
11
|
|
|
12
|
+
if typing.TYPE_CHECKING: # avoid an import cycle at runtime
|
|
13
|
+
from . import installation as config_installation
|
|
14
|
+
|
|
12
15
|
_no_repr_no_compare_none = _utils._no_repr_no_compare_none
|
|
13
16
|
|
|
14
17
|
|
|
@@ -117,7 +120,7 @@ class LogfireConfig:
|
|
|
117
120
|
instrument_fast_api: LogfireInstrumentFastAPI = None
|
|
118
121
|
|
|
119
122
|
# Set by `from_yaml` factory
|
|
120
|
-
_installation_config: InstallationConfig = (
|
|
123
|
+
_installation_config: config_installation.InstallationConfig = (
|
|
121
124
|
_no_repr_no_compare_none()
|
|
122
125
|
)
|
|
123
126
|
_config_path: pathlib.Path = None
|
|
@@ -208,7 +211,7 @@ class LogfireConfig:
|
|
|
208
211
|
@classmethod
|
|
209
212
|
def from_yaml(
|
|
210
213
|
cls,
|
|
211
|
-
installation_config: InstallationConfig,
|
|
214
|
+
installation_config: config_installation.InstallationConfig,
|
|
212
215
|
config_path: pathlib.Path,
|
|
213
216
|
config_dict: dict,
|
|
214
217
|
):
|
|
@@ -6,11 +6,15 @@ import json
|
|
|
6
6
|
import os
|
|
7
7
|
import pathlib
|
|
8
8
|
import random
|
|
9
|
+
import typing
|
|
9
10
|
|
|
10
11
|
from . import _utils
|
|
11
12
|
from . import agents
|
|
12
13
|
from . import exceptions
|
|
13
14
|
|
|
15
|
+
if typing.TYPE_CHECKING: # avoid an import cycle at runtime
|
|
16
|
+
from . import installation as config_installation
|
|
17
|
+
|
|
14
18
|
_no_repr_no_compare_none = _utils._no_repr_no_compare_none
|
|
15
19
|
_default_list_field = _utils._default_list_field
|
|
16
20
|
_default_dict_field = _utils._default_dict_field
|
|
@@ -87,7 +91,7 @@ class QuizConfig:
|
|
|
87
91
|
judge_agent: agents.AgentConfig | None = None
|
|
88
92
|
|
|
89
93
|
# Set by `from_yaml` factory
|
|
90
|
-
_installation_config: InstallationConfig = (
|
|
94
|
+
_installation_config: config_installation.InstallationConfig = (
|
|
91
95
|
_no_repr_no_compare_none()
|
|
92
96
|
)
|
|
93
97
|
_config_path: pathlib.Path = None
|
|
@@ -95,7 +99,7 @@ class QuizConfig:
|
|
|
95
99
|
@classmethod
|
|
96
100
|
def from_yaml(
|
|
97
101
|
cls,
|
|
98
|
-
installation_config: InstallationConfig,
|
|
102
|
+
installation_config: config_installation.InstallationConfig,
|
|
99
103
|
config_path: pathlib.Path,
|
|
100
104
|
config_dict: dict,
|
|
101
105
|
):
|