From 2652c5a4657f5f16e06bc28eca257c3ec4e9422a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=B9=E5=9D=A4?= Date: Mon, 31 Aug 2026 19:05:40 +0800 Subject: [PATCH] fix(qoder): skip reserved environment metadata --- packages/sdk/src/internal/providers/qoder/adapter.ts | 4 +++- packages/sdk/tests/e2e/qoder-adapter-pagination.test.ts | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/sdk/src/internal/providers/qoder/adapter.ts b/packages/sdk/src/internal/providers/qoder/adapter.ts index 718a9ce..4ca70ff 100644 --- a/packages/sdk/src/internal/providers/qoder/adapter.ts +++ b/packages/sdk/src/internal/providers/qoder/adapter.ts @@ -450,7 +450,9 @@ export class QoderAdapter implements ProviderAdapter { const currentMetadata = (current.metadata ?? {}) as Record; const metadata = { ...((body.metadata ?? {}) as Record) }; for (const key of Object.keys(currentMetadata)) { - if (!key.startsWith("agents.") && !(key in metadata)) metadata[key] = null; + // Qoder injects created_by into environment responses but rejects it on writes, + // including deletion tombstones such as { created_by: null }. + if (key !== "created_by" && !key.startsWith("agents.") && !(key in metadata)) metadata[key] = null; } body.metadata = metadata; const res = (await client.post(`/environments/${id}`, body)) as Record; diff --git a/packages/sdk/tests/e2e/qoder-adapter-pagination.test.ts b/packages/sdk/tests/e2e/qoder-adapter-pagination.test.ts index 3346ced..b750a78 100644 --- a/packages/sdk/tests/e2e/qoder-adapter-pagination.test.ts +++ b/packages/sdk/tests/e2e/qoder-adapter-pagination.test.ts @@ -166,7 +166,9 @@ describe("QoderAdapter environment contract", () => { const { calls, restore } = mockFetch([ { status: 200, - body: { metadata: { keep: "old", remove: "stale", "agents.project": "test-project" } }, + body: { + metadata: { keep: "old", remove: "stale", created_by: "forward", "agents.project": "test-project" }, + }, }, { status: 200, body: { id: "env_1", type: "environment" } }, ]); @@ -190,6 +192,7 @@ describe("QoderAdapter environment contract", () => { "agents.resource": "dev", }, }); + expect(calls[1]?.body).not.toHaveProperty("metadata.created_by"); }); test("exports normalized setup scripts and omits response-only package defaults", async () => {