chore(context): remove dead initialization trigger and unawaited promise

This commit is contained in:
Your Name
2026-05-13 00:54:24 +00:00
parent cdd482c2e0
commit 78a0e5d457
9 changed files with 309 additions and 4 deletions
+3
View File
@@ -688,6 +688,7 @@ export interface ConfigParameters {
enableShellOutputEfficiency?: boolean;
shellToolInactivityTimeout?: number;
fakeResponses?: string;
fakeResponsesNonStrict?: string;
recordResponses?: string;
ptyInfo?: string;
disableYoloMode?: boolean;
@@ -919,6 +920,7 @@ export class Config implements McpContext, AgentLoopContext {
private readonly enableShellOutputEfficiency: boolean;
private readonly shellToolInactivityTimeout: number;
readonly fakeResponses?: string;
readonly fakeResponsesNonStrict?: string;
readonly recordResponses?: string;
private readonly disableYoloMode: boolean;
private readonly disableAlwaysAllow: boolean;
@@ -1299,6 +1301,7 @@ export class Config implements McpContext, AgentLoopContext {
this.storage.setCustomPlansDir(params.planSettings?.directory);
this.fakeResponses = params.fakeResponses;
this.fakeResponsesNonStrict = params.fakeResponsesNonStrict;
this.recordResponses = params.recordResponses;
this.fileExclusions = new FileExclusions(this);
this.eventEmitter = params.eventEmitter;
@@ -7,7 +7,6 @@
import type { ContextProcessor, AsyncContextProcessor } from '../pipeline.js';
export type PipelineTrigger =
| 'initialization'
| 'new_message'
| 'retained_exceeded'
| 'gc_backstop'
+1 -1
View File
@@ -437,7 +437,7 @@ export class ContextManager {
return SnapshotStateHelper.exportState(this.buffer.nodes);
}
async restoreState(state: ContextEngineState): Promise<void> {
restoreState(state: ContextEngineState): void {
if (!state) return;
SnapshotStateHelper.restoreState(state, this.env.inbox);
}
@@ -90,6 +90,9 @@ export function createStateSnapshotProcessor(
const isValid = consumedIds.every((id) => targetIds.has(id));
if (isValid) {
debugLogger.log(
`[StateSnapshotProcessor] Successfully spliced PROPOSED_SNAPSHOT from Inbox into Graph. Consumed ${consumedIds.length} nodes.`,
);
// If valid, apply it!
const newId = randomUUID();
@@ -120,6 +123,10 @@ export function createStateSnapshotProcessor(
inbox.consume(proposed.id);
return returnedNodes;
} else {
debugLogger.log(
`[StateSnapshotProcessor] Rejected PROPOSED_SNAPSHOT from Inbox because one or more target IDs were missing from the current graph window.`,
);
}
}
}
@@ -82,12 +82,21 @@ export function findLatestSnapshotBaseline(
import type { LiveInbox } from '../pipeline/inbox.js';
import type { ContextEngineState } from '../../services/chatRecordingTypes.js';
import { debugLogger } from '../../utils/debugLogger.js';
export const SnapshotStateHelper = {
exportState(nodes: readonly ConcreteNode[]): ContextEngineState {
const baseline = findLatestSnapshotBaseline(nodes);
if (!baseline) return {};
if (!baseline) {
debugLogger.log(
'[SnapshotStateHelper] exportState: No snapshot baseline found in current nodes.',
);
return {};
}
debugLogger.log(
`[SnapshotStateHelper] exportState: Exporting snapshot ID ${baseline.id} representing ${baseline.abstractsIds.length} consumed nodes.`,
);
return {
snapshot: {
text: baseline.text,
@@ -98,18 +107,30 @@ export const SnapshotStateHelper = {
},
restoreState(state: ContextEngineState, inbox: LiveInbox): void {
if (!state.snapshot) return;
if (!state.snapshot) {
debugLogger.log(
'[SnapshotStateHelper] restoreState: No snapshot found in provided ContextEngineState.',
);
return;
}
if (
typeof state.snapshot.text === 'string' &&
Array.isArray(state.snapshot.consumedIds)
) {
debugLogger.log(
`[SnapshotStateHelper] restoreState: Publishing hydrated snapshot to LiveInbox with ${state.snapshot.consumedIds.length} consumed IDs.`,
);
inbox.publish('PROPOSED_SNAPSHOT', {
newText: state.snapshot.text,
consumedIds: state.snapshot.consumedIds,
type: 'accumulate',
timestamp: state.snapshot.timestamp ?? Date.now(),
});
} else {
debugLogger.log(
'[SnapshotStateHelper] restoreState: Invalid snapshot structural format.',
);
}
},
};
@@ -23,6 +23,7 @@ import type { UserTierId, GeminiUserTier } from '../code_assist/types.js';
import { LoggingContentGenerator } from './loggingContentGenerator.js';
import { InstallationManager } from '../utils/installationManager.js';
import { FakeContentGenerator } from './fakeContentGenerator.js';
import { NonStrictFakeContentGenerator } from './nonStrictFakeContentGenerator.js';
import { parseCustomHeaders } from '../utils/customHeaderUtils.js';
import { determineSurface } from '../utils/surface.js';
import { RecordingContentGenerator } from './recordingContentGenerator.js';
@@ -193,6 +194,12 @@ export async function createContentGenerator(
sessionId?: string,
): Promise<ContentGenerator> {
const generator = await (async () => {
if (gcConfig.fakeResponsesNonStrict) {
const fakeGenerator = await NonStrictFakeContentGenerator.fromFile(
gcConfig.fakeResponsesNonStrict,
);
return new LoggingContentGenerator(fakeGenerator, gcConfig);
}
if (gcConfig.fakeResponses) {
const fakeGenerator = await FakeContentGenerator.fromFile(
gcConfig.fakeResponses,
@@ -0,0 +1,111 @@
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {
GenerateContentResponse,
type CountTokensResponse,
type GenerateContentParameters,
type CountTokensParameters,
EmbedContentResponse,
type EmbedContentParameters,
} from '@google/genai';
import { promises } from 'node:fs';
import type { ContentGenerator } from './contentGenerator.js';
import type { UserTierId, GeminiUserTier } from '../code_assist/types.js';
import { safeJsonStringify } from '../utils/safeJsonStringify.js';
import type { LlmRole } from '../telemetry/types.js';
import type { FakeResponse } from './fakeContentGenerator.js';
/**
* A ContentGenerator that responds with canned responses, but unlike FakeContentGenerator,
* it is "non-strict": it will find and use the first available response that matches
* the requested method, rather than strictly following the input order.
*
* This is useful for testing asynchronous or non-deterministic background tasks
* (like token calibration or background snapshots) that might fire out-of-order.
*/
export class NonStrictFakeContentGenerator implements ContentGenerator {
userTier?: UserTierId;
userTierName?: string;
paidTier?: GeminiUserTier;
constructor(private readonly responses: FakeResponse[]) {}
static async fromFile(
filePath: string,
): Promise<NonStrictFakeContentGenerator> {
const fileContent = await promises.readFile(filePath, 'utf-8');
const responses = fileContent
.split('\n')
.filter((line) => line.trim() !== '')
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
.map((line) => JSON.parse(line) as FakeResponse);
return new NonStrictFakeContentGenerator(responses);
}
private getNextResponse<
M extends FakeResponse['method'],
R = Extract<FakeResponse, { method: M }>['response'],
>(method: M, request: unknown): R {
const index = this.responses.findIndex((r) => r.method === method);
if (index === -1) {
throw new Error(
`No more mock responses for ${method}, got request:\n` +
safeJsonStringify(request),
);
}
const response = this.responses.splice(index, 1)[0];
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
return response.response as R;
}
async generateContent(
request: GenerateContentParameters,
_userPromptId: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
role: LlmRole,
): Promise<GenerateContentResponse> {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return Object.setPrototypeOf(
this.getNextResponse('generateContent', request),
GenerateContentResponse.prototype,
);
}
async generateContentStream(
request: GenerateContentParameters,
_userPromptId: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
role: LlmRole,
): Promise<AsyncGenerator<GenerateContentResponse>> {
const responses = this.getNextResponse('generateContentStream', request);
async function* stream() {
for (const response of responses) {
yield Object.setPrototypeOf(
response,
GenerateContentResponse.prototype,
);
}
}
return stream();
}
async countTokens(
request: CountTokensParameters,
): Promise<CountTokensResponse> {
return this.getNextResponse('countTokens', request);
}
async embedContent(
request: EmbedContentParameters,
): Promise<EmbedContentResponse> {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return Object.setPrototypeOf(
this.getNextResponse('embedContent', request),
EmbedContentResponse.prototype,
);
}
}