editmamei 1.0.2 → 1.1.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.
Files changed (38) hide show
  1. package/README.md +7 -7
  2. package/dist/api/extendscript/_helpers.js +64 -2
  3. package/dist/api/photoshop-api.js +1 -1
  4. package/dist/bin/editmamei-core-darwin-arm64 +0 -0
  5. package/dist/bin/editmamei-core-darwin-x64 +0 -0
  6. package/dist/bin/editmamei-core-win-x64.exe +0 -0
  7. package/dist/cli/activate.js +1 -1
  8. package/dist/cli/config.js +1 -1
  9. package/dist/cli/deactivate.js +1 -1
  10. package/dist/core/raw-develop-state.js +13 -0
  11. package/dist/core/server.js +64 -3
  12. package/dist/core/tool-groups.js +14 -12
  13. package/dist/core/tool-tiers.js +4 -2
  14. package/dist/detection/runtime.js +2 -2
  15. package/dist/perception/region-scorer.js +1 -1
  16. package/dist/platform/connection.js +15 -0
  17. package/dist/skills/editmamei-skill.zip +0 -0
  18. package/dist/telemetry/client.js +15 -2
  19. package/dist/telemetry/sanitize.js +1 -0
  20. package/dist/tools/adjustment-tools.js +21 -3
  21. package/dist/tools/detection-tools.js +1 -1
  22. package/dist/tools/document-tools.js +5 -2
  23. package/dist/tools/filter-tools.js +130 -13
  24. package/dist/tools/group-tools.js +172 -54
  25. package/dist/tools/history-tools.js +1 -1
  26. package/dist/tools/inspect-tools.js +22 -3
  27. package/dist/tools/layer-tools.js +4 -4
  28. package/dist/tools/overview-tools.js +37 -8
  29. package/dist/tools/preview-tools.js +3 -2
  30. package/dist/tools/scene-tools.js +1 -1
  31. package/dist/tools/selection-tools.js +19 -17
  32. package/dist/tools/smart-object-tools.js +163 -0
  33. package/dist/tools/text-tools.js +92 -2
  34. package/dist/utils/session-log.js +42 -6
  35. package/dist/utils/temp.js +1 -1
  36. package/dist/utils/tool-helpers.js +23 -0
  37. package/dist/version.js +1 -1
  38. package/package.json +3 -2
@@ -205,7 +205,7 @@ export function createDocumentTools(connection, snippetClient) {
205
205
  {
206
206
  tool: {
207
207
  name: 'ps_open_document',
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).',
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. `is_raw_source` is workflow-critical, not a passive status field: when true, the first edit should be a Camera Raw develop pass on the base smart object (via a camera-raw develop tool, if one is registered in tools/list) — NOT stacked tonal adjustment layers. 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).',
209
209
  inputSchema: openDocumentSchema,
210
210
  outputSchema: {
211
211
  type: 'object',
@@ -217,7 +217,10 @@ export function createDocumentTools(connection, snippetClient) {
217
217
  resolution: { type: 'number' },
218
218
  color_mode: { type: 'string' },
219
219
  bits_per_channel: { type: 'number' },
220
- is_raw_source: { type: 'boolean' },
220
+ is_raw_source: {
221
+ type: 'boolean',
222
+ description: 'True when the source file was a raw capture (DNG/NEF/CR3/ARW/…). Workflow-critical: the open used last-used/default Camera Raw settings, so no deliberate develop has happened yet. When true, run the Camera Raw develop pass FIRST (via a camera-raw develop tool, if registered) for global tone/color — before any tonal adjustment layers — unless the user explicitly directs otherwise.',
223
+ },
221
224
  already_open: { type: 'boolean' },
222
225
  file_path: { type: 'string' },
223
226
  context: { type: 'object' },
@@ -2,7 +2,9 @@ import { runScript } from '../utils/run-script.js';
2
2
  import { validateArgs } from '../utils/validate.js';
3
3
  import { OnnxLandmarkDetectionClient } from '../detection/landmark-detection-client.js';
4
4
  import { resolveGatedPlacement, PLACEMENT_SCHEMA } from '../perception/grounding-locate.js';
5
- import { toolErrorResult, runSnippetTool, applyToActiveLayerProp } from '../utils/tool-helpers.js';
5
+ import { toolErrorResult, runSnippetTool, applyToActiveLayerProp, asSmartFilterProp, unknownDiscriminator, } from '../utils/tool-helpers.js';
6
+ import { LAYER_BLEND_MODES } from '../utils/blend-modes.js';
7
+ import { runSmartFilterOp } from './smart-object-tools.js';
6
8
  const gaussianBlurSchema = {
7
9
  type: 'object',
8
10
  properties: {
@@ -13,6 +15,7 @@ const gaussianBlurSchema = {
13
15
  maximum: 250,
14
16
  },
15
17
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
18
+ as_smart_filter: asSmartFilterProp(),
16
19
  },
17
20
  required: ['radius'],
18
21
  };
@@ -39,6 +42,7 @@ const sharpenSchema = {
39
42
  default: 0,
40
43
  },
41
44
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
45
+ as_smart_filter: asSmartFilterProp(),
42
46
  },
43
47
  required: ['amount', 'radius'],
44
48
  };
@@ -63,6 +67,7 @@ const noiseSchema = {
63
67
  default: false,
64
68
  },
65
69
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
70
+ as_smart_filter: asSmartFilterProp(),
66
71
  },
