@cosmoops/connect-sdk 0.38.0 → 0.41.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/dist/cjs/client/components/availability-form.js +52 -24
  3. package/dist/cjs/client/components/call-button.js +398 -0
  4. package/dist/cjs/client/components/create-workspace-form.js +66 -0
  5. package/dist/cjs/client/components/event-type-form.js +99 -25
  6. package/dist/cjs/client/components/workspace-switcher.js +42 -9
  7. package/dist/cjs/client/index.js +17 -2
  8. package/dist/cjs/client/portal-links.js +1 -1
  9. package/dist/cjs/client/use-scheduling.js +37 -0
  10. package/dist/cjs/client/use-workspaces.js +41 -0
  11. package/dist/cjs/server/client.js +1 -1
  12. package/dist/cjs/server/handler.js +176 -2
  13. package/dist/cjs/server/resources/calls.js +58 -0
  14. package/dist/cjs/server/resources/scheduling.js +67 -0
  15. package/dist/cjs/server/resources/workspaces.js +30 -11
  16. package/dist/esm/client/components/availability-form.js +53 -25
  17. package/dist/esm/client/components/call-button.js +358 -0
  18. package/dist/esm/client/components/create-workspace-form.js +63 -0
  19. package/dist/esm/client/components/event-type-form.js +100 -26
  20. package/dist/esm/client/components/workspace-switcher.js +42 -9
  21. package/dist/esm/client/index.js +8 -2
  22. package/dist/esm/client/portal-links.js +1 -1
  23. package/dist/esm/client/use-scheduling.js +34 -0
  24. package/dist/esm/client/use-workspaces.js +38 -0
  25. package/dist/esm/server/client.js +1 -1
  26. package/dist/esm/server/handler.js +176 -2
  27. package/dist/esm/server/resources/calls.js +58 -0
  28. package/dist/esm/server/resources/scheduling.js +67 -0
  29. package/dist/esm/server/resources/workspaces.js +30 -11
  30. package/dist/types/client/components/availability-form.d.ts +23 -12
  31. package/dist/types/client/components/call-button.d.ts +132 -0
  32. package/dist/types/client/components/create-workspace-form.d.ts +32 -0
  33. package/dist/types/client/components/event-type-form.d.ts +30 -8
  34. package/dist/types/client/components/workspace-switcher.d.ts +9 -9
  35. package/dist/types/client/index.d.ts +7 -1
  36. package/dist/types/client/portal-links.d.ts +1 -1
  37. package/dist/types/client/use-scheduling.d.ts +46 -2
  38. package/dist/types/client/use-workspaces.d.ts +27 -0
  39. package/dist/types/server/client.d.ts +1 -1
  40. package/dist/types/server/resources/calls.d.ts +32 -1
  41. package/dist/types/server/resources/scheduling.d.ts +66 -2
  42. package/dist/types/server/resources/workspaces.d.ts +28 -0
  43. package/dist/types/types.d.ts +143 -1
  44. package/package.json +4 -1
