mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-14 13:53:02 -07:00
feat: rename /directory to /workspace and unify terminology
Renames the /directory command to /workspace, adds aliases for backward compatibility, and updates UI strings, settings, and prompts to use 'workspace' terminology consistently. Linked to #20737. Per Core/UX chat on 2/18.
This commit is contained in:
@@ -1094,7 +1094,7 @@ describe('AppContainer State Management', () => {
|
||||
const mockResumedSessionData = {
|
||||
conversation: {
|
||||
sessionId: 'test-session-123',
|
||||
projectHash: 'test-project-hash',
|
||||
workspaceHash: 'test-workspace-hash',
|
||||
startTime: '2024-01-01T00:00:00Z',
|
||||
lastUpdated: '2024-01-01T00:00:01Z',
|
||||
messages: [
|
||||
@@ -1283,7 +1283,7 @@ describe('AppContainer State Management', () => {
|
||||
const resumedData = {
|
||||
conversation: {
|
||||
sessionId: 'resumed-session-456',
|
||||
projectHash: 'project-hash',
|
||||
workspaceHash: 'workspace-hash',
|
||||
startTime: '2024-01-01T00:00:00Z',
|
||||
lastUpdated: '2024-01-01T00:01:00Z',
|
||||
messages: [
|
||||
@@ -1339,7 +1339,7 @@ describe('AppContainer State Management', () => {
|
||||
const resumedData = {
|
||||
conversation: {
|
||||
sessionId: 'test-session',
|
||||
projectHash: 'project-hash',
|
||||
workspaceHash: 'workspace-hash',
|
||||
startTime: '2024-01-01T00:00:00Z',
|
||||
lastUpdated: '2024-01-01T00:01:00Z',
|
||||
messages: [],
|
||||
|
||||
@@ -222,7 +222,7 @@ export function AuthDialog({
|
||||
</Text>
|
||||
<Box marginTop={1}>
|
||||
<Text color={theme.text.primary}>
|
||||
How would you like to authenticate for this project?
|
||||
How would you like to authenticate for this workspace?
|
||||
</Text>
|
||||
</Box>
|
||||
<Box marginTop={1}>
|
||||
|
||||
@@ -5,7 +5,7 @@ exports[`AuthDialog > Snapshots > renders correctly with auth error 1`] = `
|
||||
│ │
|
||||
│ ? Get started │
|
||||
│ │
|
||||
│ How would you like to authenticate for this project? │
|
||||
│ How would you like to authenticate for this workspace? │
|
||||
│ │
|
||||
│ (selected) Login with Google(not selected) Use Gemini API Key(not selected) Vertex AI │
|
||||
│ │
|
||||
@@ -26,7 +26,7 @@ exports[`AuthDialog > Snapshots > renders correctly with default props 1`] = `
|
||||
│ │
|
||||
│ ? Get started │
|
||||
│ │
|
||||
│ How would you like to authenticate for this project? │
|
||||
│ How would you like to authenticate for this workspace? │
|
||||
│ │
|
||||
│ (selected) Login with Google(not selected) Use Gemini API Key(not selected) Vertex AI │
|
||||
│ │
|
||||
@@ -45,7 +45,7 @@ exports[`AuthDialog > Snapshots > renders correctly with enforced auth type 1`]
|
||||
│ │
|
||||
│ ? Get started │
|
||||
│ │
|
||||
│ How would you like to authenticate for this project? │
|
||||
│ How would you like to authenticate for this workspace? │
|
||||
│ │
|
||||
│ (selected) Use Gemini API Key │
|
||||
│ │
|
||||
|
||||
@@ -78,7 +78,7 @@ describe('initCommand', () => {
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
{
|
||||
type: 'info',
|
||||
text: 'Empty GEMINI.md created. Now analyzing the project to populate it.',
|
||||
text: 'Empty GEMINI.md created. Now analyzing the workspace to populate it.',
|
||||
},
|
||||
expect.any(Number),
|
||||
);
|
||||
|
||||
@@ -16,7 +16,7 @@ import { performInit } from '@google/gemini-cli-core';
|
||||
|
||||
export const initCommand: SlashCommand = {
|
||||
name: 'init',
|
||||
description: 'Analyzes the project and creates a tailored GEMINI.md file',
|
||||
description: 'Analyzes the workspace and creates a tailored GEMINI.md file',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
autoExecute: true,
|
||||
action: async (
|
||||
@@ -42,7 +42,7 @@ export const initCommand: SlashCommand = {
|
||||
context.ui.addItem(
|
||||
{
|
||||
type: 'info',
|
||||
text: 'Empty GEMINI.md created. Now analyzing the project to populate it.',
|
||||
text: 'Empty GEMINI.md created. Now analyzing the workspace to populate it.',
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
|
||||
+5
-5
@@ -6,7 +6,7 @@
|
||||
|
||||
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import type { Mock } from 'vitest';
|
||||
import { directoryCommand } from './directoryCommand.js';
|
||||
import { workspaceCommand } from './workspaceCommand.js';
|
||||
import {
|
||||
expandHomeDir,
|
||||
getDirectorySuggestions,
|
||||
@@ -38,14 +38,14 @@ vi.mock('../utils/directoryUtils.js', async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
describe('directoryCommand', () => {
|
||||
describe('workspaceCommand', () => {
|
||||
let mockContext: CommandContext;
|
||||
let mockConfig: Config;
|
||||
let mockWorkspaceContext: WorkspaceContext;
|
||||
const addCommand = directoryCommand.subCommands?.find(
|
||||
const addCommand = workspaceCommand.subCommands?.find(
|
||||
(c) => c.name === 'add',
|
||||
);
|
||||
const showCommand = directoryCommand.subCommands?.find(
|
||||
const showCommand = workspaceCommand.subCommands?.find(
|
||||
(c) => c.name === 'show',
|
||||
);
|
||||
|
||||
@@ -126,7 +126,7 @@ describe('directoryCommand', () => {
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content:
|
||||
'The /directory add command is not supported in restrictive sandbox profiles. Please use --include-directories when starting the session instead.',
|
||||
'The /workspace add command is not supported in restrictive sandbox profiles. Please use --include-directories when starting the session instead.',
|
||||
});
|
||||
});
|
||||
|
||||
+4
-4
@@ -77,9 +77,9 @@ async function finishAddingDirectories(
|
||||
}
|
||||
}
|
||||
|
||||
export const directoryCommand: SlashCommand = {
|
||||
name: 'directory',
|
||||
altNames: ['dir'],
|
||||
export const workspaceCommand: SlashCommand = {
|
||||
name: 'workspace',
|
||||
altNames: ['directory', 'dir'],
|
||||
description: 'Manage workspace directories',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
subCommands: [
|
||||
@@ -156,7 +156,7 @@ export const directoryCommand: SlashCommand = {
|
||||
type: 'message' as const,
|
||||
messageType: 'error' as const,
|
||||
content:
|
||||
'The /directory add command is not supported in restrictive sandbox profiles. Please use --include-directories when starting the session instead.',
|
||||
'The /workspace add command is not supported in restrictive sandbox profiles. Please use --include-directories when starting the session instead.',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -72,7 +72,8 @@ export const NewAgentsNotification = ({
|
||||
New Agents Discovered
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
The following agents were found in this project. Please review them:
|
||||
The following agents were found in this workspace. Please review
|
||||
them:
|
||||
</Text>
|
||||
<Box
|
||||
flexDirection="column"
|
||||
|
||||
@@ -55,7 +55,7 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
||||
|
||||
const createConversation = (messages: MessageRecord[]): ConversationRecord => ({
|
||||
sessionId: 'test-session',
|
||||
projectHash: 'hash',
|
||||
workspaceHash: 'hash',
|
||||
startTime: new Date().toISOString(),
|
||||
lastUpdated: new Date().toISOString(),
|
||||
messages,
|
||||
|
||||
@@ -4,7 +4,7 @@ exports[`NewAgentsNotification > renders agent list 1`] = `
|
||||
" ╭────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ │
|
||||
│ New Agents Discovered │
|
||||
│ The following agents were found in this project. Please review them: │
|
||||
│ The following agents were found in this workspace. Please review them: │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
@@ -24,7 +24,7 @@ exports[`NewAgentsNotification > truncates list if more than 5 agents 1`] = `
|
||||
" ╭────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ │
|
||||
│ New Agents Discovered │
|
||||
│ The following agents were found in this project. Please review them: │
|
||||
│ The following agents were found in this workspace. Please review them: │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
|
||||
@@ -172,12 +172,12 @@ export const TriageIssues = ({
|
||||
async (issue: Issue): Promise<AnalysisResult> => {
|
||||
const client = config.getBaseLlmClient();
|
||||
const prompt = `
|
||||
I am triaging GitHub issues for the Gemini CLI project. I need to identify issues that should be closed because they are:
|
||||
I am triaging GitHub issues for the Gemini CLI workspace. I need to identify issues that should be closed because they are:
|
||||
- Bogus (not a real issue/request)
|
||||
- Not reproducible (insufficient info, "it doesn't work" without logs/details)
|
||||
- Abusive or offensive
|
||||
- Gibberish (nonsense text)
|
||||
- Clearly out of scope for this project
|
||||
- Clearly out of scope for this workspace
|
||||
- Non-deterministic model output (e.g., "it gave me a wrong answer once", complaints about model quality without a reproducible test case)
|
||||
|
||||
<issue>
|
||||
|
||||
@@ -19,7 +19,7 @@ export const INFORMATIVE_TIPS = [
|
||||
'Hide the startup banner for a cleaner launch (/settings)…',
|
||||
'Hide the context summary above the input (/settings)…',
|
||||
'Reclaim vertical space by hiding the footer (/settings)…',
|
||||
'Hide individual footer elements like CWD or sandbox status (/settings)…',
|
||||
'Hide individual footer elements like Workspace Path or sandbox status (/settings)…',
|
||||
'Hide the context window percentage in the footer (/settings)…',
|
||||
'Show memory usage for performance monitoring (/settings)…',
|
||||
'Show line numbers in the chat for easier reference (/settings)…',
|
||||
@@ -33,7 +33,7 @@ export const INFORMATIVE_TIPS = [
|
||||
'Control when chat history gets compressed based on token usage (settings.json)…',
|
||||
'Define custom context file names, like CONTEXT.md (settings.json)…',
|
||||
'Set max directories to scan for context files (/settings)…',
|
||||
'Expand your workspace with additional directories (/directory)…',
|
||||
'Expand your workspace with additional directories (/workspace)…',
|
||||
'Control how /memory refresh loads context files (/settings)…',
|
||||
'Toggle respect for .gitignore files in context (/settings)…',
|
||||
'Toggle respect for .geminiignore files in context (/settings)…',
|
||||
@@ -131,15 +131,15 @@ export const INFORMATIVE_TIPS = [
|
||||
'Save tokens by summarizing the context with /compress…',
|
||||
'Copy the last response to your clipboard with /copy…',
|
||||
'Open the full documentation in your browser with /docs…',
|
||||
'Add directories to your workspace with /directory add <path>…',
|
||||
'Show all directories in your workspace with /directory show…',
|
||||
'Use /dir as a shortcut for /directory…',
|
||||
'Add directories to your workspace with /workspace add <path>…',
|
||||
'Show all directories in your workspace with /workspace show…',
|
||||
'Use /dir or /directory as a shortcut for /workspace…',
|
||||
'Set your preferred external editor with /editor…',
|
||||
'List all active extensions with /extensions list…',
|
||||
'Update all or specific extensions with /extensions update…',
|
||||
'Get help on commands with /help…',
|
||||
'Manage IDE integration with /ide…',
|
||||
'Create a project-specific GEMINI.md file with /init…',
|
||||
'Create a workspace-specific GEMINI.md file with /init…',
|
||||
'List configured MCP servers and tools with /mcp list…',
|
||||
'Authenticate with an OAuth-enabled MCP server with /mcp auth…',
|
||||
'Restart MCP servers with /mcp refresh…',
|
||||
@@ -149,7 +149,7 @@ export const INFORMATIVE_TIPS = [
|
||||
'List the paths of the GEMINI.md files in use with /memory list…',
|
||||
'Choose your Gemini model with /model…',
|
||||
'Display the privacy notice with /privacy…',
|
||||
'Restore project files to a previous state with /restore…',
|
||||
'Restore workspace files to a previous state with /restore…',
|
||||
'Exit the CLI with /quit or /exit…',
|
||||
'Check model-specific usage stats with /stats model…',
|
||||
'Check tool-specific usage stats with /stats tools…',
|
||||
|
||||
@@ -154,7 +154,7 @@ describe('useFolderTrust', () => {
|
||||
renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
|
||||
expect(addItem).toHaveBeenCalledWith(
|
||||
{
|
||||
text: 'This folder is untrusted, project settings, hooks, MCPs, and GEMINI.md files will not be applied for this folder.\nUse the `/permissions` command to change the trust level.',
|
||||
text: 'This folder is untrusted, workspace settings, hooks, MCPs, and GEMINI.md files will not be applied for this folder.\nUse the `/permissions` command to change the trust level.',
|
||||
type: 'info',
|
||||
},
|
||||
expect.any(Number),
|
||||
|
||||
@@ -59,7 +59,7 @@ export const useFolderTrust = (
|
||||
addItem(
|
||||
{
|
||||
type: MessageType.INFO,
|
||||
text: 'This folder is untrusted, project settings, hooks, MCPs, and GEMINI.md files will not be applied for this folder.\nUse the `/permissions` command to change the trust level.',
|
||||
text: 'This folder is untrusted, workspace settings, hooks, MCPs, and GEMINI.md files will not be applied for this folder.\nUse the `/permissions` command to change the trust level.',
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
|
||||
@@ -38,7 +38,7 @@ describe('useRewindLogic', () => {
|
||||
|
||||
const mockConversation: ConversationRecord = {
|
||||
sessionId: 'conv-1',
|
||||
projectHash: 'hash-1',
|
||||
workspaceHash: 'hash-1',
|
||||
startTime: new Date(1000).toISOString(),
|
||||
lastUpdated: new Date(1001).toISOString(),
|
||||
messages: [mockUserMessage, mockModelMessage],
|
||||
|
||||
@@ -78,7 +78,7 @@ describe('useSessionResume', () => {
|
||||
const resumedData: ResumedSessionData = {
|
||||
conversation: {
|
||||
sessionId: 'test-123',
|
||||
projectHash: 'project-123',
|
||||
workspaceHash: 'project-123',
|
||||
startTime: '2025-01-01T00:00:00Z',
|
||||
lastUpdated: '2025-01-01T01:00:00Z',
|
||||
messages: [] as MessageRecord[],
|
||||
@@ -133,7 +133,7 @@ describe('useSessionResume', () => {
|
||||
const resumedData: ResumedSessionData = {
|
||||
conversation: {
|
||||
sessionId: 'test-123',
|
||||
projectHash: 'project-123',
|
||||
workspaceHash: 'project-123',
|
||||
startTime: '2025-01-01T00:00:00Z',
|
||||
lastUpdated: '2025-01-01T01:00:00Z',
|
||||
messages: [] as MessageRecord[],
|
||||
@@ -160,7 +160,7 @@ describe('useSessionResume', () => {
|
||||
const resumedData: ResumedSessionData = {
|
||||
conversation: {
|
||||
sessionId: 'test-123',
|
||||
projectHash: 'project-123',
|
||||
workspaceHash: 'project-123',
|
||||
startTime: '2025-01-01T00:00:00Z',
|
||||
lastUpdated: '2025-01-01T01:00:00Z',
|
||||
messages: [] as MessageRecord[],
|
||||
@@ -200,7 +200,7 @@ describe('useSessionResume', () => {
|
||||
const resumedData: ResumedSessionData = {
|
||||
conversation: {
|
||||
sessionId: 'test-123',
|
||||
projectHash: 'project-123',
|
||||
workspaceHash: 'project-123',
|
||||
startTime: '2025-01-01T00:00:00Z',
|
||||
lastUpdated: '2025-01-01T01:00:00Z',
|
||||
messages: [] as MessageRecord[],
|
||||
@@ -240,7 +240,7 @@ describe('useSessionResume', () => {
|
||||
const resumedData: ResumedSessionData = {
|
||||
conversation: {
|
||||
sessionId: 'test-123',
|
||||
projectHash: 'project-123',
|
||||
workspaceHash: 'project-123',
|
||||
startTime: '2025-01-01T00:00:00Z',
|
||||
lastUpdated: '2025-01-01T01:00:00Z',
|
||||
messages: [] as MessageRecord[],
|
||||
@@ -306,7 +306,7 @@ describe('useSessionResume', () => {
|
||||
it('should not resume when user is authenticating', () => {
|
||||
const conversation: ConversationRecord = {
|
||||
sessionId: 'auto-resume-123',
|
||||
projectHash: 'project-123',
|
||||
workspaceHash: 'project-123',
|
||||
startTime: '2025-01-01T00:00:00Z',
|
||||
lastUpdated: '2025-01-01T01:00:00Z',
|
||||
messages: [
|
||||
@@ -338,7 +338,7 @@ describe('useSessionResume', () => {
|
||||
it('should not resume when Gemini client is not initialized', () => {
|
||||
const conversation: ConversationRecord = {
|
||||
sessionId: 'auto-resume-123',
|
||||
projectHash: 'project-123',
|
||||
workspaceHash: 'project-123',
|
||||
startTime: '2025-01-01T00:00:00Z',
|
||||
lastUpdated: '2025-01-01T01:00:00Z',
|
||||
messages: [
|
||||
@@ -370,7 +370,7 @@ describe('useSessionResume', () => {
|
||||
it('should automatically resume session when resumedSessionData is provided', async () => {
|
||||
const conversation: ConversationRecord = {
|
||||
sessionId: 'auto-resume-123',
|
||||
projectHash: 'project-123',
|
||||
workspaceHash: 'project-123',
|
||||
startTime: '2025-01-01T00:00:00Z',
|
||||
lastUpdated: '2025-01-01T01:00:00Z',
|
||||
messages: [
|
||||
@@ -425,7 +425,7 @@ describe('useSessionResume', () => {
|
||||
it('should only resume once even if props change', async () => {
|
||||
const conversation: ConversationRecord = {
|
||||
sessionId: 'auto-resume-123',
|
||||
projectHash: 'project-123',
|
||||
workspaceHash: 'project-123',
|
||||
startTime: '2025-01-01T00:00:00Z',
|
||||
lastUpdated: '2025-01-01T01:00:00Z',
|
||||
messages: [
|
||||
@@ -480,7 +480,7 @@ describe('useSessionResume', () => {
|
||||
it('should convert session messages correctly during auto-resume', async () => {
|
||||
const conversation: ConversationRecord = {
|
||||
sessionId: 'auto-resume-with-tools',
|
||||
projectHash: 'project-123',
|
||||
workspaceHash: 'project-123',
|
||||
startTime: '2025-01-01T00:00:00Z',
|
||||
lastUpdated: '2025-01-01T01:00:00Z',
|
||||
messages: [
|
||||
|
||||
@@ -245,22 +245,22 @@ const saveFileWithXclip = async (tempFilePath: string) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the directory where clipboard images should be stored for a specific project.
|
||||
* Gets the directory where clipboard images should be stored for a specific workspace.
|
||||
*
|
||||
* This uses the global temporary directory but creates a project-specific subdirectory
|
||||
* based on the hash of the project path (via `Storage.getProjectTempDir()`).
|
||||
* This prevents path conflicts between different projects while keeping the images
|
||||
* outside of the user's project directory.
|
||||
* This uses the global temporary directory but creates a workspace-specific subdirectory
|
||||
* based on the hash of the workspace path (via `Storage.getProjectTempDir()`).
|
||||
* This prevents path conflicts between different workspaces while keeping the images
|
||||
* outside of the user's workspace directory.
|
||||
*
|
||||
* @param targetDir The root directory of the current project.
|
||||
* @param targetDir The root directory of the current workspace.
|
||||
* @returns The absolute path to the images directory.
|
||||
*/
|
||||
async function getProjectClipboardImagesDir(
|
||||
async function getWorkspaceClipboardImagesDir(
|
||||
targetDir: string,
|
||||
): Promise<string> {
|
||||
const storage = new Storage(targetDir);
|
||||
await storage.initialize();
|
||||
const baseDir = storage.getProjectTempDir();
|
||||
const baseDir = storage.getWorkspaceTempDir();
|
||||
return path.join(baseDir, 'images');
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ export async function saveClipboardImage(
|
||||
targetDir: string,
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
const tempDir = await getProjectClipboardImagesDir(targetDir);
|
||||
const tempDir = await getWorkspaceClipboardImagesDir(targetDir);
|
||||
await fs.mkdir(tempDir, { recursive: true });
|
||||
|
||||
// Generate a unique filename with timestamp
|
||||
@@ -398,7 +398,7 @@ export async function cleanupOldClipboardImages(
|
||||
targetDir: string,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const tempDir = await getProjectClipboardImagesDir(targetDir);
|
||||
const tempDir = await getWorkspaceClipboardImagesDir(targetDir);
|
||||
const files = await fs.readdir(tempDir);
|
||||
const oneHourAgo = Date.now() - 60 * 60 * 1000;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user