editmamei 0.22.4 → 0.24.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.
Files changed (80) hide show
  1. package/README.md +8 -6
  2. package/dist/api/extendscript/_helpers.js +97 -13
  3. package/dist/api/photoshop-api.js +4 -3
  4. package/dist/api/snippet-client.js +38 -2
  5. package/dist/bin/editmamei-core-darwin-arm64 +0 -0
  6. package/dist/bin/editmamei-core-darwin-x64 +0 -0
  7. package/dist/bin/editmamei-core-win-x64.exe +0 -0
  8. package/dist/core/server.js +56 -180
  9. package/dist/delivery/client.js +50 -1
  10. package/dist/delivery/provision.js +18 -1
  11. package/dist/delivery/signing.js +38 -1
  12. package/dist/delivery/store.js +149 -16
  13. package/dist/detection/detect-active-doc.js +41 -10
  14. package/dist/detection/detection-client.js +3 -3
  15. package/dist/detection/face-detector.js +2 -2
  16. package/dist/detection/geometry.js +14 -0
  17. package/dist/detection/landmark-detection-client.js +3 -3
  18. package/dist/detection/mesh-face.js +2 -3
  19. package/dist/detection/object-detector.js +2 -2
  20. package/dist/detection/runtime.js +14 -3
  21. package/dist/detection/sam-segmenter.js +69 -26
  22. package/dist/kernel/kernel.js +5 -9
  23. package/dist/kernel/module-lifecycle.js +181 -0
  24. package/dist/license/entitlement.js +13 -3
  25. package/dist/license/store.js +8 -1
  26. package/dist/modules/ce/index.js +1 -1
  27. package/dist/perception/facets.js +19 -1
  28. package/dist/perception/grounding-anchors.js +2 -12
  29. package/dist/perception/grounding-locate.js +1 -9
  30. package/dist/perception/grounding-review-crop.js +4 -29
  31. package/dist/perception/overlay.js +62 -0
  32. package/dist/perception/pixel-identity.js +41 -0
  33. package/dist/perception/region-precompute.js +85 -17
  34. package/dist/perception/scene-model.js +93 -50
  35. package/dist/perception/select-recipes.js +107 -66
  36. package/dist/perception/sky-ground-flood.js +0 -5
  37. package/dist/perception/sky-mask-transfer.js +72 -13
  38. package/dist/platform/connection.js +42 -11
  39. package/dist/platform/executor-queue.js +68 -0
  40. package/dist/platform/macos-detector.js +2 -1
  41. package/dist/platform/macos-executor.js +18 -67
  42. package/dist/platform/run-child.js +6 -3
  43. package/dist/platform/windows-detector.js +14 -7
  44. package/dist/platform/windows-executor.js +9 -64
  45. package/dist/skills/editmamei-skill.zip +0 -0
  46. package/dist/tools/adjustment-tools.js +78 -130
  47. package/dist/tools/brush-tools.js +3 -14
  48. package/dist/tools/channel-compose-tools.js +4 -23
  49. package/dist/tools/detection-tools.js +59 -47
  50. package/dist/tools/document-tools.js +121 -131
  51. package/dist/tools/filter-tools.js +489 -730
  52. package/dist/tools/group-tools.js +90 -156
  53. package/dist/tools/guide-tools.js +52 -83
  54. package/dist/tools/history-tools.js +29 -63
  55. package/dist/tools/image-placement-tools.js +18 -37
  56. package/dist/tools/image-tools.js +23 -51
  57. package/dist/tools/layer-ordering-tools.js +2 -9
  58. package/dist/tools/layer-properties-tools.js +245 -384
  59. package/dist/tools/layer-tools.js +115 -181
  60. package/dist/tools/layer-transform-tools.js +41 -106
  61. package/dist/tools/metadata-tools.js +2 -9
  62. package/dist/tools/path-tools.js +3 -14
  63. package/dist/tools/portrait-tools.js +2 -5
  64. package/dist/tools/preview-tools.js +53 -65
  65. package/dist/tools/retouch-tools.js +32 -70
  66. package/dist/tools/scene-tools.js +94 -73
  67. package/dist/tools/selection-tools.js +306 -563
  68. package/dist/tools/shape-tools.js +18 -10
  69. package/dist/tools/text-tools.js +24 -57
  70. package/dist/tools/transform-canvas-tools.js +21 -54
  71. package/dist/tools/vector-mask-tools.js +2 -9
  72. package/dist/utils/jpeg-quality.js +1 -0
  73. package/dist/utils/logger.js +3 -0
  74. package/dist/utils/operation-timeouts.js +7 -0
  75. package/dist/utils/run-script.js +7 -2
  76. package/dist/utils/session-log.js +134 -12
  77. package/dist/utils/template-storage.js +5 -6
  78. package/dist/utils/tool-helpers.js +37 -0
  79. package/dist/version.js +1 -1
  80. package/package.json +1 -1
@@ -2,11 +2,7 @@ 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
- const APPLY_TO_ACTIVE_LAYER_PROP = {
6
- type: 'boolean',
7
- description: 'If false (default), the filter is applied to a duplicate of the active layer named "<FilterName> (<Original Name>)" — the original is preserved and the LLM can undo simply by deleting the copy. If true, the filter bakes directly into the active layer (the historical destructive behavior).',
8
- default: false,
9
- };
5
+ import { toolErrorResult, runSnippetTool, applyToActiveLayerProp } from '../utils/tool-helpers.js';
10
6
  const gaussianBlurSchema = {
11
7
  type: 'object',
12
8
  properties: {
@@ -16,7 +12,7 @@ const gaussianBlurSchema = {
16
12
  minimum: 0.1,
17
13
  maximum: 250,
18
14
  },
19
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
15
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
20
16
  },
21
17
  required: ['radius'],
22
18
  };
@@ -42,7 +38,7 @@ const sharpenSchema = {
42
38
  maximum: 255,
43
39
  default: 0,
44
40
  },
45
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
41
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
46
42
  },
47
43
  required: ['amount', 'radius'],
48
44
  };
@@ -66,7 +62,7 @@ const noiseSchema = {
66
62
  description: 'Apply monochromatic noise. Default: false.',
67
63
  default: false,
68
64
  },
69
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
65
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
70
66
  },
71
67
  required: ['amount'],
72
68
  };
@@ -85,7 +81,7 @@ const motionBlurSchema = {
85
81
  minimum: 1,
86
82
  maximum: 999,
87
83
  },
88
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
84
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
89
85
  },
90
86
  required: ['angle', 'radius'],
91
87
  };
@@ -169,7 +165,7 @@ const lensBlurSchema = {
169
165
  description: 'Invert the depth map. PS default false.',
170
166
  default: false,
171
167
  },
172
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
168
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
173
169
  },
174
170
  };
175
171
  const smartSharpenSchema = {
@@ -251,7 +247,7 @@ const smartSharpenSchema = {
251
247
  maximum: 100,
252
248
  default: 30,
253
249
  },
254
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
250
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
255
251
  },
256
252
  };
257
253
  const reduceNoiseSchema = {
@@ -337,7 +333,7 @@ const reduceNoiseSchema = {
337
333
  maximum: 100,
338
334
  default: 50,
339
335
  },
340
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
336
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
341
337
  },
342
338
  };
343
339
  const highPassSchema = {
@@ -350,7 +346,7 @@ const highPassSchema = {
350
346
  maximum: 1000,
351
347
  default: 10,
352
348
  },
353
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
349
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
354
350
  },
