2026-04-06 18:46:21 +00:00
|
|
|
/**
|
|
|
|
|
* @license
|
|
|
|
|
* Copyright 2026 Google LLC
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import type { AgentChatHistory, HistoryEvent } from '../core/agentChatHistory.js';
|
|
|
|
|
import { IrMapper } from './ir/mapper.js';
|
2026-04-06 19:54:09 +00:00
|
|
|
import type { ContextTokenCalculator } from './utils/contextTokenCalculator.js';
|
2026-04-06 18:46:21 +00:00
|
|
|
import type { ContextEventBus } from './eventBus.js';
|
|
|
|
|
import type { ContextTracer } from './tracer.js';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Connects the raw AgentChatHistory to the ContextManager.
|
|
|
|
|
* It maps raw messages into Episodic Intermediate Representation (IR)
|
|
|
|
|
* and evaluates background triggers whenever history changes.
|
|
|
|
|
*/
|
|
|
|
|
export class HistoryObserver {
|
|
|
|
|
private unsubscribeHistory?: () => void;
|
|
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
|
private readonly chatHistory: AgentChatHistory,
|
|
|
|
|
private readonly eventBus: ContextEventBus,
|
|
|
|
|
private readonly tracer: ContextTracer,
|
2026-04-06 19:54:09 +00:00
|
|
|
private readonly tokenCalculator: ContextTokenCalculator,
|
2026-04-06 18:46:21 +00:00
|
|
|
) {}
|
|
|
|
|
|
|
|
|
|
start() {
|
|
|
|
|
if (this.unsubscribeHistory) {
|
|
|
|
|
this.unsubscribeHistory();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.unsubscribeHistory = this.chatHistory.subscribe((_event: HistoryEvent) => {
|
|
|
|
|
// Rebuild the pristine IR graph from the full source history on every change.
|
2026-04-06 19:54:09 +00:00
|
|
|
const pristineEpisodes = IrMapper.toIr(this.chatHistory.get(), this.tokenCalculator);
|
2026-04-06 18:46:21 +00:00
|
|
|
this.tracer.logEvent('HistoryObserver', 'Rebuilt pristine graph from chat history update', { episodeCount: pristineEpisodes.length });
|
|
|
|
|
|
2026-04-06 19:54:09 +00:00
|
|
|
this.eventBus.emitPristineHistoryUpdated({ episodes: pristineEpisodes });
|
2026-04-06 18:46:21 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stop() {
|
|
|
|
|
if (this.unsubscribeHistory) {
|
|
|
|
|
this.unsubscribeHistory();
|
|
|
|
|
this.unsubscribeHistory = undefined;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|