editmamei 0.20.0 → 0.22.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.
- package/NOTICES.md +17 -1
- package/README.md +8 -7
- package/dist/api/extendscript/_helpers.js +1 -1
- 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/config.js +3 -3
- package/dist/cli/help.js +2 -0
- package/dist/cli/install.js +2 -2
- package/dist/cli/repair.js +36 -0
- package/dist/cli/router.js +4 -0
- package/dist/core/server.js +81 -10
- package/dist/core/settings.js +2 -2
- package/dist/core/tool-groups.js +91 -82
- package/dist/core/tool-registry.js +6 -0
- package/dist/core/tool-tiers.js +91 -82
- package/dist/delivery/provision.js +2 -2
- package/dist/delivery/store.js +63 -4
- package/dist/detection/landmark-detection-client.js +8 -0
- package/dist/detection/mesh-eye-correction.js +126 -0
- package/dist/detection/sam-segmenter.js +83 -0
- package/dist/index.js +2 -0
- package/dist/kernel/host-api.js +1 -0
- package/dist/license/entitlement.js +52 -0
- package/dist/modules/ce/index.js +4 -4
- package/dist/perception/grounding-anchors.js +37 -0
- package/dist/perception/grounding-corners.js +93 -0
- package/dist/perception/grounding-edge-trace.js +90 -0
- package/dist/perception/grounding-extrema.js +41 -0
- package/dist/perception/grounding-gate.js +154 -0
- package/dist/perception/grounding-geometry.js +132 -0
- package/dist/perception/grounding-grid.js +34 -0
- package/dist/perception/grounding-landmarks.js +40 -0
- package/dist/perception/grounding-locate.js +341 -0
- package/dist/perception/grounding-resolver.js +202 -0
- package/dist/perception/grounding-review-crop.js +85 -0
- package/dist/perception/grounding-warp.js +182 -0
- package/dist/perception/sky-mask-transfer.js +50 -18
- package/dist/skills/editmamei-skill.zip +0 -0
- package/dist/tools/adjustment-tools.js +3 -3
- package/dist/tools/brush-tools.js +111 -23
- package/dist/tools/channel-compose-tools.js +241 -0
- package/dist/tools/detection-tools.js +1 -1
- package/dist/tools/diagnostics-tools.js +1 -1
- package/dist/tools/document-tools.js +6 -6
- package/dist/tools/filter-tools.js +476 -19
- package/dist/tools/group-tools.js +10 -10
- package/dist/tools/guide-tools.js +4 -4
- package/dist/tools/history-tools.js +4 -4
- package/dist/tools/image-placement-tools.js +1 -1
- package/dist/tools/image-tools.js +62 -19
- package/dist/tools/inspect-tools.js +2 -2
- package/dist/tools/layer-ordering-tools.js +1 -1
- package/dist/tools/layer-properties-tools.js +42 -23
- package/dist/tools/layer-tools.js +10 -10
- package/dist/tools/layer-transform-tools.js +80 -41
- package/dist/tools/overview-tools.js +42 -42
- package/dist/tools/path-tools.js +53 -10
- package/dist/tools/portrait-tools.js +3 -3
- package/dist/tools/preview-tools.js +7 -82
- package/dist/tools/retouch-tools.js +93 -25
- package/dist/tools/scene-tools.js +13 -13
- package/dist/tools/selection-tools.js +319 -40
- package/dist/tools/shape-tools.js +216 -0
- package/dist/tools/text-tools.js +1 -1
- package/dist/tools/transform-canvas-tools.js +2 -2
- package/dist/tools/vector-mask-tools.js +23 -8
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/preview/coordinate-grid.js +0 -250
- package/dist/tools/object-tools.js +0 -193
- package/dist/tools/text-on-object-tools.js +0 -225
package/NOTICES.md
CHANGED
|
@@ -83,10 +83,26 @@ above.
|
|
|
83
83
|
diligence). Any upstream `NOTICE`/attribution terms (Apache-2.0 §4(d)) are
|
|
84
84
|
preserved by reference to those sources.
|
|
85
85
|
- Runs on-device via the same `onnxruntime-web` backend; the image never leaves the
|
|
86
|
-
machine. Used by the Pro `
|
|
86
|
+
machine. Used by the Pro `ps_detect_landmarks` tool to locate the 468-point
|
|
87
87
|
face mesh (eyes, brows, lips, nose, jaw). Ships in the **Pro module**
|
|
88
88
|
(`models/pro/`), not the CE tarball.
|
|
89
89
|
|
|
90
|
+
### MobileSAM (`models/pro/mobile_sam_{encoder,decoder}.onnx`) — promptable segmentation (Pro)
|
|
91
|
+
|
|
92
|
+
- **Upstream:** MobileSAM ("Faster Segment Anything: Towards Lightweight SAM for
|
|
93
|
+
Mobile Applications", Zhang et al.; `ChaoningZhang/MobileSAM`) — a distilled
|
|
94
|
+
TinyViT image encoder paired with the Segment Anything prompt-mask decoder,
|
|
95
|
+
exported to ONNX (encoder + decoder). Redistributed here as an **FP16** build
|
|
96
|
+
converted from the FP32 ONNX export (halves the download; INT8 dynamic
|
|
97
|
+
quantization was evaluated and rejected — it collapsed the encoder to
|
|
98
|
+
whole-frame masks).
|
|
99
|
+
- **License:** Apache-2.0. Any upstream `NOTICE`/attribution terms (Apache-2.0
|
|
100
|
+
§4(d)) are preserved by reference to that source.
|
|
101
|
+
- Runs on-device via the same `onnxruntime-web` backend; the image never leaves the
|
|
102
|
+
machine. Used by the Pro `ps_select_object` tool to turn a box/point prompt into a
|
|
103
|
+
pixel-accurate organic selection. Ships in the **Pro module** (`models/pro/`), not
|
|
104
|
+
the CE tarball.
|
|
105
|
+
|
|
90
106
|
---
|
|
91
107
|
|
|
92
108
|
## Trademarks
|
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Prefer not to use a terminal? Claude Desktop users can install the one-click `.m
|
|
|
52
52
|
|
|
53
53
|
## A session, end to end
|
|
54
54
|
|
|
55
|
-
The discovery chain is `
|
|
55
|
+
The discovery chain is `ps_ping` (liveness), then `ps_overview` (the working method and capability map), then `tools/list` (the full schema-typed inventory). After that you just talk to your assistant:
|
|
56
56
|
|
|
57
57
|
> _"Open my vacation photo."_
|
|
58
58
|
> _"Make the sky more dramatic but keep the foreground natural."_
|
|
@@ -67,7 +67,7 @@ Your assistant composes those into tool calls, checks the result with previews a
|
|
|
67
67
|
These are the choices that shape the surface, and the reason an AI assistant can drive it reliably rather than hopefully.
|
|
68
68
|
|
|
69
69
|
- **Structured results, not prose.** Every tool declares an `outputSchema` and returns a typed JSON payload. Any tool that changes what is active reports the current document and layer back, so the model keeps an accurate picture of Photoshop's state between calls instead of re-deriving it.
|
|
70
|
-
- **Guidance lives in the surface.** `
|
|
70
|
+
- **Guidance lives in the surface.** `ps_overview` returns the working method (assess, plan, enact, check, iterate) and `ps_list_capabilities` returns a live map of what exists. The model orients itself from the server rather than from guesswork or a stale prompt.
|
|
71
71
|
- **Measure, don't eyeball.** A dedicated set of verification tools (histogram, region compare, layer-bounds diff, selection preview) lets the model check its own work numerically instead of trusting a thumbnail.
|
|
72
72
|
- **On-device perception.** Local computer vision (ONNX) detects faces, objects, and scene regions and returns real document coordinates. The image stays on your machine for this step and is never sent to a cloud vision model.
|
|
73
73
|
- **Non-destructive by default.** Adjustments are adjustment layers, and destructive pixel operations run on an auto-created duplicate. An edit is reversible by construction.
|
|
@@ -89,10 +89,11 @@ These are the choices that shape the surface, and the reason an AI assistant can
|
|
|
89
89
|
| **Filters** | Community | `apply_filter` |
|
|
90
90
|
| **Retouch** | Community | `retouch` |
|
|
91
91
|
| **Layers** | Community | `create_layer` · `delete_layer` · `fill_layer` · `add_fill_layer` · `select_layer` · `move_layer_to_position` · `duplicate_layer` · `layer_via_copy` · `convert_to_smart_object` · `rasterize_layer` · `set_layer` · `merge` · `bake_layer` · `add_layer_style` · `transform_layer` · `create_group` · `move_layer_to_group` · `set_group_blend_mode` · `ungroup` · `delete_group` |
|
|
92
|
-
| **Masks & paths** | Community | `layer_mask` · `create_clipping_mask` · `path` · `vector_mask` |
|
|
92
|
+
| **Masks & paths** | Community | `layer_mask` · `create_clipping_mask` · `path` · `vector_mask` · `apply_image` · `calculations` |
|
|
93
93
|
| **Type** | Community | `create_text_layer` · `set_text` |
|
|
94
94
|
| **Perception** | Community | `detect` · `scene` · `select_by_reference` |
|
|
95
|
-
| **AI selection** |
|
|
95
|
+
| **AI selection** | Community | `select_subject` · `select_sky` |
|
|
96
|
+
| **AI selection** | Pro | `select_subject_instance` |
|
|
96
97
|
| **Layers (warp)** | Pro | `warp_layer` · `warp_layer_mesh` |
|
|
97
98
|
| **Face mesh** | Pro | `detect_landmarks` · `select_face_feature` |
|
|
98
99
|
| **Templates** | Pro | `template_create_evidence` · `template_save` · `template_list` · `template_apply` · `template_verify` · `template_recall` · `template_delete` |
|
|
@@ -100,8 +101,8 @@ These are the choices that shape the surface, and the reason an AI assistant can
|
|
|
100
101
|
|
|
101
102
|
## Editions
|
|
102
103
|
|
|
103
|
-
- **Community** is free and covers the everyday editing surface: documents, layers, selections, non-destructive adjustments, filters, masks, type, retouching, on-device perception, and the inspect/verify primitives.
|
|
104
|
-
- **Pro** adds
|
|
104
|
+
- **Community** is free and covers the everyday editing surface: documents, layers, selections (including AI Select Subject and Select Sky), non-destructive adjustments, filters, masks, type, retouching, on-device perception, and the inspect/verify primitives.
|
|
105
|
+
- **Pro** adds Camera Raw develop, the grounded precision tools (warp, named-object masks, precision placement), subject-instance targeting, face-mesh perception, the reproducible-template system, and Photoshop Actions plus the scripting escape hatch.
|
|
105
106
|
|
|
106
107
|
The split is detailed in [pro-features.md](https://github.com/editmamei/editmamei-wiki/blob/main/docs/pro-features.md). Pricing is at [editmamei.com](https://editmamei.com).
|
|
107
108
|
|
|
@@ -112,7 +113,7 @@ Settings live in `~/.editmamei/settings.json`, managed by the `editmamei config`
|
|
|
112
113
|
```bash
|
|
113
114
|
editmamei config list
|
|
114
115
|
editmamei config set telemetry.usage false # turn off anonymous usage telemetry
|
|
115
|
-
editmamei config set
|
|
116
|
+
editmamei config set ps_path "/path/to/Photoshop"
|
|
116
117
|
```
|
|
117
118
|
|
|
118
119
|
`PHOTOSHOP_PATH` (env var) overrides Photoshop auto-detection for a single run.
|
|
@@ -177,7 +177,7 @@ function getSelectionInfo() {
|
|
|
177
177
|
// Skipping this restoration is what caused the 2026-06-07 hotfix:
|
|
178
178
|
// every selection tool that inlines getSelectionInfo as its return
|
|
179
179
|
// value left the document on a non-composite channel, breaking the
|
|
180
|
-
// very next
|
|
180
|
+
// very next ps_layer_mask call.
|
|
181
181
|
restoreCompositeChannel(doc);
|
|
182
182
|
}
|
|
183
183
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/cli/config.js
CHANGED
package/dist/cli/help.js
CHANGED
|
@@ -9,6 +9,8 @@ Usage:
|
|
|
9
9
|
editmamei config Get/set settings (telemetry, privacy) in ~/.editmamei/settings.json
|
|
10
10
|
editmamei activate <key> Activate a Pro license on this device
|
|
11
11
|
editmamei deactivate Free this device's seat (before moving Pro to another machine)
|
|
12
|
+
editmamei repair Re-download the Pro module if it wedged after a host update
|
|
13
|
+
(fixes it without deleting ~/.editmamei — keeps templates + license)
|
|
12
14
|
editmamei license Show the current license + whether Pro is unlocked
|
|
13
15
|
editmamei report Write an anonymized diagnostic bundle to Downloads for a bug report
|
|
14
16
|
editmamei help, --help Print this help
|
package/dist/cli/install.js
CHANGED
|
@@ -65,10 +65,10 @@ export async function runInstall(opts = {}) {
|
|
|
65
65
|
out(` - Click "Upload skill"\n`);
|
|
66
66
|
out(` - Choose the file at ${skillResult.destPath}\n`);
|
|
67
67
|
out(` The skill auto-loads in any photo-editing conversation. It's a one-time upload.\n`);
|
|
68
|
-
out(` 3. Then ask the AI: "Is Photoshop connected?" — it will call
|
|
68
|
+
out(` 3. Then ask the AI: "Is Photoshop connected?" — it will call ps_ping and return your Photoshop version.\n`);
|
|
69
69
|
}
|
|
70
70
|
else {
|
|
71
|
-
out(` 2. Then ask the AI: "Is Photoshop connected?" — it will call
|
|
71
|
+
out(` 2. Then ask the AI: "Is Photoshop connected?" — it will call ps_ping and return your Photoshop version.\n`);
|
|
72
72
|
}
|
|
73
73
|
if (failed > 0) {
|
|
74
74
|
out(`\n ${failed} client(s) failed — see lines above. Other clients were registered.\n`);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { readLicense } from '../license/store.js';
|
|
2
|
+
import { provisionModules } from '../delivery/provision.js';
|
|
3
|
+
export async function runRepair(opts = {}) {
|
|
4
|
+
const out = opts.stdout ?? ((s) => process.stdout.write(s));
|
|
5
|
+
const err = opts.stderr ?? ((s) => process.stderr.write(s));
|
|
6
|
+
const license = readLicense({ dir: opts.dir });
|
|
7
|
+
if (!license) {
|
|
8
|
+
err('No Pro license found on this device. Run `editmamei activate <license-key>` first.\n');
|
|
9
|
+
throw new Error('no license');
|
|
10
|
+
}
|
|
11
|
+
out('Repairing the Pro module (re-provisioning from the delivery service)…\n');
|
|
12
|
+
const prov = await provisionModules(license.key, {
|
|
13
|
+
force: true,
|
|
14
|
+
dir: opts.dir,
|
|
15
|
+
now: opts.now,
|
|
16
|
+
config: opts.delivery?.config,
|
|
17
|
+
fetchImpl: opts.delivery?.fetchImpl,
|
|
18
|
+
signingKeys: opts.delivery?.signingKeys,
|
|
19
|
+
sleep: opts.delivery?.sleep,
|
|
20
|
+
});
|
|
21
|
+
if (prov.notConfigured) {
|
|
22
|
+
out(' Module delivery is not configured in this build — nothing to repair.\n');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
for (const m of prov.installed)
|
|
26
|
+
out(` Installed ${m.sku} module v${m.version}.\n`);
|
|
27
|
+
for (const s of prov.skipped)
|
|
28
|
+
out(` Skipped ${s.sku} v${s.version}: ${s.reason}.\n`);
|
|
29
|
+
for (const e of prov.errors) {
|
|
30
|
+
err(` Error: could not provision the ${e.sku} module: ${e.message}\n`);
|
|
31
|
+
}
|
|
32
|
+
if (prov.errors.length > 0) {
|
|
33
|
+
throw new Error('module re-provisioning failed');
|
|
34
|
+
}
|
|
35
|
+
out('\nRestart your MCP client (Claude Desktop / Claude Code) to load Pro tools.\n');
|
|
36
|
+
}
|
package/dist/cli/router.js
CHANGED
|
@@ -4,6 +4,7 @@ import { runStatus } from './status.js';
|
|
|
4
4
|
import { runConfig } from './config.js';
|
|
5
5
|
import { runActivate } from './activate.js';
|
|
6
6
|
import { runDeactivate } from './deactivate.js';
|
|
7
|
+
import { runRepair } from './repair.js';
|
|
7
8
|
import { runLicenseStatus } from './license.js';
|
|
8
9
|
import { runReport } from './report.js';
|
|
9
10
|
import { printHelp } from './help.js';
|
|
@@ -39,6 +40,9 @@ export async function routeCli(argv, opts = {}) {
|
|
|
39
40
|
case 'deactivate':
|
|
40
41
|
await runDeactivate({ stderr: err });
|
|
41
42
|
return { handled: true, exitCode: 0 };
|
|
43
|
+
case 'repair':
|
|
44
|
+
await runRepair({ stderr: err });
|
|
45
|
+
return { handled: true, exitCode: 0 };
|
|
42
46
|
case 'license':
|
|
43
47
|
await runLicenseStatus();
|
|
44
48
|
return { handled: true, exitCode: 0 };
|
package/dist/core/server.js
CHANGED
|
@@ -16,10 +16,14 @@ import { join, dirname } from 'node:path';
|
|
|
16
16
|
import { pathToFileURL } from 'node:url';
|
|
17
17
|
import { GoSnippetClient, resolveProBinaryPath, coreBinaryName } from '../api/snippet-client.js';
|
|
18
18
|
import { isProEntitled } from '../license/entitlement.js';
|
|
19
|
-
import { loadVerifiedModule, PRO_SKU } from '../delivery/store.js';
|
|
19
|
+
import { loadVerifiedModule, readInstalledModule, installedPath, PRO_SKU, } from '../delivery/store.js';
|
|
20
|
+
import { provisionModules } from '../delivery/provision.js';
|
|
21
|
+
import { readLicense } from '../license/store.js';
|
|
22
|
+
import { existsSync } from 'node:fs';
|
|
20
23
|
import { runScript } from '../utils/run-script.js';
|
|
21
24
|
import { listTemplates } from '../utils/template-storage.js';
|
|
22
25
|
import { Kernel } from '../kernel/kernel.js';
|
|
26
|
+
import { HOST_MIN_ABI } from '../kernel/host-api.js';
|
|
23
27
|
import { ceModule } from '../modules/ce/index.js';
|
|
24
28
|
let logScriptOnErrorWarned = false;
|
|
25
29
|
function warnLogScriptOnErrorOnce(logger) {
|
|
@@ -49,6 +53,7 @@ export class EditmameiServer {
|
|
|
49
53
|
telemetry;
|
|
50
54
|
kernel;
|
|
51
55
|
proModule = null;
|
|
56
|
+
moduleSkipReason = null;
|
|
52
57
|
psVersion = null;
|
|
53
58
|
updateInfo = null;
|
|
54
59
|
snippetClient = new GoSnippetClient();
|
|
@@ -110,10 +115,10 @@ export class EditmameiServer {
|
|
|
110
115
|
this.setupHandlers();
|
|
111
116
|
}
|
|
112
117
|
registerTools() {
|
|
113
|
-
this.toolRegistry.register('
|
|
118
|
+
this.toolRegistry.register('ps_ping', {
|
|
114
119
|
tool: {
|
|
115
|
-
name: '
|
|
116
|
-
description: 'Test connection to Photoshop and report session-start discovery signals. Read-only and idempotent. Call this once at the start of a session to confirm liveness before invoking any other tool. **If the user has given you an open-ended editing task, ALSO call `
|
|
120
|
+
name: 'ps_ping',
|
|
121
|
+
description: 'Test connection to Photoshop and report session-start discovery signals. Read-only and idempotent. Call this once at the start of a session to confirm liveness before invoking any other tool. **If the user has given you an open-ended editing task, ALSO call `ps_overview` after this** — it returns the workflow contract + capabilities map + verification primitives so you can plan well. Returns `version` (folds the deleted photoshop_get_version), `custom_action_sets` (count of Action Sets loaded in the Photoshop Actions palette — non-zero means recorded workflows exist; if action tools are available in this build they will appear in `tools/list`), `user_templates` (count of saved Editmamei templates), and `open_documents` (names of documents already open in Photoshop, so the LLM does not have to ask which doc to edit).',
|
|
117
122
|
inputSchema: {
|
|
118
123
|
type: 'object',
|
|
119
124
|
properties: {},
|
|
@@ -151,10 +156,10 @@ export class EditmameiServer {
|
|
|
151
156
|
},
|
|
152
157
|
handler: async () => await this.pingPhotoshop(),
|
|
153
158
|
});
|
|
154
|
-
this.toolRegistry.register('
|
|
159
|
+
this.toolRegistry.register('ps_list_capabilities', {
|
|
155
160
|
tool: {
|
|
156
|
-
name: '
|
|
157
|
-
description: 'Live map of every tool this MCP exposes, grouped by capability — each group is a one-line purpose plus the tool names in it. Read-only and cheap. Reach for it to re-orient mid-session (what exists, what to reach for) when the overview brief has scrolled out of context, or to learn which tool names to look up.
|
|
161
|
+
name: 'ps_list_capabilities',
|
|
162
|
+
description: 'Live map of every tool this MCP exposes, grouped by capability — each group is a one-line purpose plus the tool names in it. Read-only and cheap. Reach for it to re-orient mid-session (what exists, what to reach for) when the overview brief has scrolled out of context, or to learn which tool names to look up. ps_overview tells you HOW to combine tools; this tells you WHAT exists, currently; tools/list has the full schema for any one you pick.',
|
|
158
163
|
inputSchema: { type: 'object', properties: {} },
|
|
159
164
|
outputSchema: {
|
|
160
165
|
type: 'object',
|
|
@@ -202,16 +207,22 @@ export class EditmameiServer {
|
|
|
202
207
|
if (isProEntitled()) {
|
|
203
208
|
const verified = loadVerifiedModule(PRO_SKU);
|
|
204
209
|
if (verified) {
|
|
210
|
+
const abi = readInstalledModule(PRO_SKU)?.abi ?? null;
|
|
205
211
|
return {
|
|
206
212
|
importer: () => import(pathToFileURL(verified.handlersPath).href),
|
|
207
213
|
binDir: verified.binDir,
|
|
214
|
+
abi,
|
|
208
215
|
};
|
|
209
216
|
}
|
|
217
|
+
if (EDITION !== 'dev' && existsSync(installedPath(PRO_SKU))) {
|
|
218
|
+
this.moduleSkipReason = 'corrupt';
|
|
219
|
+
}
|
|
210
220
|
}
|
|
211
221
|
if (EDITION === 'dev') {
|
|
212
222
|
return {
|
|
213
223
|
importer: () => import('../modules/pro/index.js'),
|
|
214
224
|
binDir: dirname(resolveProBinaryPath()),
|
|
225
|
+
abi: null,
|
|
215
226
|
};
|
|
216
227
|
}
|
|
217
228
|
return null;
|
|
@@ -219,14 +230,73 @@ export class EditmameiServer {
|
|
|
219
230
|
async loadModules() {
|
|
220
231
|
if (!this.proModule)
|
|
221
232
|
return;
|
|
233
|
+
if (this.proModule.abi !== null && this.proModule.abi < HOST_MIN_ABI) {
|
|
234
|
+
this.logger.warn(`Pro module (abi ${this.proModule.abi}) is older than this host requires ` +
|
|
235
|
+
`(min abi ${HOST_MIN_ABI}) — booting Community; will re-provision in the background.`);
|
|
236
|
+
this.moduleSkipReason = 'incompatible';
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const snapshot = this.toolRegistry.snapshot();
|
|
222
240
|
try {
|
|
223
241
|
await this.kernel.loadDownloaded(this.proModule.importer);
|
|
242
|
+
this.assertToolsClassified();
|
|
224
243
|
}
|
|
225
244
|
catch (err) {
|
|
226
|
-
this.
|
|
245
|
+
const changed = this.toolRegistry.count() - snapshot.size;
|
|
246
|
+
this.toolRegistry.restore(snapshot);
|
|
247
|
+
this.logger.warn(`Pro module could not be loaded on this host — booting Community and rolling back ` +
|
|
248
|
+
`${changed} module tool change(s); will re-provision in the background: ` +
|
|
249
|
+
`${err instanceof Error ? err.message : String(err)}`);
|
|
250
|
+
this.moduleSkipReason = 'incompatible';
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
async reprovisionIfModuleSkipped(delivery = {}) {
|
|
254
|
+
const reason = this.moduleSkipReason;
|
|
255
|
+
if (reason === null)
|
|
256
|
+
return;
|
|
257
|
+
const license = readLicense();
|
|
258
|
+
if (!license) {
|
|
259
|
+
this.logger.warn('A Pro module was skipped but no cached license was found — staying Community. ' +
|
|
260
|
+
'Run `editmamei activate <key>` to restore Pro.');
|
|
227
261
|
return;
|
|
228
262
|
}
|
|
229
|
-
|
|
263
|
+
try {
|
|
264
|
+
const prov = await provisionModules(license.key, {
|
|
265
|
+
force: reason === 'corrupt',
|
|
266
|
+
config: delivery.config,
|
|
267
|
+
fetchImpl: delivery.fetchImpl,
|
|
268
|
+
signingKeys: delivery.signingKeys,
|
|
269
|
+
sleep: delivery.sleep,
|
|
270
|
+
});
|
|
271
|
+
if (prov.installed.length > 0) {
|
|
272
|
+
for (const m of prov.installed) {
|
|
273
|
+
this.logger.info(`Pro module updated to v${m.version}, restart to load.`);
|
|
274
|
+
}
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (prov.notConfigured) {
|
|
278
|
+
this.logger.warn('Module delivery is not configured — staying Community.');
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
for (const e of prov.errors) {
|
|
282
|
+
this.logger.warn(`Could not re-provision the ${e.sku} module (staying Community): ${e.message}`);
|
|
283
|
+
}
|
|
284
|
+
if (prov.errors.length === 0) {
|
|
285
|
+
if (reason === 'incompatible') {
|
|
286
|
+
this.logger.warn('The published Pro module does not yet support this host version — staying ' +
|
|
287
|
+
'Community. Update Editmamei when a compatible release ships; ' +
|
|
288
|
+
'`editmamei report` files a diagnostic.');
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
this.logger.warn('Re-provision installed nothing for the corrupt Pro module — staying ' +
|
|
292
|
+
'Community. Try `editmamei repair`; `editmamei report` if it persists.');
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
catch (err) {
|
|
297
|
+
this.logger.warn(`Background Pro-module re-provision failed (staying Community): ` +
|
|
298
|
+
`${err instanceof Error ? err.message : String(err)}`);
|
|
299
|
+
}
|
|
230
300
|
}
|
|
231
301
|
assertToolsClassified() {
|
|
232
302
|
for (const tool of this.toolRegistry.list()) {
|
|
@@ -252,7 +322,7 @@ export class EditmameiServer {
|
|
|
252
322
|
}))
|
|
253
323
|
.filter((g) => g.tools.length > 0);
|
|
254
324
|
const text = `Editmamei exposes ${registered.length} tools across ${groups.length} capability groups. ` +
|
|
255
|
-
`This is the live map of WHAT exists;
|
|
325
|
+
`This is the live map of WHAT exists; ps_overview is HOW to combine them, and ` +
|
|
256
326
|
`tools/list has the full schema for any one tool.\n\n` +
|
|
257
327
|
groups
|
|
258
328
|
.map((g) => `${g.label} (${g.tools.length}) — ${g.purpose}\n ${g.tools.join(', ')}`)
|
|
@@ -381,6 +451,7 @@ export class EditmameiServer {
|
|
|
381
451
|
const transport = new StdioServerTransport();
|
|
382
452
|
await this.server.connect(transport);
|
|
383
453
|
void this.session.initialize().catch(() => undefined);
|
|
454
|
+
void this.reprovisionIfModuleSkipped();
|
|
384
455
|
this.telemetry.start();
|
|
385
456
|
void this.telemetry.flushOutboxOnStartup();
|
|
386
457
|
this.server.onclose = () => {
|
package/dist/core/settings.js
CHANGED
|
@@ -19,7 +19,7 @@ function defaults(installId) {
|
|
|
19
19
|
return {
|
|
20
20
|
telemetry: { usage: true, diagnostics: false, install_id: installId },
|
|
21
21
|
privacy: { send_previews_to_llm: true },
|
|
22
|
-
|
|
22
|
+
ps_path: null,
|
|
23
23
|
update_check: true,
|
|
24
24
|
};
|
|
25
25
|
}
|
|
@@ -43,7 +43,7 @@ function coerce(raw, installId) {
|
|
|
43
43
|
? p.send_previews_to_llm
|
|
44
44
|
: base.privacy.send_previews_to_llm,
|
|
45
45
|
},
|
|
46
|
-
|
|
46
|
+
ps_path: typeof r.ps_path === 'string' ? r.ps_path : null,
|
|
47
47
|
update_check: typeof r.update_check === 'boolean' ? r.update_check : base.update_check,
|
|
48
48
|
};
|
|
49
49
|
}
|
package/dist/core/tool-groups.js
CHANGED
|
@@ -81,88 +81,97 @@ export const GROUPS = {
|
|
|
81
81
|
},
|
|
82
82
|
};
|
|
83
83
|
export const TOOL_GROUPS = {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
84
|
+
ps_ping: 'core',
|
|
85
|
+
ps_overview: 'core',
|
|
86
|
+
ps_undo: 'core',
|
|
87
|
+
ps_redo: 'core',
|
|
88
|
+
ps_list_capabilities: 'core',
|
|
89
|
+
ps_report_problem: 'core',
|
|
90
|
+
ps_inspect: 'inspect',
|
|
91
|
+
ps_get_preview: 'inspect',
|
|
92
|
+
ps_get_histogram: 'verify',
|
|
93
|
+
ps_compare_regions: 'verify',
|
|
94
|
+
ps_get_layer_bounds_diff: 'verify',
|
|
95
|
+
ps_get_selection_preview: 'verify',
|
|
96
|
+
ps_create_document: 'document',
|
|
97
|
+
ps_open_document: 'document',
|
|
98
|
+
ps_close_document: 'document',
|
|
99
|
+
ps_save_psd: 'document',
|
|
100
|
+
ps_export: 'document',
|
|
101
|
+
ps_place_image: 'document',
|
|
102
|
+
ps_resize_image: 'document',
|
|
103
|
+
ps_crop_document: 'document',
|
|
104
|
+
ps_convert_image_mode: 'document',
|
|
105
|
+
ps_transform_canvas: 'document',
|
|
106
|
+
ps_guides: 'document',
|
|
107
|
+
ps_select: 'select',
|
|
108
|
+
ps_modify_selection: 'select',
|
|
109
|
+
ps_selection_channel: 'select',
|
|
110
|
+
ps_select_subject: 'select_ai',
|
|
111
|
+
ps_select_sky: 'select_ai',
|
|
112
|
+
ps_select_subject_instance: 'select_ai',
|
|
113
|
+
ps_select_object: 'select_ai',
|
|
114
|
+
ps_add_adjustment_layer: 'adjust',
|
|
115
|
+
ps_apply_adjustment: 'adjust',
|
|
116
|
+
ps_apply_filter: 'filter',
|
|
117
|
+
ps_apply_camera_raw: 'filter',
|
|
118
|
+
ps_retouch: 'retouch',
|
|
119
|
+
ps_apply_brush_stroke: 'retouch',
|
|
120
|
+
ps_create_layer: 'layers',
|
|
121
|
+
ps_delete_layer: 'layers',
|
|
122
|
+
ps_fill_layer: 'layers',
|
|
123
|
+
ps_add_fill_layer: 'layers',
|
|
124
|
+
ps_select_layer: 'layers',
|
|
125
|
+
ps_move_layer_to_position: 'layers',
|
|
126
|
+
ps_duplicate_layer: 'layers',
|
|
127
|
+
ps_copy_to_new_layer: 'layers',
|
|
128
|
+
ps_convert_to_smart_object: 'layers',
|
|
129
|
+
ps_rasterize_layer: 'layers',
|
|
130
|
+
ps_set_layer: 'layers',
|
|
131
|
+
ps_merge: 'layers',
|
|
132
|
+
ps_bake_layer: 'layers',
|
|
133
|
+
ps_add_layer_style: 'layers',
|
|
134
|
+
ps_transform_layer: 'layers',
|
|
135
|
+
ps_warp_layer: 'layers',
|
|
136
|
+
ps_warp_layer_mesh: 'layers',
|
|
137
|
+
ps_warp_layer_along: 'layers',
|
|
138
|
+
ps_warp_layer_region: 'layers',
|
|
139
|
+
ps_warp_layer_to: 'layers',
|
|
140
|
+
ps_create_group: 'layers',
|
|
141
|
+
ps_move_layer_to_group: 'layers',
|
|
142
|
+
ps_set_group_blend_mode: 'layers',
|
|
143
|
+
ps_ungroup: 'layers',
|
|
144
|
+
ps_delete_group: 'layers',
|
|
145
|
+
ps_layer_mask: 'masks',
|
|
146
|
+
ps_create_clipping_mask: 'masks',
|
|
147
|
+
ps_release_clipping_mask: 'masks',
|
|
148
|
+
ps_path: 'masks',
|
|
149
|
+
ps_vector_mask: 'masks',
|
|
150
|
+
ps_apply_image: 'masks',
|
|
151
|
+
ps_calculations: 'masks',
|
|
152
|
+
ps_shape: 'layers',
|
|
153
|
+
ps_create_text_layer: 'type',
|
|
154
|
+
ps_set_text: 'type',
|
|
155
|
+
ps_detect: 'perception',
|
|
156
|
+
ps_read_scene: 'perception',
|
|
157
|
+
ps_select_by_reference: 'perception',
|
|
158
|
+
ps_edit_object: 'perception',
|
|
159
|
+
ps_portrait_touchup: 'perception',
|
|
160
|
+
ps_add_text_to_object: 'perception',
|
|
161
|
+
ps_resolve_placement: 'perception',
|
|
162
|
+
ps_detect_landmarks: 'face',
|
|
163
|
+
ps_select_face_feature: 'face',
|
|
164
|
+
ps_stroke_face_contour: 'face',
|
|
165
|
+
ps_template_create_evidence: 'templates',
|
|
166
|
+
ps_template_save: 'templates',
|
|
167
|
+
ps_template_list: 'templates',
|
|
168
|
+
ps_template_apply: 'templates',
|
|
169
|
+
ps_template_verify: 'templates',
|
|
170
|
+
ps_template_recall: 'templates',
|
|
171
|
+
ps_template_delete: 'templates',
|
|
172
|
+
ps_list_actions: 'automation',
|
|
173
|
+
ps_play_action: 'automation',
|
|
174
|
+
ps_execute_script: 'automation',
|
|
166
175
|
};
|
|
167
176
|
export function groupOf(toolName) {
|
|
168
177
|
const group = TOOL_GROUPS[toolName];
|