Skip to content

Commit 0857345

Browse files
authored
refactor(editor): use const assertion for editor types with single source of truth (google-gemini#8604)
1 parent b9b3b80 commit 0857345

File tree

3 files changed

+58
-44
lines changed

3 files changed

+58
-44
lines changed

packages/a2a-server/src/agent/task.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
isNodeError,
1616
parseAndFormatApiError,
1717
safeLiteralReplace,
18+
DEFAULT_GUI_EDITOR,
1819
type AnyDeclarativeTool,
1920
type ToolCall,
2021
type ToolConfirmationPayload,
@@ -435,7 +436,7 @@ export class Task {
435436
outputUpdateHandler: this._schedulerOutputUpdate.bind(this),
436437
onAllToolCallsComplete: this._schedulerAllToolCallsComplete.bind(this),
437438
onToolCallsUpdate: this._schedulerToolCallsUpdate.bind(this),
438-
getPreferredEditor: () => 'vscode',
439+
getPreferredEditor: () => DEFAULT_GUI_EDITOR,
439440
config: this.config,
440441
});
441442
return scheduler;

packages/core/src/tools/modifiable-tool.test.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
modifyWithEditor,
1414
isModifiableDeclarativeTool,
1515
} from './modifiable-tool.js';
16-
import type { EditorType } from '../utils/editor.js';
16+
import { DEFAULT_GUI_EDITOR } from '../utils/editor.js';
1717
import fs from 'node:fs';
1818
import fsp from 'node:fs/promises';
1919
import os from 'node:os';
@@ -24,9 +24,13 @@ import { debugLogger } from '../utils/debugLogger.js';
2424
const mockOpenDiff = vi.hoisted(() => vi.fn());
2525
const mockCreatePatch = vi.hoisted(() => vi.fn());
2626

27-
vi.mock('../utils/editor.js', () => ({
28-
openDiff: mockOpenDiff,
29-
}));
27+
vi.mock('../utils/editor.js', async (importOriginal) => {
28+
const actual = await importOriginal<typeof import('../utils/editor.js')>();
29+
return {
30+
...actual,
31+
openDiff: mockOpenDiff,
32+
};
33+
});
3034

