diff --git a/packages/core/src/context/ir/fromIr.ts b/packages/core/src/context/ir/fromIr.ts index f730236a6f..f27c8f00e2 100644 --- a/packages/core/src/context/ir/fromIr.ts +++ b/packages/core/src/context/ir/fromIr.ts @@ -12,11 +12,10 @@ import type { ToolExecution, AgentYield, MaskedTool, - Snapshot, - RollingSummary, } from './types.js'; +import { isAgentThought, isAgentYield, isSystemEvent, isSnapshot, isRollingSummary, isMaskedTool, isToolExecution, isUserPrompt } from './graphUtils.js'; -export function fromIr(ship: ReadonlyArray): Content[] { +export function fromIr(ship: readonly ConcreteNode[]): Content[] { const history: Content[] = []; const agentParts: Part[] = []; @@ -28,34 +27,34 @@ export function fromIr(ship: ReadonlyArray): Content[] { }; for (const node of ship) { - if (node.type === 'USER_PROMPT') { + if (isUserPrompt(node)) { flushAgentParts(); - const content = serializeUserPrompt(node as UserPrompt); + const content = serializeUserPrompt(node); if (content) history.push(content); - } else if (node.type === 'SYSTEM_EVENT') { + } else if (isSystemEvent(node)) { flushAgentParts(); // System events do not map strictly to Gemini Content parts unless synthesized. - } else if (node.type === 'AGENT_THOUGHT') { - agentParts.push(serializeAgentThought(node as AgentThought)); - } else if (node.type === 'TOOL_EXECUTION') { - const parts = serializeToolExecution(node as ToolExecution); + } else if (isAgentThought(node)) { + agentParts.push(serializeAgentThought(node)); + } else if (isToolExecution(node)) { + const parts = serializeToolExecution(node); agentParts.push(parts.call); flushAgentParts(); history.push({ role: 'user', parts: [parts.response] }); - } else if (node.type === 'MASKED_TOOL') { - const parts = serializeMaskedTool(node as MaskedTool); + } else if (isMaskedTool(node)) { + const parts = serializeMaskedTool(node); agentParts.push(parts.call); flushAgentParts(); history.push({ role: 'user', parts: [parts.response] }); - } else if (node.type === 'AGENT_YIELD') { - agentParts.push(serializeAgentYield(node as AgentYield)); + } else if (isAgentYield(node)) { + agentParts.push(serializeAgentYield(node)); flushAgentParts(); - } else if (node.type === 'SNAPSHOT') { + } else if (isSnapshot(node)) { flushAgentParts(); - history.push({ role: 'user', parts: [{ text: (node as Snapshot).text }] }); - } else if (node.type === 'ROLLING_SUMMARY') { + history.push({ role: 'user', parts: [{ text: (node).text }] }); + } else if (isRollingSummary(node)) { flushAgentParts(); - history.push({ role: 'user', parts: [{ text: (node as RollingSummary).text }] }); + history.push({ role: 'user', parts: [{ text: (node).text }] }); } } @@ -102,7 +101,7 @@ function serializeToolExecution( functionResponse: { id: tool.id, name: tool.toolName, - response: typeof tool.observation === "string" ? { message: tool.observation } : tool.observation as Record, + response: typeof tool.observation === "string" ? { message: tool.observation } : tool.observation, }, }, }; diff --git a/packages/core/src/context/ir/graphUtils.ts b/packages/core/src/context/ir/graphUtils.ts index e298561224..6c4b542ef7 100644 --- a/packages/core/src/context/ir/graphUtils.ts +++ b/packages/core/src/context/ir/graphUtils.ts @@ -5,9 +5,6 @@ */ import type { Episode, Task, IrNode, AgentThought, ToolExecution, MaskedTool, UserPrompt, AgentYield, SystemEvent, Snapshot, RollingSummary } from './types.js'; -import type { ContextTracer } from '../tracer.js'; -import { debugLogger } from '../../utils/debugLogger.js'; -import type { ContextEnvironment } from '../sidecar/environment.js'; export function isEpisode(node: IrNode): node is Episode { return node.type === 'EPISODE'; @@ -21,6 +18,10 @@ export function isAgentThought(node: IrNode): node is AgentThought { return node.type === 'AGENT_THOUGHT'; } +export function isAgentYield(node: IrNode): node is AgentYield { + return node.type === 'AGENT_YIELD'; +} + export function isToolExecution(node: IrNode): node is ToolExecution { return node.type === 'TOOL_EXECUTION'; } @@ -33,3 +34,12 @@ export function isUserPrompt(node: IrNode): node is UserPrompt { return node.type === 'USER_PROMPT'; } +export function isSystemEvent(node: IrNode): node is SystemEvent { + return node.type === 'SYSTEM_EVENT'; +} +export function isSnapshot(node: IrNode): node is Snapshot { + return node.type === 'SNAPSHOT'; +} +export function isRollingSummary(node: IrNode): node is RollingSummary { + return node.type === 'USER_PROMPT'; +} \ No newline at end of file diff --git a/packages/core/src/context/ir/mapper.ts b/packages/core/src/context/ir/mapper.ts index d443375f86..f35c1377ab 100644 --- a/packages/core/src/context/ir/mapper.ts +++ b/packages/core/src/context/ir/mapper.ts @@ -25,7 +25,7 @@ export class IrMapper { /** * Re-serializes a flat array of ConcreteNodes back into a flat Gemini Content[] array. */ - static fromIr(ship: ReadonlyArray): Content[] { + static fromIr(ship: readonly ConcreteNode[]): Content[] { return fromIr(ship); } } diff --git a/packages/core/src/context/ir/types.ts b/packages/core/src/context/ir/types.ts index a9493d646c..95e453fdb3 100644 --- a/packages/core/src/context/ir/types.ts +++ b/packages/core/src/context/ir/types.ts @@ -68,7 +68,7 @@ export interface BaseConcreteNode extends IrNode { readonly replacesId?: string; /** If this node is a synthetic summary of N nodes, this points to the original IDs */ - readonly abstractsIds?: ReadonlyArray; + readonly abstractsIds?: readonly string[]; } /** @@ -100,7 +100,7 @@ export type SemanticPart = */ export interface UserPrompt extends BaseConcreteNode { readonly type: 'USER_PROMPT'; - readonly semanticParts: ReadonlyArray; + readonly semanticParts: readonly SemanticPart[]; } export interface SystemEvent extends BaseConcreteNode { @@ -189,7 +189,7 @@ export interface Episode extends IrNode { readonly type: 'EPISODE'; readonly timestamp: number; /** References to the Concrete Node IDs that conceptually belong to this Episode. */ - concreteNodeIds: ReadonlyArray; + concreteNodeIds: readonly string[]; } export interface Task extends IrNode { @@ -198,7 +198,7 @@ export interface Task extends IrNode { readonly goal: string; readonly status: 'active' | 'completed' | 'failed'; /** References to the Episode IDs that belong to this task */ - readonly episodeIds: ReadonlyArray; + readonly episodeIds: readonly string[]; } export type LogicalNode = Task | Episode; diff --git a/packages/core/src/context/pipeline.ts b/packages/core/src/context/pipeline.ts index e952d4e708..b8130f9249 100644 --- a/packages/core/src/context/pipeline.ts +++ b/packages/core/src/context/pipeline.ts @@ -57,16 +57,13 @@ export interface ContextAccountingState { export interface ProcessArgs { /** The rich buffer containing current nodes and their history. */ readonly buffer: ContextWorkingBuffer; - - /** The full, read-only view of the ship. */ - readonly ship: readonly ConcreteNode[]; /** * The unprotected, mutable subset of nodes targeted by this trigger. * The Orchestrator strictly filters out ANY protected nodes (like active tasks) before calling. * Processors can assume all targets passed here are legally theirs to mutate or drop. */ - readonly targets: ConcreteNode[]; + readonly targets: readonly ConcreteNode[]; /** The token budget and accounting state. */ readonly state: ContextAccountingState;