@adhdev/daemon-core 0.9.30 → 0.9.32
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/cli-adapters/provider-cli-adapter.d.ts +4 -0
- package/dist/index.js +92 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +92 -19
- package/dist/index.mjs.map +1 -1
- package/dist/providers/provider-loader.d.ts +1 -0
- package/dist/status/chat-tail-hot-sessions.d.ts +1 -0
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +54 -3
- package/src/commands/chat-commands.ts +57 -17
- package/src/logging/logger.ts +5 -6
- package/src/providers/provider-loader.ts +7 -3
- package/src/status/chat-tail-hot-sessions.ts +6 -0
|
@@ -15,6 +15,7 @@ export declare function classifyHotChatSessionsForSubscriptionFlush(sessions: Ho
|
|
|
15
15
|
now?: number;
|
|
16
16
|
recentMessageGraceMs?: number;
|
|
17
17
|
activeStatuses?: ReadonlySet<string>;
|
|
18
|
+
activeSessionIds?: ReadonlySet<string>;
|
|
18
19
|
}): {
|
|
19
20
|
active: Set<string>;
|
|
20
21
|
finalizing: Set<string>;
|
package/package.json
CHANGED
|
@@ -282,6 +282,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
282
282
|
private static readonly STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS = 1000;
|
|
283
283
|
private static readonly SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
|
|
284
284
|
private static readonly MAX_TRACE_ENTRIES = 250;
|
|
285
|
+
private static readonly PARSE_MESSAGE_TAIL_LIMIT = 100;
|
|
285
286
|
|
|
286
287
|
private readonly providerResolutionMeta: ProviderResolutionMeta;
|
|
287
288
|
private static readonly FINISH_RETRY_DELAY_MS = 300;
|
|
@@ -333,6 +334,42 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
333
334
|
return null;
|
|
334
335
|
}
|
|
335
336
|
|
|
337
|
+
private selectParseBaseMessages(baseMessages: CliChatMessage[]): CliChatMessage[] {
|
|
338
|
+
if (baseMessages.length <= ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
|
|
339
|
+
return baseMessages.slice(-ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
private messagesComparable(left: any, right: any): boolean {
|
|
343
|
+
if (!left || !right) return false;
|
|
344
|
+
if ((left.role || '') !== (right.role || '')) return false;
|
|
345
|
+
const leftText = normalizeComparableTranscriptText(left.content);
|
|
346
|
+
const rightText = normalizeComparableTranscriptText(right.content);
|
|
347
|
+
return !!leftText && leftText === rightText;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
private stitchParsedMessagesWithCommittedBase(
|
|
351
|
+
parsedMessages: any[],
|
|
352
|
+
fullBaseMessages: CliChatMessage[],
|
|
353
|
+
parseBaseMessages: CliChatMessage[],
|
|
354
|
+
): any[] {
|
|
355
|
+
if (!Array.isArray(parsedMessages) || parsedMessages.length === 0) return parsedMessages;
|
|
356
|
+
if (fullBaseMessages.length <= parseBaseMessages.length) return parsedMessages;
|
|
357
|
+
|
|
358
|
+
const parsedFirst = parsedMessages[0];
|
|
359
|
+
const fullFirst = fullBaseMessages[0];
|
|
360
|
+
if (parsedMessages.length >= fullBaseMessages.length && this.messagesComparable(parsedFirst, fullFirst)) {
|
|
361
|
+
return parsedMessages;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const tailFirst = parseBaseMessages[0];
|
|
365
|
+
if (tailFirst && this.messagesComparable(parsedFirst, tailFirst)) {
|
|
366
|
+
const prefixLength = fullBaseMessages.length - parseBaseMessages.length;
|
|
367
|
+
return [...fullBaseMessages.slice(0, prefixLength), ...parsedMessages];
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return [...fullBaseMessages, ...parsedMessages];
|
|
371
|
+
}
|
|
372
|
+
|
|
336
373
|
private getIdleFinishConfirmMs(): number {
|
|
337
374
|
return this.timeouts.idleFinishConfirm;
|
|
338
375
|
}
|
|
@@ -1044,7 +1081,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1044
1081
|
if (!this.applyPendingScriptStatusDebounce(ctx)) return;
|
|
1045
1082
|
|
|
1046
1083
|
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
1047
|
-
LOG.
|
|
1084
|
+
LOG.debug(
|
|
1048
1085
|
'CLI',
|
|
1049
1086
|
`[${this.cliType}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope?.prompt || '').slice(0, 140)} status=${String(status || '')} parsedStatus=${String(parsedStatus || '')} parsedMsgCount=${parsedMessages.length} lastParsedAssistant=${JSON.stringify(summarizeCliTraceText(lastParsedAssistant?.content || '', 120)).slice(0, 160)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 160)).slice(0, 220)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 160)).slice(0, 220)}`
|
|
1050
1087
|
);
|
|
@@ -1439,18 +1476,26 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1439
1476
|
try {
|
|
1440
1477
|
const screenText = this.terminalScreen.getText();
|
|
1441
1478
|
const tail = this.recentOutputBuffer.slice(-500);
|
|
1479
|
+
const parseBaseMessages = this.selectParseBaseMessages(this.committedMessages);
|
|
1442
1480
|
const input = buildCliParseInput({
|
|
1443
1481
|
accumulatedBuffer: this.accumulatedBuffer,
|
|
1444
1482
|
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
1445
1483
|
recentOutputBuffer: this.recentOutputBuffer,
|
|
1446
1484
|
terminalScreenText: screenText,
|
|
1447
|
-
baseMessages:
|
|
1485
|
+
baseMessages: parseBaseMessages,
|
|
1448
1486
|
partialResponse: this.responseBuffer,
|
|
1449
1487
|
isWaitingForResponse: this.isWaitingForResponse,
|
|
1450
1488
|
scope: this.currentTurnScope,
|
|
1451
1489
|
runtimeSettings: this.runtimeSettings,
|
|
1452
1490
|
});
|
|
1453
1491
|
const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
|
|
1492
|
+
if (session && typeof session === 'object' && Array.isArray(session.messages)) {
|
|
1493
|
+
session.messages = this.stitchParsedMessagesWithCommittedBase(
|
|
1494
|
+
session.messages,
|
|
1495
|
+
this.committedMessages,
|
|
1496
|
+
parseBaseMessages,
|
|
1497
|
+
);
|
|
1498
|
+
}
|
|
1454
1499
|
this.parseErrorMessage = null;
|
|
1455
1500
|
return session && typeof session === 'object' ? session : null;
|
|
1456
1501
|
} catch (e: any) {
|
|
@@ -1871,12 +1916,13 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1871
1916
|
}
|
|
1872
1917
|
try {
|
|
1873
1918
|
const screenText = typeof screenTextOverride === 'string' ? screenTextOverride : this.terminalScreen.getText();
|
|
1919
|
+
const parseBaseMessages = this.selectParseBaseMessages(baseMessages);
|
|
1874
1920
|
const input = buildCliParseInput({
|
|
1875
1921
|
accumulatedBuffer: this.accumulatedBuffer,
|
|
1876
1922
|
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
1877
1923
|
recentOutputBuffer: this.recentOutputBuffer,
|
|
1878
1924
|
terminalScreenText: screenText,
|
|
1879
|
-
baseMessages,
|
|
1925
|
+
baseMessages: parseBaseMessages,
|
|
1880
1926
|
partialResponse,
|
|
1881
1927
|
isWaitingForResponse: this.isWaitingForResponse,
|
|
1882
1928
|
scope,
|
|
@@ -1888,6 +1934,11 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1888
1934
|
}
|
|
1889
1935
|
const normalizedParsed = this.suppressStaleParsedApproval(parsed, input.recentBuffer, input.screenText);
|
|
1890
1936
|
if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
|
|
1937
|
+
normalizedParsed.messages = this.stitchParsedMessagesWithCommittedBase(
|
|
1938
|
+
normalizedParsed.messages,
|
|
1939
|
+
baseMessages,
|
|
1940
|
+
parseBaseMessages,
|
|
1941
|
+
);
|
|
1891
1942
|
this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
|
|
1892
1943
|
}
|
|
1893
1944
|
this.parseErrorMessage = null;
|
|
@@ -583,11 +583,18 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
583
583
|
|
|
584
584
|
// Extension transport: evaluateInSession
|
|
585
585
|
if (isExtensionTransport(transport)) {
|
|
586
|
+
let extensionReadChatError = '';
|
|
586
587
|
try {
|
|
587
588
|
const evalResult = await h.evaluateProviderScript('readChat', undefined, READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS);
|
|
588
589
|
if (evalResult?.result) {
|
|
589
590
|
let parsed = evalResult.result;
|
|
590
|
-
if (typeof parsed === 'string') {
|
|
591
|
+
if (typeof parsed === 'string') {
|
|
592
|
+
try {
|
|
593
|
+
parsed = JSON.parse(parsed);
|
|
594
|
+
} catch (e: any) {
|
|
595
|
+
extensionReadChatError = `extension read_chat parse failed: ${e?.message || String(e)}`;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
591
598
|
if (parsed && typeof parsed === 'object') {
|
|
592
599
|
const validated = validateReadChatResultPayload(parsed, 'extension read_chat');
|
|
593
600
|
_log(`Extension OK: ${validated.messages?.length || 0} msgs`);
|
|
@@ -610,8 +617,14 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
610
617
|
);
|
|
611
618
|
return buildReadChatCommandResult(validated as Record<string, any>, args);
|
|
612
619
|
}
|
|
620
|
+
if (!extensionReadChatError) {
|
|
621
|
+
extensionReadChatError = 'extension read_chat returned a non-object payload';
|
|
622
|
+
}
|
|
623
|
+
} else {
|
|
624
|
+
extensionReadChatError = 'extension read_chat returned no payload';
|
|
613
625
|
}
|
|
614
626
|
} catch (e: any) {
|
|
627
|
+
extensionReadChatError = `extension read_chat failed: ${e?.message || String(e)}`;
|
|
615
628
|
_log(`Extension error: ${e.message}`);
|
|
616
629
|
traceProviderEvent(args, 'provider', 'extension.read_chat.error', {
|
|
617
630
|
h,
|
|
@@ -626,8 +639,8 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
626
639
|
const parentSessionId = h.currentSession?.parentSessionId;
|
|
627
640
|
if (cdp && parentSessionId) {
|
|
628
641
|
const stream = await h.agentStream.collectActiveSession(cdp, parentSessionId);
|
|
629
|
-
if (stream
|
|
630
|
-
return
|
|
642
|
+
if (stream && stream.agentType !== provider?.type) {
|
|
643
|
+
return { success: false, error: `extension read_chat stream agent mismatch for ${provider?.type || 'unknown_extension'}` };
|
|
631
644
|
}
|
|
632
645
|
if (stream) {
|
|
633
646
|
h.historyWriter.appendNewMessages(
|
|
@@ -645,7 +658,7 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
645
658
|
}
|
|
646
659
|
}
|
|
647
660
|
}
|
|
648
|
-
return
|
|
661
|
+
return { success: false, error: extensionReadChatError || 'extension read_chat unavailable' };
|
|
649
662
|
}
|
|
650
663
|
|
|
651
664
|
// IDE category (default): cdp.evaluate
|
|
@@ -655,6 +668,7 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
655
668
|
// webview IDE (Kiro, PearAI) → evaluateInWebviewFrame directly use
|
|
656
669
|
const webviewScript = h.getProviderScript('webviewReadChat') || h.getProviderScript('webview_read_chat');
|
|
657
670
|
if (webviewScript) {
|
|
671
|
+
let webviewReadChatError = '';
|
|
658
672
|
try {
|
|
659
673
|
const matchText = provider?.webviewMatchText;
|
|
660
674
|
const matchFn = matchText
|
|
@@ -663,37 +677,56 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
663
677
|
const raw = await cdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
664
678
|
if (raw) {
|
|
665
679
|
let parsed: any = raw;
|
|
666
|
-
if (typeof parsed === 'string') {
|
|
680
|
+
if (typeof parsed === 'string') {
|
|
681
|
+
try {
|
|
682
|
+
parsed = JSON.parse(parsed);
|
|
683
|
+
} catch (e: any) {
|
|
684
|
+
webviewReadChatError = `webview read_chat parse failed: ${e?.message || String(e)}`;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
667
687
|
if (parsed && typeof parsed === 'object') {
|
|
668
688
|
const validated = validateReadChatResultPayload(parsed, 'webview read_chat');
|
|
669
689
|
_log(`Webview OK: ${validated.messages?.length || 0} msgs`);
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
690
|
+
h.historyWriter.appendNewMessages(
|
|
691
|
+
provider?.type || getCurrentProviderType(h, 'unknown_webview'),
|
|
692
|
+
toHistoryPersistedMessages(normalizeReadChatMessages(validated)),
|
|
693
|
+
validated.title,
|
|
694
|
+
args?.targetSessionId,
|
|
695
|
+
historySessionId,
|
|
696
|
+
);
|
|
677
697
|
return buildReadChatCommandResult(validated as Record<string, any>, args);
|
|
678
698
|
}
|
|
699
|
+
if (!webviewReadChatError) {
|
|
700
|
+
webviewReadChatError = 'webview read_chat returned a non-object payload';
|
|
701
|
+
}
|
|
702
|
+
} else {
|
|
703
|
+
webviewReadChatError = 'webview read_chat returned no payload';
|
|
679
704
|
}
|
|
680
705
|
} catch (e: any) {
|
|
706
|
+
webviewReadChatError = `webview read_chat failed: ${e?.message || String(e)}`;
|
|
681
707
|
_log(`Webview readChat error: ${e.message}`);
|
|
682
708
|
}
|
|
683
|
-
return
|
|
709
|
+
return { success: false, error: webviewReadChatError || 'webview read_chat unavailable' };
|
|
684
710
|
}
|
|
685
711
|
|
|
686
712
|
// Regular IDE (Cursor, Windsurf, Trae etc) → main DOM evaluate
|
|
687
713
|
const script = h.getProviderScript('readChat') || h.getProviderScript('read_chat');
|
|
688
714
|
if (script) {
|
|
715
|
+
let ideReadChatError = '';
|
|
689
716
|
try {
|
|
690
717
|
const evalResult = await h.evaluateProviderScript('readChat', undefined, READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS);
|
|
691
718
|
if (evalResult?.result) {
|
|
692
719
|
let parsed: any = evalResult.result;
|
|
693
|
-
if (typeof parsed === 'string') {
|
|
694
|
-
|
|
720
|
+
if (typeof parsed === 'string') {
|
|
721
|
+
try {
|
|
722
|
+
parsed = JSON.parse(parsed);
|
|
723
|
+
} catch (e: any) {
|
|
724
|
+
ideReadChatError = `ide read_chat parse failed: ${e?.message || String(e)}`;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
if (parsed && typeof parsed === 'object') {
|
|
695
728
|
const validated = validateReadChatResultPayload(parsed, 'ide read_chat');
|
|
696
|
-
_log(`OK: ${validated.messages?.length} msgs`);
|
|
729
|
+
_log(`OK: ${validated.messages?.length || 0} msgs`);
|
|
697
730
|
traceProviderEvent(args, 'provider', 'ide.read_chat.success', {
|
|
698
731
|
h,
|
|
699
732
|
provider,
|
|
@@ -713,8 +746,14 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
713
746
|
);
|
|
714
747
|
return buildReadChatCommandResult(validated as Record<string, any>, args);
|
|
715
748
|
}
|
|
749
|
+
if (!ideReadChatError) {
|
|
750
|
+
ideReadChatError = 'ide read_chat returned a non-object payload';
|
|
751
|
+
}
|
|
752
|
+
} else {
|
|
753
|
+
ideReadChatError = 'ide read_chat returned no payload';
|
|
716
754
|
}
|
|
717
755
|
} catch (e: any) {
|
|
756
|
+
ideReadChatError = `ide read_chat failed: ${e?.message || String(e)}`;
|
|
718
757
|
LOG.info('Command', `[read_chat] Script error: ${e.message}`);
|
|
719
758
|
traceProviderEvent(args, 'provider', 'ide.read_chat.error', {
|
|
720
759
|
h,
|
|
@@ -723,9 +762,10 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
723
762
|
payload: { method: 'evaluate', error: e.message },
|
|
724
763
|
});
|
|
725
764
|
}
|
|
765
|
+
return { success: false, error: ideReadChatError || 'ide read_chat unavailable' };
|
|
726
766
|
}
|
|
727
767
|
|
|
728
|
-
return
|
|
768
|
+
return { success: false, error: 'read_chat unavailable' };
|
|
729
769
|
}
|
|
730
770
|
|
|
731
771
|
export async function handleSendChat(h: CommandHelpers, args: any): Promise<CommandResult> {
|
package/src/logging/logger.ts
CHANGED
|
@@ -175,19 +175,18 @@ export function daemonLog(category: string, msg: string, level: LogLevel = 'info
|
|
|
175
175
|
const label = LEVEL_LABEL[level];
|
|
176
176
|
const line = `[${ts()}] [${label}] [${category}] ${msg}`;
|
|
177
177
|
|
|
178
|
-
//
|
|
178
|
+
// Apply the active log level consistently to console, file, and the remote ring buffer.
|
|
179
|
+
// Debug hot paths are useful when explicitly enabled, but should not inflate normal-mode logs.
|
|
180
|
+
if (!shouldOutput) return;
|
|
181
|
+
|
|
179
182
|
writeToFile(line);
|
|
180
183
|
|
|
181
|
-
// Always save to ring buffer (for remote transmission)
|
|
182
184
|
ringBuffer.push({ ts: Date.now(), level, category, message: msg });
|
|
183
185
|
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
184
186
|
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
185
187
|
}
|
|
186
188
|
|
|
187
|
-
|
|
188
|
-
if (shouldOutput) {
|
|
189
|
-
origConsoleLog(line);
|
|
190
|
-
}
|
|
189
|
+
origConsoleLog(line);
|
|
191
190
|
}
|
|
192
191
|
|
|
193
192
|
// ─── Convenience API ────────────────────────────────
|
|
@@ -199,6 +199,10 @@ export class ProviderLoader {
|
|
|
199
199
|
this.logFn(`[ProviderLoader] ${msg}`);
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
private debugLog(msg: string): void {
|
|
203
|
+
LOG.debug('Provider', `[ProviderLoader] ${msg}`);
|
|
204
|
+
}
|
|
205
|
+
|
|
202
206
|
// ─── Public API ────────────────────────────────
|
|
203
207
|
|
|
204
208
|
/**
|
|
@@ -892,7 +896,7 @@ export class ProviderLoader {
|
|
|
892
896
|
const loaded = this.loadScriptsFromDir(type, entry.scriptDir);
|
|
893
897
|
if (loaded) {
|
|
894
898
|
resolved.scripts = loaded;
|
|
895
|
-
this.
|
|
899
|
+
this.debugLog(` [compatibility] ${type} v${currentVersion} → ${entry.scriptDir}`);
|
|
896
900
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
897
901
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
898
902
|
if (providerDir) {
|
|
@@ -912,7 +916,7 @@ export class ProviderLoader {
|
|
|
912
916
|
const loaded = this.loadScriptsFromDir(type, base.defaultScriptDir);
|
|
913
917
|
if (loaded) {
|
|
914
918
|
resolved.scripts = loaded;
|
|
915
|
-
this.
|
|
919
|
+
this.debugLog(` [compatibility] ${type} v${currentVersion} → default: ${base.defaultScriptDir}`);
|
|
916
920
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
917
921
|
resolved._resolvedScriptsSource = 'defaultScriptDir:version_miss';
|
|
918
922
|
if (providerDir) {
|
|
@@ -955,7 +959,7 @@ export class ProviderLoader {
|
|
|
955
959
|
const loaded = this.loadScriptsFromDir(type, base.defaultScriptDir);
|
|
956
960
|
if (loaded) {
|
|
957
961
|
resolved.scripts = loaded;
|
|
958
|
-
this.
|
|
962
|
+
this.debugLog(` [compatibility] ${type} no version detected → default: ${base.defaultScriptDir}`);
|
|
959
963
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
960
964
|
resolved._resolvedScriptsSource = 'defaultScriptDir:no_version';
|
|
961
965
|
if (providerDir) {
|
|
@@ -59,6 +59,7 @@ export function classifyHotChatSessionsForSubscriptionFlush(
|
|
|
59
59
|
now?: number;
|
|
60
60
|
recentMessageGraceMs?: number;
|
|
61
61
|
activeStatuses?: ReadonlySet<string>;
|
|
62
|
+
activeSessionIds?: ReadonlySet<string>;
|
|
62
63
|
} = {},
|
|
63
64
|
): { active: Set<string>; finalizing: Set<string> } {
|
|
64
65
|
const now = options.now ?? Date.now();
|
|
@@ -69,6 +70,7 @@ export function classifyHotChatSessionsForSubscriptionFlush(
|
|
|
69
70
|
: DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS,
|
|
70
71
|
);
|
|
71
72
|
const activeStatuses = options.activeStatuses ?? DEFAULT_ACTIVE_CHAT_POLL_STATUSES;
|
|
73
|
+
const activeSessionIds = options.activeSessionIds ?? new Set<string>();
|
|
72
74
|
const active = new Set<string>();
|
|
73
75
|
const excluded = new Set<string>();
|
|
74
76
|
|
|
@@ -79,6 +81,10 @@ export function classifyHotChatSessionsForSubscriptionFlush(
|
|
|
79
81
|
excluded.add(sessionId);
|
|
80
82
|
continue;
|
|
81
83
|
}
|
|
84
|
+
if (activeSessionIds.has(sessionId)) {
|
|
85
|
+
active.add(sessionId);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
82
88
|
|
|
83
89
|
const status = String(session?.status || '').toLowerCase();
|
|
84
90
|
const unread = session?.unread === true;
|