Skip to content

Commit fa609ff

Browse files
committed
Follow up to #107: pick up tool annotation icon and never escape icon or html display
1 parent 97c834c commit fa609ff

File tree

2 files changed

+46
-47
lines changed

2 files changed

+46
-47
lines changed

pkg-py/src/shinychat/_chat_normalize_chatlas.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,18 @@ def tool_result_contents(x: "ContentToolResult") -> Tagifiable:
288288

289289
tool = x.request.tool
290290
tool_title = None
291+
icon = None
291292
if tool and tool.annotations:
292293
tool_title = tool.annotations.get("title")
294+
icon = tool.annotations.get("extras", {}).get("icon")
295+
icon = icon or tool.annotations.get("icon")
296+
297+
# Icon strings and HTML display never get escaped
298+
icon = display.icon or icon
299+
if icon and isinstance(icon, str):
300+
icon = HTML(icon)
301+
if value_type == "html" and isinstance(value, str):
302+
value = HTML(value)
293303

294304
# display (tool *result* level) takes precedence over
295305
# annotations (tool *definition* level)
@@ -301,7 +311,7 @@ def tool_result_contents(x: "ContentToolResult") -> Tagifiable:
301311
status="success" if x.error is None else "error",
302312
value=value,
303313
value_type=value_type,
304-
icon=display.icon,
314+
icon=icon,
305315
intent=intent,
306316
show_request=display.show_request,
307317
expanded=display.open,

pkg-py/tests/playwright/tools/basic/app.py

Lines changed: 35 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
import faicons
77
from chatlas import ChatAuto, ContentToolResult
88
from chatlas.types import ToolAnnotations
9-
from pydantic import BaseModel, Field
109
from shiny import reactive
1110
from shiny.express import input, ui
11+
1212
from shinychat.express import Chat
1313
from shinychat.types import ToolResultDisplay
1414

@@ -39,20 +39,6 @@ def list_files_impl():
3939
)
4040

4141

42-
class ListFileParams(BaseModel):
43-
"""
44-
List files in the user's current directory. Always check again when asked.
45-
"""
46-
47-
path: str = Field(..., description="The path to list files from")
48-
49-
50-
class ListFileParamsWithIntent(ListFileParams):
51-
intent: str = Field(
52-
..., description="The user's intent for this tool", alias="_intent"
53-
)
54-
55-
5642
annotations: ToolAnnotations = {}
5743
if TOOL_OPTS["with_title"]:
5844
annotations["title"] = "List Files"
@@ -61,56 +47,59 @@ class ListFileParamsWithIntent(ListFileParams):
6147
if TOOL_OPTS["async"]:
6248
if TOOL_OPTS["with_intent"]:
6349

64-
async def list_files_func1(path: str, _intent: str):
50+
async def list_files(path: str, _intent: str): # pyright: ignore[reportRedeclaration]
51+
"""
52+
List files in the user's current directory. Always check again when asked.
53+
54+
Parameters
55+
----------
56+
path
57+
The path to list files from.
58+
_intent
59+
Reason for the request to explain the tool call to the user.
60+
"""
6561
await asyncio.sleep(random.uniform(1, 10))
6662
return list_files_impl()
6763

68-
chat_client.register_tool(
69-
list_files_func1,
70-
name="list_files",
71-
model=ListFileParamsWithIntent,
72-
annotations=annotations,
73-
)
74-
7564
else:
7665

77-
async def list_files_func2(path: str):
66+
async def list_files(path: str): # pyright: ignore[reportRedeclaration]
67+
"""
68+
List files in the user's current directory. Always check again when asked.
69+
"""
7870
await asyncio.sleep(random.uniform(1, 10))
7971
return list_files_impl()
8072

81-
chat_client.register_tool(
82-
list_files_func2,
83-
name="list_files",
84-
model=ListFileParams,
85-
annotations=annotations,
86-
)
87-
8873
else:
8974
if TOOL_OPTS["with_intent"]:
9075

91-
def list_files_func3(path: str, _intent: str):
76+
def list_files(path: str, _intent: str): # pyright: ignore[reportRedeclaration]
77+
"""
78+
List files in the user's current directory. Always check again when asked.
79+
80+
Parameters
81+
----------
82+
path
83+
The path to list files from.
84+
_intent
85+
Reason for the request to explain the tool call to the user.
86+
"""
9287
time.sleep(random.uniform(1, 3))
9388
return list_files_impl()
9489

95-
chat_client.register_tool(
96-
list_files_func3,
97-
name="list_files",
98-
model=ListFileParamsWithIntent,
99-
annotations=annotations,
100-
)
101-
10290
else:
10391

104-
def list_files_func4(path: str):
92+
def list_files(path: str): # pyright: ignore[reportRedeclaration]
93+
"""
94+
List files in the user's current directory. Always check again when asked.
95+
"""
10596
time.sleep(random.uniform(1, 3))
10697
return list_files_impl()
10798

108-
chat_client.register_tool(
109-
list_files_func4,
110-
name="list_files",
111-
model=ListFileParams,
112-
annotations=annotations,
113-
)
99+
chat_client.register_tool(
100+
list_files,
101+
annotations=annotations,
102+
)
114103

115104
ui.page_opts(fillable=True)
116105

0 commit comments

Comments
 (0)