Files
wehub-resource-sync 177604c7d1
Verify and Test / build (3.10) (push) Has been cancelled
Lint / build (3.10) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:42:59 +08:00

447 lines
14 KiB
Python

# Copyright 2026 Emcie Co Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import httpx
from fastapi import status
from lagom import Container
from pytest import mark, raises
from parlant.core.agents import AgentStore
from parlant.core.capabilities import CapabilityStore
from parlant.core.journeys import JourneyStore
from parlant.core.tags import Tag, TagStore
from parlant.core.common import ItemNotFoundError
async def test_that_a_capability_can_be_created(
async_client: httpx.AsyncClient,
) -> None:
payload = {
"title": "Provide Replacement Phone",
"description": "Provide a replacement phone when a customer needs repair for their phone.",
"signals": ["My phone is broken", "I need a replacement while my phone is being repaired"],
}
response = await async_client.post("/capabilities", json=payload)
assert response.status_code == status.HTTP_201_CREATED
capability = response.json()
assert capability["title"] == payload["title"]
assert capability["description"] == payload["description"]
assert capability["signals"] == payload["signals"]
assert capability["tags"] == []
async def test_that_a_capability_can_be_created_with_tags(
async_client: httpx.AsyncClient,
container: Container,
) -> None:
tag_store = container[TagStore]
agent_store = container[AgentStore]
journey_store = container[JourneyStore]
agent = await agent_store.create_agent("Test Agent")
journey = await journey_store.create_journey(
title="Customer Support Journey",
description="A journey for customer support interactions.",
triggers=[],
)
tag1 = await tag_store.create_tag("tag1")
tag2 = await tag_store.create_tag("tag2")
agent_tag = Tag.for_agent_id(agent.id).id
journey_tag = Tag.for_journey_id(journey.id).id
payload = {
"title": "Summarization",
"description": "Summarizes long documents.",
"signals": ["Summarize this article", "Give me a summary"],
"tags": [tag1.id, tag2.id, agent_tag, journey_tag],
}
response = await async_client.post("/capabilities", json=payload)
assert response.status_code == status.HTTP_201_CREATED
capability = response.json()
assert capability["title"] == payload["title"]
assert set(capability["tags"]) == {tag1.id, tag2.id, agent_tag, journey_tag}
async def test_that_capabilities_can_be_listed(
async_client: httpx.AsyncClient,
) -> None:
_ = (
(
await async_client.post(
"/capabilities",
json={
"title": "Provide Replacement Phone",
"description": "Provide a replacement phone when a customer needs repair for their phone.",
"signals": [
"My phone is broken",
"I need a replacement while my phone is being repaired",
],
},
)
)
.raise_for_status()
.json()
)
capabilities = (await async_client.get("/capabilities")).raise_for_status().json()
assert len(capabilities) == 1
assert capabilities[0]["title"] == "Provide Replacement Phone"
async def test_that_a_capability_can_be_read(
async_client: httpx.AsyncClient,
) -> None:
capability = (
(
await async_client.post(
"/capabilities",
json={
"title": "Q&A",
"description": "Answers questions.",
"signals": ["What is Parlant?"],
},
)
)
.raise_for_status()
.json()
)
capability_dto = (
(await async_client.get(f"/capabilities/{capability['id']}")).raise_for_status().json()
)
assert capability_dto["title"] == "Q&A"
assert capability_dto["description"] == "Answers questions."
assert capability_dto["signals"] == ["What is Parlant?"]
@mark.parametrize(
"update_payload, expected_title, expected_description, expected_signals",
[
(
{"title": "New Title"},
"New Title",
"Answers questions.",
["What is Parlant?"],
),
(
{"description": "Updated description"},
"Q&A",
"Updated description",
["What is Parlant?"],
),
(
{"signals": ["How does it work?"]},
"Q&A",
"Answers questions.",
["How does it work?"],
),
],
)
async def test_that_a_capability_can_be_updated(
async_client: httpx.AsyncClient,
update_payload: dict[str, str],
expected_title: str,
expected_description: str,
expected_signals: list[str],
) -> None:
capability = (
(
await async_client.post(
"/capabilities",
json={
"title": "Q&A",
"description": "Answers questions.",
"signals": ["What is Parlant?"],
},
)
)
.raise_for_status()
.json()
)
response = await async_client.patch(f"/capabilities/{capability['id']}", json=update_payload)
response.raise_for_status()
updated_capability = response.json()
assert updated_capability["title"] == expected_title
assert updated_capability["description"] == expected_description
assert updated_capability["signals"] == expected_signals
async def test_that_tags_can_be_added_to_a_capability(
async_client: httpx.AsyncClient,
container: Container,
) -> None:
tag_store = container[TagStore]
tag1 = await tag_store.create_tag("tag1")
tag2 = await tag_store.create_tag("tag2")
capability = (
(
await async_client.post(
"/capabilities",
json={
"title": "Provide Replacement Phone",
"description": "Provide a replacement phone when a customer needs repair for their phone.",
"signals": [
"My phone is broken",
"I need a replacement while my phone is being repaired",
],
},
)
)
.raise_for_status()
.json()
)
update_payload = {"tags": {"add": [tag1.id, tag2.id]}}
response = await async_client.patch(f"/capabilities/{capability['id']}", json=update_payload)
response.raise_for_status()
updated_capability = response.json()
assert tag1.id in updated_capability["tags"]
assert tag2.id in updated_capability["tags"]
async def test_that_tags_can_be_removed_from_a_capability(
async_client: httpx.AsyncClient,
container: Container,
) -> None:
tag_store = container[TagStore]
capability_store = container[CapabilityStore]
tag1 = await tag_store.create_tag("tag1")
tag2 = await tag_store.create_tag("tag2")
capability = await capability_store.create_capability(
title="Translation",
description="Translates text.",
signals=["Translate this sentence"],
tags=[tag1.id, tag2.id],
)
update_payload = {"tags": {"remove": [tag1.id]}}
_ = (
await async_client.patch(f"/capabilities/{capability.id}", json=update_payload)
).raise_for_status()
capability_after_update = (
(await async_client.get(f"/capabilities/{capability.id}")).raise_for_status().json()
)
assert tag1.id not in capability_after_update["tags"]
assert tag2.id in capability_after_update["tags"]
async def test_that_agent_tag_can_be_added_to_a_capability(
async_client: httpx.AsyncClient,
container: Container,
) -> None:
agent = await container[AgentStore].create_agent("Test Agent")
capability = (
(
await async_client.post(
"/capabilities",
json={
"title": "Provide Replacement Phone",
"description": "Provide a replacement phone when a customer needs repair for their phone.",
"signals": [
"My phone is broken",
"I need a replacement while my phone is being repaired",
],
},
)
)
.raise_for_status()
.json()
)
agent_tag = Tag.for_agent_id(agent.id).id
update_payload = {"tags": {"add": [agent_tag]}}
response = await async_client.patch(f"/capabilities/{capability['id']}", json=update_payload)
response.raise_for_status()
updated_capability = response.json()
assert updated_capability["tags"] == [agent_tag]
async def test_that_agent_tag_can_be_removed_from_a_capability(
async_client: httpx.AsyncClient,
container: Container,
) -> None:
tag_store = container[TagStore]
capability_store = container[CapabilityStore]
agent = await container[AgentStore].create_agent("Test Agent")
tag1 = await tag_store.create_tag("tag1")
agent_tag = Tag.for_agent_id(agent.id).id
capability = await capability_store.create_capability(
title="Translation",
description="Translates text.",
signals=["Translate this sentence"],
tags=[agent_tag, tag1.id],
)
update_payload = {"tags": {"remove": [agent_tag]}}
_ = (
await async_client.patch(f"/capabilities/{capability.id}", json=update_payload)
).raise_for_status()
capability_after_update = (
(await async_client.get(f"/capabilities/{capability.id}")).raise_for_status().json()
)
assert agent_tag not in capability_after_update["tags"]
assert tag1.id in capability_after_update["tags"]
async def test_that_journey_tags_can_be_added_to_a_capability(
async_client: httpx.AsyncClient,
container: Container,
) -> None:
tag_store = container[TagStore]
journey_store = container[JourneyStore]
journey = await journey_store.create_journey(
title="Customer Support Journey",
description="A journey for customer support interactions.",
triggers=[],
)
journey_tag = Tag.for_journey_id(journey.id).id
tag1 = await tag_store.create_tag("tag1")
capability = (
(
await async_client.post(
"/capabilities",
json={
"title": "Provide Replacement Phone",
"description": "Provide a replacement phone when a customer needs repair for their phone.",
"signals": [
"My phone is broken",
"I need a replacement while my phone is being repaired",
],
},
)
)
.raise_for_status()
.json()
)
update_payload = {"tags": {"add": [tag1.id, journey_tag]}}
response = await async_client.patch(f"/capabilities/{capability['id']}", json=update_payload)
response.raise_for_status()
updated_capability = response.json()
assert tag1.id in updated_capability["tags"]
assert journey_tag in updated_capability["tags"]
async def test_that_journey_tags_can_be_removed_from_a_capability(
async_client: httpx.AsyncClient,
container: Container,
) -> None:
tag_store = container[TagStore]
capability_store = container[CapabilityStore]
journey_store = container[JourneyStore]
journey = await journey_store.create_journey(
title="Customer Support Journey",
description="A journey for customer support interactions.",
triggers=[],
)
journey_tag = Tag.for_journey_id(journey.id).id
tag1 = await tag_store.create_tag("tag1")
capability = await capability_store.create_capability(
title="Translation",
description="Translates text.",
signals=["Translate this sentence"],
tags=[tag1.id, journey_tag],
)
update_payload = {"tags": {"remove": [journey_tag]}}
_ = (
await async_client.patch(f"/capabilities/{capability.id}", json=update_payload)
).raise_for_status()
capability_after_update = (
(await async_client.get(f"/capabilities/{capability.id}")).raise_for_status().json()
)
assert journey_tag not in capability_after_update["tags"]
assert tag1.id in capability_after_update["tags"]
async def test_that_a_capability_can_be_deleted(
async_client: httpx.AsyncClient,
container: Container,
) -> None:
capability_store = container[CapabilityStore]
capability = await capability_store.create_capability(
title="Provide Replacement Phone",
description="Provide a replacement phone when a customer needs repair for their phone.",
signals=["My phone is broken", "I need a replacement while my phone is being repaired"],
)
delete_response = await async_client.delete(f"/capabilities/{capability.id}")
assert delete_response.status_code == status.HTTP_204_NO_CONTENT
with raises(ItemNotFoundError):
await capability_store.read_capability(capability.id)
async def test_that_capabilities_can_be_filtered_by_tag(
async_client: httpx.AsyncClient,
container: Container,
) -> None:
tag_store = container[TagStore]
capability_store = container[CapabilityStore]
tag = await tag_store.create_tag("tag1")
_ = await capability_store.create_capability(
title="Provide Replacement Phone",
description="Provide a replacement phone when a customer needs repair for their phone.",
signals=["My phone is broken", "I need a replacement while my phone is being repaired"],
tags=[tag.id],
)
_ = await capability_store.create_capability(
title="Reset Password",
description="Helping customer reset their account password",
signals=["My password isn't what I thought"],
)
response = await async_client.get(f"/capabilities?tag_id={tag.id}")
response.raise_for_status()
capabilities = response.json()
assert len(capabilities) == 1