355
351
  required: ['radius'],
356
352
  };
@@ -394,7 +390,7 @@ const radialBlurSchema = {
394
390
  ...PLACEMENT_SCHEMA,
395
391
  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.',
396
392
  },
397
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
393
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
398
394
  },
399
395
  };
400
396
  const pixelateSchema = {
@@ -447,7 +443,7 @@ const pixelateSchema = {
447
443
  maximum: 300,
448
444
  default: 10,
449
445
  },
450
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
446
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
451
447
  },
452
448
  required: ['mode'],
453
449
  };
@@ -559,7 +555,7 @@ const distortSchema = {
559
555
  minimum: 0,
560
556
  default: 12345,
561
557
  },
562
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
558
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
563
559
  },
564
560
  required: ['mode'],
565
561
  };
@@ -631,7 +627,7 @@ const stylizeSchema = {
631
627
  maximum: 99,
632
628
  default: 10,
633
629
  },
634
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
630
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
635
631
  },
636
632
  required: ['mode'],
637
633
  };
@@ -663,7 +659,7 @@ const renderSchema = {
663
659
  minimum: 0,
664
660
  default: 12345,
665
661
  },
666
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
662
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
667
663
  },
668
664
  required: ['mode'],
669
665
  };
@@ -698,7 +694,7 @@ const otherSchema = {
698
694
  description: 'offset only: vertical shift in pixels (positive = down).',
699
695
  default: 0,
700
696
  },
701
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
697
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
702
698
  },
703
699
  required: ['mode'],
704
700
  };
@@ -724,7 +720,7 @@ const denoiseSchema = {
724
720
  maximum: 255,
725
721
  default: 10,
726
722
  },
727
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
723
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
728
724
  },
729
725
  required: ['mode'],
730
726
  };
@@ -750,7 +746,7 @@ const blurAdvSchema = {
750
746
  maximum: 255,
751
747
  default: 20,
752
748
  },
753
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
749
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
754
750
  },
755
751
  required: ['mode'],
756
752
  };
@@ -804,7 +800,7 @@ const oilPaintSchema = {
804
800
  description: 'Whether the lighting/shine relief is applied.',
805
801
  default: true,
806
802
  },
807
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
803
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
808
804
  },
809
805
  };
810
806
  const displaceSchema = {
@@ -840,7 +836,7 @@ const displaceSchema = {
840
836
  description: 'How to fill areas pushed outside the layer.',
841
837
  default: 'repeat_edge',
842
838
  },
843
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
839
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
844
840
  },
845
841
  required: ['map_path'],
846
842
  };
@@ -923,7 +919,7 @@ const FILTER_INPUT_SCHEMA = {
923
919
  type: 'number',
924
920
  description: 'Angle in degrees. Used by motion_blur (−360–360) and distort/twirl (−999–999).',
925
921
  },
926
- apply_to_active_layer: APPLY_TO_ACTIVE_LAYER_PROP,
922
+ apply_to_active_layer: applyToActiveLayerProp('the filter'),
927
923
  },
928
924
  required: ['type'],
929
925
  };
@@ -998,360 +994,221 @@ async function applyFilter(connection, snippetClient, detClient, rawArgs) {
998
994
  }
999
995
  }
1000
996
  async function applyGaussianBlur(connection, snippetClient, rawArgs) {
1001
- try {
1002
- const args = validateArgs(gaussianBlurSchema, rawArgs);
1003
- const radius = args.radius;
1004
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1005
- const script = await snippetClient.build('applyGaussianBlur', { radius, applyToActiveLayer });
1006
- const result = await runScript(connection, script);
1007
- const r = result;
1008
- const target = r.target_was_copy
1009
- ? `new copy "${r.target_layer_name ?? '?'}"`
1010
- : 'active layer (in place)';
1011
- return {
1012
- content: [
1013
- {
1014
- type: 'text',
1015
- text: `Gaussian Blur radius ${radius}px applied to ${target}.`,
1016
- },
1017
- ],
1018
- structuredContent: result,
1019
- };
1020
- }
1021
- catch (error) {
1022
- return {
1023
- content: [
1024
- {
1025
- type: 'text',
1026
- text: `Error applying Gaussian Blur: ${error instanceof Error ? error.message : String(error)}`,
1027
- },
1028
- ],
1029
- isError: true,
1030
- };
1031
- }
997
+ return runSnippetTool({
998
+ connection,
999
+ snippetClient,
1000
+ rawArgs,
1001
+ schema: gaussianBlurSchema,
1002
+ snippet: 'applyGaussianBlur',
1003
+ errorPrefix: 'Error applying Gaussian Blur',
1004
+ params: (args) => ({
1005
+ radius: args.radius,
1006
+ applyToActiveLayer: args.apply_to_active_layer ?? false,
1007
+ }),
1008
+ successText: (result, args) => {
1009
+ const r = result;
1010
+ const target = r.target_was_copy
1011
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1012
+ : 'active layer (in place)';
1013
+ return `Gaussian Blur radius ${args.radius}px applied to ${target}.`;
1014
+ },
1015
+ });
1032
1016
  }
1033
1017
  async function applySharpen(connection, snippetClient, rawArgs) {
1034
- try {
1035
- const args = validateArgs(sharpenSchema, rawArgs);
1036
- const amount = args.amount;
1037
- const radius = args.radius;
1038
- const threshold = args.threshold;
1039
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1040
- const script = await snippetClient.build('applyUnsharpMask', {
1041
- amount,
1042
- radius,
1043
- threshold,
1044
- applyToActiveLayer,
1045
- });
1046
- const result = await runScript(connection, script);
1047
- const r = result;
1048
- const target = r.target_was_copy
1049
- ? `new copy "${r.target_layer_name ?? '?'}"`
1050
- : 'active layer (in place)';
1051
- return {
1052
- content: [
1053
- {
1054
- type: 'text',
1055
- text: `Unsharp Mask (amount ${amount}%, radius ${radius}px, threshold ${threshold}) applied to ${target}.`,
1056
- },
1057
- ],
1058
- structuredContent: result,
1059
- };
1060
- }
1061
- catch (error) {
1062
- return {
1063
- content: [
1064
- {
1065
- type: 'text',
1066
- text: `Error applying sharpen: ${error instanceof Error ? error.message : String(error)}`,
1067
- },
1068
- ],
1069
- isError: true,
1070
- };
1071
- }
1018
+ return runSnippetTool({
1019
+ connection,
1020
+ snippetClient,
1021
+ rawArgs,
1022
+ schema: sharpenSchema,
1023
+ snippet: 'applyUnsharpMask',
1024
+ errorPrefix: 'Error applying sharpen',
1025
+ params: (args) => ({
1026
+ amount: args.amount,
1027
+ radius: args.radius,
1028
+ threshold: args.threshold,
1029
+ applyToActiveLayer: args.apply_to_active_layer ?? false,
1030
+ }),
1031
+ successText: (result, args) => {
1032
+ const r = result;
1033
+ const target = r.target_was_copy
1034
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1035
+ : 'active layer (in place)';
1036
+ return `Unsharp Mask (amount ${args.amount}%, radius ${args.radius}px, threshold ${args.threshold}) applied to ${target}.`;
1037
+ },
1038
+ });
1072
1039
  }
