editmamei 0.23.0 → 1.0.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/NOTICES.md +6 -30
- package/README.md +47 -13
- package/dist/api/extendscript/_helpers.js +1 -101
- package/dist/api/photoshop-api.js +23 -16
- package/dist/api/snippet-client.js +38 -2
- 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/core/server.js +60 -184
- package/dist/core/session.js +9 -10
- package/dist/core/tool-registry.js +4 -4
- package/dist/delivery/client.js +50 -1
- package/dist/delivery/provision.js +18 -1
- package/dist/delivery/signing.js +38 -1
- package/dist/delivery/store.js +157 -16
- package/dist/detection/detect-active-doc.js +42 -11
- package/dist/detection/detection-client.js +3 -3
- package/dist/detection/face-detector.js +2 -2
- package/dist/detection/geometry.js +14 -0
- package/dist/detection/landmark-detection-client.js +3 -3
- package/dist/detection/mesh-face.js +2 -3
- package/dist/detection/object-detector.js +2 -2
- package/dist/detection/runtime.js +14 -3
- package/dist/detection/sam-segmenter.js +69 -26
- package/dist/kernel/kernel.js +5 -9
- package/dist/kernel/module-lifecycle.js +187 -0
- package/dist/license/entitlement.js +13 -3
- package/dist/license/store.js +8 -1
- package/dist/modules/ce/index.js +1 -1
- package/dist/perception/facets.js +19 -1
- package/dist/perception/grounding-anchors.js +2 -12
- package/dist/perception/grounding-locate.js +1 -9
- package/dist/perception/grounding-review-crop.js +4 -29
- package/dist/perception/overlay.js +62 -0
- package/dist/perception/pixel-identity.js +41 -0
- package/dist/perception/region-precompute.js +96 -20
- package/dist/perception/scene-model.js +93 -50
- package/dist/perception/select-recipes.js +109 -68
- package/dist/perception/sky-ground-flood.js +0 -5
- package/dist/perception/sky-mask-transfer.js +73 -14
- package/dist/platform/connection.js +60 -43
- package/dist/platform/host-platform.js +16 -0
- package/dist/platform/macos-detector.js +41 -70
- package/dist/platform/macos-runner.js +94 -0
- package/dist/platform/script-queue.js +68 -0
- package/dist/platform/script-result.js +39 -0
- package/dist/platform/windows-detector.js +49 -66
- package/dist/platform/windows-runner.js +84 -0
- package/dist/skills/editmamei-skill.zip +0 -0
- package/dist/tools/adjustment-tools.js +80 -132
- package/dist/tools/brush-tools.js +4 -15
- package/dist/tools/channel-compose-tools.js +4 -23
- package/dist/tools/detection-tools.js +59 -47
- package/dist/tools/document-tools.js +92 -127
- package/dist/tools/filter-tools.js +490 -731
- package/dist/tools/group-tools.js +75 -156
- package/dist/tools/guide-tools.js +52 -83
- package/dist/tools/history-tools.js +29 -63
- package/dist/tools/image-placement-tools.js +18 -37
- package/dist/tools/image-tools.js +23 -51
- package/dist/tools/layer-ordering-tools.js +2 -9
- package/dist/tools/layer-properties-tools.js +207 -395
- package/dist/tools/layer-tools.js +224 -190
- package/dist/tools/layer-transform-tools.js +41 -106
- package/dist/tools/metadata-tools.js +2 -9
- package/dist/tools/path-tools.js +4 -15
- package/dist/tools/portrait-tools.js +2 -5
- package/dist/tools/preview-tools.js +59 -72
- package/dist/tools/retouch-tools.js +33 -71
- package/dist/tools/scene-tools.js +123 -75
- package/dist/tools/selection-tools.js +386 -566
- package/dist/tools/shape-tools.js +2 -9
- package/dist/tools/text-tools.js +24 -57
- package/dist/tools/transform-canvas-tools.js +21 -54
- package/dist/tools/vector-mask-tools.js +2 -9
- package/dist/update/check.js +1 -1
- package/dist/utils/jpeg-quality.js +1 -0
- package/dist/utils/logger.js +55 -45
- package/dist/utils/operation-timeouts.js +1 -0
- package/dist/utils/run-script.js +7 -2
- package/dist/utils/session-log.js +134 -12
- package/dist/utils/template-storage.js +5 -6
- package/dist/utils/tool-helpers.js +43 -0
- package/dist/version.js +1 -1
- package/package.json +10 -3
- package/LICENSE +0 -81
- package/dist/platform/detector.js +0 -32
- package/dist/platform/macos-executor.js +0 -151
- package/dist/platform/windows-executor.js +0 -160
- /package/dist/platform/{script-executor.js → ports.js} +0 -0
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { runScript } from '../utils/run-script.js';
|
|
2
2
|
import { validateArgs } from '../utils/validate.js';
|
|
3
3
|
import { OPEN_DOCUMENT_TIMEOUT_MS, OPEN_DOCUMENT_REPROBE_TIMEOUT_MS, } from '../utils/operation-timeouts.js';
|
|
4
|
+
import { toolErrorResult, runSnippetTool } from '../utils/tool-helpers.js';
|
|
5
|
+
import { purgeSceneChannels } from '../perception/region-precompute.js';
|
|
6
|
+
import { Logger } from '../utils/logger.js';
|
|
7
|
+
const logger = new Logger('document-tools');
|
|
4
8
|
const createDocumentSchema = {
|
|
5
9
|
type: 'object',
|
|
6
10
|
properties: {
|
|
@@ -69,6 +73,11 @@ const savePsdSchema = {
|
|
|
69
73
|
description: 'Include flattened composite for compatibility with other apps. Default true.',
|
|
70
74
|
default: true,
|
|
71
75
|
},
|
|
76
|
+
keep_scene_channels: {
|
|
77
|
+
type: 'boolean',
|
|
78
|
+
description: "Keep the managed scene:* alpha channels ps_read_scene precomputes. Default false — they are DERIVED masks (rebuilt by the next scene read) and each is a full-resolution channel, so baking them into the .psd bloats it badly (~51MB per channel on a 51MP document). Set true only if you want the saved file to carry the masks. The result reports scene_channels_purged either way, so it's never silent. NOTE: the `scene:` channel-name prefix is RESERVED — the purge matches on the prefix alone, so a hand-made channel named e.g. `scene:mine` is deleted along with the derived ones. Name your own channels anything else.",
|
|
79
|
+
default: false,
|
|
80
|
+
},
|
|
72
81
|
},
|
|
73
82
|
required: ['output_path'],
|
|
74
83
|
};
|
|
@@ -196,7 +205,7 @@ export function createDocumentTools(connection, snippetClient) {
|
|
|
196
205
|
{
|
|
197
206
|
tool: {
|
|
198
207
|
name: 'ps_open_document',
|
|
199
|
-
description: 'Open a file from disk into Photoshop with all dialogs suppressed (uses last-used Camera Raw settings for raw/HEIC). Returns document name, dimensions, color mode, and whether the source was a raw format. Use this in the pipeline to load Inbox files for editing.',
|
|
208
|
+
description: 'Open a file from disk into Photoshop with all dialogs suppressed (uses last-used Camera Raw settings for raw/HEIC). Returns document name, dimensions, color mode, and whether the source was a raw format. Use this in the pipeline to load Inbox files for editing. If the file is ALREADY open, its existing document is activated rather than opened a second time — `already_open: true` says so, and any edits made to it are still there (Photoshop would otherwise open a duplicate with a fresh Background, which silently strands prior work).',
|
|
200
209
|
inputSchema: openDocumentSchema,
|
|
201
210
|
outputSchema: {
|
|
202
211
|
type: 'object',
|
|
@@ -209,6 +218,7 @@ export function createDocumentTools(connection, snippetClient) {
|
|
|
209
218
|
color_mode: { type: 'string' },
|
|
210
219
|
bits_per_channel: { type: 'number' },
|
|
211
220
|
is_raw_source: { type: 'boolean' },
|
|
221
|
+
already_open: { type: 'boolean' },
|
|
212
222
|
file_path: { type: 'string' },
|
|
213
223
|
context: { type: 'object' },
|
|
214
224
|
},
|
|
@@ -298,50 +308,34 @@ async function exportImage(connection, snippetClient, rawArgs) {
|
|
|
298
308
|
}
|
|
299
309
|
}
|
|
300
310
|
async function createDocument(connection, snippetClient, rawArgs) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
},
|
|
330
|
-
],
|
|
331
|
-
structuredContent: result,
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
catch (error) {
|
|
335
|
-
return {
|
|
336
|
-
content: [
|
|
337
|
-
{
|
|
338
|
-
type: 'text',
|
|
339
|
-
text: `Error creating document: ${error instanceof Error ? error.message : String(error)}`,
|
|
340
|
-
},
|
|
341
|
-
],
|
|
342
|
-
isError: true,
|
|
343
|
-
};
|
|
344
|
-
}
|
|
311
|
+
return runSnippetTool({
|
|
312
|
+
connection,
|
|
313
|
+
snippetClient,
|
|
314
|
+
rawArgs,
|
|
315
|
+
schema: createDocumentSchema,
|
|
316
|
+
snippet: 'newDocument',
|
|
317
|
+
errorPrefix: 'Error creating document',
|
|
318
|
+
params: (args) => {
|
|
319
|
+
const colorMode = args.color_mode;
|
|
320
|
+
const colorModeMap = {
|
|
321
|
+
RGB: 'NewDocumentMode.RGB',
|
|
322
|
+
CMYK: 'NewDocumentMode.CMYK',
|
|
323
|
+
Grayscale: 'NewDocumentMode.GRAYSCALE',
|
|
324
|
+
};
|
|
325
|
+
const mappedMode = colorModeMap[colorMode];
|
|
326
|
+
if (!mappedMode) {
|
|
327
|
+
throw new Error(`colorModeMap missing entry for "${colorMode}" — schema enum and ` +
|
|
328
|
+
`internal mapping have drifted. Update src/tools/document-tools.ts.`);
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
width: args.width,
|
|
332
|
+
height: args.height,
|
|
333
|
+
resolution: args.resolution,
|
|
334
|
+
colorMode: mappedMode,
|
|
335
|
+
};
|
|
336
|
+
},
|
|
337
|
+
successText: (_result, args) => `Document created: ${args.width}x${args.height}px at ${args.resolution}dpi (${args.color_mode})`,
|
|
338
|
+
});
|
|
345
339
|
}
|
|
346
340
|
async function closeDocument(connection, snippetClient, rawArgs) {
|
|
347
341
|
try {
|
|
@@ -365,15 +359,7 @@ async function closeDocument(connection, snippetClient, rawArgs) {
|
|
|
365
359
|
};
|
|
366
360
|
}
|
|
367
361
|
catch (error) {
|
|
368
|
-
return
|
|
369
|
-
content: [
|
|
370
|
-
{
|
|
371
|
-
type: 'text',
|
|
372
|
-
text: `Error closing document: ${error instanceof Error ? error.message : String(error)}`,
|
|
373
|
-
},
|
|
374
|
-
],
|
|
375
|
-
isError: true,
|
|
376
|
-
};
|
|
362
|
+
return toolErrorResult('Error closing document', error);
|
|
377
363
|
}
|
|
378
364
|
}
|
|
379
365
|
function isScriptTimeoutError(message) {
|
|
@@ -425,45 +411,44 @@ async function openDocumentPipeline(connection, snippetClient, rawArgs) {
|
|
|
425
411
|
};
|
|
426
412
|
}
|
|
427
413
|
}
|
|
428
|
-
return
|
|
429
|
-
content: [
|
|
430
|
-
{
|
|
431
|
-
type: 'text',
|
|
432
|
-
text: `Error opening document: ${message}`,
|
|
433
|
-
},
|
|
434
|
-
],
|
|
435
|
-
isError: true,
|
|
436
|
-
};
|
|
414
|
+
return toolErrorResult('Error opening document', error);
|
|
437
415
|
}
|
|
438
416
|
}
|
|
439
417
|
async function savePsdPipeline(connection, snippetClient, rawArgs) {
|
|
418
|
+
let args;
|
|
440
419
|
try {
|
|
441
|
-
|
|
442
|
-
const outputPath = args.output_path;
|
|
443
|
-
const maximizeCompat = args.maximize_compatibility;
|
|
444
|
-
const script = await snippetClient.build('savePsdAsCopy', { outputPath, maximizeCompat });
|
|
445
|
-
const result = await runScript(connection, script);
|
|
446
|
-
return {
|
|
447
|
-
content: [
|
|
448
|
-
{
|
|
449
|
-
type: 'text',
|
|
450
|
-
text: `PSD saved:\n${JSON.stringify(result, null, 2)}`,
|
|
451
|
-
},
|
|
452
|
-
],
|
|
453
|
-
structuredContent: result,
|
|
454
|
-
};
|
|
420
|
+
args = validateArgs(savePsdSchema, rawArgs);
|
|
455
421
|
}
|
|
456
422
|
catch (error) {
|
|
457
|
-
return
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
423
|
+
return toolErrorResult('Error saving PSD', error);
|
|
424
|
+
}
|
|
425
|
+
let purged = 0;
|
|
426
|
+
if (args.keep_scene_channels !== true) {
|
|
427
|
+
try {
|
|
428
|
+
purged = await purgeSceneChannels(connection);
|
|
429
|
+
}
|
|
430
|
+
catch (err) {
|
|
431
|
+
logger.debug(`save_psd: scene-channel purge failed, saving anyway — ` +
|
|
432
|
+
`${err instanceof Error ? err.message : String(err)}`);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
const res = await runSnippetTool({
|
|
436
|
+
connection,
|
|
437
|
+
snippetClient,
|
|
438
|
+
rawArgs,
|
|
439
|
+
schema: savePsdSchema,
|
|
440
|
+
snippet: 'savePsdAsCopy',
|
|
441
|
+
errorPrefix: 'Error saving PSD',
|
|
442
|
+
params: (args) => ({
|
|
443
|
+
outputPath: args.output_path,
|
|
444
|
+
maximizeCompat: args.maximize_compatibility,
|
|
445
|
+
}),
|
|
446
|
+
successText: (result) => `PSD saved:\n${JSON.stringify(result, null, 2)}`,
|
|
447
|
+
});
|
|
448
|
+
if (!res.isError && typeof res.structuredContent === 'object' && res.structuredContent !== null) {
|
|
449
|
+
res.structuredContent.scene_channels_purged = purged;
|
|
466
450
|
}
|
|
451
|
+
return res;
|
|
467
452
|
}
|
|
468
453
|
async function exportJpegPipeline(connection, snippetClient, rawArgs) {
|
|
469
454
|
try {
|
|
@@ -491,48 +476,28 @@ async function exportJpegPipeline(connection, snippetClient, rawArgs) {
|
|
|
491
476
|
};
|
|
492
477
|
}
|
|
493
478
|
catch (error) {
|
|
494
|
-
return
|
|
495
|
-
content: [
|
|
496
|
-
{
|
|
497
|
-
type: 'text',
|
|
498
|
-
text: `Error exporting JPEG: ${error instanceof Error ? error.message : String(error)}`,
|
|
499
|
-
},
|
|
500
|
-
],
|
|
501
|
-
isError: true,
|
|
502
|
-
};
|
|
479
|
+
return toolErrorResult('Error exporting JPEG', error);
|
|
503
480
|
}
|
|
504
481
|
}
|
|
505
482
|
async function exportPngPipeline(connection, snippetClient, rawArgs) {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
}
|
|
527
|
-
catch (error) {
|
|
528
|
-
return {
|
|
529
|
-
content: [
|
|
530
|
-
{
|
|
531
|
-
type: 'text',
|
|
532
|
-
text: `Error exporting PNG: ${error instanceof Error ? error.message : String(error)}`,
|
|
533
|
-
},
|
|
534
|
-
],
|
|
535
|
-
isError: true,
|
|
536
|
-
};
|
|
537
|
-
}
|
|
483
|
+
return runSnippetTool({
|
|
484
|
+
connection,
|
|
485
|
+
snippetClient,
|
|
486
|
+
rawArgs,
|
|
487
|
+
schema: exportPngSchema,
|
|
488
|
+
snippet: 'exportPngPipeline',
|
|
489
|
+
errorPrefix: 'Error exporting PNG',
|
|
490
|
+
params: (args) => {
|
|
491
|
+
const longEdgePx = args.long_edge_px;
|
|
492
|
+
const params = {
|
|
493
|
+
outputPath: args.output_path,
|
|
494
|
+
transparentBg: args.transparent_background,
|
|
495
|
+
compression: args.compression,
|
|
496
|
+
};
|
|
497
|
+
if (longEdgePx !== undefined)
|
|
498
|
+
params.longEdgePx = longEdgePx;
|
|
499
|
+
return params;
|
|
500
|
+
},
|
|
501
|
+
successText: (result) => `PNG exported:\n${JSON.stringify(result, null, 2)}`,
|
|
502
|
+
});
|
|
538
503
|
}
|