mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-26 12:17:14 +00:00
fix(pipelines): retain debug chat image history
This commit is contained in:
@@ -457,7 +457,7 @@ export default function DebugDialog({
|
||||
return;
|
||||
}
|
||||
|
||||
const messageChain = [];
|
||||
const messageChain: MessageChainComponent[] = [];
|
||||
|
||||
// Add quoted message if present
|
||||
if (quotedMessage) {
|
||||
@@ -511,17 +511,21 @@ export default function DebugDialog({
|
||||
type: 'Image',
|
||||
path: result.file_key,
|
||||
});
|
||||
} else {
|
||||
} else if (attachment.kind === 'voice') {
|
||||
// Voice / File go through the generic document upload endpoint,
|
||||
// which returns a storage key the backend resolves into the
|
||||
// sandbox inbox just like images.
|
||||
const result = await httpClient.uploadDocumentFile(attachment.file);
|
||||
messageChain.push({
|
||||
type: attachment.kind === 'voice' ? 'Voice' : 'File',
|
||||
type: 'Voice',
|
||||
path: result.file_id,
|
||||
...(attachment.kind === 'file'
|
||||
? { name: attachment.file.name }
|
||||
: {}),
|
||||
});
|
||||
} else {
|
||||
const result = await httpClient.uploadDocumentFile(attachment.file);
|
||||
messageChain.push({
|
||||
type: 'File',
|
||||
path: result.file_id,
|
||||
name: attachment.file.name,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -19,7 +19,7 @@ export interface Plain extends MessageComponent {
|
||||
// Quote component
|
||||
export interface Quote extends MessageComponent {
|
||||
type: 'Quote';
|
||||
id?: number;
|
||||
id?: number | string;
|
||||
group_id?: number | string;
|
||||
sender_id?: number | string;
|
||||
target_id?: number | string;
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
* 用于管理WebSocket连接和消息处理
|
||||
*/
|
||||
import { getActiveWorkspaceUuid } from '@/app/infra/http/workspaceContext';
|
||||
import type { MessageChainComponent } from '@/app/infra/entities/message';
|
||||
|
||||
export interface WebSocketMessage {
|
||||
id: number;
|
||||
role: 'user' | 'assistant';
|
||||
content: string;
|
||||
message_chain: Array<{ type: string; text?: string; target?: string }>;
|
||||
message_chain: MessageChainComponent[];
|
||||
timestamp: string;
|
||||
is_final?: boolean;
|
||||
connection_id?: string;
|
||||
@@ -16,7 +17,12 @@ export interface WebSocketMessage {
|
||||
|
||||
export interface WebSocketResponse {
|
||||
type:
|
||||
'connected' | 'response' | 'user_message' | 'pong' | 'broadcast' | 'error';
|
||||
| 'connected'
|
||||
| 'response'
|
||||
| 'user_message'
|
||||
| 'pong'
|
||||
| 'broadcast'
|
||||
| 'error';
|
||||
connection_id?: string;
|
||||
pipeline_uuid?: string;
|
||||
session_type?: string;
|
||||
@@ -262,7 +268,7 @@ export class WebSocketClient {
|
||||
* 发送消息
|
||||
*/
|
||||
public sendMessage(
|
||||
messageChain: Array<{ type: string; text?: string; target?: string }>,
|
||||
messageChain: MessageChainComponent[],
|
||||
stream: boolean = true,
|
||||
) {
|
||||
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
||||
|
||||
@@ -226,6 +226,31 @@ test.describe('processor detail workbench', () => {
|
||||
page,
|
||||
}) => {
|
||||
await installLangBotApiMocks(page, { authenticated: true });
|
||||
const debugImageKey =
|
||||
'v1/mock-instance/workspace-default/1/upload_image/mock-owner/debug-image.png';
|
||||
const debugImageBytes = Buffer.from(
|
||||
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAusB9Y9Zl1sAAAAASUVORK5CYII=',
|
||||
'base64',
|
||||
);
|
||||
await page.route('**/api/v1/files/images', async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
code: 0,
|
||||
message: 'ok',
|
||||
data: { file_key: debugImageKey },
|
||||
timestamp: Date.now(),
|
||||
}),
|
||||
});
|
||||
});
|
||||
await page.route('**/api/v1/files/image/**', async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'image/png',
|
||||
body: debugImageBytes,
|
||||
});
|
||||
});
|
||||
await page.routeWebSocket('**/api/v1/pipelines/**/ws/connect**', (ws) => {
|
||||
ws.onMessage((raw) => {
|
||||
const message = JSON.parse(String(raw));
|
||||
@@ -238,6 +263,21 @@ test.describe('processor detail workbench', () => {
|
||||
session_type: 'person',
|
||||
}),
|
||||
);
|
||||
} else if (message.type === 'message') {
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
type: 'user_message',
|
||||
session_type: 'person',
|
||||
data: {
|
||||
id: 1,
|
||||
role: 'user',
|
||||
content: 'Describe this image',
|
||||
message_chain: message.message,
|
||||
timestamp: new Date().toISOString(),
|
||||
is_final: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -303,6 +343,21 @@ test.describe('processor detail workbench', () => {
|
||||
expect(Math.abs(sendBox!.y - inputBox!.y)).toBeLessThanOrEqual(1);
|
||||
expect(toolbarBox!.y).toBeLessThan(emptyStateBox!.y);
|
||||
|
||||
await composer.locator('input[type="file"]').setInputFiles({
|
||||
name: 'debug-image.png',
|
||||
mimeType: 'image/png',
|
||||
buffer: debugImageBytes,
|
||||
});
|
||||
await expect(
|
||||
debugPanel.locator('[data-debug-chat-attachment-preview="true"]'),
|
||||
).toBeVisible();
|
||||
await messageInput.fill('Describe this image');
|
||||
await sendButton.click();
|
||||
await expect(
|
||||
debugPanel.locator('[data-debug-chat-message-image="true"]'),
|
||||
).toBeVisible();
|
||||
await expect(debugPanel.getByText('Describe this image')).toBeVisible();
|
||||
|
||||
const streamSwitchBox = await composer.getByRole('switch').boundingBox();
|
||||
const resetBox = await resetButton.boundingBox();
|
||||
expect(streamSwitchBox).not.toBeNull();
|
||||
|
||||
Reference in New Issue
Block a user