67
72
  required: ['amount'],
68
73
  };
@@ -82,6 +87,7 @@ const motionBlurSchema = {
82
87
  maximum: 999,
83
88
  },
84
89
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
90
+ as_smart_filter: asSmartFilterProp(),
85
91
  },
86
92
  required: ['angle', 'radius'],
87
93
  };
@@ -166,6 +172,7 @@ const lensBlurSchema = {
166
172
  default: false,
167
173
  },
168
174
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
175
+ as_smart_filter: asSmartFilterProp(),
169
176
  },
170
177
  };
171
178
  const smartSharpenSchema = {
@@ -248,6 +255,7 @@ const smartSharpenSchema = {
248
255
  default: 30,
249
256
  },
250
257
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
258
+ as_smart_filter: asSmartFilterProp(),
251
259
  },
252
260
  };
253
261
  const reduceNoiseSchema = {
@@ -334,6 +342,7 @@ const reduceNoiseSchema = {
334
342
  default: 50,
335
343
  },
336
344
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
345
+ as_smart_filter: asSmartFilterProp(),
337
346
  },
338
347
  };
339
348
  const highPassSchema = {
@@ -347,6 +356,7 @@ const highPassSchema = {
347
356
  default: 10,
348
357
  },
349
358
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
359
+ as_smart_filter: asSmartFilterProp(),
350
360
  },
351
361
  required: ['radius'],
352
362
  };
@@ -391,6 +401,7 @@ const radialBlurSchema = {
391
401
  description: 'Grounded alternative to center_x/center_y: NAME the blur center (a `placement` resolving to a POINT — an object centroid, an extremum, a grid intersection). The resolved document-pixel point is normalized to the 0-1 center for you and WINS over center_x/center_y. The blur runs ONLY if the objective gate PASSES.',
392
402
  },
393
403
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
404
+ as_smart_filter: asSmartFilterProp(),
394
405
  },
395
406
  };
396
407
  const pixelateSchema = {
@@ -444,6 +455,7 @@ const pixelateSchema = {
444
455
  default: 10,
445
456
  },
446
457
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
458
+ as_smart_filter: asSmartFilterProp(),
447
459
  },
448
460
  required: ['mode'],
449
461
  };
@@ -556,6 +568,7 @@ const distortSchema = {
556
568
  default: 12345,
557
569
  },
558
570
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
571
+ as_smart_filter: asSmartFilterProp(),
559
572
  },
560
573
  required: ['mode'],
561
574
  };
@@ -628,6 +641,7 @@ const stylizeSchema = {
628
641
  default: 10,
629
642
  },
