@thisispamela/sdk 1.1.0 → 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 CHANGED
@@ -40,8 +40,11 @@ console.log('Call status:', status.status);
40
40
 
41
41
  ### Webhook Verification
42
42
 
43
+ **Note:** Webhook functions are only available in Node.js environments (not browsers). Import from the `/webhooks` subpath:
44
+
43
45
  ```typescript
44
46
  import { PamelaClient } from '@thisispamela/sdk';
47
+ import { verifyWebhookSignature, parseToolWebhook } from '@thisispamela/sdk/webhooks';
45
48
  import express from 'express';
46
49
 
47
50
  const app = express();
@@ -51,7 +54,7 @@ app.post('/webhooks/pamela', express.json(), (req, res) => {
51
54
  const signature = req.headers['x-pamela-signature'] as string;
52
55
  const payload = req.body;
53
56
 
54
- if (!PamelaClient.verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
57
+ if (!verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
55
58
  return res.status(401).send('Invalid signature');
56
59
  }
57
60
 
@@ -63,6 +66,10 @@ app.post('/webhooks/pamela', express.json(), (req, res) => {
63
66
  });
64
67
  ```
65
68
 
69
+ **Available webhook functions:**
70
+ - `verifyWebhookSignature(payload, signature, secret)` - Verify webhook signature
71
+ - `parseToolWebhook(payload)` - Parse tool execution webhook payload
72
+
66
73
  ## Getting API Keys
67
74
 
68
75
  ### Obtaining Your API Key
@@ -297,6 +304,23 @@ console.log(`Quota: ${usage.quota?.partner_limit || 'Unlimited'}`);
297
304
 
298
305
  **Note:** Enterprise subscriptions have no quota limits - all usage is billed per-minute.
299
306
 
307
+ ## Browser Compatibility
308
+
309
+ The main SDK package (`@thisispamela/sdk`) is **browser-compatible**. Webhook verification functions (which use Node.js `crypto`) are available via the `/webhooks` subpath:
310
+
311
+ ```typescript
312
+ // Browser - main SDK works
313
+ import { PamelaClient } from '@thisispamela/sdk';
314
+
315
+ // Node.js only - webhook verification
316
+ import { verifyWebhookSignature } from '@thisispamela/sdk/webhooks';
317
+ ```
318
+
319
+ **Subpath exports:**
320
+ - `@thisispamela/sdk/webhooks` - Webhook verification (Node.js only)
321
+ - `@thisispamela/sdk/types` - TypeScript types
322
+ - `@thisispamela/sdk/errors` - Error classes
323
+
300
324
  ## API Reference
301
325
 
