mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-16 23:02:51 -07:00
refactor(context): transition IR to immutable Concrete/Logical split
This commit is contained in:
@@ -13,109 +13,100 @@ import type { Part } from '@google/genai';
|
||||
*/
|
||||
export interface IrMetadata {
|
||||
/** The estimated number of tokens this entity originally consumed. */
|
||||
originalTokens: number;
|
||||
readonly originalTokens: number;
|
||||
/** The current estimated number of tokens this entity consumes in its degraded state. */
|
||||
currentTokens: number;
|
||||
readonly currentTokens: number;
|
||||
/** An audit trail of all transformations applied by ContextProcessors. */
|
||||
transformations: Array<{
|
||||
processorName: string;
|
||||
action:
|
||||
readonly transformations: ReadonlyArray<{
|
||||
readonly processorName: string;
|
||||
readonly action:
|
||||
| 'MASKED'
|
||||
| 'TRUNCATED'
|
||||
| 'DEGRADED'
|
||||
| 'SUMMARIZED'
|
||||
| 'EVICTED'
|
||||
| 'SYNTHESIZED';
|
||||
timestamp: number;
|
||||
readonly timestamp: number;
|
||||
/** Pointer to where the original uncompressed payload was saved (if applicable) */
|
||||
diskPointer?: string;
|
||||
readonly diskPointer?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export type IrNodeType =
|
||||
// Organic Concrete Nodes
|
||||
| 'USER_PROMPT'
|
||||
| 'SYSTEM_EVENT'
|
||||
| 'AGENT_THOUGHT'
|
||||
| 'TOOL_EXECUTION'
|
||||
| 'AGENT_YIELD';
|
||||
| 'AGENT_YIELD'
|
||||
|
||||
// Synthetic Concrete Nodes
|
||||
| 'SNAPSHOT'
|
||||
| 'ROLLING_SUMMARY'
|
||||
| 'MASKED_TOOL'
|
||||
|
||||
/** Base interface for all nodes in the Episodic IR */
|
||||
export type VariantStatus = 'computing' | 'ready' | 'failed';
|
||||
|
||||
export interface BaseVariant {
|
||||
status: VariantStatus;
|
||||
recoveredTokens?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface SummaryVariant extends BaseVariant {
|
||||
type: 'summary';
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface MaskedVariant extends BaseVariant {
|
||||
type: 'masked';
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface SnapshotVariant extends BaseVariant {
|
||||
type: 'snapshot';
|
||||
episode: Episode;
|
||||
replacedEpisodeIds: string[];
|
||||
}
|
||||
|
||||
export type Variant = SummaryVariant | MaskedVariant | SnapshotVariant;
|
||||
// Logical Nodes
|
||||
| 'TASK'
|
||||
| 'EPISODE';
|
||||
|
||||
/** Base interface for all nodes in the Episodic IR */
|
||||
export interface IrNode {
|
||||
readonly id: string;
|
||||
readonly type: IrNodeType;
|
||||
metadata: IrMetadata;
|
||||
variants?: Record<string, Variant>;
|
||||
readonly metadata: IrMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concrete Nodes: The atomic, renderable pieces of data.
|
||||
* These are the actual "planks" of the Ship of Theseus.
|
||||
*/
|
||||
export interface BaseConcreteNode extends IrNode {
|
||||
/** The ID of the Logical Node (e.g., Episode) that structurally owns this node */
|
||||
readonly logicalParentId?: string;
|
||||
|
||||
/** If this node replaced a single node 1:1 (e.g., masking), this points to the original */
|
||||
readonly replacesId?: string;
|
||||
|
||||
/** If this node is a synthetic summary of N nodes, this points to the original IDs */
|
||||
readonly abstractsIds?: ReadonlyArray<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Semantic Parts for User Prompts
|
||||
* Ensures we can safely truncate text without deleting multi-modal parts (like images).
|
||||
*/
|
||||
export type SemanticPart =
|
||||
| {
|
||||
type: 'text';
|
||||
text: string;
|
||||
presentation?: { text: string; tokens: number };
|
||||
readonly type: 'text';
|
||||
readonly text: string;
|
||||
}
|
||||
| {
|
||||
type: 'inline_data';
|
||||
mimeType: string;
|
||||
data: string;
|
||||
presentation?: { text: string; tokens: number };
|
||||
readonly type: 'inline_data';
|
||||
readonly mimeType: string;
|
||||
readonly data: string;
|
||||
}
|
||||
| {
|
||||
type: 'file_data';
|
||||
mimeType: string;
|
||||
fileUri: string;
|
||||
presentation?: { text: string; tokens: number };
|
||||
readonly type: 'file_data';
|
||||
readonly mimeType: string;
|
||||
readonly fileUri: string;
|
||||
}
|
||||
| {
|
||||
type: 'raw_part';
|
||||
part: Part;
|
||||
presentation?: { text: string; tokens: number };
|
||||
readonly type: 'raw_part';
|
||||
readonly part: Part;
|
||||
};
|
||||
|
||||
/**
|
||||
* Trigger Nodes
|
||||
* Events that wake the agent up and initiate an Episode.
|
||||
*/
|
||||
export interface UserPrompt extends IrNode {
|
||||
export interface UserPrompt extends BaseConcreteNode {
|
||||
readonly type: 'USER_PROMPT';
|
||||
/** The semantic breakdown of the user's multi-modal input */
|
||||
semanticParts: SemanticPart[];
|
||||
readonly semanticParts: ReadonlyArray<SemanticPart>;
|
||||
}
|
||||
|
||||
export interface SystemEvent extends IrNode {
|
||||
export interface SystemEvent extends BaseConcreteNode {
|
||||
readonly type: 'SYSTEM_EVENT';
|
||||
name: string;
|
||||
payload: Record<string, unknown>;
|
||||
readonly name: string;
|
||||
readonly payload: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export type EpisodeTrigger = UserPrompt | SystemEvent;
|
||||
@@ -124,82 +115,90 @@ export type EpisodeTrigger = UserPrompt | SystemEvent;
|
||||
* Step Nodes
|
||||
* The internal autonomous actions taken by the agent during its loop.
|
||||
*/
|
||||
export interface AgentThought extends IrNode {
|
||||
export interface AgentThought extends BaseConcreteNode {
|
||||
readonly type: 'AGENT_THOUGHT';
|
||||
text: string;
|
||||
/** Overrides the rendered output for this thought */
|
||||
presentation?: {
|
||||
text: string;
|
||||
tokens: number;
|
||||
};
|
||||
readonly text: string;
|
||||
}
|
||||
|
||||
export interface ToolExecution extends IrNode {
|
||||
export interface ToolExecution extends BaseConcreteNode {
|
||||
readonly type: 'TOOL_EXECUTION';
|
||||
/** The name of the tool invoked */
|
||||
toolName: string;
|
||||
|
||||
/** The arguments passed to the tool (The 'FunctionCall') */
|
||||
intent: Record<string, unknown>;
|
||||
|
||||
/** The result returned by the tool (The 'FunctionResponse') */
|
||||
observation: string | Record<string, unknown>;
|
||||
|
||||
/** Granular token tracking for the different lifecycle phases of the tool */
|
||||
tokens: {
|
||||
intent: number;
|
||||
observation: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* The presentation layer. If defined, the IrMapper uses this instead of the
|
||||
* raw observation to build the functionResponse.
|
||||
* This preserves the immutable raw data for semantic queries while modifying the rendered output.
|
||||
*/
|
||||
presentation?: {
|
||||
intent?: Record<string, unknown>;
|
||||
observation?: string | Record<string, unknown>;
|
||||
tokens: {
|
||||
intent: number;
|
||||
observation: number;
|
||||
};
|
||||
readonly toolName: string;
|
||||
readonly intent: Record<string, unknown>;
|
||||
readonly observation: string | Record<string, unknown>;
|
||||
readonly tokens: {
|
||||
readonly intent: number;
|
||||
readonly observation: number;
|
||||
};
|
||||
}
|
||||
|
||||
export type EpisodeStep = AgentThought | ToolExecution;
|
||||
export interface MaskedTool extends BaseConcreteNode {
|
||||
readonly type: 'MASKED_TOOL';
|
||||
readonly toolName: string;
|
||||
readonly intent?: Record<string, unknown>;
|
||||
readonly observation?: string | Record<string, unknown>;
|
||||
readonly tokens: {
|
||||
readonly intent: number;
|
||||
readonly observation: number;
|
||||
};
|
||||
}
|
||||
|
||||
export type EpisodeStep = AgentThought | ToolExecution | MaskedTool;
|
||||
|
||||
/**
|
||||
* Resolution Node
|
||||
* The final message where the agent yields control back to the user.
|
||||
*/
|
||||
export interface AgentYield extends IrNode {
|
||||
export interface AgentYield extends BaseConcreteNode {
|
||||
readonly type: 'AGENT_YIELD';
|
||||
text: string;
|
||||
presentation?: {
|
||||
text: string;
|
||||
tokens: number;
|
||||
};
|
||||
readonly text: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Episode
|
||||
* A discrete, continuous run of the agent. Represents the full cycle from
|
||||
* taking control (Trigger) to returning control (Yield), encompassing all
|
||||
* internal reasoning and observations (Steps).
|
||||
* Synthetic Leaf Interfaces
|
||||
* Processors that generate summaries emit explicit synthetic nodes.
|
||||
*/
|
||||
export interface Episode {
|
||||
readonly type: 'EPISODE';
|
||||
readonly id: string;
|
||||
/** When the episode began */
|
||||
export interface Snapshot extends BaseConcreteNode {
|
||||
readonly type: 'SNAPSHOT';
|
||||
readonly timestamp: number;
|
||||
variants?: Record<string, Variant>;
|
||||
|
||||
/** The event that initiated this run */
|
||||
trigger: EpisodeTrigger;
|
||||
|
||||
/** The sequence of autonomous actions and observations */
|
||||
steps: EpisodeStep[];
|
||||
|
||||
/** The final handover back to the user (can be undefined if the episode was aborted/errored) */
|
||||
yield?: AgentYield;
|
||||
readonly text: string;
|
||||
}
|
||||
|
||||
export interface RollingSummary extends BaseConcreteNode {
|
||||
readonly type: 'ROLLING_SUMMARY';
|
||||
readonly timestamp: number;
|
||||
readonly text: string;
|
||||
}
|
||||
|
||||
export type SyntheticLeaf = Snapshot | RollingSummary;
|
||||
|
||||
export type ConcreteNode =
|
||||
| UserPrompt
|
||||
| SystemEvent
|
||||
| AgentThought
|
||||
| ToolExecution
|
||||
| MaskedTool
|
||||
| AgentYield
|
||||
| Snapshot
|
||||
| RollingSummary;
|
||||
|
||||
/**
|
||||
* Logical Nodes
|
||||
* These define hierarchy and grouping. They do not directly render to Gemini.
|
||||
*/
|
||||
export interface Episode extends IrNode {
|
||||
readonly type: 'EPISODE';
|
||||
readonly timestamp: number;
|
||||
/** References to the Concrete Node IDs that conceptually belong to this Episode. */
|
||||
readonly concreteNodeIds: ReadonlyArray<string>;
|
||||
}
|
||||
|
||||
export interface Task extends IrNode {
|
||||
readonly type: 'TASK';
|
||||
readonly timestamp: number;
|
||||
readonly goal: string;
|
||||
readonly status: 'active' | 'completed' | 'failed';
|
||||
/** References to the Episode IDs that belong to this task */
|
||||
readonly episodeIds: ReadonlyArray<string>;
|
||||
}
|
||||
|
||||
export type LogicalNode = Task | Episode;
|
||||
|
||||
Reference in New Issue
Block a user