evomeme 0.1.10-beta.1 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,8 @@
1
1
  import { state } from '../../core/state.js'
2
2
  import { t } from '../../language/index.js'
3
- import { generationNode, promptField, modelField, refsField, imageWait } from './fields.js'
4
-
5
- const sizePresets = (model) => state.meta?.models?.find((entry) => entry.id === model)?.size_presets ||
6
- (state.meta?.size_presets || ['2048x2048']).filter((size) => model !== 'asset-lite' || size !== '1024x1024')
7
- const normalizeModelFields = (p) => {
8
- if (p.model !== 'asset-max' && p.background === 'auto') p.background = 'opaque'
9
- const supported = state.meta?.models?.find((entry) => entry.id === p.model)?.size_presets
10
- if (supported && !supported.includes(p.sizePreset) || p.model === 'asset-lite' && p.sizePreset === '1024x1024') {
11
- p.sizePreset = '2048x2048'
12
- }
13
- return p
14
- }
15
-
16
- export default {
3
+ import { generationNode, promptField, modelField, refsField, imageWait } from './fields.js'
4
+
5
+ export default {
17
6
  render: (ui) =>
18
7
  ui.stack(
19
8
  ui.prompt('prompt', 'refs'),
@@ -24,9 +13,7 @@ export default {
24
13
  id: 'image',
25
14
  title: 'features.generation.generationDialog.text009',
26
15
  node: generationNode('gen_dialog', 420),
27
- storage: 'imageGeneration',
28
- migrate: (saved) => normalizeModelFields(saved),
29
- changed: (p, field) => { if (field === 'model') normalizeModelFields(p) },
16
+ storage: 'imageGeneration',
30
17
  fields: [
31
18
  promptField({ required: true, placeholder: 'features.generation.imageGeneration.text022' }),
32
19
  refsField(),
@@ -34,14 +21,14 @@ export default {
34
21
  {
35
22
  path: 'background',
36
23
  type: 'enum',
37
- default: 'opaque',
24
+ default: 'auto',
38
25
  label: 'inspector.uiInspector.text014',
39
26
  visible: (p) => p.model !== 'asset-lite',
40
- options: (p) =>
41
- ['auto', 'transparent', 'opaque'].flatMap((value, index) => p.model !== 'asset-max' && value === 'auto' ? [] : [{
42
- value,
43
- labelKey: `features.generation.generationControls.text00${index + 1}`,
44
- }]),
27
+ options: () =>
28
+ ['auto', 'transparent', 'opaque'].map((value, index) => ({
29
+ value,
30
+ labelKey: `features.generation.generationControls.text00${index + 1}`,
31
+ })),
45
32
  },
46
33
  {
47
34
  path: 'sizeMode',
@@ -56,9 +43,9 @@ export default {
56
43
  {
57
44
  path: 'sizePreset',
58
45
  type: 'enum',
59
- default: () => state.meta?.default_size || '2048x2048',
46
+ default: () => state.meta?.default_size || '1024x1024',
60
47
  label: 'inspector.uiInspector.text018',
61
- options: (p) => sizePresets(p.model),
48
+ options: () => state.meta?.size_presets || ['1024x1024'],
62
49
  visible: (p) => p.sizeMode !== 'custom',
63
50
  },
64
51
  {
package/dist/index.js CHANGED
@@ -30950,12 +30950,7 @@ var messages = {
30950
30950
  "error.canvas.frontendMissing": "Image Canvas frontend assets were not found. Run npm run build first.",
30951
30951
  "error.canvas.portRead": "Could not determine the Image Canvas port",
30952
30952
  "error.canvas.portsOccupiedPrefix": "Ports ",
30953
- "error.canvas.portsOccupiedSuffix": " are all in use",
30954
- "error.image.modelSize": "{model} does not support size {size}. Use a valid size for this model; 2048x2048 is a supported default.",
30955
- "error.image.modelReferences": "{model} supports at most {limit} reference images.",
30956
- "error.image.liteTransparent": "asset-lite does not support transparent backgrounds. Use asset-max or cutout.",
30957
- "error.image.proTransparent": "asset-pro transparent backgrounds require exactly one reference image with transparency.",
30958
- "error.image.layerParameters": "Layer decomposition requires asset-pro and exactly one reference image."
30953
+ "error.canvas.portsOccupiedSuffix": " are all in use"
30959
30954
  };
30960
30955
  var en_US_default = messages;
30961
30956
 
@@ -31497,12 +31492,7 @@ var messages2 = {
31497
31492
  "error.canvas.frontendMissing": "找不到 Image Canvas 前端资源,请先运行 npm run build",
31498
31493
  "error.canvas.portRead": "无法读取素材画布端口",
31499
31494
  "error.canvas.portsOccupiedPrefix": "端口 ",
31500
- "error.canvas.portsOccupiedSuffix": " 均被占用",
31501
- "error.image.modelSize": "{model} 不支持尺寸 {size},请使用该模型的有效尺寸;默认可用 2048x2048。",
31502
- "error.image.modelReferences": "{model} 最多支持 {limit} 张参考图。",
31503
- "error.image.liteTransparent": "asset-lite 不支持透明背景,请使用 asset-max 或抠图功能。",
31504
- "error.image.proTransparent": "asset-pro 透明背景需要恰好一张带透明通道的参考图。",
31505
- "error.image.layerParameters": "图层拆分仅支持 asset-pro,且需要恰好一张参考图。"
31495
+ "error.canvas.portsOccupiedSuffix": " 均被占用"
31506
31496
  };
31507
31497
  var zh_CN_default = messages2;
31508
31498
 
@@ -31547,14 +31537,14 @@ var messages3 = {
31547
31537
  "",
31548
31538
  "On success, it downloads the final TOS image to the workspace assets directory and returns the job ID, TOS URL, local path, and an MCP multimodal image block.",
31549
31539
  "Use type asset for transparent game elements and type background for background images.",
31550
- 'For background="transparent", use image_model="asset-max" for text-to-image. asset-pro requires exactly one reference image that already has transparency; asset-lite does not support it.'
31540
+ 'Important: background="transparent" requires image_model="asset-max".'
31551
31541
  ].join("\n"),
31552
31542
  "image.prompt": "Image generation prompt. Required.",
31553
31543
  "image.type": "Image type. Defaults to background.",
31554
- "image.size": "WIDTHxHEIGHT or auto; default 2048x2048. Pro pixels: 921600..4624220; Lite: 3686400..16777216; both aspect ratios 1:16..16:1. Max pixels: 655360..8294400, edges <= 3840 and multiples of 16, aspect ratio 1:3..3:1. Pro/Lite auto uses 2048x2048.",
31555
- "image.references": "Optional reference image URL or array. At most 10 for asset-pro, 14 for asset-lite, or 16 for asset-max.",
31544
+ "image.size": "Image size preset. Defaults to 2048x2048.",
31545
+ "image.references": "Optional reference image URL or an array of up to 14 reference image URLs.",
31556
31546
  "image.model": "Image model. Defaults to asset-lite; asset-max and asset-pro are also supported.",
31557
- "image.background": "Optional background mode. auto uses the provider default on Pro/Lite. Lite rejects transparent. Pro transparent requires one reference image with transparency. Max supports all three modes.",
31547
+ "image.background": "Optional background mode. transparent can only be used with asset-max.",
31558
31548
  "image.workspace": "Optional absolute Agent workspace path. Defaults to the MCP process working directory.",
31559
31549
  "image.missingPrompt": "Missing required parameter: prompt",
31560
31550
  "image.invalidType": "Invalid image_type: ",
@@ -31676,14 +31666,14 @@ var messages4 = {
31676
31666
  "",
31677
31667
  "成功后会下载最终 TOS 图片到工作区 assets 目录,并返回 job_id、TOS URL、本地路径以及 MCP 多模态 image 内容块(Base64)。",
31678
31668
  "asset 类型用于生成透明底游戏元素(has_transparent_background=true),background 类型用于生成背景图。",
31679
- 'background="transparent":文生透明图使用 image_model="asset-max";asset-pro 必须提供恰好一张本身带透明通道的参考图;asset-lite 不支持。'
31669
+ '重要:使用 background="transparent" 时必须同时设置 image_model="asset-max";asset-pro 或 asset-lite 会直接报错。'
31680
31670
  ].join("\n"),
31681
31671
  "image.prompt": "生图提示词,必填。",
31682
31672
  "image.type": "图片类型,默认 background。",
31683
- "image.size": "尺寸 WIDTHxHEIGHT 或 auto,默认 2048x2048。Pro 总像素 921600..4624220;Lite 3686400..16777216,二者宽高比 1:16..16:1。Max 总像素 655360..8294400,边长不超过 3840 且为 16 的倍数,宽高比 1:3..3:1。auto 在 Pro/Lite 使用 2048x2048。",
31684
- "image.references": "可选,一张参考图 URL 或数组。asset-pro 最多 10 张,asset-lite 最多 14 张,asset-max 最多 16 张。",
31673
+ "image.size": "图片尺寸预设,默认 2048x2048。",
31674
+ "image.references": "可选,一张参考图 URL,或最多 14 张参考图 URL 数组。",
31685
31675
  "image.model": "生图模型,默认 asset-lite;可选 asset-max、asset-pro。",
31686
- "image.background": "可选背景模式。auto 在 Pro/Lite 中使用上游默认背景;Lite 不支持 transparent;Pro 的 transparent 必须提供一张带透明通道的参考图;Max 支持全部三种模式。",
31676
+ "image.background": "可选背景模式。transparent 仅可与 asset-max 搭配;用于 asset-pro 或 asset-lite 时生图接口会直接报错。",
31687
31677
  "image.workspace": "可选,Agent 工作区绝对路径;默认使用 MCP 进程当前工作目录。",
31688
31678
  "image.missingPrompt": "缺少必填参数 prompt",
31689
31679
  "image.invalidType": "无效的 image_type:",
@@ -39153,7 +39143,7 @@ var StdioClientTransport = class {
39153
39143
  };
39154
39144
 
39155
39145
  // src/version.ts
39156
- var VERSION = "0.1.10-beta.1";
39146
+ var VERSION = "0.1.10";
39157
39147
 
39158
39148
  // src/publishChannel.generated.ts
39159
39149
  var PUBLISH_NPM_NAME = "evomeme";
@@ -40095,31 +40085,6 @@ var GAME_IMAGE_SIZES = [
40095
40085
  ];
40096
40086
  var GAME_IMAGE_MODELS = ["asset-max", "asset-pro", "asset-lite"];
40097
40087
  var GAME_IMAGE_BACKGROUNDS = ["auto", "transparent", "opaque"];
40098
- var IMAGE_REFERENCE_LIMITS = {
40099
- "asset-pro": 10,
40100
- "asset-lite": 14,
40101
- "asset-max": 16
40102
- };
40103
- function normalizeGameImageSize(model, size) {
40104
- size = size.trim();
40105
- if (size === "auto") return model === "asset-max" ? "auto" : "2048x2048";
40106
- const match = /^([1-9][0-9]*)x([1-9][0-9]*)$/.exec(size);
40107
- const [width, height] = match ? [Number(match[1]), Number(match[2])] : [0, 0];
40108
- const pixels = width * height;
40109
- const valid = Number.isSafeInteger(pixels) && width > 0 && height > 0 && (model === "asset-max" ? width <= 3840 && height <= 3840 && width % 16 === 0 && height % 16 === 0 && Math.max(width, height) <= 3 * Math.min(width, height) && pixels >= 655360 && pixels <= 8294400 : Math.max(width, height) <= 16 * Math.min(width, height) && (model === "asset-pro" ? pixels >= 921600 && pixels <= 4624220 : pixels >= 3686400 && pixels <= 16777216));
40110
- if (!valid) throw new Error(formatMessage("error.image.modelSize", { model, size }));
40111
- return size;
40112
- }
40113
- function gameImageSizePresets(model) {
40114
- return GAME_IMAGE_SIZES.filter((size) => {
40115
- try {
40116
- normalizeGameImageSize(model, size);
40117
- return true;
40118
- } catch {
40119
- return false;
40120
- }
40121
- });
40122
- }
40123
40088
  var IMAGE_JOB_STATUSES = [
40124
40089
  "QUEUED",
40125
40090
  "RUNNING",
@@ -40140,35 +40105,7 @@ var GAME_IMAGE_MODEL_BACKEND = {
40140
40105
  function resolveGameImageModel(model) {
40141
40106
  return GAME_IMAGE_MODEL_BACKEND[model];
40142
40107
  }
40143
- function normalizeGameImageInput(input) {
40144
- const model = input.imageModel ?? "asset-lite";
40145
- const refs = (Array.isArray(input.referenceImageUrl) ? input.referenceImageUrl : input.referenceImageUrl ? [input.referenceImageUrl] : []).map((url) => url.trim()).filter(Boolean);
40146
- const limit = IMAGE_REFERENCE_LIMITS[model];
40147
- if (refs.length > limit) throw new Error(formatMessage("error.image.modelReferences", { model, limit }));
40148
- if (input.layerDecomposition) {
40149
- if (model !== "asset-pro" || refs.length !== 1) {
40150
- throw new Error(formatMessage("error.image.layerParameters", {}));
40151
- }
40152
- return { ...input, size: "auto", background: void 0 };
40153
- }
40154
- let background = input.background;
40155
- if (model === "asset-lite") {
40156
- if (background === "transparent") throw new Error(formatMessage("error.image.liteTransparent", {}));
40157
- background = void 0;
40158
- } else if (model === "asset-pro") {
40159
- if (background === "auto") background = void 0;
40160
- if (background === "transparent" && refs.length !== 1) {
40161
- throw new Error(formatMessage("error.image.proTransparent", {}));
40162
- }
40163
- }
40164
- return {
40165
- ...input,
40166
- ...input.size === void 0 ? {} : { size: normalizeGameImageSize(model, input.size) },
40167
- ...input.background === void 0 ? {} : { background }
40168
- };
40169
- }
40170
40108
  async function generateGameImage(token, input, options = {}) {
40171
- input = normalizeGameImageInput(input);
40172
40109
  const client = createPluginServerClient(options);
40173
40110
  const body = { prompt: input.prompt };
40174
40111
  if (input.imageType !== void 0) {
@@ -45373,27 +45310,17 @@ async function executeImageGeneration(workspaceDir, body, imageServiceDeps) {
45373
45310
  if (!prompt) throw httpError(400, t("error.task.promptRequired"));
45374
45311
  const operationId = String(body.client_operation_id || createOperationId());
45375
45312
  const referenceIds = Array.isArray(body.reference_ids) ? body.reference_ids.map(String).filter(Boolean) : [];
45313
+ if (referenceIds.length > 14) throw httpError(400, t("error.task.maxReferences"));
45376
45314
  const interactiveReferenceData = String(body.reference_image_data || "").trim();
45377
45315
  const imageModel = String(body.model || "asset-pro");
45378
- let size = String(body.size || "2048x2048");
45316
+ const size = String(body.size || "2048x2048");
45379
45317
  const layerDecomposition = body.layer_decomposition === true;
45380
- let requestedBackground = layerDecomposition || interactiveReferenceData ? void 0 : normalizeImageBackground(body.background);
45318
+ const requestedBackground = layerDecomposition || interactiveReferenceData ? void 0 : normalizeImageBackground(body.background);
45381
45319
  if (!GAME_IMAGE_MODELS.includes(imageModel)) {
45382
45320
  throw httpError(400, t("error.task.unsupportedImageModel") + imageModel);
45383
45321
  }
45384
- try {
45385
- const normalized = normalizeGameImageInput({
45386
- prompt,
45387
- imageModel,
45388
- size: interactiveReferenceData ? "auto" : size,
45389
- background: requestedBackground,
45390
- layerDecomposition,
45391
- referenceImageUrl: Array.isArray(body.reference_image_urls) ? body.reference_image_urls.map(String) : referenceIds
45392
- });
45393
- size = normalized.size;
45394
- requestedBackground = normalized.background;
45395
- } catch (error2) {
45396
- throw httpError(400, error2.message);
45322
+ if (!GAME_IMAGE_SIZES.includes(size)) {
45323
+ throw httpError(400, t("error.task.unsupportedImageSize") + size);
45397
45324
  }
45398
45325
  if (!body.reference_image_urls && imageModel === "asset-pro" && requestedBackground === "transparent") {
45399
45326
  if (referenceIds.length !== 1 || path35.extname(resolveAssetPath(workspaceDir, referenceIds[0])).toLowerCase() !== ".png") {
@@ -45422,7 +45349,7 @@ async function executeImageGeneration(workspaceDir, body, imageServiceDeps) {
45422
45349
  const interactiveReference = interactiveReferenceData ? await uploadInteractiveReference(workspaceDir, interactiveReferenceData, imageServiceDeps) : void 0;
45423
45350
  const referenceImageUrls = Array.isArray(body.reference_image_urls) ? body.reference_image_urls.map(String) : interactiveReference ? [interactiveReference.assetUrl] : referenceIds.length ? await Promise.all(referenceIds.map((assetId) => ensureReferenceAssetUrl(workspaceDir, assetId))) : void 0;
45424
45351
  const background = requestedBackground;
45425
- const operationSize = layerDecomposition ? "auto" : interactiveReference ? resolveInteractiveEditSize(interactiveReference.width, interactiveReference.height, imageModel) : size;
45352
+ const operationSize = layerDecomposition ? "auto" : interactiveReference ? resolveInteractiveEditSize(interactiveReference.width, interactiveReference.height) : size;
45426
45353
  const canvasJob = await beginTask({
45427
45354
  operationId,
45428
45355
  workspaceDir,
@@ -48349,39 +48276,19 @@ async function uploadInteractiveReference(workspaceDir, dataUrl, imageServiceDep
48349
48276
  await unlink4(localPath).catch(() => void 0);
48350
48277
  }
48351
48278
  }
48352
- function resolveInteractiveEditSize(width, height, model = "asset-pro") {
48279
+ function resolveInteractiveEditSize(width, height) {
48353
48280
  if (!Number.isSafeInteger(width) || width <= 0 || !Number.isSafeInteger(height) || height <= 0) {
48354
48281
  throw new Error(t("error.task.interactiveSizeInvalid") + `${width}x${height}`);
48355
48282
  }
48356
48283
  const pixels = width * height;
48357
- if (model === "asset-max") {
48358
- if (Math.max(width, height) > 3 * Math.min(width, height)) {
48359
- return normalizeGameImageSize(model, `${width}x${height}`);
48360
- }
48361
- const targetPixels2 = Math.min(8294400, Math.max(655360, pixels));
48362
- const scale = Math.min(Math.sqrt(targetPixels2 / pixels), 3840 / Math.max(width, height));
48363
- let targetWidth2 = Math.max(16, Math.round(width * scale / 16) * 16);
48364
- let targetHeight2 = Math.max(16, Math.round(height * scale / 16) * 16);
48365
- while (targetWidth2 > 3 * targetHeight2) targetHeight2 += 16;
48366
- while (targetHeight2 > 3 * targetWidth2) targetWidth2 += 16;
48367
- while (targetWidth2 * targetHeight2 < 655360) {
48368
- targetWidth2 += 16;
48369
- targetHeight2 += 16;
48370
- }
48371
- while (targetWidth2 * targetHeight2 > 8294400) {
48372
- if (targetWidth2 >= targetHeight2) targetWidth2 -= 16;
48373
- else targetHeight2 -= 16;
48374
- }
48375
- return normalizeGameImageSize(model, `${targetWidth2}x${targetHeight2}`);
48376
- }
48377
48284
  if (pixels >= INTERACTIVE_EDIT_MIN_PIXELS && pixels <= INTERACTIVE_EDIT_MAX_PIXELS) {
48378
- return normalizeGameImageSize(model, `${width}x${height}`);
48285
+ return `${width}x${height}`;
48379
48286
  }
48380
48287
  const targetPixels = pixels < INTERACTIVE_EDIT_MIN_PIXELS ? INTERACTIVE_EDIT_MIN_PIXELS : INTERACTIVE_EDIT_MAX_PIXELS;
48381
48288
  const aspectRatio = width / height;
48382
48289
  const targetHeight = Math.max(1, Math.round(Math.sqrt(targetPixels / aspectRatio)));
48383
48290
  const targetWidth = pixels < INTERACTIVE_EDIT_MIN_PIXELS ? Math.ceil(targetPixels / targetHeight) : Math.max(1, Math.floor(targetPixels / targetHeight));
48384
- return normalizeGameImageSize(model, `${targetWidth}x${targetHeight}`);
48291
+ return `${targetWidth}x${targetHeight}`;
48385
48292
  }
48386
48293
  async function extractVideoAssetFrames(workspaceDir, assetId, fps, requestedOperationId = "") {
48387
48294
  if (!Number.isFinite(fps) || fps < 0.1 || fps > 60) {
@@ -50697,12 +50604,7 @@ async function handleApi(request, response, url, workspaceDir, eventHub, videoGe
50697
50604
  if (request.method === "GET" && pathname === "/api/meta") {
50698
50605
  const paths = canvasWorkspacePaths(workspaceDir);
50699
50606
  sendJson(response, 200, {
50700
- models: GAME_IMAGE_MODELS.map((model) => ({
50701
- id: model,
50702
- label: model,
50703
- size_presets: gameImageSizePresets(model),
50704
- max_references: IMAGE_REFERENCE_LIMITS[model]
50705
- })),
50607
+ models: GAME_IMAGE_MODELS.map((model) => ({ id: model, label: model })),
50706
50608
  default_model: "asset-pro",
50707
50609
  backgrounds: GAME_IMAGE_BACKGROUNDS,
50708
50610
  size_presets: GAME_IMAGE_SIZES,
@@ -53506,12 +53408,13 @@ var generateGameImageTool = {
53506
53408
  },
53507
53409
  size: {
53508
53410
  type: "string",
53411
+ enum: [...GAME_IMAGE_SIZES],
53509
53412
  description: mcpT("image.size")
53510
53413
  },
53511
53414
  reference_image_url: {
53512
53415
  oneOf: [
53513
53416
  { type: "string" },
53514
- { type: "array", items: { type: "string" }, minItems: 1, maxItems: 16 }
53417
+ { type: "array", items: { type: "string" }, minItems: 1, maxItems: 14 }
53515
53418
  ],
53516
53419
  description: mcpT("image.references")
53517
53420
  },
@@ -53574,6 +53477,9 @@ function buildGenerateInput(args) {
53574
53477
  input.imageType = args.image_type;
53575
53478
  }
53576
53479
  if (args.size !== void 0) {
53480
+ if (!GAME_IMAGE_SIZES.includes(args.size)) {
53481
+ return new Error(mcpT("image.invalidSize") + args.size);
53482
+ }
53577
53483
  input.size = args.size;
53578
53484
  }
53579
53485
  if (args.image_model !== void 0) {
@@ -53591,9 +53497,10 @@ function buildGenerateInput(args) {
53591
53497
  if (args.reference_image_url !== void 0) {
53592
53498
  const references = (Array.isArray(args.reference_image_url) ? args.reference_image_url : [args.reference_image_url]).map((value) => value.trim()).filter(Boolean);
53593
53499
  if (!references.length) return new Error(mcpT("image.emptyReferences"));
53500
+ if (references.length > 14) return new Error(mcpT("image.tooManyReferences"));
53594
53501
  input.referenceImageUrl = references.length === 1 ? references[0] : references;
53595
53502
  }
53596
- return normalizeGameImageInput(input);
53503
+ return input;
53597
53504
  }
53598
53505
 
53599
53506
  // src/mcp/tools/cutoutGameImage.ts
@@ -55078,7 +54985,6 @@ function parseGenerateImageArgs(args) {
55078
54985
  size: typeof args.size === "string" ? args.size : void 0,
55079
54986
  reference_image_url: typeof args.reference_image_url === "string" ? args.reference_image_url : Array.isArray(args.reference_image_url) ? args.reference_image_url.filter((value) => typeof value === "string") : void 0,
55080
54987
  image_model: typeof args.image_model === "string" ? args.image_model : void 0,
55081
- background: typeof args.background === "string" ? args.background : void 0,
55082
54988
  workspace_dir: typeof args.workspace_dir === "string" ? args.workspace_dir : void 0
55083
54989
  };
55084
54990
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evomeme",
3
- "version": "0.1.10-beta.1",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "description": "evomemeplugin_client - local stdio MCP server. Install: npx -y evomeme@latest install --ide cursor. Init: npx -y evomeme@latest init.",
6
6
  "main": "dist/index.js",