@agnocon/piece-browse-ai 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.MIT-AP +24 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/actions/get-task-details.d.ts +5 -0
- package/dist/lib/actions/get-task-details.d.ts.map +1 -0
- package/dist/lib/actions/get-task-details.js +50 -0
- package/dist/lib/actions/get-task-details.js.map +1 -0
- package/dist/lib/actions/list-robots.d.ts +2 -0
- package/dist/lib/actions/list-robots.d.ts.map +1 -0
- package/dist/lib/actions/list-robots.js +45 -0
- package/dist/lib/actions/list-robots.js.map +1 -0
- package/dist/lib/actions/run-robot.d.ts +6 -0
- package/dist/lib/actions/run-robot.d.ts.map +1 -0
- package/dist/lib/actions/run-robot.js +64 -0
- package/dist/lib/actions/run-robot.js.map +1 -0
- package/dist/lib/common/auth.d.ts +2 -0
- package/dist/lib/common/auth.d.ts.map +1 -0
- package/dist/lib/common/auth.js +31 -0
- package/dist/lib/common/auth.js.map +1 -0
- package/dist/lib/common/client.d.ts +13 -0
- package/dist/lib/common/client.d.ts.map +1 -0
- package/dist/lib/common/client.js +63 -0
- package/dist/lib/common/client.js.map +1 -0
- package/dist/lib/common/props.d.ts +4 -0
- package/dist/lib/common/props.d.ts.map +1 -0
- package/dist/lib/common/props.js +168 -0
- package/dist/lib/common/props.js.map +1 -0
- package/dist/lib/triggers/task-finished-successfully.d.ts +11 -0
- package/dist/lib/triggers/task-finished-successfully.d.ts.map +1 -0
- package/dist/lib/triggers/task-finished-successfully.js +110 -0
- package/dist/lib/triggers/task-finished-successfully.js.map +1 -0
- package/dist/lib/triggers/task-finished-with-error.d.ts +11 -0
- package/dist/lib/triggers/task-finished-with-error.d.ts.map +1 -0
- package/dist/lib/triggers/task-finished-with-error.js +110 -0
- package/dist/lib/triggers/task-finished-with-error.js.map +1 -0
- package/package.json +46 -0
- package/src/index.ts +34 -0
- package/src/lib/actions/get-task-details.ts +52 -0
- package/src/lib/actions/list-robots.ts +41 -0
- package/src/lib/actions/run-robot.ts +65 -0
- package/src/lib/common/auth.ts +24 -0
- package/src/lib/common/client.ts +85 -0
- package/src/lib/common/props.ts +213 -0
- package/src/lib/triggers/task-finished-successfully.ts +139 -0
- package/src/lib/triggers/task-finished-with-error.ts +138 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { DynamicPropsValue, Property } from '@agnocon/pieces-framework';
|
|
2
|
+
import { HttpMethod } from '@agnocon/pieces-common';
|
|
3
|
+
import { browseAiApiCall } from './client';
|
|
4
|
+
import { browseAiAuth } from './auth';
|
|
5
|
+
|
|
6
|
+
interface BrowseAiRobot {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface BrowseAiTask {
|
|
12
|
+
id: string;
|
|
13
|
+
status: string;
|
|
14
|
+
createdAt?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface BrowseAiTasksResponse {
|
|
18
|
+
statusCode: number;
|
|
19
|
+
messageCode: string;
|
|
20
|
+
result: {
|
|
21
|
+
robotTasks: {
|
|
22
|
+
totalCount: number;
|
|
23
|
+
pageNumber: number;
|
|
24
|
+
hasMore: boolean;
|
|
25
|
+
items: BrowseAiTask[];
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface BrowseAiRobotResponse {
|
|
31
|
+
robot: {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
inputParameters: {
|
|
35
|
+
type: string;
|
|
36
|
+
name: string;
|
|
37
|
+
label: string;
|
|
38
|
+
required: boolean;
|
|
39
|
+
options?: { label: string; value: string }[];
|
|
40
|
+
}[];
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const robotIdDropdown = Property.Dropdown({
|
|
45
|
+
auth: browseAiAuth,
|
|
46
|
+
displayName: 'Robot',
|
|
47
|
+
description: 'Select a robot from your Browse AI account',
|
|
48
|
+
required: true,
|
|
49
|
+
refreshers: [],
|
|
50
|
+
options: async ({ auth }) => {
|
|
51
|
+
if (!auth) {
|
|
52
|
+
return {
|
|
53
|
+
disabled: true,
|
|
54
|
+
options: [],
|
|
55
|
+
placeholder: 'Please connect your Browse AI account first.',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const response = await browseAiApiCall<{
|
|
61
|
+
robots: { items: BrowseAiRobot[] };
|
|
62
|
+
}>({
|
|
63
|
+
method: HttpMethod.GET,
|
|
64
|
+
resourceUri: '/robots',
|
|
65
|
+
auth: { apiKey: auth.secret_text },
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const robots = response?.robots?.items ?? [];
|
|
69
|
+
|
|
70
|
+
if (robots.length === 0) {
|
|
71
|
+
return {
|
|
72
|
+
disabled: true,
|
|
73
|
+
options: [],
|
|
74
|
+
placeholder: 'No robots found in your account.',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
disabled: false,
|
|
80
|
+
options: robots.map((robot) => ({
|
|
81
|
+
label: robot.name,
|
|
82
|
+
value: robot.id,
|
|
83
|
+
})),
|
|
84
|
+
};
|
|
85
|
+
} catch (error: any) {
|
|
86
|
+
return {
|
|
87
|
+
disabled: true,
|
|
88
|
+
options: [],
|
|
89
|
+
placeholder:
|
|
90
|
+
'Failed to load robots. Please check your API key and try again.',
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
export const taskIdDropdown = Property.Dropdown({
|
|
97
|
+
auth: browseAiAuth,
|
|
98
|
+
displayName: 'Task',
|
|
99
|
+
description: 'Select a task associated with the selected robot',
|
|
100
|
+
required: true,
|
|
101
|
+
refreshers: ['robotId'],
|
|
102
|
+
options: async ({ auth, robotId }) => {
|
|
103
|
+
if (!auth) {
|
|
104
|
+
return {
|
|
105
|
+
disabled: true,
|
|
106
|
+
options: [],
|
|
107
|
+
placeholder: 'Please connect your Browse AI account.',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!robotId) {
|
|
112
|
+
return {
|
|
113
|
+
disabled: true,
|
|
114
|
+
options: [],
|
|
115
|
+
placeholder: 'Please select a robot first.',
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const response = await browseAiApiCall<BrowseAiTasksResponse>({
|
|
121
|
+
method: HttpMethod.GET,
|
|
122
|
+
resourceUri: `/robots/${robotId}/tasks`,
|
|
123
|
+
auth: { apiKey: auth.secret_text },
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const tasks = response.result?.robotTasks?.items ?? [];
|
|
127
|
+
|
|
128
|
+
if (tasks.length === 0) {
|
|
129
|
+
return {
|
|
130
|
+
disabled: true,
|
|
131
|
+
options: [],
|
|
132
|
+
placeholder: 'No tasks found for the selected robot.',
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
disabled: false,
|
|
138
|
+
options: tasks.map((task) => {
|
|
139
|
+
const createdDate = task.createdAt
|
|
140
|
+
? new Date(task.createdAt).toLocaleDateString()
|
|
141
|
+
: 'Unknown date';
|
|
142
|
+
return {
|
|
143
|
+
label: `${task.id} - ${task.status} (${createdDate})`,
|
|
144
|
+
value: task.id,
|
|
145
|
+
};
|
|
146
|
+
}),
|
|
147
|
+
};
|
|
148
|
+
} catch (e) {
|
|
149
|
+
return {
|
|
150
|
+
disabled: true,
|
|
151
|
+
options: [],
|
|
152
|
+
placeholder: `Error fetching tasks: ${
|
|
153
|
+
e instanceof Error ? e.message : 'Unknown error'
|
|
154
|
+
}`,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
export const robotParameters = Property.DynamicProperties({
|
|
161
|
+
auth: browseAiAuth,
|
|
162
|
+
displayName: 'Input Parameters',
|
|
163
|
+
refreshers: ['robotId'],
|
|
164
|
+
required: true,
|
|
165
|
+
props: async ({ auth, robotId }) => {
|
|
166
|
+
if (!auth || !robotId) return {};
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
const response = await browseAiApiCall<BrowseAiRobotResponse>({
|
|
170
|
+
method: HttpMethod.GET,
|
|
171
|
+
resourceUri: `/robots/${robotId}`,
|
|
172
|
+
auth: { apiKey: auth.secret_text },
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const props: DynamicPropsValue = {};
|
|
176
|
+
|
|
177
|
+
const params = response.robot.inputParameters ?? [];
|
|
178
|
+
|
|
179
|
+
for (const param of params) {
|
|
180
|
+
switch (param.type) {
|
|
181
|
+
case 'number':
|
|
182
|
+
props[param.name] = Property.Number({
|
|
183
|
+
displayName: param.label,
|
|
184
|
+
required: param.required,
|
|
185
|
+
});
|
|
186
|
+
break;
|
|
187
|
+
case 'url':
|
|
188
|
+
case 'string':
|
|
189
|
+
props[param.name] = Property.ShortText({
|
|
190
|
+
displayName: param.label,
|
|
191
|
+
required: param.required,
|
|
192
|
+
});
|
|
193
|
+
break;
|
|
194
|
+
case 'select':
|
|
195
|
+
props[param.name] = Property.StaticDropdown({
|
|
196
|
+
displayName: param.label,
|
|
197
|
+
required: param.required,
|
|
198
|
+
options: {
|
|
199
|
+
disabled: false,
|
|
200
|
+
options: param.options ? param.options : [],
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
break;
|
|
204
|
+
default:
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return props;
|
|
209
|
+
} catch {
|
|
210
|
+
return {};
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { HttpMethod } from '@agnocon/pieces-common';
|
|
2
|
+
import { createTrigger, TriggerStrategy } from '@agnocon/pieces-framework';
|
|
3
|
+
import { isNil } from '@agnocon/pieces-framework';
|
|
4
|
+
import { browseAiAuth } from '../common/auth';
|
|
5
|
+
import { browseAiApiCall } from '../common/client';
|
|
6
|
+
import { robotIdDropdown } from '../common/props';
|
|
7
|
+
|
|
8
|
+
const TRIGGER_KEY = 'browse-ai-task_finished_successfully';
|
|
9
|
+
|
|
10
|
+
export const taskFinishedSuccessfullyTrigger = createTrigger({
|
|
11
|
+
auth: browseAiAuth,
|
|
12
|
+
name: 'task_finished_successfully',
|
|
13
|
+
displayName: 'Task Finished Successfully',
|
|
14
|
+
description:
|
|
15
|
+
'Triggers when a robot finishes a task successfully.',
|
|
16
|
+
aiMetadata: {
|
|
17
|
+
description:
|
|
18
|
+
'Fires when a task run for the selected Browse AI robot completes successfully, delivering the finished task record with its captured/extracted data. Use to process scrape results as soon as they are ready.',
|
|
19
|
+
},
|
|
20
|
+
type: TriggerStrategy.WEBHOOK,
|
|
21
|
+
props: {
|
|
22
|
+
robotId: robotIdDropdown,
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
async onEnable(context) {
|
|
26
|
+
const { robotId } = context.propsValue;
|
|
27
|
+
const apiKey = context.auth.secret_text;
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
// Verify robot exists and we have access
|
|
31
|
+
await browseAiApiCall({
|
|
32
|
+
method: HttpMethod.GET,
|
|
33
|
+
auth: { apiKey },
|
|
34
|
+
resourceUri: `/robots/${robotId}`,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const response = await browseAiApiCall<{
|
|
38
|
+
webhook: { id: string; url: string; status: string };
|
|
39
|
+
}>({
|
|
40
|
+
method: HttpMethod.POST,
|
|
41
|
+
auth: { apiKey },
|
|
42
|
+
resourceUri: `/robots/${robotId}/webhooks`,
|
|
43
|
+
body: {
|
|
44
|
+
hookUrl: context.webhookUrl,
|
|
45
|
+
eventType: 'taskFinishedSuccessfully',
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
await context.store.put<string>(TRIGGER_KEY, response.webhook.id);
|
|
50
|
+
} catch (error: any) {
|
|
51
|
+
if (error.response?.status === 404) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Robot not found: The robot with ID "${robotId}" does not exist or you do not have access to it. Please verify the robot ID and your permissions.`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (error.response?.status === 403) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
'Access denied: You do not have permission to set up webhooks for this robot. Please check your Browse AI account permissions and ensure you have webhook access.'
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (error.response?.status === 400) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Invalid webhook configuration: ${
|
|
66
|
+
error.response?.data?.message || error.message
|
|
67
|
+
}. Please check your webhook URL and robot ID.`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (error.response?.status === 429) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
'Rate limit exceeded: Too many webhook requests. Please wait a moment and try again.'
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Failed to set up webhook: ${
|
|
79
|
+
error.message || 'Unknown error occurred'
|
|
80
|
+
}. Please check your robot ID and try again.`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
async onDisable(context) {
|
|
86
|
+
const { robotId } = context.propsValue;
|
|
87
|
+
|
|
88
|
+
const webhookId = await context.store.get<string>(TRIGGER_KEY);
|
|
89
|
+
const apiKey = context.auth.secret_text;
|
|
90
|
+
|
|
91
|
+
if (!isNil(webhookId)) {
|
|
92
|
+
try {
|
|
93
|
+
await browseAiApiCall({
|
|
94
|
+
method: HttpMethod.DELETE,
|
|
95
|
+
auth: { apiKey },
|
|
96
|
+
resourceUri: `/robots/${robotId}/webhooks/${webhookId}`,
|
|
97
|
+
});
|
|
98
|
+
} catch (error: any) {
|
|
99
|
+
console.warn(
|
|
100
|
+
`Warning: Failed to clean up webhook ${webhookId}:`,
|
|
101
|
+
error.message
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// Clean up the stored webhook ID even if deletion failed
|
|
105
|
+
await context.store.delete(TRIGGER_KEY);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
async run(context) {
|
|
111
|
+
const payload = context.payload.body as {
|
|
112
|
+
task: Record<string, any>;
|
|
113
|
+
event: string;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
if (payload.event !== 'task.finishedSuccessfully') return [];
|
|
117
|
+
|
|
118
|
+
return [payload.task];
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
async test(context) {
|
|
122
|
+
const { robotId } = context.propsValue;
|
|
123
|
+
|
|
124
|
+
const apiKey = context.auth.secret_text;
|
|
125
|
+
|
|
126
|
+
const response = await browseAiApiCall<{
|
|
127
|
+
result: { robotTasks: { items: { id: string }[] } };
|
|
128
|
+
}>({
|
|
129
|
+
method: HttpMethod.GET,
|
|
130
|
+
auth: { apiKey },
|
|
131
|
+
resourceUri: `/robots/${robotId}/tasks`,
|
|
132
|
+
query: { status: 'successful', sort: '-createdAt' },
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
return response.result.robotTasks.items;
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
sampleData: {},
|
|
139
|
+
});
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { HttpMethod } from '@agnocon/pieces-common';
|
|
2
|
+
import { createTrigger, TriggerStrategy } from '@agnocon/pieces-framework';
|
|
3
|
+
import { isNil } from '@agnocon/pieces-framework';
|
|
4
|
+
import { browseAiAuth } from '../common/auth';
|
|
5
|
+
import { browseAiApiCall } from '../common/client';
|
|
6
|
+
import { robotIdDropdown } from '../common/props';
|
|
7
|
+
|
|
8
|
+
const TRIGGER_KEY = 'browse-ai-task_finished_with_error';
|
|
9
|
+
|
|
10
|
+
export const taskFinishedWithErrorTrigger = createTrigger({
|
|
11
|
+
auth: browseAiAuth,
|
|
12
|
+
name: 'task_finished_with_error',
|
|
13
|
+
displayName: 'Task Finished with Error',
|
|
14
|
+
description: 'Triggers when a robot task run fails with an error.',
|
|
15
|
+
aiMetadata: {
|
|
16
|
+
description:
|
|
17
|
+
'Fires when a task run for the selected Browse AI robot finishes in a failed/error state, delivering the failed task record. Use to detect and react to scrapes that did not complete successfully.',
|
|
18
|
+
},
|
|
19
|
+
type: TriggerStrategy.WEBHOOK,
|
|
20
|
+
props: {
|
|
21
|
+
robotId: robotIdDropdown,
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
async onEnable(context) {
|
|
25
|
+
const { robotId } = context.propsValue;
|
|
26
|
+
const apiKey = context.auth.secret_text;
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
// Verify robot exists and we have access
|
|
30
|
+
await browseAiApiCall({
|
|
31
|
+
method: HttpMethod.GET,
|
|
32
|
+
auth: { apiKey },
|
|
33
|
+
resourceUri: `/robots/${robotId}`,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const response = await browseAiApiCall<{
|
|
37
|
+
webhook: { id: string; url: string; status: string };
|
|
38
|
+
}>({
|
|
39
|
+
method: HttpMethod.POST,
|
|
40
|
+
auth: { apiKey },
|
|
41
|
+
resourceUri: `/robots/${robotId}/webhooks`,
|
|
42
|
+
body: {
|
|
43
|
+
hookUrl: context.webhookUrl,
|
|
44
|
+
eventType: 'taskFinishedWithError',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
await context.store.put<string>(TRIGGER_KEY, response.webhook.id);
|
|
49
|
+
} catch (error: any) {
|
|
50
|
+
if (error.response?.status === 404) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Robot not found: The robot with ID "${robotId}" does not exist or you do not have access to it. Please verify the robot ID and your permissions.`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (error.response?.status === 403) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
'Access denied: You do not have permission to set up webhooks for this robot. Please check your Browse AI account permissions and ensure you have webhook access.'
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (error.response?.status === 400) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Invalid webhook configuration: ${
|
|
65
|
+
error.response?.data?.message || error.message
|
|
66
|
+
}. Please check your webhook URL and robot ID.`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (error.response?.status === 429) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
'Rate limit exceeded: Too many webhook requests. Please wait a moment and try again.'
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
throw new Error(
|
|
77
|
+
`Failed to set up webhook: ${
|
|
78
|
+
error.message || 'Unknown error occurred'
|
|
79
|
+
}. Please check your robot ID and try again.`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
async onDisable(context) {
|
|
85
|
+
const { robotId } = context.propsValue;
|
|
86
|
+
|
|
87
|
+
const webhookId = await context.store.get<string>(TRIGGER_KEY);
|
|
88
|
+
const apiKey = context.auth.secret_text;
|
|
89
|
+
|
|
90
|
+
if (!isNil(webhookId)) {
|
|
91
|
+
try {
|
|
92
|
+
await browseAiApiCall({
|
|
93
|
+
method: HttpMethod.DELETE,
|
|
94
|
+
auth: { apiKey },
|
|
95
|
+
resourceUri: `/robots/${robotId}/webhooks/${webhookId}`,
|
|
96
|
+
});
|
|
97
|
+
} catch (error: any) {
|
|
98
|
+
console.warn(
|
|
99
|
+
`Warning: Failed to clean up webhook ${webhookId}:`,
|
|
100
|
+
error.message
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// Clean up the stored webhook ID even if deletion failed
|
|
104
|
+
await context.store.delete(TRIGGER_KEY);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
async run(context) {
|
|
110
|
+
const payload = context.payload.body as {
|
|
111
|
+
task: Record<string, any>;
|
|
112
|
+
event: string;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
if (payload.event !== 'task.finishedWithError') return [];
|
|
116
|
+
|
|
117
|
+
return [payload.task];
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
async test(context) {
|
|
121
|
+
const { robotId } = context.propsValue;
|
|
122
|
+
|
|
123
|
+
const apiKey = context.auth.secret_text;
|
|
124
|
+
|
|
125
|
+
const response = await browseAiApiCall<{
|
|
126
|
+
result: { robotTasks: { items: { id: string }[] } };
|
|
127
|
+
}>({
|
|
128
|
+
method: HttpMethod.GET,
|
|
129
|
+
auth: { apiKey },
|
|
130
|
+
resourceUri: `/robots/${robotId}/tasks`,
|
|
131
|
+
query: { status: 'failed', sort: '-createdAt' },
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return response.result.robotTasks.items;
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
sampleData: {},
|
|
138
|
+
});
|