@gendive/chatllm 0.4.0 → 0.5.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.
@@ -57,6 +57,14 @@ interface AlternativeResponse {
57
57
  model: string;
58
58
  content: string;
59
59
  timestamp: number;
60
+ sources?: SourceItem[];
61
+ }
62
+ interface SourceItem {
63
+ id: string;
64
+ title: string;
65
+ url: string;
66
+ snippet?: string;
67
+ favicon?: string;
60
68
  }
61
69
  interface ChatMessage {
62
70
  id: string;
@@ -65,6 +73,7 @@ interface ChatMessage {
65
73
  model?: string;
66
74
  timestamp: number;
67
75
  alternatives?: AlternativeResponse[];
76
+ sources?: SourceItem[];
68
77
  }
69
78
  interface ChatSession {
70
79
  id: string;
@@ -139,7 +148,7 @@ interface ChatUIProps {
139
148
  /** CSS 클래스 */
140
149
  className?: string;
141
150
  /** 메시지 전송 핸들러 (커스텀 API 사용 시) */
142
- onSendMessage?: (params: SendMessageParams) => Promise<ReadableStream<Uint8Array> | string>;
151
+ onSendMessage?: (params: SendMessageParams) => Promise<SendMessageResponse>;
143
152
  /** 세션 변경 핸들러 */
144
153
  onSessionChange?: (session: ChatSession | null) => void;
145
154
  /** 에러 핸들러 */
@@ -155,6 +164,11 @@ interface SendMessageParams {
155
164
  apiKey?: string;
156
165
  systemPrompt?: string;
157
166
  }
167
+ /** onSendMessage 반환 타입 */
168
+ type SendMessageResponse = ReadableStream<Uint8Array> | string | {
169
+ content: string;
170
+ sources?: SourceItem[];
171
+ };
158
172
  interface ChatUIComponents {
159
173
  /** 사이드바 컴포넌트 */
160
174
  Sidebar?: React.ComponentType<SidebarProps>;
@@ -322,7 +336,7 @@ interface UseChatUIOptions {
322
336
  /** 압축 후 유지할 메시지 수 */
323
337
  keepRecentMessages?: number;
324
338
  /** 커스텀 메시지 전송 핸들러 */
325
- onSendMessage?: (params: SendMessageParams) => Promise<ReadableStream<Uint8Array> | string>;
339
+ onSendMessage?: (params: SendMessageParams) => Promise<SendMessageResponse>;
326
340
  /** 세션 변경 핸들러 */
327
341
  onSessionChange?: (session: ChatSession | null) => void;
328
342
  /** 에러 핸들러 */
@@ -493,4 +507,4 @@ interface SettingsModalProps {
493
507
  }
494
508
  declare const SettingsModal: React$1.FC<SettingsModalProps>;
495
509
 
496
- export { type ActionItem, type ActionMenuProps, type AlternativeResponse, ChatHeader, ChatInput, type ChatMessage, type ChatSession, ChatSidebar, ChatUI, type ChatUIComponents, type ChatUIProps, EmptyState, type EmptyStateProps, type HeaderProps, Icon, type IconName, type IconProps, IconSvg, type InputProps, LinkChip, type LinkChipProps, MarkdownRenderer, type MarkdownRendererProps, type MemoryItem, MemoryPanel, type MemoryPanelProps, MessageBubble, type MessageBubbleProps, MessageList, type MessageListProps, type ModelConfig, type ModelSelectorProps, type PersonalizationConfig, type PromptTemplate, type ProviderType, type ResponseStyle, type SendMessageParams, SettingsModal, type SettingsModalProps, type SettingsTab, type SidebarProps, type ThemeConfig, type ThemeMode, type UseChatUIOptions, type UseChatUIReturn, type UserProfile, useChatUI };
510
+ export { type ActionItem, type ActionMenuProps, type AlternativeResponse, ChatHeader, ChatInput, type ChatMessage, type ChatSession, ChatSidebar, ChatUI, type ChatUIComponents, type ChatUIProps, EmptyState, type EmptyStateProps, type HeaderProps, Icon, type IconName, type IconProps, IconSvg, type InputProps, LinkChip, type LinkChipProps, MarkdownRenderer, type MarkdownRendererProps, type MemoryItem, MemoryPanel, type MemoryPanelProps, MessageBubble, type MessageBubbleProps, MessageList, type MessageListProps, type ModelConfig, type ModelSelectorProps, type PersonalizationConfig, type PromptTemplate, type ProviderType, type ResponseStyle, type SendMessageParams, type SendMessageResponse, SettingsModal, type SettingsModalProps, type SettingsTab, type SidebarProps, type SourceItem, type ThemeConfig, type ThemeMode, type UseChatUIOptions, type UseChatUIReturn, type UserProfile, useChatUI };
@@ -57,6 +57,14 @@ interface AlternativeResponse {
57
57
  model: string;
58
58
  content: string;
59
59
  timestamp: number;
60
+ sources?: SourceItem[];
61
+ }
62
+ interface SourceItem {
63
+ id: string;
64
+ title: string;
65
+ url: string;
66
+ snippet?: string;
67
+ favicon?: string;
60
68
  }
61
69
  interface ChatMessage {
62
70
  id: string;
@@ -65,6 +73,7 @@ interface ChatMessage {
65
73
  model?: string;
66
74
  timestamp: number;
67
75
  alternatives?: AlternativeResponse[];
76
+ sources?: SourceItem[];
68
77
  }
69
78
  interface ChatSession {
70
79
  id: string;
@@ -139,7 +148,7 @@ interface ChatUIProps {
139
148
  /** CSS 클래스 */
140
149
  className?: string;
141
150
  /** 메시지 전송 핸들러 (커스텀 API 사용 시) */
142
- onSendMessage?: (params: SendMessageParams) => Promise<ReadableStream<Uint8Array> | string>;
151
+ onSendMessage?: (params: SendMessageParams) => Promise<SendMessageResponse>;
143
152
  /** 세션 변경 핸들러 */
144
153
  onSessionChange?: (session: ChatSession | null) => void;
145
154
  /** 에러 핸들러 */
@@ -155,6 +164,11 @@ interface SendMessageParams {
155
164
  apiKey?: string;
156
165
  systemPrompt?: string;
157
166
  }
167
+ /** onSendMessage 반환 타입 */
168
+ type SendMessageResponse = ReadableStream<Uint8Array> | string | {
169
+ content: string;
170
+ sources?: SourceItem[];
171
+ };
158
172
  interface ChatUIComponents {
159
173
  /** 사이드바 컴포넌트 */
160
174
  Sidebar?: React.ComponentType<SidebarProps>;
@@ -322,7 +336,7 @@ interface UseChatUIOptions {
322
336
  /** 압축 후 유지할 메시지 수 */
323
337
  keepRecentMessages?: number;
324
338
  /** 커스텀 메시지 전송 핸들러 */
325
- onSendMessage?: (params: SendMessageParams) => Promise<ReadableStream<Uint8Array> | string>;
339
+ onSendMessage?: (params: SendMessageParams) => Promise<SendMessageResponse>;
326
340
  /** 세션 변경 핸들러 */
327
341
  onSessionChange?: (session: ChatSession | null) => void;
328
342
  /** 에러 핸들러 */
@@ -493,4 +507,4 @@ interface SettingsModalProps {
493
507
  }
494
508
  declare const SettingsModal: React$1.FC<SettingsModalProps>;
495
509
 
496
- export { type ActionItem, type ActionMenuProps, type AlternativeResponse, ChatHeader, ChatInput, type ChatMessage, type ChatSession, ChatSidebar, ChatUI, type ChatUIComponents, type ChatUIProps, EmptyState, type EmptyStateProps, type HeaderProps, Icon, type IconName, type IconProps, IconSvg, type InputProps, LinkChip, type LinkChipProps, MarkdownRenderer, type MarkdownRendererProps, type MemoryItem, MemoryPanel, type MemoryPanelProps, MessageBubble, type MessageBubbleProps, MessageList, type MessageListProps, type ModelConfig, type ModelSelectorProps, type PersonalizationConfig, type PromptTemplate, type ProviderType, type ResponseStyle, type SendMessageParams, SettingsModal, type SettingsModalProps, type SettingsTab, type SidebarProps, type ThemeConfig, type ThemeMode, type UseChatUIOptions, type UseChatUIReturn, type UserProfile, useChatUI };
510
+ export { type ActionItem, type ActionMenuProps, type AlternativeResponse, ChatHeader, ChatInput, type ChatMessage, type ChatSession, ChatSidebar, ChatUI, type ChatUIComponents, type ChatUIProps, EmptyState, type EmptyStateProps, type HeaderProps, Icon, type IconName, type IconProps, IconSvg, type InputProps, LinkChip, type LinkChipProps, MarkdownRenderer, type MarkdownRendererProps, type MemoryItem, MemoryPanel, type MemoryPanelProps, MessageBubble, type MessageBubbleProps, MessageList, type MessageListProps, type ModelConfig, type ModelSelectorProps, type PersonalizationConfig, type PromptTemplate, type ProviderType, type ResponseStyle, type SendMessageParams, type SendMessageResponse, SettingsModal, type SettingsModalProps, type SettingsTab, type SidebarProps, type SourceItem, type ThemeConfig, type ThemeMode, type UseChatUIOptions, type UseChatUIReturn, type UserProfile, useChatUI };
@@ -408,6 +408,22 @@ ${contextSummary}` },
408
408
  );
409
409
  return;
410
410
  }
411
+ if (typeof result === "object" && "content" in result) {
412
+ setSessions(
413
+ (prev) => prev.map((s) => {
414
+ if (s.id === capturedSessionId) {
415
+ return {
416
+ ...s,
417
+ messages: s.messages.map(
418
+ (m) => m.id === assistantMessageId ? { ...m, content: result.content, sources: result.sources } : m
419
+ )
420
+ };
421
+ }
422
+ return s;
423
+ })
424
+ );
425
+ return;
426
+ }
411
427
  response = new Response(result);
412
428
  } else {
413
429
  response = await fetch(apiEndpoint, {
@@ -567,6 +583,7 @@ ${currentSession.contextSummary}` },
567
583
  const modelConfig = models.find((m) => m.id === targetModel);
568
584
  const provider = modelConfig?.provider || "ollama";
569
585
  let responseContent = "";
586
+ let responseSources;
570
587
  if (onSendMessage) {
571
588
  const result = await onSendMessage({
572
589
  messages: messagesForApi,
@@ -577,6 +594,9 @@ ${currentSession.contextSummary}` },
577
594
  });
578
595
  if (typeof result === "string") {
579
596
  responseContent = result;
597
+ } else if (typeof result === "object" && "content" in result) {
598
+ responseContent = result.content;
599
+ responseSources = result.sources;
580
600
  } else {
581
601
  const reader = result.getReader();
582
602
  const decoder = new TextDecoder();
@@ -640,7 +660,8 @@ ${currentSession.contextSummary}` },
640
660
  id: generateId("alt"),
641
661
  model: targetModel,
642
662
  content: responseContent,
643
- timestamp: Date.now()
663
+ timestamp: Date.now(),
664
+ sources: responseSources
644
665
  };
645
666
  const capturedSessionId = currentSessionId;
646
667
  setSessions(
@@ -2195,6 +2216,7 @@ var MessageBubble = ({
2195
2216
  const otherModels = models?.filter((m) => m.id !== message.model) || [];
2196
2217
  const displayContent = alternatives && alternatives.length > 0 && activeAlternativeIndex > 0 ? alternatives[activeAlternativeIndex - 1]?.content || message.content : message.content;
2197
2218
  const displayModel = alternatives && alternatives.length > 0 && activeAlternativeIndex > 0 ? alternatives[activeAlternativeIndex - 1]?.model : message.model;
2219
+ const displaySources = alternatives && alternatives.length > 0 && activeAlternativeIndex > 0 ? alternatives[activeAlternativeIndex - 1]?.sources : message.sources;
2198
2220
  const handleMouseUp = () => {
2199
2221
  if (!onQuote) return;
2200
2222
  const selection = window.getSelection();
@@ -2319,6 +2341,43 @@ var MessageBubble = ({
2319
2341
  ]
2320
2342
  }
2321
2343
  ),
2344
+ displaySources && displaySources.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2345
+ "div",
2346
+ {
2347
+ style: {
2348
+ display: "flex",
2349
+ flexWrap: "wrap",
2350
+ gap: "8px",
2351
+ marginTop: "12px",
2352
+ paddingTop: "12px",
2353
+ borderTop: "1px solid var(--chatllm-border-light, #f3f4f6)"
2354
+ },
2355
+ children: [
2356
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2357
+ "span",
2358
+ {
2359
+ style: {
2360
+ fontSize: "12px",
2361
+ fontWeight: 500,
2362
+ color: "var(--chatllm-text-muted, #9ca3af)",
2363
+ marginRight: "4px"
2364
+ },
2365
+ children: "\uCD9C\uCC98:"
2366
+ }
2367
+ ),
2368
+ displaySources.map((source, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2369
+ LinkChip,
2370
+ {
2371
+ text: source.title,
2372
+ url: source.url,
2373
+ index: index + 1,
2374
+ showFavicon: true
2375
+ },
2376
+ source.id
2377
+ ))
2378
+ ]
2379
+ }
2380
+ ),
2322
2381
  alternatives && alternatives.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2323
2382
  "div",
2324
2383
  {