fix(gateway): sign file URLs in run.completed events for real-time display

OnEvent callback only handled map[string]string payloads, but
run.completed uses map[string]any (contains usage map + media slice).
File URLs in content were never signed, and media paths were sent as
raw local paths without ?ft= hash tokens.

Switch on payload type to handle both shapes: sign content URLs and
convert media local paths to /v1/files/basename?ft=hash.
This commit is contained in:
viettranx committed 2026-03-25 09:48:39 +07:00
1 parent 9a24995e56
commit d3a4398e78
1 file changed
+19 -2
+19 -2
View File
@@ -166,9 +166,26 @@ func wireExtras(
OnEvent: func(event agent.AgentEvent) {
// Sign /v1/files/ and /v1/media/ URLs in content before delivery.
// Sessions store clean paths; signing happens only at delivery time.
if m, ok := event.Payload.(map[string]string); ok {
secret := httpapi.FileSigningKey()
switch m := event.Payload.(type) {
case map[string]string:
if c, has := m["content"]; has && strings.Contains(c, "/v1/") {
m["content"] = httpapi.SignFileURLs(c, httpapi.FileSigningKey())
m["content"] = httpapi.SignFileURLs(c, secret)
}
case map[string]any:
// Sign /v1/ URLs in content text (run.completed payload is map[string]any).
if c, ok := m["content"].(string); ok && strings.Contains(c, "/v1/") {
m["content"] = httpapi.SignFileURLs(c, secret)
}
// Convert media local paths → signed /v1/files/basename?ft=hash
if rawMedia, ok := m["media"].([]agent.MediaResult); ok {
for i := range rawMedia {
basename := filepath.Base(rawMedia[i].Path)
url := "/v1/files/" + basename
ft := httpapi.SignFileToken(url, secret, httpapi.FileTokenTTL)
rawMedia[i].Path = url + "?ft=" + ft
}
m["media"] = rawMedia
}
}
msgBus.Broadcast(bus.Event{