Skip to content

Commit 9ff4679

Browse files
committed
Restore RAG indexing event forwarding to TUI after toolset refactor
The PR #2210 moved RAG from agent-level config to standard toolset type (tools.Startable) but removed the event forwarding that showed indexing progress in the TUI sidebar. This restores event forwarding by: - Adding an EventCallback to RAGTool that forwards rag.Manager events during Start() initialization - Having StartBackgroundRAGInit discover RAG tools from agent toolsets and wire up the event callback before initialization happens - Converting RAG manager events (indexing started/progress/completed, usage, errors) back to runtime events for the TUI Assisted-By: docker-agent
1 parent cab2186 commit 9ff4679

2 files changed

Lines changed: 96 additions & 11 deletions

File tree

pkg/runtime/rag.go

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,63 @@
11
package runtime
22

3-
import "context"
3+
import (
4+
"context"
5+
"fmt"
6+
"log/slog"
47

5-
// StartBackgroundRAGInit is a no-op. RAG initialization is now handled
6-
// per-toolset via the tools.Startable interface.
7-
func (r *LocalRuntime) StartBackgroundRAGInit(_ context.Context, _ func(Event)) {
8-
// RAG toolsets are initialized lazily when first used.
8+
ragtypes "github.com/docker/docker-agent/pkg/rag/types"
9+
"github.com/docker/docker-agent/pkg/tools"
10+
"github.com/docker/docker-agent/pkg/tools/builtin"
11+
)
12+
13+
// StartBackgroundRAGInit discovers RAG toolsets from agents and wires up event
14+
// forwarding so the TUI can display indexing progress. Actual initialization
15+
// happens lazily when the tool is first used (via tools.Startable).
16+
func (r *LocalRuntime) StartBackgroundRAGInit(ctx context.Context, sendEvent func(Event)) {
17+
for _, name := range r.team.AgentNames() {
18+
a, err := r.team.Agent(name)
19+
if err != nil {
20+
continue
21+
}
22+
for _, ts := range a.ToolSets() {
23+
ragTool, ok := tools.As[*builtin.RAGTool](ts)
24+
if !ok {
25+
continue
26+
}
27+
ragTool.SetEventCallback(ragEventForwarder(ctx, ragTool.Name(), r, sendEvent))
28+
}
29+
}
930
}
1031

11-
// InitializeRAG is a no-op. RAG initialization is now handled
12-
// per-toolset via the tools.Startable interface.
13-
func (r *LocalRuntime) InitializeRAG(_ context.Context, _ chan Event) {
14-
// RAG toolsets are initialized lazily when first used.
32+
// ragEventForwarder returns a callback that converts RAG manager events to runtime events.
33+
func ragEventForwarder(ctx context.Context, ragName string, r *LocalRuntime, sendEvent func(Event)) builtin.RAGEventCallback {
34+
return func(ragEvent ragtypes.Event) {
35+
agentName := r.CurrentAgentName()
36+
slog.Debug("Forwarding RAG event", "type", ragEvent.Type, "rag", ragName, "agent", agentName)
37+
38+
switch ragEvent.Type {
39+
case ragtypes.EventTypeIndexingStarted:
40+
sendEvent(RAGIndexingStarted(ragName, ragEvent.StrategyName))
41+
case ragtypes.EventTypeIndexingProgress:
42+
if ragEvent.Progress != nil {
43+
sendEvent(RAGIndexingProgress(ragName, ragEvent.StrategyName, ragEvent.Progress.Current, ragEvent.Progress.Total, agentName))
44+
}
45+
case ragtypes.EventTypeIndexingComplete:
46+
sendEvent(RAGIndexingCompleted(ragName, ragEvent.StrategyName))
47+
case ragtypes.EventTypeUsage:
48+
sendEvent(NewTokenUsageEvent("", agentName, &Usage{
49+
InputTokens: ragEvent.TotalTokens,
50+
ContextLength: ragEvent.TotalTokens,
51+
Cost: ragEvent.Cost,
52+
}))
53+
case ragtypes.EventTypeError:
54+
if ragEvent.Error != nil {
55+
sendEvent(Error(fmt.Sprintf("RAG %s error: %v", ragName, ragEvent.Error)))
56+
}
57+
default:
58+
slog.Debug("Unhandled RAG event type", "type", ragEvent.Type, "rag", ragName)
59+
}
60+
61+
_ = ctx // available for future use
62+
}
1563
}

pkg/tools/builtin/rag.go

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,18 @@ import (
1010
"slices"
1111

1212
"github.com/docker/docker-agent/pkg/rag"
13+
ragtypes "github.com/docker/docker-agent/pkg/rag/types"
1314
"github.com/docker/docker-agent/pkg/tools"
1415
)
1516

17+
// RAGEventCallback is called to forward RAG manager events during initialization.
18+
type RAGEventCallback func(event ragtypes.Event)
19+
1620
// RAGTool provides document querying capabilities for a single RAG source
1721
type RAGTool struct {
18-
manager *rag.Manager
19-
toolName string
22+
manager *rag.Manager
23+
toolName string
24+
eventCallback RAGEventCallback
2025
}
2126

2227
// Verify interface compliance
@@ -35,6 +40,11 @@ func NewRAGTool(manager *rag.Manager, toolName string) *RAGTool {
3540
}
3641
}
3742

43+
// Name returns the tool name for this RAG source.
44+
func (t *RAGTool) Name() string {
45+
return t.toolName
46+
}
47+
3848
type QueryRAGArgs struct {
3949
Query string `json:"query" jsonschema:"Search query"`
4050
}
@@ -46,12 +56,24 @@ type QueryResult struct {
4656
ChunkIndex int `json:"chunk_index" jsonschema:"Index of the chunk within the source document"`
4757
}
4858

59+
// SetEventCallback sets a callback to receive RAG manager events during initialization.
60+
// This must be called before Start() to receive indexing progress events.
61+
func (t *RAGTool) SetEventCallback(cb RAGEventCallback) {
62+
t.eventCallback = cb
63+
}
64+
4965
// Start initializes the RAG manager (indexes documents).
5066
func (t *RAGTool) Start(ctx context.Context) error {
5167
if t.manager == nil {
5268
return nil
5369
}
5470
slog.Debug("Starting RAG tool initialization", "tool", t.toolName)
71+
72+
// Forward RAG manager events if a callback is set
73+
if t.eventCallback != nil {
74+
go t.forwardEvents(ctx)
75+
}
76+
5577
if err := t.manager.Initialize(ctx); err != nil {
5678
return fmt.Errorf("failed to initialize RAG manager %q: %w", t.toolName, err)
5779
}
@@ -64,6 +86,21 @@ func (t *RAGTool) Start(ctx context.Context) error {
6486
return nil
6587
}
6688

89+
// forwardEvents reads events from the RAG manager and forwards them via the callback.
90+
func (t *RAGTool) forwardEvents(ctx context.Context) {
91+
for {
92+
select {
93+
case <-ctx.Done():
94+
return
95+
case event, ok := <-t.manager.Events():
96+
if !ok {
97+
return
98+
}
99+
t.eventCallback(event)
100+
}
101+
}
102+
}
103+
67104
// Stop closes the RAG manager and releases resources.
68105
func (t *RAGTool) Stop(_ context.Context) error {
69106
if t.manager == nil {

0 commit comments

Comments
 (0)