@fayz-ai/plugin-conversations 0.17.1 → 0.18.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/dist/data/supabase.d.ts.map +1 -1
- package/dist/index.js +117 -4
- package/dist/index.js.map +1 -1
- package/dist/migrations/index.d.ts +1 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/views/MessageThread.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAwBpD,MAAM,WAAW,2BAA2B;IAC1C,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAA;IAC9C,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;
|
|
1
|
+
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAwBpD,MAAM,WAAW,2BAA2B;IAC1C,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAA;IAC9C,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAmDD,wBAAgB,mCAAmC,CACjD,MAAM,CAAC,EAAE,2BAA2B,GACnC,qBAAqB,CAuRvB"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React11 from 'react';
|
|
2
2
|
import React11__default, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
|
3
|
-
import { Loader2, MessageSquare, AlertTriangle, Pause, Play, Send, RefreshCw, Plus, Clock, CheckCircle2, Check, ShieldCheck, ShieldAlert, QrCode, Zap, ExternalLink, SquarePen, Globe, Mail, Instagram, Phone, Search, User, Inbox, CheckCheck, ChevronLeft, Archive, PanelRight, X, MapPin, Tag, StickyNote, Link2, MoreVertical, Snowflake, Sun, Flame, Building2 } from 'lucide-react';
|
|
3
|
+
import { Loader2, MessageSquare, AlertTriangle, Pause, Play, Send, RefreshCw, Plus, Clock, CheckCircle2, Check, ShieldCheck, ShieldAlert, QrCode, Zap, ExternalLink, SquarePen, Globe, Mail, Instagram, Phone, Search, User, Inbox, CheckCheck, ChevronLeft, Archive, PanelRight, X, MapPin, Tag, StickyNote, Link2, MoreVertical, Snowflake, Sun, Flame, Building2, UserRound, Copy } from 'lucide-react';
|
|
4
4
|
import { toast, Button, Input, defineKpiWidget, defineTableWidget, PageHeaderActions, cn, Badge, FilterChip, Skeleton, KpiCard, TableWidget } from '@fayz-ai/ui';
|
|
5
5
|
import { createConnectionStore, connectionRuns, connectionStatus, getActiveTenantId, getSupabaseClientOptional, useActiveTenantId, registerTranslations, useTranslation, countByTenant, CONNECTOR_RUNTIME_TOKEN_HEADER, connectorRuntimeToken, errorMessage } from '@fayz-ai/core';
|
|
6
6
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -1199,6 +1199,51 @@ function MessageMenu({ m }) {
|
|
|
1199
1199
|
] }) })
|
|
1200
1200
|
] });
|
|
1201
1201
|
}
|
|
1202
|
+
function ContactCard({ contacts, outbound }) {
|
|
1203
|
+
const [copied, setCopied] = React11__default.useState(null);
|
|
1204
|
+
const copy = (value) => {
|
|
1205
|
+
void navigator.clipboard?.writeText(value);
|
|
1206
|
+
setCopied(value);
|
|
1207
|
+
window.setTimeout(() => setCopied((c) => c === value ? null : c), 1500);
|
|
1208
|
+
};
|
|
1209
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: contacts.map((c, i) => /* @__PURE__ */ jsxs(
|
|
1210
|
+
"div",
|
|
1211
|
+
{
|
|
1212
|
+
className: cn(
|
|
1213
|
+
"flex items-start gap-2.5 rounded-xl px-2.5 py-2",
|
|
1214
|
+
outbound ? "bg-white/15" : "bg-muted"
|
|
1215
|
+
),
|
|
1216
|
+
children: [
|
|
1217
|
+
/* @__PURE__ */ jsx(UserRound, { className: cn("mt-0.5 h-4 w-4 shrink-0", outbound ? "text-white/80" : "text-muted-foreground") }),
|
|
1218
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1219
|
+
/* @__PURE__ */ jsx("p", { className: "truncate font-medium", children: c.name }),
|
|
1220
|
+
c.phones.map((p) => /* @__PURE__ */ jsxs(
|
|
1221
|
+
"button",
|
|
1222
|
+
{
|
|
1223
|
+
type: "button",
|
|
1224
|
+
onClick: () => copy(p.display),
|
|
1225
|
+
className: cn(
|
|
1226
|
+
"group/phone mt-0.5 flex items-center gap-1.5 text-left text-[13px] tabular-nums",
|
|
1227
|
+
outbound ? "text-white/90 hover:text-white" : "text-muted-foreground hover:text-foreground"
|
|
1228
|
+
),
|
|
1229
|
+
children: [
|
|
1230
|
+
p.display,
|
|
1231
|
+
copied === p.display ? /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3 w-3 opacity-0 transition-opacity group-hover/phone:opacity-100" })
|
|
1232
|
+
]
|
|
1233
|
+
},
|
|
1234
|
+
p.digits
|
|
1235
|
+
))
|
|
1236
|
+
] })
|
|
1237
|
+
]
|
|
1238
|
+
},
|
|
1239
|
+
`${c.name}-${i}`
|
|
1240
|
+
)) });
|
|
1241
|
+
}
|
|
1242
|
+
function MessageBody({ m, outbound }) {
|
|
1243
|
+
const contacts = m.messageType === "contact" ? m.payload?.contacts ?? [] : [];
|
|
1244
|
+
if (contacts.length > 0) return /* @__PURE__ */ jsx(ContactCard, { contacts, outbound });
|
|
1245
|
+
return /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap break-words", children: m.body });
|
|
1246
|
+
}
|
|
1202
1247
|
function buildRows(messages) {
|
|
1203
1248
|
const rows = [];
|
|
1204
1249
|
let lastDay = "";
|
|
@@ -1317,7 +1362,7 @@ function MessageThread({ selected, onTogglePanel, panelOpen, onBack, className }
|
|
|
1317
1362
|
),
|
|
1318
1363
|
style: outbound ? { backgroundColor: failed ? "hsl(var(--destructive))" : accent.color } : void 0,
|
|
1319
1364
|
children: [
|
|
1320
|
-
/* @__PURE__ */ jsx(
|
|
1365
|
+
/* @__PURE__ */ jsx(MessageBody, { m, outbound }),
|
|
1321
1366
|
/* @__PURE__ */ jsxs("div", { className: cn("mt-0.5 flex items-center justify-end gap-1 text-[10px]", outbound ? "text-white/70" : "text-muted-foreground"), children: [
|
|
1322
1367
|
new Date(m.at).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }),
|
|
1323
1368
|
/* @__PURE__ */ jsx(DeliveryMark, { m })
|
|
@@ -2078,7 +2123,12 @@ function mapMessage(r) {
|
|
|
2078
2123
|
at: r.at ?? "",
|
|
2079
2124
|
author: r.author ?? "",
|
|
2080
2125
|
deliveryStatus: r.delivery_status ?? null,
|
|
2081
|
-
providerMessageId: r.provider_message_id ?? null
|
|
2126
|
+
providerMessageId: r.provider_message_id ?? null,
|
|
2127
|
+
// NULL stays null rather than defaulting to 'text'. A row written before
|
|
2128
|
+
// migration 012 genuinely does not know what it was, and the rows that most
|
|
2129
|
+
// need saying so are the empty ones that a 'text' default would call fine.
|
|
2130
|
+
messageType: r.message_type ?? null,
|
|
2131
|
+
payload: r.payload ?? null
|
|
2082
2132
|
};
|
|
2083
2133
|
}
|
|
2084
2134
|
function createSupabaseConversationsProvider(config) {
|
|
@@ -5483,6 +5533,68 @@ END $$;
|
|
|
5483
5533
|
COMMENT ON FUNCTION public.plg_conversations_anunciar_chegada() IS
|
|
5484
5534
|
'Toca a campainha no t\xF3pico \`conversas:<tenant>\` \u2014 s\xF3 o id da conversa. O conte\xFAdo \xE9 lido da tabela, com RLS (011).';
|
|
5485
5535
|
`;
|
|
5536
|
+
var MIGRATION_012_A_RICH_MESSAGE_KEEPS_ITS_SHAPE = `-- ---------------------------------------------------------------------------
|
|
5537
|
+
-- 012_a_rich_message_keeps_its_shape.sql
|
|
5538
|
+
--
|
|
5539
|
+
-- \u2500\u2500 what was lost, and how \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
5540
|
+
--
|
|
5541
|
+
-- \`plg_conversation_messages\` has exactly one content column: \`body text\`. A
|
|
5542
|
+
-- WhatsApp message that is not text therefore arrives flattened to whatever
|
|
5543
|
+
-- string the ingest could make of it \u2014 and when the ingest could make none, to
|
|
5544
|
+
-- the empty string, which renders as an empty bubble.
|
|
5545
|
+
--
|
|
5546
|
+
-- On 2026-09-22 a lead sent his finance director's contact card. It stored as
|
|
5547
|
+
-- \`body = ''\`. He then sent a screenshot of the same card; that stored as
|
|
5548
|
+
-- \`body = ''\` too. The fact the conversation existed to obtain \u2014 a name and a
|
|
5549
|
+
-- phone number \u2014 was in the payload both times and in the row neither time.
|
|
5550
|
+
--
|
|
5551
|
+
-- Recovering it meant going back to the Evolution instance and reading the
|
|
5552
|
+
-- provider's own copy. That worked, but it is not a recovery path: Evolution
|
|
5553
|
+
-- prunes, the instance is local-only, and a row that needs a second system to
|
|
5554
|
+
-- be legible is not a record.
|
|
5555
|
+
--
|
|
5556
|
+
-- \u2500\u2500 the two columns \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
5557
|
+
--
|
|
5558
|
+
-- \`message_type\` names what the provider sent \u2014 text, contact, image, audio,
|
|
5559
|
+
-- document, sticker, location, reaction, unknown. The inbox needs it to choose
|
|
5560
|
+
-- a bubble, and \`unknown\` is the one that makes the NEXT gap visible in a query
|
|
5561
|
+
-- instead of in a complaint.
|
|
5562
|
+
--
|
|
5563
|
+
-- \`payload\` keeps the part that does not survive flattening: the vCard's parsed
|
|
5564
|
+
-- name and numbers, a media mimetype and size, a location's coordinates. Not
|
|
5565
|
+
-- the whole provider envelope \u2014 that carries decryption keys and a base64
|
|
5566
|
+
-- thumbnail, neither of which belongs in a row that every member of the tenant
|
|
5567
|
+
-- can read.
|
|
5568
|
+
--
|
|
5569
|
+
-- Deliberately NOT stored here: delivery status. It changes after the fact \u2014
|
|
5570
|
+
-- sent, delivered, read \u2014 and \`conversations-provider\`'s \`message_detail\` reads
|
|
5571
|
+
-- it live for that reason. \`payload\` is the shape of the message, which does
|
|
5572
|
+
-- not change once it arrives.
|
|
5573
|
+
--
|
|
5574
|
+
-- \u2500\u2500 why both are nullable, and nothing is backfilled \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
5575
|
+
--
|
|
5576
|
+
-- Every row written before this migration has neither, and no default can
|
|
5577
|
+
-- invent them: \`message_type\` would have to guess, and guessing 'text' for the
|
|
5578
|
+
-- three empty bubbles already in the table would assert something false about
|
|
5579
|
+
-- exactly the rows this exists to fix. A reader that treats NULL as "written
|
|
5580
|
+
-- before 012" is correct; a reader that treats '' as text is the bug.
|
|
5581
|
+
--
|
|
5582
|
+
-- Table-level \`GRANT ALL ... TO authenticated\` already covers new columns, and
|
|
5583
|
+
-- the four tenant policies are row-scoped, so neither needs restating.
|
|
5584
|
+
--
|
|
5585
|
+
-- Idempotent and replay-safe.
|
|
5586
|
+
-- ---------------------------------------------------------------------------
|
|
5587
|
+
|
|
5588
|
+
ALTER TABLE public.plg_conversation_messages
|
|
5589
|
+
ADD COLUMN IF NOT EXISTS message_type text,
|
|
5590
|
+
ADD COLUMN IF NOT EXISTS payload jsonb;
|
|
5591
|
+
|
|
5592
|
+
COMMENT ON COLUMN public.plg_conversation_messages.message_type IS
|
|
5593
|
+
'What the provider sent: text, contact, image, video, audio, document, sticker, location, reaction, unknown. NULL means the row predates 012 (#504).';
|
|
5594
|
+
|
|
5595
|
+
COMMENT ON COLUMN public.plg_conversation_messages.payload IS
|
|
5596
|
+
'The structured remainder that \`body\` cannot hold \u2014 parsed vCards, media metadata, coordinates. Never credentials, thumbnails or decryption keys; never delivery status, which is read live (#504).';
|
|
5597
|
+
`;
|
|
5486
5598
|
var MIGRATIONS = [
|
|
5487
5599
|
{ id: "000_baseline", sql: MIGRATION_000_BASELINE },
|
|
5488
5600
|
{ id: "001_a_caixa_sabe_quem_falou_por_ultimo", sql: MIGRATION_001_A_CAIXA_SABE_QUEM_FALOU_POR_ULTIMO },
|
|
@@ -5495,7 +5607,8 @@ var MIGRATIONS = [
|
|
|
5495
5607
|
{ id: "008_dar_por_vista_e_uma_decisao", sql: MIGRATION_008_DAR_POR_VISTA_E_UMA_DECISAO },
|
|
5496
5608
|
{ id: "009_a_mensagem_inteira_atravessa_o_realtime", sql: MIGRATION_009_A_MENSAGEM_INTEIRA_ATRAVESSA_O_REALTIME },
|
|
5497
5609
|
{ id: "010_a_chegada_e_anunciada_por_conta", sql: MIGRATION_010_A_CHEGADA_E_ANUNCIADA_POR_CONTA },
|
|
5498
|
-
{ id: "011_o_anuncio_e_uma_campainha_nao_um_recado", sql: MIGRATION_011_O_ANUNCIO_E_UMA_CAMPAINHA_NAO_UM_RECADO }
|
|
5610
|
+
{ id: "011_o_anuncio_e_uma_campainha_nao_um_recado", sql: MIGRATION_011_O_ANUNCIO_E_UMA_CAMPAINHA_NAO_UM_RECADO },
|
|
5611
|
+
{ id: "012_a_rich_message_keeps_its_shape", sql: MIGRATION_012_A_RICH_MESSAGE_KEEPS_ITS_SHAPE }
|
|
5499
5612
|
];
|
|
5500
5613
|
|
|
5501
5614
|
// src/index.ts
|