feat(editor): Expose View Execution links for erroneous sub-executions (#13185)

This commit is contained in:
Charlie Kolb
2025-02-13 09:44:52 +01:00
committed by GitHub
parent 85deff0b7f
commit 11cf1cd23a
14 changed files with 261 additions and 13 deletions

View File

@@ -0,0 +1,31 @@
import type { ITaskMetadata } from '.';
import { hasKey } from './utils';
function responseHasSubworkflowData(
response: unknown,
): response is { executionId: string; workflowId: string } {
return ['executionId', 'workflowId'].every(
(x) => hasKey(response, x) && typeof response[x] === 'string',
);
}
type ISubWorkflowMetadata = Required<Pick<ITaskMetadata, 'subExecution' | 'subExecutionsCount'>>;
function parseErrorResponseWorkflowMetadata(response: unknown): ISubWorkflowMetadata | undefined {
if (!responseHasSubworkflowData(response)) return undefined;
return {
subExecution: {
executionId: response.executionId,
workflowId: response.workflowId,
},
subExecutionsCount: 1,
};
}
export function parseErrorMetadata(error: unknown): ISubWorkflowMetadata | undefined {
if (hasKey(error, 'errorResponse')) {
return parseErrorResponseWorkflowMetadata(error.errorResponse);
}
return undefined;
}

View File

@@ -18,6 +18,7 @@ import type {
IDataObject,
IStatusCodeMessages,
Functionality,
RelatedExecution,
} from '../Interfaces';
import { removeCircularRefs } from '../utils';
@@ -30,6 +31,10 @@ export interface NodeOperationErrorOptions {
messageMapping?: { [key: string]: string }; // allows to pass custom mapping for error messages scoped to a node
functionality?: Functionality;
type?: string;
metadata?: {
subExecution?: RelatedExecution;
parentExecution?: RelatedExecution;
};
}
interface NodeApiErrorOptions extends NodeOperationErrorOptions {

View File

@@ -35,6 +35,7 @@ export class NodeOperationError extends NodeError {
this.description = options.description;
this.context.runIndex = options.runIndex;
this.context.itemIndex = options.itemIndex;
this.context.metadata = options.metadata;
if (this.message === this.description) {
this.description = undefined;

View File

@@ -15,6 +15,7 @@ export * from './ExecutionStatus';
export * from './Expression';
export * from './FromAIParseUtils';
export * from './NodeHelpers';
export * from './MetadataUtils';
export * from './Workflow';
export * from './WorkflowDataProxy';
export * from './WorkflowDataProxyEnvProvider';

View File

@@ -276,3 +276,10 @@ export function randomString(minLength: number, maxLength?: number): string {
.map((byte) => ALPHABET[byte % ALPHABET.length])
.join('');
}
/**
* Checks if a value is an object with a specific key and provides a type guard for the key.
*/
export function hasKey<T extends PropertyKey>(value: unknown, key: T): value is Record<T, unknown> {
return value !== null && typeof value === 'object' && value.hasOwnProperty(key);
}