@supcoflow/chat 0.1.0 → 2.1.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.
Files changed (73) hide show
  1. package/LICENSES/orca.txt +25 -0
  2. package/README.md +127 -44
  3. package/dist/apariencia.d.ts +16 -0
  4. package/dist/apariencia.d.ts.map +1 -0
  5. package/dist/cliente.d.ts +25 -0
  6. package/dist/cliente.d.ts.map +1 -0
  7. package/dist/componentes/Adjuntos.d.ts +11 -0
  8. package/dist/componentes/Adjuntos.d.ts.map +1 -0
  9. package/dist/componentes/Burbuja.d.ts +6 -0
  10. package/dist/componentes/Burbuja.d.ts.map +1 -0
  11. package/dist/componentes/Compositor.d.ts +19 -0
  12. package/dist/componentes/Compositor.d.ts.map +1 -0
  13. package/dist/componentes/Markdown.d.ts +4 -0
  14. package/dist/componentes/Markdown.d.ts.map +1 -0
  15. package/dist/componentes/Mensajes.d.ts +8 -0
  16. package/dist/componentes/Mensajes.d.ts.map +1 -0
  17. package/dist/componentes/Panel.d.ts +11 -0
  18. package/dist/componentes/Panel.d.ts.map +1 -0
  19. package/dist/componentes/PreguntaHitl.d.ts +8 -0
  20. package/dist/componentes/PreguntaHitl.d.ts.map +1 -0
  21. package/dist/componentes/Widget.d.ts +21 -0
  22. package/dist/componentes/Widget.d.ts.map +1 -0
  23. package/dist/contexto.d.ts +10 -0
  24. package/dist/contexto.d.ts.map +1 -0
  25. package/dist/estado-del-widget.d.ts +18 -31
  26. package/dist/estado-del-widget.d.ts.map +1 -1
  27. package/dist/estado.d.ts +40 -0
  28. package/dist/estado.d.ts.map +1 -0
  29. package/dist/evidencia/adjuntos.d.ts +45 -0
  30. package/dist/evidencia/adjuntos.d.ts.map +1 -0
  31. package/dist/evidencia/captura.d.ts +56 -0
  32. package/dist/evidencia/captura.d.ts.map +1 -0
  33. package/dist/evidencia/elemento.d.ts +46 -0
  34. package/dist/evidencia/elemento.d.ts.map +1 -0
  35. package/dist/evidencia/extraer-elemento.d.ts +11 -0
  36. package/dist/evidencia/extraer-elemento.d.ts.map +1 -0
  37. package/dist/evidencia/resumen-de-evidencia.d.ts +11 -0
  38. package/dist/evidencia/resumen-de-evidencia.d.ts.map +1 -0
  39. package/dist/evidencia/selector-de-elementos.d.ts +11 -0
  40. package/dist/evidencia/selector-de-elementos.d.ts.map +1 -0
  41. package/dist/evidencia/subida.d.ts +17 -0
  42. package/dist/evidencia/subida.d.ts.map +1 -0
  43. package/dist/iife.d.ts +2 -0
  44. package/dist/iife.d.ts.map +1 -0
  45. package/dist/index.d.ts +4 -1
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +91 -2
  48. package/dist/index.js.map +7 -1
  49. package/dist/markdown.d.ts +31 -0
  50. package/dist/markdown.d.ts.map +1 -0
  51. package/dist/montar.d.ts +9 -0
  52. package/dist/montar.d.ts.map +1 -0
  53. package/dist/opciones.d.ts +80 -0
  54. package/dist/opciones.d.ts.map +1 -0
  55. package/dist/protocolo.d.ts +61 -0
  56. package/dist/protocolo.d.ts.map +1 -0
  57. package/dist/react.d.ts +11 -0
  58. package/dist/react.d.ts.map +1 -0
  59. package/dist/sesion-guardada.d.ts +5 -0
  60. package/dist/sesion-guardada.d.ts.map +1 -0
  61. package/dist/tema.d.ts +3 -0
  62. package/dist/tema.d.ts.map +1 -0
  63. package/dist/textos.d.ts +32 -0
  64. package/dist/textos.d.ts.map +1 -0
  65. package/dist/widget.iife.js +91 -0
  66. package/dist/widget.iife.js.map +7 -0
  67. package/package.json +14 -33
  68. package/dist/ChatDeIntake.d.ts +0 -11
  69. package/dist/ChatDeIntake.d.ts.map +0 -1
  70. package/dist/ChatDeIntake.js +0 -47
  71. package/dist/ChatDeIntake.js.map +0 -1
  72. package/dist/estado-del-widget.js +0 -40
  73. package/dist/estado-del-widget.js.map +0 -1
