strong owner

This commit is contained in:
Your Name
2026-05-14 03:04:19 +00:00
parent d0032c6749
commit c7ba026c18
24 changed files with 1105 additions and 770 deletions
+19 -18
View File
@@ -8,25 +8,27 @@ import type { Content } from '@google/genai';
import type { ConcreteNode } from './types.js';
import { debugLogger } from '../../utils/debugLogger.js';
import type { NodeIdService } from './nodeIdService.js';
import type { HistoryTurn } from '../../core/agentChatHistory.js';
/**
* Reconstructs a valid Gemini Chat History from a list of Concrete Nodes.
* Reconstructs a list of HistoryTurns from a list of Concrete Nodes.
* This process is "role-alternation-aware" and uses turnId to
* preserve original turn boundaries even if multiple turns have the same role.
* preserve original turn boundaries and IDs.
*/
export function fromGraph(
nodes: readonly ConcreteNode[],
idService?: NodeIdService,
): Content[] {
): HistoryTurn[] {
debugLogger.log(
`[fromGraph] Reconstructing history from ${nodes.length} nodes`,
);
const history: Content[] = [];
let currentTurn: (Content & { _turnId?: string }) | null = null;
const history: HistoryTurn[] = [];
let currentTurn: { id: string; content: Content } | null = null;
for (const node of nodes) {
const turnId = node.turnId;
const turnId = node.turnId || 'orphan';
const durableId = turnId.startsWith('turn_') ? turnId.slice(5) : turnId;
// Register the payload in the identity service to ensure stability
// even if the turn content changes (e.g. after GC backstop).
@@ -40,26 +42,25 @@ export function fromGraph(
// 3. The turnId changes (Preserving distinct turns of the same role).
if (
!currentTurn ||
currentTurn.role !== node.role ||
currentTurn._turnId !== turnId
currentTurn.content.role !== node.role ||
currentTurn.id !== durableId
) {
currentTurn = {
role: node.role,
parts: [node.payload],
_turnId: turnId,
id: durableId,
content: {
role: node.role,
parts: [node.payload],
},
};
history.push(currentTurn);
} else {
currentTurn.parts = [...(currentTurn.parts || []), node.payload];
currentTurn.content.parts = [
...(currentTurn.content.parts || []),
node.payload,
];
}
}
// Final cleanup: remove our internal tracking field
for (const turn of history) {
const t = turn as Content & { _turnId?: string };
delete t._turnId;
}
debugLogger.log(`[fromGraph] Reconstructed ${history.length} turns`);
return history;
}