#
tokens: 47095/50000 3/71 files (page 3/6)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 3 of 6. Use http://codebase.md/mikechambers/adb-mcp?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .gitattributes
├── .gitignore
├── adb-proxy-socket
│   ├── .gitignore
│   ├── package-lock.json
│   ├── package.json
│   ├── proxy.js
│   └── README.md
├── cep
│   ├── com.mikechambers.ae
│   │   ├── .debug
│   │   ├── commands.js
│   │   ├── CSXS
│   │   │   └── manifest.xml
│   │   ├── index.html
│   │   ├── jsx
│   │   │   └── json-polyfill.jsx
│   │   ├── lib
│   │   │   └── CSInterface.js
│   │   ├── main.js
│   │   └── style.css
│   └── com.mikechambers.ai
│       ├── .debug
│       ├── commands.js
│       ├── CSXS
│       │   └── manifest.xml
│       ├── index.html
│       ├── jsx
│       │   ├── json-polyfill.jsx
│       │   └── utils.jsx
│       ├── lib
│       │   └── CSInterface.js
│       ├── main.js
│       └── style.css
├── dxt
│   ├── build
│   ├── pr
│   │   └── manifest.json
│   └── ps
│       └── manifest.json
├── images
│   └── claud-attach-mcp.png
├── LICENSE.md
├── mcp
│   ├── .gitignore
│   ├── ae-mcp.py
│   ├── ai-mcp.py
│   ├── core.py
│   ├── fonts.py
│   ├── id-mcp.py
│   ├── logger.py
│   ├── pr-mcp.py
│   ├── ps-batch-play.py
│   ├── ps-mcp.py
│   ├── pyproject.toml
│   ├── requirements.txt
│   ├── socket_client.py
│   └── uv.lock
├── package-lock.json
├── README.md
└── uxp
    ├── id
    │   ├── commands
    │   │   └── index.js
    │   ├── icons
    │   │   ├── [email protected]
    │   │   ├── [email protected]
    │   │   ├── [email protected]
    │   │   └── [email protected]
    │   ├── index.html
    │   ├── LICENSE
    │   ├── main.js
    │   ├── manifest.json
    │   ├── package.json
    │   ├── socket.io.js
    │   └── style.css
    ├── pr
    │   ├── commands
    │   │   ├── consts.js
    │   │   ├── core.js
    │   │   ├── index.js
    │   │   └── utils.js
    │   ├── icons
    │   │   ├── [email protected]
    │   │   ├── [email protected]
    │   │   ├── [email protected]
    │   │   └── [email protected]
    │   ├── index.html
    │   ├── LICENSE
    │   ├── main.js
    │   ├── manifest.json
    │   ├── package.json
    │   ├── socket.io.js
    │   └── style.css
    └── ps
        ├── commands
        │   ├── adjustment_layers.js
        │   ├── core.js
        │   ├── filters.js
        │   ├── index.js
        │   ├── layer_styles.js
        │   ├── layers.js
        │   ├── selection.js
        │   └── utils.js
        ├── icons
        │   ├── [email protected]
        │   ├── [email protected]
        │   ├── [email protected]
        │   └── [email protected]
        ├── index.html
        ├── LICENSE
        ├── main.js
        ├── manifest.json
        ├── package.json
        ├── socket.io.js
        └── style.css
