evomeme 0.1.9-beta.23 → 0.1.10-beta.1

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,8 +1,19 @@
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
- export default {
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 {
6
17
  render: (ui) =>
7
18
  ui.stack(
8
19
  ui.prompt('prompt', 'refs'),
@@ -13,7 +24,9 @@ export default {
13
24
  id: 'image',
14
25
  title: 'features.generation.generationDialog.text009',
15
26
  node: generationNode('gen_dialog', 420),
16
- storage: 'imageGeneration',
27
+ storage: 'imageGeneration',
28
+ migrate: (saved) => normalizeModelFields(saved),
29
+ changed: (p, field) => { if (field === 'model') normalizeModelFields(p) },
17
30
  fields: [
18
31
  promptField({ required: true, placeholder: 'features.generation.imageGeneration.text022' }),
19
32
  refsField(),
@@ -21,14 +34,14 @@ export default {
21
34
  {
22
35
  path: 'background',
23
36
  type: 'enum',
24
- default: 'auto',
37
+ default: 'opaque',
25
38
  label: 'inspector.uiInspector.text014',
26
39
  visible: (p) => p.model !== 'asset-lite',
27
- options: () =>
28
- ['auto', 'transparent', 'opaque'].map((value, index) => ({
29
- value,
30
- labelKey: `features.generation.generationControls.text00${index + 1}`,
31
- })),
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
+ }]),
32
45
  },
33
46
  {
34
47
  path: 'sizeMode',
@@ -43,9 +56,9 @@ export default {
43
56
  {
44
57
  path: 'sizePreset',
45
58
  type: 'enum',
46
- default: () => state.meta?.default_size || '1024x1024',
59
+ default: () => state.meta?.default_size || '2048x2048',
47
60
  label: 'inspector.uiInspector.text018',
48
- options: () => state.meta?.size_presets || ['1024x1024'],
61
+ options: (p) => sizePresets(p.model),
49
62
  visible: (p) => p.sizeMode !== 'custom',
50
63
  },
51
64
  {
package/dist/index.js CHANGED
@@ -30950,7 +30950,12 @@ 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"
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."
30954
30959
  };
30955
30960
  var en_US_default = messages;
30956
30961
 
@@ -31492,7 +31497,12 @@ var messages2 = {
31492
31497
  "error.canvas.frontendMissing": "找不到 Image Canvas 前端资源,请先运行 npm run build",
31493
31498
  "error.canvas.portRead": "无法读取素材画布端口",
31494
31499
  "error.canvas.portsOccupiedPrefix": "端口 ",
31495
- "error.canvas.portsOccupiedSuffix": " 均被占用"
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,且需要恰好一张参考图。"
31496
31506
  };
31497
31507
  var zh_CN_default = messages2;
31498
31508
 
@@ -31537,14 +31547,14 @@ var messages3 = {
31537
31547
  "",
31538
31548
  "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.",
31539
31549
  "Use type asset for transparent game elements and type background for background images.",
31540
- 'Important: background="transparent" requires image_model="asset-max".'
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.'
31541
31551
  ].join("\n"),
31542
31552
  "image.prompt": "Image generation prompt. Required.",
31543
31553
  "image.type": "Image type. Defaults to background.",
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.",
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.",
31546
31556
  "image.model": "Image model. Defaults to asset-lite; asset-max and asset-pro are also supported.",
31547
- "image.background": "Optional background mode. transparent can only be used with asset-max.",
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.",
31548
31558
  "image.workspace": "Optional absolute Agent workspace path. Defaults to the MCP process working directory.",
31549
31559
  "image.missingPrompt": "Missing required parameter: prompt",
31550
31560
  "image.invalidType": "Invalid image_type: ",
@@ -31666,14 +31676,14 @@ var messages4 = {
31666
31676
  "",
31667
31677
  "成功后会下载最终 TOS 图片到工作区 assets 目录,并返回 job_id、TOS URL、本地路径以及 MCP 多模态 image 内容块(Base64)。",
31668
31678
  "asset 类型用于生成透明底游戏元素(has_transparent_background=true),background 类型用于生成背景图。",
31669
- '重要:使用 background="transparent" 时必须同时设置 image_model="asset-max";asset-pro 或 asset-lite 会直接报错。'
31679
+ 'background="transparent":文生透明图使用 image_model="asset-max";asset-pro 必须提供恰好一张本身带透明通道的参考图;asset-lite 不支持。'
31670
31680
  ].join("\n"),
31671
31681
  "image.prompt": "生图提示词,必填。",
31672
31682
  "image.type": "图片类型,默认 background。",
31673
- "image.size": "图片尺寸预设,默认 2048x2048。",
31674
- "image.references": "可选,一张参考图 URL,或最多 14 张参考图 URL 数组。",
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 张。",
31675
31685
  "image.model": "生图模型,默认 asset-lite;可选 asset-max、asset-pro。",
31676
- "image.background": "可选背景模式。transparent 仅可与 asset-max 搭配;用于 asset-pro 或 asset-lite 时生图接口会直接报错。",
31686
+ "image.background": "可选背景模式。auto 在 Pro/Lite 中使用上游默认背景;Lite 不支持 transparent;Pro 的 transparent 必须提供一张带透明通道的参考图;Max 支持全部三种模式。",
31677
31687
  "image.workspace": "可选,Agent 工作区绝对路径;默认使用 MCP 进程当前工作目录。",
31678
31688
  "image.missingPrompt": "缺少必填参数 prompt",
31679
31689
  "image.invalidType": "无效的 image_type:",
@@ -39143,7 +39153,7 @@ var StdioClientTransport = class {
39143
39153
  };
39144
39154
 
39145
39155
  // src/version.ts
39146
- var VERSION = "0.1.9-beta.23";
39156
+ var VERSION = "0.1.10-beta.1";
39147
39157
 
39148
39158
  // src/publishChannel.generated.ts
39149
39159
  var PUBLISH_NPM_NAME = "evomeme";
@@ -40085,6 +40095,31 @@ var GAME_IMAGE_SIZES = [
40085
40095
  ];
40086
40096
  var GAME_IMAGE_MODELS = ["asset-max", "asset-pro", "asset-lite"];
40087
40097
  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
+ }
40088
40123
  var IMAGE_JOB_STATUSES = [
40089
40124
  "QUEUED",
40090
40125
  "RUNNING",
@@ -40105,7 +40140,35 @@ var GAME_IMAGE_MODEL_BACKEND = {
40105
40140
  function resolveGameImageModel(model) {
40106
40141
  return GAME_IMAGE_MODEL_BACKEND[model];
40107
40142
  }
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
+ }
40108
40170
  async function generateGameImage(token, input, options = {}) {
40171
+ input = normalizeGameImageInput(input);
40109
40172
  const client = createPluginServerClient(options);
40110
40173
  const body = { prompt: input.prompt };
40111
40174
  if (input.imageType !== void 0) {
@@ -45310,17 +45373,27 @@ async function executeImageGeneration(workspaceDir, body, imageServiceDeps) {
45310
45373
  if (!prompt) throw httpError(400, t("error.task.promptRequired"));
45311
45374
  const operationId = String(body.client_operation_id || createOperationId());
45312
45375
  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"));
45314
45376
  const interactiveReferenceData = String(body.reference_image_data || "").trim();
45315
45377
  const imageModel = String(body.model || "asset-pro");
45316
- const size = String(body.size || "2048x2048");
45378
+ let size = String(body.size || "2048x2048");
45317
45379
  const layerDecomposition = body.layer_decomposition === true;
45318
- const requestedBackground = layerDecomposition || interactiveReferenceData ? void 0 : normalizeImageBackground(body.background);
45380
+ let requestedBackground = layerDecomposition || interactiveReferenceData ? void 0 : normalizeImageBackground(body.background);
45319
45381
  if (!GAME_IMAGE_MODELS.includes(imageModel)) {
45320
45382
  throw httpError(400, t("error.task.unsupportedImageModel") + imageModel);
45321
45383
  }
45322
- if (!GAME_IMAGE_SIZES.includes(size)) {
45323
- throw httpError(400, t("error.task.unsupportedImageSize") + size);
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);
45324
45397
  }
45325
45398
  if (!body.reference_image_urls && imageModel === "asset-pro" && requestedBackground === "transparent") {
45326
45399
  if (referenceIds.length !== 1 || path35.extname(resolveAssetPath(workspaceDir, referenceIds[0])).toLowerCase() !== ".png") {
@@ -45349,7 +45422,7 @@ async function executeImageGeneration(workspaceDir, body, imageServiceDeps) {
45349
45422
  const interactiveReference = interactiveReferenceData ? await uploadInteractiveReference(workspaceDir, interactiveReferenceData, imageServiceDeps) : void 0;
45350
45423
  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;
45351
45424
  const background = requestedBackground;
45352
- const operationSize = layerDecomposition ? "auto" : interactiveReference ? resolveInteractiveEditSize(interactiveReference.width, interactiveReference.height) : size;
45425
+ const operationSize = layerDecomposition ? "auto" : interactiveReference ? resolveInteractiveEditSize(interactiveReference.width, interactiveReference.height, imageModel) : size;
45353
45426
  const canvasJob = await beginTask({
45354
45427
  operationId,
45355
45428
  workspaceDir,
@@ -48276,19 +48349,39 @@ async function uploadInteractiveReference(workspaceDir, dataUrl, imageServiceDep
48276
48349
  await unlink4(localPath).catch(() => void 0);
48277
48350
  }
48278
48351
  }
48279
- function resolveInteractiveEditSize(width, height) {
48352
+ function resolveInteractiveEditSize(width, height, model = "asset-pro") {
48280
48353
  if (!Number.isSafeInteger(width) || width <= 0 || !Number.isSafeInteger(height) || height <= 0) {
48281
48354
  throw new Error(t("error.task.interactiveSizeInvalid") + `${width}x${height}`);
48282
48355
  }
48283
48356
  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
+ }
48284
48377
  if (pixels >= INTERACTIVE_EDIT_MIN_PIXELS && pixels <= INTERACTIVE_EDIT_MAX_PIXELS) {
48285
- return `${width}x${height}`;
48378
+ return normalizeGameImageSize(model, `${width}x${height}`);
48286
48379
  }
48287
48380
  const targetPixels = pixels < INTERACTIVE_EDIT_MIN_PIXELS ? INTERACTIVE_EDIT_MIN_PIXELS : INTERACTIVE_EDIT_MAX_PIXELS;
48288
48381
  const aspectRatio = width / height;
48289
48382
  const targetHeight = Math.max(1, Math.round(Math.sqrt(targetPixels / aspectRatio)));
48290
48383
  const targetWidth = pixels < INTERACTIVE_EDIT_MIN_PIXELS ? Math.ceil(targetPixels / targetHeight) : Math.max(1, Math.floor(targetPixels / targetHeight));
48291
- return `${targetWidth}x${targetHeight}`;
48384
+ return normalizeGameImageSize(model, `${targetWidth}x${targetHeight}`);
48292
48385
  }
48293
48386
  async function extractVideoAssetFrames(workspaceDir, assetId, fps, requestedOperationId = "") {
48294
48387
  if (!Number.isFinite(fps) || fps < 0.1 || fps > 60) {
@@ -50604,7 +50697,12 @@ async function handleApi(request, response, url, workspaceDir, eventHub, videoGe
50604
50697
  if (request.method === "GET" && pathname === "/api/meta") {
50605
50698
  const paths = canvasWorkspacePaths(workspaceDir);
50606
50699
  sendJson(response, 200, {
50607
- models: GAME_IMAGE_MODELS.map((model) => ({ id: model, label: model })),
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
+ })),
50608
50706
  default_model: "asset-pro",
50609
50707
  backgrounds: GAME_IMAGE_BACKGROUNDS,
50610
50708
  size_presets: GAME_IMAGE_SIZES,
@@ -53408,13 +53506,12 @@ var generateGameImageTool = {
53408
53506
  },
53409
53507
  size: {
53410
53508
  type: "string",
53411
- enum: [...GAME_IMAGE_SIZES],
53412
53509
  description: mcpT("image.size")
53413
53510
  },
53414
53511
  reference_image_url: {
53415
53512
  oneOf: [
53416
53513
  { type: "string" },
53417
- { type: "array", items: { type: "string" }, minItems: 1, maxItems: 14 }
53514
+ { type: "array", items: { type: "string" }, minItems: 1, maxItems: 16 }
53418
53515
  ],
53419
53516
  description: mcpT("image.references")
53420
53517
  },
@@ -53477,9 +53574,6 @@ function buildGenerateInput(args) {
53477
53574
  input.imageType = args.image_type;
53478
53575
  }
53479
53576
  if (args.size !== void 0) {
53480
- if (!GAME_IMAGE_SIZES.includes(args.size)) {
53481
- return new Error(mcpT("image.invalidSize") + args.size);
53482
- }
53483
53577
  input.size = args.size;
53484
53578
  }
53485
53579
  if (args.image_model !== void 0) {
@@ -53497,10 +53591,9 @@ function buildGenerateInput(args) {
53497
53591
  if (args.reference_image_url !== void 0) {
53498
53592
  const references = (Array.isArray(args.reference_image_url) ? args.reference_image_url : [args.reference_image_url]).map((value) => value.trim()).filter(Boolean);
53499
53593
  if (!references.length) return new Error(mcpT("image.emptyReferences"));
53500
- if (references.length > 14) return new Error(mcpT("image.tooManyReferences"));
53501
53594
  input.referenceImageUrl = references.length === 1 ? references[0] : references;
53502
53595
  }
53503
- return input;
53596
+ return normalizeGameImageInput(input);
53504
53597
  }
53505
53598
 
53506
53599
  // src/mcp/tools/cutoutGameImage.ts
@@ -54985,6 +55078,7 @@ function parseGenerateImageArgs(args) {
54985
55078
  size: typeof args.size === "string" ? args.size : void 0,
54986
55079
  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,
54987
55080
  image_model: typeof args.image_model === "string" ? args.image_model : void 0,
55081
+ background: typeof args.background === "string" ? args.background : void 0,
54988
55082
  workspace_dir: typeof args.workspace_dir === "string" ? args.workspace_dir : void 0
54989
55083
  };
54990
55084
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evomeme",
3
- "version": "0.1.9-beta.23",
3
+ "version": "0.1.10-beta.1",
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",