Merge branch 'main' into adibakm/plan-mode-untrusted-folder

This commit is contained in:
Adib234
2026-01-26 17:16:23 -05:00
committed by GitHub
20 changed files with 1193 additions and 1242 deletions
+53
View File
@@ -14,6 +14,7 @@ import { ApprovalMode } from '../policy/types.js';
import type { HookDefinition } from '../hooks/types.js';
import { HookType, HookEventName } from '../hooks/types.js';
import * as path from 'node:path';
import * as fs from 'node:fs';
import { setGeminiMdFilename as mockSetGeminiMdFilename } from '../tools/memoryTool.js';
import {
DEFAULT_TELEMETRY_TARGET,
@@ -2238,3 +2239,55 @@ describe('Config JIT Initialization', () => {
});
});
});
describe('Plans Directory Initialization', () => {
const baseParams: ConfigParameters = {
sessionId: 'test-session',
targetDir: '/tmp/test',
debugMode: false,
model: 'test-model',
cwd: '/tmp/test',
};
beforeEach(() => {
vi.spyOn(fs.promises, 'mkdir').mockResolvedValue(undefined);
});
afterEach(() => {
vi.mocked(fs.promises.mkdir).mockRestore();
});
it('should create plans directory and add it to workspace context when plan is enabled', async () => {
const config = new Config({
...baseParams,
plan: true,
});
await config.initialize();
const plansDir = config.storage.getProjectTempPlansDir();
expect(fs.promises.mkdir).toHaveBeenCalledWith(plansDir, {
recursive: true,
});
const context = config.getWorkspaceContext();
expect(context.getDirectories()).toContain(plansDir);
});
it('should NOT create plans directory or add it to workspace context when plan is disabled', async () => {
const config = new Config({
...baseParams,
plan: false,
});
await config.initialize();
const plansDir = config.storage.getProjectTempPlansDir();
expect(fs.promises.mkdir).not.toHaveBeenCalledWith(plansDir, {
recursive: true,
});
const context = config.getWorkspaceContext();
expect(context.getDirectories()).not.toContain(plansDir);
});
});
+9
View File
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import * as fs from 'node:fs';
import * as path from 'node:path';
import { inspect } from 'node:util';
import process from 'node:process';
@@ -696,6 +697,7 @@ export class Config {
this.extensionManagement = params.extensionManagement ?? true;
this.enableExtensionReloading = params.enableExtensionReloading ?? false;
this.storage = new Storage(this.targetDir);
this.fakeResponses = params.fakeResponses;
this.recordResponses = params.recordResponses;
this.enablePromptCompletion = params.enablePromptCompletion ?? false;
@@ -794,6 +796,13 @@ export class Config {
this.workspaceContext.addDirectory(dir);
}
// Add plans directory to workspace context for plan file storage
if (this.planEnabled) {
const plansDir = this.storage.getProjectTempPlansDir();
await fs.promises.mkdir(plansDir, { recursive: true });
this.workspaceContext.addDirectory(plansDir);
}
// Initialize centralized FileDiscoveryService
const discoverToolsHandle = startupProfiler.start('discover_tools');
this.getFileService();
+6
View File
@@ -78,4 +78,10 @@ describe('Storage additional helpers', () => {
const expected = path.join(os.homedir(), GEMINI_DIR, 'tmp', 'bin');
expect(Storage.getGlobalBinDir()).toBe(expected);
});
it('getProjectTempPlansDir returns ~/.gemini/tmp/<hash>/plans', () => {
const tempDir = storage.getProjectTempDir();
const expected = path.join(tempDir, 'plans');
expect(storage.getProjectTempPlansDir()).toBe(expected);
});
});
+4
View File
@@ -155,6 +155,10 @@ export class Storage {
return path.join(this.getProjectTempDir(), 'logs');
}
getProjectTempPlansDir(): string {
return path.join(this.getProjectTempDir(), 'plans');
}
getExtensionsDir(): string {
return path.join(this.getGeminiDir(), 'extensions');
}