applied-cli 0.5.55__tar.gz → 0.5.57__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.55 → applied_cli-0.5.57}/PKG-INFO +1 -1
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli/__init__.py +1 -1
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli/cli.py +297 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli/client.py +135 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli/tools.py +217 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli.egg-info/PKG-INFO +1 -1
- {applied_cli-0.5.55 → applied_cli-0.5.57}/pyproject.toml +1 -1
- {applied_cli-0.5.55 → applied_cli-0.5.57}/README.md +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli/agent_scoped_flows.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli/conversation_lookup.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli/conversations.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli/credentials.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli/flow_helpers.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli/formatters.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli.egg-info/SOURCES.txt +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli.egg-info/dependency_links.txt +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli.egg-info/entry_points.txt +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli.egg-info/requires.txt +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/applied_cli.egg-info/top_level.txt +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/setup.cfg +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/tests/test_agent_scoped_flows.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/tests/test_audit_tools.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/tests/test_benchmark_scenario_tools.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/tests/test_cli.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/tests/test_client.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/tests/test_conversation_tools.py +0 -0
- {applied_cli-0.5.55 → applied_cli-0.5.57}/tests/test_flow_tools.py +0 -0
|
@@ -1853,6 +1853,303 @@ def connector_types(
|
|
|
1853
1853
|
typer.echo(result)
|
|
1854
1854
|
|
|
1855
1855
|
|
|
1856
|
+
@app.command("agent-update")
|
|
1857
|
+
def agent_update(
|
|
1858
|
+
id: str = typer.Argument(..., help="Agent ID"),
|
|
1859
|
+
name: str = typer.Option(None, "--name", help="Agent name"),
|
|
1860
|
+
prompt: str = typer.Option(None, "--prompt", help="Guidance/guardrails text"),
|
|
1861
|
+
model: str = typer.Option(None, "--model", help="Model name"),
|
|
1862
|
+
modality: str = typer.Option(
|
|
1863
|
+
None, "--modality", help="Modality: Chat, Email, Call, SMS, All"
|
|
1864
|
+
),
|
|
1865
|
+
agent_type: str = typer.Option(
|
|
1866
|
+
None, "--type", help="Type: Customer Support, Generic, etc."
|
|
1867
|
+
),
|
|
1868
|
+
escalation_mode: str = typer.Option(
|
|
1869
|
+
None,
|
|
1870
|
+
"--escalation-mode",
|
|
1871
|
+
help="Escalation mode: default, email, sms, email_non_opening_hours, ticketing_integration",
|
|
1872
|
+
),
|
|
1873
|
+
auto_reply: bool = typer.Option(None, "--auto-reply", help="Enable auto-reply"),
|
|
1874
|
+
metadata: str = typer.Option(
|
|
1875
|
+
None, "--metadata", help="JSON metadata to set on the agent"
|
|
1876
|
+
),
|
|
1877
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
1878
|
+
) -> None:
|
|
1879
|
+
"""Update an agent."""
|
|
1880
|
+
metadata_dict = _parse_json_option(metadata, option_name="--metadata")
|
|
1881
|
+
client = get_client(shop_id=shop_id)
|
|
1882
|
+
result = asyncio.run(
|
|
1883
|
+
tools.agent_update(
|
|
1884
|
+
client,
|
|
1885
|
+
id,
|
|
1886
|
+
name=name,
|
|
1887
|
+
prompt=prompt,
|
|
1888
|
+
model=model,
|
|
1889
|
+
modality=modality,
|
|
1890
|
+
agent_type=agent_type,
|
|
1891
|
+
escalation_mode=escalation_mode,
|
|
1892
|
+
auto_reply=auto_reply,
|
|
1893
|
+
metadata=metadata_dict,
|
|
1894
|
+
)
|
|
1895
|
+
)
|
|
1896
|
+
typer.echo(result)
|
|
1897
|
+
|
|
1898
|
+
|
|
1899
|
+
@app.command("knowledge-create")
|
|
1900
|
+
def knowledge_create(
|
|
1901
|
+
kb_type: str = typer.Option(
|
|
1902
|
+
..., "--type", "-t", help="Type: qa, exact, escalate, context, greeting, signature"
|
|
1903
|
+
),
|
|
1904
|
+
question: str = typer.Option(..., "--question", "-q", help="Trigger text / question"),
|
|
1905
|
+
answer: str = typer.Option(..., "--answer", "-a", help="Response text / answer"),
|
|
1906
|
+
guardrail: str = typer.Option("", "--guardrail", help="Guardrail instructions"),
|
|
1907
|
+
active: bool = typer.Option(True, "--active/--inactive", help="Whether the item is active"),
|
|
1908
|
+
agent_ids: str = typer.Option(
|
|
1909
|
+
None, "--agent-ids", help="Comma-separated agent UUIDs (empty = shop-wide)"
|
|
1910
|
+
),
|
|
1911
|
+
label_id: str = typer.Option(None, "--label-id", help="Topic label UUID"),
|
|
1912
|
+
flow_id: str = typer.Option(None, "--flow-id", help="Flow UUID to associate with"),
|
|
1913
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
1914
|
+
) -> None:
|
|
1915
|
+
"""Create a knowledge base item."""
|
|
1916
|
+
parsed_agent_ids = _parse_csv_option(agent_ids)
|
|
1917
|
+
client = get_client(shop_id=shop_id)
|
|
1918
|
+
result = asyncio.run(
|
|
1919
|
+
tools.knowledge_create(
|
|
1920
|
+
client,
|
|
1921
|
+
kb_type=kb_type,
|
|
1922
|
+
question=question,
|
|
1923
|
+
answer=answer,
|
|
1924
|
+
guardrail=guardrail,
|
|
1925
|
+
active=active,
|
|
1926
|
+
agent_ids=parsed_agent_ids,
|
|
1927
|
+
label_id=label_id,
|
|
1928
|
+
flow_id=flow_id,
|
|
1929
|
+
)
|
|
1930
|
+
)
|
|
1931
|
+
typer.echo(result)
|
|
1932
|
+
|
|
1933
|
+
|
|
1934
|
+
@app.command("knowledge-update")
|
|
1935
|
+
def knowledge_update(
|
|
1936
|
+
id: str = typer.Argument(..., help="Knowledge item ID"),
|
|
1937
|
+
question: str = typer.Option(None, "--question", "-q", help="Trigger text / question"),
|
|
1938
|
+
answer: str = typer.Option(None, "--answer", "-a", help="Response text / answer"),
|
|
1939
|
+
guardrail: str = typer.Option(None, "--guardrail", help="Guardrail instructions"),
|
|
1940
|
+
active: bool = typer.Option(None, "--active/--inactive", help="Whether the item is active"),
|
|
1941
|
+
agent_ids: str = typer.Option(
|
|
1942
|
+
None, "--agent-ids", help="Comma-separated agent UUIDs (empty string = shop-wide)"
|
|
1943
|
+
),
|
|
1944
|
+
label_id: str = typer.Option(None, "--label-id", help="Topic label UUID"),
|
|
1945
|
+
flow_id: str = typer.Option(None, "--flow-id", help="Flow UUID to associate with"),
|
|
1946
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
1947
|
+
) -> None:
|
|
1948
|
+
"""Update a knowledge base item."""
|
|
1949
|
+
parsed_agent_ids = _parse_csv_option(agent_ids) if agent_ids is not None else None
|
|
1950
|
+
# Allow --agent-ids "" to clear scoping (set to shop-wide)
|
|
1951
|
+
if agent_ids is not None and parsed_agent_ids is None:
|
|
1952
|
+
parsed_agent_ids = []
|
|
1953
|
+
client = get_client(shop_id=shop_id)
|
|
1954
|
+
result = asyncio.run(
|
|
1955
|
+
tools.knowledge_update(
|
|
1956
|
+
client,
|
|
1957
|
+
id,
|
|
1958
|
+
question=question,
|
|
1959
|
+
answer=answer,
|
|
1960
|
+
guardrail=guardrail,
|
|
1961
|
+
active=active,
|
|
1962
|
+
agent_ids=parsed_agent_ids,
|
|
1963
|
+
label_id=label_id,
|
|
1964
|
+
flow_id=flow_id,
|
|
1965
|
+
)
|
|
1966
|
+
)
|
|
1967
|
+
typer.echo(result)
|
|
1968
|
+
|
|
1969
|
+
|
|
1970
|
+
@app.command("product-create")
|
|
1971
|
+
def product_create(
|
|
1972
|
+
title: str = typer.Option(..., "--title", help="Product title"),
|
|
1973
|
+
description: str = typer.Option("", "--description", help="Product description"),
|
|
1974
|
+
url: str = typer.Option("", "--url", help="Product page URL"),
|
|
1975
|
+
images: str = typer.Option(None, "--images", help="Comma-separated image URLs"),
|
|
1976
|
+
price: str = typer.Option(None, "--price", help="Price (e.g. '29.99')"),
|
|
1977
|
+
compare_at_price: str = typer.Option(None, "--compare-at-price", help="Compare-at price"),
|
|
1978
|
+
currency: str = typer.Option("USD", "--currency", help="Currency code"),
|
|
1979
|
+
rating: float = typer.Option(None, "--rating", help="Average rating"),
|
|
1980
|
+
review_count: int = typer.Option(None, "--review-count", help="Number of reviews"),
|
|
1981
|
+
status: str = typer.Option("Active", "--status", help="Status: Active, Draft, Pending"),
|
|
1982
|
+
auto_generate_kb: bool = typer.Option(
|
|
1983
|
+
True, "--auto-generate-kb/--no-auto-generate-kb", help="Auto-generate Q&A"
|
|
1984
|
+
),
|
|
1985
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
1986
|
+
) -> None:
|
|
1987
|
+
"""Create a product."""
|
|
1988
|
+
parsed_images = _parse_csv_option(images)
|
|
1989
|
+
client = get_client(shop_id=shop_id)
|
|
1990
|
+
result = asyncio.run(
|
|
1991
|
+
tools.product_create(
|
|
1992
|
+
client,
|
|
1993
|
+
title=title,
|
|
1994
|
+
description=description,
|
|
1995
|
+
url=url,
|
|
1996
|
+
images=parsed_images,
|
|
1997
|
+
price=price,
|
|
1998
|
+
compare_at_price=compare_at_price,
|
|
1999
|
+
currency=currency,
|
|
2000
|
+
rating=rating,
|
|
2001
|
+
review_count=review_count,
|
|
2002
|
+
status=status,
|
|
2003
|
+
auto_generate_kb=auto_generate_kb,
|
|
2004
|
+
)
|
|
2005
|
+
)
|
|
2006
|
+
typer.echo(result)
|
|
2007
|
+
|
|
2008
|
+
|
|
2009
|
+
@app.command("taxonomy-create")
|
|
2010
|
+
def taxonomy_create(
|
|
2011
|
+
name: str = typer.Option(..., "--name", "-n", help="Topic or intent name"),
|
|
2012
|
+
parent_id: str = typer.Option(
|
|
2013
|
+
None, "--parent-id", help="Parent topic UUID (if set, creates an intent)"
|
|
2014
|
+
),
|
|
2015
|
+
color: str = typer.Option(None, "--color", help="Color"),
|
|
2016
|
+
description: str = typer.Option(None, "--description", help="Description"),
|
|
2017
|
+
comments: str = typer.Option(None, "--comments", help="Example queries (3 per line)"),
|
|
2018
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2019
|
+
) -> None:
|
|
2020
|
+
"""Create a topic or intent."""
|
|
2021
|
+
client = get_client(shop_id=shop_id)
|
|
2022
|
+
result = asyncio.run(
|
|
2023
|
+
tools.taxonomy_create(
|
|
2024
|
+
client,
|
|
2025
|
+
name=name,
|
|
2026
|
+
parent_id=parent_id,
|
|
2027
|
+
color=color,
|
|
2028
|
+
description=description,
|
|
2029
|
+
comments=comments,
|
|
2030
|
+
)
|
|
2031
|
+
)
|
|
2032
|
+
typer.echo(result)
|
|
2033
|
+
|
|
2034
|
+
|
|
2035
|
+
@app.command("taxonomy-update")
|
|
2036
|
+
def taxonomy_update(
|
|
2037
|
+
id: str = typer.Argument(..., help="Topic or intent ID"),
|
|
2038
|
+
name: str = typer.Option(None, "--name", "-n", help="Name"),
|
|
2039
|
+
color: str = typer.Option(None, "--color", help="Color"),
|
|
2040
|
+
description: str = typer.Option(None, "--description", help="Description"),
|
|
2041
|
+
comments: str = typer.Option(None, "--comments", help="Example queries"),
|
|
2042
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2043
|
+
) -> None:
|
|
2044
|
+
"""Update a topic or intent."""
|
|
2045
|
+
client = get_client(shop_id=shop_id)
|
|
2046
|
+
result = asyncio.run(
|
|
2047
|
+
tools.taxonomy_update(
|
|
2048
|
+
client,
|
|
2049
|
+
id,
|
|
2050
|
+
name=name,
|
|
2051
|
+
color=color,
|
|
2052
|
+
description=description,
|
|
2053
|
+
comments=comments,
|
|
2054
|
+
)
|
|
2055
|
+
)
|
|
2056
|
+
typer.echo(result)
|
|
2057
|
+
|
|
2058
|
+
|
|
2059
|
+
@app.command("agent-create")
|
|
2060
|
+
def agent_create(
|
|
2061
|
+
name: str = typer.Option(..., "--name", help="Agent name"),
|
|
2062
|
+
modality: str = typer.Option(
|
|
2063
|
+
..., "--modality", help="Modality: Chat, Email, Call, SMS, All"
|
|
2064
|
+
),
|
|
2065
|
+
agent_type: str = typer.Option(
|
|
2066
|
+
"Customer Support", "--type", help="Type: Customer Support, Generic, etc."
|
|
2067
|
+
),
|
|
2068
|
+
model: str = typer.Option("GPT-4.1-mini", "--model", help="Model name"),
|
|
2069
|
+
prompt: str = typer.Option("", "--prompt", help="Guidance/guardrails text"),
|
|
2070
|
+
escalation_mode: str = typer.Option(
|
|
2071
|
+
"default",
|
|
2072
|
+
"--escalation-mode",
|
|
2073
|
+
help="Escalation mode: default, email, sms, email_non_opening_hours, ticketing_integration",
|
|
2074
|
+
),
|
|
2075
|
+
auto_reply: bool = typer.Option(False, "--auto-reply", help="Enable auto-reply"),
|
|
2076
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2077
|
+
) -> None:
|
|
2078
|
+
"""Create a new agent."""
|
|
2079
|
+
client = get_client(shop_id=shop_id)
|
|
2080
|
+
result = asyncio.run(
|
|
2081
|
+
tools.agent_create(
|
|
2082
|
+
client,
|
|
2083
|
+
name=name,
|
|
2084
|
+
modality=modality,
|
|
2085
|
+
agent_type=agent_type,
|
|
2086
|
+
model=model,
|
|
2087
|
+
prompt=prompt,
|
|
2088
|
+
escalation_mode=escalation_mode,
|
|
2089
|
+
auto_reply=auto_reply,
|
|
2090
|
+
)
|
|
2091
|
+
)
|
|
2092
|
+
typer.echo(result)
|
|
2093
|
+
|
|
2094
|
+
|
|
2095
|
+
@app.command("agent-set-picture")
|
|
2096
|
+
def agent_set_picture(
|
|
2097
|
+
id: str = typer.Argument(..., help="Agent ID"),
|
|
2098
|
+
image: str = typer.Option(
|
|
2099
|
+
..., "--image", "-i", help="Path to image file (PNG, JPG, etc.)"
|
|
2100
|
+
),
|
|
2101
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2102
|
+
) -> None:
|
|
2103
|
+
"""Set an agent's profile picture."""
|
|
2104
|
+
client = get_client(shop_id=shop_id)
|
|
2105
|
+
result = asyncio.run(tools.agent_set_picture(client, id, image))
|
|
2106
|
+
typer.echo(result)
|
|
2107
|
+
|
|
2108
|
+
|
|
2109
|
+
@app.command("agent-delete")
|
|
2110
|
+
def agent_delete(
|
|
2111
|
+
id: str = typer.Argument(..., help="Agent ID"),
|
|
2112
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2113
|
+
) -> None:
|
|
2114
|
+
"""Delete an agent."""
|
|
2115
|
+
client = get_client(shop_id=shop_id)
|
|
2116
|
+
result = asyncio.run(tools.agent_delete(client, id))
|
|
2117
|
+
typer.echo(result)
|
|
2118
|
+
|
|
2119
|
+
|
|
2120
|
+
@app.command("knowledge-delete")
|
|
2121
|
+
def knowledge_delete(
|
|
2122
|
+
id: str = typer.Argument(..., help="Knowledge item ID"),
|
|
2123
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2124
|
+
) -> None:
|
|
2125
|
+
"""Delete a knowledge base item."""
|
|
2126
|
+
client = get_client(shop_id=shop_id)
|
|
2127
|
+
result = asyncio.run(tools.knowledge_delete(client, id))
|
|
2128
|
+
typer.echo(result)
|
|
2129
|
+
|
|
2130
|
+
|
|
2131
|
+
@app.command("product-delete")
|
|
2132
|
+
def product_delete(
|
|
2133
|
+
id: str = typer.Argument(..., help="Product ID"),
|
|
2134
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2135
|
+
) -> None:
|
|
2136
|
+
"""Delete a product."""
|
|
2137
|
+
client = get_client(shop_id=shop_id)
|
|
2138
|
+
result = asyncio.run(tools.product_delete(client, id))
|
|
2139
|
+
typer.echo(result)
|
|
2140
|
+
|
|
2141
|
+
|
|
2142
|
+
@app.command("taxonomy-delete")
|
|
2143
|
+
def taxonomy_delete(
|
|
2144
|
+
id: str = typer.Argument(..., help="Topic or intent ID"),
|
|
2145
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2146
|
+
) -> None:
|
|
2147
|
+
"""Delete a topic or intent."""
|
|
2148
|
+
client = get_client(shop_id=shop_id)
|
|
2149
|
+
result = asyncio.run(tools.taxonomy_delete(client, id))
|
|
2150
|
+
typer.echo(result)
|
|
2151
|
+
|
|
2152
|
+
|
|
1856
2153
|
def main() -> None:
|
|
1857
2154
|
"""CLI entrypoint."""
|
|
1858
2155
|
nested_exit_code = run_agent_scoped_flow_command(sys.argv[1:], get_client)
|
|
@@ -382,6 +382,50 @@ class AppliedClient:
|
|
|
382
382
|
return None
|
|
383
383
|
return resp.json()
|
|
384
384
|
|
|
385
|
+
async def _upload_request(
|
|
386
|
+
self,
|
|
387
|
+
method: str,
|
|
388
|
+
path: str,
|
|
389
|
+
files: dict[str, Any],
|
|
390
|
+
data: dict[str, Any] | None = None,
|
|
391
|
+
) -> Any:
|
|
392
|
+
"""Make an authenticated multipart file upload request."""
|
|
393
|
+
headers = {
|
|
394
|
+
"Authorization": f"Bearer {self.token}",
|
|
395
|
+
}
|
|
396
|
+
if self.shop_id:
|
|
397
|
+
headers["X-Shop-Id"] = self.shop_id
|
|
398
|
+
url = f"{self.base_url}{path}"
|
|
399
|
+
|
|
400
|
+
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
|
401
|
+
resp = await client.request(
|
|
402
|
+
method, url, headers=headers, files=files, data=data or {}
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
if resp.status_code >= 400:
|
|
406
|
+
detail = ""
|
|
407
|
+
try:
|
|
408
|
+
err_data = resp.json()
|
|
409
|
+
if isinstance(err_data, dict):
|
|
410
|
+
detail = str(
|
|
411
|
+
err_data.get("detail")
|
|
412
|
+
or err_data.get("error")
|
|
413
|
+
or err_data.get("message")
|
|
414
|
+
or ""
|
|
415
|
+
)
|
|
416
|
+
except Exception:
|
|
417
|
+
detail = resp.text[:200] if resp.text else ""
|
|
418
|
+
|
|
419
|
+
raise AppliedAPIError(
|
|
420
|
+
message=f"{method} {path} failed",
|
|
421
|
+
status_code=resp.status_code,
|
|
422
|
+
detail=detail,
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
if resp.status_code == 204:
|
|
426
|
+
return None
|
|
427
|
+
return resp.json()
|
|
428
|
+
|
|
385
429
|
def _require_shop_id(self, shop_id: str | None = None) -> str:
|
|
386
430
|
resolved_shop_id = shop_id or self.shop_id
|
|
387
431
|
if not resolved_shop_id:
|
|
@@ -431,6 +475,59 @@ class AppliedClient:
|
|
|
431
475
|
)
|
|
432
476
|
return self._normalize_response(data)
|
|
433
477
|
|
|
478
|
+
async def create_agent(
|
|
479
|
+
self,
|
|
480
|
+
name: str,
|
|
481
|
+
modality: str,
|
|
482
|
+
agent_type: str = "Customer Support",
|
|
483
|
+
model: str = "GPT-4.1-mini",
|
|
484
|
+
prompt: str = "",
|
|
485
|
+
escalation_mode: str = "default",
|
|
486
|
+
auto_reply: bool = False,
|
|
487
|
+
) -> dict:
|
|
488
|
+
"""Create a new agent."""
|
|
489
|
+
body: dict[str, Any] = {
|
|
490
|
+
"name": name,
|
|
491
|
+
"modality": modality,
|
|
492
|
+
"type": agent_type,
|
|
493
|
+
"model": model,
|
|
494
|
+
"escalation_mode": escalation_mode,
|
|
495
|
+
"auto_reply": auto_reply,
|
|
496
|
+
}
|
|
497
|
+
if prompt:
|
|
498
|
+
body["prompt"] = prompt
|
|
499
|
+
return await self._request("POST", "/v1/agents/", body=body)
|
|
500
|
+
|
|
501
|
+
async def update_agent(
|
|
502
|
+
self,
|
|
503
|
+
agent_id: str,
|
|
504
|
+
**kwargs: Any,
|
|
505
|
+
) -> dict:
|
|
506
|
+
"""Update an agent's properties."""
|
|
507
|
+
return await self._request(
|
|
508
|
+
"PATCH", f"/v1/agents/{agent_id}/", body=kwargs
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
async def update_agent_picture(
|
|
512
|
+
self,
|
|
513
|
+
agent_id: str,
|
|
514
|
+
image_path: str,
|
|
515
|
+
) -> dict:
|
|
516
|
+
"""Update an agent's profile picture via file upload."""
|
|
517
|
+
import mimetypes
|
|
518
|
+
|
|
519
|
+
content_type = mimetypes.guess_type(image_path)[0] or "image/png"
|
|
520
|
+
filename = image_path.rsplit("/", 1)[-1]
|
|
521
|
+
with open(image_path, "rb") as f:
|
|
522
|
+
files = {"profile_picture": (filename, f, content_type)}
|
|
523
|
+
return await self._upload_request(
|
|
524
|
+
"PATCH", f"/v1/agents/{agent_id}/", files=files
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
async def delete_agent(self, agent_id: str) -> None:
|
|
528
|
+
"""Delete an agent."""
|
|
529
|
+
await self._request("DELETE", f"/v1/agents/{agent_id}/")
|
|
530
|
+
|
|
434
531
|
# -------------------------------------------------------------------------
|
|
435
532
|
# Connector Types
|
|
436
533
|
# -------------------------------------------------------------------------
|
|
@@ -471,6 +568,40 @@ class AppliedClient:
|
|
|
471
568
|
data = await self._request("GET", "/v1/property-choices/", params=params)
|
|
472
569
|
return self._normalize_response(data)
|
|
473
570
|
|
|
571
|
+
async def create_taxonomy(
|
|
572
|
+
self,
|
|
573
|
+
name: str,
|
|
574
|
+
parent_id: str | None = None,
|
|
575
|
+
color: str | None = None,
|
|
576
|
+
description: str | None = None,
|
|
577
|
+
comments: str | None = None,
|
|
578
|
+
) -> dict:
|
|
579
|
+
"""Create a topic or intent (property choice)."""
|
|
580
|
+
body: dict[str, Any] = {"name": name}
|
|
581
|
+
if parent_id:
|
|
582
|
+
body["parent_choice_id"] = parent_id
|
|
583
|
+
if color:
|
|
584
|
+
body["color"] = color
|
|
585
|
+
if description:
|
|
586
|
+
body["description"] = description
|
|
587
|
+
if comments:
|
|
588
|
+
body["comments"] = comments
|
|
589
|
+
return await self._request("POST", "/v1/property-choices/", body=body)
|
|
590
|
+
|
|
591
|
+
async def update_taxonomy(
|
|
592
|
+
self,
|
|
593
|
+
choice_id: str,
|
|
594
|
+
**kwargs: Any,
|
|
595
|
+
) -> dict:
|
|
596
|
+
"""Update a topic or intent (property choice)."""
|
|
597
|
+
return await self._request(
|
|
598
|
+
"PATCH", f"/v1/property-choices/{choice_id}/", body=kwargs
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
async def delete_taxonomy(self, choice_id: str) -> None:
|
|
602
|
+
"""Delete a topic or intent (property choice)."""
|
|
603
|
+
await self._request("DELETE", f"/v1/property-choices/{choice_id}/")
|
|
604
|
+
|
|
474
605
|
# -------------------------------------------------------------------------
|
|
475
606
|
# Analytics
|
|
476
607
|
# -------------------------------------------------------------------------
|
|
@@ -2057,6 +2188,10 @@ class AppliedClient:
|
|
|
2057
2188
|
"PATCH", f"/v1/responses/{response_id}/", body=kwargs
|
|
2058
2189
|
)
|
|
2059
2190
|
|
|
2191
|
+
async def delete_response(self, response_id: str) -> None:
|
|
2192
|
+
"""Delete a knowledge base item."""
|
|
2193
|
+
await self._request("DELETE", f"/v1/responses/{response_id}/")
|
|
2194
|
+
|
|
2060
2195
|
# -------------------------------------------------------------------------
|
|
2061
2196
|
# Products (Content type=Product)
|
|
2062
2197
|
# -------------------------------------------------------------------------
|
|
@@ -5598,6 +5598,9 @@ async def knowledge_update(
|
|
|
5598
5598
|
answer: str | None = None,
|
|
5599
5599
|
guardrail: str | None = None,
|
|
5600
5600
|
active: bool | None = None,
|
|
5601
|
+
agent_ids: list[str] | None = None,
|
|
5602
|
+
label_id: str | None = None,
|
|
5603
|
+
flow_id: str | None = None,
|
|
5601
5604
|
) -> str:
|
|
5602
5605
|
"""
|
|
5603
5606
|
Update a knowledge base item.
|
|
@@ -5609,6 +5612,9 @@ async def knowledge_update(
|
|
|
5609
5612
|
answer: New answer/response text
|
|
5610
5613
|
guardrail: New guardrail instructions
|
|
5611
5614
|
active: Enable/disable the item
|
|
5615
|
+
agent_ids: List of agent UUIDs to scope to (empty list = shop-wide)
|
|
5616
|
+
label_id: Topic label UUID
|
|
5617
|
+
flow_id: Flow UUID to associate with
|
|
5612
5618
|
|
|
5613
5619
|
Returns:
|
|
5614
5620
|
Updated knowledge item
|
|
@@ -5622,6 +5628,12 @@ async def knowledge_update(
|
|
|
5622
5628
|
updates["guardrail"] = guardrail
|
|
5623
5629
|
if active is not None:
|
|
5624
5630
|
updates["active"] = active
|
|
5631
|
+
if agent_ids is not None:
|
|
5632
|
+
updates["agents"] = agent_ids
|
|
5633
|
+
if label_id is not None:
|
|
5634
|
+
updates["label"] = label_id
|
|
5635
|
+
if flow_id is not None:
|
|
5636
|
+
updates["flow"] = flow_id
|
|
5625
5637
|
|
|
5626
5638
|
try:
|
|
5627
5639
|
item = await client.update_response(knowledge_id, **updates)
|
|
@@ -5941,3 +5953,208 @@ async def product_delete(
|
|
|
5941
5953
|
return _format_error(e)
|
|
5942
5954
|
|
|
5943
5955
|
return f"Product {product_id} deleted successfully."
|
|
5956
|
+
|
|
5957
|
+
|
|
5958
|
+
# -----------------------------------------------------------------------------
|
|
5959
|
+
# Agent - Create / Update / Delete
|
|
5960
|
+
# -----------------------------------------------------------------------------
|
|
5961
|
+
|
|
5962
|
+
|
|
5963
|
+
async def agent_create(
|
|
5964
|
+
client: AppliedClient,
|
|
5965
|
+
name: str,
|
|
5966
|
+
modality: str,
|
|
5967
|
+
agent_type: str = "Customer Support",
|
|
5968
|
+
model: str = "GPT-4.1-mini",
|
|
5969
|
+
prompt: str = "",
|
|
5970
|
+
escalation_mode: str = "default",
|
|
5971
|
+
auto_reply: bool = False,
|
|
5972
|
+
) -> str:
|
|
5973
|
+
"""Create a new agent."""
|
|
5974
|
+
try:
|
|
5975
|
+
agent = await client.create_agent(
|
|
5976
|
+
name=name,
|
|
5977
|
+
modality=modality,
|
|
5978
|
+
agent_type=agent_type,
|
|
5979
|
+
model=model,
|
|
5980
|
+
prompt=prompt,
|
|
5981
|
+
escalation_mode=escalation_mode,
|
|
5982
|
+
auto_reply=auto_reply,
|
|
5983
|
+
)
|
|
5984
|
+
except AppliedAPIError as e:
|
|
5985
|
+
return _format_error(e)
|
|
5986
|
+
|
|
5987
|
+
result = "# Created Agent\n"
|
|
5988
|
+
result += f"id: {agent.get('id')}\n"
|
|
5989
|
+
result += f"name: {agent.get('name')}\n"
|
|
5990
|
+
result += f"modality: {agent.get('modality')}\n"
|
|
5991
|
+
return result
|
|
5992
|
+
|
|
5993
|
+
|
|
5994
|
+
async def agent_update(
|
|
5995
|
+
client: AppliedClient,
|
|
5996
|
+
agent_id: str,
|
|
5997
|
+
name: str | None = None,
|
|
5998
|
+
prompt: str | None = None,
|
|
5999
|
+
model: str | None = None,
|
|
6000
|
+
modality: str | None = None,
|
|
6001
|
+
agent_type: str | None = None,
|
|
6002
|
+
escalation_mode: str | None = None,
|
|
6003
|
+
auto_reply: bool | None = None,
|
|
6004
|
+
metadata: dict | None = None,
|
|
6005
|
+
) -> str:
|
|
6006
|
+
"""Update an agent's properties."""
|
|
6007
|
+
updates: dict = {}
|
|
6008
|
+
if name is not None:
|
|
6009
|
+
updates["name"] = name
|
|
6010
|
+
if prompt is not None:
|
|
6011
|
+
updates["prompt"] = prompt
|
|
6012
|
+
if model is not None:
|
|
6013
|
+
updates["model"] = model
|
|
6014
|
+
if modality is not None:
|
|
6015
|
+
updates["modality"] = modality
|
|
6016
|
+
if agent_type is not None:
|
|
6017
|
+
updates["type"] = agent_type
|
|
6018
|
+
if escalation_mode is not None:
|
|
6019
|
+
updates["escalation_mode"] = escalation_mode
|
|
6020
|
+
if auto_reply is not None:
|
|
6021
|
+
updates["auto_reply"] = auto_reply
|
|
6022
|
+
if metadata is not None:
|
|
6023
|
+
updates["metadata"] = metadata
|
|
6024
|
+
|
|
6025
|
+
try:
|
|
6026
|
+
agent = await client.update_agent(agent_id, **updates)
|
|
6027
|
+
except AppliedAPIError as e:
|
|
6028
|
+
return _format_error(e)
|
|
6029
|
+
|
|
6030
|
+
result = "# Updated Agent\n"
|
|
6031
|
+
result += f"id: {agent.get('id')}\n"
|
|
6032
|
+
result += f"name: {agent.get('name')}\n"
|
|
6033
|
+
result += f"modality: {agent.get('modality')}\n"
|
|
6034
|
+
return result
|
|
6035
|
+
|
|
6036
|
+
|
|
6037
|
+
async def agent_set_picture(
|
|
6038
|
+
client: AppliedClient,
|
|
6039
|
+
agent_id: str,
|
|
6040
|
+
image_path: str,
|
|
6041
|
+
) -> str:
|
|
6042
|
+
"""Set an agent's profile picture from a local file."""
|
|
6043
|
+
import os
|
|
6044
|
+
|
|
6045
|
+
if not os.path.isfile(image_path):
|
|
6046
|
+
return f"Error: File not found: {image_path}"
|
|
6047
|
+
|
|
6048
|
+
try:
|
|
6049
|
+
agent = await client.update_agent_picture(agent_id, image_path)
|
|
6050
|
+
except AppliedAPIError as e:
|
|
6051
|
+
return _format_error(e)
|
|
6052
|
+
|
|
6053
|
+
result = "# Updated Agent Picture\n"
|
|
6054
|
+
result += f"id: {agent.get('id')}\n"
|
|
6055
|
+
result += f"name: {agent.get('name')}\n"
|
|
6056
|
+
result += f"profile_picture: {agent.get('profile_picture')}\n"
|
|
6057
|
+
return result
|
|
6058
|
+
|
|
6059
|
+
|
|
6060
|
+
async def agent_delete(
|
|
6061
|
+
client: AppliedClient,
|
|
6062
|
+
agent_id: str,
|
|
6063
|
+
) -> str:
|
|
6064
|
+
"""Delete an agent."""
|
|
6065
|
+
try:
|
|
6066
|
+
await client.delete_agent(agent_id)
|
|
6067
|
+
except AppliedAPIError as e:
|
|
6068
|
+
return _format_error(e)
|
|
6069
|
+
|
|
6070
|
+
return f"Agent {agent_id} deleted successfully."
|
|
6071
|
+
|
|
6072
|
+
|
|
6073
|
+
# -----------------------------------------------------------------------------
|
|
6074
|
+
# Knowledge Base - Delete
|
|
6075
|
+
# -----------------------------------------------------------------------------
|
|
6076
|
+
|
|
6077
|
+
|
|
6078
|
+
async def knowledge_delete(
|
|
6079
|
+
client: AppliedClient,
|
|
6080
|
+
knowledge_id: str,
|
|
6081
|
+
) -> str:
|
|
6082
|
+
"""Delete a knowledge base item."""
|
|
6083
|
+
try:
|
|
6084
|
+
await client.delete_response(knowledge_id)
|
|
6085
|
+
except AppliedAPIError as e:
|
|
6086
|
+
return _format_error(e)
|
|
6087
|
+
|
|
6088
|
+
return f"Knowledge item {knowledge_id} deleted successfully."
|
|
6089
|
+
|
|
6090
|
+
|
|
6091
|
+
# -----------------------------------------------------------------------------
|
|
6092
|
+
# Taxonomy - Create / Update / Delete
|
|
6093
|
+
# -----------------------------------------------------------------------------
|
|
6094
|
+
|
|
6095
|
+
|
|
6096
|
+
async def taxonomy_create(
|
|
6097
|
+
client: AppliedClient,
|
|
6098
|
+
name: str,
|
|
6099
|
+
parent_id: str | None = None,
|
|
6100
|
+
color: str | None = None,
|
|
6101
|
+
description: str | None = None,
|
|
6102
|
+
comments: str | None = None,
|
|
6103
|
+
) -> str:
|
|
6104
|
+
"""Create a topic or intent."""
|
|
6105
|
+
try:
|
|
6106
|
+
item = await client.create_taxonomy(
|
|
6107
|
+
name=name,
|
|
6108
|
+
parent_id=parent_id,
|
|
6109
|
+
color=color,
|
|
6110
|
+
description=description,
|
|
6111
|
+
comments=comments,
|
|
6112
|
+
)
|
|
6113
|
+
except AppliedAPIError as e:
|
|
6114
|
+
return _format_error(e)
|
|
6115
|
+
|
|
6116
|
+
item_type = "intent" if parent_id else "topic"
|
|
6117
|
+
result = f"# Created {item_type.title()}\n"
|
|
6118
|
+
result += f"id: {item.get('id')}\n"
|
|
6119
|
+
result += f"name: {item.get('name')}\n"
|
|
6120
|
+
return result
|
|
6121
|
+
|
|
6122
|
+
|
|
6123
|
+
async def taxonomy_update(
|
|
6124
|
+
client: AppliedClient,
|
|
6125
|
+
choice_id: str,
|
|
6126
|
+
name: str | None = None,
|
|
6127
|
+
color: str | None = None,
|
|
6128
|
+
description: str | None = None,
|
|
6129
|
+
comments: str | None = None,
|
|
6130
|
+
) -> str:
|
|
6131
|
+
"""Update a topic or intent."""
|
|
6132
|
+
updates: dict = {}
|
|
6133
|
+
if name is not None:
|
|
6134
|
+
updates["name"] = name
|
|
6135
|
+
if color is not None:
|
|
6136
|
+
updates["color"] = color
|
|
6137
|
+
if description is not None:
|
|
6138
|
+
updates["description"] = description
|
|
6139
|
+
if comments is not None:
|
|
6140
|
+
updates["comments"] = comments
|
|
6141
|
+
|
|
6142
|
+
try:
|
|
6143
|
+
item = await client.update_taxonomy(choice_id, **updates)
|
|
6144
|
+
except AppliedAPIError as e:
|
|
6145
|
+
return _format_error(e)
|
|
6146
|
+
|
|
6147
|
+
return f"# Updated Taxonomy Item\nid: {item.get('id')}\nname: {item.get('name')}"
|
|
6148
|
+
|
|
6149
|
+
|
|
6150
|
+
async def taxonomy_delete(
|
|
6151
|
+
client: AppliedClient,
|
|
6152
|
+
choice_id: str,
|
|
6153
|
+
) -> str:
|
|
6154
|
+
"""Delete a topic or intent."""
|
|
6155
|
+
try:
|
|
6156
|
+
await client.delete_taxonomy(choice_id)
|
|
6157
|
+
except AppliedAPIError as e:
|
|
6158
|
+
return _format_error(e)
|
|
6159
|
+
|
|
6160
|
+
return f"Taxonomy item {choice_id} deleted successfully."
|
|
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
|