630
643
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
644
+ as_smart_filter: asSmartFilterProp(),
631
645
  },
632
646
  required: ['mode'],
633
647
  };
@@ -660,6 +674,7 @@ const renderSchema = {
660
674
  default: 12345,
661
675
  },
662
676
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
677
+ as_smart_filter: asSmartFilterProp(),
663
678
  },
664
679
  required: ['mode'],
665
680
  };
@@ -695,6 +710,7 @@ const otherSchema = {
695
710
  default: 0,
696
711
  },
697
712
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
713
+ as_smart_filter: asSmartFilterProp(),
698
714
  },
699
715
  required: ['mode'],
700
716
  };
@@ -721,6 +737,7 @@ const denoiseSchema = {
721
737
  default: 10,
722
738
  },
723
739
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
740
+ as_smart_filter: asSmartFilterProp(),
724
741
  },
725
742
  required: ['mode'],
726
743
  };
@@ -747,6 +764,7 @@ const blurAdvSchema = {
747
764
  default: 20,
748
765
  },
749
766
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
767
+ as_smart_filter: asSmartFilterProp(),
750
768
  },
751
769
  required: ['mode'],
752
770
  };
@@ -801,6 +819,7 @@ const oilPaintSchema = {
801
819
  default: true,
802
820
  },
803
821
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
822
+ as_smart_filter: asSmartFilterProp(),
804
823
  },
805
824
  };
806
825
  const displaceSchema = {
@@ -837,6 +856,7 @@ const displaceSchema = {
837
856
  default: 'repeat_edge',
838
857
  },
839
858
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
859
+ as_smart_filter: asSmartFilterProp(),
840
860
  },
841
861
  required: ['map_path'],
842
862
  };
@@ -848,6 +868,22 @@ const FILTER_OUTPUT_SCHEMA = {
848
868
  target_was_copy: { type: 'boolean' },
849
869
  target_layer_name: { type: 'string' },
850
870
  original_layer_name: { type: 'string' },
871
+ is_smart_object: { type: 'boolean' },
872
+ count: { type: 'number' },
873
+ filters: { type: 'array' },
874
+ visibility_set: { type: 'boolean' },
875
+ requested_enabled: { type: 'boolean' },
876
+ enabled: { type: 'boolean' },
877
+ opacity: { type: 'number' },
878
+ blend_mode: { type: 'string' },
879
+ removed: { type: 'boolean' },
880
+ removed_filter_name: { type: 'string' },
881
+ removed_filter_type: { type: 'string' },
882
+ remaining_count: { type: 'number' },
883
+ index: { type: 'number' },
884
+ filter_name: { type: 'string' },
885
+ filter_type: { type: 'string' },
886
+ layer_name: { type: 'string' },
851
887
  context: { type: 'object' },
852
888
  },
853
889
  };
@@ -871,13 +907,26 @@ const FILTER_TYPES = [
871
907
  'displace',
872
908
  'oil_paint',
873
909
  ];