1073
1040
  async function applyNoise(connection, snippetClient, rawArgs) {
1074
- try {
1075
- const args = validateArgs(noiseSchema, rawArgs);
1076
- const amount = args.amount;
1077
- const distribution = args.distribution;
1078
- const monochromatic = args.monochromatic;
1079
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1080
- const script = await snippetClient.build('applyAddNoise', {
1081
- amount,
1082
- distribution,
1083
- monochromatic,
1084
- applyToActiveLayer,
1085
- });
1086
- const result = await runScript(connection, script);
1087
- const r = result;
1088
- const target = r.target_was_copy
1089
- ? `new copy "${r.target_layer_name ?? '?'}"`
1090
- : 'active layer (in place)';
1091
- return {
1092
- content: [
1093
- {
1094
- type: 'text',
1095
- text: `Add Noise ${amount}% (${distribution}${monochromatic ? ', mono' : ''}) applied to ${target}.`,
1096
- },
1097
- ],
1098
- structuredContent: result,
1099
- };
1100
- }
1101
- catch (error) {
1102
- return {
1103
- content: [
1104
- {
1105
- type: 'text',
1106
- text: `Error applying noise: ${error instanceof Error ? error.message : String(error)}`,
1107
- },
1108
- ],
1109
- isError: true,
1110
- };
1111
- }
1041
+ return runSnippetTool({
1042
+ connection,
1043
+ snippetClient,
1044
+ rawArgs,
1045
+ schema: noiseSchema,
1046
+ snippet: 'applyAddNoise',
1047
+ errorPrefix: 'Error applying noise',
1048
+ params: (args) => ({
1049
+ amount: args.amount,
1050
+ distribution: args.distribution,
1051
+ monochromatic: args.monochromatic,
1052
+ applyToActiveLayer: args.apply_to_active_layer ?? false,
1053
+ }),
1054
+ successText: (result, args) => {
1055
+ const r = result;
1056
+ const target = r.target_was_copy
1057
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1058
+ : 'active layer (in place)';
1059
+ const amount = args.amount;
1060
+ const distribution = args.distribution;
1061
+ const monochromatic = args.monochromatic;
1062
+ return `Add Noise ${amount}% (${distribution}${monochromatic ? ', mono' : ''}) applied to ${target}.`;
1063
+ },
1064
+ });
1112
1065
  }
1113
1066
  async function applyMotionBlur(connection, snippetClient, rawArgs) {
1114
- try {
1115
- const args = validateArgs(motionBlurSchema, rawArgs);
1116
- const angle = args.angle;
1117
- const radius = args.radius;
1118
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1119
- const script = await snippetClient.build('applyMotionBlur', {
1120
- angle,
1121
- radius,
1122
- applyToActiveLayer,
1123
- });
1124
- const result = await runScript(connection, script);
1125
- const r = result;
1126
- const target = r.target_was_copy
1127
- ? `new copy "${r.target_layer_name ?? '?'}"`
1128
- : 'active layer (in place)';
1129
- return {
1130
- content: [
1131
- {
1132
- type: 'text',
1133
- text: `Motion Blur (angle ${angle}°, radius ${radius}px) applied to ${target}.`,
1134
- },
1135
- ],
1136
- structuredContent: result,
1137
- };
1138
- }
1139
- catch (error) {
1140
- return {
1141
- content: [
1142
- {
1143
- type: 'text',
1144
- text: `Error applying motion blur: ${error instanceof Error ? error.message : String(error)}`,
1145
- },
1146
- ],
1147
- isError: true,
1148
- };
1149
- }
1067
+ return runSnippetTool({
1068
+ connection,
1069
+ snippetClient,
1070
+ rawArgs,
1071
+ schema: motionBlurSchema,
1072
+ snippet: 'applyMotionBlur',
1073
+ errorPrefix: 'Error applying motion blur',
1074
+ params: (args) => ({
1075
+ angle: args.angle,
1076
+ radius: args.radius,
1077
+ applyToActiveLayer: args.apply_to_active_layer ?? false,
1078
+ }),
1079
+ successText: (result, args) => {
1080
+ const r = result;
1081
+ const target = r.target_was_copy
1082
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1083
+ : 'active layer (in place)';
1084
+ return `Motion Blur (angle ${args.angle}°, radius ${args.radius}px) applied to ${target}.`;
1085
+ },
1086
+ });
1150
1087
  }
1151
1088
  async function applyLensBlur(connection, snippetClient, rawArgs) {
1152
- try {
1153
- const args = validateArgs(lensBlurSchema, rawArgs);
1154
- const radius = args.radius ?? 15;
1155
- const irisShape = args.iris_shape ?? 'hexagon';
1156
- const irisBladeCurvature = args.iris_blade_curvature ?? 0;
1157
- const irisRotation = args.iris_rotation ?? 0;
1158
- const specularBrightness = args.specular_brightness ?? 0;
1159
- const specularThreshold = args.specular_threshold ?? 255;
1160
- const noiseAmount = args.noise_amount ?? 0;
1161
- const noiseDistribution = args.noise_distribution ?? 'uniform';
1162
- const noiseMonochromatic = args.noise_monochromatic ?? true;
1163
- const depthSource = args.depth_source ?? 'none';
1164
- const focalDistance = args.focal_distance ?? 0;
1165
- const invertDepth = args.invert_depth ?? false;
1166
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1167
- const script = await snippetClient.build('applyLensBlur', {
1168
- radius,
1169
- irisShape,
1170
- irisBladeCurvature,
1171
- irisRotation,
1172
- specularBrightness,
1173
- specularThreshold,
1174
- noiseAmount,
1175
- noiseDistribution,
1176
- noiseMonochromatic,
1177
- depthSource,
1178
- focalDistance,
1179
- invertDepth,
1180
- applyToActiveLayer,
1181
- });
1182
- const result = await runScript(connection, script);
1183
- const r = result;
1184
- const target = r.target_was_copy
1185
- ? `new copy "${r.target_layer_name ?? '?'}"`
1186
- : 'active layer (in place)';
1187
- return {
1188
- content: [
1189
- {
1190
- type: 'text',
1191
- text: `Lens Blur (radius ${radius}px, ${irisShape} iris${depthSource !== 'none' ? `, depth=${depthSource}` : ''}) applied to ${target}.`,
1192
- },
1193
- ],
1194
- structuredContent: result,
1195
- };
1196
- }
1197
- catch (error) {
1198
- return {
1199
- content: [
1200
- {
1201
- type: 'text',
1202
- text: `Error applying Lens Blur: ${error instanceof Error ? error.message : String(error)}`,
1203
- },
1204
- ],
1205
- isError: true,
1206
- };
1207
- }
1089
+ return runSnippetTool({
1090
+ connection,
1091
+ snippetClient,
1092
+ rawArgs,
1093
+ schema: lensBlurSchema,
1094
+ snippet: 'applyLensBlur',
1095
+ errorPrefix: 'Error applying Lens Blur',
1096
+ params: (args) => ({
1097
+ radius: args.radius ?? 15,
1098
+ irisShape: args.iris_shape ?? 'hexagon',
1099
+ irisBladeCurvature: args.iris_blade_curvature ?? 0,
1100
+ irisRotation: args.iris_rotation ?? 0,
1101
+ specularBrightness: args.specular_brightness ?? 0,
1102
+ specularThreshold: args.specular_threshold ?? 255,
1103
+ noiseAmount: args.noise_amount ?? 0,
1104
+ noiseDistribution: args.noise_distribution ?? 'uniform',
1105
+ noiseMonochromatic: args.noise_monochromatic ?? true,
1106
+ depthSource: args.depth_source ?? 'none',
1107
+ focalDistance: args.focal_distance ?? 0,
1108
+ invertDepth: args.invert_depth ?? false,
1109
+ applyToActiveLayer: args.apply_to_active_layer ?? false,
1110
+ }),
1111
+ successText: (result, args) => {
1112
+ const r = result;
1113
+ const target = r.target_was_copy
1114
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1115
+ : 'active layer (in place)';
1116
+ const radius = args.radius ?? 15;
1117
+ const irisShape = args.iris_shape ?? 'hexagon';
1118
+ const depthSource = args.depth_source ?? 'none';
1119
+ return `Lens Blur (radius ${radius}px, ${irisShape} iris${depthSource !== 'none' ? `, depth=${depthSource}` : ''}) applied to ${target}.`;
1120
+ },
1121
+ });
1208
1122
  }
