@yeaft/webchat-agent 1.0.54 → 1.0.56

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "1.0.54",
3
+ "version": "1.0.56",
4
4
  "description": "Remote worker agent for Yeaft Web Code Agent — connects the native Yeaft engine, CLI providers, and workbench tools",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -1115,6 +1115,13 @@ export class ConversationStore {
1115
1115
  * Used by the web client to fetch "everything new since my latest known
1116
1116
  * message" when re-entering a session — the delta path.
1117
1117
  *
1118
+ * `latestSeq` is the newest seq the client may safely keep as its tail
1119
+ * cursor. When no visible rows changed after `afterSeq`, keep the cursor at
1120
+ * least at `afterSeq` so an empty delta still completes the in-flight sync
1121
+ * without downgrading the client to a cursor-less loaded state. Hidden rows
1122
+ * are also allowed to advance this cursor because they were scanned and
1123
+ * intentionally omitted from UI replay.
1124
+ *
1118
1125
  * @param {string} sessionId
1119
1126
  * @param {number|null} afterSeq — exclusive lower bound
1120
1127
  * @param {{ limit?: number }} [opts]
@@ -1125,16 +1132,20 @@ export class ConversationStore {
1125
1132
  const limit = Number.isFinite(opts.limit) && opts.limit > 0 ? opts.limit : 500;
1126
1133
  const cutoff = Number.isFinite(afterSeq) && afterSeq >= 0 ? afterSeq : null;
1127
1134
  if (cutoff === null) return { messages: [], latestSeq: null };
1128
- const all = this.#loadSessionMessages(sessionId);
1129
- const after = all.filter((m) => {
1135
+ const rawAfter = this.#loadSessionMessages(sessionId).filter((m) => {
1130
1136
  if (!m || m.sessionId !== sessionId) return false;
1131
- if (isHiddenConversationRow(m)) return false;
1132
1137
  const seq = parseSeqFromId(m.id);
1133
1138
  return Number.isFinite(seq) && seq > cutoff;
1134
1139
  });
1140
+ const newestScannedSeq = rawAfter.slice(0, limit).reduce((max, m) => {
1141
+ const seq = parseSeqFromId(m?.id);
1142
+ return Number.isFinite(seq) && seq > max ? seq : max;
1143
+ }, cutoff);
1144
+ const after = rawAfter.filter(m => !isHiddenConversationRow(m));
1135
1145
  const sliced = pairSanitize(after.slice(0, limit));
1136
1146
  const lastSeq = sliced.length ? parseSeqFromId(sliced[sliced.length - 1].id) : null;
1137
- return { messages: sliced, latestSeq: Number.isFinite(lastSeq) ? lastSeq : null };
1147
+ const latestSeq = Number.isFinite(lastSeq) ? Math.max(lastSeq, newestScannedSeq) : newestScannedSeq;
1148
+ return { messages: sliced, latestSeq };
1138
1149
  }
1139
1150
 
1140
1151
  /**
@@ -863,6 +863,9 @@ function projectVisibleHistoryChunkMessages(messages = []) {
863
863
 
864
864
  function emitHistoryChunk({ sessionId, messages, mode = 'older', oldestSeq = null, hasMore = false, latestSeq = null, afterSeq = null, turns = null, perfTraceId = null }) {
865
865
  const projectedMessages = projectVisibleHistoryChunkMessages(messages);
866
+ if (mode === 'delta' && projectedMessages.length === 0) {
867
+ return projectedMessages;
868
+ }
866
869
  sendToServer({
867
870
  type: 'yeaft_history_chunk',
868
871
  conversationId: yeaftConversationId,