import { ServiceNowInstance } from "../ServiceNowInstance.js"; import { BackgroundScriptExecutionResult } from "../BackgroundScriptExecutor.js"; import { ExecuteFlowOptions, ExecuteFlowByNameOptions, ExecuteSubflowOptions, ExecuteActionOptions, FlowExecutionResult, FlowScriptResultEnvelope, FlowContextStatusResult, FlowOutputsResult, FlowErrorResult, FlowCancelResult, FlowSendMessageResult, FlowPublishResult, TestFlowOptions, FlowTestResult, FlowDefinitionResult, FlowActionResult, CopyFlowOptions, FlowCopyResult, FlowContextDetailsResult, FlowLogOptions, FlowLogResult, FlowDefinitionOptions, FlowArtifactDefinitionResult, ActionDefinitionResult } from './FlowModels.js'; /** * Provides operations for executing ServiceNow Flow Designer flows, * subflows, and actions remotely via BackgroundScriptExecutor. * * Uses the sn_fd.FlowAPI.getRunner() (ScriptableFlowRunner) API * on the server side to execute and capture results. */ export declare class FlowManager { private _logger; private _bgExecutor; private _instance; private _defaultScope; /** * @param instance ServiceNow instance connection * @param scope Default scope for script execution (default: "global") */ constructor(instance: ServiceNowInstance, scope?: string); /** Execute any flow object (flow, subflow, or action). */ execute(options: ExecuteFlowOptions): Promise; /** Execute a flow by scoped name. */ executeFlow(options: ExecuteFlowByNameOptions): Promise; /** Execute a subflow by scoped name. */ executeSubflow(options: ExecuteSubflowOptions): Promise; /** Execute an action by scoped name. */ executeAction(options: ExecuteActionOptions): Promise; /** Query the status of a flow context by its sys_id. */ getFlowContextStatus(contextId: string): Promise; /** Retrieve outputs from a completed flow/subflow/action by context ID. */ getFlowOutputs(contextId: string): Promise; /** Retrieve error messages from a flow/subflow/action by context ID. */ getFlowError(contextId: string): Promise; /** Cancel a running or paused flow/subflow/action. */ cancelFlow(contextId: string, reason?: string): Promise; /** Send a message to a paused flow to resume it (for Wait for Message actions). */ sendFlowMessage(contextId: string, message: string, payload?: string): Promise; /** * Publish a flow so it can be executed. * Flows deployed via the ServiceNow SDK land in an unpublished/draft state * and must be published before they can be run. * * @param flowIdentifier Either a sys_id (32-char hex) or scoped_name (e.g. "x_myapp.my_flow") * @param scope Optional scope context for BackgroundScriptExecutor * @returns FlowPublishResult with success/failure status */ publishFlow(flowIdentifier: string, scope?: string): Promise; /** * Resolve a flow identifier (sys_id or scoped_name) to both sys_id and name * by querying the sys_hub_flow table. */ private _resolveFlowIdentifier; /** * Fetch a flow definition from the ProcessFlow REST API. * * Retained unchanged for existing callers. It reports neither the artifact * type nor a machine-readable failure reason, and it throws (rather than * returning a failure) for a blank sys_id. * * @see getFlowArtifactDefinition for the typed, non-throwing replacement. * * @param flowSysId The sys_id of the flow to fetch * @param scope Optional scope sys_id for the transaction scope query parameter * @returns FlowDefinitionResult containing the raw flow definition object */ getFlowDefinition(flowSysId: string, scope?: string): Promise; /** * Fetch an action's step instances from the ProcessFlow REST API. * * Calls `GET /api/now/processflow/action/action_types/{action_sys_id}/step_instances`. * Despite the name this returns only the ordered steps — never the action's * own metadata — so it cannot describe an action on its own. * * @deprecated Use {@link getActionDefinition}, which returns action metadata * and step instances through one contract. This method keeps working and its * signature is unchanged; it will be removed no earlier than the next major. * * @param actionSysId The sys_id of the action (action type) to fetch * @param scope Optional scope sys_id for the transaction scope query parameter * @returns FlowActionResult containing the raw step instance data */ getFlowActions(actionSysId: string, scope?: string): Promise; /** * Retrieve the design-time definition of a flow **or** a subflow. * * Both are served by `GET /api/now/processflow/flow/{sys_id}` and are told * apart by the `type` ServiceNow reports, which is echoed back verbatim on * `reportedType` — the type is never inferred from the call site. * * The returned `definition` is the untouched payload and is safe to pass * straight to `JSON.stringify`. * * @param sysId sys_id of the flow or subflow * @param options Optional scope for the transaction scope query parameter */ getFlowArtifactDefinition(sysId: string, options?: FlowDefinitionOptions): Promise; /** * Retrieve the design-time definition of a flow. * * Fails with `failureReason: 'type_mismatch'` when the sys_id belongs to a * subflow (or anything else) rather than silently relabelling it. * * @param flowSysId sys_id of the flow * @param options Optional scope for the transaction scope query parameter */ getFlowDesignDefinition(flowSysId: string, options?: FlowDefinitionOptions): Promise; /** * Retrieve the design-time definition of a subflow, including its inputs, * outputs, actions, nested subflows and flow logic. * * Fails with `failureReason: 'type_mismatch'` when the sys_id belongs to a * flow rather than silently relabelling it. * * @param subflowSysId sys_id of the subflow * @param options Optional scope for the transaction scope query parameter */ getSubflowDefinition(subflowSysId: string, options?: FlowDefinitionOptions): Promise; /** * Retrieve a complete action definition: metadata plus ordered steps. * * A complete action needs two reads — `action/action_types/{id}` for the * metadata and `action/action_types/{id}/step_instances` for the steps — * which are composed into one result. `success` is true only when both * parts were retrieved; a partial read is reported as a failure rather than * as an action with no steps. * * `metadata` and `steps` are the untouched payloads and are safe to pass * straight to `JSON.stringify`. * * @param actionSysId sys_id of the action type * @param options Optional scope for the transaction scope query parameter */ getActionDefinition(actionSysId: string, options?: FlowDefinitionOptions): Promise; /** * Shared retrieval for flow and subflow definitions. * * @param sysId sys_id of the artifact * @param options Optional scope * @param expectedType When set, the reported type must match it exactly * @internal */ private _fetchFlowArtifactDefinition; /** Trim an incoming identifier, tolerating a non-string from JS callers. @internal */ private _normalizeDefinitionSysId; /** Validate a definition sys_id, returning a failure when it is unusable. @internal */ private _validateDefinitionSysId; /** Build a consistent malformed-wrapper failure. @internal */ private _malformedResponse; /** * Read `result` out of a processflow response, tolerating both the * Axios-style (`data.result`) and RequestHandler-style (`bodyObject.result`) * shapes. Returns undefined instead of throwing so a malformed wrapper can * be reported as a typed failure. * @internal */ private _readProcessFlowResult; /** * Detect an error reported inside a processflow result envelope. Mirrors the * semantics the existing definition/test/copy calls already use: a non-zero * errorCode is an error, and so is a message with no code at all. * @internal */ private _readApiError; /** * Turn a thrown request error into a typed failure. * * RequestHandler throws `Error during request. Status: Body: ` for * any non-2xx, so the status is recovered from the message. The body is * dropped deliberately — it can carry record data, and it must not travel * back to the caller or into a log line. * @internal */ private _classifyRequestFailure; /** Trim a transport error message down to something safe to surface. @internal */ private _summarizeErrorText; /** Narrow an unknown to a plain object. @internal */ private _asRecord; /** Read a string field, defaulting to '' for anything else. @internal */ private _stringField; /** Read an array field's length, defaulting to 0 for anything else. @internal */ private _countField; /** Project the commonly used fields of a flow/subflow definition. @internal */ private _buildFlowArtifactSummary; /** Project the commonly used fields of an action definition. @internal */ private _buildActionSummary; /** * Sort step instances ascending by `order`, keeping the API's own ordering * as the tie-break so a missing or non-numeric order never reshuffles steps. * @internal */ private _sortActionSteps; /** Read a step's execution order; unusable values sort last. @internal */ private _stepOrder; /** * Test a flow as if running it from Flow Designer, without requiring it to be published. * * This uses the ProcessFlow REST API (`POST /api/now/processflow/flow/{id}/test`) * rather than the scripted FlowAPI.getRunner() approach used by the execute*() methods. * * The method fetches the full flow definition from the instance, combines it with * the provided outputMap (trigger test values), and submits it to the test endpoint. * * @param options Test flow options including flowId, outputMap, and optional scope/runOnThread * @returns FlowTestResult with the execution context sys_id on success */ testFlow(options: TestFlowOptions): Promise; /** * Copy an existing flow into a target scoped application. * * This uses the ProcessFlow REST API (`POST /api/now/processflow/flow/{id}/copy`) * to create a duplicate of a flow in a specified scope. The copied flow lands in * draft/unpublished state and can then be modified, tested, and published. * * @param options Copy flow options including sourceFlowId, name, and targetScope * @returns FlowCopyResult with the new flow's sys_id on success */ copyFlow(options: CopyFlowOptions): Promise; /** * Get detailed flow execution context via the ProcessFlow operations API. * * Returns rich execution data including per-action timing, inputs, outputs, * execution metadata (who ran it, test vs production, runtime, etc.), and * optionally the full flow definition snapshot. * * This uses `GET /api/now/processflow/operations/flow/context/{id}` which is * the same endpoint Flow Designer uses to display execution details. * * Note: The execution report (`flowReport`) requires operations view / flow * logging to be enabled. If not available, `flowReportAvailabilityDetails` * will contain information about why. * * @param contextId The sys_id of the flow context (from sys_flow_context) * @param scope Optional scope sys_id for the transaction scope query parameter * @param includeFlowDefinition Whether to include the full flow definition snapshot (default: false) * @returns FlowContextDetailsResult with execution context and report */ getFlowContextDetails(contextId: string, scope?: string, includeFlowDefinition?: boolean): Promise; /** * Retrieve flow execution logs from the sys_flow_log table. * * Returns log entries associated with a flow context, including error messages, * step-level logs, and cancellation reasons. Log entries may be empty for * simple successful executions. * * @param contextId The sys_id of the flow context to get logs for * @param options Optional query options (limit, order direction) * @returns FlowLogResult with array of log entries */ getFlowLogs(contextId: string, options?: FlowLogOptions): Promise; /** * Map the raw flowContext object from the operations API to a typed FlowContextInfo. * @internal */ private _mapFlowContextInfo; /** * Map the raw flowReport object from the operations API to a typed FlowExecutionReport. * Cross-references with the flow definition to resolve human-readable step names. * @internal */ private _mapFlowExecutionReport; /** * Build a lookup map from action instance ID to human-readable names * by scanning the flow definition's actionInstances array. * @internal */ private _buildActionInstanceLookup; /** * Extract the result from a ProcessFlow API response, handling both * Axios-style (data.result) and RequestHandler-style (bodyObject.result) response shapes. */ private _extractProcessFlowResult; /** Build the ServiceNow server-side script string. */ _buildFlowScript(options: ExecuteFlowOptions): string; /** Serialize inputs for embedding in the generated script. */ _serializeInputs(inputs: Record): string; /** * Decode HTML entities and strip HTML tags from a string. * ServiceNow's background script output encodes quotes as " * and appends
tags that must be removed before JSON parsing. */ _decodeHtmlEntities(str: string): string; /** Try to parse a line containing the result marker into a FlowScriptResultEnvelope. */ private _tryParseEnvelopeFromLine; /** Extract the JSON envelope from script output lines. */ _extractResultEnvelope(bgResult: BackgroundScriptExecutionResult): FlowScriptResultEnvelope | null; /** Parse BackgroundScriptExecutionResult into FlowExecutionResult. */ _parseFlowResult(bgResult: BackgroundScriptExecutionResult, options: ExecuteFlowOptions): FlowExecutionResult; /** Validate that a context ID is a non-empty 32-character hex sys_id. */ private _validateContextId; /** Escape a string for embedding in a generated SN script single-quoted string. */ private _escapeForScript; /** Build script to query sys_flow_context status. */ _buildContextStatusScript(contextId: string): string; /** Build script to retrieve flow outputs via FlowAPI.getOutputs(). */ _buildGetOutputsScript(contextId: string): string; /** Build script to retrieve flow error via FlowAPI.getErrorMessage(). */ _buildGetErrorScript(contextId: string): string; /** Build script to cancel a flow via FlowAPI.cancel(). */ _buildCancelScript(contextId: string, reason: string): string; /** Build script to publish a flow via FlowAPI.publish(). */ private _buildPublishScript; /** Build script to send a message to a paused flow via FlowAPI.sendMessage(). */ _buildSendMessageScript(contextId: string, message: string, payload: string): string; }