mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-06-13 12:57:12 -07:00
refactor(context): completely purge legacy worker terminology and reorganize file layout
This commit serves as the final polish for the context architecture unification.
Key Changes:
- **Lexical Cleansing:** Swept the entire `context` module (including tests, documentation, and snapshot configurations) to replace all legacy terms ('worker', 'ContextWorker', 'StateSnapshotWorker') with their modern unified equivalents ('async pipeline', 'AsyncContextProcessor', 'StateSnapshotAsyncProcessor').
- **Registry Cleanup:** Stripped `registry.ts` of `ContextWorkerDef` maps, unifying around a single, clean processor definition registry.
- **File Reorganization:** Dismantled the monolithic `sidecar/` directory (which initially housed both engine machinery and configuration loaders).
- `pipeline/`: Now houses the core execution engine (`orchestrator`, `inbox`, `contextWorkingBuffer`, `environment`).
- `config/`: Now exclusively contains the dynamic JSON configuration logic (`SidecarLoader`, `profiles`, `schema`, `registry`).
This commit is contained in:
+2
-3
@@ -4,9 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type { SidecarConfig, PipelineDef } from './types.js';
|
||||
import type { ContextEnvironment } from './environment.js';
|
||||
import type { AsyncPipelineDef } from './types.js';
|
||||
import type { AsyncPipelineDef, SidecarConfig, PipelineDef } from './types.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
|
||||
// Import factories
|
||||
import { createToolMaskingProcessor } from '../processors/toolMaskingProcessor.js';
|
||||
+3
-17
@@ -9,44 +9,30 @@ export interface ContextProcessorDef {
|
||||
readonly schema: object;
|
||||
}
|
||||
|
||||
export interface ContextWorkerDef {
|
||||
readonly id: string;
|
||||
readonly schema: object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registry for validating declarative sidecar configuration schemas.
|
||||
* (Dynamic instantiation has been replaced by static ContextProfiles)
|
||||
*/
|
||||
export class SidecarRegistry {
|
||||
private processors = new Map<string, ContextProcessorDef>();
|
||||
private workers = new Map<string, ContextWorkerDef>();
|
||||
|
||||
registerProcessor(def: ContextProcessorDef) {
|
||||
this.processors.set(def.id, def);
|
||||
}
|
||||
|
||||
registerWorker(def: ContextWorkerDef) {
|
||||
this.workers.set(def.id, def);
|
||||
}
|
||||
|
||||
getSchema(id: string): object | undefined {
|
||||
return this.processors.get(id)?.schema || this.workers.get(id)?.schema;
|
||||
return this.processors.get(id)?.schema;
|
||||
}
|
||||
|
||||
getSchemaDefs(): { id: string; schema: object }[] {
|
||||
const defs: { id: string; schema: object }[] = [];
|
||||
getSchemaDefs(): Array<{ id: string; schema: object }> {
|
||||
const defs: Array<{ id: string; schema: object }> = [];
|
||||
for (const def of this.processors.values()) {
|
||||
if (def.schema) defs.push({ id: def.id, schema: def.schema });
|
||||
}
|
||||
for (const def of this.workers.values()) {
|
||||
if (def.schema) defs.push({ id: def.id, schema: def.schema });
|
||||
}
|
||||
return defs;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.processors.clear();
|
||||
this.workers.clear();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -55,7 +55,7 @@ export function getSidecarConfigSchema(registry?: SidecarRegistry) {
|
||||
},
|
||||
processorOptions: {
|
||||
type: 'object',
|
||||
description: 'Named hyperparameter configurations for ContextProcessors and Workers.',
|
||||
description: 'Named hyperparameter configurations for ContextProcessors and AsyncProcessors.',
|
||||
additionalProperties: processorOptionsMapping
|
||||
}
|
||||
},
|
||||
+1
-1
@@ -36,7 +36,7 @@ export interface SidecarConfig {
|
||||
maxTokens: number;
|
||||
};
|
||||
/**
|
||||
* Dynamic hyperparameter overrides for individual ContextProcessors and Workers.
|
||||
* Dynamic hyperparameter overrides for individual ContextProcessors and AsyncProcessors.
|
||||
* Keys are named identifiers (e.g. "gentleTruncation").
|
||||
*/
|
||||
processorOptions?: Record<string, { type: string; options: unknown }>;
|
||||
@@ -70,20 +70,20 @@ all mutations through a synchronous, blocking pipeline of pure functions, we
|
||||
guarantee that the context is always modified in a sane, predictable, and
|
||||
mathematically sound sequence.
|
||||
|
||||
### The "Open" Extensions: Processors, Workers, and Inboxes (The Actor Model)
|
||||
### The "Open" Extensions: Processors, AsyncProcessors, and Inboxes (The Actor Model)
|
||||
|
||||
To extend the system, developers author two types of plugins:
|
||||
|
||||
1. **Context Processors:** Pure, fast, synchronous functions that take an input
|
||||
graph and return an immutable mutated graph. They run inside Pipelines.
|
||||
2. **Context Workers:** Inspired by the **Actor Model**, these are
|
||||
2. **Context AsyncProcessors:** Inspired by the **Actor Model**, these are
|
||||
event-triggered background jobs designed for isolated, long-running async
|
||||
computations (e.g., asking an LLM to distill 50 turns of history).
|
||||
3. **Inboxes:** Because the graph can only be mutated synchronously, Workers
|
||||
3. **Inboxes:** Because the graph can only be mutated synchronously, AsyncProcessors
|
||||
cannot touch the graph directly (preventing race conditions). Instead, they
|
||||
drop their results via message-passing into point-in-time snapshots called
|
||||
_Inboxes_. Processors later read from these Inboxes during a synchronous
|
||||
pipeline run to safely apply the worker's findings.
|
||||
pipeline run to safely apply the async processor's findings.
|
||||
|
||||
## 4. Proofs of Construction
|
||||
|
||||
@@ -119,7 +119,7 @@ class ToolMaskingProcessor implements ContextProcessor {
|
||||
}
|
||||
```
|
||||
|
||||
### Example B: Long-Running Summarization (Worker + Inbox + Processor)
|
||||
### Example B: Long-Running Summarization (async pipeline + Inbox + Processor)
|
||||
|
||||
_Scenario: The user has exceeded their token budget. We need to use an LLM to
|
||||
summarize the oldest 20 turns of conversation, but we cannot block the user from
|
||||
@@ -127,10 +127,10 @@ continuing to chat while the LLM generates the summary._
|
||||
|
||||
This requires our async-to-sync bridge.
|
||||
|
||||
**Step 1: The Worker (Async Analysis)**
|
||||
**Step 1: The async pipeline (Async Analysis)**
|
||||
|
||||
```typescript
|
||||
class StateSnapshotWorker implements ContextWorker {
|
||||
class StateSnapshotasync pipeline implements Contextasync pipeline {
|
||||
// Triggers automatically in the background when the budget is exceeded
|
||||
async onBudgetExceeded(event: BudgetEvent, inbox: Inbox) {
|
||||
const agedOutNodes = event.getAgedOutNodes();
|
||||
@@ -138,7 +138,7 @@ class StateSnapshotWorker implements ContextWorker {
|
||||
// Slow, async LLM call
|
||||
const summaryText = await llm.summarize(agedOutNodes);
|
||||
|
||||
// The worker CANNOT mutate the graph. It leaves a message in the Inbox.
|
||||
// The async pipeline CANNOT mutate the graph. It leaves a message in the Inbox.
|
||||
inbox.deliver('SUMMARY_READY', {
|
||||
targetNodes: agedOutNodes,
|
||||
summary: summaryText,
|
||||
@@ -153,7 +153,7 @@ class StateSnapshotWorker implements ContextWorker {
|
||||
class StateSnapshotProcessor implements ContextProcessor {
|
||||
// Runs fast and synchronously during the next Pipeline execution
|
||||
apply(graph: ContextGraph, inbox: InboxSnapshot): ContextGraph {
|
||||
// Check if the background worker finished its job
|
||||
// Check if the async background pipeline finished its job
|
||||
const messages = inbox.read('SUMMARY_READY');
|
||||
if (messages.isEmpty()) return graph;
|
||||
|
||||
@@ -227,7 +227,7 @@ class MemoryExtractionProcessor implements ContextProcessor {
|
||||
|
||||
By treating the Context Graph as an immutable ledger updated only via functional
|
||||
Pipelines, we have eliminated race conditions and untraceable graph corruption.
|
||||
By utilizing Workers and Inboxes, we have safely bridged the gap between slow
|
||||
By utilizing AsyncProcessors and Inboxes, we have safely bridged the gap between slow
|
||||
LLM analysis and fast, synchronous terminal UI updates.
|
||||
|
||||
We recognize this is not the final form—future iterations may require strict
|
||||
|
||||
@@ -9,12 +9,12 @@ import type { AgentChatHistory } from '../core/agentChatHistory.js';
|
||||
import type { ConcreteNode } from './ir/types.js';
|
||||
import type { ContextEventBus } from './eventBus.js';
|
||||
import type { ContextTracer } from './tracer.js';
|
||||
import type { ContextEnvironment } from './sidecar/environment.js';
|
||||
import type { ContextProfile } from './sidecar/profiles.js';
|
||||
import type { PipelineOrchestrator } from './sidecar/orchestrator.js';
|
||||
import type { ContextEnvironment } from './pipeline/environment.js';
|
||||
import type { ContextProfile } from './config/profiles.js';
|
||||
import type { PipelineOrchestrator } from './pipeline/orchestrator.js';
|
||||
import { HistoryObserver } from './historyObserver.js';
|
||||
import { IrProjector } from './ir/projector.js';
|
||||
import { ContextWorkingBufferImpl } from './sidecar/contextWorkingBuffer.js';
|
||||
import { ContextWorkingBufferImpl } from './pipeline/contextWorkingBuffer.js';
|
||||
|
||||
export class ContextManager {
|
||||
// The master state containing the pristine graph and current active graph.
|
||||
@@ -62,7 +62,7 @@ export class ContextManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely stops background workers and clears event listeners.
|
||||
* Safely stops background async pipelines and clears event listeners.
|
||||
*/
|
||||
shutdown() {
|
||||
this.orchestrator.shutdown();
|
||||
|
||||
@@ -10,9 +10,9 @@ import { debugLogger } from '../../utils/debugLogger.js';
|
||||
import type {
|
||||
ContextEnvironment,
|
||||
ContextTracer,
|
||||
} from '../sidecar/environment.js';
|
||||
import type { PipelineOrchestrator } from '../sidecar/orchestrator.js';
|
||||
import type { ContextProfile } from '../sidecar/profiles.js';
|
||||
} from '../pipeline/environment.js';
|
||||
import type { PipelineOrchestrator } from '../pipeline/orchestrator.js';
|
||||
import type { ContextProfile } from '../config/profiles.js';
|
||||
|
||||
export class IrProjector {
|
||||
/**
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ export class InboxSnapshotImpl implements InboxSnapshot {
|
||||
* completely erases generic type information (<T>) at runtime, the central array
|
||||
* can only hold `unknown` payloads. To enforce strict type safety without a central
|
||||
* registry (which would break decoupling) or heavy runtime validation (Zod schemas),
|
||||
* we must assert the type boundary here. The contract relies on the Worker and Processor
|
||||
* we must assert the type boundary here. The contract relies on the async pipeline and Processor
|
||||
* agreeing on the payload structure associated with the configured topic string.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
+4
-4
@@ -17,7 +17,7 @@ import type {
|
||||
AsyncContextProcessor,
|
||||
ProcessArgs,
|
||||
} from '../pipeline.js';
|
||||
import type { PipelineDef, AsyncPipelineDef } from './types.js';
|
||||
import type { PipelineDef, AsyncPipelineDef } from '../config/types.js';
|
||||
import type { ContextEventBus } from '../eventBus.js';
|
||||
import type { ConcreteNode, UserPrompt } from '../ir/types.js';
|
||||
|
||||
@@ -180,10 +180,10 @@ describe('PipelineOrchestrator (Component)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Asynchronous Worker Events', () => {
|
||||
describe('Asynchronous async pipeline Events', () => {
|
||||
it('routes emitChunkReceived to async pipelines with nodes_added trigger', async () => {
|
||||
const executeSpy = vi.fn();
|
||||
const asyncProcessor = createMockAsyncProcessor('MyWorker', executeSpy);
|
||||
const asyncProcessor = createMockAsyncProcessor('MyAsyncProcessor', executeSpy);
|
||||
|
||||
setupOrchestrator([], [{
|
||||
name: 'TestAsync',
|
||||
@@ -204,7 +204,7 @@ describe('PipelineOrchestrator (Component)', () => {
|
||||
|
||||
expect(executeSpy).toHaveBeenCalledTimes(1);
|
||||
const callArgs = executeSpy.mock.calls[0][0];
|
||||
expect(callArgs.targets).toEqual([node2]); // Workers only get the target nodes
|
||||
expect(callArgs.targets).toEqual([node2]); // AsyncProcessors only get the target nodes
|
||||
});
|
||||
});
|
||||
});
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import type { ConcreteNode } from '../ir/types.js';
|
||||
import type { AsyncPipelineDef, PipelineDef, PipelineTrigger } from './types.js';
|
||||
import type { AsyncPipelineDef, PipelineDef, PipelineTrigger } from '../config/types.js';
|
||||
import type {
|
||||
ContextEnvironment,
|
||||
ContextEventBus,
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
import type { ProcessArgs, ContextProcessor } from '../pipeline.js';
|
||||
import type { ConcreteNode, UserPrompt } from '../ir/types.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
import { sanitizeFilenamePart } from '../../utils/fileUtils.js';
|
||||
|
||||
export function createBlobDegradationProcessor(
|
||||
|
||||
@@ -10,7 +10,7 @@ import type {
|
||||
ProcessArgs,
|
||||
} from '../pipeline.js';
|
||||
import type { ConcreteNode } from '../ir/types.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
|
||||
export type HistoryTruncationProcessorOptions = BackstopTargetOptions;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
import type { ContextProcessor, ProcessArgs } from '../pipeline.js';
|
||||
import type { ConcreteNode } from '../ir/types.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
import { debugLogger } from '../../utils/debugLogger.js';
|
||||
import { getResponseText } from '../../utils/partUtils.js';
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
import type { ContextProcessor, ProcessArgs } from '../pipeline.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
import { truncateProportionally } from '../truncation.js';
|
||||
import type { ConcreteNode } from '../ir/types.js';
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
ProcessArgs,
|
||||
BackstopTargetOptions,
|
||||
} from '../pipeline.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
import type { ConcreteNode, RollingSummary } from '../ir/types.js';
|
||||
import { SnapshotGenerator } from '../utils/snapshotGenerator.js';
|
||||
import { debugLogger } from '../../utils/debugLogger.js';
|
||||
|
||||
@@ -11,15 +11,15 @@ import {
|
||||
createMockProcessArgs,
|
||||
} from '../testing/contextTestUtils.js';
|
||||
import type { InboxMessage } from '../pipeline.js';
|
||||
import type { InboxSnapshotImpl } from '../sidecar/inbox.js';
|
||||
import type { InboxSnapshotImpl } from '../pipeline/inbox.js';
|
||||
|
||||
describe('StateSnapshotWorker', () => {
|
||||
describe('StateSnapshotAsyncProcessor', () => {
|
||||
it('should generate a snapshot and publish it to the inbox', async () => {
|
||||
const env = createMockEnvironment();
|
||||
// Spy on the publish method
|
||||
const publishSpy = vi.spyOn(env.inbox, 'publish');
|
||||
|
||||
const worker = createStateSnapshotAsyncProcessor('StateSnapshotWorker', env, { type: 'point-in-time' });
|
||||
const worker = createStateSnapshotAsyncProcessor('StateSnapshotAsyncProcessor', env, { type: 'point-in-time' });
|
||||
|
||||
const nodeA = createDummyNode('ep1', 'USER_PROMPT', 50, {}, 'node-A');
|
||||
const nodeB = createDummyNode('ep1', 'AGENT_THOUGHT', 60, {}, 'node-B');
|
||||
@@ -47,7 +47,7 @@ describe('StateSnapshotWorker', () => {
|
||||
const publishSpy = vi.spyOn(env.inbox, 'publish');
|
||||
const drainSpy = vi.spyOn(env.inbox, 'drainConsumed');
|
||||
|
||||
const worker = createStateSnapshotAsyncProcessor('StateSnapshotWorker', env, { type: 'accumulate' });
|
||||
const worker = createStateSnapshotAsyncProcessor('StateSnapshotAsyncProcessor', env, { type: 'accumulate' });
|
||||
|
||||
const nodeC = createDummyNode('ep2', 'USER_PROMPT', 50, {}, 'node-C');
|
||||
const targets = [nodeC];
|
||||
@@ -103,7 +103,7 @@ describe('StateSnapshotWorker', () => {
|
||||
it('should ignore empty targets', async () => {
|
||||
const env = createMockEnvironment();
|
||||
const publishSpy = vi.spyOn(env.inbox, 'publish');
|
||||
const worker = createStateSnapshotAsyncProcessor('StateSnapshotWorker', env, { type: 'accumulate' });
|
||||
const worker = createStateSnapshotAsyncProcessor('StateSnapshotAsyncProcessor', env, { type: 'accumulate' });
|
||||
|
||||
await worker.process(createMockProcessArgs([], [], []));
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
import type { AsyncContextProcessor, ProcessArgs } from '../pipeline.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
import type { ConcreteNode } from '../ir/types.js';
|
||||
import { SnapshotGenerator } from '../utils/snapshotGenerator.js';
|
||||
import { debugLogger } from '../../utils/debugLogger.js';
|
||||
@@ -30,9 +30,9 @@ export function createStateSnapshotAsyncProcessor(
|
||||
try {
|
||||
let nodesToSummarize = [...targets];
|
||||
let previousConsumedIds: string[] = [];
|
||||
const workerType = options.type ?? 'point-in-time';
|
||||
const processorType = options.type ?? 'point-in-time';
|
||||
|
||||
if (workerType === 'accumulate') {
|
||||
if (processorType === 'accumulate') {
|
||||
// Look for the most recent unconsumed accumulate snapshot in the inbox
|
||||
const proposedSnapshots = inbox.getMessages<{
|
||||
newText: string;
|
||||
@@ -80,13 +80,13 @@ export function createStateSnapshotAsyncProcessor(
|
||||
...targets.map((t) => t.id),
|
||||
];
|
||||
|
||||
// In V2, workers communicate their work to the inbox, and the processor picks it up.
|
||||
// In V2, async pipelines communicate their work to the inbox, and the processor picks it up.
|
||||
env.inbox.publish(
|
||||
'PROPOSED_SNAPSHOT',
|
||||
{
|
||||
newText: snapshotText,
|
||||
consumedIds: newConsumedIds,
|
||||
type: workerType,
|
||||
type: processorType,
|
||||
},
|
||||
env.idGenerator,
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
createDummyNode,
|
||||
createMockProcessArgs,
|
||||
} from '../testing/contextTestUtils.js';
|
||||
import type { InboxSnapshotImpl } from '../sidecar/inbox.js';
|
||||
import type { InboxSnapshotImpl } from '../pipeline/inbox.js';
|
||||
|
||||
describe('StateSnapshotProcessor', () => {
|
||||
it('should ignore if budget is satisfied', async () => {
|
||||
@@ -35,7 +35,7 @@ describe('StateSnapshotProcessor', () => {
|
||||
|
||||
const targets = [nodeA, nodeB, nodeC];
|
||||
|
||||
// The background worker created a snapshot of A and B
|
||||
// The async background pipeline created a snapshot of A and B
|
||||
const messages = [
|
||||
{
|
||||
id: 'msg-1',
|
||||
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
ProcessArgs,
|
||||
BackstopTargetOptions,
|
||||
} from '../pipeline.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
import type { ConcreteNode, Snapshot } from '../ir/types.js';
|
||||
import { SnapshotGenerator } from '../utils/snapshotGenerator.js';
|
||||
import { debugLogger } from '../../utils/debugLogger.js';
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
import type { ContextProcessor, ProcessArgs } from '../pipeline.js';
|
||||
import type { ConcreteNode, ToolExecution } from '../ir/types.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
import { sanitizeFilenamePart } from '../../utils/fileUtils.js';
|
||||
import {
|
||||
ACTIVATE_SKILL_TOOL_NAME,
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
import { ContextManager } from '../contextManager.js';
|
||||
import { AgentChatHistory } from '../../core/agentChatHistory.js';
|
||||
import type { Content } from '@google/genai';
|
||||
import type { ContextProfile } from '../sidecar/profiles.js';
|
||||
import { ContextEnvironmentImpl } from '../sidecar/environmentImpl.js';
|
||||
import type { ContextProfile } from '../config/profiles.js';
|
||||
import { ContextEnvironmentImpl } from '../pipeline/environmentImpl.js';
|
||||
import { ContextTracer } from '../tracer.js';
|
||||
import { ContextEventBus } from '../eventBus.js';
|
||||
import { PipelineOrchestrator } from '../sidecar/orchestrator.js';
|
||||
import { PipelineOrchestrator } from '../pipeline/orchestrator.js';
|
||||
import { debugLogger } from '../../utils/debugLogger.js';
|
||||
import { DeterministicIdGenerator } from '../system/DeterministicIdGenerator.js';
|
||||
import { InMemoryFileSystem } from '../system/InMemoryFileSystem.js';
|
||||
|
||||
@@ -218,7 +218,7 @@ exports[`System Lifecycle Golden Tests > Scenario 2: Under Budget (No Modificati
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`System Lifecycle Golden Tests > Scenario 3: Worker-Driven Background GC 1`] = `
|
||||
exports[`System Lifecycle Golden Tests > Scenario 3: Async-Driven Background GC 1`] = `
|
||||
{
|
||||
"finalProjection": [
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { describe, it, expect, vi, beforeAll, afterAll } from 'vitest';
|
||||
import { SimulationHarness } from './SimulationHarness.js';
|
||||
import { createMockLlmClient } from '../testing/contextTestUtils.js';
|
||||
import type { ContextProfile } from '../sidecar/profiles.js';
|
||||
import type { ContextProfile } from '../config/profiles.js';
|
||||
import { createToolMaskingProcessor } from '../processors/toolMaskingProcessor.js';
|
||||
import { createBlobDegradationProcessor } from '../processors/blobDegradationProcessor.js';
|
||||
import { createStateSnapshotProcessor } from '../processors/stateSnapshotProcessor.js';
|
||||
@@ -61,7 +61,7 @@ describe('System Lifecycle Golden Tests', () => {
|
||||
buildAsyncPipelines: (env) => [{
|
||||
name: 'Async',
|
||||
triggers: ['nodes_aged_out'],
|
||||
processors: [createStateSnapshotAsyncProcessor('StateSnapshotWorker', env, {})]
|
||||
processors: [createStateSnapshotAsyncProcessor('StateSnapshotAsyncProcessor', env, {})]
|
||||
}],
|
||||
});
|
||||
|
||||
@@ -180,7 +180,7 @@ describe('System Lifecycle Golden Tests', () => {
|
||||
expect(goldenState).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('Scenario 3: Worker-Driven Background GC', async () => {
|
||||
it('Scenario 3: Async-Driven Background GC', async () => {
|
||||
const gcConfig: ContextProfile = {
|
||||
config: {
|
||||
budget: { maxTokens: 200, retainedTokens: 100 },
|
||||
@@ -189,7 +189,7 @@ describe('System Lifecycle Golden Tests', () => {
|
||||
buildAsyncPipelines: (env) => [{
|
||||
name: 'Async',
|
||||
triggers: ['nodes_aged_out'],
|
||||
processors: [createStateSnapshotAsyncProcessor('StateSnapshotWorker', env, {})]
|
||||
processors: [createStateSnapshotAsyncProcessor('StateSnapshotAsyncProcessor', env, {})]
|
||||
}],
|
||||
};
|
||||
|
||||
@@ -201,13 +201,13 @@ describe('System Lifecycle Golden Tests', () => {
|
||||
{ role: 'model', parts: [{ text: 'B'.repeat(50) }] },
|
||||
]);
|
||||
|
||||
// Turn 1 (Should trigger StateSnapshotWorker because we exceed 100 retainedTokens)
|
||||
// Turn 1 (Should trigger StateSnapshotasync pipeline because we exceed 100 retainedTokens)
|
||||
await harness.simulateTurn([
|
||||
{ role: 'user', parts: [{ text: 'C'.repeat(50) }] },
|
||||
{ role: 'model', parts: [{ text: 'D'.repeat(50) }] },
|
||||
]);
|
||||
|
||||
// Give the background worker an extra beat to complete its async execution and emit variants
|
||||
// Give the async background pipeline an extra beat to complete its async execution and emit variants
|
||||
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||
|
||||
// Turn 2
|
||||
@@ -218,7 +218,7 @@ describe('System Lifecycle Golden Tests', () => {
|
||||
|
||||
const goldenState = await harness.getGoldenState();
|
||||
|
||||
// We should see ROLLING_SUMMARY nodes injected into the graph, proving the worker ran in the background
|
||||
// We should see ROLLING_SUMMARY nodes injected into the graph, proving the async pipeline ran in the background
|
||||
expect(goldenState).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,19 +11,19 @@ import { InMemoryFileSystem } from '../system/InMemoryFileSystem.js';
|
||||
import { DeterministicIdGenerator } from '../system/DeterministicIdGenerator.js';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { ContextTracer } from '../tracer.js';
|
||||
import { ContextEnvironmentImpl } from '../sidecar/environmentImpl.js';
|
||||
import { SidecarLoader } from '../sidecar/SidecarLoader.js';
|
||||
import { SidecarRegistry } from '../sidecar/registry.js';
|
||||
import { ContextEnvironmentImpl } from '../pipeline/environmentImpl.js';
|
||||
import { SidecarLoader } from '../config/SidecarLoader.js';
|
||||
import { SidecarRegistry } from '../config/registry.js';
|
||||
import { ContextEventBus } from '../eventBus.js';
|
||||
import { PipelineOrchestrator } from '../sidecar/orchestrator.js';
|
||||
import { PipelineOrchestrator } from '../pipeline/orchestrator.js';
|
||||
import type { ConcreteNode, ToolExecution } from '../ir/types.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
import type { Config } from '../../config/config.js';
|
||||
import type { BaseLlmClient } from '../../core/baseLlmClient.js';
|
||||
import type { Content, GenerateContentResponse } from '@google/genai';
|
||||
import { InboxSnapshotImpl } from '../sidecar/inbox.js';
|
||||
import { InboxSnapshotImpl } from '../pipeline/inbox.js';
|
||||
import type { InboxMessage, ProcessArgs } from '../pipeline.js';
|
||||
import type { ContextProfile } from '../sidecar/profiles.js';
|
||||
import type { ContextProfile } from '../config/profiles.js';
|
||||
|
||||
/**
|
||||
* Creates a valid mock GenerateContentResponse with the provided text.
|
||||
@@ -172,7 +172,7 @@ export function createMockEnvironment(
|
||||
* Creates a block of synthetic conversation history designed to consume a specific number of tokens.
|
||||
* Assumes roughly 4 characters per token for standard English text.
|
||||
*/
|
||||
import { ContextWorkingBufferImpl } from '../sidecar/contextWorkingBuffer.js';
|
||||
import { ContextWorkingBufferImpl } from '../pipeline/contextWorkingBuffer.js';
|
||||
|
||||
export function createMockProcessArgs(
|
||||
targets: ConcreteNode[],
|
||||
@@ -239,7 +239,7 @@ export function createMockContextConfig(
|
||||
}
|
||||
|
||||
/**
|
||||
* Wires up a full ContextManager component with an AgentChatHistory and active background workers.
|
||||
* Wires up a full ContextManager component with an AgentChatHistory and active background async pipelines.
|
||||
*/
|
||||
|
||||
export function setupContextComponentTest(
|
||||
@@ -281,6 +281,6 @@ export function setupContextComponentTest(
|
||||
chatHistory,
|
||||
);
|
||||
|
||||
// The async worker is now internally managed by ContextManager
|
||||
// The async async pipeline is now internally managed by ContextManager
|
||||
return { chatHistory, contextManager };
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
import type { ContextProfile } from '../sidecar/profiles.js';
|
||||
import type { PipelineDef } from '../sidecar/types.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { ContextProfile } from '../config/profiles.js';
|
||||
import type { PipelineDef } from '../config/types.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
import { createHistoryTruncationProcessor } from '../processors/historyTruncationProcessor.js';
|
||||
|
||||
export const testTruncateProfile: ContextProfile = {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
import type { ConcreteNode } from '../ir/types.js';
|
||||
import type { ContextEnvironment } from '../sidecar/environment.js';
|
||||
import type { ContextEnvironment } from '../pipeline/environment.js';
|
||||
import { LlmRole } from '../../telemetry/llmRole.js';
|
||||
|
||||
export class SnapshotGenerator {
|
||||
|
||||
Reference in New Issue
Block a user