1209
1123
  async function applySmartSharpen(connection, snippetClient, rawArgs) {
1210
- try {
1211
- const args = validateArgs(smartSharpenSchema, rawArgs);
1212
- const amount = args.amount ?? 100;
1213
- const radius = args.radius ?? 1.5;
1214
- const noiseReduction = args.noise_reduction ?? 10;
1215
- const removeMode = args.remove_mode ?? 'lensBlur';
1216
- const motionAngle = args.motion_angle ?? 0;
1217
- const shadowFade = args.shadow_fade ?? 0;
1218
- const shadowTonalWidth = args.shadow_tonal_width ?? 50;
1219
- const shadowRadius = args.shadow_radius ?? 30;
1220
- const highlightFade = args.highlight_fade ?? 0;
1221
- const highlightTonalWidth = args.highlight_tonal_width ?? 50;
1222
- const highlightRadius = args.highlight_radius ?? 30;
1223
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1224
- const script = await snippetClient.build('applySmartSharpen', {
1225
- amount,
1226
- radius,
1227
- noiseReduction,
1228
- removeMode,
1229
- motionAngle,
1230
- shadowFade,
1231
- shadowTonalWidth,
1232
- shadowRadius,
1233
- highlightFade,
1234
- highlightTonalWidth,
1235
- highlightRadius,
1236
- applyToActiveLayer,
1237
- });
1238
- const result = await runScript(connection, script);
1239
- const r = result;
1240
- const target = r.target_was_copy
1241
- ? `new copy "${r.target_layer_name ?? '?'}"`
1242
- : 'active layer (in place)';
1243
- return {
1244
- content: [
1245
- {
1246
- type: 'text',
1247
- text: `Smart Sharpen (amount ${amount}%, radius ${radius}px, remove ${removeMode}) applied to ${target}.`,
1248
- },
1249
- ],
1250
- structuredContent: result,
1251
- };
1252
- }
1253
- catch (error) {
1254
- return {
1255
- content: [
1256
- {
1257
- type: 'text',
1258
- text: `Error applying Smart Sharpen: ${error instanceof Error ? error.message : String(error)}`,
1259
- },
1260
- ],
1261
- isError: true,
1262
- };
1263
- }
1124
+ return runSnippetTool({
1125
+ connection,
1126
+ snippetClient,
1127
+ rawArgs,
1128
+ schema: smartSharpenSchema,
1129
+ snippet: 'applySmartSharpen',
1130
+ errorPrefix: 'Error applying Smart Sharpen',
1131
+ params: (args) => ({
1132
+ amount: args.amount ?? 100,
1133
+ radius: args.radius ?? 1.5,
1134
+ noiseReduction: args.noise_reduction ?? 10,
1135
+ removeMode: args.remove_mode ?? 'lensBlur',
1136
+ motionAngle: args.motion_angle ?? 0,
1137
+ shadowFade: args.shadow_fade ?? 0,
1138
+ shadowTonalWidth: args.shadow_tonal_width ?? 50,
1139
+ shadowRadius: args.shadow_radius ?? 30,
1140
+ highlightFade: args.highlight_fade ?? 0,
1141
+ highlightTonalWidth: args.highlight_tonal_width ?? 50,
1142
+ highlightRadius: args.highlight_radius ?? 30,
1143
+ applyToActiveLayer: args.apply_to_active_layer ?? false,
1144
+ }),
1145
+ successText: (result, args) => {
1146
+ const r = result;
1147
+ const target = r.target_was_copy
1148
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1149
+ : 'active layer (in place)';
1150
+ const amount = args.amount ?? 100;
1151
+ const radius = args.radius ?? 1.5;
1152
+ const removeMode = args.remove_mode ?? 'lensBlur';
1153
+ return `Smart Sharpen (amount ${amount}%, radius ${radius}px, remove ${removeMode}) applied to ${target}.`;
1154
+ },
1155
+ });
1264
1156
  }
1265
1157
  async function applyReduceNoise(connection, snippetClient, rawArgs) {
1266
- try {
1267
- const args = validateArgs(reduceNoiseSchema, rawArgs);
1268
- const strength = args.strength ?? 5;
1269
- const preserveDetails = args.preserve_details ?? 50;
1270
- const colorNoise = args.color_noise ?? 45;
1271
- const sharpenDetails = args.sharpen_details ?? 25;
1272
- const removeJpegArtifact = args.remove_jpeg_artifact ?? false;
1273
- const perChannel = args.per_channel ?? false;
1274
- const redStrength = args.red_strength ?? 5;
1275
- const redPreserveDetails = args.red_preserve_details ?? 50;
1276
- const greenStrength = args.green_strength ?? 5;
1277
- const greenPreserveDetails = args.green_preserve_details ?? 50;
1278
- const blueStrength = args.blue_strength ?? 5;
1279
- const bluePreserveDetails = args.blue_preserve_details ?? 50;
1280
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1281
- const script = await snippetClient.build('applyReduceNoise', {
1282
- strength,
1283
- preserveDetails,
1284
- colorNoise,
1285
- sharpenDetails,
1286
- removeJpegArtifact,
1287
- perChannel,
1288
- redStrength,
1289
- redPreserveDetails,
1290
- greenStrength,
1291
- greenPreserveDetails,
1292
- blueStrength,
1293
- bluePreserveDetails,
1294
- applyToActiveLayer,
1295
- });
1296
- const result = await runScript(connection, script);
1297
- const r = result;
1298
- const target = r.target_was_copy
1299
- ? `new copy "${r.target_layer_name ?? '?'}"`
1300
- : 'active layer (in place)';
1301
- return {
1302
- content: [
1303
- {
1304
- type: 'text',
1305
- text: `Reduce Noise (strength ${strength}, color ${colorNoise}${perChannel ? ', per-channel' : ''}) applied to ${target}.`,
1306
- },
1307
- ],
1308
- structuredContent: result,
1309
- };
1310
- }
1311
- catch (error) {
1312
- return {
1313
- content: [
1314
- {
1315
- type: 'text',
1316
- text: `Error applying Reduce Noise: ${error instanceof Error ? error.message : String(error)}`,
1317
- },
1318
- ],
1319
- isError: true,
1320
- };
1321
- }
1158
+ return runSnippetTool({
1159
+ connection,
1160
+ snippetClient,
1161
+ rawArgs,
1162
+ schema: reduceNoiseSchema,
1163
+ snippet: 'applyReduceNoise',
1164
+ errorPrefix: 'Error applying Reduce Noise',
1165
+ params: (args) => ({
1166
+ strength: args.strength ?? 5,
1167
+ preserveDetails: args.preserve_details ?? 50,
1168
+ colorNoise: args.color_noise ?? 45,
1169
+ sharpenDetails: args.sharpen_details ?? 25,
1170
+ removeJpegArtifact: args.remove_jpeg_artifact ?? false,
1171
+ perChannel: args.per_channel ?? false,
1172
+ redStrength: args.red_strength ?? 5,
1173
+ redPreserveDetails: args.red_preserve_details ?? 50,
1174
+ greenStrength: args.green_strength ?? 5,
1175
+ greenPreserveDetails: args.green_preserve_details ?? 50,
1176
+ blueStrength: args.blue_strength ?? 5,
1177
+ bluePreserveDetails: args.blue_preserve_details ?? 50,
1178
+ applyToActiveLayer: args.apply_to_active_layer ?? false,
1179
+ }),
1180
+ successText: (result, args) => {
1181
+ const r = result;
1182
+ const target = r.target_was_copy
1183
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1184
+ : 'active layer (in place)';
1185
+ const strength = args.strength ?? 5;
1186
+ const colorNoise = args.color_noise ?? 45;
1187
+ const perChannel = args.per_channel ?? false;
1188
+ return `Reduce Noise (strength ${strength}, color ${colorNoise}${perChannel ? ', per-channel' : ''}) applied to ${target}.`;
1189
+ },
1190
+ });
1322
1191
  }
