@yushaw/sanqian-chat 0.1.1 → 0.2.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.
@@ -1,5 +1,218 @@
1
- import { BrowserWindow } from 'electron';
1
+ import * as _yushaw_sanqian_sdk from '@yushaw/sanqian-sdk';
2
2
  import { SanqianSDK } from '@yushaw/sanqian-sdk';
3
+ import { BrowserWindow } from 'electron';
4
+
5
+ /**
6
+ * @yushaw/sanqian-chat Main - Facade Types
7
+ *
8
+ * Application-facing types that hide SDK implementation details.
9
+ * These provide a stable API even as the underlying SDK evolves.
10
+ */
11
+ /**
12
+ * Application configuration for connecting to Sanqian
13
+ */
14
+ interface AppConfig {
15
+ /** Unique application identifier (e.g., 'sanqian-notes') */
16
+ appName: string;
17
+ /** Application version string */
18
+ appVersion: string;
19
+ /** Display name shown in Sanqian UI */
20
+ displayName?: string;
21
+ /** Command to auto-launch this app */
22
+ launchCommand?: string;
23
+ /** Tools provided by this application */
24
+ tools?: AppToolDefinition[];
25
+ /** Enable debug logging */
26
+ debug?: boolean;
27
+ }
28
+ /**
29
+ * JSON Schema property definition
30
+ */
31
+ interface AppJsonSchemaProperty {
32
+ type: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null';
33
+ description?: string;
34
+ enum?: (string | number | boolean)[];
35
+ items?: AppJsonSchemaProperty;
36
+ properties?: Record<string, AppJsonSchemaProperty>;
37
+ required?: string[];
38
+ default?: unknown;
39
+ }
40
+ /**
41
+ * Tool definition for application-provided tools
42
+ */
43
+ interface AppToolDefinition {
44
+ /** Tool name (without app prefix) */
45
+ name: string;
46
+ /** Tool description for LLM */
47
+ description: string;
48
+ /** JSON Schema for parameters */
49
+ parameters: {
50
+ type: 'object';
51
+ properties: Record<string, AppJsonSchemaProperty>;
52
+ required?: string[];
53
+ };
54
+ /** Async handler function */
55
+ handler: (args: Record<string, unknown>) => Promise<unknown>;
56
+ }
57
+ /**
58
+ * Agent configuration for private agents
59
+ */
60
+ interface AppAgentConfig {
61
+ /** Agent ID (unique within this app) */
62
+ agentId: string;
63
+ /** Display name */
64
+ name: string;
65
+ /** Agent description */
66
+ description?: string;
67
+ /** System prompt */
68
+ systemPrompt?: string;
69
+ /** Enabled tool names (without app prefix) */
70
+ tools?: string[];
71
+ }
72
+ /**
73
+ * Embedding configuration from Sanqian
74
+ */
75
+ interface AppEmbeddingConfig {
76
+ /** Whether embedding is available */
77
+ available: boolean;
78
+ /** Embedding API URL */
79
+ apiUrl?: string;
80
+ /** API key */
81
+ apiKey?: string;
82
+ /** Model name */
83
+ modelName?: string;
84
+ /** Embedding dimensions */
85
+ dimensions?: number;
86
+ }
87
+ /**
88
+ * Events emitted by SanqianAppClient
89
+ */
90
+ type AppClientEvent = 'connected' | 'registered' | 'disconnected' | 'error' | 'tool_call';
91
+ /**
92
+ * Event handler types
93
+ */
94
+ interface AppClientEventHandlers {
95
+ connected: () => void;
96
+ registered: () => void;
97
+ disconnected: (reason: string) => void;
98
+ error: (error: Error) => void;
99
+ tool_call: (call: {
100
+ name: string;
101
+ arguments: Record<string, unknown>;
102
+ }) => void;
103
+ }
104
+
105
+ /**
106
+ * SanqianAppClient - Application client for connecting to Sanqian
107
+ *
108
+ * This is a Facade that wraps the SDK and provides:
109
+ * - Stable API that doesn't change when SDK internals change
110
+ * - Application-focused types and methods
111
+ * - Simplified configuration
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * import { SanqianAppClient } from '@yushaw/sanqian-chat/main'
116
+ *
117
+ * const client = new SanqianAppClient({
118
+ * appName: 'my-app',
119
+ * appVersion: '1.0.0',
120
+ * tools: [...]
121
+ * })
122
+ *
123
+ * client.on('connected', () => console.log('Connected!'))
124
+ * await client.connect()
125
+ * ```
126
+ */
127
+ declare class SanqianAppClient {
128
+ private sdk;
129
+ constructor(config: AppConfig);
130
+ /**
131
+ * Connect to Sanqian and register this application
132
+ */
133
+ connect(): Promise<void>;
134
+ /**
135
+ * Disconnect from Sanqian
136
+ */
137
+ disconnect(): Promise<void>;
138
+ /**
139
+ * Check if connected to Sanqian
140
+ */
141
+ isConnected(): boolean;
142
+ /**
143
+ * Ensure SDK is ready (connects if needed, waits for registration)
144
+ */
145
+ ensureReady(): Promise<void>;
146
+ /**
147
+ * Request persistent connection (enables auto-reconnect)
148
+ * Call when a component needs the connection to stay alive
149
+ */
150
+ acquireReconnect(): void;
151
+ /**
152
+ * Release persistent connection request
153
+ * Call when a component no longer needs the connection
154
+ */
155
+ releaseReconnect(): void;
156
+ /**
157
+ * Create or update a private agent
158
+ * @returns The full agent ID (app_name:agent_id)
159
+ */
160
+ createAgent(config: AppAgentConfig): Promise<{
161
+ agentId: string;
162
+ }>;
163
+ /**
164
+ * Get embedding configuration from Sanqian
165
+ * @returns Embedding config or null if not available
166
+ */
167
+ getEmbeddingConfig(): Promise<AppEmbeddingConfig | null>;
168
+ /**
169
+ * Subscribe to client events
170
+ */
171
+ on<E extends AppClientEvent>(event: E, handler: AppClientEventHandlers[E]): this;
172
+ /**
173
+ * Remove all event listeners
174
+ */
175
+ removeAllListeners(): void;
176
+ /**
177
+ * Stream chat messages
178
+ */
179
+ chatStream(agentId: string, messages: Array<{
180
+ role: 'user' | 'assistant';
181
+ content: string;
182
+ }>, options?: {
183
+ conversationId?: string;
184
+ }): AsyncGenerator<_yushaw_sanqian_sdk.ChatStreamEvent>;
185
+ /**
186
+ * Send HITL (Human-in-the-Loop) response
187
+ */
188
+ sendHitlResponse(runId: string, response: _yushaw_sanqian_sdk.HitlResponse): void;
189
+ /**
190
+ * List conversations for an agent
191
+ */
192
+ listConversations(options: {
193
+ agentId: string;
194
+ limit?: number;
195
+ offset?: number;
196
+ }): Promise<{
197
+ conversations: Array<_yushaw_sanqian_sdk.ConversationInfo>;
198
+ total: number;
199
+ }>;
200
+ /**
201
+ * Get conversation details
202
+ */
203
+ getConversation(conversationId: string, options?: {
204
+ messageLimit?: number;
205
+ }): Promise<_yushaw_sanqian_sdk.ConversationDetail>;
206
+ /**
207
+ * Delete a conversation
208
+ */
209
+ deleteConversation(conversationId: string): Promise<void>;
210
+ /**
211
+ * Get the underlying SDK instance
212
+ * @internal This is for internal use by other sanqian-chat components
213
+ */
214
+ _getSdk(): SanqianSDK;
215
+ }
3
216
 
