@linxin666/dsh-remote-web-ui 0.3.5 → 0.3.6
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/lib/client.js +1 -1
- package/lib/mobile.js +47 -10
- package/lib/mobile.js.map +1 -1
- package/lib/types/mobile/messages.d.ts +13 -5
- package/lib/types/mobile/messages.d.ts.map +1 -1
- package/lib/types/mobile/messages.js +13 -5
- package/lib/types/mobile/views/ChatView.d.ts +7 -0
- package/lib/types/mobile/views/ChatView.d.ts.map +1 -1
- package/lib/types/mobile/views/ChatView.js +53 -5
- package/lib/types/mobile/views/ChatView.stream.test.js +8 -3
- package/package.json +1 -1
- package/src/mobile/messages.ts +13 -5
- package/src/mobile/views/ChatView.stream.test.tsx +8 -3
- package/src/mobile/views/ChatView.tsx +52 -5
package/lib/client.js
CHANGED
package/lib/mobile.js
CHANGED
|
@@ -13475,11 +13475,19 @@ function foldEvents(events, existing) {
|
|
|
13475
13475
|
* Incremental folder for one message stream. Live chat folds one event at a
|
|
13476
13476
|
* time; rebuilding the five index maps by scanning every message per event
|
|
13477
13477
|
* made that path O(n) per event (O(n * events) per turn). A folder keeps the
|
|
13478
|
-
* indexes alive across folds, applies each event in O(1) map
|
|
13479
|
-
* returns the previous snapshot identity unchanged when
|
|
13480
|
-
* React skips the re-render entirely. Replayed events
|
|
13481
|
-
* watermark advanced by the first application skips
|
|
13482
|
-
* double-invoked React state updater harmless.
|
|
13478
|
+
* indexes alive across folds, applies each event in (near-)O(1) map
|
|
13479
|
+
* operations, and returns the previous snapshot identity unchanged when
|
|
13480
|
+
* nothing applied, so React skips the re-render entirely. Replayed events
|
|
13481
|
+
* are no-ops: the maxSeq watermark advanced by the first application skips
|
|
13482
|
+
* them, which also makes a double-invoked React state updater harmless.
|
|
13483
|
+
*
|
|
13484
|
+
* Cost contract: every fold that applies at least one event rebuilds the
|
|
13485
|
+
* snapshot as one fresh O(messages) array copy (React needs the new
|
|
13486
|
+
* identity), and replacement paths locate rows by an O(messages) identity
|
|
13487
|
+
* scan. Both are amortized by the consumer folding bursts as ONE batch on a
|
|
13488
|
+
* fixed cadence (see FOLD_FLUSH_MS in ChatView) instead of per event. An
|
|
13489
|
+
* id-to-index map was measured and deliberately rejected: at realistic
|
|
13490
|
+
* message counts the Map maintenance cost exceeds the identity-scan cost.
|
|
13483
13491
|
*/
|
|
13484
13492
|
var EventFolder = class {
|
|
13485
13493
|
state;
|
|
@@ -14023,6 +14031,14 @@ function ChatView({ session, mux, onBack }) {
|
|
|
14023
14031
|
const liveBufferRef = (0, import_react.useRef)([]);
|
|
14024
14032
|
/** Incremental folder for this session's stream (indexes stay hot across events). */
|
|
14025
14033
|
const folderRef = (0, import_react.useRef)(void 0);
|
|
14034
|
+
/**
|
|
14035
|
+
* Live events buffered between fold flushes. Folding every single event
|
|
14036
|
+
* costs one O(messages) snapshot copy per event; flushing at a fixed
|
|
14037
|
+
* cadence folds each burst once while keeping streaming text fluid.
|
|
14038
|
+
*/
|
|
14039
|
+
const foldBufferRef = (0, import_react.useRef)([]);
|
|
14040
|
+
/** Timer id of the scheduled fold flush, if any. */
|
|
14041
|
+
const foldFlushTimerRef = (0, import_react.useRef)(void 0);
|
|
14026
14042
|
/** True once the live buffer hit its cap (oldest events were dropped). */
|
|
14027
14043
|
const liveBufferOverflowRef = (0, import_react.useRef)(false);
|
|
14028
14044
|
/** The session's permission select (absent = capability not composed). */
|
|
@@ -14115,7 +14131,21 @@ function ChatView({ session, mux, onBack }) {
|
|
|
14115
14131
|
}, [session.sessionId]);
|
|
14116
14132
|
(0, import_react.useEffect)(() => {
|
|
14117
14133
|
if (mux === void 0) return;
|
|
14118
|
-
|
|
14134
|
+
/** Fold every buffered live event in one batch and publish the snapshot. */
|
|
14135
|
+
const flushFoldBuffer = () => {
|
|
14136
|
+
if (foldFlushTimerRef.current !== void 0) {
|
|
14137
|
+
clearTimeout(foldFlushTimerRef.current);
|
|
14138
|
+
foldFlushTimerRef.current = void 0;
|
|
14139
|
+
}
|
|
14140
|
+
const events = foldBufferRef.current;
|
|
14141
|
+
if (events.length === 0) return;
|
|
14142
|
+
foldBufferRef.current = [];
|
|
14143
|
+
setMessages((previous) => {
|
|
14144
|
+
const folder = folderRef.current;
|
|
14145
|
+
return folder === void 0 ? foldEvents(events, previous) : folder.fold(events);
|
|
14146
|
+
});
|
|
14147
|
+
};
|
|
14148
|
+
const unsubscribe = mux.onFrame((frame) => {
|
|
14119
14149
|
if (frame.type === "session/event") {
|
|
14120
14150
|
if (frame.sessionId !== session.sessionId) return;
|
|
14121
14151
|
const event = frame.event;
|
|
@@ -14134,10 +14164,9 @@ function ChatView({ session, mux, onBack }) {
|
|
|
14134
14164
|
liveBufferRef.current.push(event);
|
|
14135
14165
|
return;
|
|
14136
14166
|
}
|
|
14137
|
-
|
|
14138
|
-
|
|
14139
|
-
|
|
14140
|
-
});
|
|
14167
|
+
foldBufferRef.current.push(event);
|
|
14168
|
+
if (!(event.type === "assistant/chunk" || event.type === "message/chunk")) flushFoldBuffer();
|
|
14169
|
+
else if (foldFlushTimerRef.current === void 0) foldFlushTimerRef.current = setTimeout(flushFoldBuffer, 50);
|
|
14141
14170
|
return;
|
|
14142
14171
|
}
|
|
14143
14172
|
if (frame.type === "session/projection" && frame.sessionId === session.sessionId && frame.key === "permissions") {
|
|
@@ -14171,6 +14200,14 @@ function ChatView({ session, mux, onBack }) {
|
|
|
14171
14200
|
return;
|
|
14172
14201
|
}
|
|
14173
14202
|
});
|
|
14203
|
+
return () => {
|
|
14204
|
+
unsubscribe();
|
|
14205
|
+
if (foldFlushTimerRef.current !== void 0) {
|
|
14206
|
+
clearTimeout(foldFlushTimerRef.current);
|
|
14207
|
+
foldFlushTimerRef.current = void 0;
|
|
14208
|
+
}
|
|
14209
|
+
foldBufferRef.current = [];
|
|
14210
|
+
};
|
|
14174
14211
|
}, [mux, session.sessionId]);
|
|
14175
14212
|
(0, import_react.useEffect)(() => {
|
|
14176
14213
|
if (!running) return;
|