diff --git a/docs/asset_api_adoption_decision.md b/docs/asset_api_adoption_decision.md index 511a7bb..baf298e 100644 --- a/docs/asset_api_adoption_decision.md +++ b/docs/asset_api_adoption_decision.md @@ -1,5 +1,11 @@ # ComfyUI Asset API Adoption Decision (2026-04-16) +## 2026-05-31 reconfirmation + +- Current host reference evidence shows upstream asset responses may expose `hash` alongside `asset_hash`. +- OpenClaw accepts `hash` as an alias for hash-backed previews, but still resolves those refs through `/view?filename=blake3:...`. +- This does not change the no-go decision for automatic direct `/api/assets` runtime fetches. + ## Scope - Goal: decide whether OpenClaw should adopt upstream `/api/assets` semantics as a normal runtime dependency beyond the bounded `/view` interoperability layer. diff --git a/tests/e2e/specs/r107_live_backend.spec.js b/tests/e2e/specs/r107_live_backend.spec.js index d16b266..64afc59 100644 --- a/tests/e2e/specs/r107_live_backend.spec.js +++ b/tests/e2e/specs/r107_live_backend.spec.js @@ -140,7 +140,7 @@ test.describe('R107 Live Backend Parity', () => { { filename: "preview.png", type: "temp", - asset_hash: "blake3:abc123", + hash: "blake3:abc123", }, { asset: { diff --git a/web/openclaw_asset_refs.js b/web/openclaw_asset_refs.js index ffccb6e..13cbbf2 100644 --- a/web/openclaw_asset_refs.js +++ b/web/openclaw_asset_refs.js @@ -2,13 +2,20 @@ function pickAssetHash(imageRef = {}) { if (!imageRef || typeof imageRef !== "object") { return ""; } - const direct = typeof imageRef.asset_hash === "string" ? imageRef.asset_hash.trim() : ""; + const direct = typeof imageRef.asset_hash === "string" + ? imageRef.asset_hash.trim() + : (typeof imageRef.hash === "string" ? imageRef.hash.trim() : ""); if (direct) { return direct; } const nested = imageRef.asset; - if (nested && typeof nested === "object" && typeof nested.asset_hash === "string") { - return nested.asset_hash.trim(); + if (nested && typeof nested === "object") { + if (typeof nested.asset_hash === "string" && nested.asset_hash.trim()) { + return nested.asset_hash.trim(); + } + if (typeof nested.hash === "string" && nested.hash.trim()) { + return nested.hash.trim(); + } } return ""; } diff --git a/web/tests/unit/openclaw_asset_refs.test.js b/web/tests/unit/openclaw_asset_refs.test.js index 5cf7254..a7f34d9 100644 --- a/web/tests/unit/openclaw_asset_refs.test.js +++ b/web/tests/unit/openclaw_asset_refs.test.js @@ -75,6 +75,52 @@ describe("openclaw asset refs", () => { }); }); + it("accepts top-level hash as an asset_hash alias", () => { + expect( + normalizeComfyOutputRef({ + filename: "hash-alias.png", + hash: "blake3:alias123", + }) + ).toEqual({ + filename: "hash-alias.png", + subfolder: "", + type: "output", + asset_hash: "blake3:alias123", + asset_api_id: "", + asset_api_required: false, + resolution: "view", + unsupported_reason: "", + is_asset_backed: true, + viewParams: { + filename: "blake3:alias123", + }, + }); + }); + + it("accepts nested asset.hash as an asset_hash alias", () => { + expect( + normalizeComfyOutputRef({ + name: "nested-hash-alias.png", + asset: { + hash: "blake3:nested-alias", + }, + }) + ).toEqual({ + filename: "nested-hash-alias.png", + subfolder: "", + type: "output", + asset_hash: "blake3:nested-alias", + asset_api_id: "", + asset_api_required: false, + resolution: "view", + unsupported_reason: "", + is_asset_backed: true, + viewParams: { + filename: "blake3:nested-alias", + }, + }); + }); + it("keeps asset-api-only refs explicit instead of silently turning them into /api/assets fetches", () => { expect( normalizeComfyOutputRef({