Compare commits

...

4 Commits

17 changed files with 110 additions and 30 deletions
+7 -7
View File
@@ -1,12 +1,12 @@
{
"name": "@google/gemini-cli",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@google/gemini-cli",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"workspaces": [
"packages/*"
],
@@ -16960,7 +16960,7 @@
},
"packages/a2a-server": {
"name": "@google/gemini-cli-a2a-server",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"dependencies": {
"@a2a-js/sdk": "^0.3.2",
"@google-cloud/storage": "^7.16.0",
@@ -17250,7 +17250,7 @@
},
"packages/cli": {
"name": "@google/gemini-cli",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"dependencies": {
"@google/gemini-cli-core": "file:../core",
"@google/genai": "1.16.0",
@@ -17350,7 +17350,7 @@
},
"packages/core": {
"name": "@google/gemini-cli-core",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"dependencies": {
"@google-cloud/logging": "^11.2.1",
"@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.21.0",
@@ -17494,7 +17494,7 @@
},
"packages/test-utils": {
"name": "@google/gemini-cli-test-utils",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"license": "Apache-2.0",
"devDependencies": {
"typescript": "^5.3.3"
@@ -17505,7 +17505,7 @@
},
"packages/vscode-ide-companion": {
"name": "gemini-cli-vscode-ide-companion",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"license": "LICENSE",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.15.1",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"engines": {
"node": ">=20.0.0"
},
@@ -14,7 +14,7 @@
"url": "git+https://github.com/google-gemini/gemini-cli.git"
},
"config": {
"sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.16.0-preview.2"
"sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.16.0-preview.4"
},
"scripts": {
"start": "cross-env NODE_ENV=development node scripts/start.js",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli-a2a-server",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"description": "Gemini CLI A2A Server",
"repository": {
"type": "git",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"description": "Gemini CLI",
"repository": {
"type": "git",
@@ -25,7 +25,7 @@
"dist"
],
"config": {
"sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.16.0-preview.2"
"sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.16.0-preview.4"
},
"dependencies": {
"@google/gemini-cli-core": "file:../core",
+16 -6
View File
@@ -892,7 +892,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
>();
const [showEscapePrompt, setShowEscapePrompt] = useState(false);
const [showIdeRestartPrompt, setShowIdeRestartPrompt] = useState(false);
const [selectionWarning, setSelectionWarning] = useState(false);
const [warningMessage, setWarningMessage] = useState<string | null>(null);
const { isFolderTrustDialogOpen, handleFolderTrustSelect, isRestarting } =
useFolderTrust(settings, setIsTrustedFolder, historyManager.addItem);
@@ -904,18 +904,28 @@ Logging in with Google... Please restart Gemini CLI to continue.
useEffect(() => {
let timeoutId: NodeJS.Timeout;
const handleSelectionWarning = () => {
setSelectionWarning(true);
const handleWarning = (message: string) => {
setWarningMessage(message);
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
setSelectionWarning(false);
setWarningMessage(null);
}, WARNING_PROMPT_DURATION_MS);
};
const handleSelectionWarning = () => {
handleWarning('Press Ctrl-S to enter selection mode to copy text.');
};
const handlePasteTimeout = () => {
handleWarning('Paste Timed out. Possibly due to slow connection.');
};
appEvents.on(AppEvent.SelectionWarning, handleSelectionWarning);
appEvents.on(AppEvent.PasteTimeout, handlePasteTimeout);
return () => {
appEvents.off(AppEvent.SelectionWarning, handleSelectionWarning);
appEvents.off(AppEvent.PasteTimeout, handlePasteTimeout);
if (timeoutId) {
clearTimeout(timeoutId);
}
@@ -1366,7 +1376,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
embeddedShellFocused,
showDebugProfiler,
copyModeEnabled,
selectionWarning,
warningMessage,
}),
[
isThemeDialogOpen,
@@ -1452,7 +1462,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
apiKeyDefaultValue,
authState,
copyModeEnabled,
selectionWarning,
warningMessage,
],
);
+2 -4
View File
@@ -99,10 +99,8 @@ export const Composer = () => {
<Text color={theme.status.warning}>
Press Ctrl+C again to exit.
</Text>
) : uiState.selectionWarning ? (
<Text color={theme.status.warning}>
Press Ctrl-S to enter selection mode to copy text.
</Text>
) : uiState.warningMessage ? (
<Text color={theme.status.warning}>{uiState.warningMessage}</Text>
) : uiState.ctrlDPressedOnce ? (
<Text color={theme.status.warning}>
Press Ctrl+D again to exit.
@@ -18,10 +18,11 @@ import {
import { ESC } from '../utils/input.js';
import { parseMouseEvent } from '../utils/mouse.js';
import { FOCUS_IN, FOCUS_OUT } from '../hooks/useFocus.js';
import { appEvents, AppEvent } from '../../utils/events.js';
export const BACKSLASH_ENTER_TIMEOUT = 5;
export const ESC_TIMEOUT = 50;
export const PASTE_TIMEOUT = 50;
export const PASTE_TIMEOUT = 30_000;
// Parse the key itself
const KEY_INFO_MAP: Record<
@@ -211,7 +212,12 @@ function bufferPaste(
key = yield;
clearTimeout(timeoutId);
if (key === null || key.name === 'paste-end') {
if (key === null) {
appEvents.emit(AppEvent.PasteTimeout);
break;
}
if (key.name === 'paste-end') {
break;
}
buffer += key.sequence;
@@ -100,7 +100,8 @@ export function MouseProvider({
!handled &&
event.name === 'move' &&
event.col >= 0 &&
event.row >= 0
event.row >= 0 &&
event.button === 'left'
) {
// Terminal apps only receive mouse move events when the mouse is down
// so this always indicates a mouse drag that the user was expecting
@@ -113,6 +113,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -125,6 +126,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -142,6 +144,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -159,6 +162,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -172,6 +176,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'none',
});
}
expect(scrollBy).not.toHaveBeenCalled();
@@ -209,6 +214,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -231,6 +237,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -268,6 +275,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -305,6 +313,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -342,6 +351,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -407,6 +417,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -424,6 +435,7 @@ describe('ScrollProvider Drag', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
// Expect scrollTo to be called with target and duration 0
@@ -110,6 +110,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'none',
}) === true
) {
handled = true;
@@ -147,6 +148,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'none',
}) === true
) {
handled = true;
@@ -193,6 +195,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -226,6 +229,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -258,6 +262,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'none',
};
for (const callback of mockUseMouseCallbacks) {
callback(mouseEvent);
@@ -303,6 +308,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'none',
});
callback({
name: 'scroll-down',
@@ -311,6 +317,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'none',
});
callback({
name: 'scroll-up',
@@ -319,6 +326,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'none',
});
}
@@ -358,6 +366,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'none',
});
callback({
name: 'scroll-down',
@@ -366,6 +375,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'none',
});
callback({
name: 'scroll-down',
@@ -374,6 +384,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'none',
});
}
@@ -417,6 +428,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -429,6 +441,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -441,6 +454,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -475,6 +489,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -487,6 +502,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -498,6 +514,7 @@ describe('ScrollProvider', () => {
shift: false,
ctrl: false,
meta: false,
button: 'left',
});
}
@@ -124,7 +124,7 @@ export interface UIState {
showDebugProfiler: boolean;
showFullTodos: boolean;
copyModeEnabled: boolean;
selectionWarning: boolean;
warningMessage: string | null;
}
export const UIStateContext = createContext<UIState | null>(null);
+5
View File
@@ -27,6 +27,7 @@ describe('mouse utils', () => {
shift: false,
meta: false,
ctrl: false,
button: 'left',
});
expect(result!.length).toBe(input.length);
});
@@ -43,6 +44,7 @@ describe('mouse utils', () => {
shift: false,
meta: false,
ctrl: false,
button: 'left',
});
});
@@ -58,6 +60,7 @@ describe('mouse utils', () => {
shift: true,
meta: true,
ctrl: true,
button: 'left',
});
});
@@ -67,6 +70,7 @@ describe('mouse utils', () => {
const result = parseSGRMouseEvent(input);
expect(result).not.toBeNull();
expect(result!.event.name).toBe('move');
expect(result!.event.button).toBe('left');
});
it('parses SGR scroll events', () => {
@@ -100,6 +104,7 @@ describe('mouse utils', () => {
shift: false,
meta: false,
ctrl: false,
button: 'left',
});
expect(result!.length).toBe(6);
});
+30 -1
View File
@@ -33,6 +33,7 @@ export interface MouseEvent {
shift: boolean;
meta: boolean;
ctrl: boolean;
button: 'left' | 'middle' | 'right' | 'none';
}
export type MouseHandler = (event: MouseEvent) => void | boolean;
@@ -71,6 +72,20 @@ export function getMouseEventName(
}
}
function getButtonFromCode(code: number): MouseEvent['button'] {
const button = code & 3;
switch (button) {
case 0:
return 'left';
case 1:
return 'middle';
case 2:
return 'right';
default:
return 'none';
}
}
export function parseSGRMouseEvent(
buffer: string,
): { event: MouseEvent; length: number } | null {
@@ -98,6 +113,7 @@ export function parseSGRMouseEvent(
shift,
col,
row,
button: getButtonFromCode(buttonCode),
},
length: match[0].length,
};
@@ -165,8 +181,21 @@ export function parseX11MouseEvent(
}
if (name) {
let button = getButtonFromCode(b);
if (name === 'left-release' && button === 'none') {
button = 'left';
}
return {
event: { name, ctrl, meta, shift, col, row },
event: {
name,
ctrl,
meta,
shift,
col,
row,
button,
},
length: match[0].length,
};
}
+2
View File
@@ -14,6 +14,7 @@ export enum AppEvent {
Flicker = 'flicker',
McpClientUpdate = 'mcp-client-update',
SelectionWarning = 'selection-warning',
PasteTimeout = 'paste-timeout',
}
export interface AppEvents extends ExtensionEvents {
@@ -23,6 +24,7 @@ export interface AppEvents extends ExtensionEvents {
[AppEvent.Flicker]: never[];
[AppEvent.McpClientUpdate]: Array<Map<string, McpClient> | never>;
[AppEvent.SelectionWarning]: never[];
[AppEvent.PasteTimeout]: never[];
}
export const appEvents = new EventEmitter<AppEvents>();
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli-core",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"description": "Gemini CLI Core",
"repository": {
"type": "git",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli-test-utils",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"private": true,
"main": "src/index.ts",
"license": "Apache-2.0",
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "gemini-cli-vscode-ide-companion",
"displayName": "Gemini CLI Companion",
"description": "Enable Gemini CLI with direct access to your IDE workspace.",
"version": "0.16.0-preview.2",
"version": "0.16.0-preview.4",
"publisher": "google",
"icon": "assets/icon.png",
"repository": {