@cosmoops/connect-sdk 0.28.0 → 0.29.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/CHANGELOG.md +44 -0
- package/dist/cjs/server/client.js +5 -1
- package/dist/cjs/server/resources/conversations.js +70 -0
- package/dist/esm/server/client.js +5 -1
- package/dist/esm/server/resources/conversations.js +66 -0
- package/dist/types/server/client.d.ts +4 -1
- package/dist/types/server/resources/conversations.d.ts +68 -0
- package/dist/types/types.d.ts +82 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,50 @@
|
|
|
3
3
|
`@cosmoops/connect-sdk` follows semver, with the 0.x convention that **minor
|
|
4
4
|
versions may carry breaking changes** and patch versions never do.
|
|
5
5
|
|
|
6
|
+
## 0.29.0
|
|
7
|
+
|
|
8
|
+
Voice was readable and writing was not. `calls.list` has always let a partner
|
|
9
|
+
read back what a customer said out loud; the WhatsApp threads a workspace's
|
|
10
|
+
agents hold had no partner surface at all, so a CRM could show every call on a
|
|
11
|
+
contact and nothing they had typed.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `connect.conversations.list({ workspaceId, contactAddress?, status? })` and
|
|
16
|
+
`connect.conversations.get(id, { workspaceId })`, plus the four types they
|
|
17
|
+
answer with: `ConnectConversation`, `ConnectConversationMessage`,
|
|
18
|
+
`ConversationsPage` and `ConversationDetail`.
|
|
19
|
+
|
|
20
|
+
**These are the *workspace's* threads, not your application's**, which is the
|
|
21
|
+
difference from `calls` and it decides how they are gated. A call arrived on
|
|
22
|
+
a channel you hold, so `calls.list` is scoped to your application by the key
|
|
23
|
+
alone. A conversation lives in the workspace's own subtree and belongs to it
|
|
24
|
+
the way its contact book does — so reading one needs the `conversations:read`
|
|
25
|
+
scope **and** a live subscription in that workspace, and, when the call comes
|
|
26
|
+
through the browser bridge, the signed-in member's own `agent:read`.
|
|
27
|
+
|
|
28
|
+
Three things are worth reading before you render one:
|
|
29
|
+
|
|
30
|
+
`contactAddress` is the filter to reach for beside your own customer record.
|
|
31
|
+
You hold a phone number, and you cannot derive a conversation id from one —
|
|
32
|
+
the id is built from a hashed key, deliberately, so an id you could guess is
|
|
33
|
+
an id you could probe. Send the number however your records spell it.
|
|
34
|
+
|
|
35
|
+
`canReplyFreely` is computed against Connect's clock, and re-deriving it from
|
|
36
|
+
`lastInboundAt` against yours is the mistake to avoid: WhatsApp allows a
|
|
37
|
+
free-form reply only inside 24 hours of the customer's last message, and a
|
|
38
|
+
skew between your server and Connect's shows up as a thread your UI calls
|
|
39
|
+
answerable when it is not.
|
|
40
|
+
|
|
41
|
+
Messages that sent nothing are included and carry `failure`. Render them — a
|
|
42
|
+
transcript that silently drops them reads as a customer being ignored, which
|
|
43
|
+
is the opposite of what happened. `refused` is not a failure at all: it is
|
|
44
|
+
the agent deciding not to answer, which is what it is for.
|
|
45
|
+
|
|
46
|
+
Read-only, and deliberately. Sending on a thread would mean saying whether it
|
|
47
|
+
is a free-form reply or an approved template, and what that means for the
|
|
48
|
+
agent still answering it.
|
|
49
|
+
|
|
6
50
|
## 0.28.0
|
|
7
51
|
|
|
8
52
|
Connect's webhook bus carried four events, all of them about billing and
|
|
@@ -11,6 +11,7 @@ const scheduling_js_1 = require("./resources/scheduling.js");
|
|
|
11
11
|
const contacts_js_1 = require("./resources/contacts.js");
|
|
12
12
|
const channels_js_1 = require("./resources/channels.js");
|
|
13
13
|
const calls_js_1 = require("./resources/calls.js");
|
|
14
|
+
const conversations_js_1 = require("./resources/conversations.js");
|
|
14
15
|
const kv_js_1 = require("./resources/kv.js");
|
|
15
16
|
const billing_js_1 = require("./resources/billing.js");
|
|
16
17
|
const drive_js_1 = require("./resources/drive.js");
|
|
@@ -92,6 +93,8 @@ class ConnectClient {
|
|
|
92
93
|
channels;
|
|
93
94
|
/** The calls that arrived on those channels, with their transcripts. */
|
|
94
95
|
calls;
|
|
96
|
+
/** The message threads a subscribing workspace's agents are holding. */
|
|
97
|
+
conversations;
|
|
95
98
|
/** RAG chat and structured extraction. */
|
|
96
99
|
ai;
|
|
97
100
|
enrichment;
|
|
@@ -145,6 +148,7 @@ class ConnectClient {
|
|
|
145
148
|
this.contacts = new contacts_js_1.ContactsResource(transport);
|
|
146
149
|
this.channels = new channels_js_1.ChannelsResource(transport);
|
|
147
150
|
this.calls = new calls_js_1.CallsResource(transport);
|
|
151
|
+
this.conversations = new conversations_js_1.ConversationsResource(transport);
|
|
148
152
|
this.ai = new ai_js_1.AiResource(transport);
|
|
149
153
|
this.enrichment = new enrichment_js_1.EnrichmentResource(transport);
|
|
150
154
|
this.data = new data_js_1.DataResource(transport);
|
|
@@ -161,4 +165,4 @@ class ConnectClient {
|
|
|
161
165
|
}
|
|
162
166
|
exports.ConnectClient = ConnectClient;
|
|
163
167
|
/** Kept in step with `package.json` by `sdk.test.ts`. */
|
|
164
|
-
exports.SDK_VERSION = "0.
|
|
168
|
+
exports.SDK_VERSION = "0.29.0";
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConversationsResource = void 0;
|
|
4
|
+
const http_js_1 = require("../http.js");
|
|
5
|
+
const acting_as_js_1 = require("./acting-as.js");
|
|
6
|
+
/**
|
|
7
|
+
* What a workspace's agents are saying in writing.
|
|
8
|
+
*
|
|
9
|
+
* **The sibling of `calls`, with one difference that decides how it is
|
|
10
|
+
* gated: these are the *workspace's* threads, not your application's.** A call
|
|
11
|
+
* arrived on a channel you hold, so `calls.list` is scoped to your
|
|
12
|
+
* application. A conversation lives in the workspace's own subtree and belongs
|
|
13
|
+
* to it the way its contact book does - so reading one needs a live
|
|
14
|
+
* subscription in that workspace, and, when the call comes from a browser
|
|
15
|
+
* through the bridge, the signed-in member's own `agent:read`.
|
|
16
|
+
*
|
|
17
|
+
* Read-only, and deliberately. Sending on a thread is not a missing verb:
|
|
18
|
+
* inside WhatsApp's 24-hour window a reply is the agent's to make, outside it
|
|
19
|
+
* only an approved template may be sent, and posting into a thread would mean
|
|
20
|
+
* saying which of those it was and what it means for the agent still
|
|
21
|
+
* answering.
|
|
22
|
+
*/
|
|
23
|
+
class ConversationsResource {
|
|
24
|
+
transport;
|
|
25
|
+
constructor(transport) {
|
|
26
|
+
this.transport = transport;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The workspace's threads, newest activity first.
|
|
30
|
+
*
|
|
31
|
+
* **Page until `hasMore` is `false`; do not stop on an empty `items`.** An
|
|
32
|
+
* inbox grows without bound, so there is no total count to page against.
|
|
33
|
+
*/
|
|
34
|
+
list(input) {
|
|
35
|
+
return (0, http_js_1.request)(this.transport, {
|
|
36
|
+
method: "GET",
|
|
37
|
+
path: "/conversations",
|
|
38
|
+
query: {
|
|
39
|
+
workspaceId: input.workspaceId,
|
|
40
|
+
contactAddress: input.contactAddress,
|
|
41
|
+
status: input.status,
|
|
42
|
+
cursor: input.cursor,
|
|
43
|
+
limit: input.limit === undefined ? undefined : String(input.limit),
|
|
44
|
+
},
|
|
45
|
+
headers: (0, acting_as_js_1.actingAs)(input.asUser),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* One thread and its recent messages, oldest first.
|
|
50
|
+
*
|
|
51
|
+
* **Capped, not paged** - you get the same window the agent itself sees when
|
|
52
|
+
* it composes a reply, so you are never shown less context than it used.
|
|
53
|
+
*
|
|
54
|
+
* Turns that produced no message are included and carry `failure`. Render
|
|
55
|
+
* them: a transcript that silently drops them reads as a customer being
|
|
56
|
+
* ignored, which is the opposite of what happened.
|
|
57
|
+
*
|
|
58
|
+
* Throws `ConnectError` with `code: "not_found"` for a thread this workspace
|
|
59
|
+
* does not hold.
|
|
60
|
+
*/
|
|
61
|
+
get(conversationId, options) {
|
|
62
|
+
return (0, http_js_1.request)(this.transport, {
|
|
63
|
+
method: "GET",
|
|
64
|
+
path: `/conversations/${encodeURIComponent(conversationId)}`,
|
|
65
|
+
query: { workspaceId: options.workspaceId },
|
|
66
|
+
headers: (0, acting_as_js_1.actingAs)(options.asUser),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.ConversationsResource = ConversationsResource;
|
|
@@ -8,6 +8,7 @@ import { SchedulingResource } from "./resources/scheduling.js";
|
|
|
8
8
|
import { ContactsResource } from "./resources/contacts.js";
|
|
9
9
|
import { ChannelsResource } from "./resources/channels.js";
|
|
10
10
|
import { CallsResource } from "./resources/calls.js";
|
|
11
|
+
import { ConversationsResource } from "./resources/conversations.js";
|
|
11
12
|
import { KvResource } from "./resources/kv.js";
|
|
12
13
|
import { BillingResource } from "./resources/billing.js";
|
|
13
14
|
import { DriveResource } from "./resources/drive.js";
|
|
@@ -89,6 +90,8 @@ export class ConnectClient {
|
|
|
89
90
|
channels;
|
|
90
91
|
/** The calls that arrived on those channels, with their transcripts. */
|
|
91
92
|
calls;
|
|
93
|
+
/** The message threads a subscribing workspace's agents are holding. */
|
|
94
|
+
conversations;
|
|
92
95
|
/** RAG chat and structured extraction. */
|
|
93
96
|
ai;
|
|
94
97
|
enrichment;
|
|
@@ -142,6 +145,7 @@ export class ConnectClient {
|
|
|
142
145
|
this.contacts = new ContactsResource(transport);
|
|
143
146
|
this.channels = new ChannelsResource(transport);
|
|
144
147
|
this.calls = new CallsResource(transport);
|
|
148
|
+
this.conversations = new ConversationsResource(transport);
|
|
145
149
|
this.ai = new AiResource(transport);
|
|
146
150
|
this.enrichment = new EnrichmentResource(transport);
|
|
147
151
|
this.data = new DataResource(transport);
|
|
@@ -157,4 +161,4 @@ export class ConnectClient {
|
|
|
157
161
|
}
|
|
158
162
|
}
|
|
159
163
|
/** Kept in step with `package.json` by `sdk.test.ts`. */
|
|
160
|
-
export const SDK_VERSION = "0.
|
|
164
|
+
export const SDK_VERSION = "0.29.0";
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { request } from "../http.js";
|
|
2
|
+
import { actingAs } from "./acting-as.js";
|
|
3
|
+
/**
|
|
4
|
+
* What a workspace's agents are saying in writing.
|
|
5
|
+
*
|
|
6
|
+
* **The sibling of `calls`, with one difference that decides how it is
|
|
7
|
+
* gated: these are the *workspace's* threads, not your application's.** A call
|
|
8
|
+
* arrived on a channel you hold, so `calls.list` is scoped to your
|
|
9
|
+
* application. A conversation lives in the workspace's own subtree and belongs
|
|
10
|
+
* to it the way its contact book does - so reading one needs a live
|
|
11
|
+
* subscription in that workspace, and, when the call comes from a browser
|
|
12
|
+
* through the bridge, the signed-in member's own `agent:read`.
|
|
13
|
+
*
|
|
14
|
+
* Read-only, and deliberately. Sending on a thread is not a missing verb:
|
|
15
|
+
* inside WhatsApp's 24-hour window a reply is the agent's to make, outside it
|
|
16
|
+
* only an approved template may be sent, and posting into a thread would mean
|
|
17
|
+
* saying which of those it was and what it means for the agent still
|
|
18
|
+
* answering.
|
|
19
|
+
*/
|
|
20
|
+
export class ConversationsResource {
|
|
21
|
+
transport;
|
|
22
|
+
constructor(transport) {
|
|
23
|
+
this.transport = transport;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The workspace's threads, newest activity first.
|
|
27
|
+
*
|
|
28
|
+
* **Page until `hasMore` is `false`; do not stop on an empty `items`.** An
|
|
29
|
+
* inbox grows without bound, so there is no total count to page against.
|
|
30
|
+
*/
|
|
31
|
+
list(input) {
|
|
32
|
+
return request(this.transport, {
|
|
33
|
+
method: "GET",
|
|
34
|
+
path: "/conversations",
|
|
35
|
+
query: {
|
|
36
|
+
workspaceId: input.workspaceId,
|
|
37
|
+
contactAddress: input.contactAddress,
|
|
38
|
+
status: input.status,
|
|
39
|
+
cursor: input.cursor,
|
|
40
|
+
limit: input.limit === undefined ? undefined : String(input.limit),
|
|
41
|
+
},
|
|
42
|
+
headers: actingAs(input.asUser),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* One thread and its recent messages, oldest first.
|
|
47
|
+
*
|
|
48
|
+
* **Capped, not paged** - you get the same window the agent itself sees when
|
|
49
|
+
* it composes a reply, so you are never shown less context than it used.
|
|
50
|
+
*
|
|
51
|
+
* Turns that produced no message are included and carry `failure`. Render
|
|
52
|
+
* them: a transcript that silently drops them reads as a customer being
|
|
53
|
+
* ignored, which is the opposite of what happened.
|
|
54
|
+
*
|
|
55
|
+
* Throws `ConnectError` with `code: "not_found"` for a thread this workspace
|
|
56
|
+
* does not hold.
|
|
57
|
+
*/
|
|
58
|
+
get(conversationId, options) {
|
|
59
|
+
return request(this.transport, {
|
|
60
|
+
method: "GET",
|
|
61
|
+
path: `/conversations/${encodeURIComponent(conversationId)}`,
|
|
62
|
+
query: { workspaceId: options.workspaceId },
|
|
63
|
+
headers: actingAs(options.asUser),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -9,6 +9,7 @@ import { SchedulingResource } from "./resources/scheduling.js";
|
|
|
9
9
|
import { ContactsResource } from "./resources/contacts.js";
|
|
10
10
|
import { ChannelsResource } from "./resources/channels.js";
|
|
11
11
|
import { CallsResource } from "./resources/calls.js";
|
|
12
|
+
import { ConversationsResource } from "./resources/conversations.js";
|
|
12
13
|
import { KvResource } from "./resources/kv.js";
|
|
13
14
|
import { BillingResource } from "./resources/billing.js";
|
|
14
15
|
import { DriveResource } from "./resources/drive.js";
|
|
@@ -88,6 +89,8 @@ export declare class ConnectClient {
|
|
|
88
89
|
readonly channels: ChannelsResource;
|
|
89
90
|
/** The calls that arrived on those channels, with their transcripts. */
|
|
90
91
|
readonly calls: CallsResource;
|
|
92
|
+
/** The message threads a subscribing workspace's agents are holding. */
|
|
93
|
+
readonly conversations: ConversationsResource;
|
|
91
94
|
/** RAG chat and structured extraction. */
|
|
92
95
|
readonly ai: AiResource;
|
|
93
96
|
readonly enrichment: EnrichmentResource;
|
|
@@ -123,4 +126,4 @@ export declare class ConnectClient {
|
|
|
123
126
|
constructor(options: ConnectClientOptions);
|
|
124
127
|
}
|
|
125
128
|
/** Kept in step with `package.json` by `sdk.test.ts`. */
|
|
126
|
-
export declare const SDK_VERSION = "0.
|
|
129
|
+
export declare const SDK_VERSION = "0.29.0";
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { type TransportOptions } from "../http.js";
|
|
2
|
+
import type { ConversationDetail, ConversationsPage } from "../../types.js";
|
|
3
|
+
export interface ListConversationsInput {
|
|
4
|
+
workspaceId: string;
|
|
5
|
+
/**
|
|
6
|
+
* Narrow to one party's threads.
|
|
7
|
+
*
|
|
8
|
+
* Any reasonable spelling - `+919000000001`, `919000000001`,
|
|
9
|
+
* `+91 90000 00001` all resolve to the same threads, because the number is
|
|
10
|
+
* normalized server-side before the match. This is the filter to reach for
|
|
11
|
+
* beside your own customer record: you hold a phone number, and you cannot
|
|
12
|
+
* derive a conversation id from one because the id is built from a *hashed*
|
|
13
|
+
* key.
|
|
14
|
+
*/
|
|
15
|
+
contactAddress?: string;
|
|
16
|
+
status?: "open" | "snoozed" | "closed";
|
|
17
|
+
/** From a previous page's `nextCursor`. */
|
|
18
|
+
cursor?: string;
|
|
19
|
+
/** 1-50, default 20. */
|
|
20
|
+
limit?: number;
|
|
21
|
+
/** See `ActingAsOption` on the scheduling resource - same contract. */
|
|
22
|
+
asUser?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* What a workspace's agents are saying in writing.
|
|
26
|
+
*
|
|
27
|
+
* **The sibling of `calls`, with one difference that decides how it is
|
|
28
|
+
* gated: these are the *workspace's* threads, not your application's.** A call
|
|
29
|
+
* arrived on a channel you hold, so `calls.list` is scoped to your
|
|
30
|
+
* application. A conversation lives in the workspace's own subtree and belongs
|
|
31
|
+
* to it the way its contact book does - so reading one needs a live
|
|
32
|
+
* subscription in that workspace, and, when the call comes from a browser
|
|
33
|
+
* through the bridge, the signed-in member's own `agent:read`.
|
|
34
|
+
*
|
|
35
|
+
* Read-only, and deliberately. Sending on a thread is not a missing verb:
|
|
36
|
+
* inside WhatsApp's 24-hour window a reply is the agent's to make, outside it
|
|
37
|
+
* only an approved template may be sent, and posting into a thread would mean
|
|
38
|
+
* saying which of those it was and what it means for the agent still
|
|
39
|
+
* answering.
|
|
40
|
+
*/
|
|
41
|
+
export declare class ConversationsResource {
|
|
42
|
+
private readonly transport;
|
|
43
|
+
constructor(transport: TransportOptions);
|
|
44
|
+
/**
|
|
45
|
+
* The workspace's threads, newest activity first.
|
|
46
|
+
*
|
|
47
|
+
* **Page until `hasMore` is `false`; do not stop on an empty `items`.** An
|
|
48
|
+
* inbox grows without bound, so there is no total count to page against.
|
|
49
|
+
*/
|
|
50
|
+
list(input: ListConversationsInput): Promise<ConversationsPage>;
|
|
51
|
+
/**
|
|
52
|
+
* One thread and its recent messages, oldest first.
|
|
53
|
+
*
|
|
54
|
+
* **Capped, not paged** - you get the same window the agent itself sees when
|
|
55
|
+
* it composes a reply, so you are never shown less context than it used.
|
|
56
|
+
*
|
|
57
|
+
* Turns that produced no message are included and carry `failure`. Render
|
|
58
|
+
* them: a transcript that silently drops them reads as a customer being
|
|
59
|
+
* ignored, which is the opposite of what happened.
|
|
60
|
+
*
|
|
61
|
+
* Throws `ConnectError` with `code: "not_found"` for a thread this workspace
|
|
62
|
+
* does not hold.
|
|
63
|
+
*/
|
|
64
|
+
get(conversationId: string, options: {
|
|
65
|
+
workspaceId: string;
|
|
66
|
+
asUser?: string;
|
|
67
|
+
}): Promise<ConversationDetail>;
|
|
68
|
+
}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1822,3 +1822,85 @@ export interface CallsPage {
|
|
|
1822
1822
|
nextCursor: string | null;
|
|
1823
1823
|
hasMore: boolean;
|
|
1824
1824
|
}
|
|
1825
|
+
/**
|
|
1826
|
+
* One message thread a workspace's agents are holding.
|
|
1827
|
+
*
|
|
1828
|
+
* Hand-written rather than imported from Connect, like every other type in
|
|
1829
|
+
* this file - `conformance.test.ts` type-checks it against the server DTO, so
|
|
1830
|
+
* drift fails the build here rather than in your integration.
|
|
1831
|
+
*
|
|
1832
|
+
* Dates are ISO-8601 strings. JSON has no date type, and a UTC ISO string
|
|
1833
|
+
* sorts lexicographically in chronological order, so these compare and
|
|
1834
|
+
* range-filter without being parsed first.
|
|
1835
|
+
*/
|
|
1836
|
+
export interface ConnectConversation {
|
|
1837
|
+
id: string;
|
|
1838
|
+
/** The channel the thread arrived on. */
|
|
1839
|
+
channelId: string;
|
|
1840
|
+
/** Today always `whatsapp` - a voice channel produces calls, not threads. */
|
|
1841
|
+
kind: "whatsapp";
|
|
1842
|
+
/** The other party, normalized to E.164. */
|
|
1843
|
+
contactAddress: string;
|
|
1844
|
+
/**
|
|
1845
|
+
* The Connect contact this thread is about, once one has been matched.
|
|
1846
|
+
*
|
|
1847
|
+
* The join to your own records - store this on yours rather than matching
|
|
1848
|
+
* phone numbers. See `ContactsResource`.
|
|
1849
|
+
*/
|
|
1850
|
+
contactId: string | null;
|
|
1851
|
+
/** As the provider reported it, when it did. */
|
|
1852
|
+
contactName: string | null;
|
|
1853
|
+
status: "open" | "snoozed" | "closed";
|
|
1854
|
+
/** `null` means nothing is answering: no routing, or a human took over. */
|
|
1855
|
+
agentId: string | null;
|
|
1856
|
+
lastInboundAt: string;
|
|
1857
|
+
lastOutboundAt: string | null;
|
|
1858
|
+
lastMessagePreview: string;
|
|
1859
|
+
/**
|
|
1860
|
+
* Whether a free-form reply is still allowed, computed against **Connect's**
|
|
1861
|
+
* clock.
|
|
1862
|
+
*
|
|
1863
|
+
* WhatsApp allows one only inside 24 hours of the customer's last message;
|
|
1864
|
+
* outside it, only an approved template may be sent. Do not re-derive this
|
|
1865
|
+
* from `lastInboundAt` against your own clock - a skew shows up as a thread
|
|
1866
|
+
* your UI calls answerable when it is not.
|
|
1867
|
+
*/
|
|
1868
|
+
canReplyFreely: boolean;
|
|
1869
|
+
createdAt: string;
|
|
1870
|
+
updatedAt: string;
|
|
1871
|
+
}
|
|
1872
|
+
/**
|
|
1873
|
+
* Why a turn produced no message.
|
|
1874
|
+
*
|
|
1875
|
+
* `refused` is not a failure at all - it is the agent deciding not to answer,
|
|
1876
|
+
* which is what it is for.
|
|
1877
|
+
*/
|
|
1878
|
+
export type ConnectMessageFailure = "window_closed" | "no_agent" | "model_error" | "send_failed" | "refused";
|
|
1879
|
+
/** One message on a thread. A turn that sent nothing still appears, carrying `failure`. */
|
|
1880
|
+
export interface ConnectConversationMessage {
|
|
1881
|
+
id: string;
|
|
1882
|
+
direction: "inbound" | "outbound";
|
|
1883
|
+
/**
|
|
1884
|
+
* Who produced it.
|
|
1885
|
+
*
|
|
1886
|
+
* `agent` and `human` are both outbound and deliberately distinguished - a
|
|
1887
|
+
* thread that cannot show which replies were automatic is one nobody trusts
|
|
1888
|
+
* enough to leave running. `system` is neither party: a turn Connect itself
|
|
1889
|
+
* recorded, which is what a `failure` row is.
|
|
1890
|
+
*/
|
|
1891
|
+
author: "contact" | "agent" | "human" | "system";
|
|
1892
|
+
text: string;
|
|
1893
|
+
failure: ConnectMessageFailure | null;
|
|
1894
|
+
createdAt: string;
|
|
1895
|
+
}
|
|
1896
|
+
/** A thread and its recent messages, oldest first. Capped rather than paged. */
|
|
1897
|
+
export interface ConversationDetail {
|
|
1898
|
+
conversation: ConnectConversation;
|
|
1899
|
+
messages: ConnectConversationMessage[];
|
|
1900
|
+
}
|
|
1901
|
+
/** One page of threads, newest activity first. Page until `hasMore` is `false`. */
|
|
1902
|
+
export interface ConversationsPage {
|
|
1903
|
+
items: ConnectConversation[];
|
|
1904
|
+
nextCursor: string | null;
|
|
1905
|
+
hasMore: boolean;
|
|
1906
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmoops/connect-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.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",
|