4
217
  /**
5
218
  * @yushaw/sanqian-chat Core Types
@@ -7,6 +220,69 @@ import { SanqianSDK } from '@yushaw/sanqian-sdk';
7
220
  * Re-exports SDK types + chat-specific types
8
221
  */
9
222
 
223
+ type Locale = 'en' | 'zh';
224
+ interface ChatUiStrings {
225
+ inputPlaceholder: string;
226
+ inputSend: string;
227
+ inputStop: string;
228
+ chat: string;
229
+ recentChats: string;
230
+ newChat: string;
231
+ selectConversation: string;
232
+ noHistory: string;
233
+ loadMore: string;
234
+ today: string;
235
+ yesterday: string;
236
+ delete: string;
237
+ dismiss: string;
238
+ close: string;
239
+ pin: string;
240
+ unpin: string;
241
+ conversationUntitled: string;
242
+ conversationDeleteConfirm: string;
243
+ messageThinking: string;
244
+ messageError: string;
245
+ messageLoading: string;
246
+ connectionConnecting: string;
247
+ connectionConnected: string;
248
+ connectionDisconnected: string;
249
+ connectionReconnecting: string;
250
+ connectionError: string;
251
+ steps: string;
252
+ executing: string;
253
+ thinking: string;
254
+ thinkingStreaming: string;
255
+ thinkingPaused: string;
256
+ hitlApprove: string;
257
+ hitlReject: string;
258
+ hitlSubmit: string;
259
+ hitlCancel: string;
260
+ hitlRememberChoice: string;
261
+ hitlRequiredField: string;
262
+ hitlTimeoutIn: string;
263
+ hitlSeconds: string;
264
+ hitlExecuteTool: string;
265
+ hitlToolLabel: string;
266
+ hitlArgsLabel: string;
267
+ hitlDefaultPrefix: string;
268
+ hitlEnterResponse: string;
269
+ hitlApprovalRequest: string;
270
+ hitlInputRequest: string;
271
+ hitlApprovalRequired: string;
272
+ hitlInputRequired: string;
273
+ }
274
+ type ChatThemeMode = 'light' | 'dark' | 'auto';
275
+ type ChatFontSize = 'small' | 'normal' | 'large' | 'extra-large';
276
+ interface ChatUiConfigSerializable {
277
+ logo?: string;
278
+ theme?: ChatThemeMode;
279
+ /** Font size scale: small (13px), normal (14px), large (16px), extra-large (18px) */
280
+ fontSize?: ChatFontSize;
281
+ accentColor?: string;
282
+ locale?: Locale;
283
+ strings?: Partial<ChatUiStrings>;
284
+ alwaysOnTop?: boolean;
285
+ }
10
286
  type WindowPosition = 'center' | 'cursor' | 'remember' | {
11
287
  x: number;
12
288
  y: number;
@@ -16,9 +292,21 @@ interface FloatingWindowConfig {
16
292
  position?: WindowPosition;
17
293
  width?: number;
18
294
  height?: number;
295
+ /** Minimum window width (default: 320) */
296
+ minWidth?: number;
297
+ /** Minimum window height (default: 420) */
298
+ minHeight?: number;
19
299
  alwaysOnTop?: boolean;
20
300
  showInTaskbar?: boolean;
21
301
  theme?: 'light' | 'dark' | 'system';
302
+ /** Optional UI config for renderer (serializable) */
303
+ uiConfig?: ChatUiConfigSerializable;
304
+ /** Persist size/position across sessions (stored under ~/.sanqian-chat) */
305
+ rememberWindowState?: boolean;
306
+ /** Optional storage key to avoid conflicts between apps */
307
+ windowStateKey?: string;
308
+ /** Optional full path for window state file */
309
+ windowStatePath?: string;
22
310
  }
23
311
 
24
312
  /**
@@ -26,8 +314,16 @@ interface FloatingWindowConfig {
26
314
  */
27
315
 
28
316
  interface FloatingWindowOptions extends FloatingWindowConfig {
29
- /** SDK instance getter */
30
- getSdk: () => SanqianSDK | null;
317
+ /**
318
+ * AppClient instance getter (recommended)
319
+ * Use this instead of getSdk when using the Facade API
320
+ */
321
+ getClient?: () => SanqianAppClient | null;
322
+ /**
323
+ * SDK instance getter (legacy)
324
+ * @deprecated Use getClient instead
325
+ */
326
+ getSdk?: () => SanqianSDK | null;
31
327
  /** Agent ID getter */
32
328
  getAgentId: () => string | null;
33
329
  /** Path to preload script */
@@ -40,19 +336,38 @@ interface FloatingWindowOptions extends FloatingWindowConfig {
40
336
  declare class FloatingWindow {
41
337
  private window;
42
338
  private options;
43
- private savedPosition;
339
+ private savedState;
340
+ private stateSaveTimer;
44
341
  private activeStreams;
342
+ private reconnectAcquired;
343
+ /**
344
+ * Get SDK instance from either getClient or getSdk
345
+ */
346
+ private static getSdkFromOptions;
45
347
  constructor(options: FloatingWindowOptions);
46
348
  private createWindow;
349
+ private getInitialBounds;
47
350
  private getInitialPosition;
351
+ private shouldPersistWindowState;
352
+ private shouldUseSavedState;
353
+ private getMinSize;
354
+ private getWindowStatePath;
355
+ private getResolvedUiConfig;
356
+ private loadWindowState;
357
+ private scheduleSaveWindowState;
358
+ private saveWindowState;
359
+ private getPercentFromBounds;
360
+ private getSavedBounds;
48
361
  private registerShortcut;
49
362
  private setupIpcHandlers;
50
363
  show(): void;
51
364
  hide(): void;
365
+ setAlwaysOnTop(alwaysOnTop: boolean): void;
366
+ isAlwaysOnTop(): boolean;
52
367
  toggle(): void;
53
368
  isVisible(): boolean;
54
369
  destroy(): void;
55
370
  getWindow(): BrowserWindow | null;
56
371
  }
57
372
 
58
- export { FloatingWindow, type FloatingWindowConfig, type FloatingWindowOptions, type WindowPosition };
373
+ export { type AppAgentConfig, type AppClientEvent, type AppClientEventHandlers, type AppConfig, type AppEmbeddingConfig, type AppJsonSchemaProperty, type AppToolDefinition, type ChatUiConfigSerializable, FloatingWindow, type FloatingWindowConfig, type FloatingWindowOptions, SanqianAppClient, type WindowPosition };