1323
1192
  async function applyHighPass(connection, snippetClient, rawArgs) {
1324
- try {
1325
- const args = validateArgs(highPassSchema, rawArgs);
1326
- const radius = args.radius;
1327
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1328
- const script = await snippetClient.build('applyHighPass', { radius, applyToActiveLayer });
1329
- const result = await runScript(connection, script);
1330
- const r = result;
1331
- const target = r.target_was_copy
1332
- ? `new copy "${r.target_layer_name ?? '?'}"`
1333
- : 'active layer (in place)';
1334
- return {
1335
- content: [
1336
- {
1337
- type: 'text',
1338
- text: `High Pass (radius ${radius}px) applied to ${target}.`,
1339
- },
1340
- ],
1341
- structuredContent: result,
1342
- };
1343
- }
1344
- catch (error) {
1345
- return {
1346
- content: [
1347
- {
1348
- type: 'text',
1349
- text: `Error applying High Pass: ${error instanceof Error ? error.message : String(error)}`,
1350
- },
1351
- ],
1352
- isError: true,
1353
- };
1354
- }
1193
+ return runSnippetTool({
1194
+ connection,
1195
+ snippetClient,
1196
+ rawArgs,
1197
+ schema: highPassSchema,
1198
+ snippet: 'applyHighPass',
1199
+ errorPrefix: 'Error applying High Pass',
1200
+ params: (args) => ({
1201
+ radius: args.radius,
1202
+ applyToActiveLayer: args.apply_to_active_layer ?? false,
1203
+ }),
1204
+ successText: (result, args) => {
1205
+ const r = result;
1206
+ const target = r.target_was_copy
1207
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1208
+ : 'active layer (in place)';
1209
+ return `High Pass (radius ${args.radius}px) applied to ${target}.`;
1210
+ },
1211
+ });
1355
1212
  }
1356
1213
  async function applyRadialBlur(connection, snippetClient, detClient, rawArgs) {
1357
1214
  try {
@@ -1407,330 +1264,265 @@ async function applyRadialBlur(connection, snippetClient, detClient, rawArgs) {
1407
1264
  };
1408
1265
  }
1409
1266
  catch (error) {
1410
- return {
1411
- content: [
1412
- {
1413
- type: 'text',
1414
- text: `Error applying Radial Blur: ${error instanceof Error ? error.message : String(error)}`,
1415
- },
1416
- ],
1417
- isError: true,
1418
- };
1267
+ return toolErrorResult('Error applying Radial Blur', error);
1419
1268
  }
1420
1269
  }
1421
1270
  async function applyPixelate(connection, snippetClient, rawArgs) {
1422
- try {
1423
- const args = validateArgs(pixelateSchema, rawArgs);
1424
- const mode = args.mode;
1425
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1426
- const params = { mode, applyToActiveLayer };
1427
- if (mode === 'mosaic' || mode === 'crystallize' || mode === 'pointillize') {
1428
- params.cellSize = args.cell_size ?? 10;
1429
- }
1430
- else if (mode === 'color_halftone') {
1431
- params.maxRadius = args.max_radius ?? 8;
1432
- params.angle1 = args.angle_1 ?? 108;
1433
- params.angle2 = args.angle_2 ?? 162;
1434
- params.angle3 = args.angle_3 ?? 90;
1435
- params.angle4 = args.angle_4 ?? 45;
1436
- }
1437
- const script = await snippetClient.build('applyPixelate', params);
1438
- const result = await runScript(connection, script);
1439
- const r = result;
1440
- const target = r.target_was_copy
1441
- ? `new copy "${r.target_layer_name ?? '?'}"`
1442
- : 'active layer (in place)';
1443
- return {
1444
- content: [
1445
- {
1446
- type: 'text',
1447
- text: `Pixelate (${mode}) applied to ${target}.`,
1448
- },
1449
- ],
1450
- structuredContent: result,
1451
- };
1452
- }
1453
- catch (error) {
1454
- return {
1455
- content: [
1456
- {
1457
- type: 'text',
1458
- text: `Error applying Pixelate: ${error instanceof Error ? error.message : String(error)}`,
1459
- },
1460
- ],
1461
- isError: true,
1462
- };
1463
- }
1271
+ return runSnippetTool({
1272
+ connection,
1273
+ snippetClient,
1274
+ rawArgs,
1275
+ schema: pixelateSchema,
1276
+ snippet: 'applyPixelate',
1277
+ errorPrefix: 'Error applying Pixelate',
1278
+ params: (args) => {
1279
+ const mode = args.mode;
1280
+ const applyToActiveLayer = args.apply_to_active_layer ?? false;
1281
+ const params = { mode, applyToActiveLayer };
1282
+ if (mode === 'mosaic' || mode === 'crystallize' || mode === 'pointillize') {
1283
+ params.cellSize = args.cell_size ?? 10;
1284
+ }
1285
+ else if (mode === 'color_halftone') {
1286
+ params.maxRadius = args.max_radius ?? 8;
1287
+ params.angle1 = args.angle_1 ?? 108;
1288
+ params.angle2 = args.angle_2 ?? 162;
1289
+ params.angle3 = args.angle_3 ?? 90;
1290
+ params.angle4 = args.angle_4 ?? 45;
1291
+ }
1292
+ return params;
1293
+ },
1294
+ successText: (result, args) => {
1295
+ const r = result;
1296
+ const target = r.target_was_copy
1297
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1298
+ : 'active layer (in place)';
1299
+ return `Pixelate (${args.mode}) applied to ${target}.`;
1300
+ },
1301
+ });
1464
1302
  }
