From e0dc9d52565f8ebb0231616ce0515a43bc0af154 Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Sat, 6 Jun 2026 23:17:40 +0800 Subject: [PATCH] fix: pass openclaw session key when reading artifacts --- internal/acp/openclaw_artifact_download.go | 15 ++++++--- internal/acp/routing_test.go | 36 +++++++++++++++++++++- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/internal/acp/openclaw_artifact_download.go b/internal/acp/openclaw_artifact_download.go index b451d80..d54abb4 100644 --- a/internal/acp/openclaw_artifact_download.go +++ b/internal/acp/openclaw_artifact_download.go @@ -46,7 +46,10 @@ func (s *Server) HandleOpenClawArtifactDownload(w http.ResponseWriter, r *http.R } query := r.URL.Query() - sessionKey := strings.TrimSpace(query.Get("sessionKey")) + sessionKey := strings.TrimSpace(query.Get("openclawSessionKey")) + if sessionKey == "" { + sessionKey = strings.TrimSpace(query.Get("sessionKey")) + } runID := strings.TrimSpace(query.Get("runId")) rawArtifactScope := strings.TrimSpace(query.Get("artifactScope")) artifactScope := safeOpenClawArtifactDownloadArtifactScope(rawArtifactScope) @@ -80,10 +83,11 @@ func (s *Server) HandleOpenClawArtifactDownload(w http.ResponseWriter, r *http.R return } readParams := map[string]any{ - "sessionKey": sessionKey, - "runId": runID, - "relativePath": relativePath, - "maxInlineBytes": openClawArtifactDownloadMaxBytes, + "openclawSessionKey": sessionKey, + "sessionKey": sessionKey, + "runId": runID, + "relativePath": relativePath, + "maxInlineBytes": openClawArtifactDownloadMaxBytes, } if artifactScope != "" { readParams["artifactScope"] = artifactScope @@ -323,6 +327,7 @@ func (s *Server) openClawArtifactDownloadURL( parsed.RawQuery = "" expires := strconv.FormatInt(now.Add(openClawArtifactDownloadTTL).Unix(), 10) query := parsed.Query() + query.Set("openclawSessionKey", sessionKey) query.Set("sessionKey", sessionKey) query.Set("runId", runID) query.Set("artifactScope", artifactScope) diff --git a/internal/acp/routing_test.go b/internal/acp/routing_test.go index 805ce96..d461437 100644 --- a/internal/acp/routing_test.go +++ b/internal/acp/routing_test.go @@ -2064,6 +2064,13 @@ func TestHTTPHandlerOpenClawArtifactDownloadReadsViaGateway(t *testing.T) { if downloadURL == "" { t.Fatal("expected signed download URL") } + parsedDownloadURL, err := url.Parse(downloadURL) + if err != nil { + t.Fatalf("parse downloadUrl: %v", err) + } + if got := parsedDownloadURL.Query().Get("openclawSessionKey"); got != "thread-openclaw-artifact" { + t.Fatalf("expected openclawSessionKey in downloadUrl, got %q", got) + } recorder := httptest.NewRecorder() request := httptest.NewRequest(http.MethodGet, downloadURL, nil) request.Header.Set("Authorization", "Bearer bridge-token") @@ -2081,6 +2088,10 @@ func TestHTTPHandlerOpenClawArtifactDownloadReadsViaGateway(t *testing.T) { if gateway.ArtifactReadCount() != 1 { t.Fatalf("expected one OpenClaw artifact read request, got %d", gateway.ArtifactReadCount()) } + readParams := gateway.LastArtifactReadParams() + if got := shared.StringArg(readParams, "openclawSessionKey", ""); got != "thread-openclaw-artifact" { + t.Fatalf("expected OpenClaw artifact read to use openclawSessionKey, got %#v", readParams) + } if got := gateway.Methods(); !sameMethods(got, []string{"connect", "xworkmate.artifacts.read"}) { t.Fatalf("expected connect, then artifact read, got %#v", got) } @@ -2873,6 +2884,7 @@ type acpFakeOpenClawGateway struct { lastArtifactPrepareParams atomic.Value lastArtifactSnapshotParams atomic.Value lastArtifactExportParams atomic.Value + lastArtifactReadParams atomic.Value lastAgentWaitParams atomic.Value mu sync.Mutex methods []string @@ -3554,8 +3566,22 @@ func newAcpFakeOpenClawGateway(t *testing.T) *acpFakeOpenClawGateway { case "xworkmate.artifacts.read": fake.artifactReadCount.Add(1) params := shared.AsMap(frame["params"]) + fake.lastArtifactReadParams.Store(params) relativePath := strings.TrimSpace(shared.StringArg(params, "relativePath", "")) artifactScope := strings.TrimSpace(shared.StringArg(params, "artifactScope", "")) + sessionKey := strings.TrimSpace(shared.StringArg(params, "openclawSessionKey", "")) + if sessionKey == "" { + _ = conn.WriteJSON(map[string]any{ + "type": "res", + "id": id, + "ok": false, + "error": map[string]any{ + "code": "OPENCLAW_ARTIFACT_READ_FAILED", + "message": "openclawSessionKey required", + }, + }) + continue + } if fake.consumeArtifactReadFailure() { _ = conn.WriteJSON(map[string]any{ "type": "res", @@ -3588,7 +3614,7 @@ func newAcpFakeOpenClawGateway(t *testing.T) *acpFakeOpenClawGateway { "ok": true, "payload": map[string]any{ "runId": strings.TrimSpace(shared.StringArg(params, "runId", "")), - "sessionKey": strings.TrimSpace(shared.StringArg(params, "openclawSessionKey", "")), + "sessionKey": sessionKey, "remoteWorkingDirectory": "/remote/openclaw/workspace", "remoteWorkspaceRefKind": "remotePath", "artifactScope": artifactScope, @@ -3799,6 +3825,14 @@ func (f *acpFakeOpenClawGateway) ArtifactReadCount() int { return int(f.artifactReadCount.Load()) } +func (f *acpFakeOpenClawGateway) LastArtifactReadParams() map[string]any { + value := f.lastArtifactReadParams.Load() + if value == nil { + return nil + } + return shared.AsMap(value) +} + func (f *acpFakeOpenClawGateway) FailNextArtifactReads(count int) { f.artifactReadFailures.Store(int32(count)) }