@@ -11,6 +11,10 @@ import type { ConnectInvitation, ConnectMemberAccess, ConnectMemberAccessResult,
11
11
  * `createConnectHandler`, and it is why a partner cannot enumerate another
12
12
  * tenant's team with their own API key.
13
13
  */
14
+ export interface CreateUserWorkspaceInput {
15
+ name: string;
16
+ type: "individual" | "business";
17
+ }
14
18
  export declare class WorkspacesResource {
15
19
  private readonly transport;
16
20
  constructor(transport: TransportOptions);
@@ -24,6 +28,30 @@ export declare class WorkspacesResource {
24
28
  list(options: {
25
29
  asUser: string;
26
30
  }): Promise<UserWorkspace[]>;
31
+ /**
32
+ * Opens another workspace under the tenant the signed-in user already
33
+ * owns - a branch office, a second business unit.
34
+ *
35
+ * Every guard `CreateWorkspaceUseCase` enforces still applies: only the
36
+ * tenant's owner may call this, `type: "business"` still needs a non-free
37
+ * email domain, and the tenant's plan still decides whether it may hold
38
+ * another workspace at all - a `PreconditionError` surfaces as a thrown
39
+ * `ConnectError` with a message written to be shown ("Your current plan
40
+ * covers a single workspace...", "You've used all 3 of the workspaces
41
+ * your plans include..."). There is no `tenantId` parameter: the caller
42
+ * names no tenant, same as every other method on this resource names no
43
+ * workspace.
44
+ *
45
+ * `isActive`/`subscribed` on the result are always `false` - this does not
46
+ * switch the session, and the new workspace has no subscription yet. Chain
47
+ * `switch({workspaceId: result.workspaceId})` to move into it, but only
48
+ * when `result.inAudience` - a workspace outside this application's
49
+ * audience is refused by `switch` the same way `selectable()` in
50
+ * `<ConnectWorkspaceSwitcher>` already treats it.
51
+ */
52
+ create(input: CreateUserWorkspaceInput, options: {
53
+ asUser: string;
54
+ }): Promise<UserWorkspace>;
27
55
  /**
28
56
  * Moves this session to another workspace, returning a **new session
29
57
  * token**. The one you passed is revoked.
@@ -1269,12 +1269,29 @@ export interface CallCompletedEvent {
1269
1269
  * for presence.
1270
1270
  */
1271
1271
  extraction: Record<string, unknown>;
1272
+ /**
1273
+ * `member` when a person placed this call from a browser - `<ConnectCallButton>`
1274
+ * or Connect's own portal - rather than an agent handling it. Absent on
1275
+ * events sent before member calling existed; treat absent as `agent`.
1276
+ */
1277
+ handler?: CallHandler;
1278
+ /**
1279
+ * The member who placed a `member` call - their Connect user id, the same id
1280
+ * a workspace roster carries. The one to attribute the call to. `null` on an
1281
+ * agent's call.
1282
+ */
1283
+ placedByUserId?: string | null;
1284
+ /** That member's display name, else their email - so the call can be attributed without a roster read. */
1285
+ placedByName?: string | null;
1272
1286
  /** ISO-8601. */
1273
1287
  occurredAt: string;
1274
1288
  }
1275
1289
  /**
1276
1290
  * A call reached a channel and nothing answered it.
1277
1291
  *
1292
+ * Also raised for a call a member placed that the person rang did not pick
1293
+ * up (`handler: "member"`, `direction: "outbound"`) - somebody to try again.
1294
+ *
1278
1295
  * Its own event rather than an `outcome` on the one above, because the action
1279
1296
  * differs in kind: a completed call is something to file, a missed one is
1280
1297
  * somebody to ring back. Treating this as a lead is the right thing to do
@@ -1287,6 +1304,20 @@ export interface CallMissedEvent {
1287
1304
  /** E.164, and the only identity this carries - see `CallCompletedEvent.contactPhone`. */
1288
1305
  contactPhone: string | null;
1289
1306
  direction: ConnectCallDirection;
1307
+ /**
1308
+ * `member` when a person placed this call from a browser - `<ConnectCallButton>`
1309
+ * or Connect's own portal - rather than an agent handling it. Absent on
1310
+ * events sent before member calling existed; treat absent as `agent`.
1311
+ */
1312
+ handler?: CallHandler;
1313
+ /**
1314
+ * The member who placed a `member` call - their Connect user id, the same id
1315
+ * a workspace roster carries. The one to attribute the call to. `null` on an
1316
+ * agent's call.
1317
+ */
1318
+ placedByUserId?: string | null;
1319
+ /** That member's display name, else their email - so the call can be attributed without a roster read. */
1320
+ placedByName?: string | null;
1290
1321
  /** ISO-8601. */
1291
1322
  occurredAt: string;
1292
1323
  }
@@ -2029,6 +2060,39 @@ export interface AvailabilitySchedule {
2029
2060
  id: string;
2030
2061
  name: string;
2031
2062
  timezone: string;
2063
+ weeklyHours: WeeklyHours;
2064
+ }
2065
+ /**
2066
+ * One appointment type, as a management UI sees it - richer than
2067
+ * `BookableEventType`'s booking-catalogue shape, which deliberately
2068
+ * withholds `location.value` and everything else here. Fetched from
2069
+ * `listManageableEventTypes`, never the booking flow's `listEventTypes`.
2070
+ *
2071
+ * `host` collapses a group host to `{kind:"group"}` with nothing else -
2072
+ * there is no groups read in this API, so a team host is representable only
2073
+ * as "not this, edit it in Connect".
2074
+ */
2075
+ export interface ManageableEventType {
2076
+ id: string;
2077
+ slug: string;
2078
+ name: string;
2079
+ description: string | null;
2080
+ durationMinutes: number;
2081
+ bufferBeforeMinutes: number;
2082
+ bufferAfterMinutes: number;
2083
+ host: {
2084
+ kind: "member";
2085
+ memberId: string;
2086
+ } | {
2087
+ kind: "group";
2088
+ };
2089
+ scheduleId: string;
2090
+ location: {
2091
+ kind: "phone" | "address" | "link";
2092
+ value: string | null;
2093
+ };
2094
+ active: boolean;
2095
+ publicBookingEnabled: boolean;
2032
2096
  }
2033
2097
  /**
2034
2098
  * A phone or email on a contact.
@@ -2663,8 +2727,16 @@ export type CallDirection = "inbound" | "outbound";
2663
2727
  * `rejected` means Connect never connected it - see `rejectReason`.
2664
2728
  * `answered` is a call still in progress; `completed` is one that ran and
2665
2729
  * ended.
2730
+ *
2731
+ * `dialing` and `unanswered` are an outbound call's: ringing, and nobody
2732
+ * picked up - see `unansweredReason`. A call your `<ConnectCallButton>`
2733
+ * placed passes through `dialing` on its way to one of the other two.
2666
2734
  */
2667
- export type CallStatus = "answered" | "rejected" | "completed";
2735
+ export type CallStatus = "dialing" | "answered" | "rejected" | "unanswered" | "completed";
2736
+ /** Who was on Connect's end of a call: one of the workspace's agents, or a member calling from a browser. */
2737
+ export type CallHandler = "agent" | "member";
2738
+ /** Why an outbound call reached nobody. Widened at its use site like `CallRejectReason`. */
2739
+ export type CallUnansweredReason = "no_answer" | "busy" | "failed" | "cancelled";
2668
2740
  /**
2669
2741
  * Why a call was refused. Widened at the point of use with `(string & {})`,
2670
2742
  * the same way `ReadinessBlocker.code` is: Connect adds reasons as it learns
@@ -2732,6 +2804,76 @@ export interface ConnectCall {
2732
2804
  extraction: Record<string, unknown> | null;
2733
2805
  agentId: string | null;
2734
2806
  agentVersion: number | null;
2807
+ /** `member` for a call a person placed with `<ConnectCallButton>`; such a call has no agent, transcript or recording. */
2808
+ handler: CallHandler;
2809
+ /** The member who placed a `member` call - their Connect user id. */
2810
+ placedByUserId: string | null;
2811
+ /**
2812
+ * How long the person called was on the line, for a `member` call. Read this
2813
+ * rather than `durationSeconds`, which there measures the member's own leg,
2814
+ * ringing included. `null` until the carrier reports it, and for a call
2815
+ * nobody answered.
2816
+ */
2817
+ talkSeconds: number | null;
2818
+ /** Why nobody answered - set only when `status` is `unanswered`. */
2819
+ unansweredReason: CallUnansweredReason | (string & {}) | null;
2820
+ }
2821
+ /**
2822
+ * What the browser needs to place one approved call - see
2823
+ * `calls.startBrowserCall`. `headers` are SIP headers to send with it; they
2824
+ * carry a one-time key, valid for two minutes, that lets the call be placed
2825
+ * once and by nobody else.
2826
+ */
2827
+ export interface StartedBrowserCall {
2828
+ callId: string;
2829
+ /** The number being rung, E.164. */
2830
+ toNumber: string;
2831
+ /** The workspace's own number, which the person called will see. */
2832
+ fromNumber: string;
2833
+ headers: Record<string, string>;
2834
+ }
2835
+ /**
2836
+ * Why a member can or cannot call - see `calls.getCallingAvailability`.
2837
+ *
2838
+ * - `no_permission` - they lack "Make calls". Don't offer calling.
2839
+ * - `no_number` - the workspace has no business number. `offer` says where to
2840
+ * buy one (a "Business number" add-on on one of its subscriptions).
2841
+ * - `number_pending` - one was bought but Connect's pool was empty; an admin
2842
+ * can retry from Connect's Calling page.
2843
+ * - `no_balance` - a number, but not a minute's worth of prepaid minutes.
2844
+ * - `available`.
2845
+ */
2846
+ export type CallingAvailabilityStatus = "available" | "no_permission" | "no_number" | "number_pending" | "no_balance";
2847
+ export interface CallingAvailability {
2848
+ status: CallingAvailabilityStatus;
2849
+ /** The workspace's business number, E.164, when it holds one. */
2850
+ number: string | null;
2851
+ /** Prepaid balance a new call may spend, in paise, pre-tax. */
2852
+ available: number;
2853
+ /** About how many minutes that buys. */
2854
+ availableMinutes: number;
2855
+ ratePaisePerMinute: number;
2856
+ /** Under about 55 minutes - worth a warning. */
2857
+ lowBalance: boolean;
2858
+ /** Whether this member may buy minutes. */
2859
+ canTopUp: boolean;
2860
+ /** Whether this member may add the number add-on or retry a pending number. */
2861
+ canManageNumber: boolean;
2862
+ /** Where a business number can be bought, when the workspace has none. */
2863
+ offer: {
2864
+ subscriptionId: string;
2865
+ applicationId: string;
2866
+ addonId: string;
2867
+ addonName: string;
2868
+ /** Pre-tax, paise, per billing cycle. */
2869
+ price: number;
2870
+ } | null;
2871
+ }
2872
+ /** A carrier access token a member's browser signs in to the phone network with. Valid for an hour. */
2873
+ export interface BrowserCallingToken {
2874
+ token: string;
2875
+ /** ISO-8601. */
2876
+ expiresAt: string;
2735
2877
  }
2736
2878
  /** Who spoke. */
2737
2879
  export type CallTurnRole = "user" | "agent";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmoops/connect-sdk",
3
- "version": "0.38.0",
3
+ "version": "0.41.0",
4
4
  "description": "Official server-side SDK for the CosmoOps Connect platform API - Login with Connect, entitlements, billing and metering.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "commonjs",
@@ -136,5 +136,8 @@
136
136
  "streamdown": {
137
137
  "optional": true
138
138
  }
139
+ },
140
+ "dependencies": {
141
+ "plivo-browser-sdk": "2.2.21"
139
142
  }
140
143
  }