1465
1303
  async function applyDistort(connection, snippetClient, rawArgs) {
1466
- try {
1467
- const args = validateArgs(distortSchema, rawArgs);
1468
- const mode = args.mode;
1469
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1470
- const params = { mode, applyToActiveLayer };
1471
- if (mode === 'twirl') {
1472
- params.angle = args.angle ?? 90;
1473
- }
1474
- else if (mode === 'pinch') {
1475
- params.amount = args.amount ?? 50;
1476
- }
1477
- else if (mode === 'spherize') {
1478
- params.amount = args.amount ?? 100;
1479
- }
1480
- else if (mode === 'zigzag') {
1481
- params.amount = args.amount ?? 10;
1482
- params.ridges = args.ridges ?? 5;
1483
- }
1484
- else if (mode === 'ripple') {
1485
- params.amount = args.amount ?? 100;
1486
- params.size = args.size ?? 'medium';
1487
- }
1488
- else if (mode === 'polar') {
1489
- params.conversion = args.conversion ?? 'rect_to_polar';
1490
- }
1491
- else if (mode === 'wave') {
1492
- params.waveType = args.wave_type ?? 'sine';
1493
- params.generators = args.generators ?? 5;
1494
- params.wavelengthMin = args.wavelength_min ?? 10;
1495
- params.wavelengthMax = args.wavelength_max ?? 120;
1496
- params.amplitudeMin = args.amplitude_min ?? 5;
1497
- params.amplitudeMax = args.amplitude_max ?? 35;
1498
- params.scaleHorizontal = args.scale_horizontal ?? 100;
1499
- params.scaleVertical = args.scale_vertical ?? 100;
1500
- params.undefinedAreas = args.undefined_areas ?? 'repeat_edge';
1501
- params.randomSeed = args.random_seed ?? 12345;
1502
- }
1503
- const script = await snippetClient.build('applyDistort', params);
1504
- const result = await runScript(connection, script);
1505
- const r = result;
1506
- const target = r.target_was_copy
1507
- ? `new copy "${r.target_layer_name ?? '?'}"`
1508
- : 'active layer (in place)';
1509
- return {
1510
- content: [
1511
- {
1512
- type: 'text',
1513
- text: `Distort (${mode}) applied to ${target}.`,
1514
- },
1515
- ],
1516
- structuredContent: result,
1517
- };
1518
- }
1519
- catch (error) {
1520
- return {
1521
- content: [
1522
- {
1523
- type: 'text',
1524
- text: `Error applying Distort: ${error instanceof Error ? error.message : String(error)}`,
1525
- },
1526
- ],
1527
- isError: true,
1528
- };
1529
- }
1304
+ return runSnippetTool({
1305
+ connection,
1306
+ snippetClient,
1307
+ rawArgs,
1308
+ schema: distortSchema,
1309
+ snippet: 'applyDistort',
1310
+ errorPrefix: 'Error applying Distort',
1311
+ params: (args) => {
1312
+ const mode = args.mode;
1313
+ const applyToActiveLayer = args.apply_to_active_layer ?? false;
1314
+ const params = { mode, applyToActiveLayer };
1315
+ if (mode === 'twirl') {
1316
+ params.angle = args.angle ?? 90;
1317
+ }
1318
+ else if (mode === 'pinch') {
1319
+ params.amount = args.amount ?? 50;
1320
+ }
1321
+ else if (mode === 'spherize') {
1322
+ params.amount = args.amount ?? 100;
1323
+ }
1324
+ else if (mode === 'zigzag') {
1325
+ params.amount = args.amount ?? 10;
1326
+ params.ridges = args.ridges ?? 5;
1327
+ }
1328
+ else if (mode === 'ripple') {
1329
+ params.amount = args.amount ?? 100;
1330
+ params.size = args.size ?? 'medium';
1331
+ }
1332
+ else if (mode === 'polar') {
1333
+ params.conversion = args.conversion ?? 'rect_to_polar';
1334
+ }
1335
+ else if (mode === 'wave') {
1336
+ params.waveType = args.wave_type ?? 'sine';
1337
+ params.generators = args.generators ?? 5;
1338
+ params.wavelengthMin = args.wavelength_min ?? 10;
1339
+ params.wavelengthMax = args.wavelength_max ?? 120;
1340
+ params.amplitudeMin = args.amplitude_min ?? 5;
1341
+ params.amplitudeMax = args.amplitude_max ?? 35;
1342
+ params.scaleHorizontal = args.scale_horizontal ?? 100;
1343
+ params.scaleVertical = args.scale_vertical ?? 100;
1344
+ params.undefinedAreas = args.undefined_areas ?? 'repeat_edge';
1345
+ params.randomSeed = args.random_seed ?? 12345;
1346
+ }
1347
+ return params;
1348
+ },
1349
+ successText: (result, args) => {
1350
+ const r = result;
1351
+ const target = r.target_was_copy
1352
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1353
+ : 'active layer (in place)';
1354
+ return `Distort (${args.mode}) applied to ${target}.`;
1355
+ },
1356
+ });
1530
1357
  }
1531
1358
  async function applyStylize(connection, snippetClient, rawArgs) {
1532
- try {
1533
- const args = validateArgs(stylizeSchema, rawArgs);
1534
- const mode = args.mode;
1535
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1536
- const params = { mode, applyToActiveLayer };
1537
- if (mode === 'emboss') {
1538
- params.angle = args.angle ?? 135;
1539
- params.height = args.height ?? 3;
1540
- params.amount = args.amount ?? 100;
1541
- }
1542
- else if (mode === 'wind') {
1543
- params.method = args.wind_method ?? 'wind';
1544
- params.direction = args.wind_direction ?? 'left';
1545
- }
1546
- else if (mode === 'trace_contour') {
1547
- params.level = args.level ?? 128;
1548
- params.edge = args.edge ?? 'lower';
1549
- }
1550
- else if (mode === 'tiles') {
1551
- params.number = args.number ?? 10;
1552
- params.offset = args.offset ?? 10;
1553
- }
1554
- const script = await snippetClient.build('applyStylize', params);
1555
- const result = await runScript(connection, script);
1556
- const r = result;
1557
- const target = r.target_was_copy
1558
- ? `new copy "${r.target_layer_name ?? '?'}"`
1559
- : 'active layer (in place)';
1560
- return {
1561
- content: [
1562
- {
1563
- type: 'text',
1564
- text: `Stylize (${mode}) applied to ${target}.`,
1565
- },
1566
- ],
1567
- structuredContent: result,
1568
- };
1569
- }
1570
- catch (error) {
1571
- return {
1572
- content: [
1573
- {
1574
- type: 'text',
1575
- text: `Error applying Stylize: ${error instanceof Error ? error.message : String(error)}`,
1576
- },
1577
- ],
1578
- isError: true,
1579
- };
1580
- }
1359
+ return runSnippetTool({
1360
+ connection,
1361
+ snippetClient,
1362
+ rawArgs,
1363
+ schema: stylizeSchema,
1364
+ snippet: 'applyStylize',
1365
+ errorPrefix: 'Error applying Stylize',
1366
+ params: (args) => {
1367
+ const mode = args.mode;
1368
+ const applyToActiveLayer = args.apply_to_active_layer ?? false;
1369
+ const params = { mode, applyToActiveLayer };
1370
+ if (mode === 'emboss') {
1371
+ params.angle = args.angle ?? 135;
1372
+ params.height = args.height ?? 3;
1373
+ params.amount = args.amount ?? 100;
1374
+ }
1375
+ else if (mode === 'wind') {
1376
+ params.method = args.wind_method ?? 'wind';
1377
+ params.direction = args.wind_direction ?? 'left';
1378
+ }
1379
+ else if (mode === 'trace_contour') {
1380
+ params.level = args.level ?? 128;
1381
+ params.edge = args.edge ?? 'lower';
1382
+ }
1383
+ else if (mode === 'tiles') {
1384
+ params.number = args.number ?? 10;
1385
+ params.offset = args.offset ?? 10;
1386
+ }
1387
+ return params;
1388
+ },
1389
+ successText: (result, args) => {
1390
+ const r = result;
1391
+ const target = r.target_was_copy
1392
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1393
+ : 'active layer (in place)';
1394
+ return `Stylize (${args.mode}) applied to ${target}.`;
1395
+ },
1396
+ });
1581
1397
  }
