applied-cli 0.5.67__tar.gz → 0.5.69__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.
- {applied_cli-0.5.67 → applied_cli-0.5.69}/PKG-INFO +1 -1
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli/__init__.py +1 -1
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli/agent_scoped_flows.py +10 -13
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli/client.py +37 -4
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli/tools.py +22 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli.egg-info/PKG-INFO +1 -1
- {applied_cli-0.5.67 → applied_cli-0.5.69}/pyproject.toml +1 -1
- {applied_cli-0.5.67 → applied_cli-0.5.69}/tests/test_agent_scoped_flows.py +11 -4
- {applied_cli-0.5.67 → applied_cli-0.5.69}/README.md +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli/cli.py +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli/conversation_lookup.py +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli/conversations.py +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli/credentials.py +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli/flow_helpers.py +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli/formatters.py +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli.egg-info/SOURCES.txt +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli.egg-info/dependency_links.txt +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli.egg-info/entry_points.txt +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli.egg-info/requires.txt +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/applied_cli.egg-info/top_level.txt +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/setup.cfg +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/tests/test_audit_tools.py +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/tests/test_benchmark_scenario_tools.py +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/tests/test_cli.py +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/tests/test_client.py +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/tests/test_conversation_tools.py +0 -0
- {applied_cli-0.5.67 → applied_cli-0.5.69}/tests/test_flow_tools.py +0 -0
|
@@ -42,9 +42,7 @@ def _parse_json_option(value: str | None, *, option_name: str) -> dict[str, Any]
|
|
|
42
42
|
) from exc
|
|
43
43
|
|
|
44
44
|
if not isinstance(parsed, dict):
|
|
45
|
-
raise AgentScopedFlowCLIError(
|
|
46
|
-
f"{option_name} must decode to a JSON object."
|
|
47
|
-
)
|
|
45
|
+
raise AgentScopedFlowCLIError(f"{option_name} must decode to a JSON object.")
|
|
48
46
|
|
|
49
47
|
return parsed
|
|
50
48
|
|
|
@@ -123,7 +121,9 @@ async def _handle_flow_delete(
|
|
|
123
121
|
get_client: Callable[[str | None], AppliedClient],
|
|
124
122
|
) -> int:
|
|
125
123
|
client = get_client(args.shop_id)
|
|
126
|
-
flow = await _get_flow_for_agent(
|
|
124
|
+
flow = await _get_flow_for_agent(
|
|
125
|
+
client, agent_id=args.agent_id, flow_id=args.flow_id
|
|
126
|
+
)
|
|
127
127
|
await client.delete_flow(args.flow_id)
|
|
128
128
|
if args.format == "json":
|
|
129
129
|
pass
|
|
@@ -139,12 +139,6 @@ async def _handle_node_create(
|
|
|
139
139
|
client = get_client(args.shop_id)
|
|
140
140
|
await _get_flow_for_agent(client, agent_id=args.agent_id, flow_id=args.flow_id)
|
|
141
141
|
|
|
142
|
-
if args.guardrail:
|
|
143
|
-
raise AgentScopedFlowCLIError(
|
|
144
|
-
"--guardrail is not supported on node create because the API does not "
|
|
145
|
-
"persist it. Create the node first, then run node update --guardrail."
|
|
146
|
-
)
|
|
147
|
-
|
|
148
142
|
node = await client.create_node(
|
|
149
143
|
flow_id=args.flow_id,
|
|
150
144
|
name=normalize_executor_type(args.executor_type),
|
|
@@ -193,11 +187,12 @@ async def _handle_node_delete(
|
|
|
193
187
|
get_client: Callable[[str | None], AppliedClient],
|
|
194
188
|
) -> int:
|
|
195
189
|
client = get_client(args.shop_id)
|
|
196
|
-
flow = await _get_flow_for_agent(
|
|
190
|
+
flow = await _get_flow_for_agent(
|
|
191
|
+
client, agent_id=args.agent_id, flow_id=args.flow_id
|
|
192
|
+
)
|
|
197
193
|
|
|
198
194
|
graph = flow.get("graph") or {}
|
|
199
195
|
nodes = graph.get("nodes") or []
|
|
200
|
-
edges = graph.get("edges") or []
|
|
201
196
|
node = next((item for item in nodes if item.get("id") == args.node_id), None)
|
|
202
197
|
if node is None:
|
|
203
198
|
raise AgentScopedFlowCLIError(
|
|
@@ -265,7 +260,9 @@ async def _handle_edge_delete(
|
|
|
265
260
|
get_client: Callable[[str | None], AppliedClient],
|
|
266
261
|
) -> int:
|
|
267
262
|
client = get_client(args.shop_id)
|
|
268
|
-
flow = await _get_flow_for_agent(
|
|
263
|
+
flow = await _get_flow_for_agent(
|
|
264
|
+
client, agent_id=args.agent_id, flow_id=args.flow_id
|
|
265
|
+
)
|
|
269
266
|
|
|
270
267
|
graph = flow.get("graph") or {}
|
|
271
268
|
edges = graph.get("edges") or []
|
|
@@ -1777,6 +1777,10 @@ class AppliedClient:
|
|
|
1777
1777
|
},
|
|
1778
1778
|
)
|
|
1779
1779
|
|
|
1780
|
+
async def delete_benchmark(self, benchmark_id: str) -> None:
|
|
1781
|
+
"""Delete a benchmark."""
|
|
1782
|
+
await self._request("DELETE", f"/v1/conversation-benchmarks/{benchmark_id}/")
|
|
1783
|
+
|
|
1780
1784
|
# -------------------------------------------------------------------------
|
|
1781
1785
|
# Scenarios
|
|
1782
1786
|
# -------------------------------------------------------------------------
|
|
@@ -1786,9 +1790,18 @@ class AppliedClient:
|
|
|
1786
1790
|
benchmark_id: str | None = None,
|
|
1787
1791
|
agent_id: str | None = None,
|
|
1788
1792
|
pass_status: str | None = None,
|
|
1789
|
-
limit: int =
|
|
1793
|
+
limit: int = 200,
|
|
1794
|
+
fetch_all: bool = True,
|
|
1790
1795
|
) -> list[dict]:
|
|
1791
|
-
"""List conversation scenarios.
|
|
1796
|
+
"""List conversation scenarios.
|
|
1797
|
+
|
|
1798
|
+
Args:
|
|
1799
|
+
benchmark_id: Filter by benchmark UUID
|
|
1800
|
+
agent_id: Filter by agent UUID
|
|
1801
|
+
pass_status: Filter by pass status ('pass', 'fail', 'unrated')
|
|
1802
|
+
limit: Page size (default 200)
|
|
1803
|
+
fetch_all: If True, paginate through all results (default True)
|
|
1804
|
+
"""
|
|
1792
1805
|
params: dict[str, Any] = {"limit": limit}
|
|
1793
1806
|
if benchmark_id:
|
|
1794
1807
|
params["benchmark_id"] = benchmark_id
|
|
@@ -1796,8 +1809,28 @@ class AppliedClient:
|
|
|
1796
1809
|
params["agent_id"] = agent_id
|
|
1797
1810
|
if pass_status:
|
|
1798
1811
|
params["pass_status"] = pass_status
|
|
1799
|
-
|
|
1800
|
-
|
|
1812
|
+
|
|
1813
|
+
if not fetch_all:
|
|
1814
|
+
data = await self._request(
|
|
1815
|
+
"GET", "/v1/conversation-scenarios/", params=params
|
|
1816
|
+
)
|
|
1817
|
+
return self._normalize_response(data)
|
|
1818
|
+
|
|
1819
|
+
# Paginate through all results
|
|
1820
|
+
all_results: list[dict] = []
|
|
1821
|
+
page = 1
|
|
1822
|
+
while True:
|
|
1823
|
+
params["page"] = page
|
|
1824
|
+
data = await self._request(
|
|
1825
|
+
"GET", "/v1/conversation-scenarios/", params=params
|
|
1826
|
+
)
|
|
1827
|
+
results = self._normalize_response(data)
|
|
1828
|
+
all_results.extend(results)
|
|
1829
|
+
if isinstance(data, dict) and data.get("next"):
|
|
1830
|
+
page += 1
|
|
1831
|
+
else:
|
|
1832
|
+
break
|
|
1833
|
+
return all_results
|
|
1801
1834
|
|
|
1802
1835
|
async def get_scenario(self, scenario_id: str) -> dict:
|
|
1803
1836
|
"""Get a single scenario by ID."""
|
|
@@ -4604,6 +4604,28 @@ async def benchmark_create(
|
|
|
4604
4604
|
return result
|
|
4605
4605
|
|
|
4606
4606
|
|
|
4607
|
+
async def benchmark_delete(
|
|
4608
|
+
client: AppliedClient,
|
|
4609
|
+
benchmark_id: str,
|
|
4610
|
+
) -> str:
|
|
4611
|
+
"""
|
|
4612
|
+
Delete a benchmark.
|
|
4613
|
+
|
|
4614
|
+
Args:
|
|
4615
|
+
client: Authenticated AppliedClient
|
|
4616
|
+
benchmark_id: The benchmark UUID
|
|
4617
|
+
|
|
4618
|
+
Returns:
|
|
4619
|
+
Success message
|
|
4620
|
+
"""
|
|
4621
|
+
try:
|
|
4622
|
+
await client.delete_benchmark(benchmark_id)
|
|
4623
|
+
except AppliedAPIError as e:
|
|
4624
|
+
return _format_error(e)
|
|
4625
|
+
|
|
4626
|
+
return f"Benchmark {benchmark_id} deleted successfully."
|
|
4627
|
+
|
|
4628
|
+
|
|
4607
4629
|
# -----------------------------------------------------------------------------
|
|
4608
4630
|
# Scenarios
|
|
4609
4631
|
# -----------------------------------------------------------------------------
|
|
@@ -282,7 +282,7 @@ async def test_node_create_prints_raw_json(capsys):
|
|
|
282
282
|
|
|
283
283
|
|
|
284
284
|
@pytest.mark.asyncio
|
|
285
|
-
async def
|
|
285
|
+
async def test_node_create_accepts_guardrail_on_create():
|
|
286
286
|
client = StubClient()
|
|
287
287
|
args = _parse_args(
|
|
288
288
|
[
|
|
@@ -299,8 +299,11 @@ async def test_node_create_rejects_guardrail_on_create():
|
|
|
299
299
|
]
|
|
300
300
|
)
|
|
301
301
|
|
|
302
|
-
|
|
303
|
-
|
|
302
|
+
exit_code = await _handle_node_create(args, lambda _shop_id: client)
|
|
303
|
+
|
|
304
|
+
assert exit_code == 0
|
|
305
|
+
assert client.created_node_args is not None
|
|
306
|
+
assert client.created_node_args["guardrail"] == "Be careful"
|
|
304
307
|
|
|
305
308
|
|
|
306
309
|
@pytest.mark.asyncio
|
|
@@ -347,7 +350,11 @@ async def test_node_update_prints_raw_json(capsys):
|
|
|
347
350
|
|
|
348
351
|
assert exit_code == 0
|
|
349
352
|
assert client.updated_node_args == ("flow-1", "node-1", {"prompt": "hi"})
|
|
350
|
-
assert json.loads(capsys.readouterr().out) == {
|
|
353
|
+
assert json.loads(capsys.readouterr().out) == {
|
|
354
|
+
**client.node,
|
|
355
|
+
"id": "node-1",
|
|
356
|
+
"prompt": "hi",
|
|
357
|
+
}
|
|
351
358
|
|
|
352
359
|
|
|
353
360
|
@pytest.mark.asyncio
|
|
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
|