## 背景 切图新增基于连通域的切分后,LLM 仍倾向显式传 `sliceMode=grid`:参数只存在于部分 LLM 可见面、带默认值、没有任何决策规则,生成结果也不回显生效模式。 ## 变更 - 平台:`/api/editor/icon-spritesheets/generations` 与 `/api/external/v1/editor/icon-spritesheets/generations` 把 `sliceMode` 改为必填并移除默认值;缺失、空白或未知取值在引用解析、定价与任何 provider / OSS 副作用之前返回 `400`,错误统一带 `field` 与决策要求。 - 契约:`grid` 必须同时提供 `gridX`/`gridY`,`connected-components` 不接受网格尺寸;`sliceCount` 只约束连通域切分,请求与响应的公开上限统一为 `256`;OpenAPI 去掉默认值并补必填与失败语义。 - AGC:MCP 工具说明去掉默认值并补决策要求,桥接层新增可测试的切分声明校验;原生工具 `canvas.asset_generate` 暴露 `sliceMode/gridX/gridY/sliceCount` 并要求图集显式声明;生成结果回显 `sliceMode/gridX/gridY` 与 `slicePaths`;严格图集在本地提交前校验平台回显与请求声明一致。 - 标准美术包:显式声明 `connected-components` 加 `sliceCount=4`,并在四张 canonical 切片用途映射前校验数量,禁止截断或错位。 - 前端与画板:画板 Agent 工具装配与画板提交计划显式声明连通域切分;前端类型要求显式 `sliceMode` 并在本地校验声明自洽。 - 文档与 Skill:主规范、OpenAPI、AGC Skill、外部编辑器 Skill、里程碑与实施计划、共享决策记录同步更新。 - 测试环境:测试构建对提权 Windows 主机上系统临时目录的所有者偏差做一次性所有者初始化重试,临时目录之外的越权所有者继续失败关闭。 ## 兼容性影响 省略 `sliceMode` 的旧调用方(含已发布但未更新的 AGC 客户端与第三方外部 API 调用方)会在图集生成上收到 `400`;这是本次"不允许默认值"的预期结果,仓库内自有调用方已全部改为显式声明。 ## 验证 - 平台:`slice_mode_must_be_declared_*` 与 OpenAPI 契约测试通过;全量 `cargo test -p api-server` 1043 通过 / 11 失败(`wallet_refund_outbox` 临时文件 `拒绝访问`,已在改动前基线复现,属本机环境)。 - AGC:`slice` 30、`spritesheet` 21、`direct_tools_mcp` 23、`agent_native_tools` 16、`canvas_generation_tests` 83、提示词上限与桥接门禁各 1 条、`cargo check --tests` 全部通过。 - 前端:182 条定向测试与 `typecheck` 通过。 - 门禁:`cargo fmt --check`(两个 workspace)、`check:encoding`、`check:doc-index`、`git diff --check` 通过。 - 未验证:真实 Provider 与浏览器试玩、确定性 e2e 车道;整机全量 AGC 单进程运行在本机受提权 shell 的所有者与时序问题影响,不作为门禁信号。 --------- Co-authored-by: kdletters <61648117+kdletters@users.noreply.github.com> Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/408
11 KiB
name, description
| name | description |
|---|---|
| genarrative-external-editor-api | Guide use of Genarrative's hosted external editor/canvas MCP or asynchronous `/api/external/v1` OpenAPI. Use when an Agent needs to discover the hosted integration, choose a canvas or asset operation, upload local reference media, create or update projects and asset-library records, submit and poll image/video/audio generation, interpret generated artifacts and warnings, draft HTTP/Python calls, or securely handle a Genarrative developer API Key. |
Genarrative External Editor API
Discover the live integration through GET https://www.genarrative.world/api/external/v1/agent-integration.json. Treat GET https://www.genarrative.world/api/external/v1/openapi.json as the field-level source of truth. In this repository, the same contract is docs/openapi/genarrative-external-v1.openapi.json.
Prefer the hosted Streamable HTTP MCP at https://www.genarrative.world/api/external/v1/mcp when the Agent supports remote MCP with a custom Bearer token. It exposes the External v1 operations as tools and the Skill documentation as resources; it does not require a local MCP server. Use this complete Skill package when remote MCP is unavailable or local-file upload needs client-side orchestration.
Prefer scripts/genarrative_external_api.py for runnable REST calls. It uses only Python stdlib, reads the local private API Key file, keeps the production base URL fixed, uploads local references, and wraps asynchronous submission, polling, and result retrieval.
Workflow
- Discover the integration manifest. Choose hosted MCP when supported; otherwise use the helper or direct REST.
- Before the first generation in a new conversation, obtain a canvas name unless an existing
projectIdandassetFolderIdwere supplied. Create or reuse a project and a same-name asset-library folder. RetaincanvasName,projectId,assetFolderId, and the current art spec. - Normalize art requests into a reusable spec. Ask only for missing values that block the selected operation. Reuse the spec until the user changes its style, subject family, palette, format, or constraints.
- Infer the operation from the user's intent. Do not ask the user to select an API unless two operations would produce materially different artifacts.
- If a reference exists only as a local file, upload and confirm it first. Pass the stable returned
objectKeyto operations that accept object references; never substitute a temporary signed URL. For an icon-spritesheet primary spec, additionally create a project resource or asset record withassetKind="icon-spec", then pass the returned resource or asset ID asreferenceId. - For generation endpoints that support the fields, include
projectId,assetFolderId, an asset label, andcanvasCompletionso the result enters both the canvas and its same-name library folder. - Treat every generation POST as asynchronous. Send one stable
Idempotency-Keyper logical request, retain the returnedoperationId, and poll the returnedstatusUrlorGET /api/external/v1/generations/{operationId}according topollAfterMs. - Consume
resultonly afterstatus=completed. Onfailed, surface the safe error. On a client timeout or lost response, retain the operation/key; do not create a replacement request. - Reload the normal project or asset-library read endpoint when the caller needs complete authoritative state. Generation results are intentionally compact.
- Stay within
/api/external/v1. Never call internal workers, queues, admin/profile APIs, or SpacetimeDB endpoints unless the user explicitly changes scope.
Essential Invariants
- Authenticate MCP and business API calls with
Authorization: Bearer <tnr_sk_...>. Never ask the user to paste a key into chat or place one in repository files. - All nine generation POST routes require
Idempotency-Keyand return HTTP202;202is 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 where each operation permits them. Image edit/redraw is stricter:sourceReferenceIdaccepts only a registered project resource ID or asset ID; upload confirmation alone is not enough. Use/assets/read-urlonly for temporary preview/download access. - Preserve both warning channels after completion. A general
warningcan coexist withsliceWarning; 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.
- Icon spritesheet generation requires an explicit
sliceModeand has no default. UsesliceMode="grid"with thegridXandgridYthe requirement actually names (1-32 each) only for equal grid cells or fixed slots; usesliceMode="connected-components"for free-form sheets or an open number of subjects, and constrain the count withsliceCountinstead of inventing grid dimensions.connected-componentsmust not carrygridX/gridY; an omitted, contradictory, or misapplied declaration returns 400 before billing. - For successful
style="pixelArt", treat completed-result and nested resource/asset dimensions as the final logical-grid PNG dimensions. They may differ fromsize,imageSize, the provider image, andcanvasCompletion.placeholder; do not rescale or reject the artifact to match those inputs. - Keep generated artifacts in the canvas and asset library together. Character animation accepts
assetFolderIdandassetLabel; its completed result directly returns the finalassetKind="character-animation"resource and asset with formal sequence fields. Do not create a duplicate first-frame record.
Documentation Navigation
Read only the references needed for the task, but always verify exact schemas and enums against live OpenAPI:
references/capability-routing.md: read before selecting an MCP tool or REST operation, creating a canvas session, or working in the AI game creator visual DAG.references/api-operations.md: read when constructing project, canvas, asset-library, upload, generation, or generation-status calls.references/authentication-and-safety.md: read before handling credentials, local files, OSS form upload, retries, private media, or logs.references/requests-and-outputs.md: read before building generation payloads, polling, interpreting compact results, applying canvas completion, or handling post-processing warnings.
The hosted MCP exposes the same documents through:
genarrative://external-editor/skillgenarrative://external-editor/skill/references/capability-routing.mdgenarrative://external-editor/skill/references/api-operations.mdgenarrative://external-editor/skill/references/authentication-and-safety.mdgenarrative://external-editor/skill/references/requests-and-outputs.mdgenarrative://external-editor/openapi
Hosted Integration Discovery
- Manifest:
GET /api/external/v1/agent-integration.json. - Hosted MCP:
POST /api/external/v1/mcp, Streamable HTTP, same Bearer API Key. - OpenAPI:
GET /api/external/v1/openapi.json. - Raw Skill entry:
GET /api/external/v1/skill/SKILL.md. - Complete Skill archive:
GET /api/external/v1/skill.zip.
The archive contains this main file, four one-level references, the Python helper, and agents/openai.yaml. Verify its SHA-256 against agent-integration.json before installing. Discovery, OpenAPI, and Skill downloads are public; MCP and business operations require authentication.
Python Helper
Store the API Key outside the repository at ~/.config/genarrative/external-editor-api.json:
{
"apiKey": "tnr_sk_..."
}
Set restrictive permissions where possible, then smoke-test without printing the key:
chmod 600 ~/.config/genarrative/external-editor-api.json
python3 .codex/skills/genarrative-external-editor-api/scripts/genarrative_external_api.py list-projects
For a canvas-backed generation:
from genarrative_external_api import GenarrativeExternalClient
client = GenarrativeExternalClient()
session = client.prepare_canvas_session("新画板")
client.generate_image(
"生成一张 16:9 幻想森林游戏背景",
canvasSession=session,
assetLabel="森林背景",
aspectRatio="16:9",
imageSize="1K",
artSpec={
"assetType": "background",
"subject": "幻想森林主视觉",
"style": "手绘游戏概念图",
"palette": "翡翠绿与金色光斑",
"composition": "横版,中心留出角色站位",
"format": "16:9, 1K",
"constraints": "无文字、无 UI 按钮",
"references": [],
},
)
For background removal, pass a stable owner-scoped object key, project resource ID, or asset ID; the helper keeps the same asynchronous submission and polling contract:
session = client.prepare_canvas_session("去背景画布")
client.remove_background(
"editor-upload/object.png",
source_width=720,
source_height=1280,
canvasSession=session,
assetLabel="去背景结果",
)
Background removal preserves the source pixel size. For normal canvas placement with canvasSession, pass the real source_width and source_height, or provide both canvasWidth and canvasHeight; the helper rejects missing dimensions instead of guessing a square placeholder. assetKind may only describe a static image and must match the authoritative source record. Prefer a project resource ID or asset ID when the same object key has multiple semantic registrations; for a raw object key outside in-place replacement, pass sourceResourceId to disambiguate. Passing targetLayerId selects in-place replacement: the helper retains the session's project/library context but does not inject canvasCompletion, and it rejects an explicit canvasCompletion combined with targetLayerId. The target layer must point to the same authoritative object as the source, and the server durably binds a raw object key to that target resource for Worker revalidation.
Helper convenience methods wait locally, but the server still uses short asynchronous submit/status requests. For durable caller-controlled orchestration, call submit_generation, persist its operationId and idempotency key, then call get_generation or wait_for_generation.
For character animation, pass the canvas session and asset label to animate_character. The helper submits asynchronously and returns the completed compact result containing the authoritative formal resource and asset; do not synthesize a library asset from the first frame.
Guardrails
- Do not change the fixed production base URL in generated examples.
- Do not move the API Key into environment variables, source files, generated projects, logs, docs, screenshots, or shell snippets containing literal secrets.
- Do not treat a Data URL, Blob URL, expiring signed URL, worker lease, or provider diagnostic as a durable result.
- Do not reconstruct authoritative canvas, resource, or library snapshots from a compact generation response.
- Do not replace icon-spritesheet generation with ordinary image generation when the deliverable requires a reusable transparent atlas.