@rymi/node 2.3.0 → 2.4.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 CHANGED
@@ -82,7 +82,7 @@ The client exposes one namespace per resource group:
82
82
  | `contacts` | Contacts and per-channel consent |
83
83
  | `compliance` | Compliance attestations (e.g. an external DNC scrub) |
84
84
  | `toolSecrets` | Secrets for API-tool headers, referenced as `{{secrets.NAME}}` |
85
- | `workspaces` | List, create and rename workspaces. Pass `workspace` (or `RYMI_WORKSPACE`) to act in one of them. A workspace you create does not get the free monthly credit. You can own at most 20. |
85
+ | `workspaces` | List, create and update workspaces, including client workspaces (`create({ name, parent })`) that your agency pays for, with a monthly `spend_cap_cents_monthly`. `usage(id, { month })` for invoicing; `listMembers`, `addMember`, `removeMember`. Pass `workspace` (or `RYMI_WORKSPACE`) to act in one of them. |
86
86
 
87
87
  ## 📖 Documentation
88
88
 
package/dist/index.d.mts CHANGED
@@ -1418,14 +1418,39 @@ interface Workspace {
1418
1418
  id: string;
1419
1419
  name: string;
1420
1420
  role: 'owner' | 'admin' | 'client';
1421
+ /** The agency, for a client workspace. */
1421
1422
  parent_id: string | null;
1422
1423
  operating_country: string | null;
1424
+ /** Client workspaces only; absent for the client role. */
1425
+ spend_cap_cents_monthly?: number | null;
1423
1426
  current?: boolean;
1424
1427
  }
1425
1428
  interface CreateWorkspaceParams {
1426
1429
  name: string;
1427
1430
  /** ISO-3166 alpha-2, e.g. "IN". */
1428
1431
  operating_country?: string | null;
1432
+ /** An agency workspace you run: makes this a client workspace that the agency pays for. */
1433
+ parent?: string;
1434
+ }
1435
+ interface UpdateWorkspaceParams {
1436
+ name?: string;
1437
+ operating_country?: string | null;
1438
+ /** Client workspaces only. Credits per calendar month (1 credit = $0.01); null removes the cap. */
1439
+ spend_cap_cents_monthly?: number | null;
1440
+ }
1441
+ interface WorkspaceUsage {
1442
+ workspace_id: string;
1443
+ /** YYYY-MM, UTC. */
1444
+ month: string;
1445
+ calls: number;
1446
+ minutes: number;
1447
+ /** Left out for the client role. */
1448
+ credits?: number;
1449
+ }
1450
+ interface WorkspaceMember {
1451
+ user_id: string;
1452
+ email: string | null;
1453
+ role: 'owner' | 'admin' | 'client';
1429
1454
  }
