Update n8n Skyvern.node.ts to include webhook_callback_url option in … (#2230)

This commit is contained in:
dd36
2025-04-30 11:10:14 -07:00
committed by GitHub
parent c069ebe6f9
commit 3af35bc428

View File

@@ -93,7 +93,6 @@ export class Skyvern implements INodeType {
name: 'Workflow', name: 'Workflow',
value: 'workflow', value: 'workflow',
}, },
], ],
default: 'task', default: 'task',
}, },
@@ -135,18 +134,31 @@ export class Skyvern implements INodeType {
const taskOptions: IDataObject = this.getNodeParameter('taskOptions') as IDataObject; const taskOptions: IDataObject = this.getNodeParameter('taskOptions') as IDataObject;
if (taskOptions["engine"] !== "v1") return requestOptions; if (taskOptions["engine"] !== "v1") return requestOptions;
// trigger the generate task v1 logic
const credentials = await this.getCredentials('skyvernApi'); const credentials = await this.getCredentials('skyvernApi');
const userPrompt = this.getNodeParameter('userPrompt'); const userPrompt = this.getNodeParameter('userPrompt');
// *** capture optional webhook URL ***
let webhookUrl: string | undefined;
try {
webhookUrl = this.getNodeParameter('webhookUrl') as string;
} catch (e) {
webhookUrl = undefined;
}
const generateBody: IDataObject = {
prompt: userPrompt,
};
if (webhookUrl) {
generateBody['webhook_callback_url'] = webhookUrl; // include for TaskV1 generation
}
const response = await makeRequest(credentials['baseUrl'] + '/api/v1/generate/task', { const response = await makeRequest(credentials['baseUrl'] + '/api/v1/generate/task', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'x-api-key': credentials['apiKey'], 'x-api-key': credentials['apiKey'],
}, },
body: JSON.stringify({ body: JSON.stringify(generateBody),
prompt: userPrompt,
}),
}); });
if (!response.ok) { if (!response.ok) {
throw new Error('Request to generate Task V1 failed'); // eslint-disable-line throw new Error('Request to generate Task V1 failed'); // eslint-disable-line
@@ -159,7 +171,11 @@ export class Skyvern implements INodeType {
navigation_payload: data.navigation_payload, navigation_payload: data.navigation_payload,
data_extraction_goal: data.data_extraction_goal, data_extraction_goal: data.data_extraction_goal,
extracted_information_schema: data.extracted_information_schema, extracted_information_schema: data.extracted_information_schema,
}; } as IDataObject;
if (webhookUrl) {
(requestOptions.body as IDataObject)['webhook_callback_url'] = webhookUrl;
}
return requestOptions; return requestOptions;
}, },
], ],
@@ -209,6 +225,28 @@ export class Skyvern implements INodeType {
}, },
}, },
}, },
// *** New property: optional webhook URL for Task dispatch ***
{
displayName: 'Webhook Callback URL',
description: 'Optional URL that Skyvern will call when the task finishes',
name: 'webhookUrl',
type: 'string',
default: '',
placeholder: 'https://example.com/webhook',
displayOptions: {
show: {
resource: ['task'],
taskOperation: ['dispatch'],
},
},
routing: {
request: {
body: {
webhook_callback_url: '={{$value ? $value : undefined}}',
},
},
},
},
{ {
displayName: 'Task ID', displayName: 'Task ID',
description: 'The ID of the task', description: 'The ID of the task',
@@ -365,6 +403,28 @@ export class Skyvern implements INodeType {
}, },
}, },
}, },
// *** New property: optional webhook URL for Workflow dispatch ***
{
displayName: 'Webhook Callback URL',
description: 'Optional URL that Skyvern will call when the workflow run finishes',
name: 'webhookCallbackUrl',
type: 'string',
default: '',
placeholder: 'https://example.com/webhook',
displayOptions: {
show: {
resource: ['workflow'],
workflowOperation: ['dispatch'],
},
},
routing: {
request: {
body: {
webhook_callback_url: '={{$value ? $value : undefined}}',
},
},
},
},
], ],
version: 1, version: 1,
}; };
@@ -415,35 +475,36 @@ export class Skyvern implements INodeType {
const parameters: any[] = workflow.workflow_definition.parameters; const parameters: any[] = workflow.workflow_definition.parameters;
const fields: ResourceMapperField[] = await Promise.all( const fields: ResourceMapperField[] = await Promise.all(
parameters.filter((parameter: any) => parameter.parameter_type === 'workflow' || parameter.parameter_type === 'credential') parameters
.filter((parameter: any) => parameter.parameter_type === 'workflow' || parameter.parameter_type === 'credential')
.map(async (parameter: any) => { .map(async (parameter: any) => {
let options: INodePropertyOptions[] | undefined = undefined; let options: INodePropertyOptions[] | undefined = undefined;
let parameterType: FieldType | undefined = undefined; let parameterType: FieldType | undefined = undefined;
if (parameter.parameter_type === 'credential') { if (parameter.parameter_type === 'credential') {
const response = await makeRequest(credentials['baseUrl'] + '/api/v1/credentials', { const credResponse = await makeRequest(credentials['baseUrl'] + '/api/v1/credentials', {
headers: { headers: {
'x-api-key': credentials['apiKey'], 'x-api-key': credentials['apiKey'],
}, },
}); });
if (!response.ok) { if (!credResponse.ok) {
throw new Error('Request to get credentials failed'); // eslint-disable-line throw new Error('Request to get credentials failed');
} }
const data = await response.json(); const credData = await credResponse.json();
options = data.map((credential: any) => ({ options = credData.map((credential: any) => ({
name: credential.name, name: credential.name,
value: credential.credential_id, value: credential.credential_id,
})); }));
parameterType = 'options'; parameterType = 'options';
}else{ } else {
const parameter_type_map: Record<string, string> = { const parameter_type_map: Record<string, FieldType> = {
'string': 'string', string: 'string',
'integer': 'number', integer: 'number',
'float': 'number', float: 'number',
'boolean': 'boolean', boolean: 'boolean',
'json': 'json', json: 'json',
'file_url': 'url', file_url: 'url',
} }
parameterType = parameter_type_map[parameter.workflow_parameter_type] as FieldType; parameterType = parameter_type_map[parameter.workflow_parameter_type];
} }
return { return {