1582
1398
  async function applyRender(connection, snippetClient, rawArgs) {
1583
- try {
1584
- const args = validateArgs(renderSchema, rawArgs);
1585
- const mode = args.mode;
1586
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1587
- const params = { mode, applyToActiveLayer };
1588
- if (mode === 'fibers') {
1589
- params.variance = args.variance ?? 16;
1590
- params.strength = args.fiber_strength ?? 4;
1591
- params.seed = args.seed ?? 12345;
1592
- }
1593
- const script = await snippetClient.build('applyRender', params);
1594
- const result = await runScript(connection, script);
1595
- const r = result;
1596
- const target = r.target_was_copy
1597
- ? `new copy "${r.target_layer_name ?? '?'}"`
1598
- : 'active layer (in place)';
1599
- return {
1600
- content: [
1601
- {
1602
- type: 'text',
1603
- text: `Render (${mode}) applied to ${target}.`,
1604
- },
1605
- ],
1606
- structuredContent: result,
1607
- };
1608
- }
1609
- catch (error) {
1610
- return {
1611
- content: [
1612
- {
1613
- type: 'text',
1614
- text: `Error applying Render: ${error instanceof Error ? error.message : String(error)}`,
1615
- },
1616
- ],
1617
- isError: true,
1618
- };
1619
- }
1399
+ return runSnippetTool({
1400
+ connection,
1401
+ snippetClient,
1402
+ rawArgs,
1403
+ schema: renderSchema,
1404
+ snippet: 'applyRender',
1405
+ errorPrefix: 'Error applying Render',
1406
+ params: (args) => {
1407
+ const mode = args.mode;
1408
+ const applyToActiveLayer = args.apply_to_active_layer ?? false;
1409
+ const params = { mode, applyToActiveLayer };
1410
+ if (mode === 'fibers') {
1411
+ params.variance = args.variance ?? 16;
1412
+ params.strength = args.fiber_strength ?? 4;
1413
+ params.seed = args.seed ?? 12345;
1414
+ }
1415
+ return params;
1416
+ },
1417
+ successText: (result, args) => {
1418
+ const r = result;
1419
+ const target = r.target_was_copy
1420
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1421
+ : 'active layer (in place)';
1422
+ return `Render (${args.mode}) applied to ${target}.`;
1423
+ },
1424
+ });
1620
1425
  }
1621
1426
  async function applyOther(connection, snippetClient, rawArgs) {
1622
- try {
1623
- const args = validateArgs(otherSchema, rawArgs);
1624
- const mode = args.mode;
1625
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1626
- const params = { mode, applyToActiveLayer };
1627
- if (mode === 'maximum' || mode === 'minimum') {
1628
- params.radius = args.radius ?? 3;
1629
- params.preserve = args.preserve ?? 'roundness';
1630
- }
1631
- else if (mode === 'offset') {
1632
- params.horizontal = args.horizontal ?? 0;
1633
- params.vertical = args.vertical ?? 0;
1634
- }
1635
- const script = await snippetClient.build('applyOther', params);
1636
- const result = await runScript(connection, script);
1637
- const r = result;
1638
- const target = r.target_was_copy
1639
- ? `new copy "${r.target_layer_name ?? '?'}"`
1640
- : 'active layer (in place)';
1641
- return {
1642
- content: [{ type: 'text', text: `Other filter (${mode}) applied to ${target}.` }],
1643
- structuredContent: result,
1644
- };
1645
- }
1646
- catch (error) {
1647
- return {
1648
- content: [
1649
- {
1650
- type: 'text',
1651
- text: `Error applying filter: ${error instanceof Error ? error.message : String(error)}`,
1652
- },
1653
- ],
1654
- isError: true,
1655
- };
1656
- }
1427
+ return runSnippetTool({
1428
+ connection,
1429
+ snippetClient,
1430
+ rawArgs,
1431
+ schema: otherSchema,
1432
+ snippet: 'applyOther',
1433
+ errorPrefix: 'Error applying filter',
1434
+ params: (args) => {
1435
+ const mode = args.mode;
1436
+ const applyToActiveLayer = args.apply_to_active_layer ?? false;
1437
+ const params = { mode, applyToActiveLayer };
1438
+ if (mode === 'maximum' || mode === 'minimum') {
1439
+ params.radius = args.radius ?? 3;
1440
+ params.preserve = args.preserve ?? 'roundness';
1441
+ }
1442
+ else if (mode === 'offset') {
1443
+ params.horizontal = args.horizontal ?? 0;
1444
+ params.vertical = args.vertical ?? 0;
1445
+ }
1446
+ return params;
1447
+ },
1448
+ successText: (result, args) => {
1449
+ const r = result;
1450
+ const target = r.target_was_copy
1451
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1452
+ : 'active layer (in place)';
1453
+ return `Other filter (${args.mode}) applied to ${target}.`;
1454
+ },
1455
+ });
1657
1456
  }
1658
1457
  async function applyDenoise(connection, snippetClient, rawArgs) {
1659
- try {
1660
- const args = validateArgs(denoiseSchema, rawArgs);
1661
- const mode = args.mode;
1662
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1663
- const params = { mode, applyToActiveLayer };
1664
- if (mode === 'median') {
1665
- params.radius = args.radius ?? 4;
1666
- }
1667
- else if (mode === 'dust_and_scratches') {
1668
- params.radius = args.radius ?? 3;
1669
- params.threshold = args.threshold ?? 10;
1670
- }
1671
- const script = await snippetClient.build('applyDenoise', params);
1672
- const result = await runScript(connection, script);
1673
- const r = result;
1674
- const target = r.target_was_copy
1675
- ? `new copy "${r.target_layer_name ?? '?'}"`
1676
- : 'active layer (in place)';
1677
- return {
1678
- content: [{ type: 'text', text: `Noise reduction (${mode}) applied to ${target}.` }],
1679
- structuredContent: result,
1680
- };
1681
- }
1682
- catch (error) {
1683
- return {
1684
- content: [
1685
- {
1686
- type: 'text',
1687
- text: `Error applying noise reduction: ${error instanceof Error ? error.message : String(error)}`,
1688
- },
1689
- ],
1690
- isError: true,
1691
- };
1692
- }
1458
+ return runSnippetTool({
1459
+ connection,
1460
+ snippetClient,
1461
+ rawArgs,
1462
+ schema: denoiseSchema,
1463
+ snippet: 'applyDenoise',
1464
+ errorPrefix: 'Error applying noise reduction',
1465
+ params: (args) => {
1466
+ const mode = args.mode;
1467
+ const applyToActiveLayer = args.apply_to_active_layer ?? false;
1468
+ const params = { mode, applyToActiveLayer };
1469
+ if (mode === 'median') {
1470
+ params.radius = args.radius ?? 4;
1471
+ }
1472
+ else if (mode === 'dust_and_scratches') {
1473
+ params.radius = args.radius ?? 3;
1474
+ params.threshold = args.threshold ?? 10;
1475
+ }
1476
+ return params;
1477
+ },
1478
+ successText: (result, args) => {
1479
+ const r = result;
1480
+ const target = r.target_was_copy
1481
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1482
+ : 'active layer (in place)';
1483
+ return `Noise reduction (${args.mode}) applied to ${target}.`;
1484
+ },
1485
+ });
1693
1486
  }
