From cde1202f929581451377b497e7de5ebe6cf9bbdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Fri, 7 Aug 2026 14:05:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=A4=96=E9=83=A8=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E7=BC=96=E8=BE=91=E8=B0=83=E7=94=A8=E6=8C=87=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 调整 Python helper 使用 source_reference_id 并拒绝空业务 ID 说明上传对象必须先登记为项目资源或素材 同步 External Editor skill 的请求示例和安全边界 --- .codex/skills/genarrative-external-editor-api/SKILL.md | 2 +- .../references/api-operations.md | 6 +++--- .../references/requests-and-outputs.md | 2 ++ .../scripts/genarrative_external_api.py | 7 +++++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.codex/skills/genarrative-external-editor-api/SKILL.md b/.codex/skills/genarrative-external-editor-api/SKILL.md index d8aa83ba8..99139f764 100644 --- a/.codex/skills/genarrative-external-editor-api/SKILL.md +++ b/.codex/skills/genarrative-external-editor-api/SKILL.md @@ -29,7 +29,7 @@ Prefer `scripts/genarrative_external_api.py` for runnable REST calls. It uses on - Authenticate MCP and business API calls with `Authorization: Bearer `. Never ask the user to paste a key into chat or place one in repository files. - All eight generation POST routes require `Idempotency-Key` and return HTTP `202`; `202` is durable acceptance, not a media result. - Retry an uncertain submission only with the exact same body and the same idempotency key. A polling timeout is not permission to generate again. -- Use stable references such as `objectKey`, project resource ID, or asset ID in generation requests. Use `/assets/read-url` only for temporary preview/download access. +- Use stable references such as `objectKey`, project resource ID, or asset ID where each operation permits them. Image edit/redraw is stricter: `sourceReferenceId` accepts only a registered project resource ID or asset ID; upload confirmation alone is not enough. Use `/assets/read-url` only for temporary preview/download access. - Preserve both warning channels after completion. A general `warning` can coexist with `sliceWarning`; do not discard either. - Do not invent missing derivatives. A source-preserved warning means the main source remains usable but requested post-processing failed. A slice warning means the complete transparent sheet is usable but individual slices are absent. - Keep generated artifacts in the canvas and asset library together. Character animation accepts `assetFolderId` and `assetLabel`; its completed result directly returns the final `assetKind="character-animation"` resource and asset with formal sequence fields. Do not create a duplicate first-frame record. diff --git a/.codex/skills/genarrative-external-editor-api/references/api-operations.md b/.codex/skills/genarrative-external-editor-api/references/api-operations.md index 1597a2a12..7afdc0d81 100644 --- a/.codex/skills/genarrative-external-editor-api/references/api-operations.md +++ b/.codex/skills/genarrative-external-editor-api/references/api-operations.md @@ -43,7 +43,7 @@ Every generation row requires a stable `Idempotency-Key` header and returns HTTP | Capability | POST path | Required body fields | Common optional body fields | | --- | --- | --- | --- | | Image generation | `/api/external/v1/editor/images/generations` | `prompt` | `kind`, `style`, `model`, `aspectRatio`, `imageSize`, `size`, `referenceImageSrcs`, `projectId`, `assetFolderId`, `assetLabel`, `canvasCompletion`, `generationInputs` | -| Image edit/redraw | `/api/external/v1/editor/images/edits` | `prompt`, `sourceImageSrc` | `referenceImageSrcs`, `model`, `size`, `projectId`, `assetFolderId`, `assetLabel`, `sourceResourceId`, `targetLayerId`, `canvasCompletion` | +| Image edit/redraw | `/api/external/v1/editor/images/edits` | `prompt`, `sourceReferenceId` | `referenceImageSrcs`, `model`, `size`, `projectId`, `assetFolderId`, `assetLabel`, `targetLayerId`, `canvasCompletion` | | Icon spritesheet | `/api/external/v1/editor/icon-spritesheets/generations` | `referenceImageSrc`, `iconDescriptions` | `style`, `referenceImageSrcs`, `screenColor`, `model`, `aspectRatio`, `imageSize`, `projectId`, `assetFolderId`, `assetLabel`, `canvasCompletion` | | UI asset extraction | `/api/external/v1/editor/ui-designs/assets/extractions` | `sourceImageSrc`, `aspectRatio`, `imageSize` | `screenColor`, `model`, `referenceImageSrcs`, `projectId`, `assetFolderId`, `spritesheetLabel`, `canvasCompletion` | | Character animation | `/api/external/v1/editor/character-animations/generations` | `sourceLayerId`, `sourceImageSrc`, `sourceWidth`, `sourceHeight`, `promptText`, `resolution`, `ratio`, `frameCount`, `durationSeconds`, `model` | `projectId`, `sourceResourceId`, `assetFolderId`, `assetLabel`, `canvasCompletion` | @@ -75,13 +75,13 @@ After confirming a local upload, pass its stable `objectKey` into: | Target capability | Field | | --- | --- | | Image generation | `referenceImageSrcs` | -| Image edit/redraw | `sourceImageSrc`; additional references in `referenceImageSrcs` | +| Image edit/redraw | `sourceReferenceId` must be a registered project resource ID or asset ID; additional references remain in `referenceImageSrcs` | | Icon spritesheet | `referenceImageSrc`; additional style references in `referenceImageSrcs` | | UI design extraction | `sourceImageSrc`; additional references in `referenceImageSrcs` | | Character animation | `sourceImageSrc` | | Video with image references | `referenceImageSrcs` | -Use video/audio reference arrays only with models that support them. Do not pass an expiring signed read URL as a generation reference. +For image edit/redraw, confirming an upload is not sufficient: create a project resource or asset-library record first, then pass that record's ID as `sourceReferenceId`. The main source never accepts objectKey, URL, Data URL, or Blob URL. Use video/audio reference arrays only with models that support them. Do not pass an expiring signed read URL as a generation reference. ## Common Values diff --git a/.codex/skills/genarrative-external-editor-api/references/requests-and-outputs.md b/.codex/skills/genarrative-external-editor-api/references/requests-and-outputs.md index 1f3d04e3c..767a2fcc6 100644 --- a/.codex/skills/genarrative-external-editor-api/references/requests-and-outputs.md +++ b/.codex/skills/genarrative-external-editor-api/references/requests-and-outputs.md @@ -167,6 +167,8 @@ client.generate_image( ) ``` +Image edit/redraw has a stricter main-source identity rule. After upload confirmation, create either a project resource or an asset-library record and pass its `resourceId` or `assetId` as `sourceReferenceId`. Do not pass the uploaded objectKey as the main source; objectKey remains valid only for auxiliary `referenceImageSrcs` where the OpenAPI permits it. + For character animation from a local-only source, use actual dimensions and a stable synthetic layer ID: ```json diff --git a/.codex/skills/genarrative-external-editor-api/scripts/genarrative_external_api.py b/.codex/skills/genarrative-external-editor-api/scripts/genarrative_external_api.py index bce78e20e..616a5d277 100644 --- a/.codex/skills/genarrative-external-editor-api/scripts/genarrative_external_api.py +++ b/.codex/skills/genarrative-external-editor-api/scripts/genarrative_external_api.py @@ -548,13 +548,16 @@ class GenarrativeExternalClient: idempotency_key=idempotency_key, ) - def edit_image(self, prompt: str, source_image_src: str, **fields: Any) -> Any: + def edit_image(self, prompt: str, source_reference_id: str, **fields: Any) -> Any: + source_reference_id = source_reference_id.strip() + if not source_reference_id: + raise GenarrativeApiError("source_reference_id must be a registered resource or asset ID") self._apply_canvas_session_fields(fields, prompt, 1024, 1024) prompt = self._apply_art_spec(fields, prompt) idempotency_key = fields.pop("idempotencyKey", None) return self.submit_and_wait_generation( "/api/external/v1/editor/images/edits", - {"prompt": prompt, "sourceImageSrc": source_image_src, **fields}, + {"prompt": prompt, "sourceReferenceId": source_reference_id, **fields}, idempotency_key=idempotency_key, )