@iveri/contracts 0.6.0 → 0.8.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 +30 -6
- package/dist/cjs/api/identity/access-token-payload.interface.d.ts +53 -0
- package/dist/cjs/api/identity/access-token-payload.interface.d.ts.map +1 -0
- package/dist/cjs/api/identity/access-token-payload.interface.js +3 -0
- package/dist/cjs/api/identity/access-token-payload.interface.js.map +1 -0
- package/dist/cjs/api/identity/auth.type.d.ts +21 -0
- package/dist/cjs/api/identity/auth.type.d.ts.map +1 -1
- package/dist/cjs/api/identity/index.d.ts +2 -0
- package/dist/cjs/api/identity/index.d.ts.map +1 -1
- package/dist/cjs/api/identity/index.js +2 -0
- package/dist/cjs/api/identity/index.js.map +1 -1
- package/dist/cjs/api/identity/principal-type.enum.d.ts +19 -0
- package/dist/cjs/api/identity/principal-type.enum.d.ts.map +1 -0
- package/dist/cjs/api/identity/principal-type.enum.js +23 -0
- package/dist/cjs/api/identity/principal-type.enum.js.map +1 -0
- package/dist/cjs/api/unibox/canned-reply.type.d.ts +49 -0
- package/dist/cjs/api/unibox/canned-reply.type.d.ts.map +1 -0
- package/dist/cjs/api/unibox/canned-reply.type.js +3 -0
- package/dist/cjs/api/unibox/canned-reply.type.js.map +1 -0
- package/dist/cjs/api/unibox/channel-platform.enum.d.ts +32 -0
- package/dist/cjs/api/unibox/channel-platform.enum.d.ts.map +1 -0
- package/dist/cjs/api/unibox/channel-platform.enum.js +36 -0
- package/dist/cjs/api/unibox/channel-platform.enum.js.map +1 -0
- package/dist/cjs/api/unibox/channel.type.d.ts +110 -0
- package/dist/cjs/api/unibox/channel.type.d.ts.map +1 -0
- package/dist/cjs/api/unibox/channel.type.js +3 -0
- package/dist/cjs/api/unibox/channel.type.js.map +1 -0
- package/dist/cjs/api/unibox/contact.type.d.ts +102 -0
- package/dist/cjs/api/unibox/contact.type.d.ts.map +1 -0
- package/dist/cjs/api/unibox/contact.type.js +3 -0
- package/dist/cjs/api/unibox/contact.type.js.map +1 -0
- package/dist/cjs/api/unibox/conversation-status.enum.d.ts +39 -0
- package/dist/cjs/api/unibox/conversation-status.enum.d.ts.map +1 -0
- package/dist/cjs/api/unibox/conversation-status.enum.js +43 -0
- package/dist/cjs/api/unibox/conversation-status.enum.js.map +1 -0
- package/dist/cjs/api/unibox/conversation.type.d.ts +134 -0
- package/dist/cjs/api/unibox/conversation.type.d.ts.map +1 -0
- package/dist/cjs/api/unibox/conversation.type.js +3 -0
- package/dist/cjs/api/unibox/conversation.type.js.map +1 -0
- package/dist/cjs/api/unibox/index.d.ts +13 -0
- package/dist/cjs/api/unibox/index.d.ts.map +1 -0
- package/dist/cjs/api/unibox/index.js +29 -0
- package/dist/cjs/api/unibox/index.js.map +1 -0
- package/dist/cjs/api/unibox/message-author-type.enum.d.ts +26 -0
- package/dist/cjs/api/unibox/message-author-type.enum.d.ts.map +1 -0
- package/dist/cjs/api/unibox/message-author-type.enum.js +30 -0
- package/dist/cjs/api/unibox/message-author-type.enum.js.map +1 -0
- package/dist/cjs/api/unibox/message-content-type.enum.d.ts +29 -0
- package/dist/cjs/api/unibox/message-content-type.enum.d.ts.map +1 -0
- package/dist/cjs/api/unibox/message-content-type.enum.js +33 -0
- package/dist/cjs/api/unibox/message-content-type.enum.js.map +1 -0
- package/dist/cjs/api/unibox/message-direction.enum.d.ts +23 -0
- package/dist/cjs/api/unibox/message-direction.enum.d.ts.map +1 -0
- package/dist/cjs/api/unibox/message-direction.enum.js +27 -0
- package/dist/cjs/api/unibox/message-direction.enum.js.map +1 -0
- package/dist/cjs/api/unibox/message-status.enum.d.ts +40 -0
- package/dist/cjs/api/unibox/message-status.enum.d.ts.map +1 -0
- package/dist/cjs/api/unibox/message-status.enum.js +44 -0
- package/dist/cjs/api/unibox/message-status.enum.js.map +1 -0
- package/dist/cjs/api/unibox/message.type.d.ts +120 -0
- package/dist/cjs/api/unibox/message.type.d.ts.map +1 -0
- package/dist/cjs/api/unibox/message.type.js +3 -0
- package/dist/cjs/api/unibox/message.type.js.map +1 -0
- package/dist/cjs/api/unibox/team.type.d.ts +50 -0
- package/dist/cjs/api/unibox/team.type.d.ts.map +1 -0
- package/dist/cjs/api/unibox/team.type.js +3 -0
- package/dist/cjs/api/unibox/team.type.js.map +1 -0
- package/dist/cjs/enum/user-permission.enum.d.ts +48 -1
- package/dist/cjs/enum/user-permission.enum.d.ts.map +1 -1
- package/dist/cjs/enum/user-permission.enum.js +54 -0
- package/dist/cjs/enum/user-permission.enum.js.map +1 -1
- package/dist/esm/api/identity/access-token-payload.interface.d.ts +53 -0
- package/dist/esm/api/identity/access-token-payload.interface.d.ts.map +1 -0
- package/dist/esm/api/identity/access-token-payload.interface.js +2 -0
- package/dist/esm/api/identity/access-token-payload.interface.js.map +1 -0
- package/dist/esm/api/identity/auth.type.d.ts +21 -0
- package/dist/esm/api/identity/auth.type.d.ts.map +1 -1
- package/dist/esm/api/identity/index.d.ts +2 -0
- package/dist/esm/api/identity/index.d.ts.map +1 -1
- package/dist/esm/api/identity/index.js +2 -0
- package/dist/esm/api/identity/index.js.map +1 -1
- package/dist/esm/api/identity/principal-type.enum.d.ts +19 -0
- package/dist/esm/api/identity/principal-type.enum.d.ts.map +1 -0
- package/dist/esm/api/identity/principal-type.enum.js +20 -0
- package/dist/esm/api/identity/principal-type.enum.js.map +1 -0
- package/dist/esm/api/unibox/canned-reply.type.d.ts +49 -0
- package/dist/esm/api/unibox/canned-reply.type.d.ts.map +1 -0
- package/dist/esm/api/unibox/canned-reply.type.js +2 -0
- package/dist/esm/api/unibox/canned-reply.type.js.map +1 -0
- package/dist/esm/api/unibox/channel-platform.enum.d.ts +32 -0
- package/dist/esm/api/unibox/channel-platform.enum.d.ts.map +1 -0
- package/dist/esm/api/unibox/channel-platform.enum.js +33 -0
- package/dist/esm/api/unibox/channel-platform.enum.js.map +1 -0
- package/dist/esm/api/unibox/channel.type.d.ts +110 -0
- package/dist/esm/api/unibox/channel.type.d.ts.map +1 -0
- package/dist/esm/api/unibox/channel.type.js +2 -0
- package/dist/esm/api/unibox/channel.type.js.map +1 -0
- package/dist/esm/api/unibox/contact.type.d.ts +102 -0
- package/dist/esm/api/unibox/contact.type.d.ts.map +1 -0
- package/dist/esm/api/unibox/contact.type.js +2 -0
- package/dist/esm/api/unibox/contact.type.js.map +1 -0
- package/dist/esm/api/unibox/conversation-status.enum.d.ts +39 -0
- package/dist/esm/api/unibox/conversation-status.enum.d.ts.map +1 -0
- package/dist/esm/api/unibox/conversation-status.enum.js +40 -0
- package/dist/esm/api/unibox/conversation-status.enum.js.map +1 -0
- package/dist/esm/api/unibox/conversation.type.d.ts +134 -0
- package/dist/esm/api/unibox/conversation.type.d.ts.map +1 -0
- package/dist/esm/api/unibox/conversation.type.js +2 -0
- package/dist/esm/api/unibox/conversation.type.js.map +1 -0
- package/dist/esm/api/unibox/index.d.ts +13 -0
- package/dist/esm/api/unibox/index.d.ts.map +1 -0
- package/dist/esm/api/unibox/index.js +13 -0
- package/dist/esm/api/unibox/index.js.map +1 -0
- package/dist/esm/api/unibox/message-author-type.enum.d.ts +26 -0
- package/dist/esm/api/unibox/message-author-type.enum.d.ts.map +1 -0
- package/dist/esm/api/unibox/message-author-type.enum.js +27 -0
- package/dist/esm/api/unibox/message-author-type.enum.js.map +1 -0
- package/dist/esm/api/unibox/message-content-type.enum.d.ts +29 -0
- package/dist/esm/api/unibox/message-content-type.enum.d.ts.map +1 -0
- package/dist/esm/api/unibox/message-content-type.enum.js +30 -0
- package/dist/esm/api/unibox/message-content-type.enum.js.map +1 -0
- package/dist/esm/api/unibox/message-direction.enum.d.ts +23 -0
- package/dist/esm/api/unibox/message-direction.enum.d.ts.map +1 -0
- package/dist/esm/api/unibox/message-direction.enum.js +24 -0
- package/dist/esm/api/unibox/message-direction.enum.js.map +1 -0
- package/dist/esm/api/unibox/message-status.enum.d.ts +40 -0
- package/dist/esm/api/unibox/message-status.enum.d.ts.map +1 -0
- package/dist/esm/api/unibox/message-status.enum.js +41 -0
- package/dist/esm/api/unibox/message-status.enum.js.map +1 -0
- package/dist/esm/api/unibox/message.type.d.ts +120 -0
- package/dist/esm/api/unibox/message.type.d.ts.map +1 -0
- package/dist/esm/api/unibox/message.type.js +2 -0
- package/dist/esm/api/unibox/message.type.js.map +1 -0
- package/dist/esm/api/unibox/team.type.d.ts +50 -0
- package/dist/esm/api/unibox/team.type.d.ts.map +1 -0
- package/dist/esm/api/unibox/team.type.js +2 -0
- package/dist/esm/api/unibox/team.type.js.map +1 -0
- package/dist/esm/enum/user-permission.enum.d.ts +48 -1
- package/dist/esm/enum/user-permission.enum.d.ts.map +1 -1
- package/dist/esm/enum/user-permission.enum.js +54 -0
- package/dist/esm/enum/user-permission.enum.js.map +1 -1
- package/package.json +9 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The messaging network a channel is connected to.
|
|
3
|
+
*
|
|
4
|
+
* This is Unibox's vocabulary, not Conduit's. Conduit knows about *connectors* — a set of hosts
|
|
5
|
+
* and operations someone wrote down — and has no idea that any of them carry conversations.
|
|
6
|
+
* Unibox knows that a WhatsApp message and an Instagram message are the same kind of thing and
|
|
7
|
+
* belong in one inbox, which is the whole product.
|
|
8
|
+
*
|
|
9
|
+
* The members are the platforms Unibox can **normalize**, which is a stricter bar than the ones
|
|
10
|
+
* Conduit can talk to: normalizing means we can read a provider's webhook into a contact, a
|
|
11
|
+
* conversation and a message, and write a reply back. Adding one is a normalizer plus a
|
|
12
|
+
* connector manifest, and is a minor version here.
|
|
13
|
+
*/
|
|
14
|
+
export var ChannelPlatform;
|
|
15
|
+
(function (ChannelPlatform) {
|
|
16
|
+
/** WhatsApp Cloud API. The first real platform, and the one `conduit-api` ships a manifest for. */
|
|
17
|
+
ChannelPlatform["WHATSAPP"] = "whatsapp";
|
|
18
|
+
/** Instagram Direct, via the Messenger Platform. */
|
|
19
|
+
ChannelPlatform["INSTAGRAM"] = "instagram";
|
|
20
|
+
/** Facebook Messenger. */
|
|
21
|
+
ChannelPlatform["MESSENGER"] = "messenger";
|
|
22
|
+
/**
|
|
23
|
+
* A loopback platform for local development and tests, matching Conduit's `local-echo`
|
|
24
|
+
* connector.
|
|
25
|
+
*
|
|
26
|
+
* It exists for the same reason that connector does: the entire pipeline — receive,
|
|
27
|
+
* normalize, thread, reply, dispatch — is provable without a Meta app, and a real Meta app
|
|
28
|
+
* would only prove we can talk to Meta. It is a first-class member rather than a test double
|
|
29
|
+
* so the normalizer registry has no branch that only exists under Jest.
|
|
30
|
+
*/
|
|
31
|
+
ChannelPlatform["ECHO"] = "echo";
|
|
32
|
+
})(ChannelPlatform || (ChannelPlatform = {}));
|
|
33
|
+
//# sourceMappingURL=channel-platform.enum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-platform.enum.js","sourceRoot":"","sources":["../../../../src/api/unibox/channel-platform.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAN,IAAY,eAoBX;AApBD,WAAY,eAAe;IACvB,mGAAmG;IACnG,wCAAqB,CAAA;IAErB,oDAAoD;IACpD,0CAAuB,CAAA;IAEvB,0BAA0B;IAC1B,0CAAuB,CAAA;IAEvB;;;;;;;;OAQG;IACH,gCAAa,CAAA;AACjB,CAAC,EApBW,eAAe,KAAf,eAAe,QAoB1B"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { IsoDateTime } from '../../type/iso-date-time.type.js';
|
|
2
|
+
import type { Nullable } from '../../type/nil.type.js';
|
|
3
|
+
import type { Paginated } from '../../type/paginated.type.js';
|
|
4
|
+
import type { UUID } from '../../type/uuid.type.js';
|
|
5
|
+
import type { ChannelPlatform } from './channel-platform.enum.js';
|
|
6
|
+
/**
|
|
7
|
+
* One messaging account a tenant has connected — a WhatsApp number, an Instagram business
|
|
8
|
+
* account, a Facebook page.
|
|
9
|
+
*
|
|
10
|
+
* A channel is the seam between Unibox and Conduit, and it points at Conduit twice, in opposite
|
|
11
|
+
* directions:
|
|
12
|
+
*
|
|
13
|
+
* - **Inbound**, Conduit forwards a provider's raw webhook to Unibox and presents this channel's
|
|
14
|
+
* ingest secret. Conduit does not parse it — it cannot, because §11 forbids it knowing what a
|
|
15
|
+
* chat is — so normalizing the bytes into a message is Unibox's job.
|
|
16
|
+
* - **Outbound**, a reply is submitted to Conduit naming `connectionKey` and `sendOperation`.
|
|
17
|
+
* Unibox never calls the Graph API itself (§12).
|
|
18
|
+
*
|
|
19
|
+
* Neither reference is a foreign key, because they name rows in another service's database. A
|
|
20
|
+
* `connectionKey` that no longer resolves is a misconfiguration Unibox reports; it is not
|
|
21
|
+
* something Unibox can prevent, and pretending otherwise would mean Unibox reading Conduit's
|
|
22
|
+
* tables, which is exactly what §2 forbids.
|
|
23
|
+
*/
|
|
24
|
+
export interface Channel {
|
|
25
|
+
id: UUID;
|
|
26
|
+
/** Tenant-scoped, stable, and how a normalizer is chosen for inbound traffic. */
|
|
27
|
+
key: string;
|
|
28
|
+
name: string;
|
|
29
|
+
platform: ChannelPlatform;
|
|
30
|
+
/**
|
|
31
|
+
* The account's own identifier at the provider — a WhatsApp phone-number id, an Instagram
|
|
32
|
+
* account id.
|
|
33
|
+
*
|
|
34
|
+
* Stored because a provider's webhook names the *recipient* account, and a tenant may have
|
|
35
|
+
* several channels on one platform. Without it there is no way to tell which of two WhatsApp
|
|
36
|
+
* numbers a message arrived at, and both would look equally plausible.
|
|
37
|
+
*/
|
|
38
|
+
externalAccountId: string;
|
|
39
|
+
/** Conduit connection a reply is dispatched through. Loose reference into another service. */
|
|
40
|
+
connectionKey: string;
|
|
41
|
+
/** Which of that connector's operations sends a message. */
|
|
42
|
+
sendOperation: string;
|
|
43
|
+
/**
|
|
44
|
+
* Whether this channel accepts inbound traffic and sends replies.
|
|
45
|
+
*
|
|
46
|
+
* Turning it off stops new conversations and refuses sends. It does **not** delete anything
|
|
47
|
+
* already received: a channel a customer disconnected still has a history someone needs to
|
|
48
|
+
* read.
|
|
49
|
+
*/
|
|
50
|
+
isActive: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Whether an ingest secret is currently set.
|
|
53
|
+
*
|
|
54
|
+
* A boolean, never the value. The secret is what authenticates Conduit to Unibox, so it is
|
|
55
|
+
* envelope-encrypted, returned by no endpoint, and shown to the operator exactly once — at
|
|
56
|
+
* the moment it is generated, when it also has to be pasted into Conduit's destination
|
|
57
|
+
* headers. Same control as an endpoint's signing secret in Conduit.
|
|
58
|
+
*/
|
|
59
|
+
hasIngestSecret: boolean;
|
|
60
|
+
/** When a message was last received or sent here. Null until the first one. */
|
|
61
|
+
lastActivityAt: Nullable<IsoDateTime>;
|
|
62
|
+
createdAt: IsoDateTime;
|
|
63
|
+
updatedAt: IsoDateTime;
|
|
64
|
+
}
|
|
65
|
+
/** `GET /api/v1/channels`. Offset-paged: a tenant has a handful of channels, not a stream of them. */
|
|
66
|
+
export type ChannelsPage = Paginated<Channel>;
|
|
67
|
+
/** `POST /api/v1/channels`. */
|
|
68
|
+
export interface CreateChannelBody {
|
|
69
|
+
/** Lowercase, `[a-z0-9-]`. Unique within the tenant and immutable once created. */
|
|
70
|
+
key: string;
|
|
71
|
+
name: string;
|
|
72
|
+
platform: ChannelPlatform;
|
|
73
|
+
externalAccountId: string;
|
|
74
|
+
connectionKey: string;
|
|
75
|
+
/** Defaults to the platform's conventional send operation when omitted. */
|
|
76
|
+
sendOperation?: Nullable<string>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* `PATCH /api/v1/channels/:id`.
|
|
80
|
+
*
|
|
81
|
+
* `key` and `platform` are absent on purpose. The key is what an ingest request resolves and what
|
|
82
|
+
* an operator wrote into Conduit's configuration; the platform decides which normalizer reads the
|
|
83
|
+
* history already stored against this channel. Changing either would silently reinterpret rows
|
|
84
|
+
* that are already there, so both are create-only — delete and recreate is the honest path.
|
|
85
|
+
*/
|
|
86
|
+
export interface UpdateChannelBody {
|
|
87
|
+
name?: string;
|
|
88
|
+
externalAccountId?: string;
|
|
89
|
+
connectionKey?: string;
|
|
90
|
+
sendOperation?: string;
|
|
91
|
+
isActive?: boolean;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* `POST /api/v1/channels/:id/ingest-secret` — the **only** response that ever carries the secret.
|
|
95
|
+
*
|
|
96
|
+
* Rotating replaces the stored value immediately, so the previous secret stops working the moment
|
|
97
|
+
* this returns. That is deliberate and it is a brief outage by design: an ingest secret that
|
|
98
|
+
* overlapped with its replacement would mean a leaked one keeps working for as long as the
|
|
99
|
+
* overlap, which is the thing rotation exists to end.
|
|
100
|
+
*/
|
|
101
|
+
export interface ChannelIngestSecretResponse {
|
|
102
|
+
channelId: UUID;
|
|
103
|
+
/** Shown once. Not stored in retrievable form, and no endpoint returns it again. */
|
|
104
|
+
ingestSecret: string;
|
|
105
|
+
/** The URL to configure as the destination in Conduit, for convenience. */
|
|
106
|
+
ingestUrl: string;
|
|
107
|
+
/** The header Conduit must carry the secret in. */
|
|
108
|
+
ingestHeaderName: string;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=channel.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.type.d.ts","sourceRoot":"","sources":["../../../../src/api/unibox/channel.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,OAAO;IACpB,EAAE,EAAE,IAAI,CAAC;IAET,iFAAiF;IACjF,GAAG,EAAE,MAAM,CAAC;IAEZ,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,EAAE,eAAe,CAAC;IAE1B;;;;;;;OAOG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B,8FAA8F;IAC9F,aAAa,EAAE,MAAM,CAAC;IAEtB,4DAA4D;IAC5D,aAAa,EAAE,MAAM,CAAC;IAEtB;;;;;;OAMG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;;;;;;OAOG;IACH,eAAe,EAAE,OAAO,CAAC;IAEzB,+EAA+E;IAC/E,cAAc,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IAEtC,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,EAAE,WAAW,CAAC;CAC1B;AAED,sGAAsG;AACtG,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;AAE9C,+BAA+B;AAC/B,MAAM,WAAW,iBAAiB;IAC9B,mFAAmF;IACnF,GAAG,EAAE,MAAM,CAAC;IAEZ,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,EAAE,eAAe,CAAC;IAE1B,iBAAiB,EAAE,MAAM,CAAC;IAE1B,aAAa,EAAE,MAAM,CAAC;IAEtB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CACpC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,2BAA2B;IACxC,SAAS,EAAE,IAAI,CAAC;IAEhB,oFAAoF;IACpF,YAAY,EAAE,MAAM,CAAC;IAErB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAElB,mDAAmD;IACnD,gBAAgB,EAAE,MAAM,CAAC;CAC5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.type.js","sourceRoot":"","sources":["../../../../src/api/unibox/channel.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { CursorPage } from '../../type/cursor-page.type.js';
|
|
2
|
+
import type { IsoDateTime } from '../../type/iso-date-time.type.js';
|
|
3
|
+
import type { Nullable } from '../../type/nil.type.js';
|
|
4
|
+
import type { UUID } from '../../type/uuid.type.js';
|
|
5
|
+
import type { ChannelPlatform } from './channel-platform.enum.js';
|
|
6
|
+
/**
|
|
7
|
+
* One way of reaching a contact on one platform.
|
|
8
|
+
*
|
|
9
|
+
* A person is not a phone number. The same human messages a business from WhatsApp on Monday and
|
|
10
|
+
* from Instagram on Thursday, and an inbox that treats those as two strangers is an inbox that
|
|
11
|
+
* loses the thread — so identities are a child collection rather than columns on the contact.
|
|
12
|
+
*
|
|
13
|
+
* That shape is what makes merging possible later without a migration. Merging is **not built**;
|
|
14
|
+
* the modelling for it is, which is the part that is expensive to retrofit.
|
|
15
|
+
*/
|
|
16
|
+
export interface ContactIdentity {
|
|
17
|
+
id: UUID;
|
|
18
|
+
platform: ChannelPlatform;
|
|
19
|
+
/**
|
|
20
|
+
* The provider's own identifier for this person — a WhatsApp `wa_id`, an Instagram-scoped
|
|
21
|
+
* user id.
|
|
22
|
+
*
|
|
23
|
+
* Unique per `(tenant, platform)`. **Scoped ids are not portable across platforms**: the same
|
|
24
|
+
* person has an entirely different id on Instagram and on Messenger, and treating one as the
|
|
25
|
+
* other merges two strangers. That is why the platform is part of the key rather than the id
|
|
26
|
+
* being assumed globally unique.
|
|
27
|
+
*/
|
|
28
|
+
externalId: string;
|
|
29
|
+
/** The name the provider supplied, when it supplied one. Not authoritative and often absent. */
|
|
30
|
+
displayName: Nullable<string>;
|
|
31
|
+
createdAt: IsoDateTime;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A person the tenant talks to.
|
|
35
|
+
*
|
|
36
|
+
* Personal data, deliberately minimal: Unibox stores what it needs to thread a conversation and
|
|
37
|
+
* address someone by name. A CRM's worth of fields belongs in the vertical that needs them, and
|
|
38
|
+
* §17's GDPR line is materially cheaper to honour on a small table.
|
|
39
|
+
*/
|
|
40
|
+
export interface Contact {
|
|
41
|
+
id: UUID;
|
|
42
|
+
/**
|
|
43
|
+
* The name shown in the inbox.
|
|
44
|
+
*
|
|
45
|
+
* Editable by an agent, because a provider's display name is frequently a handle or absent,
|
|
46
|
+
* and correcting it is the first thing anyone does. Falls back to the first identity's
|
|
47
|
+
* `displayName`, then to its `externalId`.
|
|
48
|
+
*/
|
|
49
|
+
displayName: string;
|
|
50
|
+
email: Nullable<string>;
|
|
51
|
+
/** E.164 where known. Not the same as a WhatsApp identity's `externalId`, which is scoped. */
|
|
52
|
+
phone: Nullable<string>;
|
|
53
|
+
/** Free-form agent notes. Not shown to the contact and never sent anywhere. */
|
|
54
|
+
notes: Nullable<string>;
|
|
55
|
+
/** Lowercased, deduplicated. For filtering the inbox, not for automation. */
|
|
56
|
+
tags: string[];
|
|
57
|
+
identities: ContactIdentity[];
|
|
58
|
+
/** When this contact last sent or received a message. Null until the first one. */
|
|
59
|
+
lastActivityAt: Nullable<IsoDateTime>;
|
|
60
|
+
createdAt: IsoDateTime;
|
|
61
|
+
updatedAt: IsoDateTime;
|
|
62
|
+
}
|
|
63
|
+
/** `GET /api/v1/contacts`. Cursor-paged: inbound traffic appends to it while it is being read. */
|
|
64
|
+
export type ContactsPage = CursorPage<Contact>;
|
|
65
|
+
/** Query for `GET /api/v1/contacts`. */
|
|
66
|
+
export interface GetContactsQuery {
|
|
67
|
+
limit?: number;
|
|
68
|
+
/** Opaque cursor from the previous page's `nextCursor`. Never parse it. */
|
|
69
|
+
after?: Nullable<string>;
|
|
70
|
+
/** Case-insensitive substring of the display name, email or phone. */
|
|
71
|
+
search?: Nullable<string>;
|
|
72
|
+
tag?: Nullable<string>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* `POST /api/v1/contacts`.
|
|
76
|
+
*
|
|
77
|
+
* Creating a contact by hand is the uncommon path — almost every contact arrives because someone
|
|
78
|
+
* messaged in, and inbound creates them. This exists so an agent can prepare a record before a
|
|
79
|
+
* conversation starts, and so a vertical can seed one.
|
|
80
|
+
*/
|
|
81
|
+
export interface CreateContactBody {
|
|
82
|
+
displayName: string;
|
|
83
|
+
email?: Nullable<string>;
|
|
84
|
+
phone?: Nullable<string>;
|
|
85
|
+
notes?: Nullable<string>;
|
|
86
|
+
tags?: Nullable<string[]>;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* `PATCH /api/v1/contacts/:id`.
|
|
90
|
+
*
|
|
91
|
+
* `identities` is absent: an identity is asserted by a provider, not chosen by an agent. Adding
|
|
92
|
+
* one by hand is how two strangers get merged into one record, and there is no undo for that.
|
|
93
|
+
*/
|
|
94
|
+
export interface UpdateContactBody {
|
|
95
|
+
displayName?: string;
|
|
96
|
+
email?: Nullable<string>;
|
|
97
|
+
phone?: Nullable<string>;
|
|
98
|
+
notes?: Nullable<string>;
|
|
99
|
+
/** Replaces the whole set. Omit to leave it alone; `[]` clears it. */
|
|
100
|
+
tags?: Nullable<string[]>;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=contact.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact.type.d.ts","sourceRoot":"","sources":["../../../../src/api/unibox/contact.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,IAAI,CAAC;IAET,QAAQ,EAAE,eAAe,CAAC;IAE1B;;;;;;;;OAQG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB,gGAAgG;IAChG,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE9B,SAAS,EAAE,WAAW,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACpB,EAAE,EAAE,IAAI,CAAC;IAET;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAExB,8FAA8F;IAC9F,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAExB,+EAA+E;IAC/E,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAExB,6EAA6E;IAC7E,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf,UAAU,EAAE,eAAe,EAAE,CAAC;IAE9B,mFAAmF;IACnF,cAAc,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IAEtC,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,EAAE,WAAW,CAAC;CAC1B;AAED,kGAAkG;AAClG,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;AAE/C,wCAAwC;AACxC,MAAM,WAAW,gBAAgB;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,2EAA2E;IAC3E,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEzB,sEAAsE;IACtE,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE1B,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzB,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzB,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzB,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzB,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzB,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEzB,sEAAsE;IACtE,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact.type.js","sourceRoot":"","sources":["../../../../src/api/unibox/contact.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where one conversation is in an agent's working day.
|
|
3
|
+
*
|
|
4
|
+
* These are **workflow** states, not delivery states — nothing here says whether a message
|
|
5
|
+
* reached anyone. `MessageStatus` answers that, and conflating the two is how an inbox ends up
|
|
6
|
+
* showing a conversation as "failed".
|
|
7
|
+
*
|
|
8
|
+
* There is deliberately no `ARCHIVED`. Closing is already the "I am done with this" state, and a
|
|
9
|
+
* second one just moves the question of which list a conversation belongs in from the filter to
|
|
10
|
+
* the operator.
|
|
11
|
+
*/
|
|
12
|
+
export declare enum ConversationStatus {
|
|
13
|
+
/** Needs a human. The default for anything with an unanswered inbound message. */
|
|
14
|
+
OPEN = "open",
|
|
15
|
+
/**
|
|
16
|
+
* Answered, waiting on the contact.
|
|
17
|
+
*
|
|
18
|
+
* Distinct from `OPEN` because an inbox sorted only by "has unread" hides the conversations
|
|
19
|
+
* an agent is actually running. A new inbound message moves this back to `OPEN`.
|
|
20
|
+
*/
|
|
21
|
+
PENDING = "pending",
|
|
22
|
+
/**
|
|
23
|
+
* Deliberately out of sight until `snoozedUntil`.
|
|
24
|
+
*
|
|
25
|
+
* The only status carrying a time. It exists because "I will deal with this on Monday" is
|
|
26
|
+
* otherwise expressed by closing something that is not finished, and a closed conversation is
|
|
27
|
+
* one nobody looks at again.
|
|
28
|
+
*/
|
|
29
|
+
SNOOZED = "snoozed",
|
|
30
|
+
/**
|
|
31
|
+
* Finished. Reopened automatically by a new inbound message.
|
|
32
|
+
*
|
|
33
|
+
* That automatic reopen is the important half: a contact replying to a closed conversation is
|
|
34
|
+
* continuing it, and starting a second thread would split one person's history across two
|
|
35
|
+
* rows for no reason a customer would recognise.
|
|
36
|
+
*/
|
|
37
|
+
CLOSED = "closed"
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=conversation-status.enum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-status.enum.d.ts","sourceRoot":"","sources":["../../../../src/api/unibox/conversation-status.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,oBAAY,kBAAkB;IAC1B,kFAAkF;IAClF,IAAI,SAAS;IAEb;;;;;OAKG;IACH,OAAO,YAAY;IAEnB;;;;;;OAMG;IACH,OAAO,YAAY;IAEnB;;;;;;OAMG;IACH,MAAM,WAAW;CACpB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where one conversation is in an agent's working day.
|
|
3
|
+
*
|
|
4
|
+
* These are **workflow** states, not delivery states — nothing here says whether a message
|
|
5
|
+
* reached anyone. `MessageStatus` answers that, and conflating the two is how an inbox ends up
|
|
6
|
+
* showing a conversation as "failed".
|
|
7
|
+
*
|
|
8
|
+
* There is deliberately no `ARCHIVED`. Closing is already the "I am done with this" state, and a
|
|
9
|
+
* second one just moves the question of which list a conversation belongs in from the filter to
|
|
10
|
+
* the operator.
|
|
11
|
+
*/
|
|
12
|
+
export var ConversationStatus;
|
|
13
|
+
(function (ConversationStatus) {
|
|
14
|
+
/** Needs a human. The default for anything with an unanswered inbound message. */
|
|
15
|
+
ConversationStatus["OPEN"] = "open";
|
|
16
|
+
/**
|
|
17
|
+
* Answered, waiting on the contact.
|
|
18
|
+
*
|
|
19
|
+
* Distinct from `OPEN` because an inbox sorted only by "has unread" hides the conversations
|
|
20
|
+
* an agent is actually running. A new inbound message moves this back to `OPEN`.
|
|
21
|
+
*/
|
|
22
|
+
ConversationStatus["PENDING"] = "pending";
|
|
23
|
+
/**
|
|
24
|
+
* Deliberately out of sight until `snoozedUntil`.
|
|
25
|
+
*
|
|
26
|
+
* The only status carrying a time. It exists because "I will deal with this on Monday" is
|
|
27
|
+
* otherwise expressed by closing something that is not finished, and a closed conversation is
|
|
28
|
+
* one nobody looks at again.
|
|
29
|
+
*/
|
|
30
|
+
ConversationStatus["SNOOZED"] = "snoozed";
|
|
31
|
+
/**
|
|
32
|
+
* Finished. Reopened automatically by a new inbound message.
|
|
33
|
+
*
|
|
34
|
+
* That automatic reopen is the important half: a contact replying to a closed conversation is
|
|
35
|
+
* continuing it, and starting a second thread would split one person's history across two
|
|
36
|
+
* rows for no reason a customer would recognise.
|
|
37
|
+
*/
|
|
38
|
+
ConversationStatus["CLOSED"] = "closed";
|
|
39
|
+
})(ConversationStatus || (ConversationStatus = {}));
|
|
40
|
+
//# sourceMappingURL=conversation-status.enum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-status.enum.js","sourceRoot":"","sources":["../../../../src/api/unibox/conversation-status.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAN,IAAY,kBA6BX;AA7BD,WAAY,kBAAkB;IAC1B,kFAAkF;IAClF,mCAAa,CAAA;IAEb;;;;;OAKG;IACH,yCAAmB,CAAA;IAEnB;;;;;;OAMG;IACH,yCAAmB,CAAA;IAEnB;;;;;;OAMG;IACH,uCAAiB,CAAA;AACrB,CAAC,EA7BW,kBAAkB,KAAlB,kBAAkB,QA6B7B"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type { CursorPage } from '../../type/cursor-page.type.js';
|
|
2
|
+
import type { IsoDateTime } from '../../type/iso-date-time.type.js';
|
|
3
|
+
import type { Nullable } from '../../type/nil.type.js';
|
|
4
|
+
import type { UUID } from '../../type/uuid.type.js';
|
|
5
|
+
import type { ChannelPlatform } from './channel-platform.enum.js';
|
|
6
|
+
import type { ConversationStatus } from './conversation-status.enum.js';
|
|
7
|
+
import type { Message } from './message.type.js';
|
|
8
|
+
/**
|
|
9
|
+
* One thread between a tenant and a contact, on one channel.
|
|
10
|
+
*
|
|
11
|
+
* **One open conversation per `(channel, contact)`, never more.** A second one would split a
|
|
12
|
+
* person's history in half at the exact moment two agents are both replying, and the customer
|
|
13
|
+
* would see one conversation while the inbox showed two. A closed conversation reopens on the
|
|
14
|
+
* next inbound message rather than a new row being created, for the same reason.
|
|
15
|
+
*
|
|
16
|
+
* The denormalized fields below — `contactDisplayName`, `lastMessagePreview`, `unreadCount` — are
|
|
17
|
+
* here because an inbox list renders fifty of these at once and joining to messages for each one
|
|
18
|
+
* is the query that makes the product feel slow. They are maintained in the same transaction as
|
|
19
|
+
* the message that changes them, so they cannot drift.
|
|
20
|
+
*/
|
|
21
|
+
export interface Conversation {
|
|
22
|
+
id: UUID;
|
|
23
|
+
channelId: UUID;
|
|
24
|
+
/** Snapshotted so the list renders without a join. */
|
|
25
|
+
channelKey: string;
|
|
26
|
+
platform: ChannelPlatform;
|
|
27
|
+
contactId: UUID;
|
|
28
|
+
contactDisplayName: string;
|
|
29
|
+
status: ConversationStatus;
|
|
30
|
+
/** The agent responsible. Null means unassigned, which is a queue an inbox filters on. */
|
|
31
|
+
assigneeUserId: Nullable<UUID>;
|
|
32
|
+
/** The team it was routed to, if any. Independent of the assignee. */
|
|
33
|
+
teamId: Nullable<UUID>;
|
|
34
|
+
/**
|
|
35
|
+
* Messages the contact sent that no agent has opened.
|
|
36
|
+
*
|
|
37
|
+
* Per conversation, not per agent. A shared inbox is shared: two agents looking at the same
|
|
38
|
+
* queue should see the same numbers, and per-agent unread counts turn "has anyone dealt with
|
|
39
|
+
* this" into a question the UI cannot answer.
|
|
40
|
+
*/
|
|
41
|
+
unreadCount: number;
|
|
42
|
+
/** First ~200 characters of the last message, for the list. Null on an empty conversation. */
|
|
43
|
+
lastMessagePreview: Nullable<string>;
|
|
44
|
+
/** Sorts the inbox. Null only for a conversation created before its first message. */
|
|
45
|
+
lastMessageAt: Nullable<IsoDateTime>;
|
|
46
|
+
/** When the contact last said something. Drives "waiting on us" without reading the messages. */
|
|
47
|
+
lastInboundAt: Nullable<IsoDateTime>;
|
|
48
|
+
/** Set only while `SNOOZED`. The conversation returns to `OPEN` at this time. */
|
|
49
|
+
snoozedUntil: Nullable<IsoDateTime>;
|
|
50
|
+
/**
|
|
51
|
+
* When a human took over from the AI, and who.
|
|
52
|
+
*
|
|
53
|
+
* §12 makes handover a launch requirement, and these two fields are what make it a fact rather
|
|
54
|
+
* than a convention: once set, `unibox-ai` must not answer in this conversation again. Nothing
|
|
55
|
+
* writes them from an AI side yet, and the guarantee is the same either way — the flag is what
|
|
56
|
+
* a future agent loop reads, and it exists before there is a loop to read it.
|
|
57
|
+
*/
|
|
58
|
+
handedOverAt: Nullable<IsoDateTime>;
|
|
59
|
+
handedOverToUserId: Nullable<UUID>;
|
|
60
|
+
closedAt: Nullable<IsoDateTime>;
|
|
61
|
+
createdAt: IsoDateTime;
|
|
62
|
+
updatedAt: IsoDateTime;
|
|
63
|
+
}
|
|
64
|
+
/** One conversation with the head of its thread, for a detail view that opens in one request. */
|
|
65
|
+
export interface ConversationWithMessages {
|
|
66
|
+
conversation: Conversation;
|
|
67
|
+
/** Newest first, same order as `MessagesPage`. */
|
|
68
|
+
messages: Message[];
|
|
69
|
+
/** Cursor for the next (older) page, or null when the thread is fully loaded. */
|
|
70
|
+
nextCursor: Nullable<string>;
|
|
71
|
+
}
|
|
72
|
+
/** `GET /api/v1/conversations`. Cursor-paged — this is the busiest list in the product. */
|
|
73
|
+
export type ConversationsPage = CursorPage<Conversation>;
|
|
74
|
+
/**
|
|
75
|
+
* Query for `GET /api/v1/conversations` — the inbox itself.
|
|
76
|
+
*
|
|
77
|
+
* Every filter is optional and they compose with AND. `assigneeUserId` accepting the literal
|
|
78
|
+
* `'unassigned'` is the one piece of overloading here, and it earns its place: "nobody has picked
|
|
79
|
+
* this up" is the single most-used view in a shared inbox, and expressing it as a separate boolean
|
|
80
|
+
* would make it silently combine with an assignee filter that contradicts it.
|
|
81
|
+
*/
|
|
82
|
+
export interface GetConversationsQuery {
|
|
83
|
+
limit?: number;
|
|
84
|
+
/** Opaque cursor from the previous page's `nextCursor`. Never parse it. */
|
|
85
|
+
after?: Nullable<string>;
|
|
86
|
+
status?: Nullable<ConversationStatus>;
|
|
87
|
+
/** A user id, or `'unassigned'`. */
|
|
88
|
+
assigneeUserId?: Nullable<string>;
|
|
89
|
+
teamId?: Nullable<UUID>;
|
|
90
|
+
channelId?: Nullable<UUID>;
|
|
91
|
+
platform?: Nullable<ChannelPlatform>;
|
|
92
|
+
/** Only conversations with at least one unread inbound message. */
|
|
93
|
+
hasUnread?: Nullable<boolean>;
|
|
94
|
+
/** Case-insensitive substring of the contact's display name. */
|
|
95
|
+
search?: Nullable<string>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* `PATCH /api/v1/conversations/:id/status`.
|
|
99
|
+
*
|
|
100
|
+
* Its own endpoint rather than a field on a general update, because a status change is an event
|
|
101
|
+
* with side effects — closing stamps `closedAt` and writes a system message, snoozing schedules a
|
|
102
|
+
* reopen — and folding it into a PATCH that also renames things makes those side effects a
|
|
103
|
+
* surprise.
|
|
104
|
+
*/
|
|
105
|
+
export interface UpdateConversationStatusBody {
|
|
106
|
+
status: ConversationStatus;
|
|
107
|
+
/** Required when `status` is `snoozed`, refused otherwise. Must be in the future. */
|
|
108
|
+
snoozedUntil?: Nullable<IsoDateTime>;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* `PATCH /api/v1/conversations/:id/assignee`.
|
|
112
|
+
*
|
|
113
|
+
* `null` unassigns, which is a deliberate act and not the absence of one — hence a body with an
|
|
114
|
+
* explicitly nullable field rather than an optional one. Assigning to a user who is not an active
|
|
115
|
+
* member of the tenant is refused: identity is the authority on who exists, and an inbox that can
|
|
116
|
+
* assign work to a removed employee is an inbox with invisible work in it.
|
|
117
|
+
*/
|
|
118
|
+
export interface UpdateConversationAssigneeBody {
|
|
119
|
+
assigneeUserId: Nullable<UUID>;
|
|
120
|
+
/** Set the routing team at the same time. Omit to leave it alone; `null` clears it. */
|
|
121
|
+
teamId?: Nullable<UUID>;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* `POST /api/v1/conversations/:id/handover` — a human takes over.
|
|
125
|
+
*
|
|
126
|
+
* Idempotent: taking over a conversation already handed over to you is a no-op rather than an
|
|
127
|
+
* error, because the button will be pressed twice and the second press must not read as a failure.
|
|
128
|
+
* Taking over one handed to *somebody else* reassigns it and says so in the thread.
|
|
129
|
+
*/
|
|
130
|
+
export interface HandoverConversationBody {
|
|
131
|
+
/** Defaults to the caller. Naming someone else is a handover *to* them. */
|
|
132
|
+
userId?: Nullable<UUID>;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=conversation.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation.type.d.ts","sourceRoot":"","sources":["../../../../src/api/unibox/conversation.type.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation.type.js","sourceRoot":"","sources":["../../../../src/api/unibox/conversation.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './canned-reply.type.js';
|
|
2
|
+
export * from './channel-platform.enum.js';
|
|
3
|
+
export * from './channel.type.js';
|
|
4
|
+
export * from './contact.type.js';
|
|
5
|
+
export * from './conversation-status.enum.js';
|
|
6
|
+
export * from './conversation.type.js';
|
|
7
|
+
export * from './message-author-type.enum.js';
|
|
8
|
+
export * from './message-content-type.enum.js';
|
|
9
|
+
export * from './message-direction.enum.js';
|
|
10
|
+
export * from './message-status.enum.js';
|
|
11
|
+
export * from './message.type.js';
|
|
12
|
+
export * from './team.type.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/api/unibox/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './canned-reply.type.js';
|
|
2
|
+
export * from './channel-platform.enum.js';
|
|
3
|
+
export * from './channel.type.js';
|
|
4
|
+
export * from './contact.type.js';
|
|
5
|
+
export * from './conversation-status.enum.js';
|
|
6
|
+
export * from './conversation.type.js';
|
|
7
|
+
export * from './message-author-type.enum.js';
|
|
8
|
+
export * from './message-content-type.enum.js';
|
|
9
|
+
export * from './message-direction.enum.js';
|
|
10
|
+
export * from './message-status.enum.js';
|
|
11
|
+
export * from './message.type.js';
|
|
12
|
+
export * from './team.type.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/api/unibox/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who produced a message.
|
|
3
|
+
*
|
|
4
|
+
* `AI` is a member here even though `unibox-ai` is build-order step 9 and does not exist. That is
|
|
5
|
+
* not speculation — it is the field an agent taking over mid-conversation reads to know what the
|
|
6
|
+
* customer has already been told, and §12 makes human handoff a launch requirement rather than a
|
|
7
|
+
* v2 feature. Adding the member later would mean every message written before it was added is
|
|
8
|
+
* indistinguishable from a human's, retroactively and unfixably.
|
|
9
|
+
*/
|
|
10
|
+
export declare enum MessageAuthorType {
|
|
11
|
+
/** The person on the other end. `authorUserId` is null. */
|
|
12
|
+
CONTACT = "contact",
|
|
13
|
+
/** A human agent. `authorUserId` names them. */
|
|
14
|
+
AGENT = "agent",
|
|
15
|
+
/**
|
|
16
|
+
* The AI agent. Reserved for `unibox-ai`; nothing writes it yet.
|
|
17
|
+
*
|
|
18
|
+
* Distinct from `AGENT` because "did a person say this?" is the question a human asks before
|
|
19
|
+
* taking over, and because a customer who later asks whether they were talking to a bot
|
|
20
|
+
* deserves an answer the data can actually give.
|
|
21
|
+
*/
|
|
22
|
+
AI = "ai",
|
|
23
|
+
/** Unibox itself — assignment changes, status changes. Always `INTERNAL`. */
|
|
24
|
+
SYSTEM = "system"
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=message-author-type.enum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-author-type.enum.d.ts","sourceRoot":"","sources":["../../../../src/api/unibox/message-author-type.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,oBAAY,iBAAiB;IACzB,2DAA2D;IAC3D,OAAO,YAAY;IAEnB,gDAAgD;IAChD,KAAK,UAAU;IAEf;;;;;;OAMG;IACH,EAAE,OAAO;IAET,6EAA6E;IAC7E,MAAM,WAAW;CACpB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who produced a message.
|
|
3
|
+
*
|
|
4
|
+
* `AI` is a member here even though `unibox-ai` is build-order step 9 and does not exist. That is
|
|
5
|
+
* not speculation — it is the field an agent taking over mid-conversation reads to know what the
|
|
6
|
+
* customer has already been told, and §12 makes human handoff a launch requirement rather than a
|
|
7
|
+
* v2 feature. Adding the member later would mean every message written before it was added is
|
|
8
|
+
* indistinguishable from a human's, retroactively and unfixably.
|
|
9
|
+
*/
|
|
10
|
+
export var MessageAuthorType;
|
|
11
|
+
(function (MessageAuthorType) {
|
|
12
|
+
/** The person on the other end. `authorUserId` is null. */
|
|
13
|
+
MessageAuthorType["CONTACT"] = "contact";
|
|
14
|
+
/** A human agent. `authorUserId` names them. */
|
|
15
|
+
MessageAuthorType["AGENT"] = "agent";
|
|
16
|
+
/**
|
|
17
|
+
* The AI agent. Reserved for `unibox-ai`; nothing writes it yet.
|
|
18
|
+
*
|
|
19
|
+
* Distinct from `AGENT` because "did a person say this?" is the question a human asks before
|
|
20
|
+
* taking over, and because a customer who later asks whether they were talking to a bot
|
|
21
|
+
* deserves an answer the data can actually give.
|
|
22
|
+
*/
|
|
23
|
+
MessageAuthorType["AI"] = "ai";
|
|
24
|
+
/** Unibox itself — assignment changes, status changes. Always `INTERNAL`. */
|
|
25
|
+
MessageAuthorType["SYSTEM"] = "system";
|
|
26
|
+
})(MessageAuthorType || (MessageAuthorType = {}));
|
|
27
|
+
//# sourceMappingURL=message-author-type.enum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-author-type.enum.js","sourceRoot":"","sources":["../../../../src/api/unibox/message-author-type.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,CAAN,IAAY,iBAkBX;AAlBD,WAAY,iBAAiB;IACzB,2DAA2D;IAC3D,wCAAmB,CAAA;IAEnB,gDAAgD;IAChD,oCAAe,CAAA;IAEf;;;;;;OAMG;IACH,8BAAS,CAAA;IAET,6EAA6E;IAC7E,sCAAiB,CAAA;AACrB,CAAC,EAlBW,iBAAiB,KAAjB,iBAAiB,QAkB5B"}
|