TaskSultan Docs tasksultan.com

Migrating from UiPath

Converting a workflow into code

The behaviour model, the expression translation and the refusals the codegen reports and how a conversion declares its own incompleteness.

uipath codegen turns a workflow's behaviour into a runnable-shaped TaskSultan automation. It builds on two intermediate steps: uipath ir models the workflow as an ordered tree and the expression translator decides what each expression text means in TypeScript. The whole path is staged. It writes only into the directory you name with --out, never into automations/ or any protected path.

#The behaviour model

uipath ir parses XAML into a typed, ordered model of behaviour: nested sequences, flowcharts and their decisions, branches, loops, invoke calls with their argument bindings, assignments, declarations (name, type, default, direction, scope) and try/catch/finally. Order and nesting are the point. It is a tree, not a tally.

Totality is an identity, not an aim: nodes plus attached elements plus refused elements equals the elements the census counted and every element that is not modelled is a named refusal with its source line. An attached element is a construct consumed as part of another, such as a using wrapper. No code is produced at this stage and the expression text is carried verbatim.

npx tsx orchestrator/cli.ts uipath ir ./MyProject

#The expression translation

Expressions are translated from VB or C# into TypeScript where the meaning survives and refused where it does not. The mapped operators keep their meaning: OrElse and AndAlso become short-circuit operators, VB = becomes ===, Is becomes reference equality and ^ becomes ** with explicit parentheses because the associativity differs. A handful of members are renamed (ToString, Trim, ToLower). Every other called member is carried verbatim, because the translator does not re-spell a name it cannot vouch for.

Refusals are named, never approximated. VB integer division, Mod and And/Or/Xor are refused because their operand types are not visible at the expression level. Lambdas, LINQ queries, CType and TryCast, GetType (exact type identity in .NET), date literals, numeric type suffixes and three-valued DbNull comparisons are all refused by name. A translation also carries its runtime obligations: the names the target runtime must provide, about which the translator claims nothing.

#What the codegen emits

The codegen lowers the model into ordered named step functions in the workflow's own order. The workflow root becomes the platform's processTransaction hook and declarations become state fields. The platform's exception lanes are built from the workflow's own TryCatch structure: the catch body decides the lane, the declared type only corroborates it and an empty catch body is refused by name. Retry is declared to the runner through defineAutomation's own retry field, never emitted as a sleep or a timer.

Output is deterministic: the same model produces byte-identical text every run. A flowchart is emitted as a graph and a state machine as a machine, rather than flattened into an order the source does not have. The emitted text is then checked with the platform's own validator against the staged source.

#The refusals it reports

Every construct the model or the translator could not handle becomes a TODO(conversion) marker inline at its own position and is counted in the emission manifest beside the file. The accounting is an identity: emitted_steps + refused_steps === ir_nodes and a third state is a defect.

Some whole node kinds are refused unconditionally, each with its reason. An InterruptibleWhile carries interruption semantics the runner has no counterpart for. A TerminateWorkflow would end the run, which the framework does not define per step. An InvokeWorkflowFile is a separate conversion unit, so the invoke is carried as a refusal naming the workflow and its argument bindings rather than emitted as a call to something that does not exist. Refused features include ir-refusal, condition-refused, expression-refused, lane-unattributable, INVOKE_CODE_UNSUPPORTED and NET_METHOD_UNSUPPORTED.

npx tsx orchestrator/cli.ts uipath codegen ./MyProject --out ./staged

#Exit codes

  • 0: emitted with nothing refused anywhere.
  • 1: emitted with refusals. The artefact declares its own incompleteness and so does the code.
  • 2: a file could not be read, or an emission was structurally invalid, or the accounting did not close.

--out is required. The codegen refuses to choose a destination for you.

#Things that catch people out

  • A refusal is a result, not an error path. It is printed and counted, never silently dropped.
  • The staged automation is a candidate. It is not registered, packaged or run.
  • Host paths found in workflow text are replaced by a declared redaction marker and the manifest keeps the original text.