Make checkpoints configurable in settings.json (#1251)
This commit is contained in:
parent
ea63a8401e
commit
6c67618624
|
@ -186,4 +186,22 @@ describe('Configuration Integration Tests', () => {
|
||||||
expect(config.getFileFilteringRespectGitIgnore()).toBe(false);
|
expect(config.getFileFilteringRespectGitIgnore()).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Checkpointing Configuration', () => {
|
||||||
|
it('should enable checkpointing when the setting is true', async () => {
|
||||||
|
const configParams: ConfigParameters = {
|
||||||
|
cwd: '/tmp',
|
||||||
|
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
|
||||||
|
embeddingModel: 'test-embedding-model',
|
||||||
|
sandbox: false,
|
||||||
|
targetDir: tempDir,
|
||||||
|
debugMode: false,
|
||||||
|
checkpointing: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = new Config(configParams);
|
||||||
|
|
||||||
|
expect(config.getCheckpointingEnabled()).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -49,7 +49,7 @@ interface CliArgs {
|
||||||
show_memory_usage: boolean | undefined;
|
show_memory_usage: boolean | undefined;
|
||||||
yolo: boolean | undefined;
|
yolo: boolean | undefined;
|
||||||
telemetry: boolean | undefined;
|
telemetry: boolean | undefined;
|
||||||
checkpoint: boolean | undefined;
|
checkpointing: boolean | undefined;
|
||||||
telemetryTarget: string | undefined;
|
telemetryTarget: string | undefined;
|
||||||
telemetryOtlpEndpoint: string | undefined;
|
telemetryOtlpEndpoint: string | undefined;
|
||||||
telemetryLogPrompts: boolean | undefined;
|
telemetryLogPrompts: boolean | undefined;
|
||||||
|
@ -122,7 +122,7 @@ async function parseArguments(): Promise<CliArgs> {
|
||||||
description:
|
description:
|
||||||
'Enable or disable logging of user prompts for telemetry. Overrides settings files.',
|
'Enable or disable logging of user prompts for telemetry. Overrides settings files.',
|
||||||
})
|
})
|
||||||
.option('checkpoint', {
|
.option('checkpointing', {
|
||||||
alias: 'c',
|
alias: 'c',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
description: 'Enables checkpointing of file edits',
|
description: 'Enables checkpointing of file edits',
|
||||||
|
@ -229,7 +229,7 @@ export async function loadCliConfig(
|
||||||
},
|
},
|
||||||
// Git-aware file filtering settings
|
// Git-aware file filtering settings
|
||||||
fileFilteringRespectGitIgnore: settings.fileFiltering?.respectGitIgnore,
|
fileFilteringRespectGitIgnore: settings.fileFiltering?.respectGitIgnore,
|
||||||
checkpoint: argv.checkpoint,
|
checkpointing: argv.checkpointing || settings.checkpointing?.enabled,
|
||||||
proxy:
|
proxy:
|
||||||
process.env.HTTPS_PROXY ||
|
process.env.HTTPS_PROXY ||
|
||||||
process.env.https_proxy ||
|
process.env.https_proxy ||
|
||||||
|
|
|
@ -27,6 +27,10 @@ export enum SettingScope {
|
||||||
Workspace = 'Workspace',
|
Workspace = 'Workspace',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CheckpointingSettings {
|
||||||
|
enabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface AccessibilitySettings {
|
export interface AccessibilitySettings {
|
||||||
disableLoadingPhrases?: boolean;
|
disableLoadingPhrases?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +51,7 @@ export interface Settings {
|
||||||
telemetry?: TelemetrySettings;
|
telemetry?: TelemetrySettings;
|
||||||
preferredEditor?: string;
|
preferredEditor?: string;
|
||||||
bugCommand?: BugCommandSettings;
|
bugCommand?: BugCommandSettings;
|
||||||
|
checkpointing?: CheckpointingSettings;
|
||||||
|
|
||||||
// Git-aware file filtering settings
|
// Git-aware file filtering settings
|
||||||
fileFiltering?: {
|
fileFiltering?: {
|
||||||
|
|
|
@ -51,7 +51,7 @@ export async function main() {
|
||||||
|
|
||||||
// Initialize centralized FileDiscoveryService
|
// Initialize centralized FileDiscoveryService
|
||||||
config.getFileService();
|
config.getFileService();
|
||||||
if (config.getCheckpointEnabled()) {
|
if (config.getCheckpointingEnabled()) {
|
||||||
try {
|
try {
|
||||||
await config.getGitService();
|
await config.getGitService();
|
||||||
} catch {
|
} catch {
|
||||||
|
|
|
@ -123,7 +123,7 @@ vi.mock('@gemini-cli/core', async (importOriginal) => {
|
||||||
getAccessibility: vi.fn(() => opts.accessibility ?? {}),
|
getAccessibility: vi.fn(() => opts.accessibility ?? {}),
|
||||||
getProjectRoot: vi.fn(() => opts.projectRoot),
|
getProjectRoot: vi.fn(() => opts.projectRoot),
|
||||||
getGeminiClient: vi.fn(() => ({})),
|
getGeminiClient: vi.fn(() => ({})),
|
||||||
getCheckpointEnabled: vi.fn(() => opts.checkpoint ?? true),
|
getCheckpointingEnabled: vi.fn(() => opts.checkpointing ?? true),
|
||||||
getAllGeminiMdFilenames: vi.fn(() => ['GEMINI.md']),
|
getAllGeminiMdFilenames: vi.fn(() => ['GEMINI.md']),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -135,7 +135,7 @@ describe('useSlashCommandProcessor', () => {
|
||||||
getSandbox: vi.fn(() => 'test-sandbox'),
|
getSandbox: vi.fn(() => 'test-sandbox'),
|
||||||
getModel: vi.fn(() => 'test-model'),
|
getModel: vi.fn(() => 'test-model'),
|
||||||
getProjectRoot: vi.fn(() => '/test/dir'),
|
getProjectRoot: vi.fn(() => '/test/dir'),
|
||||||
getCheckpointEnabled: vi.fn(() => true),
|
getCheckpointingEnabled: vi.fn(() => true),
|
||||||
getBugCommand: vi.fn(() => undefined),
|
getBugCommand: vi.fn(() => undefined),
|
||||||
} as unknown as Config;
|
} as unknown as Config;
|
||||||
mockCorgiMode = vi.fn();
|
mockCorgiMode = vi.fn();
|
||||||
|
|
|
@ -647,7 +647,7 @@ Add any other context about the problem here.
|
||||||
description:
|
description:
|
||||||
'resume from conversation checkpoint. Usage: /resume [tag]',
|
'resume from conversation checkpoint. Usage: /resume [tag]',
|
||||||
completion: async () => {
|
completion: async () => {
|
||||||
const geminiDir = config?.getGeminiDir();
|
const geminiDir = config?.getProjectTempDir();
|
||||||
if (!geminiDir) {
|
if (!geminiDir) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -805,14 +805,14 @@ Add any other context about the problem here.
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (config?.getCheckpointEnabled()) {
|
if (config?.getCheckpointingEnabled()) {
|
||||||
commands.push({
|
commands.push({
|
||||||
name: 'restore',
|
name: 'restore',
|
||||||
description:
|
description:
|
||||||
'restore a tool call. This will reset the conversation and file history to the state it was in when the tool call was suggested',
|
'restore a tool call. This will reset the conversation and file history to the state it was in when the tool call was suggested',
|
||||||
action: async (_mainCommand, subCommand, _args) => {
|
action: async (_mainCommand, subCommand, _args) => {
|
||||||
const checkpointDir = config?.getGeminiDir()
|
const checkpointDir = config?.getProjectTempDir()
|
||||||
? path.join(config.getGeminiDir(), 'checkpoints')
|
? path.join(config.getProjectTempDir(), 'checkpoints')
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
if (!checkpointDir) {
|
if (!checkpointDir) {
|
||||||
|
|
|
@ -280,7 +280,7 @@ describe('useGeminiStream', () => {
|
||||||
() => ({ getToolSchemaList: vi.fn(() => []) }) as any,
|
() => ({ getToolSchemaList: vi.fn(() => []) }) as any,
|
||||||
),
|
),
|
||||||
getProjectRoot: vi.fn(() => '/test/dir'),
|
getProjectRoot: vi.fn(() => '/test/dir'),
|
||||||
getCheckpointEnabled: vi.fn(() => false),
|
getCheckpointingEnabled: vi.fn(() => false),
|
||||||
getGeminiClient: mockGetGeminiClient,
|
getGeminiClient: mockGetGeminiClient,
|
||||||
addHistory: vi.fn(),
|
addHistory: vi.fn(),
|
||||||
} as unknown as Config;
|
} as unknown as Config;
|
||||||
|
|
|
@ -638,7 +638,7 @@ export const useGeminiStream = (
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const saveRestorableToolCalls = async () => {
|
const saveRestorableToolCalls = async () => {
|
||||||
if (!config.getCheckpointEnabled()) {
|
if (!config.getCheckpointingEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const restorableToolCalls = toolCalls.filter(
|
const restorableToolCalls = toolCalls.filter(
|
||||||
|
@ -649,8 +649,8 @@ export const useGeminiStream = (
|
||||||
);
|
);
|
||||||
|
|
||||||
if (restorableToolCalls.length > 0) {
|
if (restorableToolCalls.length > 0) {
|
||||||
const checkpointDir = config.getGeminiDir()
|
const checkpointDir = config.getProjectTempDir()
|
||||||
? path.join(config.getGeminiDir(), 'checkpoints')
|
? path.join(config.getProjectTempDir(), 'checkpoints')
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
if (!checkpointDir) {
|
if (!checkpointDir) {
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
|
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
import { getProjectTempDir } from '@gemini-cli/core';
|
||||||
|
|
||||||
export async function cleanupCheckpoints() {
|
export async function cleanupCheckpoints() {
|
||||||
const geminiDir = join(process.cwd(), '.gemini');
|
const tempDir = getProjectTempDir(process.cwd());
|
||||||
const checkpointsDir = join(geminiDir, 'checkpoints');
|
const checkpointsDir = join(tempDir, 'checkpoints');
|
||||||
try {
|
try {
|
||||||
await fs.rm(checkpointsDir, { recursive: true, force: true });
|
await fs.rm(checkpointsDir, { recursive: true, force: true });
|
||||||
} catch {
|
} catch {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { GeminiClient } from '../core/client.js';
|
||||||
import { GEMINI_CONFIG_DIR as GEMINI_DIR } from '../tools/memoryTool.js';
|
import { GEMINI_CONFIG_DIR as GEMINI_DIR } from '../tools/memoryTool.js';
|
||||||
import { FileDiscoveryService } from '../services/fileDiscoveryService.js';
|
import { FileDiscoveryService } from '../services/fileDiscoveryService.js';
|
||||||
import { GitService } from '../services/gitService.js';
|
import { GitService } from '../services/gitService.js';
|
||||||
|
import { getProjectTempDir } from '../utils/paths.js';
|
||||||
import {
|
import {
|
||||||
initializeTelemetry,
|
initializeTelemetry,
|
||||||
DEFAULT_TELEMETRY_TARGET,
|
DEFAULT_TELEMETRY_TARGET,
|
||||||
|
@ -104,7 +105,7 @@ export interface ConfigParameters {
|
||||||
accessibility?: AccessibilitySettings;
|
accessibility?: AccessibilitySettings;
|
||||||
telemetry?: TelemetrySettings;
|
telemetry?: TelemetrySettings;
|
||||||
fileFilteringRespectGitIgnore?: boolean;
|
fileFilteringRespectGitIgnore?: boolean;
|
||||||
checkpoint?: boolean;
|
checkpointing?: boolean;
|
||||||
proxy?: string;
|
proxy?: string;
|
||||||
cwd: string;
|
cwd: string;
|
||||||
fileDiscoveryService?: FileDiscoveryService;
|
fileDiscoveryService?: FileDiscoveryService;
|
||||||
|
@ -138,7 +139,7 @@ export class Config {
|
||||||
private readonly fileFilteringRespectGitIgnore: boolean;
|
private readonly fileFilteringRespectGitIgnore: boolean;
|
||||||
private fileDiscoveryService: FileDiscoveryService | null = null;
|
private fileDiscoveryService: FileDiscoveryService | null = null;
|
||||||
private gitService: GitService | undefined = undefined;
|
private gitService: GitService | undefined = undefined;
|
||||||
private readonly checkpoint: boolean;
|
private readonly checkpointing: boolean;
|
||||||
private readonly proxy: string | undefined;
|
private readonly proxy: string | undefined;
|
||||||
private readonly cwd: string;
|
private readonly cwd: string;
|
||||||
private readonly bugCommand: BugCommandSettings | undefined;
|
private readonly bugCommand: BugCommandSettings | undefined;
|
||||||
|
@ -173,7 +174,7 @@ export class Config {
|
||||||
|
|
||||||
this.fileFilteringRespectGitIgnore =
|
this.fileFilteringRespectGitIgnore =
|
||||||
params.fileFilteringRespectGitIgnore ?? true;
|
params.fileFilteringRespectGitIgnore ?? true;
|
||||||
this.checkpoint = params.checkpoint ?? false;
|
this.checkpointing = params.checkpointing ?? false;
|
||||||
this.proxy = params.proxy;
|
this.proxy = params.proxy;
|
||||||
this.cwd = params.cwd ?? process.cwd();
|
this.cwd = params.cwd ?? process.cwd();
|
||||||
this.fileDiscoveryService = params.fileDiscoveryService ?? null;
|
this.fileDiscoveryService = params.fileDiscoveryService ?? null;
|
||||||
|
@ -325,12 +326,16 @@ export class Config {
|
||||||
return path.join(this.targetDir, GEMINI_DIR);
|
return path.join(this.targetDir, GEMINI_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getProjectTempDir(): string {
|
||||||
|
return getProjectTempDir(this.getProjectRoot());
|
||||||
|
}
|
||||||
|
|
||||||
getFileFilteringRespectGitIgnore(): boolean {
|
getFileFilteringRespectGitIgnore(): boolean {
|
||||||
return this.fileFilteringRespectGitIgnore;
|
return this.fileFilteringRespectGitIgnore;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCheckpointEnabled(): boolean {
|
getCheckpointingEnabled(): boolean {
|
||||||
return this.checkpoint;
|
return this.checkpointing;
|
||||||
}
|
}
|
||||||
|
|
||||||
getProxy(): string | undefined {
|
getProxy(): string | undefined {
|
||||||
|
|
Loading…
Reference in New Issue