mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-19 10:31:16 -07:00
Disallow unsafe type assertions (#18688)
This commit is contained in:
committed by
GitHub
parent
bce1caefd0
commit
fd65416a2f
@@ -249,6 +249,7 @@ export const AppContainer = (props: AppContainerProps) => {
|
||||
|
||||
const { bannerText } = useBanner(bannerData);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const extensionManager = config.getExtensionLoader() as ExtensionManager;
|
||||
// We are in the interactive CLI, update how we request consent and settings.
|
||||
extensionManager.setRequestConsent((description) =>
|
||||
@@ -468,6 +469,7 @@ export const AppContainer = (props: AppContainerProps) => {
|
||||
const staticAreaMaxItemHeight = Math.max(terminalHeight * 4, 100);
|
||||
|
||||
const getPreferredEditor = useCallback(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
() => settings.merged.general.preferredEditor as EditorType,
|
||||
[settings.merged.general.preferredEditor],
|
||||
);
|
||||
|
||||
@@ -88,8 +88,10 @@ export function AuthDialog({
|
||||
const defaultAuthTypeEnv = process.env['GEMINI_DEFAULT_AUTH_TYPE'];
|
||||
if (
|
||||
defaultAuthTypeEnv &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
Object.values(AuthType).includes(defaultAuthTypeEnv as AuthType)
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
defaultAuthType = defaultAuthTypeEnv as AuthType;
|
||||
}
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ export const useAuthCommand = (
|
||||
const defaultAuthType = process.env['GEMINI_DEFAULT_AUTH_TYPE'];
|
||||
if (
|
||||
defaultAuthType &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
!Object.values(AuthType).includes(defaultAuthType as AuthType)
|
||||
) {
|
||||
onAuthError(
|
||||
|
||||
@@ -213,6 +213,7 @@ const resumeCommand: SlashCommand = {
|
||||
continue;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
uiHistory.push({
|
||||
type: (item.role && rolemap[item.role]) || MessageType.GEMINI,
|
||||
text,
|
||||
|
||||
@@ -49,6 +49,7 @@ async function finishAddingDirectories(
|
||||
text: `Successfully added GEMINI.md files from the following directories if there are:\n- ${added.join('\n- ')}`,
|
||||
});
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
errors.push(`Error refreshing memory: ${(error as Error).message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ export const initCommand: SlashCommand = {
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return result as SlashCommandActionReturn;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -93,6 +93,7 @@ export const memoryCommand: SlashCommand = {
|
||||
context.ui.addItem(
|
||||
{
|
||||
type: MessageType.ERROR,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
text: `Error refreshing memory: ${(error as Error).message}`,
|
||||
},
|
||||
Date.now(),
|
||||
|
||||
@@ -123,6 +123,7 @@ function getNestedValue(
|
||||
for (const key of path) {
|
||||
if (current === null || current === undefined) return undefined;
|
||||
if (typeof current !== 'object') return undefined;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
current = (current as Record<string, unknown>)[key];
|
||||
}
|
||||
return current;
|
||||
@@ -144,8 +145,10 @@ function setNestedValue(
|
||||
if (current[key] === undefined || current[key] === null) {
|
||||
current[key] = {};
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
current[key] = { ...(current[key] as Record<string, unknown>) };
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
current = current[key] as Record<string, unknown>;
|
||||
}
|
||||
|
||||
@@ -265,6 +268,7 @@ export function AgentConfigDialog({
|
||||
() =>
|
||||
AGENT_CONFIG_FIELDS.map((field) => {
|
||||
const currentValue = getNestedValue(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
pendingOverride as Record<string, unknown>,
|
||||
field.path,
|
||||
);
|
||||
@@ -300,6 +304,7 @@ export function AgentConfigDialog({
|
||||
displayValue,
|
||||
isGreyedOut: currentValue === undefined,
|
||||
scopeMessage: undefined,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
rawValue: rawValue as string | number | boolean | undefined,
|
||||
};
|
||||
}),
|
||||
@@ -320,6 +325,7 @@ export function AgentConfigDialog({
|
||||
if (!field || field.type !== 'boolean') return;
|
||||
|
||||
const currentValue = getNestedValue(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
pendingOverride as Record<string, unknown>,
|
||||
field.path,
|
||||
);
|
||||
@@ -329,6 +335,7 @@ export function AgentConfigDialog({
|
||||
const newValue = !effectiveValue;
|
||||
|
||||
const newOverride = setNestedValue(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
pendingOverride as Record<string, unknown>,
|
||||
field.path,
|
||||
newValue,
|
||||
@@ -369,6 +376,7 @@ export function AgentConfigDialog({
|
||||
|
||||
// Update pending override locally
|
||||
const newOverride = setNestedValue(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
pendingOverride as Record<string, unknown>,
|
||||
field.path,
|
||||
parsed,
|
||||
@@ -391,6 +399,7 @@ export function AgentConfigDialog({
|
||||
|
||||
// Remove the override (set to undefined)
|
||||
const newOverride = setNestedValue(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
pendingOverride as Record<string, unknown>,
|
||||
field.path,
|
||||
undefined,
|
||||
|
||||
@@ -132,6 +132,7 @@ export function EditorSettingsDialog({
|
||||
) {
|
||||
mergedEditorName =
|
||||
EDITOR_DISPLAY_NAMES[
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
settings.merged.general.preferredEditor as EditorType
|
||||
];
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ export const MultiFolderTrustDialog: React.FC<MultiFolderTrustDialogProps> = ({
|
||||
workspaceContext.addDirectory(expandedPath);
|
||||
added.push(dir);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const error = e as Error;
|
||||
errors.push(`Error adding '${dir}': ${error.message}`);
|
||||
}
|
||||
|
||||
@@ -259,10 +259,12 @@ export function SettingsDialog({
|
||||
key,
|
||||
label: definition?.label || key,
|
||||
description: definition?.description,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
type: type as 'boolean' | 'number' | 'string' | 'enum',
|
||||
displayValue,
|
||||
isGreyedOut,
|
||||
scopeMessage,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
rawValue: rawValue as string | number | boolean | undefined,
|
||||
};
|
||||
});
|
||||
@@ -283,8 +285,10 @@ export function SettingsDialog({
|
||||
const currentValue = getEffectiveValue(key, pendingSettings, {});
|
||||
let newValue: SettingsValue;
|
||||
if (definition?.type === 'boolean') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
newValue = !(currentValue as boolean);
|
||||
setPendingSettings((prev) =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
setPendingSettingValue(key, newValue as boolean, prev),
|
||||
);
|
||||
} else if (definition?.type === 'enum' && definition.options) {
|
||||
@@ -377,6 +381,7 @@ export function SettingsDialog({
|
||||
// Record pending change globally
|
||||
setGlobalPendingChanges((prev) => {
|
||||
const next = new Map(prev);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
next.set(key, newValue as PendingValue);
|
||||
return next;
|
||||
});
|
||||
|
||||
@@ -75,6 +75,7 @@ export function Table<T>({ data, columns }: TableProps<T>) {
|
||||
col.renderCell(item)
|
||||
) : (
|
||||
<Text color={theme.text.primary}>
|
||||
{/* eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion */}
|
||||
{String((item as Record<string, unknown>)[col.key])}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
@@ -121,6 +121,7 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
|
||||
// where Container grows -> List renders more -> Container grows.
|
||||
const limit = maxLines ?? availableHeight ?? ACTIVE_SHELL_MAX_LINES;
|
||||
const listHeight = Math.min(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
(truncatedResultDisplay as AnsiOutput).length,
|
||||
limit,
|
||||
);
|
||||
@@ -129,6 +130,7 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
|
||||
<Box width={childWidth} flexDirection="column" maxHeight={listHeight}>
|
||||
<ScrollableList
|
||||
width={childWidth}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
data={truncatedResultDisplay as AnsiOutput}
|
||||
renderItem={renderVirtualizedAnsiLine}
|
||||
estimatedItemHeight={() => 1}
|
||||
@@ -184,7 +186,9 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
|
||||
) {
|
||||
content = (
|
||||
<DiffRenderer
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
diffContent={(truncatedResultDisplay as FileDiffResult).fileDiff}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
filename={(truncatedResultDisplay as FileDiffResult).fileName}
|
||||
availableTerminalHeight={availableHeight}
|
||||
terminalWidth={childWidth}
|
||||
@@ -197,6 +201,7 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
|
||||
|
||||
content = (
|
||||
<AnsiOutputText
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
data={truncatedResultDisplay as AnsiOutput}
|
||||
availableTerminalHeight={
|
||||
isAlternateBuffer ? undefined : availableHeight
|
||||
|
||||
@@ -153,6 +153,7 @@ export const Scrollable: React.FC<ScrollableProps> = ({
|
||||
|
||||
const scrollableEntry = useMemo(
|
||||
() => ({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
ref: ref as React.RefObject<DOMElement>,
|
||||
getScrollState,
|
||||
scrollBy: scrollByWithAnimation,
|
||||
|
||||
@@ -219,6 +219,7 @@ function ScrollableList<T>(
|
||||
|
||||
const scrollableEntry = useMemo(
|
||||
() => ({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
ref: containerRef as React.RefObject<DOMElement>,
|
||||
getScrollState,
|
||||
scrollBy: scrollByWithAnimation,
|
||||
@@ -254,6 +255,7 @@ function ScrollableList<T>(
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const ScrollableListWithForwardRef = forwardRef(ScrollableList) as <T>(
|
||||
props: ScrollableListProps<T> & { ref?: React.Ref<ScrollableListRef<T>> },
|
||||
) => React.ReactElement;
|
||||
|
||||
@@ -492,6 +492,7 @@ function VirtualizedList<T>(
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const VirtualizedListWithForwardRef = forwardRef(VirtualizedList) as <T>(
|
||||
props: VirtualizedListProps<T> & { ref?: React.Ref<VirtualizedListRef<T>> },
|
||||
) => React.ReactElement;
|
||||
|
||||
@@ -157,6 +157,7 @@ export const TriageDuplicates = ({
|
||||
'--json',
|
||||
'number,title,body,state,stateReason,labels,url,comments,author,reactionGroups',
|
||||
]);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return JSON.parse(stdout) as Candidate;
|
||||
} catch (err) {
|
||||
debugLogger.error(
|
||||
@@ -280,6 +281,7 @@ Return a JSON object with:
|
||||
promptId: 'triage-duplicates',
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const rec = response as unknown as GeminiRecommendation;
|
||||
|
||||
let canonical: Candidate | undefined;
|
||||
|
||||
@@ -225,6 +225,7 @@ Return a JSON object with:
|
||||
promptId: 'triage-issues',
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return response as unknown as AnalysisResult;
|
||||
},
|
||||
[config],
|
||||
|
||||
@@ -21,6 +21,7 @@ class EditorSettingsManager {
|
||||
private readonly availableEditors: EditorDisplay[];
|
||||
|
||||
constructor() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const editorTypes = Object.keys(
|
||||
EDITOR_DISPLAY_NAMES,
|
||||
).sort() as EditorType[];
|
||||
|
||||
@@ -467,6 +467,7 @@ export const useSlashCommandProcessor = (
|
||||
actions.openModelDialog();
|
||||
return { type: 'handled' };
|
||||
case 'agentConfig': {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const props = result.props as Record<string, unknown>;
|
||||
if (
|
||||
!props ||
|
||||
@@ -482,12 +483,14 @@ export const useSlashCommandProcessor = (
|
||||
actions.openAgentConfigDialog(
|
||||
props['name'],
|
||||
props['displayName'],
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
props['definition'] as AgentDefinition,
|
||||
);
|
||||
return { type: 'handled' };
|
||||
}
|
||||
case 'permissions':
|
||||
actions.openPermissionsDialog(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
result.props as { targetDirectory?: string },
|
||||
);
|
||||
return { type: 'handled' };
|
||||
|
||||
@@ -102,6 +102,7 @@ export function useApprovalModeIndicator({
|
||||
addItem(
|
||||
{
|
||||
type: MessageType.INFO,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
text: (e as Error).message,
|
||||
},
|
||||
Date.now(),
|
||||
|
||||
@@ -46,7 +46,6 @@ import type {
|
||||
ToolCallResponseInfo,
|
||||
GeminiErrorEventValue,
|
||||
RetryAttemptPayload,
|
||||
ToolCallConfirmationDetails,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { type Part, type PartListUnion, FinishReason } from '@google/genai';
|
||||
import type {
|
||||
@@ -427,6 +426,7 @@ export const useGeminiStream = (
|
||||
(tc) =>
|
||||
tc.status === 'executing' && tc.request.name === 'run_shell_command',
|
||||
);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return (executingShellTool as TrackedExecutingToolCall | undefined)?.pid;
|
||||
}, [toolCalls]);
|
||||
|
||||
@@ -551,6 +551,7 @@ export const useGeminiStream = (
|
||||
// If it is a shell command, we update the status to Canceled and clear the output
|
||||
// to avoid artifacts, then add it to history immediately.
|
||||
if (isShellCommand) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const toolGroup = pendingHistoryItemRef.current as HistoryItemToolGroup;
|
||||
const updatedTools = toolGroup.tools.map((tool) => {
|
||||
if (tool.name === SHELL_COMMAND_NAME) {
|
||||
@@ -764,6 +765,7 @@ export const useGeminiStream = (
|
||||
if (splitPoint === newGeminiMessageBuffer.length) {
|
||||
// Update the existing message with accumulated content
|
||||
setPendingHistoryItem((item) => ({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
type: item?.type as 'gemini' | 'gemini_content',
|
||||
text: newGeminiMessageBuffer,
|
||||
}));
|
||||
@@ -780,6 +782,7 @@ export const useGeminiStream = (
|
||||
const afterText = newGeminiMessageBuffer.substring(splitPoint);
|
||||
addItem(
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
type: pendingHistoryItemRef.current?.type as
|
||||
| 'gemini'
|
||||
| 'gemini_content',
|
||||
@@ -1372,13 +1375,10 @@ export const useGeminiStream = (
|
||||
|
||||
// Process pending tool calls sequentially to reduce UI chaos
|
||||
for (const call of awaitingApprovalCalls) {
|
||||
if (
|
||||
(call.confirmationDetails as ToolCallConfirmationDetails)?.onConfirm
|
||||
) {
|
||||
const details = call.confirmationDetails;
|
||||
if (details && 'onConfirm' in details) {
|
||||
try {
|
||||
await (
|
||||
call.confirmationDetails as ToolCallConfirmationDetails
|
||||
).onConfirm(ToolConfirmationOutcome.ProceedOnce);
|
||||
await details.onConfirm(ToolConfirmationOutcome.ProceedOnce);
|
||||
} catch (error) {
|
||||
debugLogger.warn(
|
||||
`Failed to auto-approve tool call ${call.request.callId}:`,
|
||||
@@ -1444,7 +1444,9 @@ export const useGeminiStream = (
|
||||
const pid = data?.pid;
|
||||
|
||||
if (isShell && pid) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const command = (data?.['command'] as string) ?? 'shell';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const initialOutput = (data?.['initialOutput'] as string) ?? '';
|
||||
|
||||
registerBackgroundShell(pid, command, initialOutput);
|
||||
|
||||
@@ -62,6 +62,7 @@ export function useHistory({
|
||||
isResuming: boolean = false,
|
||||
): number => {
|
||||
const id = getNextMessageId(baseTimestamp);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const newItem: HistoryItem = { ...itemData, id } as HistoryItem;
|
||||
|
||||
setHistory((prevHistory) => {
|
||||
@@ -139,6 +140,7 @@ export function useHistory({
|
||||
// Apply updates based on whether it's an object or a function
|
||||
const newUpdates =
|
||||
typeof updates === 'function' ? updates(item) : updates;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return { ...item, ...newUpdates } as HistoryItem;
|
||||
}
|
||||
return item;
|
||||
|
||||
@@ -38,6 +38,7 @@ async function finishAddingDirectories(
|
||||
await refreshServerHierarchicalMemory(config);
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
errors.push(`Error refreshing memory: ${(error as Error).message}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ async function getRemoteDataCollectionOptIn(
|
||||
return resp.freeTierDataCollectionOptin;
|
||||
} catch (error: unknown) {
|
||||
if (error && typeof error === 'object' && 'response' in error) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const gaxiosError = error as {
|
||||
response?: {
|
||||
status?: unknown;
|
||||
|
||||
@@ -127,6 +127,7 @@ export function useReactToolScheduler(
|
||||
existingTrackedCall?.responseSubmittedToGemini ?? false;
|
||||
|
||||
if (coreTc.status === 'executing') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const liveOutput = (existingTrackedCall as TrackedExecutingToolCall)
|
||||
?.liveOutput;
|
||||
return {
|
||||
|
||||
@@ -56,6 +56,7 @@ export type KeyMatchers = {
|
||||
export function createKeyMatchers(
|
||||
config: KeyBindingConfig = defaultKeyBindings,
|
||||
): KeyMatchers {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const matchers = {} as { [C in Command]: KeyMatcher };
|
||||
|
||||
for (const command of Object.values(Command)) {
|
||||
|
||||
@@ -383,6 +383,7 @@ class ThemeManager {
|
||||
|
||||
// 3. Read, parse, and validate the theme file.
|
||||
const themeContent = fs.readFileSync(canonicalPath, 'utf-8');
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const customThemeConfig = JSON.parse(themeContent) as CustomTheme;
|
||||
|
||||
const validation = validateCustomTheme(customThemeConfig);
|
||||
|
||||
@@ -41,6 +41,7 @@ function renderHastNode(
|
||||
// Handle Element Nodes: Determine color and pass it down, don't wrap
|
||||
if (node.type === 'element') {
|
||||
const nodeClasses: string[] =
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
(node.properties?.['className'] as string[]) || [];
|
||||
let elementColor: string | undefined = undefined;
|
||||
|
||||
|
||||
@@ -194,6 +194,7 @@ const writeAll = (stream: Writable, data: string): Promise<void> =>
|
||||
// On Windows, writing directly to the underlying file descriptor bypasses
|
||||
// application-level stream interception (e.g., by the Ink UI framework).
|
||||
// This ensures the raw OSC-52 escape sequence reaches the terminal host uncorrupted.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const fd = (stream as unknown as { fd?: number }).fd;
|
||||
if (
|
||||
process.platform === 'win32' &&
|
||||
@@ -214,6 +215,7 @@ const writeAll = (stream: Writable, data: string): Promise<void> =>
|
||||
|
||||
const onError = (err: unknown) => {
|
||||
cleanup();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
reject(err as Error);
|
||||
};
|
||||
const onDrain = () => {
|
||||
@@ -251,6 +253,7 @@ export const copyToClipboard = async (text: string): Promise<void> => {
|
||||
await writeAll(tty!.stream, payload);
|
||||
|
||||
if (tty!.closeAfter) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
(tty!.stream as fs.WriteStream).end();
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -174,6 +174,7 @@ export async function revertFileChanges(
|
||||
try {
|
||||
currentContent = await fs.readFile(filePath, 'utf8');
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const error = e as Error;
|
||||
if ('code' in error && error.code === 'ENOENT') {
|
||||
// File does not exist, which is fine in some revert scenarios.
|
||||
|
||||
@@ -245,6 +245,7 @@ async function configureVSCodeStyle(
|
||||
|
||||
const results = targetBindings.map((target) => {
|
||||
const hasOurBinding = keybindings.some((kb) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const binding = kb as {
|
||||
command?: string;
|
||||
args?: { text?: string };
|
||||
@@ -258,6 +259,7 @@ async function configureVSCodeStyle(
|
||||
});
|
||||
|
||||
const existingBinding = keybindings.find((kb) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const binding = kb as { key?: string };
|
||||
return binding.key === target.key;
|
||||
});
|
||||
|
||||
@@ -203,6 +203,7 @@ export function escapeAnsiCtrlCodes<T>(obj: T): T {
|
||||
}
|
||||
|
||||
regex.lastIndex = 0; // needed for global regex
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return obj.replace(regex, (match) =>
|
||||
JSON.stringify(match).slice(1, -1),
|
||||
) as T;
|
||||
@@ -225,6 +226,7 @@ export function escapeAnsiCtrlCodes<T>(obj: T): T {
|
||||
newArr[i] = escapedValue;
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return (newArr !== null ? newArr : obj) as T;
|
||||
}
|
||||
|
||||
@@ -232,6 +234,7 @@ export function escapeAnsiCtrlCodes<T>(obj: T): T {
|
||||
const keys = Object.keys(obj);
|
||||
|
||||
for (const key of keys) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const value = (obj as Record<string, unknown>)[key];
|
||||
const escapedValue = escapeAnsiCtrlCodes(value);
|
||||
|
||||
@@ -239,6 +242,7 @@ export function escapeAnsiCtrlCodes<T>(obj: T): T {
|
||||
if (newObj === null) {
|
||||
newObj = { ...obj };
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
(newObj as Record<string, unknown>)[key] = escapedValue;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user