@cossistant/core 0.0.28 → 0.0.30
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/_virtual/rolldown_runtime.js +27 -12
- package/ai-sdk-utils.d.ts +141 -0
- package/ai-sdk-utils.d.ts.map +1 -0
- package/ai-sdk-utils.js +255 -0
- package/ai-sdk-utils.js.map +1 -0
- package/client.d.ts +17 -7
- package/client.d.ts.map +1 -1
- package/client.js +34 -3
- package/client.js.map +1 -1
- package/index.d.ts +3 -1
- package/index.js +3 -1
- package/package.json +1 -1
- package/privacy-filter.d.ts +112 -0
- package/privacy-filter.d.ts.map +1 -0
- package/privacy-filter.js +170 -0
- package/privacy-filter.js.map +1 -0
- package/rest-client.d.ts +4 -4
- package/rest-client.d.ts.map +1 -1
- package/rest-client.js +4 -4
- package/rest-client.js.map +1 -1
- package/store/conversations-store.d.ts +1 -1
- package/store/seen-store.d.ts +2 -2
- package/store/timeline-items-store.d.ts +5 -5
- package/store/timeline-items-store.d.ts.map +1 -1
- package/store/timeline-items-store.js +1 -1
- package/store/timeline-items-store.js.map +1 -1
- package/store/typing-store.d.ts +1 -1
- package/store/typing-store.d.ts.map +1 -1
- package/store/typing-store.js +12 -19
- package/store/typing-store.js.map +1 -1
- package/types/src/api/contact.d.ts.map +1 -0
- package/{conversation.d.ts → types/src/api/conversation.d.ts} +458 -78
- package/types/src/api/conversation.d.ts.map +1 -0
- package/types/src/api/timeline-item.d.ts +602 -0
- package/types/src/api/timeline-item.d.ts.map +1 -0
- package/types/src/api/timeline-item.js +67 -19
- package/types/src/api/timeline-item.js.map +1 -1
- package/types/src/api/upload.d.ts.map +1 -0
- package/types/src/enums.js +4 -1
- package/types/src/enums.js.map +1 -1
- package/types/src/realtime-events.d.ts +1000 -0
- package/types/src/realtime-events.d.ts.map +1 -0
- package/{schemas.d.ts → types/src/schemas.d.ts} +92 -16
- package/types/src/schemas.d.ts.map +1 -0
- package/contact.d.ts.map +0 -1
- package/conversation.d.ts.map +0 -1
- package/realtime-events.d.ts +0 -478
- package/realtime-events.d.ts.map +0 -1
- package/schemas.d.ts.map +0 -1
- package/timeline-item.d.ts +0 -298
- package/timeline-item.d.ts.map +0 -1
- package/upload.d.ts.map +0 -1
- /package/{contact.d.ts → types/src/api/contact.d.ts} +0 -0
- /package/{upload.d.ts → types/src/api/upload.d.ts} +0 -0
|
@@ -3,25 +3,40 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (all) => {
|
|
6
|
+
var __export = (all, symbols) => {
|
|
7
7
|
let target = {};
|
|
8
|
-
for (var name in all)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
for (var name in all) {
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
if (symbols) {
|
|
15
|
+
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
16
|
+
}
|
|
12
17
|
return target;
|
|
13
18
|
};
|
|
14
19
|
var __copyProps = (to, from, except, desc) => {
|
|
15
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
21
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
22
|
+
key = keys[i];
|
|
23
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
24
|
+
__defProp(to, key, {
|
|
25
|
+
get: ((k) => from[k]).bind(null, key),
|
|
26
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
21
30
|
}
|
|
22
31
|
return to;
|
|
23
32
|
};
|
|
24
|
-
var __reExport = (target, mod, secondTarget
|
|
33
|
+
var __reExport = (target, mod, secondTarget, symbols) => {
|
|
34
|
+
if (symbols) {
|
|
35
|
+
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
36
|
+
secondTarget && __defProp(secondTarget, Symbol.toStringTag, { value: "Module" });
|
|
37
|
+
}
|
|
38
|
+
__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default");
|
|
39
|
+
};
|
|
25
40
|
|
|
26
41
|
//#endregion
|
|
27
42
|
export { __export, __reExport };
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { TimelineItem, TimelineItemParts } from "@cossistant/types";
|
|
2
|
+
|
|
3
|
+
//#region src/ai-sdk-utils.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* AI SDK UIMessage part types - these are the standard AI SDK v6 parts
|
|
7
|
+
*/
|
|
8
|
+
type AISDKTextPart = {
|
|
9
|
+
type: "text";
|
|
10
|
+
text: string;
|
|
11
|
+
state?: "streaming" | "done";
|
|
12
|
+
};
|
|
13
|
+
type AISDKReasoningPart = {
|
|
14
|
+
type: "reasoning";
|
|
15
|
+
text: string;
|
|
16
|
+
state?: "streaming" | "done";
|
|
17
|
+
providerMetadata?: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
type AISDKToolPart = {
|
|
20
|
+
type: `tool-${string}`;
|
|
21
|
+
toolCallId: string;
|
|
22
|
+
toolName: string;
|
|
23
|
+
input: Record<string, unknown>;
|
|
24
|
+
output?: unknown;
|
|
25
|
+
state: "partial" | "result" | "error";
|
|
26
|
+
errorText?: string;
|
|
27
|
+
providerMetadata?: Record<string, unknown>;
|
|
28
|
+
};
|
|
29
|
+
type AISDKSourceUrlPart = {
|
|
30
|
+
type: "source-url";
|
|
31
|
+
sourceId: string;
|
|
32
|
+
url: string;
|
|
33
|
+
title?: string;
|
|
34
|
+
providerMetadata?: Record<string, unknown>;
|
|
35
|
+
};
|
|
36
|
+
type AISDKSourceDocumentPart = {
|
|
37
|
+
type: "source-document";
|
|
38
|
+
sourceId: string;
|
|
39
|
+
mediaType: string;
|
|
40
|
+
title: string;
|
|
41
|
+
filename?: string;
|
|
42
|
+
providerMetadata?: Record<string, unknown>;
|
|
43
|
+
};
|
|
44
|
+
type AISDKStepStartPart = {
|
|
45
|
+
type: "step-start";
|
|
46
|
+
};
|
|
47
|
+
type AISDKFilePart = {
|
|
48
|
+
type: "file";
|
|
49
|
+
url: string;
|
|
50
|
+
mediaType: string;
|
|
51
|
+
filename?: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Cossistant-specific metadata stored in UIMessage.metadata
|
|
55
|
+
*/
|
|
56
|
+
type CossistantMessageMetadata = {
|
|
57
|
+
conversationId: string;
|
|
58
|
+
organizationId: string;
|
|
59
|
+
visibility: "public" | "private";
|
|
60
|
+
userId: string | null;
|
|
61
|
+
aiAgentId: string | null;
|
|
62
|
+
visitorId: string | null;
|
|
63
|
+
replyToId?: string | null;
|
|
64
|
+
createdAt: string;
|
|
65
|
+
deletedAt?: string | null;
|
|
66
|
+
tool?: string | null;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Cossistant-specific metadata stored in part.providerMetadata.cossistant
|
|
70
|
+
*/
|
|
71
|
+
type CossistantPartMetadata = {
|
|
72
|
+
visibility?: "public" | "private";
|
|
73
|
+
progressMessage?: string;
|
|
74
|
+
knowledgeId?: string;
|
|
75
|
+
};
|
|
76
|
+
type AISDKPart = AISDKTextPart | AISDKReasoningPart | AISDKToolPart | AISDKSourceUrlPart | AISDKSourceDocumentPart | AISDKStepStartPart | AISDKFilePart;
|
|
77
|
+
type CossistantPart = TimelineItemParts[number];
|
|
78
|
+
/**
|
|
79
|
+
* Cossistant-compatible UIMessage type
|
|
80
|
+
* This is structurally compatible with AI SDK v6 UIMessage
|
|
81
|
+
* but uses our own part types for flexibility
|
|
82
|
+
*/
|
|
83
|
+
type CossistantUIMessage = {
|
|
84
|
+
id: string;
|
|
85
|
+
role: "user" | "assistant" | "system";
|
|
86
|
+
metadata: CossistantMessageMetadata;
|
|
87
|
+
parts: AISDKPart[];
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Convert a Cossistant TimelineItem to AI SDK UIMessage format
|
|
91
|
+
*
|
|
92
|
+
* @param item - The Cossistant TimelineItem to convert
|
|
93
|
+
* @returns AI SDK compatible UIMessage with Cossistant metadata
|
|
94
|
+
*/
|
|
95
|
+
declare function toUIMessage(item: TimelineItem): CossistantUIMessage;
|
|
96
|
+
/**
|
|
97
|
+
* Convert multiple TimelineItems to UIMessages
|
|
98
|
+
*/
|
|
99
|
+
declare function toUIMessages(items: TimelineItem[]): CossistantUIMessage[];
|
|
100
|
+
/**
|
|
101
|
+
* Context required to create a TimelineItem from UIMessage
|
|
102
|
+
*/
|
|
103
|
+
type FromUIMessageContext = {
|
|
104
|
+
conversationId: string;
|
|
105
|
+
organizationId: string;
|
|
106
|
+
aiAgentId?: string | null;
|
|
107
|
+
userId?: string | null;
|
|
108
|
+
visitorId?: string | null;
|
|
109
|
+
visibility?: "public" | "private";
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Convert an AI SDK UIMessage to Cossistant TimelineItem format
|
|
113
|
+
*
|
|
114
|
+
* @param message - The AI SDK UIMessage to convert
|
|
115
|
+
* @param context - Context for creating the TimelineItem
|
|
116
|
+
* @returns Cossistant TimelineItem
|
|
117
|
+
*/
|
|
118
|
+
declare function fromUIMessage(message: CossistantUIMessage, context: FromUIMessageContext): TimelineItem;
|
|
119
|
+
/**
|
|
120
|
+
* Convert multiple UIMessages to TimelineItems
|
|
121
|
+
*/
|
|
122
|
+
declare function fromUIMessages(messages: CossistantUIMessage[], context: FromUIMessageContext): TimelineItem[];
|
|
123
|
+
/**
|
|
124
|
+
* Check if a part is an AI SDK compatible part type
|
|
125
|
+
*/
|
|
126
|
+
declare function isAISDKCompatiblePart(part: CossistantPart): boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Extract all sources from a message's parts
|
|
129
|
+
*/
|
|
130
|
+
declare function extractSources(parts: AISDKPart[]): (AISDKSourceUrlPart | AISDKSourceDocumentPart)[];
|
|
131
|
+
/**
|
|
132
|
+
* Extract all tool calls from a message's parts
|
|
133
|
+
*/
|
|
134
|
+
declare function extractToolCalls(parts: AISDKPart[]): AISDKToolPart[];
|
|
135
|
+
/**
|
|
136
|
+
* Check if any parts are still processing
|
|
137
|
+
*/
|
|
138
|
+
declare function hasProcessingParts(parts: AISDKPart[]): boolean;
|
|
139
|
+
//#endregion
|
|
140
|
+
export { AISDKFilePart, AISDKPart, AISDKReasoningPart, AISDKSourceDocumentPart, AISDKSourceUrlPart, AISDKStepStartPart, AISDKTextPart, AISDKToolPart, CossistantMessageMetadata, CossistantPartMetadata, CossistantUIMessage, FromUIMessageContext, extractSources, extractToolCalls, fromUIMessage, fromUIMessages, hasProcessingParts, isAISDKCompatiblePart, toUIMessage, toUIMessages };
|
|
141
|
+
//# sourceMappingURL=ai-sdk-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-sdk-utils.d.ts","names":[],"sources":["../src/ai-sdk-utils.ts"],"sourcesContent":[],"mappings":";;;;;;;AA+GG,KAzFS,aAAA,GAyFT;EACA,IAAA,EAAA,MAAA;EACA,IAAA,EAAA,MAAA;EACA,KAAA,CAAA,EAAA,WAAA,GAAA,MAAA;CAAa;AAEX,KAxFO,kBAAA,GAwFU;EA2FV,IAAA,EAAA,WAAA;EAaI,IAAA,EAAA,MAAA;EAsBA,KAAA,CAAA,EAAA,WAAY,GAAA,MAAQ;EAyHxB,gBAAA,CAAA,EA3UQ,MA2UY,CAAA,MAAA,EAAA,OAAA,CAAA;AAgBhC,CAAA;AACU,KAzVE,aAAA,GAyVF;EACA,IAAA,EAAA,QAAA,MAAA,EAAA;EACP,UAAA,EAAA,MAAA;EAAY,QAAA,EAAA,MAAA;EA0BC,KAAA,EAjXR,MAiXQ,CAAA,MAAc,EAAA,OAAA,CAAA;EACnB,MAAA,CAAA,EAAA,OAAA;EACD,KAAA,EAAA,SAAA,GAAA,QAAA,GAAA,OAAA;EACP,SAAA,CAAA,EAAA,MAAA;EAAY,gBAAA,CAAA,EAhXK,MAgXL,CAAA,MAAA,EAAA,OAAA,CAAA;AAkHf,CAAA;AAUgB,KAzeJ,kBAAA,GAyekB;EACtB,IAAA,EAAA,YAAA;EACJ,QAAA,EAAA,MAAA;EAAqB,GAAA,EAAA,MAAA;EAAuB,KAAA,CAAA,EAAA,MAAA;EAUhC,gBAAA,CAAA,EAhfI,MAgfY,CAAA,MAAQ,EAAA,OAAA,CAAc;AAUtD,CAAA;KAvfY,uBAAA;;;;;;qBAMQ;;KAGR,kBAAA;;;KAIA,aAAA;;;;;;;;;KAcA,yBAAA;;;;;;;;;;;;;;;KAgBA,sBAAA;;;;;KAUA,SAAA,GACT,gBACA,qBACA,gBACA,qBACA,0BACA,qBACA;KAEE,cAAA,GAAiB;;;;;;KA2FV,mBAAA;;;YAGD;SACH;;;;;;;;iBASQ,WAAA,OAAkB,eAAe;;;;iBAsBjC,YAAA,QAAoB,iBAAiB;;;;KAyHzC,oBAAA;;;;;;;;;;;;;;;iBAgBI,aAAA,UACN,8BACA,uBACP;;;;iBA0Ba,cAAA,WACL,gCACD,uBACP;;;;iBAkHa,qBAAA,OAA4B;;;;iBAU5B,cAAA,QACR,eACJ,qBAAqB;;;;iBAUT,gBAAA,QAAwB,cAAc;;;;iBAUtC,kBAAA,QAA0B"}
|
package/ai-sdk-utils.js
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
//#region src/ai-sdk-utils.ts
|
|
2
|
+
function isTextPart(part) {
|
|
3
|
+
return part.type === "text" && "text" in part;
|
|
4
|
+
}
|
|
5
|
+
function isReasoningPart(part) {
|
|
6
|
+
return part.type === "reasoning" && "text" in part;
|
|
7
|
+
}
|
|
8
|
+
function isSourceUrlPart(part) {
|
|
9
|
+
return part.type === "source-url" && "sourceId" in part && "url" in part;
|
|
10
|
+
}
|
|
11
|
+
function isSourceDocumentPart(part) {
|
|
12
|
+
return part.type === "source-document" && "sourceId" in part && "mediaType" in part && "title" in part;
|
|
13
|
+
}
|
|
14
|
+
function isStepStartPart(part) {
|
|
15
|
+
return part.type === "step-start";
|
|
16
|
+
}
|
|
17
|
+
function isFilePart(part) {
|
|
18
|
+
return part.type === "file" && "url" in part && "mediaType" in part;
|
|
19
|
+
}
|
|
20
|
+
function isImagePart(part) {
|
|
21
|
+
return part.type === "image" && "url" in part && "mediaType" in part;
|
|
22
|
+
}
|
|
23
|
+
function isToolPart(part) {
|
|
24
|
+
return typeof part.type === "string" && part.type.startsWith("tool-") && "toolCallId" in part && "toolName" in part;
|
|
25
|
+
}
|
|
26
|
+
function isEventPart(part) {
|
|
27
|
+
return part.type === "event";
|
|
28
|
+
}
|
|
29
|
+
function isMetadataPart(part) {
|
|
30
|
+
return part.type === "metadata";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Convert a Cossistant TimelineItem to AI SDK UIMessage format
|
|
34
|
+
*
|
|
35
|
+
* @param item - The Cossistant TimelineItem to convert
|
|
36
|
+
* @returns AI SDK compatible UIMessage with Cossistant metadata
|
|
37
|
+
*/
|
|
38
|
+
function toUIMessage(item) {
|
|
39
|
+
return {
|
|
40
|
+
id: item.id ?? "",
|
|
41
|
+
role: getAISDKRole(item),
|
|
42
|
+
metadata: {
|
|
43
|
+
conversationId: item.conversationId,
|
|
44
|
+
organizationId: item.organizationId,
|
|
45
|
+
visibility: item.visibility,
|
|
46
|
+
userId: item.userId,
|
|
47
|
+
aiAgentId: item.aiAgentId,
|
|
48
|
+
visitorId: item.visitorId,
|
|
49
|
+
createdAt: item.createdAt,
|
|
50
|
+
deletedAt: item.deletedAt ?? null,
|
|
51
|
+
tool: item.tool ?? null
|
|
52
|
+
},
|
|
53
|
+
parts: item.parts.map(toAISDKPart).filter(Boolean)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Convert multiple TimelineItems to UIMessages
|
|
58
|
+
*/
|
|
59
|
+
function toUIMessages(items) {
|
|
60
|
+
return items.map(toUIMessage);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Determine AI SDK role from TimelineItem sender fields
|
|
64
|
+
*/
|
|
65
|
+
function getAISDKRole(item) {
|
|
66
|
+
if (item.aiAgentId) return "assistant";
|
|
67
|
+
return "user";
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Convert a Cossistant part to AI SDK part format
|
|
71
|
+
*/
|
|
72
|
+
function toAISDKPart(part) {
|
|
73
|
+
if (isTextPart(part)) return {
|
|
74
|
+
type: "text",
|
|
75
|
+
text: part.text,
|
|
76
|
+
state: part.state
|
|
77
|
+
};
|
|
78
|
+
if (isReasoningPart(part)) return {
|
|
79
|
+
type: "reasoning",
|
|
80
|
+
text: part.text,
|
|
81
|
+
state: part.state,
|
|
82
|
+
providerMetadata: part.providerMetadata
|
|
83
|
+
};
|
|
84
|
+
if (isSourceUrlPart(part)) return {
|
|
85
|
+
type: "source-url",
|
|
86
|
+
sourceId: part.sourceId,
|
|
87
|
+
url: part.url,
|
|
88
|
+
title: part.title,
|
|
89
|
+
providerMetadata: part.providerMetadata
|
|
90
|
+
};
|
|
91
|
+
if (isSourceDocumentPart(part)) return {
|
|
92
|
+
type: "source-document",
|
|
93
|
+
sourceId: part.sourceId,
|
|
94
|
+
mediaType: part.mediaType,
|
|
95
|
+
title: part.title,
|
|
96
|
+
filename: part.filename,
|
|
97
|
+
providerMetadata: part.providerMetadata
|
|
98
|
+
};
|
|
99
|
+
if (isStepStartPart(part)) return { type: "step-start" };
|
|
100
|
+
if (isFilePart(part)) {
|
|
101
|
+
const typedPart = part;
|
|
102
|
+
return {
|
|
103
|
+
type: "file",
|
|
104
|
+
url: part.url,
|
|
105
|
+
mediaType: part.mediaType,
|
|
106
|
+
filename: typedPart.filename ?? typedPart.fileName
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (isImagePart(part)) {
|
|
110
|
+
const typedPart = part;
|
|
111
|
+
return {
|
|
112
|
+
type: "file",
|
|
113
|
+
url: part.url,
|
|
114
|
+
mediaType: part.mediaType,
|
|
115
|
+
filename: typedPart.filename ?? typedPart.fileName
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (isToolPart(part)) return {
|
|
119
|
+
type: part.type,
|
|
120
|
+
toolCallId: part.toolCallId,
|
|
121
|
+
toolName: part.toolName,
|
|
122
|
+
input: part.input,
|
|
123
|
+
output: part.output,
|
|
124
|
+
state: part.state,
|
|
125
|
+
errorText: part.errorText,
|
|
126
|
+
providerMetadata: part.providerMetadata
|
|
127
|
+
};
|
|
128
|
+
if (isEventPart(part) || isMetadataPart(part)) return null;
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Convert an AI SDK UIMessage to Cossistant TimelineItem format
|
|
133
|
+
*
|
|
134
|
+
* @param message - The AI SDK UIMessage to convert
|
|
135
|
+
* @param context - Context for creating the TimelineItem
|
|
136
|
+
* @returns Cossistant TimelineItem
|
|
137
|
+
*/
|
|
138
|
+
function fromUIMessage(message, context) {
|
|
139
|
+
const metadata = message.metadata;
|
|
140
|
+
return {
|
|
141
|
+
id: message.id,
|
|
142
|
+
conversationId: metadata?.conversationId ?? context.conversationId,
|
|
143
|
+
organizationId: metadata?.organizationId ?? context.organizationId,
|
|
144
|
+
visibility: metadata?.visibility ?? context.visibility ?? "public",
|
|
145
|
+
type: "message",
|
|
146
|
+
text: extractTextFromParts(message.parts),
|
|
147
|
+
parts: message.parts.map(fromAISDKPart).filter(Boolean),
|
|
148
|
+
userId: metadata?.userId ?? context.userId ?? null,
|
|
149
|
+
aiAgentId: metadata?.aiAgentId ?? context.aiAgentId ?? null,
|
|
150
|
+
visitorId: metadata?.visitorId ?? context.visitorId ?? null,
|
|
151
|
+
createdAt: metadata?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
152
|
+
deletedAt: metadata?.deletedAt ?? null,
|
|
153
|
+
tool: metadata?.tool ?? null
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Convert multiple UIMessages to TimelineItems
|
|
158
|
+
*/
|
|
159
|
+
function fromUIMessages(messages, context) {
|
|
160
|
+
return messages.map((msg) => fromUIMessage(msg, context));
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Extract plain text content from message parts
|
|
164
|
+
*/
|
|
165
|
+
function extractTextFromParts(parts) {
|
|
166
|
+
const textParts = parts.filter((part) => typeof part === "object" && part !== null && "type" in part && part.type === "text");
|
|
167
|
+
if (textParts.length === 0) return null;
|
|
168
|
+
return textParts.map((p) => p.text).join("\n");
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Convert an AI SDK part to Cossistant part format
|
|
172
|
+
*/
|
|
173
|
+
function fromAISDKPart(part) {
|
|
174
|
+
if (typeof part !== "object" || part === null || !("type" in part)) return null;
|
|
175
|
+
const typedPart = part;
|
|
176
|
+
switch (typedPart.type) {
|
|
177
|
+
case "text": return {
|
|
178
|
+
type: "text",
|
|
179
|
+
text: String(typedPart.text ?? ""),
|
|
180
|
+
state: typedPart.state
|
|
181
|
+
};
|
|
182
|
+
case "reasoning": return {
|
|
183
|
+
type: "reasoning",
|
|
184
|
+
text: String(typedPart.text ?? ""),
|
|
185
|
+
state: typedPart.state,
|
|
186
|
+
providerMetadata: typedPart.providerMetadata
|
|
187
|
+
};
|
|
188
|
+
case "source-url": return {
|
|
189
|
+
type: "source-url",
|
|
190
|
+
sourceId: String(typedPart.sourceId ?? ""),
|
|
191
|
+
url: String(typedPart.url ?? ""),
|
|
192
|
+
title: typedPart.title,
|
|
193
|
+
providerMetadata: typedPart.providerMetadata
|
|
194
|
+
};
|
|
195
|
+
case "source-document": return {
|
|
196
|
+
type: "source-document",
|
|
197
|
+
sourceId: String(typedPart.sourceId ?? ""),
|
|
198
|
+
mediaType: String(typedPart.mediaType ?? ""),
|
|
199
|
+
title: String(typedPart.title ?? ""),
|
|
200
|
+
filename: typedPart.filename,
|
|
201
|
+
providerMetadata: typedPart.providerMetadata
|
|
202
|
+
};
|
|
203
|
+
case "step-start": return { type: "step-start" };
|
|
204
|
+
case "file": return {
|
|
205
|
+
type: "file",
|
|
206
|
+
url: String(typedPart.url ?? ""),
|
|
207
|
+
mediaType: String(typedPart.mediaType ?? ""),
|
|
208
|
+
filename: typedPart.filename
|
|
209
|
+
};
|
|
210
|
+
default:
|
|
211
|
+
if (typedPart.type.startsWith("tool-")) return {
|
|
212
|
+
type: typedPart.type,
|
|
213
|
+
toolCallId: String(typedPart.toolCallId ?? ""),
|
|
214
|
+
toolName: String(typedPart.toolName ?? ""),
|
|
215
|
+
input: typedPart.input ?? {},
|
|
216
|
+
output: typedPart.output,
|
|
217
|
+
state: typedPart.state ?? "partial",
|
|
218
|
+
errorText: typedPart.errorText,
|
|
219
|
+
providerMetadata: typedPart.providerMetadata
|
|
220
|
+
};
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Check if a part is an AI SDK compatible part type
|
|
226
|
+
*/
|
|
227
|
+
function isAISDKCompatiblePart(part) {
|
|
228
|
+
if (part.type === "event" || part.type === "metadata") return false;
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Extract all sources from a message's parts
|
|
233
|
+
*/
|
|
234
|
+
function extractSources(parts) {
|
|
235
|
+
return parts.filter((part) => part.type === "source-url" || part.type === "source-document");
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Extract all tool calls from a message's parts
|
|
239
|
+
*/
|
|
240
|
+
function extractToolCalls(parts) {
|
|
241
|
+
return parts.filter((part) => typeof part.type === "string" && part.type.startsWith("tool-"));
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Check if any parts are still processing
|
|
245
|
+
*/
|
|
246
|
+
function hasProcessingParts(parts) {
|
|
247
|
+
return parts.some((part) => {
|
|
248
|
+
if ("state" in part && (part.state === "streaming" || part.state === "partial")) return true;
|
|
249
|
+
return false;
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
//#endregion
|
|
254
|
+
export { extractSources, extractToolCalls, fromUIMessage, fromUIMessages, hasProcessingParts, isAISDKCompatiblePart, toUIMessage, toUIMessages };
|
|
255
|
+
//# sourceMappingURL=ai-sdk-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-sdk-utils.js","names":[],"sources":["../src/ai-sdk-utils.ts"],"sourcesContent":["/**\n * AI SDK v6 Conversion Utilities\n *\n * This module provides utilities for converting between Cossistant's\n * TimelineItem format and Vercel AI SDK v6's UIMessage format.\n *\n * Key concepts:\n * - Cossistant uses TimelineItem with userId/aiAgentId/visitorId\n * - AI SDK uses UIMessage with role: 'user' | 'assistant' | 'system'\n * - Both use a parts array for content\n * - Extensions go in metadata (message level) and providerMetadata (part level)\n */\n\nimport type { TimelineItem, TimelineItemParts } from \"@cossistant/types\";\n\n// ============================================================================\n// AI SDK TYPES (re-export for convenience)\n// ============================================================================\n\n/**\n * AI SDK UIMessage part types - these are the standard AI SDK v6 parts\n */\nexport type AISDKTextPart = {\n\ttype: \"text\";\n\ttext: string;\n\tstate?: \"streaming\" | \"done\";\n};\n\nexport type AISDKReasoningPart = {\n\ttype: \"reasoning\";\n\ttext: string;\n\tstate?: \"streaming\" | \"done\";\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKToolPart = {\n\ttype: `tool-${string}`;\n\ttoolCallId: string;\n\ttoolName: string;\n\tinput: Record<string, unknown>;\n\toutput?: unknown;\n\tstate: \"partial\" | \"result\" | \"error\";\n\terrorText?: string;\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKSourceUrlPart = {\n\ttype: \"source-url\";\n\tsourceId: string;\n\turl: string;\n\ttitle?: string;\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKSourceDocumentPart = {\n\ttype: \"source-document\";\n\tsourceId: string;\n\tmediaType: string;\n\ttitle: string;\n\tfilename?: string;\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKStepStartPart = {\n\ttype: \"step-start\";\n};\n\nexport type AISDKFilePart = {\n\ttype: \"file\";\n\turl: string;\n\tmediaType: string;\n\tfilename?: string;\n};\n\n// ============================================================================\n// COSSISTANT METADATA TYPES\n// ============================================================================\n\n/**\n * Cossistant-specific metadata stored in UIMessage.metadata\n */\nexport type CossistantMessageMetadata = {\n\tconversationId: string;\n\torganizationId: string;\n\tvisibility: \"public\" | \"private\";\n\tuserId: string | null;\n\taiAgentId: string | null;\n\tvisitorId: string | null;\n\treplyToId?: string | null;\n\tcreatedAt: string;\n\tdeletedAt?: string | null;\n\ttool?: string | null;\n};\n\n/**\n * Cossistant-specific metadata stored in part.providerMetadata.cossistant\n */\nexport type CossistantPartMetadata = {\n\tvisibility?: \"public\" | \"private\";\n\tprogressMessage?: string;\n\tknowledgeId?: string;\n};\n\n// ============================================================================\n// TYPE HELPERS\n// ============================================================================\n\nexport type AISDKPart =\n\t| AISDKTextPart\n\t| AISDKReasoningPart\n\t| AISDKToolPart\n\t| AISDKSourceUrlPart\n\t| AISDKSourceDocumentPart\n\t| AISDKStepStartPart\n\t| AISDKFilePart;\n\ntype CossistantPart = TimelineItemParts[number];\n\n// Type guards for Cossistant parts\nfunction isTextPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"text\"; text: string } {\n\treturn part.type === \"text\" && \"text\" in part;\n}\n\nfunction isReasoningPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"reasoning\"; text: string } {\n\treturn part.type === \"reasoning\" && \"text\" in part;\n}\n\nfunction isSourceUrlPart(part: CossistantPart): part is CossistantPart & {\n\ttype: \"source-url\";\n\tsourceId: string;\n\turl: string;\n} {\n\treturn part.type === \"source-url\" && \"sourceId\" in part && \"url\" in part;\n}\n\nfunction isSourceDocumentPart(part: CossistantPart): part is CossistantPart & {\n\ttype: \"source-document\";\n\tsourceId: string;\n\tmediaType: string;\n\ttitle: string;\n} {\n\treturn (\n\t\tpart.type === \"source-document\" &&\n\t\t\"sourceId\" in part &&\n\t\t\"mediaType\" in part &&\n\t\t\"title\" in part\n\t);\n}\n\nfunction isStepStartPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"step-start\" } {\n\treturn part.type === \"step-start\";\n}\n\nfunction isFilePart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"file\"; url: string; mediaType: string } {\n\treturn part.type === \"file\" && \"url\" in part && \"mediaType\" in part;\n}\n\nfunction isImagePart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"image\"; url: string; mediaType: string } {\n\treturn part.type === \"image\" && \"url\" in part && \"mediaType\" in part;\n}\n\nfunction isToolPart(part: CossistantPart): part is CossistantPart & {\n\ttype: string;\n\ttoolCallId: string;\n\ttoolName: string;\n\tinput: Record<string, unknown>;\n\tstate: \"partial\" | \"result\" | \"error\";\n} {\n\treturn (\n\t\ttypeof part.type === \"string\" &&\n\t\tpart.type.startsWith(\"tool-\") &&\n\t\t\"toolCallId\" in part &&\n\t\t\"toolName\" in part\n\t);\n}\n\nfunction isEventPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"event\" } {\n\treturn part.type === \"event\";\n}\n\nfunction isMetadataPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"metadata\" } {\n\treturn part.type === \"metadata\";\n}\n\n// ============================================================================\n// CONVERSION: TIMELINE ITEM -> UI MESSAGE\n// ============================================================================\n\n/**\n * Cossistant-compatible UIMessage type\n * This is structurally compatible with AI SDK v6 UIMessage\n * but uses our own part types for flexibility\n */\nexport type CossistantUIMessage = {\n\tid: string;\n\trole: \"user\" | \"assistant\" | \"system\";\n\tmetadata: CossistantMessageMetadata;\n\tparts: AISDKPart[];\n};\n\n/**\n * Convert a Cossistant TimelineItem to AI SDK UIMessage format\n *\n * @param item - The Cossistant TimelineItem to convert\n * @returns AI SDK compatible UIMessage with Cossistant metadata\n */\nexport function toUIMessage(item: TimelineItem): CossistantUIMessage {\n\treturn {\n\t\tid: item.id ?? \"\",\n\t\trole: getAISDKRole(item),\n\t\tmetadata: {\n\t\t\tconversationId: item.conversationId,\n\t\t\torganizationId: item.organizationId,\n\t\t\tvisibility: item.visibility,\n\t\t\tuserId: item.userId,\n\t\t\taiAgentId: item.aiAgentId,\n\t\t\tvisitorId: item.visitorId,\n\t\t\tcreatedAt: item.createdAt,\n\t\t\tdeletedAt: item.deletedAt ?? null,\n\t\t\ttool: item.tool ?? null,\n\t\t},\n\t\tparts: item.parts.map(toAISDKPart).filter(Boolean) as AISDKPart[],\n\t};\n}\n\n/**\n * Convert multiple TimelineItems to UIMessages\n */\nexport function toUIMessages(items: TimelineItem[]): CossistantUIMessage[] {\n\treturn items.map(toUIMessage);\n}\n\n/**\n * Determine AI SDK role from TimelineItem sender fields\n */\nfunction getAISDKRole(item: TimelineItem): \"user\" | \"assistant\" | \"system\" {\n\t// AI agent messages become assistant\n\tif (item.aiAgentId) {\n\t\treturn \"assistant\";\n\t}\n\n\t// Both visitor and human user messages become user\n\t// (AI SDK doesn't distinguish between these)\n\treturn \"user\";\n}\n\n/**\n * Convert a Cossistant part to AI SDK part format\n */\nfunction toAISDKPart(part: CossistantPart): AISDKPart | null {\n\tif (isTextPart(part)) {\n\t\treturn {\n\t\t\ttype: \"text\",\n\t\t\ttext: part.text,\n\t\t\tstate: (part as { state?: \"streaming\" | \"done\" }).state,\n\t\t};\n\t}\n\n\tif (isReasoningPart(part)) {\n\t\treturn {\n\t\t\ttype: \"reasoning\",\n\t\t\ttext: part.text,\n\t\t\tstate: (part as { state?: \"streaming\" | \"done\" }).state,\n\t\t\tproviderMetadata: (part as { providerMetadata?: Record<string, unknown> })\n\t\t\t\t.providerMetadata,\n\t\t};\n\t}\n\n\tif (isSourceUrlPart(part)) {\n\t\treturn {\n\t\t\ttype: \"source-url\",\n\t\t\tsourceId: part.sourceId,\n\t\t\turl: part.url,\n\t\t\ttitle: (part as { title?: string }).title,\n\t\t\tproviderMetadata: (part as { providerMetadata?: Record<string, unknown> })\n\t\t\t\t.providerMetadata,\n\t\t};\n\t}\n\n\tif (isSourceDocumentPart(part)) {\n\t\treturn {\n\t\t\ttype: \"source-document\",\n\t\t\tsourceId: part.sourceId,\n\t\t\tmediaType: part.mediaType,\n\t\t\ttitle: part.title,\n\t\t\tfilename: (part as { filename?: string }).filename,\n\t\t\tproviderMetadata: (part as { providerMetadata?: Record<string, unknown> })\n\t\t\t\t.providerMetadata,\n\t\t};\n\t}\n\n\tif (isStepStartPart(part)) {\n\t\treturn {\n\t\t\ttype: \"step-start\",\n\t\t};\n\t}\n\n\tif (isFilePart(part)) {\n\t\t// Support both 'filename' (new) and 'fileName' (legacy) for backward compatibility\n\t\tconst typedPart = part as { filename?: string; fileName?: string };\n\t\treturn {\n\t\t\ttype: \"file\",\n\t\t\turl: part.url,\n\t\t\tmediaType: part.mediaType,\n\t\t\tfilename: typedPart.filename ?? typedPart.fileName,\n\t\t};\n\t}\n\n\tif (isImagePart(part)) {\n\t\t// Convert image to file part (AI SDK uses file for all media)\n\t\t// Support both 'filename' (new) and 'fileName' (legacy) for backward compatibility\n\t\tconst typedPart = part as { filename?: string; fileName?: string };\n\t\treturn {\n\t\t\ttype: \"file\",\n\t\t\turl: part.url,\n\t\t\tmediaType: part.mediaType,\n\t\t\tfilename: typedPart.filename ?? typedPart.fileName,\n\t\t};\n\t}\n\n\tif (isToolPart(part)) {\n\t\treturn {\n\t\t\ttype: part.type as `tool-${string}`,\n\t\t\ttoolCallId: part.toolCallId,\n\t\t\ttoolName: part.toolName,\n\t\t\tinput: part.input,\n\t\t\toutput: (part as { output?: unknown }).output,\n\t\t\tstate: part.state,\n\t\t\terrorText: (part as { errorText?: string }).errorText,\n\t\t\tproviderMetadata: (part as { providerMetadata?: Record<string, unknown> })\n\t\t\t\t.providerMetadata,\n\t\t};\n\t}\n\n\t// Event and metadata parts are Cossistant-specific, skip for AI SDK\n\tif (isEventPart(part) || isMetadataPart(part)) {\n\t\treturn null;\n\t}\n\n\treturn null;\n}\n\n// ============================================================================\n// CONVERSION: UI MESSAGE -> TIMELINE ITEM\n// ============================================================================\n\n/**\n * Context required to create a TimelineItem from UIMessage\n */\nexport type FromUIMessageContext = {\n\tconversationId: string;\n\torganizationId: string;\n\taiAgentId?: string | null;\n\tuserId?: string | null;\n\tvisitorId?: string | null;\n\tvisibility?: \"public\" | \"private\";\n};\n\n/**\n * Convert an AI SDK UIMessage to Cossistant TimelineItem format\n *\n * @param message - The AI SDK UIMessage to convert\n * @param context - Context for creating the TimelineItem\n * @returns Cossistant TimelineItem\n */\nexport function fromUIMessage(\n\tmessage: CossistantUIMessage,\n\tcontext: FromUIMessageContext\n): TimelineItem {\n\t// Extract metadata if available\n\tconst metadata = message.metadata;\n\n\treturn {\n\t\tid: message.id,\n\t\tconversationId: metadata?.conversationId ?? context.conversationId,\n\t\torganizationId: metadata?.organizationId ?? context.organizationId,\n\t\tvisibility: metadata?.visibility ?? context.visibility ?? \"public\",\n\t\ttype: \"message\",\n\t\ttext: extractTextFromParts(message.parts),\n\t\tparts: message.parts\n\t\t\t.map(fromAISDKPart)\n\t\t\t.filter(Boolean) as TimelineItemParts,\n\t\tuserId: metadata?.userId ?? context.userId ?? null,\n\t\taiAgentId: metadata?.aiAgentId ?? context.aiAgentId ?? null,\n\t\tvisitorId: metadata?.visitorId ?? context.visitorId ?? null,\n\t\tcreatedAt: metadata?.createdAt ?? new Date().toISOString(),\n\t\tdeletedAt: metadata?.deletedAt ?? null,\n\t\ttool: metadata?.tool ?? null,\n\t};\n}\n\n/**\n * Convert multiple UIMessages to TimelineItems\n */\nexport function fromUIMessages(\n\tmessages: CossistantUIMessage[],\n\tcontext: FromUIMessageContext\n): TimelineItem[] {\n\treturn messages.map((msg) => fromUIMessage(msg, context));\n}\n\n/**\n * Extract plain text content from message parts\n */\nfunction extractTextFromParts(parts: unknown[]): string | null {\n\tconst textParts = parts.filter(\n\t\t(part): part is AISDKTextPart =>\n\t\t\ttypeof part === \"object\" &&\n\t\t\tpart !== null &&\n\t\t\t\"type\" in part &&\n\t\t\tpart.type === \"text\"\n\t);\n\n\tif (textParts.length === 0) {\n\t\treturn null;\n\t}\n\treturn textParts.map((p) => p.text).join(\"\\n\");\n}\n\n/**\n * Convert an AI SDK part to Cossistant part format\n */\nfunction fromAISDKPart(part: unknown): CossistantPart | null {\n\tif (typeof part !== \"object\" || part === null || !(\"type\" in part)) {\n\t\treturn null;\n\t}\n\n\tconst typedPart = part as { type: string; [key: string]: unknown };\n\n\tswitch (typedPart.type) {\n\t\tcase \"text\":\n\t\t\treturn {\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: String(typedPart.text ?? \"\"),\n\t\t\t\tstate: typedPart.state as \"streaming\" | \"done\" | undefined,\n\t\t\t};\n\n\t\tcase \"reasoning\":\n\t\t\treturn {\n\t\t\t\ttype: \"reasoning\",\n\t\t\t\ttext: String(typedPart.text ?? \"\"),\n\t\t\t\tstate: typedPart.state as \"streaming\" | \"done\" | undefined,\n\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined,\n\t\t\t};\n\n\t\tcase \"source-url\":\n\t\t\treturn {\n\t\t\t\ttype: \"source-url\",\n\t\t\t\tsourceId: String(typedPart.sourceId ?? \"\"),\n\t\t\t\turl: String(typedPart.url ?? \"\"),\n\t\t\t\ttitle: typedPart.title as string | undefined,\n\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined,\n\t\t\t};\n\n\t\tcase \"source-document\":\n\t\t\treturn {\n\t\t\t\ttype: \"source-document\",\n\t\t\t\tsourceId: String(typedPart.sourceId ?? \"\"),\n\t\t\t\tmediaType: String(typedPart.mediaType ?? \"\"),\n\t\t\t\ttitle: String(typedPart.title ?? \"\"),\n\t\t\t\tfilename: typedPart.filename as string | undefined,\n\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined,\n\t\t\t};\n\n\t\tcase \"step-start\":\n\t\t\treturn {\n\t\t\t\ttype: \"step-start\",\n\t\t\t};\n\n\t\tcase \"file\":\n\t\t\treturn {\n\t\t\t\ttype: \"file\",\n\t\t\t\turl: String(typedPart.url ?? \"\"),\n\t\t\t\tmediaType: String(typedPart.mediaType ?? \"\"),\n\t\t\t\tfilename: typedPart.filename as string | undefined,\n\t\t\t};\n\n\t\tdefault:\n\t\t\t// Handle tool-* pattern\n\t\t\tif (typedPart.type.startsWith(\"tool-\")) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: typedPart.type,\n\t\t\t\t\ttoolCallId: String(typedPart.toolCallId ?? \"\"),\n\t\t\t\t\ttoolName: String(typedPart.toolName ?? \"\"),\n\t\t\t\t\tinput: (typedPart.input as Record<string, unknown>) ?? {},\n\t\t\t\t\toutput: typedPart.output,\n\t\t\t\t\tstate:\n\t\t\t\t\t\t(typedPart.state as \"partial\" | \"result\" | \"error\") ?? \"partial\",\n\t\t\t\t\terrorText: typedPart.errorText as string | undefined,\n\t\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t\t| undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn null;\n\t}\n}\n\n// ============================================================================\n// HELPER UTILITIES\n// ============================================================================\n\n/**\n * Check if a part is an AI SDK compatible part type\n */\nexport function isAISDKCompatiblePart(part: CossistantPart): boolean {\n\tif (part.type === \"event\" || part.type === \"metadata\") {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Extract all sources from a message's parts\n */\nexport function extractSources(\n\tparts: AISDKPart[]\n): (AISDKSourceUrlPart | AISDKSourceDocumentPart)[] {\n\treturn parts.filter(\n\t\t(part): part is AISDKSourceUrlPart | AISDKSourceDocumentPart =>\n\t\t\tpart.type === \"source-url\" || part.type === \"source-document\"\n\t);\n}\n\n/**\n * Extract all tool calls from a message's parts\n */\nexport function extractToolCalls(parts: AISDKPart[]): AISDKToolPart[] {\n\treturn parts.filter(\n\t\t(part): part is AISDKToolPart =>\n\t\t\ttypeof part.type === \"string\" && part.type.startsWith(\"tool-\")\n\t);\n}\n\n/**\n * Check if any parts are still processing\n */\nexport function hasProcessingParts(parts: AISDKPart[]): boolean {\n\treturn parts.some((part) => {\n\t\tif (\n\t\t\t\"state\" in part &&\n\t\t\t(part.state === \"streaming\" || part.state === \"partial\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t});\n}\n"],"mappings":"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"}
|
package/client.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { CreateConversationRequestBody, CreateConversationResponseBody, GetConversationRequest, GetConversationResponse, ListConversationsRequest, ListConversationsResponse, MarkConversationSeenRequestBody, MarkConversationSeenResponseBody, SetConversationTypingResponseBody } from "./conversation.js";
|
|
2
|
-
import { GetConversationTimelineItemsRequest, GetConversationTimelineItemsResponse, SendTimelineItemRequest, SendTimelineItemResponse, TimelineItem } from "./timeline-item.js";
|
|
3
|
-
import { Conversation } from "./schemas.js";
|
|
1
|
+
import { CreateConversationRequestBody, CreateConversationResponseBody, GetConversationRequest, GetConversationResponse, ListConversationsRequest, ListConversationsResponse, MarkConversationSeenRequestBody, MarkConversationSeenResponseBody, SetConversationTypingResponseBody } from "./types/src/api/conversation.js";
|
|
2
|
+
import { GetConversationTimelineItemsRequest, GetConversationTimelineItemsResponse, SendTimelineItemRequest, SendTimelineItemResponse, TimelineItem as TimelineItem$1 } from "./types/src/api/timeline-item.js";
|
|
3
|
+
import { Conversation } from "./types/src/schemas.js";
|
|
4
4
|
import { types_d_exports } from "./types.js";
|
|
5
5
|
import { CossistantRestClient } from "./rest-client.js";
|
|
6
6
|
import { ConversationsStore } from "./store/conversations-store.js";
|
|
7
7
|
import { TimelineItemsStore } from "./store/timeline-items-store.js";
|
|
8
8
|
import { WebsiteStore } from "./store/website-store.js";
|
|
9
|
-
import { AnyRealtimeEvent, DefaultMessage, IdentifyContactResponse } from "@cossistant/types";
|
|
9
|
+
import { AnyRealtimeEvent, DefaultMessage, IdentifyContactResponse, RealtimeEvent } from "@cossistant/types";
|
|
10
10
|
|
|
11
11
|
//#region src/client.d.ts
|
|
12
12
|
type InitiateConversationParams = {
|
|
@@ -15,12 +15,12 @@ type InitiateConversationParams = {
|
|
|
15
15
|
websiteId?: string | null;
|
|
16
16
|
title?: string;
|
|
17
17
|
status?: Conversation["status"];
|
|
18
|
-
defaultTimelineItems?: Array<DefaultMessage | TimelineItem>;
|
|
18
|
+
defaultTimelineItems?: Array<DefaultMessage | TimelineItem$1>;
|
|
19
19
|
};
|
|
20
20
|
type InitiateConversationResult = {
|
|
21
21
|
conversationId: string;
|
|
22
22
|
conversation: Conversation;
|
|
23
|
-
defaultTimelineItems: TimelineItem[];
|
|
23
|
+
defaultTimelineItems: TimelineItem$1[];
|
|
24
24
|
};
|
|
25
25
|
declare class CossistantClient {
|
|
26
26
|
private restClient;
|
|
@@ -84,10 +84,20 @@ declare class CossistantClient {
|
|
|
84
84
|
createIfPending?: boolean;
|
|
85
85
|
}): Promise<SendTimelineItemResponse & {
|
|
86
86
|
conversation?: Conversation;
|
|
87
|
-
initialTimelineItems?: TimelineItem[];
|
|
87
|
+
initialTimelineItems?: TimelineItem$1[];
|
|
88
88
|
wasConversationCreated?: boolean;
|
|
89
89
|
}>;
|
|
90
90
|
handleRealtimeEvent(event: AnyRealtimeEvent): void;
|
|
91
|
+
/**
|
|
92
|
+
* Extract conversation status from an event timeline item.
|
|
93
|
+
* Returns the new status if this is a status-changing event, otherwise null.
|
|
94
|
+
*/
|
|
95
|
+
private extractStatusFromEventTimelineItem;
|
|
96
|
+
/**
|
|
97
|
+
* Handle conversationUpdated event from realtime
|
|
98
|
+
* Updates conversation with new title (sentiment and escalation are dashboard-only)
|
|
99
|
+
*/
|
|
100
|
+
handleConversationUpdated(event: RealtimeEvent<"conversationUpdated">): void;
|
|
91
101
|
/**
|
|
92
102
|
* Generate a presigned URL for uploading a file to S3.
|
|
93
103
|
*/
|
package/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;KA2DK,0BAAA;;EAAA,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAKK,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EACoB,KAAA,CAAA,EAAA,MAAA;EAAiB,MAAA,CAAA,EADrC,YACqC,CAAA,QAAA,CAAA;EAAvB,oBAAA,CAAA,EAAA,KAAA,CAAM,cAAN,GAAuB,
|
|
1
|
+
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":"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"}
|
package/client.js
CHANGED
|
@@ -143,7 +143,7 @@ var CossistantClient = class {
|
|
|
143
143
|
return response;
|
|
144
144
|
}
|
|
145
145
|
async sendMessage(params) {
|
|
146
|
-
const { createIfPending
|
|
146
|
+
const { createIfPending, ...rest } = params;
|
|
147
147
|
const optimisticId = rest.item.id ?? generateMessageId();
|
|
148
148
|
const createdAt = rest.item.createdAt ? rest.item.createdAt : typeof window !== "undefined" ? (/* @__PURE__ */ new Date()).toISOString() : "";
|
|
149
149
|
const optimisticTimelineItem = {
|
|
@@ -190,7 +190,7 @@ var CossistantClient = class {
|
|
|
190
190
|
this.timelineItemsStore.removeTimelineItem(rest.conversationId, optimisticId);
|
|
191
191
|
throw error;
|
|
192
192
|
}
|
|
193
|
-
const { createdAt: _createdAt
|
|
193
|
+
const { createdAt: _createdAt, ...restItem } = rest.item;
|
|
194
194
|
const payload = {
|
|
195
195
|
...rest,
|
|
196
196
|
item: {
|
|
@@ -218,16 +218,47 @@ var CossistantClient = class {
|
|
|
218
218
|
const timelineItem = this.timelineItemsStore.ingestRealtimeTimelineItem(event);
|
|
219
219
|
const existingConversation = this.conversationsStore.getState().byId[timelineItem.conversationId];
|
|
220
220
|
if (existingConversation) {
|
|
221
|
+
const newStatus = this.extractStatusFromEventTimelineItem(timelineItem);
|
|
221
222
|
const nextConversation = {
|
|
222
223
|
...existingConversation,
|
|
223
224
|
updatedAt: timelineItem.createdAt,
|
|
224
|
-
lastTimelineItem: timelineItem
|
|
225
|
+
lastTimelineItem: timelineItem,
|
|
226
|
+
...newStatus && { status: newStatus }
|
|
225
227
|
};
|
|
226
228
|
this.conversationsStore.ingestConversation(nextConversation);
|
|
227
229
|
}
|
|
228
230
|
}
|
|
229
231
|
}
|
|
230
232
|
/**
|
|
233
|
+
* Extract conversation status from an event timeline item.
|
|
234
|
+
* Returns the new status if this is a status-changing event, otherwise null.
|
|
235
|
+
*/
|
|
236
|
+
extractStatusFromEventTimelineItem(timelineItem) {
|
|
237
|
+
if (timelineItem.type !== ConversationTimelineType.EVENT) return null;
|
|
238
|
+
const eventPart = timelineItem.parts?.find((part) => typeof part === "object" && part !== null && "type" in part && part.type === "event");
|
|
239
|
+
if (!eventPart || typeof eventPart !== "object" || !("eventType" in eventPart)) return null;
|
|
240
|
+
switch (eventPart.eventType) {
|
|
241
|
+
case "resolved": return ConversationStatus.RESOLVED;
|
|
242
|
+
case "reopened": return ConversationStatus.OPEN;
|
|
243
|
+
default: return null;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Handle conversationUpdated event from realtime
|
|
248
|
+
* Updates conversation with new title (sentiment and escalation are dashboard-only)
|
|
249
|
+
*/
|
|
250
|
+
handleConversationUpdated(event) {
|
|
251
|
+
const { conversationId, updates } = event.payload;
|
|
252
|
+
const existingConversation = this.conversationsStore.getState().byId[conversationId];
|
|
253
|
+
if (!existingConversation) return;
|
|
254
|
+
const nextConversation = {
|
|
255
|
+
...existingConversation,
|
|
256
|
+
...updates.title !== void 0 && { title: updates.title ?? void 0 },
|
|
257
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
258
|
+
};
|
|
259
|
+
this.conversationsStore.ingestConversation(nextConversation);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
231
262
|
* Generate a presigned URL for uploading a file to S3.
|
|
232
263
|
*/
|
|
233
264
|
async generateUploadUrl(params) {
|