package/package.json CHANGED
@@ -1,51 +1,32 @@
1
1
  {
2
2
  "name": "@supcoflow/chat",
3
- "version": "0.1.0",
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.",
3
+ "version": "2.1.0",
4
+ "description": "El chat de intake de Supcoflow, embebible en cualquier sitio: orienta sobre el producto y abre el reporte cuando el problema es un bug.",
5
5
  "license": "MIT",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/supcoflow/sdk.git",
9
- "directory": "packages/widget"
10
- },
6
+ "repository": { "type": "git", "url": "git+https://github.com/supcoflow/sdk.git", "directory": "packages/widget" },
11
7
  "homepage": "https://supcoflow.dev",
12
- "keywords": [
13
- "supcoflow",
14
- "chat",
15
- "intake",
16
- "bug-report",
17
- "react",
18
- "widget"
19
- ],
8
+ "keywords": ["supcoflow", "chat", "intake", "bug-report", "widget", "react", "preact"],
20
9
  "type": "module",
21
10
  "main": "./dist/index.js",
22
11
  "types": "./dist/index.d.ts",
23
12
  "exports": {
24
- ".": {
25
- "types": "./dist/index.d.ts",
26
- "default": "./dist/index.js"
27
- }
13
+ ".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
14
+ "./widget.js": "./dist/widget.iife.js"
28
15
  },
29
- "files": [
30
- "dist"
31
- ],
16
+ "files": ["dist", "LICENSES"],
17
+ "sideEffects": false,
32
18
  "scripts": {
33
- "build": "tsc -p tsconfig.build.json",
19
+ "build": "node build.mjs && tsc -p tsconfig.build.json",
34
20
  "prepare": "npm run build"
35
21
  },
36
- "peerDependencies": {
37
- "react": ">=19"
38
- },
39
- "dependencies": {
40
- "@ai-sdk/react": "^4.0.0",
41
- "ai": "^7.0.67"
42
- },
22
+ "peerDependencies": { "react": ">=18" },
23
+ "peerDependenciesMeta": { "react": { "optional": true } },
43
24
  "devDependencies": {
44
25
  "@types/react": "19.2.18",
26
+ "esbuild": "0.28.2",
27
+ "preact": "10.28.3",
45
28
  "typescript": "^5.7.0",
46
29
  "vitest": "^4.0.0"
47
30
  },
48
- "publishConfig": {
49
- "access": "public"
50
- }
31
+ "publishConfig": { "access": "public" }
51
32
  }
