Skip to content

Commit 41d59c1

Browse files
Merge pull request #39 from Promptly-Technologies-LLC/38-fix-the-display-of-tool-calls
Use oob swap helper function and correctly target the div to stream tool calls to
2 parents e70e49d + adc8a82 commit 41d59c1

File tree

3 files changed

+28
-15
lines changed

3 files changed

+28
-15
lines changed

.cursorindexingignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
# Don't index SpecStory auto-save files, but allow explicit context inclusion via @ references
3+
.specstory/**

routers/chat.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
templates = Jinja2Templates(directory="templates")
4040

4141

42+
def wrap_for_oob_swap(step_id: str, text_value: str) -> str:
43+
return f'<span hx-swap-oob="beforeend:#step-{step_id}">{text_value}</span>'
44+
45+
4246
# Route to submit a new user message to a thread and mount a component that
4347
# will start an assistant run stream
4448
@router.post("/send")
@@ -145,26 +149,27 @@ async def handle_assistant_stream(
145149
# Assuming one citation per delta for now
146150
break
147151

148-
sse_data = f'<span hx-swap-oob="beforeend:#step-{step_id}">{text_value}</span>'
152+
sse_data = wrap_for_oob_swap(step_id, text_value)
149153
yield sse_format(
150154
"textDelta",
151155
sse_data
152156
)
153157

154158
if isinstance(event, ThreadRunStepCreated) and event.data.type == "tool_calls":
159+
logger.debug(f"Tool Call Created - Data: {str(event.data)}")
155160
step_id = event.data.id
156-
logger.debug(f"Tool Call Created - Step ID: {step_id}")
157161

158162
yield sse_format(
159-
f"toolCallCreated",
163+
"toolCallCreated",
160164
templates.get_template('components/assistant-step.html').render(
161165
step_type='toolCall',
162-
stream_name=f'toolDelta{step_id}'
166+
step_id=step_id
163167
)
164168
)
165169

166170
if isinstance(event, ThreadRunStepDelta) and event.data.delta.step_details and event.data.delta.step_details.type == "tool_calls":
167171
tool_calls = event.data.delta.step_details.tool_calls
172+
step_id = event.data.id
168173
if tool_calls:
169174
# TODO: Support parallel function calling
170175
tool_call = tool_calls[0]
@@ -174,39 +179,44 @@ async def handle_assistant_stream(
174179
if tool_call.type == "function":
175180
if tool_call.function and tool_call.function.name:
176181
yield sse_format(
177-
f"toolDelta{step_id}",
178-
tool_call.function.name + "<br>"
182+
"toolDelta",
183+
wrap_for_oob_swap(step_id, f"<em>{tool_call.function.name} tool call</em><br>")
179184
)
180185
if tool_call.function and tool_call.function.arguments:
181186
yield sse_format(
182-
f"toolDelta{step_id}",
183-
tool_call.function.arguments
187+
"toolDelta",
188+
wrap_for_oob_swap(step_id, tool_call.function.arguments)
184189
)
185190

186191
# Handle code interpreter tool calls
187192
elif tool_call.type == "code_interpreter":
188193
if tool_call.code_interpreter and tool_call.code_interpreter.input:
189194
logger.debug(f"Code Interpreter Input: {tool_call.code_interpreter.input}")
190195
yield sse_format(
191-
f"toolDelta{step_id}",
192-
str(tool_call.code_interpreter.input)
196+
"toolDelta",
197+
wrap_for_oob_swap(step_id, str(tool_call.code_interpreter.input))
193198
)
194199
if tool_call.code_interpreter and tool_call.code_interpreter.outputs:
195200
for output in tool_call.code_interpreter.outputs:
196201
logger.debug(f"Code Interpreter Output Type: {output.type}")
197202
if output.type == "logs" and output.logs:
198203
yield sse_format(
199-
f"toolDelta{step_id}",
200-
str(output.logs)
204+
"toolDelta",
205+
wrap_for_oob_swap(step_id, str(output.logs))
201206
)
202207
elif output.type == "image" and output.image and output.image.file_id:
203208
logger.debug(f"Image Output - File ID: {output.image.file_id}")
204209
# Create the image HTML on the backend
205210
image_html = f'<img src="/assistants/{assistant_id}/files/{output.image.file_id}/content" class="code-interpreter-image">'
206211
yield sse_format(
207-
f"imageOutput",
208-
image_html
212+
"imageOutput",
213+
wrap_for_oob_swap(step_id, image_html)
209214
)
215+
elif tool_call.type == "file_search":
216+
yield sse_format(
217+
"toolDelta",
218+
wrap_for_oob_swap(step_id, "<em>File search tool call</em>")
219+
)
210220

211221
# If the assistant run requires an action (a tool call), break and handle it
212222
if isinstance(event, ThreadRunRequiresAction):

templates/components/assistant-run.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div class="assistant-run" hx-swap="beforeend"
33
hx-ext="sse"
44
sse-connect="/assistants/{{ assistant_id }}/messages/{{ thread_id }}/receive"
5-
sse-swap="messageCreated,toolCallCreated,toolOutput,imageOutput,fileOutput,textDelta"
5+
sse-swap="messageCreated,toolCallCreated,toolOutput,imageOutput,fileOutput,textDelta,toolDelta"
66
hx-on:htmx:sse-before-message="handleSSETextDelta(event)"
77
sse-close="endStream"
88
data-assistant-id="{{ assistant_id }}"

0 commit comments

Comments
 (0)