@thisispamela/sdk 1.0.4 → 1.1.1
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/README.md +25 -1
- package/dist/chunk-NQIPPPEL.mjs +50 -0
- package/dist/chunk-NQIPPPEL.mjs.map +1 -0
- package/dist/chunk-WMXO6YYV.mjs +50 -0
- package/dist/chunk-WMXO6YYV.mjs.map +1 -0
- package/dist/errors.d.mts +47 -0
- package/dist/errors.d.ts +8 -6
- package/dist/errors.js +78 -47
- package/dist/errors.js.map +1 -0
- package/dist/errors.mjs +17 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/index.d.mts +108 -0
- package/dist/index.d.ts +10 -69
- package/dist/index.js +278 -200
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +164 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types.d.mts +99 -0
- package/dist/types.d.ts +99 -0
- package/dist/types.js +74 -0
- package/dist/types.js.map +1 -0
- package/dist/types.mjs +7 -0
- package/dist/types.mjs.map +1 -0
- package/dist/webhooks.d.mts +12 -0
- package/dist/webhooks.d.ts +12 -0
- package/dist/webhooks.js +73 -0
- package/dist/webhooks.js.map +1 -0
- package/dist/webhooks.mjs +37 -0
- package/dist/webhooks.mjs.map +1 -0
- package/package.json +28 -4
- package/src/index.ts +10 -84
- package/src/types.ts +126 -0
- package/src/webhooks.ts +55 -0
- package/tsup.config.ts +10 -0
package/package.json
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thisispamela/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Pamela Enterprise Voice API SDK for JavaScript/TypeScript",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./webhooks": {
|
|
15
|
+
"types": "./dist/webhooks.d.ts",
|
|
16
|
+
"import": "./dist/webhooks.mjs",
|
|
17
|
+
"require": "./dist/webhooks.js"
|
|
18
|
+
},
|
|
19
|
+
"./types": {
|
|
20
|
+
"types": "./dist/types.d.ts",
|
|
21
|
+
"import": "./dist/types.mjs",
|
|
22
|
+
"require": "./dist/types.js"
|
|
23
|
+
},
|
|
24
|
+
"./errors": {
|
|
25
|
+
"types": "./dist/errors.d.ts",
|
|
26
|
+
"import": "./dist/errors.mjs",
|
|
27
|
+
"require": "./dist/errors.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
7
30
|
"scripts": {
|
|
8
|
-
"build": "
|
|
31
|
+
"build": "tsup",
|
|
9
32
|
"test": "jest",
|
|
10
33
|
"test:watch": "jest --watch",
|
|
11
34
|
"prepublishOnly": "npm run build"
|
|
@@ -26,8 +49,9 @@
|
|
|
26
49
|
"devDependencies": {
|
|
27
50
|
"@types/node": "^20.0.0",
|
|
28
51
|
"@types/jest": "^29.5.0",
|
|
29
|
-
"typescript": "^5.0.0",
|
|
30
52
|
"jest": "^29.7.0",
|
|
31
|
-
"ts-jest": "^29.1.0"
|
|
53
|
+
"ts-jest": "^29.1.0",
|
|
54
|
+
"tsup": "^8.0.0",
|
|
55
|
+
"typescript": "^5.0.0"
|
|
32
56
|
}
|
|
33
57
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import axios, { AxiosInstance, AxiosError } from 'axios';
|
|
6
|
-
import * as crypto from 'crypto';
|
|
7
6
|
import {
|
|
8
7
|
PamelaError,
|
|
9
8
|
AuthenticationError,
|
|
@@ -12,70 +11,13 @@ import {
|
|
|
12
11
|
ValidationError,
|
|
13
12
|
CallError,
|
|
14
13
|
} from './errors';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
to: string;
|
|
23
|
-
country?: string;
|
|
24
|
-
locale?: string;
|
|
25
|
-
task: string;
|
|
26
|
-
instructions?: string;
|
|
27
|
-
max_duration_seconds?: number;
|
|
28
|
-
voice?: 'male' | 'female' | 'auto';
|
|
29
|
-
agent_name?: string;
|
|
30
|
-
caller_name?: string;
|
|
31
|
-
end_user_id?: string;
|
|
32
|
-
metadata?: Record<string, any>;
|
|
33
|
-
tools?: Array<Record<string, any>>;
|
|
34
|
-
webhooks?: {
|
|
35
|
-
webhook_url?: string;
|
|
36
|
-
tool_webhook_url?: string;
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface CallResponse {
|
|
41
|
-
id: string;
|
|
42
|
-
status: string;
|
|
43
|
-
call_session_id: string;
|
|
44
|
-
created_at: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface CallStatus {
|
|
48
|
-
id: string;
|
|
49
|
-
status: string;
|
|
50
|
-
to: string;
|
|
51
|
-
from_: string; // Backend uses from_ (Python keyword)
|
|
52
|
-
country: string;
|
|
53
|
-
created_at: string;
|
|
54
|
-
started_at?: string;
|
|
55
|
-
completed_at?: string;
|
|
56
|
-
duration_seconds?: number;
|
|
57
|
-
max_duration_seconds?: number;
|
|
58
|
-
transcript?: Array<Record<string, any>>;
|
|
59
|
-
summary?: string;
|
|
60
|
-
metadata: Record<string, any>;
|
|
61
|
-
end_user_id?: string; // Marketplace end-user ID for privacy isolation
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export interface ToolDefinition {
|
|
65
|
-
name: string;
|
|
66
|
-
description: string;
|
|
67
|
-
input_schema: Record<string, any>;
|
|
68
|
-
output_schema?: Record<string, any>;
|
|
69
|
-
timeout_ms?: number;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export interface WebhookPayload {
|
|
73
|
-
event: string;
|
|
74
|
-
call_id: string;
|
|
75
|
-
call_session_id: string;
|
|
76
|
-
timestamp: string;
|
|
77
|
-
data: Record<string, any>;
|
|
78
|
-
}
|
|
14
|
+
import type {
|
|
15
|
+
PamelaClientConfig,
|
|
16
|
+
CreateCallRequest,
|
|
17
|
+
CallResponse,
|
|
18
|
+
CallStatus,
|
|
19
|
+
ToolDefinition,
|
|
20
|
+
} from './types';
|
|
79
21
|
|
|
80
22
|
const mapAxiosError = (error: AxiosError, endpoint?: string): PamelaError => {
|
|
81
23
|
const statusCode = error.response?.status;
|
|
@@ -259,25 +201,6 @@ export class PamelaClient {
|
|
|
259
201
|
return response.data;
|
|
260
202
|
}
|
|
261
203
|
|
|
262
|
-
/**
|
|
263
|
-
* Verify webhook signature.
|
|
264
|
-
*/
|
|
265
|
-
static verifyWebhookSignature(
|
|
266
|
-
payload: string | object,
|
|
267
|
-
signature: string,
|
|
268
|
-
secret: string
|
|
269
|
-
): boolean {
|
|
270
|
-
const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload);
|
|
271
|
-
const expectedSignature = crypto
|
|
272
|
-
.createHmac('sha256', secret)
|
|
273
|
-
.update(payloadString)
|
|
274
|
-
.digest('hex');
|
|
275
|
-
|
|
276
|
-
return crypto.timingSafeEqual(
|
|
277
|
-
Buffer.from(signature),
|
|
278
|
-
Buffer.from(expectedSignature)
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
204
|
}
|
|
282
205
|
|
|
283
206
|
// Export as both default and named export for flexibility
|
|
@@ -291,4 +214,7 @@ export {
|
|
|
291
214
|
ValidationError,
|
|
292
215
|
CallError,
|
|
293
216
|
};
|
|
217
|
+
export * from './types';
|
|
218
|
+
// Webhooks are available via @thisispamela/sdk/webhooks subpath
|
|
219
|
+
// (not exported here to keep main bundle browser-compatible)
|
|
294
220
|
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
export interface PamelaClientConfig {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface CreateCallRequest {
|
|
7
|
+
to: string;
|
|
8
|
+
country?: string;
|
|
9
|
+
locale?: string;
|
|
10
|
+
task: string;
|
|
11
|
+
instructions?: string;
|
|
12
|
+
max_duration_seconds?: number;
|
|
13
|
+
voice?: 'male' | 'female' | 'auto';
|
|
14
|
+
agent_name?: string;
|
|
15
|
+
caller_name?: string;
|
|
16
|
+
end_user_id?: string;
|
|
17
|
+
metadata?: Record<string, any>;
|
|
18
|
+
tools?: Array<Record<string, any>>;
|
|
19
|
+
webhooks?: {
|
|
20
|
+
webhook_url?: string;
|
|
21
|
+
tool_webhook_url?: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type CallStatusValue =
|
|
26
|
+
| 'initiating'
|
|
27
|
+
| 'queued'
|
|
28
|
+
| 'ringing'
|
|
29
|
+
| 'in_progress'
|
|
30
|
+
| 'completed'
|
|
31
|
+
| 'failed'
|
|
32
|
+
| 'cancelled'
|
|
33
|
+
| 'timeout_terminated'
|
|
34
|
+
| 'in-progress';
|
|
35
|
+
|
|
36
|
+
export interface CallResponse {
|
|
37
|
+
id: string;
|
|
38
|
+
status: CallStatusValue | string;
|
|
39
|
+
call_session_id: string;
|
|
40
|
+
created_at: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface CallStatus {
|
|
44
|
+
id: string;
|
|
45
|
+
status: CallStatusValue | string;
|
|
46
|
+
to: string;
|
|
47
|
+
from_: string; // Backend uses from_ (Python keyword)
|
|
48
|
+
country: string;
|
|
49
|
+
created_at: string;
|
|
50
|
+
started_at?: string;
|
|
51
|
+
completed_at?: string;
|
|
52
|
+
duration_seconds?: number;
|
|
53
|
+
max_duration_seconds?: number;
|
|
54
|
+
transcript?: Array<Record<string, any>>;
|
|
55
|
+
summary?: string;
|
|
56
|
+
metadata: Record<string, any>;
|
|
57
|
+
end_user_id?: string; // Marketplace end-user ID for privacy isolation
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface ToolDefinition {
|
|
61
|
+
name: string;
|
|
62
|
+
description: string;
|
|
63
|
+
input_schema: Record<string, any>;
|
|
64
|
+
output_schema?: Record<string, any>;
|
|
65
|
+
timeout_ms?: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface WebhookPayload {
|
|
69
|
+
event: string;
|
|
70
|
+
call_id: string;
|
|
71
|
+
call_session_id: string;
|
|
72
|
+
timestamp: string;
|
|
73
|
+
data: Record<string, any>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Standard error codes (aligned with backend models/errors.py) */
|
|
77
|
+
export const ErrorCodes = {
|
|
78
|
+
// Auth errors (1000-1999)
|
|
79
|
+
AUTH_REQUIRED: 1001,
|
|
80
|
+
AUTH_INVALID: 1002,
|
|
81
|
+
AUTH_EXPIRED: 1003,
|
|
82
|
+
AUTH_INSUFFICIENT_PERMISSIONS: 1004,
|
|
83
|
+
AUTH_FORBIDDEN: 1005,
|
|
84
|
+
|
|
85
|
+
// Validation errors (2000-2999)
|
|
86
|
+
VALIDATION_ERROR: 2001,
|
|
87
|
+
INVALID_PHONE: 2002,
|
|
88
|
+
INVALID_EMAIL: 2003,
|
|
89
|
+
INVALID_PASSWORD: 2004,
|
|
90
|
+
MISSING_REQUIRED_FIELD: 2005,
|
|
91
|
+
INVALID_JSON: 2006,
|
|
92
|
+
INVALID_REQUEST_BODY: 2007,
|
|
93
|
+
|
|
94
|
+
// Not found errors (3000-3999)
|
|
95
|
+
NOT_FOUND: 3001,
|
|
96
|
+
USER_NOT_FOUND: 3002,
|
|
97
|
+
CONVERSATION_NOT_FOUND: 3003,
|
|
98
|
+
CALL_SESSION_NOT_FOUND: 3004,
|
|
99
|
+
RESOURCE_NOT_FOUND: 3005,
|
|
100
|
+
MESSAGE_NOT_FOUND: 3006,
|
|
101
|
+
|
|
102
|
+
// Conflict errors (4000-4999)
|
|
103
|
+
RESOURCE_ALREADY_EXISTS: 4001,
|
|
104
|
+
EMAIL_ALREADY_REGISTERED: 4002,
|
|
105
|
+
ACCOUNT_LINKING_REQUIRED: 4003,
|
|
106
|
+
|
|
107
|
+
// Server errors (5000-5999)
|
|
108
|
+
INTERNAL_ERROR: 5001,
|
|
109
|
+
EXTERNAL_SERVICE_ERROR: 5002,
|
|
110
|
+
DATABASE_ERROR: 5003,
|
|
111
|
+
CONFIGURATION_ERROR: 5004,
|
|
112
|
+
|
|
113
|
+
// Rate limiting (6000-6999)
|
|
114
|
+
RATE_LIMIT_EXCEEDED: 6001,
|
|
115
|
+
QUOTA_EXCEEDED: 6002,
|
|
116
|
+
|
|
117
|
+
// B2B errors (7000-7999)
|
|
118
|
+
B2B_PARTNER_NOT_FOUND: 7001,
|
|
119
|
+
B2B_PROJECT_NOT_FOUND: 7002,
|
|
120
|
+
B2B_CALL_NOT_FOUND: 7003,
|
|
121
|
+
B2B_NO_PHONE_NUMBER: 7004,
|
|
122
|
+
B2B_UNSUPPORTED_COUNTRY: 7005,
|
|
123
|
+
B2B_TOOL_EXECUTION_FAILED: 7006,
|
|
124
|
+
B2B_WEBHOOK_DELIVERY_FAILED: 7007,
|
|
125
|
+
SUBSCRIPTION_EXPIRED: 7008,
|
|
126
|
+
} as const;
|
package/src/webhooks.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
|
|
3
|
+
export const verifyWebhookSignature = (
|
|
4
|
+
payload: string | object,
|
|
5
|
+
signature: string | undefined | null,
|
|
6
|
+
secret: string
|
|
7
|
+
): boolean => {
|
|
8
|
+
if (!signature) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (!secret) {
|
|
13
|
+
throw new Error('Webhook secret cannot be empty');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload);
|
|
17
|
+
const expectedSignature = crypto
|
|
18
|
+
.createHmac('sha256', secret)
|
|
19
|
+
.update(payloadString)
|
|
20
|
+
.digest('hex');
|
|
21
|
+
|
|
22
|
+
return crypto.timingSafeEqual(
|
|
23
|
+
Buffer.from(signature),
|
|
24
|
+
Buffer.from(expectedSignature)
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const parseToolWebhook = (payload: Record<string, any>): {
|
|
29
|
+
tool_name: string;
|
|
30
|
+
arguments: Record<string, any>;
|
|
31
|
+
call_id: string;
|
|
32
|
+
correlation_id: string;
|
|
33
|
+
call_session_id?: string;
|
|
34
|
+
partner_id?: string;
|
|
35
|
+
project_id?: string;
|
|
36
|
+
} => {
|
|
37
|
+
const requiredFields = ['tool_name', 'arguments', 'call_id', 'correlation_id'];
|
|
38
|
+
const missing = requiredFields.filter((field) => !(field in payload));
|
|
39
|
+
|
|
40
|
+
if (missing.length > 0) {
|
|
41
|
+
throw new Error(`Missing required fields: ${missing.join(', ')}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
tool_name: String(payload.tool_name),
|
|
46
|
+
arguments: typeof payload.arguments === 'object' && payload.arguments
|
|
47
|
+
? payload.arguments
|
|
48
|
+
: {},
|
|
49
|
+
call_id: String(payload.call_id),
|
|
50
|
+
correlation_id: String(payload.correlation_id),
|
|
51
|
+
call_session_id: payload.call_session_id,
|
|
52
|
+
partner_id: payload.partner_id,
|
|
53
|
+
project_id: payload.project_id,
|
|
54
|
+
};
|
|
55
|
+
};
|
package/tsup.config.ts
ADDED