@djangocfg/ui-tools 2.1.336 → 2.1.337
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/ChatRoot-XV2QXMV4.mjs +5 -0
- package/dist/{ChatRoot-IIYQEWUU.mjs.map → ChatRoot-XV2QXMV4.mjs.map} +1 -1
- package/dist/ChatRoot-YX4RLHQX.cjs +14 -0
- package/dist/{ChatRoot-UUKTYM4N.cjs.map → ChatRoot-YX4RLHQX.cjs.map} +1 -1
- package/dist/{chunk-KRETIZU6.mjs → chunk-YWSQDBNU.mjs} +142 -21
- package/dist/chunk-YWSQDBNU.mjs.map +1 -0
- package/dist/{chunk-NRXYYO5V.cjs → chunk-ZWPBBAR2.cjs} +141 -19
- package/dist/chunk-ZWPBBAR2.cjs.map +1 -0
- package/dist/index.cjs +49 -45
- package/dist/index.d.cts +55 -2
- package/dist/index.d.ts +55 -2
- package/dist/index.mjs +3 -3
- package/package.json +6 -6
- package/src/tools/Chat/components/ChatRoot.tsx +9 -2
- package/src/tools/Chat/context/ChatProvider.tsx +4 -0
- package/src/tools/Chat/core/logger.ts +73 -0
- package/src/tools/Chat/hooks/useChat.ts +127 -12
- package/src/tools/Chat/index.ts +3 -0
- package/dist/ChatRoot-IIYQEWUU.mjs +0 -5
- package/dist/ChatRoot-UUKTYM4N.cjs +0 -14
- package/dist/chunk-KRETIZU6.mjs.map +0 -1
- package/dist/chunk-NRXYYO5V.cjs.map +0 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat dev logger.
|
|
3
|
+
*
|
|
4
|
+
* A thin namespaced wrapper over `consola` that no-ops in production unless
|
|
5
|
+
* the host app explicitly opts in via `<ChatRoot debug />`. The default
|
|
6
|
+
* detection uses `isDev` from `@djangocfg/ui-core/lib/env` (NODE_ENV).
|
|
7
|
+
*
|
|
8
|
+
* Why a dedicated module: chat is async and event-heavy (bootstrap, transport,
|
|
9
|
+
* SSE chunks, tool calls, regenerate, …). Inline `console.log`s rot fast and
|
|
10
|
+
* leak into prod. A single `getChatLogger()` call gives every layer the same
|
|
11
|
+
* namespaced sub-logger and keeps zero-cost gating in one place.
|
|
12
|
+
*
|
|
13
|
+
* Sub-loggers:
|
|
14
|
+
* bootstrap — initial session bootstrap (createSession / loadHistory)
|
|
15
|
+
* transport — outbound transport calls + responses
|
|
16
|
+
* stream — SSE chunk / tool / message_end events
|
|
17
|
+
* lifecycle — sendMessage, regenerate, newSession, edits
|
|
18
|
+
* tools — tool_call_start / _delta / _end specifics
|
|
19
|
+
* error — caught errors (always emitted as `error` level)
|
|
20
|
+
*/
|
|
21
|
+
import { consola, type ConsolaInstance } from 'consola';
|
|
22
|
+
|
|
23
|
+
import { isDev } from '@djangocfg/ui-core/lib';
|
|
24
|
+
|
|
25
|
+
export type ChatLogScope = 'bootstrap' | 'transport' | 'stream' | 'lifecycle' | 'tools' | 'error';
|
|
26
|
+
|
|
27
|
+
export interface ChatLogger {
|
|
28
|
+
bootstrap: ConsolaInstance;
|
|
29
|
+
transport: ConsolaInstance;
|
|
30
|
+
stream: ConsolaInstance;
|
|
31
|
+
lifecycle: ConsolaInstance;
|
|
32
|
+
tools: ConsolaInstance;
|
|
33
|
+
error: ConsolaInstance;
|
|
34
|
+
/** True when this logger is actually emitting (host opted in or NODE_ENV=development). */
|
|
35
|
+
enabled: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const SCOPES: ChatLogScope[] = ['bootstrap', 'transport', 'stream', 'lifecycle', 'tools', 'error'];
|
|
39
|
+
|
|
40
|
+
/** Module-level cache so all hooks/components share the same logger instance per `enabled` mode. */
|
|
41
|
+
const cache = new Map<boolean, ChatLogger>();
|
|
42
|
+
|
|
43
|
+
function buildLogger(enabled: boolean): ChatLogger {
|
|
44
|
+
const root = consola.withTag('chat');
|
|
45
|
+
const subs = Object.fromEntries(
|
|
46
|
+
SCOPES.map((scope) => [scope, root.withTag(scope)]),
|
|
47
|
+
) as Record<ChatLogScope, ConsolaInstance>;
|
|
48
|
+
|
|
49
|
+
if (!enabled) {
|
|
50
|
+
// Silence everything except `error` — surfaced errors should never go
|
|
51
|
+
// missing even if the host didn't opt in to debug logs.
|
|
52
|
+
for (const scope of SCOPES) {
|
|
53
|
+
if (scope === 'error') continue;
|
|
54
|
+
subs[scope].level = -999;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return { ...subs, enabled };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get the chat logger.
|
|
63
|
+
* @param debug Explicit override from the host. `undefined` falls back to `isDev`.
|
|
64
|
+
*/
|
|
65
|
+
export function getChatLogger(debug?: boolean): ChatLogger {
|
|
66
|
+
const enabled = debug ?? isDev;
|
|
67
|
+
let logger = cache.get(enabled);
|
|
68
|
+
if (!logger) {
|
|
69
|
+
logger = buildLogger(enabled);
|
|
70
|
+
cache.set(enabled, logger);
|
|
71
|
+
}
|
|
72
|
+
return logger;
|
|
73
|
+
}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
type ChatAction,
|
|
19
19
|
} from '../core/reducer';
|
|
20
20
|
import { createId } from '../core/ids';
|
|
21
|
+
import { getChatLogger } from '../core/logger';
|
|
21
22
|
import { createTokenBuffer } from '../core/markdown';
|
|
22
23
|
|
|
23
24
|
export interface UseChatConfig {
|
|
@@ -36,6 +37,12 @@ export interface UseChatConfig {
|
|
|
36
37
|
metadata?: Record<string, unknown>;
|
|
37
38
|
/** Stamped on outgoing user messages as `message.sender`. */
|
|
38
39
|
userPersona?: ChatPersona;
|
|
40
|
+
/**
|
|
41
|
+
* Enable verbose dev-mode logging (consola, namespace `chat:*`).
|
|
42
|
+
* Defaults to `isDev` from `@djangocfg/ui-core/lib`. Pass `false` to silence
|
|
43
|
+
* even in development; `true` to force on in production.
|
|
44
|
+
*/
|
|
45
|
+
debug?: boolean;
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
export interface UseChatReturn extends ChatState {
|
|
@@ -59,9 +66,15 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
59
66
|
const lastErrorRef = useRef<Error | null>(null);
|
|
60
67
|
const initRef = useRef(false);
|
|
61
68
|
const streamingMsgIdRef = useRef<string | null>(null);
|
|
69
|
+
// Promise resolved once the initial session is available (or `null` when the
|
|
70
|
+
// bootstrap finished without producing one — e.g. autoCreateSession=false).
|
|
71
|
+
// Action methods (sendMessage, regenerate, …) await this so users who type
|
|
72
|
+
// before the first network round-trip resolves don't hit "No active session".
|
|
73
|
+
const bootstrapRef = useRef<Promise<string | null> | null>(null);
|
|
62
74
|
|
|
63
75
|
const { transport, autoCreateSession = true, streaming = true, pageSize = LIMITS.pageSize } =
|
|
64
76
|
config;
|
|
77
|
+
const log = getChatLogger(config.debug);
|
|
65
78
|
|
|
66
79
|
// Initial session bootstrap.
|
|
67
80
|
useEffect(() => {
|
|
@@ -69,25 +82,50 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
69
82
|
initRef.current = true;
|
|
70
83
|
|
|
71
84
|
let cancelled = false;
|
|
72
|
-
|
|
85
|
+
// Show "loading" state immediately so the UI doesn't look idle while we
|
|
86
|
+
// wait for createSession / loadHistory to come back.
|
|
87
|
+
if (config.initialSessionId || autoCreateSession) {
|
|
88
|
+
dispatch({ type: 'HISTORY_LOAD_START' });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
log.bootstrap.info('start', {
|
|
92
|
+
mode: config.initialSessionId ? 'resume' : autoCreateSession ? 'create' : 'idle',
|
|
93
|
+
initialSessionId: config.initialSessionId,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const run = async (): Promise<string | null> => {
|
|
97
|
+
const t0 = performance.now();
|
|
73
98
|
try {
|
|
74
99
|
if (config.initialSessionId) {
|
|
75
100
|
dispatch({
|
|
76
101
|
type: 'SESSION_SET',
|
|
77
102
|
sessionId: config.initialSessionId,
|
|
78
103
|
});
|
|
79
|
-
dispatch({ type: 'HISTORY_LOAD_START' });
|
|
80
104
|
const page = await transport.loadHistory(config.initialSessionId, null, pageSize);
|
|
81
|
-
if (cancelled)
|
|
105
|
+
if (cancelled) {
|
|
106
|
+
log.bootstrap.debug('cancelled (post-loadHistory)');
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
82
109
|
dispatch({
|
|
83
110
|
type: 'HISTORY_LOAD_DONE',
|
|
84
111
|
messages: page.messages,
|
|
85
112
|
hasMore: page.hasMore,
|
|
86
113
|
cursor: page.nextCursor,
|
|
87
114
|
});
|
|
88
|
-
|
|
115
|
+
log.bootstrap.success('resumed', {
|
|
116
|
+
sessionId: config.initialSessionId,
|
|
117
|
+
messages: page.messages.length,
|
|
118
|
+
hasMore: page.hasMore,
|
|
119
|
+
elapsedMs: Math.round(performance.now() - t0),
|
|
120
|
+
});
|
|
121
|
+
return config.initialSessionId;
|
|
122
|
+
}
|
|
123
|
+
if (autoCreateSession) {
|
|
89
124
|
const info = await transport.createSession({ metadata: config.metadata });
|
|
90
|
-
if (cancelled)
|
|
125
|
+
if (cancelled) {
|
|
126
|
+
log.bootstrap.debug('cancelled (post-createSession)');
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
91
129
|
dispatch({
|
|
92
130
|
type: 'SESSION_SET',
|
|
93
131
|
sessionId: info.sessionId,
|
|
@@ -95,21 +133,55 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
95
133
|
hasMore: info.hasMore ?? false,
|
|
96
134
|
cursor: info.cursor ?? null,
|
|
97
135
|
});
|
|
136
|
+
// SESSION_SET implicitly clears `error` and leaves isLoading from
|
|
137
|
+
// the earlier HISTORY_LOAD_START set; mark history as done so the
|
|
138
|
+
// composer un-disables.
|
|
139
|
+
dispatch({
|
|
140
|
+
type: 'HISTORY_LOAD_DONE',
|
|
141
|
+
messages: info.messages ?? [],
|
|
142
|
+
hasMore: info.hasMore ?? false,
|
|
143
|
+
cursor: info.cursor ?? null,
|
|
144
|
+
});
|
|
145
|
+
log.bootstrap.success('created', {
|
|
146
|
+
sessionId: info.sessionId,
|
|
147
|
+
resumed: info.resumed ?? false,
|
|
148
|
+
elapsedMs: Math.round(performance.now() - t0),
|
|
149
|
+
});
|
|
150
|
+
return info.sessionId;
|
|
98
151
|
}
|
|
152
|
+
log.bootstrap.debug('idle (no initialSessionId, autoCreateSession=false)');
|
|
153
|
+
return null;
|
|
99
154
|
} catch (err) {
|
|
155
|
+
if (cancelled) {
|
|
156
|
+
log.bootstrap.debug('cancelled (in catch)');
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
100
159
|
const e = err instanceof Error ? err : new Error(String(err));
|
|
101
160
|
lastErrorRef.current = e;
|
|
102
161
|
dispatch({ type: 'ERROR_SET', error: e.message });
|
|
103
162
|
config.onError?.(e);
|
|
163
|
+
log.error.error('bootstrap failed', { message: e.message, elapsedMs: Math.round(performance.now() - t0) });
|
|
164
|
+
return null;
|
|
104
165
|
}
|
|
105
166
|
};
|
|
106
|
-
|
|
167
|
+
bootstrapRef.current = run();
|
|
107
168
|
return () => {
|
|
108
169
|
cancelled = true;
|
|
109
170
|
};
|
|
110
171
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
111
172
|
}, []);
|
|
112
173
|
|
|
174
|
+
/** Wait for the initial session bootstrap to settle, then return whatever
|
|
175
|
+
* sessionId is now in state. Safe to call multiple times. */
|
|
176
|
+
const awaitSession = useCallback(async (): Promise<string | null> => {
|
|
177
|
+
if (stateRef.current.sessionId) return stateRef.current.sessionId;
|
|
178
|
+
if (bootstrapRef.current) {
|
|
179
|
+
const id = await bootstrapRef.current;
|
|
180
|
+
if (id) return id;
|
|
181
|
+
}
|
|
182
|
+
return stateRef.current.sessionId;
|
|
183
|
+
}, []);
|
|
184
|
+
|
|
113
185
|
const consumeStream = useCallback(
|
|
114
186
|
async (
|
|
115
187
|
sessionId: string,
|
|
@@ -123,12 +195,16 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
123
195
|
|
|
124
196
|
dispatch({ type: 'STREAM_START', id: assistantId });
|
|
125
197
|
config.onStreamStart?.(assistantId);
|
|
198
|
+
log.stream.info('start', { sessionId, assistantId, chars: content.length });
|
|
126
199
|
|
|
127
200
|
const tokenBuffer = createTokenBuffer((delta) =>
|
|
128
201
|
dispatch({ type: 'STREAM_CHUNK', delta }),
|
|
129
202
|
);
|
|
130
203
|
|
|
131
204
|
let serverMessageId: string | null = null;
|
|
205
|
+
let chunkCount = 0;
|
|
206
|
+
let charsReceived = 0;
|
|
207
|
+
const t0 = performance.now();
|
|
132
208
|
|
|
133
209
|
try {
|
|
134
210
|
const iterator = transport.stream(sessionId, content, {
|
|
@@ -150,18 +226,26 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
150
226
|
|
|
151
227
|
const finalMsg = stateRef.current.messages.find((m) => m.id === assistantId);
|
|
152
228
|
if (finalMsg) config.onMessageEnd?.(finalMsg);
|
|
229
|
+
log.stream.success('done', {
|
|
230
|
+
assistantId,
|
|
231
|
+
chunks: chunkCount,
|
|
232
|
+
chars: charsReceived,
|
|
233
|
+
elapsedMs: Math.round(performance.now() - t0),
|
|
234
|
+
});
|
|
153
235
|
} catch (err) {
|
|
154
236
|
tokenBuffer.close();
|
|
155
237
|
if (ctrl.signal.aborted) {
|
|
156
238
|
const partial =
|
|
157
239
|
stateRef.current.messages.find((m) => m.id === assistantId)?.content ?? '';
|
|
158
240
|
dispatch({ type: 'STREAM_CANCELLED', id: assistantId, partialText: partial });
|
|
241
|
+
log.stream.warn('cancelled', { assistantId, partialChars: partial.length });
|
|
159
242
|
return;
|
|
160
243
|
}
|
|
161
244
|
const e = err instanceof Error ? err : new Error(String(err));
|
|
162
245
|
lastErrorRef.current = e;
|
|
163
246
|
dispatch({ type: 'STREAM_ERROR', id: assistantId, message: e.message });
|
|
164
247
|
config.onError?.(e);
|
|
248
|
+
log.error.error('stream failed', { assistantId, message: e.message });
|
|
165
249
|
} finally {
|
|
166
250
|
tokenBuffer.close();
|
|
167
251
|
if (abortRef.current === ctrl) abortRef.current = null;
|
|
@@ -172,13 +256,17 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
172
256
|
switch (ev.type) {
|
|
173
257
|
case 'message_start':
|
|
174
258
|
serverMessageId = ev.messageId;
|
|
259
|
+
log.stream.debug('message_start', { messageId: ev.messageId });
|
|
175
260
|
return;
|
|
176
261
|
case 'chunk':
|
|
177
262
|
tokenBuffer.push(ev.delta);
|
|
263
|
+
chunkCount += 1;
|
|
264
|
+
charsReceived += ev.delta.length;
|
|
178
265
|
return;
|
|
179
266
|
case 'tool_activity':
|
|
180
267
|
tokenBuffer.flush();
|
|
181
268
|
dispatch({ type: 'STREAM_TOOL_ACTIVITY', tool: ev.tool });
|
|
269
|
+
log.tools.debug('activity', { tool: ev.tool, status: ev.status });
|
|
182
270
|
return;
|
|
183
271
|
case 'tool_call_start': {
|
|
184
272
|
tokenBuffer.flush();
|
|
@@ -195,6 +283,7 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
195
283
|
messageId: assistantId,
|
|
196
284
|
toolCall,
|
|
197
285
|
});
|
|
286
|
+
log.tools.info('call_start', { toolId: ev.toolId, name: ev.name });
|
|
198
287
|
return;
|
|
199
288
|
}
|
|
200
289
|
case 'tool_call_delta':
|
|
@@ -213,6 +302,7 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
213
302
|
output: ev.output,
|
|
214
303
|
status: ev.status,
|
|
215
304
|
});
|
|
305
|
+
log.tools.info('call_end', { toolId: ev.toolId, status: ev.status });
|
|
216
306
|
return;
|
|
217
307
|
case 'message_end':
|
|
218
308
|
tokenBuffer.flush();
|
|
@@ -223,6 +313,11 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
223
313
|
tokensOut: ev.tokensOut,
|
|
224
314
|
sources: ev.sources,
|
|
225
315
|
});
|
|
316
|
+
log.stream.debug('message_end', {
|
|
317
|
+
tokensIn: ev.tokensIn,
|
|
318
|
+
tokensOut: ev.tokensOut,
|
|
319
|
+
sources: ev.sources?.length ?? 0,
|
|
320
|
+
});
|
|
226
321
|
return;
|
|
227
322
|
case 'error':
|
|
228
323
|
tokenBuffer.flush();
|
|
@@ -231,6 +326,7 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
231
326
|
id: assistantId,
|
|
232
327
|
message: ev.message,
|
|
233
328
|
});
|
|
329
|
+
log.error.error('stream event error', { code: ev.code, message: ev.message });
|
|
234
330
|
return;
|
|
235
331
|
}
|
|
236
332
|
// unreachable; prevents unused-var on serverMessageId
|
|
@@ -270,16 +366,31 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
270
366
|
|
|
271
367
|
const sendMessage = useCallback(
|
|
272
368
|
async (content: string, attachments?: ChatAttachment[]) => {
|
|
273
|
-
|
|
369
|
+
// Wait for the initial session bootstrap if it's still in flight.
|
|
370
|
+
// Without this, fast typers hit "No active session" before
|
|
371
|
+
// transport.createSession resolves.
|
|
372
|
+
log.lifecycle.info('sendMessage', {
|
|
373
|
+
chars: content.length,
|
|
374
|
+
attachments: attachments?.length ?? 0,
|
|
375
|
+
hasSession: !!stateRef.current.sessionId,
|
|
376
|
+
});
|
|
377
|
+
const sessionId = await awaitSession();
|
|
274
378
|
if (!sessionId) {
|
|
275
379
|
const e = new Error('No active session');
|
|
276
380
|
lastErrorRef.current = e;
|
|
277
381
|
dispatch({ type: 'ERROR_SET', error: e.message });
|
|
278
382
|
config.onError?.(e);
|
|
383
|
+
log.error.error('sendMessage aborted: no session');
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
if (!content.trim() && !(attachments && attachments.length > 0)) {
|
|
387
|
+
log.lifecycle.debug('sendMessage skipped (empty)');
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
if (stateRef.current.isStreaming) {
|
|
391
|
+
log.lifecycle.debug('sendMessage skipped (already streaming)');
|
|
279
392
|
return;
|
|
280
393
|
}
|
|
281
|
-
if (!content.trim() && !(attachments && attachments.length > 0)) return;
|
|
282
|
-
if (stateRef.current.isStreaming) return;
|
|
283
394
|
|
|
284
395
|
const userMsg: ChatMessage = {
|
|
285
396
|
id: createId('u'),
|
|
@@ -298,7 +409,7 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
298
409
|
await consumeBuffered(sessionId, content, attachments);
|
|
299
410
|
}
|
|
300
411
|
},
|
|
301
|
-
[streaming, consumeStream, consumeBuffered, config],
|
|
412
|
+
[streaming, consumeStream, consumeBuffered, config, awaitSession],
|
|
302
413
|
);
|
|
303
414
|
|
|
304
415
|
const cancelStream = useCallback(() => {
|
|
@@ -307,6 +418,7 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
307
418
|
|
|
308
419
|
const regenerate = useCallback(
|
|
309
420
|
async (messageId?: string) => {
|
|
421
|
+
log.lifecycle.info('regenerate', { messageId: messageId ?? '(last)' });
|
|
310
422
|
const messages = stateRef.current.messages;
|
|
311
423
|
let targetUserIdx = -1;
|
|
312
424
|
if (messageId) {
|
|
@@ -324,7 +436,7 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
324
436
|
for (let i = messages.length - 1; i > targetUserIdx; i -= 1) {
|
|
325
437
|
dispatch({ type: 'MESSAGE_DELETE', id: messages[i].id });
|
|
326
438
|
}
|
|
327
|
-
const sessionId =
|
|
439
|
+
const sessionId = await awaitSession();
|
|
328
440
|
if (!sessionId) return;
|
|
329
441
|
if (streaming) {
|
|
330
442
|
await consumeStream(sessionId, userMsg.content, userMsg.attachments);
|
|
@@ -332,7 +444,7 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
332
444
|
await consumeBuffered(sessionId, userMsg.content, userMsg.attachments);
|
|
333
445
|
}
|
|
334
446
|
},
|
|
335
|
-
[streaming, consumeStream, consumeBuffered],
|
|
447
|
+
[streaming, consumeStream, consumeBuffered, awaitSession],
|
|
336
448
|
);
|
|
337
449
|
|
|
338
450
|
const editMessage = useCallback(
|
|
@@ -381,6 +493,7 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
381
493
|
}, [transport, pageSize, config]);
|
|
382
494
|
|
|
383
495
|
const newSession = useCallback(async () => {
|
|
496
|
+
log.lifecycle.info('newSession', { previous: stateRef.current.sessionId });
|
|
384
497
|
abortRef.current?.abort();
|
|
385
498
|
const previous = stateRef.current.sessionId;
|
|
386
499
|
if (previous) {
|
|
@@ -400,11 +513,13 @@ export function useChat(config: UseChatConfig): UseChatReturn {
|
|
|
400
513
|
hasMore: info.hasMore ?? false,
|
|
401
514
|
cursor: info.cursor ?? null,
|
|
402
515
|
});
|
|
516
|
+
log.lifecycle.success('newSession ok', { sessionId: info.sessionId });
|
|
403
517
|
} catch (err) {
|
|
404
518
|
const e = err instanceof Error ? err : new Error(String(err));
|
|
405
519
|
lastErrorRef.current = e;
|
|
406
520
|
dispatch({ type: 'ERROR_SET', error: e.message });
|
|
407
521
|
config.onError?.(e);
|
|
522
|
+
log.error.error('newSession failed', { message: e.message });
|
|
408
523
|
}
|
|
409
524
|
}, [transport, config]);
|
|
410
525
|
|
package/src/tools/Chat/index.ts
CHANGED
|
@@ -109,6 +109,9 @@ export {
|
|
|
109
109
|
export { useChatLightbox, type UseChatLightboxReturn, type ChatLightboxState } from './hooks';
|
|
110
110
|
export { collectImageAttachments } from './utils/collectImageAttachments';
|
|
111
111
|
|
|
112
|
+
// Dev logger (consola-based, namespace "chat:*")
|
|
113
|
+
export { getChatLogger, type ChatLogger, type ChatLogScope } from './core/logger';
|
|
114
|
+
|
|
112
115
|
// Context
|
|
113
116
|
export {
|
|
114
117
|
ChatProvider,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkNRXYYO5V_cjs = require('./chunk-NRXYYO5V.cjs');
|
|
4
|
-
require('./chunk-B5AWZOHJ.cjs');
|
|
5
|
-
require('./chunk-OLISEQHS.cjs');
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Object.defineProperty(exports, "ChatRoot", {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
get: function () { return chunkNRXYYO5V_cjs.ChatRoot; }
|
|
12
|
-
});
|
|
13
|
-
//# sourceMappingURL=ChatRoot-UUKTYM4N.cjs.map
|
|
14
|
-
//# sourceMappingURL=ChatRoot-UUKTYM4N.cjs.map
|