1430
1455
  declare class WorkspacesResource {
1431
1456
  private client;
@@ -1436,10 +1461,24 @@ declare class WorkspacesResource {
1436
1461
  create(data: CreateWorkspaceParams): Promise<{
1437
1462
  workspace: Workspace;
1438
1463
  }>;
1439
- update(id: string, data: {
1440
- name?: string;
1441
- operating_country?: string | null;
1464
+ update(id: string, data: UpdateWorkspaceParams): Promise<{
1465
+ ok: true;
1466
+ }>;
1467
+ /** Calls, minutes and credits for one month (default: this month, UTC). */
1468
+ usage(id: string, params?: {
1469
+ month?: string;
1470
+ }): Promise<WorkspaceUsage>;
1471
+ listMembers(id: string): Promise<{
1472
+ members: WorkspaceMember[];
1473
+ }>;
1474
+ /** Someone without a Rymi account gets an invite email. Client workspaces take the client role. */
1475
+ addMember(id: string, data: {
1476
+ email: string;
1477
+ role?: 'admin' | 'client';
1442
1478
  }): Promise<{
1479
+ member: WorkspaceMember;
1480
+ }>;
1481
+ removeMember(id: string, userId: string): Promise<{
1443
1482
  ok: true;
1444
1483
  }>;
1445
1484
  }
@@ -1463,4 +1502,4 @@ declare class Rymi {
1463
1502
  constructor(options?: ClientOptions);
1464
1503
  }
1465
1504
 
1466
- export { type AddCampaignMembersParams, type AddKnowledgeSourceParams, type AgentCallListResponse, type AgentChange, type AgentKnowledgeSource, type AgentListResponse, type AgentShareLink, type AgentShareLinkSettings, type AgentTemplateSummary, AgentsResource, type ApplyChangesParams, type ApplyChangesResponse, type AttestParams, type AttestResponse, type Attestation, type BatchCallParams, BillingResource, type CallListResponse, type CallRecord, CallsResource, type CampaignAttemptListResponse, type CampaignBatch, type CampaignBatchListResponse, type CampaignFollowupJob, type CampaignFollowupListResponse, type CampaignIntake, type CampaignIntakeSettings, type CampaignListResponse, type CampaignMemberListResponse, type CampaignReportResponse, type CampaignRoute, type CampaignRouteListResponse, type CampaignSuggestion, type CampaignSuggestionListResponse, CampaignsResource, type ChangeEntry, type ClientOptions, ComplianceResource, type ConnectTelephonyParams, type ContactListResponse, ContactsResource, type CreateAgentParams, type CreateCallParams, type CreateCallResponse, type CreateCampaignParams, type CreateCampaignRouteParams, type CreateContactParams, type CreateContactResponse, type CreatePublishableKeyParams, type CreateWorkspaceParams, type DncCheckResult, type DncEntry, type DncListResponse, DncResource, type EnrichCompanyParams, type EnrichCompanyResponse, type FanoutCallParams, type ImportCampaignMembersParams, type ImportCampaignMembersResponse, type ImportContactsParams, type ImportContactsResponse, type ImproveCampaignResponse, KeysResource, type LaunchBlocker, type LaunchCampaignResponse, type ListAttestationsResponse, type ListCallsParams, type ListCampaignAttemptsParams, type ListCampaignBatchesParams, type ListCampaignFollowupsParams, type ListCampaignMembersParams, type ListCampaignRoutesParams, type ListCampaignSuggestionsParams, type ListCampaignsParams, type ListContactsParams, type NumberRecord, NumbersResource, type PreviewStackParams, type PublishAgentResponse, type PublishValidationIssue, type PublishableKeyRecord, Rymi, RymiClient, RymiError, type SetConsentParams, type SetConsentResponse, type TelephonyProvider, TelephonyResource, TemplatesResource, type ToolSecretRecord, ToolSecretsResource, type UpdateAgentParams, type UpdateCampaignMemberParams, type UpdateCampaignParams, type UpdateCampaignRouteParams, type UpdateContactParams, type UsageSummary, type ValidatePublishParams, type WebhookProvisionResult, type WebhookRecord, WebhooksResource, type Workspace, WorkspacesResource, Rymi as default };
1505
+ export { type AddCampaignMembersParams, type AddKnowledgeSourceParams, type AgentCallListResponse, type AgentChange, type AgentKnowledgeSource, type AgentListResponse, type AgentShareLink, type AgentShareLinkSettings, type AgentTemplateSummary, AgentsResource, type ApplyChangesParams, type ApplyChangesResponse, type AttestParams, type AttestResponse, type Attestation, type BatchCallParams, BillingResource, type CallListResponse, type CallRecord, CallsResource, type CampaignAttemptListResponse, type CampaignBatch, type CampaignBatchListResponse, type CampaignFollowupJob, type CampaignFollowupListResponse, type CampaignIntake, type CampaignIntakeSettings, type CampaignListResponse, type CampaignMemberListResponse, type CampaignReportResponse, type CampaignRoute, type CampaignRouteListResponse, type CampaignSuggestion, type CampaignSuggestionListResponse, CampaignsResource, type ChangeEntry, type ClientOptions, ComplianceResource, type ConnectTelephonyParams, type ContactListResponse, ContactsResource, type CreateAgentParams, type CreateCallParams, type CreateCallResponse, type CreateCampaignParams, type CreateCampaignRouteParams, type CreateContactParams, type CreateContactResponse, type CreatePublishableKeyParams, type CreateWorkspaceParams, type DncCheckResult, type DncEntry, type DncListResponse, DncResource, type EnrichCompanyParams, type EnrichCompanyResponse, type FanoutCallParams, type ImportCampaignMembersParams, type ImportCampaignMembersResponse, type ImportContactsParams, type ImportContactsResponse, type ImproveCampaignResponse, KeysResource, type LaunchBlocker, type LaunchCampaignResponse, type ListAttestationsResponse, type ListCallsParams, type ListCampaignAttemptsParams, type ListCampaignBatchesParams, type ListCampaignFollowupsParams, type ListCampaignMembersParams, type ListCampaignRoutesParams, type ListCampaignSuggestionsParams, type ListCampaignsParams, type ListContactsParams, type NumberRecord, NumbersResource, type PreviewStackParams, type PublishAgentResponse, type PublishValidationIssue, type PublishableKeyRecord, Rymi, RymiClient, RymiError, type SetConsentParams, type SetConsentResponse, type TelephonyProvider, TelephonyResource, TemplatesResource, type ToolSecretRecord, ToolSecretsResource, type UpdateAgentParams, type UpdateCampaignMemberParams, type UpdateCampaignParams, type UpdateCampaignRouteParams, type UpdateContactParams, type UpdateWorkspaceParams, type UsageSummary, type ValidatePublishParams, type WebhookProvisionResult, type WebhookRecord, WebhooksResource, type Workspace, type WorkspaceMember, type WorkspaceUsage, WorkspacesResource, Rymi as default };
package/dist/index.d.ts CHANGED
@@ -1418,14 +1418,39 @@ interface Workspace {
1418
1418
  id: string;
1419
1419
  name: string;
1420
1420
  role: 'owner' | 'admin' | 'client';
1421
+ /** The agency, for a client workspace. */
1421
1422
  parent_id: string | null;
1422
1423
  operating_country: string | null;
1424
+ /** Client workspaces only; absent for the client role. */
1425
+ spend_cap_cents_monthly?: number | null;
1423
1426
  current?: boolean;
1424
1427
  }
1425
1428
  interface CreateWorkspaceParams {
1426
1429
  name: string;
1427
1430
  /** ISO-3166 alpha-2, e.g. "IN". */
1428
1431
  operating_country?: string | null;
1432
+ /** An agency workspace you run: makes this a client workspace that the agency pays for. */
1433
+ parent?: string;
1434
+ }
1435
+ interface UpdateWorkspaceParams {
1436
+ name?: string;
1437
+ operating_country?: string | null;
1438
+ /** Client workspaces only. Credits per calendar month (1 credit = $0.01); null removes the cap. */
1439
+ spend_cap_cents_monthly?: number | null;
1440
+ }
1441
+ interface WorkspaceUsage {
1442
+ workspace_id: string;
1443
+ /** YYYY-MM, UTC. */
1444
+ month: string;
1445
+ calls: number;
1446
+ minutes: number;
1447
+ /** Left out for the client role. */
1448
+ credits?: number;
1449
+ }
1450
+ interface WorkspaceMember {
1451
+ user_id: string;
1452
+ email: string | null;
1453
+ role: 'owner' | 'admin' | 'client';
1429
1454
  }
1430
1455
  declare class WorkspacesResource {
1431
1456
  private client;
@@ -1436,10 +1461,24 @@ declare class WorkspacesResource {
1436
1461
  create(data: CreateWorkspaceParams): Promise<{
1437
1462
  workspace: Workspace;
1438
1463
  }>;
1439
- update(id: string, data: {
1440
- name?: string;
1441
- operating_country?: string | null;
1464
+ update(id: string, data: UpdateWorkspaceParams): Promise<{
1465
+ ok: true;
1466
+ }>;
1467
+ /** Calls, minutes and credits for one month (default: this month, UTC). */
1468
+ usage(id: string, params?: {
1469
+ month?: string;
1470
+ }): Promise<WorkspaceUsage>;
1471
+ listMembers(id: string): Promise<{
1472
+ members: WorkspaceMember[];
1473
+ }>;
1474
+ /** Someone without a Rymi account gets an invite email. Client workspaces take the client role. */
1475
+ addMember(id: string, data: {
1476
+ email: string;
1477
+ role?: 'admin' | 'client';
1442
1478
  }): Promise<{
1479
+ member: WorkspaceMember;
1480
+ }>;
1481
+ removeMember(id: string, userId: string): Promise<{
1443
1482
  ok: true;
1444
1483
  }>;
1445
1484
  }
@@ -1463,4 +1502,4 @@ declare class Rymi {
1463
1502
  constructor(options?: ClientOptions);
1464
1503
  }
1465
1504
 
1466
- export { type AddCampaignMembersParams, type AddKnowledgeSourceParams, type AgentCallListResponse, type AgentChange, type AgentKnowledgeSource, type AgentListResponse, type AgentShareLink, type AgentShareLinkSettings, type AgentTemplateSummary, AgentsResource, type ApplyChangesParams, type ApplyChangesResponse, type AttestParams, type AttestResponse, type Attestation, type BatchCallParams, BillingResource, type CallListResponse, type CallRecord, CallsResource, type CampaignAttemptListResponse, type CampaignBatch, type CampaignBatchListResponse, type CampaignFollowupJob, type CampaignFollowupListResponse, type CampaignIntake, type CampaignIntakeSettings, type CampaignListResponse, type CampaignMemberListResponse, type CampaignReportResponse, type CampaignRoute, type CampaignRouteListResponse, type CampaignSuggestion, type CampaignSuggestionListResponse, CampaignsResource, type ChangeEntry, type ClientOptions, ComplianceResource, type ConnectTelephonyParams, type ContactListResponse, ContactsResource, type CreateAgentParams, type CreateCallParams, type CreateCallResponse, type CreateCampaignParams, type CreateCampaignRouteParams, type CreateContactParams, type CreateContactResponse, type CreatePublishableKeyParams, type CreateWorkspaceParams, type DncCheckResult, type DncEntry, type DncListResponse, DncResource, type EnrichCompanyParams, type EnrichCompanyResponse, type FanoutCallParams, type ImportCampaignMembersParams, type ImportCampaignMembersResponse, type ImportContactsParams, type ImportContactsResponse, type ImproveCampaignResponse, KeysResource, type LaunchBlocker, type LaunchCampaignResponse, type ListAttestationsResponse, type ListCallsParams, type ListCampaignAttemptsParams, type ListCampaignBatchesParams, type ListCampaignFollowupsParams, type ListCampaignMembersParams, type ListCampaignRoutesParams, type ListCampaignSuggestionsParams, type ListCampaignsParams, type ListContactsParams, type NumberRecord, NumbersResource, type PreviewStackParams, type PublishAgentResponse, type PublishValidationIssue, type PublishableKeyRecord, Rymi, RymiClient, RymiError, type SetConsentParams, type SetConsentResponse, type TelephonyProvider, TelephonyResource, TemplatesResource, type ToolSecretRecord, ToolSecretsResource, type UpdateAgentParams, type UpdateCampaignMemberParams, type UpdateCampaignParams, type UpdateCampaignRouteParams, type UpdateContactParams, type UsageSummary, type ValidatePublishParams, type WebhookProvisionResult, type WebhookRecord, WebhooksResource, type Workspace, WorkspacesResource, Rymi as default };
1505
+ export { type AddCampaignMembersParams, type AddKnowledgeSourceParams, type AgentCallListResponse, type AgentChange, type AgentKnowledgeSource, type AgentListResponse, type AgentShareLink, type AgentShareLinkSettings, type AgentTemplateSummary, AgentsResource, type ApplyChangesParams, type ApplyChangesResponse, type AttestParams, type AttestResponse, type Attestation, type BatchCallParams, BillingResource, type CallListResponse, type CallRecord, CallsResource, type CampaignAttemptListResponse, type CampaignBatch, type CampaignBatchListResponse, type CampaignFollowupJob, type CampaignFollowupListResponse, type CampaignIntake, type CampaignIntakeSettings, type CampaignListResponse, type CampaignMemberListResponse, type CampaignReportResponse, type CampaignRoute, type CampaignRouteListResponse, type CampaignSuggestion, type CampaignSuggestionListResponse, CampaignsResource, type ChangeEntry, type ClientOptions, ComplianceResource, type ConnectTelephonyParams, type ContactListResponse, ContactsResource, type CreateAgentParams, type CreateCallParams, type CreateCallResponse, type CreateCampaignParams, type CreateCampaignRouteParams, type CreateContactParams, type CreateContactResponse, type CreatePublishableKeyParams, type CreateWorkspaceParams, type DncCheckResult, type DncEntry, type DncListResponse, DncResource, type EnrichCompanyParams, type EnrichCompanyResponse, type FanoutCallParams, type ImportCampaignMembersParams, type ImportCampaignMembersResponse, type ImportContactsParams, type ImportContactsResponse, type ImproveCampaignResponse, KeysResource, type LaunchBlocker, type LaunchCampaignResponse, type ListAttestationsResponse, type ListCallsParams, type ListCampaignAttemptsParams, type ListCampaignBatchesParams, type ListCampaignFollowupsParams, type ListCampaignMembersParams, type ListCampaignRoutesParams, type ListCampaignSuggestionsParams, type ListCampaignsParams, type ListContactsParams, type NumberRecord, NumbersResource, type PreviewStackParams, type PublishAgentResponse, type PublishValidationIssue, type PublishableKeyRecord, Rymi, RymiClient, RymiError, type SetConsentParams, type SetConsentResponse, type TelephonyProvider, TelephonyResource, TemplatesResource, type ToolSecretRecord, ToolSecretsResource, type UpdateAgentParams, type UpdateCampaignMemberParams, type UpdateCampaignParams, type UpdateCampaignRouteParams, type UpdateContactParams, type UpdateWorkspaceParams, type UsageSummary, type ValidatePublishParams, type WebhookProvisionResult, type WebhookRecord, WebhooksResource, type Workspace, type WorkspaceMember, type WorkspaceUsage, WorkspacesResource, Rymi as default };
package/dist/index.js CHANGED
@@ -876,6 +876,21 @@ var WorkspacesResource = class {
876
876
  async update(id, data) {
877
877
  return this.client.patch(`/workspaces/${encodeURIComponent(id)}`, data);
878
878
  }
879
+ /** Calls, minutes and credits for one month (default: this month, UTC). */
880
+ async usage(id, params = {}) {
881
+ const query = params.month ? `?month=${encodeURIComponent(params.month)}` : "";
882
+ return this.client.get(`/workspaces/${encodeURIComponent(id)}/usage${query}`);
883
+ }
884
+ async listMembers(id) {
885
+ return this.client.get(`/workspaces/${encodeURIComponent(id)}/members`);
886
+ }
887
+ /** Someone without a Rymi account gets an invite email. Client workspaces take the client role. */
888
+ async addMember(id, data) {
889
+ return this.client.post(`/workspaces/${encodeURIComponent(id)}/members`, data);
890
+ }
891
+ async removeMember(id, userId) {
892
+ return this.client.delete(`/workspaces/${encodeURIComponent(id)}/members/${encodeURIComponent(userId)}`);
893
+ }
879
894
  };
880
895
 
881
896
  // src/index.ts
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/resources/agents.ts","../src/resources/calls.ts","../src/resources/dnc.ts","../src/resources/numbers.ts","../src/resources/webhooks.ts","../src/resources/keys.ts","../src/resources/telephony.ts","../src/resources/billing.ts","../src/resources/templates.ts","../src/resources/campaigns.ts","../src/resources/contacts.ts","../src/resources/compliance.ts","../src/resources/toolSecrets.ts","../src/resources/workspaces.ts"],"sourcesContent":["import { RymiClient, ClientOptions, RymiError } from './client';\nimport { AgentsResource } from './resources/agents';\nimport { CallsResource } from './resources/calls';\nimport { DncResource } from './resources/dnc';\nimport { NumbersResource } from './resources/numbers';\nimport { WebhooksResource } from './resources/webhooks';\nimport { KeysResource } from './resources/keys';\nimport { TelephonyResource } from './resources/telephony';\nimport { BillingResource } from './resources/billing';\nimport { TemplatesResource } from './resources/templates';\nimport { CampaignsResource } from './resources/campaigns';\nimport { ContactsResource } from './resources/contacts';\nimport { ComplianceResource } from './resources/compliance';\nimport { ToolSecretsResource } from './resources/toolSecrets';\nimport { WorkspacesResource } from './resources/workspaces';\n\nexport class Rymi {\n private client: RymiClient;\n\n public agents: AgentsResource;\n public calls: CallsResource;\n public dnc: DncResource;\n public numbers: NumbersResource;\n public webhooks: WebhooksResource;\n public keys: KeysResource;\n public telephony: TelephonyResource;\n public billing: BillingResource;\n public templates: TemplatesResource;\n public campaigns: CampaignsResource;\n public contacts: ContactsResource;\n public compliance: ComplianceResource;\n public toolSecrets: ToolSecretsResource;\n public workspaces: WorkspacesResource;\n\n constructor(options?: ClientOptions) {\n this.client = new RymiClient(options);\n\n // Initialize API Sub-modules\n this.agents = new AgentsResource(this.client);\n this.calls = new CallsResource(this.client);\n this.dnc = new DncResource(this.client);\n this.numbers = new NumbersResource(this.client);\n this.webhooks = new WebhooksResource(this.client);\n this.keys = new KeysResource(this.client);\n this.telephony = new TelephonyResource(this.client);\n this.billing = new BillingResource(this.client);\n this.templates = new TemplatesResource(this.client);\n this.campaigns = new CampaignsResource(this.client);\n this.contacts = new ContactsResource(this.client);\n this.compliance = new ComplianceResource(this.client);\n this.toolSecrets = new ToolSecretsResource(this.client);\n this.workspaces = new WorkspacesResource(this.client);\n }\n}\n\n// Re-export common types\nexport * from './client';\nexport * from './resources/agents';\nexport * from './resources/calls';\nexport * from './resources/dnc';\nexport * from './resources/numbers';\nexport * from './resources/webhooks';\nexport * from './resources/keys';\nexport * from './resources/telephony';\nexport * from './resources/billing';\nexport * from './resources/templates';\nexport * from './resources/campaigns';\nexport * from './resources/contacts';\nexport * from './resources/compliance';\nexport * from './resources/toolSecrets';\nexport * from './resources/workspaces';\n\n// Re-export the curated public type surface (see @rymi/sdk-types).\nexport * from '@rymi/sdk-types';\nexport default Rymi;\n","export interface ClientOptions {\n /**\n * The Rymi secret API key (`rymi_...`)\n */\n apiKey?: string;\n \n /**\n * The base URL for the API. Defaults to `https://api.rymi.live/v1`\n */\n baseURL?: string;\n\n /**\n * Custom fetch implementation. Lets embedders route requests without a\n * network socket (e.g. Fastify app.inject). Defaults to global fetch.\n */\n fetch?: typeof globalThis.fetch;\n\n /**\n * Act in this workspace (sent as `Rymi-Workspace`). Defaults to the\n * `RYMI_WORKSPACE` environment variable, else the key's own workspace.\n */\n workspace?: string;\n}\n\nexport class RymiError extends Error {\n public status?: number;\n public code?: string;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.name = 'RymiError';\n this.status = status;\n this.code = code;\n }\n}\n\nexport class RymiClient {\n private apiKey: string;\n private baseURL: string;\n private fetchImpl: typeof globalThis.fetch;\n private workspace?: string;\n\n constructor(options?: ClientOptions) {\n // Prefer explicit option, then fallback to environment variable\n const key = options?.apiKey || (typeof process !== 'undefined' ? process.env.RYMI_API_KEY : undefined);\n\n if (!key) {\n throw new Error('The Rymi API Key must be set either by passing `apiKey` to the client or setting the `RYMI_API_KEY` environment variable.');\n }\n\n this.apiKey = key;\n this.baseURL = options?.baseURL || 'https://api.rymi.live/v1';\n this.fetchImpl = options?.fetch ?? globalThis.fetch;\n\n // Remove trailing slashes\n if (this.baseURL.endsWith('/')) {\n this.baseURL = this.baseURL.slice(0, -1);\n }\n\n this.workspace = options?.workspace\n || (typeof process !== 'undefined' ? process.env.RYMI_WORKSPACE : undefined)\n || undefined;\n }\n\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\n const url = `${this.baseURL}${path.startsWith('/') ? path : `/${path}`}`;\n \n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Accept': 'application/json',\n 'User-Agent': 'rymi-node/1.0.0'\n };\n if (this.workspace) headers['Rymi-Workspace'] = this.workspace;\n\n const init: RequestInit = {\n method,\n headers\n };\n\n if (body) {\n headers['Content-Type'] = 'application/json';\n init.body = JSON.stringify(body);\n }\n\n try {\n const response = await this.fetchImpl(url, init);\n const isJson = response.headers.get('content-type')?.includes('application/json');\n \n const data = isJson ? await response.json() : await response.text();\n\n if (!response.ok) {\n const message = (data && typeof data === 'object' && 'error' in data) ? (data as any).error : \n (typeof data === 'string' ? data : response.statusText);\n throw new RymiError(message, response.status, (data && typeof data === 'object' && 'code' in data) ? (data as any).code : undefined);\n }\n\n return data as T;\n } catch (error) {\n if (error instanceof RymiError) {\n throw error;\n }\n throw new RymiError(`Network Error: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n public get<T>(path: string): Promise<T> {\n return this.request<T>('GET', path);\n }\n\n public post<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('POST', path, body);\n }\n\n public put<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('PUT', path, body);\n }\n\n public patch<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('PATCH', path, body);\n }\n\n public delete<T>(path: string): Promise<T> {\n return this.request<T>('DELETE', path);\n }\n}\n","import { RymiClient } from '../client';\nimport { Agent, AgentToolBinding } from '@rymi/sdk-types';\n\nexport interface CreateAgentParams {\n name: string;\n /** @deprecated Use system_prompt. This alias is mapped before the request is sent. */\n prompt?: string;\n system_prompt?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n llm_provider?: 'gemini' | 'openai' | 'anthropic' | 'sarvam';\n llm_model?: string;\n llm_fallback_provider?: string | null;\n llm_fallback_model?: string | null;\n stt_provider?: string;\n stt_model?: string;\n stt_fallback_provider?: string | null;\n stt_fallback_model?: string | null;\n tts_provider?: string;\n tts_model?: string;\n tts_fallback_provider?: string | null;\n tts_fallback_model?: string | null;\n /** Self-hosted endpoint URLs (https:// or wss://). Enterprise only. */\n custom_llm_url?: string | null;\n custom_voice_url?: string | null;\n custom_voice_mode?: 'rymi' | 'openai-compat';\n custom_transcriber_url?: string | null;\n language?: string | null;\n /** All BCP-47 languages the agent should handle, e.g. [\"hi-IN\",\"en-US\"] for a bilingual agent. */\n supported_languages?: string[];\n provider_config?: any;\n tools?: AgentToolBinding[];\n}\n\nexport interface UpdateAgentParams {\n name?: string;\n /** @deprecated Use system_prompt. This alias is mapped before the request is sent. */\n prompt?: string;\n system_prompt?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n llm_provider?: 'gemini' | 'openai' | 'anthropic' | 'sarvam';\n llm_model?: string;\n llm_fallback_provider?: string | null;\n llm_fallback_model?: string | null;\n stt_provider?: string;\n stt_model?: string;\n stt_fallback_provider?: string | null;\n stt_fallback_model?: string | null;\n tts_provider?: string;\n tts_model?: string;\n tts_fallback_provider?: string | null;\n tts_fallback_model?: string | null;\n /** Self-hosted endpoint URLs (https:// or wss://). Enterprise only. */\n custom_llm_url?: string | null;\n custom_voice_url?: string | null;\n custom_voice_mode?: 'rymi' | 'openai-compat';\n custom_transcriber_url?: string | null;\n language?: string | null;\n /** All BCP-47 languages the agent should handle, e.g. [\"hi-IN\",\"en-US\"] for a bilingual agent. */\n supported_languages?: string[];\n chat_summary?: string | null;\n provider_config?: any;\n /** Replaces the whole bindings array — build it from a fresh retrieve(). */\n tools?: AgentToolBinding[];\n}\n\nexport interface AgentListResponse {\n agents: Agent[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface AgentCallListResponse {\n calls: any[];\n total: number;\n offset: number;\n limit: number;\n agent_id: string;\n}\n\nexport interface ValidatePublishParams {\n agent_id?: string;\n name?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n [key: string]: any;\n}\n\nexport interface PublishValidationIssue {\n severity?: string;\n section?: string;\n title?: string;\n detail?: string;\n [key: string]: any;\n}\n\nexport interface PublishAgentResponse {\n published: boolean;\n agent_id?: string;\n /** Present when published — the frozen snapshot id and timestamp. */\n snapshot_id?: string | null;\n published_at?: string | null;\n /** Present when published: false because of unresolved blockers. */\n reason?: string;\n blockers?: PublishValidationIssue[];\n warnings?: PublishValidationIssue[];\n error?: string;\n details?: string;\n}\n\nexport interface ChangeEntry {\n key: string;\n value: any;\n}\n\nexport interface ApplyChangesParams {\n currentConfig: Record<string, any>;\n changes: ChangeEntry[];\n mode: 'create' | 'edit';\n lenient?: boolean;\n}\n\nexport interface ApplyChangesResponse {\n valid: true;\n config: Record<string, any>;\n applied: ChangeEntry[];\n}\n\nexport interface EnrichCompanyParams {\n companyName: string;\n websiteUrl: string;\n}\n\nexport interface EnrichCompanyResponse {\n enriched: boolean;\n companyDescription?: string;\n knowledgeBase?: any[];\n error?: string;\n}\n\nexport interface PreviewStackParams {\n language?: string | null;\n /** Required, non-empty list of BCP-47 languages to resolve a stack for. */\n supported_languages: string[];\n current_provider_config?: Record<string, any> | null;\n}\n\nexport interface AgentKnowledgeSource {\n id: string;\n kind?: 'text' | 'url';\n title?: string;\n source_uri?: string | null;\n bytes?: number;\n created_at?: string;\n [key: string]: any;\n}\n\nexport type AddKnowledgeSourceParams =\n | { kind: 'text'; title: string; text: string }\n | { kind: 'url'; title: string; url: string };\n\n/** A public share link: anyone with the URL can talk to the agent, billed to your workspace. */\nexport interface AgentShareLink {\n id: string;\n url: string;\n enabled: boolean;\n minutes_limit: number;\n minutes_used: number;\n minutes_reserved: number;\n minutes_remaining: number;\n live_calls: number;\n max_call_seconds: number;\n max_concurrent: number;\n calls_per_ip_hour: number;\n minutes_requested_at: string | null;\n}\n\n/** All optional; omitted fields keep their current value (or the default on create). */\nexport interface AgentShareLinkSettings {\n enabled?: boolean;\n /** Total talk-time pool for the link, 0–6000 minutes. */\n minutes_limit?: number;\n /** Per-call cap, 60–1800 seconds. */\n max_call_seconds?: number;\n /** Simultaneous calls, 1–10. */\n max_concurrent?: number;\n /** Calls per caller IP per hour, 1–30. */\n calls_per_ip_hour?: number;\n}\n\nexport interface AgentChange {\n change_id: string;\n field_path?: string;\n before_jsonb?: any;\n after_jsonb?: any;\n changed_by?: string;\n created_at?: string;\n undone_at?: string | null;\n [key: string]: any;\n}\n\nfunction normalizeAgentPayload<T extends CreateAgentParams | UpdateAgentParams>(data: T): Omit<T, 'prompt'> & { system_prompt?: string } {\n const { prompt, ...rest } = data as any;\n return {\n ...rest,\n ...(!rest.system_prompt && prompt ? { system_prompt: prompt } : {})\n };\n}\n\nexport class AgentsResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all your AI Agents.\n */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<AgentListResponse> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n const query = searchParams.toString();\n return this.client.get<AgentListResponse>(`/agents${query ? `?${query}` : ''}`);\n }\n\n /**\n * Retrieve a single AI Agent by its unique ID.\n */\n public async retrieve(agentId: string): Promise<Agent> {\n return this.client.get<Agent>(`/agents/${agentId}`);\n }\n\n /**\n * Create a new AI Agent with a complete system prompt and voice settings.\n */\n public async create(data: CreateAgentParams): Promise<{ status: 'created'; id: string }> {\n return this.client.post<{ status: 'created'; id: string }>('/agents', normalizeAgentPayload(data));\n }\n\n /**\n * Update an existing AI Agent's persona or configuration.\n */\n public async update(agentId: string, data: UpdateAgentParams): Promise<{ status: 'updated' }> {\n return this.client.put<{ status: 'updated' }>(`/agents/${agentId}`, normalizeAgentPayload(data));\n }\n\n /**\n * Delete an AI Agent permanently.\n */\n public async delete(agentId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete<{ status: 'deleted'; id: string }>(`/agents/${agentId}`);\n }\n\n public async llmOptions(): Promise<{ models: any[]; voices: any[] }> {\n return this.client.get('/agents/llm-options');\n }\n\n public async generate(data: { prompt: string; options?: Record<string, any> }): Promise<Record<string, any>> {\n return this.client.post('/agents/generate', data);\n }\n\n /**\n * List calls made with a specific agent.\n */\n public async listCalls(agentId: string, params: { limit?: number; offset?: number; status?: string } = {}): Promise<AgentCallListResponse> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n if (params.status) searchParams.set('status', params.status);\n const query = searchParams.toString();\n return this.client.get<AgentCallListResponse>(`/agents/${agentId}/calls${query ? `?${query}` : ''}`);\n }\n\n /**\n * Duplicate an existing agent. The clone gets \" (Copy)\" appended to its name.\n */\n public async clone(agentId: string): Promise<{ status: 'created'; id: string }> {\n return this.client.post<{ status: 'created'; id: string }>(`/agents/${agentId}/clone`, {});\n }\n\n /**\n * Validate an agent's configuration before publishing.\n * Pass agent_id to merge with an existing persisted agent, or supply fields directly.\n */\n public async validatePublish(params: ValidatePublishParams): Promise<Record<string, any>> {\n return this.client.post('/agents/validate-publish', params);\n }\n\n /**\n * Publish an agent: validate its persisted config and freeze it into the\n * published snapshot the harness/review pipeline reads as the baseline.\n * Returns `{ published: false, blockers }` (HTTP 200) when blockers remain —\n * inspect `blockers` rather than relying on a thrown error.\n */\n public async publish(agentId: string): Promise<PublishAgentResponse> {\n return this.client.post<PublishAgentResponse>(`/agents/${agentId}/publish`, {});\n }\n\n /**\n * Validate and apply a flat-diff change-set against the AgentConfig field registry.\n * Does NOT persist — callers must follow up with update().\n */\n public async applyChanges(params: ApplyChangesParams): Promise<ApplyChangesResponse> {\n return this.client.post('/agents/apply-changes', params);\n }\n\n /**\n * Use AI with Google Search grounding to generate a company description from a website URL.\n */\n public async enrichCompany(params: EnrichCompanyParams): Promise<EnrichCompanyResponse> {\n return this.client.post('/agents/enrich-company', params);\n }\n\n /**\n * Preview the resolved per-language model stack (STT/LLM/TTS), blockers,\n * warnings, and model diffs for a set of supported languages — without\n * persisting anything.\n */\n public async previewStack(params: PreviewStackParams): Promise<Record<string, any>> {\n return this.client.post('/agents/stack-preview', params);\n }\n\n /**\n * List the knowledge sources (RAG context) attached to an agent.\n */\n public async listKnowledgeSources(agentId: string): Promise<{ sources: AgentKnowledgeSource[] }> {\n return this.client.get(`/agents/${agentId}/knowledge-sources`);\n }\n\n /**\n * Add a knowledge source to an agent from raw text or a URL.\n */\n public async addKnowledgeSource(agentId: string, data: AddKnowledgeSourceParams): Promise<Record<string, any>> {\n return this.client.post(`/agents/${agentId}/knowledge-sources`, data);\n }\n\n /**\n * Delete a knowledge source from an agent.\n */\n public async deleteKnowledgeSource(agentId: string, sourceId: string): Promise<Record<string, any>> {\n return this.client.delete(`/agents/${agentId}/knowledge-sources/${sourceId}`);\n }\n\n /**\n * Get the agent's public share link, or `link: null` if none exists.\n * `link_feature: false` means share links are disabled on this deployment.\n */\n public async getShareLink(agentId: string): Promise<{ link_feature: boolean; link: AgentShareLink | null }> {\n const res = await this.client.get<{ link_feature: boolean; link: AgentShareLink | null }>(`/agents/${agentId}/testers`);\n return { link_feature: res.link_feature, link: res.link };\n }\n\n /**\n * Create the agent's public share link, or update its settings if one exists.\n */\n public async setShareLink(agentId: string, settings: AgentShareLinkSettings = {}): Promise<{ link: AgentShareLink }> {\n return this.client.put(`/agents/${agentId}/share-link`, settings);\n }\n\n /**\n * Issue a new URL for the share link. The old URL stops working immediately.\n */\n public async regenerateShareLink(agentId: string): Promise<{ link: AgentShareLink }> {\n return this.client.post(`/agents/${agentId}/share-link/regenerate`, {});\n }\n\n /**\n * List the recorded configuration changes for an agent (most recent first).\n * Optionally pass an ISO timestamp to only return changes since then.\n */\n public async listChanges(agentId: string, params: { since?: string } = {}): Promise<{ changes: AgentChange[] }> {\n const query = params.since ? `?since=${encodeURIComponent(params.since)}` : '';\n return this.client.get(`/agents/${agentId}/changes${query}`);\n }\n\n /**\n * Undo a single recorded configuration change, reverting that field to its\n * previous value. Returns the resulting agent snapshot.\n */\n public async undoChange(agentId: string, changeId: string): Promise<{ ok: boolean; changeId: string; agentSnapshot: Agent }> {\n return this.client.post(`/agents/${agentId}/changes/${changeId}/undo`, {});\n }\n\n /**\n * Run the evaluation suite for an agent. mode=\"synthetic\" (default) uses\n * the offline scorer; mode=\"live\" runs the model-driven runner.\n */\n public async runEvals(\n agentId: string,\n params: { mode?: 'synthetic' | 'live'; judge?: boolean } = {},\n ): Promise<Record<string, any>> {\n const query = new URLSearchParams();\n if (params.mode) query.set('mode', params.mode);\n if (params.judge) query.set('judge', '1');\n const qs = query.toString();\n return this.client.post(`/agents/${agentId}/evals/run${qs ? `?${qs}` : ''}`, {});\n }\n\n /**\n * Run the eval SUITE across many agents at once (agents × seeded scenarios),\n * bounded by the optional concurrency cap. One eval run is persisted per\n * agent; the aggregate EvalSuiteReport is returned. Pass `judge: true` to\n * supplement the heuristics with the opt-in LLM judge (needs a Gemini key).\n */\n public async runEvalSuite(params: {\n agentIds: string[];\n scenarioIds?: string[];\n concurrency?: number;\n judge?: boolean;\n }): Promise<Record<string, any>> {\n return this.client.post('/agents/evals/suite', params);\n }\n\n /**\n * List previous evaluation runs for an agent.\n */\n public async listEvalRuns(agentId: string): Promise<Record<string, any>> {\n return this.client.get(`/agents/${agentId}/evals/runs`);\n }\n\n /**\n * Retrieve a single evaluation run, including per-scenario scores.\n */\n public async getEvalRun(agentId: string, runId: string): Promise<Record<string, any>> {\n return this.client.get(`/agents/${agentId}/evals/runs/${runId}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface ListCallsParams {\n limit?: number;\n offset?: number;\n cursor?: string;\n status?: string;\n}\n\nexport interface CallRecord {\n id: string;\n agent_id: string;\n room_name: string;\n status: 'queued' | 'ringing' | 'in_progress' | 'completed' | 'failed' | 'busy' | 'canceled';\n duration_seconds?: number;\n started_at?: string;\n ended_at?: string;\n participants?: Array<{\n id: string;\n role: 'agent' | 'customer' | 'observer';\n transport: 'webrtc' | 'pstn' | 'sip' | 'internal';\n identity: string;\n status: string;\n }>;\n metadata?: Record<string, any>;\n intelligence_status?: string;\n participant_count?: number;\n primary_participant?: Record<string, any> | null;\n total_cost?: number;\n provider_cost?: number;\n provider_cost_breakdown?: Record<string, any>;\n provider_cost_calculated_at?: string | null;\n bill_duration?: number;\n}\n\nexport interface CallListResponse {\n calls: CallRecord[];\n total: number;\n limit: number;\n offset: number;\n next_cursor?: string | null;\n}\n\nexport interface CreateCallParams {\n agent_id: string;\n participants: Array<{\n transport: 'webrtc' | 'pstn';\n identity: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface BatchCallParams {\n agent_id: string;\n to?: string[];\n recipients?: Array<{\n to?: string;\n identity?: string;\n phone?: string;\n phone_number?: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n from_number?: string;\n batch_id?: string;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface FanoutCallParams {\n agent_id: string;\n to?: string[];\n recipients?: Array<{\n to?: string;\n identity?: string;\n phone?: string;\n phone_number?: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n from_number?: string;\n /** Preferred tracking id for this fanout. Falls back to batch_id, then auto-generated. */\n fanout_id?: string;\n /** Compatibility alias for fanout_id. */\n batch_id?: string;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface CreateCallResponse {\n id: string;\n room_name: string;\n status: string;\n participants: Array<{\n id: string;\n transport: 'webrtc' | 'pstn';\n identity: string;\n status: string;\n access?: { url: string; token: string };\n telephony_leg_id?: string;\n job_id?: string;\n }>;\n agent?: { id: string; name: string };\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n searchParams.set(key, String(value));\n }\n }\n const query = searchParams.toString();\n return query ? `?${query}` : '';\n}\n\nexport class CallsResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all previous and active calls.\n */\n public async list(params: ListCallsParams = {}): Promise<CallListResponse> {\n return this.client.get<CallListResponse>(`/calls${buildQuery(params)}`);\n }\n\n /**\n * Retrieve calls currently in progress.\n */\n public async active(params: ListCallsParams = {}): Promise<CallListResponse> {\n return this.client.get<CallListResponse>(`/calls/active${buildQuery(params)}`);\n }\n\n /**\n * Retrieve details, transcripts, and analysis of a single call by its unique ID.\n */\n public async retrieve(callId: string): Promise<CallRecord> {\n return this.client.get<CallRecord>(`/calls/${callId}`);\n }\n\n /**\n * Dispatch an outbound phone call securely using your configured carrier.\n */\n public async create(data: CreateCallParams): Promise<CreateCallResponse> {\n return this.client.post('/calls', data);\n }\n\n /**\n * Group call fanout: dial up to 500 PSTN participants into a single call room.\n * Every recipient joins the same call. For independent per-recipient attempts,\n * retries, and reports, use `campaigns` instead.\n */\n public async fanout(data: FanoutCallParams): Promise<CreateCallResponse & { fanout_id: string; batch_id: string; queued: number }> {\n return this.client.post('/calls/fanout', data);\n }\n\n /**\n * Compatibility alias for {@link fanout}. Creates one call room with multiple\n * PSTN participants. Queue up to 500 outbound PSTN recipients in one request.\n */\n public async batch(data: BatchCallParams): Promise<CreateCallResponse & { batch_id: string; queued: number }> {\n return this.client.post('/calls/batch', data);\n }\n\n public async summary(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/summary`);\n }\n\n public async transcript(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/transcript`);\n }\n\n public async recording(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/recording`);\n }\n\n public async reprocess(callId: string): Promise<Record<string, any>> {\n return this.client.post(`/calls/${callId}/reprocess`);\n }\n\n /** Force-end an active call. Irreversible — closes the LiveKit room and triggers post-call processing. */\n public async end(callId: string): Promise<{ status: string; id: string; message: string }> {\n return this.client.post(`/calls/${callId}/end`);\n }\n\n /** Add one or more participants to an in-progress call (warm transfer / conference). */\n public async addParticipants(\n callId: string,\n data: { participants: CreateCallParams['participants'] }\n ): Promise<CreateCallResponse> {\n return this.client.post(`/calls/${callId}/participants`, data);\n }\n\n public async queueStats(): Promise<Record<string, number>> {\n return this.client.get('/calls/queue/stats');\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface DncEntry {\n id?: string;\n phone: string;\n reason?: string;\n created_at?: string;\n}\n\nexport interface DncListResponse {\n dnc_entries: DncEntry[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface DncCheckResult {\n phone_number: string;\n normalized: string | null;\n blocked: boolean;\n valid: boolean;\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\n/**\n * Do-Not-Call registry. Numbers are normalized to E.164 server-side on both\n * write and read, so any input format is accepted.\n */\nexport class DncResource {\n constructor(private client: RymiClient) {}\n\n /** List all DNC entries for the tenant. */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<DncListResponse> {\n return this.client.get<DncListResponse>(`/dnc${buildQuery(params)}`);\n }\n\n /** Add a single number to the Do-Not-Call registry. */\n public async add(data: { phone_number: string; reason?: string }): Promise<{ status: 'blocklisted'; phone_number: string }> {\n return this.client.post('/dnc', data);\n }\n\n /** Add up to 1000 numbers in one request. Invalid numbers are skipped and returned in `invalid`. */\n public async addBatch(data: { phone_numbers: string[]; reason?: string }): Promise<{ status: 'blocklisted'; count: number; invalid_count: number; invalid: string[] }> {\n return this.client.post('/dnc/batch', data);\n }\n\n /** Check up to 500 numbers without adding them. Read-only. */\n public async check(data: { phone_numbers: string[] }): Promise<{ results: DncCheckResult[]; blocked_count: number; total_checked: number }> {\n return this.client.post('/dnc/check', data);\n }\n\n /** Remove a number from the registry (re-enables outbound to it). */\n public async remove(phone: string): Promise<{ status: 'removed'; phone: string }> {\n return this.client.delete(`/dnc/${encodeURIComponent(phone)}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface NumberRecord {\n id?: string;\n number?: string;\n phone_number?: string;\n provider?: 'plivo' | 'twilio' | 'vonage' | 'telnyx';\n capabilities?: string[];\n price?: string | number;\n monthly_price?: number;\n agent_id?: string | null;\n assigned_agent_id?: string | null;\n created_at?: string;\n /** Carrier inbound-webhook provisioning state (set once an agent is attached). */\n webhook_status?: 'configured' | 'manual_required' | 'failed' | null;\n webhook_url?: string | null;\n webhook_error?: string | null;\n last_inbound_at?: string | null;\n}\n\n/** Outcome of carrier inbound-webhook auto-provisioning. */\nexport interface WebhookProvisionResult {\n status: 'configured' | 'manual_required' | 'failed' | 'no_carrier';\n provider: string | null;\n webhookUrl: string | null;\n verified: boolean;\n error?: string;\n}\n\nexport class NumbersResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all phone numbers assigned to your Rymi account.\n */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<{ numbers: NumberRecord[]; total: number; offset: number; limit: number }> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n const query = searchParams.toString();\n return this.client.get(`/numbers${query ? `?${query}` : ''}`);\n }\n\n public async register(number: string, params: { agent_id?: string } = {}): Promise<{ status: 'registered'; number: string; agent_id: string | null; webhook: WebhookProvisionResult | null }> {\n return this.client.post('/numbers', { number, ...params });\n }\n\n public async attach(number: string, agentId: string): Promise<{ status: 'attached'; agent_id: string; number: string; webhook: WebhookProvisionResult | null }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/attach`, { agent_id: agentId });\n }\n\n /** Clear the agent association without deregistering the number. */\n public async detach(number: string): Promise<{ status: 'detached'; number: string }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/detach`);\n }\n\n /** Re-run carrier inbound-webhook auto-provisioning for a number. */\n public async provisionWebhook(number: string): Promise<{ number: string; webhook: WebhookProvisionResult }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/webhook`);\n }\n\n public async remove(number: string): Promise<{ status: 'removed'; number: string }> {\n return this.client.delete(`/numbers/${encodeURIComponent(number)}`);\n }\n}\n","import * as crypto from 'crypto';\nimport { RymiClient } from '../client';\n\nexport interface WebhookRecord {\n id: string;\n url: string;\n events: string[];\n alert_email?: string | null;\n created_at?: string;\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\nexport class WebhooksResource {\n constructor(private client: RymiClient) {}\n\n /** List registered webhook endpoints. The signing secret is never returned. */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<{ webhooks: WebhookRecord[]; total: number; offset: number; limit: number }> {\n return this.client.get(`/webhooks${buildQuery(params)}`);\n }\n\n /** Register a webhook. `url` must be public https. `secret` must be 16–256 chars. */\n public async create(data: { url: string; events: string[]; secret: string; alert_email?: string }): Promise<{ status: 'registered' }> {\n return this.client.post('/webhooks', data);\n }\n\n /** Update a webhook. Only provided fields change. Pass `secret` to rotate it. */\n public async update(id: string, data: { url?: string; events?: string[]; secret?: string; alert_email?: string | null }): Promise<{ status: 'updated'; id: string }> {\n return this.client.patch(`/webhooks/${id}`, data);\n }\n\n /** Delete a webhook endpoint. */\n public async delete(id: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/webhooks/${id}`);\n }\n /**\n * Verifies that a webhook received by your backend was genuinely dispatched by Rymi.\n * \n * Rymi endpoints secure webhooks by computing an HMAC-SHA256 signature\n * of the raw JSON body concatenated with the timestamp, using your Webhook Secret.\n * \n * @param payload The raw stringified JSON body of the webhook hook request.\n * @param signatureHeader The value of the `X-Rymi-Signature` header from the request.\n * @param timestampHeader The value of the `X-Rymi-Timestamp` header from the request.\n * @param webhookSecret Your project's unique Webhook Signing Secret (starts with `whsec_`)\n * @param toleranceMillis Allowed time difference in milliseconds to prevent replay attacks (default 5 mins)\n * \n * @throws {Error} if the signature is invalid or if the timestamp exceeds the tolerance.\n */\n public verifySignature(\n payload: string,\n signatureHeader: string,\n timestampHeader: string,\n webhookSecret: string,\n toleranceMillis = 300000 // 5 minutes\n ): boolean {\n // 1. Check for Replay Attacks\n const timestamp = parseInt(timestampHeader, 10);\n if (isNaN(timestamp)) {\n throw new Error('Invalid Rymi-Timestamp header');\n }\n\n const now = Date.now();\n if (now - timestamp > toleranceMillis) {\n throw new Error('Webhook timestamp is too old. Possible replay attack.');\n }\n\n // 2. Prepare the verification string\n const signaturePayload = `${timestamp}.${payload}`;\n\n // 3. Compute the expected HMAC using the developer's Webhook Secret\n const expectedSignature = crypto\n .createHmac('sha256', webhookSecret)\n .update(signaturePayload, 'utf8')\n .digest('hex');\n\n // 4. Secure string comparison (constant-time to prevent timing attacks)\n try {\n const isValid = crypto.timingSafeEqual(\n Buffer.from(signatureHeader),\n Buffer.from(expectedSignature)\n );\n\n if (!isValid) {\n throw new Error('Invalid Webhook Signature. The secret might be incorrect.');\n }\n\n return true;\n } catch (err) {\n throw new Error('Invalid Webhook Signature. The secret might be incorrect.');\n }\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface PublishableKeyRecord {\n id: string;\n key_prefix: string;\n agent_id: string;\n label: string;\n allowed_channels: Array<'web' | 'phone'>;\n audience: 'sdk' | 'landing_demo';\n default_from_number: string | null;\n created_at: string;\n}\n\nexport interface CreatePublishableKeyParams {\n agent_id: string;\n label: string;\n allowed_channels?: Array<'web' | 'phone'>;\n audience?: 'sdk' | 'landing_demo';\n default_from_number?: string | null;\n}\n\nexport class KeysResource {\n constructor(private client: RymiClient) {}\n\n public async listPublishable(): Promise<{ keys: PublishableKeyRecord[] }> {\n return this.client.get('/keys/publishable');\n }\n\n public async createPublishable(data: CreatePublishableKeyParams): Promise<CreatePublishableKeyParams & { key: string }> {\n return this.client.post('/keys/publishable', data);\n }\n\n public async revokePublishable(id: string): Promise<{ success: true }> {\n return this.client.delete(`/keys/publishable/${id}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport type TelephonyProvider = 'plivo' | 'twilio' | 'vonage' | 'telnyx';\n\nexport interface ConnectTelephonyParams {\n provider: TelephonyProvider;\n auth_id?: string;\n auth_token?: string;\n api_key?: string;\n api_secret?: string;\n signature_secret?: string;\n /** Telnyx Ed25519 webhook signing secret (optional). */\n auth_secret?: string;\n}\n\nexport class TelephonyResource {\n constructor(private client: RymiClient) {}\n\n public async connect(data: ConnectTelephonyParams): Promise<{ status: 'connected'; provider: TelephonyProvider; account_name: string; message: string }> {\n return this.client.post('/telephony/connect', data);\n }\n\n public async disconnect(): Promise<{ status: 'disconnected'; message: string }> {\n return this.client.post('/telephony/disconnect');\n }\n\n public async status(): Promise<{ connected: boolean; provider: TelephonyProvider | null; account_name: string | null; account_country: string | null }> {\n return this.client.get('/telephony/status');\n }\n\n public async numbers(): Promise<{ numbers: any[] }> {\n return this.client.get('/telephony/numbers');\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface UsageSummary {\n voice_runtime: {\n remaining_minutes: number;\n status: string;\n };\n studio_ai?: {\n used_units?: number;\n included_units?: number | null;\n quota_percent?: number;\n status?: string;\n overage_enabled?: boolean;\n };\n post_call_intelligence?: {\n status?: string;\n used_units?: number;\n };\n}\n\nexport class BillingResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Lane-aware usage summary: remaining voice-runtime minutes, Studio AI unit\n * usage, and post-call intelligence usage. Voice balance is reported in\n * MINUTES (the customer-facing unit), not dollars.\n */\n public async usageSummary(): Promise<UsageSummary> {\n return this.client.get<UsageSummary>('/billing/usage-summary');\n }\n\n /** Estimate the cost of a call for a custom model stack and duration. */\n public async estimate(data: { stt_model?: string; llm_model?: string; tts_model?: string; duration_seconds?: number } = {}): Promise<Record<string, any>> {\n return this.client.post('/billing/estimate', data);\n }\n\n /** Configure auto-recharge. Server rejects (400) if enabled && pack_usd <= threshold_usd. */\n public async setAutoRecharge(data: { enabled?: boolean; pack_usd?: number; threshold_usd?: number }): Promise<{ ok: true }> {\n return this.client.put('/billing/auto-recharge', data);\n }\n\n /** Configure spend-alert preferences. */\n public async setAlerts(data: { thresholds_usd?: number[]; low_balance_pct?: number; email_enabled?: boolean }): Promise<{ ok: true }> {\n return this.client.put('/billing/alerts', data);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface AgentTemplateSummary {\n id?: string;\n slug?: string;\n label?: string;\n description?: string;\n icon?: string;\n color?: string;\n defaults?: Record<string, any>;\n [key: string]: any;\n}\n\nexport class TemplatesResource {\n constructor(private client: RymiClient) {}\n\n /**\n * List published agent templates available to the current tenant. Use a\n * template's `defaults` as the starting config for create_agent.\n */\n public async list(): Promise<{ templates: AgentTemplateSummary[]; source?: string }> {\n return this.client.get('/agent-templates');\n }\n}\n","import { RymiClient } from '../client';\nimport type {\n Campaign,\n CampaignStatus,\n CampaignType,\n CampaignMember,\n CampaignAttempt,\n CampaignReport,\n CampaignGoal,\n CampaignCompliancePolicy\n} from '@rymi/sdk-types';\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\n// ─── list/create/update params + responses ─────────────────────────────────\n\nexport interface ListCampaignsParams {\n limit?: number;\n offset?: number;\n status?: CampaignStatus;\n type?: CampaignType;\n agent_id?: string;\n}\n\nexport interface CampaignListResponse {\n campaigns: Campaign[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateCampaignParams {\n agent_id: string;\n type: CampaignType;\n name: string;\n goal?: CampaignGoal;\n schedule_policy?: Record<string, unknown>;\n retry_policy?: Record<string, unknown>;\n concurrency_policy?: Record<string, unknown>;\n automation_policy?: Record<string, unknown>;\n reporting_policy?: Record<string, unknown>;\n compliance_policy?: CampaignCompliancePolicy;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateCampaignParams {\n name?: string;\n goal?: CampaignGoal;\n schedule_policy?: Record<string, unknown>;\n retry_policy?: Record<string, unknown>;\n concurrency_policy?: Record<string, unknown>;\n automation_policy?: Record<string, unknown>;\n reporting_policy?: Record<string, unknown>;\n compliance_policy?: CampaignCompliancePolicy;\n post_call_config_override?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface LaunchBlocker {\n code: string;\n ok: boolean;\n detail?: string;\n}\n\nexport interface LaunchCampaignResponse {\n campaign: Campaign;\n blockers: LaunchBlocker[];\n}\n\n/**\n * GET /campaigns/:id/report response. Extends the shared CampaignReport with\n * the report-endpoint-only derived fields (top failure reasons + cost per\n * success) that the API adds on top of the persisted shape.\n */\nexport interface CampaignReportResponse extends CampaignReport {\n distributions: CampaignReport['distributions'] & {\n top_failure_reasons: Array<{ reason: string; count: number }>;\n cost_per_success_credits: number;\n };\n}\n\n// ─── members ────────────────────────────────────────────────────────────────\n\nexport interface ListCampaignMembersParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignMemberListResponse {\n members: CampaignMember[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface AddCampaignMembersParams {\n contact_ids: string[];\n variables_override?: Record<string, string>;\n}\n\nexport interface ImportCampaignMembersParams {\n contacts?: Array<Record<string, unknown>>;\n csv?: string;\n}\n\nexport interface ImportCampaignMembersResponse {\n created: number;\n merged: number;\n /** Members attached to the campaign in this import. */\n attached: number;\n invalid: Array<{ row: number; reason: string }>;\n}\n\nexport interface UpdateCampaignMemberParams {\n status?: string;\n variables_override?: Record<string, string>;\n next_attempt_at?: string;\n}\n\nclass CampaignMembersResource {\n constructor(private client: RymiClient) {}\n\n /** List a campaign's members, paginated. */\n public async list(campaignId: string, params: ListCampaignMembersParams = {}): Promise<CampaignMemberListResponse> {\n return this.client.get(`/campaigns/${campaignId}/members${buildQuery(params)}`);\n }\n\n /** Attach existing contacts to a campaign as members. */\n public async add(campaignId: string, data: AddCampaignMembersParams): Promise<{ members: CampaignMember[] }> {\n return this.client.post(`/campaigns/${campaignId}/members`, data);\n }\n\n /** Import inline contact rows (JSON or CSV): creates/merges contacts and attaches members in one call. */\n public async import(campaignId: string, data: ImportCampaignMembersParams): Promise<ImportCampaignMembersResponse> {\n return this.client.post(`/campaigns/${campaignId}/members/import`, data);\n }\n\n /** Update a campaign member (status, variables, next attempt time). */\n public async update(campaignId: string, memberId: string, data: UpdateCampaignMemberParams): Promise<{ member: CampaignMember }> {\n return this.client.patch(`/campaigns/${campaignId}/members/${memberId}`, data);\n }\n\n /** Remove a member from a campaign. */\n public async remove(campaignId: string, memberId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/campaigns/${campaignId}/members/${memberId}`);\n }\n}\n\n// ─── inbound routes ─────────────────────────────────────────────────────────\n\nexport interface CampaignRoute {\n id: string;\n tenant_id: string;\n campaign_id: string;\n phone_number: string;\n schedule: Record<string, unknown>;\n active: boolean;\n created_at: string;\n updated_at: string;\n}\n\nexport interface ListCampaignRoutesParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface CampaignRouteListResponse {\n routes: CampaignRoute[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateCampaignRouteParams {\n phone_number: string;\n schedule?: Record<string, unknown>;\n active?: boolean;\n}\n\nexport interface UpdateCampaignRouteParams {\n schedule?: Record<string, unknown>;\n active?: boolean;\n}\n\nclass CampaignRoutesResource {\n constructor(private client: RymiClient) {}\n\n /** List a campaign's inbound routing rules. */\n public async list(campaignId: string, params: ListCampaignRoutesParams = {}): Promise<CampaignRouteListResponse> {\n return this.client.get(`/campaigns/${campaignId}/routes${buildQuery(params)}`);\n }\n\n /** Bind an owned phone number to this campaign for inbound routing. Only one active route per number is allowed. */\n public async create(campaignId: string, data: CreateCampaignRouteParams): Promise<{ route: CampaignRoute }> {\n return this.client.post(`/campaigns/${campaignId}/routes`, data);\n }\n\n /** Update an inbound route's schedule or active flag. */\n public async update(campaignId: string, routeId: string, data: UpdateCampaignRouteParams): Promise<{ route: CampaignRoute }> {\n return this.client.patch(`/campaigns/${campaignId}/routes/${routeId}`, data);\n }\n\n /** Delete an inbound route. */\n public async delete(campaignId: string, routeId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/campaigns/${campaignId}/routes/${routeId}`);\n }\n}\n\n// ─── attempts / batches / followups (read-only) ────────────────────────────\n\nexport interface ListCampaignAttemptsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignAttemptListResponse {\n attempts: CampaignAttempt[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface ListCampaignBatchesParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface CampaignBatch {\n id: string;\n tenant_id: string;\n campaign_id: string;\n batch_key: string;\n status: string;\n selected_count: number;\n queued_count: number;\n completed_count: number;\n failed_count: number;\n started_at?: string | null;\n completed_at?: string | null;\n created_at: string;\n}\n\nexport interface CampaignBatchListResponse {\n batches: CampaignBatch[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface ListCampaignFollowupsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignFollowupJob {\n id: string;\n tenant_id: string;\n campaign_id: string;\n campaign_attempt_id?: string | null;\n campaign_member_id?: string | null;\n kind: string;\n status: string;\n scheduled_at: string;\n consent_checked: boolean;\n capability_checked: boolean;\n idempotency_key: string;\n payload: Record<string, unknown>;\n result?: Record<string, unknown> | null;\n created_at: string;\n updated_at: string;\n}\n\nexport interface CampaignFollowupListResponse {\n followups: CampaignFollowupJob[];\n total: number;\n offset: number;\n limit: number;\n}\n\n// ─── improve / suggestions ──────────────────────────────────────────────────\n\nexport interface CampaignSuggestion {\n id: string;\n tenant_id: string;\n campaign_id: string;\n category: string;\n evidence: Record<string, unknown>;\n proposal: Record<string, unknown>;\n status: 'proposed' | 'accepted' | 'dismissed';\n created_by_model?: string | null;\n created_at: string;\n updated_at: string;\n}\n\nexport interface ImproveCampaignResponse {\n suggestions: CampaignSuggestion[];\n}\n\nexport interface ListCampaignSuggestionsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignSuggestionListResponse {\n suggestions: CampaignSuggestion[];\n total: number;\n offset: number;\n limit: number;\n}\n\n// ─── CampaignIntakeResource ──────────────────────────────────────────────────\n\n/** A campaign's lead-intake URL settings. The URL itself is only returned on create/rotate. */\nexport interface CampaignIntake {\n enabled: true;\n assume_voice_consent: boolean;\n default_country: string | null;\n created_at: string;\n rotated_at: string;\n last_used_at: string | null;\n}\n\nexport interface CampaignIntakeSettings {\n /** Treat every lead posted to the URL as having voice consent (e.g. a subscribe form with a consent line). */\n assume_voice_consent?: boolean;\n /** ISO-3166 alpha-2 (e.g. \"IN\") used for numbers posted without a +country code. */\n default_country?: string | null;\n}\n\nclass CampaignIntakeResource {\n constructor(private client: RymiClient) {}\n\n /** Get the campaign's lead-intake settings, or `intake: null` if it has none. */\n public async get(campaignId: string): Promise<{ intake: CampaignIntake | null }> {\n return this.client.get(`/campaigns/${campaignId}/intake`);\n }\n\n /** Create the lead-intake URL (returned once as `url`), or update its settings (`url: null`). */\n public async set(campaignId: string, settings: CampaignIntakeSettings = {}): Promise<{ intake: CampaignIntake; url: string | null }> {\n return this.client.put(`/campaigns/${campaignId}/intake`, settings);\n }\n\n /** Issue a new URL. The old one stops accepting leads immediately. */\n public async rotate(campaignId: string): Promise<{ intake: CampaignIntake; url: string }> {\n return this.client.post(`/campaigns/${campaignId}/intake/rotate`, {});\n }\n\n /** Remove the lead-intake URL. */\n public async disable(campaignId: string): Promise<void> {\n return this.client.delete(`/campaigns/${campaignId}/intake`);\n }\n}\n\n// ─── CampaignsResource ───────────────────────────────────────────────────────\n\nexport class CampaignsResource {\n public members: CampaignMembersResource;\n public routes: CampaignRoutesResource;\n public intake: CampaignIntakeResource;\n\n constructor(private client: RymiClient) {\n this.members = new CampaignMembersResource(client);\n this.routes = new CampaignRoutesResource(client);\n this.intake = new CampaignIntakeResource(client);\n }\n\n /** List campaigns for the authenticated tenant, paginated. */\n public async list(params: ListCampaignsParams = {}): Promise<CampaignListResponse> {\n return this.client.get(`/campaigns${buildQuery(params)}`);\n }\n\n /** Create a new campaign in draft status against a published agent. */\n public async create(data: CreateCampaignParams): Promise<{ campaign: Campaign }> {\n return this.client.post('/campaigns', data);\n }\n\n /** Retrieve a single campaign by id. */\n public async get(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.get(`/campaigns/${campaignId}`);\n }\n\n /** Update campaign policy/goal fields. Status and lifecycle fields are not writable here. */\n public async update(campaignId: string, data: UpdateCampaignParams): Promise<{ campaign: Campaign }> {\n return this.client.patch(`/campaigns/${campaignId}`, data);\n }\n\n /**\n * Launch a campaign: validates launch blockers, then stamps\n * `launched_at` + `agent_snapshot_id`, flips members to `ready`, and\n * transitions status to `running`.\n */\n public async launch(campaignId: string): Promise<LaunchCampaignResponse> {\n return this.client.post(`/campaigns/${campaignId}/launch`);\n }\n\n /** Evaluate launch blockers without launching (dry run). Safe from any status. */\n public async launchBlockers(campaignId: string): Promise<{ blockers: LaunchBlocker[]; launchable: boolean }> {\n return this.client.get(`/campaigns/${campaignId}/launch-blockers`);\n }\n\n /** Pause a running campaign. In-flight calls finish naturally. */\n public async pause(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/pause`);\n }\n\n /** Resume a paused campaign. */\n public async resume(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/resume`);\n }\n\n /** Archive a campaign. Terminal — the scheduler never selects work for it again. */\n public async archive(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/archive`);\n }\n\n /** Read the campaign report: `stat_*` summary counters + outcome/sentiment/hourly/snapshot distributions. */\n public async report(campaignId: string): Promise<CampaignReportResponse> {\n return this.client.get(`/campaigns/${campaignId}/report`);\n }\n\n /** List a campaign's dial attempts, paginated. */\n public async attempts(campaignId: string, params: ListCampaignAttemptsParams = {}): Promise<CampaignAttemptListResponse> {\n return this.client.get(`/campaigns/${campaignId}/attempts${buildQuery(params)}`);\n }\n\n /** List a campaign's sweep-claim batches, paginated. */\n public async batches(campaignId: string, params: ListCampaignBatchesParams = {}): Promise<CampaignBatchListResponse> {\n return this.client.get(`/campaigns/${campaignId}/batches${buildQuery(params)}`);\n }\n\n /** List a campaign's follow-up jobs, paginated. */\n public async followups(campaignId: string, params: ListCampaignFollowupsParams = {}): Promise<CampaignFollowupListResponse> {\n return this.client.get(`/campaigns/${campaignId}/followups${buildQuery(params)}`);\n }\n\n /** Run the improve engine: detectors gate an LLM proposal writer, persisting new `campaign_suggestions`. */\n public async improve(campaignId: string): Promise<ImproveCampaignResponse> {\n return this.client.post(`/campaigns/${campaignId}/improve`);\n }\n\n /** List a campaign's improvement suggestions, paginated. */\n public async suggestions(campaignId: string, params: ListCampaignSuggestionsParams = {}): Promise<CampaignSuggestionListResponse> {\n return this.client.get(`/campaigns/${campaignId}/suggestions${buildQuery(params)}`);\n }\n\n /** Accept a suggestion: agent-editing suggestions create an agent-changes draft; campaign-policy suggestions patch the campaign. */\n public async acceptSuggestion(campaignId: string, suggestionId: string): Promise<{ suggestion: CampaignSuggestion }> {\n return this.client.post(`/campaigns/${campaignId}/suggestions/${suggestionId}/accept`);\n }\n\n /** Dismiss a suggestion without applying it. */\n public async dismissSuggestion(campaignId: string, suggestionId: string): Promise<{ suggestion: CampaignSuggestion }> {\n return this.client.post(`/campaigns/${campaignId}/suggestions/${suggestionId}/dismiss`);\n }\n}\n","import { RymiClient } from '../client';\nimport type { Contact } from '@rymi/sdk-types';\n\nexport interface ListContactsParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface ContactListResponse {\n contacts: Contact[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateContactParams {\n phone?: string;\n email?: string;\n name?: string;\n timezone?: string;\n language?: string;\n tags?: string[];\n custom_fields?: Record<string, unknown>;\n consent?: Record<string, boolean>;\n source?: string;\n}\n\nexport interface CreateContactResponse {\n contact: Contact;\n deduped: boolean;\n}\n\nexport interface UpdateContactParams {\n phone?: string;\n email?: string | null;\n name?: string | null;\n timezone?: string | null;\n language?: string | null;\n tags?: string[];\n custom_fields?: Record<string, unknown>;\n consent?: Record<string, boolean>;\n source?: string | null;\n}\n\nexport interface ImportContactsParams {\n contacts?: Array<Record<string, unknown>>;\n csv?: string;\n}\n\nexport interface ImportContactsResponse {\n created: number;\n merged: number;\n invalid: Array<{ row: number; reason: string }>;\n}\n\nexport interface SetConsentParams {\n channel: 'voice' | 'sms' | 'whatsapp' | 'telegram';\n granted: boolean;\n source?: string;\n method?: string;\n}\n\nexport interface SetConsentResponse {\n contact_id: string;\n channel: string;\n consent: { granted: boolean; at: string; source: string; method: string };\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\nexport class ContactsResource {\n constructor(private client: RymiClient) {}\n\n /** List tenant-level contacts, paginated. */\n public async list(params: ListContactsParams = {}): Promise<ContactListResponse> {\n return this.client.get(`/contacts${buildQuery(params)}`);\n }\n\n /**\n * Create a tenant-level contact. If a contact with the same\n * (tenant, phone) already exists, the existing row is returned instead\n * of creating a duplicate — check `deduped` in the response.\n */\n public async create(data: CreateContactParams): Promise<CreateContactResponse> {\n return this.client.post('/contacts', data);\n }\n\n /** Retrieve a single tenant-scoped contact by id. */\n public async get(contactId: string): Promise<{ contact: Contact }> {\n return this.client.get(`/contacts/${contactId}`);\n }\n\n /** Update an existing tenant-scoped contact. Only provided fields change. */\n public async update(contactId: string, data: UpdateContactParams): Promise<{ contact: Contact }> {\n return this.client.patch(`/contacts/${contactId}`, data);\n }\n\n /** Delete a tenant-scoped contact. */\n public async delete(contactId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/contacts/${contactId}`);\n }\n\n /**\n * Bulk import contacts from JSON rows or CSV text. Each row's phone is\n * normalized to E.164 and upserted on (tenant_id, phone); rows with\n * unparseable phones are skipped and reported in `invalid`.\n */\n public async import(data: ImportContactsParams): Promise<ImportContactsResponse> {\n return this.client.post('/contacts/import', data);\n }\n\n /** Record a consent grant or revoke for one channel, with evidence. Also\n * appends an immutable row to the consent_events proof log. */\n public async setConsent(contactId: string, data: SetConsentParams): Promise<SetConsentResponse> {\n return this.client.patch(`/contacts/${contactId}/consent`, data);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface AttestParams {\n kind: 'dnc_external_scrub' | 'ai_disclosure';\n note?: string;\n}\n\nexport interface Attestation {\n id: string;\n tenant_id: string;\n kind: string;\n attested_by: string | null;\n note: string | null;\n created_at: string;\n}\n\nexport interface AttestResponse {\n attestation: Attestation;\n}\n\nexport interface ListAttestationsResponse {\n attestations: Attestation[];\n}\n\nexport class ComplianceResource {\n constructor(private client: RymiClient) {}\n\n /** Record a compliance attestation (append-only). Campaign launch blockers\n * in `attested` mode read the most recent one of the matching `kind`. */\n public async attest(data: AttestParams): Promise<AttestResponse> {\n return this.client.post('/compliance/attestations', data);\n }\n\n /** List the tenant's 50 most recent compliance attestations, newest first. */\n public async listAttestations(): Promise<ListAttestationsResponse> {\n return this.client.get('/compliance/attestations');\n }\n}\n","import { RymiClient } from '../client';\n\n/** A stored API-tool secret. Values are write-only — never returned. */\nexport interface ToolSecretRecord {\n name: string;\n /** The only host this secret is ever sent to. */\n host: string | null;\n}\n\n/**\n * Tenant secrets referenced from call_webhook headers as `{{secrets.NAME}}`.\n * Each secret is pinned to one host and only interpolated into requests to it.\n */\nexport class ToolSecretsResource {\n constructor(private client: RymiClient) {}\n\n public async list(): Promise<{ data: ToolSecretRecord[] }> {\n return this.client.get('/tool-secrets');\n }\n\n /** Create or replace. `name` is UPPER_SNAKE_CASE; `host` is a public hostname. */\n public async set(name: string, data: { value: string; host: string }): Promise<{ data: { name: string } }> {\n return this.client.put(`/tool-secrets/${encodeURIComponent(name)}`, data);\n }\n\n public async delete(name: string): Promise<{ data: { name: string } }> {\n return this.client.delete(`/tool-secrets/${encodeURIComponent(name)}`);\n }\n}\n","// packages/node/src/resources/workspaces.ts\nimport { RymiClient } from '../client';\n\nexport interface Workspace {\n id: string;\n name: string;\n role: 'owner' | 'admin' | 'client';\n parent_id: string | null;\n operating_country: string | null;\n current?: boolean;\n}\n\nexport interface CreateWorkspaceParams {\n name: string;\n /** ISO-3166 alpha-2, e.g. \"IN\". */\n operating_country?: string | null;\n}\n\nexport class WorkspacesResource {\n constructor(private client: RymiClient) {}\n\n public async list(): Promise<{ workspaces: Workspace[] }> {\n return this.client.get('/workspaces');\n }\n\n public async create(data: CreateWorkspaceParams): Promise<{ workspace: Workspace }> {\n return this.client.post('/workspaces', data);\n }\n\n public async update(id: string, data: { name?: string; operating_country?: string | null }): Promise<{ ok: true }> {\n return this.client.patch(`/workspaces/${encodeURIComponent(id)}`, data);\n }\n}\n"],"mappings":"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","names":["buildQuery","buildQuery","buildQuery","buildQuery"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/resources/agents.ts","../src/resources/calls.ts","../src/resources/dnc.ts","../src/resources/numbers.ts","../src/resources/webhooks.ts","../src/resources/keys.ts","../src/resources/telephony.ts","../src/resources/billing.ts","../src/resources/templates.ts","../src/resources/campaigns.ts","../src/resources/contacts.ts","../src/resources/compliance.ts","../src/resources/toolSecrets.ts","../src/resources/workspaces.ts"],"sourcesContent":["import { RymiClient, ClientOptions, RymiError } from './client';\nimport { AgentsResource } from './resources/agents';\nimport { CallsResource } from './resources/calls';\nimport { DncResource } from './resources/dnc';\nimport { NumbersResource } from './resources/numbers';\nimport { WebhooksResource } from './resources/webhooks';\nimport { KeysResource } from './resources/keys';\nimport { TelephonyResource } from './resources/telephony';\nimport { BillingResource } from './resources/billing';\nimport { TemplatesResource } from './resources/templates';\nimport { CampaignsResource } from './resources/campaigns';\nimport { ContactsResource } from './resources/contacts';\nimport { ComplianceResource } from './resources/compliance';\nimport { ToolSecretsResource } from './resources/toolSecrets';\nimport { WorkspacesResource } from './resources/workspaces';\n\nexport class Rymi {\n private client: RymiClient;\n\n public agents: AgentsResource;\n public calls: CallsResource;\n public dnc: DncResource;\n public numbers: NumbersResource;\n public webhooks: WebhooksResource;\n public keys: KeysResource;\n public telephony: TelephonyResource;\n public billing: BillingResource;\n public templates: TemplatesResource;\n public campaigns: CampaignsResource;\n public contacts: ContactsResource;\n public compliance: ComplianceResource;\n public toolSecrets: ToolSecretsResource;\n public workspaces: WorkspacesResource;\n\n constructor(options?: ClientOptions) {\n this.client = new RymiClient(options);\n\n // Initialize API Sub-modules\n this.agents = new AgentsResource(this.client);\n this.calls = new CallsResource(this.client);\n this.dnc = new DncResource(this.client);\n this.numbers = new NumbersResource(this.client);\n this.webhooks = new WebhooksResource(this.client);\n this.keys = new KeysResource(this.client);\n this.telephony = new TelephonyResource(this.client);\n this.billing = new BillingResource(this.client);\n this.templates = new TemplatesResource(this.client);\n this.campaigns = new CampaignsResource(this.client);\n this.contacts = new ContactsResource(this.client);\n this.compliance = new ComplianceResource(this.client);\n this.toolSecrets = new ToolSecretsResource(this.client);\n this.workspaces = new WorkspacesResource(this.client);\n }\n}\n\n// Re-export common types\nexport * from './client';\nexport * from './resources/agents';\nexport * from './resources/calls';\nexport * from './resources/dnc';\nexport * from './resources/numbers';\nexport * from './resources/webhooks';\nexport * from './resources/keys';\nexport * from './resources/telephony';\nexport * from './resources/billing';\nexport * from './resources/templates';\nexport * from './resources/campaigns';\nexport * from './resources/contacts';\nexport * from './resources/compliance';\nexport * from './resources/toolSecrets';\nexport * from './resources/workspaces';\n\n// Re-export the curated public type surface (see @rymi/sdk-types).\nexport * from '@rymi/sdk-types';\nexport default Rymi;\n","export interface ClientOptions {\n /**\n * The Rymi secret API key (`rymi_...`)\n */\n apiKey?: string;\n \n /**\n * The base URL for the API. Defaults to `https://api.rymi.live/v1`\n */\n baseURL?: string;\n\n /**\n * Custom fetch implementation. Lets embedders route requests without a\n * network socket (e.g. Fastify app.inject). Defaults to global fetch.\n */\n fetch?: typeof globalThis.fetch;\n\n /**\n * Act in this workspace (sent as `Rymi-Workspace`). Defaults to the\n * `RYMI_WORKSPACE` environment variable, else the key's own workspace.\n */\n workspace?: string;\n}\n\nexport class RymiError extends Error {\n public status?: number;\n public code?: string;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.name = 'RymiError';\n this.status = status;\n this.code = code;\n }\n}\n\nexport class RymiClient {\n private apiKey: string;\n private baseURL: string;\n private fetchImpl: typeof globalThis.fetch;\n private workspace?: string;\n\n constructor(options?: ClientOptions) {\n // Prefer explicit option, then fallback to environment variable\n const key = options?.apiKey || (typeof process !== 'undefined' ? process.env.RYMI_API_KEY : undefined);\n\n if (!key) {\n throw new Error('The Rymi API Key must be set either by passing `apiKey` to the client or setting the `RYMI_API_KEY` environment variable.');\n }\n\n this.apiKey = key;\n this.baseURL = options?.baseURL || 'https://api.rymi.live/v1';\n this.fetchImpl = options?.fetch ?? globalThis.fetch;\n\n // Remove trailing slashes\n if (this.baseURL.endsWith('/')) {\n this.baseURL = this.baseURL.slice(0, -1);\n }\n\n this.workspace = options?.workspace\n || (typeof process !== 'undefined' ? process.env.RYMI_WORKSPACE : undefined)\n || undefined;\n }\n\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\n const url = `${this.baseURL}${path.startsWith('/') ? path : `/${path}`}`;\n \n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Accept': 'application/json',\n 'User-Agent': 'rymi-node/1.0.0'\n };\n if (this.workspace) headers['Rymi-Workspace'] = this.workspace;\n\n const init: RequestInit = {\n method,\n headers\n };\n\n if (body) {\n headers['Content-Type'] = 'application/json';\n init.body = JSON.stringify(body);\n }\n\n try {\n const response = await this.fetchImpl(url, init);\n const isJson = response.headers.get('content-type')?.includes('application/json');\n \n const data = isJson ? await response.json() : await response.text();\n\n if (!response.ok) {\n const message = (data && typeof data === 'object' && 'error' in data) ? (data as any).error : \n (typeof data === 'string' ? data : response.statusText);\n throw new RymiError(message, response.status, (data && typeof data === 'object' && 'code' in data) ? (data as any).code : undefined);\n }\n\n return data as T;\n } catch (error) {\n if (error instanceof RymiError) {\n throw error;\n }\n throw new RymiError(`Network Error: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n public get<T>(path: string): Promise<T> {\n return this.request<T>('GET', path);\n }\n\n public post<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('POST', path, body);\n }\n\n public put<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('PUT', path, body);\n }\n\n public patch<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('PATCH', path, body);\n }\n\n public delete<T>(path: string): Promise<T> {\n return this.request<T>('DELETE', path);\n }\n}\n","import { RymiClient } from '../client';\nimport { Agent, AgentToolBinding } from '@rymi/sdk-types';\n\nexport interface CreateAgentParams {\n name: string;\n /** @deprecated Use system_prompt. This alias is mapped before the request is sent. */\n prompt?: string;\n system_prompt?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n llm_provider?: 'gemini' | 'openai' | 'anthropic' | 'sarvam';\n llm_model?: string;\n llm_fallback_provider?: string | null;\n llm_fallback_model?: string | null;\n stt_provider?: string;\n stt_model?: string;\n stt_fallback_provider?: string | null;\n stt_fallback_model?: string | null;\n tts_provider?: string;\n tts_model?: string;\n tts_fallback_provider?: string | null;\n tts_fallback_model?: string | null;\n /** Self-hosted endpoint URLs (https:// or wss://). Enterprise only. */\n custom_llm_url?: string | null;\n custom_voice_url?: string | null;\n custom_voice_mode?: 'rymi' | 'openai-compat';\n custom_transcriber_url?: string | null;\n language?: string | null;\n /** All BCP-47 languages the agent should handle, e.g. [\"hi-IN\",\"en-US\"] for a bilingual agent. */\n supported_languages?: string[];\n provider_config?: any;\n tools?: AgentToolBinding[];\n}\n\nexport interface UpdateAgentParams {\n name?: string;\n /** @deprecated Use system_prompt. This alias is mapped before the request is sent. */\n prompt?: string;\n system_prompt?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n llm_provider?: 'gemini' | 'openai' | 'anthropic' | 'sarvam';\n llm_model?: string;\n llm_fallback_provider?: string | null;\n llm_fallback_model?: string | null;\n stt_provider?: string;\n stt_model?: string;\n stt_fallback_provider?: string | null;\n stt_fallback_model?: string | null;\n tts_provider?: string;\n tts_model?: string;\n tts_fallback_provider?: string | null;\n tts_fallback_model?: string | null;\n /** Self-hosted endpoint URLs (https:// or wss://). Enterprise only. */\n custom_llm_url?: string | null;\n custom_voice_url?: string | null;\n custom_voice_mode?: 'rymi' | 'openai-compat';\n custom_transcriber_url?: string | null;\n language?: string | null;\n /** All BCP-47 languages the agent should handle, e.g. [\"hi-IN\",\"en-US\"] for a bilingual agent. */\n supported_languages?: string[];\n chat_summary?: string | null;\n provider_config?: any;\n /** Replaces the whole bindings array — build it from a fresh retrieve(). */\n tools?: AgentToolBinding[];\n}\n\nexport interface AgentListResponse {\n agents: Agent[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface AgentCallListResponse {\n calls: any[];\n total: number;\n offset: number;\n limit: number;\n agent_id: string;\n}\n\nexport interface ValidatePublishParams {\n agent_id?: string;\n name?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n [key: string]: any;\n}\n\nexport interface PublishValidationIssue {\n severity?: string;\n section?: string;\n title?: string;\n detail?: string;\n [key: string]: any;\n}\n\nexport interface PublishAgentResponse {\n published: boolean;\n agent_id?: string;\n /** Present when published — the frozen snapshot id and timestamp. */\n snapshot_id?: string | null;\n published_at?: string | null;\n /** Present when published: false because of unresolved blockers. */\n reason?: string;\n blockers?: PublishValidationIssue[];\n warnings?: PublishValidationIssue[];\n error?: string;\n details?: string;\n}\n\nexport interface ChangeEntry {\n key: string;\n value: any;\n}\n\nexport interface ApplyChangesParams {\n currentConfig: Record<string, any>;\n changes: ChangeEntry[];\n mode: 'create' | 'edit';\n lenient?: boolean;\n}\n\nexport interface ApplyChangesResponse {\n valid: true;\n config: Record<string, any>;\n applied: ChangeEntry[];\n}\n\nexport interface EnrichCompanyParams {\n companyName: string;\n websiteUrl: string;\n}\n\nexport interface EnrichCompanyResponse {\n enriched: boolean;\n companyDescription?: string;\n knowledgeBase?: any[];\n error?: string;\n}\n\nexport interface PreviewStackParams {\n language?: string | null;\n /** Required, non-empty list of BCP-47 languages to resolve a stack for. */\n supported_languages: string[];\n current_provider_config?: Record<string, any> | null;\n}\n\nexport interface AgentKnowledgeSource {\n id: string;\n kind?: 'text' | 'url';\n title?: string;\n source_uri?: string | null;\n bytes?: number;\n created_at?: string;\n [key: string]: any;\n}\n\nexport type AddKnowledgeSourceParams =\n | { kind: 'text'; title: string; text: string }\n | { kind: 'url'; title: string; url: string };\n\n/** A public share link: anyone with the URL can talk to the agent, billed to your workspace. */\nexport interface AgentShareLink {\n id: string;\n url: string;\n enabled: boolean;\n minutes_limit: number;\n minutes_used: number;\n minutes_reserved: number;\n minutes_remaining: number;\n live_calls: number;\n max_call_seconds: number;\n max_concurrent: number;\n calls_per_ip_hour: number;\n minutes_requested_at: string | null;\n}\n\n/** All optional; omitted fields keep their current value (or the default on create). */\nexport interface AgentShareLinkSettings {\n enabled?: boolean;\n /** Total talk-time pool for the link, 0–6000 minutes. */\n minutes_limit?: number;\n /** Per-call cap, 60–1800 seconds. */\n max_call_seconds?: number;\n /** Simultaneous calls, 1–10. */\n max_concurrent?: number;\n /** Calls per caller IP per hour, 1–30. */\n calls_per_ip_hour?: number;\n}\n\nexport interface AgentChange {\n change_id: string;\n field_path?: string;\n before_jsonb?: any;\n after_jsonb?: any;\n changed_by?: string;\n created_at?: string;\n undone_at?: string | null;\n [key: string]: any;\n}\n\nfunction normalizeAgentPayload<T extends CreateAgentParams | UpdateAgentParams>(data: T): Omit<T, 'prompt'> & { system_prompt?: string } {\n const { prompt, ...rest } = data as any;\n return {\n ...rest,\n ...(!rest.system_prompt && prompt ? { system_prompt: prompt } : {})\n };\n}\n\nexport class AgentsResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all your AI Agents.\n */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<AgentListResponse> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n const query = searchParams.toString();\n return this.client.get<AgentListResponse>(`/agents${query ? `?${query}` : ''}`);\n }\n\n /**\n * Retrieve a single AI Agent by its unique ID.\n */\n public async retrieve(agentId: string): Promise<Agent> {\n return this.client.get<Agent>(`/agents/${agentId}`);\n }\n\n /**\n * Create a new AI Agent with a complete system prompt and voice settings.\n */\n public async create(data: CreateAgentParams): Promise<{ status: 'created'; id: string }> {\n return this.client.post<{ status: 'created'; id: string }>('/agents', normalizeAgentPayload(data));\n }\n\n /**\n * Update an existing AI Agent's persona or configuration.\n */\n public async update(agentId: string, data: UpdateAgentParams): Promise<{ status: 'updated' }> {\n return this.client.put<{ status: 'updated' }>(`/agents/${agentId}`, normalizeAgentPayload(data));\n }\n\n /**\n * Delete an AI Agent permanently.\n */\n public async delete(agentId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete<{ status: 'deleted'; id: string }>(`/agents/${agentId}`);\n }\n\n public async llmOptions(): Promise<{ models: any[]; voices: any[] }> {\n return this.client.get('/agents/llm-options');\n }\n\n public async generate(data: { prompt: string; options?: Record<string, any> }): Promise<Record<string, any>> {\n return this.client.post('/agents/generate', data);\n }\n\n /**\n * List calls made with a specific agent.\n */\n public async listCalls(agentId: string, params: { limit?: number; offset?: number; status?: string } = {}): Promise<AgentCallListResponse> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n if (params.status) searchParams.set('status', params.status);\n const query = searchParams.toString();\n return this.client.get<AgentCallListResponse>(`/agents/${agentId}/calls${query ? `?${query}` : ''}`);\n }\n\n /**\n * Duplicate an existing agent. The clone gets \" (Copy)\" appended to its name.\n */\n public async clone(agentId: string): Promise<{ status: 'created'; id: string }> {\n return this.client.post<{ status: 'created'; id: string }>(`/agents/${agentId}/clone`, {});\n }\n\n /**\n * Validate an agent's configuration before publishing.\n * Pass agent_id to merge with an existing persisted agent, or supply fields directly.\n */\n public async validatePublish(params: ValidatePublishParams): Promise<Record<string, any>> {\n return this.client.post('/agents/validate-publish', params);\n }\n\n /**\n * Publish an agent: validate its persisted config and freeze it into the\n * published snapshot the harness/review pipeline reads as the baseline.\n * Returns `{ published: false, blockers }` (HTTP 200) when blockers remain —\n * inspect `blockers` rather than relying on a thrown error.\n */\n public async publish(agentId: string): Promise<PublishAgentResponse> {\n return this.client.post<PublishAgentResponse>(`/agents/${agentId}/publish`, {});\n }\n\n /**\n * Validate and apply a flat-diff change-set against the AgentConfig field registry.\n * Does NOT persist — callers must follow up with update().\n */\n public async applyChanges(params: ApplyChangesParams): Promise<ApplyChangesResponse> {\n return this.client.post('/agents/apply-changes', params);\n }\n\n /**\n * Use AI with Google Search grounding to generate a company description from a website URL.\n */\n public async enrichCompany(params: EnrichCompanyParams): Promise<EnrichCompanyResponse> {\n return this.client.post('/agents/enrich-company', params);\n }\n\n /**\n * Preview the resolved per-language model stack (STT/LLM/TTS), blockers,\n * warnings, and model diffs for a set of supported languages — without\n * persisting anything.\n */\n public async previewStack(params: PreviewStackParams): Promise<Record<string, any>> {\n return this.client.post('/agents/stack-preview', params);\n }\n\n /**\n * List the knowledge sources (RAG context) attached to an agent.\n */\n public async listKnowledgeSources(agentId: string): Promise<{ sources: AgentKnowledgeSource[] }> {\n return this.client.get(`/agents/${agentId}/knowledge-sources`);\n }\n\n /**\n * Add a knowledge source to an agent from raw text or a URL.\n */\n public async addKnowledgeSource(agentId: string, data: AddKnowledgeSourceParams): Promise<Record<string, any>> {\n return this.client.post(`/agents/${agentId}/knowledge-sources`, data);\n }\n\n /**\n * Delete a knowledge source from an agent.\n */\n public async deleteKnowledgeSource(agentId: string, sourceId: string): Promise<Record<string, any>> {\n return this.client.delete(`/agents/${agentId}/knowledge-sources/${sourceId}`);\n }\n\n /**\n * Get the agent's public share link, or `link: null` if none exists.\n * `link_feature: false` means share links are disabled on this deployment.\n */\n public async getShareLink(agentId: string): Promise<{ link_feature: boolean; link: AgentShareLink | null }> {\n const res = await this.client.get<{ link_feature: boolean; link: AgentShareLink | null }>(`/agents/${agentId}/testers`);\n return { link_feature: res.link_feature, link: res.link };\n }\n\n /**\n * Create the agent's public share link, or update its settings if one exists.\n */\n public async setShareLink(agentId: string, settings: AgentShareLinkSettings = {}): Promise<{ link: AgentShareLink }> {\n return this.client.put(`/agents/${agentId}/share-link`, settings);\n }\n\n /**\n * Issue a new URL for the share link. The old URL stops working immediately.\n */\n public async regenerateShareLink(agentId: string): Promise<{ link: AgentShareLink }> {\n return this.client.post(`/agents/${agentId}/share-link/regenerate`, {});\n }\n\n /**\n * List the recorded configuration changes for an agent (most recent first).\n * Optionally pass an ISO timestamp to only return changes since then.\n */\n public async listChanges(agentId: string, params: { since?: string } = {}): Promise<{ changes: AgentChange[] }> {\n const query = params.since ? `?since=${encodeURIComponent(params.since)}` : '';\n return this.client.get(`/agents/${agentId}/changes${query}`);\n }\n\n /**\n * Undo a single recorded configuration change, reverting that field to its\n * previous value. Returns the resulting agent snapshot.\n */\n public async undoChange(agentId: string, changeId: string): Promise<{ ok: boolean; changeId: string; agentSnapshot: Agent }> {\n return this.client.post(`/agents/${agentId}/changes/${changeId}/undo`, {});\n }\n\n /**\n * Run the evaluation suite for an agent. mode=\"synthetic\" (default) uses\n * the offline scorer; mode=\"live\" runs the model-driven runner.\n */\n public async runEvals(\n agentId: string,\n params: { mode?: 'synthetic' | 'live'; judge?: boolean } = {},\n ): Promise<Record<string, any>> {\n const query = new URLSearchParams();\n if (params.mode) query.set('mode', params.mode);\n if (params.judge) query.set('judge', '1');\n const qs = query.toString();\n return this.client.post(`/agents/${agentId}/evals/run${qs ? `?${qs}` : ''}`, {});\n }\n\n /**\n * Run the eval SUITE across many agents at once (agents × seeded scenarios),\n * bounded by the optional concurrency cap. One eval run is persisted per\n * agent; the aggregate EvalSuiteReport is returned. Pass `judge: true` to\n * supplement the heuristics with the opt-in LLM judge (needs a Gemini key).\n */\n public async runEvalSuite(params: {\n agentIds: string[];\n scenarioIds?: string[];\n concurrency?: number;\n judge?: boolean;\n }): Promise<Record<string, any>> {\n return this.client.post('/agents/evals/suite', params);\n }\n\n /**\n * List previous evaluation runs for an agent.\n */\n public async listEvalRuns(agentId: string): Promise<Record<string, any>> {\n return this.client.get(`/agents/${agentId}/evals/runs`);\n }\n\n /**\n * Retrieve a single evaluation run, including per-scenario scores.\n */\n public async getEvalRun(agentId: string, runId: string): Promise<Record<string, any>> {\n return this.client.get(`/agents/${agentId}/evals/runs/${runId}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface ListCallsParams {\n limit?: number;\n offset?: number;\n cursor?: string;\n status?: string;\n}\n\nexport interface CallRecord {\n id: string;\n agent_id: string;\n room_name: string;\n status: 'queued' | 'ringing' | 'in_progress' | 'completed' | 'failed' | 'busy' | 'canceled';\n duration_seconds?: number;\n started_at?: string;\n ended_at?: string;\n participants?: Array<{\n id: string;\n role: 'agent' | 'customer' | 'observer';\n transport: 'webrtc' | 'pstn' | 'sip' | 'internal';\n identity: string;\n status: string;\n }>;\n metadata?: Record<string, any>;\n intelligence_status?: string;\n participant_count?: number;\n primary_participant?: Record<string, any> | null;\n total_cost?: number;\n provider_cost?: number;\n provider_cost_breakdown?: Record<string, any>;\n provider_cost_calculated_at?: string | null;\n bill_duration?: number;\n}\n\nexport interface CallListResponse {\n calls: CallRecord[];\n total: number;\n limit: number;\n offset: number;\n next_cursor?: string | null;\n}\n\nexport interface CreateCallParams {\n agent_id: string;\n participants: Array<{\n transport: 'webrtc' | 'pstn';\n identity: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface BatchCallParams {\n agent_id: string;\n to?: string[];\n recipients?: Array<{\n to?: string;\n identity?: string;\n phone?: string;\n phone_number?: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n from_number?: string;\n batch_id?: string;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface FanoutCallParams {\n agent_id: string;\n to?: string[];\n recipients?: Array<{\n to?: string;\n identity?: string;\n phone?: string;\n phone_number?: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n from_number?: string;\n /** Preferred tracking id for this fanout. Falls back to batch_id, then auto-generated. */\n fanout_id?: string;\n /** Compatibility alias for fanout_id. */\n batch_id?: string;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface CreateCallResponse {\n id: string;\n room_name: string;\n status: string;\n participants: Array<{\n id: string;\n transport: 'webrtc' | 'pstn';\n identity: string;\n status: string;\n access?: { url: string; token: string };\n telephony_leg_id?: string;\n job_id?: string;\n }>;\n agent?: { id: string; name: string };\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n searchParams.set(key, String(value));\n }\n }\n const query = searchParams.toString();\n return query ? `?${query}` : '';\n}\n\nexport class CallsResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all previous and active calls.\n */\n public async list(params: ListCallsParams = {}): Promise<CallListResponse> {\n return this.client.get<CallListResponse>(`/calls${buildQuery(params)}`);\n }\n\n /**\n * Retrieve calls currently in progress.\n */\n public async active(params: ListCallsParams = {}): Promise<CallListResponse> {\n return this.client.get<CallListResponse>(`/calls/active${buildQuery(params)}`);\n }\n\n /**\n * Retrieve details, transcripts, and analysis of a single call by its unique ID.\n */\n public async retrieve(callId: string): Promise<CallRecord> {\n return this.client.get<CallRecord>(`/calls/${callId}`);\n }\n\n /**\n * Dispatch an outbound phone call securely using your configured carrier.\n */\n public async create(data: CreateCallParams): Promise<CreateCallResponse> {\n return this.client.post('/calls', data);\n }\n\n /**\n * Group call fanout: dial up to 500 PSTN participants into a single call room.\n * Every recipient joins the same call. For independent per-recipient attempts,\n * retries, and reports, use `campaigns` instead.\n */\n public async fanout(data: FanoutCallParams): Promise<CreateCallResponse & { fanout_id: string; batch_id: string; queued: number }> {\n return this.client.post('/calls/fanout', data);\n }\n\n /**\n * Compatibility alias for {@link fanout}. Creates one call room with multiple\n * PSTN participants. Queue up to 500 outbound PSTN recipients in one request.\n */\n public async batch(data: BatchCallParams): Promise<CreateCallResponse & { batch_id: string; queued: number }> {\n return this.client.post('/calls/batch', data);\n }\n\n public async summary(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/summary`);\n }\n\n public async transcript(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/transcript`);\n }\n\n public async recording(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/recording`);\n }\n\n public async reprocess(callId: string): Promise<Record<string, any>> {\n return this.client.post(`/calls/${callId}/reprocess`);\n }\n\n /** Force-end an active call. Irreversible — closes the LiveKit room and triggers post-call processing. */\n public async end(callId: string): Promise<{ status: string; id: string; message: string }> {\n return this.client.post(`/calls/${callId}/end`);\n }\n\n /** Add one or more participants to an in-progress call (warm transfer / conference). */\n public async addParticipants(\n callId: string,\n data: { participants: CreateCallParams['participants'] }\n ): Promise<CreateCallResponse> {\n return this.client.post(`/calls/${callId}/participants`, data);\n }\n\n public async queueStats(): Promise<Record<string, number>> {\n return this.client.get('/calls/queue/stats');\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface DncEntry {\n id?: string;\n phone: string;\n reason?: string;\n created_at?: string;\n}\n\nexport interface DncListResponse {\n dnc_entries: DncEntry[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface DncCheckResult {\n phone_number: string;\n normalized: string | null;\n blocked: boolean;\n valid: boolean;\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\n/**\n * Do-Not-Call registry. Numbers are normalized to E.164 server-side on both\n * write and read, so any input format is accepted.\n */\nexport class DncResource {\n constructor(private client: RymiClient) {}\n\n /** List all DNC entries for the tenant. */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<DncListResponse> {\n return this.client.get<DncListResponse>(`/dnc${buildQuery(params)}`);\n }\n\n /** Add a single number to the Do-Not-Call registry. */\n public async add(data: { phone_number: string; reason?: string }): Promise<{ status: 'blocklisted'; phone_number: string }> {\n return this.client.post('/dnc', data);\n }\n\n /** Add up to 1000 numbers in one request. Invalid numbers are skipped and returned in `invalid`. */\n public async addBatch(data: { phone_numbers: string[]; reason?: string }): Promise<{ status: 'blocklisted'; count: number; invalid_count: number; invalid: string[] }> {\n return this.client.post('/dnc/batch', data);\n }\n\n /** Check up to 500 numbers without adding them. Read-only. */\n public async check(data: { phone_numbers: string[] }): Promise<{ results: DncCheckResult[]; blocked_count: number; total_checked: number }> {\n return this.client.post('/dnc/check', data);\n }\n\n /** Remove a number from the registry (re-enables outbound to it). */\n public async remove(phone: string): Promise<{ status: 'removed'; phone: string }> {\n return this.client.delete(`/dnc/${encodeURIComponent(phone)}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface NumberRecord {\n id?: string;\n number?: string;\n phone_number?: string;\n provider?: 'plivo' | 'twilio' | 'vonage' | 'telnyx';\n capabilities?: string[];\n price?: string | number;\n monthly_price?: number;\n agent_id?: string | null;\n assigned_agent_id?: string | null;\n created_at?: string;\n /** Carrier inbound-webhook provisioning state (set once an agent is attached). */\n webhook_status?: 'configured' | 'manual_required' | 'failed' | null;\n webhook_url?: string | null;\n webhook_error?: string | null;\n last_inbound_at?: string | null;\n}\n\n/** Outcome of carrier inbound-webhook auto-provisioning. */\nexport interface WebhookProvisionResult {\n status: 'configured' | 'manual_required' | 'failed' | 'no_carrier';\n provider: string | null;\n webhookUrl: string | null;\n verified: boolean;\n error?: string;\n}\n\nexport class NumbersResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all phone numbers assigned to your Rymi account.\n */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<{ numbers: NumberRecord[]; total: number; offset: number; limit: number }> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n const query = searchParams.toString();\n return this.client.get(`/numbers${query ? `?${query}` : ''}`);\n }\n\n public async register(number: string, params: { agent_id?: string } = {}): Promise<{ status: 'registered'; number: string; agent_id: string | null; webhook: WebhookProvisionResult | null }> {\n return this.client.post('/numbers', { number, ...params });\n }\n\n public async attach(number: string, agentId: string): Promise<{ status: 'attached'; agent_id: string; number: string; webhook: WebhookProvisionResult | null }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/attach`, { agent_id: agentId });\n }\n\n /** Clear the agent association without deregistering the number. */\n public async detach(number: string): Promise<{ status: 'detached'; number: string }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/detach`);\n }\n\n /** Re-run carrier inbound-webhook auto-provisioning for a number. */\n public async provisionWebhook(number: string): Promise<{ number: string; webhook: WebhookProvisionResult }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/webhook`);\n }\n\n public async remove(number: string): Promise<{ status: 'removed'; number: string }> {\n return this.client.delete(`/numbers/${encodeURIComponent(number)}`);\n }\n}\n","import * as crypto from 'crypto';\nimport { RymiClient } from '../client';\n\nexport interface WebhookRecord {\n id: string;\n url: string;\n events: string[];\n alert_email?: string | null;\n created_at?: string;\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\nexport class WebhooksResource {\n constructor(private client: RymiClient) {}\n\n /** List registered webhook endpoints. The signing secret is never returned. */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<{ webhooks: WebhookRecord[]; total: number; offset: number; limit: number }> {\n return this.client.get(`/webhooks${buildQuery(params)}`);\n }\n\n /** Register a webhook. `url` must be public https. `secret` must be 16–256 chars. */\n public async create(data: { url: string; events: string[]; secret: string; alert_email?: string }): Promise<{ status: 'registered' }> {\n return this.client.post('/webhooks', data);\n }\n\n /** Update a webhook. Only provided fields change. Pass `secret` to rotate it. */\n public async update(id: string, data: { url?: string; events?: string[]; secret?: string; alert_email?: string | null }): Promise<{ status: 'updated'; id: string }> {\n return this.client.patch(`/webhooks/${id}`, data);\n }\n\n /** Delete a webhook endpoint. */\n public async delete(id: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/webhooks/${id}`);\n }\n /**\n * Verifies that a webhook received by your backend was genuinely dispatched by Rymi.\n * \n * Rymi endpoints secure webhooks by computing an HMAC-SHA256 signature\n * of the raw JSON body concatenated with the timestamp, using your Webhook Secret.\n * \n * @param payload The raw stringified JSON body of the webhook hook request.\n * @param signatureHeader The value of the `X-Rymi-Signature` header from the request.\n * @param timestampHeader The value of the `X-Rymi-Timestamp` header from the request.\n * @param webhookSecret Your project's unique Webhook Signing Secret (starts with `whsec_`)\n * @param toleranceMillis Allowed time difference in milliseconds to prevent replay attacks (default 5 mins)\n * \n * @throws {Error} if the signature is invalid or if the timestamp exceeds the tolerance.\n */\n public verifySignature(\n payload: string,\n signatureHeader: string,\n timestampHeader: string,\n webhookSecret: string,\n toleranceMillis = 300000 // 5 minutes\n ): boolean {\n // 1. Check for Replay Attacks\n const timestamp = parseInt(timestampHeader, 10);\n if (isNaN(timestamp)) {\n throw new Error('Invalid Rymi-Timestamp header');\n }\n\n const now = Date.now();\n if (now - timestamp > toleranceMillis) {\n throw new Error('Webhook timestamp is too old. Possible replay attack.');\n }\n\n // 2. Prepare the verification string\n const signaturePayload = `${timestamp}.${payload}`;\n\n // 3. Compute the expected HMAC using the developer's Webhook Secret\n const expectedSignature = crypto\n .createHmac('sha256', webhookSecret)\n .update(signaturePayload, 'utf8')\n .digest('hex');\n\n // 4. Secure string comparison (constant-time to prevent timing attacks)\n try {\n const isValid = crypto.timingSafeEqual(\n Buffer.from(signatureHeader),\n Buffer.from(expectedSignature)\n );\n\n if (!isValid) {\n throw new Error('Invalid Webhook Signature. The secret might be incorrect.');\n }\n\n return true;\n } catch (err) {\n throw new Error('Invalid Webhook Signature. The secret might be incorrect.');\n }\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface PublishableKeyRecord {\n id: string;\n key_prefix: string;\n agent_id: string;\n label: string;\n allowed_channels: Array<'web' | 'phone'>;\n audience: 'sdk' | 'landing_demo';\n default_from_number: string | null;\n created_at: string;\n}\n\nexport interface CreatePublishableKeyParams {\n agent_id: string;\n label: string;\n allowed_channels?: Array<'web' | 'phone'>;\n audience?: 'sdk' | 'landing_demo';\n default_from_number?: string | null;\n}\n\nexport class KeysResource {\n constructor(private client: RymiClient) {}\n\n public async listPublishable(): Promise<{ keys: PublishableKeyRecord[] }> {\n return this.client.get('/keys/publishable');\n }\n\n public async createPublishable(data: CreatePublishableKeyParams): Promise<CreatePublishableKeyParams & { key: string }> {\n return this.client.post('/keys/publishable', data);\n }\n\n public async revokePublishable(id: string): Promise<{ success: true }> {\n return this.client.delete(`/keys/publishable/${id}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport type TelephonyProvider = 'plivo' | 'twilio' | 'vonage' | 'telnyx';\n\nexport interface ConnectTelephonyParams {\n provider: TelephonyProvider;\n auth_id?: string;\n auth_token?: string;\n api_key?: string;\n api_secret?: string;\n signature_secret?: string;\n /** Telnyx Ed25519 webhook signing secret (optional). */\n auth_secret?: string;\n}\n\nexport class TelephonyResource {\n constructor(private client: RymiClient) {}\n\n public async connect(data: ConnectTelephonyParams): Promise<{ status: 'connected'; provider: TelephonyProvider; account_name: string; message: string }> {\n return this.client.post('/telephony/connect', data);\n }\n\n public async disconnect(): Promise<{ status: 'disconnected'; message: string }> {\n return this.client.post('/telephony/disconnect');\n }\n\n public async status(): Promise<{ connected: boolean; provider: TelephonyProvider | null; account_name: string | null; account_country: string | null }> {\n return this.client.get('/telephony/status');\n }\n\n public async numbers(): Promise<{ numbers: any[] }> {\n return this.client.get('/telephony/numbers');\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface UsageSummary {\n voice_runtime: {\n remaining_minutes: number;\n status: string;\n };\n studio_ai?: {\n used_units?: number;\n included_units?: number | null;\n quota_percent?: number;\n status?: string;\n overage_enabled?: boolean;\n };\n post_call_intelligence?: {\n status?: string;\n used_units?: number;\n };\n}\n\nexport class BillingResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Lane-aware usage summary: remaining voice-runtime minutes, Studio AI unit\n * usage, and post-call intelligence usage. Voice balance is reported in\n * MINUTES (the customer-facing unit), not dollars.\n */\n public async usageSummary(): Promise<UsageSummary> {\n return this.client.get<UsageSummary>('/billing/usage-summary');\n }\n\n /** Estimate the cost of a call for a custom model stack and duration. */\n public async estimate(data: { stt_model?: string; llm_model?: string; tts_model?: string; duration_seconds?: number } = {}): Promise<Record<string, any>> {\n return this.client.post('/billing/estimate', data);\n }\n\n /** Configure auto-recharge. Server rejects (400) if enabled && pack_usd <= threshold_usd. */\n public async setAutoRecharge(data: { enabled?: boolean; pack_usd?: number; threshold_usd?: number }): Promise<{ ok: true }> {\n return this.client.put('/billing/auto-recharge', data);\n }\n\n /** Configure spend-alert preferences. */\n public async setAlerts(data: { thresholds_usd?: number[]; low_balance_pct?: number; email_enabled?: boolean }): Promise<{ ok: true }> {\n return this.client.put('/billing/alerts', data);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface AgentTemplateSummary {\n id?: string;\n slug?: string;\n label?: string;\n description?: string;\n icon?: string;\n color?: string;\n defaults?: Record<string, any>;\n [key: string]: any;\n}\n\nexport class TemplatesResource {\n constructor(private client: RymiClient) {}\n\n /**\n * List published agent templates available to the current tenant. Use a\n * template's `defaults` as the starting config for create_agent.\n */\n public async list(): Promise<{ templates: AgentTemplateSummary[]; source?: string }> {\n return this.client.get('/agent-templates');\n }\n}\n","import { RymiClient } from '../client';\nimport type {\n Campaign,\n CampaignStatus,\n CampaignType,\n CampaignMember,\n CampaignAttempt,\n CampaignReport,\n CampaignGoal,\n CampaignCompliancePolicy\n} from '@rymi/sdk-types';\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\n// ─── list/create/update params + responses ─────────────────────────────────\n\nexport interface ListCampaignsParams {\n limit?: number;\n offset?: number;\n status?: CampaignStatus;\n type?: CampaignType;\n agent_id?: string;\n}\n\nexport interface CampaignListResponse {\n campaigns: Campaign[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateCampaignParams {\n agent_id: string;\n type: CampaignType;\n name: string;\n goal?: CampaignGoal;\n schedule_policy?: Record<string, unknown>;\n retry_policy?: Record<string, unknown>;\n concurrency_policy?: Record<string, unknown>;\n automation_policy?: Record<string, unknown>;\n reporting_policy?: Record<string, unknown>;\n compliance_policy?: CampaignCompliancePolicy;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateCampaignParams {\n name?: string;\n goal?: CampaignGoal;\n schedule_policy?: Record<string, unknown>;\n retry_policy?: Record<string, unknown>;\n concurrency_policy?: Record<string, unknown>;\n automation_policy?: Record<string, unknown>;\n reporting_policy?: Record<string, unknown>;\n compliance_policy?: CampaignCompliancePolicy;\n post_call_config_override?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface LaunchBlocker {\n code: string;\n ok: boolean;\n detail?: string;\n}\n\nexport interface LaunchCampaignResponse {\n campaign: Campaign;\n blockers: LaunchBlocker[];\n}\n\n/**\n * GET /campaigns/:id/report response. Extends the shared CampaignReport with\n * the report-endpoint-only derived fields (top failure reasons + cost per\n * success) that the API adds on top of the persisted shape.\n */\nexport interface CampaignReportResponse extends CampaignReport {\n distributions: CampaignReport['distributions'] & {\n top_failure_reasons: Array<{ reason: string; count: number }>;\n cost_per_success_credits: number;\n };\n}\n\n// ─── members ────────────────────────────────────────────────────────────────\n\nexport interface ListCampaignMembersParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignMemberListResponse {\n members: CampaignMember[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface AddCampaignMembersParams {\n contact_ids: string[];\n variables_override?: Record<string, string>;\n}\n\nexport interface ImportCampaignMembersParams {\n contacts?: Array<Record<string, unknown>>;\n csv?: string;\n}\n\nexport interface ImportCampaignMembersResponse {\n created: number;\n merged: number;\n /** Members attached to the campaign in this import. */\n attached: number;\n invalid: Array<{ row: number; reason: string }>;\n}\n\nexport interface UpdateCampaignMemberParams {\n status?: string;\n variables_override?: Record<string, string>;\n next_attempt_at?: string;\n}\n\nclass CampaignMembersResource {\n constructor(private client: RymiClient) {}\n\n /** List a campaign's members, paginated. */\n public async list(campaignId: string, params: ListCampaignMembersParams = {}): Promise<CampaignMemberListResponse> {\n return this.client.get(`/campaigns/${campaignId}/members${buildQuery(params)}`);\n }\n\n /** Attach existing contacts to a campaign as members. */\n public async add(campaignId: string, data: AddCampaignMembersParams): Promise<{ members: CampaignMember[] }> {\n return this.client.post(`/campaigns/${campaignId}/members`, data);\n }\n\n /** Import inline contact rows (JSON or CSV): creates/merges contacts and attaches members in one call. */\n public async import(campaignId: string, data: ImportCampaignMembersParams): Promise<ImportCampaignMembersResponse> {\n return this.client.post(`/campaigns/${campaignId}/members/import`, data);\n }\n\n /** Update a campaign member (status, variables, next attempt time). */\n public async update(campaignId: string, memberId: string, data: UpdateCampaignMemberParams): Promise<{ member: CampaignMember }> {\n return this.client.patch(`/campaigns/${campaignId}/members/${memberId}`, data);\n }\n\n /** Remove a member from a campaign. */\n public async remove(campaignId: string, memberId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/campaigns/${campaignId}/members/${memberId}`);\n }\n}\n\n// ─── inbound routes ─────────────────────────────────────────────────────────\n\nexport interface CampaignRoute {\n id: string;\n tenant_id: string;\n campaign_id: string;\n phone_number: string;\n schedule: Record<string, unknown>;\n active: boolean;\n created_at: string;\n updated_at: string;\n}\n\nexport interface ListCampaignRoutesParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface CampaignRouteListResponse {\n routes: CampaignRoute[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateCampaignRouteParams {\n phone_number: string;\n schedule?: Record<string, unknown>;\n active?: boolean;\n}\n\nexport interface UpdateCampaignRouteParams {\n schedule?: Record<string, unknown>;\n active?: boolean;\n}\n\nclass CampaignRoutesResource {\n constructor(private client: RymiClient) {}\n\n /** List a campaign's inbound routing rules. */\n public async list(campaignId: string, params: ListCampaignRoutesParams = {}): Promise<CampaignRouteListResponse> {\n return this.client.get(`/campaigns/${campaignId}/routes${buildQuery(params)}`);\n }\n\n /** Bind an owned phone number to this campaign for inbound routing. Only one active route per number is allowed. */\n public async create(campaignId: string, data: CreateCampaignRouteParams): Promise<{ route: CampaignRoute }> {\n return this.client.post(`/campaigns/${campaignId}/routes`, data);\n }\n\n /** Update an inbound route's schedule or active flag. */\n public async update(campaignId: string, routeId: string, data: UpdateCampaignRouteParams): Promise<{ route: CampaignRoute }> {\n return this.client.patch(`/campaigns/${campaignId}/routes/${routeId}`, data);\n }\n\n /** Delete an inbound route. */\n public async delete(campaignId: string, routeId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/campaigns/${campaignId}/routes/${routeId}`);\n }\n}\n\n// ─── attempts / batches / followups (read-only) ────────────────────────────\n\nexport interface ListCampaignAttemptsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignAttemptListResponse {\n attempts: CampaignAttempt[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface ListCampaignBatchesParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface CampaignBatch {\n id: string;\n tenant_id: string;\n campaign_id: string;\n batch_key: string;\n status: string;\n selected_count: number;\n queued_count: number;\n completed_count: number;\n failed_count: number;\n started_at?: string | null;\n completed_at?: string | null;\n created_at: string;\n}\n\nexport interface CampaignBatchListResponse {\n batches: CampaignBatch[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface ListCampaignFollowupsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignFollowupJob {\n id: string;\n tenant_id: string;\n campaign_id: string;\n campaign_attempt_id?: string | null;\n campaign_member_id?: string | null;\n kind: string;\n status: string;\n scheduled_at: string;\n consent_checked: boolean;\n capability_checked: boolean;\n idempotency_key: string;\n payload: Record<string, unknown>;\n result?: Record<string, unknown> | null;\n created_at: string;\n updated_at: string;\n}\n\nexport interface CampaignFollowupListResponse {\n followups: CampaignFollowupJob[];\n total: number;\n offset: number;\n limit: number;\n}\n\n// ─── improve / suggestions ──────────────────────────────────────────────────\n\nexport interface CampaignSuggestion {\n id: string;\n tenant_id: string;\n campaign_id: string;\n category: string;\n evidence: Record<string, unknown>;\n proposal: Record<string, unknown>;\n status: 'proposed' | 'accepted' | 'dismissed';\n created_by_model?: string | null;\n created_at: string;\n updated_at: string;\n}\n\nexport interface ImproveCampaignResponse {\n suggestions: CampaignSuggestion[];\n}\n\nexport interface ListCampaignSuggestionsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignSuggestionListResponse {\n suggestions: CampaignSuggestion[];\n total: number;\n offset: number;\n limit: number;\n}\n\n// ─── CampaignIntakeResource ──────────────────────────────────────────────────\n\n/** A campaign's lead-intake URL settings. The URL itself is only returned on create/rotate. */\nexport interface CampaignIntake {\n enabled: true;\n assume_voice_consent: boolean;\n default_country: string | null;\n created_at: string;\n rotated_at: string;\n last_used_at: string | null;\n}\n\nexport interface CampaignIntakeSettings {\n /** Treat every lead posted to the URL as having voice consent (e.g. a subscribe form with a consent line). */\n assume_voice_consent?: boolean;\n /** ISO-3166 alpha-2 (e.g. \"IN\") used for numbers posted without a +country code. */\n default_country?: string | null;\n}\n\nclass CampaignIntakeResource {\n constructor(private client: RymiClient) {}\n\n /** Get the campaign's lead-intake settings, or `intake: null` if it has none. */\n public async get(campaignId: string): Promise<{ intake: CampaignIntake | null }> {\n return this.client.get(`/campaigns/${campaignId}/intake`);\n }\n\n /** Create the lead-intake URL (returned once as `url`), or update its settings (`url: null`). */\n public async set(campaignId: string, settings: CampaignIntakeSettings = {}): Promise<{ intake: CampaignIntake; url: string | null }> {\n return this.client.put(`/campaigns/${campaignId}/intake`, settings);\n }\n\n /** Issue a new URL. The old one stops accepting leads immediately. */\n public async rotate(campaignId: string): Promise<{ intake: CampaignIntake; url: string }> {\n return this.client.post(`/campaigns/${campaignId}/intake/rotate`, {});\n }\n\n /** Remove the lead-intake URL. */\n public async disable(campaignId: string): Promise<void> {\n return this.client.delete(`/campaigns/${campaignId}/intake`);\n }\n}\n\n// ─── CampaignsResource ───────────────────────────────────────────────────────\n\nexport class CampaignsResource {\n public members: CampaignMembersResource;\n public routes: CampaignRoutesResource;\n public intake: CampaignIntakeResource;\n\n constructor(private client: RymiClient) {\n this.members = new CampaignMembersResource(client);\n this.routes = new CampaignRoutesResource(client);\n this.intake = new CampaignIntakeResource(client);\n }\n\n /** List campaigns for the authenticated tenant, paginated. */\n public async list(params: ListCampaignsParams = {}): Promise<CampaignListResponse> {\n return this.client.get(`/campaigns${buildQuery(params)}`);\n }\n\n /** Create a new campaign in draft status against a published agent. */\n public async create(data: CreateCampaignParams): Promise<{ campaign: Campaign }> {\n return this.client.post('/campaigns', data);\n }\n\n /** Retrieve a single campaign by id. */\n public async get(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.get(`/campaigns/${campaignId}`);\n }\n\n /** Update campaign policy/goal fields. Status and lifecycle fields are not writable here. */\n public async update(campaignId: string, data: UpdateCampaignParams): Promise<{ campaign: Campaign }> {\n return this.client.patch(`/campaigns/${campaignId}`, data);\n }\n\n /**\n * Launch a campaign: validates launch blockers, then stamps\n * `launched_at` + `agent_snapshot_id`, flips members to `ready`, and\n * transitions status to `running`.\n */\n public async launch(campaignId: string): Promise<LaunchCampaignResponse> {\n return this.client.post(`/campaigns/${campaignId}/launch`);\n }\n\n /** Evaluate launch blockers without launching (dry run). Safe from any status. */\n public async launchBlockers(campaignId: string): Promise<{ blockers: LaunchBlocker[]; launchable: boolean }> {\n return this.client.get(`/campaigns/${campaignId}/launch-blockers`);\n }\n\n /** Pause a running campaign. In-flight calls finish naturally. */\n public async pause(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/pause`);\n }\n\n /** Resume a paused campaign. */\n public async resume(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/resume`);\n }\n\n /** Archive a campaign. Terminal — the scheduler never selects work for it again. */\n public async archive(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/archive`);\n }\n\n /** Read the campaign report: `stat_*` summary counters + outcome/sentiment/hourly/snapshot distributions. */\n public async report(campaignId: string): Promise<CampaignReportResponse> {\n return this.client.get(`/campaigns/${campaignId}/report`);\n }\n\n /** List a campaign's dial attempts, paginated. */\n public async attempts(campaignId: string, params: ListCampaignAttemptsParams = {}): Promise<CampaignAttemptListResponse> {\n return this.client.get(`/campaigns/${campaignId}/attempts${buildQuery(params)}`);\n }\n\n /** List a campaign's sweep-claim batches, paginated. */\n public async batches(campaignId: string, params: ListCampaignBatchesParams = {}): Promise<CampaignBatchListResponse> {\n return this.client.get(`/campaigns/${campaignId}/batches${buildQuery(params)}`);\n }\n\n /** List a campaign's follow-up jobs, paginated. */\n public async followups(campaignId: string, params: ListCampaignFollowupsParams = {}): Promise<CampaignFollowupListResponse> {\n return this.client.get(`/campaigns/${campaignId}/followups${buildQuery(params)}`);\n }\n\n /** Run the improve engine: detectors gate an LLM proposal writer, persisting new `campaign_suggestions`. */\n public async improve(campaignId: string): Promise<ImproveCampaignResponse> {\n return this.client.post(`/campaigns/${campaignId}/improve`);\n }\n\n /** List a campaign's improvement suggestions, paginated. */\n public async suggestions(campaignId: string, params: ListCampaignSuggestionsParams = {}): Promise<CampaignSuggestionListResponse> {\n return this.client.get(`/campaigns/${campaignId}/suggestions${buildQuery(params)}`);\n }\n\n /** Accept a suggestion: agent-editing suggestions create an agent-changes draft; campaign-policy suggestions patch the campaign. */\n public async acceptSuggestion(campaignId: string, suggestionId: string): Promise<{ suggestion: CampaignSuggestion }> {\n return this.client.post(`/campaigns/${campaignId}/suggestions/${suggestionId}/accept`);\n }\n\n /** Dismiss a suggestion without applying it. */\n public async dismissSuggestion(campaignId: string, suggestionId: string): Promise<{ suggestion: CampaignSuggestion }> {\n return this.client.post(`/campaigns/${campaignId}/suggestions/${suggestionId}/dismiss`);\n }\n}\n","import { RymiClient } from '../client';\nimport type { Contact } from '@rymi/sdk-types';\n\nexport interface ListContactsParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface ContactListResponse {\n contacts: Contact[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateContactParams {\n phone?: string;\n email?: string;\n name?: string;\n timezone?: string;\n language?: string;\n tags?: string[];\n custom_fields?: Record<string, unknown>;\n consent?: Record<string, boolean>;\n source?: string;\n}\n\nexport interface CreateContactResponse {\n contact: Contact;\n deduped: boolean;\n}\n\nexport interface UpdateContactParams {\n phone?: string;\n email?: string | null;\n name?: string | null;\n timezone?: string | null;\n language?: string | null;\n tags?: string[];\n custom_fields?: Record<string, unknown>;\n consent?: Record<string, boolean>;\n source?: string | null;\n}\n\nexport interface ImportContactsParams {\n contacts?: Array<Record<string, unknown>>;\n csv?: string;\n}\n\nexport interface ImportContactsResponse {\n created: number;\n merged: number;\n invalid: Array<{ row: number; reason: string }>;\n}\n\nexport interface SetConsentParams {\n channel: 'voice' | 'sms' | 'whatsapp' | 'telegram';\n granted: boolean;\n source?: string;\n method?: string;\n}\n\nexport interface SetConsentResponse {\n contact_id: string;\n channel: string;\n consent: { granted: boolean; at: string; source: string; method: string };\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\nexport class ContactsResource {\n constructor(private client: RymiClient) {}\n\n /** List tenant-level contacts, paginated. */\n public async list(params: ListContactsParams = {}): Promise<ContactListResponse> {\n return this.client.get(`/contacts${buildQuery(params)}`);\n }\n\n /**\n * Create a tenant-level contact. If a contact with the same\n * (tenant, phone) already exists, the existing row is returned instead\n * of creating a duplicate — check `deduped` in the response.\n */\n public async create(data: CreateContactParams): Promise<CreateContactResponse> {\n return this.client.post('/contacts', data);\n }\n\n /** Retrieve a single tenant-scoped contact by id. */\n public async get(contactId: string): Promise<{ contact: Contact }> {\n return this.client.get(`/contacts/${contactId}`);\n }\n\n /** Update an existing tenant-scoped contact. Only provided fields change. */\n public async update(contactId: string, data: UpdateContactParams): Promise<{ contact: Contact }> {\n return this.client.patch(`/contacts/${contactId}`, data);\n }\n\n /** Delete a tenant-scoped contact. */\n public async delete(contactId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/contacts/${contactId}`);\n }\n\n /**\n * Bulk import contacts from JSON rows or CSV text. Each row's phone is\n * normalized to E.164 and upserted on (tenant_id, phone); rows with\n * unparseable phones are skipped and reported in `invalid`.\n */\n public async import(data: ImportContactsParams): Promise<ImportContactsResponse> {\n return this.client.post('/contacts/import', data);\n }\n\n /** Record a consent grant or revoke for one channel, with evidence. Also\n * appends an immutable row to the consent_events proof log. */\n public async setConsent(contactId: string, data: SetConsentParams): Promise<SetConsentResponse> {\n return this.client.patch(`/contacts/${contactId}/consent`, data);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface AttestParams {\n kind: 'dnc_external_scrub' | 'ai_disclosure';\n note?: string;\n}\n\nexport interface Attestation {\n id: string;\n tenant_id: string;\n kind: string;\n attested_by: string | null;\n note: string | null;\n created_at: string;\n}\n\nexport interface AttestResponse {\n attestation: Attestation;\n}\n\nexport interface ListAttestationsResponse {\n attestations: Attestation[];\n}\n\nexport class ComplianceResource {\n constructor(private client: RymiClient) {}\n\n /** Record a compliance attestation (append-only). Campaign launch blockers\n * in `attested` mode read the most recent one of the matching `kind`. */\n public async attest(data: AttestParams): Promise<AttestResponse> {\n return this.client.post('/compliance/attestations', data);\n }\n\n /** List the tenant's 50 most recent compliance attestations, newest first. */\n public async listAttestations(): Promise<ListAttestationsResponse> {\n return this.client.get('/compliance/attestations');\n }\n}\n","import { RymiClient } from '../client';\n\n/** A stored API-tool secret. Values are write-only — never returned. */\nexport interface ToolSecretRecord {\n name: string;\n /** The only host this secret is ever sent to. */\n host: string | null;\n}\n\n/**\n * Tenant secrets referenced from call_webhook headers as `{{secrets.NAME}}`.\n * Each secret is pinned to one host and only interpolated into requests to it.\n */\nexport class ToolSecretsResource {\n constructor(private client: RymiClient) {}\n\n public async list(): Promise<{ data: ToolSecretRecord[] }> {\n return this.client.get('/tool-secrets');\n }\n\n /** Create or replace. `name` is UPPER_SNAKE_CASE; `host` is a public hostname. */\n public async set(name: string, data: { value: string; host: string }): Promise<{ data: { name: string } }> {\n return this.client.put(`/tool-secrets/${encodeURIComponent(name)}`, data);\n }\n\n public async delete(name: string): Promise<{ data: { name: string } }> {\n return this.client.delete(`/tool-secrets/${encodeURIComponent(name)}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface Workspace {\n id: string;\n name: string;\n role: 'owner' | 'admin' | 'client';\n /** The agency, for a client workspace. */\n parent_id: string | null;\n operating_country: string | null;\n /** Client workspaces only; absent for the client role. */\n spend_cap_cents_monthly?: number | null;\n current?: boolean;\n}\n\nexport interface CreateWorkspaceParams {\n name: string;\n /** ISO-3166 alpha-2, e.g. \"IN\". */\n operating_country?: string | null;\n /** An agency workspace you run: makes this a client workspace that the agency pays for. */\n parent?: string;\n}\n\nexport interface UpdateWorkspaceParams {\n name?: string;\n operating_country?: string | null;\n /** Client workspaces only. Credits per calendar month (1 credit = $0.01); null removes the cap. */\n spend_cap_cents_monthly?: number | null;\n}\n\nexport interface WorkspaceUsage {\n workspace_id: string;\n /** YYYY-MM, UTC. */\n month: string;\n calls: number;\n minutes: number;\n /** Left out for the client role. */\n credits?: number;\n}\n\nexport interface WorkspaceMember {\n user_id: string;\n email: string | null;\n role: 'owner' | 'admin' | 'client';\n}\n\nexport class WorkspacesResource {\n constructor(private client: RymiClient) {}\n\n public async list(): Promise<{ workspaces: Workspace[] }> {\n return this.client.get('/workspaces');\n }\n\n public async create(data: CreateWorkspaceParams): Promise<{ workspace: Workspace }> {\n return this.client.post('/workspaces', data);\n }\n\n public async update(id: string, data: UpdateWorkspaceParams): Promise<{ ok: true }> {\n return this.client.patch(`/workspaces/${encodeURIComponent(id)}`, data);\n }\n\n /** Calls, minutes and credits for one month (default: this month, UTC). */\n public async usage(id: string, params: { month?: string } = {}): Promise<WorkspaceUsage> {\n const query = params.month ? `?month=${encodeURIComponent(params.month)}` : '';\n return this.client.get(`/workspaces/${encodeURIComponent(id)}/usage${query}`);\n }\n\n public async listMembers(id: string): Promise<{ members: WorkspaceMember[] }> {\n return this.client.get(`/workspaces/${encodeURIComponent(id)}/members`);\n }\n\n /** Someone without a Rymi account gets an invite email. Client workspaces take the client role. */\n public async addMember(id: string, data: { email: string; role?: 'admin' | 'client' }): Promise<{ member: WorkspaceMember }> {\n return this.client.post(`/workspaces/${encodeURIComponent(id)}/members`, data);\n }\n\n public async removeMember(id: string, userId: string): Promise<{ ok: true }> {\n return this.client.delete(`/workspaces/${encodeURIComponent(id)}/members/${encodeURIComponent(userId)}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACwBO,IAAM,YAAN,cAAwB,MAAM;AAAA,EAC1B;AAAA,EACA;AAAA,EAEP,YAAY,SAAiB,QAAiB,MAAe;AACzD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EAChB;AACJ;AAEO,IAAM,aAAN,MAAiB;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,SAAyB;AAEjC,UAAM,MAAM,SAAS,WAAW,OAAO,YAAY,cAAc,QAAQ,IAAI,eAAe;AAE5F,QAAI,CAAC,KAAK;AACN,YAAM,IAAI,MAAM,2HAA2H;AAAA,IAC/I;AAEA,SAAK,SAAS;AACd,SAAK,UAAU,SAAS,WAAW;AACnC,SAAK,YAAY,SAAS,SAAS,WAAW;AAG9C,QAAI,KAAK,QAAQ,SAAS,GAAG,GAAG;AAC5B,WAAK,UAAU,KAAK,QAAQ,MAAM,GAAG,EAAE;AAAA,IAC3C;AAEA,SAAK,YAAY,SAAS,cAClB,OAAO,YAAY,cAAc,QAAQ,IAAI,iBAAiB,WAC/D;AAAA,EACX;AAAA,EAEA,MAAc,QAAW,QAAgB,MAAc,MAAwB;AAC3E,UAAM,MAAM,GAAG,KAAK,OAAO,GAAG,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI,EAAE;AAEtE,UAAM,UAAkC;AAAA,MACpC,iBAAiB,UAAU,KAAK,MAAM;AAAA,MACtC,UAAU;AAAA,MACV,cAAc;AAAA,IAClB;AACA,QAAI,KAAK,UAAW,SAAQ,gBAAgB,IAAI,KAAK;AAErD,UAAM,OAAoB;AAAA,MACtB;AAAA,MACA;AAAA,IACJ;AAEA,QAAI,MAAM;AACN,cAAQ,cAAc,IAAI;AAC1B,WAAK,OAAO,KAAK,UAAU,IAAI;AAAA,IACnC;AAEA,QAAI;AACA,YAAM,WAAW,MAAM,KAAK,UAAU,KAAK,IAAI;AAC/C,YAAM,SAAS,SAAS,QAAQ,IAAI,cAAc,GAAG,SAAS,kBAAkB;AAEhF,YAAM,OAAO,SAAS,MAAM,SAAS,KAAK,IAAI,MAAM,SAAS,KAAK;AAElE,UAAI,CAAC,SAAS,IAAI;AACd,cAAM,UAAW,QAAQ,OAAO,SAAS,YAAY,WAAW,OAAS,KAAa,QACtE,OAAO,SAAS,WAAW,OAAO,SAAS;AAC3D,cAAM,IAAI,UAAU,SAAS,SAAS,QAAS,QAAQ,OAAO,SAAS,YAAY,UAAU,OAAS,KAAa,OAAO,MAAS;AAAA,MACvI;AAEA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,UAAI,iBAAiB,WAAW;AAC5B,cAAM;AAAA,MACV;AACA,YAAM,IAAI,UAAU,kBAAkB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAAA,IAClG;AAAA,EACJ;AAAA,EAEO,IAAO,MAA0B;AACpC,WAAO,KAAK,QAAW,OAAO,IAAI;AAAA,EACtC;AAAA,EAEO,KAAQ,MAAc,MAAwB;AACjD,WAAO,KAAK,QAAW,QAAQ,MAAM,IAAI;AAAA,EAC7C;AAAA,EAEO,IAAO,MAAc,MAAwB;AAChD,WAAO,KAAK,QAAW,OAAO,MAAM,IAAI;AAAA,EAC5C;AAAA,EAEO,MAAS,MAAc,MAAwB;AAClD,WAAO,KAAK,QAAW,SAAS,MAAM,IAAI;AAAA,EAC9C;AAAA,EAEO,OAAU,MAA0B;AACvC,WAAO,KAAK,QAAW,UAAU,IAAI;AAAA,EACzC;AACJ;;;AC2FA,SAAS,sBAAuE,MAAyD;AACrI,QAAM,EAAE,QAAQ,GAAG,KAAK,IAAI;AAC5B,SAAO;AAAA,IACH,GAAG;AAAA,IACH,GAAI,CAAC,KAAK,iBAAiB,SAAS,EAAE,eAAe,OAAO,IAAI,CAAC;AAAA,EACrE;AACJ;AAEO,IAAM,iBAAN,MAAqB;AAAA,EACxB,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA;AAAA;AAAA,EAKzC,MAAa,KAAK,SAA8C,CAAC,GAA+B;AAC5F,UAAM,eAAe,IAAI,gBAAgB;AACzC,QAAI,OAAO,UAAU,OAAW,cAAa,IAAI,SAAS,OAAO,OAAO,KAAK,CAAC;AAC9E,QAAI,OAAO,WAAW,OAAW,cAAa,IAAI,UAAU,OAAO,OAAO,MAAM,CAAC;AACjF,UAAM,QAAQ,aAAa,SAAS;AACpC,WAAO,KAAK,OAAO,IAAuB,UAAU,QAAQ,IAAI,KAAK,KAAK,EAAE,EAAE;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,SAAS,SAAiC;AACnD,WAAO,KAAK,OAAO,IAAW,WAAW,OAAO,EAAE;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,MAAqE;AACrF,WAAO,KAAK,OAAO,KAAwC,WAAW,sBAAsB,IAAI,CAAC;AAAA,EACrG;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,SAAiB,MAAyD;AAC1F,WAAO,KAAK,OAAO,IAA2B,WAAW,OAAO,IAAI,sBAAsB,IAAI,CAAC;AAAA,EACnG;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,SAA6D;AAC7E,WAAO,KAAK,OAAO,OAA0C,WAAW,OAAO,EAAE;AAAA,EACrF;AAAA,EAEA,MAAa,aAAwD;AACjE,WAAO,KAAK,OAAO,IAAI,qBAAqB;AAAA,EAChD;AAAA,EAEA,MAAa,SAAS,MAAuF;AACzG,WAAO,KAAK,OAAO,KAAK,oBAAoB,IAAI;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,UAAU,SAAiB,SAA+D,CAAC,GAAmC;AACvI,UAAM,eAAe,IAAI,gBAAgB;AACzC,QAAI,OAAO,UAAU,OAAW,cAAa,IAAI,SAAS,OAAO,OAAO,KAAK,CAAC;AAC9E,QAAI,OAAO,WAAW,OAAW,cAAa,IAAI,UAAU,OAAO,OAAO,MAAM,CAAC;AACjF,QAAI,OAAO,OAAQ,cAAa,IAAI,UAAU,OAAO,MAAM;AAC3D,UAAM,QAAQ,aAAa,SAAS;AACpC,WAAO,KAAK,OAAO,IAA2B,WAAW,OAAO,SAAS,QAAQ,IAAI,KAAK,KAAK,EAAE,EAAE;AAAA,EACvG;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,MAAM,SAA6D;AAC5E,WAAO,KAAK,OAAO,KAAwC,WAAW,OAAO,UAAU,CAAC,CAAC;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,gBAAgB,QAA6D;AACtF,WAAO,KAAK,OAAO,KAAK,4BAA4B,MAAM;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,QAAQ,SAAgD;AACjE,WAAO,KAAK,OAAO,KAA2B,WAAW,OAAO,YAAY,CAAC,CAAC;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,aAAa,QAA2D;AACjF,WAAO,KAAK,OAAO,KAAK,yBAAyB,MAAM;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,cAAc,QAA6D;AACpF,WAAO,KAAK,OAAO,KAAK,0BAA0B,MAAM;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,aAAa,QAA0D;AAChF,WAAO,KAAK,OAAO,KAAK,yBAAyB,MAAM;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,qBAAqB,SAA+D;AAC7F,WAAO,KAAK,OAAO,IAAI,WAAW,OAAO,oBAAoB;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,mBAAmB,SAAiB,MAA8D;AAC3G,WAAO,KAAK,OAAO,KAAK,WAAW,OAAO,sBAAsB,IAAI;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,sBAAsB,SAAiB,UAAgD;AAChG,WAAO,KAAK,OAAO,OAAO,WAAW,OAAO,sBAAsB,QAAQ,EAAE;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,aAAa,SAAkF;AACxG,UAAM,MAAM,MAAM,KAAK,OAAO,IAA4D,WAAW,OAAO,UAAU;AACtH,WAAO,EAAE,cAAc,IAAI,cAAc,MAAM,IAAI,KAAK;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,aAAa,SAAiB,WAAmC,CAAC,GAAsC;AACjH,WAAO,KAAK,OAAO,IAAI,WAAW,OAAO,eAAe,QAAQ;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,oBAAoB,SAAoD;AACjF,WAAO,KAAK,OAAO,KAAK,WAAW,OAAO,0BAA0B,CAAC,CAAC;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,YAAY,SAAiB,SAA6B,CAAC,GAAwC;AAC5G,UAAM,QAAQ,OAAO,QAAQ,UAAU,mBAAmB,OAAO,KAAK,CAAC,KAAK;AAC5E,WAAO,KAAK,OAAO,IAAI,WAAW,OAAO,WAAW,KAAK,EAAE;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,WAAW,SAAiB,UAAoF;AACzH,WAAO,KAAK,OAAO,KAAK,WAAW,OAAO,YAAY,QAAQ,SAAS,CAAC,CAAC;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,SACT,SACA,SAA2D,CAAC,GAChC;AAC5B,UAAM,QAAQ,IAAI,gBAAgB;AAClC,QAAI,OAAO,KAAM,OAAM,IAAI,QAAQ,OAAO,IAAI;AAC9C,QAAI,OAAO,MAAO,OAAM,IAAI,SAAS,GAAG;AACxC,UAAM,KAAK,MAAM,SAAS;AAC1B,WAAO,KAAK,OAAO,KAAK,WAAW,OAAO,aAAa,KAAK,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,aAAa,QAKO;AAC7B,WAAO,KAAK,OAAO,KAAK,uBAAuB,MAAM;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,aAAa,SAA+C;AACrE,WAAO,KAAK,OAAO,IAAI,WAAW,OAAO,aAAa;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,WAAW,SAAiB,OAA6C;AAClF,WAAO,KAAK,OAAO,IAAI,WAAW,OAAO,eAAe,KAAK,EAAE;AAAA,EACnE;AACJ;;;ACvUA,SAAS,WAAW,QAA6B;AAC7C,QAAM,eAAe,IAAI,gBAAgB;AACzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC/C,QAAI,UAAU,UAAa,UAAU,MAAM;AACvC,mBAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,IACvC;AAAA,EACJ;AACA,QAAM,QAAQ,aAAa,SAAS;AACpC,SAAO,QAAQ,IAAI,KAAK,KAAK;AACjC;AAEO,IAAM,gBAAN,MAAoB;AAAA,EACvB,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA;AAAA;AAAA,EAKzC,MAAa,KAAK,SAA0B,CAAC,GAA8B;AACvE,WAAO,KAAK,OAAO,IAAsB,SAAS,WAAW,MAAM,CAAC,EAAE;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,SAA0B,CAAC,GAA8B;AACzE,WAAO,KAAK,OAAO,IAAsB,gBAAgB,WAAW,MAAM,CAAC,EAAE;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,SAAS,QAAqC;AACvD,WAAO,KAAK,OAAO,IAAgB,UAAU,MAAM,EAAE;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,MAAqD;AACrE,WAAO,KAAK,OAAO,KAAK,UAAU,IAAI;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,OAAO,MAA+G;AAC/H,WAAO,KAAK,OAAO,KAAK,iBAAiB,IAAI;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,MAAM,MAA2F;AAC1G,WAAO,KAAK,OAAO,KAAK,gBAAgB,IAAI;AAAA,EAChD;AAAA,EAEA,MAAa,QAAQ,QAA8C;AAC/D,WAAO,KAAK,OAAO,IAAI,UAAU,MAAM,UAAU;AAAA,EACrD;AAAA,EAEA,MAAa,WAAW,QAA8C;AAClE,WAAO,KAAK,OAAO,IAAI,UAAU,MAAM,aAAa;AAAA,EACxD;AAAA,EAEA,MAAa,UAAU,QAA8C;AACjE,WAAO,KAAK,OAAO,IAAI,UAAU,MAAM,YAAY;AAAA,EACvD;AAAA,EAEA,MAAa,UAAU,QAA8C;AACjE,WAAO,KAAK,OAAO,KAAK,UAAU,MAAM,YAAY;AAAA,EACxD;AAAA;AAAA,EAGA,MAAa,IAAI,QAA0E;AACvF,WAAO,KAAK,OAAO,KAAK,UAAU,MAAM,MAAM;AAAA,EAClD;AAAA;AAAA,EAGA,MAAa,gBACT,QACA,MAC2B;AAC3B,WAAO,KAAK,OAAO,KAAK,UAAU,MAAM,iBAAiB,IAAI;AAAA,EACjE;AAAA,EAEA,MAAa,aAA8C;AACvD,WAAO,KAAK,OAAO,IAAI,oBAAoB;AAAA,EAC/C;AACJ;;;ACnLA,SAASA,YAAW,QAA6B;AAC7C,QAAM,KAAK,IAAI,gBAAgB;AAC/B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AACzC,QAAI,MAAM,UAAa,MAAM,KAAM,IAAG,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,EAC1D;AACA,QAAM,IAAI,GAAG,SAAS;AACtB,SAAO,IAAI,IAAI,CAAC,KAAK;AACzB;AAMO,IAAM,cAAN,MAAkB;AAAA,EACrB,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA,EAGzC,MAAa,KAAK,SAA8C,CAAC,GAA6B;AAC1F,WAAO,KAAK,OAAO,IAAqB,OAAOA,YAAW,MAAM,CAAC,EAAE;AAAA,EACvE;AAAA;AAAA,EAGA,MAAa,IAAI,MAA2G;AACxH,WAAO,KAAK,OAAO,KAAK,QAAQ,IAAI;AAAA,EACxC;AAAA;AAAA,EAGA,MAAa,SAAS,MAAiJ;AACnK,WAAO,KAAK,OAAO,KAAK,cAAc,IAAI;AAAA,EAC9C;AAAA;AAAA,EAGA,MAAa,MAAM,MAAyH;AACxI,WAAO,KAAK,OAAO,KAAK,cAAc,IAAI;AAAA,EAC9C;AAAA;AAAA,EAGA,MAAa,OAAO,OAA8D;AAC9E,WAAO,KAAK,OAAO,OAAO,QAAQ,mBAAmB,KAAK,CAAC,EAAE;AAAA,EACjE;AACJ;;;AClCO,IAAM,kBAAN,MAAsB;AAAA,EACzB,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA;AAAA;AAAA,EAKzC,MAAa,KAAK,SAA8C,CAAC,GAAuF;AACpJ,UAAM,eAAe,IAAI,gBAAgB;AACzC,QAAI,OAAO,UAAU,OAAW,cAAa,IAAI,SAAS,OAAO,OAAO,KAAK,CAAC;AAC9E,QAAI,OAAO,WAAW,OAAW,cAAa,IAAI,UAAU,OAAO,OAAO,MAAM,CAAC;AACjF,UAAM,QAAQ,aAAa,SAAS;AACpC,WAAO,KAAK,OAAO,IAAI,WAAW,QAAQ,IAAI,KAAK,KAAK,EAAE,EAAE;AAAA,EAChE;AAAA,EAEA,MAAa,SAAS,QAAgB,SAAgC,CAAC,GAAuH;AAC1L,WAAO,KAAK,OAAO,KAAK,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAC;AAAA,EAC7D;AAAA,EAEA,MAAa,OAAO,QAAgB,SAA4H;AAC5J,WAAO,KAAK,OAAO,KAAK,YAAY,mBAAmB,MAAM,CAAC,WAAW,EAAE,UAAU,QAAQ,CAAC;AAAA,EAClG;AAAA;AAAA,EAGA,MAAa,OAAO,QAAiE;AACjF,WAAO,KAAK,OAAO,KAAK,YAAY,mBAAmB,MAAM,CAAC,SAAS;AAAA,EAC3E;AAAA;AAAA,EAGA,MAAa,iBAAiB,QAA8E;AACxG,WAAO,KAAK,OAAO,KAAK,YAAY,mBAAmB,MAAM,CAAC,UAAU;AAAA,EAC5E;AAAA,EAEA,MAAa,OAAO,QAAgE;AAChF,WAAO,KAAK,OAAO,OAAO,YAAY,mBAAmB,MAAM,CAAC,EAAE;AAAA,EACtE;AACJ;;;AChEA,aAAwB;AAWxB,SAASC,YAAW,QAA6B;AAC7C,QAAM,KAAK,IAAI,gBAAgB;AAC/B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AACzC,QAAI,MAAM,UAAa,MAAM,KAAM,IAAG,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,EAC1D;AACA,QAAM,IAAI,GAAG,SAAS;AACtB,SAAO,IAAI,IAAI,CAAC,KAAK;AACzB;AAEO,IAAM,mBAAN,MAAuB;AAAA,EAC1B,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA,EAGzC,MAAa,KAAK,SAA8C,CAAC,GAAyF;AACtJ,WAAO,KAAK,OAAO,IAAI,YAAYA,YAAW,MAAM,CAAC,EAAE;AAAA,EAC3D;AAAA;AAAA,EAGA,MAAa,OAAO,MAAkH;AAClI,WAAO,KAAK,OAAO,KAAK,aAAa,IAAI;AAAA,EAC7C;AAAA;AAAA,EAGA,MAAa,OAAO,IAAY,MAAqI;AACjK,WAAO,KAAK,OAAO,MAAM,aAAa,EAAE,IAAI,IAAI;AAAA,EACpD;AAAA;AAAA,EAGA,MAAa,OAAO,IAAwD;AACxE,WAAO,KAAK,OAAO,OAAO,aAAa,EAAE,EAAE;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeO,gBACH,SACA,iBACA,iBACA,eACA,kBAAkB,KACX;AAEP,UAAM,YAAY,SAAS,iBAAiB,EAAE;AAC9C,QAAI,MAAM,SAAS,GAAG;AAClB,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACnD;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,MAAM,YAAY,iBAAiB;AACnC,YAAM,IAAI,MAAM,uDAAuD;AAAA,IAC3E;AAGA,UAAM,mBAAmB,GAAG,SAAS,IAAI,OAAO;AAGhD,UAAM,oBACD,kBAAW,UAAU,aAAa,EAClC,OAAO,kBAAkB,MAAM,EAC/B,OAAO,KAAK;AAGjB,QAAI;AACA,YAAM,UAAiB;AAAA,QACnB,OAAO,KAAK,eAAe;AAAA,QAC3B,OAAO,KAAK,iBAAiB;AAAA,MACjC;AAEA,UAAI,CAAC,SAAS;AACV,cAAM,IAAI,MAAM,2DAA2D;AAAA,MAC/E;AAEA,aAAO;AAAA,IACX,SAAS,KAAK;AACV,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC/E;AAAA,EACJ;AACJ;;;AC9EO,IAAM,eAAN,MAAmB;AAAA,EACtB,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA,EAEzC,MAAa,kBAA6D;AACtE,WAAO,KAAK,OAAO,IAAI,mBAAmB;AAAA,EAC9C;AAAA,EAEA,MAAa,kBAAkB,MAAyF;AACpH,WAAO,KAAK,OAAO,KAAK,qBAAqB,IAAI;AAAA,EACrD;AAAA,EAEA,MAAa,kBAAkB,IAAwC;AACnE,WAAO,KAAK,OAAO,OAAO,qBAAqB,EAAE,EAAE;AAAA,EACvD;AACJ;;;ACpBO,IAAM,oBAAN,MAAwB;AAAA,EAC3B,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA,EAEzC,MAAa,QAAQ,MAAoI;AACrJ,WAAO,KAAK,OAAO,KAAK,sBAAsB,IAAI;AAAA,EACtD;AAAA,EAEA,MAAa,aAAmE;AAC5E,WAAO,KAAK,OAAO,KAAK,uBAAuB;AAAA,EACnD;AAAA,EAEA,MAAa,SAA2I;AACpJ,WAAO,KAAK,OAAO,IAAI,mBAAmB;AAAA,EAC9C;AAAA,EAEA,MAAa,UAAuC;AAChD,WAAO,KAAK,OAAO,IAAI,oBAAoB;AAAA,EAC/C;AACJ;;;ACbO,IAAM,kBAAN,MAAsB;AAAA,EACzB,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOzC,MAAa,eAAsC;AAC/C,WAAO,KAAK,OAAO,IAAkB,wBAAwB;AAAA,EACjE;AAAA;AAAA,EAGA,MAAa,SAAS,OAAkG,CAAC,GAAiC;AACtJ,WAAO,KAAK,OAAO,KAAK,qBAAqB,IAAI;AAAA,EACrD;AAAA;AAAA,EAGA,MAAa,gBAAgB,MAA+F;AACxH,WAAO,KAAK,OAAO,IAAI,0BAA0B,IAAI;AAAA,EACzD;AAAA;AAAA,EAGA,MAAa,UAAU,MAA+G;AAClI,WAAO,KAAK,OAAO,IAAI,mBAAmB,IAAI;AAAA,EAClD;AACJ;;;ACjCO,IAAM,oBAAN,MAAwB;AAAA,EAC3B,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMzC,MAAa,OAAwE;AACjF,WAAO,KAAK,OAAO,IAAI,kBAAkB;AAAA,EAC7C;AACJ;;;ACXA,SAASC,YAAW,QAA6B;AAC7C,QAAM,KAAK,IAAI,gBAAgB;AAC/B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AACzC,QAAI,MAAM,UAAa,MAAM,KAAM,IAAG,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,EAC1D;AACA,QAAM,IAAI,GAAG,SAAS;AACtB,SAAO,IAAI,IAAI,CAAC,KAAK;AACzB;AA4GA,IAAM,0BAAN,MAA8B;AAAA,EAC1B,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA,EAGzC,MAAa,KAAK,YAAoB,SAAoC,CAAC,GAAwC;AAC/G,WAAO,KAAK,OAAO,IAAI,cAAc,UAAU,WAAWA,YAAW,MAAM,CAAC,EAAE;AAAA,EAClF;AAAA;AAAA,EAGA,MAAa,IAAI,YAAoB,MAAwE;AACzG,WAAO,KAAK,OAAO,KAAK,cAAc,UAAU,YAAY,IAAI;AAAA,EACpE;AAAA;AAAA,EAGA,MAAa,OAAO,YAAoB,MAA2E;AAC/G,WAAO,KAAK,OAAO,KAAK,cAAc,UAAU,mBAAmB,IAAI;AAAA,EAC3E;AAAA;AAAA,EAGA,MAAa,OAAO,YAAoB,UAAkB,MAAuE;AAC7H,WAAO,KAAK,OAAO,MAAM,cAAc,UAAU,YAAY,QAAQ,IAAI,IAAI;AAAA,EACjF;AAAA;AAAA,EAGA,MAAa,OAAO,YAAoB,UAA8D;AAClG,WAAO,KAAK,OAAO,OAAO,cAAc,UAAU,YAAY,QAAQ,EAAE;AAAA,EAC5E;AACJ;AAsCA,IAAM,yBAAN,MAA6B;AAAA,EACzB,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA,EAGzC,MAAa,KAAK,YAAoB,SAAmC,CAAC,GAAuC;AAC7G,WAAO,KAAK,OAAO,IAAI,cAAc,UAAU,UAAUA,YAAW,MAAM,CAAC,EAAE;AAAA,EACjF;AAAA;AAAA,EAGA,MAAa,OAAO,YAAoB,MAAoE;AACxG,WAAO,KAAK,OAAO,KAAK,cAAc,UAAU,WAAW,IAAI;AAAA,EACnE;AAAA;AAAA,EAGA,MAAa,OAAO,YAAoB,SAAiB,MAAoE;AACzH,WAAO,KAAK,OAAO,MAAM,cAAc,UAAU,WAAW,OAAO,IAAI,IAAI;AAAA,EAC/E;AAAA;AAAA,EAGA,MAAa,OAAO,YAAoB,SAA6D;AACjG,WAAO,KAAK,OAAO,OAAO,cAAc,UAAU,WAAW,OAAO,EAAE;AAAA,EAC1E;AACJ;AA8HA,IAAM,yBAAN,MAA6B;AAAA,EACzB,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA,EAGzC,MAAa,IAAI,YAAgE;AAC7E,WAAO,KAAK,OAAO,IAAI,cAAc,UAAU,SAAS;AAAA,EAC5D;AAAA;AAAA,EAGA,MAAa,IAAI,YAAoB,WAAmC,CAAC,GAA4D;AACjI,WAAO,KAAK,OAAO,IAAI,cAAc,UAAU,WAAW,QAAQ;AAAA,EACtE;AAAA;AAAA,EAGA,MAAa,OAAO,YAAsE;AACtF,WAAO,KAAK,OAAO,KAAK,cAAc,UAAU,kBAAkB,CAAC,CAAC;AAAA,EACxE;AAAA;AAAA,EAGA,MAAa,QAAQ,YAAmC;AACpD,WAAO,KAAK,OAAO,OAAO,cAAc,UAAU,SAAS;AAAA,EAC/D;AACJ;AAIO,IAAM,oBAAN,MAAwB;AAAA,EAK3B,YAAoB,QAAoB;AAApB;AAChB,SAAK,UAAU,IAAI,wBAAwB,MAAM;AACjD,SAAK,SAAS,IAAI,uBAAuB,MAAM;AAC/C,SAAK,SAAS,IAAI,uBAAuB,MAAM;AAAA,EACnD;AAAA,EARO;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EASP,MAAa,KAAK,SAA8B,CAAC,GAAkC;AAC/E,WAAO,KAAK,OAAO,IAAI,aAAaA,YAAW,MAAM,CAAC,EAAE;AAAA,EAC5D;AAAA;AAAA,EAGA,MAAa,OAAO,MAA6D;AAC7E,WAAO,KAAK,OAAO,KAAK,cAAc,IAAI;AAAA,EAC9C;AAAA;AAAA,EAGA,MAAa,IAAI,YAAqD;AAClE,WAAO,KAAK,OAAO,IAAI,cAAc,UAAU,EAAE;AAAA,EACrD;AAAA;AAAA,EAGA,MAAa,OAAO,YAAoB,MAA6D;AACjG,WAAO,KAAK,OAAO,MAAM,cAAc,UAAU,IAAI,IAAI;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,OAAO,YAAqD;AACrE,WAAO,KAAK,OAAO,KAAK,cAAc,UAAU,SAAS;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAa,eAAe,YAAiF;AACzG,WAAO,KAAK,OAAO,IAAI,cAAc,UAAU,kBAAkB;AAAA,EACrE;AAAA;AAAA,EAGA,MAAa,MAAM,YAAqD;AACpE,WAAO,KAAK,OAAO,KAAK,cAAc,UAAU,QAAQ;AAAA,EAC5D;AAAA;AAAA,EAGA,MAAa,OAAO,YAAqD;AACrE,WAAO,KAAK,OAAO,KAAK,cAAc,UAAU,SAAS;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAa,QAAQ,YAAqD;AACtE,WAAO,KAAK,OAAO,KAAK,cAAc,UAAU,UAAU;AAAA,EAC9D;AAAA;AAAA,EAGA,MAAa,OAAO,YAAqD;AACrE,WAAO,KAAK,OAAO,IAAI,cAAc,UAAU,SAAS;AAAA,EAC5D;AAAA;AAAA,EAGA,MAAa,SAAS,YAAoB,SAAqC,CAAC,GAAyC;AACrH,WAAO,KAAK,OAAO,IAAI,cAAc,UAAU,YAAYA,YAAW,MAAM,CAAC,EAAE;AAAA,EACnF;AAAA;AAAA,EAGA,MAAa,QAAQ,YAAoB,SAAoC,CAAC,GAAuC;AACjH,WAAO,KAAK,OAAO,IAAI,cAAc,UAAU,WAAWA,YAAW,MAAM,CAAC,EAAE;AAAA,EAClF;AAAA;AAAA,EAGA,MAAa,UAAU,YAAoB,SAAsC,CAAC,GAA0C;AACxH,WAAO,KAAK,OAAO,IAAI,cAAc,UAAU,aAAaA,YAAW,MAAM,CAAC,EAAE;AAAA,EACpF;AAAA;AAAA,EAGA,MAAa,QAAQ,YAAsD;AACvE,WAAO,KAAK,OAAO,KAAK,cAAc,UAAU,UAAU;AAAA,EAC9D;AAAA;AAAA,EAGA,MAAa,YAAY,YAAoB,SAAwC,CAAC,GAA4C;AAC9H,WAAO,KAAK,OAAO,IAAI,cAAc,UAAU,eAAeA,YAAW,MAAM,CAAC,EAAE;AAAA,EACtF;AAAA;AAAA,EAGA,MAAa,iBAAiB,YAAoB,cAAmE;AACjH,WAAO,KAAK,OAAO,KAAK,cAAc,UAAU,gBAAgB,YAAY,SAAS;AAAA,EACzF;AAAA;AAAA,EAGA,MAAa,kBAAkB,YAAoB,cAAmE;AAClH,WAAO,KAAK,OAAO,KAAK,cAAc,UAAU,gBAAgB,YAAY,UAAU;AAAA,EAC1F;AACJ;;;AC7YA,SAASC,YAAW,QAA6B;AAC7C,QAAM,KAAK,IAAI,gBAAgB;AAC/B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AACzC,QAAI,MAAM,UAAa,MAAM,KAAM,IAAG,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,EAC1D;AACA,QAAM,IAAI,GAAG,SAAS;AACtB,SAAO,IAAI,IAAI,CAAC,KAAK;AACzB;AAEO,IAAM,mBAAN,MAAuB;AAAA,EAC1B,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA,EAGzC,MAAa,KAAK,SAA6B,CAAC,GAAiC;AAC7E,WAAO,KAAK,OAAO,IAAI,YAAYA,YAAW,MAAM,CAAC,EAAE;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,OAAO,MAA2D;AAC3E,WAAO,KAAK,OAAO,KAAK,aAAa,IAAI;AAAA,EAC7C;AAAA;AAAA,EAGA,MAAa,IAAI,WAAkD;AAC/D,WAAO,KAAK,OAAO,IAAI,aAAa,SAAS,EAAE;AAAA,EACnD;AAAA;AAAA,EAGA,MAAa,OAAO,WAAmB,MAA0D;AAC7F,WAAO,KAAK,OAAO,MAAM,aAAa,SAAS,IAAI,IAAI;AAAA,EAC3D;AAAA;AAAA,EAGA,MAAa,OAAO,WAA+D;AAC/E,WAAO,KAAK,OAAO,OAAO,aAAa,SAAS,EAAE;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,OAAO,MAA6D;AAC7E,WAAO,KAAK,OAAO,KAAK,oBAAoB,IAAI;AAAA,EACpD;AAAA;AAAA;AAAA,EAIA,MAAa,WAAW,WAAmB,MAAqD;AAC5F,WAAO,KAAK,OAAO,MAAM,aAAa,SAAS,YAAY,IAAI;AAAA,EACnE;AACJ;;;ACnGO,IAAM,qBAAN,MAAyB;AAAA,EAC5B,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA;AAAA;AAAA,EAIzC,MAAa,OAAO,MAA6C;AAC7D,WAAO,KAAK,OAAO,KAAK,4BAA4B,IAAI;AAAA,EAC5D;AAAA;AAAA,EAGA,MAAa,mBAAsD;AAC/D,WAAO,KAAK,OAAO,IAAI,0BAA0B;AAAA,EACrD;AACJ;;;ACxBO,IAAM,sBAAN,MAA0B;AAAA,EAC7B,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA,EAEzC,MAAa,OAA8C;AACvD,WAAO,KAAK,OAAO,IAAI,eAAe;AAAA,EAC1C;AAAA;AAAA,EAGA,MAAa,IAAI,MAAc,MAA4E;AACvG,WAAO,KAAK,OAAO,IAAI,iBAAiB,mBAAmB,IAAI,CAAC,IAAI,IAAI;AAAA,EAC5E;AAAA,EAEA,MAAa,OAAO,MAAmD;AACnE,WAAO,KAAK,OAAO,OAAO,iBAAiB,mBAAmB,IAAI,CAAC,EAAE;AAAA,EACzE;AACJ;;;ACiBO,IAAM,qBAAN,MAAyB;AAAA,EAC5B,YAAoB,QAAoB;AAApB;AAAA,EAAqB;AAAA,EAEzC,MAAa,OAA6C;AACtD,WAAO,KAAK,OAAO,IAAI,aAAa;AAAA,EACxC;AAAA,EAEA,MAAa,OAAO,MAAgE;AAChF,WAAO,KAAK,OAAO,KAAK,eAAe,IAAI;AAAA,EAC/C;AAAA,EAEA,MAAa,OAAO,IAAY,MAAoD;AAChF,WAAO,KAAK,OAAO,MAAM,eAAe,mBAAmB,EAAE,CAAC,IAAI,IAAI;AAAA,EAC1E;AAAA;AAAA,EAGA,MAAa,MAAM,IAAY,SAA6B,CAAC,GAA4B;AACrF,UAAM,QAAQ,OAAO,QAAQ,UAAU,mBAAmB,OAAO,KAAK,CAAC,KAAK;AAC5E,WAAO,KAAK,OAAO,IAAI,eAAe,mBAAmB,EAAE,CAAC,SAAS,KAAK,EAAE;AAAA,EAChF;AAAA,EAEA,MAAa,YAAY,IAAqD;AAC1E,WAAO,KAAK,OAAO,IAAI,eAAe,mBAAmB,EAAE,CAAC,UAAU;AAAA,EAC1E;AAAA;AAAA,EAGA,MAAa,UAAU,IAAY,MAA0F;AACzH,WAAO,KAAK,OAAO,KAAK,eAAe,mBAAmB,EAAE,CAAC,YAAY,IAAI;AAAA,EACjF;AAAA,EAEA,MAAa,aAAa,IAAY,QAAuC;AACzE,WAAO,KAAK,OAAO,OAAO,eAAe,mBAAmB,EAAE,CAAC,YAAY,mBAAmB,MAAM,CAAC,EAAE;AAAA,EAC3G;AACJ;;;AfLA,0BAAc,4BAzEd;AAgBO,IAAM,OAAN,MAAW;AAAA,EACN;AAAA,EAED;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEP,YAAY,SAAyB;AACjC,SAAK,SAAS,IAAI,WAAW,OAAO;AAGpC,SAAK,SAAS,IAAI,eAAe,KAAK,MAAM;AAC5C,SAAK,QAAQ,IAAI,cAAc,KAAK,MAAM;AAC1C,SAAK,MAAM,IAAI,YAAY,KAAK,MAAM;AACtC,SAAK,UAAU,IAAI,gBAAgB,KAAK,MAAM;AAC9C,SAAK,WAAW,IAAI,iBAAiB,KAAK,MAAM;AAChD,SAAK,OAAO,IAAI,aAAa,KAAK,MAAM;AACxC,SAAK,YAAY,IAAI,kBAAkB,KAAK,MAAM;AAClD,SAAK,UAAU,IAAI,gBAAgB,KAAK,MAAM;AAC9C,SAAK,YAAY,IAAI,kBAAkB,KAAK,MAAM;AAClD,SAAK,YAAY,IAAI,kBAAkB,KAAK,MAAM;AAClD,SAAK,WAAW,IAAI,iBAAiB,KAAK,MAAM;AAChD,SAAK,aAAa,IAAI,mBAAmB,KAAK,MAAM;AACpD,SAAK,cAAc,IAAI,oBAAoB,KAAK,MAAM;AACtD,SAAK,aAAa,IAAI,mBAAmB,KAAK,MAAM;AAAA,EACxD;AACJ;AAqBA,IAAO,gBAAQ;","names":["buildQuery","buildQuery","buildQuery","buildQuery"]}
package/dist/index.mjs CHANGED
@@ -822,6 +822,21 @@ var WorkspacesResource = class {
822
822
  async update(id, data) {
823
823
  return this.client.patch(`/workspaces/${encodeURIComponent(id)}`, data);
824
824
  }
825
+ /** Calls, minutes and credits for one month (default: this month, UTC). */
826
+ async usage(id, params = {}) {
827
+ const query = params.month ? `?month=${encodeURIComponent(params.month)}` : "";
828
+ return this.client.get(`/workspaces/${encodeURIComponent(id)}/usage${query}`);
829
+ }
830
+ async listMembers(id) {
831
+ return this.client.get(`/workspaces/${encodeURIComponent(id)}/members`);
832
+ }
833
+ /** Someone without a Rymi account gets an invite email. Client workspaces take the client role. */
834
+ async addMember(id, data) {
835
+ return this.client.post(`/workspaces/${encodeURIComponent(id)}/members`, data);
836
+ }
837
+ async removeMember(id, userId) {
838
+ return this.client.delete(`/workspaces/${encodeURIComponent(id)}/members/${encodeURIComponent(userId)}`);
839
+ }
825
840
  };
826
841
 
827
842
  // src/index.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts","../src/resources/agents.ts","../src/resources/calls.ts","../src/resources/dnc.ts","../src/resources/numbers.ts","../src/resources/webhooks.ts","../src/resources/keys.ts","../src/resources/telephony.ts","../src/resources/billing.ts","../src/resources/templates.ts","../src/resources/campaigns.ts","../src/resources/contacts.ts","../src/resources/compliance.ts","../src/resources/toolSecrets.ts","../src/resources/workspaces.ts","../src/index.ts"],"sourcesContent":["export interface ClientOptions {\n /**\n * The Rymi secret API key (`rymi_...`)\n */\n apiKey?: string;\n \n /**\n * The base URL for the API. Defaults to `https://api.rymi.live/v1`\n */\n baseURL?: string;\n\n /**\n * Custom fetch implementation. Lets embedders route requests without a\n * network socket (e.g. Fastify app.inject). Defaults to global fetch.\n */\n fetch?: typeof globalThis.fetch;\n\n /**\n * Act in this workspace (sent as `Rymi-Workspace`). Defaults to the\n * `RYMI_WORKSPACE` environment variable, else the key's own workspace.\n */\n workspace?: string;\n}\n\nexport class RymiError extends Error {\n public status?: number;\n public code?: string;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.name = 'RymiError';\n this.status = status;\n this.code = code;\n }\n}\n\nexport class RymiClient {\n private apiKey: string;\n private baseURL: string;\n private fetchImpl: typeof globalThis.fetch;\n private workspace?: string;\n\n constructor(options?: ClientOptions) {\n // Prefer explicit option, then fallback to environment variable\n const key = options?.apiKey || (typeof process !== 'undefined' ? process.env.RYMI_API_KEY : undefined);\n\n if (!key) {\n throw new Error('The Rymi API Key must be set either by passing `apiKey` to the client or setting the `RYMI_API_KEY` environment variable.');\n }\n\n this.apiKey = key;\n this.baseURL = options?.baseURL || 'https://api.rymi.live/v1';\n this.fetchImpl = options?.fetch ?? globalThis.fetch;\n\n // Remove trailing slashes\n if (this.baseURL.endsWith('/')) {\n this.baseURL = this.baseURL.slice(0, -1);\n }\n\n this.workspace = options?.workspace\n || (typeof process !== 'undefined' ? process.env.RYMI_WORKSPACE : undefined)\n || undefined;\n }\n\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\n const url = `${this.baseURL}${path.startsWith('/') ? path : `/${path}`}`;\n \n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Accept': 'application/json',\n 'User-Agent': 'rymi-node/1.0.0'\n };\n if (this.workspace) headers['Rymi-Workspace'] = this.workspace;\n\n const init: RequestInit = {\n method,\n headers\n };\n\n if (body) {\n headers['Content-Type'] = 'application/json';\n init.body = JSON.stringify(body);\n }\n\n try {\n const response = await this.fetchImpl(url, init);\n const isJson = response.headers.get('content-type')?.includes('application/json');\n \n const data = isJson ? await response.json() : await response.text();\n\n if (!response.ok) {\n const message = (data && typeof data === 'object' && 'error' in data) ? (data as any).error : \n (typeof data === 'string' ? data : response.statusText);\n throw new RymiError(message, response.status, (data && typeof data === 'object' && 'code' in data) ? (data as any).code : undefined);\n }\n\n return data as T;\n } catch (error) {\n if (error instanceof RymiError) {\n throw error;\n }\n throw new RymiError(`Network Error: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n public get<T>(path: string): Promise<T> {\n return this.request<T>('GET', path);\n }\n\n public post<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('POST', path, body);\n }\n\n public put<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('PUT', path, body);\n }\n\n public patch<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('PATCH', path, body);\n }\n\n public delete<T>(path: string): Promise<T> {\n return this.request<T>('DELETE', path);\n }\n}\n","import { RymiClient } from '../client';\nimport { Agent, AgentToolBinding } from '@rymi/sdk-types';\n\nexport interface CreateAgentParams {\n name: string;\n /** @deprecated Use system_prompt. This alias is mapped before the request is sent. */\n prompt?: string;\n system_prompt?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n llm_provider?: 'gemini' | 'openai' | 'anthropic' | 'sarvam';\n llm_model?: string;\n llm_fallback_provider?: string | null;\n llm_fallback_model?: string | null;\n stt_provider?: string;\n stt_model?: string;\n stt_fallback_provider?: string | null;\n stt_fallback_model?: string | null;\n tts_provider?: string;\n tts_model?: string;\n tts_fallback_provider?: string | null;\n tts_fallback_model?: string | null;\n /** Self-hosted endpoint URLs (https:// or wss://). Enterprise only. */\n custom_llm_url?: string | null;\n custom_voice_url?: string | null;\n custom_voice_mode?: 'rymi' | 'openai-compat';\n custom_transcriber_url?: string | null;\n language?: string | null;\n /** All BCP-47 languages the agent should handle, e.g. [\"hi-IN\",\"en-US\"] for a bilingual agent. */\n supported_languages?: string[];\n provider_config?: any;\n tools?: AgentToolBinding[];\n}\n\nexport interface UpdateAgentParams {\n name?: string;\n /** @deprecated Use system_prompt. This alias is mapped before the request is sent. */\n prompt?: string;\n system_prompt?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n llm_provider?: 'gemini' | 'openai' | 'anthropic' | 'sarvam';\n llm_model?: string;\n llm_fallback_provider?: string | null;\n llm_fallback_model?: string | null;\n stt_provider?: string;\n stt_model?: string;\n stt_fallback_provider?: string | null;\n stt_fallback_model?: string | null;\n tts_provider?: string;\n tts_model?: string;\n tts_fallback_provider?: string | null;\n tts_fallback_model?: string | null;\n /** Self-hosted endpoint URLs (https:// or wss://). Enterprise only. */\n custom_llm_url?: string | null;\n custom_voice_url?: string | null;\n custom_voice_mode?: 'rymi' | 'openai-compat';\n custom_transcriber_url?: string | null;\n language?: string | null;\n /** All BCP-47 languages the agent should handle, e.g. [\"hi-IN\",\"en-US\"] for a bilingual agent. */\n supported_languages?: string[];\n chat_summary?: string | null;\n provider_config?: any;\n /** Replaces the whole bindings array — build it from a fresh retrieve(). */\n tools?: AgentToolBinding[];\n}\n\nexport interface AgentListResponse {\n agents: Agent[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface AgentCallListResponse {\n calls: any[];\n total: number;\n offset: number;\n limit: number;\n agent_id: string;\n}\n\nexport interface ValidatePublishParams {\n agent_id?: string;\n name?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n [key: string]: any;\n}\n\nexport interface PublishValidationIssue {\n severity?: string;\n section?: string;\n title?: string;\n detail?: string;\n [key: string]: any;\n}\n\nexport interface PublishAgentResponse {\n published: boolean;\n agent_id?: string;\n /** Present when published — the frozen snapshot id and timestamp. */\n snapshot_id?: string | null;\n published_at?: string | null;\n /** Present when published: false because of unresolved blockers. */\n reason?: string;\n blockers?: PublishValidationIssue[];\n warnings?: PublishValidationIssue[];\n error?: string;\n details?: string;\n}\n\nexport interface ChangeEntry {\n key: string;\n value: any;\n}\n\nexport interface ApplyChangesParams {\n currentConfig: Record<string, any>;\n changes: ChangeEntry[];\n mode: 'create' | 'edit';\n lenient?: boolean;\n}\n\nexport interface ApplyChangesResponse {\n valid: true;\n config: Record<string, any>;\n applied: ChangeEntry[];\n}\n\nexport interface EnrichCompanyParams {\n companyName: string;\n websiteUrl: string;\n}\n\nexport interface EnrichCompanyResponse {\n enriched: boolean;\n companyDescription?: string;\n knowledgeBase?: any[];\n error?: string;\n}\n\nexport interface PreviewStackParams {\n language?: string | null;\n /** Required, non-empty list of BCP-47 languages to resolve a stack for. */\n supported_languages: string[];\n current_provider_config?: Record<string, any> | null;\n}\n\nexport interface AgentKnowledgeSource {\n id: string;\n kind?: 'text' | 'url';\n title?: string;\n source_uri?: string | null;\n bytes?: number;\n created_at?: string;\n [key: string]: any;\n}\n\nexport type AddKnowledgeSourceParams =\n | { kind: 'text'; title: string; text: string }\n | { kind: 'url'; title: string; url: string };\n\n/** A public share link: anyone with the URL can talk to the agent, billed to your workspace. */\nexport interface AgentShareLink {\n id: string;\n url: string;\n enabled: boolean;\n minutes_limit: number;\n minutes_used: number;\n minutes_reserved: number;\n minutes_remaining: number;\n live_calls: number;\n max_call_seconds: number;\n max_concurrent: number;\n calls_per_ip_hour: number;\n minutes_requested_at: string | null;\n}\n\n/** All optional; omitted fields keep their current value (or the default on create). */\nexport interface AgentShareLinkSettings {\n enabled?: boolean;\n /** Total talk-time pool for the link, 0–6000 minutes. */\n minutes_limit?: number;\n /** Per-call cap, 60–1800 seconds. */\n max_call_seconds?: number;\n /** Simultaneous calls, 1–10. */\n max_concurrent?: number;\n /** Calls per caller IP per hour, 1–30. */\n calls_per_ip_hour?: number;\n}\n\nexport interface AgentChange {\n change_id: string;\n field_path?: string;\n before_jsonb?: any;\n after_jsonb?: any;\n changed_by?: string;\n created_at?: string;\n undone_at?: string | null;\n [key: string]: any;\n}\n\nfunction normalizeAgentPayload<T extends CreateAgentParams | UpdateAgentParams>(data: T): Omit<T, 'prompt'> & { system_prompt?: string } {\n const { prompt, ...rest } = data as any;\n return {\n ...rest,\n ...(!rest.system_prompt && prompt ? { system_prompt: prompt } : {})\n };\n}\n\nexport class AgentsResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all your AI Agents.\n */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<AgentListResponse> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n const query = searchParams.toString();\n return this.client.get<AgentListResponse>(`/agents${query ? `?${query}` : ''}`);\n }\n\n /**\n * Retrieve a single AI Agent by its unique ID.\n */\n public async retrieve(agentId: string): Promise<Agent> {\n return this.client.get<Agent>(`/agents/${agentId}`);\n }\n\n /**\n * Create a new AI Agent with a complete system prompt and voice settings.\n */\n public async create(data: CreateAgentParams): Promise<{ status: 'created'; id: string }> {\n return this.client.post<{ status: 'created'; id: string }>('/agents', normalizeAgentPayload(data));\n }\n\n /**\n * Update an existing AI Agent's persona or configuration.\n */\n public async update(agentId: string, data: UpdateAgentParams): Promise<{ status: 'updated' }> {\n return this.client.put<{ status: 'updated' }>(`/agents/${agentId}`, normalizeAgentPayload(data));\n }\n\n /**\n * Delete an AI Agent permanently.\n */\n public async delete(agentId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete<{ status: 'deleted'; id: string }>(`/agents/${agentId}`);\n }\n\n public async llmOptions(): Promise<{ models: any[]; voices: any[] }> {\n return this.client.get('/agents/llm-options');\n }\n\n public async generate(data: { prompt: string; options?: Record<string, any> }): Promise<Record<string, any>> {\n return this.client.post('/agents/generate', data);\n }\n\n /**\n * List calls made with a specific agent.\n */\n public async listCalls(agentId: string, params: { limit?: number; offset?: number; status?: string } = {}): Promise<AgentCallListResponse> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n if (params.status) searchParams.set('status', params.status);\n const query = searchParams.toString();\n return this.client.get<AgentCallListResponse>(`/agents/${agentId}/calls${query ? `?${query}` : ''}`);\n }\n\n /**\n * Duplicate an existing agent. The clone gets \" (Copy)\" appended to its name.\n */\n public async clone(agentId: string): Promise<{ status: 'created'; id: string }> {\n return this.client.post<{ status: 'created'; id: string }>(`/agents/${agentId}/clone`, {});\n }\n\n /**\n * Validate an agent's configuration before publishing.\n * Pass agent_id to merge with an existing persisted agent, or supply fields directly.\n */\n public async validatePublish(params: ValidatePublishParams): Promise<Record<string, any>> {\n return this.client.post('/agents/validate-publish', params);\n }\n\n /**\n * Publish an agent: validate its persisted config and freeze it into the\n * published snapshot the harness/review pipeline reads as the baseline.\n * Returns `{ published: false, blockers }` (HTTP 200) when blockers remain —\n * inspect `blockers` rather than relying on a thrown error.\n */\n public async publish(agentId: string): Promise<PublishAgentResponse> {\n return this.client.post<PublishAgentResponse>(`/agents/${agentId}/publish`, {});\n }\n\n /**\n * Validate and apply a flat-diff change-set against the AgentConfig field registry.\n * Does NOT persist — callers must follow up with update().\n */\n public async applyChanges(params: ApplyChangesParams): Promise<ApplyChangesResponse> {\n return this.client.post('/agents/apply-changes', params);\n }\n\n /**\n * Use AI with Google Search grounding to generate a company description from a website URL.\n */\n public async enrichCompany(params: EnrichCompanyParams): Promise<EnrichCompanyResponse> {\n return this.client.post('/agents/enrich-company', params);\n }\n\n /**\n * Preview the resolved per-language model stack (STT/LLM/TTS), blockers,\n * warnings, and model diffs for a set of supported languages — without\n * persisting anything.\n */\n public async previewStack(params: PreviewStackParams): Promise<Record<string, any>> {\n return this.client.post('/agents/stack-preview', params);\n }\n\n /**\n * List the knowledge sources (RAG context) attached to an agent.\n */\n public async listKnowledgeSources(agentId: string): Promise<{ sources: AgentKnowledgeSource[] }> {\n return this.client.get(`/agents/${agentId}/knowledge-sources`);\n }\n\n /**\n * Add a knowledge source to an agent from raw text or a URL.\n */\n public async addKnowledgeSource(agentId: string, data: AddKnowledgeSourceParams): Promise<Record<string, any>> {\n return this.client.post(`/agents/${agentId}/knowledge-sources`, data);\n }\n\n /**\n * Delete a knowledge source from an agent.\n */\n public async deleteKnowledgeSource(agentId: string, sourceId: string): Promise<Record<string, any>> {\n return this.client.delete(`/agents/${agentId}/knowledge-sources/${sourceId}`);\n }\n\n /**\n * Get the agent's public share link, or `link: null` if none exists.\n * `link_feature: false` means share links are disabled on this deployment.\n */\n public async getShareLink(agentId: string): Promise<{ link_feature: boolean; link: AgentShareLink | null }> {\n const res = await this.client.get<{ link_feature: boolean; link: AgentShareLink | null }>(`/agents/${agentId}/testers`);\n return { link_feature: res.link_feature, link: res.link };\n }\n\n /**\n * Create the agent's public share link, or update its settings if one exists.\n */\n public async setShareLink(agentId: string, settings: AgentShareLinkSettings = {}): Promise<{ link: AgentShareLink }> {\n return this.client.put(`/agents/${agentId}/share-link`, settings);\n }\n\n /**\n * Issue a new URL for the share link. The old URL stops working immediately.\n */\n public async regenerateShareLink(agentId: string): Promise<{ link: AgentShareLink }> {\n return this.client.post(`/agents/${agentId}/share-link/regenerate`, {});\n }\n\n /**\n * List the recorded configuration changes for an agent (most recent first).\n * Optionally pass an ISO timestamp to only return changes since then.\n */\n public async listChanges(agentId: string, params: { since?: string } = {}): Promise<{ changes: AgentChange[] }> {\n const query = params.since ? `?since=${encodeURIComponent(params.since)}` : '';\n return this.client.get(`/agents/${agentId}/changes${query}`);\n }\n\n /**\n * Undo a single recorded configuration change, reverting that field to its\n * previous value. Returns the resulting agent snapshot.\n */\n public async undoChange(agentId: string, changeId: string): Promise<{ ok: boolean; changeId: string; agentSnapshot: Agent }> {\n return this.client.post(`/agents/${agentId}/changes/${changeId}/undo`, {});\n }\n\n /**\n * Run the evaluation suite for an agent. mode=\"synthetic\" (default) uses\n * the offline scorer; mode=\"live\" runs the model-driven runner.\n */\n public async runEvals(\n agentId: string,\n params: { mode?: 'synthetic' | 'live'; judge?: boolean } = {},\n ): Promise<Record<string, any>> {\n const query = new URLSearchParams();\n if (params.mode) query.set('mode', params.mode);\n if (params.judge) query.set('judge', '1');\n const qs = query.toString();\n return this.client.post(`/agents/${agentId}/evals/run${qs ? `?${qs}` : ''}`, {});\n }\n\n /**\n * Run the eval SUITE across many agents at once (agents × seeded scenarios),\n * bounded by the optional concurrency cap. One eval run is persisted per\n * agent; the aggregate EvalSuiteReport is returned. Pass `judge: true` to\n * supplement the heuristics with the opt-in LLM judge (needs a Gemini key).\n */\n public async runEvalSuite(params: {\n agentIds: string[];\n scenarioIds?: string[];\n concurrency?: number;\n judge?: boolean;\n }): Promise<Record<string, any>> {\n return this.client.post('/agents/evals/suite', params);\n }\n\n /**\n * List previous evaluation runs for an agent.\n */\n public async listEvalRuns(agentId: string): Promise<Record<string, any>> {\n return this.client.get(`/agents/${agentId}/evals/runs`);\n }\n\n /**\n * Retrieve a single evaluation run, including per-scenario scores.\n */\n public async getEvalRun(agentId: string, runId: string): Promise<Record<string, any>> {\n return this.client.get(`/agents/${agentId}/evals/runs/${runId}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface ListCallsParams {\n limit?: number;\n offset?: number;\n cursor?: string;\n status?: string;\n}\n\nexport interface CallRecord {\n id: string;\n agent_id: string;\n room_name: string;\n status: 'queued' | 'ringing' | 'in_progress' | 'completed' | 'failed' | 'busy' | 'canceled';\n duration_seconds?: number;\n started_at?: string;\n ended_at?: string;\n participants?: Array<{\n id: string;\n role: 'agent' | 'customer' | 'observer';\n transport: 'webrtc' | 'pstn' | 'sip' | 'internal';\n identity: string;\n status: string;\n }>;\n metadata?: Record<string, any>;\n intelligence_status?: string;\n participant_count?: number;\n primary_participant?: Record<string, any> | null;\n total_cost?: number;\n provider_cost?: number;\n provider_cost_breakdown?: Record<string, any>;\n provider_cost_calculated_at?: string | null;\n bill_duration?: number;\n}\n\nexport interface CallListResponse {\n calls: CallRecord[];\n total: number;\n limit: number;\n offset: number;\n next_cursor?: string | null;\n}\n\nexport interface CreateCallParams {\n agent_id: string;\n participants: Array<{\n transport: 'webrtc' | 'pstn';\n identity: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface BatchCallParams {\n agent_id: string;\n to?: string[];\n recipients?: Array<{\n to?: string;\n identity?: string;\n phone?: string;\n phone_number?: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n from_number?: string;\n batch_id?: string;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface FanoutCallParams {\n agent_id: string;\n to?: string[];\n recipients?: Array<{\n to?: string;\n identity?: string;\n phone?: string;\n phone_number?: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n from_number?: string;\n /** Preferred tracking id for this fanout. Falls back to batch_id, then auto-generated. */\n fanout_id?: string;\n /** Compatibility alias for fanout_id. */\n batch_id?: string;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface CreateCallResponse {\n id: string;\n room_name: string;\n status: string;\n participants: Array<{\n id: string;\n transport: 'webrtc' | 'pstn';\n identity: string;\n status: string;\n access?: { url: string; token: string };\n telephony_leg_id?: string;\n job_id?: string;\n }>;\n agent?: { id: string; name: string };\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n searchParams.set(key, String(value));\n }\n }\n const query = searchParams.toString();\n return query ? `?${query}` : '';\n}\n\nexport class CallsResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all previous and active calls.\n */\n public async list(params: ListCallsParams = {}): Promise<CallListResponse> {\n return this.client.get<CallListResponse>(`/calls${buildQuery(params)}`);\n }\n\n /**\n * Retrieve calls currently in progress.\n */\n public async active(params: ListCallsParams = {}): Promise<CallListResponse> {\n return this.client.get<CallListResponse>(`/calls/active${buildQuery(params)}`);\n }\n\n /**\n * Retrieve details, transcripts, and analysis of a single call by its unique ID.\n */\n public async retrieve(callId: string): Promise<CallRecord> {\n return this.client.get<CallRecord>(`/calls/${callId}`);\n }\n\n /**\n * Dispatch an outbound phone call securely using your configured carrier.\n */\n public async create(data: CreateCallParams): Promise<CreateCallResponse> {\n return this.client.post('/calls', data);\n }\n\n /**\n * Group call fanout: dial up to 500 PSTN participants into a single call room.\n * Every recipient joins the same call. For independent per-recipient attempts,\n * retries, and reports, use `campaigns` instead.\n */\n public async fanout(data: FanoutCallParams): Promise<CreateCallResponse & { fanout_id: string; batch_id: string; queued: number }> {\n return this.client.post('/calls/fanout', data);\n }\n\n /**\n * Compatibility alias for {@link fanout}. Creates one call room with multiple\n * PSTN participants. Queue up to 500 outbound PSTN recipients in one request.\n */\n public async batch(data: BatchCallParams): Promise<CreateCallResponse & { batch_id: string; queued: number }> {\n return this.client.post('/calls/batch', data);\n }\n\n public async summary(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/summary`);\n }\n\n public async transcript(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/transcript`);\n }\n\n public async recording(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/recording`);\n }\n\n public async reprocess(callId: string): Promise<Record<string, any>> {\n return this.client.post(`/calls/${callId}/reprocess`);\n }\n\n /** Force-end an active call. Irreversible — closes the LiveKit room and triggers post-call processing. */\n public async end(callId: string): Promise<{ status: string; id: string; message: string }> {\n return this.client.post(`/calls/${callId}/end`);\n }\n\n /** Add one or more participants to an in-progress call (warm transfer / conference). */\n public async addParticipants(\n callId: string,\n data: { participants: CreateCallParams['participants'] }\n ): Promise<CreateCallResponse> {\n return this.client.post(`/calls/${callId}/participants`, data);\n }\n\n public async queueStats(): Promise<Record<string, number>> {\n return this.client.get('/calls/queue/stats');\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface DncEntry {\n id?: string;\n phone: string;\n reason?: string;\n created_at?: string;\n}\n\nexport interface DncListResponse {\n dnc_entries: DncEntry[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface DncCheckResult {\n phone_number: string;\n normalized: string | null;\n blocked: boolean;\n valid: boolean;\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\n/**\n * Do-Not-Call registry. Numbers are normalized to E.164 server-side on both\n * write and read, so any input format is accepted.\n */\nexport class DncResource {\n constructor(private client: RymiClient) {}\n\n /** List all DNC entries for the tenant. */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<DncListResponse> {\n return this.client.get<DncListResponse>(`/dnc${buildQuery(params)}`);\n }\n\n /** Add a single number to the Do-Not-Call registry. */\n public async add(data: { phone_number: string; reason?: string }): Promise<{ status: 'blocklisted'; phone_number: string }> {\n return this.client.post('/dnc', data);\n }\n\n /** Add up to 1000 numbers in one request. Invalid numbers are skipped and returned in `invalid`. */\n public async addBatch(data: { phone_numbers: string[]; reason?: string }): Promise<{ status: 'blocklisted'; count: number; invalid_count: number; invalid: string[] }> {\n return this.client.post('/dnc/batch', data);\n }\n\n /** Check up to 500 numbers without adding them. Read-only. */\n public async check(data: { phone_numbers: string[] }): Promise<{ results: DncCheckResult[]; blocked_count: number; total_checked: number }> {\n return this.client.post('/dnc/check', data);\n }\n\n /** Remove a number from the registry (re-enables outbound to it). */\n public async remove(phone: string): Promise<{ status: 'removed'; phone: string }> {\n return this.client.delete(`/dnc/${encodeURIComponent(phone)}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface NumberRecord {\n id?: string;\n number?: string;\n phone_number?: string;\n provider?: 'plivo' | 'twilio' | 'vonage' | 'telnyx';\n capabilities?: string[];\n price?: string | number;\n monthly_price?: number;\n agent_id?: string | null;\n assigned_agent_id?: string | null;\n created_at?: string;\n /** Carrier inbound-webhook provisioning state (set once an agent is attached). */\n webhook_status?: 'configured' | 'manual_required' | 'failed' | null;\n webhook_url?: string | null;\n webhook_error?: string | null;\n last_inbound_at?: string | null;\n}\n\n/** Outcome of carrier inbound-webhook auto-provisioning. */\nexport interface WebhookProvisionResult {\n status: 'configured' | 'manual_required' | 'failed' | 'no_carrier';\n provider: string | null;\n webhookUrl: string | null;\n verified: boolean;\n error?: string;\n}\n\nexport class NumbersResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all phone numbers assigned to your Rymi account.\n */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<{ numbers: NumberRecord[]; total: number; offset: number; limit: number }> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n const query = searchParams.toString();\n return this.client.get(`/numbers${query ? `?${query}` : ''}`);\n }\n\n public async register(number: string, params: { agent_id?: string } = {}): Promise<{ status: 'registered'; number: string; agent_id: string | null; webhook: WebhookProvisionResult | null }> {\n return this.client.post('/numbers', { number, ...params });\n }\n\n public async attach(number: string, agentId: string): Promise<{ status: 'attached'; agent_id: string; number: string; webhook: WebhookProvisionResult | null }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/attach`, { agent_id: agentId });\n }\n\n /** Clear the agent association without deregistering the number. */\n public async detach(number: string): Promise<{ status: 'detached'; number: string }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/detach`);\n }\n\n /** Re-run carrier inbound-webhook auto-provisioning for a number. */\n public async provisionWebhook(number: string): Promise<{ number: string; webhook: WebhookProvisionResult }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/webhook`);\n }\n\n public async remove(number: string): Promise<{ status: 'removed'; number: string }> {\n return this.client.delete(`/numbers/${encodeURIComponent(number)}`);\n }\n}\n","import * as crypto from 'crypto';\nimport { RymiClient } from '../client';\n\nexport interface WebhookRecord {\n id: string;\n url: string;\n events: string[];\n alert_email?: string | null;\n created_at?: string;\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\nexport class WebhooksResource {\n constructor(private client: RymiClient) {}\n\n /** List registered webhook endpoints. The signing secret is never returned. */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<{ webhooks: WebhookRecord[]; total: number; offset: number; limit: number }> {\n return this.client.get(`/webhooks${buildQuery(params)}`);\n }\n\n /** Register a webhook. `url` must be public https. `secret` must be 16–256 chars. */\n public async create(data: { url: string; events: string[]; secret: string; alert_email?: string }): Promise<{ status: 'registered' }> {\n return this.client.post('/webhooks', data);\n }\n\n /** Update a webhook. Only provided fields change. Pass `secret` to rotate it. */\n public async update(id: string, data: { url?: string; events?: string[]; secret?: string; alert_email?: string | null }): Promise<{ status: 'updated'; id: string }> {\n return this.client.patch(`/webhooks/${id}`, data);\n }\n\n /** Delete a webhook endpoint. */\n public async delete(id: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/webhooks/${id}`);\n }\n /**\n * Verifies that a webhook received by your backend was genuinely dispatched by Rymi.\n * \n * Rymi endpoints secure webhooks by computing an HMAC-SHA256 signature\n * of the raw JSON body concatenated with the timestamp, using your Webhook Secret.\n * \n * @param payload The raw stringified JSON body of the webhook hook request.\n * @param signatureHeader The value of the `X-Rymi-Signature` header from the request.\n * @param timestampHeader The value of the `X-Rymi-Timestamp` header from the request.\n * @param webhookSecret Your project's unique Webhook Signing Secret (starts with `whsec_`)\n * @param toleranceMillis Allowed time difference in milliseconds to prevent replay attacks (default 5 mins)\n * \n * @throws {Error} if the signature is invalid or if the timestamp exceeds the tolerance.\n */\n public verifySignature(\n payload: string,\n signatureHeader: string,\n timestampHeader: string,\n webhookSecret: string,\n toleranceMillis = 300000 // 5 minutes\n ): boolean {\n // 1. Check for Replay Attacks\n const timestamp = parseInt(timestampHeader, 10);\n if (isNaN(timestamp)) {\n throw new Error('Invalid Rymi-Timestamp header');\n }\n\n const now = Date.now();\n if (now - timestamp > toleranceMillis) {\n throw new Error('Webhook timestamp is too old. Possible replay attack.');\n }\n\n // 2. Prepare the verification string\n const signaturePayload = `${timestamp}.${payload}`;\n\n // 3. Compute the expected HMAC using the developer's Webhook Secret\n const expectedSignature = crypto\n .createHmac('sha256', webhookSecret)\n .update(signaturePayload, 'utf8')\n .digest('hex');\n\n // 4. Secure string comparison (constant-time to prevent timing attacks)\n try {\n const isValid = crypto.timingSafeEqual(\n Buffer.from(signatureHeader),\n Buffer.from(expectedSignature)\n );\n\n if (!isValid) {\n throw new Error('Invalid Webhook Signature. The secret might be incorrect.');\n }\n\n return true;\n } catch (err) {\n throw new Error('Invalid Webhook Signature. The secret might be incorrect.');\n }\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface PublishableKeyRecord {\n id: string;\n key_prefix: string;\n agent_id: string;\n label: string;\n allowed_channels: Array<'web' | 'phone'>;\n audience: 'sdk' | 'landing_demo';\n default_from_number: string | null;\n created_at: string;\n}\n\nexport interface CreatePublishableKeyParams {\n agent_id: string;\n label: string;\n allowed_channels?: Array<'web' | 'phone'>;\n audience?: 'sdk' | 'landing_demo';\n default_from_number?: string | null;\n}\n\nexport class KeysResource {\n constructor(private client: RymiClient) {}\n\n public async listPublishable(): Promise<{ keys: PublishableKeyRecord[] }> {\n return this.client.get('/keys/publishable');\n }\n\n public async createPublishable(data: CreatePublishableKeyParams): Promise<CreatePublishableKeyParams & { key: string }> {\n return this.client.post('/keys/publishable', data);\n }\n\n public async revokePublishable(id: string): Promise<{ success: true }> {\n return this.client.delete(`/keys/publishable/${id}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport type TelephonyProvider = 'plivo' | 'twilio' | 'vonage' | 'telnyx';\n\nexport interface ConnectTelephonyParams {\n provider: TelephonyProvider;\n auth_id?: string;\n auth_token?: string;\n api_key?: string;\n api_secret?: string;\n signature_secret?: string;\n /** Telnyx Ed25519 webhook signing secret (optional). */\n auth_secret?: string;\n}\n\nexport class TelephonyResource {\n constructor(private client: RymiClient) {}\n\n public async connect(data: ConnectTelephonyParams): Promise<{ status: 'connected'; provider: TelephonyProvider; account_name: string; message: string }> {\n return this.client.post('/telephony/connect', data);\n }\n\n public async disconnect(): Promise<{ status: 'disconnected'; message: string }> {\n return this.client.post('/telephony/disconnect');\n }\n\n public async status(): Promise<{ connected: boolean; provider: TelephonyProvider | null; account_name: string | null; account_country: string | null }> {\n return this.client.get('/telephony/status');\n }\n\n public async numbers(): Promise<{ numbers: any[] }> {\n return this.client.get('/telephony/numbers');\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface UsageSummary {\n voice_runtime: {\n remaining_minutes: number;\n status: string;\n };\n studio_ai?: {\n used_units?: number;\n included_units?: number | null;\n quota_percent?: number;\n status?: string;\n overage_enabled?: boolean;\n };\n post_call_intelligence?: {\n status?: string;\n used_units?: number;\n };\n}\n\nexport class BillingResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Lane-aware usage summary: remaining voice-runtime minutes, Studio AI unit\n * usage, and post-call intelligence usage. Voice balance is reported in\n * MINUTES (the customer-facing unit), not dollars.\n */\n public async usageSummary(): Promise<UsageSummary> {\n return this.client.get<UsageSummary>('/billing/usage-summary');\n }\n\n /** Estimate the cost of a call for a custom model stack and duration. */\n public async estimate(data: { stt_model?: string; llm_model?: string; tts_model?: string; duration_seconds?: number } = {}): Promise<Record<string, any>> {\n return this.client.post('/billing/estimate', data);\n }\n\n /** Configure auto-recharge. Server rejects (400) if enabled && pack_usd <= threshold_usd. */\n public async setAutoRecharge(data: { enabled?: boolean; pack_usd?: number; threshold_usd?: number }): Promise<{ ok: true }> {\n return this.client.put('/billing/auto-recharge', data);\n }\n\n /** Configure spend-alert preferences. */\n public async setAlerts(data: { thresholds_usd?: number[]; low_balance_pct?: number; email_enabled?: boolean }): Promise<{ ok: true }> {\n return this.client.put('/billing/alerts', data);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface AgentTemplateSummary {\n id?: string;\n slug?: string;\n label?: string;\n description?: string;\n icon?: string;\n color?: string;\n defaults?: Record<string, any>;\n [key: string]: any;\n}\n\nexport class TemplatesResource {\n constructor(private client: RymiClient) {}\n\n /**\n * List published agent templates available to the current tenant. Use a\n * template's `defaults` as the starting config for create_agent.\n */\n public async list(): Promise<{ templates: AgentTemplateSummary[]; source?: string }> {\n return this.client.get('/agent-templates');\n }\n}\n","import { RymiClient } from '../client';\nimport type {\n Campaign,\n CampaignStatus,\n CampaignType,\n CampaignMember,\n CampaignAttempt,\n CampaignReport,\n CampaignGoal,\n CampaignCompliancePolicy\n} from '@rymi/sdk-types';\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\n// ─── list/create/update params + responses ─────────────────────────────────\n\nexport interface ListCampaignsParams {\n limit?: number;\n offset?: number;\n status?: CampaignStatus;\n type?: CampaignType;\n agent_id?: string;\n}\n\nexport interface CampaignListResponse {\n campaigns: Campaign[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateCampaignParams {\n agent_id: string;\n type: CampaignType;\n name: string;\n goal?: CampaignGoal;\n schedule_policy?: Record<string, unknown>;\n retry_policy?: Record<string, unknown>;\n concurrency_policy?: Record<string, unknown>;\n automation_policy?: Record<string, unknown>;\n reporting_policy?: Record<string, unknown>;\n compliance_policy?: CampaignCompliancePolicy;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateCampaignParams {\n name?: string;\n goal?: CampaignGoal;\n schedule_policy?: Record<string, unknown>;\n retry_policy?: Record<string, unknown>;\n concurrency_policy?: Record<string, unknown>;\n automation_policy?: Record<string, unknown>;\n reporting_policy?: Record<string, unknown>;\n compliance_policy?: CampaignCompliancePolicy;\n post_call_config_override?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface LaunchBlocker {\n code: string;\n ok: boolean;\n detail?: string;\n}\n\nexport interface LaunchCampaignResponse {\n campaign: Campaign;\n blockers: LaunchBlocker[];\n}\n\n/**\n * GET /campaigns/:id/report response. Extends the shared CampaignReport with\n * the report-endpoint-only derived fields (top failure reasons + cost per\n * success) that the API adds on top of the persisted shape.\n */\nexport interface CampaignReportResponse extends CampaignReport {\n distributions: CampaignReport['distributions'] & {\n top_failure_reasons: Array<{ reason: string; count: number }>;\n cost_per_success_credits: number;\n };\n}\n\n// ─── members ────────────────────────────────────────────────────────────────\n\nexport interface ListCampaignMembersParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignMemberListResponse {\n members: CampaignMember[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface AddCampaignMembersParams {\n contact_ids: string[];\n variables_override?: Record<string, string>;\n}\n\nexport interface ImportCampaignMembersParams {\n contacts?: Array<Record<string, unknown>>;\n csv?: string;\n}\n\nexport interface ImportCampaignMembersResponse {\n created: number;\n merged: number;\n /** Members attached to the campaign in this import. */\n attached: number;\n invalid: Array<{ row: number; reason: string }>;\n}\n\nexport interface UpdateCampaignMemberParams {\n status?: string;\n variables_override?: Record<string, string>;\n next_attempt_at?: string;\n}\n\nclass CampaignMembersResource {\n constructor(private client: RymiClient) {}\n\n /** List a campaign's members, paginated. */\n public async list(campaignId: string, params: ListCampaignMembersParams = {}): Promise<CampaignMemberListResponse> {\n return this.client.get(`/campaigns/${campaignId}/members${buildQuery(params)}`);\n }\n\n /** Attach existing contacts to a campaign as members. */\n public async add(campaignId: string, data: AddCampaignMembersParams): Promise<{ members: CampaignMember[] }> {\n return this.client.post(`/campaigns/${campaignId}/members`, data);\n }\n\n /** Import inline contact rows (JSON or CSV): creates/merges contacts and attaches members in one call. */\n public async import(campaignId: string, data: ImportCampaignMembersParams): Promise<ImportCampaignMembersResponse> {\n return this.client.post(`/campaigns/${campaignId}/members/import`, data);\n }\n\n /** Update a campaign member (status, variables, next attempt time). */\n public async update(campaignId: string, memberId: string, data: UpdateCampaignMemberParams): Promise<{ member: CampaignMember }> {\n return this.client.patch(`/campaigns/${campaignId}/members/${memberId}`, data);\n }\n\n /** Remove a member from a campaign. */\n public async remove(campaignId: string, memberId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/campaigns/${campaignId}/members/${memberId}`);\n }\n}\n\n// ─── inbound routes ─────────────────────────────────────────────────────────\n\nexport interface CampaignRoute {\n id: string;\n tenant_id: string;\n campaign_id: string;\n phone_number: string;\n schedule: Record<string, unknown>;\n active: boolean;\n created_at: string;\n updated_at: string;\n}\n\nexport interface ListCampaignRoutesParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface CampaignRouteListResponse {\n routes: CampaignRoute[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateCampaignRouteParams {\n phone_number: string;\n schedule?: Record<string, unknown>;\n active?: boolean;\n}\n\nexport interface UpdateCampaignRouteParams {\n schedule?: Record<string, unknown>;\n active?: boolean;\n}\n\nclass CampaignRoutesResource {\n constructor(private client: RymiClient) {}\n\n /** List a campaign's inbound routing rules. */\n public async list(campaignId: string, params: ListCampaignRoutesParams = {}): Promise<CampaignRouteListResponse> {\n return this.client.get(`/campaigns/${campaignId}/routes${buildQuery(params)}`);\n }\n\n /** Bind an owned phone number to this campaign for inbound routing. Only one active route per number is allowed. */\n public async create(campaignId: string, data: CreateCampaignRouteParams): Promise<{ route: CampaignRoute }> {\n return this.client.post(`/campaigns/${campaignId}/routes`, data);\n }\n\n /** Update an inbound route's schedule or active flag. */\n public async update(campaignId: string, routeId: string, data: UpdateCampaignRouteParams): Promise<{ route: CampaignRoute }> {\n return this.client.patch(`/campaigns/${campaignId}/routes/${routeId}`, data);\n }\n\n /** Delete an inbound route. */\n public async delete(campaignId: string, routeId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/campaigns/${campaignId}/routes/${routeId}`);\n }\n}\n\n// ─── attempts / batches / followups (read-only) ────────────────────────────\n\nexport interface ListCampaignAttemptsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignAttemptListResponse {\n attempts: CampaignAttempt[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface ListCampaignBatchesParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface CampaignBatch {\n id: string;\n tenant_id: string;\n campaign_id: string;\n batch_key: string;\n status: string;\n selected_count: number;\n queued_count: number;\n completed_count: number;\n failed_count: number;\n started_at?: string | null;\n completed_at?: string | null;\n created_at: string;\n}\n\nexport interface CampaignBatchListResponse {\n batches: CampaignBatch[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface ListCampaignFollowupsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignFollowupJob {\n id: string;\n tenant_id: string;\n campaign_id: string;\n campaign_attempt_id?: string | null;\n campaign_member_id?: string | null;\n kind: string;\n status: string;\n scheduled_at: string;\n consent_checked: boolean;\n capability_checked: boolean;\n idempotency_key: string;\n payload: Record<string, unknown>;\n result?: Record<string, unknown> | null;\n created_at: string;\n updated_at: string;\n}\n\nexport interface CampaignFollowupListResponse {\n followups: CampaignFollowupJob[];\n total: number;\n offset: number;\n limit: number;\n}\n\n// ─── improve / suggestions ──────────────────────────────────────────────────\n\nexport interface CampaignSuggestion {\n id: string;\n tenant_id: string;\n campaign_id: string;\n category: string;\n evidence: Record<string, unknown>;\n proposal: Record<string, unknown>;\n status: 'proposed' | 'accepted' | 'dismissed';\n created_by_model?: string | null;\n created_at: string;\n updated_at: string;\n}\n\nexport interface ImproveCampaignResponse {\n suggestions: CampaignSuggestion[];\n}\n\nexport interface ListCampaignSuggestionsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignSuggestionListResponse {\n suggestions: CampaignSuggestion[];\n total: number;\n offset: number;\n limit: number;\n}\n\n// ─── CampaignIntakeResource ──────────────────────────────────────────────────\n\n/** A campaign's lead-intake URL settings. The URL itself is only returned on create/rotate. */\nexport interface CampaignIntake {\n enabled: true;\n assume_voice_consent: boolean;\n default_country: string | null;\n created_at: string;\n rotated_at: string;\n last_used_at: string | null;\n}\n\nexport interface CampaignIntakeSettings {\n /** Treat every lead posted to the URL as having voice consent (e.g. a subscribe form with a consent line). */\n assume_voice_consent?: boolean;\n /** ISO-3166 alpha-2 (e.g. \"IN\") used for numbers posted without a +country code. */\n default_country?: string | null;\n}\n\nclass CampaignIntakeResource {\n constructor(private client: RymiClient) {}\n\n /** Get the campaign's lead-intake settings, or `intake: null` if it has none. */\n public async get(campaignId: string): Promise<{ intake: CampaignIntake | null }> {\n return this.client.get(`/campaigns/${campaignId}/intake`);\n }\n\n /** Create the lead-intake URL (returned once as `url`), or update its settings (`url: null`). */\n public async set(campaignId: string, settings: CampaignIntakeSettings = {}): Promise<{ intake: CampaignIntake; url: string | null }> {\n return this.client.put(`/campaigns/${campaignId}/intake`, settings);\n }\n\n /** Issue a new URL. The old one stops accepting leads immediately. */\n public async rotate(campaignId: string): Promise<{ intake: CampaignIntake; url: string }> {\n return this.client.post(`/campaigns/${campaignId}/intake/rotate`, {});\n }\n\n /** Remove the lead-intake URL. */\n public async disable(campaignId: string): Promise<void> {\n return this.client.delete(`/campaigns/${campaignId}/intake`);\n }\n}\n\n// ─── CampaignsResource ───────────────────────────────────────────────────────\n\nexport class CampaignsResource {\n public members: CampaignMembersResource;\n public routes: CampaignRoutesResource;\n public intake: CampaignIntakeResource;\n\n constructor(private client: RymiClient) {\n this.members = new CampaignMembersResource(client);\n this.routes = new CampaignRoutesResource(client);\n this.intake = new CampaignIntakeResource(client);\n }\n\n /** List campaigns for the authenticated tenant, paginated. */\n public async list(params: ListCampaignsParams = {}): Promise<CampaignListResponse> {\n return this.client.get(`/campaigns${buildQuery(params)}`);\n }\n\n /** Create a new campaign in draft status against a published agent. */\n public async create(data: CreateCampaignParams): Promise<{ campaign: Campaign }> {\n return this.client.post('/campaigns', data);\n }\n\n /** Retrieve a single campaign by id. */\n public async get(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.get(`/campaigns/${campaignId}`);\n }\n\n /** Update campaign policy/goal fields. Status and lifecycle fields are not writable here. */\n public async update(campaignId: string, data: UpdateCampaignParams): Promise<{ campaign: Campaign }> {\n return this.client.patch(`/campaigns/${campaignId}`, data);\n }\n\n /**\n * Launch a campaign: validates launch blockers, then stamps\n * `launched_at` + `agent_snapshot_id`, flips members to `ready`, and\n * transitions status to `running`.\n */\n public async launch(campaignId: string): Promise<LaunchCampaignResponse> {\n return this.client.post(`/campaigns/${campaignId}/launch`);\n }\n\n /** Evaluate launch blockers without launching (dry run). Safe from any status. */\n public async launchBlockers(campaignId: string): Promise<{ blockers: LaunchBlocker[]; launchable: boolean }> {\n return this.client.get(`/campaigns/${campaignId}/launch-blockers`);\n }\n\n /** Pause a running campaign. In-flight calls finish naturally. */\n public async pause(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/pause`);\n }\n\n /** Resume a paused campaign. */\n public async resume(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/resume`);\n }\n\n /** Archive a campaign. Terminal — the scheduler never selects work for it again. */\n public async archive(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/archive`);\n }\n\n /** Read the campaign report: `stat_*` summary counters + outcome/sentiment/hourly/snapshot distributions. */\n public async report(campaignId: string): Promise<CampaignReportResponse> {\n return this.client.get(`/campaigns/${campaignId}/report`);\n }\n\n /** List a campaign's dial attempts, paginated. */\n public async attempts(campaignId: string, params: ListCampaignAttemptsParams = {}): Promise<CampaignAttemptListResponse> {\n return this.client.get(`/campaigns/${campaignId}/attempts${buildQuery(params)}`);\n }\n\n /** List a campaign's sweep-claim batches, paginated. */\n public async batches(campaignId: string, params: ListCampaignBatchesParams = {}): Promise<CampaignBatchListResponse> {\n return this.client.get(`/campaigns/${campaignId}/batches${buildQuery(params)}`);\n }\n\n /** List a campaign's follow-up jobs, paginated. */\n public async followups(campaignId: string, params: ListCampaignFollowupsParams = {}): Promise<CampaignFollowupListResponse> {\n return this.client.get(`/campaigns/${campaignId}/followups${buildQuery(params)}`);\n }\n\n /** Run the improve engine: detectors gate an LLM proposal writer, persisting new `campaign_suggestions`. */\n public async improve(campaignId: string): Promise<ImproveCampaignResponse> {\n return this.client.post(`/campaigns/${campaignId}/improve`);\n }\n\n /** List a campaign's improvement suggestions, paginated. */\n public async suggestions(campaignId: string, params: ListCampaignSuggestionsParams = {}): Promise<CampaignSuggestionListResponse> {\n return this.client.get(`/campaigns/${campaignId}/suggestions${buildQuery(params)}`);\n }\n\n /** Accept a suggestion: agent-editing suggestions create an agent-changes draft; campaign-policy suggestions patch the campaign. */\n public async acceptSuggestion(campaignId: string, suggestionId: string): Promise<{ suggestion: CampaignSuggestion }> {\n return this.client.post(`/campaigns/${campaignId}/suggestions/${suggestionId}/accept`);\n }\n\n /** Dismiss a suggestion without applying it. */\n public async dismissSuggestion(campaignId: string, suggestionId: string): Promise<{ suggestion: CampaignSuggestion }> {\n return this.client.post(`/campaigns/${campaignId}/suggestions/${suggestionId}/dismiss`);\n }\n}\n","import { RymiClient } from '../client';\nimport type { Contact } from '@rymi/sdk-types';\n\nexport interface ListContactsParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface ContactListResponse {\n contacts: Contact[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateContactParams {\n phone?: string;\n email?: string;\n name?: string;\n timezone?: string;\n language?: string;\n tags?: string[];\n custom_fields?: Record<string, unknown>;\n consent?: Record<string, boolean>;\n source?: string;\n}\n\nexport interface CreateContactResponse {\n contact: Contact;\n deduped: boolean;\n}\n\nexport interface UpdateContactParams {\n phone?: string;\n email?: string | null;\n name?: string | null;\n timezone?: string | null;\n language?: string | null;\n tags?: string[];\n custom_fields?: Record<string, unknown>;\n consent?: Record<string, boolean>;\n source?: string | null;\n}\n\nexport interface ImportContactsParams {\n contacts?: Array<Record<string, unknown>>;\n csv?: string;\n}\n\nexport interface ImportContactsResponse {\n created: number;\n merged: number;\n invalid: Array<{ row: number; reason: string }>;\n}\n\nexport interface SetConsentParams {\n channel: 'voice' | 'sms' | 'whatsapp' | 'telegram';\n granted: boolean;\n source?: string;\n method?: string;\n}\n\nexport interface SetConsentResponse {\n contact_id: string;\n channel: string;\n consent: { granted: boolean; at: string; source: string; method: string };\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\nexport class ContactsResource {\n constructor(private client: RymiClient) {}\n\n /** List tenant-level contacts, paginated. */\n public async list(params: ListContactsParams = {}): Promise<ContactListResponse> {\n return this.client.get(`/contacts${buildQuery(params)}`);\n }\n\n /**\n * Create a tenant-level contact. If a contact with the same\n * (tenant, phone) already exists, the existing row is returned instead\n * of creating a duplicate — check `deduped` in the response.\n */\n public async create(data: CreateContactParams): Promise<CreateContactResponse> {\n return this.client.post('/contacts', data);\n }\n\n /** Retrieve a single tenant-scoped contact by id. */\n public async get(contactId: string): Promise<{ contact: Contact }> {\n return this.client.get(`/contacts/${contactId}`);\n }\n\n /** Update an existing tenant-scoped contact. Only provided fields change. */\n public async update(contactId: string, data: UpdateContactParams): Promise<{ contact: Contact }> {\n return this.client.patch(`/contacts/${contactId}`, data);\n }\n\n /** Delete a tenant-scoped contact. */\n public async delete(contactId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/contacts/${contactId}`);\n }\n\n /**\n * Bulk import contacts from JSON rows or CSV text. Each row's phone is\n * normalized to E.164 and upserted on (tenant_id, phone); rows with\n * unparseable phones are skipped and reported in `invalid`.\n */\n public async import(data: ImportContactsParams): Promise<ImportContactsResponse> {\n return this.client.post('/contacts/import', data);\n }\n\n /** Record a consent grant or revoke for one channel, with evidence. Also\n * appends an immutable row to the consent_events proof log. */\n public async setConsent(contactId: string, data: SetConsentParams): Promise<SetConsentResponse> {\n return this.client.patch(`/contacts/${contactId}/consent`, data);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface AttestParams {\n kind: 'dnc_external_scrub' | 'ai_disclosure';\n note?: string;\n}\n\nexport interface Attestation {\n id: string;\n tenant_id: string;\n kind: string;\n attested_by: string | null;\n note: string | null;\n created_at: string;\n}\n\nexport interface AttestResponse {\n attestation: Attestation;\n}\n\nexport interface ListAttestationsResponse {\n attestations: Attestation[];\n}\n\nexport class ComplianceResource {\n constructor(private client: RymiClient) {}\n\n /** Record a compliance attestation (append-only). Campaign launch blockers\n * in `attested` mode read the most recent one of the matching `kind`. */\n public async attest(data: AttestParams): Promise<AttestResponse> {\n return this.client.post('/compliance/attestations', data);\n }\n\n /** List the tenant's 50 most recent compliance attestations, newest first. */\n public async listAttestations(): Promise<ListAttestationsResponse> {\n return this.client.get('/compliance/attestations');\n }\n}\n","import { RymiClient } from '../client';\n\n/** A stored API-tool secret. Values are write-only — never returned. */\nexport interface ToolSecretRecord {\n name: string;\n /** The only host this secret is ever sent to. */\n host: string | null;\n}\n\n/**\n * Tenant secrets referenced from call_webhook headers as `{{secrets.NAME}}`.\n * Each secret is pinned to one host and only interpolated into requests to it.\n */\nexport class ToolSecretsResource {\n constructor(private client: RymiClient) {}\n\n public async list(): Promise<{ data: ToolSecretRecord[] }> {\n return this.client.get('/tool-secrets');\n }\n\n /** Create or replace. `name` is UPPER_SNAKE_CASE; `host` is a public hostname. */\n public async set(name: string, data: { value: string; host: string }): Promise<{ data: { name: string } }> {\n return this.client.put(`/tool-secrets/${encodeURIComponent(name)}`, data);\n }\n\n public async delete(name: string): Promise<{ data: { name: string } }> {\n return this.client.delete(`/tool-secrets/${encodeURIComponent(name)}`);\n }\n}\n","// packages/node/src/resources/workspaces.ts\nimport { RymiClient } from '../client';\n\nexport interface Workspace {\n id: string;\n name: string;\n role: 'owner' | 'admin' | 'client';\n parent_id: string | null;\n operating_country: string | null;\n current?: boolean;\n}\n\nexport interface CreateWorkspaceParams {\n name: string;\n /** ISO-3166 alpha-2, e.g. \"IN\". */\n operating_country?: string | null;\n}\n\nexport class WorkspacesResource {\n constructor(private client: RymiClient) {}\n\n public async list(): Promise<{ workspaces: Workspace[] }> {\n return this.client.get('/workspaces');\n }\n\n public async create(data: CreateWorkspaceParams): Promise<{ workspace: Workspace }> {\n return this.client.post('/workspaces', data);\n }\n\n public async update(id: string, data: { name?: string; operating_country?: string | null }): Promise<{ ok: true }> {\n return this.client.patch(`/workspaces/${encodeURIComponent(id)}`, data);\n }\n}\n","import { RymiClient, ClientOptions, RymiError } from './client';\nimport { AgentsResource } from './resources/agents';\nimport { CallsResource } from './resources/calls';\nimport { DncResource } from './resources/dnc';\nimport { NumbersResource } from './resources/numbers';\nimport { WebhooksResource } from './resources/webhooks';\nimport { KeysResource } from './resources/keys';\nimport { TelephonyResource } from './resources/telephony';\nimport { BillingResource } from './resources/billing';\nimport { TemplatesResource } from './resources/templates';\nimport { CampaignsResource } from './resources/campaigns';\nimport { ContactsResource } from './resources/contacts';\nimport { ComplianceResource } from './resources/compliance';\nimport { ToolSecretsResource } from './resources/toolSecrets';\nimport { WorkspacesResource } from './resources/workspaces';\n\nexport class Rymi {\n private client: RymiClient;\n\n public agents: AgentsResource;\n public calls: CallsResource;\n public dnc: DncResource;\n public numbers: NumbersResource;\n public webhooks: WebhooksResource;\n public keys: KeysResource;\n public telephony: TelephonyResource;\n public billing: BillingResource;\n public templates: TemplatesResource;\n public campaigns: CampaignsResource;\n public contacts: ContactsResource;\n public compliance: ComplianceResource;\n public toolSecrets: ToolSecretsResource;\n public workspaces: WorkspacesResource;\n\n constructor(options?: ClientOptions) {\n this.client = new RymiClient(options);\n\n // Initialize API Sub-modules\n this.agents = new AgentsResource(this.client);\n this.calls = new CallsResource(this.client);\n this.dnc = new DncResource(this.client);\n this.numbers = new NumbersResource(this.client);\n this.webhooks = new WebhooksResource(this.client);\n this.keys = new KeysResource(this.client);\n this.telephony = new TelephonyResource(this.client);\n this.billing = new BillingResource(this.client);\n this.templates = new TemplatesResource(this.client);\n this.campaigns = new CampaignsResource(this.client);\n this.contacts = new ContactsResource(this.client);\n this.compliance = new ComplianceResource(this.client);\n this.toolSecrets = new ToolSecretsResource(this.client);\n this.workspaces = new WorkspacesResource(this.client);\n }\n}\n\n// Re-export common types\nexport * from './client';\nexport * from './resources/agents';\nexport * from './resources/calls';\nexport * from './resources/dnc';\nexport * from './resources/numbers';\nexport * from './resources/webhooks';\nexport * from './resources/keys';\nexport * from './resources/telephony';\nexport * from './resources/billing';\nexport * from './resources/templates';\nexport * from './resources/campaigns';\nexport * from './resources/contacts';\nexport * from './resources/compliance';\nexport * from './resources/toolSecrets';\nexport * from './resources/workspaces';\n\n// Re-export the curated public type surface (see @rymi/sdk-types).\nexport * from '@rymi/sdk-types';\nexport default Rymi;\n"],"mappings":"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","names":["buildQuery","buildQuery","buildQuery","buildQuery"]}
1
+ {"version":3,"sources":["../src/client.ts","../src/resources/agents.ts","../src/resources/calls.ts","../src/resources/dnc.ts","../src/resources/numbers.ts","../src/resources/webhooks.ts","../src/resources/keys.ts","../src/resources/telephony.ts","../src/resources/billing.ts","../src/resources/templates.ts","../src/resources/campaigns.ts","../src/resources/contacts.ts","../src/resources/compliance.ts","../src/resources/toolSecrets.ts","../src/resources/workspaces.ts","../src/index.ts"],"sourcesContent":["export interface ClientOptions {\n /**\n * The Rymi secret API key (`rymi_...`)\n */\n apiKey?: string;\n \n /**\n * The base URL for the API. Defaults to `https://api.rymi.live/v1`\n */\n baseURL?: string;\n\n /**\n * Custom fetch implementation. Lets embedders route requests without a\n * network socket (e.g. Fastify app.inject). Defaults to global fetch.\n */\n fetch?: typeof globalThis.fetch;\n\n /**\n * Act in this workspace (sent as `Rymi-Workspace`). Defaults to the\n * `RYMI_WORKSPACE` environment variable, else the key's own workspace.\n */\n workspace?: string;\n}\n\nexport class RymiError extends Error {\n public status?: number;\n public code?: string;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.name = 'RymiError';\n this.status = status;\n this.code = code;\n }\n}\n\nexport class RymiClient {\n private apiKey: string;\n private baseURL: string;\n private fetchImpl: typeof globalThis.fetch;\n private workspace?: string;\n\n constructor(options?: ClientOptions) {\n // Prefer explicit option, then fallback to environment variable\n const key = options?.apiKey || (typeof process !== 'undefined' ? process.env.RYMI_API_KEY : undefined);\n\n if (!key) {\n throw new Error('The Rymi API Key must be set either by passing `apiKey` to the client or setting the `RYMI_API_KEY` environment variable.');\n }\n\n this.apiKey = key;\n this.baseURL = options?.baseURL || 'https://api.rymi.live/v1';\n this.fetchImpl = options?.fetch ?? globalThis.fetch;\n\n // Remove trailing slashes\n if (this.baseURL.endsWith('/')) {\n this.baseURL = this.baseURL.slice(0, -1);\n }\n\n this.workspace = options?.workspace\n || (typeof process !== 'undefined' ? process.env.RYMI_WORKSPACE : undefined)\n || undefined;\n }\n\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\n const url = `${this.baseURL}${path.startsWith('/') ? path : `/${path}`}`;\n \n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Accept': 'application/json',\n 'User-Agent': 'rymi-node/1.0.0'\n };\n if (this.workspace) headers['Rymi-Workspace'] = this.workspace;\n\n const init: RequestInit = {\n method,\n headers\n };\n\n if (body) {\n headers['Content-Type'] = 'application/json';\n init.body = JSON.stringify(body);\n }\n\n try {\n const response = await this.fetchImpl(url, init);\n const isJson = response.headers.get('content-type')?.includes('application/json');\n \n const data = isJson ? await response.json() : await response.text();\n\n if (!response.ok) {\n const message = (data && typeof data === 'object' && 'error' in data) ? (data as any).error : \n (typeof data === 'string' ? data : response.statusText);\n throw new RymiError(message, response.status, (data && typeof data === 'object' && 'code' in data) ? (data as any).code : undefined);\n }\n\n return data as T;\n } catch (error) {\n if (error instanceof RymiError) {\n throw error;\n }\n throw new RymiError(`Network Error: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n public get<T>(path: string): Promise<T> {\n return this.request<T>('GET', path);\n }\n\n public post<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('POST', path, body);\n }\n\n public put<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('PUT', path, body);\n }\n\n public patch<T>(path: string, body?: any): Promise<T> {\n return this.request<T>('PATCH', path, body);\n }\n\n public delete<T>(path: string): Promise<T> {\n return this.request<T>('DELETE', path);\n }\n}\n","import { RymiClient } from '../client';\nimport { Agent, AgentToolBinding } from '@rymi/sdk-types';\n\nexport interface CreateAgentParams {\n name: string;\n /** @deprecated Use system_prompt. This alias is mapped before the request is sent. */\n prompt?: string;\n system_prompt?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n llm_provider?: 'gemini' | 'openai' | 'anthropic' | 'sarvam';\n llm_model?: string;\n llm_fallback_provider?: string | null;\n llm_fallback_model?: string | null;\n stt_provider?: string;\n stt_model?: string;\n stt_fallback_provider?: string | null;\n stt_fallback_model?: string | null;\n tts_provider?: string;\n tts_model?: string;\n tts_fallback_provider?: string | null;\n tts_fallback_model?: string | null;\n /** Self-hosted endpoint URLs (https:// or wss://). Enterprise only. */\n custom_llm_url?: string | null;\n custom_voice_url?: string | null;\n custom_voice_mode?: 'rymi' | 'openai-compat';\n custom_transcriber_url?: string | null;\n language?: string | null;\n /** All BCP-47 languages the agent should handle, e.g. [\"hi-IN\",\"en-US\"] for a bilingual agent. */\n supported_languages?: string[];\n provider_config?: any;\n tools?: AgentToolBinding[];\n}\n\nexport interface UpdateAgentParams {\n name?: string;\n /** @deprecated Use system_prompt. This alias is mapped before the request is sent. */\n prompt?: string;\n system_prompt?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n llm_provider?: 'gemini' | 'openai' | 'anthropic' | 'sarvam';\n llm_model?: string;\n llm_fallback_provider?: string | null;\n llm_fallback_model?: string | null;\n stt_provider?: string;\n stt_model?: string;\n stt_fallback_provider?: string | null;\n stt_fallback_model?: string | null;\n tts_provider?: string;\n tts_model?: string;\n tts_fallback_provider?: string | null;\n tts_fallback_model?: string | null;\n /** Self-hosted endpoint URLs (https:// or wss://). Enterprise only. */\n custom_llm_url?: string | null;\n custom_voice_url?: string | null;\n custom_voice_mode?: 'rymi' | 'openai-compat';\n custom_transcriber_url?: string | null;\n language?: string | null;\n /** All BCP-47 languages the agent should handle, e.g. [\"hi-IN\",\"en-US\"] for a bilingual agent. */\n supported_languages?: string[];\n chat_summary?: string | null;\n provider_config?: any;\n /** Replaces the whole bindings array — build it from a fresh retrieve(). */\n tools?: AgentToolBinding[];\n}\n\nexport interface AgentListResponse {\n agents: Agent[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface AgentCallListResponse {\n calls: any[];\n total: number;\n offset: number;\n limit: number;\n agent_id: string;\n}\n\nexport interface ValidatePublishParams {\n agent_id?: string;\n name?: string;\n voice?: string;\n persona?: any;\n playbook?: any;\n advanced?: any;\n features?: any;\n post_call?: any;\n [key: string]: any;\n}\n\nexport interface PublishValidationIssue {\n severity?: string;\n section?: string;\n title?: string;\n detail?: string;\n [key: string]: any;\n}\n\nexport interface PublishAgentResponse {\n published: boolean;\n agent_id?: string;\n /** Present when published — the frozen snapshot id and timestamp. */\n snapshot_id?: string | null;\n published_at?: string | null;\n /** Present when published: false because of unresolved blockers. */\n reason?: string;\n blockers?: PublishValidationIssue[];\n warnings?: PublishValidationIssue[];\n error?: string;\n details?: string;\n}\n\nexport interface ChangeEntry {\n key: string;\n value: any;\n}\n\nexport interface ApplyChangesParams {\n currentConfig: Record<string, any>;\n changes: ChangeEntry[];\n mode: 'create' | 'edit';\n lenient?: boolean;\n}\n\nexport interface ApplyChangesResponse {\n valid: true;\n config: Record<string, any>;\n applied: ChangeEntry[];\n}\n\nexport interface EnrichCompanyParams {\n companyName: string;\n websiteUrl: string;\n}\n\nexport interface EnrichCompanyResponse {\n enriched: boolean;\n companyDescription?: string;\n knowledgeBase?: any[];\n error?: string;\n}\n\nexport interface PreviewStackParams {\n language?: string | null;\n /** Required, non-empty list of BCP-47 languages to resolve a stack for. */\n supported_languages: string[];\n current_provider_config?: Record<string, any> | null;\n}\n\nexport interface AgentKnowledgeSource {\n id: string;\n kind?: 'text' | 'url';\n title?: string;\n source_uri?: string | null;\n bytes?: number;\n created_at?: string;\n [key: string]: any;\n}\n\nexport type AddKnowledgeSourceParams =\n | { kind: 'text'; title: string; text: string }\n | { kind: 'url'; title: string; url: string };\n\n/** A public share link: anyone with the URL can talk to the agent, billed to your workspace. */\nexport interface AgentShareLink {\n id: string;\n url: string;\n enabled: boolean;\n minutes_limit: number;\n minutes_used: number;\n minutes_reserved: number;\n minutes_remaining: number;\n live_calls: number;\n max_call_seconds: number;\n max_concurrent: number;\n calls_per_ip_hour: number;\n minutes_requested_at: string | null;\n}\n\n/** All optional; omitted fields keep their current value (or the default on create). */\nexport interface AgentShareLinkSettings {\n enabled?: boolean;\n /** Total talk-time pool for the link, 0–6000 minutes. */\n minutes_limit?: number;\n /** Per-call cap, 60–1800 seconds. */\n max_call_seconds?: number;\n /** Simultaneous calls, 1–10. */\n max_concurrent?: number;\n /** Calls per caller IP per hour, 1–30. */\n calls_per_ip_hour?: number;\n}\n\nexport interface AgentChange {\n change_id: string;\n field_path?: string;\n before_jsonb?: any;\n after_jsonb?: any;\n changed_by?: string;\n created_at?: string;\n undone_at?: string | null;\n [key: string]: any;\n}\n\nfunction normalizeAgentPayload<T extends CreateAgentParams | UpdateAgentParams>(data: T): Omit<T, 'prompt'> & { system_prompt?: string } {\n const { prompt, ...rest } = data as any;\n return {\n ...rest,\n ...(!rest.system_prompt && prompt ? { system_prompt: prompt } : {})\n };\n}\n\nexport class AgentsResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all your AI Agents.\n */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<AgentListResponse> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n const query = searchParams.toString();\n return this.client.get<AgentListResponse>(`/agents${query ? `?${query}` : ''}`);\n }\n\n /**\n * Retrieve a single AI Agent by its unique ID.\n */\n public async retrieve(agentId: string): Promise<Agent> {\n return this.client.get<Agent>(`/agents/${agentId}`);\n }\n\n /**\n * Create a new AI Agent with a complete system prompt and voice settings.\n */\n public async create(data: CreateAgentParams): Promise<{ status: 'created'; id: string }> {\n return this.client.post<{ status: 'created'; id: string }>('/agents', normalizeAgentPayload(data));\n }\n\n /**\n * Update an existing AI Agent's persona or configuration.\n */\n public async update(agentId: string, data: UpdateAgentParams): Promise<{ status: 'updated' }> {\n return this.client.put<{ status: 'updated' }>(`/agents/${agentId}`, normalizeAgentPayload(data));\n }\n\n /**\n * Delete an AI Agent permanently.\n */\n public async delete(agentId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete<{ status: 'deleted'; id: string }>(`/agents/${agentId}`);\n }\n\n public async llmOptions(): Promise<{ models: any[]; voices: any[] }> {\n return this.client.get('/agents/llm-options');\n }\n\n public async generate(data: { prompt: string; options?: Record<string, any> }): Promise<Record<string, any>> {\n return this.client.post('/agents/generate', data);\n }\n\n /**\n * List calls made with a specific agent.\n */\n public async listCalls(agentId: string, params: { limit?: number; offset?: number; status?: string } = {}): Promise<AgentCallListResponse> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n if (params.status) searchParams.set('status', params.status);\n const query = searchParams.toString();\n return this.client.get<AgentCallListResponse>(`/agents/${agentId}/calls${query ? `?${query}` : ''}`);\n }\n\n /**\n * Duplicate an existing agent. The clone gets \" (Copy)\" appended to its name.\n */\n public async clone(agentId: string): Promise<{ status: 'created'; id: string }> {\n return this.client.post<{ status: 'created'; id: string }>(`/agents/${agentId}/clone`, {});\n }\n\n /**\n * Validate an agent's configuration before publishing.\n * Pass agent_id to merge with an existing persisted agent, or supply fields directly.\n */\n public async validatePublish(params: ValidatePublishParams): Promise<Record<string, any>> {\n return this.client.post('/agents/validate-publish', params);\n }\n\n /**\n * Publish an agent: validate its persisted config and freeze it into the\n * published snapshot the harness/review pipeline reads as the baseline.\n * Returns `{ published: false, blockers }` (HTTP 200) when blockers remain —\n * inspect `blockers` rather than relying on a thrown error.\n */\n public async publish(agentId: string): Promise<PublishAgentResponse> {\n return this.client.post<PublishAgentResponse>(`/agents/${agentId}/publish`, {});\n }\n\n /**\n * Validate and apply a flat-diff change-set against the AgentConfig field registry.\n * Does NOT persist — callers must follow up with update().\n */\n public async applyChanges(params: ApplyChangesParams): Promise<ApplyChangesResponse> {\n return this.client.post('/agents/apply-changes', params);\n }\n\n /**\n * Use AI with Google Search grounding to generate a company description from a website URL.\n */\n public async enrichCompany(params: EnrichCompanyParams): Promise<EnrichCompanyResponse> {\n return this.client.post('/agents/enrich-company', params);\n }\n\n /**\n * Preview the resolved per-language model stack (STT/LLM/TTS), blockers,\n * warnings, and model diffs for a set of supported languages — without\n * persisting anything.\n */\n public async previewStack(params: PreviewStackParams): Promise<Record<string, any>> {\n return this.client.post('/agents/stack-preview', params);\n }\n\n /**\n * List the knowledge sources (RAG context) attached to an agent.\n */\n public async listKnowledgeSources(agentId: string): Promise<{ sources: AgentKnowledgeSource[] }> {\n return this.client.get(`/agents/${agentId}/knowledge-sources`);\n }\n\n /**\n * Add a knowledge source to an agent from raw text or a URL.\n */\n public async addKnowledgeSource(agentId: string, data: AddKnowledgeSourceParams): Promise<Record<string, any>> {\n return this.client.post(`/agents/${agentId}/knowledge-sources`, data);\n }\n\n /**\n * Delete a knowledge source from an agent.\n */\n public async deleteKnowledgeSource(agentId: string, sourceId: string): Promise<Record<string, any>> {\n return this.client.delete(`/agents/${agentId}/knowledge-sources/${sourceId}`);\n }\n\n /**\n * Get the agent's public share link, or `link: null` if none exists.\n * `link_feature: false` means share links are disabled on this deployment.\n */\n public async getShareLink(agentId: string): Promise<{ link_feature: boolean; link: AgentShareLink | null }> {\n const res = await this.client.get<{ link_feature: boolean; link: AgentShareLink | null }>(`/agents/${agentId}/testers`);\n return { link_feature: res.link_feature, link: res.link };\n }\n\n /**\n * Create the agent's public share link, or update its settings if one exists.\n */\n public async setShareLink(agentId: string, settings: AgentShareLinkSettings = {}): Promise<{ link: AgentShareLink }> {\n return this.client.put(`/agents/${agentId}/share-link`, settings);\n }\n\n /**\n * Issue a new URL for the share link. The old URL stops working immediately.\n */\n public async regenerateShareLink(agentId: string): Promise<{ link: AgentShareLink }> {\n return this.client.post(`/agents/${agentId}/share-link/regenerate`, {});\n }\n\n /**\n * List the recorded configuration changes for an agent (most recent first).\n * Optionally pass an ISO timestamp to only return changes since then.\n */\n public async listChanges(agentId: string, params: { since?: string } = {}): Promise<{ changes: AgentChange[] }> {\n const query = params.since ? `?since=${encodeURIComponent(params.since)}` : '';\n return this.client.get(`/agents/${agentId}/changes${query}`);\n }\n\n /**\n * Undo a single recorded configuration change, reverting that field to its\n * previous value. Returns the resulting agent snapshot.\n */\n public async undoChange(agentId: string, changeId: string): Promise<{ ok: boolean; changeId: string; agentSnapshot: Agent }> {\n return this.client.post(`/agents/${agentId}/changes/${changeId}/undo`, {});\n }\n\n /**\n * Run the evaluation suite for an agent. mode=\"synthetic\" (default) uses\n * the offline scorer; mode=\"live\" runs the model-driven runner.\n */\n public async runEvals(\n agentId: string,\n params: { mode?: 'synthetic' | 'live'; judge?: boolean } = {},\n ): Promise<Record<string, any>> {\n const query = new URLSearchParams();\n if (params.mode) query.set('mode', params.mode);\n if (params.judge) query.set('judge', '1');\n const qs = query.toString();\n return this.client.post(`/agents/${agentId}/evals/run${qs ? `?${qs}` : ''}`, {});\n }\n\n /**\n * Run the eval SUITE across many agents at once (agents × seeded scenarios),\n * bounded by the optional concurrency cap. One eval run is persisted per\n * agent; the aggregate EvalSuiteReport is returned. Pass `judge: true` to\n * supplement the heuristics with the opt-in LLM judge (needs a Gemini key).\n */\n public async runEvalSuite(params: {\n agentIds: string[];\n scenarioIds?: string[];\n concurrency?: number;\n judge?: boolean;\n }): Promise<Record<string, any>> {\n return this.client.post('/agents/evals/suite', params);\n }\n\n /**\n * List previous evaluation runs for an agent.\n */\n public async listEvalRuns(agentId: string): Promise<Record<string, any>> {\n return this.client.get(`/agents/${agentId}/evals/runs`);\n }\n\n /**\n * Retrieve a single evaluation run, including per-scenario scores.\n */\n public async getEvalRun(agentId: string, runId: string): Promise<Record<string, any>> {\n return this.client.get(`/agents/${agentId}/evals/runs/${runId}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface ListCallsParams {\n limit?: number;\n offset?: number;\n cursor?: string;\n status?: string;\n}\n\nexport interface CallRecord {\n id: string;\n agent_id: string;\n room_name: string;\n status: 'queued' | 'ringing' | 'in_progress' | 'completed' | 'failed' | 'busy' | 'canceled';\n duration_seconds?: number;\n started_at?: string;\n ended_at?: string;\n participants?: Array<{\n id: string;\n role: 'agent' | 'customer' | 'observer';\n transport: 'webrtc' | 'pstn' | 'sip' | 'internal';\n identity: string;\n status: string;\n }>;\n metadata?: Record<string, any>;\n intelligence_status?: string;\n participant_count?: number;\n primary_participant?: Record<string, any> | null;\n total_cost?: number;\n provider_cost?: number;\n provider_cost_breakdown?: Record<string, any>;\n provider_cost_calculated_at?: string | null;\n bill_duration?: number;\n}\n\nexport interface CallListResponse {\n calls: CallRecord[];\n total: number;\n limit: number;\n offset: number;\n next_cursor?: string | null;\n}\n\nexport interface CreateCallParams {\n agent_id: string;\n participants: Array<{\n transport: 'webrtc' | 'pstn';\n identity: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface BatchCallParams {\n agent_id: string;\n to?: string[];\n recipients?: Array<{\n to?: string;\n identity?: string;\n phone?: string;\n phone_number?: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n from_number?: string;\n batch_id?: string;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface FanoutCallParams {\n agent_id: string;\n to?: string[];\n recipients?: Array<{\n to?: string;\n identity?: string;\n phone?: string;\n phone_number?: string;\n from_number?: string;\n metadata?: Record<string, any>;\n }>;\n from_number?: string;\n /** Preferred tracking id for this fanout. Falls back to batch_id, then auto-generated. */\n fanout_id?: string;\n /** Compatibility alias for fanout_id. */\n batch_id?: string;\n metadata?: Record<string, any>;\n variables?: Record<string, any>;\n post_call?: Record<string, any>;\n}\n\nexport interface CreateCallResponse {\n id: string;\n room_name: string;\n status: string;\n participants: Array<{\n id: string;\n transport: 'webrtc' | 'pstn';\n identity: string;\n status: string;\n access?: { url: string; token: string };\n telephony_leg_id?: string;\n job_id?: string;\n }>;\n agent?: { id: string; name: string };\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n searchParams.set(key, String(value));\n }\n }\n const query = searchParams.toString();\n return query ? `?${query}` : '';\n}\n\nexport class CallsResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all previous and active calls.\n */\n public async list(params: ListCallsParams = {}): Promise<CallListResponse> {\n return this.client.get<CallListResponse>(`/calls${buildQuery(params)}`);\n }\n\n /**\n * Retrieve calls currently in progress.\n */\n public async active(params: ListCallsParams = {}): Promise<CallListResponse> {\n return this.client.get<CallListResponse>(`/calls/active${buildQuery(params)}`);\n }\n\n /**\n * Retrieve details, transcripts, and analysis of a single call by its unique ID.\n */\n public async retrieve(callId: string): Promise<CallRecord> {\n return this.client.get<CallRecord>(`/calls/${callId}`);\n }\n\n /**\n * Dispatch an outbound phone call securely using your configured carrier.\n */\n public async create(data: CreateCallParams): Promise<CreateCallResponse> {\n return this.client.post('/calls', data);\n }\n\n /**\n * Group call fanout: dial up to 500 PSTN participants into a single call room.\n * Every recipient joins the same call. For independent per-recipient attempts,\n * retries, and reports, use `campaigns` instead.\n */\n public async fanout(data: FanoutCallParams): Promise<CreateCallResponse & { fanout_id: string; batch_id: string; queued: number }> {\n return this.client.post('/calls/fanout', data);\n }\n\n /**\n * Compatibility alias for {@link fanout}. Creates one call room with multiple\n * PSTN participants. Queue up to 500 outbound PSTN recipients in one request.\n */\n public async batch(data: BatchCallParams): Promise<CreateCallResponse & { batch_id: string; queued: number }> {\n return this.client.post('/calls/batch', data);\n }\n\n public async summary(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/summary`);\n }\n\n public async transcript(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/transcript`);\n }\n\n public async recording(callId: string): Promise<Record<string, any>> {\n return this.client.get(`/calls/${callId}/recording`);\n }\n\n public async reprocess(callId: string): Promise<Record<string, any>> {\n return this.client.post(`/calls/${callId}/reprocess`);\n }\n\n /** Force-end an active call. Irreversible — closes the LiveKit room and triggers post-call processing. */\n public async end(callId: string): Promise<{ status: string; id: string; message: string }> {\n return this.client.post(`/calls/${callId}/end`);\n }\n\n /** Add one or more participants to an in-progress call (warm transfer / conference). */\n public async addParticipants(\n callId: string,\n data: { participants: CreateCallParams['participants'] }\n ): Promise<CreateCallResponse> {\n return this.client.post(`/calls/${callId}/participants`, data);\n }\n\n public async queueStats(): Promise<Record<string, number>> {\n return this.client.get('/calls/queue/stats');\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface DncEntry {\n id?: string;\n phone: string;\n reason?: string;\n created_at?: string;\n}\n\nexport interface DncListResponse {\n dnc_entries: DncEntry[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface DncCheckResult {\n phone_number: string;\n normalized: string | null;\n blocked: boolean;\n valid: boolean;\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\n/**\n * Do-Not-Call registry. Numbers are normalized to E.164 server-side on both\n * write and read, so any input format is accepted.\n */\nexport class DncResource {\n constructor(private client: RymiClient) {}\n\n /** List all DNC entries for the tenant. */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<DncListResponse> {\n return this.client.get<DncListResponse>(`/dnc${buildQuery(params)}`);\n }\n\n /** Add a single number to the Do-Not-Call registry. */\n public async add(data: { phone_number: string; reason?: string }): Promise<{ status: 'blocklisted'; phone_number: string }> {\n return this.client.post('/dnc', data);\n }\n\n /** Add up to 1000 numbers in one request. Invalid numbers are skipped and returned in `invalid`. */\n public async addBatch(data: { phone_numbers: string[]; reason?: string }): Promise<{ status: 'blocklisted'; count: number; invalid_count: number; invalid: string[] }> {\n return this.client.post('/dnc/batch', data);\n }\n\n /** Check up to 500 numbers without adding them. Read-only. */\n public async check(data: { phone_numbers: string[] }): Promise<{ results: DncCheckResult[]; blocked_count: number; total_checked: number }> {\n return this.client.post('/dnc/check', data);\n }\n\n /** Remove a number from the registry (re-enables outbound to it). */\n public async remove(phone: string): Promise<{ status: 'removed'; phone: string }> {\n return this.client.delete(`/dnc/${encodeURIComponent(phone)}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface NumberRecord {\n id?: string;\n number?: string;\n phone_number?: string;\n provider?: 'plivo' | 'twilio' | 'vonage' | 'telnyx';\n capabilities?: string[];\n price?: string | number;\n monthly_price?: number;\n agent_id?: string | null;\n assigned_agent_id?: string | null;\n created_at?: string;\n /** Carrier inbound-webhook provisioning state (set once an agent is attached). */\n webhook_status?: 'configured' | 'manual_required' | 'failed' | null;\n webhook_url?: string | null;\n webhook_error?: string | null;\n last_inbound_at?: string | null;\n}\n\n/** Outcome of carrier inbound-webhook auto-provisioning. */\nexport interface WebhookProvisionResult {\n status: 'configured' | 'manual_required' | 'failed' | 'no_carrier';\n provider: string | null;\n webhookUrl: string | null;\n verified: boolean;\n error?: string;\n}\n\nexport class NumbersResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Retrieve a list of all phone numbers assigned to your Rymi account.\n */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<{ numbers: NumberRecord[]; total: number; offset: number; limit: number }> {\n const searchParams = new URLSearchParams();\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.offset !== undefined) searchParams.set('offset', String(params.offset));\n const query = searchParams.toString();\n return this.client.get(`/numbers${query ? `?${query}` : ''}`);\n }\n\n public async register(number: string, params: { agent_id?: string } = {}): Promise<{ status: 'registered'; number: string; agent_id: string | null; webhook: WebhookProvisionResult | null }> {\n return this.client.post('/numbers', { number, ...params });\n }\n\n public async attach(number: string, agentId: string): Promise<{ status: 'attached'; agent_id: string; number: string; webhook: WebhookProvisionResult | null }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/attach`, { agent_id: agentId });\n }\n\n /** Clear the agent association without deregistering the number. */\n public async detach(number: string): Promise<{ status: 'detached'; number: string }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/detach`);\n }\n\n /** Re-run carrier inbound-webhook auto-provisioning for a number. */\n public async provisionWebhook(number: string): Promise<{ number: string; webhook: WebhookProvisionResult }> {\n return this.client.post(`/numbers/${encodeURIComponent(number)}/webhook`);\n }\n\n public async remove(number: string): Promise<{ status: 'removed'; number: string }> {\n return this.client.delete(`/numbers/${encodeURIComponent(number)}`);\n }\n}\n","import * as crypto from 'crypto';\nimport { RymiClient } from '../client';\n\nexport interface WebhookRecord {\n id: string;\n url: string;\n events: string[];\n alert_email?: string | null;\n created_at?: string;\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\nexport class WebhooksResource {\n constructor(private client: RymiClient) {}\n\n /** List registered webhook endpoints. The signing secret is never returned. */\n public async list(params: { limit?: number; offset?: number } = {}): Promise<{ webhooks: WebhookRecord[]; total: number; offset: number; limit: number }> {\n return this.client.get(`/webhooks${buildQuery(params)}`);\n }\n\n /** Register a webhook. `url` must be public https. `secret` must be 16–256 chars. */\n public async create(data: { url: string; events: string[]; secret: string; alert_email?: string }): Promise<{ status: 'registered' }> {\n return this.client.post('/webhooks', data);\n }\n\n /** Update a webhook. Only provided fields change. Pass `secret` to rotate it. */\n public async update(id: string, data: { url?: string; events?: string[]; secret?: string; alert_email?: string | null }): Promise<{ status: 'updated'; id: string }> {\n return this.client.patch(`/webhooks/${id}`, data);\n }\n\n /** Delete a webhook endpoint. */\n public async delete(id: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/webhooks/${id}`);\n }\n /**\n * Verifies that a webhook received by your backend was genuinely dispatched by Rymi.\n * \n * Rymi endpoints secure webhooks by computing an HMAC-SHA256 signature\n * of the raw JSON body concatenated with the timestamp, using your Webhook Secret.\n * \n * @param payload The raw stringified JSON body of the webhook hook request.\n * @param signatureHeader The value of the `X-Rymi-Signature` header from the request.\n * @param timestampHeader The value of the `X-Rymi-Timestamp` header from the request.\n * @param webhookSecret Your project's unique Webhook Signing Secret (starts with `whsec_`)\n * @param toleranceMillis Allowed time difference in milliseconds to prevent replay attacks (default 5 mins)\n * \n * @throws {Error} if the signature is invalid or if the timestamp exceeds the tolerance.\n */\n public verifySignature(\n payload: string,\n signatureHeader: string,\n timestampHeader: string,\n webhookSecret: string,\n toleranceMillis = 300000 // 5 minutes\n ): boolean {\n // 1. Check for Replay Attacks\n const timestamp = parseInt(timestampHeader, 10);\n if (isNaN(timestamp)) {\n throw new Error('Invalid Rymi-Timestamp header');\n }\n\n const now = Date.now();\n if (now - timestamp > toleranceMillis) {\n throw new Error('Webhook timestamp is too old. Possible replay attack.');\n }\n\n // 2. Prepare the verification string\n const signaturePayload = `${timestamp}.${payload}`;\n\n // 3. Compute the expected HMAC using the developer's Webhook Secret\n const expectedSignature = crypto\n .createHmac('sha256', webhookSecret)\n .update(signaturePayload, 'utf8')\n .digest('hex');\n\n // 4. Secure string comparison (constant-time to prevent timing attacks)\n try {\n const isValid = crypto.timingSafeEqual(\n Buffer.from(signatureHeader),\n Buffer.from(expectedSignature)\n );\n\n if (!isValid) {\n throw new Error('Invalid Webhook Signature. The secret might be incorrect.');\n }\n\n return true;\n } catch (err) {\n throw new Error('Invalid Webhook Signature. The secret might be incorrect.');\n }\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface PublishableKeyRecord {\n id: string;\n key_prefix: string;\n agent_id: string;\n label: string;\n allowed_channels: Array<'web' | 'phone'>;\n audience: 'sdk' | 'landing_demo';\n default_from_number: string | null;\n created_at: string;\n}\n\nexport interface CreatePublishableKeyParams {\n agent_id: string;\n label: string;\n allowed_channels?: Array<'web' | 'phone'>;\n audience?: 'sdk' | 'landing_demo';\n default_from_number?: string | null;\n}\n\nexport class KeysResource {\n constructor(private client: RymiClient) {}\n\n public async listPublishable(): Promise<{ keys: PublishableKeyRecord[] }> {\n return this.client.get('/keys/publishable');\n }\n\n public async createPublishable(data: CreatePublishableKeyParams): Promise<CreatePublishableKeyParams & { key: string }> {\n return this.client.post('/keys/publishable', data);\n }\n\n public async revokePublishable(id: string): Promise<{ success: true }> {\n return this.client.delete(`/keys/publishable/${id}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport type TelephonyProvider = 'plivo' | 'twilio' | 'vonage' | 'telnyx';\n\nexport interface ConnectTelephonyParams {\n provider: TelephonyProvider;\n auth_id?: string;\n auth_token?: string;\n api_key?: string;\n api_secret?: string;\n signature_secret?: string;\n /** Telnyx Ed25519 webhook signing secret (optional). */\n auth_secret?: string;\n}\n\nexport class TelephonyResource {\n constructor(private client: RymiClient) {}\n\n public async connect(data: ConnectTelephonyParams): Promise<{ status: 'connected'; provider: TelephonyProvider; account_name: string; message: string }> {\n return this.client.post('/telephony/connect', data);\n }\n\n public async disconnect(): Promise<{ status: 'disconnected'; message: string }> {\n return this.client.post('/telephony/disconnect');\n }\n\n public async status(): Promise<{ connected: boolean; provider: TelephonyProvider | null; account_name: string | null; account_country: string | null }> {\n return this.client.get('/telephony/status');\n }\n\n public async numbers(): Promise<{ numbers: any[] }> {\n return this.client.get('/telephony/numbers');\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface UsageSummary {\n voice_runtime: {\n remaining_minutes: number;\n status: string;\n };\n studio_ai?: {\n used_units?: number;\n included_units?: number | null;\n quota_percent?: number;\n status?: string;\n overage_enabled?: boolean;\n };\n post_call_intelligence?: {\n status?: string;\n used_units?: number;\n };\n}\n\nexport class BillingResource {\n constructor(private client: RymiClient) {}\n\n /**\n * Lane-aware usage summary: remaining voice-runtime minutes, Studio AI unit\n * usage, and post-call intelligence usage. Voice balance is reported in\n * MINUTES (the customer-facing unit), not dollars.\n */\n public async usageSummary(): Promise<UsageSummary> {\n return this.client.get<UsageSummary>('/billing/usage-summary');\n }\n\n /** Estimate the cost of a call for a custom model stack and duration. */\n public async estimate(data: { stt_model?: string; llm_model?: string; tts_model?: string; duration_seconds?: number } = {}): Promise<Record<string, any>> {\n return this.client.post('/billing/estimate', data);\n }\n\n /** Configure auto-recharge. Server rejects (400) if enabled && pack_usd <= threshold_usd. */\n public async setAutoRecharge(data: { enabled?: boolean; pack_usd?: number; threshold_usd?: number }): Promise<{ ok: true }> {\n return this.client.put('/billing/auto-recharge', data);\n }\n\n /** Configure spend-alert preferences. */\n public async setAlerts(data: { thresholds_usd?: number[]; low_balance_pct?: number; email_enabled?: boolean }): Promise<{ ok: true }> {\n return this.client.put('/billing/alerts', data);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface AgentTemplateSummary {\n id?: string;\n slug?: string;\n label?: string;\n description?: string;\n icon?: string;\n color?: string;\n defaults?: Record<string, any>;\n [key: string]: any;\n}\n\nexport class TemplatesResource {\n constructor(private client: RymiClient) {}\n\n /**\n * List published agent templates available to the current tenant. Use a\n * template's `defaults` as the starting config for create_agent.\n */\n public async list(): Promise<{ templates: AgentTemplateSummary[]; source?: string }> {\n return this.client.get('/agent-templates');\n }\n}\n","import { RymiClient } from '../client';\nimport type {\n Campaign,\n CampaignStatus,\n CampaignType,\n CampaignMember,\n CampaignAttempt,\n CampaignReport,\n CampaignGoal,\n CampaignCompliancePolicy\n} from '@rymi/sdk-types';\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\n// ─── list/create/update params + responses ─────────────────────────────────\n\nexport interface ListCampaignsParams {\n limit?: number;\n offset?: number;\n status?: CampaignStatus;\n type?: CampaignType;\n agent_id?: string;\n}\n\nexport interface CampaignListResponse {\n campaigns: Campaign[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateCampaignParams {\n agent_id: string;\n type: CampaignType;\n name: string;\n goal?: CampaignGoal;\n schedule_policy?: Record<string, unknown>;\n retry_policy?: Record<string, unknown>;\n concurrency_policy?: Record<string, unknown>;\n automation_policy?: Record<string, unknown>;\n reporting_policy?: Record<string, unknown>;\n compliance_policy?: CampaignCompliancePolicy;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateCampaignParams {\n name?: string;\n goal?: CampaignGoal;\n schedule_policy?: Record<string, unknown>;\n retry_policy?: Record<string, unknown>;\n concurrency_policy?: Record<string, unknown>;\n automation_policy?: Record<string, unknown>;\n reporting_policy?: Record<string, unknown>;\n compliance_policy?: CampaignCompliancePolicy;\n post_call_config_override?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface LaunchBlocker {\n code: string;\n ok: boolean;\n detail?: string;\n}\n\nexport interface LaunchCampaignResponse {\n campaign: Campaign;\n blockers: LaunchBlocker[];\n}\n\n/**\n * GET /campaigns/:id/report response. Extends the shared CampaignReport with\n * the report-endpoint-only derived fields (top failure reasons + cost per\n * success) that the API adds on top of the persisted shape.\n */\nexport interface CampaignReportResponse extends CampaignReport {\n distributions: CampaignReport['distributions'] & {\n top_failure_reasons: Array<{ reason: string; count: number }>;\n cost_per_success_credits: number;\n };\n}\n\n// ─── members ────────────────────────────────────────────────────────────────\n\nexport interface ListCampaignMembersParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignMemberListResponse {\n members: CampaignMember[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface AddCampaignMembersParams {\n contact_ids: string[];\n variables_override?: Record<string, string>;\n}\n\nexport interface ImportCampaignMembersParams {\n contacts?: Array<Record<string, unknown>>;\n csv?: string;\n}\n\nexport interface ImportCampaignMembersResponse {\n created: number;\n merged: number;\n /** Members attached to the campaign in this import. */\n attached: number;\n invalid: Array<{ row: number; reason: string }>;\n}\n\nexport interface UpdateCampaignMemberParams {\n status?: string;\n variables_override?: Record<string, string>;\n next_attempt_at?: string;\n}\n\nclass CampaignMembersResource {\n constructor(private client: RymiClient) {}\n\n /** List a campaign's members, paginated. */\n public async list(campaignId: string, params: ListCampaignMembersParams = {}): Promise<CampaignMemberListResponse> {\n return this.client.get(`/campaigns/${campaignId}/members${buildQuery(params)}`);\n }\n\n /** Attach existing contacts to a campaign as members. */\n public async add(campaignId: string, data: AddCampaignMembersParams): Promise<{ members: CampaignMember[] }> {\n return this.client.post(`/campaigns/${campaignId}/members`, data);\n }\n\n /** Import inline contact rows (JSON or CSV): creates/merges contacts and attaches members in one call. */\n public async import(campaignId: string, data: ImportCampaignMembersParams): Promise<ImportCampaignMembersResponse> {\n return this.client.post(`/campaigns/${campaignId}/members/import`, data);\n }\n\n /** Update a campaign member (status, variables, next attempt time). */\n public async update(campaignId: string, memberId: string, data: UpdateCampaignMemberParams): Promise<{ member: CampaignMember }> {\n return this.client.patch(`/campaigns/${campaignId}/members/${memberId}`, data);\n }\n\n /** Remove a member from a campaign. */\n public async remove(campaignId: string, memberId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/campaigns/${campaignId}/members/${memberId}`);\n }\n}\n\n// ─── inbound routes ─────────────────────────────────────────────────────────\n\nexport interface CampaignRoute {\n id: string;\n tenant_id: string;\n campaign_id: string;\n phone_number: string;\n schedule: Record<string, unknown>;\n active: boolean;\n created_at: string;\n updated_at: string;\n}\n\nexport interface ListCampaignRoutesParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface CampaignRouteListResponse {\n routes: CampaignRoute[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateCampaignRouteParams {\n phone_number: string;\n schedule?: Record<string, unknown>;\n active?: boolean;\n}\n\nexport interface UpdateCampaignRouteParams {\n schedule?: Record<string, unknown>;\n active?: boolean;\n}\n\nclass CampaignRoutesResource {\n constructor(private client: RymiClient) {}\n\n /** List a campaign's inbound routing rules. */\n public async list(campaignId: string, params: ListCampaignRoutesParams = {}): Promise<CampaignRouteListResponse> {\n return this.client.get(`/campaigns/${campaignId}/routes${buildQuery(params)}`);\n }\n\n /** Bind an owned phone number to this campaign for inbound routing. Only one active route per number is allowed. */\n public async create(campaignId: string, data: CreateCampaignRouteParams): Promise<{ route: CampaignRoute }> {\n return this.client.post(`/campaigns/${campaignId}/routes`, data);\n }\n\n /** Update an inbound route's schedule or active flag. */\n public async update(campaignId: string, routeId: string, data: UpdateCampaignRouteParams): Promise<{ route: CampaignRoute }> {\n return this.client.patch(`/campaigns/${campaignId}/routes/${routeId}`, data);\n }\n\n /** Delete an inbound route. */\n public async delete(campaignId: string, routeId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/campaigns/${campaignId}/routes/${routeId}`);\n }\n}\n\n// ─── attempts / batches / followups (read-only) ────────────────────────────\n\nexport interface ListCampaignAttemptsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignAttemptListResponse {\n attempts: CampaignAttempt[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface ListCampaignBatchesParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface CampaignBatch {\n id: string;\n tenant_id: string;\n campaign_id: string;\n batch_key: string;\n status: string;\n selected_count: number;\n queued_count: number;\n completed_count: number;\n failed_count: number;\n started_at?: string | null;\n completed_at?: string | null;\n created_at: string;\n}\n\nexport interface CampaignBatchListResponse {\n batches: CampaignBatch[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface ListCampaignFollowupsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignFollowupJob {\n id: string;\n tenant_id: string;\n campaign_id: string;\n campaign_attempt_id?: string | null;\n campaign_member_id?: string | null;\n kind: string;\n status: string;\n scheduled_at: string;\n consent_checked: boolean;\n capability_checked: boolean;\n idempotency_key: string;\n payload: Record<string, unknown>;\n result?: Record<string, unknown> | null;\n created_at: string;\n updated_at: string;\n}\n\nexport interface CampaignFollowupListResponse {\n followups: CampaignFollowupJob[];\n total: number;\n offset: number;\n limit: number;\n}\n\n// ─── improve / suggestions ──────────────────────────────────────────────────\n\nexport interface CampaignSuggestion {\n id: string;\n tenant_id: string;\n campaign_id: string;\n category: string;\n evidence: Record<string, unknown>;\n proposal: Record<string, unknown>;\n status: 'proposed' | 'accepted' | 'dismissed';\n created_by_model?: string | null;\n created_at: string;\n updated_at: string;\n}\n\nexport interface ImproveCampaignResponse {\n suggestions: CampaignSuggestion[];\n}\n\nexport interface ListCampaignSuggestionsParams {\n limit?: number;\n offset?: number;\n status?: string;\n}\n\nexport interface CampaignSuggestionListResponse {\n suggestions: CampaignSuggestion[];\n total: number;\n offset: number;\n limit: number;\n}\n\n// ─── CampaignIntakeResource ──────────────────────────────────────────────────\n\n/** A campaign's lead-intake URL settings. The URL itself is only returned on create/rotate. */\nexport interface CampaignIntake {\n enabled: true;\n assume_voice_consent: boolean;\n default_country: string | null;\n created_at: string;\n rotated_at: string;\n last_used_at: string | null;\n}\n\nexport interface CampaignIntakeSettings {\n /** Treat every lead posted to the URL as having voice consent (e.g. a subscribe form with a consent line). */\n assume_voice_consent?: boolean;\n /** ISO-3166 alpha-2 (e.g. \"IN\") used for numbers posted without a +country code. */\n default_country?: string | null;\n}\n\nclass CampaignIntakeResource {\n constructor(private client: RymiClient) {}\n\n /** Get the campaign's lead-intake settings, or `intake: null` if it has none. */\n public async get(campaignId: string): Promise<{ intake: CampaignIntake | null }> {\n return this.client.get(`/campaigns/${campaignId}/intake`);\n }\n\n /** Create the lead-intake URL (returned once as `url`), or update its settings (`url: null`). */\n public async set(campaignId: string, settings: CampaignIntakeSettings = {}): Promise<{ intake: CampaignIntake; url: string | null }> {\n return this.client.put(`/campaigns/${campaignId}/intake`, settings);\n }\n\n /** Issue a new URL. The old one stops accepting leads immediately. */\n public async rotate(campaignId: string): Promise<{ intake: CampaignIntake; url: string }> {\n return this.client.post(`/campaigns/${campaignId}/intake/rotate`, {});\n }\n\n /** Remove the lead-intake URL. */\n public async disable(campaignId: string): Promise<void> {\n return this.client.delete(`/campaigns/${campaignId}/intake`);\n }\n}\n\n// ─── CampaignsResource ───────────────────────────────────────────────────────\n\nexport class CampaignsResource {\n public members: CampaignMembersResource;\n public routes: CampaignRoutesResource;\n public intake: CampaignIntakeResource;\n\n constructor(private client: RymiClient) {\n this.members = new CampaignMembersResource(client);\n this.routes = new CampaignRoutesResource(client);\n this.intake = new CampaignIntakeResource(client);\n }\n\n /** List campaigns for the authenticated tenant, paginated. */\n public async list(params: ListCampaignsParams = {}): Promise<CampaignListResponse> {\n return this.client.get(`/campaigns${buildQuery(params)}`);\n }\n\n /** Create a new campaign in draft status against a published agent. */\n public async create(data: CreateCampaignParams): Promise<{ campaign: Campaign }> {\n return this.client.post('/campaigns', data);\n }\n\n /** Retrieve a single campaign by id. */\n public async get(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.get(`/campaigns/${campaignId}`);\n }\n\n /** Update campaign policy/goal fields. Status and lifecycle fields are not writable here. */\n public async update(campaignId: string, data: UpdateCampaignParams): Promise<{ campaign: Campaign }> {\n return this.client.patch(`/campaigns/${campaignId}`, data);\n }\n\n /**\n * Launch a campaign: validates launch blockers, then stamps\n * `launched_at` + `agent_snapshot_id`, flips members to `ready`, and\n * transitions status to `running`.\n */\n public async launch(campaignId: string): Promise<LaunchCampaignResponse> {\n return this.client.post(`/campaigns/${campaignId}/launch`);\n }\n\n /** Evaluate launch blockers without launching (dry run). Safe from any status. */\n public async launchBlockers(campaignId: string): Promise<{ blockers: LaunchBlocker[]; launchable: boolean }> {\n return this.client.get(`/campaigns/${campaignId}/launch-blockers`);\n }\n\n /** Pause a running campaign. In-flight calls finish naturally. */\n public async pause(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/pause`);\n }\n\n /** Resume a paused campaign. */\n public async resume(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/resume`);\n }\n\n /** Archive a campaign. Terminal — the scheduler never selects work for it again. */\n public async archive(campaignId: string): Promise<{ campaign: Campaign }> {\n return this.client.post(`/campaigns/${campaignId}/archive`);\n }\n\n /** Read the campaign report: `stat_*` summary counters + outcome/sentiment/hourly/snapshot distributions. */\n public async report(campaignId: string): Promise<CampaignReportResponse> {\n return this.client.get(`/campaigns/${campaignId}/report`);\n }\n\n /** List a campaign's dial attempts, paginated. */\n public async attempts(campaignId: string, params: ListCampaignAttemptsParams = {}): Promise<CampaignAttemptListResponse> {\n return this.client.get(`/campaigns/${campaignId}/attempts${buildQuery(params)}`);\n }\n\n /** List a campaign's sweep-claim batches, paginated. */\n public async batches(campaignId: string, params: ListCampaignBatchesParams = {}): Promise<CampaignBatchListResponse> {\n return this.client.get(`/campaigns/${campaignId}/batches${buildQuery(params)}`);\n }\n\n /** List a campaign's follow-up jobs, paginated. */\n public async followups(campaignId: string, params: ListCampaignFollowupsParams = {}): Promise<CampaignFollowupListResponse> {\n return this.client.get(`/campaigns/${campaignId}/followups${buildQuery(params)}`);\n }\n\n /** Run the improve engine: detectors gate an LLM proposal writer, persisting new `campaign_suggestions`. */\n public async improve(campaignId: string): Promise<ImproveCampaignResponse> {\n return this.client.post(`/campaigns/${campaignId}/improve`);\n }\n\n /** List a campaign's improvement suggestions, paginated. */\n public async suggestions(campaignId: string, params: ListCampaignSuggestionsParams = {}): Promise<CampaignSuggestionListResponse> {\n return this.client.get(`/campaigns/${campaignId}/suggestions${buildQuery(params)}`);\n }\n\n /** Accept a suggestion: agent-editing suggestions create an agent-changes draft; campaign-policy suggestions patch the campaign. */\n public async acceptSuggestion(campaignId: string, suggestionId: string): Promise<{ suggestion: CampaignSuggestion }> {\n return this.client.post(`/campaigns/${campaignId}/suggestions/${suggestionId}/accept`);\n }\n\n /** Dismiss a suggestion without applying it. */\n public async dismissSuggestion(campaignId: string, suggestionId: string): Promise<{ suggestion: CampaignSuggestion }> {\n return this.client.post(`/campaigns/${campaignId}/suggestions/${suggestionId}/dismiss`);\n }\n}\n","import { RymiClient } from '../client';\nimport type { Contact } from '@rymi/sdk-types';\n\nexport interface ListContactsParams {\n limit?: number;\n offset?: number;\n}\n\nexport interface ContactListResponse {\n contacts: Contact[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport interface CreateContactParams {\n phone?: string;\n email?: string;\n name?: string;\n timezone?: string;\n language?: string;\n tags?: string[];\n custom_fields?: Record<string, unknown>;\n consent?: Record<string, boolean>;\n source?: string;\n}\n\nexport interface CreateContactResponse {\n contact: Contact;\n deduped: boolean;\n}\n\nexport interface UpdateContactParams {\n phone?: string;\n email?: string | null;\n name?: string | null;\n timezone?: string | null;\n language?: string | null;\n tags?: string[];\n custom_fields?: Record<string, unknown>;\n consent?: Record<string, boolean>;\n source?: string | null;\n}\n\nexport interface ImportContactsParams {\n contacts?: Array<Record<string, unknown>>;\n csv?: string;\n}\n\nexport interface ImportContactsResponse {\n created: number;\n merged: number;\n invalid: Array<{ row: number; reason: string }>;\n}\n\nexport interface SetConsentParams {\n channel: 'voice' | 'sms' | 'whatsapp' | 'telegram';\n granted: boolean;\n source?: string;\n method?: string;\n}\n\nexport interface SetConsentResponse {\n contact_id: string;\n channel: string;\n consent: { granted: boolean; at: string; source: string; method: string };\n}\n\nfunction buildQuery(params: Record<string, any>) {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) sp.set(k, String(v));\n }\n const q = sp.toString();\n return q ? `?${q}` : '';\n}\n\nexport class ContactsResource {\n constructor(private client: RymiClient) {}\n\n /** List tenant-level contacts, paginated. */\n public async list(params: ListContactsParams = {}): Promise<ContactListResponse> {\n return this.client.get(`/contacts${buildQuery(params)}`);\n }\n\n /**\n * Create a tenant-level contact. If a contact with the same\n * (tenant, phone) already exists, the existing row is returned instead\n * of creating a duplicate — check `deduped` in the response.\n */\n public async create(data: CreateContactParams): Promise<CreateContactResponse> {\n return this.client.post('/contacts', data);\n }\n\n /** Retrieve a single tenant-scoped contact by id. */\n public async get(contactId: string): Promise<{ contact: Contact }> {\n return this.client.get(`/contacts/${contactId}`);\n }\n\n /** Update an existing tenant-scoped contact. Only provided fields change. */\n public async update(contactId: string, data: UpdateContactParams): Promise<{ contact: Contact }> {\n return this.client.patch(`/contacts/${contactId}`, data);\n }\n\n /** Delete a tenant-scoped contact. */\n public async delete(contactId: string): Promise<{ status: 'deleted'; id: string }> {\n return this.client.delete(`/contacts/${contactId}`);\n }\n\n /**\n * Bulk import contacts from JSON rows or CSV text. Each row's phone is\n * normalized to E.164 and upserted on (tenant_id, phone); rows with\n * unparseable phones are skipped and reported in `invalid`.\n */\n public async import(data: ImportContactsParams): Promise<ImportContactsResponse> {\n return this.client.post('/contacts/import', data);\n }\n\n /** Record a consent grant or revoke for one channel, with evidence. Also\n * appends an immutable row to the consent_events proof log. */\n public async setConsent(contactId: string, data: SetConsentParams): Promise<SetConsentResponse> {\n return this.client.patch(`/contacts/${contactId}/consent`, data);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface AttestParams {\n kind: 'dnc_external_scrub' | 'ai_disclosure';\n note?: string;\n}\n\nexport interface Attestation {\n id: string;\n tenant_id: string;\n kind: string;\n attested_by: string | null;\n note: string | null;\n created_at: string;\n}\n\nexport interface AttestResponse {\n attestation: Attestation;\n}\n\nexport interface ListAttestationsResponse {\n attestations: Attestation[];\n}\n\nexport class ComplianceResource {\n constructor(private client: RymiClient) {}\n\n /** Record a compliance attestation (append-only). Campaign launch blockers\n * in `attested` mode read the most recent one of the matching `kind`. */\n public async attest(data: AttestParams): Promise<AttestResponse> {\n return this.client.post('/compliance/attestations', data);\n }\n\n /** List the tenant's 50 most recent compliance attestations, newest first. */\n public async listAttestations(): Promise<ListAttestationsResponse> {\n return this.client.get('/compliance/attestations');\n }\n}\n","import { RymiClient } from '../client';\n\n/** A stored API-tool secret. Values are write-only — never returned. */\nexport interface ToolSecretRecord {\n name: string;\n /** The only host this secret is ever sent to. */\n host: string | null;\n}\n\n/**\n * Tenant secrets referenced from call_webhook headers as `{{secrets.NAME}}`.\n * Each secret is pinned to one host and only interpolated into requests to it.\n */\nexport class ToolSecretsResource {\n constructor(private client: RymiClient) {}\n\n public async list(): Promise<{ data: ToolSecretRecord[] }> {\n return this.client.get('/tool-secrets');\n }\n\n /** Create or replace. `name` is UPPER_SNAKE_CASE; `host` is a public hostname. */\n public async set(name: string, data: { value: string; host: string }): Promise<{ data: { name: string } }> {\n return this.client.put(`/tool-secrets/${encodeURIComponent(name)}`, data);\n }\n\n public async delete(name: string): Promise<{ data: { name: string } }> {\n return this.client.delete(`/tool-secrets/${encodeURIComponent(name)}`);\n }\n}\n","import { RymiClient } from '../client';\n\nexport interface Workspace {\n id: string;\n name: string;\n role: 'owner' | 'admin' | 'client';\n /** The agency, for a client workspace. */\n parent_id: string | null;\n operating_country: string | null;\n /** Client workspaces only; absent for the client role. */\n spend_cap_cents_monthly?: number | null;\n current?: boolean;\n}\n\nexport interface CreateWorkspaceParams {\n name: string;\n /** ISO-3166 alpha-2, e.g. \"IN\". */\n operating_country?: string | null;\n /** An agency workspace you run: makes this a client workspace that the agency pays for. */\n parent?: string;\n}\n\nexport interface UpdateWorkspaceParams {\n name?: string;\n operating_country?: string | null;\n /** Client workspaces only. Credits per calendar month (1 credit = $0.01); null removes the cap. */\n spend_cap_cents_monthly?: number | null;\n}\n\nexport interface WorkspaceUsage {\n workspace_id: string;\n /** YYYY-MM, UTC. */\n month: string;\n calls: number;\n minutes: number;\n /** Left out for the client role. */\n credits?: number;\n}\n\nexport interface WorkspaceMember {\n user_id: string;\n email: string | null;\n role: 'owner' | 'admin' | 'client';\n}\n\nexport class WorkspacesResource {\n constructor(private client: RymiClient) {}\n\n public async list(): Promise<{ workspaces: Workspace[] }> {\n return this.client.get('/workspaces');\n }\n\n public async create(data: CreateWorkspaceParams): Promise<{ workspace: Workspace }> {\n return this.client.post('/workspaces', data);\n }\n\n public async update(id: string, data: UpdateWorkspaceParams): Promise<{ ok: true }> {\n return this.client.patch(`/workspaces/${encodeURIComponent(id)}`, data);\n }\n\n /** Calls, minutes and credits for one month (default: this month, UTC). */\n public async usage(id: string, params: { month?: string } = {}): Promise<WorkspaceUsage> {\n const query = params.month ? `?month=${encodeURIComponent(params.month)}` : '';\n return this.client.get(`/workspaces/${encodeURIComponent(id)}/usage${query}`);\n }\n\n public async listMembers(id: string): Promise<{ members: WorkspaceMember[] }> {\n return this.client.get(`/workspaces/${encodeURIComponent(id)}/members`);\n }\n\n /** Someone without a Rymi account gets an invite email. Client workspaces take the client role. */\n public async addMember(id: string, data: { email: string; role?: 'admin' | 'client' }): Promise<{ member: WorkspaceMember }> {\n return this.client.post(`/workspaces/${encodeURIComponent(id)}/members`, data);\n }\n\n public async removeMember(id: string, userId: string): Promise<{ ok: true }> {\n return this.client.delete(`/workspaces/${encodeURIComponent(id)}/members/${encodeURIComponent(userId)}`);\n }\n}\n","import { RymiClient, ClientOptions, RymiError } from './client';\nimport { AgentsResource } from './resources/agents';\nimport { CallsResource } from './resources/calls';\nimport { DncResource } from './resources/dnc';\nimport { NumbersResource } from './resources/numbers';\nimport { WebhooksResource } from './resources/webhooks';\nimport { KeysResource } from './resources/keys';\nimport { TelephonyResource } from './resources/telephony';\nimport { BillingResource } from './resources/billing';\nimport { TemplatesResource } from './resources/templates';\nimport { CampaignsResource } from './resources/campaigns';\nimport { ContactsResource } from './resources/contacts';\nimport { ComplianceResource } from './resources/compliance';\nimport { ToolSecretsResource } from './resources/toolSecrets';\nimport { WorkspacesResource } from './resources/workspaces';\n\nexport class Rymi {\n private client: RymiClient;\n\n public agents: AgentsResource;\n public calls: CallsResource;\n public dnc: DncResource;\n public numbers: NumbersResource;\n public webhooks: WebhooksResource;\n public keys: KeysResource;\n public telephony: TelephonyResource;\n public billing: BillingResource;\n public templates: TemplatesResource;\n public campaigns: CampaignsResource;\n public contacts: ContactsResource;\n public compliance: ComplianceResource;\n public toolSecrets: ToolSecretsResource;\n public workspaces: WorkspacesResource;\n\n constructor(options?: ClientOptions) {\n this.client = new RymiClient(options);\n\n // Initialize API Sub-modules\n this.agents = new AgentsResource(this.client);\n this.calls = new CallsResource(this.client);\n this.dnc = new DncResource(this.client);\n this.numbers = new NumbersResource(this.client);\n this.webhooks = new WebhooksResource(this.client);\n this.keys = new KeysResource(this.client);\n this.telephony = new TelephonyResource(this.client);\n this.billing = new BillingResource(this.client);\n this.templates = new TemplatesResource(this.client);\n this.campaigns = new CampaignsResource(this.client);\n this.contacts = new ContactsResource(this.client);\n this.compliance = new ComplianceResource(this.client);\n this.toolSecrets = new ToolSecretsResource(this.client);\n this.workspaces = new WorkspacesResource(this.client);\n }\n}\n\n// Re-export common types\nexport * from './client';\nexport * from './resources/agents';\nexport * from './resources/calls';\nexport * from './resources/dnc';\nexport * from './resources/numbers';\nexport * from './resources/webhooks';\nexport * from './resources/keys';\nexport * from './resources/telephony';\nexport * from './resources/billing';\nexport * from './resources/templates';\nexport * from './resources/campaigns';\nexport * from './resources/contacts';\nexport * from './resources/compliance';\nexport * from './resources/toolSecrets';\nexport * from './resources/workspaces';\n\n// Re-export the curated public type surface (see @rymi/sdk-types).\nexport * from '@rymi/sdk-types';\nexport default Rymi;\n"],"mappings":"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","names":["buildQuery","buildQuery","buildQuery","buildQuery"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rymi/node",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "The official Node.js REST API wrapper for Rymi.",
5
5
  "license": "MIT",
6
6
  "author": "Rymi AI <engineering@rymi.live>",