910
+ const FILTER_OPS = ['apply', 'list', 'set_visibility', 'set_blend', 'remove'];
874
911
  const FILTER_INPUT_SCHEMA = {
875
912
  type: 'object',
876
913
  properties: {
914
+ op: {
915
+ type: 'string',
916
+ enum: [...FILTER_OPS],
917
+ default: 'apply',
918
+ description: 'apply (default): apply a NEW filter — set `type` (+ its own params). ' +
919
+ 'list: read every re-editable Smart Filter on the active Smart Object (index, name, type, enabled, opacity, blend mode). ' +
920
+ 'set_visibility: turn one Smart Filter on/off without losing its settings (needs `index` + `enabled`). ' +
921
+ "set_blend: restyle one Smart Filter's `opacity` and/or `blend_mode` (needs `index` + at least one of them). " +
922
+ 'remove: delete one Smart Filter from the stack (needs `index`). ' +
923
+ 'The four management ops act on the Smart Filter stack that apply as_smart_filter=true creates; indices are ' +
924
+ '1-based and come from op=list, where 1 is the first-applied filter (bottom of the stack).',
925
+ },
877
926
  type: {
878
927
  type: 'string',
879
928
  enum: [...FILTER_TYPES],
880
- description: 'Which filter to apply. Each type uses its own parameters: ' +
929
+ description: 'Which filter to apply. Required when op=apply (the default); ignored otherwise. Each type uses its own parameters: ' +
881
930
  'gaussian_blur(radius); motion_blur(angle, radius); lens_blur(radius, iris_shape, …); ' +
882
931
  'radial_blur(amount, method spin|zoom, quality, center_x, center_y); ' +
883
932
  'sharpen=Unsharp Mask(amount, radius, threshold); smart_sharpen(amount, radius, remove_mode, …); ' +
@@ -920,15 +969,51 @@ const FILTER_INPUT_SCHEMA = {
920
969
  description: 'Angle in degrees. Used by motion_blur (−360–360) and distort/twirl (−999–999).',
921
970
  },
922
971
  apply_to_active_layer: applyToActiveLayerProp('the filter'),
972
+ as_smart_filter: asSmartFilterProp(),
973
+ index: {
974
+ type: 'integer',
975
+ description: "1-based index of the filter to act on, as reported by op=list. 1 is the FIRST-APPLIED filter (bottom of the Smart Filters stack in the Layers panel). Required for every op except 'list'.",
976
+ minimum: 1,
977
+ maximum: 1000,
978
+ },
979
+ enabled: {
980
+ type: 'boolean',
981
+ description: 'set_visibility only: true shows the filter, false hides it. The filter stays in the stack either way and keeps all its settings.',
982
+ },
983
+ opacity: {
984
+ type: 'number',
985
+ description: 'set_blend only: filter opacity 0-100. Omit to leave the current opacity untouched.',
986
+ minimum: 0,
987
+ maximum: 100,
988
+ },
989
+ blend_mode: {
990
+ type: 'string',
991
+ enum: [...LAYER_BLEND_MODES],
992
+ description: 'set_blend only: how the filter result composites against the unfiltered layer. Same names as ps_set_layer. Omit to leave the current mode untouched.',
993
+ },
923
994
  },
924
- required: ['type'],
925
995
  };
996
+ const FILTER_DESCRIPTION = "Apply a Photoshop filter (op=apply, the default) to a DUPLICATE of the active layer by default — the original is preserved, undo by deleting the copy. Pass apply_to_active_layer:true to bake into the original instead. Choose the filter with `type` (see the `type` field for its params); pass as_smart_filter:true on a Smart Object to apply it as a re-editable SMART FILTER instead of rasterizing. This same tool also reads and manages that re-editable Smart Filter stack: op=list (every filter's index/name/type/enabled/opacity/blend), op=set_visibility (toggle one off/on), op=set_blend (restyle opacity/blend_mode), op=remove (delete one). Management ops need a 1-based `index` from op=list first — index 1 is the first-applied filter, at the bottom of the stack. Covers blur, sharpen, noise, high_pass, pixelate, distort, displace, and oil_paint.";
926
997
  export function createFilterTools(connection, snippetClient, client = new OnnxLandmarkDetectionClient()) {
927
998
  return [
999
+ {
1000
+ tool: {
1001
+ name: 'ps_filter',
1002
+ description: FILTER_DESCRIPTION,
1003
+ inputSchema: FILTER_INPUT_SCHEMA,
1004
+ outputSchema: FILTER_OUTPUT_SCHEMA,
1005
+ annotations: {
1006
+ title: 'Filter',
1007
+ destructiveHint: true,
1008
+ idempotentHint: false,
1009
+ },
1010
+ },
1011
+ handler: async (args) => runFilterTool(connection, snippetClient, client, args),
1012
+ },
928
1013
  {
929
1014
  tool: {
930
1015
  name: 'ps_apply_filter',
931
- description: 'Apply a Photoshop filter to a DUPLICATE of the active layer by default (auto-duplicate-first — the original is preserved, undo by deleting the copy). Pass `apply_to_active_layer: true` to bake into the original. Auto-rasterizes text/smart-object layers. Choose the filter with `type`; each type takes its own parameters (see the `type` field). Covers blur (gaussian_blur/motion_blur/lens_blur/radial_blur), sharpen (`sharpen`=Unsharp Mask, `smart_sharpen`), noise (`noise`=Add Noise, `reduce_noise`), high_pass, pixelate, distort, displace, and oil_paint.',
1016
+ description: `DEPRECATED — use ps_filter instead (kept for one release for backward compatibility, identical behaviour). ${FILTER_DESCRIPTION}`,
932
1017
  inputSchema: FILTER_INPUT_SCHEMA,
933
1018
  outputSchema: FILTER_OUTPUT_SCHEMA,
934
1019
  annotations: {
@@ -937,13 +1022,26 @@ export function createFilterTools(connection, snippetClient, client = new OnnxLa
937
1022
  idempotentHint: false,
938
1023
  },
939
1024
  },
940
- handler: async (args) => applyFilter(connection, snippetClient, client, args),
1025
+ handler: async (args) => runFilterTool(connection, snippetClient, client, args),
941
1026
  },
942
1027
  ];
943
1028
  }
1029
+ async function runFilterTool(connection, snippetClient, detClient, rawArgs) {
1030
+ const op = rawArgs.op ?? 'apply';
1031
+ if (op !== 'apply') {
1032
+ if (!FILTER_OPS.includes(op)) {
1033
+ return unknownDiscriminator('filter op', op, FILTER_OPS);
1034
+ }
1035
+ return runSmartFilterOp(connection, snippetClient, rawArgs);
1036
+ }
1037
+ if (rawArgs.type === undefined) {
1038
+ return toolErrorResult('Error in ps_filter', new Error('op=apply needs a `type` (which filter to apply) — see the `type` field for the full list.'));
1039
+ }
1040
+ return applyFilter(connection, snippetClient, detClient, rawArgs);
1041
+ }
944
1042
  async function applyFilter(connection, snippetClient, detClient, rawArgs) {
945
1043
  const type = rawArgs.type;
946
- const { type: _omit, ...rest } = rawArgs;
1044
+ const { type: _omitType, op: _omitOp, ...rest } = rawArgs;
947
1045
  switch (type) {
948
1046
  case 'gaussian_blur':
949
1047
  return applyGaussianBlur(connection, snippetClient, rest);
@@ -1004,6 +1102,7 @@ async function applyGaussianBlur(connection, snippetClient, rawArgs) {
1004
1102
  params: (args) => ({
1005
1103
  radius: args.radius,
1006
1104
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1105
+ asSmartFilter: args.as_smart_filter ?? false,
1007
1106
  }),
1008
1107
  successText: (result, args) => {
1009
1108
  const r = result;
@@ -1027,6 +1126,7 @@ async function applySharpen(connection, snippetClient, rawArgs) {
1027
1126
  radius: args.radius,
1028
1127
  threshold: args.threshold,
1029
1128
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1129
+ asSmartFilter: args.as_smart_filter ?? false,
1030
1130
  }),
1031
1131
  successText: (result, args) => {
1032
1132
  const r = result;
@@ -1050,6 +1150,7 @@ async function applyNoise(connection, snippetClient, rawArgs) {
1050
1150
  distribution: args.distribution,
1051
1151
  monochromatic: args.monochromatic,
1052
1152
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1153
+ asSmartFilter: args.as_smart_filter ?? false,
1053
1154
  }),
1054
1155
  successText: (result, args) => {
1055
1156
  const r = result;
@@ -1075,6 +1176,7 @@ async function applyMotionBlur(connection, snippetClient, rawArgs) {
1075
1176
  angle: args.angle,
1076
1177
  radius: args.radius,
1077
1178
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1179
+ asSmartFilter: args.as_smart_filter ?? false,
1078
1180
  }),
1079
1181
  successText: (result, args) => {
1080
1182
  const r = result;
@@ -1107,6 +1209,7 @@ async function applyLensBlur(connection, snippetClient, rawArgs) {
1107
1209
  focalDistance: args.focal_distance ?? 0,
1108
1210
  invertDepth: args.invert_depth ?? false,
1109
1211
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1212
+ asSmartFilter: args.as_smart_filter ?? false,
1110
1213
  }),
1111
1214
  successText: (result, args) => {
1112
1215
  const r = result;
@@ -1141,6 +1244,7 @@ async function applySmartSharpen(connection, snippetClient, rawArgs) {
1141
1244
  highlightTonalWidth: args.highlight_tonal_width ?? 50,
1142
1245
  highlightRadius: args.highlight_radius ?? 30,
1143
1246
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1247
+ asSmartFilter: args.as_smart_filter ?? false,
1144
1248
  }),
1145
1249
  successText: (result, args) => {
1146
1250
  const r = result;
@@ -1176,6 +1280,7 @@ async function applyReduceNoise(connection, snippetClient, rawArgs) {
1176
1280
  blueStrength: args.blue_strength ?? 5,
1177
1281
  bluePreserveDetails: args.blue_preserve_details ?? 50,
1178
1282
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1283
+ asSmartFilter: args.as_smart_filter ?? false,
1179
1284
  }),
1180
1285
  successText: (result, args) => {
1181
1286
  const r = result;
@@ -1200,6 +1305,7 @@ async function applyHighPass(connection, snippetClient, rawArgs) {
1200
1305
  params: (args) => ({
1201
1306
  radius: args.radius,
1202
1307
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1308
+ asSmartFilter: args.as_smart_filter ?? false,
1203
1309
  }),
1204
1310
  successText: (result, args) => {
1205
1311
  const r = result;
@@ -1229,6 +1335,7 @@ async function applyRadialBlur(connection, snippetClient, detClient, rawArgs) {
1229
1335
  grounded = { x: Math.round(loc.geom.point.x), y: Math.round(loc.geom.point.y) };
1230
1336
  }
1231
1337
  const applyToActiveLayer = args.apply_to_active_layer ?? false;
1338
+ const asSmartFilter = args.as_smart_filter ?? false;
1232
1339
  const script = await snippetClient.build('applyRadialBlur', {
1233
1340
  amount,
1234
1341
  method,
@@ -1236,6 +1343,7 @@ async function applyRadialBlur(connection, snippetClient, detClient, rawArgs) {
1236
1343
  centerX,
1237
1344
  centerY,
1238
1345
  applyToActiveLayer,
1346
+ asSmartFilter,
1239
1347
  });
1240
1348
  const result = await runScript(connection, script);
1241
1349
  const r = result;
@@ -1278,7 +1386,8 @@ async function applyPixelate(connection, snippetClient, rawArgs) {
1278
1386
  params: (args) => {
1279
1387
  const mode = args.mode;
1280
1388
  const applyToActiveLayer = args.apply_to_active_layer ?? false;
1281
- const params = { mode, applyToActiveLayer };
1389
+ const asSmartFilter = args.as_smart_filter ?? false;
1390
+ const params = { mode, applyToActiveLayer, asSmartFilter };
1282
1391
  if (mode === 'mosaic' || mode === 'crystallize' || mode === 'pointillize') {
1283
1392
  params.cellSize = args.cell_size ?? 10;
1284
1393
  }
@@ -1311,7 +1420,8 @@ async function applyDistort(connection, snippetClient, rawArgs) {
1311
1420
  params: (args) => {
1312
1421
  const mode = args.mode;
1313
1422
  const applyToActiveLayer = args.apply_to_active_layer ?? false;
1314
- const params = { mode, applyToActiveLayer };
1423
+ const asSmartFilter = args.as_smart_filter ?? false;
1424
+ const params = { mode, applyToActiveLayer, asSmartFilter };
1315
1425
  if (mode === 'twirl') {
1316
1426
  params.angle = args.angle ?? 90;
1317
1427
  }
@@ -1366,7 +1476,8 @@ async function applyStylize(connection, snippetClient, rawArgs) {
1366
1476
  params: (args) => {
1367
1477
  const mode = args.mode;
1368
1478
  const applyToActiveLayer = args.apply_to_active_layer ?? false;
1369
- const params = { mode, applyToActiveLayer };
1479
+ const asSmartFilter = args.as_smart_filter ?? false;
1480
+ const params = { mode, applyToActiveLayer, asSmartFilter };
1370
1481
  if (mode === 'emboss') {
1371
1482
  params.angle = args.angle ?? 135;
1372
1483
  params.height = args.height ?? 3;
@@ -1406,7 +1517,8 @@ async function applyRender(connection, snippetClient, rawArgs) {
1406
1517
  params: (args) => {
1407
1518
  const mode = args.mode;
1408
1519
  const applyToActiveLayer = args.apply_to_active_layer ?? false;
1409
- const params = { mode, applyToActiveLayer };
1520
+ const asSmartFilter = args.as_smart_filter ?? false;
1521
+ const params = { mode, applyToActiveLayer, asSmartFilter };
1410
1522
  if (mode === 'fibers') {
1411
1523
  params.variance = args.variance ?? 16;
1412
1524
  params.strength = args.fiber_strength ?? 4;
@@ -1434,7 +1546,8 @@ async function applyOther(connection, snippetClient, rawArgs) {
1434
1546
  params: (args) => {
1435
1547
  const mode = args.mode;
1436
1548
  const applyToActiveLayer = args.apply_to_active_layer ?? false;
1437
- const params = { mode, applyToActiveLayer };
1549
+ const asSmartFilter = args.as_smart_filter ?? false;
1550
+ const params = { mode, applyToActiveLayer, asSmartFilter };
1438
1551
  if (mode === 'maximum' || mode === 'minimum') {
1439
1552
  params.radius = args.radius ?? 3;
1440
1553
  params.preserve = args.preserve ?? 'roundness';
@@ -1465,7 +1578,8 @@ async function applyDenoise(connection, snippetClient, rawArgs) {
1465
1578
  params: (args) => {
1466
1579
  const mode = args.mode;
1467
1580
  const applyToActiveLayer = args.apply_to_active_layer ?? false;
1468
- const params = { mode, applyToActiveLayer };
1581
+ const asSmartFilter = args.as_smart_filter ?? false;
1582
+ const params = { mode, applyToActiveLayer, asSmartFilter };
1469
1583
  if (mode === 'median') {
1470
1584
  params.radius = args.radius ?? 4;
1471
1585
  }
@@ -1495,7 +1609,8 @@ async function applyBlurAdv(connection, snippetClient, rawArgs) {
1495
1609
  params: (args) => {
1496
1610
  const mode = args.mode;
1497
1611
  const applyToActiveLayer = args.apply_to_active_layer ?? false;
1498
- const params = { mode, applyToActiveLayer };
1612
+ const asSmartFilter = args.as_smart_filter ?? false;
1613
+ const params = { mode, applyToActiveLayer, asSmartFilter };
1499
1614
  if (mode === 'surface_blur') {
1500
1615
  params.radius = args.radius ?? 15;
1501
1616
  params.threshold = args.threshold ?? 20;
@@ -1531,6 +1646,7 @@ async function applyOilPaint(connection, snippetClient, rawArgs) {
1531
1646
  shine: args.shine ?? 1.3,
1532
1647
  lightingOn: args.lighting_on ?? true,
1533
1648
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1649
+ asSmartFilter: args.as_smart_filter ?? false,
1534
1650
  }),
1535
1651
  successText: (result) => {
1536
1652
  const r = result;
@@ -1556,6 +1672,7 @@ async function applyDisplace(connection, snippetClient, rawArgs) {
1556
1672
  displacementMap: args.displacement_map ?? 'stretch_to_fit',
1557
1673
  undefinedAreas: args.undefined_areas ?? 'repeat_edge',
1558
1674
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1675
+ asSmartFilter: args.as_smart_filter ?? false,
1559
1676
  }),
1560
1677
  successText: (result, args) => {
1561
1678
  const r = result;