editmamei 1.2.1 → 1.3.0
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.
- package/dist/bin/editmamei-core-darwin-arm64 +0 -0
- package/dist/bin/editmamei-core-darwin-x64 +0 -0
- package/dist/bin/editmamei-core-win-x64.exe +0 -0
- package/dist/cli/repair.js +11 -3
- package/dist/core/tool-tiers.js +2 -2
- package/dist/delivery/provision.js +19 -1
- package/dist/kernel/kernel.js +2 -1
- package/dist/kernel/module-lifecycle.js +24 -4
- package/dist/modules/ce/index.js +1 -1
- package/dist/perception/grounding-locate.js +7 -5
- package/dist/skills/editmamei-skill.zip +0 -0
- package/dist/tools/document-tools.js +0 -1
- package/dist/tools/image-tools.js +2 -1
- package/dist/tools/layer-transform-tools.js +2 -1
- package/dist/tools/path-tools.js +1 -1
- package/dist/tools/selection-tools.js +1 -1
- package/dist/tools/shape-tools.js +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/cli/repair.js
CHANGED
|
@@ -26,11 +26,19 @@ export async function runRepair(opts = {}) {
|
|
|
26
26
|
out(` Installed ${m.sku} module v${m.version}.\n`);
|
|
27
27
|
for (const s of prov.skipped)
|
|
28
28
|
out(` Skipped ${s.sku} v${s.version}: ${s.reason}.\n`);
|
|
29
|
-
|
|
29
|
+
const tooNew = prov.errors.filter((e) => e.code === 'abi_too_new');
|
|
30
|
+
const failures = prov.errors.filter((e) => e.code !== 'abi_too_new');
|
|
31
|
+
for (const e of tooNew) {
|
|
32
|
+
out(` The published ${e.sku} module needs a newer Editmamei than this one — ` +
|
|
33
|
+
`update Editmamei to load it. Your installed module is unchanged.\n`);
|
|
34
|
+
}
|
|
35
|
+
for (const e of failures) {
|
|
30
36
|
err(` Error: could not provision the ${e.sku} module: ${e.message}\n`);
|
|
31
37
|
}
|
|
32
|
-
if (
|
|
38
|
+
if (failures.length > 0) {
|
|
33
39
|
throw new Error('module re-provisioning failed');
|
|
34
40
|
}
|
|
35
|
-
|
|
41
|
+
if (prov.installed.length > 0 || tooNew.length === 0) {
|
|
42
|
+
out('\nRestart your MCP client (Claude Desktop / Claude Code) to load Pro tools.\n');
|
|
43
|
+
}
|
|
36
44
|
}
|
package/dist/core/tool-tiers.js
CHANGED
|
@@ -8,7 +8,7 @@ export const TOOL_TIERS = {
|
|
|
8
8
|
ps_batch: 'pro',
|
|
9
9
|
ps_add_adjustment_layer: 'community',
|
|
10
10
|
ps_apply_adjustment: 'community',
|
|
11
|
-
ps_document: '
|
|
11
|
+
ps_document: 'community',
|
|
12
12
|
ps_create_document: 'community',
|
|
13
13
|
ps_close_document: 'community',
|
|
14
14
|
ps_open_document: 'community',
|
|
@@ -69,7 +69,7 @@ export const TOOL_TIERS = {
|
|
|
69
69
|
ps_select_subject_instance: 'pro',
|
|
70
70
|
ps_select_object: 'pro',
|
|
71
71
|
ps_select_focus_area: 'dev',
|
|
72
|
-
ps_replace_sky: '
|
|
72
|
+
ps_replace_sky: 'community',
|
|
73
73
|
ps_modify_selection: 'community',
|
|
74
74
|
ps_get_selection_preview: 'community',
|
|
75
75
|
ps_selection_channel: 'community',
|
|
@@ -2,6 +2,7 @@ import { DeliveryClient, DeliveryError } from './client.js';
|
|
|
2
2
|
import { sha256Hex } from './crypto.js';
|
|
3
3
|
import { verifyModuleSignature, verifyModuleSignatureV2, digestsRootSha256Hex, isModuleFileDigestArray, } from './signing.js';
|
|
4
4
|
import { installModule, readInstalledModule } from './store.js';
|
|
5
|
+
import { KERNEL_ABI } from '../kernel/host-api.js';
|
|
5
6
|
import { Logger } from '../utils/logger.js';
|
|
6
7
|
const logger = new Logger('Modules');
|
|
7
8
|
const SKU_RE = /^[a-z0-9-]{2,32}$/;
|
|
@@ -52,6 +53,23 @@ export async function provisionModules(key, opts = {}) {
|
|
|
52
53
|
});
|
|
53
54
|
continue;
|
|
54
55
|
}
|
|
56
|
+
const abi = entry.abi;
|
|
57
|
+
if (!Number.isInteger(abi) || abi < 1) {
|
|
58
|
+
result.errors.push({
|
|
59
|
+
sku,
|
|
60
|
+
code: 'abi_invalid',
|
|
61
|
+
message: `the manifest entry for ${sku} declares an invalid abi '${String(abi)}' (expected a whole number of at least 1) — refusing to install it`,
|
|
62
|
+
});
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (abi > KERNEL_ABI) {
|
|
66
|
+
result.errors.push({
|
|
67
|
+
sku,
|
|
68
|
+
code: 'abi_too_new',
|
|
69
|
+
message: `the published ${sku} module needs a newer Editmamei than this one (module abi ${abi}, this host runs up to abi ${KERNEL_ABI}) — update Editmamei; the installed module is left as it is`,
|
|
70
|
+
});
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
55
73
|
const installed = readInstalledModule(sku, opts);
|
|
56
74
|
if (installed && installed.version === latest && !opts.force) {
|
|
57
75
|
result.skipped.push({ sku, version: latest, reason: 'up-to-date' });
|
|
@@ -119,7 +137,7 @@ export async function provisionModules(key, opts = {}) {
|
|
|
119
137
|
installModule({
|
|
120
138
|
sku,
|
|
121
139
|
version: latest,
|
|
122
|
-
abi
|
|
140
|
+
abi,
|
|
123
141
|
sha256: digest,
|
|
124
142
|
alg: contentKey.alg,
|
|
125
143
|
content_key: contentKey.key,
|
package/dist/kernel/kernel.js
CHANGED
|
@@ -73,9 +73,10 @@ export class Kernel {
|
|
|
73
73
|
throw new Error('downloaded module export is not an EditmameiModule (expected a default export with a manifest + register())');
|
|
74
74
|
}
|
|
75
75
|
if (this.abiTooNew(mod.manifest))
|
|
76
|
-
return;
|
|
76
|
+
return 'abi-too-new';
|
|
77
77
|
const before = this.registry.count();
|
|
78
78
|
await mod.register(this.hostApiFor(mod.manifest));
|
|
79
79
|
this.logger.info(`Loaded downloaded module '${mod.manifest.id}' (${mod.manifest.name}) — ${this.registry.count() - before} tools.`);
|
|
80
|
+
return 'loaded';
|
|
80
81
|
}
|
|
81
82
|
}
|
|
@@ -7,7 +7,7 @@ import { isProEntitled } from '../license/entitlement.js';
|
|
|
7
7
|
import { loadVerifiedModule, readInstalledModule, installedPath, PRO_SKU, } from '../delivery/store.js';
|
|
8
8
|
import { provisionModules, compareVersions, VERSION_RE, } from '../delivery/provision.js';
|
|
9
9
|
import { readLicense } from '../license/store.js';
|
|
10
|
-
import { HOST_MIN_ABI } from './host-api.js';
|
|
10
|
+
import { HOST_MIN_ABI, KERNEL_ABI } from './host-api.js';
|
|
11
11
|
import { VERSION } from '../version.js';
|
|
12
12
|
export function classifyModuleOutcome(inputs) {
|
|
13
13
|
if (inputs.proModuleLoaded && inputs.skipReason === null)
|
|
@@ -79,9 +79,21 @@ export class ModuleLifecycle {
|
|
|
79
79
|
this._moduleSkipReason = 'incompatible';
|
|
80
80
|
return;
|
|
81
81
|
}
|
|
82
|
+
if (this._proModule.abi !== null && this._proModule.abi > KERNEL_ABI) {
|
|
83
|
+
this.deps.logger.warn(`Pro module (abi ${this._proModule.abi}) needs a newer host than this build ` +
|
|
84
|
+
`(kernel abi ${KERNEL_ABI}) — booting Community; update Editmamei to load it.`);
|
|
85
|
+
this._moduleSkipReason = 'incompatible';
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
82
88
|
const snapshot = this.deps.toolRegistry.snapshot();
|
|
83
89
|
try {
|
|
84
|
-
await this.kernel.loadDownloaded(this._proModule.importer);
|
|
90
|
+
const outcome = await this.kernel.loadDownloaded(this._proModule.importer);
|
|
91
|
+
if (outcome === 'abi-too-new') {
|
|
92
|
+
this.deps.logger.warn(`The installed Pro module needs a newer host than this build (kernel abi ` +
|
|
93
|
+
`${KERNEL_ABI}) — booting Community; update Editmamei to load it.`);
|
|
94
|
+
this._moduleSkipReason = 'incompatible';
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
85
97
|
if (this._proModule.version !== null &&
|
|
86
98
|
VERSION_RE.test(this._proModule.version) &&
|
|
87
99
|
compareVersions(this._proModule.version, VERSION) > 0) {
|
|
@@ -159,11 +171,14 @@ export class ModuleLifecycle {
|
|
|
159
171
|
this.deps.logger.warn('Module delivery is not configured — staying Community.');
|
|
160
172
|
return;
|
|
161
173
|
}
|
|
174
|
+
const abiTooNew = prov.errors.some((e) => e.code === 'abi_too_new');
|
|
162
175
|
for (const e of prov.errors) {
|
|
176
|
+
if (e.code === 'abi_too_new')
|
|
177
|
+
continue;
|
|
163
178
|
this.deps.logger.warn(`Could not re-provision the ${e.sku} module (staying Community): ${e.message}`);
|
|
164
179
|
}
|
|
165
|
-
if (prov.errors.length === 0) {
|
|
166
|
-
if (reason === 'incompatible') {
|
|
180
|
+
if (prov.errors.length === 0 || abiTooNew) {
|
|
181
|
+
if (reason === 'incompatible' || abiTooNew) {
|
|
167
182
|
this.deps.logger.warn('The published Pro module does not yet support this host version — staying ' +
|
|
168
183
|
'Community. Update Editmamei when a compatible release ships; ' +
|
|
169
184
|
'`editmamei report` files a diagnostic.');
|
|
@@ -201,6 +216,11 @@ export class ModuleLifecycle {
|
|
|
201
216
|
this.deps.logger.info(`Pro module updated to v${m.version} — restart to load.`);
|
|
202
217
|
}
|
|
203
218
|
for (const e of prov.errors) {
|
|
219
|
+
if (e.code === 'abi_too_new') {
|
|
220
|
+
this.deps.logger.info(`A newer Pro module is published but needs a newer Editmamei than this ` +
|
|
221
|
+
`one — staying on the installed version, which works. Update Editmamei to get it.`);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
204
224
|
this.deps.logger.warn(`Pro-module freshness check could not provision the ${e.sku} module ` +
|
|
205
225
|
`(staying on the installed version): ${e.message}`);
|
|
206
226
|
}
|
package/dist/modules/ce/index.js
CHANGED
|
@@ -30,7 +30,7 @@ import { createVectorMaskTools } from '../../tools/vector-mask-tools.js';
|
|
|
30
30
|
import { createChannelComposeTools } from '../../tools/channel-compose-tools.js';
|
|
31
31
|
import { createShapeTools } from '../../tools/shape-tools.js';
|
|
32
32
|
import { createSkyTools } from '../../tools/sky-tools.js';
|
|
33
|
-
const ceFactories = [
|
|
33
|
+
export const ceFactories = [
|
|
34
34
|
createDocumentTools,
|
|
35
35
|
createLayerTools,
|
|
36
36
|
createGroupTools,
|
|
@@ -254,17 +254,19 @@ export const PLACEMENT_SCHEMA = {
|
|
|
254
254
|
type: 'object',
|
|
255
255
|
description: 'ANCHOR-RELATIONAL placement (preferred over guessing pixels): name anchors + a relation and the ' +
|
|
256
256
|
'spatial-grounding resolver computes the geometry, verified by an objective gate; the action runs ONLY if the ' +
|
|
257
|
-
'gate PASSES. For a HARD or ambiguous placement, first concur
|
|
258
|
-
'
|
|
259
|
-
'
|
|
257
|
+
'gate PASSES. For a HARD or ambiguous placement, first concur with the placement-resolver tool — when this ' +
|
|
258
|
+
'build has one, it appears in tools/list — by calling it with review_crop: true for a read-only zoomed crop ' +
|
|
259
|
+
'with a marker at the resolved spot, then pass the SAME anchors + relation here. The full anchors + relation ' +
|
|
260
|
+
'vocabulary is documented on that tool.',
|
|
260
261
|
properties: {
|
|
261
262
|
anchors: {
|
|
262
263
|
type: 'array',
|
|
263
|
-
description: 'Named anchors, same vocabulary as
|
|
264
|
+
description: 'Named anchors, same vocabulary as the placement-resolver tool, when this build has one ' +
|
|
265
|
+
'(face/object/grid/extremum/corner/edge/landmark).',
|
|
264
266
|
},
|
|
265
267
|
relation: {
|
|
266
268
|
type: 'object',
|
|
267
|
-
description: 'The relation, same vocabulary as
|
|
269
|
+
description: 'The relation, same vocabulary as the placement-resolver tool, when this build has one.',
|
|
268
270
|
},
|
|
269
271
|
max_dimension: {
|
|
270
272
|
type: 'number',
|
|
Binary file
|
|
@@ -29,7 +29,8 @@ const cropDocumentSchema = {
|
|
|
29
29
|
...PLACEMENT_SCHEMA,
|
|
30
30
|
description: 'ANCHOR-RELATIONAL crop (preferred over guessing pixels): a REGION relation (inside/gap) → the crop is the ' +
|
|
31
31
|
'resolved region bounding box, verified by the gate. Crops ONLY if the gate PASSES. When set, ' +
|
|
32
|
-
'left/top/right/bottom are ignored. See
|
|
32
|
+
'left/top/right/bottom are ignored. See the placement-resolver tool, when this build has one, for the ' +
|
|
33
|
+
'anchors + relation vocabulary.',
|
|
33
34
|
},
|
|
34
35
|
left: {
|
|
35
36
|
type: 'integer',
|
|
@@ -82,7 +82,8 @@ const moveLayerSchema = {
|
|
|
82
82
|
description: 'ANCHOR-RELATIONAL move (preferred over guessing a pixel): a POINT relation (centroid/midpoint/offset) → ' +
|
|
83
83
|
'the layer\'s CENTER is moved to the resolved, gate-verified point (e.g. "center this layer on the detected ' +
|
|
84
84
|
'subject" / "…in the gap between the two people"). Moves ONLY if the gate PASSES. When set, delta_*/' +
|
|
85
|
-
'absolute_*/center_on_* are ignored. See
|
|
85
|
+
'absolute_*/center_on_* are ignored. See the placement-resolver tool, when this build has one, for the ' +
|
|
86
|
+
'anchors + relation vocabulary.',
|
|
86
87
|
},
|
|
87
88
|
},
|
|
88
89
|
};
|
package/dist/tools/path-tools.js
CHANGED
|
@@ -73,7 +73,7 @@ const pathInputSchema = {
|
|
|
73
73
|
tool: {
|
|
74
74
|
type: 'string',
|
|
75
75
|
enum: SUPPORTED_BRUSH_TOOLS,
|
|
76
|
-
description: "stroke only: which brush-family tool paints the path
|
|
76
|
+
description: "stroke only: which brush-family tool paints the path (see this field's own enum for the full supported set). Default 'brush'.",
|
|
77
77
|
default: 'brush',
|
|
78
78
|
},
|
|
79
79
|
color: {
|
|
@@ -466,7 +466,7 @@ const SELECT_INPUT_SCHEMA = {
|
|
|
466
466
|
...selectPolygonSchema.properties,
|
|
467
467
|
placement: {
|
|
468
468
|
...PLACEMENT_SCHEMA,
|
|
469
|
-
description: 'Grounded coordinates (rectangle/ellipse/magic_wand): NAME anchors + a relation instead of guessing pixels. rectangle/ellipse ← a REGION relation (inside/gap) → the selection bounding box; magic_wand ← a POINT relation (centroid/extremum/grid) → the click. Verified by the objective gate; wins over the raw edges/x-y. See
|
|
469
|
+
description: 'Grounded coordinates (rectangle/ellipse/magic_wand): NAME anchors + a relation instead of guessing pixels. rectangle/ellipse ← a REGION relation (inside/gap) → the selection bounding box; magic_wand ← a POINT relation (centroid/extremum/grid) → the click. Verified by the objective gate; wins over the raw edges/x-y. See the placement-resolver tool, when this build has one, for the vocabulary.',
|
|
470
470
|
},
|
|
471
471
|
},
|
|
472
472
|
required: ['mode'],
|
|
@@ -31,7 +31,7 @@ const shapeInputSchema = {
|
|
|
31
31
|
'edge or a Pro face-mesh landmark curve) → a straight line between the resolved curve endpoints. The shape ' +
|
|
32
32
|
'is created ONLY if the gate PASSES (otherwise an error and no layer). When set, left/top/right/bottom and ' +
|
|
33
33
|
'start_x/start_y/end_x/end_y are ignored, but styling (fill_color/stroke/weight/corner_radius) still ' +
|
|
34
|
-
'applies. See
|
|
34
|
+
'applies. See the placement-resolver tool, when this build has one, for the anchors + relation vocabulary.',
|
|
35
35
|
},
|
|
36
36
|
left: {
|
|
37
37
|
type: 'number',
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '1.
|
|
1
|
+
export const VERSION = '1.3.0';
|
package/package.json
CHANGED