Files
gemini-cli/packages/core/src/context/historyObserver.ts
T

63 lines
1.7 KiB
TypeScript
Raw Normal View History

2026-04-06 18:46:21 +00:00
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
2026-04-07 04:46:04 +00:00
import type {
AgentChatHistory,
HistoryEvent,
} from '../core/agentChatHistory.js';
2026-04-06 18:46:21 +00:00
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();
}
2026-04-07 04:46:04 +00:00
this.unsubscribeHistory = this.chatHistory.subscribe(
(_event: HistoryEvent) => {
// Rebuild the pristine IR graph from the full source history on every change.
const pristineEpisodes = IrMapper.toIr(
this.chatHistory.get(),
this.tokenCalculator,
);
this.tracer.logEvent(
'HistoryObserver',
'Rebuilt pristine graph from chat history update',
{ episodeCount: pristineEpisodes.length },
);
this.eventBus.emitPristineHistoryUpdated({
episodes: pristineEpisodes,
});
},
);
2026-04-06 18:46:21 +00:00
}
stop() {
if (this.unsubscribeHistory) {
this.unsubscribeHistory();
this.unsubscribeHistory = undefined;
}
}
}