[ide-mode] Send the cursor and selected text from the IDE server (#4621)
This commit is contained in:
parent
f9930c2d36
commit
4e376c0447
|
@ -15,7 +15,6 @@ let log: (message: string) => void = () => {};
|
||||||
export async function activate(context: vscode.ExtensionContext) {
|
export async function activate(context: vscode.ExtensionContext) {
|
||||||
logger = vscode.window.createOutputChannel('Gemini CLI IDE Companion');
|
logger = vscode.window.createOutputChannel('Gemini CLI IDE Companion');
|
||||||
log = createLogger(context, logger);
|
log = createLogger(context, logger);
|
||||||
|
|
||||||
log('Extension activated');
|
log('Extension activated');
|
||||||
ideServer = new IDEServer(log);
|
ideServer = new IDEServer(log);
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { RecentFilesManager } from './recent-files-manager.js';
|
||||||
|
|
||||||
const MCP_SESSION_ID_HEADER = 'mcp-session-id';
|
const MCP_SESSION_ID_HEADER = 'mcp-session-id';
|
||||||
const IDE_SERVER_PORT_ENV_VAR = 'GEMINI_CLI_IDE_SERVER_PORT';
|
const IDE_SERVER_PORT_ENV_VAR = 'GEMINI_CLI_IDE_SERVER_PORT';
|
||||||
|
const MAX_SELECTED_TEXT_LENGTH = 16384; // 16 KiB limit
|
||||||
|
|
||||||
function sendOpenFilesChangedNotification(
|
function sendOpenFilesChangedNotification(
|
||||||
transport: StreamableHTTPServerTransport,
|
transport: StreamableHTTPServerTransport,
|
||||||
|
@ -29,6 +30,19 @@ function sendOpenFilesChangedNotification(
|
||||||
editor && editor.document.uri.scheme === 'file'
|
editor && editor.document.uri.scheme === 'file'
|
||||||
? editor.document.uri.fsPath
|
? editor.document.uri.fsPath
|
||||||
: '';
|
: '';
|
||||||
|
const selection = editor?.selection;
|
||||||
|
const cursor = selection
|
||||||
|
? {
|
||||||
|
// This value is a zero-based index, but the vscode IDE is one-based.
|
||||||
|
line: selection.active.line + 1,
|
||||||
|
character: selection.active.character,
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
let selectedText = editor?.document.getText(selection) ?? undefined;
|
||||||
|
if (selectedText && selectedText.length > MAX_SELECTED_TEXT_LENGTH) {
|
||||||
|
selectedText =
|
||||||
|
selectedText.substring(0, MAX_SELECTED_TEXT_LENGTH) + '... [TRUNCATED]';
|
||||||
|
}
|
||||||
const notification: JSONRPCNotification = {
|
const notification: JSONRPCNotification = {
|
||||||
jsonrpc: '2.0',
|
jsonrpc: '2.0',
|
||||||
method: 'ide/openFilesChanged',
|
method: 'ide/openFilesChanged',
|
||||||
|
@ -37,6 +51,8 @@ function sendOpenFilesChangedNotification(
|
||||||
recentOpenFiles: recentFilesManager.recentFiles.filter(
|
recentOpenFiles: recentFilesManager.recentFiles.filter(
|
||||||
(file) => file.filePath !== filePath,
|
(file) => file.filePath !== filePath,
|
||||||
),
|
),
|
||||||
|
cursor,
|
||||||
|
selectedText,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
log(
|
log(
|
||||||
|
@ -69,7 +85,7 @@ export class IDEServer {
|
||||||
const mcpServer = createMcpServer();
|
const mcpServer = createMcpServer();
|
||||||
|
|
||||||
const recentFilesManager = new RecentFilesManager(context);
|
const recentFilesManager = new RecentFilesManager(context);
|
||||||
const disposable = recentFilesManager.onDidChange(() => {
|
const onDidChangeSubscription = recentFilesManager.onDidChange(() => {
|
||||||
for (const transport of Object.values(transports)) {
|
for (const transport of Object.values(transports)) {
|
||||||
sendOpenFilesChangedNotification(
|
sendOpenFilesChangedNotification(
|
||||||
transport,
|
transport,
|
||||||
|
@ -78,7 +94,7 @@ export class IDEServer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
context.subscriptions.push(disposable);
|
context.subscriptions.push(onDidChangeSubscription);
|
||||||
|
|
||||||
app.post('/mcp', async (req: Request, res: Response) => {
|
app.post('/mcp', async (req: Request, res: Response) => {
|
||||||
const sessionId = req.headers[MCP_SESSION_ID_HEADER] as
|
const sessionId = req.headers[MCP_SESSION_ID_HEADER] as
|
||||||
|
|
|
@ -28,6 +28,7 @@ vi.mock('vscode', () => ({
|
||||||
}),
|
}),
|
||||||
window: {
|
window: {
|
||||||
onDidChangeActiveTextEditor: vi.fn(),
|
onDidChangeActiveTextEditor: vi.fn(),
|
||||||
|
onDidChangeTextEditorSelection: vi.fn(),
|
||||||
},
|
},
|
||||||
workspace: {
|
workspace: {
|
||||||
onDidDeleteFiles: vi.fn(),
|
onDidDeleteFiles: vi.fn(),
|
||||||
|
|
|
@ -47,11 +47,19 @@ export class RecentFilesManager {
|
||||||
this.add(newUri);
|
this.add(newUri);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const selectionWatcher = vscode.window.onDidChangeTextEditorSelection(
|
||||||
|
() => {
|
||||||
|
this.fireWithDebounce();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
editorWatcher,
|
editorWatcher,
|
||||||
deleteWatcher,
|
deleteWatcher,
|
||||||
closeWatcher,
|
closeWatcher,
|
||||||
renameWatcher,
|
renameWatcher,
|
||||||
|
selectionWatcher,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue