Add artifact message persistence for session reconstruction

- Add ArtifactMessage type as core part of AppMessage union (not CustomMessages)
- ArtifactsRuntimeProvider appends artifact messages on create/update/delete
- MessageList filters out artifact messages (UI display only)
- artifacts.ts reconstructFromMessages handles artifact messages
- Export ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION from main index
- Fix artifact creation bug: pass filename as title instead of mimeType

Changes:
- web-ui/src/components/Messages.ts: Add ArtifactMessage to BaseMessage union
- web-ui/src/components/MessageList.ts: Skip artifact messages in render
- web-ui/src/components/sandbox/ArtifactsRuntimeProvider.ts: Append messages, fix title parameter
- web-ui/src/ChatPanel.ts: Pass agent.appendMessage callback
- web-ui/src/tools/artifacts/artifacts.ts: Handle artifact messages in reconstructFromMessages
- web-ui/src/index.ts: Export ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION
- web-ui/example/src/custom-messages.ts: Update message transformer to filter artifacts
This commit is contained in:
Mario Zechner 2025-10-09 04:07:59 +02:00
parent 0eaa879d46
commit 4d2ca6ab2a
20 changed files with 669 additions and 239 deletions

View file

@ -8,7 +8,7 @@ export interface MessageConsumer {
* Handle a message from a sandbox.
* @returns true if message was consumed (stops propagation), false otherwise
*/
handleMessage(message: any): boolean;
handleMessage(message: any): Promise<boolean>;
}
/**
@ -111,7 +111,7 @@ export class SandboxMessageRouter {
private setupListener(): void {
if (this.messageListener) return;
this.messageListener = (e: MessageEvent) => {
this.messageListener = async (e: MessageEvent) => {
const { sandboxId } = e.data;
if (!sandboxId) return;
@ -129,14 +129,14 @@ export class SandboxMessageRouter {
// 1. Try provider handlers first (for bidirectional comm like memory)
for (const provider of context.providers) {
if (provider.handleMessage) {
const handled = provider.handleMessage(e.data, respond);
const handled = await provider.handleMessage(e.data, respond);
if (handled) return; // Stop if handled
}
}
// 2. Broadcast to consumers (for one-way messages like console)
for (const consumer of context.consumers) {
const consumed = consumer.handleMessage(e.data);
const consumed = await consumer.handleMessage(e.data);
if (consumed) break; // Stop if consumed
}
};