3135
vi.mock('diff', () => ({
3236
createPatch: mockCreatePatch,
@@ -103,7 +107,7 @@ describe('modifyWithEditor', () => {
103107
const result = await modifyWithEditor(
104108
mockParams,
105109
mockModifyContext,
106-
'vscode' as EditorType,
110+
DEFAULT_GUI_EDITOR,
107111
abortSignal,
108112
);
109113

@@ -169,9 +173,14 @@ describe('modifyWithEditor', () => {
169173
await modifyWithEditor(
170174
mockParams,
171175
mockModifyContext,
172-
'vscode' as EditorType,
176+
DEFAULT_GUI_EDITOR,
173177
abortSignal,
174178
);
179+
180+
const [oldFilePath] = mockOpenDiff.mock.calls[0];
181+
const diffDir = path.dirname(oldFilePath);
182+
// Temp directory should be cleaned up after modification
183+
await expect(fsp.stat(diffDir)).rejects.toThrow();
175184
});
176185
});
177186

@@ -184,7 +193,7 @@ describe('modifyWithEditor', () => {
184193
const result = await modifyWithEditor(
185194
mockParams,
186195
mockModifyContext,
187-
'vscode' as EditorType,
196+
DEFAULT_GUI_EDITOR,
188197
abortSignal,
189198
);
190199

@@ -212,7 +221,7 @@ describe('modifyWithEditor', () => {
212221
const result = await modifyWithEditor(
213222
mockParams,
214223
mockModifyContext,
215-
'vscode' as EditorType,
224+
DEFAULT_GUI_EDITOR,
216225
abortSignal,
217226
);
218227

@@ -241,7 +250,7 @@ describe('modifyWithEditor', () => {
241250
await modifyWithEditor(
242251
mockParams,
243252
mockModifyContext,
244-
'vscode' as EditorType,
253+
DEFAULT_GUI_EDITOR,
245254
abortSignal,
246255
{
247256
currentContent: overrideCurrent,
@@ -268,7 +277,7 @@ describe('modifyWithEditor', () => {
268277
await modifyWithEditor(
269278
mockParams,
270279
mockModifyContext,
271-
'vscode' as EditorType,
280+
DEFAULT_GUI_EDITOR,
272281
abortSignal,
273282
{
274283
currentContent: null,
@@ -298,7 +307,7 @@ describe('modifyWithEditor', () => {
298307
modifyWithEditor(
299308
mockParams,
300309
mockModifyContext,
301-
'vscode' as EditorType,
310+
DEFAULT_GUI_EDITOR,
302311
abortSignal,
303312
),
304313
).rejects.toThrow('Editor failed to open');
@@ -327,7 +336,7 @@ describe('modifyWithEditor', () => {
327336
await modifyWithEditor(
328337
mockParams,
329338
mockModifyContext,
330-
'vscode' as EditorType,
339+
DEFAULT_GUI_EDITOR,
331340
abortSignal,
332341
);
333342

@@ -353,7 +362,7 @@ describe('modifyWithEditor', () => {
353362
await modifyWithEditor(
354363
mockParams,
355364
mockModifyContext,
356-
'vscode' as EditorType,
365+
DEFAULT_GUI_EDITOR,
357366
abortSignal,
358367
);
359368

@@ -374,7 +383,7 @@ describe('modifyWithEditor', () => {
374383
await modifyWithEditor(
375384
mockParams,
376385
mockModifyContext,
377-
'vscode' as EditorType,
386+
DEFAULT_GUI_EDITOR,
378387
abortSignal,
379388
);
380389

packages/core/src/utils/editor.ts

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,36 @@ import { execSync, spawn, spawnSync } from 'node:child_process';
88
import { debugLogger } from './debugLogger.js';
99
import { coreEvents, CoreEvent } from './events.js';
1010

11-
export type EditorType =
12-
| 'vscode'
13-
| 'vscodium'
14-
| 'windsurf'
15-
| 'cursor'
16-
| 'vim'
17-
| 'neovim'
18-
| 'zed'
19-
| 'emacs'
20-
| 'antigravity';
11+
const GUI_EDITORS = [
12+
'vscode',
13+
'vscodium',
14+
'windsurf',
15+
'cursor',
16+
'zed',
17+
'antigravity',
18+
] as const;
19+
const TERMINAL_EDITORS = ['vim', 'neovim', 'emacs'] as const;
20+
const EDITORS = [...GUI_EDITORS, ...TERMINAL_EDITORS] as const;
21+
22+
const GUI_EDITORS_SET = new Set<string>(GUI_EDITORS);
23+
const TERMINAL_EDITORS_SET = new Set<string>(TERMINAL_EDITORS);
24+
const EDITORS_SET = new Set<string>(EDITORS);
25+
26+
export const DEFAULT_GUI_EDITOR: GuiEditorType = 'vscode';
27+
28+
export type GuiEditorType = (typeof GUI_EDITORS)[number];
29+
export type TerminalEditorType = (typeof TERMINAL_EDITORS)[number];
30+
export type EditorType = (typeof EDITORS)[number];
31+
32+
export function isGuiEditor(editor: EditorType): editor is GuiEditorType {
33+
return GUI_EDITORS_SET.has(editor);
34+
}
35+
36+
export function isTerminalEditor(
37+
editor: EditorType,
38+
): editor is TerminalEditorType {
39+
return TERMINAL_EDITORS_SET.has(editor);
40+
}
2141

2242
export const EDITOR_DISPLAY_NAMES: Record<EditorType, string> = {
2343
vscode: 'VS Code',
@@ -36,17 +56,7 @@ export function getEditorDisplayName(editor: EditorType): string {
3656
}
3757

3858
function isValidEditorType(editor: string): editor is EditorType {
39-
return [
40-
'vscode',
41-
'vscodium',
42-
'windsurf',
43-
'cursor',
44-
'vim',
45-
'neovim',
46-
'zed',
47-
'emacs',
48-
'antigravity',
49-
].includes(editor);
59+
return EDITORS_SET.has(editor);
5060
}
5161

5262
interface DiffCommand {
@@ -94,11 +104,7 @@ export function checkHasEditorType(editor: EditorType): boolean {
94104

95105
export function allowEditorTypeInSandbox(editor: EditorType): boolean {
96106
const notUsingSandbox = !process.env['SANDBOX'];
97-
if (
98-
['vscode', 'vscodium', 'windsurf', 'cursor', 'zed', 'antigravity'].includes(
99-
editor,
100-
)
101-
) {
107+
if (isGuiEditor(editor)) {
102108
return notUsingSandbox;
103109
}
104110
// For terminal-based editors like vim and emacs, allow in sandbox.
@@ -197,9 +203,7 @@ export async function openDiff(
197203
return;
198204
}
199205

200-
const isTerminalEditor = ['vim', 'emacs', 'neovim'].includes(editor);
201-
202-
if (isTerminalEditor) {
206+
if (isTerminalEditor(editor)) {
203207
try {
204208
const result = spawnSync(diffCommand.command, diffCommand.args, {
205209
stdio: 'inherit',

0 commit comments

Comments
 (0)