@cosmoops/connect-sdk 0.20.0 → 0.23.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 (48) hide show
  1. package/CHANGELOG.md +281 -0
  2. package/README.md +2 -0
  3. package/dist/cjs/client/components/identity.js +24 -0
  4. package/dist/cjs/client/components/one-tap-state.js +96 -0
  5. package/dist/cjs/client/components/one-tap.js +106 -0
  6. package/dist/cjs/client/components/plan-pricing.js +28 -0
  7. package/dist/cjs/client/components/plans.js +8 -3
  8. package/dist/cjs/client/components/user-menu.js +2 -6
  9. package/dist/cjs/client/index.js +11 -3
  10. package/dist/cjs/client/provider.js +102 -7
  11. package/dist/cjs/server/client.js +12 -1
  12. package/dist/cjs/server/handler.js +126 -2
  13. package/dist/cjs/server/resources/calls.js +57 -0
  14. package/dist/cjs/server/resources/channels.js +115 -0
  15. package/dist/cjs/server/resources/enrichment.js +56 -0
  16. package/dist/cjs/server/resources/identity.js +40 -0
  17. package/dist/cjs/server/resources/workspaces.js +73 -2
  18. package/dist/esm/client/components/identity.js +21 -0
  19. package/dist/esm/client/components/one-tap-state.js +90 -0
  20. package/dist/esm/client/components/one-tap.js +103 -0
  21. package/dist/esm/client/components/plan-pricing.js +27 -0
  22. package/dist/esm/client/components/plans.js +9 -4
  23. package/dist/esm/client/components/user-menu.js +1 -5
  24. package/dist/esm/client/index.js +8 -1
  25. package/dist/esm/client/provider.js +102 -7
  26. package/dist/esm/server/client.js +12 -1
  27. package/dist/esm/server/handler.js +127 -3
  28. package/dist/esm/server/resources/calls.js +53 -0
  29. package/dist/esm/server/resources/channels.js +111 -0
  30. package/dist/esm/server/resources/enrichment.js +52 -0
  31. package/dist/esm/server/resources/identity.js +39 -0
  32. package/dist/esm/server/resources/workspaces.js +73 -2
  33. package/dist/types/client/components/identity.d.ts +17 -0
  34. package/dist/types/client/components/one-tap-state.d.ts +39 -0
  35. package/dist/types/client/components/one-tap.d.ts +50 -0
  36. package/dist/types/client/components/plan-pricing.d.ts +23 -0
  37. package/dist/types/client/index.d.ts +4 -2
  38. package/dist/types/client/provider.d.ts +101 -3
  39. package/dist/types/client/use-checkout.d.ts +9 -0
  40. package/dist/types/server/client.d.ts +9 -1
  41. package/dist/types/server/index.d.ts +3 -0
  42. package/dist/types/server/resources/calls.d.ts +45 -0
  43. package/dist/types/server/resources/channels.d.ts +91 -0
  44. package/dist/types/server/resources/enrichment.d.ts +44 -0
  45. package/dist/types/server/resources/identity.d.ts +35 -0
  46. package/dist/types/server/resources/workspaces.d.ts +63 -3
  47. package/dist/types/types.d.ts +344 -1
  48. package/package.json +1 -1
