@djangocfg/ui-tools 2.1.372 → 2.1.373
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-3LA3DSNY.cjs +14 -0
- package/dist/{ChatRoot-2WNYE2V5.mjs.map → ChatRoot-3LA3DSNY.cjs.map} +1 -1
- package/dist/ChatRoot-RIETBE55.mjs +5 -0
- package/dist/{ChatRoot-AD2JIUIU.cjs.map → ChatRoot-RIETBE55.mjs.map} +1 -1
- package/dist/{chunk-KSBMKHYY.mjs → chunk-PSM3DUTC.mjs} +4 -7
- package/dist/chunk-PSM3DUTC.mjs.map +1 -0
- package/dist/{chunk-A6DDYQQV.cjs → chunk-TAEHNX4W.cjs} +4 -7
- package/dist/chunk-TAEHNX4W.cjs.map +1 -0
- package/dist/index.cjs +47 -47
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.mjs +3 -3
- package/package.json +6 -6
- package/src/tools/Chat/Chat.story.tsx +171 -0
- package/src/tools/Chat/components/MessageList.tsx +30 -25
- package/dist/ChatRoot-2WNYE2V5.mjs +0 -5
- package/dist/ChatRoot-AD2JIUIU.cjs +0 -14
- package/dist/chunk-A6DDYQQV.cjs.map +0 -1
- package/dist/chunk-KSBMKHYY.mjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -7,7 +7,7 @@ var chunkKNDLV4PI_cjs = require('./chunk-KNDLV4PI.cjs');
|
|
|
7
7
|
var chunk5I5QNGUG_cjs = require('./chunk-5I5QNGUG.cjs');
|
|
8
8
|
var chunkYW5IVWHQ_cjs = require('./chunk-YW5IVWHQ.cjs');
|
|
9
9
|
var chunk76NNDZH6_cjs = require('./chunk-76NNDZH6.cjs');
|
|
10
|
-
var
|
|
10
|
+
var chunkTAEHNX4W_cjs = require('./chunk-TAEHNX4W.cjs');
|
|
11
11
|
var chunkYXZ6GU7H_cjs = require('./chunk-YXZ6GU7H.cjs');
|
|
12
12
|
var chunkFVVF7VCD_cjs = require('./chunk-FVVF7VCD.cjs');
|
|
13
13
|
var chunk7EYHNP3E_cjs = require('./chunk-7EYHNP3E.cjs');
|
|
@@ -373,7 +373,7 @@ var LazyTree = createLazyComponent(
|
|
|
373
373
|
}
|
|
374
374
|
);
|
|
375
375
|
var LazyChat = createLazyComponent(
|
|
376
|
-
() => import('./ChatRoot-
|
|
376
|
+
() => import('./ChatRoot-3LA3DSNY.cjs').then((m) => ({ default: m.ChatRoot })),
|
|
377
377
|
{
|
|
378
378
|
displayName: "LazyChat",
|
|
379
379
|
fallback: /* @__PURE__ */ jsxRuntime.jsx(LoadingFallback, { minHeight: 320, text: "Loading chat\u2026" })
|
|
@@ -410,7 +410,7 @@ async function* parseSSE(response, options = {}) {
|
|
|
410
410
|
throw new Error("SSE response has no body");
|
|
411
411
|
}
|
|
412
412
|
const map = options.map ?? DEFAULT_MAP;
|
|
413
|
-
const idleMs = options.idleTimeoutMs ??
|
|
413
|
+
const idleMs = options.idleTimeoutMs ?? chunkTAEHNX4W_cjs.LIMITS.sseIdleMs;
|
|
414
414
|
const reader = response.body.getReader();
|
|
415
415
|
const decoder = new TextDecoder();
|
|
416
416
|
let buffer = "";
|
|
@@ -613,7 +613,7 @@ function createMockTransport(opts = {}) {
|
|
|
613
613
|
async createSession(_opts) {
|
|
614
614
|
await sleep(latency);
|
|
615
615
|
return {
|
|
616
|
-
sessionId:
|
|
616
|
+
sessionId: chunkTAEHNX4W_cjs.createId("s"),
|
|
617
617
|
messages: history.length ? [...history] : void 0,
|
|
618
618
|
hasMore: false,
|
|
619
619
|
cursor: null,
|
|
@@ -630,12 +630,12 @@ function createMockTransport(opts = {}) {
|
|
|
630
630
|
throw new Error("mock transport scripted failure");
|
|
631
631
|
}
|
|
632
632
|
history.push({
|
|
633
|
-
id:
|
|
633
|
+
id: chunkTAEHNX4W_cjs.createId("u"),
|
|
634
634
|
role: "user",
|
|
635
635
|
content,
|
|
636
636
|
createdAt: Date.now()
|
|
637
637
|
});
|
|
638
|
-
const messageId =
|
|
638
|
+
const messageId = chunkTAEHNX4W_cjs.createId("a");
|
|
639
639
|
yield { type: "message_start", messageId, sessionId: _sid };
|
|
640
640
|
const reply = replies[turn % replies.length];
|
|
641
641
|
turn += 1;
|
|
@@ -664,7 +664,7 @@ function createMockTransport(opts = {}) {
|
|
|
664
664
|
turn += 1;
|
|
665
665
|
const text = typeof reply === "string" ? reply : reply.filter((e) => e.type === "chunk").map((e) => e.delta).join("");
|
|
666
666
|
return {
|
|
667
|
-
id:
|
|
667
|
+
id: chunkTAEHNX4W_cjs.createId("a"),
|
|
668
668
|
role: "assistant",
|
|
669
669
|
content: text || DEFAULT_REPLY,
|
|
670
670
|
createdAt: Date.now()
|
|
@@ -864,9 +864,9 @@ function AudioToggle({
|
|
|
864
864
|
alwaysShow = false,
|
|
865
865
|
className
|
|
866
866
|
}) {
|
|
867
|
-
const muted =
|
|
868
|
-
const setMuted =
|
|
869
|
-
const ctx =
|
|
867
|
+
const muted = chunkTAEHNX4W_cjs.useChatAudioPrefs((s) => s.muted);
|
|
868
|
+
const setMuted = chunkTAEHNX4W_cjs.useChatAudioPrefs((s) => s.setMuted);
|
|
869
|
+
const ctx = chunkTAEHNX4W_cjs.useChatContextOptional();
|
|
870
870
|
if (ctx && !ctx.hasAudio && !alwaysShow) return null;
|
|
871
871
|
const Icon = muted ? lucideReact.VolumeX : lucideReact.Volume2;
|
|
872
872
|
const label = muted ? "Unmute chat sounds" : "Mute chat sounds";
|
|
@@ -2180,151 +2180,151 @@ Object.defineProperty(exports, "useCronWeekDays", {
|
|
|
2180
2180
|
});
|
|
2181
2181
|
Object.defineProperty(exports, "Attachments", {
|
|
2182
2182
|
enumerable: true,
|
|
2183
|
-
get: function () { return
|
|
2183
|
+
get: function () { return chunkTAEHNX4W_cjs.Attachments; }
|
|
2184
2184
|
});
|
|
2185
2185
|
Object.defineProperty(exports, "AttachmentsGrid", {
|
|
2186
2186
|
enumerable: true,
|
|
2187
|
-
get: function () { return
|
|
2187
|
+
get: function () { return chunkTAEHNX4W_cjs.AttachmentsGrid; }
|
|
2188
2188
|
});
|
|
2189
2189
|
Object.defineProperty(exports, "AttachmentsList", {
|
|
2190
2190
|
enumerable: true,
|
|
2191
|
-
get: function () { return
|
|
2191
|
+
get: function () { return chunkTAEHNX4W_cjs.AttachmentsList; }
|
|
2192
2192
|
});
|
|
2193
2193
|
Object.defineProperty(exports, "CHAT_EVENT_NAME", {
|
|
2194
2194
|
enumerable: true,
|
|
2195
|
-
get: function () { return
|
|
2195
|
+
get: function () { return chunkTAEHNX4W_cjs.CHAT_EVENT_NAME; }
|
|
2196
2196
|
});
|
|
2197
2197
|
Object.defineProperty(exports, "CSS_VARS", {
|
|
2198
2198
|
enumerable: true,
|
|
2199
|
-
get: function () { return
|
|
2199
|
+
get: function () { return chunkTAEHNX4W_cjs.CSS_VARS; }
|
|
2200
2200
|
});
|
|
2201
2201
|
Object.defineProperty(exports, "ChatProvider", {
|
|
2202
2202
|
enumerable: true,
|
|
2203
|
-
get: function () { return
|
|
2203
|
+
get: function () { return chunkTAEHNX4W_cjs.ChatProvider; }
|
|
2204
2204
|
});
|
|
2205
2205
|
Object.defineProperty(exports, "ChatRoot", {
|
|
2206
2206
|
enumerable: true,
|
|
2207
|
-
get: function () { return
|
|
2207
|
+
get: function () { return chunkTAEHNX4W_cjs.ChatRoot; }
|
|
2208
2208
|
});
|
|
2209
2209
|
Object.defineProperty(exports, "Composer", {
|
|
2210
2210
|
enumerable: true,
|
|
2211
|
-
get: function () { return
|
|
2211
|
+
get: function () { return chunkTAEHNX4W_cjs.Composer; }
|
|
2212
2212
|
});
|
|
2213
2213
|
Object.defineProperty(exports, "DEFAULT_LABELS", {
|
|
2214
2214
|
enumerable: true,
|
|
2215
|
-
get: function () { return
|
|
2215
|
+
get: function () { return chunkTAEHNX4W_cjs.DEFAULT_LABELS; }
|
|
2216
2216
|
});
|
|
2217
2217
|
Object.defineProperty(exports, "DEFAULT_SIDEBAR", {
|
|
2218
2218
|
enumerable: true,
|
|
2219
|
-
get: function () { return
|
|
2219
|
+
get: function () { return chunkTAEHNX4W_cjs.DEFAULT_SIDEBAR; }
|
|
2220
2220
|
});
|
|
2221
2221
|
Object.defineProperty(exports, "DEFAULT_Z_INDEX", {
|
|
2222
2222
|
enumerable: true,
|
|
2223
|
-
get: function () { return
|
|
2223
|
+
get: function () { return chunkTAEHNX4W_cjs.DEFAULT_Z_INDEX; }
|
|
2224
2224
|
});
|
|
2225
2225
|
Object.defineProperty(exports, "EmptyState", {
|
|
2226
2226
|
enumerable: true,
|
|
2227
|
-
get: function () { return
|
|
2227
|
+
get: function () { return chunkTAEHNX4W_cjs.EmptyState; }
|
|
2228
2228
|
});
|
|
2229
2229
|
Object.defineProperty(exports, "ErrorBanner", {
|
|
2230
2230
|
enumerable: true,
|
|
2231
|
-
get: function () { return
|
|
2231
|
+
get: function () { return chunkTAEHNX4W_cjs.ErrorBanner; }
|
|
2232
2232
|
});
|
|
2233
2233
|
Object.defineProperty(exports, "HOTKEYS", {
|
|
2234
2234
|
enumerable: true,
|
|
2235
|
-
get: function () { return
|
|
2235
|
+
get: function () { return chunkTAEHNX4W_cjs.HOTKEYS; }
|
|
2236
2236
|
});
|
|
2237
2237
|
Object.defineProperty(exports, "JumpToLatest", {
|
|
2238
2238
|
enumerable: true,
|
|
2239
|
-
get: function () { return
|
|
2239
|
+
get: function () { return chunkTAEHNX4W_cjs.JumpToLatest; }
|
|
2240
2240
|
});
|
|
2241
2241
|
Object.defineProperty(exports, "LIMITS", {
|
|
2242
2242
|
enumerable: true,
|
|
2243
|
-
get: function () { return
|
|
2243
|
+
get: function () { return chunkTAEHNX4W_cjs.LIMITS; }
|
|
2244
2244
|
});
|
|
2245
2245
|
Object.defineProperty(exports, "MessageActions", {
|
|
2246
2246
|
enumerable: true,
|
|
2247
|
-
get: function () { return
|
|
2247
|
+
get: function () { return chunkTAEHNX4W_cjs.MessageActions; }
|
|
2248
2248
|
});
|
|
2249
2249
|
Object.defineProperty(exports, "MessageBubble", {
|
|
2250
2250
|
enumerable: true,
|
|
2251
|
-
get: function () { return
|
|
2251
|
+
get: function () { return chunkTAEHNX4W_cjs.MessageBubble; }
|
|
2252
2252
|
});
|
|
2253
2253
|
Object.defineProperty(exports, "MessageList", {
|
|
2254
2254
|
enumerable: true,
|
|
2255
|
-
get: function () { return
|
|
2255
|
+
get: function () { return chunkTAEHNX4W_cjs.MessageList; }
|
|
2256
2256
|
});
|
|
2257
2257
|
Object.defineProperty(exports, "STORAGE_KEYS", {
|
|
2258
2258
|
enumerable: true,
|
|
2259
|
-
get: function () { return
|
|
2259
|
+
get: function () { return chunkTAEHNX4W_cjs.STORAGE_KEYS; }
|
|
2260
2260
|
});
|
|
2261
2261
|
Object.defineProperty(exports, "Sources", {
|
|
2262
2262
|
enumerable: true,
|
|
2263
|
-
get: function () { return
|
|
2263
|
+
get: function () { return chunkTAEHNX4W_cjs.Sources; }
|
|
2264
2264
|
});
|
|
2265
2265
|
Object.defineProperty(exports, "StreamingIndicator", {
|
|
2266
2266
|
enumerable: true,
|
|
2267
|
-
get: function () { return
|
|
2267
|
+
get: function () { return chunkTAEHNX4W_cjs.StreamingIndicator; }
|
|
2268
2268
|
});
|
|
2269
2269
|
Object.defineProperty(exports, "ToolCalls", {
|
|
2270
2270
|
enumerable: true,
|
|
2271
|
-
get: function () { return
|
|
2271
|
+
get: function () { return chunkTAEHNX4W_cjs.ToolCalls; }
|
|
2272
2272
|
});
|
|
2273
2273
|
Object.defineProperty(exports, "createId", {
|
|
2274
2274
|
enumerable: true,
|
|
2275
|
-
get: function () { return
|
|
2275
|
+
get: function () { return chunkTAEHNX4W_cjs.createId; }
|
|
2276
2276
|
});
|
|
2277
2277
|
Object.defineProperty(exports, "createTokenBuffer", {
|
|
2278
2278
|
enumerable: true,
|
|
2279
|
-
get: function () { return
|
|
2279
|
+
get: function () { return chunkTAEHNX4W_cjs.createTokenBuffer; }
|
|
2280
2280
|
});
|
|
2281
2281
|
Object.defineProperty(exports, "deriveInitials", {
|
|
2282
2282
|
enumerable: true,
|
|
2283
|
-
get: function () { return
|
|
2283
|
+
get: function () { return chunkTAEHNX4W_cjs.deriveInitials; }
|
|
2284
2284
|
});
|
|
2285
2285
|
Object.defineProperty(exports, "getChatLogger", {
|
|
2286
2286
|
enumerable: true,
|
|
2287
|
-
get: function () { return
|
|
2287
|
+
get: function () { return chunkTAEHNX4W_cjs.getChatLogger; }
|
|
2288
2288
|
});
|
|
2289
2289
|
Object.defineProperty(exports, "initialState", {
|
|
2290
2290
|
enumerable: true,
|
|
2291
|
-
get: function () { return
|
|
2291
|
+
get: function () { return chunkTAEHNX4W_cjs.initialState; }
|
|
2292
2292
|
});
|
|
2293
2293
|
Object.defineProperty(exports, "reducer", {
|
|
2294
2294
|
enumerable: true,
|
|
2295
|
-
get: function () { return
|
|
2295
|
+
get: function () { return chunkTAEHNX4W_cjs.reducer; }
|
|
2296
2296
|
});
|
|
2297
2297
|
Object.defineProperty(exports, "resolvePersona", {
|
|
2298
2298
|
enumerable: true,
|
|
2299
|
-
get: function () { return
|
|
2299
|
+
get: function () { return chunkTAEHNX4W_cjs.resolvePersona; }
|
|
2300
2300
|
});
|
|
2301
2301
|
Object.defineProperty(exports, "useChat", {
|
|
2302
2302
|
enumerable: true,
|
|
2303
|
-
get: function () { return
|
|
2303
|
+
get: function () { return chunkTAEHNX4W_cjs.useChat; }
|
|
2304
2304
|
});
|
|
2305
2305
|
Object.defineProperty(exports, "useChatAudio", {
|
|
2306
2306
|
enumerable: true,
|
|
2307
|
-
get: function () { return
|
|
2307
|
+
get: function () { return chunkTAEHNX4W_cjs.useChatAudio; }
|
|
2308
2308
|
});
|
|
2309
2309
|
Object.defineProperty(exports, "useChatAudioPrefs", {
|
|
2310
2310
|
enumerable: true,
|
|
2311
|
-
get: function () { return
|
|
2311
|
+
get: function () { return chunkTAEHNX4W_cjs.useChatAudioPrefs; }
|
|
2312
2312
|
});
|
|
2313
2313
|
Object.defineProperty(exports, "useChatComposer", {
|
|
2314
2314
|
enumerable: true,
|
|
2315
|
-
get: function () { return
|
|
2315
|
+
get: function () { return chunkTAEHNX4W_cjs.useChatComposer; }
|
|
2316
2316
|
});
|
|
2317
2317
|
Object.defineProperty(exports, "useChatContext", {
|
|
2318
2318
|
enumerable: true,
|
|
2319
|
-
get: function () { return
|
|
2319
|
+
get: function () { return chunkTAEHNX4W_cjs.useChatContext; }
|
|
2320
2320
|
});
|
|
2321
2321
|
Object.defineProperty(exports, "useChatContextOptional", {
|
|
2322
2322
|
enumerable: true,
|
|
2323
|
-
get: function () { return
|
|
2323
|
+
get: function () { return chunkTAEHNX4W_cjs.useChatContextOptional; }
|
|
2324
2324
|
});
|
|
2325
2325
|
Object.defineProperty(exports, "useChatLayout", {
|
|
2326
2326
|
enumerable: true,
|
|
2327
|
-
get: function () { return
|
|
2327
|
+
get: function () { return chunkTAEHNX4W_cjs.useChatLayout; }
|
|
2328
2328
|
});
|
|
2329
2329
|
Object.defineProperty(exports, "TreeError", {
|
|
2330
2330
|
enumerable: true,
|
package/dist/index.d.cts
CHANGED
|
@@ -2413,9 +2413,12 @@ interface MessageListProps {
|
|
|
2413
2413
|
*/
|
|
2414
2414
|
noVirtualize?: boolean;
|
|
2415
2415
|
/**
|
|
2416
|
-
*
|
|
2417
|
-
*
|
|
2418
|
-
*
|
|
2416
|
+
* @deprecated No-op as of 2.1.373. We intentionally let Virtuoso run
|
|
2417
|
+
* its first-item probe pass: cmdop bubbles vary from 40px (one-line
|
|
2418
|
+
* user message) to 800px (markdown with code blocks), so any single
|
|
2419
|
+
* estimate fed here forces a measure/reshape loop on every render.
|
|
2420
|
+
* The kept prop avoids a breaking-change bump for hosts that still
|
|
2421
|
+
* pass it explicitly.
|
|
2419
2422
|
*/
|
|
2420
2423
|
defaultItemHeight?: number;
|
|
2421
2424
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -2413,9 +2413,12 @@ interface MessageListProps {
|
|
|
2413
2413
|
*/
|
|
2414
2414
|
noVirtualize?: boolean;
|
|
2415
2415
|
/**
|
|
2416
|
-
*
|
|
2417
|
-
*
|
|
2418
|
-
*
|
|
2416
|
+
* @deprecated No-op as of 2.1.373. We intentionally let Virtuoso run
|
|
2417
|
+
* its first-item probe pass: cmdop bubbles vary from 40px (one-line
|
|
2418
|
+
* user message) to 800px (markdown with code blocks), so any single
|
|
2419
|
+
* estimate fed here forces a measure/reshape loop on every render.
|
|
2420
|
+
* The kept prop avoids a breaking-change bump for hosts that still
|
|
2421
|
+
* pass it explicitly.
|
|
2419
2422
|
*/
|
|
2420
2423
|
defaultItemHeight?: number;
|
|
2421
2424
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -5,8 +5,8 @@ export { NativeProvider, StreamProvider, VideoControls, VideoErrorFallback, Vide
|
|
|
5
5
|
export { ImageViewer } from './chunk-OBRSGM64.mjs';
|
|
6
6
|
export { generateContentKey, useAudioCache, useBlobUrlCleanup, useImageCache, useMediaCacheStore, useVideoCache, useVideoPlayerSettings } from './chunk-C6GXVH5J.mjs';
|
|
7
7
|
export { CronSchedulerProvider, CustomInput, DayChips, MonthDayGrid, SchedulePreview, ScheduleTypeSelector, TimeSelector, buildCron, humanizeCron, isValidCron, parseCron, useCronCustom, useCronMonthDays, useCronPreview, useCronScheduler, useCronSchedulerContext, useCronTime, useCronType, useCronWeekDays } from './chunk-PVAX67JG.mjs';
|
|
8
|
-
import { LIMITS, createId, useChatAudioPrefs, useChatContextOptional } from './chunk-
|
|
9
|
-
export { Attachments, AttachmentsGrid, AttachmentsList, CHAT_EVENT_NAME, CSS_VARS, ChatProvider, ChatRoot, Composer, DEFAULT_LABELS, DEFAULT_SIDEBAR, DEFAULT_Z_INDEX, EmptyState, ErrorBanner, HOTKEYS, JumpToLatest, LIMITS, MessageActions, MessageBubble, MessageList, STORAGE_KEYS, Sources, StreamingIndicator, ToolCalls, createId, createTokenBuffer, deriveInitials, getChatLogger, initialState, reducer, resolvePersona, useChat, useChatAudio, useChatAudioPrefs, useChatComposer, useChatContext, useChatContextOptional, useChatLayout } from './chunk-
|
|
8
|
+
import { LIMITS, createId, useChatAudioPrefs, useChatContextOptional } from './chunk-PSM3DUTC.mjs';
|
|
9
|
+
export { Attachments, AttachmentsGrid, AttachmentsList, CHAT_EVENT_NAME, CSS_VARS, ChatProvider, ChatRoot, Composer, DEFAULT_LABELS, DEFAULT_SIDEBAR, DEFAULT_Z_INDEX, EmptyState, ErrorBanner, HOTKEYS, JumpToLatest, LIMITS, MessageActions, MessageBubble, MessageList, STORAGE_KEYS, Sources, StreamingIndicator, ToolCalls, createId, createTokenBuffer, deriveInitials, getChatLogger, initialState, reducer, resolvePersona, useChat, useChatAudio, useChatAudioPrefs, useChatComposer, useChatContext, useChatContextOptional, useChatLayout } from './chunk-PSM3DUTC.mjs';
|
|
10
10
|
export { TreeError, TreeSkeleton, createDemoTree } from './chunk-B6IR5KSC.mjs';
|
|
11
11
|
export { DEFAULT_TREE_APPEARANCE, DEFAULT_TREE_LABELS, TreeRoot as Tree, TreeChevron, TreeContent, TreeEmpty, TreeIcon, TreeIndentGuides, TreeLabel, TreeProvider, TreeRoot, TreeRow, TreeSearchInput, appearanceToStyle, clearTreeState, createChildCache, flattenTree, loadTreeState, resolveAppearance, resolveChildren, saveTreeState, useTreeActions, useTreeContext, useTreeExpansion, useTreeFocus, useTreeKeyboard, useTreeLabels, useTreeRows, useTreeSearch, useTreeSelection, useTreeTypeAhead } from './chunk-ZL7FH4NW.mjs';
|
|
12
12
|
import { PlaygroundProvider } from './chunk-Y6UTOBF6.mjs';
|
|
@@ -348,7 +348,7 @@ var LazyTree = createLazyComponent(
|
|
|
348
348
|
}
|
|
349
349
|
);
|
|
350
350
|
var LazyChat = createLazyComponent(
|
|
351
|
-
() => import('./ChatRoot-
|
|
351
|
+
() => import('./ChatRoot-RIETBE55.mjs').then((m) => ({ default: m.ChatRoot })),
|
|
352
352
|
{
|
|
353
353
|
displayName: "LazyChat",
|
|
354
354
|
fallback: /* @__PURE__ */ jsx(LoadingFallback, { minHeight: 320, text: "Loading chat\u2026" })
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ui-tools",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.373",
|
|
4
4
|
"description": "Heavy React tools with lazy loading - for Electron, Vite, CRA, Next.js apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ui-tools",
|
|
@@ -156,8 +156,8 @@
|
|
|
156
156
|
"check": "tsc --noEmit"
|
|
157
157
|
},
|
|
158
158
|
"peerDependencies": {
|
|
159
|
-
"@djangocfg/i18n": "^2.1.
|
|
160
|
-
"@djangocfg/ui-core": "^2.1.
|
|
159
|
+
"@djangocfg/i18n": "^2.1.373",
|
|
160
|
+
"@djangocfg/ui-core": "^2.1.373",
|
|
161
161
|
"consola": "^3.4.2",
|
|
162
162
|
"lodash-es": "^4.18.1",
|
|
163
163
|
"lucide-react": "^0.545.0",
|
|
@@ -211,10 +211,10 @@
|
|
|
211
211
|
"material-file-icons": "^2.4.0"
|
|
212
212
|
},
|
|
213
213
|
"devDependencies": {
|
|
214
|
-
"@djangocfg/i18n": "^2.1.
|
|
214
|
+
"@djangocfg/i18n": "^2.1.373",
|
|
215
215
|
"@djangocfg/playground": "workspace:*",
|
|
216
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
217
|
-
"@djangocfg/ui-core": "^2.1.
|
|
216
|
+
"@djangocfg/typescript-config": "^2.1.373",
|
|
217
|
+
"@djangocfg/ui-core": "^2.1.373",
|
|
218
218
|
"@types/lodash-es": "^4.17.12",
|
|
219
219
|
"@types/mapbox__mapbox-gl-draw": "^1.4.8",
|
|
220
220
|
"@types/node": "^24.7.2",
|
|
@@ -1110,3 +1110,174 @@ export const Playground = () => {
|
|
|
1110
1110
|
</div>
|
|
1111
1111
|
);
|
|
1112
1112
|
};
|
|
1113
|
+
|
|
1114
|
+
// ---------------------------------------------------------------------------
|
|
1115
|
+
// 15) WailsLikeVirtualization — stress-test for the virtuoso integration
|
|
1116
|
+
//
|
|
1117
|
+
// Mirrors the cmdop-desktop (Wails) chat use case that drove the
|
|
1118
|
+
// plan64 migration:
|
|
1119
|
+
// - 200 pre-loaded history bubbles of varying heights (short, long
|
|
1120
|
+
// prose, code blocks, tool calls) — exercises Virtuoso's dynamic
|
|
1121
|
+
// measurement path and the bug where bubbles "disappeared" when
|
|
1122
|
+
// scrolling to the bottom.
|
|
1123
|
+
// - Streamed reply with token-by-token deltas — exercises
|
|
1124
|
+
// `followOutput` sticky-bottom behaviour.
|
|
1125
|
+
// - Tool call mid-stream — exercises bubble-resize during streaming
|
|
1126
|
+
// (the second virtuoso jitter source).
|
|
1127
|
+
//
|
|
1128
|
+
// Use this story to verify:
|
|
1129
|
+
// 1. Mount → viewport lands at the last bubble, not the top.
|
|
1130
|
+
// 2. Scroll up → JumpToLatest pill appears; click → smooth jump.
|
|
1131
|
+
// 3. Sit at the bottom → streaming reply tracks without flicker.
|
|
1132
|
+
// 4. Drag scrollbar to the very bottom → bubbles stay visible (no
|
|
1133
|
+
// empty viewport).
|
|
1134
|
+
// ---------------------------------------------------------------------------
|
|
1135
|
+
|
|
1136
|
+
function makeWailsLikeHistory(count: number): ChatMessage[] {
|
|
1137
|
+
// Mix of bubble shapes so virtuoso has to measure heterogeneous
|
|
1138
|
+
// heights instead of locking onto one cheap estimate.
|
|
1139
|
+
const SHORT_USER = 'Quick ping — can you check the latest deploy?';
|
|
1140
|
+
const SHORT_AI = 'Yes, all clear. CI passed, no regressions.';
|
|
1141
|
+
const LONG_PROSE =
|
|
1142
|
+
'Sure, here is the rundown.\n\nThe service has been migrated to the new transport layer. The reducer split is in plan64 phase 4, and the audio cues now respect `prefers-reduced-motion`.\n\n' +
|
|
1143
|
+
'A few things to double-check before we sign off:\n\n' +
|
|
1144
|
+
'- The auto-scroll behaviour on streaming chunks\n' +
|
|
1145
|
+
'- Tool-call panels expanding mid-stream\n' +
|
|
1146
|
+
'- The mention popup positioning inside the composer\n\n' +
|
|
1147
|
+
'Let me know if any of those need a second pass.';
|
|
1148
|
+
const CODE_REPLY =
|
|
1149
|
+
'Here is the snippet you asked for:\n\n```ts\n' +
|
|
1150
|
+
'export function createWailsTransport(): ChatTransport {\n' +
|
|
1151
|
+
' return {\n' +
|
|
1152
|
+
' async *stream(sid, content, { signal }) {\n' +
|
|
1153
|
+
' const queue = createAsyncQueue<ChatStreamEvent>();\n' +
|
|
1154
|
+
' const off = subscribeChatStreamEvents(sid, (e) => queue.push(e));\n' +
|
|
1155
|
+
' try {\n' +
|
|
1156
|
+
' await ChatService.SendMessage(sid, content);\n' +
|
|
1157
|
+
' for await (const evt of queue) {\n' +
|
|
1158
|
+
' yield evt;\n' +
|
|
1159
|
+
' if (isTerminalStreamEvent(evt)) break;\n' +
|
|
1160
|
+
' }\n' +
|
|
1161
|
+
' } finally {\n' +
|
|
1162
|
+
' off(); queue.close();\n' +
|
|
1163
|
+
' }\n' +
|
|
1164
|
+
' },\n' +
|
|
1165
|
+
' };\n' +
|
|
1166
|
+
'}\n' +
|
|
1167
|
+
'```\n\nDoes that match what you had in mind?';
|
|
1168
|
+
|
|
1169
|
+
const shapes: Array<(i: number) => ChatMessage> = [
|
|
1170
|
+
(i) => ({
|
|
1171
|
+
id: `u${i}`,
|
|
1172
|
+
role: 'user',
|
|
1173
|
+
content: SHORT_USER,
|
|
1174
|
+
createdAt: Date.now() - (count - i) * 10_000,
|
|
1175
|
+
}),
|
|
1176
|
+
(i) => ({
|
|
1177
|
+
id: `a${i}`,
|
|
1178
|
+
role: 'assistant',
|
|
1179
|
+
content: SHORT_AI,
|
|
1180
|
+
createdAt: Date.now() - (count - i) * 10_000,
|
|
1181
|
+
}),
|
|
1182
|
+
(i) => ({
|
|
1183
|
+
id: `a${i}`,
|
|
1184
|
+
role: 'assistant',
|
|
1185
|
+
content: LONG_PROSE,
|
|
1186
|
+
createdAt: Date.now() - (count - i) * 10_000,
|
|
1187
|
+
}),
|
|
1188
|
+
(i) => ({
|
|
1189
|
+
id: `a${i}`,
|
|
1190
|
+
role: 'assistant',
|
|
1191
|
+
content: CODE_REPLY,
|
|
1192
|
+
createdAt: Date.now() - (count - i) * 10_000,
|
|
1193
|
+
}),
|
|
1194
|
+
(i) => ({
|
|
1195
|
+
id: `a${i}`,
|
|
1196
|
+
role: 'assistant',
|
|
1197
|
+
content: 'Running diagnostics…',
|
|
1198
|
+
createdAt: Date.now() - (count - i) * 10_000,
|
|
1199
|
+
toolCalls: [
|
|
1200
|
+
{
|
|
1201
|
+
id: `t${i}`,
|
|
1202
|
+
name: 'read_file',
|
|
1203
|
+
input: { path: `/var/log/app-${i}.log`, lines: 50 },
|
|
1204
|
+
output: { ok: true, bytes: 4096 + (i % 7) * 512 },
|
|
1205
|
+
status: 'success',
|
|
1206
|
+
startedAt: Date.now() - (count - i) * 10_000,
|
|
1207
|
+
endedAt: Date.now() - (count - i) * 10_000 + 250,
|
|
1208
|
+
},
|
|
1209
|
+
],
|
|
1210
|
+
}),
|
|
1211
|
+
];
|
|
1212
|
+
|
|
1213
|
+
return Array.from({ length: count }, (_, i) => shapes[i % shapes.length](i));
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
export const WailsLikeVirtualization = () => {
|
|
1217
|
+
const [count] = useSelect('history', {
|
|
1218
|
+
options: ['50', '200', '500', '1000'] as const,
|
|
1219
|
+
defaultValue: '200',
|
|
1220
|
+
label: 'History size',
|
|
1221
|
+
});
|
|
1222
|
+
|
|
1223
|
+
// Pre-seeded history simulating a long-running cmdop session.
|
|
1224
|
+
// `resumeSession` is the key bit: the mock transport returns these
|
|
1225
|
+
// as `SessionInfo.messages` so they're available at mount time
|
|
1226
|
+
// (mirrors `ChatService.GetHistoryPaginated` on the Wails side).
|
|
1227
|
+
const history = useMemo(() => makeWailsLikeHistory(Number(count)), [count]);
|
|
1228
|
+
|
|
1229
|
+
const transport = useMemo(() => {
|
|
1230
|
+
const sequence: ChatStreamEvent[] = [
|
|
1231
|
+
{ type: 'chunk', delta: 'Let me pull the latest stats.\n\n' },
|
|
1232
|
+
{
|
|
1233
|
+
type: 'tool_call_start',
|
|
1234
|
+
toolId: 'live-1',
|
|
1235
|
+
name: 'fetch_metrics',
|
|
1236
|
+
input: { window: '15m' },
|
|
1237
|
+
},
|
|
1238
|
+
{ type: 'tool_call_delta', toolId: 'live-1', delta: 'connecting…\n' },
|
|
1239
|
+
{ type: 'tool_call_delta', toolId: 'live-1', delta: 'fetched 3214 rows\n' },
|
|
1240
|
+
{
|
|
1241
|
+
type: 'tool_call_end',
|
|
1242
|
+
toolId: 'live-1',
|
|
1243
|
+
output: { rows: 3214, p95_ms: 142, errors: 0 },
|
|
1244
|
+
status: 'success',
|
|
1245
|
+
},
|
|
1246
|
+
{
|
|
1247
|
+
type: 'chunk',
|
|
1248
|
+
delta:
|
|
1249
|
+
'All green:\n\n- **3214 rows** in the last 15 min\n- **p95 latency**: 142 ms\n- **errors**: 0\n\n',
|
|
1250
|
+
},
|
|
1251
|
+
{
|
|
1252
|
+
type: 'chunk',
|
|
1253
|
+
delta:
|
|
1254
|
+
'If you want to stress-test virtualization, scroll up and check the JumpToLatest pill — it should appear once you move out of the sticky-bottom zone.',
|
|
1255
|
+
},
|
|
1256
|
+
{ type: 'message_end' },
|
|
1257
|
+
];
|
|
1258
|
+
return createMockTransport({
|
|
1259
|
+
replies: [sequence, sequence, sequence],
|
|
1260
|
+
latencyMs: 25,
|
|
1261
|
+
// Mock transport returns `initialMessages` from `createSession`
|
|
1262
|
+
// as `SessionInfo.messages` — mimics the Wails path where the
|
|
1263
|
+
// default chat session resumes with its on-disk history.
|
|
1264
|
+
initialMessages: history,
|
|
1265
|
+
});
|
|
1266
|
+
}, [history]);
|
|
1267
|
+
|
|
1268
|
+
return (
|
|
1269
|
+
<Frame h={620} w={520}>
|
|
1270
|
+
<ChatRoot
|
|
1271
|
+
transport={transport}
|
|
1272
|
+
config={{
|
|
1273
|
+
greeting: `Wails-like session — ${history.length} bubbles preloaded`,
|
|
1274
|
+
description:
|
|
1275
|
+
'Stress test for the virtuoso integration: long history, dynamic bubble heights, streaming tool calls. Scroll to the bottom; bubbles must stay visible. Streaming should follow without flicker.',
|
|
1276
|
+
placeholder: 'Send a message to trigger a streamed reply…',
|
|
1277
|
+
user: { name: 'Mark', initials: 'MO' },
|
|
1278
|
+
assistant: { name: 'cmdop', initials: 'CM' },
|
|
1279
|
+
}}
|
|
1280
|
+
/>
|
|
1281
|
+
</Frame>
|
|
1282
|
+
);
|
|
1283
|
+
};
|
|
@@ -55,9 +55,12 @@ export interface MessageListProps {
|
|
|
55
55
|
*/
|
|
56
56
|
noVirtualize?: boolean;
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
58
|
+
* @deprecated No-op as of 2.1.373. We intentionally let Virtuoso run
|
|
59
|
+
* its first-item probe pass: cmdop bubbles vary from 40px (one-line
|
|
60
|
+
* user message) to 800px (markdown with code blocks), so any single
|
|
61
|
+
* estimate fed here forces a measure/reshape loop on every render.
|
|
62
|
+
* The kept prop avoids a breaking-change bump for hosts that still
|
|
63
|
+
* pass it explicitly.
|
|
61
64
|
*/
|
|
62
65
|
defaultItemHeight?: number;
|
|
63
66
|
/**
|
|
@@ -85,11 +88,12 @@ export const MessageList = forwardRef<MessageListHandle, MessageListProps>(funct
|
|
|
85
88
|
className,
|
|
86
89
|
itemClassName,
|
|
87
90
|
noVirtualize = false,
|
|
88
|
-
defaultItemHeight
|
|
91
|
+
defaultItemHeight: _deprecatedDefaultItemHeight,
|
|
89
92
|
onAtBottomChange,
|
|
90
93
|
},
|
|
91
94
|
ref,
|
|
92
95
|
) {
|
|
96
|
+
void _deprecatedDefaultItemHeight;
|
|
93
97
|
const ctx = useChatContextOptional();
|
|
94
98
|
const messages = messagesProp ?? ctx?.messages ?? [];
|
|
95
99
|
const isLoadingMore = isLoadingMoreProp ?? ctx?.isLoadingMore ?? false;
|
|
@@ -238,26 +242,31 @@ export const MessageList = forwardRef<MessageListHandle, MessageListProps>(funct
|
|
|
238
242
|
data={messages}
|
|
239
243
|
computeItemKey={computeItemKey}
|
|
240
244
|
itemContent={(index, m) => (m ? itemRenderer(m, index) : null)}
|
|
241
|
-
defaultItemHeight
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
//
|
|
245
|
+
// No `defaultItemHeight` — Virtuoso uses its first-item probe
|
|
246
|
+
// pass. We previously fed it `120` which was wildly low for
|
|
247
|
+
// chat bubbles (markdown + code blocks reach 500px+) and forced
|
|
248
|
+
// virtuoso into a measure/reshape loop on every render: predicted
|
|
249
|
+
// height << real height → page recompute → measure → repeat,
|
|
250
|
+
// visible as jittery scrolling and bubbles "blinking" in and out.
|
|
251
|
+
// The probe pass costs one extra render on mount; that's cheaper
|
|
252
|
+
// than perpetual reshape.
|
|
253
|
+
//
|
|
254
|
+
// No `alignToBottom` — it only matters when the list is shorter
|
|
255
|
+
// than the viewport (centers items near the bottom). Combined
|
|
256
|
+
// with dynamic bubble heights it triggered the same measure loop:
|
|
257
|
+
// virtuoso recomputes top padding on every size change to keep
|
|
258
|
+
// the cluster bottom-aligned. `initialTopMostItemIndex` + the
|
|
259
|
+
// mount-time imperative scroll already land us at the bottom on
|
|
260
|
+
// open, which is what users actually want.
|
|
261
|
+
//
|
|
262
|
+
// No `increaseViewportBy` overscan — virtuoso's default (~0px)
|
|
263
|
+
// is the right call for chat: every overscanned bubble re-renders
|
|
264
|
+
// on every streaming token delta, so a 400px buffer means 3–4
|
|
265
|
+
// extra bubbles re-rendering at 60Hz during a stream. Default
|
|
266
|
+
// keeps the working set tight.
|
|
248
267
|
initialTopMostItemIndex={messages.length > 0 ? messages.length - 1 : 0}
|
|
249
|
-
// Sticky-bottom: keep the viewport anchored to the latest message
|
|
250
|
-
// unless the user scrolled up. `'smooth'` while streaming would
|
|
251
|
-
// jank; Virtuoso defaults to `'auto'` which is what we want.
|
|
252
268
|
followOutput={(isAtBottom) => (isAtBottom ? 'auto' : false)}
|
|
253
269
|
atBottomStateChange={onAtBottomChange}
|
|
254
|
-
// Pad the list so a short conversation still hugs the bottom of
|
|
255
|
-
// the viewport (Telegram / iMessage feel) instead of stacking at
|
|
256
|
-
// the top.
|
|
257
|
-
alignToBottom
|
|
258
|
-
// Top-of-list pagination — fire when the topmost item enters the
|
|
259
|
-
// viewport. Virtuoso pauses this until `data` grows, so loadMore
|
|
260
|
-
// implementations don't need their own debounce.
|
|
261
270
|
startReached={startReachedHandler}
|
|
262
271
|
// Spinner while older history is loading. Rendering it as the
|
|
263
272
|
// Header keeps it inside the virtualized scroll, so it doesn't
|
|
@@ -278,10 +287,6 @@ export const MessageList = forwardRef<MessageListHandle, MessageListProps>(funct
|
|
|
278
287
|
}
|
|
279
288
|
: EMPTY_COMPONENTS
|
|
280
289
|
}
|
|
281
|
-
// Item height is dynamic; Virtuoso re-measures on resize. We
|
|
282
|
-
// bias the initial overscan a bit so streaming-token re-layout
|
|
283
|
-
// doesn't leave gaps before the next measurement lands.
|
|
284
|
-
increaseViewportBy={{ top: 200, bottom: 400 }}
|
|
285
290
|
/>
|
|
286
291
|
);
|
|
287
292
|
});
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkA6DDYQQV_cjs = require('./chunk-A6DDYQQV.cjs');
|
|
4
|
-
require('./chunk-XACCHZH2.cjs');
|
|
5
|
-
require('./chunk-OLISEQHS.cjs');
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Object.defineProperty(exports, "ChatRoot", {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
get: function () { return chunkA6DDYQQV_cjs.ChatRoot; }
|
|
12
|
-
});
|
|
13
|
-
//# sourceMappingURL=ChatRoot-AD2JIUIU.cjs.map
|
|
14
|
-
//# sourceMappingURL=ChatRoot-AD2JIUIU.cjs.map
|