How Can I Get the Commands Of Actions

Hello UXP Developer Community,

I am developing a UXP plugin that allows users to play their own recorded actions. I’ve run into a common issue: if an action contains a step like “Free Transform” and it’s played when the selection is empty, Photoshop throws a “Could not transform because the selected area is empty” error, which stops the entire action playback and halts my plugin’s workflow. Although do transform on empty only waste computing power , do not bother result.

Instead of the whole action failing, I want to catch this particular error, ignore it, and continue executing the rest of the steps in the action.

To do this, I believe I need to programmatically “read” the action, get an array of all its command descriptors, and then execute them one by one in my own code. This would allow me to wrap the transform command in a try…catch block.

What I have tried:

Getting DOM: I’ve used UXP Dom to get the properties of the action reference. But there are no commands.
Using Alchemist: The Alchemist plugin is fantastic and shows me that an action does indeed contain command children. When I get a reference to a single command using its index (e.g., { _ref: ‘command’, _index: 1 }), I can successfully retrieve the descriptor for that single step. This successfully returns metadata like the command’s name, ID, and numberOfChildren. The presence of numberOfChildren correctly implies that the command details are stored as children objects. The issue is that I cannot figure out how to access these “children”. I don’t know the property name or the correct reference structure to get the array of command descriptors. I want get the content of the command, instead of properties.

It seems like there is a command to access action step details, but I couldn’t find anything.
But there is an alternative to access action step details, using “copy as JavaScript” to extract details.

executeAsModal(async () => {
      try {
         // get a command string through ID 15010 in case of "copy as JavaScript"
         const f = await core.getMenuCommandState({ commandID: 15010 });
         const title = await core.getMenuCommandTitle({ commandID: 15010 });
         // checking any an active action on action panel
         if (f[0]) {
           // executing "copy as a JavaScript" by ID
            await core.performMenuCommand({ commandID: 15010 });
            // reading command details through clipboard
            const d = await navigator.clipboard.read();
            const funcText = d["text/plain"];
            // reading command details
            console.log(funcText);
         } else {
            await app.showAlert("select any action on action panel.");
         }
      } catch (e) {
         await app.showAlert(e);
      }
}, {"commandName": "Action Commands"});
view raw

However, it reads as a string text, making me bit frustrated to analyse each detail.
You need to use RegExp or something…

// an exmaple, reading a curve action by using "copy as JavaScript"
async function curve() {
    let commands = [
        {
            "_obj": "set",
            "_target": [
                {
                    "_enum": "ordinal",
                    "_ref": "adjustmentLayer",
                    "_value": "targetEnum"
                }
            ],
            "to": {
                "_obj": "curves",
                "adjustment": [
                    {
                        "_obj": "curvesAdjustment",
                        "channel": {
                            "_enum": "channel",
                            "_ref": "channel",
                            "_value": "composite"
                        },
                        "curve": [
                            {
                                "_obj": "paint",
                                "horizontal": 1.0,
                                "vertical": 0.0
                            },
                            {
                                "_obj": "paint",
                                "horizontal": 126.0,
                                "vertical": 128.0
                            },
                            {
                                "_obj": "paint",
                                "horizontal": 255.0,
                                "vertical": 255.0
                            }
                        ]
                    }
                ]
            }
        }
    ];
    return await require("photoshop").action.batchPlay(commands, {});
}

console.log(
    await require("photoshop").core.executeAsModal(curve, {"commandName": "Action Commands"})
);