@portablecore/chat 0.1.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/dist/chat-interface-core.d.ts +27 -0
- package/dist/chat-interface-core.d.ts.map +1 -0
- package/dist/chat-interface-core.js +35 -0
- package/dist/chat-interface-core.js.map +1 -0
- package/dist/components/empty-state.d.ts +10 -0
- package/dist/components/empty-state.d.ts.map +1 -0
- package/dist/components/empty-state.js +16 -0
- package/dist/components/empty-state.js.map +1 -0
- package/dist/components/input-area.d.ts +26 -0
- package/dist/components/input-area.d.ts.map +1 -0
- package/dist/components/input-area.js +66 -0
- package/dist/components/input-area.js.map +1 -0
- package/dist/components/message-bubble.d.ts +20 -0
- package/dist/components/message-bubble.d.ts.map +1 -0
- package/dist/components/message-bubble.js +36 -0
- package/dist/components/message-bubble.js.map +1 -0
- package/dist/components/message-list.d.ts +23 -0
- package/dist/components/message-list.d.ts.map +1 -0
- package/dist/components/message-list.js +24 -0
- package/dist/components/message-list.js.map +1 -0
- package/dist/components/streaming-text.d.ts +14 -0
- package/dist/components/streaming-text.d.ts.map +1 -0
- package/dist/components/streaming-text.js +41 -0
- package/dist/components/streaming-text.js.map +1 -0
- package/dist/components/thinking-indicator.d.ts +18 -0
- package/dist/components/thinking-indicator.d.ts.map +1 -0
- package/dist/components/thinking-indicator.js +29 -0
- package/dist/components/thinking-indicator.js.map +1 -0
- package/dist/hooks/use-chat-scroll.d.ts +23 -0
- package/dist/hooks/use-chat-scroll.d.ts.map +1 -0
- package/dist/hooks/use-chat-scroll.js +66 -0
- package/dist/hooks/use-chat-scroll.js.map +1 -0
- package/dist/hooks/use-chat-session.d.ts +15 -0
- package/dist/hooks/use-chat-session.d.ts.map +1 -0
- package/dist/hooks/use-chat-session.js +224 -0
- package/dist/hooks/use-chat-session.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/markdown-config.d.ts +9 -0
- package/dist/utils/markdown-config.d.ts.map +1 -0
- package/dist/utils/markdown-config.js +21 -0
- package/dist/utils/markdown-config.js.map +1 -0
- package/dist/utils/message-grouping.d.ts +10 -0
- package/dist/utils/message-grouping.d.ts.map +1 -0
- package/dist/utils/message-grouping.js +36 -0
- package/dist/utils/message-grouping.js.map +1 -0
- package/dist/utils/time.d.ts +8 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +34 -0
- package/dist/utils/time.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.useChatSession = useChatSession;
|
|
5
|
+
/**
|
|
6
|
+
* useChatSession — Chat lifecycle hook driven by ChatInterfaceConfig.
|
|
7
|
+
*
|
|
8
|
+
* Composes lower-level primitives from @portablecore/chat-runtime:
|
|
9
|
+
* - parseSseStream for SSE parsing
|
|
10
|
+
* - useStreamingMessage for RAF-batched text accumulation
|
|
11
|
+
* - useSkillIndicators for thinking/skill indicator state
|
|
12
|
+
*
|
|
13
|
+
* Unlike useChatRuntime (which takes flat options), this hook is
|
|
14
|
+
* designed to work with the ChatInterfaceConfig extension point API,
|
|
15
|
+
* giving platforms full control over the request body via buildBody.
|
|
16
|
+
*/
|
|
17
|
+
const react_1 = require("react");
|
|
18
|
+
const chat_runtime_1 = require("@portablecore/chat-runtime");
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Hook
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
function useChatSession(config) {
|
|
23
|
+
const { chatId, expert, initialMessages, stream: streamConfig, handlers, } = config;
|
|
24
|
+
// ---- State ----
|
|
25
|
+
const [messages, setMessages] = (0, react_1.useState)(initialMessages || []);
|
|
26
|
+
const [streaming, setStreaming] = (0, react_1.useState)(false);
|
|
27
|
+
const [sending, setSending] = (0, react_1.useState)(false);
|
|
28
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
29
|
+
// Sync initialMessages when they change (e.g., page navigation)
|
|
30
|
+
const initialMessagesRef = (0, react_1.useRef)(initialMessages);
|
|
31
|
+
(0, react_1.useEffect)(() => {
|
|
32
|
+
if (initialMessages !== initialMessagesRef.current) {
|
|
33
|
+
initialMessagesRef.current = initialMessages;
|
|
34
|
+
setMessages(initialMessages || []);
|
|
35
|
+
}
|
|
36
|
+
}, [initialMessages]);
|
|
37
|
+
// ---- Streaming primitives ----
|
|
38
|
+
const { streamingMessageId, updateStreamingMessage, flushPendingContent, } = (0, chat_runtime_1.useStreamingMessage)(setMessages);
|
|
39
|
+
const { thinkingStages, activeSkill, handleEvent: handleIndicatorEvent, reset: resetIndicators, } = (0, chat_runtime_1.useSkillIndicators)([]);
|
|
40
|
+
// ---- Refs for stable callbacks ----
|
|
41
|
+
const abortRef = (0, react_1.useRef)(null);
|
|
42
|
+
const handlersRef = (0, react_1.useRef)(handlers);
|
|
43
|
+
(0, react_1.useEffect)(() => {
|
|
44
|
+
handlersRef.current = handlers;
|
|
45
|
+
}, [handlers]);
|
|
46
|
+
// ---- Stream response ----
|
|
47
|
+
const streamResponse = (0, react_1.useCallback)(async (userMessage) => {
|
|
48
|
+
setStreaming(true);
|
|
49
|
+
setError(null);
|
|
50
|
+
resetIndicators();
|
|
51
|
+
const tempId = `stream-${Date.now()}`;
|
|
52
|
+
streamingMessageId.current = tempId;
|
|
53
|
+
setMessages((prev) => [
|
|
54
|
+
...prev,
|
|
55
|
+
{
|
|
56
|
+
id: tempId,
|
|
57
|
+
role: "assistant",
|
|
58
|
+
content: "",
|
|
59
|
+
streaming: true,
|
|
60
|
+
createdAt: new Date().toISOString(),
|
|
61
|
+
},
|
|
62
|
+
]);
|
|
63
|
+
const controller = new AbortController();
|
|
64
|
+
abortRef.current = controller;
|
|
65
|
+
try {
|
|
66
|
+
const body = streamConfig.buildBody(userMessage, {
|
|
67
|
+
chatId,
|
|
68
|
+
expertId: expert?.id,
|
|
69
|
+
});
|
|
70
|
+
const headers = {
|
|
71
|
+
"Content-Type": "application/json",
|
|
72
|
+
...streamConfig.authHeaders?.(),
|
|
73
|
+
};
|
|
74
|
+
const response = await fetch(streamConfig.endpoint, {
|
|
75
|
+
method: "POST",
|
|
76
|
+
headers,
|
|
77
|
+
body: JSON.stringify(body),
|
|
78
|
+
signal: controller.signal,
|
|
79
|
+
});
|
|
80
|
+
if (!response.ok || !response.body) {
|
|
81
|
+
const errorText = "Something went wrong. Try again.";
|
|
82
|
+
setMessages((prev) => prev.map((m) => m.id === tempId
|
|
83
|
+
? { ...m, content: errorText, streaming: false }
|
|
84
|
+
: m));
|
|
85
|
+
setStreaming(false);
|
|
86
|
+
setError(errorText);
|
|
87
|
+
handlersRef.current?.onError?.(new Error(`HTTP ${response.status}`));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
for await (const event of (0, chat_runtime_1.parseSseStream)(response)) {
|
|
91
|
+
handlersRef.current?.onStreamEvent?.(event);
|
|
92
|
+
handleIndicatorEvent(event);
|
|
93
|
+
switch (event.type) {
|
|
94
|
+
case "text": {
|
|
95
|
+
updateStreamingMessage(event.text);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case "replace_content": {
|
|
99
|
+
flushPendingContent();
|
|
100
|
+
const target = streamingMessageId.current || tempId;
|
|
101
|
+
setMessages((prev) => prev.filter((m) => m.id !== target));
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case "first_response": {
|
|
105
|
+
flushPendingContent();
|
|
106
|
+
const frTarget = streamingMessageId.current || tempId;
|
|
107
|
+
setMessages((prev) => prev.map((m) => m.id === frTarget
|
|
108
|
+
? { ...m, content: m.content + "\n\n" }
|
|
109
|
+
: m));
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case "done": {
|
|
113
|
+
flushPendingContent();
|
|
114
|
+
const finalId = event.messageId;
|
|
115
|
+
const doneTarget = streamingMessageId.current || tempId;
|
|
116
|
+
setMessages((prev) => prev.map((m) => m.id === doneTarget
|
|
117
|
+
? {
|
|
118
|
+
...m,
|
|
119
|
+
id: finalId || doneTarget,
|
|
120
|
+
streaming: false,
|
|
121
|
+
}
|
|
122
|
+
: m));
|
|
123
|
+
const finalMessage = messages.find((m) => m.id === doneTarget) || { id: finalId || doneTarget, role: "assistant", content: "" };
|
|
124
|
+
handlersRef.current?.onMessageReceived?.(finalMessage);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
case "error": {
|
|
128
|
+
flushPendingContent();
|
|
129
|
+
const errTarget = streamingMessageId.current || tempId;
|
|
130
|
+
setMessages((prev) => prev.map((m) => m.id === errTarget
|
|
131
|
+
? {
|
|
132
|
+
...m,
|
|
133
|
+
content: m.content || event.error,
|
|
134
|
+
streaming: false,
|
|
135
|
+
}
|
|
136
|
+
: m));
|
|
137
|
+
setError(event.error);
|
|
138
|
+
handlersRef.current?.onError?.(new Error(event.error));
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Ensure no messages remain in streaming state
|
|
144
|
+
setMessages((prev) => prev.map((m) => (m.streaming ? { ...m, streaming: false } : m)));
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
if (err.name !== "AbortError") {
|
|
148
|
+
const errorMsg = "Connection lost. Try again.";
|
|
149
|
+
setMessages((prev) => prev.map((m) => m.id === tempId
|
|
150
|
+
? { ...m, content: errorMsg, streaming: false }
|
|
151
|
+
: m));
|
|
152
|
+
setError(errorMsg);
|
|
153
|
+
handlersRef.current?.onError?.(err);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
streamingMessageId.current = null;
|
|
158
|
+
setStreaming(false);
|
|
159
|
+
resetIndicators();
|
|
160
|
+
abortRef.current = null;
|
|
161
|
+
}
|
|
162
|
+
}, [
|
|
163
|
+
chatId,
|
|
164
|
+
expert?.id,
|
|
165
|
+
streamConfig,
|
|
166
|
+
messages,
|
|
167
|
+
streamingMessageId,
|
|
168
|
+
updateStreamingMessage,
|
|
169
|
+
flushPendingContent,
|
|
170
|
+
handleIndicatorEvent,
|
|
171
|
+
resetIndicators,
|
|
172
|
+
]);
|
|
173
|
+
// ---- Public API ----
|
|
174
|
+
const send = (0, react_1.useCallback)(async (content) => {
|
|
175
|
+
const trimmed = content.trim();
|
|
176
|
+
if (!trimmed || sending || streaming)
|
|
177
|
+
return;
|
|
178
|
+
setSending(true);
|
|
179
|
+
setError(null);
|
|
180
|
+
let processedContent = trimmed;
|
|
181
|
+
if (handlersRef.current?.onBeforeSend) {
|
|
182
|
+
processedContent = await handlersRef.current.onBeforeSend(trimmed);
|
|
183
|
+
}
|
|
184
|
+
const userTempId = `user-${Date.now()}`;
|
|
185
|
+
setMessages((prev) => [
|
|
186
|
+
...prev,
|
|
187
|
+
{
|
|
188
|
+
id: userTempId,
|
|
189
|
+
role: "user",
|
|
190
|
+
content: processedContent,
|
|
191
|
+
createdAt: new Date().toISOString(),
|
|
192
|
+
},
|
|
193
|
+
]);
|
|
194
|
+
setSending(false);
|
|
195
|
+
await streamResponse(processedContent);
|
|
196
|
+
}, [sending, streaming, streamResponse]);
|
|
197
|
+
const abort = (0, react_1.useCallback)(() => {
|
|
198
|
+
if (abortRef.current) {
|
|
199
|
+
abortRef.current.abort();
|
|
200
|
+
abortRef.current = null;
|
|
201
|
+
}
|
|
202
|
+
flushPendingContent();
|
|
203
|
+
setMessages((prev) => prev.map((m) => (m.streaming ? { ...m, streaming: false } : m)));
|
|
204
|
+
setStreaming(false);
|
|
205
|
+
resetIndicators();
|
|
206
|
+
}, [flushPendingContent, resetIndicators]);
|
|
207
|
+
const clear = (0, react_1.useCallback)(() => {
|
|
208
|
+
setMessages([]);
|
|
209
|
+
setError(null);
|
|
210
|
+
resetIndicators();
|
|
211
|
+
}, [resetIndicators]);
|
|
212
|
+
return {
|
|
213
|
+
messages,
|
|
214
|
+
streaming,
|
|
215
|
+
sending,
|
|
216
|
+
error,
|
|
217
|
+
thinkingStages,
|
|
218
|
+
activeSkill,
|
|
219
|
+
send,
|
|
220
|
+
abort,
|
|
221
|
+
clear,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=use-chat-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-chat-session.js","sourceRoot":"","sources":["../../src/hooks/use-chat-session.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @portablecore/chat
|
|
3
|
+
*
|
|
4
|
+
* Unified chat UI for Portable platforms.
|
|
5
|
+
* Composes @portablecore/chat-runtime with React components
|
|
6
|
+
* and the ChatInterfaceConfig extension point API.
|
|
7
|
+
*
|
|
8
|
+
* Both Expert and Team render the same ChatInterfaceCore.
|
|
9
|
+
* Platform-specific behavior is injected via config (features,
|
|
10
|
+
* slots, resolvers, handlers).
|
|
11
|
+
*/
|
|
12
|
+
export { ChatInterfaceCore } from "./chat-interface-core.js";
|
|
13
|
+
export { useChatSession } from "./hooks/use-chat-session.js";
|
|
14
|
+
export type { ChatSession } from "./hooks/use-chat-session.js";
|
|
15
|
+
export { useChatScroll } from "./hooks/use-chat-scroll.js";
|
|
16
|
+
export { MessageList } from "./components/message-list.js";
|
|
17
|
+
export { MessageBubble } from "./components/message-bubble.js";
|
|
18
|
+
export { InputArea } from "./components/input-area.js";
|
|
19
|
+
export { StreamingText } from "./components/streaming-text.js";
|
|
20
|
+
export { ThinkingIndicator } from "./components/thinking-indicator.js";
|
|
21
|
+
export type { ThinkingStage } from "./components/thinking-indicator.js";
|
|
22
|
+
export { EmptyState } from "./components/empty-state.js";
|
|
23
|
+
export { formatTime, getDateSeparator, isDifferentDay } from "./utils/time.js";
|
|
24
|
+
export { groupMessages } from "./utils/message-grouping.js";
|
|
25
|
+
export { remarkPlugins, rehypePlugins } from "./utils/markdown-config.js";
|
|
26
|
+
export type { ChatInterfaceConfig, ChatFeatureFlags, StreamBodyOpts, MentionSuggestion, SkillSuggestion, DocumentRef, LiteMessage, SseEvent, ChatSlots, RenderableMessage, } from "./types.js";
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAG5D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAG9D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAG1D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAA;AACtE,YAAY,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAA;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAGxD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAGzE,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,WAAW,EACX,QAAQ,EACR,SAAS,EACT,iBAAiB,GAClB,MAAM,YAAY,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @portablecore/chat
|
|
4
|
+
*
|
|
5
|
+
* Unified chat UI for Portable platforms.
|
|
6
|
+
* Composes @portablecore/chat-runtime with React components
|
|
7
|
+
* and the ChatInterfaceConfig extension point API.
|
|
8
|
+
*
|
|
9
|
+
* Both Expert and Team render the same ChatInterfaceCore.
|
|
10
|
+
* Platform-specific behavior is injected via config (features,
|
|
11
|
+
* slots, resolvers, handlers).
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.rehypePlugins = exports.remarkPlugins = exports.groupMessages = exports.isDifferentDay = exports.getDateSeparator = exports.formatTime = exports.EmptyState = exports.ThinkingIndicator = exports.StreamingText = exports.InputArea = exports.MessageBubble = exports.MessageList = exports.useChatScroll = exports.useChatSession = exports.ChatInterfaceCore = void 0;
|
|
15
|
+
// The main product
|
|
16
|
+
var chat_interface_core_js_1 = require("./chat-interface-core.js");
|
|
17
|
+
Object.defineProperty(exports, "ChatInterfaceCore", { enumerable: true, get: function () { return chat_interface_core_js_1.ChatInterfaceCore; } });
|
|
18
|
+
// Session hook (for platforms that need direct access to chat state)
|
|
19
|
+
var use_chat_session_js_1 = require("./hooks/use-chat-session.js");
|
|
20
|
+
Object.defineProperty(exports, "useChatSession", { enumerable: true, get: function () { return use_chat_session_js_1.useChatSession; } });
|
|
21
|
+
// Scroll management
|
|
22
|
+
var use_chat_scroll_js_1 = require("./hooks/use-chat-scroll.js");
|
|
23
|
+
Object.defineProperty(exports, "useChatScroll", { enumerable: true, get: function () { return use_chat_scroll_js_1.useChatScroll; } });
|
|
24
|
+
// UI components (for platforms that want to compose their own layout)
|
|
25
|
+
var message_list_js_1 = require("./components/message-list.js");
|
|
26
|
+
Object.defineProperty(exports, "MessageList", { enumerable: true, get: function () { return message_list_js_1.MessageList; } });
|
|
27
|
+
var message_bubble_js_1 = require("./components/message-bubble.js");
|
|
28
|
+
Object.defineProperty(exports, "MessageBubble", { enumerable: true, get: function () { return message_bubble_js_1.MessageBubble; } });
|
|
29
|
+
var input_area_js_1 = require("./components/input-area.js");
|
|
30
|
+
Object.defineProperty(exports, "InputArea", { enumerable: true, get: function () { return input_area_js_1.InputArea; } });
|
|
31
|
+
var streaming_text_js_1 = require("./components/streaming-text.js");
|
|
32
|
+
Object.defineProperty(exports, "StreamingText", { enumerable: true, get: function () { return streaming_text_js_1.StreamingText; } });
|
|
33
|
+
var thinking_indicator_js_1 = require("./components/thinking-indicator.js");
|
|
34
|
+
Object.defineProperty(exports, "ThinkingIndicator", { enumerable: true, get: function () { return thinking_indicator_js_1.ThinkingIndicator; } });
|
|
35
|
+
var empty_state_js_1 = require("./components/empty-state.js");
|
|
36
|
+
Object.defineProperty(exports, "EmptyState", { enumerable: true, get: function () { return empty_state_js_1.EmptyState; } });
|
|
37
|
+
// Utilities
|
|
38
|
+
var time_js_1 = require("./utils/time.js");
|
|
39
|
+
Object.defineProperty(exports, "formatTime", { enumerable: true, get: function () { return time_js_1.formatTime; } });
|
|
40
|
+
Object.defineProperty(exports, "getDateSeparator", { enumerable: true, get: function () { return time_js_1.getDateSeparator; } });
|
|
41
|
+
Object.defineProperty(exports, "isDifferentDay", { enumerable: true, get: function () { return time_js_1.isDifferentDay; } });
|
|
42
|
+
var message_grouping_js_1 = require("./utils/message-grouping.js");
|
|
43
|
+
Object.defineProperty(exports, "groupMessages", { enumerable: true, get: function () { return message_grouping_js_1.groupMessages; } });
|
|
44
|
+
var markdown_config_js_1 = require("./utils/markdown-config.js");
|
|
45
|
+
Object.defineProperty(exports, "remarkPlugins", { enumerable: true, get: function () { return markdown_config_js_1.remarkPlugins; } });
|
|
46
|
+
Object.defineProperty(exports, "rehypePlugins", { enumerable: true, get: function () { return markdown_config_js_1.rehypePlugins; } });
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAEH,mBAAmB;AACnB,mEAA4D;AAAnD,2HAAA,iBAAiB,OAAA;AAE1B,qEAAqE;AACrE,mEAA4D;AAAnD,qHAAA,cAAc,OAAA;AAGvB,oBAAoB;AACpB,iEAA0D;AAAjD,mHAAA,aAAa,OAAA;AAEtB,sEAAsE;AACtE,gEAA0D;AAAjD,8GAAA,WAAW,OAAA;AACpB,oEAA8D;AAArD,kHAAA,aAAa,OAAA;AACtB,4DAAsD;AAA7C,0GAAA,SAAS,OAAA;AAClB,oEAA8D;AAArD,kHAAA,aAAa,OAAA;AACtB,4EAAsE;AAA7D,0HAAA,iBAAiB,OAAA;AAE1B,8DAAwD;AAA/C,4GAAA,UAAU,OAAA;AAEnB,YAAY;AACZ,2CAA8E;AAArE,qGAAA,UAAU,OAAA;AAAE,2GAAA,gBAAgB,OAAA;AAAE,yGAAA,cAAc,OAAA;AACrD,mEAA2D;AAAlD,oHAAA,aAAa,OAAA;AACtB,iEAAyE;AAAhE,mHAAA,aAAa,OAAA;AAAE,mHAAA,aAAa,OAAA"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal prop types for @portablecore/chat components.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the public ChatInterfaceConfig from @portablecore/types
|
|
5
|
+
* and adds component-level prop interfaces.
|
|
6
|
+
*/
|
|
7
|
+
import type { ReactNode } from "react";
|
|
8
|
+
import type { LiteMessage } from "@portablecore/types/chat";
|
|
9
|
+
export type { ChatInterfaceConfig, ChatFeatureFlags, StreamBodyOpts, MentionSuggestion, SkillSuggestion, DocumentRef, } from "@portablecore/types/chat";
|
|
10
|
+
export type { LiteMessage, SseEvent } from "@portablecore/types/chat";
|
|
11
|
+
/**
|
|
12
|
+
* Slots narrowed to ReactNode for use inside React components.
|
|
13
|
+
* The types package uses `unknown` to avoid a React dependency.
|
|
14
|
+
*/
|
|
15
|
+
export interface ChatSlots {
|
|
16
|
+
beforeMessageList?: ReactNode;
|
|
17
|
+
afterMessageList?: ReactNode;
|
|
18
|
+
inputPrefix?: ReactNode;
|
|
19
|
+
inputSuffix?: ReactNode;
|
|
20
|
+
sidePanel?: ReactNode;
|
|
21
|
+
emptyState?: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A message ready for rendering, with grouping metadata attached.
|
|
25
|
+
*/
|
|
26
|
+
export interface RenderableMessage {
|
|
27
|
+
message: LiteMessage;
|
|
28
|
+
isFirstInGroup: boolean;
|
|
29
|
+
isLastInGroup: boolean;
|
|
30
|
+
showDateSeparator: boolean;
|
|
31
|
+
dateSeparatorLabel?: string;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAG3D,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,WAAW,GACZ,MAAM,0BAA0B,CAAA;AAEjC,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAErE;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,iBAAiB,CAAC,EAAE,SAAS,CAAA;IAC7B,gBAAgB,CAAC,EAAE,SAAS,CAAA;IAC5B,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,UAAU,CAAC,EAAE,SAAS,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,WAAW,CAAA;IACpB,cAAc,EAAE,OAAO,CAAA;IACvB,aAAa,EAAE,OAAO,CAAA;IACtB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Internal prop types for @portablecore/chat components.
|
|
4
|
+
*
|
|
5
|
+
* Re-exports the public ChatInterfaceConfig from @portablecore/types
|
|
6
|
+
* and adds component-level prop interfaces.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared markdown plugin configuration for chat messages.
|
|
3
|
+
*
|
|
4
|
+
* Both StreamingText (post-stream render) and MessageBubble
|
|
5
|
+
* use the same plugin set for consistent rendering.
|
|
6
|
+
*/
|
|
7
|
+
export declare const remarkPlugins: any[];
|
|
8
|
+
export declare const rehypePlugins: any[];
|
|
9
|
+
//# sourceMappingURL=markdown-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-config.d.ts","sourceRoot":"","sources":["../../src/utils/markdown-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,eAAO,MAAM,aAAa,EAAE,GAAG,EAA8B,CAAA;AAG7D,eAAO,MAAM,aAAa,EAAE,GAAG,EAAiC,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared markdown plugin configuration for chat messages.
|
|
4
|
+
*
|
|
5
|
+
* Both StreamingText (post-stream render) and MessageBubble
|
|
6
|
+
* use the same plugin set for consistent rendering.
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.rehypePlugins = exports.remarkPlugins = void 0;
|
|
13
|
+
const remark_gfm_1 = __importDefault(require("remark-gfm"));
|
|
14
|
+
const remark_breaks_1 = __importDefault(require("remark-breaks"));
|
|
15
|
+
const rehype_raw_1 = __importDefault(require("rehype-raw"));
|
|
16
|
+
const rehype_highlight_1 = __importDefault(require("rehype-highlight"));
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
exports.remarkPlugins = [remark_gfm_1.default, remark_breaks_1.default];
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
exports.rehypePlugins = [rehype_raw_1.default, rehype_highlight_1.default];
|
|
21
|
+
//# sourceMappingURL=markdown-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-config.js","sourceRoot":"","sources":["../../src/utils/markdown-config.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;AAEH,4DAAkC;AAClC,kEAAwC;AACxC,4DAAkC;AAClC,wEAA8C;AAE9C,8DAA8D;AACjD,QAAA,aAAa,GAAU,CAAC,oBAAS,EAAE,uBAAY,CAAC,CAAA;AAE7D,8DAA8D;AACjD,QAAA,aAAa,GAAU,CAAC,oBAAS,EAAE,0BAAe,CAAC,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Group consecutive messages from the same sender for visual clustering.
|
|
3
|
+
*
|
|
4
|
+
* Produces RenderableMessage[] with grouping metadata so MessageList
|
|
5
|
+
* can render date separators and tighten spacing within groups.
|
|
6
|
+
*/
|
|
7
|
+
import type { LiteMessage } from "@portablecore/types/chat";
|
|
8
|
+
import type { RenderableMessage } from "../types.js";
|
|
9
|
+
export declare function groupMessages(messages: LiteMessage[]): RenderableMessage[];
|
|
10
|
+
//# sourceMappingURL=message-grouping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-grouping.d.ts","sourceRoot":"","sources":["../../src/utils/message-grouping.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGpD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,iBAAiB,EAAE,CA+B1E"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Group consecutive messages from the same sender for visual clustering.
|
|
4
|
+
*
|
|
5
|
+
* Produces RenderableMessage[] with grouping metadata so MessageList
|
|
6
|
+
* can render date separators and tighten spacing within groups.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.groupMessages = groupMessages;
|
|
10
|
+
const time_js_1 = require("./time.js");
|
|
11
|
+
function groupMessages(messages) {
|
|
12
|
+
return messages.map((message, index) => {
|
|
13
|
+
const prev = messages[index - 1];
|
|
14
|
+
const next = messages[index + 1];
|
|
15
|
+
const prevRole = prev?.role;
|
|
16
|
+
const nextRole = next?.role;
|
|
17
|
+
const currRole = message.role;
|
|
18
|
+
const isFirstInGroup = currRole !== prevRole;
|
|
19
|
+
const isLastInGroup = currRole !== nextRole;
|
|
20
|
+
const showDateSeparator = index === 0 ||
|
|
21
|
+
(prev?.createdAt != null &&
|
|
22
|
+
message.createdAt != null &&
|
|
23
|
+
(0, time_js_1.isDifferentDay)(prev.createdAt, message.createdAt));
|
|
24
|
+
const dateSeparatorLabel = showDateSeparator && message.createdAt
|
|
25
|
+
? (0, time_js_1.getDateSeparator)(message.createdAt)
|
|
26
|
+
: undefined;
|
|
27
|
+
return {
|
|
28
|
+
message,
|
|
29
|
+
isFirstInGroup,
|
|
30
|
+
isLastInGroup,
|
|
31
|
+
showDateSeparator,
|
|
32
|
+
dateSeparatorLabel,
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=message-grouping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-grouping.js","sourceRoot":"","sources":["../../src/utils/message-grouping.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAMH,sCA+BC;AAjCD,uCAA4D;AAE5D,SAAgB,aAAa,CAAC,QAAuB;IACnD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;QAChC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;QAEhC,MAAM,QAAQ,GAAG,IAAI,EAAE,IAAI,CAAA;QAC3B,MAAM,QAAQ,GAAG,IAAI,EAAE,IAAI,CAAA;QAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAA;QAE7B,MAAM,cAAc,GAAG,QAAQ,KAAK,QAAQ,CAAA;QAC5C,MAAM,aAAa,GAAG,QAAQ,KAAK,QAAQ,CAAA;QAE3C,MAAM,iBAAiB,GACrB,KAAK,KAAK,CAAC;YACX,CAAC,IAAI,EAAE,SAAS,IAAI,IAAI;gBACtB,OAAO,CAAC,SAAS,IAAI,IAAI;gBACzB,IAAA,wBAAc,EAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAA;QAEtD,MAAM,kBAAkB,GACtB,iBAAiB,IAAI,OAAO,CAAC,SAAS;YACpC,CAAC,CAAC,IAAA,0BAAgB,EAAC,OAAO,CAAC,SAAS,CAAC;YACrC,CAAC,CAAC,SAAS,CAAA;QAEf,OAAO;YACL,OAAO;YACP,cAAc;YACd,aAAa;YACb,iBAAiB;YACjB,kBAAkB;SACnB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time formatting utilities for chat messages.
|
|
3
|
+
* Extracted from Expert's ChatMessage component.
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatTime(dateString: string): string;
|
|
6
|
+
export declare function getDateSeparator(dateString: string): string;
|
|
7
|
+
export declare function isDifferentDay(date1: string, date2: string): boolean;
|
|
8
|
+
//# sourceMappingURL=time.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/utils/time.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAiB3D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Time formatting utilities for chat messages.
|
|
4
|
+
* Extracted from Expert's ChatMessage component.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.formatTime = formatTime;
|
|
8
|
+
exports.getDateSeparator = getDateSeparator;
|
|
9
|
+
exports.isDifferentDay = isDifferentDay;
|
|
10
|
+
function formatTime(dateString) {
|
|
11
|
+
const date = new Date(dateString);
|
|
12
|
+
return date.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" });
|
|
13
|
+
}
|
|
14
|
+
function getDateSeparator(dateString) {
|
|
15
|
+
const date = new Date(dateString);
|
|
16
|
+
const today = new Date();
|
|
17
|
+
const yesterday = new Date(today);
|
|
18
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
19
|
+
const isToday = date.toDateString() === today.toDateString();
|
|
20
|
+
const isYesterday = date.toDateString() === yesterday.toDateString();
|
|
21
|
+
if (isToday)
|
|
22
|
+
return "Today";
|
|
23
|
+
if (isYesterday)
|
|
24
|
+
return "Yesterday";
|
|
25
|
+
return date.toLocaleDateString([], {
|
|
26
|
+
weekday: "long",
|
|
27
|
+
month: "short",
|
|
28
|
+
day: "numeric",
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function isDifferentDay(date1, date2) {
|
|
32
|
+
return new Date(date1).toDateString() !== new Date(date2).toDateString();
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=time.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/utils/time.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAEH,gCAGC;AAED,4CAiBC;AAED,wCAEC;AA1BD,SAAgB,UAAU,CAAC,UAAkB;IAC3C,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAA;IACjC,OAAO,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAA;AAC5E,CAAC;AAED,SAAgB,gBAAgB,CAAC,UAAkB;IACjD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAA;IACjC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAA;IACxB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAA;IACjC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAA;IAE1C,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,KAAK,KAAK,CAAC,YAAY,EAAE,CAAA;IAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,KAAK,SAAS,CAAC,YAAY,EAAE,CAAA;IAEpE,IAAI,OAAO;QAAE,OAAO,OAAO,CAAA;IAC3B,IAAI,WAAW;QAAE,OAAO,WAAW,CAAA;IAEnC,OAAO,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE;QACjC,OAAO,EAAE,MAAM;QACf,KAAK,EAAE,OAAO;QACd,GAAG,EAAE,SAAS;KACf,CAAC,CAAA;AACJ,CAAC;AAED,SAAgB,cAAc,CAAC,KAAa,EAAE,KAAa;IACzD,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,EAAE,CAAA;AAC1E,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@portablecore/chat",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Unified chat UI for Portable platforms — composable ChatInterface with extension points",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"keywords": [
|
|
17
|
+
"portable",
|
|
18
|
+
"chat",
|
|
19
|
+
"ui",
|
|
20
|
+
"streaming",
|
|
21
|
+
"sse"
|
|
22
|
+
],
|
|
23
|
+
"author": "Portable",
|
|
24
|
+
"license": "UNLICENSED",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"remark-gfm": "^4.0.1",
|
|
27
|
+
"remark-breaks": "^4.0.0",
|
|
28
|
+
"rehype-raw": "^7.0.0",
|
|
29
|
+
"rehype-highlight": "^7.0.2",
|
|
30
|
+
"@portablecore/types": "0.10.0",
|
|
31
|
+
"@portablecore/chat-runtime": "0.1.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"react": ">=18.0.0",
|
|
35
|
+
"react-markdown": ">=9.0.0",
|
|
36
|
+
"@nvq/flowtoken": ">=2.0.0",
|
|
37
|
+
"lucide-react": ">=0.300.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"typescript": "^5.3.0",
|
|
41
|
+
"@types/react": "^18.0.0",
|
|
42
|
+
"react": "^18.0.0",
|
|
43
|
+
"react-markdown": "^10.1.0",
|
|
44
|
+
"@nvq/flowtoken": "^2.0.6",
|
|
45
|
+
"lucide-react": "^0.562.0"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsc",
|
|
49
|
+
"dev": "tsc --watch",
|
|
50
|
+
"clean": "rm -rf dist",
|
|
51
|
+
"typecheck": "tsc --noEmit"
|
|
52
|
+
}
|
|
53
|
+
}
|