302
326
  See the [Pamela Enterprise API Documentation](https://docs.thisispamela.com/enterprise) for full API reference.
package/dist/index.d.mts CHANGED
@@ -2,7 +2,6 @@ import { AxiosInstance } from 'axios';
2
2
  export { AuthenticationError, CallError, PamelaError, RateLimitError, SubscriptionError, ValidationError } from './errors.mjs';
3
3
  import { PamelaClientConfig, CreateCallRequest, CallResponse, CallStatus, ToolDefinition } from './types.mjs';
4
4
  export { CallStatusValue, ErrorCodes, WebhookPayload } from './types.mjs';
5
- export { parseToolWebhook, verifyWebhookSignature } from './webhooks.mjs';
6
5
 
7
6
  /**
8
7
  * Pamela Enterprise Voice API SDK for JavaScript/TypeScript
package/dist/index.d.ts CHANGED
@@ -2,7 +2,6 @@ import { AxiosInstance } from 'axios';
2
2
  export { AuthenticationError, CallError, PamelaError, RateLimitError, SubscriptionError, ValidationError } from './errors.js';
3
3
  import { PamelaClientConfig, CreateCallRequest, CallResponse, CallStatus, ToolDefinition } from './types.js';
4
4
  export { CallStatusValue, ErrorCodes, WebhookPayload } from './types.js';
5
- export { parseToolWebhook, verifyWebhookSignature } from './webhooks.js';
6
5
 
7
6
  /**
8
7
  * Pamela Enterprise Voice API SDK for JavaScript/TypeScript
package/dist/index.js CHANGED
@@ -40,9 +40,7 @@ __export(index_exports, {
40
40
  SubscriptionError: () => SubscriptionError,
41
41
  UsageClient: () => UsageClient,
42
42
  ValidationError: () => ValidationError,
43
- default: () => index_default,
44
- parseToolWebhook: () => parseToolWebhook,
45
- verifyWebhookSignature: () => verifyWebhookSignature
43
+ default: () => index_default
46
44
  });
47
45
  module.exports = __toCommonJS(index_exports);
48
46
  var import_axios = __toESM(require("axios"));
@@ -134,39 +132,6 @@ var ErrorCodes = {
134
132
  SUBSCRIPTION_EXPIRED: 7008
135
133
  };
136
134
 
137
- // src/webhooks.ts
138
- var crypto = __toESM(require("crypto"));
139
- var verifyWebhookSignature = (payload, signature, secret) => {
140
- if (!signature) {
141
- return false;
142
- }
143
- if (!secret) {
144
- throw new Error("Webhook secret cannot be empty");
145
- }
146
- const payloadString = typeof payload === "string" ? payload : JSON.stringify(payload);
147
- const expectedSignature = crypto.createHmac("sha256", secret).update(payloadString).digest("hex");
148
- return crypto.timingSafeEqual(
149
- Buffer.from(signature),
150
- Buffer.from(expectedSignature)
151
- );
152
- };
153
- var parseToolWebhook = (payload) => {
154
- const requiredFields = ["tool_name", "arguments", "call_id", "correlation_id"];
155
- const missing = requiredFields.filter((field) => !(field in payload));
156
- if (missing.length > 0) {
157
- throw new Error(`Missing required fields: ${missing.join(", ")}`);
158
- }
159
- return {
160
- tool_name: String(payload.tool_name),
161
- arguments: typeof payload.arguments === "object" && payload.arguments ? payload.arguments : {},
162
- call_id: String(payload.call_id),
163
- correlation_id: String(payload.correlation_id),
164
- call_session_id: payload.call_session_id,
165
- partner_id: payload.partner_id,
166
- project_id: payload.project_id
167
- };
168
- };
169
-
170
135
  // src/index.ts
171
136
  var mapAxiosError = (error, endpoint) => {
172
137
  const statusCode = error.response?.status;
@@ -315,8 +280,6 @@ var index_default = PamelaClient;
315
280
  RateLimitError,
316
281
  SubscriptionError,
317
282
  UsageClient,
318
- ValidationError,
319
- parseToolWebhook,
320
- verifyWebhookSignature
283
+ ValidationError
321
284
  });
322
285
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/types.ts","../src/webhooks.ts"],"sourcesContent":["/**\n * Pamela Enterprise Voice API SDK for JavaScript/TypeScript\n */\n\nimport axios, { AxiosInstance, AxiosError } from 'axios';\nimport {\n PamelaError,\n AuthenticationError,\n SubscriptionError,\n RateLimitError,\n ValidationError,\n CallError,\n} from './errors';\nimport type {\n PamelaClientConfig,\n CreateCallRequest,\n CallResponse,\n CallStatus,\n ToolDefinition,\n} from './types';\n\nconst mapAxiosError = (error: AxiosError, endpoint?: string): PamelaError => {\n const statusCode = error.response?.status;\n const data = error.response?.data as any;\n let errorCode: number | undefined;\n let message: string | undefined;\n let details: Record<string, any> | undefined;\n\n if (data && typeof data === 'object') {\n const detail = data.detail;\n if (detail && typeof detail === 'object') {\n errorCode = detail.error_code ?? detail.error?.code;\n message = detail.message ?? detail.error?.message;\n details = detail.details ?? detail.error?.details;\n } else {\n errorCode = data.error_code ?? data.error?.code;\n message = data.message ?? data.detail;\n details = data.details ?? data.error?.details;\n }\n }\n\n if (!message) {\n message = error.message || 'Request failed';\n }\n\n const options = { errorCode, details, statusCode };\n if (statusCode === 401) return new AuthenticationError(message, options);\n if (statusCode === 403) return new SubscriptionError(message, options);\n if (statusCode === 429) return new RateLimitError(message, options);\n if (statusCode === 400 || statusCode === 422) return new ValidationError(message, options);\n\n if (endpoint?.startsWith('/calls')) {\n return new CallError(message, options);\n }\n\n return new PamelaError(message, options);\n};\n\nexport class UsageClient {\n private client: AxiosInstance;\n\n constructor(client: AxiosInstance) {\n this.client = client;\n }\n\n /**\n * Get usage statistics for partner/project.\n */\n async get(period?: string): Promise<{\n partner_id: string;\n project_id?: string;\n period: string;\n call_count: number;\n last_updated?: string;\n quota?: {\n partner_limit?: number;\n project_limit?: number;\n };\n }> {\n const params = period ? { period } : {};\n const response = await this.client.get('/usage', { params });\n return response.data;\n }\n}\n\nexport class PamelaClient {\n private client: AxiosInstance;\n private apiKey: string;\n public usage: UsageClient;\n\n constructor(config: PamelaClientConfig) {\n this.apiKey = config.apiKey;\n const baseURL = config.baseUrl || 'https://api.thisispamela.com';\n \n this.client = axios.create({\n baseURL: `${baseURL}/api/b2b/v1`,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n timeout: 30000,\n });\n\n // Initialize usage client\n this.usage = new UsageClient(this.client);\n\n // Add retry logic\n this.client.interceptors.response.use(\n (response) => response,\n async (error: AxiosError) => {\n const config = error.config as any;\n if (!config || !config.retry) {\n config.retry = 0;\n }\n config.retry += 1;\n\n if (config.retry <= 3 && error.response?.status && error.response.status >= 500) {\n await new Promise(resolve => setTimeout(resolve, 1000 * config.retry));\n return this.client.request(config);\n }\n\n return Promise.reject(mapAxiosError(error, config?.url));\n }\n );\n }\n\n /**\n * Create a new call.\n */\n async createCall(request: CreateCallRequest): Promise<CallResponse> {\n const response = await this.client.post<CallResponse>('/calls', request);\n return response.data;\n }\n\n /**\n * Get call status and details.\n */\n async getCall(callId: string): Promise<CallStatus> {\n const response = await this.client.get<CallStatus>(`/calls/${callId}`);\n return response.data;\n }\n\n /**\n * List calls for the authenticated partner/project.\n */\n async listCalls(params?: {\n status?: string;\n status_filter?: string;\n limit?: number;\n offset?: number;\n start_date?: string;\n end_date?: string;\n }): Promise<{ items: CallStatus[]; total: number; limit: number; offset: number }> {\n const normalizedParams = { ...params };\n if (params?.status_filter || params?.status) {\n normalizedParams.status_filter = params?.status_filter ?? params?.status;\n delete (normalizedParams as { status?: string }).status;\n }\n const response = await this.client.get('/calls', { params: normalizedParams });\n // Backend returns { items: [...], total, limit, offset }\n return response.data;\n }\n\n /**\n * Cancel an in-progress call.\n */\n async cancelCall(callId: string): Promise<{ success: boolean; call_id: string; status: string }> {\n const response = await this.client.post(`/calls/${callId}/cancel`);\n return response.data;\n }\n\n /**\n * Force hangup an in-progress call.\n */\n async hangupCall(callId: string): Promise<{ success: boolean; call_id: string; status: string }> {\n const response = await this.client.post(`/calls/${callId}/hangup`);\n return response.data;\n }\n\n /**\n * Register a tool.\n */\n async registerTool(tool: ToolDefinition): Promise<{ id: string; project_id: string; name: string; description: string; input_schema: Record<string, any>; output_schema: Record<string, any>; timeout_ms: number; created_at: string }> {\n const response = await this.client.post('/tools', { tool });\n return response.data;\n }\n\n /**\n * List all tools for the project.\n */\n async listTools(): Promise<Array<{ id: string; project_id: string; name: string; description: string; input_schema: Record<string, any>; output_schema: Record<string, any>; timeout_ms: number; created_at: string }>> {\n const response = await this.client.get('/tools');\n return response.data;\n }\n\n /**\n * Delete a tool.\n */\n async deleteTool(toolId: string): Promise<{ success: boolean; tool_id: string }> {\n const response = await this.client.delete(`/tools/${toolId}`);\n return response.data;\n }\n\n}\n\n// Export as both default and named export for flexibility\nexport default PamelaClient;\nexport { PamelaClient as Pamela };\nexport {\n PamelaError,\n AuthenticationError,\n SubscriptionError,\n RateLimitError,\n ValidationError,\n CallError,\n};\nexport * from './types';\nexport * from './webhooks';\n\n","export class PamelaError extends Error {\n public errorCode?: number;\n public details?: Record<string, any>;\n public statusCode?: number;\n\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message);\n this.name = 'PamelaError';\n this.errorCode = options?.errorCode;\n this.details = options?.details;\n this.statusCode = options?.statusCode;\n }\n}\n\nexport class AuthenticationError extends PamelaError {\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message, options);\n this.name = 'AuthenticationError';\n }\n}\n\nexport class SubscriptionError extends PamelaError {\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message, options);\n this.name = 'SubscriptionError';\n }\n}\n\nexport class RateLimitError extends PamelaError {\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message, options);\n this.name = 'RateLimitError';\n }\n}\n\nexport class ValidationError extends PamelaError {\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message, options);\n this.name = 'ValidationError';\n }\n}\n\nexport class CallError extends PamelaError {\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message, options);\n this.name = 'CallError';\n }\n}\n","export interface PamelaClientConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport interface CreateCallRequest {\n to: string;\n country?: string;\n locale?: string;\n task: string;\n instructions?: string;\n max_duration_seconds?: number;\n voice?: 'male' | 'female' | 'auto';\n agent_name?: string;\n caller_name?: string;\n end_user_id?: string;\n metadata?: Record<string, any>;\n tools?: Array<Record<string, any>>;\n webhooks?: {\n webhook_url?: string;\n tool_webhook_url?: string;\n };\n}\n\nexport type CallStatusValue =\n | 'initiating'\n | 'queued'\n | 'ringing'\n | 'in_progress'\n | 'completed'\n | 'failed'\n | 'cancelled'\n | 'timeout_terminated'\n | 'in-progress';\n\nexport interface CallResponse {\n id: string;\n status: CallStatusValue | string;\n call_session_id: string;\n created_at: string;\n}\n\nexport interface CallStatus {\n id: string;\n status: CallStatusValue | string;\n to: string;\n from_: string; // Backend uses from_ (Python keyword)\n country: string;\n created_at: string;\n started_at?: string;\n completed_at?: string;\n duration_seconds?: number;\n max_duration_seconds?: number;\n transcript?: Array<Record<string, any>>;\n summary?: string;\n metadata: Record<string, any>;\n end_user_id?: string; // Marketplace end-user ID for privacy isolation\n}\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n input_schema: Record<string, any>;\n output_schema?: Record<string, any>;\n timeout_ms?: number;\n}\n\nexport interface WebhookPayload {\n event: string;\n call_id: string;\n call_session_id: string;\n timestamp: string;\n data: Record<string, any>;\n}\n\n/** Standard error codes (aligned with backend models/errors.py) */\nexport const ErrorCodes = {\n // Auth errors (1000-1999)\n AUTH_REQUIRED: 1001,\n AUTH_INVALID: 1002,\n AUTH_EXPIRED: 1003,\n AUTH_INSUFFICIENT_PERMISSIONS: 1004,\n AUTH_FORBIDDEN: 1005,\n\n // Validation errors (2000-2999)\n VALIDATION_ERROR: 2001,\n INVALID_PHONE: 2002,\n INVALID_EMAIL: 2003,\n INVALID_PASSWORD: 2004,\n MISSING_REQUIRED_FIELD: 2005,\n INVALID_JSON: 2006,\n INVALID_REQUEST_BODY: 2007,\n\n // Not found errors (3000-3999)\n NOT_FOUND: 3001,\n USER_NOT_FOUND: 3002,\n CONVERSATION_NOT_FOUND: 3003,\n CALL_SESSION_NOT_FOUND: 3004,\n RESOURCE_NOT_FOUND: 3005,\n MESSAGE_NOT_FOUND: 3006,\n\n // Conflict errors (4000-4999)\n RESOURCE_ALREADY_EXISTS: 4001,\n EMAIL_ALREADY_REGISTERED: 4002,\n ACCOUNT_LINKING_REQUIRED: 4003,\n\n // Server errors (5000-5999)\n INTERNAL_ERROR: 5001,\n EXTERNAL_SERVICE_ERROR: 5002,\n DATABASE_ERROR: 5003,\n CONFIGURATION_ERROR: 5004,\n\n // Rate limiting (6000-6999)\n RATE_LIMIT_EXCEEDED: 6001,\n QUOTA_EXCEEDED: 6002,\n\n // B2B errors (7000-7999)\n B2B_PARTNER_NOT_FOUND: 7001,\n B2B_PROJECT_NOT_FOUND: 7002,\n B2B_CALL_NOT_FOUND: 7003,\n B2B_NO_PHONE_NUMBER: 7004,\n B2B_UNSUPPORTED_COUNTRY: 7005,\n B2B_TOOL_EXECUTION_FAILED: 7006,\n B2B_WEBHOOK_DELIVERY_FAILED: 7007,\n SUBSCRIPTION_EXPIRED: 7008,\n} as const;\n","import * as crypto from 'crypto';\n\nexport const verifyWebhookSignature = (\n payload: string | object,\n signature: string | undefined | null,\n secret: string\n): boolean => {\n if (!signature) {\n return false;\n }\n\n if (!secret) {\n throw new Error('Webhook secret cannot be empty');\n }\n\n const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload);\n const expectedSignature = crypto\n .createHmac('sha256', secret)\n .update(payloadString)\n .digest('hex');\n\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSignature)\n );\n};\n\nexport const parseToolWebhook = (payload: Record<string, any>): {\n tool_name: string;\n arguments: Record<string, any>;\n call_id: string;\n correlation_id: string;\n call_session_id?: string;\n partner_id?: string;\n project_id?: string;\n} => {\n const requiredFields = ['tool_name', 'arguments', 'call_id', 'correlation_id'];\n const missing = requiredFields.filter((field) => !(field in payload));\n\n if (missing.length > 0) {\n throw new Error(`Missing required fields: ${missing.join(', ')}`);\n }\n\n return {\n tool_name: String(payload.tool_name),\n arguments: typeof payload.arguments === 'object' && payload.arguments\n ? payload.arguments\n : {},\n call_id: String(payload.call_id),\n correlation_id: String(payload.correlation_id),\n call_session_id: payload.call_session_id,\n partner_id: payload.partner_id,\n project_id: payload.project_id,\n };\n};\n"],"mappings":"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","names":["axios","config"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/types.ts"],"sourcesContent":["/**\n * Pamela Enterprise Voice API SDK for JavaScript/TypeScript\n */\n\nimport axios, { AxiosInstance, AxiosError } from 'axios';\nimport {\n PamelaError,\n AuthenticationError,\n SubscriptionError,\n RateLimitError,\n ValidationError,\n CallError,\n} from './errors';\nimport type {\n PamelaClientConfig,\n CreateCallRequest,\n CallResponse,\n CallStatus,\n ToolDefinition,\n} from './types';\n\nconst mapAxiosError = (error: AxiosError, endpoint?: string): PamelaError => {\n const statusCode = error.response?.status;\n const data = error.response?.data as any;\n let errorCode: number | undefined;\n let message: string | undefined;\n let details: Record<string, any> | undefined;\n\n if (data && typeof data === 'object') {\n const detail = data.detail;\n if (detail && typeof detail === 'object') {\n errorCode = detail.error_code ?? detail.error?.code;\n message = detail.message ?? detail.error?.message;\n details = detail.details ?? detail.error?.details;\n } else {\n errorCode = data.error_code ?? data.error?.code;\n message = data.message ?? data.detail;\n details = data.details ?? data.error?.details;\n }\n }\n\n if (!message) {\n message = error.message || 'Request failed';\n }\n\n const options = { errorCode, details, statusCode };\n if (statusCode === 401) return new AuthenticationError(message, options);\n if (statusCode === 403) return new SubscriptionError(message, options);\n if (statusCode === 429) return new RateLimitError(message, options);\n if (statusCode === 400 || statusCode === 422) return new ValidationError(message, options);\n\n if (endpoint?.startsWith('/calls')) {\n return new CallError(message, options);\n }\n\n return new PamelaError(message, options);\n};\n\nexport class UsageClient {\n private client: AxiosInstance;\n\n constructor(client: AxiosInstance) {\n this.client = client;\n }\n\n /**\n * Get usage statistics for partner/project.\n */\n async get(period?: string): Promise<{\n partner_id: string;\n project_id?: string;\n period: string;\n call_count: number;\n last_updated?: string;\n quota?: {\n partner_limit?: number;\n project_limit?: number;\n };\n }> {\n const params = period ? { period } : {};\n const response = await this.client.get('/usage', { params });\n return response.data;\n }\n}\n\nexport class PamelaClient {\n private client: AxiosInstance;\n private apiKey: string;\n public usage: UsageClient;\n\n constructor(config: PamelaClientConfig) {\n this.apiKey = config.apiKey;\n const baseURL = config.baseUrl || 'https://api.thisispamela.com';\n \n this.client = axios.create({\n baseURL: `${baseURL}/api/b2b/v1`,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n timeout: 30000,\n });\n\n // Initialize usage client\n this.usage = new UsageClient(this.client);\n\n // Add retry logic\n this.client.interceptors.response.use(\n (response) => response,\n async (error: AxiosError) => {\n const config = error.config as any;\n if (!config || !config.retry) {\n config.retry = 0;\n }\n config.retry += 1;\n\n if (config.retry <= 3 && error.response?.status && error.response.status >= 500) {\n await new Promise(resolve => setTimeout(resolve, 1000 * config.retry));\n return this.client.request(config);\n }\n\n return Promise.reject(mapAxiosError(error, config?.url));\n }\n );\n }\n\n /**\n * Create a new call.\n */\n async createCall(request: CreateCallRequest): Promise<CallResponse> {\n const response = await this.client.post<CallResponse>('/calls', request);\n return response.data;\n }\n\n /**\n * Get call status and details.\n */\n async getCall(callId: string): Promise<CallStatus> {\n const response = await this.client.get<CallStatus>(`/calls/${callId}`);\n return response.data;\n }\n\n /**\n * List calls for the authenticated partner/project.\n */\n async listCalls(params?: {\n status?: string;\n status_filter?: string;\n limit?: number;\n offset?: number;\n start_date?: string;\n end_date?: string;\n }): Promise<{ items: CallStatus[]; total: number; limit: number; offset: number }> {\n const normalizedParams = { ...params };\n if (params?.status_filter || params?.status) {\n normalizedParams.status_filter = params?.status_filter ?? params?.status;\n delete (normalizedParams as { status?: string }).status;\n }\n const response = await this.client.get('/calls', { params: normalizedParams });\n // Backend returns { items: [...], total, limit, offset }\n return response.data;\n }\n\n /**\n * Cancel an in-progress call.\n */\n async cancelCall(callId: string): Promise<{ success: boolean; call_id: string; status: string }> {\n const response = await this.client.post(`/calls/${callId}/cancel`);\n return response.data;\n }\n\n /**\n * Force hangup an in-progress call.\n */\n async hangupCall(callId: string): Promise<{ success: boolean; call_id: string; status: string }> {\n const response = await this.client.post(`/calls/${callId}/hangup`);\n return response.data;\n }\n\n /**\n * Register a tool.\n */\n async registerTool(tool: ToolDefinition): Promise<{ id: string; project_id: string; name: string; description: string; input_schema: Record<string, any>; output_schema: Record<string, any>; timeout_ms: number; created_at: string }> {\n const response = await this.client.post('/tools', { tool });\n return response.data;\n }\n\n /**\n * List all tools for the project.\n */\n async listTools(): Promise<Array<{ id: string; project_id: string; name: string; description: string; input_schema: Record<string, any>; output_schema: Record<string, any>; timeout_ms: number; created_at: string }>> {\n const response = await this.client.get('/tools');\n return response.data;\n }\n\n /**\n * Delete a tool.\n */\n async deleteTool(toolId: string): Promise<{ success: boolean; tool_id: string }> {\n const response = await this.client.delete(`/tools/${toolId}`);\n return response.data;\n }\n\n}\n\n// Export as both default and named export for flexibility\nexport default PamelaClient;\nexport { PamelaClient as Pamela };\nexport {\n PamelaError,\n AuthenticationError,\n SubscriptionError,\n RateLimitError,\n ValidationError,\n CallError,\n};\nexport * from './types';\n// Webhooks are available via @thisispamela/sdk/webhooks subpath\n// (not exported here to keep main bundle browser-compatible)\n\n","export class PamelaError extends Error {\n public errorCode?: number;\n public details?: Record<string, any>;\n public statusCode?: number;\n\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message);\n this.name = 'PamelaError';\n this.errorCode = options?.errorCode;\n this.details = options?.details;\n this.statusCode = options?.statusCode;\n }\n}\n\nexport class AuthenticationError extends PamelaError {\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message, options);\n this.name = 'AuthenticationError';\n }\n}\n\nexport class SubscriptionError extends PamelaError {\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message, options);\n this.name = 'SubscriptionError';\n }\n}\n\nexport class RateLimitError extends PamelaError {\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message, options);\n this.name = 'RateLimitError';\n }\n}\n\nexport class ValidationError extends PamelaError {\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message, options);\n this.name = 'ValidationError';\n }\n}\n\nexport class CallError extends PamelaError {\n constructor(message: string, options?: { errorCode?: number; details?: Record<string, any>; statusCode?: number }) {\n super(message, options);\n this.name = 'CallError';\n }\n}\n","export interface PamelaClientConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport interface CreateCallRequest {\n to: string;\n country?: string;\n locale?: string;\n task: string;\n instructions?: string;\n max_duration_seconds?: number;\n voice?: 'male' | 'female' | 'auto';\n agent_name?: string;\n caller_name?: string;\n end_user_id?: string;\n metadata?: Record<string, any>;\n tools?: Array<Record<string, any>>;\n webhooks?: {\n webhook_url?: string;\n tool_webhook_url?: string;\n };\n}\n\nexport type CallStatusValue =\n | 'initiating'\n | 'queued'\n | 'ringing'\n | 'in_progress'\n | 'completed'\n | 'failed'\n | 'cancelled'\n | 'timeout_terminated'\n | 'in-progress';\n\nexport interface CallResponse {\n id: string;\n status: CallStatusValue | string;\n call_session_id: string;\n created_at: string;\n}\n\nexport interface CallStatus {\n id: string;\n status: CallStatusValue | string;\n to: string;\n from_: string; // Backend uses from_ (Python keyword)\n country: string;\n created_at: string;\n started_at?: string;\n completed_at?: string;\n duration_seconds?: number;\n max_duration_seconds?: number;\n transcript?: Array<Record<string, any>>;\n summary?: string;\n metadata: Record<string, any>;\n end_user_id?: string; // Marketplace end-user ID for privacy isolation\n}\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n input_schema: Record<string, any>;\n output_schema?: Record<string, any>;\n timeout_ms?: number;\n}\n\nexport interface WebhookPayload {\n event: string;\n call_id: string;\n call_session_id: string;\n timestamp: string;\n data: Record<string, any>;\n}\n\n/** Standard error codes (aligned with backend models/errors.py) */\nexport const ErrorCodes = {\n // Auth errors (1000-1999)\n AUTH_REQUIRED: 1001,\n AUTH_INVALID: 1002,\n AUTH_EXPIRED: 1003,\n AUTH_INSUFFICIENT_PERMISSIONS: 1004,\n AUTH_FORBIDDEN: 1005,\n\n // Validation errors (2000-2999)\n VALIDATION_ERROR: 2001,\n INVALID_PHONE: 2002,\n INVALID_EMAIL: 2003,\n INVALID_PASSWORD: 2004,\n MISSING_REQUIRED_FIELD: 2005,\n INVALID_JSON: 2006,\n INVALID_REQUEST_BODY: 2007,\n\n // Not found errors (3000-3999)\n NOT_FOUND: 3001,\n USER_NOT_FOUND: 3002,\n CONVERSATION_NOT_FOUND: 3003,\n CALL_SESSION_NOT_FOUND: 3004,\n RESOURCE_NOT_FOUND: 3005,\n MESSAGE_NOT_FOUND: 3006,\n\n // Conflict errors (4000-4999)\n RESOURCE_ALREADY_EXISTS: 4001,\n EMAIL_ALREADY_REGISTERED: 4002,\n ACCOUNT_LINKING_REQUIRED: 4003,\n\n // Server errors (5000-5999)\n INTERNAL_ERROR: 5001,\n EXTERNAL_SERVICE_ERROR: 5002,\n DATABASE_ERROR: 5003,\n CONFIGURATION_ERROR: 5004,\n\n // Rate limiting (6000-6999)\n RATE_LIMIT_EXCEEDED: 6001,\n QUOTA_EXCEEDED: 6002,\n\n // B2B errors (7000-7999)\n B2B_PARTNER_NOT_FOUND: 7001,\n B2B_PROJECT_NOT_FOUND: 7002,\n B2B_CALL_NOT_FOUND: 7003,\n B2B_NO_PHONE_NUMBER: 7004,\n B2B_UNSUPPORTED_COUNTRY: 7005,\n B2B_TOOL_EXECUTION_FAILED: 7006,\n B2B_WEBHOOK_DELIVERY_FAILED: 7007,\n SUBSCRIPTION_EXPIRED: 7008,\n} as const;\n"],"mappings":"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","names":["axios","config"]}
package/dist/index.mjs CHANGED
@@ -9,10 +9,6 @@ import {
9
9
  import {
10
10
  ErrorCodes
11
11
  } from "./chunk-WMXO6YYV.mjs";
12
- import {
13
- parseToolWebhook,
14
- verifyWebhookSignature
15
- } from "./chunk-IKGLZFM6.mjs";
16
12
 
17
13
  // src/index.ts
18
14
  import axios from "axios";
@@ -163,8 +159,6 @@ export {
163
159
  SubscriptionError,
164
160
  UsageClient,
165
161
  ValidationError,
166
- index_default as default,
167
- parseToolWebhook,
168
- verifyWebhookSignature
162
+ index_default as default
169
163
  };
170
164
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Pamela Enterprise Voice API SDK for JavaScript/TypeScript\n */\n\nimport axios, { AxiosInstance, AxiosError } from 'axios';\nimport {\n PamelaError,\n AuthenticationError,\n SubscriptionError,\n RateLimitError,\n ValidationError,\n CallError,\n} from './errors';\nimport type {\n PamelaClientConfig,\n CreateCallRequest,\n CallResponse,\n CallStatus,\n ToolDefinition,\n} from './types';\n\nconst mapAxiosError = (error: AxiosError, endpoint?: string): PamelaError => {\n const statusCode = error.response?.status;\n const data = error.response?.data as any;\n let errorCode: number | undefined;\n let message: string | undefined;\n let details: Record<string, any> | undefined;\n\n if (data && typeof data === 'object') {\n const detail = data.detail;\n if (detail && typeof detail === 'object') {\n errorCode = detail.error_code ?? detail.error?.code;\n message = detail.message ?? detail.error?.message;\n details = detail.details ?? detail.error?.details;\n } else {\n errorCode = data.error_code ?? data.error?.code;\n message = data.message ?? data.detail;\n details = data.details ?? data.error?.details;\n }\n }\n\n if (!message) {\n message = error.message || 'Request failed';\n }\n\n const options = { errorCode, details, statusCode };\n if (statusCode === 401) return new AuthenticationError(message, options);\n if (statusCode === 403) return new SubscriptionError(message, options);\n if (statusCode === 429) return new RateLimitError(message, options);\n if (statusCode === 400 || statusCode === 422) return new ValidationError(message, options);\n\n if (endpoint?.startsWith('/calls')) {\n return new CallError(message, options);\n }\n\n return new PamelaError(message, options);\n};\n\nexport class UsageClient {\n private client: AxiosInstance;\n\n constructor(client: AxiosInstance) {\n this.client = client;\n }\n\n /**\n * Get usage statistics for partner/project.\n */\n async get(period?: string): Promise<{\n partner_id: string;\n project_id?: string;\n period: string;\n call_count: number;\n last_updated?: string;\n quota?: {\n partner_limit?: number;\n project_limit?: number;\n };\n }> {\n const params = period ? { period } : {};\n const response = await this.client.get('/usage', { params });\n return response.data;\n }\n}\n\nexport class PamelaClient {\n private client: AxiosInstance;\n private apiKey: string;\n public usage: UsageClient;\n\n constructor(config: PamelaClientConfig) {\n this.apiKey = config.apiKey;\n const baseURL = config.baseUrl || 'https://api.thisispamela.com';\n \n this.client = axios.create({\n baseURL: `${baseURL}/api/b2b/v1`,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n timeout: 30000,\n });\n\n // Initialize usage client\n this.usage = new UsageClient(this.client);\n\n // Add retry logic\n this.client.interceptors.response.use(\n (response) => response,\n async (error: AxiosError) => {\n const config = error.config as any;\n if (!config || !config.retry) {\n config.retry = 0;\n }\n config.retry += 1;\n\n if (config.retry <= 3 && error.response?.status && error.response.status >= 500) {\n await new Promise(resolve => setTimeout(resolve, 1000 * config.retry));\n return this.client.request(config);\n }\n\n return Promise.reject(mapAxiosError(error, config?.url));\n }\n );\n }\n\n /**\n * Create a new call.\n */\n async createCall(request: CreateCallRequest): Promise<CallResponse> {\n const response = await this.client.post<CallResponse>('/calls', request);\n return response.data;\n }\n\n /**\n * Get call status and details.\n */\n async getCall(callId: string): Promise<CallStatus> {\n const response = await this.client.get<CallStatus>(`/calls/${callId}`);\n return response.data;\n }\n\n /**\n * List calls for the authenticated partner/project.\n */\n async listCalls(params?: {\n status?: string;\n status_filter?: string;\n limit?: number;\n offset?: number;\n start_date?: string;\n end_date?: string;\n }): Promise<{ items: CallStatus[]; total: number; limit: number; offset: number }> {\n const normalizedParams = { ...params };\n if (params?.status_filter || params?.status) {\n normalizedParams.status_filter = params?.status_filter ?? params?.status;\n delete (normalizedParams as { status?: string }).status;\n }\n const response = await this.client.get('/calls', { params: normalizedParams });\n // Backend returns { items: [...], total, limit, offset }\n return response.data;\n }\n\n /**\n * Cancel an in-progress call.\n */\n async cancelCall(callId: string): Promise<{ success: boolean; call_id: string; status: string }> {\n const response = await this.client.post(`/calls/${callId}/cancel`);\n return response.data;\n }\n\n /**\n * Force hangup an in-progress call.\n */\n async hangupCall(callId: string): Promise<{ success: boolean; call_id: string; status: string }> {\n const response = await this.client.post(`/calls/${callId}/hangup`);\n return response.data;\n }\n\n /**\n * Register a tool.\n */\n async registerTool(tool: ToolDefinition): Promise<{ id: string; project_id: string; name: string; description: string; input_schema: Record<string, any>; output_schema: Record<string, any>; timeout_ms: number; created_at: string }> {\n const response = await this.client.post('/tools', { tool });\n return response.data;\n }\n\n /**\n * List all tools for the project.\n */\n async listTools(): Promise<Array<{ id: string; project_id: string; name: string; description: string; input_schema: Record<string, any>; output_schema: Record<string, any>; timeout_ms: number; created_at: string }>> {\n const response = await this.client.get('/tools');\n return response.data;\n }\n\n /**\n * Delete a tool.\n */\n async deleteTool(toolId: string): Promise<{ success: boolean; tool_id: string }> {\n const response = await this.client.delete(`/tools/${toolId}`);\n return response.data;\n }\n\n}\n\n// Export as both default and named export for flexibility\nexport default PamelaClient;\nexport { PamelaClient as Pamela };\nexport {\n PamelaError,\n AuthenticationError,\n SubscriptionError,\n RateLimitError,\n ValidationError,\n CallError,\n};\nexport * from './types';\nexport * from './webhooks';\n\n"],"mappings":"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","names":["config"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Pamela Enterprise Voice API SDK for JavaScript/TypeScript\n */\n\nimport axios, { AxiosInstance, AxiosError } from 'axios';\nimport {\n PamelaError,\n AuthenticationError,\n SubscriptionError,\n RateLimitError,\n ValidationError,\n CallError,\n} from './errors';\nimport type {\n PamelaClientConfig,\n CreateCallRequest,\n CallResponse,\n CallStatus,\n ToolDefinition,\n} from './types';\n\nconst mapAxiosError = (error: AxiosError, endpoint?: string): PamelaError => {\n const statusCode = error.response?.status;\n const data = error.response?.data as any;\n let errorCode: number | undefined;\n let message: string | undefined;\n let details: Record<string, any> | undefined;\n\n if (data && typeof data === 'object') {\n const detail = data.detail;\n if (detail && typeof detail === 'object') {\n errorCode = detail.error_code ?? detail.error?.code;\n message = detail.message ?? detail.error?.message;\n details = detail.details ?? detail.error?.details;\n } else {\n errorCode = data.error_code ?? data.error?.code;\n message = data.message ?? data.detail;\n details = data.details ?? data.error?.details;\n }\n }\n\n if (!message) {\n message = error.message || 'Request failed';\n }\n\n const options = { errorCode, details, statusCode };\n if (statusCode === 401) return new AuthenticationError(message, options);\n if (statusCode === 403) return new SubscriptionError(message, options);\n if (statusCode === 429) return new RateLimitError(message, options);\n if (statusCode === 400 || statusCode === 422) return new ValidationError(message, options);\n\n if (endpoint?.startsWith('/calls')) {\n return new CallError(message, options);\n }\n\n return new PamelaError(message, options);\n};\n\nexport class UsageClient {\n private client: AxiosInstance;\n\n constructor(client: AxiosInstance) {\n this.client = client;\n }\n\n /**\n * Get usage statistics for partner/project.\n */\n async get(period?: string): Promise<{\n partner_id: string;\n project_id?: string;\n period: string;\n call_count: number;\n last_updated?: string;\n quota?: {\n partner_limit?: number;\n project_limit?: number;\n };\n }> {\n const params = period ? { period } : {};\n const response = await this.client.get('/usage', { params });\n return response.data;\n }\n}\n\nexport class PamelaClient {\n private client: AxiosInstance;\n private apiKey: string;\n public usage: UsageClient;\n\n constructor(config: PamelaClientConfig) {\n this.apiKey = config.apiKey;\n const baseURL = config.baseUrl || 'https://api.thisispamela.com';\n \n this.client = axios.create({\n baseURL: `${baseURL}/api/b2b/v1`,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n timeout: 30000,\n });\n\n // Initialize usage client\n this.usage = new UsageClient(this.client);\n\n // Add retry logic\n this.client.interceptors.response.use(\n (response) => response,\n async (error: AxiosError) => {\n const config = error.config as any;\n if (!config || !config.retry) {\n config.retry = 0;\n }\n config.retry += 1;\n\n if (config.retry <= 3 && error.response?.status && error.response.status >= 500) {\n await new Promise(resolve => setTimeout(resolve, 1000 * config.retry));\n return this.client.request(config);\n }\n\n return Promise.reject(mapAxiosError(error, config?.url));\n }\n );\n }\n\n /**\n * Create a new call.\n */\n async createCall(request: CreateCallRequest): Promise<CallResponse> {\n const response = await this.client.post<CallResponse>('/calls', request);\n return response.data;\n }\n\n /**\n * Get call status and details.\n */\n async getCall(callId: string): Promise<CallStatus> {\n const response = await this.client.get<CallStatus>(`/calls/${callId}`);\n return response.data;\n }\n\n /**\n * List calls for the authenticated partner/project.\n */\n async listCalls(params?: {\n status?: string;\n status_filter?: string;\n limit?: number;\n offset?: number;\n start_date?: string;\n end_date?: string;\n }): Promise<{ items: CallStatus[]; total: number; limit: number; offset: number }> {\n const normalizedParams = { ...params };\n if (params?.status_filter || params?.status) {\n normalizedParams.status_filter = params?.status_filter ?? params?.status;\n delete (normalizedParams as { status?: string }).status;\n }\n const response = await this.client.get('/calls', { params: normalizedParams });\n // Backend returns { items: [...], total, limit, offset }\n return response.data;\n }\n\n /**\n * Cancel an in-progress call.\n */\n async cancelCall(callId: string): Promise<{ success: boolean; call_id: string; status: string }> {\n const response = await this.client.post(`/calls/${callId}/cancel`);\n return response.data;\n }\n\n /**\n * Force hangup an in-progress call.\n */\n async hangupCall(callId: string): Promise<{ success: boolean; call_id: string; status: string }> {\n const response = await this.client.post(`/calls/${callId}/hangup`);\n return response.data;\n }\n\n /**\n * Register a tool.\n */\n async registerTool(tool: ToolDefinition): Promise<{ id: string; project_id: string; name: string; description: string; input_schema: Record<string, any>; output_schema: Record<string, any>; timeout_ms: number; created_at: string }> {\n const response = await this.client.post('/tools', { tool });\n return response.data;\n }\n\n /**\n * List all tools for the project.\n */\n async listTools(): Promise<Array<{ id: string; project_id: string; name: string; description: string; input_schema: Record<string, any>; output_schema: Record<string, any>; timeout_ms: number; created_at: string }>> {\n const response = await this.client.get('/tools');\n return response.data;\n }\n\n /**\n * Delete a tool.\n */\n async deleteTool(toolId: string): Promise<{ success: boolean; tool_id: string }> {\n const response = await this.client.delete(`/tools/${toolId}`);\n return response.data;\n }\n\n}\n\n// Export as both default and named export for flexibility\nexport default PamelaClient;\nexport { PamelaClient as Pamela };\nexport {\n PamelaError,\n AuthenticationError,\n SubscriptionError,\n RateLimitError,\n ValidationError,\n CallError,\n};\nexport * from './types';\n// Webhooks are available via @thisispamela/sdk/webhooks subpath\n// (not exported here to keep main bundle browser-compatible)\n\n"],"mappings":"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","names":["config"]}
package/dist/webhooks.mjs CHANGED
@@ -1,7 +1,35 @@
1
- import {
2
- parseToolWebhook,
3
- verifyWebhookSignature
4
- } from "./chunk-IKGLZFM6.mjs";
1
+ // src/webhooks.ts
2
+ import * as crypto from "crypto";
3
+ var verifyWebhookSignature = (payload, signature, secret) => {
4
+ if (!signature) {
5
+ return false;
6
+ }
7
+ if (!secret) {
8
+ throw new Error("Webhook secret cannot be empty");
9
+ }
10
+ const payloadString = typeof payload === "string" ? payload : JSON.stringify(payload);
11
+ const expectedSignature = crypto.createHmac("sha256", secret).update(payloadString).digest("hex");
12
+ return crypto.timingSafeEqual(
13
+ Buffer.from(signature),
14
+ Buffer.from(expectedSignature)
15
+ );
16
+ };
17
+ var parseToolWebhook = (payload) => {
18
+ const requiredFields = ["tool_name", "arguments", "call_id", "correlation_id"];
19
+ const missing = requiredFields.filter((field) => !(field in payload));
20
+ if (missing.length > 0) {
21
+ throw new Error(`Missing required fields: ${missing.join(", ")}`);
22
+ }
23
+ return {
24
+ tool_name: String(payload.tool_name),
25
+ arguments: typeof payload.arguments === "object" && payload.arguments ? payload.arguments : {},
26
+ call_id: String(payload.call_id),
27
+ correlation_id: String(payload.correlation_id),
28
+ call_session_id: payload.call_session_id,
29
+ partner_id: payload.partner_id,
30
+ project_id: payload.project_id
31
+ };
32
+ };
5
33
  export {
6
34
  parseToolWebhook,
7
35
  verifyWebhookSignature
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../src/webhooks.ts"],"sourcesContent":["import * as crypto from 'crypto';\n\nexport const verifyWebhookSignature = (\n payload: string | object,\n signature: string | undefined | null,\n secret: string\n): boolean => {\n if (!signature) {\n return false;\n }\n\n if (!secret) {\n throw new Error('Webhook secret cannot be empty');\n }\n\n const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload);\n const expectedSignature = crypto\n .createHmac('sha256', secret)\n .update(payloadString)\n .digest('hex');\n\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSignature)\n );\n};\n\nexport const parseToolWebhook = (payload: Record<string, any>): {\n tool_name: string;\n arguments: Record<string, any>;\n call_id: string;\n correlation_id: string;\n call_session_id?: string;\n partner_id?: string;\n project_id?: string;\n} => {\n const requiredFields = ['tool_name', 'arguments', 'call_id', 'correlation_id'];\n const missing = requiredFields.filter((field) => !(field in payload));\n\n if (missing.length > 0) {\n throw new Error(`Missing required fields: ${missing.join(', ')}`);\n }\n\n return {\n tool_name: String(payload.tool_name),\n arguments: typeof payload.arguments === 'object' && payload.arguments\n ? payload.arguments\n : {},\n call_id: String(payload.call_id),\n correlation_id: String(payload.correlation_id),\n call_session_id: payload.call_session_id,\n partner_id: payload.partner_id,\n project_id: payload.project_id,\n };\n};\n"],"mappings":";AAAA,YAAY,YAAY;AAEjB,IAAM,yBAAyB,CACpC,SACA,WACA,WACY;AACZ,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AAEA,QAAM,gBAAgB,OAAO,YAAY,WAAW,UAAU,KAAK,UAAU,OAAO;AACpF,QAAM,oBACH,kBAAW,UAAU,MAAM,EAC3B,OAAO,aAAa,EACpB,OAAO,KAAK;AAEf,SAAc;AAAA,IACZ,OAAO,KAAK,SAAS;AAAA,IACrB,OAAO,KAAK,iBAAiB;AAAA,EAC/B;AACF;AAEO,IAAM,mBAAmB,CAAC,YAQ5B;AACH,QAAM,iBAAiB,CAAC,aAAa,aAAa,WAAW,gBAAgB;AAC7E,QAAM,UAAU,eAAe,OAAO,CAAC,UAAU,EAAE,SAAS,QAAQ;AAEpE,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,IAAI,MAAM,4BAA4B,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,EAClE;AAEA,SAAO;AAAA,IACL,WAAW,OAAO,QAAQ,SAAS;AAAA,IACnC,WAAW,OAAO,QAAQ,cAAc,YAAY,QAAQ,YACxD,QAAQ,YACR,CAAC;AAAA,IACL,SAAS,OAAO,QAAQ,OAAO;AAAA,IAC/B,gBAAgB,OAAO,QAAQ,cAAc;AAAA,IAC7C,iBAAiB,QAAQ;AAAA,IACzB,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,EACtB;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thisispamela/sdk",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Pamela Enterprise Voice API SDK for JavaScript/TypeScript",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/index.ts CHANGED
@@ -215,5 +215,6 @@ export {
215
215
  CallError,
216
216
  };
217
217
  export * from './types';
218
- export * from './webhooks';
218
+ // Webhooks are available via @thisispamela/sdk/webhooks subpath
219
+ // (not exported here to keep main bundle browser-compatible)
219
220
 
@@ -1,38 +0,0 @@
1
- // src/webhooks.ts
2
- import * as crypto from "crypto";
3
- var verifyWebhookSignature = (payload, signature, secret) => {
4
- if (!signature) {
5
- return false;
6
- }
7
- if (!secret) {
8
- throw new Error("Webhook secret cannot be empty");
9
- }
10
- const payloadString = typeof payload === "string" ? payload : JSON.stringify(payload);
11
- const expectedSignature = crypto.createHmac("sha256", secret).update(payloadString).digest("hex");
12
- return crypto.timingSafeEqual(
13
- Buffer.from(signature),
14
- Buffer.from(expectedSignature)
15
- );
16
- };
17
- var parseToolWebhook = (payload) => {
18
- const requiredFields = ["tool_name", "arguments", "call_id", "correlation_id"];
19
- const missing = requiredFields.filter((field) => !(field in payload));
20
- if (missing.length > 0) {
21
- throw new Error(`Missing required fields: ${missing.join(", ")}`);
22
- }
23
- return {
24
- tool_name: String(payload.tool_name),
25
- arguments: typeof payload.arguments === "object" && payload.arguments ? payload.arguments : {},
26
- call_id: String(payload.call_id),
27
- correlation_id: String(payload.correlation_id),
28
- call_session_id: payload.call_session_id,
29
- partner_id: payload.partner_id,
30
- project_id: payload.project_id
31
- };
32
- };
33
-
34
- export {
35
- verifyWebhookSignature,
36
- parseToolWebhook
37
- };
38
- //# sourceMappingURL=chunk-IKGLZFM6.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/webhooks.ts"],"sourcesContent":["import * as crypto from 'crypto';\n\nexport const verifyWebhookSignature = (\n payload: string | object,\n signature: string | undefined | null,\n secret: string\n): boolean => {\n if (!signature) {\n return false;\n }\n\n if (!secret) {\n throw new Error('Webhook secret cannot be empty');\n }\n\n const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload);\n const expectedSignature = crypto\n .createHmac('sha256', secret)\n .update(payloadString)\n .digest('hex');\n\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSignature)\n );\n};\n\nexport const parseToolWebhook = (payload: Record<string, any>): {\n tool_name: string;\n arguments: Record<string, any>;\n call_id: string;\n correlation_id: string;\n call_session_id?: string;\n partner_id?: string;\n project_id?: string;\n} => {\n const requiredFields = ['tool_name', 'arguments', 'call_id', 'correlation_id'];\n const missing = requiredFields.filter((field) => !(field in payload));\n\n if (missing.length > 0) {\n throw new Error(`Missing required fields: ${missing.join(', ')}`);\n }\n\n return {\n tool_name: String(payload.tool_name),\n arguments: typeof payload.arguments === 'object' && payload.arguments\n ? payload.arguments\n : {},\n call_id: String(payload.call_id),\n correlation_id: String(payload.correlation_id),\n call_session_id: payload.call_session_id,\n partner_id: payload.partner_id,\n project_id: payload.project_id,\n };\n};\n"],"mappings":";AAAA,YAAY,YAAY;AAEjB,IAAM,yBAAyB,CACpC,SACA,WACA,WACY;AACZ,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AAEA,QAAM,gBAAgB,OAAO,YAAY,WAAW,UAAU,KAAK,UAAU,OAAO;AACpF,QAAM,oBACH,kBAAW,UAAU,MAAM,EAC3B,OAAO,aAAa,EACpB,OAAO,KAAK;AAEf,SAAc;AAAA,IACZ,OAAO,KAAK,SAAS;AAAA,IACrB,OAAO,KAAK,iBAAiB;AAAA,EAC/B;AACF;AAEO,IAAM,mBAAmB,CAAC,YAQ5B;AACH,QAAM,iBAAiB,CAAC,aAAa,aAAa,WAAW,gBAAgB;AAC7E,QAAM,UAAU,eAAe,OAAO,CAAC,UAAU,EAAE,SAAS,QAAQ;AAEpE,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,IAAI,MAAM,4BAA4B,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,EAClE;AAEA,SAAO;AAAA,IACL,WAAW,OAAO,QAAQ,SAAS;AAAA,IACnC,WAAW,OAAO,QAAQ,cAAc,YAAY,QAAQ,YACxD,QAAQ,YACR,CAAC;AAAA,IACL,SAAS,OAAO,QAAQ,OAAO;AAAA,IAC/B,gBAAgB,OAAO,QAAQ,cAAc;AAAA,IAC7C,iBAAiB,QAAQ;AAAA,IACzB,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,EACtB;AACF;","names":[]}