planar 0.10.0__py3-none-any.whl → 0.11.0__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.
- planar/app.py +18 -6
- planar/routers/info.py +79 -36
- planar/scaffold_templates/pyproject.toml.j2 +1 -1
- planar/testing/fixtures.py +7 -4
- {planar-0.10.0.dist-info → planar-0.11.0.dist-info}/METADATA +9 -1
- {planar-0.10.0.dist-info → planar-0.11.0.dist-info}/RECORD +8 -60
- planar/ai/test_agent_serialization.py +0 -229
- planar/ai/test_agent_tool_step_display.py +0 -78
- planar/data/test_dataset.py +0 -358
- planar/files/storage/test_azure_blob.py +0 -435
- planar/files/storage/test_local_directory.py +0 -162
- planar/files/storage/test_s3.py +0 -299
- planar/files/test_files.py +0 -282
- planar/human/test_human.py +0 -385
- planar/logging/test_formatter.py +0 -327
- planar/modeling/mixins/test_auditable.py +0 -97
- planar/modeling/mixins/test_timestamp.py +0 -134
- planar/modeling/mixins/test_uuid_primary_key.py +0 -52
- planar/routers/test_agents_router.py +0 -174
- planar/routers/test_dataset_router.py +0 -429
- planar/routers/test_files_router.py +0 -49
- planar/routers/test_object_config_router.py +0 -367
- planar/routers/test_routes_security.py +0 -168
- planar/routers/test_rule_router.py +0 -470
- planar/routers/test_workflow_router.py +0 -564
- planar/rules/test_data/account_dormancy_management.json +0 -223
- planar/rules/test_data/airline_loyalty_points_calculator.json +0 -262
- planar/rules/test_data/applicant_risk_assessment.json +0 -435
- planar/rules/test_data/booking_fraud_detection.json +0 -407
- planar/rules/test_data/cellular_data_rollover_system.json +0 -258
- planar/rules/test_data/clinical_trial_eligibility_screener.json +0 -437
- planar/rules/test_data/customer_lifetime_value.json +0 -143
- planar/rules/test_data/import_duties_calculator.json +0 -289
- planar/rules/test_data/insurance_prior_authorization.json +0 -443
- planar/rules/test_data/online_check_in_eligibility_system.json +0 -254
- planar/rules/test_data/order_consolidation_system.json +0 -375
- planar/rules/test_data/portfolio_risk_monitor.json +0 -471
- planar/rules/test_data/supply_chain_risk.json +0 -253
- planar/rules/test_data/warehouse_cross_docking.json +0 -237
- planar/rules/test_rules.py +0 -1494
- planar/security/tests/test_auth_middleware.py +0 -162
- planar/security/tests/test_authorization_context.py +0 -78
- planar/security/tests/test_cedar_basics.py +0 -41
- planar/security/tests/test_cedar_policies.py +0 -158
- planar/security/tests/test_jwt_principal_context.py +0 -179
- planar/test_app.py +0 -142
- planar/test_cli.py +0 -394
- planar/test_config.py +0 -515
- planar/test_object_config.py +0 -527
- planar/test_object_registry.py +0 -14
- planar/test_sqlalchemy.py +0 -193
- planar/test_utils.py +0 -105
- planar/testing/test_memory_storage.py +0 -143
- planar/workflows/test_concurrency_detection.py +0 -120
- planar/workflows/test_lock_timeout.py +0 -140
- planar/workflows/test_serialization.py +0 -1203
- planar/workflows/test_suspend_deserialization.py +0 -231
- planar/workflows/test_workflow.py +0 -2005
- {planar-0.10.0.dist-info → planar-0.11.0.dist-info}/WHEEL +0 -0
- {planar-0.10.0.dist-info → planar-0.11.0.dist-info}/entry_points.txt +0 -0
planar/app.py
CHANGED
@@ -28,7 +28,6 @@ from planar.routers import (
|
|
28
28
|
create_workflow_router,
|
29
29
|
)
|
30
30
|
from planar.routers.agents_router import create_agent_router
|
31
|
-
from planar.routers.dataset_router import create_dataset_router
|
32
31
|
from planar.routers.entity_router import create_entities_router
|
33
32
|
from planar.routers.object_config_router import create_object_config_router
|
34
33
|
from planar.routers.rule import create_rule_router
|
@@ -130,14 +129,27 @@ class PlanarApp:
|
|
130
129
|
create_human_task_routes(),
|
131
130
|
prefix="/human-tasks",
|
132
131
|
)
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
132
|
+
|
133
|
+
if self.config.data:
|
134
|
+
try:
|
135
|
+
from planar.routers.dataset_router import create_dataset_router
|
136
|
+
|
137
|
+
self.router_v1.include_router(
|
138
|
+
create_dataset_router(),
|
139
|
+
prefix="/datasets",
|
140
|
+
)
|
141
|
+
except ImportError:
|
142
|
+
logger.error(
|
143
|
+
"Data dependencies not installed. Ensure you install the `data` optional dependency in your project (planar[data])"
|
144
|
+
)
|
145
|
+
raise
|
137
146
|
|
138
147
|
self.router_v1.include_router(
|
139
148
|
create_info_router(
|
140
|
-
title=title or "Planar API",
|
149
|
+
title=title or "Planar API",
|
150
|
+
description=description or "Planar API",
|
151
|
+
config=self.config,
|
152
|
+
registry=self._object_registry,
|
141
153
|
),
|
142
154
|
prefix="",
|
143
155
|
)
|
planar/routers/info.py
CHANGED
@@ -1,16 +1,34 @@
|
|
1
|
+
import importlib.metadata
|
2
|
+
from typing import Literal, TypedDict
|
3
|
+
|
1
4
|
from fastapi import APIRouter, Depends
|
2
5
|
from pydantic import BaseModel
|
3
|
-
from
|
4
|
-
from sqlmodel import
|
6
|
+
from sqlmodel import col, func, select
|
7
|
+
from sqlmodel.ext.asyncio.session import AsyncSession
|
5
8
|
|
9
|
+
from planar.config import PlanarConfig, get_environment
|
10
|
+
from planar.data.config import DataConfig
|
11
|
+
from planar.files.storage.config import StorageConfig
|
6
12
|
from planar.human.models import HumanTask, HumanTaskStatus
|
7
13
|
from planar.logging import get_logger
|
8
|
-
from planar.
|
14
|
+
from planar.object_registry import ObjectRegistry
|
9
15
|
from planar.session import get_session
|
10
16
|
from planar.workflows.models import Workflow, WorkflowStatus
|
11
17
|
|
12
18
|
logger = get_logger(__name__)
|
13
19
|
|
20
|
+
StorageInfo = Literal["s3", "localdir", "azure_blob"]
|
21
|
+
|
22
|
+
|
23
|
+
class DatasetsInfo(BaseModel):
|
24
|
+
catalog: Literal["duckdb", "postgres", "sqlite"]
|
25
|
+
storage: StorageInfo
|
26
|
+
|
27
|
+
|
28
|
+
class SystemFeatures(BaseModel):
|
29
|
+
storage: StorageInfo | None = None
|
30
|
+
datasets: DatasetsInfo | None = None
|
31
|
+
|
14
32
|
|
15
33
|
class SystemInfo(BaseModel):
|
16
34
|
"""Combined application information and system statistics"""
|
@@ -19,6 +37,11 @@ class SystemInfo(BaseModel):
|
|
19
37
|
title: str
|
20
38
|
description: str
|
21
39
|
|
40
|
+
version: str
|
41
|
+
environment: str
|
42
|
+
|
43
|
+
features: SystemFeatures
|
44
|
+
|
22
45
|
# System stats
|
23
46
|
total_workflow_runs: int = 0
|
24
47
|
completed_runs: int = 0
|
@@ -27,7 +50,18 @@ class SystemInfo(BaseModel):
|
|
27
50
|
active_agents: int = 0
|
28
51
|
|
29
52
|
|
30
|
-
|
53
|
+
class SystemStats(TypedDict):
|
54
|
+
total_workflow_runs: int
|
55
|
+
completed_runs: int
|
56
|
+
in_progress_runs: int
|
57
|
+
pending_human_tasks: int
|
58
|
+
active_agents: int
|
59
|
+
|
60
|
+
|
61
|
+
async def get_system_stats(
|
62
|
+
registry: ObjectRegistry,
|
63
|
+
session: AsyncSession = Depends(get_session),
|
64
|
+
) -> SystemStats:
|
31
65
|
"""
|
32
66
|
Get system-wide statistics directly from the database.
|
33
67
|
|
@@ -35,8 +69,10 @@ async def get_system_stats(session: AsyncSession = Depends(get_session)) -> dict
|
|
35
69
|
rather than fetching all records and calculating in the application.
|
36
70
|
"""
|
37
71
|
try:
|
72
|
+
agent_count = len(registry.get_agents())
|
73
|
+
|
38
74
|
# Get workflow run counts
|
39
|
-
workflow_stats = await session.
|
75
|
+
workflow_stats = await session.exec(
|
40
76
|
select(
|
41
77
|
func.count().label("total_runs"),
|
42
78
|
func.count(col(Workflow.id))
|
@@ -47,42 +83,21 @@ async def get_system_stats(session: AsyncSession = Depends(get_session)) -> dict
|
|
47
83
|
.label("in_progress_runs"),
|
48
84
|
).select_from(Workflow)
|
49
85
|
)
|
50
|
-
|
86
|
+
total_runs, completed_runs, in_progress_runs = workflow_stats.one()
|
51
87
|
|
52
88
|
# Get pending human task count
|
53
|
-
human_task_query = await session.
|
89
|
+
human_task_query = await session.exec(
|
54
90
|
select(func.count())
|
55
91
|
.select_from(HumanTask)
|
56
92
|
.where(HumanTask.status == HumanTaskStatus.PENDING)
|
57
93
|
)
|
58
|
-
pending_tasks = human_task_query.
|
59
|
-
|
60
|
-
# Get agent count from the registry or count distinct agent configs
|
61
|
-
agent_count = 0
|
62
|
-
try:
|
63
|
-
# Count distinct agent names in the AgentConfig table
|
64
|
-
agent_query = await session.execute(
|
65
|
-
select(
|
66
|
-
func.count(distinct(ObjectConfiguration.object_name))
|
67
|
-
).select_from(
|
68
|
-
select(ObjectConfiguration)
|
69
|
-
.where(
|
70
|
-
ObjectConfiguration.object_type == ConfigurableObjectType.AGENT
|
71
|
-
)
|
72
|
-
.subquery()
|
73
|
-
)
|
74
|
-
)
|
75
|
-
agent_count = agent_query.scalar() or 0
|
76
|
-
except Exception:
|
77
|
-
logger.exception("error counting agents")
|
78
|
-
# Fallback to 0
|
79
|
-
agent_count = 0
|
94
|
+
pending_tasks = human_task_query.one()
|
80
95
|
|
81
96
|
# Return stats dict
|
82
97
|
return {
|
83
|
-
"total_workflow_runs":
|
84
|
-
"completed_runs":
|
85
|
-
"in_progress_runs":
|
98
|
+
"total_workflow_runs": total_runs,
|
99
|
+
"completed_runs": completed_runs,
|
100
|
+
"in_progress_runs": in_progress_runs,
|
86
101
|
"pending_human_tasks": pending_tasks,
|
87
102
|
"active_agents": agent_count,
|
88
103
|
}
|
@@ -98,13 +113,31 @@ async def get_system_stats(session: AsyncSession = Depends(get_session)) -> dict
|
|
98
113
|
}
|
99
114
|
|
100
115
|
|
101
|
-
def
|
116
|
+
def get_app_version() -> str:
|
117
|
+
try:
|
118
|
+
return importlib.metadata.version("planar")
|
119
|
+
except importlib.metadata.PackageNotFoundError:
|
120
|
+
logger.warning("Planar package not found, returning development version")
|
121
|
+
return "development"
|
122
|
+
|
123
|
+
|
124
|
+
def get_storage_info(cfg: StorageConfig) -> StorageInfo:
|
125
|
+
return cfg.backend
|
126
|
+
|
127
|
+
|
128
|
+
def get_datasets_info(cfg: DataConfig) -> DatasetsInfo | None:
|
129
|
+
return DatasetsInfo(catalog=cfg.catalog.type, storage=get_storage_info(cfg.storage))
|
130
|
+
|
131
|
+
|
132
|
+
def create_info_router(
|
133
|
+
title: str, description: str, config: PlanarConfig, registry: ObjectRegistry
|
134
|
+
) -> APIRouter:
|
102
135
|
"""
|
103
136
|
Create a router for serving combined application information and system statistics.
|
104
137
|
|
105
138
|
This router provides a single endpoint to retrieve the application's title,
|
106
139
|
description, and system-wide statistics on workflow runs, human tasks,
|
107
|
-
and registered agents.
|
140
|
+
and registered agents, as well as the application's features and configuration.
|
108
141
|
|
109
142
|
Args:
|
110
143
|
title: The application title
|
@@ -125,7 +158,17 @@ def create_info_router(title: str, description: str) -> APIRouter:
|
|
125
158
|
Returns:
|
126
159
|
SystemInfo object containing app details and system stats
|
127
160
|
"""
|
128
|
-
stats = await get_system_stats(session)
|
129
|
-
return SystemInfo(
|
161
|
+
stats = await get_system_stats(registry, session)
|
162
|
+
return SystemInfo(
|
163
|
+
title=title,
|
164
|
+
description=description,
|
165
|
+
version=get_app_version(),
|
166
|
+
environment=get_environment(),
|
167
|
+
features=SystemFeatures(
|
168
|
+
storage=get_storage_info(config.storage) if config.storage else None,
|
169
|
+
datasets=get_datasets_info(config.data) if config.data else None,
|
170
|
+
),
|
171
|
+
**stats,
|
172
|
+
)
|
130
173
|
|
131
174
|
return router
|
planar/testing/fixtures.py
CHANGED
@@ -36,7 +36,7 @@ from pathlib import Path
|
|
36
36
|
import pytest
|
37
37
|
|
38
38
|
from planar.app import PlanarApp
|
39
|
-
from planar.config import load_config
|
39
|
+
from planar.config import load_config, load_environment_aware_config
|
40
40
|
from planar.data.config import DataConfig, SQLiteCatalogConfig
|
41
41
|
from planar.db import DatabaseManager, new_session
|
42
42
|
from planar.files.storage.config import LocalDirectoryConfig
|
@@ -138,9 +138,12 @@ def data_config(tmp_path):
|
|
138
138
|
@pytest.fixture(name="app_with_data")
|
139
139
|
def app_with_data_fixture(data_config):
|
140
140
|
"""Create a PlanarApp with data configuration."""
|
141
|
-
|
142
|
-
|
143
|
-
|
141
|
+
config = load_environment_aware_config()
|
142
|
+
|
143
|
+
config.data = data_config
|
144
|
+
|
145
|
+
app = PlanarApp(config=config)
|
146
|
+
|
144
147
|
return app
|
145
148
|
|
146
149
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: planar
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.11.0
|
4
4
|
Summary: Add your description here
|
5
5
|
License-Expression: LicenseRef-Proprietary
|
6
6
|
Requires-Dist: aiofiles>=24.1.0
|
@@ -296,6 +296,14 @@ To disable SQLite testing:
|
|
296
296
|
PLANAR_TEST_SQLITE=0 uv run pytest
|
297
297
|
```
|
298
298
|
|
299
|
+
### Test coverage
|
300
|
+
|
301
|
+
We use [pytest-cov](https://pypi.org/project/pytest-cov/) to measure test coverage. To generate a simple coverage report use the following command:
|
302
|
+
|
303
|
+
```bash
|
304
|
+
uv run pytest --cov=planar
|
305
|
+
```
|
306
|
+
|
299
307
|
### Pre-commit hooks
|
300
308
|
|
301
309
|
We use [pre-commit](https://pre-commit.com/) to manage pre-commit hooks. To install the pre-commit hooks, run the following command:
|
@@ -6,10 +6,8 @@ planar/ai/agent_utils.py,sha256=MYNerdAm2TPVbDSKAmBCUlGmR56NAc8seZmDAFOWvUA,4199
|
|
6
6
|
planar/ai/models.py,sha256=bZd4MoBBJMqzXJqsmsbMdZtOaRrNeX438CHAqOvmpfw,4598
|
7
7
|
planar/ai/pydantic_ai.py,sha256=FpD0pE7wWNYwmEUZ90D7_J8gbAoqKmWtrLr2fhAd7rg,23503
|
8
8
|
planar/ai/state.py,sha256=6vQ8VMLxJYB75QXkm8AVPkdXHUMwwjKxBWH-hGIK9p0,278
|
9
|
-
planar/ai/test_agent_serialization.py,sha256=zYLIxhYdFhOZzBrEBoQNyYLyNcNxWwaMTkjt_ARTkZk,8073
|
10
|
-
planar/ai/test_agent_tool_step_display.py,sha256=7OeKLnimItAkAFcArufDfiL3rXnQ1GwEtrE58_557hM,2588
|
11
9
|
planar/ai/utils.py,sha256=WVBW0TGaoKytC4bNd_a9lXrBf5QsDRut4GBcA53U2Ww,3116
|
12
|
-
planar/app.py,sha256=
|
10
|
+
planar/app.py,sha256=SKP7xinjQZfVKssKdfq0eK7VaJru99ReGJpn5KeTD3w,19108
|
13
11
|
planar/cli.py,sha256=SIyQOY3MbNDuohNcXFRIrHJuGxFNNC8C_ihfCXIUvbE,9900
|
14
12
|
planar/config.py,sha256=6J42G9rEVUiOyCAY3EwUTU3PPmWthGTnrHMzST9TMcc,17809
|
15
13
|
planar/data/__init__.py,sha256=LwrWl925w1CN0aW645Wpj_kDp0B8j5SsPzjr9iyrcmI,285
|
@@ -17,7 +15,6 @@ planar/data/config.py,sha256=zp6ChI_2MUMbupEVQNY-BxzcdLvejXG33DCp0BujGVU,1209
|
|
17
15
|
planar/data/connection.py,sha256=OGBVVapxDu1-vxAHjlEmSQiapBXBegetb4Nu0wg4n2Q,3846
|
18
16
|
planar/data/dataset.py,sha256=FKvuM2-xI101mEf1eeOYfNjSpHk8XjFXnAktTNR8Nig,5800
|
19
17
|
planar/data/exceptions.py,sha256=AlhGQ_TReyEzfPSlqoXCjoZ1206Ut7dS4lrukVfGHaw,358
|
20
|
-
planar/data/test_dataset.py,sha256=_tYvzw4y2-8rlRELdJxItcG_0OCFlOv7tBC7QI1j21o,10196
|
21
18
|
planar/data/utils.py,sha256=hhHKpYBvzLdzjNy_OElpAqIU-3XuHqUkFCiF5YWsShs,2556
|
22
19
|
planar/db/__init__.py,sha256=SNgB6unQ1f1E9dB9O-KrsPsYM17KLsgOW1u0ajqs57I,318
|
23
20
|
planar/db/alembic/env.py,sha256=4yX_aCqrXScVN3q7ISiMEDz40-5Dmociqh6d7VCUPwc,6051
|
@@ -35,29 +32,20 @@ planar/files/storage/config.py,sha256=jE9Dn6cG_a4x9pdaZkasOxjyWkK6hmplLrPjEsRXGL
|
|
35
32
|
planar/files/storage/context.py,sha256=Qadlz4T-FQ1A0TdGsOfuNmM679ohayU7oaexUpT8AY0,361
|
36
33
|
planar/files/storage/local_directory.py,sha256=1SsEfr0Ud9TvSQJneDl_M-D7AFYixLE9t-bVIiY3aSI,7395
|
37
34
|
planar/files/storage/s3.py,sha256=1861rSw3kplXtugUWD7mdSD_EnPSHME1mGc82V69r5g,8234
|
38
|
-
planar/files/storage/test_azure_blob.py,sha256=OFYpns6JyeCCBHCoLz56uUHR6tWWeSZldUant5llczI,14200
|
39
|
-
planar/files/storage/test_local_directory.py,sha256=KtzRfjtZUew1U-KETtD2mb6ywwX6HmjzaaeixOP0Ebg,5751
|
40
|
-
planar/files/storage/test_s3.py,sha256=QG-CH7fiaRmQRwffnqG2mLRrw9LIlR2-xRyHs6Wuspo,10565
|
41
|
-
planar/files/test_files.py,sha256=nclsbLnbijCWQ-Aj8Yvo06hs72PygL1Wps7uk7716sc,8957
|
42
35
|
planar/human/__init__.py,sha256=FwpV-FFssKKlvKSjWoI4gJB1XTMaNb1UNCSBxjAtIBw,147
|
43
36
|
planar/human/human.py,sha256=-oRtN_8bCtSV7Sxku7yG4rof7T5pr4j18Cfm3u4Z3PM,14925
|
44
37
|
planar/human/models.py,sha256=Cec1Y9NGGtuAl1ZhqNc9PWIq__BbiWVTh7IYKR4yl3w,2317
|
45
|
-
planar/human/test_human.py,sha256=GlbTjCNeAAfcwVIPq1TRiH0ojSgAU0i3oMc2yQe0xVo,13226
|
46
38
|
planar/logging/__init__.py,sha256=BW101gskQS3C2agKSDiJEy4L-j5z6BP1AwEfd2JMXHM,254
|
47
39
|
planar/logging/attributes.py,sha256=SB-lC-Osa55zXkX2UAWm56vKXvHgbF7TmhGnSiBWejk,1529
|
48
40
|
planar/logging/context.py,sha256=mGVpL-276VWpRUIGlkGwbn9gkATqFS7lcFn1aM0v-eQ,384
|
49
41
|
planar/logging/formatter.py,sha256=NMDhpo7ezsfGO7cPwOWbClqODviEgSjqHCoqrCCIu2c,3560
|
50
42
|
planar/logging/logger.py,sha256=vj3-z2ea0J1ppgDpJBsrueA3jg5kjk9ceIo-4tWarXk,2650
|
51
43
|
planar/logging/otel.py,sha256=bD1wgKTon1ooq3JIWc_i0_d_ejxw8_a5YPFuizRa5ic,1734
|
52
|
-
planar/logging/test_formatter.py,sha256=nzlZFUC1JD4Imcy1H7VaFhwjrHzRc_oQLXWZXiN7iGA,11695
|
53
44
|
planar/modeling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
54
45
|
planar/modeling/field_helpers.py,sha256=9SOHTWPzjlaiq7RF88wjug3NvAywFurcHn651YL_SNY,1903
|
55
46
|
planar/modeling/json_schema_generator.py,sha256=NDqPkWQA_I7ywQXCEQfj5ub9u5KAFEcSQpXVkrCluV4,2864
|
56
47
|
planar/modeling/mixins/__init__.py,sha256=Lwg5eL4VFfv61FRBvH5OZqIyfrSogxQlYLUDnWnSorg,320
|
57
48
|
planar/modeling/mixins/auditable.py,sha256=WP7aDWVn1j22ZffKzYRpu23JQJ4vvHCU1qxcbgChwhc,1619
|
58
|
-
planar/modeling/mixins/test_auditable.py,sha256=RSYesWWBysFEWTD39-yDhww3wCe1OPN9Yt3ywGmx4d8,2912
|
59
|
-
planar/modeling/mixins/test_timestamp.py,sha256=oLKPvr8oUdjJPJRif81nn4YV_uwbxql_ojjXdKI7j7E,4366
|
60
|
-
planar/modeling/mixins/test_uuid_primary_key.py,sha256=t9ZoB0dS4jjJVrHic7EeEh_g3eZeYV3mr0ylv3Kr1Io,1575
|
61
49
|
planar/modeling/mixins/timestamp.py,sha256=-eHndCWztDiOxfCI2UknmphGeoHMJVDJG1Lz4KtkQUA,1641
|
62
50
|
planar/modeling/mixins/uuid_primary_key.py,sha256=O1BtuXk5GdsfpwTS6nGZm1GNi0pdXKQ6Kt2f5ZjiuMc,453
|
63
51
|
planar/modeling/orm/__init__.py,sha256=QwPgToKEf_gCdjAjKKmgh0xLTHGsboK1kH1a1a0tSy0,339
|
@@ -77,55 +65,28 @@ planar/routers/entity_router.py,sha256=7Y1LDSqI_ovoOGr9DGylGM8BmRxF-WSPQSwITJHc6
|
|
77
65
|
planar/routers/event.py,sha256=yvzzMQaKRoS2A0KSjQTyWcfmBzpt8xPNDfVW50XUSCw,2961
|
78
66
|
planar/routers/files.py,sha256=udu6PeZ9AuOpNyJete21rWAVQyE0qnC7tnSyJ97AH4Y,5644
|
79
67
|
planar/routers/human.py,sha256=m_CbH97_QGmzriui_xopLOq-2D1kR0WgvO92fMaFeBQ,5010
|
80
|
-
planar/routers/info.py,sha256=
|
68
|
+
planar/routers/info.py,sha256=_7edvZjWbI65htI8nrQdHNxjMfSn2u-JHmxnpNWUAiU,5396
|
81
69
|
planar/routers/models.py,sha256=zknkVs9-B4UJlMe9fl2EpXx7sdzfjQfwAbNoL1a0wmI,4694
|
82
70
|
planar/routers/object_config_router.py,sha256=zA8-gGBQp1-Gm3uCC4WJ6nLicFwt4CsCqCYLFp1lRN8,4802
|
83
71
|
planar/routers/rule.py,sha256=d6giUwYRKzxQFPeoWbe8Ylp2Cxd71_uK8yoS9NrOOBg,3563
|
84
|
-
planar/routers/test_agents_router.py,sha256=jzRCLB21YcEfhaFUos_gfRp9WDdP38_cozTQkHbi9b4,6099
|
85
|
-
planar/routers/test_dataset_router.py,sha256=8Dm6ZFlIXQgwWLG3y00mz5cMsZvmIw7yM2-w-Qe_sCQ,13058
|
86
|
-
planar/routers/test_files_router.py,sha256=HfZF1zeJ9BD2jhE6s698Jo7sDpO55RJF5g1Ksup4jtM,1576
|
87
|
-
planar/routers/test_object_config_router.py,sha256=JpzoNlNONgljmGJYtrXnhtGhKjUT3YQMhP89fnt7dn4,11406
|
88
|
-
planar/routers/test_routes_security.py,sha256=lXHeYg_th4UaDWeANM-dzONF8p2bEtwXJYYUlftE9R8,5556
|
89
|
-
planar/routers/test_rule_router.py,sha256=08fa4sc7RaXvQzPCQQ4LaftfXuQwoPEDzcS4lesPG2Q,17220
|
90
|
-
planar/routers/test_workflow_router.py,sha256=h2XTJrlO3vAshd45abtMaE0kigWTNxXjfJiuGcjcA7s,17463
|
91
72
|
planar/routers/workflow.py,sha256=I9wJLqcFf52eEREhwqMsYICBEVD7I07g7ILWzxR5x9Y,18151
|
92
73
|
planar/rules/__init__.py,sha256=lF3F8Rdf2ottjiJu0IeBdqhg1bckLhOqZFI2t-8KItM,474
|
93
74
|
planar/rules/decorator.py,sha256=nxT17n9uwfXMOlk5lliw_cRS7Y83gMI6CQdrf_pB5yk,6666
|
94
75
|
planar/rules/models.py,sha256=vC38JLeGzmU87L8BX4AyVJLJHmRYjWRmoHQ6S6ZlhPg,10186
|
95
76
|
planar/rules/rule_configuration.py,sha256=B2G6mPnfxA277nF-Gr-B_Uely-ZOhz2jAhiwQMZuY-k,6508
|
96
77
|
planar/rules/runner.py,sha256=KIPrt_ri50qotvDLOY9xly40bNTWRh8GVT2kEJFFtFo,1714
|
97
|
-
planar/rules/test_data/account_dormancy_management.json,sha256=9aMMELZrF5DTBluMKUXJptxwULEcva4GHEyaapIeerY,4776
|
98
|
-
planar/rules/test_data/airline_loyalty_points_calculator.json,sha256=7S1koMe60yR3h2VQys34oLy5ynhsEQ5wadMLPHCRQZA,5689
|
99
|
-
planar/rules/test_data/applicant_risk_assessment.json,sha256=rj-Q13NczdNt00x5wrvGLalw5IfdT1j-_RvpwCZa7Fc,9994
|
100
|
-
planar/rules/test_data/booking_fraud_detection.json,sha256=HCAsUIIlaPL8Ph3jtUFVi2vTZxZW53-XggjDWEoXmi4,10027
|
101
|
-
planar/rules/test_data/cellular_data_rollover_system.json,sha256=8GjkKqqzK7usSa5KAvUwkD2CzW5JtLGECjlD5gH-vHk,6317
|
102
|
-
planar/rules/test_data/clinical_trial_eligibility_screener.json,sha256=VV0RzWdThBNlIffuyklqAcKtRq-aOLHpcXX28IR9qOU,11152
|
103
|
-
planar/rules/test_data/customer_lifetime_value.json,sha256=ZYeISNOsgT7zLcddeNrrrHlrocDlDBmSfOlQqhu3PTE,3562
|
104
|
-
planar/rules/test_data/import_duties_calculator.json,sha256=JsXuvkiGQF6MxrgrIhFC1UxDCtO9nQpxtKKXwOQ1VYs,9062
|
105
|
-
planar/rules/test_data/insurance_prior_authorization.json,sha256=27_jET4mmpuzLeOzVF5xi7c9IexX1UJTKsIoQGQ0n8c,12145
|
106
|
-
planar/rules/test_data/online_check_in_eligibility_system.json,sha256=c6zCGojFN6c-CnuvG93zqlCZIrMccnOGAPMZVoMfirg,6114
|
107
|
-
planar/rules/test_data/order_consolidation_system.json,sha256=kWJuVHAfAqsDW2xVdxHbtJTlfolQ_SM6_GISgnxsYB8,9803
|
108
|
-
planar/rules/test_data/portfolio_risk_monitor.json,sha256=tTvQOJJLhakGxG4CnA9fdBIECstJnp0B8ogFADkdy8s,15168
|
109
|
-
planar/rules/test_data/supply_chain_risk.json,sha256=fO0wV5ZnsZQpOP19Zp2troTMADaX0-KMpCxG_uHG198,7263
|
110
|
-
planar/rules/test_data/warehouse_cross_docking.json,sha256=IPfcgNkY2sds301BeW6CjgFtK_zRyr27gI3UcqCB2Uo,5549
|
111
|
-
planar/rules/test_rules.py,sha256=6M7CSg1bwn7O7DOoNi38vyVG4UmPQfRFxEO9qGE6rz0,52011
|
112
78
|
planar/scaffold_templates/app/__init__.py.j2,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
113
79
|
planar/scaffold_templates/app/db/entities.py.j2,sha256=wg9O3JtRaRMKlDtoWHHodyNRL0s1UILvsr9fCQ_O2-4,279
|
114
80
|
planar/scaffold_templates/app/flows/process_invoice.py.j2,sha256=R3EII_O2DHV1kvffW_AApZyaS6rR9eikcpxI08XH9dI,1691
|
115
81
|
planar/scaffold_templates/main.py.j2,sha256=zrqsuv3Fp4lcknvB37RrRHy11msdFB1yDguYmTLLPhw,398
|
116
82
|
planar/scaffold_templates/planar.dev.yaml.j2,sha256=I5-IqX7GJm6qA91WtUMw43L4hKACqgnER_H2racim4c,998
|
117
83
|
planar/scaffold_templates/planar.prod.yaml.j2,sha256=FahJ2atDtvVH7IUCatGq6h9hmyF8meeiWC8RLfWphOQ,867
|
118
|
-
planar/scaffold_templates/pyproject.toml.j2,sha256=
|
84
|
+
planar/scaffold_templates/pyproject.toml.j2,sha256=HpBc3cuTr-VeVN3BQ8y1Vr2eOtkL7TLH5mNz_T-akpA,190
|
119
85
|
planar/security/auth_context.py,sha256=i63JkHQ3oXNlTis7GIKRkZJbkcvZhD2jVDuO7blgbSc,5068
|
120
86
|
planar/security/auth_middleware.py,sha256=Grrm0i2bstWZ83ukrNZsHvFbNzffN0rvbbCcb2OxRY0,5746
|
121
87
|
planar/security/authorization.py,sha256=zTh5rLmVJZnGDq540_1WYljJ7Hws-BY_P6VqUCONqLE,12760
|
122
88
|
planar/security/default_policies.cedar,sha256=j7stjEfmgzthsDCjw1NwlE3_SxXQmLOGNRONM_2htoE,1492
|
123
89
|
planar/security/security_context.py,sha256=vzfwiDJRzq8snaENrJddG5Ei-UUq_a5hkInMEOZf0mM,496
|
124
|
-
planar/security/tests/test_auth_middleware.py,sha256=GjAyJYAR6jF_zGG85ZKY-E_e_aoqjK8qiHSalv2T2rk,6206
|
125
|
-
planar/security/tests/test_authorization_context.py,sha256=cnsC3V13NBJwzyIwZaM9wu_vergcnmVhwB3khVH7G-o,2364
|
126
|
-
planar/security/tests/test_cedar_basics.py,sha256=i1jLPjlJT1n_97onbeDYVpnwAzU2PmHvIPvaJSH1J2U,1026
|
127
|
-
planar/security/tests/test_cedar_policies.py,sha256=-Vn_CQgCUAVg7YhdUd34FsOjNL1EmY_o92r-fzmknP8,4848
|
128
|
-
planar/security/tests/test_jwt_principal_context.py,sha256=nGElTLtXbabkAxd3kXVpSFdH7kvSzHzSkp89g5Vu5Hc,4691
|
129
90
|
planar/session.py,sha256=xLS9WPvaiy9nr2Olju1-C-7_sU5VXK8RuNdjuKndul4,1020
|
130
91
|
planar/sse/constants.py,sha256=jE3SooTEWPuuL_Bi6DisJYMR9pKOiHVfboU2h5QTJRg,22
|
131
92
|
planar/sse/example.html,sha256=SgTJbdJ3B1F1DxLC2YWuX2F1XVwKcTjX34CbJCXoCTM,4144
|
@@ -133,19 +94,11 @@ planar/sse/hub.py,sha256=5jhfk7zdCivau3TT1MxU2qtvETSskhqEiXzt-t0sRpE,6859
|
|
133
94
|
planar/sse/model.py,sha256=fU_Fx9LS2ouS6-Dj1TIF-PLGul9YratKWafoWfZR1gc,123
|
134
95
|
planar/sse/proxy.py,sha256=aJGo_-JIeQ0xSmE4HJdulZxIgCVRsBMMXqqSqtPvTvo,9177
|
135
96
|
planar/task_local.py,sha256=pyvT0bdzAn15HL2yQUs9YrU5MVXh9njQt9MH51AGljs,1102
|
136
|
-
planar/test_app.py,sha256=5dYhOW6lRbAx2X270DfqktkJ5IfuqfowX6bwxM1WQAM,4865
|
137
|
-
planar/test_cli.py,sha256=faR6CSuooHHyyB5Yt-p8CIr7mGtKrrU2TLQbc4Oe9bA,13834
|
138
|
-
planar/test_config.py,sha256=HcmDu1nwKZZhzHQLGVyP9oxje-_g_XubEsvzRj28QPg,14328
|
139
|
-
planar/test_object_config.py,sha256=izn4s2HmSDWpGtgpOTDmKeUYN2-63WDR1QtVQrT-x00,20135
|
140
|
-
planar/test_object_registry.py,sha256=R7IwbB2GACm2HUuVZTeVY4V12XB9_JgSSeppPxiCdfs,480
|
141
|
-
planar/test_sqlalchemy.py,sha256=QTloaipWiFmlLTBGH6YCRkwi1R27gmQZnwprO7lPLfU,7058
|
142
|
-
planar/test_utils.py,sha256=gKenXotj36SN_bb3bQpYPfD8t06IjnGBQqEgWpujHcA,3086
|
143
97
|
planar/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
144
|
-
planar/testing/fixtures.py,sha256=
|
98
|
+
planar/testing/fixtures.py,sha256=z0VkKTqAg9z_1L_ojB0pTzKSaLPcDeNxRq_RB36rUU8,9740
|
145
99
|
planar/testing/memory_storage.py,sha256=apcuFisC3hW9KiU3kO8zwHQ6oK9Lu20NSX5fJ0LSZUY,2824
|
146
100
|
planar/testing/planar_test_client.py,sha256=2atx5zER5bGrCVoa-lcag8xP2ZcbnOLKoGRKpfOJCg8,1992
|
147
101
|
planar/testing/synchronizable_tracer.py,sha256=SWeta1CgwGsN5duC0FR8NyXOQ1b1L8nDpvGdjZVJ9Bg,4938
|
148
|
-
planar/testing/test_memory_storage.py,sha256=So32XL0gbLDFMTl-WJN445x9jL6O8Qsqw8IRaiZnsPs,4797
|
149
102
|
planar/testing/workflow_observer.py,sha256=0Q2xsYuZzNGXHZVwvXBqL9KXPsdIXuSZGBJAxHopzJw,2976
|
150
103
|
planar/utils.py,sha256=YP37-ODS8nYOIfHPo11CwCpQRsg8oc57lQ0wkXwqCyo,3607
|
151
104
|
planar/workflows/__init__.py,sha256=yFrrtKYUCx4jBPpHdEWDfKQgZXzGyr9voj5lFe9C-_w,826
|
@@ -166,14 +119,9 @@ planar/workflows/step_core.py,sha256=e-O-SP_1ufr3EYwuvu3O4I06aoqMxu_tpvHAUO-pMWg
|
|
166
119
|
planar/workflows/step_metadata.py,sha256=7hwcIm6ot8m-iUXSYCbPmkg6bWegF6_RJ1stInvaFII,10903
|
167
120
|
planar/workflows/step_testing_utils.py,sha256=WiTwxB4mM2y6dW7CJ3PlIR1BkBodSxQV7-S25pQ3Ycs,2361
|
168
121
|
planar/workflows/sub_workflow_runner.py,sha256=EpS7DhhXRbC6ABm-Sho6Uyxh2TqCjcTPDYvcTQN4FjY,8313
|
169
|
-
planar/workflows/test_concurrency_detection.py,sha256=yfgvLOMkPaK7EiW4ihm1KQx82Y-s9pB6uJhBfDi7PwQ,4528
|
170
|
-
planar/workflows/test_lock_timeout.py,sha256=H78N090wJtiEg6SaJosfRWijpX6HwnyWyNNb7WaGPe0,5746
|
171
|
-
planar/workflows/test_serialization.py,sha256=JfaveBRQTNMkucqkTorIMGcvi8S0j6uRtboFaWpCmes,39586
|
172
|
-
planar/workflows/test_suspend_deserialization.py,sha256=ddw2jToSJ-ebQ0RfT7KWTRMCOs1nis1lprQiGIGuaJ0,7751
|
173
|
-
planar/workflows/test_workflow.py,sha256=hBLPQYqUsWEQ_SopKgi69ckRC5OpmQEBlsPcftGMu_Q,65266
|
174
122
|
planar/workflows/tracing.py,sha256=E7E_kj2VBQisDqrllviIshbvOmB9QcEeRwMapunqio4,2732
|
175
123
|
planar/workflows/wrappers.py,sha256=dY_3NqkzGMG4jgX2lkAqvHTYFA1lBzhkQCw7N5CyaQM,1174
|
176
|
-
planar-0.
|
177
|
-
planar-0.
|
178
|
-
planar-0.
|
179
|
-
planar-0.
|
124
|
+
planar-0.11.0.dist-info/WHEEL,sha256=-neZj6nU9KAMg2CnCY6T3w8J53nx1kFGw_9HfoSzM60,79
|
125
|
+
planar-0.11.0.dist-info/entry_points.txt,sha256=L3T0w9u2UPKWXv6JbXFWKU1d5xyEAq1xVWbpYS6mLNg,96
|
126
|
+
planar-0.11.0.dist-info/METADATA,sha256=jlCvhwa-3Djk8_A05TJqgcGxE4Hj5U3wbYrDp5hNSi4,12556
|
127
|
+
planar-0.11.0.dist-info/RECORD,,
|
@@ -1,229 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Tests for agent serialization functionality.
|
3
|
-
|
4
|
-
This module tests the serialization of agents including configuration
|
5
|
-
management and schema validation warnings.
|
6
|
-
"""
|
7
|
-
|
8
|
-
import pytest
|
9
|
-
from pydantic import BaseModel
|
10
|
-
from sqlmodel.ext.asyncio.session import AsyncSession
|
11
|
-
|
12
|
-
from planar.ai.agent import Agent
|
13
|
-
from planar.ai.agent_utils import AgentConfig, agent_configuration
|
14
|
-
from planar.ai.models import AgentSerializeable
|
15
|
-
from planar.ai.utils import serialize_agent
|
16
|
-
from planar.object_config.object_config import ObjectConfigurationBase
|
17
|
-
|
18
|
-
|
19
|
-
class InputModelForTest(BaseModel):
|
20
|
-
"""Test input model for agents."""
|
21
|
-
|
22
|
-
text: str
|
23
|
-
value: int
|
24
|
-
|
25
|
-
|
26
|
-
class OutputModelForTest(BaseModel):
|
27
|
-
"""Test output model for agents."""
|
28
|
-
|
29
|
-
result: str
|
30
|
-
score: float
|
31
|
-
|
32
|
-
|
33
|
-
@pytest.fixture
|
34
|
-
def test_agent():
|
35
|
-
"""Create a test agent with various configurations."""
|
36
|
-
return Agent(
|
37
|
-
name="test_serialization_agent",
|
38
|
-
system_prompt="Test system prompt",
|
39
|
-
user_prompt="Test user prompt: {input}",
|
40
|
-
model="openai:gpt-4o",
|
41
|
-
max_turns=3,
|
42
|
-
input_type=InputModelForTest,
|
43
|
-
output_type=OutputModelForTest,
|
44
|
-
)
|
45
|
-
|
46
|
-
|
47
|
-
@pytest.fixture
|
48
|
-
def test_agent_with_tools():
|
49
|
-
"""Create a test agent with tools."""
|
50
|
-
|
51
|
-
async def test_tool(param: str) -> str:
|
52
|
-
"""A test tool."""
|
53
|
-
return f"Processed: {param}"
|
54
|
-
|
55
|
-
return Agent(
|
56
|
-
name="test_agent_with_tools",
|
57
|
-
system_prompt="System with tools",
|
58
|
-
user_prompt="User: {input}",
|
59
|
-
model="anthropic:claude-3-5-sonnet-latest",
|
60
|
-
max_turns=5,
|
61
|
-
tools=[test_tool],
|
62
|
-
)
|
63
|
-
|
64
|
-
|
65
|
-
async def test_serialize_agent_basic(session: AsyncSession, test_agent):
|
66
|
-
"""Test basic agent serialization without any configurations."""
|
67
|
-
|
68
|
-
# Serialize the agent
|
69
|
-
serialized = await serialize_agent(test_agent)
|
70
|
-
|
71
|
-
# Verify basic fields
|
72
|
-
assert isinstance(serialized, AgentSerializeable)
|
73
|
-
assert serialized.name == "test_serialization_agent"
|
74
|
-
assert serialized.input_schema is not None
|
75
|
-
assert serialized.output_schema is not None
|
76
|
-
assert serialized.tool_definitions == []
|
77
|
-
|
78
|
-
# Verify configs field exists and contains the default config (at least one config always present)
|
79
|
-
assert hasattr(serialized, "configs")
|
80
|
-
assert len(serialized.configs) == 1
|
81
|
-
|
82
|
-
# Verify the default config is present and correct
|
83
|
-
default_config = serialized.configs[-1]
|
84
|
-
assert isinstance(default_config, ObjectConfigurationBase)
|
85
|
-
assert default_config.version == 0
|
86
|
-
assert default_config.data.system_prompt == test_agent.system_prompt
|
87
|
-
assert default_config.data.user_prompt == test_agent.user_prompt
|
88
|
-
assert default_config.data.model == str(test_agent.model)
|
89
|
-
assert default_config.data.max_turns == test_agent.max_turns
|
90
|
-
assert default_config.data.model_parameters == test_agent.model_parameters
|
91
|
-
|
92
|
-
# Verify overwrites field is removed
|
93
|
-
assert not hasattr(serialized, "overwrites")
|
94
|
-
|
95
|
-
|
96
|
-
async def test_serialize_agent_with_configs(session: AsyncSession, test_agent):
|
97
|
-
"""Test agent serialization with multiple configurations."""
|
98
|
-
|
99
|
-
# Create multiple configurations
|
100
|
-
config1 = AgentConfig(
|
101
|
-
system_prompt="Override system 1",
|
102
|
-
user_prompt="Override user 1: {input}",
|
103
|
-
model="openai:gpt-4o",
|
104
|
-
max_turns=2,
|
105
|
-
model_parameters={"temperature": 0.7},
|
106
|
-
)
|
107
|
-
|
108
|
-
config2 = AgentConfig(
|
109
|
-
system_prompt="Override system 2",
|
110
|
-
user_prompt="Override user 2: {input}",
|
111
|
-
model="anthropic:claude-3-opus",
|
112
|
-
max_turns=4,
|
113
|
-
model_parameters={"temperature": 0.9},
|
114
|
-
)
|
115
|
-
|
116
|
-
# Write configurations
|
117
|
-
await agent_configuration.write_config(test_agent.name, config1)
|
118
|
-
await agent_configuration.write_config(test_agent.name, config2)
|
119
|
-
|
120
|
-
# Serialize the agent
|
121
|
-
serialized = await serialize_agent(test_agent)
|
122
|
-
|
123
|
-
# Verify configs are included
|
124
|
-
assert len(serialized.configs) == 3
|
125
|
-
|
126
|
-
# Verify default config is included
|
127
|
-
default_config = serialized.configs[-1]
|
128
|
-
assert isinstance(default_config, ObjectConfigurationBase)
|
129
|
-
assert default_config.version == 0
|
130
|
-
assert default_config.data.system_prompt == test_agent.system_prompt
|
131
|
-
assert default_config.data.user_prompt == test_agent.user_prompt
|
132
|
-
assert default_config.data.model == str(test_agent.model)
|
133
|
-
assert default_config.data.max_turns == test_agent.max_turns
|
134
|
-
assert default_config.data.model_parameters == test_agent.model_parameters
|
135
|
-
|
136
|
-
# Verify configs are ordered by version (descending)
|
137
|
-
assert all(
|
138
|
-
isinstance(config, ObjectConfigurationBase) for config in serialized.configs
|
139
|
-
)
|
140
|
-
assert serialized.configs[0].version == 2 # Latest version first
|
141
|
-
assert serialized.configs[1].version == 1
|
142
|
-
|
143
|
-
# Verify config data
|
144
|
-
latest_config = serialized.configs[0]
|
145
|
-
assert latest_config.data.system_prompt == "Override system 2"
|
146
|
-
assert latest_config.data.user_prompt == "Override user 2: {input}"
|
147
|
-
assert latest_config.data.model == "anthropic:claude-3-opus"
|
148
|
-
assert latest_config.data.max_turns == 4
|
149
|
-
|
150
|
-
older_config = serialized.configs[1]
|
151
|
-
assert older_config.data.system_prompt == "Override system 1"
|
152
|
-
assert older_config.data.user_prompt == "Override user 1: {input}"
|
153
|
-
|
154
|
-
|
155
|
-
async def test_serialize_agent_with_tools(session: AsyncSession, test_agent_with_tools):
|
156
|
-
"""Test serialization of agent with tools."""
|
157
|
-
|
158
|
-
# Serialize the agent
|
159
|
-
serialized = await serialize_agent(test_agent_with_tools)
|
160
|
-
|
161
|
-
# Verify tool definitions are included
|
162
|
-
assert len(serialized.tool_definitions) == 1
|
163
|
-
tool_def = serialized.tool_definitions[0]
|
164
|
-
assert tool_def["name"] == "test_tool"
|
165
|
-
assert tool_def["description"] == "A test tool."
|
166
|
-
assert "parameters" in tool_def
|
167
|
-
|
168
|
-
|
169
|
-
async def test_serialize_agent_no_duplicate_fields(session: AsyncSession, test_agent):
|
170
|
-
"""Test that AgentSerializeable doesn't duplicate fields from AgentConfig."""
|
171
|
-
|
172
|
-
# Create a configuration
|
173
|
-
config = AgentConfig(
|
174
|
-
system_prompt="Config system",
|
175
|
-
user_prompt="Config user: {input}",
|
176
|
-
model="openai:gpt-3.5-turbo",
|
177
|
-
max_turns=1,
|
178
|
-
model_parameters={},
|
179
|
-
)
|
180
|
-
|
181
|
-
await agent_configuration.write_config(test_agent.name, config)
|
182
|
-
|
183
|
-
# Serialize the agent
|
184
|
-
serialized = await serialize_agent(test_agent)
|
185
|
-
|
186
|
-
# Verify that system_prompt, user_prompt, model, max_turns are NOT in the serialized object
|
187
|
-
# They should only be in the configs
|
188
|
-
assert not hasattr(serialized, "system_prompt")
|
189
|
-
assert not hasattr(serialized, "user_prompt")
|
190
|
-
assert not hasattr(serialized, "model")
|
191
|
-
assert not hasattr(serialized, "max_turns")
|
192
|
-
|
193
|
-
# These fields should only be accessible through configs
|
194
|
-
assert serialized.configs[0].data.system_prompt == "Config system"
|
195
|
-
assert serialized.configs[0].data.user_prompt == "Config user: {input}"
|
196
|
-
assert serialized.configs[0].data.model == "openai:gpt-3.5-turbo"
|
197
|
-
assert serialized.configs[0].data.max_turns == 1
|
198
|
-
|
199
|
-
|
200
|
-
async def test_agent_serializable_structure():
|
201
|
-
"""Test the structure of AgentSerializeable model."""
|
202
|
-
# Verify the model has the expected fields
|
203
|
-
fields = AgentSerializeable.model_fields.keys()
|
204
|
-
|
205
|
-
# Should have these fields
|
206
|
-
assert "name" in fields
|
207
|
-
assert "input_schema" in fields
|
208
|
-
assert "output_schema" in fields
|
209
|
-
assert "tool_definitions" in fields
|
210
|
-
assert "configs" in fields
|
211
|
-
assert "built_in_vars" in fields
|
212
|
-
|
213
|
-
# Should NOT have these fields (moved to configs)
|
214
|
-
assert "system_prompt" not in fields
|
215
|
-
assert "user_prompt" not in fields
|
216
|
-
assert "model" not in fields
|
217
|
-
assert "max_turns" not in fields
|
218
|
-
assert "overwrites" not in fields
|
219
|
-
|
220
|
-
|
221
|
-
async def test_configs_field_type():
|
222
|
-
"""Test that configs field has the correct type annotation."""
|
223
|
-
# Get the type annotation for configs field
|
224
|
-
configs_field = AgentSerializeable.model_fields["configs"]
|
225
|
-
|
226
|
-
# The annotation should be list[ObjectConfigurationBase[AgentConfig]]
|
227
|
-
# This is a complex type, so we'll check the string representation
|
228
|
-
assert "ObjectConfigurationBase" in str(configs_field.annotation)
|
229
|
-
assert "AgentConfig" in str(configs_field.annotation)
|