mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-26 03:33:12 -07:00
not building
This commit is contained in:
@@ -4,35 +4,51 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type { Episode, IrNode, AgentThought, ToolExecution, UserPrompt, AgentYield, SystemEvent } from './types.js';
|
||||
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 | Episode): node is Episode {
|
||||
export function isEpisode(node: IrNode): node is Episode {
|
||||
return node.type === 'EPISODE';
|
||||
}
|
||||
|
||||
export function isAgentThought(node: IrNode | Episode): node is AgentThought {
|
||||
export function isTask(node: IrNode): node is Task {
|
||||
return node.type === 'TASK';
|
||||
}
|
||||
|
||||
export function isAgentThought(node: IrNode): node is AgentThought {
|
||||
return node.type === 'AGENT_THOUGHT';
|
||||
}
|
||||
|
||||
export function isToolExecution(node: IrNode | Episode): node is ToolExecution {
|
||||
export function isToolExecution(node: IrNode): node is ToolExecution {
|
||||
return node.type === 'TOOL_EXECUTION';
|
||||
}
|
||||
|
||||
export function isUserPrompt(node: IrNode | Episode): node is UserPrompt {
|
||||
export function isMaskedTool(node: IrNode): node is MaskedTool {
|
||||
return node.type === 'MASKED_TOOL';
|
||||
}
|
||||
|
||||
export function isUserPrompt(node: IrNode): node is UserPrompt {
|
||||
return node.type === 'USER_PROMPT';
|
||||
}
|
||||
|
||||
export function isAgentYield(node: IrNode | Episode): node is AgentYield {
|
||||
export function isAgentYield(node: IrNode): node is AgentYield {
|
||||
return node.type === 'AGENT_YIELD';
|
||||
}
|
||||
|
||||
export function isSystemEvent(node: IrNode | Episode): node is SystemEvent {
|
||||
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 === 'ROLLING_SUMMARY';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a computed view of the pristine log.
|
||||
* Sweeps backwards (newest to oldest), tracking rolling tokens.
|
||||
@@ -41,7 +57,7 @@ export function isSystemEvent(node: IrNode | Episode): node is SystemEvent {
|
||||
* Handles N-to-1 variant skipping automatically.
|
||||
*/
|
||||
|
||||
export function generateWorkingBufferView(
|
||||
export function generateWorkingBufferView_OLD(
|
||||
pristineEpisodes: Episode[],
|
||||
retainedTokens: number,
|
||||
tracer: ContextTracer,
|
||||
|
||||
@@ -4,7 +4,27 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type { ConcreteNode, IrMetadata } from './ir/types.js';
|
||||
import type { ConcreteNode, Snapshot, RollingSummary, IrMetadata } from './ir/types.js';
|
||||
|
||||
export type InboxMessage =
|
||||
| { type: 'SNAPSHOT_READY'; snapshot: Snapshot; abstractsIds: string[] }
|
||||
| { type: 'BACKGROUND_SUMMARY'; summary: RollingSummary; targetId: string };
|
||||
|
||||
export interface ContextInbox {
|
||||
dispatch(message: InboxMessage): void;
|
||||
peek<T extends InboxMessage['type']>(type: T): Extract<InboxMessage, { type: T }> | undefined;
|
||||
}
|
||||
|
||||
export interface ContextWorkingBuffer {
|
||||
/** The current active (projected) flat list of ConcreteNodes. */
|
||||
readonly nodes: ReadonlyArray<ConcreteNode>;
|
||||
|
||||
/** Retrieves the historical, pristine version of a node (before any masks/summaries). */
|
||||
getPristineNode(id: string): ConcreteNode | undefined;
|
||||
|
||||
/** Retrieves the full audit lineage of a specific node ID. */
|
||||
getLineage(id: string): ReadonlyArray<ConcreteNode>;
|
||||
}
|
||||
|
||||
/**
|
||||
* State object passed through the processing pipeline.
|
||||
@@ -52,6 +72,9 @@ export interface ContextPatch {
|
||||
}
|
||||
|
||||
export interface ProcessArgs {
|
||||
/** The rich buffer containing current nodes and their history. */
|
||||
readonly buffer: ContextWorkingBuffer;
|
||||
|
||||
/** The flat, sequential array of current renderable nodes (The Ship). */
|
||||
readonly ship: ReadonlyArray<ConcreteNode>;
|
||||
|
||||
@@ -64,11 +87,8 @@ export interface ProcessArgs {
|
||||
/** The token budget and accounting state. */
|
||||
readonly state: ContextAccountingState;
|
||||
|
||||
/**
|
||||
* An escape hatch allowing the processor to query the original, uncompressed
|
||||
* state of a node from the Pristine Graph.
|
||||
*/
|
||||
readonly getPristineNode: (id: string) => ConcreteNode | undefined;
|
||||
/** Type-safe messaging system for async/sync coordination. */
|
||||
readonly inbox: ContextInbox;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +101,7 @@ export interface ContextProcessor {
|
||||
/** Unique name for telemetry and logging. */
|
||||
readonly name: string;
|
||||
|
||||
/** Returns an array of declarative patches to apply to the Ship. */
|
||||
/** Returns an array of declarative patches applied at this specific temporal phase. */
|
||||
process(args: ProcessArgs): Promise<ContextPatch[]>;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
import type {
|
||||
ContextProcessor,
|
||||
ContextAccountingState,
|
||||
BackstopTargetOptions,
|
||||
ProcessArgs,
|
||||
ContextPatch,
|
||||
} from '../pipeline.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { EpisodeEditor } from '../ir/episodeEditor.js';
|
||||
|
||||
export type EmergencyTruncationProcessorOptions = BackstopTargetOptions;
|
||||
|
||||
@@ -47,10 +47,11 @@ export class EmergencyTruncationProcessor implements ContextProcessor {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
async process(
|
||||
editor: EpisodeEditor,
|
||||
state: ContextAccountingState,
|
||||
): Promise<void> {
|
||||
async process({
|
||||
ship,
|
||||
triggerTargets,
|
||||
state,
|
||||
}: ProcessArgs): Promise<ContextPatch[]> {
|
||||
const toRemove: string[] = [];
|
||||
|
||||
// Calculate how many tokens we need to remove based on the configured knob
|
||||
@@ -58,11 +59,11 @@ export class EmergencyTruncationProcessor implements ContextProcessor {
|
||||
const strategy = this.options.target ?? 'max';
|
||||
|
||||
if (strategy === 'incremental') {
|
||||
if (state.currentTokens <= state.maxTokens) return;
|
||||
if (state.currentTokens <= state.maxTokens) return [];
|
||||
targetTokensToRemove = state.currentTokens - state.maxTokens;
|
||||
} else if (strategy === 'freeNTokens') {
|
||||
targetTokensToRemove = this.options.freeTokensTarget ?? 0;
|
||||
if (targetTokensToRemove <= 0) return;
|
||||
if (targetTokensToRemove <= 0) return [];
|
||||
} else if (strategy === 'max') {
|
||||
// 'max' means we remove all targets without stopping early
|
||||
targetTokensToRemove = Infinity;
|
||||
@@ -70,28 +71,33 @@ export class EmergencyTruncationProcessor implements ContextProcessor {
|
||||
|
||||
let removedTokens = 0;
|
||||
|
||||
// Iterate specifically over targets (which represent the aged-out delta).
|
||||
// The editor returns targets from oldest to newest based on the working order.
|
||||
// For truncation, we want to cut the oldest first.
|
||||
for (const target of editor.targets) {
|
||||
const ep = target.episode;
|
||||
// We only truncate entire episodes here for safety and structural integrity
|
||||
if (target.node !== ep) continue;
|
||||
// The ship is sequentially ordered from oldest to newest.
|
||||
// We want to delete the oldest targeted nodes first.
|
||||
for (const node of ship) {
|
||||
// Is this node part of the targeted delta (e.g. aged out of the budget)?
|
||||
if (!triggerTargets.has(node.id)) continue;
|
||||
// Is this node explicitly protected (e.g. part of an active Task)?
|
||||
if (node.logicalParentId && state.protectedLogicalIds.has(node.logicalParentId)) continue;
|
||||
|
||||
if (removedTokens >= targetTokensToRemove) break;
|
||||
|
||||
const epTokens = this._env.tokenCalculator.calculateEpisodeListTokens([
|
||||
ep,
|
||||
]);
|
||||
removedTokens += node.metadata.currentTokens;
|
||||
toRemove.push(node.id);
|
||||
}
|
||||
|
||||
if (!state.protectedEpisodeIds.has(ep.id) && !toRemove.includes(ep.id)) {
|
||||
removedTokens += epTokens;
|
||||
toRemove.push(ep.id);
|
||||
if (toRemove.length === 0) return [];
|
||||
|
||||
return [{
|
||||
removedIds: toRemove,
|
||||
metadata: {
|
||||
originalTokens: removedTokens,
|
||||
currentTokens: 0,
|
||||
transformations: [{
|
||||
processorName: this.name,
|
||||
action: 'TRUNCATED',
|
||||
timestamp: Date.now(),
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
||||
if (toRemove.length > 0) {
|
||||
editor.removeEpisodes(toRemove, 'TRUNCATED');
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,8 @@ export class PipelineOrchestrator {
|
||||
ship: currentShip,
|
||||
triggerTargets,
|
||||
state,
|
||||
getPristineNode: () => undefined,
|
||||
buffer: {} as any, // TODO: Implement ContextWorkingBuffer fully
|
||||
inbox: {} as any, // TODO: Implement ContextInbox fully
|
||||
});
|
||||
|
||||
currentShip = this.reduceShip(currentShip, patches);
|
||||
@@ -200,7 +201,8 @@ export class PipelineOrchestrator {
|
||||
ship: currentShip,
|
||||
triggerTargets,
|
||||
state,
|
||||
getPristineNode: () => undefined,
|
||||
buffer: {} as any, // TODO: Implement ContextWorkingBuffer fully
|
||||
inbox: {} as any, // TODO: Implement ContextInbox fully
|
||||
});
|
||||
currentShip = this.reduceShip(currentShip, patches);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user