fix disables

This commit is contained in:
Your Name
2026-04-07 04:46:04 +00:00
parent 1754797929
commit 370e2b9e1d
46 changed files with 1602 additions and 884 deletions
@@ -1,9 +1,3 @@
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import type { BaseLlmClient } from "../../core/baseLlmClient.js";
/**
* @license
* Copyright 2026 Google LLC
@@ -19,8 +13,11 @@ import { ContextTracer } from '../tracer.js';
import { ContextEventBus } from '../eventBus.js';
import { PipelineOrchestrator } from '../sidecar/orchestrator.js';
import { registerBuiltInProcessors } from '../sidecar/builtins.js';
import { debugLogger } from "../../utils/debugLogger.js";
import { ProcessorRegistry } from "../sidecar/registry.js";
import { debugLogger } from '../../utils/debugLogger.js';
import { ProcessorRegistry } from '../sidecar/registry.js';
import { DeterministicIdGenerator } from '../system/DeterministicIdGenerator.js';
import { InMemoryFileSystem } from '../system/InMemoryFileSystem.js';
import type { BaseLlmClient } from '../../core/baseLlmClient.js';
export interface TurnSummary {
turnIndex: number;
@@ -39,7 +36,11 @@ export class SimulationHarness {
private currentTurnIndex = 0;
private tokenTrajectory: TurnSummary[] = [];
static async create(config: SidecarConfig, mockLlmClient: BaseLlmClient, mockTempDir = '/tmp/sim'): Promise<SimulationHarness> {
static async create(
config: SidecarConfig,
mockLlmClient: BaseLlmClient,
mockTempDir = '/tmp/sim',
): Promise<SimulationHarness> {
const harness = new SimulationHarness();
await harness.init(config, mockLlmClient, mockTempDir);
return harness;
@@ -53,19 +54,17 @@ export class SimulationHarness {
private async init(
config: SidecarConfig,
mockLlmClient: BaseLlmClient,
mockTempDir: string
mockTempDir: string,
) {
this.config = config;
const registry = new ProcessorRegistry();
// Register all standard processors
registerBuiltInProcessors(registry);
this.tracer = new ContextTracer({ targetDir: mockTempDir, sessionId: 'sim-session' });
// Using real token calculator instead of mock, so we test actual string sizes
const InMemoryFS = (await import('../system/InMemoryFileSystem.js')).InMemoryFileSystem;
const DetIdGen = (await import('../system/DeterministicIdGenerator.js')).DeterministicIdGenerator;
this.tracer = new ContextTracer({
targetDir: mockTempDir,
sessionId: 'sim-session',
});
this.env = new ContextEnvironmentImpl(
mockLlmClient,
'sim-prompt',
@@ -75,12 +74,24 @@ export class SimulationHarness {
this.tracer,
4, // 4 chars per token average
this.eventBus,
new InMemoryFS(),
new DetIdGen()
new InMemoryFileSystem(),
new DeterministicIdGenerator(),
);
this.orchestrator = new PipelineOrchestrator(config, this.env, this.eventBus, this.tracer, registry);
this.contextManager = ContextManager.create(config, this.env, this.tracer, this.orchestrator, registry);
this.orchestrator = new PipelineOrchestrator(
config,
this.env,
this.eventBus,
this.tracer,
registry,
);
this.contextManager = ContextManager.create(
config,
this.env,
this.tracer,
this.orchestrator,
registry,
);
this.contextManager.subscribeToHistory(this.chatHistory);
}
@@ -92,61 +103,74 @@ export class SimulationHarness {
// 1. Append the new messages
const currentHistory = this.chatHistory.get();
this.chatHistory.set([...currentHistory, ...messages]);
// 2. Measure tokens immediately after append (Before background processing)
const tokensBefore = this.env.tokenCalculator.calculateEpisodeListTokens(
this.contextManager.getWorkingBufferView()
this.contextManager.getWorkingBufferView(),
);
debugLogger.log(`[Turn ${this.currentTurnIndex}] Tokens BEFORE: ${tokensBefore}`);
debugLogger.log(
`[Turn ${this.currentTurnIndex}] Tokens BEFORE: ${tokensBefore}`,
);
// 3. Yield to event loop to allow internal async subscribers and orchestrator to finish
await new Promise(resolve => setTimeout(resolve, 50));
await new Promise((resolve) => setTimeout(resolve, 50));
// 3.1 Simulate what projectCompressedHistory does with the sync handlers
let currentView = this.contextManager.getWorkingBufferView();
const currentTokens = this.env.tokenCalculator.calculateEpisodeListTokens(currentView);
const currentTokens =
this.env.tokenCalculator.calculateEpisodeListTokens(currentView);
if (this.config.budget && currentTokens > this.config.budget.maxTokens) {
debugLogger.log(`[Turn ${this.currentTurnIndex}] Sync panic triggered! ${currentTokens} > ${this.config.budget.maxTokens}`);
const syncPipelines = this.config.pipelines.filter(p => p.execution === 'blocking');
debugLogger.log(
`[Turn ${this.currentTurnIndex}] Sync panic triggered! ${currentTokens} > ${this.config.budget.maxTokens}`,
);
const syncPipelines = this.config.pipelines.filter(
(p) => p.execution === 'blocking',
);
const orchestrator = this.orchestrator;
for (const pipe of syncPipelines) {
await orchestrator.executePipeline(pipe.name, currentView, {
currentTokens,
maxTokens: this.config.budget.maxTokens,
retainedTokens: this.config.budget.retainedTokens,
isBudgetSatisfied: false,
deficitTokens: currentTokens - this.config.budget.maxTokens,
protectedEpisodeIds: new Set()
});
currentView = this.contextManager.getWorkingBufferView();
await orchestrator.executePipeline(pipe.name, currentView, {
currentTokens,
maxTokens: this.config.budget.maxTokens,
retainedTokens: this.config.budget.retainedTokens,
isBudgetSatisfied: false,
deficitTokens: currentTokens - this.config.budget.maxTokens,
protectedEpisodeIds: new Set(),
});
currentView = this.contextManager.getWorkingBufferView();
}
// Inject the truncated view back into the graph
for (let i = 0; i < currentView.length; i++) {
const ep = currentView[i];
if (!this.contextManager.getWorkingBufferView().find(c => c.id === ep.id)) {
this.eventBus.emitVariantReady({
targetId: ep.id,
variantId: 'v-emergency',
variant: {
status: 'ready',
type: 'masked', // Truncation is technically a mask
text: ep.yield?.text || '',
recoveredTokens: 0,
}
});
}
const ep = currentView[i];
if (
!this.contextManager
.getWorkingBufferView()
.find((c) => c.id === ep.id)
) {
this.eventBus.emitVariantReady({
targetId: ep.id,
variantId: 'v-emergency',
variant: {
status: 'ready',
type: 'masked', // Truncation is technically a mask
text: ep.yield?.text || '',
recoveredTokens: 0,
},
});
}
}
// Wait for variant propagation
await new Promise(resolve => setTimeout(resolve, 50));
await new Promise((resolve) => setTimeout(resolve, 50));
}
// 4. Measure tokens after background processors have (hopefully) emitted variants
const tokensAfter = this.env.tokenCalculator.calculateEpisodeListTokens(
this.contextManager.getWorkingBufferView()
this.contextManager.getWorkingBufferView(),
);
debugLogger.log(`[Turn ${this.currentTurnIndex}] Tokens AFTER: ${tokensAfter}`);
debugLogger.log(
`[Turn ${this.currentTurnIndex}] Tokens AFTER: ${tokensAfter}`,
);
this.tokenTrajectory.push({
turnIndex: this.currentTurnIndex++,
tokensBeforeBackground: tokensBefore,
@@ -155,10 +179,11 @@ export class SimulationHarness {
}
async getGoldenState() {
const finalProjection = await this.contextManager.projectCompressedHistory();
const finalProjection =
await this.contextManager.projectCompressedHistory();
return {
tokenTrajectory: this.tokenTrajectory,
finalProjection
finalProjection,
};
}
}