@hoilab/ada-cli 0.84.11 → 0.84.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"home-screen.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/home-screen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAwD,MAAM,wBAAwB,CAAC;AACzH,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAKzF,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC;AAEzF,KAAK,cAAc,GAAG,CAAC,UAAU,CAAC,EAAE,mBAAmB,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;AAwDnF;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,SAAU,YAAW,SAAS;IACtE,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAwB;IAExC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,kEAAkE;IAC3D,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IAEhC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAExC;IAED,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE/B;IAED,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEvC;IAED,YAAY,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAMxD;IAGD,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IAEK,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAW5B;IAED,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,SAAS;YAQH,WAAW;IAczB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkD9B;IAED,UAAU,IAAI,IAAI,CAAG;IAErB,gBAAgB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAErC;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAmI9B;IAED,8DAA8D;IAC9D,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,WAAW;CAGnB","sourcesContent":["import { type Component, Container, Input, getKeybindings, truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport type { SessionInfo, SessionListProgress } from \"../../../core/session-manager.ts\";\nimport { checkForNewPiVersion } from \"../../../utils/version-check.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { filterAndSortSessions } from \"./session-selector-search.ts\";\n\nexport type HomeScreenResult = { kind: \"new\" } | { kind: \"resume\"; path: string } | null;\n\ntype SessionsLoader = (onProgress?: SessionListProgress) => Promise<SessionInfo[]>;\n\nconst ASCII_LOGO = [\n\t\" █████╗ ██████╗ █████╗\",\n\t\" ██╔══██╗██╔══██╗██╔══██╗\",\n\t\" ███████║██║ ██║███████║\",\n\t\" ██╔══██║██║ ██║██╔══██║\",\n\t\" ██║ ██║██████╔╝██║ ██║\",\n\t\" ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝\",\n].join(\"\\n\");\n\n/** Vertical teal-to-gray gradient for the ASCII logo. */\nconst LOGO_GRADIENT = [\"accent\", \"accent\", \"borderAccent\", \"border\", \"borderMuted\", \"muted\"] as const;\n\n/** Draw a rounded box around centered content with an optional title. */\nfunction box(\n\tcontentLines: string[],\n\twidth: number,\n\toptions: { title?: string; color?: (str: string) => string } = {},\n): string[] {\n\tconst color = options.color ?? ((str: string) => theme.fg(\"border\", str));\n\tconst innerWidth = Math.max(10, width - 4);\n\tconst top =\n\t\toptions.title !== undefined\n\t\t\t? color(`╭─ ${options.title} `) + \"─\".repeat(Math.max(1, innerWidth - options.title.length - 2)) + color(\"─╮\")\n\t\t\t: color(`╭${\"─\".repeat(innerWidth)}╮`);\n\tconst bottom = color(`╰${\"─\".repeat(innerWidth)}╯`);\n\tconst pad = (line: string) => {\n\t\tconst visible = visibleWidth(line);\n\t\tconst left = Math.max(0, Math.floor((innerWidth - visible) / 2));\n\t\tconst right = Math.max(0, innerWidth - visible - left);\n\t\treturn color(\"│ \") + \" \".repeat(left) + line + \" \".repeat(right) + color(\" │\");\n\t};\n\treturn [top, ...contentLines.map(pad), bottom];\n}\n\nfunction sessionTitle(session: SessionInfo): string {\n\tif (session.name) return session.name;\n\tconst first = (session.firstMessage ?? \"\").replace(/\\s+/g, \" \").trim();\n\tif (first.length > 0) return first.length > 60 ? `${first.slice(0, 60)}…` : first;\n\treturn \"Conversation\";\n}\n\nfunction relativeTime(iso: string): string {\n\tconst diffMs = Date.now() - new Date(iso).getTime();\n\tconst mins = Math.floor(diffMs / 60000);\n\tif (mins < 1) return \"now\";\n\tif (mins < 60) return `${mins}m`;\n\tconst hours = Math.floor(mins / 60);\n\tif (hours < 24) return `${hours}h`;\n\tconst days = Math.floor(hours / 24);\n\tif (days < 7) return `${days}d`;\n\tif (days < 30) return `${Math.floor(days / 7)}w`;\n\treturn `${Math.floor(days / 30)}mo`;\n}\n\n/**\n * Central welcome flow (opencode style) shown when the CLI starts:\n * 1) entry screen: \"Enter as guest\" (login is disabled for now)\n * 2) home screen: welcome banner, update notice, recent conversations and\n * a \"New conversation\" action.\n */\nexport class HomeScreenComponent extends Container implements Component {\n\tprivate phase: \"login\" | \"home\" = \"login\";\n\tprivate sessions: SessionInfo[] = [];\n\tprivate filtered: SessionInfo[] = [];\n\tprivate selectedIndex = 0; // 0 = \"New conversation\", then sessions\n\tprivate query = \"\";\n\tprivate loading = false;\n\tprivate updateAvailable: string | null = null;\n\tprivate updateChecked = false;\n\tprivate searchInput: Input;\n\tprivate loadSessions: SessionsLoader;\n\tprivate version: string;\n\tprivate modelLabel: string | null = null;\n\tprivate cwdLabelValue: string | null = null;\n\tprivate memoryEnabled = true;\n\tprivate _focused = false;\n\tprivate requestRenderFn: () => void = () => {};\n\n\tpublic onNew?: () => void;\n\tpublic onResume?: (path: string) => void;\n\tpublic onExit?: () => void;\n\tpublic onUpdate?: () => void;\n\t/** Fired when the entry screen transitions to the home screen. */\n\tpublic onEnterHome?: () => void;\n\n\tsetModelLabel(label: string | null): void {\n\t\tthis.modelLabel = label;\n\t}\n\n\tsetCwdLabel(label: string): void {\n\t\tthis.cwdLabelValue = label;\n\t}\n\n\tsetMemoryEnabled(enabled: boolean): void {\n\t\tthis.memoryEnabled = enabled;\n\t}\n\n\tconstructor(loadSessions: SessionsLoader, version: string) {\n\t\tsuper();\n\t\tthis.loadSessions = loadSessions;\n\t\tthis.version = version;\n\t\tthis.searchInput = new Input();\n\t\tthis.searchInput.onSubmit = () => this.confirmSelection();\n\t}\n\n\t// Focusable\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tasync reload(): Promise<void> {\n\t\tthis.loading = true;\n\t\tthis.requestRenderFn();\n\t\ttry {\n\t\t\tthis.sessions = await this.loadSessions();\n\t\t} catch {\n\t\t\tthis.sessions = [];\n\t\t}\n\t\tthis.loading = false;\n\t\tthis.applyFilter();\n\t\tthis.requestRenderFn();\n\t}\n\n\tprivate applyFilter(): void {\n\t\tconst q = this.query.trim();\n\t\tthis.filtered = q\n\t\t\t? filterAndSortSessions(this.sessions, q, \"recent\", \"all\")\n\t\t\t: [...this.sessions].sort((a, b) => b.modified.getTime() - a.modified.getTime());\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.filtered.length);\n\t}\n\n\tprivate confirmSelection(): void {\n\t\tif (this.phase === \"login\") {\n\t\t\tthis.enterHome();\n\t\t\treturn;\n\t\t}\n\t\tif (this.selectedIndex === 0) {\n\t\t\tthis.onNew?.();\n\t\t} else {\n\t\t\tconst session = this.filtered[this.selectedIndex - 1];\n\t\t\tif (session) this.onResume?.(session.path);\n\t\t}\n\t}\n\n\tprivate enterHome(): void {\n\t\tthis.phase = \"home\";\n\t\tthis.selectedIndex = 0;\n\t\tthis.onEnterHome?.();\n\t\tvoid this.reload();\n\t\tvoid this.checkUpdate();\n\t}\n\n\tprivate async checkUpdate(): Promise<void> {\n\t\tif (this.updateChecked) return;\n\t\tthis.updateChecked = true;\n\t\ttry {\n\t\t\tconst release = await checkForNewPiVersion(this.version);\n\t\t\tif (release) {\n\t\t\t\tthis.updateAvailable = release.version;\n\t\t\t\tthis.requestRenderFn();\n\t\t\t}\n\t\t} catch {\n\t\t\t// Offline or unreachable — ignore silently.\n\t\t}\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (this.phase === \"login\") {\n\t\t\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\r\" || data === \"\\n\") {\n\t\t\t\tthis.enterHome();\n\t\t\t} else if (kb.matches(data, \"tui.select.cancel\") || data === \"q\" || data === \"Q\") {\n\t\t\t\tthis.onExit?.();\n\t\t\t} else if (kb.matches(data, \"tui.select.down\")) {\n\t\t\t\t// Only one actionable option on the login screen; ignore.\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.requestRenderFn();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tthis.selectedIndex = Math.min(this.filtered.length, this.selectedIndex + 1);\n\t\t\tthis.requestRenderFn();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\r\" || data === \"\\n\") {\n\t\t\tthis.confirmSelection();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onExit?.();\n\t\t\treturn;\n\t\t}\n\t\tif (data === \"n\" || data === \"N\") {\n\t\t\tthis.onNew?.();\n\t\t\treturn;\n\t\t}\n\t\tif (data === \"u\" || data === \"U\") {\n\t\t\tif (this.updateAvailable) {\n\t\t\t\tthis.onUpdate?.();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (data === \"q\" || data === \"Q\") {\n\t\t\tthis.onExit?.();\n\t\t\treturn;\n\t\t}\n\t\t// Anything else goes to the search input (filters sessions)\n\t\tthis.searchInput.handleInput(data);\n\t\tthis.query = this.searchInput.getValue();\n\t\tthis.applyFilter();\n\t\tthis.requestRenderFn();\n\t}\n\n\tinvalidate(): void {}\n\n\tsetRequestRender(fn: () => void): void {\n\t\tthis.requestRenderFn = fn;\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst center = (text: string) => {\n\t\t\tconst pad = Math.max(0, Math.floor((width - visibleWidth(text)) / 2));\n\t\t\treturn \" \".repeat(pad) + text;\n\t\t};\n\t\tconst dim = (t: string) => theme.fg(\"dim\", t);\n\t\tconst muted = (t: string) => theme.fg(\"muted\", t);\n\t\tconst accent = (t: string) => theme.fg(\"accent\", t);\n\t\tconst border = (t: string) => theme.fg(\"border\", t);\n\t\tconst success = (t: string) => theme.fg(\"success\", t);\n\t\tconst warning = (t: string) => theme.fg(\"warning\", t);\n\n\t\t// Gradient logo (teal -> gray)\n\t\tconst logoLines = ASCII_LOGO.split(\"\\n\").map((line, i) =>\n\t\t\ttheme.fg(LOGO_GRADIENT[Math.min(i, LOGO_GRADIENT.length - 1)], line),\n\t\t);\n\t\tconst tagline =\n\t\t\taccent(\"Ada\") + dim(\" · coding agent · HOILAB TECH\") + muted(` v${this.version}`);\n\n\t\tlines.push(\"\");\n\n\t\tif (this.phase === \"login\") {\n\t\t\t// ---- Entry screen -------------------------------------------\n\t\t\tconst boxW = Math.min(56, width - 4);\n\t\t\tconst boxLines = box(\n\t\t\t\t[\n\t\t\t\t\t\"\",\n\t\t\t\t\t...logoLines,\n\t\t\t\t\ttagline,\n\t\t\t\t\t\"\",\n\t\t\t\t\tdim(\"Bienvenido a Ada — el agente de codificación de HOILAB TECH\"),\n\t\t\t\t\t\"\",\n\t\t\t\t\taccent(\"▸ \") + theme.bold(\"Entrar como invitado\"),\n\t\t\t\t\tmuted(\" Loguearme\") + dim(\" (próximamente)\"),\n\t\t\t\t\t\"\",\n\t\t\t\t],\n\t\t\t\tboxW,\n\t\t\t\t{ title: \" ✦ HOILAB TECH ✦ \" },\n\t\t\t);\n\t\t\tlines.push(...boxLines.map((l) => center(l)));\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(center(success(\"●\") + dim(\" En línea · sin conexión a cuentas\") + muted(\" · todo queda en tu máquina\")));\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\n\t\t\t\tcenter(muted([\"Enter para continuar\", \"q para salir\"].join(\" · \"))),\n\t\t\t);\n\t\t\treturn this.finishRender(lines, width);\n\t\t}\n\n\t\t// ---- Home screen ------------------------------------------------\n\t\tconst boxW = Math.min(width - 4, 72);\n\n\t\t// Header box: logo + status\n\t\tconst statusParts = [\n\t\t\tdim(`model: ${this.defaultModelLabel()}`),\n\t\t\tdim(`cwd: ${this.cwdLabel()}`),\n\t\t\tdim(`memoria: ${this.memoryLabel()}`),\n\t\t\t\"\",\n\t\t];\n\t\tif (this.updateAvailable) {\n\t\t\tstatusParts.push(\n\t\t\t\twarning(\n\t\t\t\t\t`⚠ Nueva versión disponible: v${this.updateAvailable} ` +\n\t\t\t\t\t\taccent(\"[u] actualizar\") +\n\t\t\t\t\t\tdim(\" · q para ignorar\"),\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (this.updateChecked) {\n\t\t\tstatusParts.push(success(\"✓ Sistema actualizado\"));\n\t\t}\n\t\tlines.push(...box([\"\", ...logoLines, tagline, \"\", ...statusParts], boxW, { title: \" ✦ HOILAB TECH ✦ \" }).map((l) => center(l)));\n\t\tlines.push(\"\");\n\n\t\t// Conversations box\n\t\tconst convLines: string[] = [\"\"];\n\t\tconst isNew = this.selectedIndex === 0;\n\t\tconvLines.push(\n\t\t\t`${isNew ? accent(\"▸ \") : \" \"}${accent(\"✦\")} ${isNew ? theme.bold(\"Nueva conversación\") : \"Nueva conversación\"}`,\n\t\t);\n\t\tconvLines.push(dim(\"─\".repeat(Math.max(4, boxW - 6))));\n\t\tconvLines.push(\"\");\n\n\t\tif (this.loading) {\n\t\t\tconvLines.push(dim(\"Cargando conversaciones…\"));\n\t\t} else if (this.filtered.length === 0) {\n\t\t\tconvLines.push(\n\t\t\t\tmuted(\n\t\t\t\t\tthis.query\n\t\t\t\t\t\t? \"No hay conversaciones que coincidan con tu búsqueda\"\n\t\t\t\t\t\t: \"Todavía no hay conversaciones anteriores\",\n\t\t\t\t),\n\t\t\t);\n\t\t} else {\n\t\t\tconst maxVisible = Math.max(1, Math.min(12, Math.floor((width * 2) / 3)));\n\t\t\tconst visible = this.filtered.slice(0, maxVisible);\n\t\t\tfor (let i = 0; i < visible.length; i++) {\n\t\t\t\tconst session = visible[i];\n\t\t\t\tconst isSelected = this.selectedIndex === i + 1;\n\t\t\t\tconst title = sessionTitle(session);\n\t\t\t\tconst meta = muted(\n\t\t\t\t\t`${relativeTime(session.modified.toISOString())} · ${session.messageCount} msgs`,\n\t\t\t\t);\n\t\t\t\tconst arrow = isSelected ? accent(\"▸ \") : \" \";\n\t\t\t\tconst titleStyled = isSelected ? theme.bold(accent(title)) : title;\n\t\t\t\tconvLines.push(`${arrow}${titleStyled} ${meta}`);\n\t\t\t}\n\t\t\tif (this.filtered.length > maxVisible) {\n\t\t\t\tconvLines.push(dim(`… y ${this.filtered.length - maxVisible} más`));\n\t\t\t}\n\t\t}\n\t\tconvLines.push(\"\");\n\t\tlines.push(...box(convLines, boxW, { title: \" Conversaciones \" }).map((l) => center(l)));\n\t\tlines.push(\"\");\n\n\t\t// Search + hints\n\t\tlines.push(center(accent(\"🔎\") + dim(` Buscar: ${this.query}${this.searchInput.focused ? \"▍\" : \"\"}`)));\n\t\tlines.push(\"\");\n\t\tconst hints = [\n\t\t\t\"↑/↓ navegar\",\n\t\t\t\"Enter seleccionar\",\n\t\t\t\"n nueva\",\n\t\t\tthis.updateAvailable ? \"u actualizar\" : null,\n\t\t\t\"escribir para buscar\",\n\t\t\t\"q salir\",\n\t\t].filter((h): h is string => h !== null);\n\t\tlines.push(\n\t\t\tborder(\"─\".repeat(Math.min(boxW - 2, width - 4))),\n\t\t);\n\t\tlines.push(center(muted(hints.join(\" · \"))));\n\t\treturn this.finishRender(lines, width);\n\t}\n\n\t/** Vertical centering + truncation of every rendered line. */\n\tprivate finishRender(lines: string[], width: number): string[] {\n\t\tconst rows = process.stdout.rows ?? 24;\n\t\tconst contentHeight = lines.length;\n\t\tconst topPad = Math.min(3, Math.max(0, Math.floor((rows - contentHeight) / 3)));\n\t\treturn [...Array<string>(topPad).fill(\"\"), ...lines.map((line) => truncateToWidth(line, width))];\n\t}\n\n\tprivate defaultModelLabel(): string {\n\t\treturn this.modelLabel ?? \"no configurado (/model)\";\n\t}\n\n\tprivate cwdLabel(): string {\n\t\treturn this.cwdLabelValue ?? process.cwd();\n\t}\n\n\tprivate memoryLabel(): string {\n\t\treturn this.memoryEnabled ? \"activada\" : \"desactivada\";\n\t}\n}\n"]}
1
+ {"version":3,"file":"home-screen.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/home-screen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAwD,MAAM,wBAAwB,CAAC;AACzH,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAKzF,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC;AAEzF,KAAK,cAAc,GAAG,CAAC,UAAU,CAAC,EAAE,mBAAmB,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;AAwDnF;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,SAAU,YAAW,SAAS;IACtE,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAwB;IAExC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,kEAAkE;IAC3D,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IAEhC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAExC;IAED,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE/B;IAED,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEvC;IAED,YAAY,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAMxD;IAGD,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IAEK,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAW5B;IAED,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,SAAS;YAQH,WAAW;IAczB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkD9B;IAED,UAAU,IAAI,IAAI,CAAG;IAErB,gBAAgB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAErC;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA2H9B;IAED,8DAA8D;IAC9D,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,WAAW;CAGnB","sourcesContent":["import { type Component, Container, Input, getKeybindings, truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport type { SessionInfo, SessionListProgress } from \"../../../core/session-manager.ts\";\nimport { checkForNewPiVersion } from \"../../../utils/version-check.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { filterAndSortSessions } from \"./session-selector-search.ts\";\n\nexport type HomeScreenResult = { kind: \"new\" } | { kind: \"resume\"; path: string } | null;\n\ntype SessionsLoader = (onProgress?: SessionListProgress) => Promise<SessionInfo[]>;\n\nconst ASCII_LOGO = [\n\t\" █████╗ ██████╗ █████╗\",\n\t\" ██╔══██╗██╔══██╗██╔══██╗\",\n\t\" ███████║██║ ██║███████║\",\n\t\" ██╔══██║██║ ██║██╔══██║\",\n\t\" ██║ ██║██████╔╝██║ ██║\",\n\t\" ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝\",\n].join(\"\\n\");\n\n/** Vertical teal-to-gray gradient for the ASCII logo. */\nconst LOGO_GRADIENT = [\"accent\", \"accent\", \"borderAccent\", \"border\", \"borderMuted\", \"muted\"] as const;\n\n/** Draw a rounded box around centered content with an optional title. */\nfunction box(\n\tcontentLines: string[],\n\twidth: number,\n\toptions: { title?: string; color?: (str: string) => string } = {},\n): string[] {\n\tconst color = options.color ?? ((str: string) => theme.fg(\"border\", str));\n\tconst innerWidth = Math.max(10, width - 4);\n\tconst top =\n\t\toptions.title !== undefined\n\t\t\t? color(`╭─ ${options.title} `) + \"─\".repeat(Math.max(1, innerWidth - options.title.length - 2)) + color(\"─╮\")\n\t\t\t: color(`╭${\"─\".repeat(innerWidth)}╮`);\n\tconst bottom = color(`╰${\"─\".repeat(innerWidth)}╯`);\n\tconst pad = (line: string) => {\n\t\tconst visible = visibleWidth(line);\n\t\tconst left = Math.max(0, Math.floor((innerWidth - visible) / 2));\n\t\tconst right = Math.max(0, innerWidth - visible - left);\n\t\treturn color(\"│ \") + \" \".repeat(left) + line + \" \".repeat(right) + color(\" │\");\n\t};\n\treturn [top, ...contentLines.map(pad), bottom];\n}\n\nfunction sessionTitle(session: SessionInfo): string {\n\tif (session.name) return session.name;\n\tconst first = (session.firstMessage ?? \"\").replace(/\\s+/g, \" \").trim();\n\tif (first.length > 0) return first.length > 60 ? `${first.slice(0, 60)}…` : first;\n\treturn \"Conversation\";\n}\n\nfunction relativeTime(iso: string): string {\n\tconst diffMs = Date.now() - new Date(iso).getTime();\n\tconst mins = Math.floor(diffMs / 60000);\n\tif (mins < 1) return \"now\";\n\tif (mins < 60) return `${mins}m`;\n\tconst hours = Math.floor(mins / 60);\n\tif (hours < 24) return `${hours}h`;\n\tconst days = Math.floor(hours / 24);\n\tif (days < 7) return `${days}d`;\n\tif (days < 30) return `${Math.floor(days / 7)}w`;\n\treturn `${Math.floor(days / 30)}mo`;\n}\n\n/**\n * Central welcome flow (opencode style) shown when the CLI starts:\n * 1) entry screen: \"Enter as guest\" (login is disabled for now)\n * 2) home screen: welcome banner, update notice, recent conversations and\n * a \"New conversation\" action.\n */\nexport class HomeScreenComponent extends Container implements Component {\n\tprivate phase: \"login\" | \"home\" = \"login\";\n\tprivate sessions: SessionInfo[] = [];\n\tprivate filtered: SessionInfo[] = [];\n\tprivate selectedIndex = 0; // 0 = \"New conversation\", then sessions\n\tprivate query = \"\";\n\tprivate loading = false;\n\tprivate updateAvailable: string | null = null;\n\tprivate updateChecked = false;\n\tprivate searchInput: Input;\n\tprivate loadSessions: SessionsLoader;\n\tprivate version: string;\n\tprivate modelLabel: string | null = null;\n\tprivate cwdLabelValue: string | null = null;\n\tprivate memoryEnabled = true;\n\tprivate _focused = false;\n\tprivate requestRenderFn: () => void = () => {};\n\n\tpublic onNew?: () => void;\n\tpublic onResume?: (path: string) => void;\n\tpublic onExit?: () => void;\n\tpublic onUpdate?: () => void;\n\t/** Fired when the entry screen transitions to the home screen. */\n\tpublic onEnterHome?: () => void;\n\n\tsetModelLabel(label: string | null): void {\n\t\tthis.modelLabel = label;\n\t}\n\n\tsetCwdLabel(label: string): void {\n\t\tthis.cwdLabelValue = label;\n\t}\n\n\tsetMemoryEnabled(enabled: boolean): void {\n\t\tthis.memoryEnabled = enabled;\n\t}\n\n\tconstructor(loadSessions: SessionsLoader, version: string) {\n\t\tsuper();\n\t\tthis.loadSessions = loadSessions;\n\t\tthis.version = version;\n\t\tthis.searchInput = new Input();\n\t\tthis.searchInput.onSubmit = () => this.confirmSelection();\n\t}\n\n\t// Focusable\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tasync reload(): Promise<void> {\n\t\tthis.loading = true;\n\t\tthis.requestRenderFn();\n\t\ttry {\n\t\t\tthis.sessions = await this.loadSessions();\n\t\t} catch {\n\t\t\tthis.sessions = [];\n\t\t}\n\t\tthis.loading = false;\n\t\tthis.applyFilter();\n\t\tthis.requestRenderFn();\n\t}\n\n\tprivate applyFilter(): void {\n\t\tconst q = this.query.trim();\n\t\tthis.filtered = q\n\t\t\t? filterAndSortSessions(this.sessions, q, \"recent\", \"all\")\n\t\t\t: [...this.sessions].sort((a, b) => b.modified.getTime() - a.modified.getTime());\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.filtered.length);\n\t}\n\n\tprivate confirmSelection(): void {\n\t\tif (this.phase === \"login\") {\n\t\t\tthis.enterHome();\n\t\t\treturn;\n\t\t}\n\t\tif (this.selectedIndex === 0) {\n\t\t\tthis.onNew?.();\n\t\t} else {\n\t\t\tconst session = this.filtered[this.selectedIndex - 1];\n\t\t\tif (session) this.onResume?.(session.path);\n\t\t}\n\t}\n\n\tprivate enterHome(): void {\n\t\tthis.phase = \"home\";\n\t\tthis.selectedIndex = 0;\n\t\tthis.onEnterHome?.();\n\t\tvoid this.reload();\n\t\tvoid this.checkUpdate();\n\t}\n\n\tprivate async checkUpdate(): Promise<void> {\n\t\tif (this.updateChecked) return;\n\t\tthis.updateChecked = true;\n\t\ttry {\n\t\t\tconst release = await checkForNewPiVersion(this.version);\n\t\t\tif (release) {\n\t\t\t\tthis.updateAvailable = release.version;\n\t\t\t\tthis.requestRenderFn();\n\t\t\t}\n\t\t} catch {\n\t\t\t// Offline or unreachable — ignore silently.\n\t\t}\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (this.phase === \"login\") {\n\t\t\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\r\" || data === \"\\n\") {\n\t\t\t\tthis.enterHome();\n\t\t\t} else if (kb.matches(data, \"tui.select.cancel\") || data === \"q\" || data === \"Q\") {\n\t\t\t\tthis.onExit?.();\n\t\t\t} else if (kb.matches(data, \"tui.select.down\")) {\n\t\t\t\t// Only one actionable option on the login screen; ignore.\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.requestRenderFn();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tthis.selectedIndex = Math.min(this.filtered.length, this.selectedIndex + 1);\n\t\t\tthis.requestRenderFn();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\r\" || data === \"\\n\") {\n\t\t\tthis.confirmSelection();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onExit?.();\n\t\t\treturn;\n\t\t}\n\t\tif (data === \"n\" || data === \"N\") {\n\t\t\tthis.onNew?.();\n\t\t\treturn;\n\t\t}\n\t\tif (data === \"u\" || data === \"U\") {\n\t\t\tif (this.updateAvailable) {\n\t\t\t\tthis.onUpdate?.();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (data === \"q\" || data === \"Q\") {\n\t\t\tthis.onExit?.();\n\t\t\treturn;\n\t\t}\n\t\t// Anything else goes to the search input (filters sessions)\n\t\tthis.searchInput.handleInput(data);\n\t\tthis.query = this.searchInput.getValue();\n\t\tthis.applyFilter();\n\t\tthis.requestRenderFn();\n\t}\n\n\tinvalidate(): void {}\n\n\tsetRequestRender(fn: () => void): void {\n\t\tthis.requestRenderFn = fn;\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst center = (text: string) => {\n\t\t\tconst pad = Math.max(0, Math.floor((width - visibleWidth(text)) / 2));\n\t\t\treturn \" \".repeat(pad) + text;\n\t\t};\n\t\tconst dim = (t: string) => theme.fg(\"dim\", t);\n\t\tconst muted = (t: string) => theme.fg(\"muted\", t);\n\t\tconst accent = (t: string) => theme.fg(\"accent\", t);\n\t\tconst border = (t: string) => theme.fg(\"border\", t);\n\t\tconst success = (t: string) => theme.fg(\"success\", t);\n\t\tconst warning = (t: string) => theme.fg(\"warning\", t);\n\n\t\t// Gradient logo (teal -> gray)\n\t\tconst logoLines = ASCII_LOGO.split(\"\\n\").map((line, i) =>\n\t\t\ttheme.fg(LOGO_GRADIENT[Math.min(i, LOGO_GRADIENT.length - 1)], line),\n\t\t);\n\t\tconst tagline =\n\t\t\taccent(\"Ada\") + dim(\" · coding agent · HOILAB TECH\") + muted(` v${this.version}`);\n\n\t\tlines.push(\"\");\n\n\t\tif (this.phase === \"login\") {\n\t\t\t// ---- Entry screen -------------------------------------------\n\t\t\tconst boxW = Math.min(56, width - 4);\n\t\t\tconst boxLines = box(\n\t\t\t\t[\n\t\t\t\t\t\"\",\n\t\t\t\t\t...logoLines,\n\t\t\t\t\ttagline,\n\t\t\t\t\t\"\",\n\t\t\t\t\tdim(\"Bienvenido a Ada — el agente de codificación de HOILAB TECH\"),\n\t\t\t\t\t\"\",\n\t\t\t\t\taccent(\"▸ \") + theme.bold(\"Entrar como invitado\"),\n\t\t\t\t\tmuted(\" Loguearme\") + dim(\" (próximamente)\"),\n\t\t\t\t\t\"\",\n\t\t\t\t],\n\t\t\t\tboxW,\n\t\t\t\t{ title: \" ✦ HOILAB TECH ✦ \" },\n\t\t\t);\n\t\t\tlines.push(...boxLines.map((l) => center(l)));\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(center(success(\"●\") + dim(\" En línea · sin conexión a cuentas\") + muted(\" · todo queda en tu máquina\")));\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\n\t\t\t\tcenter(muted([\"Enter para continuar\", \"q para salir\"].join(\" · \"))),\n\t\t\t);\n\t\t\treturn this.finishRender(lines, width);\n\t\t}\n\n\t\t// ---- Home screen ------------------------------------------------\n\t\tconst boxW = Math.min(width - 4, 72);\n\n\t\t// Header box: logo + status\n\t\tconst statusParts = [\n\t\t\tdim(`model: ${this.defaultModelLabel()}`),\n\t\t\tdim(`cwd: ${this.cwdLabel()}`),\n\t\t\tdim(`memoria: ${this.memoryLabel()}`),\n\t\t\t\"\",\n\t\t];\n\t\tif (this.updateAvailable) {\n\t\t\tstatusParts.push(\n\t\t\t\twarning(\n\t\t\t\t\t`⚠ Nueva versión disponible: v${this.updateAvailable} ` +\n\t\t\t\t\t\taccent(\"[u] actualizar\") +\n\t\t\t\t\t\tdim(\" · q para ignorar\"),\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (this.updateChecked) {\n\t\t\tstatusParts.push(success(\"✓ Sistema actualizado\"));\n\t\t}\n\t\tlines.push(...box([\"\", ...logoLines, tagline, \"\", ...statusParts], boxW, { title: \" ✦ HOILAB TECH ✦ \" }).map((l) => center(l)));\n\t\tlines.push(\"\");\n\n\t\t// Conversations box\n\t\tconst convLines: string[] = [\"\"];\n\t\tconst isNew = this.selectedIndex === 0;\n\t\tconvLines.push(\n\t\t\t`${isNew ? accent(\"▸ \") : \" \"}${accent(\"✦\")} ${isNew ? theme.bold(\"Nueva conversación\") : \"Nueva conversación\"}`,\n\t\t);\n\t\tconvLines.push(\"\");\n\n\t\tif (this.loading) {\n\t\t\tconvLines.push(dim(\"Cargando conversaciones…\"));\n\t\t} else if (this.filtered.length === 0) {\n\t\t\tconvLines.push(\n\t\t\t\tmuted(\n\t\t\t\t\tthis.query\n\t\t\t\t\t\t? \"No hay conversaciones que coincidan con tu búsqueda\"\n\t\t\t\t\t\t: \"Todavía no hay conversaciones anteriores\",\n\t\t\t\t),\n\t\t\t);\n\t\t} else {\n\t\t\tconst maxVisible = Math.max(1, Math.min(12, Math.floor((width * 2) / 3)));\n\t\t\tconst visible = this.filtered.slice(0, maxVisible);\n\t\t\tfor (let i = 0; i < visible.length; i++) {\n\t\t\t\tconst session = visible[i];\n\t\t\t\tconst isSelected = this.selectedIndex === i + 1;\n\t\t\t\tconst title = sessionTitle(session);\n\t\t\t\tconst meta = muted(\n\t\t\t\t\t`${relativeTime(session.modified.toISOString())} · ${session.messageCount} msgs`,\n\t\t\t\t);\n\t\t\t\tconst arrow = isSelected ? accent(\"▸ \") : \" \";\n\t\t\t\tconst titleStyled = isSelected ? theme.bold(accent(title)) : title;\n\t\t\t\tconvLines.push(`${arrow}${titleStyled} ${meta}`);\n\t\t\t}\n\t\t\tif (this.filtered.length > maxVisible) {\n\t\t\t\tconvLines.push(dim(`… y ${this.filtered.length - maxVisible} más`));\n\t\t\t}\n\t\t}\n\t\tconvLines.push(\"\");\n\t\tlines.push(...box(convLines, boxW, { title: \" Conversaciones \" }).map((l) => center(l)));\n\t\tlines.push(\"\");\n\n\t\tconst hints = [\n\t\t\t\"↑/↓ navegar\",\n\t\t\t\"Enter seleccionar\",\n\t\t\t\"n nueva\",\n\t\t\tthis.updateAvailable ? \"u actualizar\" : null,\n\t\t\t\"q salir\",\n\t\t].filter((h): h is string => h !== null);\n\t\tlines.push(center(muted(hints.join(\" · \"))));\n\t\treturn this.finishRender(lines, width);\n\t}\n\n\t/** Vertical centering + truncation of every rendered line. */\n\tprivate finishRender(lines: string[], width: number): string[] {\n\t\tconst rows = process.stdout.rows ?? 24;\n\t\tconst contentHeight = lines.length;\n\t\tconst topPad = Math.min(3, Math.max(0, Math.floor((rows - contentHeight) / 3)));\n\t\treturn [...Array<string>(topPad).fill(\"\"), ...lines.map((line) => truncateToWidth(line, width))];\n\t}\n\n\tprivate defaultModelLabel(): string {\n\t\treturn this.modelLabel ?? \"no configurado (/model)\";\n\t}\n\n\tprivate cwdLabel(): string {\n\t\treturn this.cwdLabelValue ?? process.cwd();\n\t}\n\n\tprivate memoryLabel(): string {\n\t\treturn this.memoryEnabled ? \"activada\" : \"desactivada\";\n\t}\n}\n"]}
@@ -278,7 +278,6 @@ export class HomeScreenComponent extends Container {
278
278
  const convLines = [""];
279
279
  const isNew = this.selectedIndex === 0;
280
280
  convLines.push(`${isNew ? accent("▸ ") : " "}${accent("✦")} ${isNew ? theme.bold("Nueva conversación") : "Nueva conversación"}`);
281
- convLines.push(dim("─".repeat(Math.max(4, boxW - 6))));
282
281
  convLines.push("");
283
282
  if (this.loading) {
284
283
  convLines.push(dim("Cargando conversaciones…"));
@@ -307,18 +306,13 @@ export class HomeScreenComponent extends Container {
307
306
  convLines.push("");
308
307
  lines.push(...box(convLines, boxW, { title: " Conversaciones " }).map((l) => center(l)));
309
308
  lines.push("");
310
- // Search + hints
311
- lines.push(center(accent("🔎") + dim(` Buscar: ${this.query}${this.searchInput.focused ? "▍" : ""}`)));
312
- lines.push("");
313
309
  const hints = [
314
310
  "↑/↓ navegar",
315
311
  "Enter seleccionar",
316
312
  "n nueva",
317
313
  this.updateAvailable ? "u actualizar" : null,
318
- "escribir para buscar",
319
314
  "q salir",
320
315
  ].filter((h) => h !== null);
321
- lines.push(border("─".repeat(Math.min(boxW - 2, width - 4))));
322
316
  lines.push(center(muted(hints.join(" · "))));
323
317
  return this.finishRender(lines, width);
324
318
  }
@@ -1 +1 @@
1
- {"version":3,"file":"home-screen.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/home-screen.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, Container, Input, getKeybindings, truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport type { SessionInfo, SessionListProgress } from \"../../../core/session-manager.ts\";\nimport { checkForNewPiVersion } from \"../../../utils/version-check.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { filterAndSortSessions } from \"./session-selector-search.ts\";\n\nexport type HomeScreenResult = { kind: \"new\" } | { kind: \"resume\"; path: string } | null;\n\ntype SessionsLoader = (onProgress?: SessionListProgress) => Promise<SessionInfo[]>;\n\nconst ASCII_LOGO = [\n\t\" █████╗ ██████╗ █████╗\",\n\t\" ██╔══██╗██╔══██╗██╔══██╗\",\n\t\" ███████║██║ ██║███████║\",\n\t\" ██╔══██║██║ ██║██╔══██║\",\n\t\" ██║ ██║██████╔╝██║ ██║\",\n\t\" ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝\",\n].join(\"\\n\");\n\n/** Vertical teal-to-gray gradient for the ASCII logo. */\nconst LOGO_GRADIENT = [\"accent\", \"accent\", \"borderAccent\", \"border\", \"borderMuted\", \"muted\"] as const;\n\n/** Draw a rounded box around centered content with an optional title. */\nfunction box(\n\tcontentLines: string[],\n\twidth: number,\n\toptions: { title?: string; color?: (str: string) => string } = {},\n): string[] {\n\tconst color = options.color ?? ((str: string) => theme.fg(\"border\", str));\n\tconst innerWidth = Math.max(10, width - 4);\n\tconst top =\n\t\toptions.title !== undefined\n\t\t\t? color(`╭─ ${options.title} `) + \"─\".repeat(Math.max(1, innerWidth - options.title.length - 2)) + color(\"─╮\")\n\t\t\t: color(`╭${\"─\".repeat(innerWidth)}╮`);\n\tconst bottom = color(`╰${\"─\".repeat(innerWidth)}╯`);\n\tconst pad = (line: string) => {\n\t\tconst visible = visibleWidth(line);\n\t\tconst left = Math.max(0, Math.floor((innerWidth - visible) / 2));\n\t\tconst right = Math.max(0, innerWidth - visible - left);\n\t\treturn color(\"│ \") + \" \".repeat(left) + line + \" \".repeat(right) + color(\" │\");\n\t};\n\treturn [top, ...contentLines.map(pad), bottom];\n}\n\nfunction sessionTitle(session: SessionInfo): string {\n\tif (session.name) return session.name;\n\tconst first = (session.firstMessage ?? \"\").replace(/\\s+/g, \" \").trim();\n\tif (first.length > 0) return first.length > 60 ? `${first.slice(0, 60)}…` : first;\n\treturn \"Conversation\";\n}\n\nfunction relativeTime(iso: string): string {\n\tconst diffMs = Date.now() - new Date(iso).getTime();\n\tconst mins = Math.floor(diffMs / 60000);\n\tif (mins < 1) return \"now\";\n\tif (mins < 60) return `${mins}m`;\n\tconst hours = Math.floor(mins / 60);\n\tif (hours < 24) return `${hours}h`;\n\tconst days = Math.floor(hours / 24);\n\tif (days < 7) return `${days}d`;\n\tif (days < 30) return `${Math.floor(days / 7)}w`;\n\treturn `${Math.floor(days / 30)}mo`;\n}\n\n/**\n * Central welcome flow (opencode style) shown when the CLI starts:\n * 1) entry screen: \"Enter as guest\" (login is disabled for now)\n * 2) home screen: welcome banner, update notice, recent conversations and\n * a \"New conversation\" action.\n */\nexport class HomeScreenComponent extends Container implements Component {\n\tprivate phase: \"login\" | \"home\" = \"login\";\n\tprivate sessions: SessionInfo[] = [];\n\tprivate filtered: SessionInfo[] = [];\n\tprivate selectedIndex = 0; // 0 = \"New conversation\", then sessions\n\tprivate query = \"\";\n\tprivate loading = false;\n\tprivate updateAvailable: string | null = null;\n\tprivate updateChecked = false;\n\tprivate searchInput: Input;\n\tprivate loadSessions: SessionsLoader;\n\tprivate version: string;\n\tprivate modelLabel: string | null = null;\n\tprivate cwdLabelValue: string | null = null;\n\tprivate memoryEnabled = true;\n\tprivate _focused = false;\n\tprivate requestRenderFn: () => void = () => {};\n\n\tpublic onNew?: () => void;\n\tpublic onResume?: (path: string) => void;\n\tpublic onExit?: () => void;\n\tpublic onUpdate?: () => void;\n\t/** Fired when the entry screen transitions to the home screen. */\n\tpublic onEnterHome?: () => void;\n\n\tsetModelLabel(label: string | null): void {\n\t\tthis.modelLabel = label;\n\t}\n\n\tsetCwdLabel(label: string): void {\n\t\tthis.cwdLabelValue = label;\n\t}\n\n\tsetMemoryEnabled(enabled: boolean): void {\n\t\tthis.memoryEnabled = enabled;\n\t}\n\n\tconstructor(loadSessions: SessionsLoader, version: string) {\n\t\tsuper();\n\t\tthis.loadSessions = loadSessions;\n\t\tthis.version = version;\n\t\tthis.searchInput = new Input();\n\t\tthis.searchInput.onSubmit = () => this.confirmSelection();\n\t}\n\n\t// Focusable\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tasync reload(): Promise<void> {\n\t\tthis.loading = true;\n\t\tthis.requestRenderFn();\n\t\ttry {\n\t\t\tthis.sessions = await this.loadSessions();\n\t\t} catch {\n\t\t\tthis.sessions = [];\n\t\t}\n\t\tthis.loading = false;\n\t\tthis.applyFilter();\n\t\tthis.requestRenderFn();\n\t}\n\n\tprivate applyFilter(): void {\n\t\tconst q = this.query.trim();\n\t\tthis.filtered = q\n\t\t\t? filterAndSortSessions(this.sessions, q, \"recent\", \"all\")\n\t\t\t: [...this.sessions].sort((a, b) => b.modified.getTime() - a.modified.getTime());\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.filtered.length);\n\t}\n\n\tprivate confirmSelection(): void {\n\t\tif (this.phase === \"login\") {\n\t\t\tthis.enterHome();\n\t\t\treturn;\n\t\t}\n\t\tif (this.selectedIndex === 0) {\n\t\t\tthis.onNew?.();\n\t\t} else {\n\t\t\tconst session = this.filtered[this.selectedIndex - 1];\n\t\t\tif (session) this.onResume?.(session.path);\n\t\t}\n\t}\n\n\tprivate enterHome(): void {\n\t\tthis.phase = \"home\";\n\t\tthis.selectedIndex = 0;\n\t\tthis.onEnterHome?.();\n\t\tvoid this.reload();\n\t\tvoid this.checkUpdate();\n\t}\n\n\tprivate async checkUpdate(): Promise<void> {\n\t\tif (this.updateChecked) return;\n\t\tthis.updateChecked = true;\n\t\ttry {\n\t\t\tconst release = await checkForNewPiVersion(this.version);\n\t\t\tif (release) {\n\t\t\t\tthis.updateAvailable = release.version;\n\t\t\t\tthis.requestRenderFn();\n\t\t\t}\n\t\t} catch {\n\t\t\t// Offline or unreachable — ignore silently.\n\t\t}\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (this.phase === \"login\") {\n\t\t\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\r\" || data === \"\\n\") {\n\t\t\t\tthis.enterHome();\n\t\t\t} else if (kb.matches(data, \"tui.select.cancel\") || data === \"q\" || data === \"Q\") {\n\t\t\t\tthis.onExit?.();\n\t\t\t} else if (kb.matches(data, \"tui.select.down\")) {\n\t\t\t\t// Only one actionable option on the login screen; ignore.\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.requestRenderFn();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tthis.selectedIndex = Math.min(this.filtered.length, this.selectedIndex + 1);\n\t\t\tthis.requestRenderFn();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\r\" || data === \"\\n\") {\n\t\t\tthis.confirmSelection();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onExit?.();\n\t\t\treturn;\n\t\t}\n\t\tif (data === \"n\" || data === \"N\") {\n\t\t\tthis.onNew?.();\n\t\t\treturn;\n\t\t}\n\t\tif (data === \"u\" || data === \"U\") {\n\t\t\tif (this.updateAvailable) {\n\t\t\t\tthis.onUpdate?.();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (data === \"q\" || data === \"Q\") {\n\t\t\tthis.onExit?.();\n\t\t\treturn;\n\t\t}\n\t\t// Anything else goes to the search input (filters sessions)\n\t\tthis.searchInput.handleInput(data);\n\t\tthis.query = this.searchInput.getValue();\n\t\tthis.applyFilter();\n\t\tthis.requestRenderFn();\n\t}\n\n\tinvalidate(): void {}\n\n\tsetRequestRender(fn: () => void): void {\n\t\tthis.requestRenderFn = fn;\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst center = (text: string) => {\n\t\t\tconst pad = Math.max(0, Math.floor((width - visibleWidth(text)) / 2));\n\t\t\treturn \" \".repeat(pad) + text;\n\t\t};\n\t\tconst dim = (t: string) => theme.fg(\"dim\", t);\n\t\tconst muted = (t: string) => theme.fg(\"muted\", t);\n\t\tconst accent = (t: string) => theme.fg(\"accent\", t);\n\t\tconst border = (t: string) => theme.fg(\"border\", t);\n\t\tconst success = (t: string) => theme.fg(\"success\", t);\n\t\tconst warning = (t: string) => theme.fg(\"warning\", t);\n\n\t\t// Gradient logo (teal -> gray)\n\t\tconst logoLines = ASCII_LOGO.split(\"\\n\").map((line, i) =>\n\t\t\ttheme.fg(LOGO_GRADIENT[Math.min(i, LOGO_GRADIENT.length - 1)], line),\n\t\t);\n\t\tconst tagline =\n\t\t\taccent(\"Ada\") + dim(\" · coding agent · HOILAB TECH\") + muted(` v${this.version}`);\n\n\t\tlines.push(\"\");\n\n\t\tif (this.phase === \"login\") {\n\t\t\t// ---- Entry screen -------------------------------------------\n\t\t\tconst boxW = Math.min(56, width - 4);\n\t\t\tconst boxLines = box(\n\t\t\t\t[\n\t\t\t\t\t\"\",\n\t\t\t\t\t...logoLines,\n\t\t\t\t\ttagline,\n\t\t\t\t\t\"\",\n\t\t\t\t\tdim(\"Bienvenido a Ada — el agente de codificación de HOILAB TECH\"),\n\t\t\t\t\t\"\",\n\t\t\t\t\taccent(\"▸ \") + theme.bold(\"Entrar como invitado\"),\n\t\t\t\t\tmuted(\" Loguearme\") + dim(\" (próximamente)\"),\n\t\t\t\t\t\"\",\n\t\t\t\t],\n\t\t\t\tboxW,\n\t\t\t\t{ title: \" ✦ HOILAB TECH ✦ \" },\n\t\t\t);\n\t\t\tlines.push(...boxLines.map((l) => center(l)));\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(center(success(\"●\") + dim(\" En línea · sin conexión a cuentas\") + muted(\" · todo queda en tu máquina\")));\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\n\t\t\t\tcenter(muted([\"Enter para continuar\", \"q para salir\"].join(\" · \"))),\n\t\t\t);\n\t\t\treturn this.finishRender(lines, width);\n\t\t}\n\n\t\t// ---- Home screen ------------------------------------------------\n\t\tconst boxW = Math.min(width - 4, 72);\n\n\t\t// Header box: logo + status\n\t\tconst statusParts = [\n\t\t\tdim(`model: ${this.defaultModelLabel()}`),\n\t\t\tdim(`cwd: ${this.cwdLabel()}`),\n\t\t\tdim(`memoria: ${this.memoryLabel()}`),\n\t\t\t\"\",\n\t\t];\n\t\tif (this.updateAvailable) {\n\t\t\tstatusParts.push(\n\t\t\t\twarning(\n\t\t\t\t\t`⚠ Nueva versión disponible: v${this.updateAvailable} ` +\n\t\t\t\t\t\taccent(\"[u] actualizar\") +\n\t\t\t\t\t\tdim(\" · q para ignorar\"),\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (this.updateChecked) {\n\t\t\tstatusParts.push(success(\"✓ Sistema actualizado\"));\n\t\t}\n\t\tlines.push(...box([\"\", ...logoLines, tagline, \"\", ...statusParts], boxW, { title: \" ✦ HOILAB TECH ✦ \" }).map((l) => center(l)));\n\t\tlines.push(\"\");\n\n\t\t// Conversations box\n\t\tconst convLines: string[] = [\"\"];\n\t\tconst isNew = this.selectedIndex === 0;\n\t\tconvLines.push(\n\t\t\t`${isNew ? accent(\"▸ \") : \" \"}${accent(\"✦\")} ${isNew ? theme.bold(\"Nueva conversación\") : \"Nueva conversación\"}`,\n\t\t);\n\t\tconvLines.push(dim(\"─\".repeat(Math.max(4, boxW - 6))));\n\t\tconvLines.push(\"\");\n\n\t\tif (this.loading) {\n\t\t\tconvLines.push(dim(\"Cargando conversaciones…\"));\n\t\t} else if (this.filtered.length === 0) {\n\t\t\tconvLines.push(\n\t\t\t\tmuted(\n\t\t\t\t\tthis.query\n\t\t\t\t\t\t? \"No hay conversaciones que coincidan con tu búsqueda\"\n\t\t\t\t\t\t: \"Todavía no hay conversaciones anteriores\",\n\t\t\t\t),\n\t\t\t);\n\t\t} else {\n\t\t\tconst maxVisible = Math.max(1, Math.min(12, Math.floor((width * 2) / 3)));\n\t\t\tconst visible = this.filtered.slice(0, maxVisible);\n\t\t\tfor (let i = 0; i < visible.length; i++) {\n\t\t\t\tconst session = visible[i];\n\t\t\t\tconst isSelected = this.selectedIndex === i + 1;\n\t\t\t\tconst title = sessionTitle(session);\n\t\t\t\tconst meta = muted(\n\t\t\t\t\t`${relativeTime(session.modified.toISOString())} · ${session.messageCount} msgs`,\n\t\t\t\t);\n\t\t\t\tconst arrow = isSelected ? accent(\"▸ \") : \" \";\n\t\t\t\tconst titleStyled = isSelected ? theme.bold(accent(title)) : title;\n\t\t\t\tconvLines.push(`${arrow}${titleStyled} ${meta}`);\n\t\t\t}\n\t\t\tif (this.filtered.length > maxVisible) {\n\t\t\t\tconvLines.push(dim(`… y ${this.filtered.length - maxVisible} más`));\n\t\t\t}\n\t\t}\n\t\tconvLines.push(\"\");\n\t\tlines.push(...box(convLines, boxW, { title: \" Conversaciones \" }).map((l) => center(l)));\n\t\tlines.push(\"\");\n\n\t\t// Search + hints\n\t\tlines.push(center(accent(\"🔎\") + dim(` Buscar: ${this.query}${this.searchInput.focused ? \"▍\" : \"\"}`)));\n\t\tlines.push(\"\");\n\t\tconst hints = [\n\t\t\t\"↑/↓ navegar\",\n\t\t\t\"Enter seleccionar\",\n\t\t\t\"n nueva\",\n\t\t\tthis.updateAvailable ? \"u actualizar\" : null,\n\t\t\t\"escribir para buscar\",\n\t\t\t\"q salir\",\n\t\t].filter((h): h is string => h !== null);\n\t\tlines.push(\n\t\t\tborder(\"─\".repeat(Math.min(boxW - 2, width - 4))),\n\t\t);\n\t\tlines.push(center(muted(hints.join(\" · \"))));\n\t\treturn this.finishRender(lines, width);\n\t}\n\n\t/** Vertical centering + truncation of every rendered line. */\n\tprivate finishRender(lines: string[], width: number): string[] {\n\t\tconst rows = process.stdout.rows ?? 24;\n\t\tconst contentHeight = lines.length;\n\t\tconst topPad = Math.min(3, Math.max(0, Math.floor((rows - contentHeight) / 3)));\n\t\treturn [...Array<string>(topPad).fill(\"\"), ...lines.map((line) => truncateToWidth(line, width))];\n\t}\n\n\tprivate defaultModelLabel(): string {\n\t\treturn this.modelLabel ?? \"no configurado (/model)\";\n\t}\n\n\tprivate cwdLabel(): string {\n\t\treturn this.cwdLabelValue ?? process.cwd();\n\t}\n\n\tprivate memoryLabel(): string {\n\t\treturn this.memoryEnabled ? \"activada\" : \"desactivada\";\n\t}\n}\n"]}
1
+ {"version":3,"file":"home-screen.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/home-screen.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, Container, Input, getKeybindings, truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport type { SessionInfo, SessionListProgress } from \"../../../core/session-manager.ts\";\nimport { checkForNewPiVersion } from \"../../../utils/version-check.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { filterAndSortSessions } from \"./session-selector-search.ts\";\n\nexport type HomeScreenResult = { kind: \"new\" } | { kind: \"resume\"; path: string } | null;\n\ntype SessionsLoader = (onProgress?: SessionListProgress) => Promise<SessionInfo[]>;\n\nconst ASCII_LOGO = [\n\t\" █████╗ ██████╗ █████╗\",\n\t\" ██╔══██╗██╔══██╗██╔══██╗\",\n\t\" ███████║██║ ██║███████║\",\n\t\" ██╔══██║██║ ██║██╔══██║\",\n\t\" ██║ ██║██████╔╝██║ ██║\",\n\t\" ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝\",\n].join(\"\\n\");\n\n/** Vertical teal-to-gray gradient for the ASCII logo. */\nconst LOGO_GRADIENT = [\"accent\", \"accent\", \"borderAccent\", \"border\", \"borderMuted\", \"muted\"] as const;\n\n/** Draw a rounded box around centered content with an optional title. */\nfunction box(\n\tcontentLines: string[],\n\twidth: number,\n\toptions: { title?: string; color?: (str: string) => string } = {},\n): string[] {\n\tconst color = options.color ?? ((str: string) => theme.fg(\"border\", str));\n\tconst innerWidth = Math.max(10, width - 4);\n\tconst top =\n\t\toptions.title !== undefined\n\t\t\t? color(`╭─ ${options.title} `) + \"─\".repeat(Math.max(1, innerWidth - options.title.length - 2)) + color(\"─╮\")\n\t\t\t: color(`╭${\"─\".repeat(innerWidth)}╮`);\n\tconst bottom = color(`╰${\"─\".repeat(innerWidth)}╯`);\n\tconst pad = (line: string) => {\n\t\tconst visible = visibleWidth(line);\n\t\tconst left = Math.max(0, Math.floor((innerWidth - visible) / 2));\n\t\tconst right = Math.max(0, innerWidth - visible - left);\n\t\treturn color(\"│ \") + \" \".repeat(left) + line + \" \".repeat(right) + color(\" │\");\n\t};\n\treturn [top, ...contentLines.map(pad), bottom];\n}\n\nfunction sessionTitle(session: SessionInfo): string {\n\tif (session.name) return session.name;\n\tconst first = (session.firstMessage ?? \"\").replace(/\\s+/g, \" \").trim();\n\tif (first.length > 0) return first.length > 60 ? `${first.slice(0, 60)}…` : first;\n\treturn \"Conversation\";\n}\n\nfunction relativeTime(iso: string): string {\n\tconst diffMs = Date.now() - new Date(iso).getTime();\n\tconst mins = Math.floor(diffMs / 60000);\n\tif (mins < 1) return \"now\";\n\tif (mins < 60) return `${mins}m`;\n\tconst hours = Math.floor(mins / 60);\n\tif (hours < 24) return `${hours}h`;\n\tconst days = Math.floor(hours / 24);\n\tif (days < 7) return `${days}d`;\n\tif (days < 30) return `${Math.floor(days / 7)}w`;\n\treturn `${Math.floor(days / 30)}mo`;\n}\n\n/**\n * Central welcome flow (opencode style) shown when the CLI starts:\n * 1) entry screen: \"Enter as guest\" (login is disabled for now)\n * 2) home screen: welcome banner, update notice, recent conversations and\n * a \"New conversation\" action.\n */\nexport class HomeScreenComponent extends Container implements Component {\n\tprivate phase: \"login\" | \"home\" = \"login\";\n\tprivate sessions: SessionInfo[] = [];\n\tprivate filtered: SessionInfo[] = [];\n\tprivate selectedIndex = 0; // 0 = \"New conversation\", then sessions\n\tprivate query = \"\";\n\tprivate loading = false;\n\tprivate updateAvailable: string | null = null;\n\tprivate updateChecked = false;\n\tprivate searchInput: Input;\n\tprivate loadSessions: SessionsLoader;\n\tprivate version: string;\n\tprivate modelLabel: string | null = null;\n\tprivate cwdLabelValue: string | null = null;\n\tprivate memoryEnabled = true;\n\tprivate _focused = false;\n\tprivate requestRenderFn: () => void = () => {};\n\n\tpublic onNew?: () => void;\n\tpublic onResume?: (path: string) => void;\n\tpublic onExit?: () => void;\n\tpublic onUpdate?: () => void;\n\t/** Fired when the entry screen transitions to the home screen. */\n\tpublic onEnterHome?: () => void;\n\n\tsetModelLabel(label: string | null): void {\n\t\tthis.modelLabel = label;\n\t}\n\n\tsetCwdLabel(label: string): void {\n\t\tthis.cwdLabelValue = label;\n\t}\n\n\tsetMemoryEnabled(enabled: boolean): void {\n\t\tthis.memoryEnabled = enabled;\n\t}\n\n\tconstructor(loadSessions: SessionsLoader, version: string) {\n\t\tsuper();\n\t\tthis.loadSessions = loadSessions;\n\t\tthis.version = version;\n\t\tthis.searchInput = new Input();\n\t\tthis.searchInput.onSubmit = () => this.confirmSelection();\n\t}\n\n\t// Focusable\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tasync reload(): Promise<void> {\n\t\tthis.loading = true;\n\t\tthis.requestRenderFn();\n\t\ttry {\n\t\t\tthis.sessions = await this.loadSessions();\n\t\t} catch {\n\t\t\tthis.sessions = [];\n\t\t}\n\t\tthis.loading = false;\n\t\tthis.applyFilter();\n\t\tthis.requestRenderFn();\n\t}\n\n\tprivate applyFilter(): void {\n\t\tconst q = this.query.trim();\n\t\tthis.filtered = q\n\t\t\t? filterAndSortSessions(this.sessions, q, \"recent\", \"all\")\n\t\t\t: [...this.sessions].sort((a, b) => b.modified.getTime() - a.modified.getTime());\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.filtered.length);\n\t}\n\n\tprivate confirmSelection(): void {\n\t\tif (this.phase === \"login\") {\n\t\t\tthis.enterHome();\n\t\t\treturn;\n\t\t}\n\t\tif (this.selectedIndex === 0) {\n\t\t\tthis.onNew?.();\n\t\t} else {\n\t\t\tconst session = this.filtered[this.selectedIndex - 1];\n\t\t\tif (session) this.onResume?.(session.path);\n\t\t}\n\t}\n\n\tprivate enterHome(): void {\n\t\tthis.phase = \"home\";\n\t\tthis.selectedIndex = 0;\n\t\tthis.onEnterHome?.();\n\t\tvoid this.reload();\n\t\tvoid this.checkUpdate();\n\t}\n\n\tprivate async checkUpdate(): Promise<void> {\n\t\tif (this.updateChecked) return;\n\t\tthis.updateChecked = true;\n\t\ttry {\n\t\t\tconst release = await checkForNewPiVersion(this.version);\n\t\t\tif (release) {\n\t\t\t\tthis.updateAvailable = release.version;\n\t\t\t\tthis.requestRenderFn();\n\t\t\t}\n\t\t} catch {\n\t\t\t// Offline or unreachable — ignore silently.\n\t\t}\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (this.phase === \"login\") {\n\t\t\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\r\" || data === \"\\n\") {\n\t\t\t\tthis.enterHome();\n\t\t\t} else if (kb.matches(data, \"tui.select.cancel\") || data === \"q\" || data === \"Q\") {\n\t\t\t\tthis.onExit?.();\n\t\t\t} else if (kb.matches(data, \"tui.select.down\")) {\n\t\t\t\t// Only one actionable option on the login screen; ignore.\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.requestRenderFn();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tthis.selectedIndex = Math.min(this.filtered.length, this.selectedIndex + 1);\n\t\t\tthis.requestRenderFn();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\r\" || data === \"\\n\") {\n\t\t\tthis.confirmSelection();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onExit?.();\n\t\t\treturn;\n\t\t}\n\t\tif (data === \"n\" || data === \"N\") {\n\t\t\tthis.onNew?.();\n\t\t\treturn;\n\t\t}\n\t\tif (data === \"u\" || data === \"U\") {\n\t\t\tif (this.updateAvailable) {\n\t\t\t\tthis.onUpdate?.();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (data === \"q\" || data === \"Q\") {\n\t\t\tthis.onExit?.();\n\t\t\treturn;\n\t\t}\n\t\t// Anything else goes to the search input (filters sessions)\n\t\tthis.searchInput.handleInput(data);\n\t\tthis.query = this.searchInput.getValue();\n\t\tthis.applyFilter();\n\t\tthis.requestRenderFn();\n\t}\n\n\tinvalidate(): void {}\n\n\tsetRequestRender(fn: () => void): void {\n\t\tthis.requestRenderFn = fn;\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst center = (text: string) => {\n\t\t\tconst pad = Math.max(0, Math.floor((width - visibleWidth(text)) / 2));\n\t\t\treturn \" \".repeat(pad) + text;\n\t\t};\n\t\tconst dim = (t: string) => theme.fg(\"dim\", t);\n\t\tconst muted = (t: string) => theme.fg(\"muted\", t);\n\t\tconst accent = (t: string) => theme.fg(\"accent\", t);\n\t\tconst border = (t: string) => theme.fg(\"border\", t);\n\t\tconst success = (t: string) => theme.fg(\"success\", t);\n\t\tconst warning = (t: string) => theme.fg(\"warning\", t);\n\n\t\t// Gradient logo (teal -> gray)\n\t\tconst logoLines = ASCII_LOGO.split(\"\\n\").map((line, i) =>\n\t\t\ttheme.fg(LOGO_GRADIENT[Math.min(i, LOGO_GRADIENT.length - 1)], line),\n\t\t);\n\t\tconst tagline =\n\t\t\taccent(\"Ada\") + dim(\" · coding agent · HOILAB TECH\") + muted(` v${this.version}`);\n\n\t\tlines.push(\"\");\n\n\t\tif (this.phase === \"login\") {\n\t\t\t// ---- Entry screen -------------------------------------------\n\t\t\tconst boxW = Math.min(56, width - 4);\n\t\t\tconst boxLines = box(\n\t\t\t\t[\n\t\t\t\t\t\"\",\n\t\t\t\t\t...logoLines,\n\t\t\t\t\ttagline,\n\t\t\t\t\t\"\",\n\t\t\t\t\tdim(\"Bienvenido a Ada — el agente de codificación de HOILAB TECH\"),\n\t\t\t\t\t\"\",\n\t\t\t\t\taccent(\"▸ \") + theme.bold(\"Entrar como invitado\"),\n\t\t\t\t\tmuted(\" Loguearme\") + dim(\" (próximamente)\"),\n\t\t\t\t\t\"\",\n\t\t\t\t],\n\t\t\t\tboxW,\n\t\t\t\t{ title: \" ✦ HOILAB TECH ✦ \" },\n\t\t\t);\n\t\t\tlines.push(...boxLines.map((l) => center(l)));\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(center(success(\"●\") + dim(\" En línea · sin conexión a cuentas\") + muted(\" · todo queda en tu máquina\")));\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\n\t\t\t\tcenter(muted([\"Enter para continuar\", \"q para salir\"].join(\" · \"))),\n\t\t\t);\n\t\t\treturn this.finishRender(lines, width);\n\t\t}\n\n\t\t// ---- Home screen ------------------------------------------------\n\t\tconst boxW = Math.min(width - 4, 72);\n\n\t\t// Header box: logo + status\n\t\tconst statusParts = [\n\t\t\tdim(`model: ${this.defaultModelLabel()}`),\n\t\t\tdim(`cwd: ${this.cwdLabel()}`),\n\t\t\tdim(`memoria: ${this.memoryLabel()}`),\n\t\t\t\"\",\n\t\t];\n\t\tif (this.updateAvailable) {\n\t\t\tstatusParts.push(\n\t\t\t\twarning(\n\t\t\t\t\t`⚠ Nueva versión disponible: v${this.updateAvailable} ` +\n\t\t\t\t\t\taccent(\"[u] actualizar\") +\n\t\t\t\t\t\tdim(\" · q para ignorar\"),\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (this.updateChecked) {\n\t\t\tstatusParts.push(success(\"✓ Sistema actualizado\"));\n\t\t}\n\t\tlines.push(...box([\"\", ...logoLines, tagline, \"\", ...statusParts], boxW, { title: \" ✦ HOILAB TECH ✦ \" }).map((l) => center(l)));\n\t\tlines.push(\"\");\n\n\t\t// Conversations box\n\t\tconst convLines: string[] = [\"\"];\n\t\tconst isNew = this.selectedIndex === 0;\n\t\tconvLines.push(\n\t\t\t`${isNew ? accent(\"▸ \") : \" \"}${accent(\"✦\")} ${isNew ? theme.bold(\"Nueva conversación\") : \"Nueva conversación\"}`,\n\t\t);\n\t\tconvLines.push(\"\");\n\n\t\tif (this.loading) {\n\t\t\tconvLines.push(dim(\"Cargando conversaciones…\"));\n\t\t} else if (this.filtered.length === 0) {\n\t\t\tconvLines.push(\n\t\t\t\tmuted(\n\t\t\t\t\tthis.query\n\t\t\t\t\t\t? \"No hay conversaciones que coincidan con tu búsqueda\"\n\t\t\t\t\t\t: \"Todavía no hay conversaciones anteriores\",\n\t\t\t\t),\n\t\t\t);\n\t\t} else {\n\t\t\tconst maxVisible = Math.max(1, Math.min(12, Math.floor((width * 2) / 3)));\n\t\t\tconst visible = this.filtered.slice(0, maxVisible);\n\t\t\tfor (let i = 0; i < visible.length; i++) {\n\t\t\t\tconst session = visible[i];\n\t\t\t\tconst isSelected = this.selectedIndex === i + 1;\n\t\t\t\tconst title = sessionTitle(session);\n\t\t\t\tconst meta = muted(\n\t\t\t\t\t`${relativeTime(session.modified.toISOString())} · ${session.messageCount} msgs`,\n\t\t\t\t);\n\t\t\t\tconst arrow = isSelected ? accent(\"▸ \") : \" \";\n\t\t\t\tconst titleStyled = isSelected ? theme.bold(accent(title)) : title;\n\t\t\t\tconvLines.push(`${arrow}${titleStyled} ${meta}`);\n\t\t\t}\n\t\t\tif (this.filtered.length > maxVisible) {\n\t\t\t\tconvLines.push(dim(`… y ${this.filtered.length - maxVisible} más`));\n\t\t\t}\n\t\t}\n\t\tconvLines.push(\"\");\n\t\tlines.push(...box(convLines, boxW, { title: \" Conversaciones \" }).map((l) => center(l)));\n\t\tlines.push(\"\");\n\n\t\tconst hints = [\n\t\t\t\"↑/↓ navegar\",\n\t\t\t\"Enter seleccionar\",\n\t\t\t\"n nueva\",\n\t\t\tthis.updateAvailable ? \"u actualizar\" : null,\n\t\t\t\"q salir\",\n\t\t].filter((h): h is string => h !== null);\n\t\tlines.push(center(muted(hints.join(\" · \"))));\n\t\treturn this.finishRender(lines, width);\n\t}\n\n\t/** Vertical centering + truncation of every rendered line. */\n\tprivate finishRender(lines: string[], width: number): string[] {\n\t\tconst rows = process.stdout.rows ?? 24;\n\t\tconst contentHeight = lines.length;\n\t\tconst topPad = Math.min(3, Math.max(0, Math.floor((rows - contentHeight) / 3)));\n\t\treturn [...Array<string>(topPad).fill(\"\"), ...lines.map((line) => truncateToWidth(line, width))];\n\t}\n\n\tprivate defaultModelLabel(): string {\n\t\treturn this.modelLabel ?? \"no configurado (/model)\";\n\t}\n\n\tprivate cwdLabel(): string {\n\t\treturn this.cwdLabelValue ?? process.cwd();\n\t}\n\n\tprivate memoryLabel(): string {\n\t\treturn this.memoryEnabled ? \"activada\" : \"desactivada\";\n\t}\n}\n"]}
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@hoilab/ada-cli",
3
- "version": "0.84.11",
3
+ "version": "0.84.12",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@hoilab/ada-cli",
9
- "version": "0.84.11",
9
+ "version": "0.84.12",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@earendil-works/pi-agent-core": "^0.84.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hoilab/ada-cli",
3
- "version": "0.84.11",
3
+ "version": "0.84.12",
4
4
  "description": "Ada CLI - coding agent CLI (rebranded fork of pi.dev) with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {