@thisispamela/sdk 1.0.3 → 1.1.0
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 +2 -0
- package/dist/chunk-IKGLZFM6.mjs +38 -0
- package/dist/chunk-IKGLZFM6.mjs.map +1 -0
- 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 +109 -0
- package/dist/index.d.ts +19 -67
- package/dist/index.js +315 -193
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +170 -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 +9 -0
- package/dist/webhooks.mjs.map +1 -0
- package/package.json +28 -4
- package/src/index.ts +17 -82
- package/src/types.ts +126 -0
- package/src/webhooks.ts +55 -0
- package/tsup.config.ts +10 -0
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,68 +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
|
-
voice?: 'male' | 'female' | 'auto';
|
|
28
|
-
agent_name?: string;
|
|
29
|
-
caller_name?: string;
|
|
30
|
-
end_user_id?: string;
|
|
31
|
-
metadata?: Record<string, any>;
|
|
32
|
-
tools?: Array<Record<string, any>>;
|
|
33
|
-
webhooks?: {
|
|
34
|
-
webhook_url?: string;
|
|
35
|
-
tool_webhook_url?: string;
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface CallResponse {
|
|
40
|
-
id: string;
|
|
41
|
-
status: string;
|
|
42
|
-
call_session_id: string;
|
|
43
|
-
created_at: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface CallStatus {
|
|
47
|
-
id: string;
|
|
48
|
-
status: string;
|
|
49
|
-
to: string;
|
|
50
|
-
from_: string; // Backend uses from_ (Python keyword)
|
|
51
|
-
country: string;
|
|
52
|
-
created_at: string;
|
|
53
|
-
started_at?: string;
|
|
54
|
-
completed_at?: string;
|
|
55
|
-
duration_seconds?: number;
|
|
56
|
-
transcript?: Array<Record<string, any>>;
|
|
57
|
-
summary?: string;
|
|
58
|
-
metadata: Record<string, any>;
|
|
59
|
-
end_user_id?: string; // Marketplace end-user ID for privacy isolation
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface ToolDefinition {
|
|
63
|
-
name: string;
|
|
64
|
-
description: string;
|
|
65
|
-
input_schema: Record<string, any>;
|
|
66
|
-
output_schema?: Record<string, any>;
|
|
67
|
-
timeout_ms?: number;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export interface WebhookPayload {
|
|
71
|
-
event: string;
|
|
72
|
-
call_id: string;
|
|
73
|
-
call_session_id: string;
|
|
74
|
-
timestamp: string;
|
|
75
|
-
data: Record<string, any>;
|
|
76
|
-
}
|
|
14
|
+
import type {
|
|
15
|
+
PamelaClientConfig,
|
|
16
|
+
CreateCallRequest,
|
|
17
|
+
CallResponse,
|
|
18
|
+
CallStatus,
|
|
19
|
+
ToolDefinition,
|
|
20
|
+
} from './types';
|
|
77
21
|
|
|
78
22
|
const mapAxiosError = (error: AxiosError, endpoint?: string): PamelaError => {
|
|
79
23
|
const statusCode = error.response?.status;
|
|
@@ -225,6 +169,14 @@ export class PamelaClient {
|
|
|
225
169
|
return response.data;
|
|
226
170
|
}
|
|
227
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Force hangup an in-progress call.
|
|
174
|
+
*/
|
|
175
|
+
async hangupCall(callId: string): Promise<{ success: boolean; call_id: string; status: string }> {
|
|
176
|
+
const response = await this.client.post(`/calls/${callId}/hangup`);
|
|
177
|
+
return response.data;
|
|
178
|
+
}
|
|
179
|
+
|
|
228
180
|
/**
|
|
229
181
|
* Register a tool.
|
|
230
182
|
*/
|
|
@@ -249,25 +201,6 @@ export class PamelaClient {
|
|
|
249
201
|
return response.data;
|
|
250
202
|
}
|
|
251
203
|
|
|
252
|
-
/**
|
|
253
|
-
* Verify webhook signature.
|
|
254
|
-
*/
|
|
255
|
-
static verifyWebhookSignature(
|
|
256
|
-
payload: string | object,
|
|
257
|
-
signature: string,
|
|
258
|
-
secret: string
|
|
259
|
-
): boolean {
|
|
260
|
-
const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload);
|
|
261
|
-
const expectedSignature = crypto
|
|
262
|
-
.createHmac('sha256', secret)
|
|
263
|
-
.update(payloadString)
|
|
264
|
-
.digest('hex');
|
|
265
|
-
|
|
266
|
-
return crypto.timingSafeEqual(
|
|
267
|
-
Buffer.from(signature),
|
|
268
|
-
Buffer.from(expectedSignature)
|
|
269
|
-
);
|
|
270
|
-
}
|
|
271
204
|
}
|
|
272
205
|
|
|
273
206
|
// Export as both default and named export for flexibility
|
|
@@ -281,4 +214,6 @@ export {
|
|
|
281
214
|
ValidationError,
|
|
282
215
|
CallError,
|
|
283
216
|
};
|
|
217
|
+
export * from './types';
|
|
218
|
+
export * from './webhooks';
|
|
284
219
|
|
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