applied-cli 0.5.71__tar.gz → 0.5.72__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.71 → applied_cli-0.5.72}/PKG-INFO +11 -1
- {applied_cli-0.5.71 → applied_cli-0.5.72}/README.md +10 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli/cli.py +285 -2
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli/client.py +34 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli/tools.py +850 -5
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli.egg-info/PKG-INFO +11 -1
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli.egg-info/SOURCES.txt +2 -1
- {applied_cli-0.5.71 → applied_cli-0.5.72}/pyproject.toml +1 -1
- applied_cli-0.5.72/tests/test_cli.py +564 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/tests/test_client.py +148 -0
- applied_cli-0.5.72/tests/test_knowledge_content_tools.py +383 -0
- applied_cli-0.5.71/tests/test_cli.py +0 -96
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli/__init__.py +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli/agent_scoped_flows.py +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli/conversation_lookup.py +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli/conversations.py +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli/credentials.py +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli/flow_helpers.py +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli/formatters.py +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli.egg-info/dependency_links.txt +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli.egg-info/entry_points.txt +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli.egg-info/requires.txt +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/applied_cli.egg-info/top_level.txt +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/setup.cfg +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/tests/test_agent_scoped_flows.py +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/tests/test_audit_tools.py +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/tests/test_benchmark_scenario_tools.py +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/tests/test_conversation_tools.py +0 -0
- {applied_cli-0.5.71 → applied_cli-0.5.72}/tests/test_flow_tools.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: applied-cli
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.72
|
|
4
4
|
Summary: CLI and shared client library for Applied Labs AI support agents
|
|
5
5
|
Author: Applied Labs
|
|
6
6
|
License-Expression: MIT
|
|
@@ -53,6 +53,16 @@ applied tickets --status open
|
|
|
53
53
|
|
|
54
54
|
# Knowledge base
|
|
55
55
|
applied knowledge --type qa --search "refund"
|
|
56
|
+
applied knowledge <id> --format json
|
|
57
|
+
applied knowledge --source "https://help.example.com" --format csv
|
|
58
|
+
applied knowledge-diff --source "https://help.example.com"
|
|
59
|
+
applied content list --source "https://help.example.com"
|
|
60
|
+
applied content-update <content_id> --text "Corrected source text"
|
|
61
|
+
applied content-resync <content_id> --wait
|
|
62
|
+
applied knowledge-pin <id>
|
|
63
|
+
applied knowledge-link <response_id> --content <content_id>
|
|
64
|
+
applied knowledge-protect <id>
|
|
65
|
+
applied knowledge-unprotect <id>
|
|
56
66
|
|
|
57
67
|
# Taxonomy
|
|
58
68
|
applied taxonomy --type topics
|
|
@@ -28,6 +28,16 @@ applied tickets --status open
|
|
|
28
28
|
|
|
29
29
|
# Knowledge base
|
|
30
30
|
applied knowledge --type qa --search "refund"
|
|
31
|
+
applied knowledge <id> --format json
|
|
32
|
+
applied knowledge --source "https://help.example.com" --format csv
|
|
33
|
+
applied knowledge-diff --source "https://help.example.com"
|
|
34
|
+
applied content list --source "https://help.example.com"
|
|
35
|
+
applied content-update <content_id> --text "Corrected source text"
|
|
36
|
+
applied content-resync <content_id> --wait
|
|
37
|
+
applied knowledge-pin <id>
|
|
38
|
+
applied knowledge-link <response_id> --content <content_id>
|
|
39
|
+
applied knowledge-protect <id>
|
|
40
|
+
applied knowledge-unprotect <id>
|
|
31
41
|
|
|
32
42
|
# Taxonomy
|
|
33
43
|
applied taxonomy --type topics
|
|
@@ -22,6 +22,8 @@ app = typer.Typer(
|
|
|
22
22
|
help="Applied Labs CLI - manage your AI agents and conversations.",
|
|
23
23
|
no_args_is_help=True,
|
|
24
24
|
)
|
|
25
|
+
content_app = typer.Typer(help="Inspect synced content items.")
|
|
26
|
+
app.add_typer(content_app, name="content")
|
|
25
27
|
|
|
26
28
|
DEFAULT_BASE_URL = "https://api.appliedlabs.ai"
|
|
27
29
|
DEFAULT_CLIENT_URL = "https://appliedlabs.ai"
|
|
@@ -938,27 +940,174 @@ def ticket_update(
|
|
|
938
940
|
|
|
939
941
|
@app.command()
|
|
940
942
|
def knowledge(
|
|
943
|
+
id: str = typer.Argument(None, help="Knowledge item ID to fetch"),
|
|
941
944
|
type: str = typer.Option(
|
|
942
945
|
None, "--type", "-t", help="Filter by type: qa, context, escalate, exact"
|
|
943
946
|
),
|
|
944
947
|
search: str = typer.Option(None, "--search", "-s", help="Search query"),
|
|
948
|
+
linked_to: str = typer.Option(
|
|
949
|
+
None, "--linked-to", help="Filter by linked content ID"
|
|
950
|
+
),
|
|
951
|
+
source: str = typer.Option(
|
|
952
|
+
None, "--source", help="Filter by linked content source URL/domain"
|
|
953
|
+
),
|
|
954
|
+
has_content: bool | None = typer.Option(
|
|
955
|
+
None,
|
|
956
|
+
"--has-content/--no-content",
|
|
957
|
+
help="Filter content-linked vs standalone manual entries",
|
|
958
|
+
),
|
|
945
959
|
limit: int = typer.Option(100, "--limit", "-l", help="Results per page"),
|
|
946
960
|
all_pages: bool = typer.Option(
|
|
947
961
|
True, "--all/--no-all", help="Fetch all pages (default: True)"
|
|
948
962
|
),
|
|
963
|
+
full: bool = typer.Option(False, "--full", help="Include full audit fields in CSV"),
|
|
949
964
|
format: str = typer.Option(
|
|
950
965
|
"csv", "--format", "-f", help="Output format: csv or json"
|
|
951
966
|
),
|
|
967
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
952
968
|
) -> None:
|
|
953
|
-
"""List knowledge base items."""
|
|
954
|
-
client = get_client()
|
|
969
|
+
"""List knowledge base items or fetch one item by ID."""
|
|
970
|
+
client = get_client(shop_id=shop_id)
|
|
971
|
+
if id:
|
|
972
|
+
item_format = "json" if format == "json" else "text"
|
|
973
|
+
result = asyncio.run(tools.knowledge_get(client, id, output_format=item_format))
|
|
974
|
+
typer.echo(result)
|
|
975
|
+
return
|
|
976
|
+
|
|
955
977
|
result = asyncio.run(
|
|
956
978
|
tools.knowledge_list(
|
|
957
979
|
client,
|
|
958
980
|
kb_type=type,
|
|
959
981
|
search=search,
|
|
982
|
+
linked_to=linked_to,
|
|
983
|
+
source=source,
|
|
984
|
+
has_content=has_content,
|
|
960
985
|
limit=limit,
|
|
961
986
|
fetch_all=all_pages,
|
|
987
|
+
full=full,
|
|
988
|
+
output_format=format,
|
|
989
|
+
)
|
|
990
|
+
)
|
|
991
|
+
typer.echo(result)
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
@app.command("knowledge-diff")
|
|
995
|
+
def knowledge_diff(
|
|
996
|
+
source: str = typer.Option(..., "--source", help="Source URL/domain to audit"),
|
|
997
|
+
limit: int = typer.Option(100, "--limit", "-l", help="Results per API page"),
|
|
998
|
+
format: str = typer.Option(
|
|
999
|
+
"text", "--format", "-f", help="Output format: text or json"
|
|
1000
|
+
),
|
|
1001
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
1002
|
+
) -> None:
|
|
1003
|
+
"""Diff content-linked knowledge against current source pages."""
|
|
1004
|
+
client = get_client(shop_id=shop_id)
|
|
1005
|
+
result = asyncio.run(
|
|
1006
|
+
tools.knowledge_diff(
|
|
1007
|
+
client,
|
|
1008
|
+
source=source,
|
|
1009
|
+
limit=limit,
|
|
1010
|
+
output_format=format,
|
|
1011
|
+
)
|
|
1012
|
+
)
|
|
1013
|
+
typer.echo(result)
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
# -----------------------------------------------------------------------------
|
|
1017
|
+
# Content commands
|
|
1018
|
+
# -----------------------------------------------------------------------------
|
|
1019
|
+
|
|
1020
|
+
|
|
1021
|
+
@content_app.command("list")
|
|
1022
|
+
def content_list_cmd(
|
|
1023
|
+
type: str = typer.Option(
|
|
1024
|
+
None, "--type", "-t", help="Filter by type: Article, Product, Document, Site"
|
|
1025
|
+
),
|
|
1026
|
+
status: str = typer.Option(None, "--status", "-s", help="Filter by status"),
|
|
1027
|
+
search: str = typer.Option(None, "--search", help="Search query"),
|
|
1028
|
+
source: str = typer.Option(None, "--source", help="Filter by source URL/domain"),
|
|
1029
|
+
limit: int = typer.Option(100, "--limit", "-l", help="Results per page"),
|
|
1030
|
+
all_pages: bool = typer.Option(
|
|
1031
|
+
True, "--all/--no-all", help="Fetch all pages (default: True)"
|
|
1032
|
+
),
|
|
1033
|
+
full: bool = typer.Option(False, "--full", help="Include sync audit fields in CSV"),
|
|
1034
|
+
format: str = typer.Option(
|
|
1035
|
+
"csv", "--format", "-f", help="Output format: csv or json"
|
|
1036
|
+
),
|
|
1037
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
1038
|
+
) -> None:
|
|
1039
|
+
"""List content items imported into the knowledge system."""
|
|
1040
|
+
client = get_client(shop_id=shop_id)
|
|
1041
|
+
result = asyncio.run(
|
|
1042
|
+
tools.content_list(
|
|
1043
|
+
client,
|
|
1044
|
+
content_type=type,
|
|
1045
|
+
status=status,
|
|
1046
|
+
search=search,
|
|
1047
|
+
source=source,
|
|
1048
|
+
limit=limit,
|
|
1049
|
+
fetch_all=all_pages,
|
|
1050
|
+
full=full,
|
|
1051
|
+
output_format=format,
|
|
1052
|
+
)
|
|
1053
|
+
)
|
|
1054
|
+
typer.echo(result)
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
@app.command("content-resync")
|
|
1058
|
+
def content_resync(
|
|
1059
|
+
id: str = typer.Argument(..., help="Content item ID"),
|
|
1060
|
+
wait: bool = typer.Option(
|
|
1061
|
+
False, "--wait", help="Poll until the content item is no longer syncing"
|
|
1062
|
+
),
|
|
1063
|
+
poll_interval: float = typer.Option(
|
|
1064
|
+
2.0, "--poll-interval", help="Seconds between --wait polls"
|
|
1065
|
+
),
|
|
1066
|
+
timeout: float = typer.Option(
|
|
1067
|
+
300.0, "--timeout", help="Maximum seconds to wait for sync completion"
|
|
1068
|
+
),
|
|
1069
|
+
format: str = typer.Option(
|
|
1070
|
+
"text", "--format", "-f", help="Output format: text or json"
|
|
1071
|
+
),
|
|
1072
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
1073
|
+
) -> None:
|
|
1074
|
+
"""Trigger a resync for one content item."""
|
|
1075
|
+
client = get_client(shop_id=shop_id)
|
|
1076
|
+
result = asyncio.run(
|
|
1077
|
+
tools.content_resync(
|
|
1078
|
+
client,
|
|
1079
|
+
id,
|
|
1080
|
+
wait=wait,
|
|
1081
|
+
poll_interval=poll_interval,
|
|
1082
|
+
timeout=timeout,
|
|
1083
|
+
output_format=format,
|
|
1084
|
+
)
|
|
1085
|
+
)
|
|
1086
|
+
typer.echo(result)
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
@app.command("content-update")
|
|
1090
|
+
def content_update(
|
|
1091
|
+
id: str = typer.Argument(..., help="Content item ID"),
|
|
1092
|
+
text: str = typer.Option(None, "--text", help="Override source text"),
|
|
1093
|
+
title: str = typer.Option(None, "--title", help="Content title"),
|
|
1094
|
+
description: str = typer.Option(None, "--description", help="Content description"),
|
|
1095
|
+
status: str = typer.Option(None, "--status", help="Content status"),
|
|
1096
|
+
format: str = typer.Option(
|
|
1097
|
+
"text", "--format", "-f", help="Output format: text or json"
|
|
1098
|
+
),
|
|
1099
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
1100
|
+
) -> None:
|
|
1101
|
+
"""Update a content item before resyncing linked responses."""
|
|
1102
|
+
client = get_client(shop_id=shop_id)
|
|
1103
|
+
result = asyncio.run(
|
|
1104
|
+
tools.content_update(
|
|
1105
|
+
client,
|
|
1106
|
+
id,
|
|
1107
|
+
text=text,
|
|
1108
|
+
title=title,
|
|
1109
|
+
description=description,
|
|
1110
|
+
status=status,
|
|
962
1111
|
output_format=format,
|
|
963
1112
|
)
|
|
964
1113
|
)
|
|
@@ -1923,6 +2072,9 @@ def knowledge_create(
|
|
|
1923
2072
|
),
|
|
1924
2073
|
question: str = typer.Option(..., "--question", "-q", help="Trigger text / question"),
|
|
1925
2074
|
answer: str = typer.Option(..., "--answer", "-a", help="Response text / answer"),
|
|
2075
|
+
chunk_text: str = typer.Option(
|
|
2076
|
+
None, "--chunk-text", help="Raw retrieval chunk text"
|
|
2077
|
+
),
|
|
1926
2078
|
guardrail: str = typer.Option("", "--guardrail", help="Guardrail instructions"),
|
|
1927
2079
|
active: bool = typer.Option(True, "--active/--inactive", help="Whether the item is active"),
|
|
1928
2080
|
agent_ids: str = typer.Option(
|
|
@@ -1941,6 +2093,7 @@ def knowledge_create(
|
|
|
1941
2093
|
kb_type=kb_type,
|
|
1942
2094
|
question=question,
|
|
1943
2095
|
answer=answer,
|
|
2096
|
+
chunk_text=chunk_text,
|
|
1944
2097
|
guardrail=guardrail,
|
|
1945
2098
|
active=active,
|
|
1946
2099
|
agent_ids=parsed_agent_ids,
|
|
@@ -1963,6 +2116,11 @@ def knowledge_update(
|
|
|
1963
2116
|
),
|
|
1964
2117
|
label_id: str = typer.Option(None, "--label-id", help="Topic label UUID"),
|
|
1965
2118
|
flow_id: str = typer.Option(None, "--flow-id", help="Flow UUID to associate with"),
|
|
2119
|
+
pin: bool = typer.Option(
|
|
2120
|
+
False,
|
|
2121
|
+
"--pin",
|
|
2122
|
+
help="Mark the response as manually managed while updating",
|
|
2123
|
+
),
|
|
1966
2124
|
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
1967
2125
|
) -> None:
|
|
1968
2126
|
"""Update a knowledge base item."""
|
|
@@ -1982,6 +2140,95 @@ def knowledge_update(
|
|
|
1982
2140
|
agent_ids=parsed_agent_ids,
|
|
1983
2141
|
label_id=label_id,
|
|
1984
2142
|
flow_id=flow_id,
|
|
2143
|
+
pin=pin,
|
|
2144
|
+
)
|
|
2145
|
+
)
|
|
2146
|
+
typer.echo(result)
|
|
2147
|
+
|
|
2148
|
+
|
|
2149
|
+
@app.command("knowledge-pin")
|
|
2150
|
+
def knowledge_pin(
|
|
2151
|
+
id: str = typer.Argument(..., help="Knowledge item ID"),
|
|
2152
|
+
unpin: bool = typer.Option(False, "--unpin", help="Remove the pin/manual flag"),
|
|
2153
|
+
format: str = typer.Option(
|
|
2154
|
+
"text", "--format", "-f", help="Output format: text or json"
|
|
2155
|
+
),
|
|
2156
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2157
|
+
) -> None:
|
|
2158
|
+
"""Pin a knowledge item so manual edits can survive content resyncs."""
|
|
2159
|
+
client = get_client(shop_id=shop_id)
|
|
2160
|
+
result = asyncio.run(
|
|
2161
|
+
tools.knowledge_pin(
|
|
2162
|
+
client,
|
|
2163
|
+
id,
|
|
2164
|
+
pinned=not unpin,
|
|
2165
|
+
output_format=format,
|
|
2166
|
+
)
|
|
2167
|
+
)
|
|
2168
|
+
typer.echo(result)
|
|
2169
|
+
|
|
2170
|
+
|
|
2171
|
+
@app.command("knowledge-link")
|
|
2172
|
+
def knowledge_link(
|
|
2173
|
+
id: str = typer.Argument(..., help="Knowledge item ID"),
|
|
2174
|
+
content_id: str = typer.Option(
|
|
2175
|
+
..., "--content", help="Content item ID to link to"
|
|
2176
|
+
),
|
|
2177
|
+
format: str = typer.Option(
|
|
2178
|
+
"text", "--format", "-f", help="Output format: text or json"
|
|
2179
|
+
),
|
|
2180
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2181
|
+
) -> None:
|
|
2182
|
+
"""Link a knowledge item to a content item so sync can manage it."""
|
|
2183
|
+
client = get_client(shop_id=shop_id)
|
|
2184
|
+
result = asyncio.run(
|
|
2185
|
+
tools.knowledge_link(
|
|
2186
|
+
client,
|
|
2187
|
+
id,
|
|
2188
|
+
content_id=content_id,
|
|
2189
|
+
output_format=format,
|
|
2190
|
+
)
|
|
2191
|
+
)
|
|
2192
|
+
typer.echo(result)
|
|
2193
|
+
|
|
2194
|
+
|
|
2195
|
+
@app.command("knowledge-protect")
|
|
2196
|
+
def knowledge_protect(
|
|
2197
|
+
id: str = typer.Argument(..., help="Knowledge item ID"),
|
|
2198
|
+
format: str = typer.Option(
|
|
2199
|
+
"text", "--format", "-f", help="Output format: text or json"
|
|
2200
|
+
),
|
|
2201
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2202
|
+
) -> None:
|
|
2203
|
+
"""Disable autogeneration on the linked content for a knowledge item."""
|
|
2204
|
+
client = get_client(shop_id=shop_id)
|
|
2205
|
+
result = asyncio.run(
|
|
2206
|
+
tools.knowledge_protect(
|
|
2207
|
+
client,
|
|
2208
|
+
id,
|
|
2209
|
+
protected=True,
|
|
2210
|
+
output_format=format,
|
|
2211
|
+
)
|
|
2212
|
+
)
|
|
2213
|
+
typer.echo(result)
|
|
2214
|
+
|
|
2215
|
+
|
|
2216
|
+
@app.command("knowledge-unprotect")
|
|
2217
|
+
def knowledge_unprotect(
|
|
2218
|
+
id: str = typer.Argument(..., help="Knowledge item ID"),
|
|
2219
|
+
format: str = typer.Option(
|
|
2220
|
+
"text", "--format", "-f", help="Output format: text or json"
|
|
2221
|
+
),
|
|
2222
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2223
|
+
) -> None:
|
|
2224
|
+
"""Re-enable autogeneration on the linked content for a knowledge item."""
|
|
2225
|
+
client = get_client(shop_id=shop_id)
|
|
2226
|
+
result = asyncio.run(
|
|
2227
|
+
tools.knowledge_protect(
|
|
2228
|
+
client,
|
|
2229
|
+
id,
|
|
2230
|
+
protected=False,
|
|
2231
|
+
output_format=format,
|
|
1985
2232
|
)
|
|
1986
2233
|
)
|
|
1987
2234
|
typer.echo(result)
|
|
@@ -2226,6 +2473,42 @@ def product_update(
|
|
|
2226
2473
|
typer.echo(result)
|
|
2227
2474
|
|
|
2228
2475
|
|
|
2476
|
+
@app.command("agent-deploy")
|
|
2477
|
+
def agent_deploy(
|
|
2478
|
+
agent_ids: list[str] = typer.Argument(..., help="One or more Agent IDs to deploy"),
|
|
2479
|
+
description: str = typer.Option("", "--description", "-d", help="Optional revision description"),
|
|
2480
|
+
shop_id: str = typer.Option(None, "--shop-id", help="Override shop ID"),
|
|
2481
|
+
) -> None:
|
|
2482
|
+
"""Deploy the current configuration for one or more agents as new live revisions.
|
|
2483
|
+
|
|
2484
|
+
Creates a new revision from each agent's current state and immediately sets it live,
|
|
2485
|
+
so new conversations use the latest changes.
|
|
2486
|
+
|
|
2487
|
+
Pass multiple agent IDs to deploy several agents at once:
|
|
2488
|
+
applied agent-deploy <id1> <id2> <id3> --description "what changed"
|
|
2489
|
+
"""
|
|
2490
|
+
client = get_client(shop_id=shop_id)
|
|
2491
|
+
|
|
2492
|
+
async def _deploy_one(agent_id: str):
|
|
2493
|
+
return await client._request(
|
|
2494
|
+
"POST",
|
|
2495
|
+
"/v1/revisions/",
|
|
2496
|
+
body={"agent_id": agent_id, "deploy": True, "description": description},
|
|
2497
|
+
)
|
|
2498
|
+
|
|
2499
|
+
async def _deploy_all():
|
|
2500
|
+
import asyncio as _asyncio
|
|
2501
|
+
return await _asyncio.gather(*[_deploy_one(aid) for aid in agent_ids])
|
|
2502
|
+
|
|
2503
|
+
results = asyncio.run(_deploy_all())
|
|
2504
|
+
for result in results:
|
|
2505
|
+
version = result.get("version", "?")
|
|
2506
|
+
revision_id = result.get("id", "?")
|
|
2507
|
+
is_live = result.get("is_live", False)
|
|
2508
|
+
agent_id = result.get("agent_id", "?")
|
|
2509
|
+
typer.echo(f"Deployed agent {agent_id}: revision v{version} (id={revision_id}, is_live={is_live})")
|
|
2510
|
+
|
|
2511
|
+
|
|
2229
2512
|
def main() -> None:
|
|
2230
2513
|
"""CLI entrypoint."""
|
|
2231
2514
|
nested_exit_code = run_agent_scoped_flow_command(sys.argv[1:], get_client)
|
|
@@ -1152,6 +1152,9 @@ class AppliedClient:
|
|
|
1152
1152
|
self,
|
|
1153
1153
|
kb_type: str | None = None,
|
|
1154
1154
|
search: str | None = None,
|
|
1155
|
+
content_id: str | None = None,
|
|
1156
|
+
source: str | None = None,
|
|
1157
|
+
has_content: bool | None = None,
|
|
1155
1158
|
limit: int = 100,
|
|
1156
1159
|
fetch_all: bool = False,
|
|
1157
1160
|
) -> list[dict]:
|
|
@@ -1160,6 +1163,9 @@ class AppliedClient:
|
|
|
1160
1163
|
Args:
|
|
1161
1164
|
kb_type: Filter by type
|
|
1162
1165
|
search: Search query
|
|
1166
|
+
content_id: Filter by linked content ID
|
|
1167
|
+
source: Filter by linked content source URL
|
|
1168
|
+
has_content: Filter to content-linked or standalone items
|
|
1163
1169
|
limit: Page size (default 100, max per request)
|
|
1164
1170
|
fetch_all: If True, paginate through all results
|
|
1165
1171
|
"""
|
|
@@ -1168,6 +1174,12 @@ class AppliedClient:
|
|
|
1168
1174
|
params["type"] = kb_type
|
|
1169
1175
|
if search:
|
|
1170
1176
|
params["search"] = search
|
|
1177
|
+
if content_id:
|
|
1178
|
+
params["content_id"] = content_id
|
|
1179
|
+
if source:
|
|
1180
|
+
params["source"] = source
|
|
1181
|
+
if has_content is not None:
|
|
1182
|
+
params["content__isnull"] = str(not has_content).lower()
|
|
1171
1183
|
|
|
1172
1184
|
if not fetch_all:
|
|
1173
1185
|
data = await self._request("GET", "/v1/responses/", params=params)
|
|
@@ -1223,6 +1235,7 @@ class AppliedClient:
|
|
|
1223
1235
|
content_type: str | None = None,
|
|
1224
1236
|
status: str | None = None,
|
|
1225
1237
|
search: str | None = None,
|
|
1238
|
+
source: str | None = None,
|
|
1226
1239
|
limit: int = 100,
|
|
1227
1240
|
fetch_all: bool = False,
|
|
1228
1241
|
) -> list[dict]:
|
|
@@ -1232,6 +1245,7 @@ class AppliedClient:
|
|
|
1232
1245
|
content_type: Filter by type - 'Article', 'Product', 'Document', 'Site'
|
|
1233
1246
|
status: Filter by status - 'Published', 'Draft', 'Pending'
|
|
1234
1247
|
search: Search query
|
|
1248
|
+
source: Filter by source URL/domain
|
|
1235
1249
|
limit: Page size (default 100)
|
|
1236
1250
|
fetch_all: If True, paginate through all results
|
|
1237
1251
|
"""
|
|
@@ -1242,6 +1256,8 @@ class AppliedClient:
|
|
|
1242
1256
|
params["status"] = status
|
|
1243
1257
|
if search:
|
|
1244
1258
|
params["search"] = search
|
|
1259
|
+
if source:
|
|
1260
|
+
params["source"] = source
|
|
1245
1261
|
|
|
1246
1262
|
if not fetch_all:
|
|
1247
1263
|
data = await self._request("GET", "/v1/content/", params=params)
|
|
@@ -1344,6 +1360,10 @@ class AppliedClient:
|
|
|
1344
1360
|
body=kwargs,
|
|
1345
1361
|
)
|
|
1346
1362
|
|
|
1363
|
+
async def resync_content(self, content_id: str) -> dict:
|
|
1364
|
+
"""Trigger a resync for a content item."""
|
|
1365
|
+
return await self._request("POST", f"/v1/content/{content_id}/resync/")
|
|
1366
|
+
|
|
1347
1367
|
async def delete_content(self, content_id: str) -> None:
|
|
1348
1368
|
"""Delete a content item."""
|
|
1349
1369
|
await self._request("DELETE", f"/v1/content/{content_id}/")
|
|
@@ -2382,6 +2402,7 @@ class AppliedClient:
|
|
|
2382
2402
|
kb_type: str,
|
|
2383
2403
|
question: str,
|
|
2384
2404
|
answer: str,
|
|
2405
|
+
chunk_text: str | None = None,
|
|
2385
2406
|
guardrail: str = "",
|
|
2386
2407
|
active: bool = True,
|
|
2387
2408
|
agent_ids: list[str] | None = None,
|
|
@@ -2394,6 +2415,7 @@ class AppliedClient:
|
|
|
2394
2415
|
kb_type: Type - 'qa', 'exact', 'escalate', 'context', 'greeting', 'signature'
|
|
2395
2416
|
question: Trigger text / question
|
|
2396
2417
|
answer: Response text / answer
|
|
2418
|
+
chunk_text: Raw retrieval chunk text
|
|
2397
2419
|
guardrail: Optional guardrail instructions
|
|
2398
2420
|
active: Whether the item is active (default True)
|
|
2399
2421
|
agent_ids: Optional list of agent UUIDs to assign to
|
|
@@ -2406,6 +2428,8 @@ class AppliedClient:
|
|
|
2406
2428
|
"answer": answer,
|
|
2407
2429
|
"active": active,
|
|
2408
2430
|
}
|
|
2431
|
+
if chunk_text is not None:
|
|
2432
|
+
body["chunk_text"] = chunk_text
|
|
2409
2433
|
if guardrail:
|
|
2410
2434
|
body["guardrail"] = guardrail
|
|
2411
2435
|
if agent_ids:
|
|
@@ -2426,6 +2450,16 @@ class AppliedClient:
|
|
|
2426
2450
|
"PATCH", f"/v1/responses/{response_id}/", body=kwargs
|
|
2427
2451
|
)
|
|
2428
2452
|
|
|
2453
|
+
async def pin_response(
|
|
2454
|
+
self,
|
|
2455
|
+
response_id: str,
|
|
2456
|
+
pinned: bool = True,
|
|
2457
|
+
*,
|
|
2458
|
+
field: str = "pinned",
|
|
2459
|
+
) -> dict:
|
|
2460
|
+
"""Mark a knowledge base response as pinned/manually managed."""
|
|
2461
|
+
return await self.update_response(response_id, **{field: pinned})
|
|
2462
|
+
|
|
2429
2463
|
async def delete_response(self, response_id: str) -> None:
|
|
2430
2464
|
"""Delete a knowledge base item."""
|
|
2431
2465
|
await self._request("DELETE", f"/v1/responses/{response_id}/")
|