sergio/takana
> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…
⎇ 4a2801331696245af7df3cccbbac5da68360bf98
recipes/atuq/extensions/ia/panel.js
Ñawpa willay
Pi imata llamkarqan
ch'uya
atuq §6.3: la búsqueda semántica, VERDE en la jaula — y la barra lateral tiene las dos preguntas
1"use strict";
2// La barra lateral: una caja de texto y lo que contestó el modelo local.
3//
4// `?q=…` abre el panel con la pregunta ya hecha. Es la puerta por la que entran las
5// preguntas que NO se tipean acá (y la que usa el guardián); no es superficie de
6// prueba: sin ella, «preguntarle a la IA sobre esto» tendría que reescribir la
7// pregunta a mano.
8
9function agregar(clase, texto) {
10 const d = document.createElement("div");
11 d.className = "turno " + clase;
12 d.textContent = texto;
13 document.getElementById("hilo").appendChild(d);
14 d.scrollIntoView({ block: "end" });
15 return d;
16}
17
18async function preguntar(texto) {
19 if (!texto.trim()) return;
20 agregar("yo", texto);
21 const esperando = agregar("", "pensando…");
22 const boton = document.getElementById("enviar");
23 boton.disabled = true;
24 let r;
25 try {
26 r = await browser.runtime.sendMessage({ tipo: "preguntar", texto });
27 } catch (e) {
28 r = { ok: false, error: String(e) };
29 }
30 boton.disabled = false;
31 // La causa se MUESTRA. «No pude contestar» a secas dejaría al usuario sin saber
32 // si falta el modelo, si el motor no está en la imagen o si se cayó el host.
33 if (!r || !r.ok) {
34 esperando.className = "turno error";
35 esperando.textContent = (r && r.error) || "el host no contestó";
36 return;
37 }
38 esperando.textContent = r.answer;
39}
40
41// Las páginas ya leídas (§6.3): la misma caja, otra pregunta. No se mezcla con la del
42// modelo a propósito — una INVENTA texto y la otra devuelve lo que vos leíste, y presentarlas
43// juntas haría imposible saber cuál de las dos contestó.
44async function buscarEnMisPaginas(texto) {
45 if (!texto.trim()) return;
46 agregar("yo", texto);
47 const esperando = agregar("", "buscando en lo que leíste…");
48 let r;
49 try {
50 r = await browser.runtime.sendMessage({ tipo: "archivo", texto });
51 } catch (e) {
52 r = { ok: false, error: String(e) };
53 }
54 if (!r || !r.ok) {
55 esperando.className = "turno error";
56 esperando.textContent = (r && r.error) || "el host no contestó";
57 return;
58 }
59 const m = r.matches || [];
60 if (!m.length) {
61 esperando.textContent = `no encontré nada entre tus ${r.archived} páginas`;
62 return;
63 }
64 // Se muestran EN ORDEN y sin porcentaje: el puntaje es un coseno y leerlo como
65 // «85 % de acierto» sería inventarle un significado que no tiene.
66 esperando.textContent = `de tus ${r.archived} páginas, en orden de parecido:`;
67 for (const c of m.slice(0, 8)) {
68 const d = document.createElement("div");
69 d.className = "fuente";
70 const a = document.createElement("a");
71 a.href = c.page.url;
72 a.textContent = c.page.title || c.page.url;
73 a.title = c.page.url;
74 d.appendChild(a);
75 esperando.appendChild(d);
76 }
77}
78
79document.getElementById("forma").addEventListener("submit", (ev) => {
80 ev.preventDefault();
81 const caja = document.getElementById("texto");
82 const texto = caja.value;
83 caja.value = "";
84 preguntar(texto);
85});
86
87document.getElementById("archivo").addEventListener("click", () => {
88 const caja = document.getElementById("texto");
89 const texto = caja.value;
90 caja.value = "";
91 buscarEnMisPaginas(texto);
92});
93
94// `?q=` pregunta al modelo; `?p=` busca en las páginas. Las dos son la puerta por la que
95// entran las preguntas que no se tipean acá (y las que usan los guardianes).
96const params = new URLSearchParams(location.search);
97const q = params.get("q");
98if (q) preguntar(q);
99const pag = params.get("p");
100if (pag) buscarEnMisPaginas(pag);