```

# Files

--------------------------------------------------------------------------------
/cep/com.mikechambers.ae/lib/CSInterface.js:
--------------------------------------------------------------------------------

```javascript
   1 | /**************************************************************************************************
   2 | *
   3 | * ADOBE SYSTEMS INCORPORATED
   4 | * Copyright 2020 Adobe Systems Incorporated
   5 | * All Rights Reserved.
   6 | *
   7 | * NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the
   8 | * terms of the Adobe license agreement accompanying it.  If you have received this file from a
   9 | * source other than Adobe, then your use, modification, or distribution of it requires the prior
  10 | * written permission of Adobe.
  11 | *
  12 | **************************************************************************************************/
  13 | 
  14 | /** CSInterface - v12.0.0 */
  15 | 
  16 | /**
  17 |  * Stores constants for the window types supported by the CSXS infrastructure.
  18 |  */
  19 | function CSXSWindowType()
  20 | {
  21 | }
  22 | 
  23 | /** Constant for the CSXS window type Panel. */
  24 | CSXSWindowType._PANEL = "Panel";
  25 | 
  26 | /** Constant for the CSXS window type Modeless. */
  27 | CSXSWindowType._MODELESS = "Modeless";
  28 | 
  29 | /** Constant for the CSXS window type ModalDialog. */
  30 | CSXSWindowType._MODAL_DIALOG = "ModalDialog";
  31 | 
  32 | /** EvalScript error message */
  33 | EvalScript_ErrMessage = "EvalScript error.";
  34 | 
  35 | /**
  36 |  * @class Version
  37 |  * Defines a version number with major, minor, micro, and special
  38 |  * components. The major, minor and micro values are numeric; the special
  39 |  * value can be any string.
  40 |  *
  41 |  * @param major   The major version component, a positive integer up to nine digits long.
  42 |  * @param minor   The minor version component, a positive integer up to nine digits long.
  43 |  * @param micro   The micro version component, a positive integer up to nine digits long.
  44 |  * @param special The special version component, an arbitrary string.
  45 |  *
  46 |  * @return A new \c Version object.
  47 |  */
  48 | function Version(major, minor, micro, special)
  49 | {
  50 |     this.major = major;
  51 |     this.minor = minor;
  52 |     this.micro = micro;
  53 |     this.special = special;
  54 | }
  55 | 
  56 | /**
  57 |  * The maximum value allowed for a numeric version component.
  58 |  * This reflects the maximum value allowed in PlugPlug and the manifest schema.
  59 |  */
  60 | Version.MAX_NUM = 999999999;
  61 | 
  62 | /**
  63 |  * @class VersionBound
  64 |  * Defines a boundary for a version range, which associates a \c Version object
  65 |  * with a flag for whether it is an inclusive or exclusive boundary.
  66 |  *
  67 |  * @param version   The \c #Version object.
  68 |  * @param inclusive True if this boundary is inclusive, false if it is exclusive.
  69 |  *
  70 |  * @return A new \c VersionBound object.
  71 |  */
  72 | function VersionBound(version, inclusive)
  73 | {
  74 |     this.version = version;
  75 |     this.inclusive = inclusive;
  76 | }
  77 | 
  78 | /**
  79 |  * @class VersionRange
  80 |  * Defines a range of versions using a lower boundary and optional upper boundary.
  81 |  *
  82 |  * @param lowerBound The \c #VersionBound object.
  83 |  * @param upperBound The \c #VersionBound object, or null for a range with no upper boundary.
  84 |  *
  85 |  * @return A new \c VersionRange object.
  86 |  */
  87 | function VersionRange(lowerBound, upperBound)
  88 | {
  89 |     this.lowerBound = lowerBound;
  90 |     this.upperBound = upperBound;
  91 | }
  92 | 
  93 | /**
  94 |  * @class Runtime
  95 |  * Represents a runtime related to the CEP infrastructure.
  96 |  * Extensions can declare dependencies on particular
  97 |  * CEP runtime versions in the extension manifest.
  98 |  *
  99 |  * @param name    The runtime name.
 100 |  * @param version A \c #VersionRange object that defines a range of valid versions.
 101 |  *
 102 |  * @return A new \c Runtime object.
 103 |  */
 104 | function Runtime(name, versionRange)
 105 | {
 106 |     this.name = name;
 107 |     this.versionRange = versionRange;
 108 | }
 109 | 
 110 | /**
 111 | * @class Extension
 112 | * Encapsulates a CEP-based extension to an Adobe application.
 113 | *
 114 | * @param id              The unique identifier of this extension.
 115 | * @param name            The localizable display name of this extension.
 116 | * @param mainPath        The path of the "index.html" file.
 117 | * @param basePath        The base path of this extension.
 118 | * @param windowType          The window type of the main window of this extension.
 119 |                  Valid values are defined by \c #CSXSWindowType.
 120 | * @param width           The default width in pixels of the main window of this extension.
 121 | * @param height          The default height in pixels of the main window of this extension.
 122 | * @param minWidth        The minimum width in pixels of the main window of this extension.
 123 | * @param minHeight       The minimum height in pixels of the main window of this extension.
 124 | * @param maxWidth        The maximum width in pixels of the main window of this extension.
 125 | * @param maxHeight       The maximum height in pixels of the main window of this extension.
 126 | * @param defaultExtensionDataXml The extension data contained in the default \c ExtensionDispatchInfo section of the extension manifest.
 127 | * @param specialExtensionDataXml The extension data contained in the application-specific \c ExtensionDispatchInfo section of the extension manifest.
 128 | * @param requiredRuntimeList     An array of \c Runtime objects for runtimes required by this extension.
 129 | * @param isAutoVisible       True if this extension is visible on loading.
 130 | * @param isPluginExtension   True if this extension has been deployed in the Plugins folder of the host application.
 131 | *
 132 | * @return A new \c Extension object.
 133 | */
 134 | function Extension(id, name, mainPath, basePath, windowType, width, height, minWidth, minHeight, maxWidth, maxHeight,
 135 |                    defaultExtensionDataXml, specialExtensionDataXml, requiredRuntimeList, isAutoVisible, isPluginExtension)
 136 | {
 137 |     this.id = id;
 138 |     this.name = name;
 139 |     this.mainPath = mainPath;
 140 |     this.basePath = basePath;
 141 |     this.windowType = windowType;
 142 |     this.width = width;
 143 |     this.height = height;
 144 |     this.minWidth = minWidth;
 145 |     this.minHeight = minHeight;
 146 |     this.maxWidth = maxWidth;
 147 |     this.maxHeight = maxHeight;
 148 |     this.defaultExtensionDataXml = defaultExtensionDataXml;
 149 |     this.specialExtensionDataXml = specialExtensionDataXml;
 150 |     this.requiredRuntimeList = requiredRuntimeList;
 151 |     this.isAutoVisible = isAutoVisible;
 152 |     this.isPluginExtension = isPluginExtension;
 153 | }
 154 | 
 155 | /**
 156 |  * @class CSEvent
 157 |  * A standard JavaScript event, the base class for CEP events.
 158 |  *
 159 |  * @param type        The name of the event type.
 160 |  * @param scope       The scope of event, can be "GLOBAL" or "APPLICATION".
 161 |  * @param appId       The unique identifier of the application that generated the event.
 162 |  * @param extensionId     The unique identifier of the extension that generated the event.
 163 |  *
 164 |  * @return A new \c CSEvent object
 165 |  */
 166 | function CSEvent(type, scope, appId, extensionId)
 167 | {
 168 |     this.type = type;
 169 |     this.scope = scope;
 170 |     this.appId = appId;
 171 |     this.extensionId = extensionId;
 172 | }
 173 | 
 174 | /** Event-specific data. */
 175 | CSEvent.prototype.data = "";
 176 | 
 177 | /**
 178 |  * @class SystemPath
 179 |  * Stores operating-system-specific location constants for use in the
 180 |  * \c #CSInterface.getSystemPath() method.
 181 |  * @return A new \c SystemPath object.
 182 |  */
 183 | function SystemPath()
 184 | {
 185 | }
 186 | 
 187 | /** The path to user data.  */
 188 | SystemPath.USER_DATA = "userData";
 189 | 
 190 | /** The path to common files for Adobe applications.  */
 191 | SystemPath.COMMON_FILES = "commonFiles";
 192 | 
 193 | /** The path to the user's default document folder.  */
 194 | SystemPath.MY_DOCUMENTS = "myDocuments";
 195 | 
 196 | /** @deprecated. Use \c #SystemPath.Extension.  */
 197 | SystemPath.APPLICATION = "application";
 198 | 
 199 | /** The path to current extension.  */
 200 | SystemPath.EXTENSION = "extension";
 201 | 
 202 | /** The path to hosting application's executable.  */
 203 | SystemPath.HOST_APPLICATION = "hostApplication";
 204 | 
 205 | /**
 206 |  * @class ColorType
 207 |  * Stores color-type constants.
 208 |  */
 209 | function ColorType()
 210 | {
 211 | }
 212 | 
 213 | /** RGB color type. */
 214 | ColorType.RGB = "rgb";
 215 | 
 216 | /** Gradient color type. */
 217 | ColorType.GRADIENT = "gradient";
 218 | 
 219 | /** Null color type. */
 220 | ColorType.NONE = "none";
 221 | 
 222 | /**
 223 |  * @class RGBColor
 224 |  * Stores an RGB color with red, green, blue, and alpha values.
 225 |  * All values are in the range [0.0 to 255.0]. Invalid numeric values are
 226 |  * converted to numbers within this range.
 227 |  *
 228 |  * @param red   The red value, in the range [0.0 to 255.0].
 229 |  * @param green The green value, in the range [0.0 to 255.0].
 230 |  * @param blue  The blue value, in the range [0.0 to 255.0].
 231 |  * @param alpha The alpha (transparency) value, in the range [0.0 to 255.0].
 232 |  *      The default, 255.0, means that the color is fully opaque.
 233 |  *
 234 |  * @return A new RGBColor object.
 235 |  */
 236 | function RGBColor(red, green, blue, alpha)
 237 | {
 238 |     this.red = red;
 239 |     this.green = green;
 240 |     this.blue = blue;
 241 |     this.alpha = alpha;
 242 | }
 243 | 
 244 | /**
 245 |  * @class Direction
 246 |  * A point value  in which the y component is 0 and the x component
 247 |  * is positive or negative for a right or left direction,
 248 |  * or the x component is 0 and the y component is positive or negative for
 249 |  * an up or down direction.
 250 |  *
 251 |  * @param x     The horizontal component of the point.
 252 |  * @param y     The vertical component of the point.
 253 |  *
 254 |  * @return A new \c Direction object.
 255 |  */
 256 | function Direction(x, y)
 257 | {
 258 |     this.x = x;
 259 |     this.y = y;
 260 | }
 261 | 
 262 | /**
 263 |  * @class GradientStop
 264 |  * Stores gradient stop information.
 265 |  *
 266 |  * @param offset   The offset of the gradient stop, in the range [0.0 to 1.0].
 267 |  * @param rgbColor The color of the gradient at this point, an \c #RGBColor object.
 268 |  *
 269 |  * @return GradientStop object.
 270 |  */
 271 | function GradientStop(offset, rgbColor)
 272 | {
 273 |     this.offset = offset;
 274 |     this.rgbColor = rgbColor;
 275 | }
 276 | 
 277 | /**
 278 |  * @class GradientColor
 279 |  * Stores gradient color information.
 280 |  *
 281 |  * @param type          The gradient type, must be "linear".
 282 |  * @param direction     A \c #Direction object for the direction of the gradient
 283 |                 (up, down, right, or left).
 284 |  * @param numStops          The number of stops in the gradient.
 285 |  * @param gradientStopList  An array of \c #GradientStop objects.
 286 |  *
 287 |  * @return A new \c GradientColor object.
 288 |  */
 289 | function GradientColor(type, direction, numStops, arrGradientStop)
 290 | {
 291 |     this.type = type;
 292 |     this.direction = direction;
 293 |     this.numStops = numStops;
 294 |     this.arrGradientStop = arrGradientStop;
 295 | }
 296 | 
 297 | /**
 298 |  * @class UIColor
 299 |  * Stores color information, including the type, anti-alias level, and specific color
 300 |  * values in a color object of an appropriate type.
 301 |  *
 302 |  * @param type          The color type, 1 for "rgb" and 2 for "gradient".
 303 |                 The supplied color object must correspond to this type.
 304 |  * @param antialiasLevel    The anti-alias level constant.
 305 |  * @param color         A \c #RGBColor or \c #GradientColor object containing specific color information.
 306 |  *
 307 |  * @return A new \c UIColor object.
 308 |  */
 309 | function UIColor(type, antialiasLevel, color)
 310 | {
 311 |     this.type = type;
 312 |     this.antialiasLevel = antialiasLevel;
 313 |     this.color = color;
 314 | }
 315 | 
 316 | /**
 317 |  * @class AppSkinInfo
 318 |  * Stores window-skin properties, such as color and font. All color parameter values are \c #UIColor objects except that systemHighlightColor is \c #RGBColor object.
 319 |  *
 320 |  * @param baseFontFamily        The base font family of the application.
 321 |  * @param baseFontSize          The base font size of the application.
 322 |  * @param appBarBackgroundColor     The application bar background color.
 323 |  * @param panelBackgroundColor      The background color of the extension panel.
 324 |  * @param appBarBackgroundColorSRGB     The application bar background color, as sRGB.
 325 |  * @param panelBackgroundColorSRGB      The background color of the extension panel, as sRGB.
 326 |  * @param systemHighlightColor          The highlight color of the extension panel, if provided by the host application. Otherwise, the operating-system highlight color.
 327 |  *
 328 |  * @return AppSkinInfo object.
 329 |  */
 330 | function AppSkinInfo(baseFontFamily, baseFontSize, appBarBackgroundColor, panelBackgroundColor, appBarBackgroundColorSRGB, panelBackgroundColorSRGB, systemHighlightColor)
 331 | {
 332 |     this.baseFontFamily = baseFontFamily;
 333 |     this.baseFontSize = baseFontSize;
 334 |     this.appBarBackgroundColor = appBarBackgroundColor;
 335 |     this.panelBackgroundColor = panelBackgroundColor;
 336 |     this.appBarBackgroundColorSRGB = appBarBackgroundColorSRGB;
 337 |     this.panelBackgroundColorSRGB = panelBackgroundColorSRGB;
 338 |     this.systemHighlightColor = systemHighlightColor;
 339 | }
 340 | 
 341 | /**
 342 |  * @class HostEnvironment
 343 |  * Stores information about the environment in which the extension is loaded.
 344 |  *
 345 |  * @param appName   The application's name.
 346 |  * @param appVersion    The application's version.
 347 |  * @param appLocale The application's current license locale.
 348 |  * @param appUILocale   The application's current UI locale.
 349 |  * @param appId     The application's unique identifier.
 350 |  * @param isAppOnline  True if the application is currently online.
 351 |  * @param appSkinInfo   An \c #AppSkinInfo object containing the application's default color and font styles.
 352 |  *
 353 |  * @return A new \c HostEnvironment object.
 354 |  */
 355 | function HostEnvironment(appName, appVersion, appLocale, appUILocale, appId, isAppOnline, appSkinInfo)
 356 | {
 357 |     this.appName = appName;
 358 |     this.appVersion = appVersion;
 359 |     this.appLocale = appLocale;
 360 |     this.appUILocale = appUILocale;
 361 |     this.appId = appId;
 362 |     this.isAppOnline = isAppOnline;
 363 |     this.appSkinInfo = appSkinInfo;
 364 | }
 365 | 
 366 | /**
 367 |  * @class HostCapabilities
 368 |  * Stores information about the host capabilities.
 369 |  *
 370 |  * @param EXTENDED_PANEL_MENU True if the application supports panel menu.
 371 |  * @param EXTENDED_PANEL_ICONS True if the application supports panel icon.
 372 |  * @param DELEGATE_APE_ENGINE True if the application supports delegated APE engine.
 373 |  * @param SUPPORT_HTML_EXTENSIONS True if the application supports HTML extensions.
 374 |  * @param DISABLE_FLASH_EXTENSIONS True if the application disables FLASH extensions.
 375 |  *
 376 |  * @return A new \c HostCapabilities object.
 377 |  */
 378 | function HostCapabilities(EXTENDED_PANEL_MENU, EXTENDED_PANEL_ICONS, DELEGATE_APE_ENGINE, SUPPORT_HTML_EXTENSIONS, DISABLE_FLASH_EXTENSIONS)
 379 | {
 380 |     this.EXTENDED_PANEL_MENU = EXTENDED_PANEL_MENU;
 381 |     this.EXTENDED_PANEL_ICONS = EXTENDED_PANEL_ICONS;
 382 |     this.DELEGATE_APE_ENGINE = DELEGATE_APE_ENGINE;
 383 |     this.SUPPORT_HTML_EXTENSIONS = SUPPORT_HTML_EXTENSIONS;
 384 |     this.DISABLE_FLASH_EXTENSIONS = DISABLE_FLASH_EXTENSIONS; // Since 5.0.0
 385 | }
 386 | 
 387 | /**
 388 |  * @class ApiVersion
 389 |  * Stores current api version.
 390 |  *
 391 |  * Since 4.2.0
 392 |  *
 393 |  * @param major  The major version
 394 |  * @param minor  The minor version.
 395 |  * @param micro  The micro version.
 396 |  *
 397 |  * @return ApiVersion object.
 398 |  */
 399 | function ApiVersion(major, minor, micro)
 400 | {
 401 |     this.major = major;
 402 |     this.minor = minor;
 403 |     this.micro = micro;
 404 | }
 405 | 
 406 | /**
 407 |  * @class MenuItemStatus
 408 |  * Stores flyout menu item status
 409 |  *
 410 |  * Since 5.2.0
 411 |  *
 412 |  * @param menuItemLabel  The menu item label.
 413 |  * @param enabled        True if user wants to enable the menu item.
 414 |  * @param checked        True if user wants to check the menu item.
 415 |  *
 416 |  * @return MenuItemStatus object.
 417 |  */
 418 | function MenuItemStatus(menuItemLabel, enabled, checked)
 419 | {
 420 |     this.menuItemLabel = menuItemLabel;
 421 |     this.enabled = enabled;
 422 |     this.checked = checked;
 423 | }
 424 | 
 425 | /**
 426 |  * @class ContextMenuItemStatus
 427 |  * Stores the status of the context menu item.
 428 |  *
 429 |  * Since 5.2.0
 430 |  *
 431 |  * @param menuItemID     The menu item id.
 432 |  * @param enabled        True if user wants to enable the menu item.
 433 |  * @param checked        True if user wants to check the menu item.
 434 |  *
 435 |  * @return MenuItemStatus object.
 436 |  */
 437 | function ContextMenuItemStatus(menuItemID, enabled, checked)
 438 | {
 439 |     this.menuItemID = menuItemID;
 440 |     this.enabled = enabled;
 441 |     this.checked = checked;
 442 | }
 443 | //------------------------------ CSInterface ----------------------------------
 444 | 
 445 | /**
 446 |  * @class CSInterface
 447 |  * This is the entry point to the CEP extensibility infrastructure.
 448 |  * Instantiate this object and use it to:
 449 |  * <ul>
 450 |  * <li>Access information about the host application in which an extension is running</li>
 451 |  * <li>Launch an extension</li>
 452 |  * <li>Register interest in event notifications, and dispatch events</li>
 453 |  * </ul>
 454 |  *
 455 |  * @return A new \c CSInterface object
 456 |  */
 457 | function CSInterface()
 458 | {
 459 | }
 460 | 
 461 | /**
 462 |  * User can add this event listener to handle native application theme color changes.
 463 |  * Callback function gives extensions ability to fine-tune their theme color after the
 464 |  * global theme color has been changed.
 465 |  * The callback function should be like below:
 466 |  *
 467 |  * @example
 468 |  * // event is a CSEvent object, but user can ignore it.
 469 |  * function OnAppThemeColorChanged(event)
 470 |  * {
 471 |  *    // Should get a latest HostEnvironment object from application.
 472 |  *    var skinInfo = JSON.parse(window.__adobe_cep__.getHostEnvironment()).appSkinInfo;
 473 |  *    // Gets the style information such as color info from the skinInfo,
 474 |  *    // and redraw all UI controls of your extension according to the style info.
 475 |  * }
 476 |  */
 477 | CSInterface.THEME_COLOR_CHANGED_EVENT = "com.adobe.csxs.events.ThemeColorChanged";
 478 | 
 479 | /** The host environment data object. */
 480 | CSInterface.prototype.hostEnvironment = window.__adobe_cep__ ? JSON.parse(window.__adobe_cep__.getHostEnvironment()) : null;
 481 | 
 482 | /** Retrieves information about the host environment in which the
 483 |  *  extension is currently running.
 484 |  *
 485 |  *   @return A \c #HostEnvironment object.
 486 |  */
 487 | CSInterface.prototype.getHostEnvironment = function()
 488 | {
 489 |     this.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment());
 490 |     return this.hostEnvironment;
 491 | };
 492 | 
 493 | /** Loads binary file created which is located at url asynchronously
 494 | *
 495 | *@param urlName url at which binary file is located. Local files should start with 'file://'
 496 | *@param callback Optional. A callback function that returns after binary is loaded
 497 | 
 498 | *@example
 499 | * To create JS binary use command ./cep_compiler test.js test.bin
 500 | * To load JS binary asyncronously
 501 | *   var CSLib = new CSInterface();
 502 | *   CSLib.loadBinAsync(url, function () { });
 503 | */
 504 | CSInterface.prototype.loadBinAsync = function(urlName,callback)
 505 | {
 506 |     try
 507 |     {
 508 |         var xhr = new XMLHttpRequest();
 509 |         xhr.responseType = 'arraybuffer'; // make response as ArrayBuffer
 510 |         xhr.open('GET', urlName, true);
 511 |         xhr.onerror = function ()
 512 |         {
 513 |   		  console.log("Unable to load snapshot from given URL");
 514 |   		  return false;
 515 | 		};
 516 |         xhr.send();
 517 |         xhr.onload = () => {
 518 |             window.__adobe_cep__.loadSnapshot(xhr.response);
 519 |             if (typeof callback === "function")
 520 |             {
 521 |                 callback();
 522 |             }
 523 |             else if(typeof callback !== "undefined")
 524 |             {
 525 |                 console.log("Provided callback is not a function");
 526 |             }
 527 |         }
 528 |     }
 529 |     catch(err)
 530 |     {
 531 |         console.log(err);
 532 |         return false;
 533 |     }
 534 | 
 535 | 	return true;
 536 | };
 537 | 
 538 | /** Loads binary file created synchronously
 539 | *
 540 | *@param pathName the local path at which binary file is located
 541 | 
 542 | *@example
 543 | * To create JS binary use command ./cep_compiler test.js test.bin
 544 | * To load JS binary syncronously
 545 | *   var CSLib = new CSInterface();
 546 | *   CSLib.loadBinSync(path);
 547 | */
 548 | CSInterface.prototype.loadBinSync  = function(pathName)
 549 | {
 550 |     try
 551 |     {
 552 |         var OSVersion = this.getOSInformation();
 553 |         if(pathName.startsWith("file://"))
 554 |         {
 555 |             if (OSVersion.indexOf("Windows") >= 0)
 556 |             {
 557 |                pathName = pathName.replace("file:///", "");
 558 |             }
 559 |             else if (OSVersion.indexOf("Mac") >= 0)
 560 |             {
 561 |                 pathName = pathName.replace("file://", "");
 562 |             }
 563 |             window.__adobe_cep__.loadSnapshot(pathName);
 564 |             return true;
 565 |         }
 566 |     }
 567 |     catch(err)
 568 |     {
 569 |         console.log(err);
 570 |         return false;
 571 |     }
 572 |     //control should not come here
 573 |     return false;
 574 | };
 575 | 
 576 | /** Closes this extension. */
 577 | CSInterface.prototype.closeExtension = function()
 578 | {
 579 |     window.__adobe_cep__.closeExtension();
 580 | };
 581 | 
 582 | /**
 583 |  * Retrieves a path for which a constant is defined in the system.
 584 |  *
 585 |  * @param pathType The path-type constant defined in \c #SystemPath ,
 586 |  *
 587 |  * @return The platform-specific system path string.
 588 |  */
 589 | CSInterface.prototype.getSystemPath = function(pathType)
 590 | {
 591 |     var path = decodeURI(window.__adobe_cep__.getSystemPath(pathType));
 592 |     var OSVersion = this.getOSInformation();
 593 |     if (OSVersion.indexOf("Windows") >= 0)
 594 |     {
 595 |       path = path.replace("file:///", "");
 596 |     }
 597 |     else if (OSVersion.indexOf("Mac") >= 0)
 598 |     {
 599 |       path = path.replace("file://", "");
 600 |     }
 601 |     return path;
 602 | };
 603 | 
 604 | /**
 605 |  * Evaluates a JavaScript script, which can use the JavaScript DOM
 606 |  * of the host application.
 607 |  *
 608 |  * @param script    The JavaScript script.
 609 |  * @param callback  Optional. A callback function that receives the result of execution.
 610 |  *          If execution fails, the callback function receives the error message \c EvalScript_ErrMessage.
 611 |  */
 612 | CSInterface.prototype.evalScript = function(script, callback)
 613 | {
 614 |     if(callback === null || callback === undefined)
 615 |     {
 616 |         callback = function(result){};
 617 |     }
 618 |     window.__adobe_cep__.evalScript(script, callback);
 619 | };
 620 | 
 621 | /**
 622 |  * Retrieves the unique identifier of the application.
 623 |  * in which the extension is currently running.
 624 |  *
 625 |  * @return The unique ID string.
 626 |  */
 627 | CSInterface.prototype.getApplicationID = function()
 628 | {
 629 |     var appId = this.hostEnvironment.appId;
 630 |     return appId;
 631 | };
 632 | 
 633 | /**
 634 |  * Retrieves host capability information for the application
 635 |  * in which the extension is currently running.
 636 |  *
 637 |  * @return A \c #HostCapabilities object.
 638 |  */
 639 | CSInterface.prototype.getHostCapabilities = function()
 640 | {
 641 |     var hostCapabilities = JSON.parse(window.__adobe_cep__.getHostCapabilities() );
 642 |     return hostCapabilities;
 643 | };
 644 | 
 645 | /**
 646 |  * Triggers a CEP event programmatically. Yoy can use it to dispatch
 647 |  * an event of a predefined type, or of a type you have defined.
 648 |  *
 649 |  * @param event A \c CSEvent object.
 650 |  */
 651 | CSInterface.prototype.dispatchEvent = function(event)
 652 | {
 653 |     if (typeof event.data == "object")
 654 |     {
 655 |         event.data = JSON.stringify(event.data);
 656 |     }
 657 | 
 658 |     window.__adobe_cep__.dispatchEvent(event);
 659 | };
 660 | 
 661 | /**
 662 |  * Registers an interest in a CEP event of a particular type, and
 663 |  * assigns an event handler.
 664 |  * The event infrastructure notifies your extension when events of this type occur,
 665 |  * passing the event object to the registered handler function.
 666 |  *
 667 |  * @param type     The name of the event type of interest.
 668 |  * @param listener The JavaScript handler function or method.
 669 |  * @param obj      Optional, the object containing the handler method, if any.
 670 |  *         Default is null.
 671 |  */
 672 | CSInterface.prototype.addEventListener = function(type, listener, obj)
 673 | {
 674 |     window.__adobe_cep__.addEventListener(type, listener, obj);
 675 | };
 676 | 
 677 | /**
 678 |  * Removes a registered event listener.
 679 |  *
 680 |  * @param type      The name of the event type of interest.
 681 |  * @param listener  The JavaScript handler function or method that was registered.
 682 |  * @param obj       Optional, the object containing the handler method, if any.
 683 |  *          Default is null.
 684 |  */
 685 | CSInterface.prototype.removeEventListener = function(type, listener, obj)
 686 | {
 687 |     window.__adobe_cep__.removeEventListener(type, listener, obj);
 688 | };
 689 | 
 690 | /**
 691 |  * Loads and launches another extension, or activates the extension if it is already loaded.
 692 |  *
 693 |  * @param extensionId       The extension's unique identifier.
 694 |  * @param startupParams     Not currently used, pass "".
 695 |  *
 696 |  * @example
 697 |  * To launch the extension "help" with ID "HLP" from this extension, call:
 698 |  * <code>requestOpenExtension("HLP", ""); </code>
 699 |  *
 700 |  */
 701 | CSInterface.prototype.requestOpenExtension = function(extensionId, params)
 702 | {
 703 |     window.__adobe_cep__.requestOpenExtension(extensionId, params);
 704 | };
 705 | 
 706 | /**
 707 |  * Retrieves the list of extensions currently loaded in the current host application.
 708 |  * The extension list is initialized once, and remains the same during the lifetime
 709 |  * of the CEP session.
 710 |  *
 711 |  * @param extensionIds  Optional, an array of unique identifiers for extensions of interest.
 712 |  *          If omitted, retrieves data for all extensions.
 713 |  *
 714 |  * @return Zero or more \c #Extension objects.
 715 |  */
 716 | CSInterface.prototype.getExtensions = function(extensionIds)
 717 | {
 718 |     var extensionIdsStr = JSON.stringify(extensionIds);
 719 |     var extensionsStr = window.__adobe_cep__.getExtensions(extensionIdsStr);
 720 | 
 721 |     var extensions = JSON.parse(extensionsStr);
 722 |     return extensions;
 723 | };
 724 | 
 725 | /**
 726 |  * Retrieves network-related preferences.
 727 |  *
 728 |  * @return A JavaScript object containing network preferences.
 729 |  */
 730 | CSInterface.prototype.getNetworkPreferences = function()
 731 | {
 732 |     var result = window.__adobe_cep__.getNetworkPreferences();
 733 |     var networkPre = JSON.parse(result);
 734 | 
 735 |     return networkPre;
 736 | };
 737 | 
 738 | /**
 739 |  * Initializes the resource bundle for this extension with property values
 740 |  * for the current application and locale.
 741 |  * To support multiple locales, you must define a property file for each locale,
 742 |  * containing keyed display-string values for that locale.
 743 |  * See localization documentation for Extension Builder and related products.
 744 |  *
 745 |  * Keys can be in the
 746 |  * form <code>key.value="localized string"</code>, for use in HTML text elements.
 747 |  * For example, in this input element, the localized \c key.value string is displayed
 748 |  * instead of the empty \c value string:
 749 |  *
 750 |  * <code><input type="submit" value="" data-locale="key"/></code>
 751 |  *
 752 |  * @return An object containing the resource bundle information.
 753 |  */
 754 | CSInterface.prototype.initResourceBundle = function()
 755 | {
 756 |     var resourceBundle = JSON.parse(window.__adobe_cep__.initResourceBundle());
 757 |     var resElms = document.querySelectorAll('[data-locale]');
 758 |     for (var n = 0; n < resElms.length; n++)
 759 |     {
 760 |        var resEl = resElms[n];
 761 |        // Get the resource key from the element.
 762 |        var resKey = resEl.getAttribute('data-locale');
 763 |        if (resKey)
 764 |        {
 765 |            // Get all the resources that start with the key.
 766 |            for (var key in resourceBundle)
 767 |            {
 768 |                if (key.indexOf(resKey) === 0)
 769 |                {
 770 |                    var resValue = resourceBundle[key];
 771 |                    if (key.length == resKey.length)
 772 |                    {
 773 |                         resEl.innerHTML = resValue;
 774 |                    }
 775 |                    else if ('.' == key.charAt(resKey.length))
 776 |                    {
 777 |                         var attrKey = key.substring(resKey.length + 1);
 778 |                         resEl[attrKey] = resValue;
 779 |                    }
 780 |                }
 781 |            }
 782 |        }
 783 |     }
 784 |     return resourceBundle;
 785 | };
 786 | 
 787 | /**
 788 |  * Writes installation information to a file.
 789 |  *
 790 |  * @return The file path.
 791 |  */
 792 | CSInterface.prototype.dumpInstallationInfo = function()
 793 | {
 794 |     return window.__adobe_cep__.dumpInstallationInfo();
 795 | };
 796 | 
 797 | /**
 798 |  * Retrieves version information for the current Operating System,
 799 |  * See http://www.useragentstring.com/pages/Chrome/ for Chrome \c navigator.userAgent values.
 800 |  *
 801 |  * @return A string containing the OS version, or "unknown Operation System".
 802 |  * If user customizes the User Agent by setting CEF command parameter "--user-agent", only
 803 |  * "Mac OS X" or "Windows" will be returned.
 804 |  */
 805 | CSInterface.prototype.getOSInformation = function()
 806 | {
 807 |     var userAgent = navigator.userAgent;
 808 | 
 809 |     if ((navigator.platform == "Win32") || (navigator.platform == "Windows"))
 810 |     {
 811 |         var winVersion = "Windows";
 812 |         var winBit = "";
 813 |         if (userAgent.indexOf("Windows") > -1)
 814 |         {
 815 |             if (userAgent.indexOf("Windows NT 5.0") > -1)
 816 |             {
 817 |                 winVersion = "Windows 2000";
 818 |             }
 819 |             else if (userAgent.indexOf("Windows NT 5.1") > -1)
 820 |             {
 821 |                 winVersion = "Windows XP";
 822 |             }
 823 |             else if (userAgent.indexOf("Windows NT 5.2") > -1)
 824 |             {
 825 |                 winVersion = "Windows Server 2003";
 826 |             }
 827 |             else if (userAgent.indexOf("Windows NT 6.0") > -1)
 828 |             {
 829 |                 winVersion = "Windows Vista";
 830 |             }
 831 |             else if (userAgent.indexOf("Windows NT 6.1") > -1)
 832 |             {
 833 |                 winVersion = "Windows 7";
 834 |             }
 835 |             else if (userAgent.indexOf("Windows NT 6.2") > -1)
 836 |             {
 837 |                 winVersion = "Windows 8";
 838 |             }
 839 |             else if (userAgent.indexOf("Windows NT 6.3") > -1)
 840 |             {
 841 |                 winVersion = "Windows 8.1";
 842 |             }
 843 |             else if (userAgent.indexOf("Windows NT 10") > -1)
 844 |             {
 845 |                 winVersion = "Windows 10";
 846 |             }
 847 | 
 848 |             if (userAgent.indexOf("WOW64") > -1 || userAgent.indexOf("Win64") > -1)
 849 |             {
 850 |                 winBit = " 64-bit";
 851 |             }
 852 |             else
 853 |             {
 854 |                 winBit = " 32-bit";
 855 |             }
 856 |         }
 857 | 
 858 |         return winVersion + winBit;
 859 |     }
 860 |     else if ((navigator.platform == "MacIntel") || (navigator.platform == "Macintosh"))
 861 |     {
 862 |         var result = "Mac OS X";
 863 | 
 864 |         if (userAgent.indexOf("Mac OS X") > -1)
 865 |         {
 866 |             result = userAgent.substring(userAgent.indexOf("Mac OS X"), userAgent.indexOf(")"));
 867 |             result = result.replace(/_/g, ".");
 868 |         }
 869 | 
 870 |         return result;
 871 |     }
 872 | 
 873 |     return "Unknown Operation System";
 874 | };
 875 | 
 876 | /**
 877 |  * Opens a page in the default system browser.
 878 |  *
 879 |  * Since 4.2.0
 880 |  *
 881 |  * @param url  The URL of the page/file to open, or the email address.
 882 |  * Must use HTTP/HTTPS/file/mailto protocol. For example:
 883 |  *   "http://www.adobe.com"
 884 |  *   "https://github.com"
 885 |  *   "file:///C:/log.txt"
 886 |  *   "mailto:[email protected]"
 887 |  *
 888 |  * @return One of these error codes:\n
 889 |  *      <ul>\n
 890 |  *          <li>NO_ERROR - 0</li>\n
 891 |  *          <li>ERR_UNKNOWN - 1</li>\n
 892 |  *          <li>ERR_INVALID_PARAMS - 2</li>\n
 893 |  *          <li>ERR_INVALID_URL - 201</li>\n
 894 |  *      </ul>\n
 895 |  */
 896 | CSInterface.prototype.openURLInDefaultBrowser = function(url)
 897 | {
 898 |     return cep.util.openURLInDefaultBrowser(url);
 899 | };
 900 | 
 901 | /**
 902 |  * Retrieves extension ID.
 903 |  *
 904 |  * Since 4.2.0
 905 |  *
 906 |  * @return extension ID.
 907 |  */
 908 | CSInterface.prototype.getExtensionID = function()
 909 | {
 910 |      return window.__adobe_cep__.getExtensionId();
 911 | };
 912 | 
 913 | /**
 914 |  * Retrieves the scale factor of screen.
 915 |  * On Windows platform, the value of scale factor might be different from operating system's scale factor,
 916 |  * since host application may use its self-defined scale factor.
 917 |  *
 918 |  * Since 4.2.0
 919 |  *
 920 |  * @return One of the following float number.
 921 |  *      <ul>\n
 922 |  *          <li> -1.0 when error occurs </li>\n
 923 |  *          <li> 1.0 means normal screen </li>\n
 924 |  *          <li> >1.0 means HiDPI screen </li>\n
 925 |  *      </ul>\n
 926 |  */
 927 | CSInterface.prototype.getScaleFactor = function()
 928 | {
 929 |     return window.__adobe_cep__.getScaleFactor();
 930 | };
 931 | 
 932 | /**
 933 |  * Retrieves the scale factor of Monitor.
 934 |  *
 935 |  * Since 8.5.0
 936 |  *
 937 |  * @return value >= 1.0f
 938 |  * only available for windows machine
 939 |  */
 940 |  if(navigator.appVersion.toLowerCase().indexOf("windows") >= 0) {
 941 |     CSInterface.prototype.getMonitorScaleFactor = function()
 942 |     {
 943 |         return window.__adobe_cep__.getMonitorScaleFactor();
 944 |     };
 945 | }
 946 | 
 947 | /**
 948 |  * Set a handler to detect any changes of scale factor. This only works on Mac.
 949 |  *
 950 |  * Since 4.2.0
 951 |  *
 952 |  * @param handler   The function to be called when scale factor is changed.
 953 |  *
 954 |  */
 955 | CSInterface.prototype.setScaleFactorChangedHandler = function(handler)
 956 | {
 957 |     window.__adobe_cep__.setScaleFactorChangedHandler(handler);
 958 | };
 959 | 
 960 | /**
 961 |  * Retrieves current API version.
 962 |  *
 963 |  * Since 4.2.0
 964 |  *
 965 |  * @return ApiVersion object.
 966 |  *
 967 |  */
 968 | CSInterface.prototype.getCurrentApiVersion = function()
 969 | {
 970 |     var apiVersion = JSON.parse(window.__adobe_cep__.getCurrentApiVersion());
 971 |     return apiVersion;
 972 | };
 973 | 
 974 | /**
 975 |  * Set panel flyout menu by an XML.
 976 |  *
 977 |  * Since 5.2.0
 978 |  *
 979 |  * Register a callback function for "com.adobe.csxs.events.flyoutMenuClicked" to get notified when a
 980 |  * menu item is clicked.
 981 |  * The "data" attribute of event is an object which contains "menuId" and "menuName" attributes.
 982 |  *
 983 |  * Register callback functions for "com.adobe.csxs.events.flyoutMenuOpened" and "com.adobe.csxs.events.flyoutMenuClosed"
 984 |  * respectively to get notified when flyout menu is opened or closed.
 985 |  *
 986 |  * @param menu     A XML string which describes menu structure.
 987 |  * An example menu XML:
 988 |  * <Menu>
 989 |  *   <MenuItem Id="menuItemId1" Label="TestExample1" Enabled="true" Checked="false"/>
 990 |  *   <MenuItem Label="TestExample2">
 991 |  *     <MenuItem Label="TestExample2-1" >
 992 |  *       <MenuItem Label="TestExample2-1-1" Enabled="false" Checked="true"/>
 993 |  *     </MenuItem>
 994 |  *     <MenuItem Label="TestExample2-2" Enabled="true" Checked="true"/>
 995 |  *   </MenuItem>
 996 |  *   <MenuItem Label="---" />
 997 |  *   <MenuItem Label="TestExample3" Enabled="false" Checked="false"/>
 998 |  * </Menu>
 999 |  *
1000 |  */
1001 | CSInterface.prototype.setPanelFlyoutMenu = function(menu)
1002 | {
1003 |     if ("string" != typeof menu)
1004 |     {
1005 |         return;
1006 |     }
1007 | 
1008 |     window.__adobe_cep__.invokeSync("setPanelFlyoutMenu", menu);
1009 | };
1010 | 
1011 | /**
1012 |  * Updates a menu item in the extension window's flyout menu, by setting the enabled
1013 |  * and selection status.
1014 |  *
1015 |  * Since 5.2.0
1016 |  *
1017 |  * @param menuItemLabel The menu item label.
1018 |  * @param enabled       True to enable the item, false to disable it (gray it out).
1019 |  * @param checked       True to select the item, false to deselect it.
1020 |  *
1021 |  * @return false when the host application does not support this functionality (HostCapabilities.EXTENDED_PANEL_MENU is false).
1022 |  *         Fails silently if menu label is invalid.
1023 |  *
1024 |  * @see HostCapabilities.EXTENDED_PANEL_MENU
1025 |  */
1026 | CSInterface.prototype.updatePanelMenuItem = function(menuItemLabel, enabled, checked)
1027 | {
1028 |     var ret = false;
1029 |     if (this.getHostCapabilities().EXTENDED_PANEL_MENU)
1030 |     {
1031 |         var itemStatus = new MenuItemStatus(menuItemLabel, enabled, checked);
1032 |         ret = window.__adobe_cep__.invokeSync("updatePanelMenuItem", JSON.stringify(itemStatus));
1033 |     }
1034 |     return ret;
1035 | };
1036 | 
1037 | 
1038 | /**
1039 |  * Set context menu by XML string.
1040 |  *
1041 |  * Since 5.2.0
1042 |  *
1043 |  * There are a number of conventions used to communicate what type of menu item to create and how it should be handled.
1044 |  * - an item without menu ID or menu name is disabled and is not shown.
1045 |  * - if the item name is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL.
1046 |  * - Checkable attribute takes precedence over Checked attribute.
1047 |  * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item.
1048 |      The Chrome extension contextMenus API was taken as a reference.
1049 |      https://developer.chrome.com/extensions/contextMenus
1050 |  * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter.
1051 |  *
1052 |  * @param menu      A XML string which describes menu structure.
1053 |  * @param callback  The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item.
1054 |  *
1055 |  * @description An example menu XML:
1056 |  * <Menu>
1057 |  *   <MenuItem Id="menuItemId1" Label="TestExample1" Enabled="true" Checkable="true" Checked="false" Icon="./image/small_16X16.png"/>
1058 |  *   <MenuItem Id="menuItemId2" Label="TestExample2">
1059 |  *     <MenuItem Id="menuItemId2-1" Label="TestExample2-1" >
1060 |  *       <MenuItem Id="menuItemId2-1-1" Label="TestExample2-1-1" Enabled="false" Checkable="true" Checked="true"/>
1061 |  *     </MenuItem>
1062 |  *     <MenuItem Id="menuItemId2-2" Label="TestExample2-2" Enabled="true" Checkable="true" Checked="true"/>
1063 |  *   </MenuItem>
1064 |  *   <MenuItem Label="---" />
1065 |  *   <MenuItem Id="menuItemId3" Label="TestExample3" Enabled="false" Checkable="true" Checked="false"/>
1066 |  * </Menu>
1067 |  */
1068 | CSInterface.prototype.setContextMenu = function(menu, callback)
1069 | {
1070 |     if ("string" != typeof menu)
1071 |     {
1072 |         return;
1073 |     }
1074 | 
1075 |     window.__adobe_cep__.invokeAsync("setContextMenu", menu, callback);
1076 | };
1077 | 
1078 | /**
1079 |  * Set context menu by JSON string.
1080 |  *
1081 |  * Since 6.0.0
1082 |  *
1083 |  * There are a number of conventions used to communicate what type of menu item to create and how it should be handled.
1084 |  * - an item without menu ID or menu name is disabled and is not shown.
1085 |  * - if the item label is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL.
1086 |  * - Checkable attribute takes precedence over Checked attribute.
1087 |  * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item.
1088 |      The Chrome extension contextMenus API was taken as a reference.
1089 |  * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter.
1090 |      https://developer.chrome.com/extensions/contextMenus
1091 |  *
1092 |  * @param menu      A JSON string which describes menu structure.
1093 |  * @param callback  The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item.
1094 |  *
1095 |  * @description An example menu JSON:
1096 |  *
1097 |  * {
1098 |  *      "menu": [
1099 |  *          {
1100 |  *              "id": "menuItemId1",
1101 |  *              "label": "testExample1",
1102 |  *              "enabled": true,
1103 |  *              "checkable": true,
1104 |  *              "checked": false,
1105 |  *              "icon": "./image/small_16X16.png"
1106 |  *          },
1107 |  *          {
1108 |  *              "id": "menuItemId2",
1109 |  *              "label": "testExample2",
1110 |  *              "menu": [
1111 |  *                  {
1112 |  *                      "id": "menuItemId2-1",
1113 |  *                      "label": "testExample2-1",
1114 |  *                      "menu": [
1115 |  *                          {
1116 |  *                              "id": "menuItemId2-1-1",
1117 |  *                              "label": "testExample2-1-1",
1118 |  *                              "enabled": false,
1119 |  *                              "checkable": true,
1120 |  *                              "checked": true
1121 |  *                          }
1122 |  *                      ]
1123 |  *                  },
1124 |  *                  {
1125 |  *                      "id": "menuItemId2-2",
1126 |  *                      "label": "testExample2-2",
1127 |  *                      "enabled": true,
1128 |  *                      "checkable": true,
1129 |  *                      "checked": true
1130 |  *                  }
1131 |  *              ]
1132 |  *          },
1133 |  *          {
1134 |  *              "label": "---"
1135 |  *          },
1136 |  *          {
1137 |  *              "id": "menuItemId3",
1138 |  *              "label": "testExample3",
1139 |  *              "enabled": false,
1140 |  *              "checkable": true,
1141 |  *              "checked": false
1142 |  *          }
1143 |  *      ]
1144 |  *  }
1145 |  *
1146 |  */
1147 | CSInterface.prototype.setContextMenuByJSON = function(menu, callback)
1148 | {
1149 |     if ("string" != typeof menu)
1150 |     {
1151 |         return;
1152 |     }
1153 | 
1154 |     window.__adobe_cep__.invokeAsync("setContextMenuByJSON", menu, callback);
1155 | };
1156 | 
1157 | /**
1158 |  * Updates a context menu item by setting the enabled and selection status.
1159 |  *
1160 |  * Since 5.2.0
1161 |  *
1162 |  * @param menuItemID    The menu item ID.
1163 |  * @param enabled       True to enable the item, false to disable it (gray it out).
1164 |  * @param checked       True to select the item, false to deselect it.
1165 |  */
1166 | CSInterface.prototype.updateContextMenuItem = function(menuItemID, enabled, checked)
1167 | {
1168 |     var itemStatus = new ContextMenuItemStatus(menuItemID, enabled, checked);
1169 |     ret = window.__adobe_cep__.invokeSync("updateContextMenuItem", JSON.stringify(itemStatus));
1170 | };
1171 | 
1172 | /**
1173 |  * Get the visibility status of an extension window.
1174 |  *
1175 |  * Since 6.0.0
1176 |  *
1177 |  * @return true if the extension window is visible; false if the extension window is hidden.
1178 |  */
1179 | CSInterface.prototype.isWindowVisible = function()
1180 | {
1181 |     return window.__adobe_cep__.invokeSync("isWindowVisible", "");
1182 | };
1183 | 
1184 | /**
1185 |  * Resize extension's content to the specified dimensions.
1186 |  * 1. Works with modal and modeless extensions in all Adobe products.
1187 |  * 2. Extension's manifest min/max size constraints apply and take precedence.
1188 |  * 3. For panel extensions
1189 |  *    3.1 This works in all Adobe products except:
1190 |  *        * Premiere Pro
1191 |  *        * Prelude
1192 |  *        * After Effects
1193 |  *    3.2 When the panel is in certain states (especially when being docked),
1194 |  *        it will not change to the desired dimensions even when the
1195 |  *        specified size satisfies min/max constraints.
1196 |  *
1197 |  * Since 6.0.0
1198 |  *
1199 |  * @param width  The new width
1200 |  * @param height The new height
1201 |  */
1202 | CSInterface.prototype.resizeContent = function(width, height)
1203 | {
1204 |     window.__adobe_cep__.resizeContent(width, height);
1205 | };
1206 | 
1207 | /**
1208 |  * Register the invalid certificate callback for an extension.
1209 |  * This callback will be triggered when the extension tries to access the web site that contains the invalid certificate on the main frame.
1210 |  * But if the extension does not call this function and tries to access the web site containing the invalid certificate, a default error page will be shown.
1211 |  *
1212 |  * Since 6.1.0
1213 |  *
1214 |  * @param callback the callback function
1215 |  */
1216 | CSInterface.prototype.registerInvalidCertificateCallback = function(callback)
1217 | {
1218 |     return window.__adobe_cep__.registerInvalidCertificateCallback(callback);
1219 | };
1220 | 
1221 | /**
1222 |  * Register an interest in some key events to prevent them from being sent to the host application.
1223 |  *
1224 |  * This function works with modeless extensions and panel extensions.
1225 |  * Generally all the key events will be sent to the host application for these two extensions if the current focused element
1226 |  * is not text input or dropdown,
1227 |  * If you want to intercept some key events and want them to be handled in the extension, please call this function
1228 |  * in advance to prevent them being sent to the host application.
1229 |  *
1230 |  * Since 6.1.0
1231 |  *
1232 |  * @param keyEventsInterest      A JSON string describing those key events you are interested in. A null object or
1233 |                                  an empty string will lead to removing the interest
1234 |  *
1235 |  * This JSON string should be an array, each object has following keys:
1236 |  *
1237 |  * keyCode:  [Required] represents an OS system dependent virtual key code identifying
1238 |  *           the unmodified value of the pressed key.
1239 |  * ctrlKey:  [optional] a Boolean that indicates if the control key was pressed (true) or not (false) when the event occurred.
1240 |  * altKey:   [optional] a Boolean that indicates if the alt key was pressed (true) or not (false) when the event occurred.
1241 |  * shiftKey: [optional] a Boolean that indicates if the shift key was pressed (true) or not (false) when the event occurred.
1242 |  * metaKey:  [optional] (Mac Only) a Boolean that indicates if the Meta key was pressed (true) or not (false) when the event occurred.
1243 |  *                      On Macintosh keyboards, this is the command key. To detect Windows key on Windows, please use keyCode instead.
1244 |  * An example JSON string:
1245 |  *
1246 |  * [
1247 |  *     {
1248 |  *         "keyCode": 48
1249 |  *     },
1250 |  *     {
1251 |  *         "keyCode": 123,
1252 |  *         "ctrlKey": true
1253 |  *     },
1254 |  *     {
1255 |  *         "keyCode": 123,
1256 |  *         "ctrlKey": true,
1257 |  *         "metaKey": true
1258 |  *     }
1259 |  * ]
1260 |  *
1261 |  */
1262 | CSInterface.prototype.registerKeyEventsInterest = function(keyEventsInterest)
1263 | {
1264 |     return window.__adobe_cep__.registerKeyEventsInterest(keyEventsInterest);
1265 | };
1266 | 
1267 | /**
1268 |  * Set the title of the extension window.
1269 |  * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver.
1270 |  *
1271 |  * Since 6.1.0
1272 |  *
1273 |  * @param title The window title.
1274 |  */
1275 | CSInterface.prototype.setWindowTitle = function(title)
1276 | {
1277 |     window.__adobe_cep__.invokeSync("setWindowTitle", title);
1278 | };
1279 | 
1280 | /**
1281 |  * Get the title of the extension window.
1282 |  * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver.
1283 |  *
1284 |  * Since 6.1.0
1285 |  *
1286 |  * @return The window title.
1287 |  */
1288 | CSInterface.prototype.getWindowTitle = function()
1289 | {
1290 |     return window.__adobe_cep__.invokeSync("getWindowTitle", "");
1291 | };
1292 | 
```

--------------------------------------------------------------------------------
/cep/com.mikechambers.ai/lib/CSInterface.js:
--------------------------------------------------------------------------------

```javascript
   1 | /**************************************************************************************************
   2 | *
   3 | * ADOBE SYSTEMS INCORPORATED
   4 | * Copyright 2020 Adobe Systems Incorporated
   5 | * All Rights Reserved.
   6 | *
   7 | * NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the
   8 | * terms of the Adobe license agreement accompanying it.  If you have received this file from a
   9 | * source other than Adobe, then your use, modification, or distribution of it requires the prior
  10 | * written permission of Adobe.
  11 | *
  12 | **************************************************************************************************/
  13 | 
  14 | /** CSInterface - v12.0.0 */
  15 | 
  16 | /**
  17 |  * Stores constants for the window types supported by the CSXS infrastructure.
  18 |  */
  19 | function CSXSWindowType()
  20 | {
  21 | }
  22 | 
  23 | /** Constant for the CSXS window type Panel. */
  24 | CSXSWindowType._PANEL = "Panel";
  25 | 
  26 | /** Constant for the CSXS window type Modeless. */
  27 | CSXSWindowType._MODELESS = "Modeless";
  28 | 
  29 | /** Constant for the CSXS window type ModalDialog. */
  30 | CSXSWindowType._MODAL_DIALOG = "ModalDialog";
  31 | 
  32 | /** EvalScript error message */
  33 | EvalScript_ErrMessage = "EvalScript error.";
  34 | 
  35 | /**
  36 |  * @class Version
  37 |  * Defines a version number with major, minor, micro, and special
  38 |  * components. The major, minor and micro values are numeric; the special
  39 |  * value can be any string.
  40 |  *
  41 |  * @param major   The major version component, a positive integer up to nine digits long.
  42 |  * @param minor   The minor version component, a positive integer up to nine digits long.
  43 |  * @param micro   The micro version component, a positive integer up to nine digits long.
  44 |  * @param special The special version component, an arbitrary string.
  45 |  *
  46 |  * @return A new \c Version object.
  47 |  */
  48 | function Version(major, minor, micro, special)
  49 | {
  50 |     this.major = major;
  51 |     this.minor = minor;
  52 |     this.micro = micro;
  53 |     this.special = special;
  54 | }
  55 | 
  56 | /**
  57 |  * The maximum value allowed for a numeric version component.
  58 |  * This reflects the maximum value allowed in PlugPlug and the manifest schema.
  59 |  */
  60 | Version.MAX_NUM = 999999999;
  61 | 
  62 | /**
  63 |  * @class VersionBound
  64 |  * Defines a boundary for a version range, which associates a \c Version object
  65 |  * with a flag for whether it is an inclusive or exclusive boundary.
  66 |  *
  67 |  * @param version   The \c #Version object.
  68 |  * @param inclusive True if this boundary is inclusive, false if it is exclusive.
  69 |  *
  70 |  * @return A new \c VersionBound object.
  71 |  */
  72 | function VersionBound(version, inclusive)
  73 | {
  74 |     this.version = version;
  75 |     this.inclusive = inclusive;
  76 | }
  77 | 
  78 | /**
  79 |  * @class VersionRange
  80 |  * Defines a range of versions using a lower boundary and optional upper boundary.
  81 |  *
  82 |  * @param lowerBound The \c #VersionBound object.
  83 |  * @param upperBound The \c #VersionBound object, or null for a range with no upper boundary.
  84 |  *
  85 |  * @return A new \c VersionRange object.
  86 |  */
  87 | function VersionRange(lowerBound, upperBound)
  88 | {
  89 |     this.lowerBound = lowerBound;
  90 |     this.upperBound = upperBound;
  91 | }
  92 | 
  93 | /**
  94 |  * @class Runtime
  95 |  * Represents a runtime related to the CEP infrastructure.
  96 |  * Extensions can declare dependencies on particular
  97 |  * CEP runtime versions in the extension manifest.
  98 |  *
  99 |  * @param name    The runtime name.
 100 |  * @param version A \c #VersionRange object that defines a range of valid versions.
 101 |  *
 102 |  * @return A new \c Runtime object.
 103 |  */
 104 | function Runtime(name, versionRange)
 105 | {
 106 |     this.name = name;
 107 |     this.versionRange = versionRange;
 108 | }
 109 | 
 110 | /**
 111 | * @class Extension
 112 | * Encapsulates a CEP-based extension to an Adobe application.
 113 | *
 114 | * @param id              The unique identifier of this extension.
 115 | * @param name            The localizable display name of this extension.
 116 | * @param mainPath        The path of the "index.html" file.
 117 | * @param basePath        The base path of this extension.
 118 | * @param windowType          The window type of the main window of this extension.
 119 |                  Valid values are defined by \c #CSXSWindowType.
 120 | * @param width           The default width in pixels of the main window of this extension.
 121 | * @param height          The default height in pixels of the main window of this extension.
 122 | * @param minWidth        The minimum width in pixels of the main window of this extension.
 123 | * @param minHeight       The minimum height in pixels of the main window of this extension.
 124 | * @param maxWidth        The maximum width in pixels of the main window of this extension.
 125 | * @param maxHeight       The maximum height in pixels of the main window of this extension.
 126 | * @param defaultExtensionDataXml The extension data contained in the default \c ExtensionDispatchInfo section of the extension manifest.
 127 | * @param specialExtensionDataXml The extension data contained in the application-specific \c ExtensionDispatchInfo section of the extension manifest.
 128 | * @param requiredRuntimeList     An array of \c Runtime objects for runtimes required by this extension.
 129 | * @param isAutoVisible       True if this extension is visible on loading.
 130 | * @param isPluginExtension   True if this extension has been deployed in the Plugins folder of the host application.
 131 | *
 132 | * @return A new \c Extension object.
 133 | */
 134 | function Extension(id, name, mainPath, basePath, windowType, width, height, minWidth, minHeight, maxWidth, maxHeight,
 135 |                    defaultExtensionDataXml, specialExtensionDataXml, requiredRuntimeList, isAutoVisible, isPluginExtension)
 136 | {
 137 |     this.id = id;
 138 |     this.name = name;
 139 |     this.mainPath = mainPath;
 140 |     this.basePath = basePath;
 141 |     this.windowType = windowType;
 142 |     this.width = width;
 143 |     this.height = height;
 144 |     this.minWidth = minWidth;
 145 |     this.minHeight = minHeight;
 146 |     this.maxWidth = maxWidth;
 147 |     this.maxHeight = maxHeight;
 148 |     this.defaultExtensionDataXml = defaultExtensionDataXml;
 149 |     this.specialExtensionDataXml = specialExtensionDataXml;
 150 |     this.requiredRuntimeList = requiredRuntimeList;
 151 |     this.isAutoVisible = isAutoVisible;
 152 |     this.isPluginExtension = isPluginExtension;
 153 | }
 154 | 
 155 | /**
 156 |  * @class CSEvent
 157 |  * A standard JavaScript event, the base class for CEP events.
 158 |  *
 159 |  * @param type        The name of the event type.
 160 |  * @param scope       The scope of event, can be "GLOBAL" or "APPLICATION".
 161 |  * @param appId       The unique identifier of the application that generated the event.
 162 |  * @param extensionId     The unique identifier of the extension that generated the event.
 163 |  *
 164 |  * @return A new \c CSEvent object
 165 |  */
 166 | function CSEvent(type, scope, appId, extensionId)
 167 | {
 168 |     this.type = type;
 169 |     this.scope = scope;
 170 |     this.appId = appId;
 171 |     this.extensionId = extensionId;
 172 | }
 173 | 
 174 | /** Event-specific data. */
 175 | CSEvent.prototype.data = "";
 176 | 
 177 | /**
 178 |  * @class SystemPath
 179 |  * Stores operating-system-specific location constants for use in the
 180 |  * \c #CSInterface.getSystemPath() method.
 181 |  * @return A new \c SystemPath object.
 182 |  */
 183 | function SystemPath()
 184 | {
 185 | }
 186 | 
 187 | /** The path to user data.  */
 188 | SystemPath.USER_DATA = "userData";
 189 | 
 190 | /** The path to common files for Adobe applications.  */
 191 | SystemPath.COMMON_FILES = "commonFiles";
 192 | 
 193 | /** The path to the user's default document folder.  */
 194 | SystemPath.MY_DOCUMENTS = "myDocuments";
 195 | 
 196 | /** @deprecated. Use \c #SystemPath.Extension.  */
 197 | SystemPath.APPLICATION = "application";
 198 | 
 199 | /** The path to current extension.  */
 200 | SystemPath.EXTENSION = "extension";
 201 | 
 202 | /** The path to hosting application's executable.  */
 203 | SystemPath.HOST_APPLICATION = "hostApplication";
 204 | 
 205 | /**
 206 |  * @class ColorType
 207 |  * Stores color-type constants.
 208 |  */
 209 | function ColorType()
 210 | {
 211 | }
 212 | 
 213 | /** RGB color type. */
 214 | ColorType.RGB = "rgb";
 215 | 
 216 | /** Gradient color type. */
 217 | ColorType.GRADIENT = "gradient";
 218 | 
 219 | /** Null color type. */
 220 | ColorType.NONE = "none";
 221 | 
 222 | /**
 223 |  * @class RGBColor
 224 |  * Stores an RGB color with red, green, blue, and alpha values.
 225 |  * All values are in the range [0.0 to 255.0]. Invalid numeric values are
 226 |  * converted to numbers within this range.
 227 |  *
 228 |  * @param red   The red value, in the range [0.0 to 255.0].
 229 |  * @param green The green value, in the range [0.0 to 255.0].
 230 |  * @param blue  The blue value, in the range [0.0 to 255.0].
 231 |  * @param alpha The alpha (transparency) value, in the range [0.0 to 255.0].
 232 |  *      The default, 255.0, means that the color is fully opaque.
 233 |  *
 234 |  * @return A new RGBColor object.
 235 |  */
 236 | function RGBColor(red, green, blue, alpha)
 237 | {
 238 |     this.red = red;
 239 |     this.green = green;
 240 |     this.blue = blue;
 241 |     this.alpha = alpha;
 242 | }
 243 | 
 244 | /**
 245 |  * @class Direction
 246 |  * A point value  in which the y component is 0 and the x component
 247 |  * is positive or negative for a right or left direction,
 248 |  * or the x component is 0 and the y component is positive or negative for
 249 |  * an up or down direction.
 250 |  *
 251 |  * @param x     The horizontal component of the point.
 252 |  * @param y     The vertical component of the point.
 253 |  *
 254 |  * @return A new \c Direction object.
 255 |  */
 256 | function Direction(x, y)
 257 | {
 258 |     this.x = x;
 259 |     this.y = y;
 260 | }
 261 | 
 262 | /**
 263 |  * @class GradientStop
 264 |  * Stores gradient stop information.
 265 |  *
 266 |  * @param offset   The offset of the gradient stop, in the range [0.0 to 1.0].
 267 |  * @param rgbColor The color of the gradient at this point, an \c #RGBColor object.
 268 |  *
 269 |  * @return GradientStop object.
 270 |  */
 271 | function GradientStop(offset, rgbColor)
 272 | {
 273 |     this.offset = offset;
 274 |     this.rgbColor = rgbColor;
 275 | }
 276 | 
 277 | /**
 278 |  * @class GradientColor
 279 |  * Stores gradient color information.
 280 |  *
 281 |  * @param type          The gradient type, must be "linear".
 282 |  * @param direction     A \c #Direction object for the direction of the gradient
 283 |                 (up, down, right, or left).
 284 |  * @param numStops          The number of stops in the gradient.
 285 |  * @param gradientStopList  An array of \c #GradientStop objects.
 286 |  *
 287 |  * @return A new \c GradientColor object.
 288 |  */
 289 | function GradientColor(type, direction, numStops, arrGradientStop)
 290 | {
 291 |     this.type = type;
 292 |     this.direction = direction;
 293 |     this.numStops = numStops;
 294 |     this.arrGradientStop = arrGradientStop;
 295 | }
 296 | 
 297 | /**
 298 |  * @class UIColor
 299 |  * Stores color information, including the type, anti-alias level, and specific color
 300 |  * values in a color object of an appropriate type.
 301 |  *
 302 |  * @param type          The color type, 1 for "rgb" and 2 for "gradient".
 303 |                 The supplied color object must correspond to this type.
 304 |  * @param antialiasLevel    The anti-alias level constant.
 305 |  * @param color         A \c #RGBColor or \c #GradientColor object containing specific color information.
 306 |  *
 307 |  * @return A new \c UIColor object.
 308 |  */
 309 | function UIColor(type, antialiasLevel, color)
 310 | {
 311 |     this.type = type;
 312 |     this.antialiasLevel = antialiasLevel;
 313 |     this.color = color;
 314 | }
 315 | 
 316 | /**
 317 |  * @class AppSkinInfo
 318 |  * Stores window-skin properties, such as color and font. All color parameter values are \c #UIColor objects except that systemHighlightColor is \c #RGBColor object.
 319 |  *
 320 |  * @param baseFontFamily        The base font family of the application.
 321 |  * @param baseFontSize          The base font size of the application.
 322 |  * @param appBarBackgroundColor     The application bar background color.
 323 |  * @param panelBackgroundColor      The background color of the extension panel.
 324 |  * @param appBarBackgroundColorSRGB     The application bar background color, as sRGB.
 325 |  * @param panelBackgroundColorSRGB      The background color of the extension panel, as sRGB.
 326 |  * @param systemHighlightColor          The highlight color of the extension panel, if provided by the host application. Otherwise, the operating-system highlight color.
 327 |  *
 328 |  * @return AppSkinInfo object.
 329 |  */
 330 | function AppSkinInfo(baseFontFamily, baseFontSize, appBarBackgroundColor, panelBackgroundColor, appBarBackgroundColorSRGB, panelBackgroundColorSRGB, systemHighlightColor)
 331 | {
 332 |     this.baseFontFamily = baseFontFamily;
 333 |     this.baseFontSize = baseFontSize;
 334 |     this.appBarBackgroundColor = appBarBackgroundColor;
 335 |     this.panelBackgroundColor = panelBackgroundColor;
 336 |     this.appBarBackgroundColorSRGB = appBarBackgroundColorSRGB;
 337 |     this.panelBackgroundColorSRGB = panelBackgroundColorSRGB;
 338 |     this.systemHighlightColor = systemHighlightColor;
 339 | }
 340 | 
 341 | /**
 342 |  * @class HostEnvironment
 343 |  * Stores information about the environment in which the extension is loaded.
 344 |  *
 345 |  * @param appName   The application's name.
 346 |  * @param appVersion    The application's version.
 347 |  * @param appLocale The application's current license locale.
 348 |  * @param appUILocale   The application's current UI locale.
 349 |  * @param appId     The application's unique identifier.
 350 |  * @param isAppOnline  True if the application is currently online.
 351 |  * @param appSkinInfo   An \c #AppSkinInfo object containing the application's default color and font styles.
 352 |  *
 353 |  * @return A new \c HostEnvironment object.
 354 |  */
 355 | function HostEnvironment(appName, appVersion, appLocale, appUILocale, appId, isAppOnline, appSkinInfo)
 356 | {
 357 |     this.appName = appName;
 358 |     this.appVersion = appVersion;
 359 |     this.appLocale = appLocale;
 360 |     this.appUILocale = appUILocale;
 361 |     this.appId = appId;
 362 |     this.isAppOnline = isAppOnline;
 363 |     this.appSkinInfo = appSkinInfo;
 364 | }
 365 | 
 366 | /**
 367 |  * @class HostCapabilities
 368 |  * Stores information about the host capabilities.
 369 |  *
 370 |  * @param EXTENDED_PANEL_MENU True if the application supports panel menu.
 371 |  * @param EXTENDED_PANEL_ICONS True if the application supports panel icon.
 372 |  * @param DELEGATE_APE_ENGINE True if the application supports delegated APE engine.
 373 |  * @param SUPPORT_HTML_EXTENSIONS True if the application supports HTML extensions.
 374 |  * @param DISABLE_FLASH_EXTENSIONS True if the application disables FLASH extensions.
 375 |  *
 376 |  * @return A new \c HostCapabilities object.
 377 |  */
 378 | function HostCapabilities(EXTENDED_PANEL_MENU, EXTENDED_PANEL_ICONS, DELEGATE_APE_ENGINE, SUPPORT_HTML_EXTENSIONS, DISABLE_FLASH_EXTENSIONS)
 379 | {
 380 |     this.EXTENDED_PANEL_MENU = EXTENDED_PANEL_MENU;
 381 |     this.EXTENDED_PANEL_ICONS = EXTENDED_PANEL_ICONS;
 382 |     this.DELEGATE_APE_ENGINE = DELEGATE_APE_ENGINE;
 383 |     this.SUPPORT_HTML_EXTENSIONS = SUPPORT_HTML_EXTENSIONS;
 384 |     this.DISABLE_FLASH_EXTENSIONS = DISABLE_FLASH_EXTENSIONS; // Since 5.0.0
 385 | }
 386 | 
 387 | /**
 388 |  * @class ApiVersion
 389 |  * Stores current api version.
 390 |  *
 391 |  * Since 4.2.0
 392 |  *
 393 |  * @param major  The major version
 394 |  * @param minor  The minor version.
 395 |  * @param micro  The micro version.
 396 |  *
 397 |  * @return ApiVersion object.
 398 |  */
 399 | function ApiVersion(major, minor, micro)
 400 | {
 401 |     this.major = major;
 402 |     this.minor = minor;
 403 |     this.micro = micro;
 404 | }
 405 | 
 406 | /**
 407 |  * @class MenuItemStatus
 408 |  * Stores flyout menu item status
 409 |  *
 410 |  * Since 5.2.0
 411 |  *
 412 |  * @param menuItemLabel  The menu item label.
 413 |  * @param enabled        True if user wants to enable the menu item.
 414 |  * @param checked        True if user wants to check the menu item.
 415 |  *
 416 |  * @return MenuItemStatus object.
 417 |  */
 418 | function MenuItemStatus(menuItemLabel, enabled, checked)
 419 | {
 420 |     this.menuItemLabel = menuItemLabel;
 421 |     this.enabled = enabled;
 422 |     this.checked = checked;
 423 | }
 424 | 
 425 | /**
 426 |  * @class ContextMenuItemStatus
 427 |  * Stores the status of the context menu item.
 428 |  *
 429 |  * Since 5.2.0
 430 |  *
 431 |  * @param menuItemID     The menu item id.
 432 |  * @param enabled        True if user wants to enable the menu item.
 433 |  * @param checked        True if user wants to check the menu item.
 434 |  *
 435 |  * @return MenuItemStatus object.
 436 |  */
 437 | function ContextMenuItemStatus(menuItemID, enabled, checked)
 438 | {
 439 |     this.menuItemID = menuItemID;
 440 |     this.enabled = enabled;
 441 |     this.checked = checked;
 442 | }
 443 | //------------------------------ CSInterface ----------------------------------
 444 | 
 445 | /**
 446 |  * @class CSInterface
 447 |  * This is the entry point to the CEP extensibility infrastructure.
 448 |  * Instantiate this object and use it to:
 449 |  * <ul>
 450 |  * <li>Access information about the host application in which an extension is running</li>
 451 |  * <li>Launch an extension</li>
 452 |  * <li>Register interest in event notifications, and dispatch events</li>
 453 |  * </ul>
 454 |  *
 455 |  * @return A new \c CSInterface object
 456 |  */
 457 | function CSInterface()
 458 | {
 459 | }
 460 | 
 461 | /**
 462 |  * User can add this event listener to handle native application theme color changes.
 463 |  * Callback function gives extensions ability to fine-tune their theme color after the
 464 |  * global theme color has been changed.
 465 |  * The callback function should be like below:
 466 |  *
 467 |  * @example
 468 |  * // event is a CSEvent object, but user can ignore it.
 469 |  * function OnAppThemeColorChanged(event)
 470 |  * {
 471 |  *    // Should get a latest HostEnvironment object from application.
 472 |  *    var skinInfo = JSON.parse(window.__adobe_cep__.getHostEnvironment()).appSkinInfo;
 473 |  *    // Gets the style information such as color info from the skinInfo,
 474 |  *    // and redraw all UI controls of your extension according to the style info.
 475 |  * }
 476 |  */
 477 | CSInterface.THEME_COLOR_CHANGED_EVENT = "com.adobe.csxs.events.ThemeColorChanged";
 478 | 
 479 | /** The host environment data object. */
 480 | CSInterface.prototype.hostEnvironment = window.__adobe_cep__ ? JSON.parse(window.__adobe_cep__.getHostEnvironment()) : null;
 481 | 
 482 | /** Retrieves information about the host environment in which the
 483 |  *  extension is currently running.
 484 |  *
 485 |  *   @return A \c #HostEnvironment object.
 486 |  */
 487 | CSInterface.prototype.getHostEnvironment = function()
 488 | {
 489 |     this.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment());
 490 |     return this.hostEnvironment;
 491 | };
 492 | 
 493 | /** Loads binary file created which is located at url asynchronously
 494 | *
 495 | *@param urlName url at which binary file is located. Local files should start with 'file://'
 496 | *@param callback Optional. A callback function that returns after binary is loaded
 497 | 
 498 | *@example
 499 | * To create JS binary use command ./cep_compiler test.js test.bin
 500 | * To load JS binary asyncronously
 501 | *   var CSLib = new CSInterface();
 502 | *   CSLib.loadBinAsync(url, function () { });
 503 | */
 504 | CSInterface.prototype.loadBinAsync = function(urlName,callback)
 505 | {
 506 |     try
 507 |     {
 508 |         var xhr = new XMLHttpRequest();
 509 |         xhr.responseType = 'arraybuffer'; // make response as ArrayBuffer
 510 |         xhr.open('GET', urlName, true);
 511 |         xhr.onerror = function ()
 512 |         {
 513 |   		  console.log("Unable to load snapshot from given URL");
 514 |   		  return false;
 515 | 		};
 516 |         xhr.send();
 517 |         xhr.onload = () => {
 518 |             window.__adobe_cep__.loadSnapshot(xhr.response);
 519 |             if (typeof callback === "function")
 520 |             {
 521 |                 callback();
 522 |             }
 523 |             else if(typeof callback !== "undefined")
 524 |             {
 525 |                 console.log("Provided callback is not a function");
 526 |             }
 527 |         }
 528 |     }
 529 |     catch(err)
 530 |     {
 531 |         console.log(err);
 532 |         return false;
 533 |     }
 534 | 
 535 | 	return true;
 536 | };
 537 | 
 538 | /** Loads binary file created synchronously
 539 | *
 540 | *@param pathName the local path at which binary file is located
 541 | 
 542 | *@example
 543 | * To create JS binary use command ./cep_compiler test.js test.bin
 544 | * To load JS binary syncronously
 545 | *   var CSLib = new CSInterface();
 546 | *   CSLib.loadBinSync(path);
 547 | */
 548 | CSInterface.prototype.loadBinSync  = function(pathName)
 549 | {
 550 |     try
 551 |     {
 552 |         var OSVersion = this.getOSInformation();
 553 |         if(pathName.startsWith("file://"))
 554 |         {
 555 |             if (OSVersion.indexOf("Windows") >= 0)
 556 |             {
 557 |                pathName = pathName.replace("file:///", "");
 558 |             }
 559 |             else if (OSVersion.indexOf("Mac") >= 0)
 560 |             {
 561 |                 pathName = pathName.replace("file://", "");
 562 |             }
 563 |             window.__adobe_cep__.loadSnapshot(pathName);
 564 |             return true;
 565 |         }
 566 |     }
 567 |     catch(err)
 568 |     {
 569 |         console.log(err);
 570 |         return false;
 571 |     }
 572 |     //control should not come here
 573 |     return false;
 574 | };
 575 | 
 576 | /** Closes this extension. */
 577 | CSInterface.prototype.closeExtension = function()
 578 | {
 579 |     window.__adobe_cep__.closeExtension();
 580 | };
 581 | 
 582 | /**
 583 |  * Retrieves a path for which a constant is defined in the system.
 584 |  *
 585 |  * @param pathType The path-type constant defined in \c #SystemPath ,
 586 |  *
 587 |  * @return The platform-specific system path string.
 588 |  */
 589 | CSInterface.prototype.getSystemPath = function(pathType)
 590 | {
 591 |     var path = decodeURI(window.__adobe_cep__.getSystemPath(pathType));
 592 |     var OSVersion = this.getOSInformation();
 593 |     if (OSVersion.indexOf("Windows") >= 0)
 594 |     {
 595 |       path = path.replace("file:///", "");
 596 |     }
 597 |     else if (OSVersion.indexOf("Mac") >= 0)
 598 |     {
 599 |       path = path.replace("file://", "");
 600 |     }
 601 |     return path;
 602 | };
 603 | 
 604 | /**
 605 |  * Evaluates a JavaScript script, which can use the JavaScript DOM
 606 |  * of the host application.
 607 |  *
 608 |  * @param script    The JavaScript script.
 609 |  * @param callback  Optional. A callback function that receives the result of execution.
 610 |  *          If execution fails, the callback function receives the error message \c EvalScript_ErrMessage.
 611 |  */
 612 | CSInterface.prototype.evalScript = function(script, callback)
 613 | {
 614 |     if(callback === null || callback === undefined)
 615 |     {
 616 |         callback = function(result){};
 617 |     }
 618 |     window.__adobe_cep__.evalScript(script, callback);
 619 | };
 620 | 
 621 | /**
 622 |  * Retrieves the unique identifier of the application.
 623 |  * in which the extension is currently running.
 624 |  *
 625 |  * @return The unique ID string.
 626 |  */
 627 | CSInterface.prototype.getApplicationID = function()
 628 | {
 629 |     var appId = this.hostEnvironment.appId;
 630 |     return appId;
 631 | };
 632 | 
 633 | /**
 634 |  * Retrieves host capability information for the application
 635 |  * in which the extension is currently running.
 636 |  *
 637 |  * @return A \c #HostCapabilities object.
 638 |  */
 639 | CSInterface.prototype.getHostCapabilities = function()
 640 | {
 641 |     var hostCapabilities = JSON.parse(window.__adobe_cep__.getHostCapabilities() );
 642 |     return hostCapabilities;
 643 | };
 644 | 
 645 | /**
 646 |  * Triggers a CEP event programmatically. Yoy can use it to dispatch
 647 |  * an event of a predefined type, or of a type you have defined.
 648 |  *
 649 |  * @param event A \c CSEvent object.
 650 |  */
 651 | CSInterface.prototype.dispatchEvent = function(event)
 652 | {
 653 |     if (typeof event.data == "object")
 654 |     {
 655 |         event.data = JSON.stringify(event.data);
 656 |     }
 657 | 
 658 |     window.__adobe_cep__.dispatchEvent(event);
 659 | };
 660 | 
 661 | /**
 662 |  * Registers an interest in a CEP event of a particular type, and
 663 |  * assigns an event handler.
 664 |  * The event infrastructure notifies your extension when events of this type occur,
 665 |  * passing the event object to the registered handler function.
 666 |  *
 667 |  * @param type     The name of the event type of interest.
 668 |  * @param listener The JavaScript handler function or method.
 669 |  * @param obj      Optional, the object containing the handler method, if any.
 670 |  *         Default is null.
 671 |  */
 672 | CSInterface.prototype.addEventListener = function(type, listener, obj)
 673 | {
 674 |     window.__adobe_cep__.addEventListener(type, listener, obj);
 675 | };
 676 | 
 677 | /**
 678 |  * Removes a registered event listener.
 679 |  *
 680 |  * @param type      The name of the event type of interest.
 681 |  * @param listener  The JavaScript handler function or method that was registered.
 682 |  * @param obj       Optional, the object containing the handler method, if any.
 683 |  *          Default is null.
 684 |  */
 685 | CSInterface.prototype.removeEventListener = function(type, listener, obj)
 686 | {
 687 |     window.__adobe_cep__.removeEventListener(type, listener, obj);
 688 | };
 689 | 
 690 | /**
 691 |  * Loads and launches another extension, or activates the extension if it is already loaded.
 692 |  *
 693 |  * @param extensionId       The extension's unique identifier.
 694 |  * @param startupParams     Not currently used, pass "".
 695 |  *
 696 |  * @example
 697 |  * To launch the extension "help" with ID "HLP" from this extension, call:
 698 |  * <code>requestOpenExtension("HLP", ""); </code>
 699 |  *
 700 |  */
 701 | CSInterface.prototype.requestOpenExtension = function(extensionId, params)
 702 | {
 703 |     window.__adobe_cep__.requestOpenExtension(extensionId, params);
 704 | };
 705 | 
 706 | /**
 707 |  * Retrieves the list of extensions currently loaded in the current host application.
 708 |  * The extension list is initialized once, and remains the same during the lifetime
 709 |  * of the CEP session.
 710 |  *
 711 |  * @param extensionIds  Optional, an array of unique identifiers for extensions of interest.
 712 |  *          If omitted, retrieves data for all extensions.
 713 |  *
 714 |  * @return Zero or more \c #Extension objects.
 715 |  */
 716 | CSInterface.prototype.getExtensions = function(extensionIds)
 717 | {
 718 |     var extensionIdsStr = JSON.stringify(extensionIds);
 719 |     var extensionsStr = window.__adobe_cep__.getExtensions(extensionIdsStr);
 720 | 
 721 |     var extensions = JSON.parse(extensionsStr);
 722 |     return extensions;
 723 | };
 724 | 
 725 | /**
 726 |  * Retrieves network-related preferences.
 727 |  *
 728 |  * @return A JavaScript object containing network preferences.
 729 |  */
 730 | CSInterface.prototype.getNetworkPreferences = function()
 731 | {
 732 |     var result = window.__adobe_cep__.getNetworkPreferences();
 733 |     var networkPre = JSON.parse(result);
 734 | 
 735 |     return networkPre;
 736 | };
 737 | 
 738 | /**
 739 |  * Initializes the resource bundle for this extension with property values
 740 |  * for the current application and locale.
 741 |  * To support multiple locales, you must define a property file for each locale,
 742 |  * containing keyed display-string values for that locale.
 743 |  * See localization documentation for Extension Builder and related products.
 744 |  *
 745 |  * Keys can be in the
 746 |  * form <code>key.value="localized string"</code>, for use in HTML text elements.
 747 |  * For example, in this input element, the localized \c key.value string is displayed
 748 |  * instead of the empty \c value string:
 749 |  *
 750 |  * <code><input type="submit" value="" data-locale="key"/></code>
 751 |  *
 752 |  * @return An object containing the resource bundle information.
 753 |  */
 754 | CSInterface.prototype.initResourceBundle = function()
 755 | {
 756 |     var resourceBundle = JSON.parse(window.__adobe_cep__.initResourceBundle());
 757 |     var resElms = document.querySelectorAll('[data-locale]');
 758 |     for (var n = 0; n < resElms.length; n++)
 759 |     {
 760 |        var resEl = resElms[n];
 761 |        // Get the resource key from the element.
 762 |        var resKey = resEl.getAttribute('data-locale');
 763 |        if (resKey)
 764 |        {
 765 |            // Get all the resources that start with the key.
 766 |            for (var key in resourceBundle)
 767 |            {
 768 |                if (key.indexOf(resKey) === 0)
 769 |                {
 770 |                    var resValue = resourceBundle[key];
 771 |                    if (key.length == resKey.length)
 772 |                    {
 773 |                         resEl.innerHTML = resValue;
 774 |                    }
 775 |                    else if ('.' == key.charAt(resKey.length))
 776 |                    {
 777 |                         var attrKey = key.substring(resKey.length + 1);
 778 |                         resEl[attrKey] = resValue;
 779 |                    }
 780 |                }
 781 |            }
 782 |        }
 783 |     }
 784 |     return resourceBundle;
 785 | };
 786 | 
 787 | /**
 788 |  * Writes installation information to a file.
 789 |  *
 790 |  * @return The file path.
 791 |  */
 792 | CSInterface.prototype.dumpInstallationInfo = function()
 793 | {
 794 |     return window.__adobe_cep__.dumpInstallationInfo();
 795 | };
 796 | 
 797 | /**
 798 |  * Retrieves version information for the current Operating System,
 799 |  * See http://www.useragentstring.com/pages/Chrome/ for Chrome \c navigator.userAgent values.
 800 |  *
 801 |  * @return A string containing the OS version, or "unknown Operation System".
 802 |  * If user customizes the User Agent by setting CEF command parameter "--user-agent", only
 803 |  * "Mac OS X" or "Windows" will be returned.
 804 |  */
 805 | CSInterface.prototype.getOSInformation = function()
 806 | {
 807 |     var userAgent = navigator.userAgent;
 808 | 
 809 |     if ((navigator.platform == "Win32") || (navigator.platform == "Windows"))
 810 |     {
 811 |         var winVersion = "Windows";
 812 |         var winBit = "";
 813 |         if (userAgent.indexOf("Windows") > -1)
 814 |         {
 815 |             if (userAgent.indexOf("Windows NT 5.0") > -1)
 816 |             {
 817 |                 winVersion = "Windows 2000";
 818 |             }
 819 |             else if (userAgent.indexOf("Windows NT 5.1") > -1)
 820 |             {
 821 |                 winVersion = "Windows XP";
 822 |             }
 823 |             else if (userAgent.indexOf("Windows NT 5.2") > -1)
 824 |             {
 825 |                 winVersion = "Windows Server 2003";
 826 |             }
 827 |             else if (userAgent.indexOf("Windows NT 6.0") > -1)
 828 |             {
 829 |                 winVersion = "Windows Vista";
 830 |             }
 831 |             else if (userAgent.indexOf("Windows NT 6.1") > -1)
 832 |             {
 833 |                 winVersion = "Windows 7";
 834 |             }
 835 |             else if (userAgent.indexOf("Windows NT 6.2") > -1)
 836 |             {
 837 |                 winVersion = "Windows 8";
 838 |             }
 839 |             else if (userAgent.indexOf("Windows NT 6.3") > -1)
 840 |             {
 841 |                 winVersion = "Windows 8.1";
 842 |             }
 843 |             else if (userAgent.indexOf("Windows NT 10") > -1)
 844 |             {
 845 |                 winVersion = "Windows 10";
 846 |             }
 847 | 
 848 |             if (userAgent.indexOf("WOW64") > -1 || userAgent.indexOf("Win64") > -1)
 849 |             {
 850 |                 winBit = " 64-bit";
 851 |             }
 852 |             else
 853 |             {
 854 |                 winBit = " 32-bit";
 855 |             }
 856 |         }
 857 | 
 858 |         return winVersion + winBit;
 859 |     }
 860 |     else if ((navigator.platform == "MacIntel") || (navigator.platform == "Macintosh"))
 861 |     {
 862 |         var result = "Mac OS X";
 863 | 
 864 |         if (userAgent.indexOf("Mac OS X") > -1)
 865 |         {
 866 |             result = userAgent.substring(userAgent.indexOf("Mac OS X"), userAgent.indexOf(")"));
 867 |             result = result.replace(/_/g, ".");
 868 |         }
 869 | 
 870 |         return result;
 871 |     }
 872 | 
 873 |     return "Unknown Operation System";
 874 | };
 875 | 
 876 | /**
 877 |  * Opens a page in the default system browser.
 878 |  *
 879 |  * Since 4.2.0
 880 |  *
 881 |  * @param url  The URL of the page/file to open, or the email address.
 882 |  * Must use HTTP/HTTPS/file/mailto protocol. For example:
 883 |  *   "http://www.adobe.com"
 884 |  *   "https://github.com"
 885 |  *   "file:///C:/log.txt"
 886 |  *   "mailto:[email protected]"
 887 |  *
 888 |  * @return One of these error codes:\n
 889 |  *      <ul>\n
 890 |  *          <li>NO_ERROR - 0</li>\n
 891 |  *          <li>ERR_UNKNOWN - 1</li>\n
 892 |  *          <li>ERR_INVALID_PARAMS - 2</li>\n
 893 |  *          <li>ERR_INVALID_URL - 201</li>\n
 894 |  *      </ul>\n
 895 |  */
 896 | CSInterface.prototype.openURLInDefaultBrowser = function(url)
 897 | {
 898 |     return cep.util.openURLInDefaultBrowser(url);
 899 | };
 900 | 
 901 | /**
 902 |  * Retrieves extension ID.
 903 |  *
 904 |  * Since 4.2.0
 905 |  *
 906 |  * @return extension ID.
 907 |  */
 908 | CSInterface.prototype.getExtensionID = function()
 909 | {
 910 |      return window.__adobe_cep__.getExtensionId();
 911 | };
 912 | 
 913 | /**
 914 |  * Retrieves the scale factor of screen.
 915 |  * On Windows platform, the value of scale factor might be different from operating system's scale factor,
 916 |  * since host application may use its self-defined scale factor.
 917 |  *
 918 |  * Since 4.2.0
 919 |  *
 920 |  * @return One of the following float number.
 921 |  *      <ul>\n
 922 |  *          <li> -1.0 when error occurs </li>\n
 923 |  *          <li> 1.0 means normal screen </li>\n
 924 |  *          <li> >1.0 means HiDPI screen </li>\n
 925 |  *      </ul>\n
 926 |  */
 927 | CSInterface.prototype.getScaleFactor = function()
 928 | {
 929 |     return window.__adobe_cep__.getScaleFactor();
 930 | };
 931 | 
 932 | /**
 933 |  * Retrieves the scale factor of Monitor.
 934 |  *
 935 |  * Since 8.5.0
 936 |  *
 937 |  * @return value >= 1.0f
 938 |  * only available for windows machine
 939 |  */
 940 |  if(navigator.appVersion.toLowerCase().indexOf("windows") >= 0) {
 941 |     CSInterface.prototype.getMonitorScaleFactor = function()
 942 |     {
 943 |         return window.__adobe_cep__.getMonitorScaleFactor();
 944 |     };
 945 | }
 946 | 
 947 | /**
 948 |  * Set a handler to detect any changes of scale factor. This only works on Mac.
 949 |  *
 950 |  * Since 4.2.0
 951 |  *
 952 |  * @param handler   The function to be called when scale factor is changed.
 953 |  *
 954 |  */
 955 | CSInterface.prototype.setScaleFactorChangedHandler = function(handler)
 956 | {
 957 |     window.__adobe_cep__.setScaleFactorChangedHandler(handler);
 958 | };
 959 | 
 960 | /**
 961 |  * Retrieves current API version.
 962 |  *
 963 |  * Since 4.2.0
 964 |  *
 965 |  * @return ApiVersion object.
 966 |  *
 967 |  */
 968 | CSInterface.prototype.getCurrentApiVersion = function()
 969 | {
 970 |     var apiVersion = JSON.parse(window.__adobe_cep__.getCurrentApiVersion());
 971 |     return apiVersion;
 972 | };
 973 | 
 974 | /**
 975 |  * Set panel flyout menu by an XML.
 976 |  *
 977 |  * Since 5.2.0
 978 |  *
 979 |  * Register a callback function for "com.adobe.csxs.events.flyoutMenuClicked" to get notified when a
 980 |  * menu item is clicked.
 981 |  * The "data" attribute of event is an object which contains "menuId" and "menuName" attributes.
 982 |  *
 983 |  * Register callback functions for "com.adobe.csxs.events.flyoutMenuOpened" and "com.adobe.csxs.events.flyoutMenuClosed"
 984 |  * respectively to get notified when flyout menu is opened or closed.
 985 |  *
 986 |  * @param menu     A XML string which describes menu structure.
 987 |  * An example menu XML:
 988 |  * <Menu>
 989 |  *   <MenuItem Id="menuItemId1" Label="TestExample1" Enabled="true" Checked="false"/>
 990 |  *   <MenuItem Label="TestExample2">
 991 |  *     <MenuItem Label="TestExample2-1" >
 992 |  *       <MenuItem Label="TestExample2-1-1" Enabled="false" Checked="true"/>
 993 |  *     </MenuItem>
 994 |  *     <MenuItem Label="TestExample2-2" Enabled="true" Checked="true"/>
 995 |  *   </MenuItem>
 996 |  *   <MenuItem Label="---" />
 997 |  *   <MenuItem Label="TestExample3" Enabled="false" Checked="false"/>
 998 |  * </Menu>
 999 |  *
1000 |  */
1001 | CSInterface.prototype.setPanelFlyoutMenu = function(menu)
1002 | {
1003 |     if ("string" != typeof menu)
1004 |     {
1005 |         return;
1006 |     }
1007 | 
1008 |     window.__adobe_cep__.invokeSync("setPanelFlyoutMenu", menu);
1009 | };
1010 | 
1011 | /**
1012 |  * Updates a menu item in the extension window's flyout menu, by setting the enabled
1013 |  * and selection status.
1014 |  *
1015 |  * Since 5.2.0
1016 |  *
1017 |  * @param menuItemLabel The menu item label.
1018 |  * @param enabled       True to enable the item, false to disable it (gray it out).
1019 |  * @param checked       True to select the item, false to deselect it.
1020 |  *
1021 |  * @return false when the host application does not support this functionality (HostCapabilities.EXTENDED_PANEL_MENU is false).
1022 |  *         Fails silently if menu label is invalid.
1023 |  *
1024 |  * @see HostCapabilities.EXTENDED_PANEL_MENU
1025 |  */
1026 | CSInterface.prototype.updatePanelMenuItem = function(menuItemLabel, enabled, checked)
1027 | {
1028 |     var ret = false;
1029 |     if (this.getHostCapabilities().EXTENDED_PANEL_MENU)
1030 |     {
1031 |         var itemStatus = new MenuItemStatus(menuItemLabel, enabled, checked);
1032 |         ret = window.__adobe_cep__.invokeSync("updatePanelMenuItem", JSON.stringify(itemStatus));
1033 |     }
1034 |     return ret;
1035 | };
1036 | 
1037 | 
1038 | /**
1039 |  * Set context menu by XML string.
1040 |  *
1041 |  * Since 5.2.0
1042 |  *
1043 |  * There are a number of conventions used to communicate what type of menu item to create and how it should be handled.
1044 |  * - an item without menu ID or menu name is disabled and is not shown.
1045 |  * - if the item name is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL.
1046 |  * - Checkable attribute takes precedence over Checked attribute.
1047 |  * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item.
1048 |      The Chrome extension contextMenus API was taken as a reference.
1049 |      https://developer.chrome.com/extensions/contextMenus
1050 |  * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter.
1051 |  *
1052 |  * @param menu      A XML string which describes menu structure.
1053 |  * @param callback  The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item.
1054 |  *
1055 |  * @description An example menu XML:
1056 |  * <Menu>
1057 |  *   <MenuItem Id="menuItemId1" Label="TestExample1" Enabled="true" Checkable="true" Checked="false" Icon="./image/small_16X16.png"/>
1058 |  *   <MenuItem Id="menuItemId2" Label="TestExample2">
1059 |  *     <MenuItem Id="menuItemId2-1" Label="TestExample2-1" >
1060 |  *       <MenuItem Id="menuItemId2-1-1" Label="TestExample2-1-1" Enabled="false" Checkable="true" Checked="true"/>
1061 |  *     </MenuItem>
1062 |  *     <MenuItem Id="menuItemId2-2" Label="TestExample2-2" Enabled="true" Checkable="true" Checked="true"/>
1063 |  *   </MenuItem>
1064 |  *   <MenuItem Label="---" />
1065 |  *   <MenuItem Id="menuItemId3" Label="TestExample3" Enabled="false" Checkable="true" Checked="false"/>
1066 |  * </Menu>
1067 |  */
1068 | CSInterface.prototype.setContextMenu = function(menu, callback)
1069 | {
1070 |     if ("string" != typeof menu)
1071 |     {
1072 |         return;
1073 |     }
1074 | 
1075 |     window.__adobe_cep__.invokeAsync("setContextMenu", menu, callback);
1076 | };
1077 | 
1078 | /**
1079 |  * Set context menu by JSON string.
1080 |  *
1081 |  * Since 6.0.0
1082 |  *
1083 |  * There are a number of conventions used to communicate what type of menu item to create and how it should be handled.
1084 |  * - an item without menu ID or menu name is disabled and is not shown.
1085 |  * - if the item label is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL.
1086 |  * - Checkable attribute takes precedence over Checked attribute.
1087 |  * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item.
1088 |      The Chrome extension contextMenus API was taken as a reference.
1089 |  * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter.
1090 |      https://developer.chrome.com/extensions/contextMenus
1091 |  *
1092 |  * @param menu      A JSON string which describes menu structure.
1093 |  * @param callback  The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item.
1094 |  *
1095 |  * @description An example menu JSON:
1096 |  *
1097 |  * {
1098 |  *      "menu": [
1099 |  *          {
1100 |  *              "id": "menuItemId1",
1101 |  *              "label": "testExample1",
1102 |  *              "enabled": true,
1103 |  *              "checkable": true,
1104 |  *              "checked": false,
1105 |  *              "icon": "./image/small_16X16.png"
1106 |  *          },
1107 |  *          {
1108 |  *              "id": "menuItemId2",
1109 |  *              "label": "testExample2",
1110 |  *              "menu": [
1111 |  *                  {
1112 |  *                      "id": "menuItemId2-1",
1113 |  *                      "label": "testExample2-1",
1114 |  *                      "menu": [
1115 |  *                          {
1116 |  *                              "id": "menuItemId2-1-1",
1117 |  *                              "label": "testExample2-1-1",
1118 |  *                              "enabled": false,
1119 |  *                              "checkable": true,
1120 |  *                              "checked": true
1121 |  *                          }
1122 |  *                      ]
1123 |  *                  },
1124 |  *                  {
1125 |  *                      "id": "menuItemId2-2",
1126 |  *                      "label": "testExample2-2",
1127 |  *                      "enabled": true,
1128 |  *                      "checkable": true,
1129 |  *                      "checked": true
1130 |  *                  }
1131 |  *              ]
1132 |  *          },
1133 |  *          {
1134 |  *              "label": "---"
1135 |  *          },
1136 |  *          {
1137 |  *              "id": "menuItemId3",
1138 |  *              "label": "testExample3",
1139 |  *              "enabled": false,
1140 |  *              "checkable": true,
1141 |  *              "checked": false
1142 |  *          }
1143 |  *      ]
1144 |  *  }
1145 |  *
1146 |  */
1147 | CSInterface.prototype.setContextMenuByJSON = function(menu, callback)
1148 | {
1149 |     if ("string" != typeof menu)
1150 |     {
1151 |         return;
1152 |     }
1153 | 
1154 |     window.__adobe_cep__.invokeAsync("setContextMenuByJSON", menu, callback);
1155 | };
1156 | 
1157 | /**
1158 |  * Updates a context menu item by setting the enabled and selection status.
1159 |  *
1160 |  * Since 5.2.0
1161 |  *
1162 |  * @param menuItemID    The menu item ID.
1163 |  * @param enabled       True to enable the item, false to disable it (gray it out).
1164 |  * @param checked       True to select the item, false to deselect it.
1165 |  */
1166 | CSInterface.prototype.updateContextMenuItem = function(menuItemID, enabled, checked)
1167 | {
1168 |     var itemStatus = new ContextMenuItemStatus(menuItemID, enabled, checked);
1169 |     ret = window.__adobe_cep__.invokeSync("updateContextMenuItem", JSON.stringify(itemStatus));
1170 | };
1171 | 
1172 | /**
1173 |  * Get the visibility status of an extension window.
1174 |  *
1175 |  * Since 6.0.0
1176 |  *
1177 |  * @return true if the extension window is visible; false if the extension window is hidden.
1178 |  */
1179 | CSInterface.prototype.isWindowVisible = function()
1180 | {
1181 |     return window.__adobe_cep__.invokeSync("isWindowVisible", "");
1182 | };
1183 | 
1184 | /**
1185 |  * Resize extension's content to the specified dimensions.
1186 |  * 1. Works with modal and modeless extensions in all Adobe products.
1187 |  * 2. Extension's manifest min/max size constraints apply and take precedence.
1188 |  * 3. For panel extensions
1189 |  *    3.1 This works in all Adobe products except:
1190 |  *        * Premiere Pro
1191 |  *        * Prelude
1192 |  *        * After Effects
1193 |  *    3.2 When the panel is in certain states (especially when being docked),
1194 |  *        it will not change to the desired dimensions even when the
1195 |  *        specified size satisfies min/max constraints.
1196 |  *
1197 |  * Since 6.0.0
1198 |  *
1199 |  * @param width  The new width
1200 |  * @param height The new height
1201 |  */
1202 | CSInterface.prototype.resizeContent = function(width, height)
1203 | {
1204 |     window.__adobe_cep__.resizeContent(width, height);
1205 | };
1206 | 
1207 | /**
1208 |  * Register the invalid certificate callback for an extension.
1209 |  * This callback will be triggered when the extension tries to access the web site that contains the invalid certificate on the main frame.
1210 |  * But if the extension does not call this function and tries to access the web site containing the invalid certificate, a default error page will be shown.
1211 |  *
1212 |  * Since 6.1.0
1213 |  *
1214 |  * @param callback the callback function
1215 |  */
1216 | CSInterface.prototype.registerInvalidCertificateCallback = function(callback)
1217 | {
1218 |     return window.__adobe_cep__.registerInvalidCertificateCallback(callback);
1219 | };
1220 | 
1221 | /**
1222 |  * Register an interest in some key events to prevent them from being sent to the host application.
1223 |  *
1224 |  * This function works with modeless extensions and panel extensions.
1225 |  * Generally all the key events will be sent to the host application for these two extensions if the current focused element
1226 |  * is not text input or dropdown,
1227 |  * If you want to intercept some key events and want them to be handled in the extension, please call this function
1228 |  * in advance to prevent them being sent to the host application.
1229 |  *
1230 |  * Since 6.1.0
1231 |  *
1232 |  * @param keyEventsInterest      A JSON string describing those key events you are interested in. A null object or
1233 |                                  an empty string will lead to removing the interest
1234 |  *
1235 |  * This JSON string should be an array, each object has following keys:
1236 |  *
1237 |  * keyCode:  [Required] represents an OS system dependent virtual key code identifying
1238 |  *           the unmodified value of the pressed key.
1239 |  * ctrlKey:  [optional] a Boolean that indicates if the control key was pressed (true) or not (false) when the event occurred.
1240 |  * altKey:   [optional] a Boolean that indicates if the alt key was pressed (true) or not (false) when the event occurred.
1241 |  * shiftKey: [optional] a Boolean that indicates if the shift key was pressed (true) or not (false) when the event occurred.
1242 |  * metaKey:  [optional] (Mac Only) a Boolean that indicates if the Meta key was pressed (true) or not (false) when the event occurred.
1243 |  *                      On Macintosh keyboards, this is the command key. To detect Windows key on Windows, please use keyCode instead.
1244 |  * An example JSON string:
1245 |  *
1246 |  * [
1247 |  *     {
1248 |  *         "keyCode": 48
1249 |  *     },
1250 |  *     {
1251 |  *         "keyCode": 123,
1252 |  *         "ctrlKey": true
1253 |  *     },
1254 |  *     {
1255 |  *         "keyCode": 123,
1256 |  *         "ctrlKey": true,
1257 |  *         "metaKey": true
1258 |  *     }
1259 |  * ]
1260 |  *
1261 |  */
1262 | CSInterface.prototype.registerKeyEventsInterest = function(keyEventsInterest)
1263 | {
1264 |     return window.__adobe_cep__.registerKeyEventsInterest(keyEventsInterest);
1265 | };
1266 | 
1267 | /**
1268 |  * Set the title of the extension window.
1269 |  * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver.
1270 |  *
1271 |  * Since 6.1.0
1272 |  *
1273 |  * @param title The window title.
1274 |  */
1275 | CSInterface.prototype.setWindowTitle = function(title)
1276 | {
1277 |     window.__adobe_cep__.invokeSync("setWindowTitle", title);
1278 | };
1279 | 
1280 | /**
1281 |  * Get the title of the extension window.
1282 |  * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver.
1283 |  *
1284 |  * Since 6.1.0
1285 |  *
1286 |  * @return The window title.
1287 |  */
1288 | CSInterface.prototype.getWindowTitle = function()
1289 | {
1290 |     return window.__adobe_cep__.invokeSync("getWindowTitle", "");
1291 | };
1292 | 
```

--------------------------------------------------------------------------------
/mcp/ps-mcp.py:
--------------------------------------------------------------------------------

```python
   1 | # MIT License
   2 | #
   3 | # Copyright (c) 2025 Mike Chambers
   4 | #
   5 | # Permission is hereby granted, free of charge, to any person obtaining a copy
   6 | # of this software and associated documentation files (the "Software"), to deal
   7 | # in the Software without restriction, including without limitation the rights
   8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   9 | # copies of the Software, and to permit persons to whom the Software is
  10 | # furnished to do so, subject to the following conditions:
  11 | #
  12 | # The above copyright notice and this permission notice shall be included in all
  13 | # copies or substantial portions of the Software.
  14 | #
  15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21 | # SOFTWARE.
  22 | 
  23 | from mcp.server.fastmcp import FastMCP, Image
  24 | from core import init, sendCommand, createCommand
  25 | from fonts import list_all_fonts_postscript
  26 | import numpy as np
  27 | import base64
  28 | import socket_client
  29 | import sys
  30 | import os
  31 | 
  32 | FONT_LIMIT = 1000 #max number of font names to return to AI
  33 | 
  34 | #logger.log(f"Python path: {sys.executable}")
  35 | #logger.log(f"PYTHONPATH: {os.environ.get('PYTHONPATH')}")
  36 | #logger.log(f"Current working directory: {os.getcwd()}")
  37 | #logger.log(f"Sys.path: {sys.path}")
  38 | 
  39 | 
  40 | mcp_name = "Adobe Photoshop MCP Server"
  41 | mcp = FastMCP(mcp_name, log_level="ERROR")
  42 | print(f"{mcp_name} running on stdio", file=sys.stderr)
  43 | 
  44 | APPLICATION = "photoshop"
  45 | PROXY_URL = 'http://localhost:3001'
  46 | PROXY_TIMEOUT = 20
  47 | 
  48 | socket_client.configure(
  49 |     app=APPLICATION, 
  50 |     url=PROXY_URL,
  51 |     timeout=PROXY_TIMEOUT
  52 | )
  53 | 
  54 | init(APPLICATION, socket_client)
  55 | 
  56 | @mcp.tool()
  57 | def set_active_document(document_id:int):
  58 |     """
  59 |     Sets the document with the specified ID to the active document in Photoshop
  60 | 
  61 |     Args:
  62 |         document_id (int): ID for the document to set as active.
  63 |     """
  64 | 
  65 |     command = createCommand("setActiveDocument", {
  66 |         "documentId":document_id
  67 |     })
  68 | 
  69 |     return sendCommand(command)
  70 | 
  71 | @mcp.tool()
  72 | def get_documents():
  73 |     """
  74 |     Returns information on the documents currently open in Photoshop
  75 |     """
  76 | 
  77 |     command = createCommand("getDocuments", {
  78 |     })
  79 | 
  80 |     return sendCommand(command)
  81 | 
  82 | 
  83 | @mcp.tool()
  84 | def create_gradient_layer_style(
  85 |     layer_id: int,
  86 |     angle: int,
  87 |     type:str,
  88 |     color_stops: list,
  89 |     opacity_stops: list):
  90 |     """
  91 |     Applies gradient to active selection or entire layer if no selection exists.
  92 | 
  93 |     Color stops define transition points along the gradient (0-100), with color blending between stops. Opacity stops similarly control transparency transitions.
  94 | 
  95 |     Args:
  96 |         layer_id (int): ID for layer to apply gradient to.
  97 |         angle (int): Gradient angle (-180 to 180).
  98 |         type (str): LINEAR or RADIAL gradient.
  99 |         color_stops (list): Dictionaries defining color stops:
 100 |             - location (int): Position (0-100) along gradient.
 101 |             - color (dict): RGB values (0-255 for red/green/blue).
 102 |             - midpoint (int): Transition bias (0-100, default 50).
 103 |         opacity_stops (list): Dictionaries defining opacity stops:
 104 |             - location (int): Position (0-100) along gradient.
 105 |             - opacity (int): Level (0=transparent, 100=opaque).
 106 |             - midpoint (int): Transition bias (0-100, default 50).
 107 |     """
 108 | 
 109 |     command = createCommand("createGradientLayerStyle", {
 110 |         "layerId":layer_id,
 111 |         "angle":angle,
 112 |         "colorStops":color_stops,
 113 |         "type":type,
 114 |         "opacityStops":opacity_stops
 115 |     })
 116 | 
 117 |     return sendCommand(command)
 118 | 
 119 | 
 120 | @mcp.tool()
 121 | def duplicate_document(document_name: str):
 122 |     """Duplicates the current Photoshop Document into a new file
 123 | 
 124 | 
 125 |         Args:
 126 |             document_name (str): Name for the new document being created
 127 |     """
 128 |     
 129 |     command = createCommand("duplicateDocument", {
 130 |         "name":document_name
 131 |     })
 132 | 
 133 |     return sendCommand(command)
 134 | 
 135 | 
 136 | @mcp.tool()
 137 | def create_document(document_name: str, width: int, height:int, resolution:int, fill_color:dict = {"red":0, "green":0, "blue":0}, color_mode:str = "RGB"):
 138 |     """Creates a new Photoshop Document
 139 | 
 140 |         Layer are created from bottom up based on the order they are created in, so create background elements first and then build on top.
 141 | 
 142 |         New document will contain a layer named "Background" that is filled with the specified fill color
 143 | 
 144 |         Args:
 145 |             document_name (str): Name for the new document being created
 146 |             width (int): Width in pixels of the new document
 147 |             height (int): Height in pixels of the new document
 148 |             resolution (int): Resolution (Pixels per Inch) of the new document
 149 |             fill_color (dict): dict defining the background color fill of the new document
 150 |             color_mode (str): Color mode for the new document
 151 |     """
 152 |     
 153 |     command = createCommand("createDocument", {
 154 |         "name":document_name,
 155 |         "width":width,
 156 |         "height":height,
 157 |         "resolution":resolution,
 158 |         "fillColor":fill_color,
 159 |         "colorMode":color_mode
 160 |     })
 161 | 
 162 |     return sendCommand(command)
 163 | 
 164 | @mcp.tool()
 165 | def export_layers_as_png(layers_info: list[dict[str, str|int]]):
 166 |     """Exports multiple layers from the Photoshop document as PNG files.
 167 |     
 168 |     This function exports each specified layer as a separate PNG image file to its 
 169 |     corresponding file path. The entire layer, including transparent space will be saved.
 170 |     
 171 |     Args:
 172 |         layers_info (list[dict[str, str|int]]): A list of dictionaries containing the export information.
 173 |             Each dictionary must have the following keys:
 174 |                 - "layerId" (int): The ID of the layer to export as PNG. 
 175 |                    This layer must exist in the current document.
 176 |                 - "filePath" (str): The absolute file path including filename where the PNG
 177 |                    will be saved (e.g., "/path/to/directory/layername.png").
 178 |                    The parent directory must already exist or the export will fail.
 179 |     """
 180 |     
 181 |     command = createCommand("exportLayersAsPng", {
 182 |         "layersInfo":layers_info
 183 |     })
 184 | 
 185 |     return sendCommand(command)
 186 | 
 187 | 
 188 | 
 189 | @mcp.tool()
 190 | def save_document_as(file_path: str, file_type: str = "PSD"):
 191 |     """Saves the current Photoshop document to the specified location and format.
 192 |     
 193 |     Args:
 194 |         file_path (str): The absolute path (including filename) where the file will be saved.
 195 |             Example: "/Users/username/Documents/my_image.psd"
 196 |         file_type (str, optional): The file format to use when saving the document.
 197 |             Defaults to "PSD".
 198 |             Supported formats:
 199 |                 - "PSD": Adobe Photoshop Document (preserves layers and editability)
 200 |                 - "PNG": Portable Network Graphics (lossless compression with transparency)
 201 |                 - "JPG": Joint Photographic Experts Group (lossy compression)
 202 |     
 203 |     Returns:
 204 |         dict: Response from the Photoshop operation indicating success status, and the path that the file was saved at
 205 |     """
 206 |     
 207 |     command = createCommand("saveDocumentAs", {
 208 |         "filePath":file_path,
 209 |         "fileType":file_type
 210 |     })
 211 | 
 212 |     return sendCommand(command)
 213 | 
 214 | @mcp.tool()
 215 | def save_document():
 216 |     """Saves the current Photoshop Document
 217 |     """
 218 |     
 219 |     command = createCommand("saveDocument", {
 220 |     })
 221 | 
 222 |     return sendCommand(command)
 223 | 
 224 | @mcp.tool()
 225 | def group_layers(group_name: str, layer_ids: list[int]) -> list:
 226 |     """
 227 |     Creates a new layer group from the specified layers in Photoshop.
 228 | 
 229 |     Note: The layers will be added to the group in the order they are specified in the document, and not the order of their layerIds passed in. The group will be made at the same level as the top most layer in the layer tree.
 230 | 
 231 |     Args:
 232 |         groupName (str): The name to assign to the newly created layer group.
 233 |         layerIds (list[int]): A list of layer ids to include in the new group.
 234 | 
 235 |     Raises:
 236 |         RuntimeError: If the operation fails or times out.
 237 | 
 238 |     """
 239 | 
 240 | 
 241 |     command = createCommand("groupLayers", {
 242 |         "groupName":group_name,
 243 |         "layerIds":layer_ids
 244 |     })
 245 | 
 246 |     return sendCommand(command)
 247 | 
 248 | 
 249 | @mcp.tool()
 250 | def get_layer_image(layer_id: int):
 251 |     """Returns a jpeg of the specified layer's content as an MCP Image object that can be displayed."""
 252 | 
 253 |     command = createCommand("getLayerImage",
 254 |         {
 255 |             "layerId":layer_id
 256 |         }
 257 |     )
 258 | 
 259 |     response = sendCommand(command)
 260 | 
 261 |     if response.get('status') == 'SUCCESS' and 'response' in response:
 262 |         image_data = response['response']
 263 |         data_url = image_data.get('dataUrl')
 264 | 
 265 |         if data_url and data_url.startswith("data:image/jpeg;base64,"):
 266 |             # Strip the data URL prefix and decode the base64 JPEG bytes
 267 |             base64_data = data_url.split(",", 1)[1]
 268 |             jpeg_bytes = base64.b64decode(base64_data)
 269 | 
 270 |             return Image(data=jpeg_bytes, format="jpeg")
 271 | 
 272 |     return response
 273 | 
 274 | 
 275 | @mcp.tool()
 276 | def get_document_image():
 277 |     """Returns a jpeg of the current visible Photoshop document as an MCP Image object that can be displayed."""
 278 |     command = createCommand("getDocumentImage", {})
 279 |     response = sendCommand(command)
 280 | 
 281 |     if response.get('status') == 'SUCCESS' and 'response' in response:
 282 |         image_data = response['response']
 283 |         data_url = image_data.get('dataUrl')
 284 | 
 285 |         if data_url and data_url.startswith("data:image/jpeg;base64,"):
 286 |             # Strip the data URL prefix and decode the base64 JPEG bytes
 287 |             base64_data = data_url.split(",", 1)[1]
 288 |             jpeg_bytes = base64.b64decode(base64_data)
 289 | 
 290 |             return Image(data=jpeg_bytes, format="jpeg")
 291 | 
 292 |     return response
 293 | 
 294 | @mcp.tool()
 295 | def save_document_image_as_png(file_path: str):
 296 |     """
 297 |     Capture the Photoshop document and save as PNG file
 298 |     
 299 |     Args:
 300 |         file_path: Where to save the PNG file
 301 |         
 302 |     Returns:
 303 |         dict: Status and file info
 304 |     """
 305 |     command = createCommand("getDocumentImage", {})
 306 |     response = sendCommand(command)
 307 |     
 308 |     if response.get('format') == 'raw' and 'rawDataBase64' in response:
 309 |         try:
 310 |             # Decode raw data
 311 |             raw_bytes = base64.b64decode(response['rawDataBase64'])
 312 |             
 313 |             # Extract metadata
 314 |             width = response['width']
 315 |             height = response['height']
 316 |             components = response['components']
 317 |             
 318 |             # Convert to numpy array and reshape
 319 |             pixel_array = np.frombuffer(raw_bytes, dtype=np.uint8)
 320 |             image_array = pixel_array.reshape((height, width, components))
 321 |             
 322 |             # Create and save PNG
 323 |             mode = 'RGBA' if components == 4 else 'RGB'
 324 |             image = Image.fromarray(image_array, mode)
 325 |             image.save(file_path, 'PNG')
 326 |             
 327 |             return {
 328 |                 'status': 'success',
 329 |                 'file_path': file_path,
 330 |                 'width': width,
 331 |                 'height': height,
 332 |                 'size_bytes': os.path.getsize(file_path)
 333 |             }
 334 |             
 335 |         except Exception as e:
 336 |             return {
 337 |                 'status': 'error',
 338 |                 'error': str(e)
 339 |             }
 340 |     else:
 341 |         return {
 342 |             'status': 'error',
 343 |             'error': 'No raw image data received'
 344 |         }
 345 | 
 346 | @mcp.tool()
 347 | def get_layers() -> list:
 348 |     """Returns a nested list of dicts that contain layer info and the order they are arranged in.
 349 | 
 350 |     Args:
 351 |         None
 352 |         
 353 |     Returns:
 354 |         list: A nested list of dictionaries containing layer information and hierarchy.
 355 |             Each dict has at minimum a 'name' key with the layer name.
 356 |             If a layer has sublayers, they will be contained in a 'layers' key which contains another list of layer dicts.
 357 |             Example: [{'name': 'Group 1', 'layers': [{'name': 'Layer 1'}, {'name': 'Layer 2'}]}, {'name': 'Background'}]
 358 |     """
 359 | 
 360 |     command = createCommand("getLayers", {})
 361 | 
 362 |     return sendCommand(command)
 363 | 
 364 | 
 365 | @mcp.tool()
 366 | def place_image(
 367 |     layer_id: int,
 368 |     image_path: str
 369 | ):
 370 |     """Places the image at the specified path on the existing pixel layer with the specified id.
 371 | 
 372 |     The image will be placed on the center of the layer, and will fill the layer without changing its aspect ration (thus there may be bars at the top or bottom) 
 373 | 
 374 |     Args:
 375 |         layer_id (int): The id of the layer where the image will be placed.
 376 |         image_path (str): The file path to the image that will be placed on the layer.
 377 |     """
 378 |     
 379 |     command = createCommand("placeImage", {
 380 |         "layerId":layer_id,
 381 |         "imagePath":image_path
 382 |     })
 383 | 
 384 |     return sendCommand(command)
 385 | 
 386 | @mcp.tool()
 387 | def harmonize_layer(layer_id:int,  new_layer_name:str, rasterize_layer:bool = True):
 388 |     """Harmonizes (matches lighting and other settings) the selected layer with the background layers.
 389 | 
 390 |     The layer being harmonized should be rasterized and have some transparency.
 391 | 
 392 |     Args:
 393 |         layer_id (int): ID of the layer to be harmonizes.
 394 |         new_layer_name (str): Name for the new layer that will be created with the harmonized content
 395 |         rasterize_layer (bool): Whether the new layer should be rasterized.
 396 |             If not rasterized, the layer will remain a generative layer which
 397 |             allows the user to interact with it. True by default.
 398 |     """
 399 | 
 400 |     command = createCommand("harmonizeLayer", {
 401 |         "layerId":layer_id,
 402 |          "newLayerName":new_layer_name,
 403 |         "rasterizeLayer":rasterize_layer
 404 |     })
 405 | 
 406 |     return sendCommand(command)
 407 | 
 408 | 
 409 | @mcp.tool()
 410 | def rename_layers(
 411 |     layer_data: list[dict]
 412 | ):
 413 |     """Renames one or more layers
 414 | 
 415 |     Args:
 416 |         layer_data (list[dict]): A list of dictionaries containing layer rename information.
 417 |             Each dictionary must have the following keys:
 418 |                 - "layer_id" (int): ID of the layer to be renamed.
 419 |                 - "new_layer_name" (str): New name for the layer.
 420 |     """
 421 |     
 422 |     command = createCommand("renameLayers", {
 423 |         "layerData":layer_data
 424 |     })
 425 |     
 426 |     return sendCommand(command)
 427 | 
 428 | 
 429 | @mcp.tool()
 430 | def scale_layer(
 431 |     layer_id:int,
 432 |     width:int,
 433 |     height:int,
 434 |     anchor_position:str,
 435 |     interpolation_method:str = "AUTOMATIC"
 436 | ):
 437 |     """Scales the layer with the specified ID.
 438 | 
 439 |     Args:
 440 |         layer_id (int): ID of layer to be scaled.
 441 |         width (int): Percentage to scale horizontally.
 442 |         height (int): Percentage to scale vertically.
 443 |         anchor_position (str): The anchor position to rotate around,
 444 |         interpolation_method (str): Interpolation method to use when resampling the image
 445 |     """
 446 |     
 447 |     command = createCommand("scaleLayer", {
 448 |         "layerId":layer_id,
 449 |         "width":width,
 450 |         "height":height,
 451 |         "anchorPosition":anchor_position,
 452 |         "interpolationMethod":interpolation_method
 453 |     })
 454 | 
 455 |     return sendCommand(command)
 456 | 
 457 | 
 458 | @mcp.tool()
 459 | def rotate_layer(
 460 |     layer_id:int,
 461 |     angle:int,
 462 |     anchor_position:str,
 463 |     interpolation_method:str = "AUTOMATIC"
 464 | ):
 465 |     """Rotates the layer with the specified ID.
 466 | 
 467 |     Args:
 468 |         layer_id (int): ID of layer to be scaled.
 469 |         angle (int): Angle (-359 to 359) to rotate the layer by in degrees
 470 |         anchor_position (str): The anchor position to rotate around,
 471 |         interpolation_method (str): Interpolation method to use when resampling the image
 472 |     """
 473 |     
 474 |     command = createCommand("rotateLayer", {
 475 |         "layerId":layer_id,
 476 |         "angle":angle,
 477 |         "anchorPosition":anchor_position,
 478 |         "interpolationMethod":interpolation_method
 479 |     })
 480 | 
 481 |     return sendCommand(command)
 482 | 
 483 | 
 484 | @mcp.tool()
 485 | def flip_layer(
 486 |     layer_id:int,
 487 |     axis:str
 488 | ):
 489 |     """Flips the layer with the specified ID on the specified axis.
 490 | 
 491 |     Args:
 492 |         layer_id (int): ID of layer to be scaled.
 493 |         axis (str): The axis on which to flip the layer. Valid values are "horizontal", "vertical" or "both"
 494 |     """
 495 |     
 496 |     command = createCommand("flipLayer", {
 497 |         "layerId":layer_id,
 498 |         "axis":axis
 499 |     })
 500 | 
 501 |     return sendCommand(command)
 502 | 
 503 | 
 504 | @mcp.tool()
 505 | def delete_layer(
 506 |     layer_id:int
 507 | ):
 508 |     """Deletes the layer with the specified ID
 509 | 
 510 |     Args:
 511 |         layer_id (int): ID of the layer to be deleted
 512 |     """
 513 |     
 514 |     command = createCommand("deleteLayer", {
 515 |         "layerId":layer_id
 516 |     })
 517 | 
 518 |     return sendCommand(command)
 519 | 
 520 | 
 521 | 
 522 | @mcp.tool()
 523 | def set_layer_visibility(
 524 |     layer_id:int,
 525 |     visible:bool
 526 | ):
 527 |     """Sets the visibility of the layer with the specified ID
 528 | 
 529 |     Args:
 530 |         layer_id (int): ID of the layer to set visibility
 531 |         visible (bool): Whether the layer is visible
 532 |     """
 533 |     
 534 |     command = createCommand("setLayerVisibility", {
 535 |         "layerId":layer_id,
 536 |         "visible":visible
 537 |     })
 538 | 
 539 |     return sendCommand(command)
 540 | 
 541 | 
 542 | @mcp.tool()
 543 | def generate_image(
 544 |     layer_name:str,
 545 |     prompt:str,
 546 |     content_type:str = "none"
 547 | ):
 548 |     """Uses Adobe Firefly Generative AI to generate an image on a new layer with the specified layer name.
 549 | 
 550 |     If there is an active selection, it will use that region for the generation. Otherwise it will generate
 551 |     on the entire layer.
 552 | 
 553 |     Args:
 554 |         layer_name (str): Name for the layer that will be created and contain the generated image
 555 |         prompt (str): Prompt describing the image to be generated
 556 |         content_type (str): The type of image to be generated. Options include "photo", "art" or "none" (default)
 557 |     """
 558 |     
 559 |     command = createCommand("generateImage", {
 560 |         "layerName":layer_name,
 561 |         "prompt":prompt,
 562 |         "contentType":content_type
 563 |     })
 564 | 
 565 |     return sendCommand(command)
 566 | 
 567 | @mcp.tool()
 568 | def generative_fill(
 569 |     layer_name: str,
 570 |     prompt: str,
 571 |     layer_id: int,
 572 |     content_type: str = "none"
 573 | ):
 574 |     """Uses Adobe Firefly Generative AI to perform generative fill within the current selection.
 575 | 
 576 |     This function uses generative fill to seamlessly integrate new content into the existing image.
 577 |     It requires an active selection, and will fill that region taking into account the surrounding 
 578 |     context and layers below. The AI considers the existing content to create a natural, 
 579 |     contextually-aware fill.
 580 | 
 581 |     Args:
 582 |         layer_name (str): Name for the layer that will be created and contain the generated fill
 583 |         prompt (str): Prompt describing the content to be generated within the selection
 584 |         layer_id (int): ID of the layer to work with (though a new layer is created for the result)
 585 |         content_type (str): The type of image to be generated. Options include "photo", "art" or "none" (default)
 586 |     
 587 |     Returns:
 588 |         dict: Response from Photoshop containing the operation status and layer information
 589 |     """
 590 | 
 591 |     command = createCommand("generativeFill", {
 592 |         "layerName":layer_name,
 593 |         "prompt":prompt,
 594 |         "layerId":layer_id,
 595 |         "contentType":content_type,
 596 |     })
 597 | 
 598 |     return sendCommand(command)
 599 | 
 600 | 
 601 | @mcp.tool()
 602 | def move_layer(
 603 |     layer_id:int,
 604 |     position:str
 605 | ):
 606 |     """Moves the layer within the layer stack based on the specified position
 607 | 
 608 |     Args:
 609 |         layer_id (int): Name for the layer that will be moved
 610 |         position (str): How the layer position within the layer stack will be updated. Value values are: TOP (Place above all layers), BOTTOM (Place below all layers), UP (Move up one layer), DOWN (Move down one layer)
 611 |     """
 612 | 
 613 |     command = createCommand("moveLayer", {
 614 |         "layerId":layer_id,
 615 |         "position":position
 616 |     })
 617 | 
 618 |     return sendCommand(command)
 619 | 
 620 | @mcp.tool()
 621 | def get_document_info():
 622 |     """Retrieves information about the currently active document.
 623 | 
 624 |     Returns:
 625 |         response : An object containing the following document properties:
 626 |             - height (int): The height of the document in pixels.
 627 |             - width (int): The width of the document in pixels.
 628 |             - colorMode (str): The document's color mode as a string.
 629 |             - pixelAspectRatio (float): The pixel aspect ratio of the document.
 630 |             - resolution (float): The document's resolution (DPI).
 631 |             - path (str): The file path of the document, if saved.
 632 |             - saved (bool): Whether the document has been saved (True if it has a valid file path).
 633 |             - hasUnsavedChanges (bool): Whether the document contains unsaved changes.
 634 | 
 635 |     """
 636 | 
 637 |     command = createCommand("getDocumentInfo", {})
 638 | 
 639 |     return sendCommand(command)
 640 | 
 641 | @mcp.tool()
 642 | def crop_document():
 643 |     """Crops the document to the active selection.
 644 | 
 645 |     This function removes all content outside the selection area and resizes the document 
 646 |     so that the selection becomes the new canvas size.
 647 | 
 648 |     An active selection is required.
 649 |     """
 650 | 
 651 |     command = createCommand("cropDocument", {})
 652 | 
 653 |     return sendCommand(command)
 654 | 
 655 | @mcp.tool()
 656 | def paste_from_clipboard(layer_id: int, paste_in_place: bool = True):
 657 |     """Pastes the current clipboard contents onto the specified layer.
 658 | 
 659 |     If `paste_in_place` is True, the content will be positioned exactly where it was cut or copied from.
 660 |     If False and an active selection exists, the content will be centered within the selection.
 661 |     If no selection is active, the content will be placed at the center of the layer.
 662 | 
 663 |     Args:
 664 |         layer_id (int): The ID of the layer where the clipboard contents will be pasted.
 665 |         paste_in_place (bool): Whether to paste at the original location (True) or adjust based on selection/layer center (False).
 666 |     """
 667 | 
 668 | 
 669 |     command = createCommand("pasteFromClipboard", {
 670 |         "layerId":layer_id,
 671 |         "pasteInPlace":paste_in_place
 672 |     })
 673 | 
 674 |     return sendCommand(command)
 675 | 
 676 | @mcp.tool()
 677 | def rasterize_layer(layer_id: int):
 678 |     """Converts the specified layer into a rasterized (flat) image.
 679 | 
 680 |     This process removes any vector, text, or smart object properties, turning the layer 
 681 |     into pixel-based content.
 682 | 
 683 |     Args:
 684 |         layer_id (int): The name of the layer to rasterize.
 685 |     """
 686 | 
 687 |     command = createCommand("rasterizeLayer", {
 688 |         "layerId":layer_id
 689 |     })
 690 | 
 691 |     return sendCommand(command)
 692 | 
 693 | @mcp.tool()
 694 | def open_photoshop_file(file_path: str):
 695 |     """Opens the specified Photoshop-compatible file within Photoshop.
 696 | 
 697 |     This function attempts to open a file in Adobe Photoshop. The file must be in a 
 698 |     format compatible with Photoshop, such as PSD, TIFF, JPEG, PNG, etc.
 699 | 
 700 |     Args:
 701 |         file_path (str): Complete absolute path to the file to be opened, including filename and extension.
 702 | 
 703 |     Returns:
 704 |         dict: Response from the Photoshop operation indicating success status.
 705 |         
 706 |     Raises:
 707 |         RuntimeError: If the file doesn't exist, is not accessible, or is in an unsupported format.
 708 |     """
 709 | 
 710 |     command = createCommand("openFile", {
 711 |         "filePath":file_path
 712 |     })
 713 | 
 714 |     return sendCommand(command)
 715 | 
 716 | @mcp.tool()
 717 | def cut_selection_to_clipboard(layer_id: int):
 718 |     """Copies and removes (cuts) the selected pixels from the specified layer to the system clipboard.
 719 | 
 720 |     This function requires an active selection.
 721 | 
 722 |     Args:
 723 |         layer_id (int): The name of the layer that contains the pixels to copy and remove.
 724 |     """
 725 | 
 726 |     command = createCommand("cutSelectionToClipboard", {
 727 |         "layerId":layer_id
 728 |     })
 729 | 
 730 |     return sendCommand(command)
 731 | 
 732 | 
 733 | @mcp.tool()
 734 | def copy_merged_selection_to_clipboard():
 735 |     """Copies the selected pixels from all visible layers to the system clipboard.
 736 | 
 737 |     This function requires an active selection. If no selection is active, the operation will fail.
 738 |     The copied content will include pixel data from all visible layers within the selection area,
 739 |     effectively capturing what you see on screen.
 740 | 
 741 |     Returns:
 742 |         dict: Response from the Photoshop operation indicating success status.
 743 |         
 744 |     Raises:
 745 |         RuntimeError: If no active selection exists.
 746 |     """
 747 | 
 748 |     command = createCommand("copyMergedSelectionToClipboard", {})
 749 | 
 750 |     return sendCommand(command)
 751 | 
 752 | @mcp.tool()
 753 | def copy_selection_to_clipboard(layer_id: int):
 754 |     """Copies the selected pixels from the specified layer to the system clipboard.
 755 | 
 756 |     This function requires an active selection. If no selection is active, the operation will fail.
 757 | 
 758 |     Args:
 759 |         layer_id (int): The name of the layer that contains the pixels to copy.
 760 |         
 761 |     Returns:
 762 |         dict: Response from the Photoshop operation indicating success status.
 763 |     """
 764 | 
 765 |     command = createCommand("copySelectionToClipboard", {
 766 |         "layerId":layer_id
 767 |     })
 768 | 
 769 |     return sendCommand(command)
 770 | 
 771 | @mcp.tool()
 772 | def select_subject(layer_id: int):
 773 |     """Automatically selects the subject in the specified layer.
 774 | 
 775 |     This function identifies and selects the subject in the given image layer. 
 776 |     It returns an object containing a property named `hasActiveSelection`, 
 777 |     which indicates whether any pixels were selected (e.g., if no subject was detected).
 778 | 
 779 |     Args:
 780 |         layer_int (int): The name of that contains the image to select the subject from.
 781 |     """
 782 | 
 783 |     
 784 |     command = createCommand("selectSubject", {
 785 |         "layerId":layer_id
 786 |     })
 787 | 
 788 |     return sendCommand(command)
 789 | 
 790 | @mcp.tool()
 791 | def select_sky(layer_id: int):
 792 |     """Automatically selects the sky in the specified layer.
 793 | 
 794 |     This function identifies and selects the sky in the given image layer. 
 795 |     It returns an object containing a property named `hasActiveSelection`, 
 796 |     which indicates whether any pixels were selected (e.g., if no sky was detected).
 797 | 
 798 |     Args:
 799 |         layer_id (int): The name of that contains the image to select the sky from.
 800 |     """
 801 | 
 802 |     
 803 |     command = createCommand("selectSky", {
 804 |         "layerId":layer_id
 805 |     })
 806 | 
 807 |     return sendCommand(command)
 808 | 
 809 | 
 810 | @mcp.tool()
 811 | def get_layer_bounds(
 812 |     layer_id: int
 813 | ):
 814 |     """Returns the pixel bounds for the layer with the specified ID
 815 |     
 816 |     Args:
 817 |         layer_id (int): ID of the layer to get the bounds information from
 818 | 
 819 |     Returns:
 820 |         dict: A dictionary containing the layer bounds with the following properties:
 821 |             - left (int): The x-coordinate of the left edge of the layer
 822 |             - top (int): The y-coordinate of the top edge of the layer
 823 |             - right (int): The x-coordinate of the right edge of the layer
 824 |             - bottom (int): The y-coordinate of the bottom edge of the layer
 825 |             
 826 |     Raises:
 827 |         RuntimeError: If the layer doesn't exist or if the operation fails
 828 |     """
 829 |     
 830 |     command = createCommand("getLayerBounds", {
 831 |         "layerId":layer_id
 832 |     })
 833 | 
 834 |     return sendCommand(command)
 835 | 
 836 | @mcp.tool()
 837 | def remove_background(
 838 |     layer_id:int
 839 | ):
 840 |     """Automatically removes the background of the image in the layer with the specified ID and keeps the main subject
 841 |     
 842 |     Args:
 843 |         layer_id (int): ID of the layer to remove the background from
 844 |     """
 845 |     
 846 |     command = createCommand("removeBackground", {
 847 |         "layerId":layer_id
 848 |     })
 849 | 
 850 |     return sendCommand(command)
 851 | 
 852 | @mcp.tool()
 853 | def create_pixel_layer(
 854 |     layer_name:str,
 855 |     fill_neutral:bool,
 856 |     opacity:int = 100,
 857 |     blend_mode:str = "NORMAL",
 858 | ):
 859 |     """Creates a new pixel layer with the specified ID
 860 |     
 861 |     Args:
 862 |         layer_name (str): Name of the new layer being created
 863 |         fill_neutral (bool): Whether to fill the layer with a neutral color when applying Blend Mode.
 864 |         opacity (int): Opacity of the newly created layer
 865 |         blend_mode (str): Blend mode of the newly created layer
 866 |     """
 867 |     
 868 |     command = createCommand("createPixelLayer", {
 869 |         "layerName":layer_name,
 870 |         "opacity":opacity,
 871 |         "fillNeutral":fill_neutral,
 872 |         "blendMode":blend_mode
 873 |     })
 874 | 
 875 |     return sendCommand(command)
 876 | 
 877 | @mcp.tool()
 878 | def create_multi_line_text_layer(
 879 |     layer_name:str, 
 880 |     text:str, 
 881 |     font_size:int, 
 882 |     postscript_font_name:str, 
 883 |     opacity:int = 100,
 884 |     blend_mode:str = "NORMAL",
 885 |     text_color:dict = {"red":255, "green":255, "blue":255}, 
 886 |     position:dict = {"x": 100, "y":100},
 887 |     bounds:dict = {"top": 0, "left": 0, "bottom": 250, "right": 300},
 888 |     justification:str = "LEFT"
 889 |     ):
 890 | 
 891 |     """
 892 |     Creates a new multi-line text layer with the specified ID within the current Photoshop document.
 893 |     
 894 |     Args:
 895 |         layer_name (str): The name of the layer to be created. Can be used to select in other api calls.
 896 |         text (str): The text to include on the layer.
 897 |         font_size (int): Font size.
 898 |         postscript_font_name (string): Postscript Font Name to display the text in. Valid list available via get_option_info.
 899 |         opacity (int): Opacity for the layer specified in percent.
 900 |         blend_mode (str): Blend Mode for the layer. Valid list available via get_option_info
 901 |         text_color (dict): Color of the text expressed in Red, Green, Blue values between 0 and 255
 902 |         position (dict): Position (dict with x, y values) where the text will be placed in the layer. Based on bottom left point of the text.
 903 |         bounds (dict): text bounding box
 904 |         justification (str): text justification. Valid list available via get_option_info.
 905 |     """
 906 | 
 907 |     command = createCommand("createMultiLineTextLayer", {
 908 |         "layerName":layer_name,
 909 |         "contents":text,
 910 |         "fontSize": font_size,
 911 |         "opacity":opacity,
 912 |         "position":position,
 913 |         "fontName":postscript_font_name,
 914 |         "textColor":text_color,
 915 |         "blendMode":blend_mode,
 916 |         "bounds":bounds,
 917 |         "justification":justification
 918 |     })
 919 | 
 920 |     return sendCommand(command)
 921 | 
 922 | 
 923 | @mcp.tool()
 924 | def create_single_line_text_layer(
 925 |     layer_name:str, 
 926 |     text:str, 
 927 |     font_size:int, 
 928 |     postscript_font_name:str, 
 929 |     opacity:int = 100,
 930 |     blend_mode:str = "NORMAL",
 931 |     text_color:dict = {"red":255, "green":255, "blue":255}, 
 932 |     position:dict = {"x": 100, "y":100}
 933 |     ):
 934 | 
 935 |     """
 936 |     Create a new single line text layer with the specified ID within the current Photoshop document.
 937 |     
 938 |      Args:
 939 |         layer_name (str): The name of the layer to be created. Can be used to select in other api calls.
 940 |         text (str): The text to include on the layer.
 941 |         font_size (int): Font size.
 942 |         postscript_font_name (string): Postscript Font Name to display the text in. Valid list available via get_option_info.
 943 |         opacity (int): Opacity for the layer specified in percent.
 944 |         blend_mode (str): Blend Mode for the layer. Valid list available via get_option_info
 945 |         text_color (dict): Color of the text expressed in Red, Green, Blue values between 0 and 255
 946 |         position (dict): Position (dict with x, y values) where the text will be placed in the layer. Based on bottom left point of the text.
 947 |     """
 948 | 
 949 |     command = createCommand("createSingleLineTextLayer", {
 950 |         "layerName":layer_name,
 951 |         "contents":text,
 952 |         "fontSize": font_size,
 953 |         "opacity":opacity,
 954 |         "position":position,
 955 |         "fontName":postscript_font_name,
 956 |         "textColor":text_color,
 957 |         "blendMode":blend_mode
 958 |     })
 959 | 
 960 |     return sendCommand(command)
 961 | 
 962 | @mcp.tool()
 963 | def edit_text_layer(
 964 |     layer_id:int, 
 965 |     text:str = None,
 966 |     font_size:int = None,
 967 |     postscript_font_name:str = None, 
 968 |     text_color:dict = None,
 969 |     ):
 970 | 
 971 |     """
 972 |     Edits the text content of an existing text layer in the current Photoshop document.
 973 |     
 974 |     Args:
 975 |         layer_id (int): The ID of the existing text layer to edit.
 976 |         text (str): The new text content to replace the current text in the layer. If None, text will not be changed.
 977 |         font_size (int): Font size. If None, size will not be changed.
 978 |         postscript_font_name (string): Postscript Font Name to display the text in. Valid list available via get_option_info. If None, font will not will not be changed.
 979 |         text_color (dict): Color of the text expressed in Red, Green, Blue values between 0 and 255 in format of {"red":255, "green":255, "blue":255}. If None, color will not be changed
 980 |     """
 981 | 
 982 |     command = createCommand("editTextLayer", {
 983 |         "layerId":layer_id,
 984 |         "contents":text,
 985 |         "fontSize": font_size,
 986 |         "fontName":postscript_font_name,
 987 |         "textColor":text_color
 988 |     })
 989 | 
 990 |     return sendCommand(command)
 991 | 
 992 | 
 993 | 
 994 | @mcp.tool()
 995 | def translate_layer(
 996 |     layer_id: int,
 997 |     x_offset:int = 0,
 998 |     y_offset:int = 0
 999 |     ):
