mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-15 22:33:05 -07:00
feat(cli): add support for external knowledge sources in UserSimulator
This commit is contained in:
@@ -98,6 +98,7 @@ export interface CliArgs {
|
||||
acceptRawOutputRisk: boolean | undefined;
|
||||
isCommand: boolean | undefined;
|
||||
simulateUser: boolean | undefined;
|
||||
knowledgeSources: string[] | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,6 +305,14 @@ export async function parseArguments(
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Run the user simulation agent in the background for evaluation purposes.',
|
||||
})
|
||||
.option('knowledge-sources', {
|
||||
type: 'array',
|
||||
string: true,
|
||||
nargs: 1,
|
||||
description:
|
||||
'List of files or folders to load into the user simulator context (comma-separated or multiple --knowledge-sources)',
|
||||
coerce: coerceCommaSeparated,
|
||||
}),
|
||||
)
|
||||
// Register MCP subcommands
|
||||
@@ -806,6 +815,7 @@ export async function loadCliConfig(
|
||||
disableYoloMode:
|
||||
settings.security?.disableYoloMode || settings.admin?.secureModeEnabled,
|
||||
simulateUser: !!argv.simulateUser,
|
||||
knowledgeSources: argv.knowledgeSources,
|
||||
disableAlwaysAllow:
|
||||
settings.security?.disableAlwaysAllow ||
|
||||
settings.admin?.secureModeEnabled,
|
||||
|
||||
@@ -514,6 +514,7 @@ describe('gemini.tsx main function kitty protocol', () => {
|
||||
acceptRawOutputRisk: undefined,
|
||||
isCommand: undefined,
|
||||
simulateUser: undefined,
|
||||
knowledgeSources: undefined,
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from '@google/gemini-cli-core';
|
||||
import type { Writable } from 'node:stream';
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
|
||||
export class UserSimulator {
|
||||
private isRunning = false;
|
||||
@@ -20,6 +21,7 @@ export class UserSimulator {
|
||||
private isProcessing = false;
|
||||
private interactionsFile: string | null = null;
|
||||
private actionHistory: string[] = [];
|
||||
private knowledgeBase = '';
|
||||
|
||||
constructor(
|
||||
private readonly config: Config,
|
||||
@@ -31,6 +33,10 @@ export class UserSimulator {
|
||||
if (!this.config.getSimulateUser()) {
|
||||
return;
|
||||
}
|
||||
const sources = (this.config as any).getKnowledgeSources?.() || [];
|
||||
if (sources.length > 0) {
|
||||
this.loadKnowledge(sources);
|
||||
}
|
||||
this.interactionsFile = `interactions_${Date.now()}.txt`;
|
||||
this.isRunning = true;
|
||||
this.timer = setInterval(() => this.tick(), 3000);
|
||||
@@ -45,6 +51,30 @@ export class UserSimulator {
|
||||
debugLogger.log('User simulator stopped');
|
||||
}
|
||||
|
||||
private loadKnowledge(paths: string[]) {
|
||||
const loadFromPath = (p: string) => {
|
||||
try {
|
||||
if (!fs.existsSync(p)) return;
|
||||
const stats = fs.statSync(p);
|
||||
if (stats.isFile()) {
|
||||
const content = fs.readFileSync(p, 'utf-8');
|
||||
this.knowledgeBase += `\nFile: ${p}\nContent:\n${content}\n---\n`;
|
||||
} else if (stats.isDirectory()) {
|
||||
const files = fs.readdirSync(p);
|
||||
for (const file of files) {
|
||||
loadFromPath(path.join(p, file));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
debugLogger.error(`Failed to load knowledge from ${p}`, e);
|
||||
}
|
||||
};
|
||||
|
||||
for (const p of paths) {
|
||||
loadFromPath(p);
|
||||
}
|
||||
}
|
||||
|
||||
private async tick() {
|
||||
if (!this.isRunning || this.isProcessing) return;
|
||||
|
||||
@@ -91,6 +121,10 @@ export class UserSimulator {
|
||||
? `\nYou have previously taken the following actions (in order):\n${this.actionHistory.map((a, i) => `${i + 1}. ${JSON.stringify(a)}`).join('\n')}\nPay close attention to whether you have already asked for the original goal. If you have already submitted the original goal, DO NOT repeat it verbatim. If the UI shows your typed text but hasn't submitted it yet, just output \\r to press Enter.\n`
|
||||
: '';
|
||||
|
||||
const knowledgeInstruction = this.knowledgeBase
|
||||
? `\nUser Knowledge Base:\nUse this information to answer questions if applicable. If the answer is not here, respond as you normally would.\n${this.knowledgeBase}\n`
|
||||
: '';
|
||||
|
||||
const prompt = `You are evaluating a CLI agent by simulating a user sitting at the terminal.
|
||||
Look carefully at the screen and determine the CLI's current state:
|
||||
|
||||
@@ -114,7 +148,7 @@ CRITICAL RULES:
|
||||
- RULE 2: If there is an "Action Required" or confirmation prompt on the screen, YOU MUST HANDLE IT (State 2). This takes precedence over everything else.
|
||||
- RULE 3: Output ONLY the raw characters to send, <WAIT>, or <DONE>.
|
||||
- RULE 4: Do NOT output markdown, explanations of your thought process, or quotes.
|
||||
${goalInstruction}${historyInstruction}
|
||||
${goalInstruction}${historyInstruction}${knowledgeInstruction}
|
||||
|
||||
Here is the current terminal screen output:
|
||||
|
||||
|
||||
@@ -650,6 +650,7 @@ export interface ConfigParameters {
|
||||
overageStrategy?: OverageStrategy;
|
||||
};
|
||||
simulateUser?: boolean;
|
||||
knowledgeSources?: string[];
|
||||
}
|
||||
|
||||
export class Config implements McpContext, AgentLoopContext {
|
||||
@@ -868,6 +869,7 @@ export class Config implements McpContext, AgentLoopContext {
|
||||
readonly injectionService: InjectionService;
|
||||
private approvedPlanPath: string | undefined;
|
||||
private readonly simulateUser: boolean;
|
||||
private readonly knowledgeSources: string[];
|
||||
|
||||
constructor(params: ConfigParameters) {
|
||||
this._sessionId = params.sessionId;
|
||||
@@ -1098,6 +1100,7 @@ export class Config implements McpContext, AgentLoopContext {
|
||||
this.eventEmitter = params.eventEmitter;
|
||||
this.enableConseca = params.enableConseca ?? false;
|
||||
this.simulateUser = params.simulateUser ?? false;
|
||||
this.knowledgeSources = params.knowledgeSources ?? [];
|
||||
|
||||
// Initialize Safety Infrastructure
|
||||
const contextBuilder = new ContextBuilder(this);
|
||||
@@ -2515,6 +2518,10 @@ export class Config implements McpContext, AgentLoopContext {
|
||||
getSimulateUser(): boolean {
|
||||
return this.simulateUser;
|
||||
}
|
||||
|
||||
getKnowledgeSources(): string[] {
|
||||
return this.knowledgeSources;
|
||||
}
|
||||
|
||||
getAcpMode(): boolean {
|
||||
return this.acpMode;
|
||||
|
||||
Reference in New Issue
Block a user