feat(agents): wire AgentArtifactIndex into server, broadcast agent:artifact SSE

Starts agentArtifactIndex alongside the existing subagentWatcher listeners (sourced
from its subagent:tool_call stream) and rebroadcasts artifact:added/updated as a single
agent:artifact SSE event. Registers the event in sse-events.ts + constants.js (parity
test passes). Listeners detached and the index stopped in cleanupSubagentWatcherListeners.

Purely additive — no existing behavior changes. Server boots clean on an isolated beta
instance and discovers subagents as before. Backend half of the Agent Gallery; the serve
route and frontend are still to come.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arkon
2026-06-13 06:10:30 +02:00
co-authored by Claude Opus 4.8
parent dae4d8fbee
commit 95a59b0e9f
3 changed files with 29 additions and 0 deletions
+1
View File
@@ -333,6 +333,7 @@ const SSE_EVENTS = {
SUBAGENT_MESSAGE: 'subagent:message',
SUBAGENT_TOOL_RESULT: 'subagent:tool_result',
SUBAGENT_COMPLETED: 'subagent:completed',
AGENT_ARTIFACT: 'agent:artifact',
// Images
IMAGE_DETECTED: 'image:detected',
+25
View File
@@ -59,6 +59,7 @@ import {
type SubagentMessage,
type SubagentToolResult,
} from '../subagent-watcher.js';
import { agentArtifactIndex, type AgentArtifact } from '../agent-artifact-index.js';
import { imageWatcher } from '../image-watcher.js';
import { attachmentRegistry, registerExternalAttachment } from '../attachment-registry.js';
import { TranscriptWatcher } from '../transcript-watcher.js';
@@ -248,6 +249,11 @@ export class WebServer extends EventEmitter {
completed: (info: SubagentInfo) => void;
error: (error: Error, agentId?: string) => void;
} | null = null;
private artifactIndexHandlers: {
added: (artifact: AgentArtifact) => void;
updated: (artifact: AgentArtifact) => void;
error: (error: Error) => void;
} | null = null;
private imageWatcherHandlers: {
detected: (event: ImageDetectedEvent) => void;
attachmentDetected: (event: AttachmentDetectedEvent) => void;
@@ -412,6 +418,18 @@ export class WebServer extends EventEmitter {
subagentWatcher.on('subagent:message', this.subagentWatcherHandlers.message);
subagentWatcher.on('subagent:completed', this.subagentWatcherHandlers.completed);
subagentWatcher.on('subagent:error', this.subagentWatcherHandlers.error);
// Agent artifact index: attribute the files each subagent writes (from subagentWatcher's
// tool-call stream) and broadcast them as `agent:artifact` for the Agent Gallery view.
agentArtifactIndex.start(subagentWatcher);
this.artifactIndexHandlers = {
added: (artifact: AgentArtifact) => this.broadcast(SseEvent.AgentArtifact, artifact),
updated: (artifact: AgentArtifact) => this.broadcast(SseEvent.AgentArtifact, artifact),
error: (error: Error) => console.error('[AgentArtifactIndex] Error:', error.message),
};
agentArtifactIndex.on('artifact:added', this.artifactIndexHandlers.added);
agentArtifactIndex.on('artifact:updated', this.artifactIndexHandlers.updated);
agentArtifactIndex.on('artifact:error', this.artifactIndexHandlers.error);
}
/**
@@ -429,6 +447,13 @@ export class WebServer extends EventEmitter {
subagentWatcher.off('subagent:error', this.subagentWatcherHandlers.error);
this.subagentWatcherHandlers = null;
}
if (this.artifactIndexHandlers) {
agentArtifactIndex.off('artifact:added', this.artifactIndexHandlers.added);
agentArtifactIndex.off('artifact:updated', this.artifactIndexHandlers.updated);
agentArtifactIndex.off('artifact:error', this.artifactIndexHandlers.error);
this.artifactIndexHandlers = null;
}
agentArtifactIndex.stop();
}
/**
+3
View File
@@ -212,6 +212,8 @@ export const SubagentProgress = 'subagent:progress' as const;
export const SubagentMessage = 'subagent:message' as const;
/** Subagent finished. */
export const SubagentCompleted = 'subagent:completed' as const;
/** A file artifact was attributed to a subagent (newly added or re-written). Powers the Agent Gallery. */
export const AgentArtifact = 'agent:artifact' as const;
// ─── Scheduled Runs ──────────────────────────────────────────────────────────
@@ -442,6 +444,7 @@ export const SseEvent = {
SubagentProgress,
SubagentMessage,
SubagentCompleted,
AgentArtifact,
// Scheduled runs
ScheduledCreated,