@supcoflow/chat 0.1.0 → 1.0.0
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.
- package/CHANGELOG.md +24 -0
- package/README.md +32 -27
- package/dist/ChatDeIntake.d.ts.map +1 -1
- package/dist/ChatDeIntake.js +28 -19
- package/dist/ChatDeIntake.js.map +1 -1
- package/dist/estado-del-widget.d.ts +9 -3
- package/dist/estado-del-widget.d.ts.map +1 -1
- package/dist/estado-del-widget.js +7 -1
- package/dist/estado-del-widget.js.map +1 -1
- package/dist/partes-visibles.d.ts +16 -0
- package/dist/partes-visibles.d.ts.map +1 -0
- package/dist/partes-visibles.js +14 -0
- package/dist/partes-visibles.js.map +1 -0
- package/package.json +4 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Changelog de @supcoflow/chat
|
|
2
|
+
|
|
3
|
+
## 1.0.0 — 2026-09-02
|
|
4
|
+
|
|
5
|
+
Para quien instala, no para quien mantiene.
|
|
6
|
+
|
|
7
|
+
- **El transporte pasa a Eve** (`useEveAgent`): sesión por conversación y stream NDJSON contra
|
|
8
|
+
`{backendUrl}/eve/v1/*`. El uso del componente no cambia: mismas tres props.
|
|
9
|
+
- **React ≥19**, igual que antes.
|
|
10
|
+
- **Nuevo requisito: Node ≥24** en el entorno de instalación y build, por `eve`.
|
|
11
|
+
- **Nueva dependencia: `eve@0.47.7`** (~47 MB instalados) y `ai` como peer que npm instala solo.
|
|
12
|
+
Deuda declarada: separar el cliente en un paquete liviano es una rebanada aparte.
|
|
13
|
+
- **`contexto` sale del README**: el prop sigue aceptado por compatibilidad de tipos pero no viaja
|
|
14
|
+
al reporte. Ya era así en 0.1.0 y el README lo prometía igual.
|
|
15
|
+
- **La CSP entra al README** (`connect-src`), y «tope por día» pasa a «ventana rodante de 24 h».
|
|
16
|
+
- El backend sigue sirviendo `POST /api/chat` para las instalaciones de 0.1.0 (1.0.0 ya no lo
|
|
17
|
+
usa: el transporte pasó a Eve). `GET /api/chat/estado` es distinto: lo sondean las DOS
|
|
18
|
+
versiones al montar el widget, y además el motor lo usa para «probar la instalación» — así
|
|
19
|
+
que no queda libre para retirar el día que 0.1.0 se dé de baja. Retirar cualquiera de las dos
|
|
20
|
+
es una decisión aparte, protegida por un test.
|
|
21
|
+
|
|
22
|
+
## 0.1.0 — 2026-08-19
|
|
23
|
+
|
|
24
|
+
Primera publicación: transporte `useChat` de AI SDK, sondeo de estado, sin estilos configurables.
|
package/README.md
CHANGED
|
@@ -6,9 +6,12 @@ reporte en Supcoflow.
|
|
|
6
6
|
|
|
7
7
|
## Requisitos
|
|
8
8
|
|
|
9
|
-
- **React 19** (`peerDependencies: react >=19`)
|
|
10
|
-
-
|
|
11
|
-
|
|
9
|
+
- **React 19** (`peerDependencies: react >=19`).
|
|
10
|
+
- **Node 24 o mayor** en el entorno donde se instala y se hace el build: el transporte es
|
|
11
|
+
[`eve`](https://eve.dev), que lo exige. Con Node 22 o 23, `npm install` avisa por `engines`.
|
|
12
|
+
- Un bundler (Next, Vite, webpack): el paquete emite ESM con imports relativos sin extensión.
|
|
13
|
+
- Un proyecto de Supcoflow con **el chat activado**. La sección `sdk` del proyecto en la consola
|
|
14
|
+
tiene el checklist de lo que falta.
|
|
12
15
|
|
|
13
16
|
## Instalación
|
|
14
17
|
|
|
@@ -16,11 +19,9 @@ reporte en Supcoflow.
|
|
|
16
19
|
npm i @supcoflow/chat
|
|
17
20
|
```
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
npm i /ruta/al/supcoflow-chat-0.1.0.tgz
|
|
23
|
-
```
|
|
22
|
+
Trae `eve` como dependencia (hoy son ~47 MB instalados por un widget de 20 KB — está anotado
|
|
23
|
+
como deuda y se va a separar en un paquete cliente liviano). `ai` entra solo como peer de `eve`.
|
|
24
|
+
No hace falta `transpilePackages` en `next.config`.
|
|
24
25
|
|
|
25
26
|
## Uso
|
|
26
27
|
|
|
@@ -31,37 +32,41 @@ import { ChatDeIntake } from "@supcoflow/chat";
|
|
|
31
32
|
tenantId="tnt_xxx"
|
|
32
33
|
projectId="proj_xxx"
|
|
33
34
|
backendUrl="https://chat.supcoflow.dev"
|
|
34
|
-
contexto={{ url: location.href, versionApp: "1.4.2" }} // opcional
|
|
35
35
|
/>
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
Los tres identificadores **son públicos** — modelo DSN. La contención no es un secreto: es la
|
|
39
|
-
lista de
|
|
40
|
-
motor. Poner el `tenantId` en el HTML de un sitio público es el uso previsto.
|
|
39
|
+
lista de orígenes admitidos del proyecto más el tope de mensajes (ventana rodante de 24 h), los
|
|
40
|
+
dos del lado del motor. Poner el `tenantId` en el HTML de un sitio público es el uso previsto.
|
|
41
|
+
|
|
42
|
+
El prop `contexto` se acepta por compatibilidad de tipos pero **hoy no viaja al reporte**. Si
|
|
43
|
+
necesitás mandar URL o versión con el reporte, usá la API de ingesta desde tu servidor (la
|
|
44
|
+
sección `sdk` de la consola tiene el snippet).
|
|
45
|
+
|
|
46
|
+
## Si tu sitio tiene CSP
|
|
41
47
|
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
Agregá el backend a `connect-src`, o el navegador bloquea el pedido y el widget no se dibuja
|
|
49
|
+
nunca — es la causa más común de «lo instalé y no aparece»:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
connect-src 'self' https://chat.supcoflow.dev;
|
|
53
|
+
```
|
|
44
54
|
|
|
45
55
|
## Lo que hace cuando algo falla: nada visible
|
|
46
56
|
|
|
47
|
-
El widget **se oculta** —no muestra un error— si el chat está apagado, si el tope
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
(
|
|
53
|
-
|
|
57
|
+
El widget **se oculta** —no muestra un error— si el chat está apagado, si el tope se agotó, si el
|
|
58
|
+
origen del sitio no está admitido o si el backend no contesta. Es deliberado: quien está del otro
|
|
59
|
+
lado es un usuario final del producto del cliente. Para diagnosticar, mirá el status de
|
|
60
|
+
`GET {backendUrl}/api/chat/estado?tenant_id=…&project_id=…` **desde el sitio** (el origen
|
|
61
|
+
importa): 403 (chat apagado u origen no admitido), 429 (tope agotado), 404 (proyecto
|
|
62
|
+
desconocido), 502 (backend sin poder hablar con el motor). O usá «probar la instalación» en la
|
|
63
|
+
sección `sdk` de la consola. Ojo con `www.tu-sitio.com` contra `tu-sitio.com`: la comparación es
|
|
64
|
+
por origen exacto, y son dos entradas de la lista.
|
|
54
65
|
|
|
55
66
|
## Lo que este paquete NO hace
|
|
56
67
|
|
|
57
|
-
- No persiste la conversación
|
|
68
|
+
- No persiste la conversación fuera de la sesión del navegador.
|
|
58
69
|
- No le da seguimiento del reporte al que reportó. Es a propósito — el único lugar donde un
|
|
59
70
|
reporte se ve es la consola del operador.
|
|
60
71
|
- No trae estilos configurables todavía: el panel usa estilos en línea y hereda la tipografía del
|
|
61
72
|
sitio.
|
|
62
|
-
|
|
63
|
-
## Nota para quien lo consuma sin bundler
|
|
64
|
-
|
|
65
|
-
El paquete emite ESM con imports relativos sin extensión (`./ChatDeIntake`), que cualquier bundler
|
|
66
|
-
—Next, Vite, webpack— resuelve. Node ESM en crudo, sin bundler, no: es un componente de cliente,
|
|
67
|
-
así que ese caso no existe en la práctica, pero queda dicho.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatDeIntake.d.ts","sourceRoot":"","sources":["../src/ChatDeIntake.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ChatDeIntake.d.ts","sourceRoot":"","sources":["../src/ChatDeIntake.tsx"],"names":[],"mappings":"AAYA,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B,sCAgFA"}
|
package/dist/ChatDeIntake.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
import { DefaultChatTransport } from "ai";
|
|
3
|
+
import { useEveAgent } from "eve/react";
|
|
5
4
|
import { useEffect, useMemo, useState } from "react";
|
|
6
|
-
import {
|
|
5
|
+
import { partesVisibles } from "./partes-visibles";
|
|
6
|
+
import { decidirVisibilidad, mostrarIndicadorDeEscritura, normalizarBackendUrl, } from "./estado-del-widget";
|
|
7
7
|
export function ChatDeIntake(props) {
|
|
8
8
|
const [visibilidad, setVisibilidad] = useState("oculto");
|
|
9
9
|
const [entrada, setEntrada] = useState("");
|
|
10
|
-
// Un id de canal por montaje: identifica la conversación en `reportado_por_externo`
|
|
11
|
-
// sin identificar a la persona (el chat es anónimo, §9 del diseño).
|
|
12
|
-
const canalId = useMemo(() => generarCanalId(), []);
|
|
13
10
|
const backendUrl = useMemo(() => normalizarBackendUrl(props.backendUrl), [props.backendUrl]);
|
|
14
11
|
useEffect(() => {
|
|
15
12
|
let vivo = true;
|
|
@@ -21,27 +18,39 @@ export function ChatDeIntake(props) {
|
|
|
21
18
|
setVisibilidad(decidirVisibilidad({ respuesta: null, huboError: true })); });
|
|
22
19
|
return () => { vivo = false; };
|
|
23
20
|
}, [backendUrl, props.tenantId, props.projectId]);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
// `host`/`headers` son los nombres reales de `UseEveAgentOptions` (verificado contra
|
|
22
|
+
// `eve/dist/src/react/use-eve-agent.d.ts`) — no "api"/"body" como en el `DefaultChatTransport`
|
|
23
|
+
// viejo. Los dos headers son el borde de auth por proyecto que `agent/channels/eve.ts`
|
|
24
|
+
// (tarea 4) exige: sin `x-supcoflow-project` el canal contesta 401 antes de tocar el agente.
|
|
25
|
+
// Un mapa estático alcanza: `tenantId`/`projectId` son props fijas del montaje, igual que
|
|
26
|
+
// `backendUrl` ya lo era para `canalId` en la versión vieja.
|
|
27
|
+
const agent = useEveAgent({
|
|
28
|
+
host: backendUrl,
|
|
29
|
+
headers: {
|
|
30
|
+
"x-supcoflow-tenant": props.tenantId,
|
|
31
|
+
"x-supcoflow-project": props.projectId,
|
|
32
|
+
},
|
|
29
33
|
});
|
|
30
34
|
// La misma política que el montaje: un error en medio de la conversación repliega el panel.
|
|
31
|
-
useEffect(() => { if (error !== undefined)
|
|
32
|
-
setVisibilidad("oculto"); }, [error]);
|
|
35
|
+
useEffect(() => { if (agent.error !== undefined)
|
|
36
|
+
setVisibilidad("oculto"); }, [agent.error]);
|
|
33
37
|
if (visibilidad === "oculto")
|
|
34
38
|
return null;
|
|
39
|
+
const mensajes = agent.data.messages;
|
|
35
40
|
// Entre Enviar y el primer token del stream pasan 4-8 s en el peor caso (hallazgo de la
|
|
36
41
|
// pasada visual: el dueño lo leyó como "se rompió el botón" con la pantalla en silencio).
|
|
37
|
-
// El indicador cubre ese hueco sin prometer nada sobre CUÁNTO va a tardar.
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
// El indicador cubre ese hueco sin prometer nada sobre CUÁNTO va a tardar. `agent.status`
|
|
43
|
+
// reemplaza al `status` de `useChat` con el mismo vocabulario para "submitted"/"streaming".
|
|
44
|
+
const mostrarIndicador = mostrarIndicadorDeEscritura({
|
|
45
|
+
status: agent.status,
|
|
46
|
+
ultimoMensaje: mensajes[mensajes.length - 1],
|
|
47
|
+
});
|
|
48
|
+
return (_jsxs("div", { style: { border: "1px solid #ccc", borderRadius: 8, maxWidth: 420, display: "flex", flexDirection: "column", fontFamily: "inherit" }, children: [_jsxs("div", { style: { padding: 12, overflowY: "auto", maxHeight: 420, display: "flex", flexDirection: "column", gap: 8 }, children: [mensajes.map((m) => (_jsx("div", { style: { alignSelf: m.role === "user" ? "flex-end" : "flex-start", whiteSpace: "pre-wrap" }, children: partesVisibles(m.parts).map((p, i) => _jsx("span", { children: p.text }, i)) }, m.id))), mostrarIndicador && (_jsx("div", { style: { alignSelf: "flex-start", whiteSpace: "pre-wrap" }, "aria-live": "polite", children: "\u2026" }))] }), _jsxs("form", { style: { display: "flex", gap: 8, padding: 12, borderTop: "1px solid #ccc" }, onSubmit: (e) => {
|
|
40
49
|
e.preventDefault();
|
|
41
|
-
if (entrada.trim().length === 0 || status !== "ready")
|
|
50
|
+
if (entrada.trim().length === 0 || agent.status !== "ready")
|
|
42
51
|
return;
|
|
43
|
-
|
|
52
|
+
void agent.send(entrada);
|
|
44
53
|
setEntrada("");
|
|
45
|
-
}, children: [_jsx("input", { style: { flex: 1 }, value: entrada, onChange: (e) => setEntrada(e.target.value), placeholder: "Pregunt\u00E1 o cont\u00E1 qu\u00E9 pas\u00F3\u2026", "aria-label": "Mensaje" }), _jsx("button", { type: "submit", disabled: status !== "ready", children: "Enviar" })] })] }));
|
|
54
|
+
}, children: [_jsx("input", { style: { flex: 1 }, value: entrada, onChange: (e) => setEntrada(e.target.value), placeholder: "Pregunt\u00E1 o cont\u00E1 qu\u00E9 pas\u00F3\u2026", "aria-label": "Mensaje" }), _jsx("button", { type: "submit", disabled: agent.status !== "ready", children: "Enviar" })] })] }));
|
|
46
55
|
}
|
|
47
56
|
//# sourceMappingURL=ChatDeIntake.js.map
|
package/dist/ChatDeIntake.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatDeIntake.js","sourceRoot":"","sources":["../src/ChatDeIntake.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ChatDeIntake.js","sourceRoot":"","sources":["../src/ChatDeIntake.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,oBAAoB,GAErB,MAAM,qBAAqB,CAAC;AAO7B,MAAM,UAAU,YAAY,CAAC,KAK5B;IACC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAc,QAAQ,CAAC,CAAC;IACtE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;IAE7F,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,GAAG,IAAI,CAAC;QAChB,KAAK,CAAC,GAAG,UAAU,8BAA8B,kBAAkB,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;aACrI,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACrB,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,IAAI;YAAE,cAAc,CAAC,kBAAkB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAC5G,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI;YAAE,cAAc,CAAC,kBAAkB,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxG,OAAO,GAAG,EAAE,GAAG,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAElD,qFAAqF;IACrF,+FAA+F;IAC/F,uFAAuF;IACvF,6FAA6F;IAC7F,0FAA0F;IAC1F,6DAA6D;IAC7D,MAAM,KAAK,GAAG,WAAW,CAAC;QACxB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE;YACP,oBAAoB,EAAE,KAAK,CAAC,QAAQ;YACpC,qBAAqB,EAAE,KAAK,CAAC,SAAS;SACvC;KACF,CAAC,CAAC;IAEH,4FAA4F;IAC5F,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAE7F,IAAI,WAAW,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;IAErC,wFAAwF;IACxF,0FAA0F;IAC1F,0FAA0F;IAC1F,4FAA4F;IAC5F,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;QACnD,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;KAC7C,CAAC,CAAC;IAEH,OAAO,CACL,eAAK,KAAK,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,YAAY,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,aACvI,eAAK,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,aAC7G,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACnB,cAAgB,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,YAGxG,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,yBAAe,CAAC,CAAC,IAAI,IAAV,CAAC,CAAiB,CAAC,IAH7D,CAAC,CAAC,EAAE,CAIR,CACP,CAAC,EACD,gBAAgB,IAAI,CACnB,cAAK,KAAK,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,eAAY,QAAQ,uBAE7E,CACP,IACG,EACN,gBACE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,EAC5E,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;oBACd,CAAC,CAAC,cAAc,EAAE,CAAC;oBACnB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO;wBAAE,OAAO;oBACpE,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACzB,UAAU,CAAC,EAAE,CAAC,CAAC;gBACjB,CAAC,aAED,gBACE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAClB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC3C,WAAW,EAAC,qDAA4B,gBAC7B,SAAS,GACpB,EACF,iBAAQ,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,KAAK,OAAO,uBAAiB,IACpE,IACH,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -2,7 +2,13 @@ export type Visibilidad = "visible" | "oculto";
|
|
|
2
2
|
/** `crypto.randomUUID` no existe en un contexto no-seguro (un sitio embebido por HTTP
|
|
3
3
|
* plano, no HTTPS) — sin este chequeo, el `useMemo` del widget lanza en el render y
|
|
4
4
|
* tira abajo el host entero, justo lo opuesto a la promesa de "se oculta" del §8. El
|
|
5
|
-
* fallback no necesita ser criptográfico: es un id de canal anónimo, no un secreto.
|
|
5
|
+
* fallback no necesita ser criptográfico: es un id de canal anónimo, no un secreto.
|
|
6
|
+
*
|
|
7
|
+
* `ChatDeIntake` dejó de llamar esta función: sobre `useEveAgent` el rol de identificar la
|
|
8
|
+
* conversación lo cumple el `sessionId` que pone el backend. Queda EXPORTADA sin llamador
|
|
9
|
+
* dentro de este paquete —no se borra especulativamente— porque `POST /api/chat`, el camino
|
|
10
|
+
* viejo, sigue vivo hasta el corte, y es la ruta que necesita el concepto de "id de canal" del
|
|
11
|
+
* lado del cliente. */
|
|
6
12
|
export declare function generarCanalId(): string;
|
|
7
13
|
/** Una barra final en `backendUrl` ("https://x.com/", la forma más natural de
|
|
8
14
|
* escribirlo) deja `//` duplicado en las URLs armadas más abajo: el motor responde con
|
|
@@ -18,14 +24,14 @@ export declare function decidirVisibilidad(h: {
|
|
|
18
24
|
} | null;
|
|
19
25
|
huboError: boolean;
|
|
20
26
|
}): Visibilidad;
|
|
21
|
-
export type EstadoDelChat = "submitted" | "streaming" | "ready" | "error";
|
|
27
|
+
export type EstadoDelChat = "submitted" | "streaming" | "ready" | "error" | "resuming";
|
|
22
28
|
interface ParteMinima {
|
|
23
29
|
type: string;
|
|
24
30
|
text?: string;
|
|
25
31
|
}
|
|
26
32
|
interface MensajeMinimo {
|
|
27
33
|
role: string;
|
|
28
|
-
parts: ParteMinima[];
|
|
34
|
+
parts: readonly ParteMinima[];
|
|
29
35
|
}
|
|
30
36
|
/** Entre Enviar y el primer token del stream pasan 4-8 s en el peor caso (medido en la pasada
|
|
31
37
|
* visual del demo) — el backend responde perfecto, pero un silencio así se lee como "se rompió
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"estado-del-widget.d.ts","sourceRoot":"","sources":["../src/estado-del-widget.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE/C
|
|
1
|
+
{"version":3,"file":"estado-del-widget.d.ts","sourceRoot":"","sources":["../src/estado-del-widget.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE/C;;;;;;;;;uBASuB;AACvB,wBAAgB,cAAc,IAAI,MAAM,CAKvC;AAED;;;wEAGwE;AACxE,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;mCAEmC;AACnC,wBAAgB,kBAAkB,CAAC,CAAC,EAAE;IACpC,SAAS,EAAE;QAAE,EAAE,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,WAAW,CAGd;AAMD,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;AAEvF,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IAGb,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;CAC/B;AAED;;;;sEAIsE;AACtE,wBAAgB,2BAA2B,CAAC,CAAC,EAAE;IAC7C,MAAM,EAAE,aAAa,CAAC;IACtB,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;CAC1C,GAAG,OAAO,CAOV"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
/** `crypto.randomUUID` no existe en un contexto no-seguro (un sitio embebido por HTTP
|
|
2
2
|
* plano, no HTTPS) — sin este chequeo, el `useMemo` del widget lanza en el render y
|
|
3
3
|
* tira abajo el host entero, justo lo opuesto a la promesa de "se oculta" del §8. El
|
|
4
|
-
* fallback no necesita ser criptográfico: es un id de canal anónimo, no un secreto.
|
|
4
|
+
* fallback no necesita ser criptográfico: es un id de canal anónimo, no un secreto.
|
|
5
|
+
*
|
|
6
|
+
* `ChatDeIntake` dejó de llamar esta función: sobre `useEveAgent` el rol de identificar la
|
|
7
|
+
* conversación lo cumple el `sessionId` que pone el backend. Queda EXPORTADA sin llamador
|
|
8
|
+
* dentro de este paquete —no se borra especulativamente— porque `POST /api/chat`, el camino
|
|
9
|
+
* viejo, sigue vivo hasta el corte, y es la ruta que necesita el concepto de "id de canal" del
|
|
10
|
+
* lado del cliente. */
|
|
5
11
|
export function generarCanalId() {
|
|
6
12
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
7
13
|
return crypto.randomUUID();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"estado-del-widget.js","sourceRoot":"","sources":["../src/estado-del-widget.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"estado-del-widget.js","sourceRoot":"","sources":["../src/estado-del-widget.ts"],"names":[],"mappings":"AAEA;;;;;;;;;uBASuB;AACvB,MAAM,UAAU,cAAc;IAC5B,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;QAC7E,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,SAAS,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACtE,CAAC;AAED;;;wEAGwE;AACxE,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACrD,OAAO,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC;AAED;;mCAEmC;AACnC,MAAM,UAAU,kBAAkB,CAAC,CAGlC;IACC,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE;QAAE,OAAO,QAAQ,CAAC;IAC5E,OAAO,SAAS,CAAC;AACnB,CAAC;AAoBD;;;;sEAIsE;AACtE,MAAM,UAAU,2BAA2B,CAAC,CAG3C;IACC,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,UAAU,GACd,CAAC,CAAC,aAAa,EAAE,IAAI,KAAK,WAAW;QACrC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpF,OAAO,CAAC,UAAU,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** El §6 del diseño: en el sitio del CLIENTE se dibuja solo texto. El reasoning streamea por
|
|
2
|
+
* defecto en el protocolo de Eve, y el modelo razonando en crudo sobre el producto del
|
|
3
|
+
* cliente delante de su usuario final no es una feature.
|
|
4
|
+
*
|
|
5
|
+
* El predicado de tipo (`p is Extract<P, { type: "text" }>`) es lo que hace que el llamador
|
|
6
|
+
* pueda leer `p.text` sin volver a angostar: `EveMessagePart` es una unión con variantes que
|
|
7
|
+
* NO tienen `text` (`dynamic-tool`, `file`, `step-start`, `authorization`), así que un filtro
|
|
8
|
+
* sin predicado devolvería la unión completa y el acceso a `.text` no compilaría. El filtro en
|
|
9
|
+
* sí es exactamente el que pide la tarea — comparar `p.type === "text"` — solo el tipo de
|
|
10
|
+
* retorno cambió. */
|
|
11
|
+
export declare function partesVisibles<P extends {
|
|
12
|
+
type: string;
|
|
13
|
+
}>(partes: readonly P[]): Extract<P, {
|
|
14
|
+
type: "text";
|
|
15
|
+
}>[];
|
|
16
|
+
//# sourceMappingURL=partes-visibles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"partes-visibles.d.ts","sourceRoot":"","sources":["../src/partes-visibles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;qBASqB;AACrB,wBAAgB,cAAc,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EACvD,MAAM,EAAE,SAAS,CAAC,EAAE,GACnB,OAAO,CAAC,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,CAEhC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** El §6 del diseño: en el sitio del CLIENTE se dibuja solo texto. El reasoning streamea por
|
|
2
|
+
* defecto en el protocolo de Eve, y el modelo razonando en crudo sobre el producto del
|
|
3
|
+
* cliente delante de su usuario final no es una feature.
|
|
4
|
+
*
|
|
5
|
+
* El predicado de tipo (`p is Extract<P, { type: "text" }>`) es lo que hace que el llamador
|
|
6
|
+
* pueda leer `p.text` sin volver a angostar: `EveMessagePart` es una unión con variantes que
|
|
7
|
+
* NO tienen `text` (`dynamic-tool`, `file`, `step-start`, `authorization`), así que un filtro
|
|
8
|
+
* sin predicado devolvería la unión completa y el acceso a `.text` no compilaría. El filtro en
|
|
9
|
+
* sí es exactamente el que pide la tarea — comparar `p.type === "text"` — solo el tipo de
|
|
10
|
+
* retorno cambió. */
|
|
11
|
+
export function partesVisibles(partes) {
|
|
12
|
+
return partes.filter((p) => p.type === "text");
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=partes-visibles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"partes-visibles.js","sourceRoot":"","sources":["../src/partes-visibles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;qBASqB;AACrB,MAAM,UAAU,cAAc,CAC5B,MAAoB;IAEpB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAqC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;AACpF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supcoflow/chat",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "El chat de intake de Supcoflow como componente de React: orienta sobre el producto y abre el reporte cuando el problema es un bug.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
30
|
-
"dist"
|
|
30
|
+
"dist",
|
|
31
|
+
"CHANGELOG.md"
|
|
31
32
|
],
|
|
32
33
|
"scripts": {
|
|
33
34
|
"build": "tsc -p tsconfig.build.json",
|
|
@@ -37,8 +38,7 @@
|
|
|
37
38
|
"react": ">=19"
|
|
38
39
|
},
|
|
39
40
|
"dependencies": {
|
|
40
|
-
"
|
|
41
|
-
"ai": "^7.0.67"
|
|
41
|
+
"eve": "0.47.7"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/react": "19.2.18",
|