mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-05 23:42:03 +00:00
fix revert changes
This commit is contained in:
parent
86ba86e297
commit
7a154b8a62
2 changed files with 139 additions and 97 deletions
|
|
@ -229,6 +229,33 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should not process kitty sequences when kitty protocol is disabled', async () => {
|
||||
const keyHandler = vi.fn();
|
||||
|
||||
const { result } = renderHook(() => useKeypressContext(), {
|
||||
wrapper: ({ children }) =>
|
||||
wrapper({ children, kittyProtocolEnabled: false }),
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.subscribe(keyHandler);
|
||||
});
|
||||
|
||||
// Send kitty protocol sequence for numpad enter
|
||||
act(() => {
|
||||
stdin.sendKittySequence(`\x1b[57414u`);
|
||||
});
|
||||
|
||||
// When kitty protocol is disabled, the sequence should be passed through
|
||||
// as individual keypresses, not recognized as a single enter key
|
||||
expect(keyHandler).not.toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
name: 'return',
|
||||
kittyProtocol: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Escape key handling', () => {
|
||||
|
|
@ -1229,13 +1256,13 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|||
});
|
||||
|
||||
expect(consoleLogSpy).toHaveBeenCalledWith(
|
||||
'[DEBUG] CSI buffer accumulating:',
|
||||
'[DEBUG] Kitty buffer accumulating:',
|
||||
expect.stringContaining('\x1b[27u'),
|
||||
);
|
||||
const parsedCall = consoleLogSpy.mock.calls.find(
|
||||
(args) =>
|
||||
typeof args[0] === 'string' &&
|
||||
args[0].includes('[DEBUG] CSI sequence parsed successfully'),
|
||||
args[0].includes('[DEBUG] Kitty sequence parsed successfully'),
|
||||
);
|
||||
expect(parsedCall).toBeTruthy();
|
||||
expect(parsedCall?.[1]).toEqual(expect.stringContaining('\x1b[27u'));
|
||||
|
|
@ -1266,7 +1293,7 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|||
});
|
||||
|
||||
expect(consoleLogSpy).toHaveBeenCalledWith(
|
||||
'[DEBUG] CSI buffer overflow, clearing:',
|
||||
'[DEBUG] Kitty buffer overflow, clearing:',
|
||||
expect.any(String),
|
||||
);
|
||||
});
|
||||
|
|
@ -1357,13 +1384,13 @@ describe('KeypressContext - Kitty Protocol', () => {
|
|||
|
||||
// Verify debug logging for accumulation
|
||||
expect(consoleLogSpy).toHaveBeenCalledWith(
|
||||
'[DEBUG] CSI buffer accumulating:',
|
||||
'[DEBUG] Kitty buffer accumulating:',
|
||||
sequence,
|
||||
);
|
||||
|
||||
// Verify warning for char codes
|
||||
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
||||
'CSI sequence buffer has char codes:',
|
||||
'Kitty sequence buffer has char codes:',
|
||||
[27, 91, 49, 50],
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import {
|
|||
MODIFIER_ALT_BIT,
|
||||
MODIFIER_CTRL_BIT,
|
||||
} from '../utils/platformConstants.js';
|
||||
import { clipboardHasImage } from '../utils/clipboardUtils.js';
|
||||
|
||||
import { FOCUS_IN, FOCUS_OUT } from '../hooks/useFocus.js';
|
||||
|
||||
|
|
@ -53,6 +54,7 @@ export interface Key {
|
|||
paste: boolean;
|
||||
sequence: string;
|
||||
kittyProtocol?: boolean;
|
||||
pasteImage?: boolean;
|
||||
}
|
||||
|
||||
export type KeypressHandler = (key: Key) => void;
|
||||
|
|
@ -387,7 +389,7 @@ export function KeypressProvider({
|
|||
}
|
||||
};
|
||||
|
||||
const handleKeypress = (_: unknown, key: Key) => {
|
||||
const handleKeypress = async (_: unknown, key: Key) => {
|
||||
if (key.sequence === FOCUS_IN || key.sequence === FOCUS_OUT) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -397,14 +399,28 @@ export function KeypressProvider({
|
|||
}
|
||||
if (key.name === 'paste-end') {
|
||||
isPaste = false;
|
||||
broadcast({
|
||||
name: '',
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
shift: false,
|
||||
paste: true,
|
||||
sequence: pasteBuffer.toString(),
|
||||
});
|
||||
if (pasteBuffer.toString().length > 0) {
|
||||
broadcast({
|
||||
name: '',
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
shift: false,
|
||||
paste: true,
|
||||
sequence: pasteBuffer.toString(),
|
||||
});
|
||||
} else {
|
||||
const hasImage = await clipboardHasImage();
|
||||
broadcast({
|
||||
name: '',
|
||||
ctrl: false,
|
||||
meta: false,
|
||||
shift: false,
|
||||
paste: true,
|
||||
pasteImage: hasImage,
|
||||
sequence: pasteBuffer.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
pasteBuffer = Buffer.alloc(0);
|
||||
return;
|
||||
}
|
||||
|
|
@ -508,97 +524,95 @@ export function KeypressProvider({
|
|||
return;
|
||||
}
|
||||
|
||||
// Parse CSI sequences for both Kitty protocol and legacy terminals
|
||||
// This ensures Shift+Tab and other special keys work correctly even when
|
||||
// Kitty protocol is not available (e.g., Windows PowerShell)
|
||||
if (
|
||||
kittySequenceBuffer ||
|
||||
(key.sequence &&
|
||||
key.sequence.startsWith(`${ESC}[`) &&
|
||||
!key.sequence.startsWith(PASTE_MODE_PREFIX) &&
|
||||
!key.sequence.startsWith(PASTE_MODE_SUFFIX) &&
|
||||
!key.sequence.startsWith(FOCUS_IN) &&
|
||||
!key.sequence.startsWith(FOCUS_OUT))
|
||||
) {
|
||||
kittySequenceBuffer += key.sequence;
|
||||
|
||||
if (debugKeystrokeLogging) {
|
||||
console.log('[DEBUG] CSI buffer accumulating:', kittySequenceBuffer);
|
||||
}
|
||||
|
||||
// Try to peel off as many complete sequences as are available at the
|
||||
// start of the buffer. This handles batched inputs cleanly. If the
|
||||
// prefix is incomplete or invalid, skip to the next CSI introducer
|
||||
// (ESC[) so that a following valid sequence can still be parsed.
|
||||
let parsedAny = false;
|
||||
while (kittySequenceBuffer) {
|
||||
const parsed = parseKittyPrefix(kittySequenceBuffer);
|
||||
if (!parsed) {
|
||||
// Look for the next potential CSI start beyond index 0
|
||||
const nextStart = kittySequenceBuffer.indexOf(`${ESC}[`, 1);
|
||||
if (nextStart > 0) {
|
||||
if (debugKeystrokeLogging) {
|
||||
console.log(
|
||||
'[DEBUG] Skipping incomplete/invalid CSI prefix:',
|
||||
kittySequenceBuffer.slice(0, nextStart),
|
||||
);
|
||||
}
|
||||
kittySequenceBuffer = kittySequenceBuffer.slice(nextStart);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (debugKeystrokeLogging) {
|
||||
const parsedSequence = kittySequenceBuffer.slice(0, parsed.length);
|
||||
if (kittySequenceBuffer.length > parsed.length) {
|
||||
console.log(
|
||||
'[DEBUG] CSI sequence parsed successfully (prefix):',
|
||||
parsedSequence,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
'[DEBUG] CSI sequence parsed successfully:',
|
||||
parsedSequence,
|
||||
);
|
||||
}
|
||||
}
|
||||
// Consume the parsed prefix and broadcast it.
|
||||
kittySequenceBuffer = kittySequenceBuffer.slice(parsed.length);
|
||||
broadcast(parsed.key);
|
||||
parsedAny = true;
|
||||
}
|
||||
if (parsedAny) return;
|
||||
|
||||
if (config?.getDebugMode() || debugKeystrokeLogging) {
|
||||
const codes = Array.from(kittySequenceBuffer).map((ch) =>
|
||||
ch.charCodeAt(0),
|
||||
);
|
||||
console.warn('CSI sequence buffer has char codes:', codes);
|
||||
}
|
||||
|
||||
if (kittyProtocolEnabled) {
|
||||
if (
|
||||
kittyProtocolEnabled &&
|
||||
kittySequenceBuffer.length > MAX_KITTY_SEQUENCE_LENGTH
|
||||
kittySequenceBuffer ||
|
||||
(key.sequence.startsWith(`${ESC}[`) &&
|
||||
!key.sequence.startsWith(PASTE_MODE_PREFIX) &&
|
||||
!key.sequence.startsWith(PASTE_MODE_SUFFIX) &&
|
||||
!key.sequence.startsWith(FOCUS_IN) &&
|
||||
!key.sequence.startsWith(FOCUS_OUT))
|
||||
) {
|
||||
kittySequenceBuffer += key.sequence;
|
||||
|
||||
if (debugKeystrokeLogging) {
|
||||
console.log(
|
||||
'[DEBUG] CSI buffer overflow, clearing:',
|
||||
'[DEBUG] Kitty buffer accumulating:',
|
||||
kittySequenceBuffer,
|
||||
);
|
||||
}
|
||||
if (config) {
|
||||
const event = new KittySequenceOverflowEvent(
|
||||
kittySequenceBuffer.length,
|
||||
kittySequenceBuffer,
|
||||
);
|
||||
logKittySequenceOverflow(config, event);
|
||||
|
||||
// Try to peel off as many complete sequences as are available at the
|
||||
// start of the buffer. This handles batched inputs cleanly. If the
|
||||
// prefix is incomplete or invalid, skip to the next CSI introducer
|
||||
// (ESC[) so that a following valid sequence can still be parsed.
|
||||
let parsedAny = false;
|
||||
while (kittySequenceBuffer) {
|
||||
const parsed = parseKittyPrefix(kittySequenceBuffer);
|
||||
if (!parsed) {
|
||||
// Look for the next potential CSI start beyond index 0
|
||||
const nextStart = kittySequenceBuffer.indexOf(`${ESC}[`, 1);
|
||||
if (nextStart > 0) {
|
||||
if (debugKeystrokeLogging) {
|
||||
console.log(
|
||||
'[DEBUG] Skipping incomplete/invalid CSI prefix:',
|
||||
kittySequenceBuffer.slice(0, nextStart),
|
||||
);
|
||||
}
|
||||
kittySequenceBuffer = kittySequenceBuffer.slice(nextStart);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (debugKeystrokeLogging) {
|
||||
const parsedSequence = kittySequenceBuffer.slice(
|
||||
0,
|
||||
parsed.length,
|
||||
);
|
||||
if (kittySequenceBuffer.length > parsed.length) {
|
||||
console.log(
|
||||
'[DEBUG] Kitty sequence parsed successfully (prefix):',
|
||||
parsedSequence,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
'[DEBUG] Kitty sequence parsed successfully:',
|
||||
parsedSequence,
|
||||
);
|
||||
}
|
||||
}
|
||||
// Consume the parsed prefix and broadcast it.
|
||||
kittySequenceBuffer = kittySequenceBuffer.slice(parsed.length);
|
||||
broadcast(parsed.key);
|
||||
parsedAny = true;
|
||||
}
|
||||
if (parsedAny) return;
|
||||
|
||||
if (config?.getDebugMode() || debugKeystrokeLogging) {
|
||||
const codes = Array.from(kittySequenceBuffer).map((ch) =>
|
||||
ch.charCodeAt(0),
|
||||
);
|
||||
console.warn('Kitty sequence buffer has char codes:', codes);
|
||||
}
|
||||
|
||||
if (kittySequenceBuffer.length > MAX_KITTY_SEQUENCE_LENGTH) {
|
||||
if (debugKeystrokeLogging) {
|
||||
console.log(
|
||||
'[DEBUG] Kitty buffer overflow, clearing:',
|
||||
kittySequenceBuffer,
|
||||
);
|
||||
}
|
||||
if (config) {
|
||||
const event = new KittySequenceOverflowEvent(
|
||||
kittySequenceBuffer.length,
|
||||
kittySequenceBuffer,
|
||||
);
|
||||
logKittySequenceOverflow(config, event);
|
||||
}
|
||||
kittySequenceBuffer = '';
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
kittySequenceBuffer = '';
|
||||
} else if (!kittyProtocolEnabled) {
|
||||
// For non-Kitty terminals, clear the buffer to avoid accumulation
|
||||
kittySequenceBuffer = '';
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -721,6 +735,7 @@ export function KeypressProvider({
|
|||
};
|
||||
|
||||
let rl: readline.Interface;
|
||||
|
||||
if (usePassthrough) {
|
||||
rl = readline.createInterface({
|
||||
input: keypressStream,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue