@yushaw/sanqian-chat 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -0
- package/dist/core/index.d.mts +180 -6
- package/dist/core/index.d.ts +180 -6
- package/dist/core/index.js +548 -64
- package/dist/core/index.mjs +534 -63
- package/dist/main/index.d.mts +320 -5
- package/dist/main/index.d.ts +320 -5
- package/dist/main/index.js +466 -39
- package/dist/main/index.mjs +454 -38
- package/dist/preload/index.d.ts +88 -0
- package/dist/preload/index.js +5 -1
- package/dist/renderer/index.d.mts +609 -18
- package/dist/renderer/index.d.ts +609 -18
- package/dist/renderer/index.js +7870 -537
- package/dist/renderer/index.mjs +7854 -538
- package/package.json +16 -4
- package/src/renderer/styles/baseStyles.ts +74 -0
- package/src/renderer/styles/chat.css +3674 -0
- package/src/renderer/styles/chatCss.ts +11 -0
- package/src/renderer/styles/coreCss.ts +3237 -0
- package/src/renderer/styles/preflightCss.ts +454 -0
- package/src/renderer/styles/safe.css +3227 -0
- package/src/renderer/styles/safeCss.ts +10 -0
- package/src/renderer/styles/tailwind.css +683 -0
- package/src/renderer/styles/variables.css +704 -0
package/dist/renderer/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { HitlInterruptPayload, HitlResponse, SanqianSDK } from '@yushaw/sanqian-sdk';
|
|
2
|
-
export {
|
|
2
|
+
export { HitlInterruptPayload, HitlInterruptType, HitlResponse, HitlRiskLevel, ChatMessage as SdkChatMessage, ConversationDetail as SdkConversationDetail, ConversationInfo as SdkConversationInfo, ToolCall as SdkToolCall } from '@yushaw/sanqian-sdk';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import * as react from 'react';
|
|
5
|
-
import { ReactNode } from 'react';
|
|
5
|
+
import { ReactNode, RefObject, CSSProperties } from 'react';
|
|
6
|
+
export { ChatMessage, ChatStreamEvent, SDKConfig, SanqianSDK, ToolDefinition } from '@yushaw/sanqian-sdk/browser';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @yushaw/sanqian-chat Core Types
|
|
@@ -10,16 +11,80 @@ import { ReactNode } from 'react';
|
|
|
10
11
|
* Re-exports SDK types + chat-specific types
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
|
-
type
|
|
14
|
+
type Locale = 'en' | 'zh';
|
|
15
|
+
interface ChatUiStrings {
|
|
16
|
+
inputPlaceholder: string;
|
|
17
|
+
inputSend: string;
|
|
18
|
+
inputStop: string;
|
|
19
|
+
chat: string;
|
|
20
|
+
recentChats: string;
|
|
21
|
+
newChat: string;
|
|
22
|
+
selectConversation: string;
|
|
23
|
+
noHistory: string;
|
|
24
|
+
loadMore: string;
|
|
25
|
+
today: string;
|
|
26
|
+
yesterday: string;
|
|
27
|
+
delete: string;
|
|
28
|
+
dismiss: string;
|
|
29
|
+
close: string;
|
|
30
|
+
pin: string;
|
|
31
|
+
unpin: string;
|
|
32
|
+
conversationUntitled: string;
|
|
33
|
+
conversationDeleteConfirm: string;
|
|
34
|
+
messageThinking: string;
|
|
35
|
+
messageError: string;
|
|
36
|
+
messageLoading: string;
|
|
37
|
+
connectionConnecting: string;
|
|
38
|
+
connectionConnected: string;
|
|
39
|
+
connectionDisconnected: string;
|
|
40
|
+
connectionReconnecting: string;
|
|
41
|
+
connectionError: string;
|
|
42
|
+
steps: string;
|
|
43
|
+
executing: string;
|
|
44
|
+
thinking: string;
|
|
45
|
+
thinkingStreaming: string;
|
|
46
|
+
thinkingPaused: string;
|
|
47
|
+
hitlApprove: string;
|
|
48
|
+
hitlReject: string;
|
|
49
|
+
hitlSubmit: string;
|
|
50
|
+
hitlCancel: string;
|
|
51
|
+
hitlRememberChoice: string;
|
|
52
|
+
hitlRequiredField: string;
|
|
53
|
+
hitlTimeoutIn: string;
|
|
54
|
+
hitlSeconds: string;
|
|
55
|
+
hitlExecuteTool: string;
|
|
56
|
+
hitlToolLabel: string;
|
|
57
|
+
hitlArgsLabel: string;
|
|
58
|
+
hitlDefaultPrefix: string;
|
|
59
|
+
hitlEnterResponse: string;
|
|
60
|
+
hitlApprovalRequest: string;
|
|
61
|
+
hitlInputRequest: string;
|
|
62
|
+
hitlApprovalRequired: string;
|
|
63
|
+
hitlInputRequired: string;
|
|
64
|
+
}
|
|
65
|
+
type ChatThemeMode = 'light' | 'dark' | 'auto';
|
|
66
|
+
type ChatFontSize = 'small' | 'normal' | 'large' | 'extra-large';
|
|
67
|
+
interface ChatUiConfigSerializable {
|
|
68
|
+
logo?: string;
|
|
69
|
+
theme?: ChatThemeMode;
|
|
70
|
+
/** Font size scale: small (13px), normal (14px), large (16px), extra-large (18px) */
|
|
71
|
+
fontSize?: ChatFontSize;
|
|
72
|
+
accentColor?: string;
|
|
73
|
+
locale?: Locale;
|
|
74
|
+
strings?: Partial<ChatUiStrings>;
|
|
75
|
+
alwaysOnTop?: boolean;
|
|
76
|
+
}
|
|
77
|
+
type MessageRole = 'user' | 'assistant' | 'system' | 'tool';
|
|
14
78
|
type ToolCallStatus = 'pending' | 'running' | 'completed' | 'error' | 'cancelled';
|
|
15
79
|
type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error';
|
|
16
80
|
type ConnectionErrorCode = 'NOT_FOUND' | 'CONNECTION_FAILED' | 'WEBSOCKET_ERROR' | 'AUTH_ERROR' | 'TIMEOUT' | 'UNKNOWN';
|
|
17
81
|
/** Tool call for UI rendering (extended from SDK) */
|
|
18
82
|
interface ToolCall {
|
|
19
|
-
id
|
|
83
|
+
id?: string;
|
|
20
84
|
name: string;
|
|
21
|
-
|
|
22
|
-
|
|
85
|
+
args?: Record<string, unknown>;
|
|
86
|
+
argsRaw?: string;
|
|
87
|
+
status?: ToolCallStatus;
|
|
23
88
|
result?: unknown;
|
|
24
89
|
error?: string;
|
|
25
90
|
}
|
|
@@ -30,9 +95,11 @@ interface MessageBlock {
|
|
|
30
95
|
timestamp: number;
|
|
31
96
|
toolName?: string;
|
|
32
97
|
toolArgs?: Record<string, unknown>;
|
|
98
|
+
toolArgsRaw?: string;
|
|
33
99
|
toolCallId?: string;
|
|
34
100
|
toolStatus?: ToolCallStatus;
|
|
35
101
|
isIntermediate?: boolean;
|
|
102
|
+
fromSubagent?: boolean;
|
|
36
103
|
}
|
|
37
104
|
/** Chat message for UI rendering */
|
|
38
105
|
interface ChatMessage {
|
|
@@ -45,8 +112,12 @@ interface ChatMessage {
|
|
|
45
112
|
thinking?: string;
|
|
46
113
|
currentThinking?: string;
|
|
47
114
|
isThinkingStreaming?: boolean;
|
|
115
|
+
isThinkingPaused?: boolean;
|
|
116
|
+
isToolCallsStreaming?: boolean;
|
|
48
117
|
blocks?: MessageBlock[];
|
|
118
|
+
finalContent?: string;
|
|
49
119
|
isComplete?: boolean;
|
|
120
|
+
filePaths?: string[];
|
|
50
121
|
}
|
|
51
122
|
/** Conversation info for UI */
|
|
52
123
|
interface ConversationInfo {
|
|
@@ -55,6 +126,7 @@ interface ConversationInfo {
|
|
|
55
126
|
createdAt: string;
|
|
56
127
|
updatedAt: string;
|
|
57
128
|
messageCount: number;
|
|
129
|
+
agentId?: string | null;
|
|
58
130
|
}
|
|
59
131
|
interface ConversationDetail extends ConversationInfo {
|
|
60
132
|
messages: ChatMessage[];
|
|
@@ -70,9 +142,21 @@ interface FloatingWindowConfig {
|
|
|
70
142
|
position?: WindowPosition;
|
|
71
143
|
width?: number;
|
|
72
144
|
height?: number;
|
|
145
|
+
/** Minimum window width (default: 320) */
|
|
146
|
+
minWidth?: number;
|
|
147
|
+
/** Minimum window height (default: 420) */
|
|
148
|
+
minHeight?: number;
|
|
73
149
|
alwaysOnTop?: boolean;
|
|
74
150
|
showInTaskbar?: boolean;
|
|
75
151
|
theme?: 'light' | 'dark' | 'system';
|
|
152
|
+
/** Optional UI config for renderer (serializable) */
|
|
153
|
+
uiConfig?: ChatUiConfigSerializable;
|
|
154
|
+
/** Persist size/position across sessions (stored under ~/.sanqian-chat) */
|
|
155
|
+
rememberWindowState?: boolean;
|
|
156
|
+
/** Optional storage key to avoid conflicts between apps */
|
|
157
|
+
windowStateKey?: string;
|
|
158
|
+
/** Optional full path for window state file */
|
|
159
|
+
windowStatePath?: string;
|
|
76
160
|
}
|
|
77
161
|
|
|
78
162
|
/**
|
|
@@ -84,6 +168,10 @@ interface FloatingWindowConfig {
|
|
|
84
168
|
|
|
85
169
|
/** Stream event callback */
|
|
86
170
|
type StreamEvent = {
|
|
171
|
+
type: 'start';
|
|
172
|
+
run_id: string;
|
|
173
|
+
conversationId?: string;
|
|
174
|
+
} | {
|
|
87
175
|
type: 'text';
|
|
88
176
|
content: string;
|
|
89
177
|
} | {
|
|
@@ -98,6 +186,16 @@ type StreamEvent = {
|
|
|
98
186
|
arguments: string;
|
|
99
187
|
};
|
|
100
188
|
};
|
|
189
|
+
} | {
|
|
190
|
+
type: 'tool_args_chunk';
|
|
191
|
+
tool_call_id: string;
|
|
192
|
+
tool_name?: string;
|
|
193
|
+
chunk: string;
|
|
194
|
+
} | {
|
|
195
|
+
type: 'tool_args';
|
|
196
|
+
tool_call_id: string;
|
|
197
|
+
tool_name?: string;
|
|
198
|
+
args: Record<string, unknown>;
|
|
101
199
|
} | {
|
|
102
200
|
type: 'tool_result';
|
|
103
201
|
tool_call_id: string;
|
|
@@ -114,6 +212,9 @@ type StreamEvent = {
|
|
|
114
212
|
interrupt_type: string;
|
|
115
213
|
interrupt_payload: HitlInterruptData;
|
|
116
214
|
run_id?: string;
|
|
215
|
+
} | {
|
|
216
|
+
type: 'cancelled';
|
|
217
|
+
run_id?: string;
|
|
117
218
|
};
|
|
118
219
|
/** Message to send */
|
|
119
220
|
interface SendMessage {
|
|
@@ -138,7 +239,9 @@ interface ChatAdapter {
|
|
|
138
239
|
messageLimit?: number;
|
|
139
240
|
}): Promise<ConversationDetail>;
|
|
140
241
|
deleteConversation(id: string): Promise<void>;
|
|
141
|
-
chatStream(messages: SendMessage[], conversationId: string | undefined, onEvent: (event: StreamEvent) => void
|
|
242
|
+
chatStream(messages: SendMessage[], conversationId: string | undefined, onEvent: (event: StreamEvent) => void, options?: {
|
|
243
|
+
agentId?: string | null;
|
|
244
|
+
}): Promise<{
|
|
142
245
|
cancel: () => void;
|
|
143
246
|
}>;
|
|
144
247
|
sendHitlResponse?(response: HitlResponse, runId?: string): void;
|
|
@@ -151,8 +254,47 @@ interface SdkAdapterConfig {
|
|
|
151
254
|
/** Agent ID getter */
|
|
152
255
|
getAgentId: () => string | null;
|
|
153
256
|
}
|
|
257
|
+
/** Simple chat adapter config (no SDK knowledge required) */
|
|
258
|
+
interface ChatAdapterConfig {
|
|
259
|
+
/** App name for registration */
|
|
260
|
+
appName: string;
|
|
261
|
+
/** App version */
|
|
262
|
+
appVersion: string;
|
|
263
|
+
/** Agent ID to chat with */
|
|
264
|
+
agentId: string;
|
|
265
|
+
/** Whether to persist conversation history (default: false) */
|
|
266
|
+
persistHistory?: boolean;
|
|
267
|
+
/** Tools to expose to the agent */
|
|
268
|
+
tools?: Array<{
|
|
269
|
+
name: string;
|
|
270
|
+
description: string;
|
|
271
|
+
parameters?: Record<string, unknown>;
|
|
272
|
+
handler?: (args: Record<string, unknown>) => Promise<unknown>;
|
|
273
|
+
}>;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Create a chat adapter with simple config (recommended for most use cases)
|
|
277
|
+
*
|
|
278
|
+
* This is the easiest way to integrate with Sanqian. Just provide your app info
|
|
279
|
+
* and agent ID, and the adapter handles SDK lifecycle automatically.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```typescript
|
|
283
|
+
* const adapter = createChatAdapter({
|
|
284
|
+
* appName: 'my-app',
|
|
285
|
+
* appVersion: '1.0.0',
|
|
286
|
+
* agentId: 'assistant',
|
|
287
|
+
* });
|
|
288
|
+
*
|
|
289
|
+
* <CompactChat adapter={adapter} />
|
|
290
|
+
* ```
|
|
291
|
+
*/
|
|
292
|
+
declare function createChatAdapter(config: ChatAdapterConfig): ChatAdapter;
|
|
154
293
|
/**
|
|
155
294
|
* Create adapter that wraps @yushaw/sanqian-sdk
|
|
295
|
+
*
|
|
296
|
+
* Use this when you need more control over the SDK instance.
|
|
297
|
+
* For simpler usage, prefer `createChatAdapter()`.
|
|
156
298
|
*/
|
|
157
299
|
declare function createSdkAdapter(config: SdkAdapterConfig): ChatAdapter;
|
|
158
300
|
|
|
@@ -209,7 +351,12 @@ declare function useTheme(): ThemeContextValue;
|
|
|
209
351
|
*/
|
|
210
352
|
declare function useStandaloneTheme(defaultTheme?: ThemeMode): ThemeContextValue;
|
|
211
353
|
|
|
212
|
-
|
|
354
|
+
interface ChatUiConfig extends Omit<ChatUiConfigSerializable, 'logo'> {
|
|
355
|
+
logo?: string | ReactNode;
|
|
356
|
+
onClose?: () => void;
|
|
357
|
+
onPin?: (pinned: boolean) => void;
|
|
358
|
+
}
|
|
359
|
+
|
|
213
360
|
interface Translations {
|
|
214
361
|
hitl: {
|
|
215
362
|
approvalRequired: string;
|
|
@@ -268,6 +415,107 @@ declare function useStandaloneI18n(defaultLocale?: Locale): I18nContextValue;
|
|
|
268
415
|
*/
|
|
269
416
|
declare function getTranslations(locale: Locale): Translations;
|
|
270
417
|
|
|
418
|
+
/**
|
|
419
|
+
* useConnection Hook
|
|
420
|
+
*
|
|
421
|
+
* Manages connection state with the backend.
|
|
422
|
+
*/
|
|
423
|
+
|
|
424
|
+
interface UseConnectionOptions {
|
|
425
|
+
/** Chat adapter */
|
|
426
|
+
adapter: ChatAdapter;
|
|
427
|
+
/** Auto-connect on mount */
|
|
428
|
+
autoConnect?: boolean;
|
|
429
|
+
/** Called when connection status changes */
|
|
430
|
+
onStatusChange?: (status: ConnectionStatus, error?: string, errorCode?: ConnectionErrorCode) => void;
|
|
431
|
+
}
|
|
432
|
+
interface UseConnectionReturn {
|
|
433
|
+
/** Current connection status */
|
|
434
|
+
status: ConnectionStatus;
|
|
435
|
+
/** Connection error message (if any) */
|
|
436
|
+
error: string | undefined;
|
|
437
|
+
/** Connection error code (if any) */
|
|
438
|
+
errorCode: ConnectionErrorCode | undefined;
|
|
439
|
+
/** Whether currently connected */
|
|
440
|
+
isConnected: boolean;
|
|
441
|
+
/** Whether currently connecting/reconnecting */
|
|
442
|
+
isConnecting: boolean;
|
|
443
|
+
/** Connect to the backend */
|
|
444
|
+
connect: () => Promise<void>;
|
|
445
|
+
/** Disconnect from the backend */
|
|
446
|
+
disconnect: () => Promise<void>;
|
|
447
|
+
}
|
|
448
|
+
declare function useConnection(options: UseConnectionOptions): UseConnectionReturn;
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* useConversations Hook
|
|
452
|
+
*
|
|
453
|
+
* Manages conversation history list with loading and delete operations.
|
|
454
|
+
*/
|
|
455
|
+
|
|
456
|
+
interface UseConversationsOptions {
|
|
457
|
+
/** Chat adapter for backend communication */
|
|
458
|
+
adapter: ChatAdapter;
|
|
459
|
+
/** Number of conversations per page */
|
|
460
|
+
pageSize?: number;
|
|
461
|
+
/** Called when an error occurs */
|
|
462
|
+
onError?: (error: Error) => void;
|
|
463
|
+
}
|
|
464
|
+
interface UseConversationsReturn {
|
|
465
|
+
conversations: ConversationInfo[];
|
|
466
|
+
isLoading: boolean;
|
|
467
|
+
hasMore: boolean;
|
|
468
|
+
total: number;
|
|
469
|
+
error: string | null;
|
|
470
|
+
/** Whether last loadMore failed (for retry button) */
|
|
471
|
+
loadError: boolean;
|
|
472
|
+
loadConversations: () => Promise<void>;
|
|
473
|
+
loadMore: () => Promise<void>;
|
|
474
|
+
deleteConversation: (id: string) => Promise<void>;
|
|
475
|
+
refresh: () => Promise<void>;
|
|
476
|
+
}
|
|
477
|
+
declare function useConversations(options: UseConversationsOptions): UseConversationsReturn;
|
|
478
|
+
|
|
479
|
+
declare function useChatStyles(): void;
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* useFocusPersistence Hook
|
|
483
|
+
*
|
|
484
|
+
* Restores focus to input when clicking empty areas in the chat container.
|
|
485
|
+
* Inspired by Slack's forceFocus pattern - always keep input ready for typing.
|
|
486
|
+
*/
|
|
487
|
+
|
|
488
|
+
interface UseFocusPersistenceOptions {
|
|
489
|
+
/** Container element ref */
|
|
490
|
+
containerRef: RefObject<HTMLElement | null>;
|
|
491
|
+
/** Input element ref (must have focus method) */
|
|
492
|
+
inputRef: RefObject<{
|
|
493
|
+
focus: () => void;
|
|
494
|
+
} | null>;
|
|
495
|
+
/** Skip focus restoration when this is true (e.g., HITL dialog open, history view) */
|
|
496
|
+
disabled?: boolean;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Hook that restores focus to input when clicking empty areas.
|
|
500
|
+
*
|
|
501
|
+
* @example
|
|
502
|
+
* ```tsx
|
|
503
|
+
* const containerRef = useRef<HTMLDivElement>(null);
|
|
504
|
+
* const inputRef = useRef<ChatInputHandle>(null);
|
|
505
|
+
*
|
|
506
|
+
* useFocusPersistence({
|
|
507
|
+
* containerRef,
|
|
508
|
+
* inputRef,
|
|
509
|
+
* disabled: !!pendingInterrupt || showHistory,
|
|
510
|
+
* });
|
|
511
|
+
* ```
|
|
512
|
+
*/
|
|
513
|
+
declare function useFocusPersistence({ containerRef, inputRef, disabled, }: UseFocusPersistenceOptions): void;
|
|
514
|
+
|
|
515
|
+
declare function useIpcUiConfig(): ChatUiConfigSerializable | null;
|
|
516
|
+
|
|
517
|
+
declare function useResolvedUiConfig(config?: ChatUiConfig): ChatUiConfig | undefined;
|
|
518
|
+
|
|
271
519
|
/**
|
|
272
520
|
* IPC Adapter
|
|
273
521
|
*
|
|
@@ -296,6 +544,41 @@ interface MessageBubbleProps {
|
|
|
296
544
|
}
|
|
297
545
|
declare const MessageBubble: react.NamedExoticComponent<MessageBubbleProps>;
|
|
298
546
|
|
|
547
|
+
interface SanqianChatProps {
|
|
548
|
+
adapter: ChatAdapter;
|
|
549
|
+
placeholder?: string;
|
|
550
|
+
autoConnect?: boolean;
|
|
551
|
+
className?: string;
|
|
552
|
+
emptyState?: ReactNode;
|
|
553
|
+
onError?: (error: Error) => void;
|
|
554
|
+
onConversationChange?: (conversationId: string, title?: string) => void;
|
|
555
|
+
onStateChange?: (state: {
|
|
556
|
+
messages: ChatMessage[];
|
|
557
|
+
conversationId: string | null;
|
|
558
|
+
}) => void;
|
|
559
|
+
config?: ChatUiConfig;
|
|
560
|
+
logo?: string | ReactNode;
|
|
561
|
+
}
|
|
562
|
+
declare const SanqianChat: react.NamedExoticComponent<SanqianChatProps>;
|
|
563
|
+
|
|
564
|
+
interface SanqianMessageListProps {
|
|
565
|
+
messages: ChatMessage[];
|
|
566
|
+
isLoading: boolean;
|
|
567
|
+
className?: string;
|
|
568
|
+
emptyState?: ReactNode;
|
|
569
|
+
onClickEmpty?: () => void;
|
|
570
|
+
onAtBottomChange?: (atBottom: boolean) => void;
|
|
571
|
+
}
|
|
572
|
+
interface SanqianMessageListHandle {
|
|
573
|
+
scrollToBottom: (behavior?: 'smooth' | 'auto', source?: string) => void;
|
|
574
|
+
}
|
|
575
|
+
declare const SanqianMessageList: react.ForwardRefExoticComponent<SanqianMessageListProps & react.RefAttributes<SanqianMessageListHandle>>;
|
|
576
|
+
|
|
577
|
+
interface SanqianChatMessageProps {
|
|
578
|
+
message: ChatMessage;
|
|
579
|
+
}
|
|
580
|
+
declare const SanqianChatMessage: react.NamedExoticComponent<SanqianChatMessageProps>;
|
|
581
|
+
|
|
299
582
|
interface ChatInputProps {
|
|
300
583
|
onSend: (content: string) => void;
|
|
301
584
|
onStop?: () => void;
|
|
@@ -303,17 +586,22 @@ interface ChatInputProps {
|
|
|
303
586
|
disabled?: boolean;
|
|
304
587
|
isStreaming?: boolean;
|
|
305
588
|
isLoading?: boolean;
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
sendButtonClassName?: string;
|
|
309
|
-
stopButtonClassName?: string;
|
|
310
|
-
sendButtonContent?: ReactNode;
|
|
311
|
-
stopButtonContent?: ReactNode;
|
|
589
|
+
sendLabel?: string;
|
|
590
|
+
stopLabel?: string;
|
|
312
591
|
maxRows?: number;
|
|
313
592
|
autoFocus?: boolean;
|
|
314
|
-
|
|
593
|
+
leftSlot?: ReactNode;
|
|
594
|
+
rightSlot?: ReactNode;
|
|
595
|
+
className?: string;
|
|
596
|
+
style?: CSSProperties;
|
|
597
|
+
}
|
|
598
|
+
interface ChatInputHandle {
|
|
599
|
+
focus: () => void;
|
|
600
|
+
setValue: (text: string) => void;
|
|
601
|
+
getValue: () => string;
|
|
602
|
+
clear: () => void;
|
|
315
603
|
}
|
|
316
|
-
declare const ChatInput: react.
|
|
604
|
+
declare const ChatInput: react.MemoExoticComponent<react.ForwardRefExoticComponent<ChatInputProps & react.RefAttributes<ChatInputHandle>>>;
|
|
317
605
|
|
|
318
606
|
interface FloatingChatProps {
|
|
319
607
|
messages: ChatMessage[];
|
|
@@ -325,10 +613,11 @@ interface FloatingChatProps {
|
|
|
325
613
|
onStopStreaming: () => void;
|
|
326
614
|
onApproveHitl?: (remember?: boolean) => void;
|
|
327
615
|
onRejectHitl?: (remember?: boolean) => void;
|
|
328
|
-
onHide?: () => void;
|
|
329
616
|
className?: string;
|
|
330
617
|
placeholder?: string;
|
|
331
618
|
locale?: Locale;
|
|
619
|
+
config?: ChatUiConfig;
|
|
620
|
+
logo?: string | ReactNode;
|
|
332
621
|
renderMessage?: (message: ChatMessage, index: number) => ReactNode;
|
|
333
622
|
renderContent?: (content: string, isStreaming: boolean) => ReactNode;
|
|
334
623
|
renderHitl?: (interrupt: HitlInterruptData, onApprove: () => void, onReject: () => void) => ReactNode;
|
|
@@ -337,4 +626,306 @@ interface FloatingChatProps {
|
|
|
337
626
|
}
|
|
338
627
|
declare const FloatingChat: react.NamedExoticComponent<FloatingChatProps>;
|
|
339
628
|
|
|
340
|
-
|
|
629
|
+
interface IntermediateStepsProps {
|
|
630
|
+
/** Message blocks to display */
|
|
631
|
+
blocks: MessageBlock[];
|
|
632
|
+
/** Additional CSS classes */
|
|
633
|
+
className?: string;
|
|
634
|
+
/** Default expanded state (default: false) */
|
|
635
|
+
defaultExpanded?: boolean;
|
|
636
|
+
/** Localized strings */
|
|
637
|
+
strings?: {
|
|
638
|
+
steps?: string;
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
interface StreamingTimelineProps {
|
|
642
|
+
blocks: MessageBlock[];
|
|
643
|
+
currentThinking?: string;
|
|
644
|
+
isThinkingStreaming?: boolean;
|
|
645
|
+
isToolCallsStreaming?: boolean;
|
|
646
|
+
isComplete?: boolean;
|
|
647
|
+
className?: string;
|
|
648
|
+
strings?: {
|
|
649
|
+
steps?: string;
|
|
650
|
+
executing?: string;
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
interface ThinkingSectionProps {
|
|
654
|
+
thinking: string;
|
|
655
|
+
currentThinking?: string;
|
|
656
|
+
isStreaming?: boolean;
|
|
657
|
+
isPaused?: boolean;
|
|
658
|
+
isComplete?: boolean;
|
|
659
|
+
className?: string;
|
|
660
|
+
strings?: {
|
|
661
|
+
thinkingStreaming?: string;
|
|
662
|
+
thinkingPaused?: string;
|
|
663
|
+
thinking?: string;
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Thinking section component with streaming support
|
|
668
|
+
* Three states:
|
|
669
|
+
* 1. Streaming: show currentThinking, auto-expand, animated loading symbol
|
|
670
|
+
* 2. Paused: show currentThinking, stay expanded, "已思考" (waiting for next round)
|
|
671
|
+
* 3. Finished: show full thinking, collapsed by default, "思考过程"
|
|
672
|
+
*/
|
|
673
|
+
declare const ThinkingSection: react.NamedExoticComponent<ThinkingSectionProps>;
|
|
674
|
+
declare const IntermediateSteps: react.NamedExoticComponent<IntermediateStepsProps>;
|
|
675
|
+
declare const StreamingTimeline: react.NamedExoticComponent<StreamingTimelineProps>;
|
|
676
|
+
|
|
677
|
+
interface HitlCardProps {
|
|
678
|
+
/** Interrupt data from backend */
|
|
679
|
+
interrupt: HitlInterruptData;
|
|
680
|
+
/** Called when user approves (for approval_request) */
|
|
681
|
+
onApprove?: (remember?: boolean) => void;
|
|
682
|
+
/** Called when user rejects (for approval_request) */
|
|
683
|
+
onReject?: (remember?: boolean) => void;
|
|
684
|
+
/** Called when user submits input (for user_input_request) */
|
|
685
|
+
onSubmit?: (response: HitlResponse) => void;
|
|
686
|
+
/** Called when user cancels */
|
|
687
|
+
onCancel?: () => void;
|
|
688
|
+
/** Whether in dark mode */
|
|
689
|
+
isDarkMode?: boolean;
|
|
690
|
+
/** Custom strings for i18n */
|
|
691
|
+
strings?: {
|
|
692
|
+
approve?: string;
|
|
693
|
+
reject?: string;
|
|
694
|
+
submit?: string;
|
|
695
|
+
cancel?: string;
|
|
696
|
+
rememberChoice?: string;
|
|
697
|
+
requiredField?: string;
|
|
698
|
+
timeoutIn?: string;
|
|
699
|
+
seconds?: string;
|
|
700
|
+
executeTool?: string;
|
|
701
|
+
toolLabel?: string;
|
|
702
|
+
argsLabel?: string;
|
|
703
|
+
defaultPrefix?: string;
|
|
704
|
+
enterResponse?: string;
|
|
705
|
+
approvalRequest?: string;
|
|
706
|
+
inputRequest?: string;
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
declare const HitlCard: react.NamedExoticComponent<HitlCardProps>;
|
|
710
|
+
|
|
711
|
+
interface HistoryListProps {
|
|
712
|
+
/** List of conversations */
|
|
713
|
+
conversations: ConversationInfo[];
|
|
714
|
+
/** Currently selected conversation ID */
|
|
715
|
+
selectedId?: string | null;
|
|
716
|
+
/** Whether loading */
|
|
717
|
+
isLoading?: boolean;
|
|
718
|
+
/** Whether there are more items to load */
|
|
719
|
+
hasMore?: boolean;
|
|
720
|
+
/** Whether last load failed */
|
|
721
|
+
loadError?: boolean;
|
|
722
|
+
/** Called when a conversation is selected */
|
|
723
|
+
onSelect: (id: string) => void;
|
|
724
|
+
/** Called when a conversation should be deleted */
|
|
725
|
+
onDelete: (id: string) => void;
|
|
726
|
+
/** Called when load more is triggered */
|
|
727
|
+
onLoadMore?: () => void;
|
|
728
|
+
/** Dark mode */
|
|
729
|
+
isDarkMode?: boolean;
|
|
730
|
+
/** Localized strings */
|
|
731
|
+
strings?: {
|
|
732
|
+
noHistory?: string;
|
|
733
|
+
loadMore?: string;
|
|
734
|
+
today?: string;
|
|
735
|
+
yesterday?: string;
|
|
736
|
+
delete?: string;
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
declare const HistoryList: react.NamedExoticComponent<HistoryListProps>;
|
|
740
|
+
|
|
741
|
+
declare function resolveChatStrings(locale?: Locale, overrides?: Partial<ChatUiStrings>): ChatUiStrings;
|
|
742
|
+
|
|
743
|
+
type AlertType = 'warning' | 'error';
|
|
744
|
+
interface AlertAction {
|
|
745
|
+
/** Action label */
|
|
746
|
+
label: string;
|
|
747
|
+
/** Action handler */
|
|
748
|
+
onClick: () => void;
|
|
749
|
+
}
|
|
750
|
+
interface AlertBannerProps {
|
|
751
|
+
/** Alert type - determines styling */
|
|
752
|
+
type: AlertType;
|
|
753
|
+
/** Alert message content */
|
|
754
|
+
message: string | ReactNode;
|
|
755
|
+
/** Optional action button */
|
|
756
|
+
action?: AlertAction;
|
|
757
|
+
/** Optional dismiss handler - shows dismiss button when provided */
|
|
758
|
+
onDismiss?: () => void;
|
|
759
|
+
/** Additional class names */
|
|
760
|
+
className?: string;
|
|
761
|
+
/** Custom icon */
|
|
762
|
+
icon?: ReactNode;
|
|
763
|
+
/** Max lines before truncating (default: 3) */
|
|
764
|
+
maxLines?: number;
|
|
765
|
+
/** Localized strings */
|
|
766
|
+
strings?: {
|
|
767
|
+
collapse?: string;
|
|
768
|
+
expand?: string;
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
declare const AlertBanner: react.NamedExoticComponent<AlertBannerProps>;
|
|
772
|
+
|
|
773
|
+
/** Alert configuration for displaying warnings/errors above input */
|
|
774
|
+
interface AlertConfig {
|
|
775
|
+
type: AlertType;
|
|
776
|
+
message: string;
|
|
777
|
+
action?: AlertAction;
|
|
778
|
+
dismissible?: boolean;
|
|
779
|
+
}
|
|
780
|
+
interface CompactChatProps {
|
|
781
|
+
/** Chat adapter for backend communication */
|
|
782
|
+
adapter: ChatAdapter;
|
|
783
|
+
/** UI configuration */
|
|
784
|
+
config?: ChatUiConfig;
|
|
785
|
+
/** Logo override (takes precedence over config.logo) */
|
|
786
|
+
logo?: string | ReactNode;
|
|
787
|
+
/** Input placeholder */
|
|
788
|
+
placeholder?: string;
|
|
789
|
+
/** Whether to auto-connect on mount */
|
|
790
|
+
autoConnect?: boolean;
|
|
791
|
+
/** Called when an error occurs */
|
|
792
|
+
onError?: (error: Error) => void;
|
|
793
|
+
/** Called when a message is received (for session tracking) */
|
|
794
|
+
onMessageReceived?: (message: ChatMessage) => void;
|
|
795
|
+
/** Called when loading state changes */
|
|
796
|
+
onLoadingChange?: (isLoading: boolean) => void;
|
|
797
|
+
/** Called when chat state changes (messages, conversationId) */
|
|
798
|
+
onStateChange?: (state: {
|
|
799
|
+
messages: ChatMessage[];
|
|
800
|
+
conversationId: string | null;
|
|
801
|
+
}) => void;
|
|
802
|
+
/** Header content (left side) */
|
|
803
|
+
headerLeft?: ReactNode;
|
|
804
|
+
/** Header content (right side) */
|
|
805
|
+
headerRight?: ReactNode;
|
|
806
|
+
/** Whether to hide header */
|
|
807
|
+
hideHeader?: boolean;
|
|
808
|
+
/** Whether to hide input area (for custom external input) */
|
|
809
|
+
hideInput?: boolean;
|
|
810
|
+
/** Container element for rendering input via Portal */
|
|
811
|
+
inputPortalContainer?: HTMLElement | null;
|
|
812
|
+
/** Ref to expose sendMessage function for external input */
|
|
813
|
+
sendMessageRef?: React.MutableRefObject<((message: string) => void) | null>;
|
|
814
|
+
/** Ref to expose newConversation function */
|
|
815
|
+
newConversationRef?: React.MutableRefObject<(() => void) | null>;
|
|
816
|
+
/** Ref to expose focusInput function */
|
|
817
|
+
focusInputRef?: React.MutableRefObject<(() => void) | null>;
|
|
818
|
+
/** Ref to expose setText function (for filling input externally) */
|
|
819
|
+
setTextRef?: React.MutableRefObject<((text: string) => void) | null>;
|
|
820
|
+
/** Custom message renderer */
|
|
821
|
+
renderMessage?: (message: ChatMessage) => ReactNode;
|
|
822
|
+
/** Empty state content (when no messages) */
|
|
823
|
+
emptyState?: ReactNode;
|
|
824
|
+
/** Additional class name */
|
|
825
|
+
className?: string;
|
|
826
|
+
/**
|
|
827
|
+
* Dark mode.
|
|
828
|
+
* @deprecated Use config.theme instead.
|
|
829
|
+
*/
|
|
830
|
+
isDarkMode?: boolean;
|
|
831
|
+
/** Localized strings */
|
|
832
|
+
strings?: Partial<ChatUiStrings>;
|
|
833
|
+
/** Custom alert to display above input (overrides default connection/error alerts) */
|
|
834
|
+
alert?: AlertConfig | null;
|
|
835
|
+
/** Callback when alert is dismissed */
|
|
836
|
+
onAlertDismiss?: () => void;
|
|
837
|
+
/** Function to get error message from error code (for i18n) */
|
|
838
|
+
getErrorMessage?: (errorCode: string) => string;
|
|
839
|
+
/** Use floating window container style (for transparent Electron windows) */
|
|
840
|
+
floating?: boolean;
|
|
841
|
+
}
|
|
842
|
+
declare const CompactChat: react.NamedExoticComponent<CompactChatProps>;
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Tool Arguments Display Component
|
|
846
|
+
*
|
|
847
|
+
* Displays tool call arguments in a compact, Python kwargs-like format.
|
|
848
|
+
* No JSON braces, uses indentation and bullet points for nested structures.
|
|
849
|
+
*
|
|
850
|
+
* Features:
|
|
851
|
+
* - Python kwargs-style display (key=value)
|
|
852
|
+
* - Recursive nested object/array rendering
|
|
853
|
+
* - Smart inline vs multi-line formatting
|
|
854
|
+
* - Theme-aware using CSS variables
|
|
855
|
+
*/
|
|
856
|
+
interface ToolArgumentsDisplayProps {
|
|
857
|
+
/** Arguments object to display */
|
|
858
|
+
args: Record<string, unknown>;
|
|
859
|
+
/** Additional CSS classes */
|
|
860
|
+
className?: string;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Displays tool arguments in Python kwargs style.
|
|
864
|
+
*
|
|
865
|
+
* @example
|
|
866
|
+
* <ToolArgumentsDisplay
|
|
867
|
+
* args={{ file_path: "/path/to/file", content: "Hello" }}
|
|
868
|
+
* />
|
|
869
|
+
* // Renders:
|
|
870
|
+
* // file_path = "/path/to/file"
|
|
871
|
+
* // content = "Hello"
|
|
872
|
+
*/
|
|
873
|
+
declare const ToolArgumentsDisplay: react.NamedExoticComponent<ToolArgumentsDisplayProps>;
|
|
874
|
+
|
|
875
|
+
interface MarkdownRendererProps {
|
|
876
|
+
/** Markdown content to render */
|
|
877
|
+
content: string;
|
|
878
|
+
/** Whether content is still streaming */
|
|
879
|
+
isStreaming?: boolean;
|
|
880
|
+
/** Additional CSS classes */
|
|
881
|
+
className?: string;
|
|
882
|
+
/** Custom component overrides */
|
|
883
|
+
components?: {
|
|
884
|
+
/** Custom link renderer */
|
|
885
|
+
a?: React.ComponentType<{
|
|
886
|
+
href?: string;
|
|
887
|
+
children?: ReactNode;
|
|
888
|
+
}>;
|
|
889
|
+
/** Custom code block renderer */
|
|
890
|
+
code?: React.ComponentType<{
|
|
891
|
+
className?: string;
|
|
892
|
+
children?: ReactNode;
|
|
893
|
+
}>;
|
|
894
|
+
/** Custom paragraph renderer */
|
|
895
|
+
p?: React.ComponentType<{
|
|
896
|
+
children?: ReactNode;
|
|
897
|
+
}>;
|
|
898
|
+
};
|
|
899
|
+
/** Callback when a link is clicked */
|
|
900
|
+
onLinkClick?: (href: string, event: React.MouseEvent) => void;
|
|
901
|
+
}
|
|
902
|
+
declare const MarkdownRenderer: react.NamedExoticComponent<MarkdownRendererProps>;
|
|
903
|
+
|
|
904
|
+
/**
|
|
905
|
+
* Inject chat styles into the document.
|
|
906
|
+
*
|
|
907
|
+
* Style modes:
|
|
908
|
+
* - 'safe' (default): CSS variables + component styles + Tailwind utilities.
|
|
909
|
+
* No global resets (preflight). Safe for third-party integration.
|
|
910
|
+
* - 'full': Complete styles including Tailwind CSS preflight.
|
|
911
|
+
* Use this for standalone windows where you control the entire page.
|
|
912
|
+
* - false: Disable all style injection.
|
|
913
|
+
*
|
|
914
|
+
* Configure via:
|
|
915
|
+
* - window.__SANQIAN_CHAT_STYLE_MODE__ = 'full' | 'safe' | false
|
|
916
|
+
* - window.__SANQIAN_CHAT_DISABLE_STYLES__ = true (legacy, same as 'false')
|
|
917
|
+
*
|
|
918
|
+
* Or import CSS directly:
|
|
919
|
+
* - '@yushaw/sanqian-chat/renderer/styles/safe.css' (no preflight)
|
|
920
|
+
* - '@yushaw/sanqian-chat/renderer/styles/chat.css' (full with preflight)
|
|
921
|
+
*/
|
|
922
|
+
declare function ensureChatBaseStyles(): void;
|
|
923
|
+
/**
|
|
924
|
+
* Inject full chat styles including Tailwind preflight.
|
|
925
|
+
* Use this for standalone windows where you control the entire page.
|
|
926
|
+
*
|
|
927
|
+
* @deprecated Use window.__SANQIAN_CHAT_STYLE_MODE__ = 'full' instead
|
|
928
|
+
*/
|
|
929
|
+
declare function ensureFullChatStyles(): void;
|
|
930
|
+
|
|
931
|
+
export { type AlertAction, AlertBanner, type AlertBannerProps, type AlertConfig, type AlertType, type ChatAdapter, type ChatAdapterConfig, type ChatFontSize, ChatInput, type ChatInputHandle, type ChatInputProps, type ChatThemeMode, type ChatUiConfig, type ChatUiConfigSerializable, type ChatUiStrings, CompactChat, type CompactChatProps, type ConnectionErrorCode, type ConnectionStatus, type ConversationDetail, type ConversationInfo, FloatingChat, type FloatingChatProps, type FloatingWindowConfig, HistoryList, type HistoryListProps, HitlCard, type HitlCardProps, type HitlInterruptData, I18nProvider, type I18nProviderProps, IntermediateSteps, type IntermediateStepsProps, type Locale, MarkdownRenderer, type MarkdownRendererProps, type MessageBlock, MessageBubble, type MessageBubbleProps, MessageList, type MessageListProps, type MessageRole, type ResolvedTheme, SanqianChat, SanqianChatMessage, type SanqianChatMessageProps, type SanqianChatProps, SanqianMessageList, type SanqianMessageListHandle, type SanqianMessageListProps, type SdkAdapterConfig, type SendMessage, type StreamEvent, StreamingTimeline, type StreamingTimelineProps, type ThemeMode, ThemeProvider, type ThemeProviderProps, ThinkingSection, type ThinkingSectionProps, ToolArgumentsDisplay, type ToolArgumentsDisplayProps, type ToolCall, type ToolCallStatus, type Translations, type UseChatOptions, type UseChatReturn, type UseConnectionOptions, type UseConnectionReturn, type UseConversationsOptions, type UseConversationsReturn, type UseFocusPersistenceOptions, type WindowPosition, createChatAdapter, createIpcAdapter, createSdkAdapter, ensureChatBaseStyles, ensureFullChatStyles, getTranslations, resolveChatStrings, useChat, useChatStyles, useConnection, useConversations, useFocusPersistence, useI18n, useIpcUiConfig, useResolvedUiConfig, useStandaloneI18n, useStandaloneTheme, useTheme };
|