applied-cli 0.5.54__tar.gz → 0.5.56__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.54 → applied_cli-0.5.56}/PKG-INFO +1 -1
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli/__init__.py +1 -1
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli/cli.py +285 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli/client.py +138 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli/flow_helpers.py +3 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli/tools.py +270 -7
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli.egg-info/PKG-INFO +1 -1
- {applied_cli-0.5.54 → applied_cli-0.5.56}/pyproject.toml +1 -1
- {applied_cli-0.5.54 → applied_cli-0.5.56}/README.md +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli/agent_scoped_flows.py +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli/conversation_lookup.py +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli/conversations.py +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli/credentials.py +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli/formatters.py +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli.egg-info/SOURCES.txt +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli.egg-info/dependency_links.txt +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli.egg-info/entry_points.txt +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli.egg-info/requires.txt +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/applied_cli.egg-info/top_level.txt +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/setup.cfg +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/tests/test_agent_scoped_flows.py +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/tests/test_audit_tools.py +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/tests/test_benchmark_scenario_tools.py +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/tests/test_cli.py +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/tests/test_client.py +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/tests/test_conversation_tools.py +0 -0
- {applied_cli-0.5.54 → applied_cli-0.5.56}/tests/test_flow_tools.py +0 -0
|
@@ -1853,6 +1853,291 @@ 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
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
1942
|
+
) -> None:
|
|
1943
|
+
"""Update a knowledge base item."""
|
|
1944
|
+
client = get_client(shop_id=shop_id)
|
|
1945
|
+
result = asyncio.run(
|
|
1946
|
+
tools.knowledge_update(
|
|
1947
|
+
client,
|
|
1948
|
+
id,
|
|
1949
|
+
question=question,
|
|
1950
|
+
answer=answer,
|
|
1951
|
+
guardrail=guardrail,
|
|
1952
|
+
active=active,
|
|
1953
|
+
)
|
|
1954
|
+
)
|
|
1955
|
+
typer.echo(result)
|
|
1956
|
+
|
|
1957
|
+
|
|
1958
|
+
@app.command("product-create")
|
|
1959
|
+
def product_create(
|
|
1960
|
+
title: str = typer.Option(..., "--title", help="Product title"),
|
|
1961
|
+
description: str = typer.Option("", "--description", help="Product description"),
|
|
1962
|
+
url: str = typer.Option("", "--url", help="Product page URL"),
|
|
1963
|
+
images: str = typer.Option(None, "--images", help="Comma-separated image URLs"),
|
|
1964
|
+
price: str = typer.Option(None, "--price", help="Price (e.g. '29.99')"),
|
|
1965
|
+
compare_at_price: str = typer.Option(None, "--compare-at-price", help="Compare-at price"),
|
|
1966
|
+
currency: str = typer.Option("USD", "--currency", help="Currency code"),
|
|
1967
|
+
rating: float = typer.Option(None, "--rating", help="Average rating"),
|
|
1968
|
+
review_count: int = typer.Option(None, "--review-count", help="Number of reviews"),
|
|
1969
|
+
status: str = typer.Option("Active", "--status", help="Status: Active, Draft, Pending"),
|
|
1970
|
+
auto_generate_kb: bool = typer.Option(
|
|
1971
|
+
True, "--auto-generate-kb/--no-auto-generate-kb", help="Auto-generate Q&A"
|
|
1972
|
+
),
|
|
1973
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
1974
|
+
) -> None:
|
|
1975
|
+
"""Create a product."""
|
|
1976
|
+
parsed_images = _parse_csv_option(images)
|
|
1977
|
+
client = get_client(shop_id=shop_id)
|
|
1978
|
+
result = asyncio.run(
|
|
1979
|
+
tools.product_create(
|
|
1980
|
+
client,
|
|
1981
|
+
title=title,
|
|
1982
|
+
description=description,
|
|
1983
|
+
url=url,
|
|
1984
|
+
images=parsed_images,
|
|
1985
|
+
price=price,
|
|
1986
|
+
compare_at_price=compare_at_price,
|
|
1987
|
+
currency=currency,
|
|
1988
|
+
rating=rating,
|
|
1989
|
+
review_count=review_count,
|
|
1990
|
+
status=status,
|
|
1991
|
+
auto_generate_kb=auto_generate_kb,
|
|
1992
|
+
)
|
|
1993
|
+
)
|
|
1994
|
+
typer.echo(result)
|
|
1995
|
+
|
|
1996
|
+
|
|
1997
|
+
@app.command("taxonomy-create")
|
|
1998
|
+
def taxonomy_create(
|
|
1999
|
+
name: str = typer.Option(..., "--name", "-n", help="Topic or intent name"),
|
|
2000
|
+
parent_id: str = typer.Option(
|
|
2001
|
+
None, "--parent-id", help="Parent topic UUID (if set, creates an intent)"
|
|
2002
|
+
),
|
|
2003
|
+
color: str = typer.Option(None, "--color", help="Color"),
|
|
2004
|
+
description: str = typer.Option(None, "--description", help="Description"),
|
|
2005
|
+
comments: str = typer.Option(None, "--comments", help="Example queries (3 per line)"),
|
|
2006
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2007
|
+
) -> None:
|
|
2008
|
+
"""Create a topic or intent."""
|
|
2009
|
+
client = get_client(shop_id=shop_id)
|
|
2010
|
+
result = asyncio.run(
|
|
2011
|
+
tools.taxonomy_create(
|
|
2012
|
+
client,
|
|
2013
|
+
name=name,
|
|
2014
|
+
parent_id=parent_id,
|
|
2015
|
+
color=color,
|
|
2016
|
+
description=description,
|
|
2017
|
+
comments=comments,
|
|
2018
|
+
)
|
|
2019
|
+
)
|
|
2020
|
+
typer.echo(result)
|
|
2021
|
+
|
|
2022
|
+
|
|
2023
|
+
@app.command("taxonomy-update")
|
|
2024
|
+
def taxonomy_update(
|
|
2025
|
+
id: str = typer.Argument(..., help="Topic or intent ID"),
|
|
2026
|
+
name: str = typer.Option(None, "--name", "-n", help="Name"),
|
|
2027
|
+
color: str = typer.Option(None, "--color", help="Color"),
|
|
2028
|
+
description: str = typer.Option(None, "--description", help="Description"),
|
|
2029
|
+
comments: str = typer.Option(None, "--comments", help="Example queries"),
|
|
2030
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2031
|
+
) -> None:
|
|
2032
|
+
"""Update a topic or intent."""
|
|
2033
|
+
client = get_client(shop_id=shop_id)
|
|
2034
|
+
result = asyncio.run(
|
|
2035
|
+
tools.taxonomy_update(
|
|
2036
|
+
client,
|
|
2037
|
+
id,
|
|
2038
|
+
name=name,
|
|
2039
|
+
color=color,
|
|
2040
|
+
description=description,
|
|
2041
|
+
comments=comments,
|
|
2042
|
+
)
|
|
2043
|
+
)
|
|
2044
|
+
typer.echo(result)
|
|
2045
|
+
|
|
2046
|
+
|
|
2047
|
+
@app.command("agent-create")
|
|
2048
|
+
def agent_create(
|
|
2049
|
+
name: str = typer.Option(..., "--name", help="Agent name"),
|
|
2050
|
+
modality: str = typer.Option(
|
|
2051
|
+
..., "--modality", help="Modality: Chat, Email, Call, SMS, All"
|
|
2052
|
+
),
|
|
2053
|
+
agent_type: str = typer.Option(
|
|
2054
|
+
"Customer Support", "--type", help="Type: Customer Support, Generic, etc."
|
|
2055
|
+
),
|
|
2056
|
+
model: str = typer.Option("GPT-4.1-mini", "--model", help="Model name"),
|
|
2057
|
+
prompt: str = typer.Option("", "--prompt", help="Guidance/guardrails text"),
|
|
2058
|
+
escalation_mode: str = typer.Option(
|
|
2059
|
+
"default",
|
|
2060
|
+
"--escalation-mode",
|
|
2061
|
+
help="Escalation mode: default, email, sms, email_non_opening_hours, ticketing_integration",
|
|
2062
|
+
),
|
|
2063
|
+
auto_reply: bool = typer.Option(False, "--auto-reply", help="Enable auto-reply"),
|
|
2064
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2065
|
+
) -> None:
|
|
2066
|
+
"""Create a new agent."""
|
|
2067
|
+
client = get_client(shop_id=shop_id)
|
|
2068
|
+
result = asyncio.run(
|
|
2069
|
+
tools.agent_create(
|
|
2070
|
+
client,
|
|
2071
|
+
name=name,
|
|
2072
|
+
modality=modality,
|
|
2073
|
+
agent_type=agent_type,
|
|
2074
|
+
model=model,
|
|
2075
|
+
prompt=prompt,
|
|
2076
|
+
escalation_mode=escalation_mode,
|
|
2077
|
+
auto_reply=auto_reply,
|
|
2078
|
+
)
|
|
2079
|
+
)
|
|
2080
|
+
typer.echo(result)
|
|
2081
|
+
|
|
2082
|
+
|
|
2083
|
+
@app.command("agent-set-picture")
|
|
2084
|
+
def agent_set_picture(
|
|
2085
|
+
id: str = typer.Argument(..., help="Agent ID"),
|
|
2086
|
+
image: str = typer.Option(
|
|
2087
|
+
..., "--image", "-i", help="Path to image file (PNG, JPG, etc.)"
|
|
2088
|
+
),
|
|
2089
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2090
|
+
) -> None:
|
|
2091
|
+
"""Set an agent's profile picture."""
|
|
2092
|
+
client = get_client(shop_id=shop_id)
|
|
2093
|
+
result = asyncio.run(tools.agent_set_picture(client, id, image))
|
|
2094
|
+
typer.echo(result)
|
|
2095
|
+
|
|
2096
|
+
|
|
2097
|
+
@app.command("agent-delete")
|
|
2098
|
+
def agent_delete(
|
|
2099
|
+
id: str = typer.Argument(..., help="Agent ID"),
|
|
2100
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2101
|
+
) -> None:
|
|
2102
|
+
"""Delete an agent."""
|
|
2103
|
+
client = get_client(shop_id=shop_id)
|
|
2104
|
+
result = asyncio.run(tools.agent_delete(client, id))
|
|
2105
|
+
typer.echo(result)
|
|
2106
|
+
|
|
2107
|
+
|
|
2108
|
+
@app.command("knowledge-delete")
|
|
2109
|
+
def knowledge_delete(
|
|
2110
|
+
id: str = typer.Argument(..., help="Knowledge item ID"),
|
|
2111
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2112
|
+
) -> None:
|
|
2113
|
+
"""Delete a knowledge base item."""
|
|
2114
|
+
client = get_client(shop_id=shop_id)
|
|
2115
|
+
result = asyncio.run(tools.knowledge_delete(client, id))
|
|
2116
|
+
typer.echo(result)
|
|
2117
|
+
|
|
2118
|
+
|
|
2119
|
+
@app.command("product-delete")
|
|
2120
|
+
def product_delete(
|
|
2121
|
+
id: str = typer.Argument(..., help="Product ID"),
|
|
2122
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2123
|
+
) -> None:
|
|
2124
|
+
"""Delete a product."""
|
|
2125
|
+
client = get_client(shop_id=shop_id)
|
|
2126
|
+
result = asyncio.run(tools.product_delete(client, id))
|
|
2127
|
+
typer.echo(result)
|
|
2128
|
+
|
|
2129
|
+
|
|
2130
|
+
@app.command("taxonomy-delete")
|
|
2131
|
+
def taxonomy_delete(
|
|
2132
|
+
id: str = typer.Argument(..., help="Topic or intent ID"),
|
|
2133
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2134
|
+
) -> None:
|
|
2135
|
+
"""Delete a topic or intent."""
|
|
2136
|
+
client = get_client(shop_id=shop_id)
|
|
2137
|
+
result = asyncio.run(tools.taxonomy_delete(client, id))
|
|
2138
|
+
typer.echo(result)
|
|
2139
|
+
|
|
2140
|
+
|
|
1856
2141
|
def main() -> None:
|
|
1857
2142
|
"""CLI entrypoint."""
|
|
1858
2143
|
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
|
# -------------------------------------------------------------------------
|
|
@@ -1174,6 +1305,7 @@ class AppliedClient:
|
|
|
1174
1305
|
source_handle: str | None = None,
|
|
1175
1306
|
target_handle: str | None = None,
|
|
1176
1307
|
label: str | None = None,
|
|
1308
|
+
metadata: dict[str, Any] | None = None,
|
|
1177
1309
|
) -> dict:
|
|
1178
1310
|
"""Create an edge connecting two nodes."""
|
|
1179
1311
|
body: dict[str, Any] = {
|
|
@@ -1186,6 +1318,8 @@ class AppliedClient:
|
|
|
1186
1318
|
body["target_handle"] = target_handle
|
|
1187
1319
|
if label:
|
|
1188
1320
|
body["label"] = label
|
|
1321
|
+
if metadata:
|
|
1322
|
+
body["metadata"] = metadata
|
|
1189
1323
|
|
|
1190
1324
|
return await self._request(
|
|
1191
1325
|
"POST",
|
|
@@ -2054,6 +2188,10 @@ class AppliedClient:
|
|
|
2054
2188
|
"PATCH", f"/v1/responses/{response_id}/", body=kwargs
|
|
2055
2189
|
)
|
|
2056
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
|
+
|
|
2057
2195
|
# -------------------------------------------------------------------------
|
|
2058
2196
|
# Products (Content type=Product)
|
|
2059
2197
|
# -------------------------------------------------------------------------
|
|
@@ -28,6 +28,7 @@ _CANONICAL_EXECUTOR_TYPES: tuple[str, ...] = (
|
|
|
28
28
|
"mutate_ticket",
|
|
29
29
|
"mutate_conversation",
|
|
30
30
|
"mutate_message",
|
|
31
|
+
"end_conversation",
|
|
31
32
|
)
|
|
32
33
|
|
|
33
34
|
_EXECUTOR_UI_LABELS: dict[str, str] = {
|
|
@@ -49,6 +50,7 @@ _EXECUTOR_UI_LABELS: dict[str, str] = {
|
|
|
49
50
|
"mutate_ticket": "Ticket",
|
|
50
51
|
"mutate_conversation": "Conversation",
|
|
51
52
|
"mutate_message": "Add Message",
|
|
53
|
+
"end_conversation": "End Conversation",
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
_EXECUTOR_ALIASES: dict[str, tuple[str, ...]] = {
|
|
@@ -70,6 +72,7 @@ _EXECUTOR_ALIASES: dict[str, tuple[str, ...]] = {
|
|
|
70
72
|
"mutate_ticket": ("ticket",),
|
|
71
73
|
"mutate_conversation": ("conversation",),
|
|
72
74
|
"mutate_message": ("add message",),
|
|
75
|
+
"end_conversation": ("end conversation", "end call", "close conversation"),
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
_BRANCH_DEFAULT_ALIASES = {
|
|
@@ -2500,6 +2500,9 @@ async def flow_edge_create(
|
|
|
2500
2500
|
branch: str | int | None = None,
|
|
2501
2501
|
target_handle: str | None = None,
|
|
2502
2502
|
label: str | None = None,
|
|
2503
|
+
metadata: dict | None = None,
|
|
2504
|
+
temporal_timeout_seconds: int | None = None,
|
|
2505
|
+
temporal_disabled_contact_groups: dict | None = None,
|
|
2503
2506
|
) -> str:
|
|
2504
2507
|
"""
|
|
2505
2508
|
Connect two nodes with an edge.
|
|
@@ -2513,7 +2516,14 @@ async def flow_edge_create(
|
|
|
2513
2516
|
branch: Branch path alias for conversational branch nodes, e.g. "1",
|
|
2514
2517
|
"branch 2", or "default". Preferred over source_handle for branch nodes.
|
|
2515
2518
|
target_handle: Input handle name (for mapping)
|
|
2516
|
-
label: Edge label/condition
|
|
2519
|
+
label: Edge label/condition describing when to traverse this edge
|
|
2520
|
+
metadata: Edge metadata dict. For temporal edges, include a "temporal"
|
|
2521
|
+
key (or use the temporal_* convenience params below).
|
|
2522
|
+
temporal_timeout_seconds: Convenience param to create a temporal edge
|
|
2523
|
+
that auto-fires after this many seconds of inactivity.
|
|
2524
|
+
temporal_disabled_contact_groups: Optional dict of contact group
|
|
2525
|
+
overrides for the temporal edge, e.g.
|
|
2526
|
+
{"__default__": false, "<group_id>": true}.
|
|
2517
2527
|
|
|
2518
2528
|
Returns:
|
|
2519
2529
|
Created edge
|
|
@@ -2523,6 +2533,14 @@ async def flow_edge_create(
|
|
|
2523
2533
|
|
|
2524
2534
|
resolved_source_handle = normalize_branch_handle(branch or source_handle)
|
|
2525
2535
|
|
|
2536
|
+
# Build metadata with temporal settings
|
|
2537
|
+
metadata = dict(metadata or {})
|
|
2538
|
+
if temporal_timeout_seconds is not None:
|
|
2539
|
+
temporal = metadata.setdefault("temporal", {})
|
|
2540
|
+
temporal["timeout_seconds"] = temporal_timeout_seconds
|
|
2541
|
+
if temporal_disabled_contact_groups is not None:
|
|
2542
|
+
temporal["disabled_contact_groups"] = temporal_disabled_contact_groups
|
|
2543
|
+
|
|
2526
2544
|
try:
|
|
2527
2545
|
flow = await client.get_flow(flow_id)
|
|
2528
2546
|
except AppliedAPIError as e:
|
|
@@ -2589,6 +2607,7 @@ async def flow_edge_create(
|
|
|
2589
2607
|
source_handle=resolved_source_handle,
|
|
2590
2608
|
target_handle=target_handle,
|
|
2591
2609
|
label=label,
|
|
2610
|
+
metadata=metadata or None,
|
|
2592
2611
|
)
|
|
2593
2612
|
except AppliedAPIError as e:
|
|
2594
2613
|
# Add extra context for edge errors
|
|
@@ -2602,14 +2621,33 @@ async def flow_edge_create(
|
|
|
2602
2621
|
)
|
|
2603
2622
|
return _format_error(e) + extra
|
|
2604
2623
|
|
|
2624
|
+
edge_id = edge.get("id")
|
|
2625
|
+
|
|
2626
|
+
# Follow-up update to persist label and metadata (backend create
|
|
2627
|
+
# endpoint may not pass these through to the model).
|
|
2628
|
+
needs_update = label or metadata
|
|
2629
|
+
if needs_update and edge_id:
|
|
2630
|
+
updates: dict = {}
|
|
2631
|
+
if label:
|
|
2632
|
+
updates["label"] = label
|
|
2633
|
+
if metadata:
|
|
2634
|
+
updates["metadata"] = metadata
|
|
2635
|
+
try:
|
|
2636
|
+
edge = await client.update_edge(flow_id, edge_id, **updates)
|
|
2637
|
+
except AppliedAPIError:
|
|
2638
|
+
pass # best-effort; edge was already created
|
|
2639
|
+
|
|
2605
2640
|
result = "# Created Edge\n"
|
|
2606
|
-
result += f"id: {
|
|
2641
|
+
result += f"id: {edge_id}\n"
|
|
2607
2642
|
result += f"source: {edge.get('source')}\n"
|
|
2608
2643
|
result += f"target: {edge.get('target')}\n"
|
|
2609
2644
|
if resolved_source_handle is not None:
|
|
2610
2645
|
result += f"source_handle: {resolved_source_handle}\n"
|
|
2611
2646
|
if label:
|
|
2612
2647
|
result += f"label: {label}\n"
|
|
2648
|
+
if metadata.get("temporal"):
|
|
2649
|
+
temporal = metadata["temporal"]
|
|
2650
|
+
result += f"temporal_timeout_seconds: {temporal.get('timeout_seconds')}\n"
|
|
2613
2651
|
result += "\nTip: run flow_layout(flow_id) after wiring a complex flow to tidy node positions.\n"
|
|
2614
2652
|
|
|
2615
2653
|
return result
|
|
@@ -2666,6 +2704,8 @@ async def flow_edge_update(
|
|
|
2666
2704
|
edge_id: str,
|
|
2667
2705
|
label: str | None = None,
|
|
2668
2706
|
metadata: dict | None = None,
|
|
2707
|
+
temporal_timeout_seconds: int | None = None,
|
|
2708
|
+
temporal_disabled_contact_groups: dict | None = None,
|
|
2669
2709
|
) -> str:
|
|
2670
2710
|
"""
|
|
2671
2711
|
Update an edge's properties.
|
|
@@ -2674,21 +2714,39 @@ async def flow_edge_update(
|
|
|
2674
2714
|
client: Authenticated AppliedClient
|
|
2675
2715
|
flow_id: The flow UUID
|
|
2676
2716
|
edge_id: The edge UUID
|
|
2677
|
-
label: New label/condition
|
|
2678
|
-
metadata: New metadata
|
|
2717
|
+
label: New label/condition describing when to traverse this edge
|
|
2718
|
+
metadata: New metadata dict. For temporal edges, include a "temporal"
|
|
2719
|
+
key or use the temporal_* convenience params.
|
|
2720
|
+
temporal_timeout_seconds: Set/update the temporal timeout in seconds.
|
|
2721
|
+
Makes this edge auto-fire after inactivity.
|
|
2722
|
+
temporal_disabled_contact_groups: Contact group overrides for the
|
|
2723
|
+
temporal edge, e.g. {"__default__": false, "<group_id>": true}.
|
|
2679
2724
|
|
|
2680
2725
|
Returns:
|
|
2681
2726
|
Updated edge
|
|
2682
2727
|
"""
|
|
2683
|
-
|
|
2728
|
+
metadata = dict(metadata or {}) if metadata else {}
|
|
2729
|
+
if temporal_timeout_seconds is not None:
|
|
2730
|
+
temporal = metadata.setdefault("temporal", {})
|
|
2731
|
+
temporal["timeout_seconds"] = temporal_timeout_seconds
|
|
2732
|
+
if temporal_disabled_contact_groups is not None:
|
|
2733
|
+
temporal["disabled_contact_groups"] = temporal_disabled_contact_groups
|
|
2734
|
+
|
|
2735
|
+
updates: dict = {}
|
|
2684
2736
|
if label is not None:
|
|
2685
2737
|
updates["label"] = label
|
|
2686
|
-
if metadata
|
|
2738
|
+
if metadata:
|
|
2687
2739
|
updates["metadata"] = metadata
|
|
2688
2740
|
|
|
2689
2741
|
edge = await client.update_edge(flow_id, edge_id, **updates)
|
|
2690
2742
|
|
|
2691
|
-
|
|
2743
|
+
result = f"# Updated Edge\nid: {edge.get('id')}"
|
|
2744
|
+
if label is not None:
|
|
2745
|
+
result += f"\nlabel: {label}"
|
|
2746
|
+
if metadata.get("temporal"):
|
|
2747
|
+
temporal = metadata["temporal"]
|
|
2748
|
+
result += f"\ntemporal_timeout_seconds: {temporal.get('timeout_seconds')}"
|
|
2749
|
+
return result
|
|
2692
2750
|
|
|
2693
2751
|
|
|
2694
2752
|
async def flow_edge_delete(
|
|
@@ -5883,3 +5941,208 @@ async def product_delete(
|
|
|
5883
5941
|
return _format_error(e)
|
|
5884
5942
|
|
|
5885
5943
|
return f"Product {product_id} deleted successfully."
|
|
5944
|
+
|
|
5945
|
+
|
|
5946
|
+
# -----------------------------------------------------------------------------
|
|
5947
|
+
# Agent - Create / Update / Delete
|
|
5948
|
+
# -----------------------------------------------------------------------------
|
|
5949
|
+
|
|
5950
|
+
|
|
5951
|
+
async def agent_create(
|
|
5952
|
+
client: AppliedClient,
|
|
5953
|
+
name: str,
|
|
5954
|
+
modality: str,
|
|
5955
|
+
agent_type: str = "Customer Support",
|
|
5956
|
+
model: str = "GPT-4.1-mini",
|
|
5957
|
+
prompt: str = "",
|
|
5958
|
+
escalation_mode: str = "default",
|
|
5959
|
+
auto_reply: bool = False,
|
|
5960
|
+
) -> str:
|
|
5961
|
+
"""Create a new agent."""
|
|
5962
|
+
try:
|
|
5963
|
+
agent = await client.create_agent(
|
|
5964
|
+
name=name,
|
|
5965
|
+
modality=modality,
|
|
5966
|
+
agent_type=agent_type,
|
|
5967
|
+
model=model,
|
|
5968
|
+
prompt=prompt,
|
|
5969
|
+
escalation_mode=escalation_mode,
|
|
5970
|
+
auto_reply=auto_reply,
|
|
5971
|
+
)
|
|
5972
|
+
except AppliedAPIError as e:
|
|
5973
|
+
return _format_error(e)
|
|
5974
|
+
|
|
5975
|
+
result = "# Created Agent\n"
|
|
5976
|
+
result += f"id: {agent.get('id')}\n"
|
|
5977
|
+
result += f"name: {agent.get('name')}\n"
|
|
5978
|
+
result += f"modality: {agent.get('modality')}\n"
|
|
5979
|
+
return result
|
|
5980
|
+
|
|
5981
|
+
|
|
5982
|
+
async def agent_update(
|
|
5983
|
+
client: AppliedClient,
|
|
5984
|
+
agent_id: str,
|
|
5985
|
+
name: str | None = None,
|
|
5986
|
+
prompt: str | None = None,
|
|
5987
|
+
model: str | None = None,
|
|
5988
|
+
modality: str | None = None,
|
|
5989
|
+
agent_type: str | None = None,
|
|
5990
|
+
escalation_mode: str | None = None,
|
|
5991
|
+
auto_reply: bool | None = None,
|
|
5992
|
+
metadata: dict | None = None,
|
|
5993
|
+
) -> str:
|
|
5994
|
+
"""Update an agent's properties."""
|
|
5995
|
+
updates: dict = {}
|
|
5996
|
+
if name is not None:
|
|
5997
|
+
updates["name"] = name
|
|
5998
|
+
if prompt is not None:
|
|
5999
|
+
updates["prompt"] = prompt
|
|
6000
|
+
if model is not None:
|
|
6001
|
+
updates["model"] = model
|
|
6002
|
+
if modality is not None:
|
|
6003
|
+
updates["modality"] = modality
|
|
6004
|
+
if agent_type is not None:
|
|
6005
|
+
updates["type"] = agent_type
|
|
6006
|
+
if escalation_mode is not None:
|
|
6007
|
+
updates["escalation_mode"] = escalation_mode
|
|
6008
|
+
if auto_reply is not None:
|
|
6009
|
+
updates["auto_reply"] = auto_reply
|
|
6010
|
+
if metadata is not None:
|
|
6011
|
+
updates["metadata"] = metadata
|
|
6012
|
+
|
|
6013
|
+
try:
|
|
6014
|
+
agent = await client.update_agent(agent_id, **updates)
|
|
6015
|
+
except AppliedAPIError as e:
|
|
6016
|
+
return _format_error(e)
|
|
6017
|
+
|
|
6018
|
+
result = "# Updated Agent\n"
|
|
6019
|
+
result += f"id: {agent.get('id')}\n"
|
|
6020
|
+
result += f"name: {agent.get('name')}\n"
|
|
6021
|
+
result += f"modality: {agent.get('modality')}\n"
|
|
6022
|
+
return result
|
|
6023
|
+
|
|
6024
|
+
|
|
6025
|
+
async def agent_set_picture(
|
|
6026
|
+
client: AppliedClient,
|
|
6027
|
+
agent_id: str,
|
|
6028
|
+
image_path: str,
|
|
6029
|
+
) -> str:
|
|
6030
|
+
"""Set an agent's profile picture from a local file."""
|
|
6031
|
+
import os
|
|
6032
|
+
|
|
6033
|
+
if not os.path.isfile(image_path):
|
|
6034
|
+
return f"Error: File not found: {image_path}"
|
|
6035
|
+
|
|
6036
|
+
try:
|
|
6037
|
+
agent = await client.update_agent_picture(agent_id, image_path)
|
|
6038
|
+
except AppliedAPIError as e:
|
|
6039
|
+
return _format_error(e)
|
|
6040
|
+
|
|
6041
|
+
result = "# Updated Agent Picture\n"
|
|
6042
|
+
result += f"id: {agent.get('id')}\n"
|
|
6043
|
+
result += f"name: {agent.get('name')}\n"
|
|
6044
|
+
result += f"profile_picture: {agent.get('profile_picture')}\n"
|
|
6045
|
+
return result
|
|
6046
|
+
|
|
6047
|
+
|
|
6048
|
+
async def agent_delete(
|
|
6049
|
+
client: AppliedClient,
|
|
6050
|
+
agent_id: str,
|
|
6051
|
+
) -> str:
|
|
6052
|
+
"""Delete an agent."""
|
|
6053
|
+
try:
|
|
6054
|
+
await client.delete_agent(agent_id)
|
|
6055
|
+
except AppliedAPIError as e:
|
|
6056
|
+
return _format_error(e)
|
|
6057
|
+
|
|
6058
|
+
return f"Agent {agent_id} deleted successfully."
|
|
6059
|
+
|
|
6060
|
+
|
|
6061
|
+
# -----------------------------------------------------------------------------
|
|
6062
|
+
# Knowledge Base - Delete
|
|
6063
|
+
# -----------------------------------------------------------------------------
|
|
6064
|
+
|
|
6065
|
+
|
|
6066
|
+
async def knowledge_delete(
|
|
6067
|
+
client: AppliedClient,
|
|
6068
|
+
knowledge_id: str,
|
|
6069
|
+
) -> str:
|
|
6070
|
+
"""Delete a knowledge base item."""
|
|
6071
|
+
try:
|
|
6072
|
+
await client.delete_response(knowledge_id)
|
|
6073
|
+
except AppliedAPIError as e:
|
|
6074
|
+
return _format_error(e)
|
|
6075
|
+
|
|
6076
|
+
return f"Knowledge item {knowledge_id} deleted successfully."
|
|
6077
|
+
|
|
6078
|
+
|
|
6079
|
+
# -----------------------------------------------------------------------------
|
|
6080
|
+
# Taxonomy - Create / Update / Delete
|
|
6081
|
+
# -----------------------------------------------------------------------------
|
|
6082
|
+
|
|
6083
|
+
|
|
6084
|
+
async def taxonomy_create(
|
|
6085
|
+
client: AppliedClient,
|
|
6086
|
+
name: str,
|
|
6087
|
+
parent_id: str | None = None,
|
|
6088
|
+
color: str | None = None,
|
|
6089
|
+
description: str | None = None,
|
|
6090
|
+
comments: str | None = None,
|
|
6091
|
+
) -> str:
|
|
6092
|
+
"""Create a topic or intent."""
|
|
6093
|
+
try:
|
|
6094
|
+
item = await client.create_taxonomy(
|
|
6095
|
+
name=name,
|
|
6096
|
+
parent_id=parent_id,
|
|
6097
|
+
color=color,
|
|
6098
|
+
description=description,
|
|
6099
|
+
comments=comments,
|
|
6100
|
+
)
|
|
6101
|
+
except AppliedAPIError as e:
|
|
6102
|
+
return _format_error(e)
|
|
6103
|
+
|
|
6104
|
+
item_type = "intent" if parent_id else "topic"
|
|
6105
|
+
result = f"# Created {item_type.title()}\n"
|
|
6106
|
+
result += f"id: {item.get('id')}\n"
|
|
6107
|
+
result += f"name: {item.get('name')}\n"
|
|
6108
|
+
return result
|
|
6109
|
+
|
|
6110
|
+
|
|
6111
|
+
async def taxonomy_update(
|
|
6112
|
+
client: AppliedClient,
|
|
6113
|
+
choice_id: str,
|
|
6114
|
+
name: str | None = None,
|
|
6115
|
+
color: str | None = None,
|
|
6116
|
+
description: str | None = None,
|
|
6117
|
+
comments: str | None = None,
|
|
6118
|
+
) -> str:
|
|
6119
|
+
"""Update a topic or intent."""
|
|
6120
|
+
updates: dict = {}
|
|
6121
|
+
if name is not None:
|
|
6122
|
+
updates["name"] = name
|
|
6123
|
+
if color is not None:
|
|
6124
|
+
updates["color"] = color
|
|
6125
|
+
if description is not None:
|
|
6126
|
+
updates["description"] = description
|
|
6127
|
+
if comments is not None:
|
|
6128
|
+
updates["comments"] = comments
|
|
6129
|
+
|
|
6130
|
+
try:
|
|
6131
|
+
item = await client.update_taxonomy(choice_id, **updates)
|
|
6132
|
+
except AppliedAPIError as e:
|
|
6133
|
+
return _format_error(e)
|
|
6134
|
+
|
|
6135
|
+
return f"# Updated Taxonomy Item\nid: {item.get('id')}\nname: {item.get('name')}"
|
|
6136
|
+
|
|
6137
|
+
|
|
6138
|
+
async def taxonomy_delete(
|
|
6139
|
+
client: AppliedClient,
|
|
6140
|
+
choice_id: str,
|
|
6141
|
+
) -> str:
|
|
6142
|
+
"""Delete a topic or intent."""
|
|
6143
|
+
try:
|
|
6144
|
+
await client.delete_taxonomy(choice_id)
|
|
6145
|
+
except AppliedAPIError as e:
|
|
6146
|
+
return _format_error(e)
|
|
6147
|
+
|
|
6148
|
+
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
|