fix(canvas): set role field on USER_MESSAGE entries so bubbles render correctly #1517
@@ -271,7 +271,7 @@ export function MobileChat({
|
||||
const msgs = consume(agentId);
|
||||
for (const m of msgs) {
|
||||
appendMessageDeduped(
|
||||
createMessage("agent", m.content, m.attachments),
|
||||
createMessage(m.role ?? "agent", m.content, m.attachments),
|
||||
);
|
||||
}
|
||||
}, [historyLoading, agentId, appendMessageDeduped]);
|
||||
|
||||
@@ -27,7 +27,7 @@ export function useChatSocket(
|
||||
const msgs = consume(workspaceId);
|
||||
for (const m of msgs) {
|
||||
callbacksRef.current.onAgentMessage?.(
|
||||
createMessage("agent", m.content, m.attachments),
|
||||
createMessage(m.role ?? "agent", m.content, m.attachments),
|
||||
);
|
||||
}
|
||||
if (msgs.length > 0) {
|
||||
|
||||
@@ -840,6 +840,7 @@ describe("handleCanvasEvent – USER_MESSAGE", () => {
|
||||
expect(agentMessages["ws-1"]).toHaveLength(1);
|
||||
expect(agentMessages["ws-1"][0].id).toBe("msg-abc");
|
||||
expect(agentMessages["ws-1"][0].content).toBe("Hello, agent!");
|
||||
expect(agentMessages["ws-1"][0].role).toBe("user");
|
||||
expect(typeof agentMessages["ws-1"][0].timestamp).toBe("string");
|
||||
});
|
||||
|
||||
@@ -933,6 +934,7 @@ describe("handleCanvasEvent – USER_MESSAGE", () => {
|
||||
};
|
||||
expect(agentMessages["ws-1"]).toHaveLength(1);
|
||||
expect(agentMessages["ws-1"][0].id).toBe("msg-with-file");
|
||||
expect(agentMessages["ws-1"][0].role).toBe("user");
|
||||
expect(agentMessages["ws-1"][0].attachments).toEqual([att]);
|
||||
});
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ export function handleCanvasEvent(
|
||||
nodes: Node<WorkspaceNodeData>[];
|
||||
edges: Edge[];
|
||||
selectedNodeId: string | null;
|
||||
agentMessages: Record<string, Array<{ id: string; content: string; timestamp: string; attachments?: Array<{ name: string; uri: string; mimeType?: string; size?: number }> }>>;
|
||||
agentMessages: Record<string, Array<{ id: string; content: string; timestamp: string; role?: "user" | "agent"; attachments?: Array<{ name: string; uri: string; mimeType?: string; size?: number }> }>>;
|
||||
},
|
||||
set: (partial: Record<string, unknown>) => void,
|
||||
): void {
|
||||
@@ -552,9 +552,8 @@ export function handleCanvasEvent(
|
||||
// Render only when there's something visible.
|
||||
if (content || files.length > 0) {
|
||||
// Insert into agentMessages for rendering as a user-bubble.
|
||||
// ChatTab renders role:agent bubbles from agentMessages; the
|
||||
// bubble renderer uses the content/attachments fields, not the
|
||||
// role field, so inserting a user message here works correctly.
|
||||
// ChatTab uses msg.role === "user" for right-side alignment and
|
||||
// user-toned styling, so we must set role:"user" explicitly.
|
||||
const { agentMessages } = get();
|
||||
const existing = agentMessages[msg.workspace_id] || [];
|
||||
set({
|
||||
@@ -565,6 +564,7 @@ export function handleCanvasEvent(
|
||||
{
|
||||
id: payload?.messageId ?? crypto.randomUUID(),
|
||||
content,
|
||||
role: "user",
|
||||
timestamp: new Date().toISOString(),
|
||||
...(files.length > 0 ? { attachments: files } : {}),
|
||||
},
|
||||
|
||||
@@ -224,8 +224,8 @@ interface CanvasState {
|
||||
batchPause: () => Promise<void>;
|
||||
batchDelete: () => Promise<void>;
|
||||
/** Agent-pushed messages keyed by workspace ID. ChatTab consumes and clears these. */
|
||||
agentMessages: Record<string, Array<{ id: string; content: string; timestamp: string; attachments?: Array<{ name: string; uri: string; mimeType?: string; size?: number }> }>>;
|
||||
consumeAgentMessages: (workspaceId: string) => Array<{ id: string; content: string; timestamp: string; attachments?: Array<{ name: string; uri: string; mimeType?: string; size?: number }> }>;
|
||||
agentMessages: Record<string, Array<{ id: string; content: string; timestamp: string; role?: "user" | "agent"; attachments?: Array<{ name: string; uri: string; mimeType?: string; size?: number }> }>>;
|
||||
consumeAgentMessages: (workspaceId: string) => Array<{ id: string; content: string; timestamp: string; role?: "user" | "agent"; attachments?: Array<{ name: string; uri: string; mimeType?: string; size?: number }> }>;
|
||||
/** WebSocket connection status — drives the live indicator in the Toolbar. */
|
||||
wsStatus: "connected" | "connecting" | "disconnected";
|
||||
setWsStatus: (status: "connected" | "connecting" | "disconnected") => void;
|
||||
|
||||
Reference in New Issue
Block a user