@@ -597,13 +597,30 @@ export interface GrievanceChannel {
597
597
  */
598
598
  export interface CompanyProfile {
599
599
  legalName: string;
600
- /** Trading name, for prose the full registered name reads oddly in. */
600
+ /**
601
+ * Trading name, for prose the full registered name reads oddly in.
602
+ *
603
+ * Editable by the platform operator since SDK 0.23. It was a hardcoded
604
+ * constant on Connect's side before that - the one company fact no
605
+ * operator could correct without a deploy.
606
+ */
601
607
  brandName: string;
602
608
  registeredAddress: string;
603
609
  contactEmail: string;
604
610
  website: string | null;
605
611
  /** GSTIN, `null` if the operating entity is not GST-registered. */
606
612
  gstNumber: string | null;
613
+ /**
614
+ * The seat a governing-law clause names - `"Chennai, Tamil Nadu"`.
615
+ *
616
+ * **Not the registered address**, and the distinction is the reason it is
617
+ * its own field: an entity registered in one state routinely names another
618
+ * as the venue for disputes, and the two copies of this that applications
619
+ * used to keep disagreed about which. `null` when the operator has not
620
+ * published one, in which case a terms page should omit the venue rather
621
+ * than reach for `registeredAddress` instead.
622
+ */
623
+ legalJurisdiction: string | null;
607
624
  grievance: GrievanceChannel;
608
625
  }
609
626
  export interface CompanyProfileResponse {
@@ -1153,6 +1170,71 @@ export interface ConnectWorkspaceMember {
1153
1170
  granted: string[];
1154
1171
  role: string | null;
1155
1172
  }
1173
+ /**
1174
+ * How many member seats the workspace has, and whether there is another.
1175
+ *
1176
+ * The number is the **workspace's**, not your plan's: a baseline plus
1177
+ * `allowances.members` from every subscription it holds, folded across
1178
+ * applications - so a seat bought through another product is a seat you may
1179
+ * fill. `included: null` means unlimited. `used` counts active members *and*
1180
+ * pending invitations, because an invitation is a seat already spoken for.
1181
+ *
1182
+ * Advisory. The authoritative check runs inside `invite`, which is where two
1183
+ * people claiming the last seat at once is settled.
1184
+ */
1185
+ export interface ConnectMemberCapacity {
1186
+ included: number | null;
1187
+ used: number;
1188
+ canAdd: boolean;
1189
+ /**
1190
+ * `no_allowance` - nothing the workspace subscribes to grants member seats,
1191
+ * and the answer is a plan. `exhausted` - every seat is taken, and the
1192
+ * answer is an upgrade or a removal. They read alike and need different
1193
+ * next steps, so word them differently.
1194
+ */
1195
+ reason: "no_allowance" | "exhausted" | "hard_ceiling" | null;
1196
+ }
1197
+ /**
1198
+ * What the **signed-in caller** may do with the roster, from their Connect
1199
+ * permissions - not your application's.
1200
+ *
1201
+ * Render your Invite and Change-role controls from this. Without it the only
1202
+ * way to find out is to try, which is a button that exists to fail.
1203
+ */
1204
+ export interface ConnectMemberViewer {
1205
+ canInvite: boolean;
1206
+ canManageAccess: boolean;
1207
+ }
1208
+ /** An invitation that has been sent and not yet accepted - and is holding a seat. */
1209
+ export interface ConnectPendingInvitation {
1210
+ invitationId: string;
1211
+ inviteeEmail: string;
1212
+ /** The role on *your* application it carries, or `null`. */
1213
+ roleKey: string | null;
1214
+ /** ISO 8601. Seven days from when it was sent. */
1215
+ expiresAt: string;
1216
+ }
1217
+ export interface ConnectMemberAccess {
1218
+ capacity: ConnectMemberCapacity;
1219
+ viewer: ConnectMemberViewer;
1220
+ invitations: ConnectPendingInvitation[];
1221
+ }
1222
+ export interface ConnectInvitation {
1223
+ invitationId: string;
1224
+ inviteeEmail: string;
1225
+ /** ISO 8601. */
1226
+ expiresAt: string;
1227
+ /** Always present, so you can offer copy/share when the email did not go out. */
1228
+ inviteUrl: string;
1229
+ emailSent: boolean;
1230
+ }
1231
+ export interface ConnectMemberAccessResult {
1232
+ userId: string;
1233
+ /** The role on your application after the change - `null` when access was revoked. */
1234
+ roleKey: string | null;
1235
+ /** Your application's permissions this member now holds, re-resolved. */
1236
+ granted: string[];
1237
+ }
1156
1238
  /**
1157
1239
  * One bookable thing a workspace offers - "15-minute intro call", "site
1158
1240
  * survey".
@@ -1282,3 +1364,264 @@ export interface ConnectContact {
1282
1364
  createdAt: string;
1283
1365
  updatedAt: string;
1284
1366
  }
1367
+ /** Coarse on purpose - a headcount read off a homepage is a claim, not a measurement. */
1368
+ export type CompanySizeBand = "1-10" | "11-50" | "51-200" | "201-500" | "500+";
1369
+ /**
1370
+ * Where a value came from.
1371
+ *
1372
+ * - `domain` - the input itself. `url` is `null`, because there is no page.
1373
+ * - `website` - a page on the company's own site, at `url`.
1374
+ * - `registry` - a statutory register. Reserved; nothing returns it yet.
1375
+ */
1376
+ export type EnrichmentSource = "domain" | "registry" | "website";
1377
+ export interface EnrichmentCitation {
1378
+ source: EnrichmentSource;
1379
+ /** The exact page read. `null` only for `domain`. */
1380
+ url: string | null;
1381
+ /** ISO-8601. */
1382
+ retrievedAt: string;
1383
+ }
1384
+ /**
1385
+ * Every field nullable, including the ones your own record calls required.
1386
+ *
1387
+ * An enrichment is partial by nature: a site with no address printed on it
1388
+ * yields no address. A shape that demanded a city would only be forcing one to
1389
+ * be invented.
1390
+ */
1391
+ export interface EnrichedAddress {
1392
+ line1: string | null;
1393
+ line2: string | null;
1394
+ city: string | null;
1395
+ /** The state or region's *name* as written, not a code. */
1396
+ state: string | null;
1397
+ postalCode: string | null;
1398
+ /** ISO 3166-1 alpha-2, uppercase. */
1399
+ country: string | null;
1400
+ }
1401
+ /**
1402
+ * What Connect read about a company, and where each part came from.
1403
+ *
1404
+ * Every value is a claim from a page named in `citations`. Nothing here is
1405
+ * recalled by a model: a field the pages did not state is `null`, which is why
1406
+ * `null` is common and should be rendered as "not found" rather than as an
1407
+ * empty input somebody has to notice.
1408
+ */
1409
+ export interface EnrichedCompany {
1410
+ /** Normalised - lowercase, no scheme, no `www.`. */
1411
+ domain: string;
1412
+ name: string | null;
1413
+ /**
1414
+ * The registered entity name.
1415
+ *
1416
+ * Always `null` today. It is reserved for a statutory register, and
1417
+ * deliberately never filled from a website - a footer says "Acme" where the
1418
+ * register says "Acme Industries Private Limited", and this is the one field
1419
+ * here that would end up on a contract.
1420
+ */
1421
+ legalName: string | null;
1422
+ description: string | null;
1423
+ industry: string | null;
1424
+ sizeBand: CompanySizeBand | null;
1425
+ phone: string | null;
1426
+ email: string | null;
1427
+ website: string | null;
1428
+ address: EnrichedAddress | null;
1429
+ /**
1430
+ * Derived from how many fields the pages actually supported - not the
1431
+ * model's opinion of itself, which reflects the confidence of the prose it
1432
+ * read. Treat `low` as "offer this", `high` as "safe to pre-fill".
1433
+ */
1434
+ confidence: "high" | "medium" | "low";
1435
+ citations: EnrichmentCitation[];
1436
+ /** ISO-8601. Age the profile against this. */
1437
+ retrievedAt: string;
1438
+ }
1439
+ /**
1440
+ * Why there is nothing to report. A normal outcome, not an error - most
1441
+ * records legitimately have nothing to enrich.
1442
+ *
1443
+ * `consumer_domain` and `blocked_domain` will never succeed on retry.
1444
+ * `unreachable` and `no_signal` may, later.
1445
+ */
1446
+ export type EnrichmentSkipReason = "no_domain" | "consumer_domain" | "blocked_domain" | "unreachable" | "no_signal";
1447
+ export type CompanyEnrichmentResult = {
1448
+ status: "enriched";
1449
+ profile: EnrichedCompany;
1450
+ /** Whether Connect served this from its platform-wide cache. The profile is the same either way. */
1451
+ cached: boolean;
1452
+ } | {
1453
+ status: "skipped";
1454
+ reason: EnrichmentSkipReason;
1455
+ };
1456
+ /**
1457
+ * What kind of conversation a channel carries. `voice` is the only kind
1458
+ * Connect stocks inventory for today - `whatsapp` and `meeting` are modelled
1459
+ * end to end and have no runtime yet, so `claim` refuses them.
1460
+ */
1461
+ export type ChannelKind = "voice" | "meeting" | "whatsapp";
1462
+ /**
1463
+ * `suspended` and `released` both stop the channel answering. The difference
1464
+ * is whose act it was: a Connect operator suspended it, or the number went
1465
+ * back to inventory.
1466
+ */
1467
+ export type ChannelStatus = "active" | "suspended" | "released";
1468
+ /**
1469
+ * Where inbound conversations on a channel go.
1470
+ *
1471
+ * `destination` is **yours**: an arbitrary JSON object Connect stores verbatim
1472
+ * and never reads into. Which agent answers, business hours, overflow - all of
1473
+ * it is your application's model, not Connect's.
1474
+ */
1475
+ export interface ChannelRouting {
1476
+ destination: Record<string, unknown>;
1477
+ updatedAt: string;
1478
+ }
1479
+ /**
1480
+ * A number assigned to your application, as your application sees it.
1481
+ *
1482
+ * Two things are deliberately withheld and will not appear later:
1483
+ * `createdBy` names a Connect operator, and the carrier-side record (which
1484
+ * carrier, which provider resource, what Connect pays per month) is Connect's
1485
+ * cost and Connect's credential surface. An application reads what was
1486
+ * assigned to it; it never provisions, prices or releases a number.
1487
+ */
1488
+ export interface ConnectChannel {
1489
+ id: string;
1490
+ kind: ChannelKind;
1491
+ /** E.164 for a voice channel - the number a caller dials. */
1492
+ address: string;
1493
+ label: string | null;
1494
+ workspaceId: string;
1495
+ status: ChannelStatus;
1496
+ /** `null` when nothing has been routed yet, and after a `clearRouting()`. */
1497
+ routing: ChannelRouting | null;
1498
+ }
1499
+ /**
1500
+ * What a claim answers with - narrower than `ConnectChannel`, because a
1501
+ * just-claimed number has no label and no routing yet. Read it back with
1502
+ * `channels.get(id)` once you have written routing.
1503
+ */
1504
+ export interface ClaimedChannel {
1505
+ id: string;
1506
+ kind: ChannelKind;
1507
+ address: string;
1508
+ workspaceId: string;
1509
+ status: ChannelStatus;
1510
+ }
1511
+ /**
1512
+ * What both routing writes echo back - the stored record, not the whole
1513
+ * channel. `routing` is `null` after `clearRouting()`, which is the same shape
1514
+ * a channel that was never routed has: to the answer path "cleared" and "never
1515
+ * set" are the same fact.
1516
+ */
1517
+ export interface ChannelRoutingRecord {
1518
+ id: string;
1519
+ routing: ChannelRouting | null;
1520
+ }
1521
+ /** One page of channels. Page until `hasMore` is `false`. */
1522
+ export interface ChannelsPage {
1523
+ items: ConnectChannel[];
1524
+ nextCursor: string | null;
1525
+ hasMore: boolean;
1526
+ }
1527
+ /** Which way the call went. */
1528
+ export type CallDirection = "inbound" | "outbound";
1529
+ /**
1530
+ * `rejected` means Connect never connected it - see `rejectReason`.
1531
+ * `answered` is a call still in progress; `completed` is one that ran and
1532
+ * ended.
1533
+ */
1534
+ export type CallStatus = "answered" | "rejected" | "completed";
1535
+ /**
1536
+ * Why a call was refused. Widened at the point of use with `(string & {})`,
1537
+ * the same way `ReadinessBlocker.code` is: Connect adds reasons as it learns
1538
+ * to tell failures apart, and a new one should reach you as a value to handle
1539
+ * rather than as a type error on a published package you cannot patch. Handle
1540
+ * the ones you branch on and treat the rest as "refused".
1541
+ */
1542
+ export type CallRejectReason = "unknown_number" | "channel_suspended" | "channel_released" | "channel_unassigned" | "no_routing" | "workspace_blocked" | "answer_unavailable" | "runtime_unconfigured";
1543
+ /** How a call that actually ran came to an end. Widened at its use site for the same reason as `CallRejectReason`. */
1544
+ export type CallDisconnectReason = "caller_hangup" | "agent_hangup" | "max_duration" | "transferred" | "error" | "abandoned";
1545
+ /**
1546
+ * Where the recording has got to. `pending` is normal for a call that has just
1547
+ * ended - the carrier posts the audio afterwards - and `failed` is kept
1548
+ * distinct from `none` so "we never recorded this" is never read as "we
1549
+ * recorded it and lost it".
1550
+ */
1551
+ export type CallRecordingStatus = "none" | "pending" | "stored" | "failed";
1552
+ /** What the model leg of a call cost. */
1553
+ export interface CallTokenUsage {
1554
+ promptTokens: number;
1555
+ responseTokens: number;
1556
+ totalTokens: number;
1557
+ }
1558
+ /** One tool the agent called mid-conversation. Arguments and results are JSON strings, not parsed objects. */
1559
+ export interface CallToolInvocation {
1560
+ name: string;
1561
+ argumentsJson: string;
1562
+ resultJson: string | null;
1563
+ durationMs: number | null;
1564
+ /** `null` for calls closed out before the runtime reported it - which is not zero. */
1565
+ startedAt: string | null;
1566
+ error: string | null;
1567
+ }
1568
+ /**
1569
+ * One call that arrived on a channel assigned to your application.
1570
+ *
1571
+ * `durationSeconds` and `billDurationSeconds` are the two durations Connect
1572
+ * stands behind - the carrier's own measure of the audio is deliberately not
1573
+ * published, since a third near-identical number only invites a billing
1574
+ * argument settled off the wrong one.
1575
+ */
1576
+ export interface ConnectCall {
1577
+ id: string;
1578
+ channelId: string;
1579
+ workspaceId: string;
1580
+ direction: CallDirection;
1581
+ fromNumber: string;
1582
+ toNumber: string;
1583
+ status: CallStatus;
1584
+ rejectReason: CallRejectReason | (string & {}) | null;
1585
+ disconnectReason: CallDisconnectReason | (string & {}) | null;
1586
+ startedAt: string;
1587
+ answeredAt: string | null;
1588
+ endedAt: string | null;
1589
+ durationSeconds: number | null;
1590
+ billDurationSeconds: number | null;
1591
+ recordingStatus: CallRecordingStatus;
1592
+ /** A Drive file id - read it with a `drive:read` key. `null` until the carrier posts the audio. */
1593
+ recordingFileId: string | null;
1594
+ transcriptFileId: string | null;
1595
+ turnCount: number | null;
1596
+ tokenUsage: CallTokenUsage | null;
1597
+ toolInvocations: CallToolInvocation[];
1598
+ /** Your agent's own post-call structured output, keyed by its extraction schema. Connect stores it without interpreting it. */
1599
+ extraction: Record<string, unknown> | null;
1600
+ agentId: string | null;
1601
+ agentVersion: number | null;
1602
+ }
1603
+ /** Who spoke. */
1604
+ export type CallTurnRole = "user" | "agent";
1605
+ /**
1606
+ * One transcript turn. Order by `sequence`, never by `startedAt` - two turns
1607
+ * can share a millisecond.
1608
+ */
1609
+ export interface CallTranscriptTurn {
1610
+ sequence: number;
1611
+ role: CallTurnRole;
1612
+ text: string;
1613
+ startedAt: string | null;
1614
+ /** True only ever for an `agent` turn - the caller talked over it. */
1615
+ interrupted: boolean;
1616
+ }
1617
+ /** A call and its transcript. Long calls are capped at 2,000 turns. */
1618
+ export interface CallDetail {
1619
+ call: ConnectCall;
1620
+ turns: CallTranscriptTurn[];
1621
+ }
1622
+ /** One page of calls, newest first. Page until `hasMore` is `false` - do not stop on an empty `items`. */
1623
+ export interface CallsPage {
1624
+ items: ConnectCall[];
1625
+ nextCursor: string | null;
1626
+ hasMore: boolean;
1627
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmoops/connect-sdk",
3
- "version": "0.20.0",
3
+ "version": "0.23.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",