Skip to content

Commit 8bd424a

Browse files
authored
vapi: fixes (patch) (#970)
1 parent 1753e18 commit 8bd424a

File tree

9 files changed

+81
-43
lines changed

9 files changed

+81
-43
lines changed

src/appmixer/vapi/bundle.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
{
22
"name": "appmixer.vapi",
3-
"version": "1.0.0",
3+
"version": "1.0.1",
44
"changelog": {
55
"1.0.0": [
66
"Initial release with assistants and squads components."
7+
],
8+
"1.0.1": [
9+
"CreateSquad: changed Assistant field to multiselect Members, marked as required.",
10+
"UpdateSquad: marked Members field as required.",
11+
"FindSquads, FindAssistants: fixed date filter fields showing one day earlier than selected."
712
]
813
}
914
}
Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
'use strict';
22

3+
const { normalizeMultiselectInput } = require('../../lib');
4+
35
module.exports = {
46
async receive(context) {
5-
const { name, assistantId } = context.messages.in.content;
7+
const { name, members } = context.messages.in.content;
68

79
if (!name) {
810
throw new context.CancelError('Name is required!');
911
}
1012

11-
const payload = { name };
12-
13-
// Add members array with assistantId if provided
14-
if (assistantId) {
15-
payload.members = [
16-
{
17-
assistantId: assistantId
18-
}
19-
];
13+
if (!members) {
14+
throw new context.CancelError('Members is required!');
2015
}
2116

17+
const payload = {
18+
name,
19+
members: normalizeMultiselectInput(members, context, 'Members').map(assistantId => ({ assistantId }))
20+
};
21+
2222
const { data } = await context.httpRequest({
2323
method: 'POST',
2424
url: 'https://api.vapi.ai/squad',
@@ -32,3 +32,4 @@ module.exports = {
3232
return context.sendJson(data, 'out');
3333
}
3434
};
35+

src/appmixer/vapi/core/CreateSquad/component.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
"name": {
2323
"type": "string"
2424
},
25-
"assistantId": {
26-
"type": "string"
25+
"members": {
26+
"type": [ "array", "string"]
2727
}
2828
},
29-
"required": ["name"]
29+
"required": ["name", "members"]
3030
},
3131
"inspector": {
3232
"inputs": {
@@ -36,11 +36,11 @@
3636
"label": "Name",
3737
"tooltip": "Name of the squad"
3838
},
39-
"assistantId": {
40-
"type": "select",
39+
"members": {
40+
"type": "multiselect",
4141
"index": 2,
42-
"label": "Assistant",
43-
"tooltip": "Select an assistant to add to the squad",
42+
"label": "Members",
43+
"tooltip": "Select assistants to add as members of the squad.",
4444
"source": {
4545
"url": "/component/appmixer/vapi/core/ListAssistants?outPort=out"
4646
}

src/appmixer/vapi/core/FindAssistants/FindAssistants.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,19 +123,19 @@ module.exports = {
123123
}
124124

125125
if (createdAtGt) {
126-
params.createdAtGt = createdAtGt;
126+
params.createdAtGt = new Date(createdAtGt).toISOString();
127127
}
128128

129129
if (createdAtLt) {
130-
params.createdAtLt = createdAtLt;
130+
params.createdAtLt = new Date(createdAtLt).toISOString();
131131
}
132132

133133
if (updatedAtGt) {
134-
params.updatedAtGt = updatedAtGt;
134+
params.updatedAtGt = new Date(updatedAtGt).toISOString();
135135
}
136136

137137
if (updatedAtLt) {
138-
params.updatedAtLt = updatedAtLt;
138+
params.updatedAtLt = new Date(updatedAtLt).toISOString();
139139
}
140140

141141
// https://docs.vapi.ai/api-reference/assistants/list

src/appmixer/vapi/core/FindSquads/FindSquads.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ module.exports = {
2424
const params = {};
2525

2626
if (createdAtGt) {
27-
params.createdAtGt = createdAtGt;
27+
params.createdAtGt = new Date(createdAtGt).toISOString();
2828
}
2929
if (createdAtLt) {
30-
params.createdAtLt = createdAtLt;
30+
params.createdAtLt = new Date(createdAtLt).toISOString();
3131
}
3232
if (updatedAtGt) {
33-
params.updatedAtGt = updatedAtGt;
33+
params.updatedAtGt = new Date(updatedAtGt).toISOString();
3434
}
3535
if (updatedAtLt) {
36-
params.updatedAtLt = updatedAtLt;
36+
params.updatedAtLt = new Date(updatedAtLt).toISOString();
3737
}
3838

3939
const { data } = await context.httpRequest({

src/appmixer/vapi/core/FindSquads/component.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,25 @@
4242
"createdAtGt": {
4343
"type": "date-time",
4444
"tooltip": "Filter squads created after this timestamp (ISO 8601 format).",
45-
"label": "Created At Gt",
45+
"label": "Created At Greater Than",
4646
"index": 0
4747
},
4848
"createdAtLt": {
4949
"type": "date-time",
5050
"tooltip": "Filter squads created before this timestamp (ISO 8601 format).",
51-
"label": "Created At Lt",
51+
"label": "Created At Less Than",
5252
"index": 1
5353
},
5454
"updatedAtGt": {
5555
"type": "date-time",
5656
"tooltip": "Filter squads updated after this timestamp (ISO 8601 format).",
57-
"label": "Updated At Gt",
57+
"label": "Updated At Greater Than",
5858
"index": 2
5959
},
6060
"updatedAtLt": {
6161
"type": "date-time",
6262
"tooltip": "Filter squads updated before this timestamp (ISO 8601 format).",
63-
"label": "Updated At Lt",
63+
"label": "Updated At Less Than",
6464
"index": 3
6565
},
6666
"outputType": {

src/appmixer/vapi/core/UpdateSquad/UpdateSquad.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
const { normalizeMultiselectInput } = require('../../lib');
4+
35
module.exports = {
46
async receive(context) {
57
const { squadId, name, members } = context.messages.in.content;
@@ -8,20 +10,18 @@ module.exports = {
810
throw new context.CancelError('Squad ID is required!');
911
}
1012

11-
const payload = {};
13+
if (!members) {
14+
throw new context.CancelError('Members is required!');
15+
}
16+
17+
const payload = {
18+
members: normalizeMultiselectInput(members, context, 'Members').map(assistantId => ({ assistantId }))
19+
};
1220

1321
if (name) {
1422
payload.name = name;
1523
}
1624

17-
if (members) {
18-
try {
19-
payload.members = JSON.parse(members);
20-
} catch (error) {
21-
throw new context.CancelError(`Invalid members JSON: ${error.message}`);
22-
}
23-
}
24-
2525
await context.httpRequest({
2626
method: 'PATCH',
2727
url: `https://api.vapi.ai/squad/${squadId}`,

src/appmixer/vapi/core/UpdateSquad/component.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@
2626
"type": "string"
2727
},
2828
"members": {
29-
"type": "string"
29+
"type": [ "array", "string"]
3030
}
3131
},
3232
"required": [
33-
"squadId"
33+
"squadId",
34+
"members"
3435
]
3536
},
3637
"inspector": {
@@ -48,10 +49,13 @@
4849
"tooltip": "Name of the squad"
4950
},
5051
"members": {
51-
"type": "textarea",
52+
"type": "multiselect",
5253
"index": 3,
5354
"label": "Members",
54-
"tooltip": "Squad members configuration as JSON. Example: [{ \"assistantId\": \"assistant-123\" }, { \"assistantId\": \"assistant-456\" }]."
55+
"tooltip": "Select assistants to set as members of the squad.",
56+
"source": {
57+
"url": "/component/appmixer/vapi/core/ListAssistants?outPort=out"
58+
}
5559
}
5660
}
5761
}

src/appmixer/vapi/lib.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,34 @@ module.exports = {
7979
if (outputType === 'file') {
8080
return context.sendJson([{ label: 'File ID', value: 'fileId' }], 'out');
8181
}
82+
},
83+
84+
/**
85+
* Normalize multiselect input (array or string) to array format for Airtable API.
86+
* @param {string|string[]} input
87+
* @param {number} maxItems
88+
* @param {object} context
89+
* @param {string} fieldName
90+
* @returns {string[]}
91+
*/
92+
normalizeMultiselectInput(input, context, fieldName, maxItems) {
93+
94+
let normalizedInput;
95+
96+
if (Array.isArray(input)) {
97+
normalizedInput = input;
98+
} else if (typeof input === 'string') {
99+
// Handle comma-separated string
100+
normalizedInput = input.split(',').map(item => item.trim()).filter(item => item.length > 0);
101+
} else {
102+
throw new context.CancelError(`${fieldName} must be a string or an array`);
103+
}
104+
105+
if (maxItems !== Infinity && normalizedInput.length > maxItems) {
106+
throw new context.CancelError(`Cannot have more than ${maxItems} fields selected in ${fieldName}.`);
107+
}
108+
109+
return normalizedInput;
82110
}
83111
};
84112

0 commit comments

Comments
 (0)