Skip to content

Commit 45e0d6d

Browse files
author
Eva (agent)
committed
fix: render sanitized webchat message-tool text
1 parent 486d54d commit 45e0d6d

3 files changed

Lines changed: 74 additions & 1 deletion

File tree

extensions/codex/src/app-server/dynamic-tools.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,41 @@ describe("createCodexDynamicToolBridge", () => {
354354
]);
355355
});
356356

357+
it("records sanitized message text from successful message tool result details", async () => {
358+
const tool = createTool({
359+
name: "message",
360+
execute: vi.fn(async () =>
361+
textToolResult("Sent.", {
362+
ok: true,
363+
status: "ok",
364+
deliveryStatus: "sent",
365+
delivery: "webchat-session",
366+
message: "Visible reply from Codex.",
367+
}),
368+
),
369+
});
370+
const bridge = createCodexDynamicToolBridge({
371+
tools: [tool],
372+
signal: new AbortController().signal,
373+
});
374+
375+
const result = await handleMessageToolCall(bridge, {
376+
action: "send",
377+
message: "<think>internal scratchpad</think>Visible reply from Codex.",
378+
});
379+
380+
expect(result).toEqual(expectInputText("Sent."));
381+
expect(bridge.telemetry.didSendViaMessagingTool).toBe(true);
382+
expect(bridge.telemetry.messagingToolSentTexts).toEqual(["Visible reply from Codex."]);
383+
expect(bridge.telemetry.messagingToolSentTargets).toEqual([
384+
{
385+
tool: "message",
386+
provider: "message",
387+
text: "Visible reply from Codex.",
388+
},
389+
]);
390+
});
391+
357392
it("does not record messaging side effects when the send fails", async () => {
358393
const tool = createTool({
359394
name: "message",

extensions/codex/src/app-server/dynamic-tools.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,9 @@ function collectToolTelemetry(params: {
279279
return;
280280
}
281281
params.telemetry.didSendViaMessagingTool = true;
282-
const text = readFirstString(params.args, ["text", "message", "body", "content"]);
282+
const text =
283+
readToolResultDetailString(params.result, ["text", "message", "body", "content"]) ??
284+
readFirstString(params.args, ["text", "message", "body", "content"]);
283285
if (text) {
284286
params.telemetry.messagingToolSentTexts.push(text);
285287
}
@@ -372,6 +374,16 @@ function readFirstString(record: Record<string, unknown>, keys: string[]): strin
372374
return undefined;
373375
}
374376

377+
function readToolResultDetailString(
378+
result: AgentToolResult<unknown> | undefined,
379+
keys: string[],
380+
): string | undefined {
381+
if (!isRecord(result?.details)) {
382+
return undefined;
383+
}
384+
return readFirstString(result.details, keys);
385+
}
386+
375387
function collectMediaUrls(record: Record<string, unknown>): string[] {
376388
const urls: string[] = [];
377389
for (const key of ["mediaUrl", "media_url", "imageUrl", "image_url"]) {

src/agents/tools/message-tool.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,32 @@ describe("message tool agent routing", () => {
516516
});
517517
});
518518

519+
it("sanitizes same-session WebChat visible reply text", async () => {
520+
const tool = createMessageTool({
521+
config: {} as never,
522+
currentChannelProvider: "webchat",
523+
currentChannelId: "webchat-session-1",
524+
sourceReplyDeliveryMode: "message_tool_only",
525+
runMessageAction: mocks.runMessageAction as never,
526+
});
527+
528+
const result = await tool.execute("1", {
529+
action: "send",
530+
message: "<think>internal scratchpad</think>Actual visible reply after tools.",
531+
});
532+
533+
expect(mocks.runMessageAction).not.toHaveBeenCalled();
534+
expect(result.details).toMatchObject({
535+
ok: true,
536+
status: "ok",
537+
deliveryStatus: "sent",
538+
delivery: "webchat-session",
539+
channel: "webchat",
540+
to: "webchat-session-1",
541+
message: "Actual visible reply after tools.",
542+
});
543+
});
544+
519545
it("keeps explicit external message-tool sends on the outbound path from WebChat", async () => {
520546
mockSendResult({ channel: "telegram", to: "telegram:123" });
521547

0 commit comments

Comments
 (0)