@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 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
- - Un proyecto de Supcoflow con **el chat activado** que exige una skill aprobada y la lista de
11
- Origins admitidos escrita. Si el chat está apagado, el widget **no se dibuja** (ver abajo).
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
- Mientras el paquete no esté publicado, se instala del tarball que produce `npm pack -w @supcoflow/chat`:
20
-
21
- ```bash
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 Origins admitidos del proyecto más el tope de mensajes por día, los dos del lado del
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
- `contexto` es opcional y viaja al reporte: sirve para que el issue diga en qué URL y con qué
43
- versión pasó.
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 del día se
48
- agotó, si el Origin del sitio no está admitido o si el backend no contesta. Es deliberado: quien
49
- está del otro lado es un usuario final del producto del cliente, y no tiene nada que hacer con
50
- "el proyecto tiene el tope agotado". Si esperabas ver el chat y no aparece, mirá la respuesta de
51
- `GET {backendUrl}/api/chat/estado?tenant_id=…&project_id=…`, que dice la causa por status: 403
52
- (chat apagado u Origin no admitido), 429 (tope agotado), 404 (proyecto desconocido), 502 (backend
53
- sin poder hablar con el motor).
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: el historial vive en el navegador y viaja entero en cada pedido.
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":"AAaA,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,sCAoEA"}
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"}
@@ -1,15 +1,12 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useChat } from "@ai-sdk/react";
4
- import { DefaultChatTransport } from "ai";
3
+ import { useEveAgent } from "eve/react";
5
4
  import { useEffect, useMemo, useState } from "react";
6
- import { decidirVisibilidad, generarCanalId, mostrarIndicadorDeEscritura, normalizarBackendUrl, } from "./estado-del-widget";
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
- const { messages, sendMessage, status, error } = useChat({
25
- transport: new DefaultChatTransport({
26
- api: `${backendUrl}/api/chat`,
27
- body: { tenant_id: props.tenantId, project_id: props.projectId, canal_id: canalId },
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
- const mostrarIndicador = mostrarIndicadorDeEscritura({ status, ultimoMensaje: messages[messages.length - 1] });
39
- 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: [messages.map((m) => (_jsx("div", { style: { alignSelf: m.role === "user" ? "flex-end" : "flex-start", whiteSpace: "pre-wrap" }, children: m.parts.map((p, i) => (p.type === "text" ? _jsx("span", { children: p.text }, i) : null)) }, 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) => {
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
- sendMessage({ text: entrada });
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
@@ -1 +1 @@
1
- {"version":3,"file":"ChatDeIntake.js","sourceRoot":"","sources":["../src/ChatDeIntake.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChatDeIntake.js","sourceRoot":"","sources":["../src/ChatDeIntake.tsx"],"names":[],"mappings":"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"}
@@ -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;;;uFAGuF;AACvF,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;AAED,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1E,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;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
+ {"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;;;uFAGuF;AACvF,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;AAcD;;;;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"}
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": "0.1.0",
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
- "@ai-sdk/react": "^4.0.0",
41
- "ai": "^7.0.67"
41
+ "eve": "0.47.7"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/react": "19.2.18",