import os from 'node:os' import path from 'node:path' const RESET = '\x1b[0m' const DIM = '\x1b[2m' const BOLD = '\x1b[1m' const CYAN = '\x1b[36m' const GRAY = '\x1b[90m' const WHITE = '\x1b[97m' const LINE = '─'.repeat(58) /** * Muestra el prompt de confianza de workspace al inicio de cada sesión fresca. * Igual que el "trust prompt" de Claude Code: informa al usuario qué carpeta * va a gestionar sq y pide confirmación explícita antes de arrancar. * * Devuelve true si el usuario confía, false si elige salir o pulsa Esc. */ export async function runTrustPrompt(): Promise { if (!process.stdin.isTTY) return true // modo no-interactivo: pasar siempre const cwd = process.cwd() const home = os.homedir() // Mostrar path abreviado: ~/foo si está dentro de home const display = cwd.startsWith(home) ? '~' + cwd.slice(home.length) : cwd const options = [ '1. Yes, I trust this folder', '2. No, exit', ] return new Promise((resolve) => { let idx = 0 let linesWritten = 0 const wasRaw = process.stdin.isRaw process.stdin.setRawMode(true) process.stdin.resume() process.stdout.write('\x1b[?25l') // ocultar cursor const draw = () => { if (linesWritten > 0) { process.stdout.write(`\r\x1b[${linesWritten}A\x1b[J`) } const lines: string[] = [] lines.push(` ${DIM}${LINE}${RESET}`) lines.push(` ${BOLD}Accessing workspace:${RESET}`) lines.push('') lines.push(` ${CYAN}${display}${RESET}`) lines.push('') lines.push(` ${WHITE}Quick safety check: Is this a project you created or${RESET}`) lines.push(` ${WHITE}one you trust? (Like your own code, a well-known open${RESET}`) lines.push(` ${WHITE}source project, or work from your team). If not, take${RESET}`) lines.push(` ${WHITE}a moment to review what's in this folder first.${RESET}`) lines.push('') lines.push(` ${DIM}squeezr-code will be able to read, edit, and execute${RESET}`) lines.push(` ${DIM}files here.${RESET}`) lines.push('') for (let i = 0; i < options.length; i++) { const active = i === idx const cursor = active ? `${CYAN}❯${RESET}` : ' ' const label = active ? `${BOLD}${options[i]}${RESET}` : `${GRAY}${options[i]}${RESET}` lines.push(` ${cursor} ${label}`) } lines.push('') lines.push(` ${DIM}Enter to confirm · Esc to cancel${RESET}`) process.stdout.write(lines.join('\n') + '\n') linesWritten = lines.length } const cleanup = () => { process.stdin.off('data', onData) if (process.stdin.isTTY) process.stdin.setRawMode(wasRaw) process.stdout.write('\x1b[?25h') // mostrar cursor } const onData = (chunk: Buffer) => { const s = chunk.toString('utf-8') // Ctrl+C o Esc → salir if (s === '\x03' || s === '\x1b') { cleanup() // Limpiar el prompt antes de salir process.stdout.write(`\r\x1b[${linesWritten}A\x1b[J`) resolve(false) return } // Enter → confirmar selección if (s === '\r' || s === '\n') { cleanup() process.stdout.write(`\r\x1b[${linesWritten}A\x1b[J`) resolve(idx === 0) return } // Tecla '2' directa → seleccionar "No, exit" if (s === '2') { idx = 1; cleanup(); process.stdout.write(`\r\x1b[${linesWritten}A\x1b[J`); resolve(false); return } // Tecla '1' directa → seleccionar "Yes" if (s === '1') { idx = 0; cleanup(); process.stdout.write(`\r\x1b[${linesWritten}A\x1b[J`); resolve(true); return } // ↑ / k if (s === '\x1b[A' || s === 'k') { idx = (idx - 1 + options.length) % options.length; draw(); return } // ↓ / j if (s === '\x1b[B' || s === 'j') { idx = (idx + 1) % options.length; draw(); return } } process.stdin.on('data', onData) draw() }) }