1694
1487
  async function applyBlurAdv(connection, snippetClient, rawArgs) {
1695
- try {
1696
- const args = validateArgs(blurAdvSchema, rawArgs);
1697
- const mode = args.mode;
1698
- const applyToActiveLayer = args.apply_to_active_layer ?? false;
1699
- const params = { mode, applyToActiveLayer };
1700
- if (mode === 'surface_blur') {
1701
- params.radius = args.radius ?? 15;
1702
- params.threshold = args.threshold ?? 20;
1703
- }
1704
- else if (mode === 'box_blur') {
1705
- params.radius = args.radius ?? 12;
1706
- }
1707
- const script = await snippetClient.build('applyBlurAdv', params);
1708
- const result = await runScript(connection, script);
1709
- const r = result;
1710
- const target = r.target_was_copy
1711
- ? `new copy "${r.target_layer_name ?? '?'}"`
1712
- : 'active layer (in place)';
1713
- return {
1714
- content: [{ type: 'text', text: `Blur (${mode}) applied to ${target}.` }],
1715
- structuredContent: result,
1716
- };
1717
- }
1718
- catch (error) {
1719
- return {
1720
- content: [
1721
- {
1722
- type: 'text',
1723
- text: `Error applying blur: ${error instanceof Error ? error.message : String(error)}`,
1724
- },
1725
- ],
1726
- isError: true,
1727
- };
1728
- }
1488
+ return runSnippetTool({
1489
+ connection,
1490
+ snippetClient,
1491
+ rawArgs,
1492
+ schema: blurAdvSchema,
1493
+ snippet: 'applyBlurAdv',
1494
+ errorPrefix: 'Error applying blur',
1495
+ params: (args) => {
1496
+ const mode = args.mode;
1497
+ const applyToActiveLayer = args.apply_to_active_layer ?? false;
1498
+ const params = { mode, applyToActiveLayer };
1499
+ if (mode === 'surface_blur') {
1500
+ params.radius = args.radius ?? 15;
1501
+ params.threshold = args.threshold ?? 20;
1502
+ }
1503
+ else if (mode === 'box_blur') {
1504
+ params.radius = args.radius ?? 12;
1505
+ }
1506
+ return params;
1507
+ },
1508
+ successText: (result, args) => {
1509
+ const r = result;
1510
+ const target = r.target_was_copy
1511
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1512
+ : 'active layer (in place)';
1513
+ return `Blur (${args.mode}) applied to ${target}.`;
1514
+ },
1515
+ });
1729
1516
  }
1730
1517
  async function applyOilPaint(connection, snippetClient, rawArgs) {
1731
- try {
1732
- const args = validateArgs(oilPaintSchema, rawArgs);
1733
- const params = {
1518
+ return runSnippetTool({
1519
+ connection,
1520
+ snippetClient,
1521
+ rawArgs,
1522
+ schema: oilPaintSchema,
1523
+ snippet: 'applyOilPaint',
1524
+ errorPrefix: 'Error applying Oil Paint',
1525
+ params: (args) => ({
1734
1526
  stylization: args.stylization ?? 4,
1735
1527
  cleanliness: args.cleanliness ?? 2.3,
1736
1528
  brushScale: args.brush_scale ?? 0.8,
@@ -1739,71 +1531,38 @@ async function applyOilPaint(connection, snippetClient, rawArgs) {
1739
1531
  shine: args.shine ?? 1.3,
1740
1532
  lightingOn: args.lighting_on ?? true,
1741
1533
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1742
- };
1743
- const script = await snippetClient.build('applyOilPaint', params);
1744
- const result = await runScript(connection, script);
1745
- const r = result;
1746
- const target = r.target_was_copy
1747
- ? `new copy "${r.target_layer_name ?? '?'}"`
1748
- : 'active layer (in place)';
1749
- return {
1750
- content: [
1751
- {
1752
- type: 'text',
1753
- text: `Oil Paint applied to ${target}.`,
1754
- },
1755
- ],
1756
- structuredContent: result,
1757
- };
1758
- }
1759
- catch (error) {
1760
- return {
1761
- content: [
1762
- {
1763
- type: 'text',
1764
- text: `Error applying Oil Paint: ${error instanceof Error ? error.message : String(error)}`,
1765
- },
1766
- ],
1767
- isError: true,
1768
- };
1769
- }
1534
+ }),
1535
+ successText: (result) => {
1536
+ const r = result;
1537
+ const target = r.target_was_copy
1538
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1539
+ : 'active layer (in place)';
1540
+ return `Oil Paint applied to ${target}.`;
1541
+ },
1542
+ });
1770
1543
  }
1771
1544
  async function applyDisplace(connection, snippetClient, rawArgs) {
1772
- try {
1773
- const args = validateArgs(displaceSchema, rawArgs);
1774
- const params = {
1545
+ return runSnippetTool({
1546
+ connection,
1547
+ snippetClient,
1548
+ rawArgs,
1549
+ schema: displaceSchema,
1550
+ snippet: 'applyDisplace',
1551
+ errorPrefix: 'Error applying Displace',
1552
+ params: (args) => ({
1775
1553
  mapPath: args.map_path,
1776
1554
  horizontalScale: args.horizontal_scale ?? 10,
1777
1555
  verticalScale: args.vertical_scale ?? 10,
1778
1556
  displacementMap: args.displacement_map ?? 'stretch_to_fit',
1779
1557
  undefinedAreas: args.undefined_areas ?? 'repeat_edge',
1780
1558
  applyToActiveLayer: args.apply_to_active_layer ?? false,
1781
- };
1782
- const script = await snippetClient.build('applyDisplace', params);
1783
- const result = await runScript(connection, script);
1784
- const r = result;
1785
- const target = r.target_was_copy
1786
- ? `new copy "${r.target_layer_name ?? '?'}"`
1787
- : 'active layer (in place)';
1788
- return {
1789
- content: [
1790
- {
1791
- type: 'text',
1792
- text: `Displace applied to ${target} using map ${params.mapPath}.`,
1793
- },
1794
- ],
1795
- structuredContent: result,
1796
- };
1797
- }
1798
- catch (error) {
1799
- return {
1800
- content: [
1801
- {
1802
- type: 'text',
1803
- text: `Error applying Displace: ${error instanceof Error ? error.message : String(error)}`,
1804
- },
1805
- ],
1806
- isError: true,
1807
- };
1808
- }
1559
+ }),
1560
+ successText: (result, args) => {
1561
+ const r = result;
1562
+ const target = r.target_was_copy
1563
+ ? `new copy "${r.target_layer_name ?? '?'}"`
1564
+ : 'active layer (in place)';
1565
+ return `Displace applied to ${target} using map ${args.map_path}.`;
1566
+ },
1567
+ });
1809
1568
  }