1000 | 
1001 |     """
1002 |         Moves the layer with the specified ID on the X and Y axis by the specified number of pixels.
1003 | 
1004 |     Args:
1005 |         layer_name (str): The name of the layer that should be moved.
1006 |         x_offset (int): Amount to move on the horizontal axis. Negative values move the layer left, positive values right
1007 |         y_offset (int): Amount to move on the vertical axis. Negative values move the layer down, positive values up
1008 |     """
1009 |     
1010 |     command = createCommand("translateLayer", {
1011 |         "layerId":layer_id,
1012 |         "xOffset":x_offset,
1013 |         "yOffset":y_offset
1014 |     })
1015 | 
1016 |     return sendCommand(command)
1017 | 
1018 | @mcp.tool()
1019 | def remove_layer_mask(
1020 |     layer_id: int
1021 |     ):
1022 | 
1023 |     """Removes the layer mask from the specified layer.
1024 | 
1025 |     Args:
1026 |         None
1027 |     """
1028 |     
1029 |     command = createCommand("removeLayerMask", {
1030 |         "layerId":layer_id
1031 |     })
1032 | 
1033 |     return sendCommand(command)
1034 | 
1035 | @mcp.tool()
1036 | def add_layer_mask_from_selection(
1037 |     layer_id: int
1038 |     ):
1039 | 
1040 |     """Creates a layer mask on the specified layer defined by the active selection.
1041 |     
1042 |     This function takes the current active selection in the document and converts it into a layer mask
1043 |     for the specified layer. Selected areas will be visible, while non-selected areas will be hidden.
1044 |     An active selection must exist before calling this function.
1045 | 
1046 |     Args:
1047 |         layer_name (str): The name of the layer to which the mask will be applied
1048 |     """
1049 |     
1050 |     command = createCommand("addLayerMask", {
1051 |         "layerId":layer_id
1052 |     })
1053 | 
1054 |     return sendCommand(command)
1055 | 
1056 | @mcp.tool()
1057 | def set_layer_properties(
1058 |     layer_id: int,
1059 |     blend_mode: str = "NORMAL",
1060 |     layer_opacity: int = 100,
1061 |     fill_opacity: int = 100,
1062 |     is_clipping_mask: bool = False
1063 |     ):
1064 | 
1065 |     """Sets the blend mode and opacity properties on the layer with the specified ID
1066 | 
1067 |     Args:
1068 |         layer_id (int): The ID of the layer whose properties should be updated
1069 |         blend_mode (str): The blend mode for the layer
1070 |         layer_opacity (int): The opacity for the layer (0 - 100)
1071 |         fill_opacity (int): The fill opacity for the layer (0 - 100). Will ignore anny effects that have been applied to the layer.
1072 |         is_clipping_mask (bool): A boolean indicating whether this layer will be clipped to (masked by) the layer below it
1073 |     """
1074 |     
1075 |     command = createCommand("setLayerProperties", {
1076 |         "layerId":layer_id,
1077 |         "blendMode":blend_mode,
1078 |         "layerOpacity":layer_opacity,
1079 |         "fillOpacity":fill_opacity,
1080 |         "isClippingMask":is_clipping_mask
1081 |     })
1082 | 
1083 |     return sendCommand(command)
1084 | 
1085 | @mcp.tool()
1086 | def fill_selection(
1087 |     layer_id: int,
1088 |     color:dict = {"red":255, "green":0, "blue":0},
1089 |     blend_mode:str = "NORMAL",
1090 |     opacity:int = 100,
1091 |     ):
1092 | 
1093 |     """Fills the selection on the pixel layer with the specified ID
1094 |     
1095 |     Args:
1096 |         layer_id (int): The ID of existing pixel layer to add the fill
1097 |         color (dict): The color of the fill
1098 |         blend_mode (dict): The blend mode for the fill
1099 |         opacity (int) : The opacity of the color for the fill
1100 |     """
1101 |     
1102 |     command = createCommand("fillSelection", {
1103 |         "layerId":layer_id,
1104 |         "color":color,
1105 |         "blendMode":blend_mode,
1106 |         "opacity":opacity
1107 |     })
1108 | 
1109 |     return sendCommand(command)
1110 | 
1111 | 
1112 | 
1113 | @mcp.tool()
1114 | def delete_selection(
1115 |     layer_id: int
1116 |     ):
1117 | 
1118 |     """Removes the pixels within the selection on the pixel layer with the specified ID
1119 |     
1120 |     Args:
1121 |         layer_id (int): The ID of the layer from which the content of the selection should be deleted
1122 |     """
1123 |     
1124 |     command = createCommand("deleteSelection", {
1125 |         "layerId":layer_id
1126 |     })
1127 | 
1128 |     return sendCommand(command)
1129 | 
1130 | 
1131 | @mcp.tool()
1132 | def invert_selection():
1133 |     
1134 |     """Inverts the current selection in the Photoshop document"""
1135 | 
1136 |     command = createCommand("invertSelection", {})
1137 |     return sendCommand(command)
1138 | 
1139 | 
1140 | @mcp.tool()
1141 | def clear_selection():
1142 |     
1143 |     """Clears / deselects the current selection"""
1144 | 
1145 |     command = createCommand("selectRectangle", {
1146 |         "feather":0,
1147 |         "antiAlias":True,
1148 |         "bounds":{"top": 0, "left": 0, "bottom": 0, "right": 0}
1149 |     })
1150 | 
1151 |     return sendCommand(command)
1152 | 
1153 | @mcp.tool()
1154 | def select_rectangle(
1155 |     layer_id:int,
1156 |     feather:int = 0,
1157 |     anti_alias:bool = True,
1158 |     bounds:dict = {"top": 0, "left": 0, "bottom": 100, "right": 100}
1159 |     ):
1160 |     
1161 |     """Creates a rectangular selection and selects the specified layer
1162 |     
1163 |     Args:
1164 |         layer_id (int): The layer to do the select rectangle action on.
1165 |         feather (int): The amount of feathering in pixels to apply to the selection (0 - 1000)
1166 |         anti_alias (bool): Whether anti-aliases is applied to the selection
1167 |         bounds (dict): The bounds for the rectangle selection
1168 |     """
1169 | 
1170 |     command = createCommand("selectRectangle", {
1171 |         "layerId":layer_id,
1172 |         "feather":feather,
1173 |         "antiAlias":anti_alias,
1174 |         "bounds":bounds
1175 |     })
1176 | 
1177 |     return sendCommand(command)
1178 | 
1179 | @mcp.tool()
1180 | def select_polygon(
1181 |     layer_id:int,
1182 |     feather:int = 0,
1183 |     anti_alias:bool = True,
1184 |     points:list[dict[str, int]] = [{"x": 50, "y": 10}, {"x": 100, "y": 90}, {"x": 10, "y": 40}]
1185 |     ):
1186 |     
1187 |     """Creates an n-sided polygon selection and selects the specified layer
1188 |     
1189 |     Args:
1190 |         layer_id (int): The layer to do the selection action on.
1191 |         feather (int): The amount of feathering in pixels to apply to the selection (0 - 1000)
1192 |         anti_alias (bool): Whether anti-aliases is applied to the selection
1193 |         points (list): The points that define the sides of the selection, defined via a list of dicts with x, y values.
1194 |     """
1195 | 
1196 |     command = createCommand("selectPolygon", {
1197 |         "layerId":layer_id,
1198 |         "feather":feather,
1199 |         "antiAlias":anti_alias,
1200 |         "points":points
1201 |     })
1202 | 
1203 |     return sendCommand(command)
1204 | 
1205 | @mcp.tool()
1206 | def select_ellipse(
1207 |     layer_id:int,
1208 |     feather:int = 0,
1209 |     anti_alias:bool = True,
1210 |     bounds:dict = {"top": 0, "left": 0, "bottom": 100, "right": 100}
1211 |     ):
1212 |     
1213 |     """Creates an elliptical selection and selects the specified layer
1214 |     
1215 |     Args:
1216 |         layer_id (int): The layer to do the selection action on.
1217 |         feather (int): The amount of feathering in pixels to apply to the selection (0 - 1000)
1218 |         anti_alias (bool): Whether anti-aliases is applied to the selection
1219 |         bounds (dict): The bounds that will define the elliptical selection.
1220 |     """
1221 | 
1222 |     command = createCommand("selectEllipse", {
1223 |         "layerId":layer_id,
1224 |         "feather":feather,
1225 |         "antiAlias":anti_alias,
1226 |         "bounds":bounds
1227 |     })
1228 | 
1229 |     return sendCommand(command)
1230 | 
1231 | @mcp.tool()
1232 | def align_content(
1233 |     layer_id: int,
1234 |     alignment_mode:str
1235 |     ):
1236 |     
1237 |     """
1238 |     Aligns content on layer with the specified ID to the current selection.
1239 | 
1240 |     Args:
1241 |         layer_id (int): The ID of the layer in which to align the content
1242 |         alignment_mode (str): How the content should be aligned. Available options via alignment_modes
1243 |     """
1244 | 
1245 |     command = createCommand("alignContent", {
1246 |         "layerId":layer_id,
1247 |         "alignmentMode":alignment_mode
1248 |     })
1249 | 
1250 |     return sendCommand(command)
1251 | 
1252 | @mcp.tool()
1253 | def add_drop_shadow_layer_style(
1254 |     layer_id: int,
1255 |     blend_mode:str = "MULTIPLY",
1256 |     color:dict = {"red":0, "green":0, "blue":0},
1257 |     opacity:int = 35,
1258 |     angle:int = 160,
1259 |     distance:int = 3,
1260 |     spread:int = 0,
1261 |     size:int = 7
1262 |     ):
1263 |     """Adds a drop shadow layer style to the layer with the specified ID
1264 | 
1265 |     Args:
1266 |         layer_id (int): The ID for the layer with the content to add the drop shadow to
1267 |         blend_mode (str): The blend mode for the drop shadow
1268 |         color (dict): The color for the drop shadow
1269 |         opacity (int): The opacity of the drop shadow
1270 |         angle (int): The angle (-180 to 180) of the drop shadow relative to the content
1271 |         distance (int): The distance in pixels of the drop shadow (0 to 30000)
1272 |         spread (int): Defines how gradually the shadow fades out at its edges, with higher values creating a harsher, more defined edge, and lower values a softer, more feathered edge (0 to 100)
1273 |         size (int): Control the blur and spread of the shadow effect (0 to 250)
1274 |     """
1275 | 
1276 |     command = createCommand("addDropShadowLayerStyle", {
1277 |         "layerId":layer_id,
1278 |         "blendMode":blend_mode,
1279 |         "color":color,
1280 |         "opacity":opacity,
1281 |         "angle":angle,
1282 |         "distance":distance,
1283 |         "spread":spread,
1284 |         "size":size
1285 |     })
1286 | 
1287 |     return sendCommand(command)
1288 | 
1289 | @mcp.tool()
1290 | def duplicate_layer(layer_to_duplicate_id:int, duplicate_layer_name:str):
1291 |     """
1292 |     Duplicates the layer specified by layer_to_duplicate_id ID, creating a new layer above it with the name specified by duplicate_layer_name
1293 | 
1294 |     Args:
1295 |         layer_to_duplicate_id (id): The id of the layer to be duplicated
1296 |         duplicate_layer_name (str): Name for the newly created layer
1297 |     """
1298 | 
1299 |     command = createCommand("duplicateLayer", {
1300 |         "sourceLayerId":layer_to_duplicate_id,
1301 |         "duplicateLayerName":duplicate_layer_name,
1302 |     })
1303 | 
1304 |     return sendCommand(command)
1305 | 
1306 | @mcp.tool()
1307 | def flatten_all_layers(layer_name:str):
1308 |     """
1309 |     Flatten all layers in the document into a single layer with specified name
1310 | 
1311 |     Args:
1312 |         layer_name (str): The name of the merged layer
1313 |     """
1314 | 
1315 |     command = createCommand("flattenAllLayers", {
1316 |         "layerName":layer_name,
1317 |     })
1318 | 
1319 |     return sendCommand(command)
1320 | 
1321 | @mcp.tool()
1322 | def add_color_balance_adjustment_layer(
1323 |     layer_id: int,
1324 |     highlights:list = [0,0,0],
1325 |     midtones:list = [0,0,0],
1326 |     shadows:list = [0,0,0]):
1327 |     """Adds an adjustment layer to the layer with the specified ID to adjust color balance
1328 | 
1329 |     Each property highlights, midtones and shadows contains an array of 3 values between
1330 |     -100 and 100 that represent the relative position between two colors.
1331 | 
1332 |     First value is between cyan and red
1333 |     The second value is between magenta and green
1334 |     The third value is between yellow and blue    
1335 | 
1336 |     Args:
1337 |         layer_id (int): The ID of the layer to apply the color balance adjustment layer
1338 |         highlights (list): Relative color values for highlights
1339 |         midtones (list): Relative color values for midtones
1340 |         shadows (list): Relative color values for shadows
1341 |     """
1342 | 
1343 |     command = createCommand("addColorBalanceAdjustmentLayer", {
1344 |         "layerId":layer_id,
1345 |         "highlights":highlights,
1346 |         "midtones":midtones,
1347 |         "shadows":shadows
1348 |     })
1349 | 
1350 |     return sendCommand(command)
1351 | 
1352 | @mcp.tool()
1353 | def add_brightness_contrast_adjustment_layer(
1354 |     layer_id: int,
1355 |     brightness:int = 0,
1356 |     contrast:int = 0):
1357 |     """Adds an adjustment layer to the layer with the specified ID to adjust brightness and contrast
1358 | 
1359 |     Args:
1360 |         layer_id (int): The ID of the layer to apply the brightness and contrast adjustment layer
1361 |         brightness (int): The brightness value (-150 to 150)
1362 |         contrasts (int): The contrast value (-50 to 100)
1363 |     """
1364 | 
1365 |     command = createCommand("addBrightnessContrastAdjustmentLayer", {
1366 |         "layerId":layer_id,
1367 |         "brightness":brightness,
1368 |         "contrast":contrast
1369 |     })
1370 | 
1371 |     return sendCommand(command)
1372 | 
1373 | 
1374 | @mcp.tool()
1375 | def add_stroke_layer_style(
1376 |     layer_id: int,
1377 |     size: int = 2,
1378 |     color: dict = {"red": 0, "green": 0, "blue": 0},
1379 |     opacity: int = 100,
1380 |     position: str = "CENTER",
1381 |     blend_mode: str = "NORMAL"
1382 |     ):
1383 |     """Adds a stroke layer style to the layer with the specified ID.
1384 |     
1385 |     Args:
1386 |         layer_id (int): The ID of the layer to apply the stroke effect to.
1387 |         size (int, optional): The width of the stroke in pixels. Defaults to 2.
1388 |         color (dict, optional): The color of the stroke as RGB values. Defaults to black {"red": 0, "green": 0, "blue": 0}.
1389 |         opacity (int, optional): The opacity of the stroke as a percentage (0-100). Defaults to 100.
1390 |         position (str, optional): The position of the stroke relative to the layer content. 
1391 |                                  Options include "CENTER", "INSIDE", or "OUTSIDE". Defaults to "CENTER".
1392 |         blend_mode (str, optional): The blend mode for the stroke effect. Defaults to "NORMAL".
1393 |     """
1394 | 
1395 |     command = createCommand("addStrokeLayerStyle", {
1396 |         "layerId":layer_id,
1397 |         "size":size,
1398 |         "color":color,
1399 |         "opacity":opacity,
1400 |         "position":position,
1401 |         "blendMode":blend_mode
1402 |     })
1403 | 
1404 |     return sendCommand(command)
1405 | 
1406 | 
1407 | @mcp.tool()
1408 | def add_vibrance_adjustment_layer(
1409 |     layer_id: int,
1410 |     vibrance:int = 0,
1411 |     saturation:int = 0):
1412 |     """Adds an adjustment layer to layer with the specified ID to adjust vibrance and saturation
1413 |     
1414 |     Args:
1415 |         layer_id (int): The ID of the layer to apply the vibrance and saturation adjustment layer
1416 |         vibrance (int): Controls the intensity of less-saturated colors while preventing oversaturation of already-saturated colors. Range -100 to 100.
1417 |         saturation (int): Controls the intensity of all colors equally. Range -100 to 100.
1418 |     """
1419 |     #0.1 to 255
1420 | 
1421 |     command = createCommand("addAdjustmentLayerVibrance", {
1422 |         "layerId":layer_id,
1423 |         "saturation":saturation,
1424 |         "vibrance":vibrance
1425 |     })
1426 | 
1427 |     return sendCommand(command)
1428 | 
1429 | @mcp.tool()
1430 | def add_black_and_white_adjustment_layer(
1431 |     layer_id: int,
1432 |     colors: dict = {"blue": 20, "cyan": 60, "green": 40, "magenta": 80, "red": 40, "yellow": 60},
1433 |     tint: bool = False,
1434 |     tint_color: dict = {"red": 225, "green": 211, "blue": 179}
1435 | ):
1436 |     """Adds a Black & White adjustment layer to the specified layer.
1437 |     
1438 |     Creates an adjustment layer that converts the target layer to black and white. Optionally applies a color tint to the result.
1439 |     
1440 |     Args:
1441 |         layer_id (int): The ID of the layer to apply the black and white adjustment to.
1442 |         colors (dict): Controls how each color channel converts to grayscale. Values range from 
1443 |                       -200 to 300, with higher values making that color appear lighter in the 
1444 |                       conversion. Must include all keys: red, yellow, green, cyan, blue, magenta.
1445 |         tint (bool, optional): Whether to apply a color tint to the black and white result.
1446 |                               Defaults to False.
1447 |         tint_color (dict, optional): The RGB color dict to use for tinting
1448 |                                     with "red", "green", and "blue" keys (values 0-255).
1449 |     """
1450 | 
1451 |     command = createCommand("addAdjustmentLayerBlackAndWhite", {
1452 |         "layerId":layer_id,
1453 |         "colors":colors,
1454 |         "tint":tint,
1455 |         "tintColor":tint_color
1456 |     })
1457 | 
1458 |     return sendCommand(command)
1459 | 
1460 | @mcp.tool()
1461 | def apply_gaussian_blur(layer_id: int, radius: float = 2.5):
1462 |     """Applies a Gaussian Blur to the layer with the specified ID
1463 |     
1464 |     Args:
1465 |         layer_id (int): ID of layer to be blurred
1466 |         radius (float): The blur radius in pixels determining the intensity of the blur effect. Default is 2.5.
1467 |         Valid values range from 0.1 (subtle blur) to 10000 (extreme blur).
1468 | 
1469 |     Returns:
1470 |         dict: Response from the Photoshop operation
1471 |         
1472 |     Raises:
1473 |         RuntimeError: If the operation fails or times out
1474 |     """
1475 | 
1476 | 
1477 | 
1478 |     command = createCommand("applyGaussianBlur", {
1479 |         "layerId":layer_id,
1480 |         "radius":radius,
1481 |     })
1482 | 
1483 |     return sendCommand(command)
1484 | 
1485 | 
1486 | 
1487 | 
1488 | @mcp.tool()
1489 | def apply_motion_blur(layer_id: int, angle: int = 0, distance: float = 30):
1490 |     """Applies a Motion Blur to the layer with the specified ID
1491 | 
1492 |     Args:
1493 |     layer_id (int): ID of layer to be blurred
1494 |     angle (int): The angle in degrees (0 to 360) that determines the direction of the motion blur effect. Default is 0.
1495 |     distance (float): The distance in pixels that controls the length/strength of the motion blur. Default is 30.
1496 |         Higher values create a more pronounced motion effect.
1497 | 
1498 |     Returns:
1499 |         dict: Response from the Photoshop operation
1500 |         
1501 |     Raises:
1502 |         RuntimeError: If the operation fails or times out
1503 |     """
1504 | 
1505 | 
1506 |     command = createCommand("applyMotionBlur", {
1507 |         "layerId":layer_id,
1508 |         "angle":angle,
1509 |         "distance":distance
1510 |     })
1511 | 
1512 |     return sendCommand(command)
1513 | 
1514 | 
1515 | @mcp.resource("config://get_instructions")
1516 | def get_instructions() -> str:
1517 |     """Read this first! Returns information and instructions on how to use Photoshop and this API"""
1518 | 
1519 |     return f"""
1520 |     You are a photoshop expert who is creative and loves to help other people learn to use Photoshop and create. You are well versed in composition, design and color theory, and try to follow that theory when making decisions.
1521 | 
1522 |     Unless otherwise specified, all commands act on the currently active document in Photoshop
1523 | 
1524 |     Rules to follow:
1525 | 
1526 |     1. Think deeply about how to solve the task
1527 |     2. Always check your work
1528 |     3. You can view the current visible photoshop file by calling get_document_image
1529 |     4. Pay attention to font size (dont make it too big)
1530 |     5. Always use alignment (align_content()) to position your text.
1531 |     6. Read the info for the API calls to make sure you understand the requirements and arguments
1532 |     7. When you make a selection, clear it once you no longer need it
1533 | 
1534 |     Here are some general tips for when working with Photoshop.
1535 | 
1536 |     In general, layers are created from bottom up, so keep that in mind as you figure out the order or operations. If you want you have lower layers show through higher ones you must either change the opacity of the higher layers and / or blend modes.
1537 | 
1538 |     When using fonts there are a couple of things to keep in mind. First, the font origin is the bottom left of the font, not the top right.
1539 | 
1540 |     Suggestions for sizes:
1541 |     Paragraph text : 8 to 12 pts
1542 |     Headings : 14 - 20 pts
1543 |     Single Word Large : 20 to 25pt
1544 | 
1545 |     Pay attention to what layer names are needed for. Sometimes the specify the name of a newly created layer and sometimes they specify the name of the layer that the action should be performed on.
1546 | 
1547 |     As a general rule, you should not flatten files unless asked to do so, or its necessary to apply an effect or look.
1548 | 
1549 |     When generating an image, you do not need to first create a pixel layer. A layer will automatically be created when you generate the image.
1550 | 
1551 |     Colors are defined via a dict with red, green and blue properties with values between 0 and 255
1552 |     {{"red":255, "green":0, "blue":0}}
1553 | 
1554 |     Bounds is defined as a dict with top, left, bottom and right properties
1555 |     {{"top": 0, "left": 0, "bottom": 250, "right": 300}}
1556 | 
1557 |     Valid options for API calls:
1558 | 
1559 |     alignment_modes: {", ".join(alignment_modes)}
1560 | 
1561 |     justification_modes: {", ".join(justification_modes)}
1562 | 
1563 |     blend_modes: {", ".join(blend_modes)}
1564 | 
1565 |     anchor_positions: {", ".join(anchor_positions)}
1566 | 
1567 |     interpolation_methods: {", ".join(interpolation_methods)}
1568 | 
1569 |     fonts: {", ".join(font_names[:FONT_LIMIT])}
1570 |     """
1571 | 
1572 | font_names = list_all_fonts_postscript()
1573 | 
1574 | interpolation_methods = [
1575 |    "AUTOMATIC",
1576 |    "BICUBIC",
1577 |    "BICUBICSHARPER",
1578 |    "BICUBICSMOOTHER",
1579 |    "BILINEAR",
1580 |    "NEARESTNEIGHBOR"
1581 | ]
1582 | 
1583 | anchor_positions = [
1584 |    "BOTTOMCENTER",
1585 |    "BOTTOMLEFT", 
1586 |    "BOTTOMRIGHT", 
1587 |    "MIDDLECENTER", 
1588 |    "MIDDLELEFT", 
1589 |    "MIDDLERIGHT", 
1590 |    "TOPCENTER", 
1591 |    "TOPLEFT", 
1592 |    "TOPRIGHT"
1593 | ]
1594 | 
1595 | justification_modes = [
1596 |     "CENTER",
1597 |     "CENTERJUSTIFIED",
1598 |     "FULLYJUSTIFIED",
1599 |     "LEFT",
1600 |     "LEFTJUSTIFIED",
1601 |     "RIGHT",
1602 |     "RIGHTJUSTIFIED"
1603 | ]
1604 | 
1605 | alignment_modes = [
1606 |     "LEFT",
1607 |     "CENTER_HORIZONTAL",
1608 |     "RIGHT",
1609 |     "TOP",
1610 |     "CENTER_VERTICAL",
1611 |     "BOTTOM"
1612 | ]
1613 | 
1614 | blend_modes = [
1615 |     "COLOR",
1616 |     "COLORBURN",
1617 |     "COLORDODGE",
1618 |     "DARKEN",
1619 |     "DARKERCOLOR",
1620 |     "DIFFERENCE",
1621 |     "DISSOLVE",
1622 |     "DIVIDE",
1623 |     "EXCLUSION",
1624 |     "HARDLIGHT",
1625 |     "HARDMIX",
1626 |     "HUE",
1627 |     "LIGHTEN",
1628 |     "LIGHTERCOLOR",
1629 |     "LINEARBURN",
1630 |     "LINEARDODGE",
1631 |     "LINEARLIGHT",
1632 |     "LUMINOSITY",
1633 |     "MULTIPLY",
1634 |     "NORMAL",
1635 |     "OVERLAY",
1636 |     "PASSTHROUGH",
1637 |     "PINLIGHT",
1638 |     "SATURATION",
1639 |     "SCREEN",
1640 |     "SOFTLIGHT",
1641 |     "SUBTRACT",
1642 |     "VIVIDLIGHT"
1643 | ]
1644 | 
```
Page 3/6FirstPrevNextLast