@@ -1,11 +0,0 @@
1
- export interface ContextoDelReporte {
2
- url?: string;
3
- versionApp?: string;
4
- }
5
- export declare function ChatDeIntake(props: {
6
- tenantId: string;
7
- projectId: string;
8
- backendUrl: string;
9
- contexto?: ContextoDelReporte;
10
- }): import("react").JSX.Element | null;
11
- //# sourceMappingURL=ChatDeIntake.d.ts.map
@@ -1 +0,0 @@
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,47 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useChat } from "@ai-sdk/react";
4
- import { DefaultChatTransport } from "ai";
5
- import { useEffect, useMemo, useState } from "react";
6
- import { decidirVisibilidad, generarCanalId, mostrarIndicadorDeEscritura, normalizarBackendUrl, } from "./estado-del-widget";
7
- export function ChatDeIntake(props) {
8
- const [visibilidad, setVisibilidad] = useState("oculto");
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
- const backendUrl = useMemo(() => normalizarBackendUrl(props.backendUrl), [props.backendUrl]);
14
- useEffect(() => {
15
- let vivo = true;
16
- fetch(`${backendUrl}/api/chat/estado?tenant_id=${encodeURIComponent(props.tenantId)}&project_id=${encodeURIComponent(props.projectId)}`)
17
- .then((r) => r.json())
18
- .then((cuerpo) => { if (vivo)
19
- setVisibilidad(decidirVisibilidad({ respuesta: cuerpo, huboError: false })); })
20
- .catch(() => { if (vivo)
21
- setVisibilidad(decidirVisibilidad({ respuesta: null, huboError: true })); });
22
- return () => { vivo = false; };
23
- }, [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
- }),
29
- });
30
- // 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]);
33
- if (visibilidad === "oculto")
34
- return null;
35
- // Entre Enviar y el primer token del stream pasan 4-8 s en el peor caso (hallazgo de la
36
- // 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) => {
40
- e.preventDefault();
41
- if (entrada.trim().length === 0 || status !== "ready")
42
- return;
43
- sendMessage({ text: entrada });
44
- 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" })] })] }));
46
- }
47
- //# sourceMappingURL=ChatDeIntake.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ChatDeIntake.js","sourceRoot":"","sources":["../src/ChatDeIntake.tsx"],"names":[],"mappings":"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"}
@@ -1,40 +0,0 @@
1
- /** `crypto.randomUUID` no existe en un contexto no-seguro (un sitio embebido por HTTP
2
- * plano, no HTTPS) — sin este chequeo, el `useMemo` del widget lanza en el render y
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. */
5
- export function generarCanalId() {
6
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
7
- return crypto.randomUUID();
8
- }
9
- return `canal_${Date.now()}_${Math.random().toString(36).slice(2)}`;
10
- }
11
- /** Una barra final en `backendUrl` ("https://x.com/", la forma más natural de
12
- * escribirlo) deja `//` duplicado en las URLs armadas más abajo: el motor responde con
13
- * un 308 sin headers de CORS y el navegador lo bloquea sin explicar que el problema es
14
- * la barra. Mismo patrón que `motor.ts` usa para su propia base URL. */
15
- export function normalizarBackendUrl(backendUrl) {
16
- return backendUrl.replace(/\/$/, "");
17
- }
18
- /** §8 del diseño: sin backend, sin tope, o ante cualquier duda, el widget NO se dibuja.
19
- * Ocultarse es lo honesto: no hay nada que decirle al usuario final sobre el estado interno
20
- * del proyecto de otra empresa. */
21
- export function decidirVisibilidad(h) {
22
- if (h.huboError || h.respuesta === null || !h.respuesta.ok)
23
- return "oculto";
24
- return "visible";
25
- }
26
- /** Entre Enviar y el primer token del stream pasan 4-8 s en el peor caso (medido en la pasada
27
- * visual del demo) — el backend responde perfecto, pero un silencio así se lee como "se rompió
28
- * el botón", no como "está pensando". Mostramos un indicador mientras el pedido está en vuelo
29
- * ("submitted") y mientras ya empezó a transmitir pero todavía no llegó texto del asistente
30
- * ("streaming" sin parts de texto no vacíos en el último mensaje). */
31
- export function mostrarIndicadorDeEscritura(h) {
32
- if (h.status === "submitted")
33
- return true;
34
- if (h.status !== "streaming")
35
- return false;
36
- const yaHayTexto = h.ultimoMensaje?.role === "assistant" &&
37
- h.ultimoMensaje.parts.some((p) => p.type === "text" && (p.text?.length ?? 0) > 0);
38
- return !yaHayTexto;
39
- }
40
- //# sourceMappingURL=estado-del-widget.js.map
@@ -1 +0,0 @@
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"}