@agnocon/piece-bland-ai 0.1.4
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 +38 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/actions/get-call-details.d.ts +4 -0
- package/dist/lib/actions/get-call-details.d.ts.map +1 -0
- package/dist/lib/actions/get-call-details.js +38 -0
- package/dist/lib/actions/get-call-details.js.map +1 -0
- package/dist/lib/actions/list-calls.d.ts +6 -0
- package/dist/lib/actions/list-calls.d.ts.map +1 -0
- package/dist/lib/actions/list-calls.js +53 -0
- package/dist/lib/actions/list-calls.js.map +1 -0
- package/dist/lib/actions/send-call.d.ts +16 -0
- package/dist/lib/actions/send-call.d.ts.map +1 -0
- package/dist/lib/actions/send-call.js +152 -0
- package/dist/lib/actions/send-call.js.map +1 -0
- package/dist/lib/auth.d.ts +3 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +54 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/common/client.d.ts +9 -0
- package/dist/lib/common/client.d.ts.map +1 -0
- package/dist/lib/common/client.js +24 -0
- package/dist/lib/common/client.js.map +1 -0
- package/package.json +46 -0
- package/src/index.ts +30 -0
- package/src/lib/actions/get-call-details.ts +31 -0
- package/src/lib/actions/list-calls.ts +51 -0
- package/src/lib/actions/send-call.ts +158 -0
- package/src/lib/auth.ts +48 -0
- package/src/lib/common/client.ts +22 -0
package/LICENSE.MIT-AP
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Activepieces AB
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
Derived helpers in this folder are adapted from Activepieces (MIT) for use
|
|
24
|
+
inside CX without depending on @activepieces/* packages at runtime.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,OAAO,yGAqBlB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.blandAi = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
// Vendored from Activepieces packages/pieces/community/bland-ai/src/index.ts (MIT).
|
|
6
|
+
// Generated by packages/scripts/vendor-ap.mjs - do not edit by hand.
|
|
7
|
+
const pieces_common_1 = require("@agnocon/pieces-common");
|
|
8
|
+
const pieces_framework_1 = require("@agnocon/pieces-framework");
|
|
9
|
+
const pieces_framework_2 = require("@agnocon/pieces-framework");
|
|
10
|
+
const auth_1 = require("./lib/auth");
|
|
11
|
+
const send_call_1 = require("./lib/actions/send-call");
|
|
12
|
+
const get_call_details_1 = require("./lib/actions/get-call-details");
|
|
13
|
+
const list_calls_1 = require("./lib/actions/list-calls");
|
|
14
|
+
exports.blandAi = (0, pieces_framework_1.createPiece)({
|
|
15
|
+
displayName: 'Bland AI',
|
|
16
|
+
description: 'AI phone calling platform for outbound and conversational voice workflows.',
|
|
17
|
+
minimumSupportedRelease: '0.30.0',
|
|
18
|
+
logoUrl: 'https://cdn.activepieces.com/pieces/bland-ai.png',
|
|
19
|
+
categories: [pieces_framework_2.PieceCategory.COMMUNICATION],
|
|
20
|
+
auth: auth_1.blandAiAuth,
|
|
21
|
+
authors: ['Harmatta'],
|
|
22
|
+
actions: [
|
|
23
|
+
send_call_1.sendCall,
|
|
24
|
+
get_call_details_1.getCallDetails,
|
|
25
|
+
list_calls_1.listCalls,
|
|
26
|
+
(0, pieces_common_1.createCustomApiCallAction)({
|
|
27
|
+
auth: auth_1.blandAiAuth,
|
|
28
|
+
baseUrl: () => auth_1.BLAND_AI_BASE_URL,
|
|
29
|
+
authMapping: (auth) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
|
|
30
|
+
return ({
|
|
31
|
+
authorization: auth.secret_text,
|
|
32
|
+
});
|
|
33
|
+
}),
|
|
34
|
+
}),
|
|
35
|
+
],
|
|
36
|
+
triggers: [],
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,oFAAoF;AACpF,qEAAqE;AACrE,0DAAmE;AACnE,gEAAwD;AACxD,gEAA0D;AAC1D,qCAA4D;AAC5D,uDAAmD;AACnD,qEAAgE;AAChE,yDAAqD;AAExC,QAAA,OAAO,GAAG,IAAA,8BAAW,EAAC;IACjC,WAAW,EAAE,UAAU;IACvB,WAAW,EAAE,4EAA4E;IACzF,uBAAuB,EAAE,QAAQ;IACjC,OAAO,EAAE,kDAAkD;IAC3D,UAAU,EAAE,CAAC,gCAAa,CAAC,aAAa,CAAC;IACzC,IAAI,EAAE,kBAAW;IACjB,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,OAAO,EAAE;QACP,oBAAQ;QACR,iCAAc;QACd,sBAAS;QACT,IAAA,yCAAyB,EAAC;YACxB,IAAI,EAAE,kBAAW;YACjB,OAAO,EAAE,GAAG,EAAE,CAAC,wBAAiB;YAChC,WAAW,EAAE,CAAO,IAAI,EAAE,EAAE;gBAAC,OAAA,CAAC;oBAC5B,aAAa,EAAE,IAAI,CAAC,WAAW;iBAChC,CAAC,CAAA;cAAA;SACH,CAAC;KACH;IACD,QAAQ,EAAE,EAAE;CACb,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-call-details.d.ts","sourceRoot":"","sources":["../../../src/lib/actions/get-call-details.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,cAAc;;EAyBzB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCallDetails = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
// Vendored from Activepieces packages/pieces/community/bland-ai/src/lib/actions/get-call-details.ts (MIT).
|
|
6
|
+
// Generated by packages/scripts/vendor-ap.mjs - do not edit by hand.
|
|
7
|
+
const pieces_common_1 = require("@agnocon/pieces-common");
|
|
8
|
+
const pieces_framework_1 = require("@agnocon/pieces-framework");
|
|
9
|
+
const auth_1 = require("../auth");
|
|
10
|
+
const client_1 = require("../common/client");
|
|
11
|
+
exports.getCallDetails = (0, pieces_framework_1.createAction)({
|
|
12
|
+
auth: auth_1.blandAiAuth,
|
|
13
|
+
name: 'get_call_details',
|
|
14
|
+
displayName: 'Get Call Details',
|
|
15
|
+
description: 'Retrieve details for a specific Bland AI call.',
|
|
16
|
+
audience: 'both',
|
|
17
|
+
aiMetadata: {
|
|
18
|
+
description: 'Fetches the full record of one Bland AI call by its call ID (status, transcript, summary, recording URL, and post-call data). Use to inspect or poll the outcome of a call after it has been placed. Read-only and idempotent.',
|
|
19
|
+
idempotent: true,
|
|
20
|
+
},
|
|
21
|
+
props: {
|
|
22
|
+
callId: pieces_framework_1.Property.ShortText({
|
|
23
|
+
displayName: 'Call ID',
|
|
24
|
+
description: 'The Bland AI call identifier.',
|
|
25
|
+
required: true,
|
|
26
|
+
}),
|
|
27
|
+
},
|
|
28
|
+
run(context) {
|
|
29
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
30
|
+
return (0, client_1.blandApiCall)({
|
|
31
|
+
apiKey: context.auth.secret_text,
|
|
32
|
+
method: pieces_common_1.HttpMethod.GET,
|
|
33
|
+
path: `/calls/${encodeURIComponent(context.propsValue.callId)}`,
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=get-call-details.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-call-details.js","sourceRoot":"","sources":["../../../src/lib/actions/get-call-details.ts"],"names":[],"mappings":";;;;AAAA,2GAA2G;AAC3G,qEAAqE;AACrE,0DAAoD;AACpD,gEAAmE;AACnE,kCAAsC;AACtC,6CAAgD;AAEnC,QAAA,cAAc,GAAG,IAAA,+BAAY,EAAC;IACzC,IAAI,EAAE,kBAAW;IACjB,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,kBAAkB;IAC/B,WAAW,EAAE,gDAAgD;IAC7D,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE;QACV,WAAW,EACT,gOAAgO;QAClO,UAAU,EAAE,IAAI;KACjB;IACD,KAAK,EAAE;QACL,MAAM,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACzB,WAAW,EAAE,SAAS;YACtB,WAAW,EAAE,+BAA+B;YAC5C,QAAQ,EAAE,IAAI;SACf,CAAC;KACH;IACK,GAAG,CAAC,OAAO;;YACf,OAAO,IAAA,qBAAY,EAAC;gBAClB,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW;gBAChC,MAAM,EAAE,0BAAU,CAAC,GAAG;gBACtB,IAAI,EAAE,UAAU,kBAAkB,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;aAChE,CAAC,CAAC;QACL,CAAC;KAAA;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const listCalls: import("@agnocon/pieces-framework").IAction<import("@agnocon/pieces-framework").SecretTextProperty<true>, {
|
|
2
|
+
limit: import("@agnocon/pieces-framework").NumberProperty<false>;
|
|
3
|
+
fromNumber: import("@agnocon/pieces-framework").ShortTextProperty<false>;
|
|
4
|
+
toNumber: import("@agnocon/pieces-framework").ShortTextProperty<false>;
|
|
5
|
+
}>;
|
|
6
|
+
//# sourceMappingURL=list-calls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-calls.d.ts","sourceRoot":"","sources":["../../../src/lib/actions/list-calls.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,SAAS;;;;EA6CpB,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listCalls = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
// Vendored from Activepieces packages/pieces/community/bland-ai/src/lib/actions/list-calls.ts (MIT).
|
|
6
|
+
// Generated by packages/scripts/vendor-ap.mjs - do not edit by hand.
|
|
7
|
+
const pieces_common_1 = require("@agnocon/pieces-common");
|
|
8
|
+
const pieces_framework_1 = require("@agnocon/pieces-framework");
|
|
9
|
+
const auth_1 = require("../auth");
|
|
10
|
+
const client_1 = require("../common/client");
|
|
11
|
+
exports.listCalls = (0, pieces_framework_1.createAction)({
|
|
12
|
+
auth: auth_1.blandAiAuth,
|
|
13
|
+
name: 'list_calls',
|
|
14
|
+
displayName: 'List Calls',
|
|
15
|
+
description: 'List recent Bland AI calls with optional filters.',
|
|
16
|
+
audience: 'both',
|
|
17
|
+
aiMetadata: {
|
|
18
|
+
description: 'Lists recent Bland AI calls, optionally narrowed by origin (from) and/or destination (to) phone number and capped by a limit (1-100). Leave the number filters empty to retrieve the most recent calls regardless of party. Use to discover call IDs or survey call history. Read-only and idempotent.',
|
|
19
|
+
idempotent: true,
|
|
20
|
+
},
|
|
21
|
+
props: {
|
|
22
|
+
limit: pieces_framework_1.Property.Number({
|
|
23
|
+
displayName: 'Limit',
|
|
24
|
+
description: 'Maximum number of calls to return.',
|
|
25
|
+
required: false,
|
|
26
|
+
defaultValue: 10,
|
|
27
|
+
}),
|
|
28
|
+
fromNumber: pieces_framework_1.Property.ShortText({
|
|
29
|
+
displayName: 'From Number',
|
|
30
|
+
description: 'Optional origin phone number filter.',
|
|
31
|
+
required: false,
|
|
32
|
+
}),
|
|
33
|
+
toNumber: pieces_framework_1.Property.ShortText({
|
|
34
|
+
displayName: 'To Number',
|
|
35
|
+
description: 'Optional destination phone number filter.',
|
|
36
|
+
required: false,
|
|
37
|
+
}),
|
|
38
|
+
},
|
|
39
|
+
run(context) {
|
|
40
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
const { limit, fromNumber, toNumber } = context.propsValue;
|
|
42
|
+
const safeLimit = Math.max(1, Math.min(100, limit !== null && limit !== void 0 ? limit : 10));
|
|
43
|
+
const query = Object.assign(Object.assign({ limit: String(safeLimit) }, (fromNumber ? { from_number: fromNumber } : {})), (toNumber ? { to_number: toNumber } : {}));
|
|
44
|
+
return (0, client_1.blandApiCall)({
|
|
45
|
+
apiKey: context.auth.secret_text,
|
|
46
|
+
method: pieces_common_1.HttpMethod.GET,
|
|
47
|
+
path: '/calls',
|
|
48
|
+
query,
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=list-calls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-calls.js","sourceRoot":"","sources":["../../../src/lib/actions/list-calls.ts"],"names":[],"mappings":";;;;AAAA,qGAAqG;AACrG,qEAAqE;AACrE,0DAAoD;AACpD,gEAAmE;AACnE,kCAAsC;AACtC,6CAAgD;AAEnC,QAAA,SAAS,GAAG,IAAA,+BAAY,EAAC;IACpC,IAAI,EAAE,kBAAW;IACjB,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,YAAY;IACzB,WAAW,EAAE,mDAAmD;IAChE,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE;QACV,WAAW,EACT,wSAAwS;QAC1S,UAAU,EAAE,IAAI;KACjB;IACD,KAAK,EAAE;QACL,KAAK,EAAE,2BAAQ,CAAC,MAAM,CAAC;YACrB,WAAW,EAAE,OAAO;YACpB,WAAW,EAAE,oCAAoC;YACjD,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,EAAE;SACjB,CAAC;QACF,UAAU,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAC7B,WAAW,EAAE,aAAa;YAC1B,WAAW,EAAE,sCAAsC;YACnD,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,QAAQ,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAC3B,WAAW,EAAE,WAAW;YACxB,WAAW,EAAE,2CAA2C;YACxD,QAAQ,EAAE,KAAK;SAChB,CAAC;KACH;IACK,GAAG,CAAC,OAAO;;YACf,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;YAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,KAAK,iCACT,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,IACrB,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAC/C,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC7C,CAAC;YAEF,OAAO,IAAA,qBAAY,EAAC;gBAClB,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW;gBAChC,MAAM,EAAE,0BAAU,CAAC,GAAG;gBACtB,IAAI,EAAE,QAAQ;gBACd,KAAK;aACN,CAAC,CAAC;QACL,CAAC;KAAA;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const sendCall: import("@agnocon/pieces-framework").IAction<import("@agnocon/pieces-framework").SecretTextProperty<true>, {
|
|
2
|
+
phoneNumber: import("@agnocon/pieces-framework").ShortTextProperty<true>;
|
|
3
|
+
task: import("@agnocon/pieces-framework").LongTextProperty<false>;
|
|
4
|
+
pathwayId: import("@agnocon/pieces-framework").ShortTextProperty<false>;
|
|
5
|
+
firstSentence: import("@agnocon/pieces-framework").ShortTextProperty<false>;
|
|
6
|
+
voice: import("@agnocon/pieces-framework").StaticDropdownProperty<string, false>;
|
|
7
|
+
model: import("@agnocon/pieces-framework").StaticDropdownProperty<string, false>;
|
|
8
|
+
language: import("@agnocon/pieces-framework").ShortTextProperty<false>;
|
|
9
|
+
maxDuration: import("@agnocon/pieces-framework").NumberProperty<false>;
|
|
10
|
+
waitForGreeting: import("@agnocon/pieces-framework").CheckboxProperty<false>;
|
|
11
|
+
record: import("@agnocon/pieces-framework").CheckboxProperty<false>;
|
|
12
|
+
transferPhoneNumber: import("@agnocon/pieces-framework").ShortTextProperty<false>;
|
|
13
|
+
webhook: import("@agnocon/pieces-framework").ShortTextProperty<false>;
|
|
14
|
+
summaryPrompt: import("@agnocon/pieces-framework").LongTextProperty<false>;
|
|
15
|
+
}>;
|
|
16
|
+
//# sourceMappingURL=send-call.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-call.d.ts","sourceRoot":"","sources":["../../../src/lib/actions/send-call.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;EAwJnB,CAAC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendCall = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
// Vendored from Activepieces packages/pieces/community/bland-ai/src/lib/actions/send-call.ts (MIT).
|
|
6
|
+
// Generated by packages/scripts/vendor-ap.mjs - do not edit by hand.
|
|
7
|
+
const pieces_common_1 = require("@agnocon/pieces-common");
|
|
8
|
+
const pieces_framework_1 = require("@agnocon/pieces-framework");
|
|
9
|
+
const auth_1 = require("../auth");
|
|
10
|
+
const client_1 = require("../common/client");
|
|
11
|
+
exports.sendCall = (0, pieces_framework_1.createAction)({
|
|
12
|
+
auth: auth_1.blandAiAuth,
|
|
13
|
+
name: 'send_call',
|
|
14
|
+
displayName: 'Send Call',
|
|
15
|
+
description: 'Initiate an AI phone call to a recipient.',
|
|
16
|
+
audience: 'both',
|
|
17
|
+
aiMetadata: {
|
|
18
|
+
description: 'Places an outbound AI voice call to a phone number (E.164 format, with country code) via Bland AI. Drive the conversation either by supplying free-text Task instructions for the agent or by referencing a pre-built Pathway ID (the Pathway overrides the Task). Use to actually start a call; not idempotent — each call triggers a new outbound dial.',
|
|
19
|
+
idempotent: false,
|
|
20
|
+
},
|
|
21
|
+
props: {
|
|
22
|
+
phoneNumber: pieces_framework_1.Property.ShortText({
|
|
23
|
+
displayName: 'Phone Number',
|
|
24
|
+
description: 'The number to call in E.164 format (e.g. +12223334444). Must include the country code.',
|
|
25
|
+
required: true,
|
|
26
|
+
}),
|
|
27
|
+
task: pieces_framework_1.Property.LongText({
|
|
28
|
+
displayName: 'Task',
|
|
29
|
+
description: 'Instructions for the AI agent — what it should say, ask, or accomplish during the call. Not required if using a Pathway ID.',
|
|
30
|
+
required: false,
|
|
31
|
+
}),
|
|
32
|
+
pathwayId: pieces_framework_1.Property.ShortText({
|
|
33
|
+
displayName: 'Pathway ID',
|
|
34
|
+
description: 'UUID of a pre-built Pathway from your Bland AI dashboard. When provided, it overrides the Task field. Find it in the Pathways section of your dashboard.',
|
|
35
|
+
required: false,
|
|
36
|
+
}),
|
|
37
|
+
firstSentence: pieces_framework_1.Property.ShortText({
|
|
38
|
+
displayName: 'First Sentence',
|
|
39
|
+
description: "Exact opening line the agent will say when the call is answered. Leave blank to let the agent decide.",
|
|
40
|
+
required: false,
|
|
41
|
+
}),
|
|
42
|
+
voice: pieces_framework_1.Property.StaticDropdown({
|
|
43
|
+
displayName: 'Voice',
|
|
44
|
+
description: 'The voice the AI agent will use. Choose from Bland AI preset voices optimised for phone quality.',
|
|
45
|
+
required: false,
|
|
46
|
+
defaultValue: 'maya',
|
|
47
|
+
options: {
|
|
48
|
+
options: [
|
|
49
|
+
{ label: 'Maya — Young American Female', value: 'maya' },
|
|
50
|
+
{ label: 'Ryan — Professional American Male', value: 'ryan' },
|
|
51
|
+
{ label: 'Mason — American Male', value: 'mason' },
|
|
52
|
+
{ label: 'Tina — Gentle American Female', value: 'tina' },
|
|
53
|
+
{ label: 'Josh — American Male', value: 'josh' },
|
|
54
|
+
{ label: 'Florian', value: 'florian' },
|
|
55
|
+
{ label: 'Derek', value: 'derek' },
|
|
56
|
+
{ label: 'June', value: 'june' },
|
|
57
|
+
{ label: 'Nat', value: 'nat' },
|
|
58
|
+
{ label: 'Paige', value: 'paige' },
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
}),
|
|
62
|
+
model: pieces_framework_1.Property.StaticDropdown({
|
|
63
|
+
displayName: 'Model',
|
|
64
|
+
description: '"Base" is the standard model. "Turbo" is faster with lower latency, recommended for time-sensitive conversations.',
|
|
65
|
+
required: false,
|
|
66
|
+
defaultValue: 'base',
|
|
67
|
+
options: {
|
|
68
|
+
options: [
|
|
69
|
+
{ label: 'Base (standard)', value: 'base' },
|
|
70
|
+
{ label: 'Turbo (lower latency)', value: 'turbo' },
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
74
|
+
language: pieces_framework_1.Property.ShortText({
|
|
75
|
+
displayName: 'Language',
|
|
76
|
+
description: 'Language code for transcription and speech (e.g. "en", "es", "fr"). Defaults to "babel-en" (English with accent tolerance).',
|
|
77
|
+
required: false,
|
|
78
|
+
}),
|
|
79
|
+
maxDuration: pieces_framework_1.Property.Number({
|
|
80
|
+
displayName: 'Max Duration (minutes)',
|
|
81
|
+
description: 'Maximum call length in minutes. The call ends automatically after this time. Defaults to 30.',
|
|
82
|
+
required: false,
|
|
83
|
+
defaultValue: 30,
|
|
84
|
+
}),
|
|
85
|
+
waitForGreeting: pieces_framework_1.Property.Checkbox({
|
|
86
|
+
displayName: 'Wait for Greeting',
|
|
87
|
+
description: 'When enabled, the AI waits for the recipient to speak first before responding. Useful when calling into IVR systems.',
|
|
88
|
+
required: false,
|
|
89
|
+
defaultValue: false,
|
|
90
|
+
}),
|
|
91
|
+
record: pieces_framework_1.Property.Checkbox({
|
|
92
|
+
displayName: 'Record Call',
|
|
93
|
+
description: 'When enabled, the call is recorded. The recording URL is included in the post-call data.',
|
|
94
|
+
required: false,
|
|
95
|
+
defaultValue: false,
|
|
96
|
+
}),
|
|
97
|
+
transferPhoneNumber: pieces_framework_1.Property.ShortText({
|
|
98
|
+
displayName: 'Transfer Phone Number',
|
|
99
|
+
description: 'E.164 phone number to transfer the call to if the AI decides a human is needed (e.g. +12223334444).',
|
|
100
|
+
required: false,
|
|
101
|
+
}),
|
|
102
|
+
webhook: pieces_framework_1.Property.ShortText({
|
|
103
|
+
displayName: 'Webhook URL',
|
|
104
|
+
description: 'URL that receives a POST request with full call data (transcript, summary, recording URL) after the call ends.',
|
|
105
|
+
required: false,
|
|
106
|
+
}),
|
|
107
|
+
summaryPrompt: pieces_framework_1.Property.LongText({
|
|
108
|
+
displayName: 'Summary Prompt',
|
|
109
|
+
description: 'Custom instructions for how the post-call summary should be written (max 2000 characters). Leave blank to use the default summary format.',
|
|
110
|
+
required: false,
|
|
111
|
+
}),
|
|
112
|
+
},
|
|
113
|
+
run(context) {
|
|
114
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
115
|
+
const { phoneNumber, task, pathwayId, firstSentence, voice, model, language, maxDuration, waitForGreeting, record, transferPhoneNumber, webhook, summaryPrompt, } = context.propsValue;
|
|
116
|
+
const body = {
|
|
117
|
+
phone_number: phoneNumber,
|
|
118
|
+
};
|
|
119
|
+
if (task)
|
|
120
|
+
body['task'] = task;
|
|
121
|
+
if (pathwayId)
|
|
122
|
+
body['pathway_id'] = pathwayId;
|
|
123
|
+
if (firstSentence)
|
|
124
|
+
body['first_sentence'] = firstSentence;
|
|
125
|
+
if (voice)
|
|
126
|
+
body['voice'] = voice;
|
|
127
|
+
if (model)
|
|
128
|
+
body['model'] = model;
|
|
129
|
+
if (language)
|
|
130
|
+
body['language'] = language;
|
|
131
|
+
if (maxDuration !== undefined && maxDuration !== null)
|
|
132
|
+
body['max_duration'] = maxDuration;
|
|
133
|
+
if (waitForGreeting !== undefined)
|
|
134
|
+
body['wait_for_greeting'] = waitForGreeting;
|
|
135
|
+
if (record !== undefined)
|
|
136
|
+
body['record'] = record;
|
|
137
|
+
if (transferPhoneNumber)
|
|
138
|
+
body['transfer_phone_number'] = transferPhoneNumber;
|
|
139
|
+
if (webhook)
|
|
140
|
+
body['webhook'] = webhook;
|
|
141
|
+
if (summaryPrompt)
|
|
142
|
+
body['summary_prompt'] = summaryPrompt;
|
|
143
|
+
return (0, client_1.blandApiCall)({
|
|
144
|
+
apiKey: context.auth.secret_text,
|
|
145
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
146
|
+
path: '/calls',
|
|
147
|
+
body,
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
//# sourceMappingURL=send-call.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-call.js","sourceRoot":"","sources":["../../../src/lib/actions/send-call.ts"],"names":[],"mappings":";;;;AAAA,oGAAoG;AACpG,qEAAqE;AACrE,0DAAoD;AACpD,gEAAmE;AACnE,kCAAsC;AACtC,6CAAgD;AAEnC,QAAA,QAAQ,GAAG,IAAA,+BAAY,EAAC;IACnC,IAAI,EAAE,kBAAW;IACjB,IAAI,EAAE,WAAW;IACjB,WAAW,EAAE,WAAW;IACxB,WAAW,EAAE,2CAA2C;IACxD,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE;QACV,WAAW,EACT,2VAA2V;QAC7V,UAAU,EAAE,KAAK;KAClB;IACD,KAAK,EAAE;QACL,WAAW,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAC9B,WAAW,EAAE,cAAc;YAC3B,WAAW,EAAE,wFAAwF;YACrG,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,IAAI,EAAE,2BAAQ,CAAC,QAAQ,CAAC;YACtB,WAAW,EAAE,MAAM;YACnB,WAAW,EACT,6HAA6H;YAC/H,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,SAAS,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAC5B,WAAW,EAAE,YAAY;YACzB,WAAW,EACT,0JAA0J;YAC5J,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,aAAa,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAChC,WAAW,EAAE,gBAAgB;YAC7B,WAAW,EAAE,uGAAuG;YACpH,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,KAAK,EAAE,2BAAQ,CAAC,cAAc,CAAC;YAC7B,WAAW,EAAE,OAAO;YACpB,WAAW,EAAE,kGAAkG;YAC/G,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,MAAM;YACpB,OAAO,EAAE;gBACP,OAAO,EAAE;oBACP,EAAE,KAAK,EAAE,8BAA8B,EAAE,KAAK,EAAE,MAAM,EAAE;oBACxD,EAAE,KAAK,EAAE,mCAAmC,EAAE,KAAK,EAAE,MAAM,EAAE;oBAC7D,EAAE,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,OAAO,EAAE;oBAClD,EAAE,KAAK,EAAE,+BAA+B,EAAE,KAAK,EAAE,MAAM,EAAE;oBACzD,EAAE,KAAK,EAAE,sBAAsB,EAAE,KAAK,EAAE,MAAM,EAAE;oBAChD,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;oBACtC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;oBAClC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;oBAChC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;oBAC9B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;iBACnC;aACF;SACF,CAAC;QACF,KAAK,EAAE,2BAAQ,CAAC,cAAc,CAAC;YAC7B,WAAW,EAAE,OAAO;YACpB,WAAW,EACT,mHAAmH;YACrH,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,MAAM;YACpB,OAAO,EAAE;gBACP,OAAO,EAAE;oBACP,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE;oBAC3C,EAAE,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,OAAO,EAAE;iBACnD;aACF;SACF,CAAC;QACF,QAAQ,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAC3B,WAAW,EAAE,UAAU;YACvB,WAAW,EACT,6HAA6H;YAC/H,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,WAAW,EAAE,2BAAQ,CAAC,MAAM,CAAC;YAC3B,WAAW,EAAE,wBAAwB;YACrC,WAAW,EAAE,8FAA8F;YAC3G,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,EAAE;SACjB,CAAC;QACF,eAAe,EAAE,2BAAQ,CAAC,QAAQ,CAAC;YACjC,WAAW,EAAE,mBAAmB;YAChC,WAAW,EACT,sHAAsH;YACxH,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,KAAK;SACpB,CAAC;QACF,MAAM,EAAE,2BAAQ,CAAC,QAAQ,CAAC;YACxB,WAAW,EAAE,aAAa;YAC1B,WAAW,EAAE,0FAA0F;YACvG,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,KAAK;SACpB,CAAC;QACF,mBAAmB,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACtC,WAAW,EAAE,uBAAuB;YACpC,WAAW,EACT,qGAAqG;YACvG,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,OAAO,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAC1B,WAAW,EAAE,aAAa;YAC1B,WAAW,EACT,gHAAgH;YAClH,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,aAAa,EAAE,2BAAQ,CAAC,QAAQ,CAAC;YAC/B,WAAW,EAAE,gBAAgB;YAC7B,WAAW,EACT,2IAA2I;YAC7I,QAAQ,EAAE,KAAK;SAChB,CAAC;KACH;IACK,GAAG,CAAC,OAAO;;YACf,MAAM,EACJ,WAAW,EACX,IAAI,EACJ,SAAS,EACT,aAAa,EACb,KAAK,EACL,KAAK,EACL,QAAQ,EACR,WAAW,EACX,eAAe,EACf,MAAM,EACN,mBAAmB,EACnB,OAAO,EACP,aAAa,GACd,GAAG,OAAO,CAAC,UAAU,CAAC;YAEvB,MAAM,IAAI,GAA4B;gBACpC,YAAY,EAAE,WAAW;aAC1B,CAAC;YAEF,IAAI,IAAI;gBAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;YAC9B,IAAI,SAAS;gBAAE,IAAI,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;YAC9C,IAAI,aAAa;gBAAE,IAAI,CAAC,gBAAgB,CAAC,GAAG,aAAa,CAAC;YAC1D,IAAI,KAAK;gBAAE,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;YACjC,IAAI,KAAK;gBAAE,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;YACjC,IAAI,QAAQ;gBAAE,IAAI,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC;YAC1C,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,IAAI;gBAAE,IAAI,CAAC,cAAc,CAAC,GAAG,WAAW,CAAC;YAC1F,IAAI,eAAe,KAAK,SAAS;gBAAE,IAAI,CAAC,mBAAmB,CAAC,GAAG,eAAe,CAAC;YAC/E,IAAI,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;YAClD,IAAI,mBAAmB;gBAAE,IAAI,CAAC,uBAAuB,CAAC,GAAG,mBAAmB,CAAC;YAC7E,IAAI,OAAO;gBAAE,IAAI,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC;YACvC,IAAI,aAAa;gBAAE,IAAI,CAAC,gBAAgB,CAAC,GAAG,aAAa,CAAC;YAE1D,OAAO,IAAA,qBAAY,EAAC;gBAClB,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW;gBAChC,MAAM,EAAE,0BAAU,CAAC,IAAI;gBACvB,IAAI,EAAE,QAAQ;gBACd,IAAI;aACL,CAAC,CAAC;QACL,CAAC;KAAA;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,iBAAiB,4BAA4B,CAAC;AAE3D,eAAO,MAAM,WAAW,8DAyCtB,CAAC"}
|
package/dist/lib/auth.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.blandAiAuth = exports.BLAND_AI_BASE_URL = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
// Vendored from Activepieces packages/pieces/community/bland-ai/src/lib/auth.ts (MIT).
|
|
6
|
+
// Generated by packages/scripts/vendor-ap.mjs - do not edit by hand.
|
|
7
|
+
const pieces_framework_1 = require("@agnocon/pieces-framework");
|
|
8
|
+
const pieces_common_1 = require("@agnocon/pieces-common");
|
|
9
|
+
exports.BLAND_AI_BASE_URL = 'https://api.bland.ai/v1';
|
|
10
|
+
exports.blandAiAuth = pieces_framework_1.PieceAuth.SecretText({
|
|
11
|
+
displayName: 'API Key',
|
|
12
|
+
description: `To get your API key:
|
|
13
|
+
1. Log in to your [Bland AI dashboard](https://app.bland.ai)
|
|
14
|
+
2. Go to **Profile** (bottom-left menu) -> **Settings**
|
|
15
|
+
3. Click **API Keys** and copy your key`,
|
|
16
|
+
required: true,
|
|
17
|
+
validate: (_a) => tslib_1.__awaiter(void 0, [_a], void 0, function* ({ auth }) {
|
|
18
|
+
var _b, _c;
|
|
19
|
+
try {
|
|
20
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
21
|
+
method: pieces_common_1.HttpMethod.GET,
|
|
22
|
+
url: `${exports.BLAND_AI_BASE_URL}/calls`,
|
|
23
|
+
headers: {
|
|
24
|
+
authorization: auth,
|
|
25
|
+
'Content-Type': 'application/json',
|
|
26
|
+
},
|
|
27
|
+
queryParams: {
|
|
28
|
+
limit: '1',
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
if (response.status === 200) {
|
|
32
|
+
return { valid: true };
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
valid: false,
|
|
36
|
+
error: `Unexpected status: ${response.status}`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
const err = e;
|
|
41
|
+
if (((_b = err.response) === null || _b === void 0 ? void 0 : _b.status) === 401 || ((_c = err.response) === null || _c === void 0 ? void 0 : _c.status) === 403) {
|
|
42
|
+
return {
|
|
43
|
+
valid: false,
|
|
44
|
+
error: 'Invalid API key. Please check your Bland AI account settings.',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
valid: false,
|
|
49
|
+
error: `Connection failed: ${String(e).slice(0, 100)}`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":";;;;AAAA,uFAAuF;AACvF,qEAAqE;AACrE,gEAAsD;AACtD,0DAAgE;AAEnD,QAAA,iBAAiB,GAAG,yBAAyB,CAAC;AAE9C,QAAA,WAAW,GAAG,4BAAS,CAAC,UAAU,CAAC;IAC9C,WAAW,EAAE,SAAS;IACtB,WAAW,EAAE;;;wCAGyB;IACtC,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAiB,EAAE,oDAAZ,EAAE,IAAI,EAAE;;QACvB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,0BAAU,CAAC,WAAW,CAAC;gBAC5C,MAAM,EAAE,0BAAU,CAAC,GAAG;gBACtB,GAAG,EAAE,GAAG,yBAAiB,QAAQ;gBACjC,OAAO,EAAE;oBACP,aAAa,EAAE,IAAI;oBACnB,cAAc,EAAE,kBAAkB;iBACnC;gBACD,WAAW,EAAE;oBACX,KAAK,EAAE,GAAG;iBACX;aACF,CAAC,CAAC;YACH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;YACzB,CAAC;YACD,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,sBAAsB,QAAQ,CAAC,MAAM,EAAE;aAC/C,CAAC;QACJ,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,CAAuC,CAAC;YACpD,IAAI,CAAA,MAAA,GAAG,CAAC,QAAQ,0CAAE,MAAM,MAAK,GAAG,IAAI,CAAA,MAAA,GAAG,CAAC,QAAQ,0CAAE,MAAM,MAAK,GAAG,EAAE,CAAC;gBACjE,OAAO;oBACL,KAAK,EAAE,KAAK;oBACZ,KAAK,EAAE,+DAA+D;iBACvE,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,sBAAsB,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;aACvD,CAAC;QACJ,CAAC;IACH,CAAC,CAAA;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { HttpMethod } from '@agnocon/pieces-common';
|
|
2
|
+
export declare function blandApiCall<T>(params: {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
method: HttpMethod;
|
|
5
|
+
path: string;
|
|
6
|
+
body?: unknown;
|
|
7
|
+
query?: Record<string, string>;
|
|
8
|
+
}): Promise<T>;
|
|
9
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/common/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAc,MAAM,wBAAwB,CAAC;AAGhE,wBAAsB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,GAAG,OAAO,CAAC,CAAC,CAAC,CAYb"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.blandApiCall = blandApiCall;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
// Vendored from Activepieces packages/pieces/community/bland-ai/src/lib/common/client.ts (MIT).
|
|
6
|
+
// Generated by packages/scripts/vendor-ap.mjs - do not edit by hand.
|
|
7
|
+
const pieces_common_1 = require("@agnocon/pieces-common");
|
|
8
|
+
const auth_1 = require("../auth");
|
|
9
|
+
function blandApiCall(params) {
|
|
10
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
11
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
12
|
+
method: params.method,
|
|
13
|
+
url: `${auth_1.BLAND_AI_BASE_URL}${params.path}`,
|
|
14
|
+
headers: {
|
|
15
|
+
authorization: params.apiKey,
|
|
16
|
+
'Content-Type': 'application/json',
|
|
17
|
+
},
|
|
18
|
+
body: params.body,
|
|
19
|
+
queryParams: params.query,
|
|
20
|
+
});
|
|
21
|
+
return response.body;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/lib/common/client.ts"],"names":[],"mappings":";;AAKA,oCAkBC;;AAvBD,gGAAgG;AAChG,qEAAqE;AACrE,0DAAgE;AAChE,kCAA4C;AAE5C,SAAsB,YAAY,CAAI,MAMrC;;QACC,MAAM,QAAQ,GAAG,MAAM,0BAAU,CAAC,WAAW,CAAI;YAC/C,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,GAAG,EAAE,GAAG,wBAAiB,GAAG,MAAM,CAAC,IAAI,EAAE;YACzC,OAAO,EAAE;gBACP,aAAa,EAAE,MAAM,CAAC,MAAM;gBAC5B,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,WAAW,EAAE,MAAM,CAAC,KAAK;SAC1B,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agnocon/piece-bland-ai",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "AgnoCon bland ai connector",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"src",
|
|
17
|
+
"LICENSE.MIT-AP"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json",
|
|
21
|
+
"vendor": "node ../scripts/vendor-ap.mjs piece-bland-ai"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@agnocon/core-utils": "0.2.0",
|
|
25
|
+
"@agnocon/piece-types": "0.3.1",
|
|
26
|
+
"@agnocon/pieces-common": "0.12.8",
|
|
27
|
+
"@agnocon/pieces-framework": "0.36.0",
|
|
28
|
+
"tslib": "2.6.2"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "20.17.6",
|
|
32
|
+
"typescript": "5.5.4"
|
|
33
|
+
},
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"agnocon": {
|
|
36
|
+
"originVersion": "0.1.4"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "restricted",
|
|
40
|
+
"tag": "latest"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"agnocon",
|
|
44
|
+
"connector"
|
|
45
|
+
]
|
|
46
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createCustomApiCallAction } from '@agnocon/pieces-common';
|
|
2
|
+
import { createPiece } from '@agnocon/pieces-framework';
|
|
3
|
+
import { PieceCategory } from '@agnocon/pieces-framework';
|
|
4
|
+
import { blandAiAuth, BLAND_AI_BASE_URL } from './lib/auth';
|
|
5
|
+
import { sendCall } from './lib/actions/send-call';
|
|
6
|
+
import { getCallDetails } from './lib/actions/get-call-details';
|
|
7
|
+
import { listCalls } from './lib/actions/list-calls';
|
|
8
|
+
|
|
9
|
+
export const blandAi = createPiece({
|
|
10
|
+
displayName: 'Bland AI',
|
|
11
|
+
description: 'AI phone calling platform for outbound and conversational voice workflows.',
|
|
12
|
+
minimumSupportedRelease: '0.30.0',
|
|
13
|
+
logoUrl: 'https://cdn.activepieces.com/pieces/bland-ai.png',
|
|
14
|
+
categories: [PieceCategory.COMMUNICATION],
|
|
15
|
+
auth: blandAiAuth,
|
|
16
|
+
authors: ['Harmatta'],
|
|
17
|
+
actions: [
|
|
18
|
+
sendCall,
|
|
19
|
+
getCallDetails,
|
|
20
|
+
listCalls,
|
|
21
|
+
createCustomApiCallAction({
|
|
22
|
+
auth: blandAiAuth,
|
|
23
|
+
baseUrl: () => BLAND_AI_BASE_URL,
|
|
24
|
+
authMapping: async (auth) => ({
|
|
25
|
+
authorization: auth.secret_text,
|
|
26
|
+
}),
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
29
|
+
triggers: [],
|
|
30
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { HttpMethod } from '@agnocon/pieces-common';
|
|
2
|
+
import { createAction, Property } from '@agnocon/pieces-framework';
|
|
3
|
+
import { blandAiAuth } from '../auth';
|
|
4
|
+
import { blandApiCall } from '../common/client';
|
|
5
|
+
|
|
6
|
+
export const getCallDetails = createAction({
|
|
7
|
+
auth: blandAiAuth,
|
|
8
|
+
name: 'get_call_details',
|
|
9
|
+
displayName: 'Get Call Details',
|
|
10
|
+
description: 'Retrieve details for a specific Bland AI call.',
|
|
11
|
+
audience: 'both',
|
|
12
|
+
aiMetadata: {
|
|
13
|
+
description:
|
|
14
|
+
'Fetches the full record of one Bland AI call by its call ID (status, transcript, summary, recording URL, and post-call data). Use to inspect or poll the outcome of a call after it has been placed. Read-only and idempotent.',
|
|
15
|
+
idempotent: true,
|
|
16
|
+
},
|
|
17
|
+
props: {
|
|
18
|
+
callId: Property.ShortText({
|
|
19
|
+
displayName: 'Call ID',
|
|
20
|
+
description: 'The Bland AI call identifier.',
|
|
21
|
+
required: true,
|
|
22
|
+
}),
|
|
23
|
+
},
|
|
24
|
+
async run(context) {
|
|
25
|
+
return blandApiCall({
|
|
26
|
+
apiKey: context.auth.secret_text,
|
|
27
|
+
method: HttpMethod.GET,
|
|
28
|
+
path: `/calls/${encodeURIComponent(context.propsValue.callId)}`,
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { HttpMethod } from '@agnocon/pieces-common';
|
|
2
|
+
import { createAction, Property } from '@agnocon/pieces-framework';
|
|
3
|
+
import { blandAiAuth } from '../auth';
|
|
4
|
+
import { blandApiCall } from '../common/client';
|
|
5
|
+
|
|
6
|
+
export const listCalls = createAction({
|
|
7
|
+
auth: blandAiAuth,
|
|
8
|
+
name: 'list_calls',
|
|
9
|
+
displayName: 'List Calls',
|
|
10
|
+
description: 'List recent Bland AI calls with optional filters.',
|
|
11
|
+
audience: 'both',
|
|
12
|
+
aiMetadata: {
|
|
13
|
+
description:
|
|
14
|
+
'Lists recent Bland AI calls, optionally narrowed by origin (from) and/or destination (to) phone number and capped by a limit (1-100). Leave the number filters empty to retrieve the most recent calls regardless of party. Use to discover call IDs or survey call history. Read-only and idempotent.',
|
|
15
|
+
idempotent: true,
|
|
16
|
+
},
|
|
17
|
+
props: {
|
|
18
|
+
limit: Property.Number({
|
|
19
|
+
displayName: 'Limit',
|
|
20
|
+
description: 'Maximum number of calls to return.',
|
|
21
|
+
required: false,
|
|
22
|
+
defaultValue: 10,
|
|
23
|
+
}),
|
|
24
|
+
fromNumber: Property.ShortText({
|
|
25
|
+
displayName: 'From Number',
|
|
26
|
+
description: 'Optional origin phone number filter.',
|
|
27
|
+
required: false,
|
|
28
|
+
}),
|
|
29
|
+
toNumber: Property.ShortText({
|
|
30
|
+
displayName: 'To Number',
|
|
31
|
+
description: 'Optional destination phone number filter.',
|
|
32
|
+
required: false,
|
|
33
|
+
}),
|
|
34
|
+
},
|
|
35
|
+
async run(context) {
|
|
36
|
+
const { limit, fromNumber, toNumber } = context.propsValue;
|
|
37
|
+
const safeLimit = Math.max(1, Math.min(100, limit ?? 10));
|
|
38
|
+
const query: Record<string, string> = {
|
|
39
|
+
limit: String(safeLimit),
|
|
40
|
+
...(fromNumber ? { from_number: fromNumber } : {}),
|
|
41
|
+
...(toNumber ? { to_number: toNumber } : {}),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return blandApiCall({
|
|
45
|
+
apiKey: context.auth.secret_text,
|
|
46
|
+
method: HttpMethod.GET,
|
|
47
|
+
path: '/calls',
|
|
48
|
+
query,
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
});
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { HttpMethod } from '@agnocon/pieces-common';
|
|
2
|
+
import { createAction, Property } from '@agnocon/pieces-framework';
|
|
3
|
+
import { blandAiAuth } from '../auth';
|
|
4
|
+
import { blandApiCall } from '../common/client';
|
|
5
|
+
|
|
6
|
+
export const sendCall = createAction({
|
|
7
|
+
auth: blandAiAuth,
|
|
8
|
+
name: 'send_call',
|
|
9
|
+
displayName: 'Send Call',
|
|
10
|
+
description: 'Initiate an AI phone call to a recipient.',
|
|
11
|
+
audience: 'both',
|
|
12
|
+
aiMetadata: {
|
|
13
|
+
description:
|
|
14
|
+
'Places an outbound AI voice call to a phone number (E.164 format, with country code) via Bland AI. Drive the conversation either by supplying free-text Task instructions for the agent or by referencing a pre-built Pathway ID (the Pathway overrides the Task). Use to actually start a call; not idempotent — each call triggers a new outbound dial.',
|
|
15
|
+
idempotent: false,
|
|
16
|
+
},
|
|
17
|
+
props: {
|
|
18
|
+
phoneNumber: Property.ShortText({
|
|
19
|
+
displayName: 'Phone Number',
|
|
20
|
+
description: 'The number to call in E.164 format (e.g. +12223334444). Must include the country code.',
|
|
21
|
+
required: true,
|
|
22
|
+
}),
|
|
23
|
+
task: Property.LongText({
|
|
24
|
+
displayName: 'Task',
|
|
25
|
+
description:
|
|
26
|
+
'Instructions for the AI agent — what it should say, ask, or accomplish during the call. Not required if using a Pathway ID.',
|
|
27
|
+
required: false,
|
|
28
|
+
}),
|
|
29
|
+
pathwayId: Property.ShortText({
|
|
30
|
+
displayName: 'Pathway ID',
|
|
31
|
+
description:
|
|
32
|
+
'UUID of a pre-built Pathway from your Bland AI dashboard. When provided, it overrides the Task field. Find it in the Pathways section of your dashboard.',
|
|
33
|
+
required: false,
|
|
34
|
+
}),
|
|
35
|
+
firstSentence: Property.ShortText({
|
|
36
|
+
displayName: 'First Sentence',
|
|
37
|
+
description: "Exact opening line the agent will say when the call is answered. Leave blank to let the agent decide.",
|
|
38
|
+
required: false,
|
|
39
|
+
}),
|
|
40
|
+
voice: Property.StaticDropdown({
|
|
41
|
+
displayName: 'Voice',
|
|
42
|
+
description: 'The voice the AI agent will use. Choose from Bland AI preset voices optimised for phone quality.',
|
|
43
|
+
required: false,
|
|
44
|
+
defaultValue: 'maya',
|
|
45
|
+
options: {
|
|
46
|
+
options: [
|
|
47
|
+
{ label: 'Maya — Young American Female', value: 'maya' },
|
|
48
|
+
{ label: 'Ryan — Professional American Male', value: 'ryan' },
|
|
49
|
+
{ label: 'Mason — American Male', value: 'mason' },
|
|
50
|
+
{ label: 'Tina — Gentle American Female', value: 'tina' },
|
|
51
|
+
{ label: 'Josh — American Male', value: 'josh' },
|
|
52
|
+
{ label: 'Florian', value: 'florian' },
|
|
53
|
+
{ label: 'Derek', value: 'derek' },
|
|
54
|
+
{ label: 'June', value: 'june' },
|
|
55
|
+
{ label: 'Nat', value: 'nat' },
|
|
56
|
+
{ label: 'Paige', value: 'paige' },
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
}),
|
|
60
|
+
model: Property.StaticDropdown({
|
|
61
|
+
displayName: 'Model',
|
|
62
|
+
description:
|
|
63
|
+
'"Base" is the standard model. "Turbo" is faster with lower latency, recommended for time-sensitive conversations.',
|
|
64
|
+
required: false,
|
|
65
|
+
defaultValue: 'base',
|
|
66
|
+
options: {
|
|
67
|
+
options: [
|
|
68
|
+
{ label: 'Base (standard)', value: 'base' },
|
|
69
|
+
{ label: 'Turbo (lower latency)', value: 'turbo' },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
language: Property.ShortText({
|
|
74
|
+
displayName: 'Language',
|
|
75
|
+
description:
|
|
76
|
+
'Language code for transcription and speech (e.g. "en", "es", "fr"). Defaults to "babel-en" (English with accent tolerance).',
|
|
77
|
+
required: false,
|
|
78
|
+
}),
|
|
79
|
+
maxDuration: Property.Number({
|
|
80
|
+
displayName: 'Max Duration (minutes)',
|
|
81
|
+
description: 'Maximum call length in minutes. The call ends automatically after this time. Defaults to 30.',
|
|
82
|
+
required: false,
|
|
83
|
+
defaultValue: 30,
|
|
84
|
+
}),
|
|
85
|
+
waitForGreeting: Property.Checkbox({
|
|
86
|
+
displayName: 'Wait for Greeting',
|
|
87
|
+
description:
|
|
88
|
+
'When enabled, the AI waits for the recipient to speak first before responding. Useful when calling into IVR systems.',
|
|
89
|
+
required: false,
|
|
90
|
+
defaultValue: false,
|
|
91
|
+
}),
|
|
92
|
+
record: Property.Checkbox({
|
|
93
|
+
displayName: 'Record Call',
|
|
94
|
+
description: 'When enabled, the call is recorded. The recording URL is included in the post-call data.',
|
|
95
|
+
required: false,
|
|
96
|
+
defaultValue: false,
|
|
97
|
+
}),
|
|
98
|
+
transferPhoneNumber: Property.ShortText({
|
|
99
|
+
displayName: 'Transfer Phone Number',
|
|
100
|
+
description:
|
|
101
|
+
'E.164 phone number to transfer the call to if the AI decides a human is needed (e.g. +12223334444).',
|
|
102
|
+
required: false,
|
|
103
|
+
}),
|
|
104
|
+
webhook: Property.ShortText({
|
|
105
|
+
displayName: 'Webhook URL',
|
|
106
|
+
description:
|
|
107
|
+
'URL that receives a POST request with full call data (transcript, summary, recording URL) after the call ends.',
|
|
108
|
+
required: false,
|
|
109
|
+
}),
|
|
110
|
+
summaryPrompt: Property.LongText({
|
|
111
|
+
displayName: 'Summary Prompt',
|
|
112
|
+
description:
|
|
113
|
+
'Custom instructions for how the post-call summary should be written (max 2000 characters). Leave blank to use the default summary format.',
|
|
114
|
+
required: false,
|
|
115
|
+
}),
|
|
116
|
+
},
|
|
117
|
+
async run(context) {
|
|
118
|
+
const {
|
|
119
|
+
phoneNumber,
|
|
120
|
+
task,
|
|
121
|
+
pathwayId,
|
|
122
|
+
firstSentence,
|
|
123
|
+
voice,
|
|
124
|
+
model,
|
|
125
|
+
language,
|
|
126
|
+
maxDuration,
|
|
127
|
+
waitForGreeting,
|
|
128
|
+
record,
|
|
129
|
+
transferPhoneNumber,
|
|
130
|
+
webhook,
|
|
131
|
+
summaryPrompt,
|
|
132
|
+
} = context.propsValue;
|
|
133
|
+
|
|
134
|
+
const body: Record<string, unknown> = {
|
|
135
|
+
phone_number: phoneNumber,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
if (task) body['task'] = task;
|
|
139
|
+
if (pathwayId) body['pathway_id'] = pathwayId;
|
|
140
|
+
if (firstSentence) body['first_sentence'] = firstSentence;
|
|
141
|
+
if (voice) body['voice'] = voice;
|
|
142
|
+
if (model) body['model'] = model;
|
|
143
|
+
if (language) body['language'] = language;
|
|
144
|
+
if (maxDuration !== undefined && maxDuration !== null) body['max_duration'] = maxDuration;
|
|
145
|
+
if (waitForGreeting !== undefined) body['wait_for_greeting'] = waitForGreeting;
|
|
146
|
+
if (record !== undefined) body['record'] = record;
|
|
147
|
+
if (transferPhoneNumber) body['transfer_phone_number'] = transferPhoneNumber;
|
|
148
|
+
if (webhook) body['webhook'] = webhook;
|
|
149
|
+
if (summaryPrompt) body['summary_prompt'] = summaryPrompt;
|
|
150
|
+
|
|
151
|
+
return blandApiCall({
|
|
152
|
+
apiKey: context.auth.secret_text,
|
|
153
|
+
method: HttpMethod.POST,
|
|
154
|
+
path: '/calls',
|
|
155
|
+
body,
|
|
156
|
+
});
|
|
157
|
+
},
|
|
158
|
+
});
|
package/src/lib/auth.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { PieceAuth } from '@agnocon/pieces-framework';
|
|
2
|
+
import { HttpMethod, httpClient } from '@agnocon/pieces-common';
|
|
3
|
+
|
|
4
|
+
export const BLAND_AI_BASE_URL = 'https://api.bland.ai/v1';
|
|
5
|
+
|
|
6
|
+
export const blandAiAuth = PieceAuth.SecretText({
|
|
7
|
+
displayName: 'API Key',
|
|
8
|
+
description: `To get your API key:
|
|
9
|
+
1. Log in to your [Bland AI dashboard](https://app.bland.ai)
|
|
10
|
+
2. Go to **Profile** (bottom-left menu) -> **Settings**
|
|
11
|
+
3. Click **API Keys** and copy your key`,
|
|
12
|
+
required: true,
|
|
13
|
+
validate: async ({ auth }) => {
|
|
14
|
+
try {
|
|
15
|
+
const response = await httpClient.sendRequest({
|
|
16
|
+
method: HttpMethod.GET,
|
|
17
|
+
url: `${BLAND_AI_BASE_URL}/calls`,
|
|
18
|
+
headers: {
|
|
19
|
+
authorization: auth,
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
},
|
|
22
|
+
queryParams: {
|
|
23
|
+
limit: '1',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
if (response.status === 200) {
|
|
27
|
+
return { valid: true };
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
valid: false,
|
|
31
|
+
error: `Unexpected status: ${response.status}`,
|
|
32
|
+
};
|
|
33
|
+
} catch (e: unknown) {
|
|
34
|
+
const err = e as { response?: { status?: number } };
|
|
35
|
+
if (err.response?.status === 401 || err.response?.status === 403) {
|
|
36
|
+
return {
|
|
37
|
+
valid: false,
|
|
38
|
+
error: 'Invalid API key. Please check your Bland AI account settings.',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
valid: false,
|
|
43
|
+
error: `Connection failed: ${String(e).slice(0, 100)}`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { HttpMethod, httpClient } from '@agnocon/pieces-common';
|
|
2
|
+
import { BLAND_AI_BASE_URL } from '../auth';
|
|
3
|
+
|
|
4
|
+
export async function blandApiCall<T>(params: {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
method: HttpMethod;
|
|
7
|
+
path: string;
|
|
8
|
+
body?: unknown;
|
|
9
|
+
query?: Record<string, string>;
|
|
10
|
+
}): Promise<T> {
|
|
11
|
+
const response = await httpClient.sendRequest<T>({
|
|
12
|
+
method: params.method,
|
|
13
|
+
url: `${BLAND_AI_BASE_URL}${params.path}`,
|
|
14
|
+
headers: {
|
|
15
|
+
authorization: params.apiKey,
|
|
16
|
+
'Content-Type': 'application/json',
|
|
17
|
+
},
|
|
18
|
+
body: params.body,
|
|
19
|
+
queryParams: params.query,
|
|
20
|
+
});
|
|
21
|
+
return response.body;
|
|
22
|
+
}
|