UNPKG

naisys

Version:

NAISYS - Autonomous AI agent runner with built-in context management and cost tracking

206 lines 5.71 kB
// How long each chord in a press is held down. Matches typical human keypress // duration (~100ms) and, crucially, spans enough frames (~6 @ 60Hz) for games // and emulators to reliably sample the input. Agent loops think and screenshot // between presses, so the throughput cost is irrelevant here — reliability wins. export const PRESS_KEY_HOLD_MS = 100; const MODIFIER_ALIASES = new Map([ ["ctrl", "ctrl"], ["control", "ctrl"], ["alt", "alt"], ["option", "alt"], ["shift", "shift"], ["meta", "meta"], ["super", "meta"], ["win", "meta"], ["windows", "meta"], ["cmd", "meta"], ["command", "meta"], ["fn", "fn"], ]); const KEY_ALIASES = new Map([ ["enter", "enter"], ["return", "enter"], ["space", "space"], ["spacebar", "space"], ["tab", "tab"], ["esc", "escape"], ["escape", "escape"], ["backspace", "backspace"], ["delete", "delete"], ["del", "delete"], ["forwarddelete", "delete"], ["fwddelete", "delete"], ["home", "home"], ["end", "end"], ["pageup", "pageup"], ["pgup", "pageup"], ["pagedown", "pagedown"], ["pgdn", "pagedown"], ["up", "up"], ["arrowup", "up"], ["down", "down"], ["arrowdown", "down"], ["left", "left"], ["arrowleft", "left"], ["right", "right"], ["arrowright", "right"], ]); function sanitizeKeyToken(token) { return token.trim().toLowerCase().replace(/[_-]+/g, ""); } function normalizeChordPart(part) { const raw = part.trim(); if (!raw) return null; const sanitized = sanitizeKeyToken(raw); const modifier = MODIFIER_ALIASES.get(sanitized); if (modifier) { return { kind: "modifier", value: modifier }; } const key = KEY_ALIASES.get(sanitized); if (key) { return { kind: "key", value: key }; } if (/^f\d{1,2}$/i.test(sanitized)) { return { kind: "key", value: sanitized.toLowerCase() }; } if (raw.length === 1) { return { kind: "key", value: raw.toLowerCase() }; } return { kind: "key", value: raw }; } export function normalizeKeyCombo(keyCombo) { return keyCombo .trim() .split(/\s+/) .filter(Boolean) .map((rawChord) => { const modifiers = []; const keys = []; for (const rawPart of rawChord.split("+")) { const part = normalizeChordPart(rawPart); if (!part) continue; if (part.kind === "modifier") { if (!modifiers.includes(part.value)) { modifiers.push(part.value); } continue; } keys.push(part.value); } return { modifiers, keys }; }) .filter((chord) => chord.modifiers.length > 0 || chord.keys.length > 0); } export function canonicalizeKeyCombo(keyCombo) { return normalizeKeyCombo(keyCombo) .map((chord) => [...chord.modifiers, ...chord.keys].join("+")) .join(" "); } /** Map a normalized key combo to Playwright's case-sensitive key syntax. */ export function toPlaywrightKeyCombo(keyCombo) { return normalizeKeyCombo(keyCombo) .map((chord) => { const parts = []; for (const mod of chord.modifiers) { parts.push(toPlaywrightModifier(mod)); } for (const key of chord.keys) { parts.push(toPlaywrightKey(key)); } return parts.join("+"); }) .join(" "); } function toPlaywrightModifier(mod) { switch (mod) { case "ctrl": return "Control"; case "alt": return "Alt"; case "shift": return "Shift"; case "meta": return "Meta"; case "fn": return "Fn"; } } function toPlaywrightKey(key) { switch (key) { case "enter": return "Enter"; case "tab": return "Tab"; case "escape": return "Escape"; case "backspace": return "Backspace"; case "delete": return "Delete"; case "space": return "Space"; case "up": return "ArrowUp"; case "down": return "ArrowDown"; case "left": return "ArrowLeft"; case "right": return "ArrowRight"; case "home": return "Home"; case "end": return "End"; case "pageup": return "PageUp"; case "pagedown": return "PageDown"; default: if (/^f\d{1,2}$/i.test(key)) { return key.toUpperCase(); } return key; } } export function toLinuxKeyToken(key) { switch (key) { case "enter": return "Return"; case "tab": return "Tab"; case "escape": return "Escape"; case "backspace": return "BackSpace"; case "delete": return "Delete"; case "space": return "space"; case "up": return "Up"; case "down": return "Down"; case "left": return "Left"; case "right": return "Right"; case "home": return "Home"; case "end": return "End"; case "pageup": return "Page_Up"; case "pagedown": return "Page_Down"; case "meta": return "super"; default: if (/^f\d{1,2}$/i.test(key)) { return key.toUpperCase(); } return key; } } //# sourceMappingURL=keyCombo.js.map