@fayz-ai/plugin-automations 0.9.1 → 0.10.1
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/fayz.d.ts +11 -0
- package/dist/data/fayz.d.ts.map +1 -0
- package/dist/data/fayz.test.d.ts +2 -0
- package/dist/data/fayz.test.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +353 -11
- package/dist/index.js.map +1 -1
- package/dist/lib/connector-automations.d.ts +32 -0
- package/dist/lib/connector-automations.d.ts.map +1 -0
- package/dist/views/AutomationDetailPage.d.ts.map +1 -1
- package/dist/views/AutomationsList.d.ts.map +1 -1
- package/dist/views/ConnectorAutomations.d.ts +6 -0
- package/dist/views/ConnectorAutomations.d.ts.map +1 -0
- package/dist/views/RunLog.d.ts +9 -1
- package/dist/views/RunLog.d.ts.map +1 -1
- package/package.json +7 -4
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ResolvedFayzAgentConnection } from '@fayz-ai/admin';
|
|
2
|
+
import { type FayzAutomationsClient } from '@fayz-ai/sdk/automations';
|
|
3
|
+
import type { MessageTemplateStore } from './templates';
|
|
4
|
+
export interface FayzTemplateStoreDeps {
|
|
5
|
+
client?: FayzAutomationsClient;
|
|
6
|
+
getSessionToken?: () => Promise<string | null>;
|
|
7
|
+
}
|
|
8
|
+
export declare function createFayzTemplateStore(connection: ResolvedFayzAgentConnection, deps?: FayzTemplateStoreDeps): MessageTemplateStore;
|
|
9
|
+
/** One client per connection — RunLog and the store read the same surface. */
|
|
10
|
+
export declare function getFayzAutomationsClient(connection: ResolvedFayzAgentConnection): FayzAutomationsClient;
|
|
11
|
+
//# sourceMappingURL=fayz.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fayz.d.ts","sourceRoot":"","sources":["../../src/data/fayz.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAA;AAGjE,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAwCvD,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,qBAAqB,CAAA;IAC9B,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CAC/C;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,2BAA2B,EACvC,IAAI,GAAE,qBAA0B,GAC/B,oBAAoB,CAsItB;AAID,8EAA8E;AAC9E,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,2BAA2B,GAAG,qBAAqB,CAUvG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fayz.test.d.ts","sourceRoot":"","sources":["../../src/data/fayz.test.ts"],"names":[],"mappings":""}
|
package/dist/index.d.ts
CHANGED
|
@@ -21,5 +21,6 @@ export interface AutomationsPluginOptions {
|
|
|
21
21
|
}
|
|
22
22
|
export declare function createAutomationsPlugin(options?: AutomationsPluginOptions): PluginManifest;
|
|
23
23
|
export { createSupabaseTemplateStore };
|
|
24
|
+
export { createFayzTemplateStore } from './data/fayz';
|
|
24
25
|
export type { MessageTemplateStore };
|
|
25
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAK5E,OAAO,EAAE,2BAA2B,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAkBzF,MAAM,WAAW,wBAAwB;IACvC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAA;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,KAAK,GAAG,UAAU,CAAA;IAC9B,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,oBAAoB,CAAA;CAC7B;AAED,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,cAAc,CAkE1F;AAED,OAAO,EAAE,2BAA2B,EAAE,CAAA;AACtC,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AACrD,YAAY,EAAE,oBAAoB,EAAE,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,147 @@
|
|
|
1
1
|
import React3 from 'react';
|
|
2
|
-
import { startEventLog, getSupabaseClientOptional, usePluginRuntimeOptional, resolveMessages, resolveMessage, renderMessageTemplate, loadEventRuns } from '@fayz-ai/core';
|
|
2
|
+
import { startEventLog, getSupabaseClientOptional, getMessageDefaults, usePluginRuntimeOptional, resolveMessages, resolveMessage, renderMessageTemplate, loadEventRuns } from '@fayz-ai/core';
|
|
3
|
+
import { resolveFayzAgentConnection, getFayzSupabaseClientOptional, useConnectors, adminNavigateTo, useOrganizationStore, connectorRoute, ConnectorMark, ConnectorDeliveries } from '@fayz-ai/admin';
|
|
3
4
|
import * as LucideIcons from 'lucide-react';
|
|
4
|
-
import { Zap, MessageSquare, Smartphone, MessageCircle, Mail, ChevronRight, RotateCcw, Clock, Monitor, RefreshCw, History, AlertTriangle,
|
|
5
|
+
import { Zap, MessageSquare, Smartphone, MessageCircle, Mail, ChevronRight, RotateCcw, Clock, Monitor, RefreshCw, History, AlertTriangle, CircleCheck, CircleSlash } from 'lucide-react';
|
|
5
6
|
import { HeaderTabs, Card, Switch, SubpageHeader, Button, Badge, Hint, toast } from '@fayz-ai/ui';
|
|
6
|
-
import { adminNavigateTo, useOrganizationStore } from '@fayz-ai/admin';
|
|
7
7
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
8
|
+
import { createFayzAutomationsClient, FayzAutomationsError } from '@fayz-ai/sdk/automations';
|
|
8
9
|
|
|
9
10
|
// src/index.ts
|
|
10
11
|
function useOrganizationStoreLike() {
|
|
11
12
|
return useOrganizationStore((s) => s.currentOrg?.id);
|
|
12
13
|
}
|
|
14
|
+
|
|
15
|
+
// src/lib/connector-automations.ts
|
|
16
|
+
function connectorAutomationRows(connectors) {
|
|
17
|
+
const out = [];
|
|
18
|
+
for (const connector of connectors) {
|
|
19
|
+
if (connector.state !== "connected") continue;
|
|
20
|
+
for (const auto of connector.definition?.managedAutomations ?? []) {
|
|
21
|
+
out.push({
|
|
22
|
+
connectorId: connector.id,
|
|
23
|
+
connectorName: connector.name,
|
|
24
|
+
hostPluginId: connector.hostPluginId,
|
|
25
|
+
icon: connector.icon,
|
|
26
|
+
logoUrl: connector.logoUrl,
|
|
27
|
+
eventKey: auto.eventKey,
|
|
28
|
+
label: auto.label,
|
|
29
|
+
optional: auto.optional ?? false,
|
|
30
|
+
...connector.definition?.listDeliveries ? { listDeliveries: connector.definition.listDeliveries.bind(connector.definition) } : {}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
function groupConnectorAutomations(rows) {
|
|
37
|
+
const groups = [];
|
|
38
|
+
for (const row of rows) {
|
|
39
|
+
let group = groups.find((g) => g.connectorId === row.connectorId);
|
|
40
|
+
if (!group) {
|
|
41
|
+
group = {
|
|
42
|
+
connectorId: row.connectorId,
|
|
43
|
+
connectorName: row.connectorName,
|
|
44
|
+
hostPluginId: row.hostPluginId,
|
|
45
|
+
icon: row.icon,
|
|
46
|
+
logoUrl: row.logoUrl,
|
|
47
|
+
items: []
|
|
48
|
+
};
|
|
49
|
+
groups.push(group);
|
|
50
|
+
}
|
|
51
|
+
group.items.push(row);
|
|
52
|
+
}
|
|
53
|
+
return groups;
|
|
54
|
+
}
|
|
55
|
+
function ConnectorAutomations({ rows }) {
|
|
56
|
+
if (rows.length === 0) return null;
|
|
57
|
+
return /* @__PURE__ */ jsx(Fragment, { children: groupConnectorAutomations(rows).map((group) => {
|
|
58
|
+
const href = connectorRoute({ hostPluginId: group.hostPluginId });
|
|
59
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
60
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: group.connectorName }),
|
|
61
|
+
group.items.map((row) => /* @__PURE__ */ jsx(
|
|
62
|
+
AutomationCard,
|
|
63
|
+
{
|
|
64
|
+
row,
|
|
65
|
+
group,
|
|
66
|
+
href
|
|
67
|
+
},
|
|
68
|
+
`${group.connectorId}:${row.eventKey}`
|
|
69
|
+
))
|
|
70
|
+
] }, group.connectorId);
|
|
71
|
+
}) });
|
|
72
|
+
}
|
|
73
|
+
function AutomationCard({
|
|
74
|
+
row,
|
|
75
|
+
group,
|
|
76
|
+
href
|
|
77
|
+
}) {
|
|
78
|
+
const [open, setOpen] = React3.useState(false);
|
|
79
|
+
return /* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
|
|
80
|
+
/* @__PURE__ */ jsxs(
|
|
81
|
+
"div",
|
|
82
|
+
{
|
|
83
|
+
role: "button",
|
|
84
|
+
tabIndex: 0,
|
|
85
|
+
onClick: () => adminNavigateTo(href),
|
|
86
|
+
onKeyDown: (e) => {
|
|
87
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
88
|
+
e.preventDefault();
|
|
89
|
+
adminNavigateTo(href);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
className: "flex cursor-pointer items-start gap-4 p-4 transition-colors hover:bg-muted/30 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ jsx(
|
|
95
|
+
ConnectorMark,
|
|
96
|
+
{
|
|
97
|
+
connector: {
|
|
98
|
+
id: group.connectorId,
|
|
99
|
+
name: group.connectorName,
|
|
100
|
+
icon: group.icon,
|
|
101
|
+
logoUrl: group.logoUrl
|
|
102
|
+
},
|
|
103
|
+
size: "sm"
|
|
104
|
+
}
|
|
105
|
+
),
|
|
106
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
107
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium", children: row.label }),
|
|
108
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
109
|
+
"Quando ",
|
|
110
|
+
/* @__PURE__ */ jsx("code", { className: "font-mono text-xs", children: row.eventKey }),
|
|
111
|
+
" acontece aqui."
|
|
112
|
+
] })
|
|
113
|
+
] }),
|
|
114
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 pt-0.5 text-right text-xs text-muted-foreground", children: row.optional ? `Opcional \u2014 desligue em ${group.connectorName}` : `Ligada pela integra\xE7\xE3o \xB7 sai ao desconectar ${group.connectorName}` })
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
),
|
|
118
|
+
row.listDeliveries && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
119
|
+
/* @__PURE__ */ jsxs(
|
|
120
|
+
"button",
|
|
121
|
+
{
|
|
122
|
+
type: "button",
|
|
123
|
+
onClick: () => setOpen(!open),
|
|
124
|
+
"aria-expanded": open,
|
|
125
|
+
className: "flex w-full items-center gap-2 border-t border-border px-4 py-2 text-left transition-colors hover:bg-muted/40",
|
|
126
|
+
children: [
|
|
127
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: `h-3.5 w-3.5 shrink-0 text-muted-foreground transition-transform ${open ? "rotate-90" : ""}` }),
|
|
128
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium", children: [
|
|
129
|
+
"O que j\xE1 foi para o ",
|
|
130
|
+
group.connectorName
|
|
131
|
+
] })
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
),
|
|
135
|
+
open && /* @__PURE__ */ jsx("div", { className: "border-t border-border p-4", children: /* @__PURE__ */ jsx(
|
|
136
|
+
ConnectorDeliveries,
|
|
137
|
+
{
|
|
138
|
+
load: (options) => row.listDeliveries({ ...options, eventKey: row.eventKey }),
|
|
139
|
+
providerName: group.connectorName
|
|
140
|
+
}
|
|
141
|
+
) })
|
|
142
|
+
] })
|
|
143
|
+
] });
|
|
144
|
+
}
|
|
13
145
|
var CHANNEL_ICON = {
|
|
14
146
|
email: Mail,
|
|
15
147
|
whatsapp: MessageCircle,
|
|
@@ -44,6 +176,8 @@ function AutomationsList({ store }) {
|
|
|
44
176
|
const runtime = usePluginRuntimeOptional();
|
|
45
177
|
const [messages, setMessages] = React3.useState(null);
|
|
46
178
|
const [kind, setKind] = React3.useState("all");
|
|
179
|
+
const { connectors } = useConnectors({ includeGrants: false, includeCatalog: false });
|
|
180
|
+
const owned = React3.useMemo(() => connectorAutomationRows(connectors ?? []), [connectors]);
|
|
47
181
|
const reload = React3.useCallback(async () => {
|
|
48
182
|
let overrides = [];
|
|
49
183
|
try {
|
|
@@ -68,7 +202,9 @@ function AutomationsList({ store }) {
|
|
|
68
202
|
}
|
|
69
203
|
};
|
|
70
204
|
const visible = (messages ?? []).filter((m) => kind === "all" || m.kind === kind);
|
|
71
|
-
const
|
|
205
|
+
const ownedVisible = kind === "all" ? owned : [];
|
|
206
|
+
const activeCount = (messages ?? []).filter((m) => m.enabled).length + owned.length;
|
|
207
|
+
const totalCount = (messages?.length ?? 0) + owned.length;
|
|
72
208
|
const groups = [];
|
|
73
209
|
for (const m of visible) {
|
|
74
210
|
let g = groups.find((x) => x.module === m.event.pluginId);
|
|
@@ -84,7 +220,7 @@ function AutomationsList({ store }) {
|
|
|
84
220
|
messages !== null && /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", children: [
|
|
85
221
|
activeCount,
|
|
86
222
|
" de ",
|
|
87
|
-
|
|
223
|
+
totalCount,
|
|
88
224
|
" automa\xE7\xF5es ativas"
|
|
89
225
|
] })
|
|
90
226
|
] }),
|
|
@@ -92,7 +228,7 @@ function AutomationsList({ store }) {
|
|
|
92
228
|
messages === null ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsxs(Card, { className: "p-4", children: [
|
|
93
229
|
/* @__PURE__ */ jsx("div", { className: "h-4 w-40 animate-pulse rounded bg-muted" }),
|
|
94
230
|
/* @__PURE__ */ jsx("div", { className: "mt-2 h-3 w-64 animate-pulse rounded bg-muted" })
|
|
95
|
-
] }, i)) }) : groups.length === 0 ? /* @__PURE__ */ jsxs(Card, { className: "flex flex-col items-center gap-1 p-12 text-center", children: [
|
|
231
|
+
] }, i)) }) : groups.length === 0 && ownedVisible.length === 0 ? /* @__PURE__ */ jsxs(Card, { className: "flex flex-col items-center gap-1 p-12 text-center", children: [
|
|
96
232
|
/* @__PURE__ */ jsx(Zap, { className: "mb-2 h-9 w-9 text-muted-foreground/40", strokeWidth: 1.5 }),
|
|
97
233
|
/* @__PURE__ */ jsx("p", { className: "text-base font-semibold", children: "Nenhuma automa\xE7\xE3o nesta aba" }),
|
|
98
234
|
/* @__PURE__ */ jsx("p", { className: "max-w-sm text-sm text-muted-foreground", children: "Os eventos v\xEAm dos m\xF3dulos instalados \u2014 a loja traz os do pedido, o CRM os do funil." })
|
|
@@ -155,14 +291,164 @@ function AutomationsList({ store }) {
|
|
|
155
291
|
`${m.event.name}:${m.channel}`
|
|
156
292
|
);
|
|
157
293
|
})
|
|
158
|
-
] }, group.module))
|
|
294
|
+
] }, group.module)),
|
|
295
|
+
messages !== null && /* @__PURE__ */ jsx(ConnectorAutomations, { rows: ownedVisible })
|
|
159
296
|
] });
|
|
160
297
|
}
|
|
298
|
+
function toTemplate(automation) {
|
|
299
|
+
const eventKey = automation.triggerConfig?.eventKey;
|
|
300
|
+
if (!eventKey) return null;
|
|
301
|
+
const action = automation.actions?.[0];
|
|
302
|
+
return {
|
|
303
|
+
id: automation.id,
|
|
304
|
+
tenantId: automation.tenantId ?? "",
|
|
305
|
+
eventKey,
|
|
306
|
+
channel: automation.triggerConfig.sourceChannel ?? "email",
|
|
307
|
+
enabled: automation.enabled,
|
|
308
|
+
// Empty and absent mean the same — "no customisation", the catalogue default.
|
|
309
|
+
subject: action?.config?.subject || null,
|
|
310
|
+
body: action?.config?.body || null,
|
|
311
|
+
// The automation name belongs to the platform, not a user rename: the
|
|
312
|
+
// catalogue title still owns the screen.
|
|
313
|
+
name: null,
|
|
314
|
+
updatedAt: automation.updatedAt
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function catalogDefaultEnabled(eventKey, channel) {
|
|
318
|
+
const def = getMessageDefaults().find((d) => d.eventKey === eventKey);
|
|
319
|
+
return def?.defaultEnabled?.[channel] ?? false;
|
|
320
|
+
}
|
|
321
|
+
async function defaultSessionToken() {
|
|
322
|
+
const session = (await getFayzSupabaseClientOptional()?.auth.getSession())?.data.session;
|
|
323
|
+
return session?.access_token ?? null;
|
|
324
|
+
}
|
|
325
|
+
function createFayzTemplateStore(connection, deps = {}) {
|
|
326
|
+
const client = deps.client ?? createFayzAutomationsClient({
|
|
327
|
+
baseUrl: connection.apiBaseUrl,
|
|
328
|
+
projectId: connection.projectId,
|
|
329
|
+
publishableKey: connection.publishableKey
|
|
330
|
+
});
|
|
331
|
+
const getSessionToken = deps.getSessionToken ?? defaultSessionToken;
|
|
332
|
+
const ids = /* @__PURE__ */ new Map();
|
|
333
|
+
const keyOf = (eventKey, channel) => `${eventKey}:${channel}`;
|
|
334
|
+
async function refresh(tenantId) {
|
|
335
|
+
const automations = await client.list({ tenantId });
|
|
336
|
+
ids.clear();
|
|
337
|
+
const rows = [];
|
|
338
|
+
for (const automation of automations) {
|
|
339
|
+
const row = toTemplate(automation);
|
|
340
|
+
if (!row) continue;
|
|
341
|
+
ids.set(keyOf(row.eventKey, row.channel), automation.id);
|
|
342
|
+
rows.push(row);
|
|
343
|
+
}
|
|
344
|
+
return rows;
|
|
345
|
+
}
|
|
346
|
+
const LIST_TTL_MS = 3e4;
|
|
347
|
+
let cache = null;
|
|
348
|
+
function invalidate() {
|
|
349
|
+
cache = null;
|
|
350
|
+
}
|
|
351
|
+
function load(tenantId) {
|
|
352
|
+
if (cache && cache.tenantId === tenantId && Date.now() - cache.at < LIST_TTL_MS) return cache.promise;
|
|
353
|
+
const promise = refresh(tenantId);
|
|
354
|
+
promise.catch(() => {
|
|
355
|
+
if (cache?.promise === promise) cache = null;
|
|
356
|
+
});
|
|
357
|
+
cache = { tenantId, at: Date.now(), promise };
|
|
358
|
+
return promise;
|
|
359
|
+
}
|
|
360
|
+
async function requireToken() {
|
|
361
|
+
const token = await getSessionToken();
|
|
362
|
+
if (!token) throw new Error("Sess\xE3o expirada \u2014 entre de novo.");
|
|
363
|
+
return token;
|
|
364
|
+
}
|
|
365
|
+
async function resolveId(eventKey, channel, tenantId) {
|
|
366
|
+
const key = keyOf(eventKey, channel);
|
|
367
|
+
if (!ids.has(key)) await load(tenantId);
|
|
368
|
+
return ids.get(key);
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
async list(tenantId) {
|
|
372
|
+
if (!tenantId) return [];
|
|
373
|
+
return load(tenantId);
|
|
374
|
+
},
|
|
375
|
+
async upsert(input, tenantId) {
|
|
376
|
+
if (!tenantId) throw new Error("@fayz-ai/plugin-automations: tenantId is required");
|
|
377
|
+
const appSessionToken = await requireToken();
|
|
378
|
+
const key = keyOf(input.eventKey, input.channel);
|
|
379
|
+
let id = await resolveId(input.eventKey, input.channel, tenantId);
|
|
380
|
+
if (!id) {
|
|
381
|
+
const action = {};
|
|
382
|
+
if (input.subject != null) action.subject = input.subject;
|
|
383
|
+
if (input.body != null) action.body = input.body;
|
|
384
|
+
try {
|
|
385
|
+
const created = await client.create({
|
|
386
|
+
tenantId,
|
|
387
|
+
appSessionToken,
|
|
388
|
+
eventKey: input.eventKey,
|
|
389
|
+
sourceChannel: input.channel,
|
|
390
|
+
// The platform has no "inherit from catalogue": materialise the default.
|
|
391
|
+
enabled: input.enabled ?? catalogDefaultEnabled(input.eventKey, input.channel),
|
|
392
|
+
...Object.keys(action).length ? { action } : {}
|
|
393
|
+
});
|
|
394
|
+
ids.set(key, created.id);
|
|
395
|
+
invalidate();
|
|
396
|
+
const row2 = toTemplate(created);
|
|
397
|
+
if (!row2) throw new Error("@fayz-ai/plugin-automations: platform did not round-trip eventKey");
|
|
398
|
+
return row2;
|
|
399
|
+
} catch (err) {
|
|
400
|
+
if (!(err instanceof FayzAutomationsError) || err.status !== 409) throw err;
|
|
401
|
+
invalidate();
|
|
402
|
+
await refresh(tenantId);
|
|
403
|
+
id = ids.get(key);
|
|
404
|
+
if (!id) throw err;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
const updated = await client.update({
|
|
408
|
+
id,
|
|
409
|
+
tenantId,
|
|
410
|
+
appSessionToken,
|
|
411
|
+
// Only what was sent: omitting has to mean "leave it alone", as in the local store.
|
|
412
|
+
...typeof input.enabled === "boolean" ? { enabled: input.enabled } : {},
|
|
413
|
+
...input.subject !== void 0 || input.body !== void 0 ? {
|
|
414
|
+
action: {
|
|
415
|
+
...input.subject !== void 0 ? { subject: input.subject } : {},
|
|
416
|
+
...input.body !== void 0 ? { body: input.body } : {}
|
|
417
|
+
}
|
|
418
|
+
} : {}
|
|
419
|
+
});
|
|
420
|
+
invalidate();
|
|
421
|
+
const row = toTemplate(updated);
|
|
422
|
+
if (!row) throw new Error("@fayz-ai/plugin-automations: platform did not round-trip eventKey");
|
|
423
|
+
return row;
|
|
424
|
+
},
|
|
425
|
+
async reset(eventKey, channel, tenantId) {
|
|
426
|
+
if (!tenantId) return;
|
|
427
|
+
const id = await resolveId(eventKey, channel, tenantId);
|
|
428
|
+
if (!id) return;
|
|
429
|
+
const appSessionToken = await requireToken();
|
|
430
|
+
await client.update({ id, tenantId, appSessionToken, action: { subject: null, body: null } });
|
|
431
|
+
invalidate();
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
var cachedClient = null;
|
|
436
|
+
function getFayzAutomationsClient(connection) {
|
|
437
|
+
const key = `${connection.apiBaseUrl}|${connection.projectId}|${connection.publishableKey}`;
|
|
438
|
+
if (cachedClient?.key === key) return cachedClient.client;
|
|
439
|
+
const client = createFayzAutomationsClient({
|
|
440
|
+
baseUrl: connection.apiBaseUrl,
|
|
441
|
+
projectId: connection.projectId,
|
|
442
|
+
publishableKey: connection.publishableKey
|
|
443
|
+
});
|
|
444
|
+
cachedClient = { key, client };
|
|
445
|
+
return client;
|
|
446
|
+
}
|
|
161
447
|
var STATUS = {
|
|
162
448
|
sent: { label: "Enviado", hint: "A mensagem saiu.", variant: "success", Icon: CircleCheck },
|
|
163
449
|
recorded: {
|
|
164
450
|
label: "Disparou",
|
|
165
|
-
//
|
|
451
|
+
// Today's honest state: the trigger works, the send doesn't exist yet.
|
|
166
452
|
hint: "O gatilho disparou e ficou registrado. O envio autom\xE1tico ainda n\xE3o est\xE1 ligado neste ambiente.",
|
|
167
453
|
variant: "info",
|
|
168
454
|
Icon: History
|
|
@@ -240,6 +526,56 @@ function RunLog({ eventKey, tenantId, enabled }) {
|
|
|
240
526
|
] }) : /* @__PURE__ */ jsx("div", { children: runs.map((run) => /* @__PURE__ */ jsx(RunRow, { run }, run.id)) })
|
|
241
527
|
] });
|
|
242
528
|
}
|
|
529
|
+
var EXEC_STATUS = {
|
|
530
|
+
success: { label: "Executada", variant: "success", Icon: CircleCheck },
|
|
531
|
+
error: { label: "Falhou", variant: "destructive", Icon: AlertTriangle }
|
|
532
|
+
};
|
|
533
|
+
function ExecutionRow({ execution }) {
|
|
534
|
+
const cfg = EXEC_STATUS[execution.status] ?? { label: execution.status, variant: "info", Icon: History };
|
|
535
|
+
const { Icon } = cfg;
|
|
536
|
+
return /* @__PURE__ */ jsxs("div", { className: "border-b border-border px-4 py-2.5 last:border-b-0", children: [
|
|
537
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
538
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
539
|
+
/* @__PURE__ */ jsx(Badge, { variant: cfg.variant, children: cfg.label }),
|
|
540
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm text-muted-foreground", children: execution.automationName }),
|
|
541
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs text-muted-foreground", children: when(execution.executedAt) })
|
|
542
|
+
] }),
|
|
543
|
+
execution.error && /* @__PURE__ */ jsx("p", { className: "ml-6 mt-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 font-mono text-[11px] text-destructive", children: execution.error })
|
|
544
|
+
] });
|
|
545
|
+
}
|
|
546
|
+
function FayzRunLog({ connection, eventKey, tenantId, enabled }) {
|
|
547
|
+
const [executions, setExecutions] = React3.useState(null);
|
|
548
|
+
const [loading, setLoading] = React3.useState(false);
|
|
549
|
+
const load = React3.useCallback(async () => {
|
|
550
|
+
if (!tenantId) return;
|
|
551
|
+
setLoading(true);
|
|
552
|
+
try {
|
|
553
|
+
setExecutions(await getFayzAutomationsClient(connection).listExecutions({ tenantId, eventKey, limit: 20 }));
|
|
554
|
+
} catch (err) {
|
|
555
|
+
console.warn("[automations] could not load platform executions", err);
|
|
556
|
+
setExecutions([]);
|
|
557
|
+
} finally {
|
|
558
|
+
setLoading(false);
|
|
559
|
+
}
|
|
560
|
+
}, [connection, eventKey, tenantId]);
|
|
561
|
+
React3.useEffect(() => {
|
|
562
|
+
void load();
|
|
563
|
+
}, [load]);
|
|
564
|
+
return /* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
|
|
565
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 border-b border-border px-4 py-2.5", children: [
|
|
566
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
567
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Execu\xE7\xF5es recentes" }),
|
|
568
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "O que a plataforma Fayz executou para este gatilho nesta conta." })
|
|
569
|
+
] }),
|
|
570
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => void load(), disabled: loading, children: /* @__PURE__ */ jsx(RefreshCw, { className: `h-3.5 w-3.5 ${loading ? "animate-spin" : ""}` }) })
|
|
571
|
+
] }),
|
|
572
|
+
executions === null ? /* @__PURE__ */ jsx("div", { className: "space-y-2 p-4", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsx("div", { className: "h-8 animate-pulse rounded bg-muted/40" }, i)) }) : executions.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 px-4 py-10 text-center", children: [
|
|
573
|
+
/* @__PURE__ */ jsx(History, { className: "h-7 w-7 text-muted-foreground/40", strokeWidth: 1.5 }),
|
|
574
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Nenhuma execu\xE7\xE3o ainda" }),
|
|
575
|
+
/* @__PURE__ */ jsx("p", { className: "max-w-sm text-xs text-muted-foreground", children: enabled ? "Assim que este evento acontecer, a plataforma executa a automa\xE7\xE3o e o resultado aparece aqui." : "A automa\xE7\xE3o est\xE1 desligada \u2014 a plataforma n\xE3o executa nada para este gatilho." })
|
|
576
|
+
] }) : /* @__PURE__ */ jsx("div", { children: executions.map((e) => /* @__PURE__ */ jsx(ExecutionRow, { execution: e }, e.id)) })
|
|
577
|
+
] });
|
|
578
|
+
}
|
|
243
579
|
var TABS = [
|
|
244
580
|
{ value: "preview", label: "Pr\xE9via" },
|
|
245
581
|
{ value: "code", label: "C\xF3digo" },
|
|
@@ -280,6 +616,7 @@ function iconFor2(name) {
|
|
|
280
616
|
function AutomationDetailPage({ eventKey, channel, store, backTo = "/automations" }) {
|
|
281
617
|
const tenantId = useOrganizationStoreLike();
|
|
282
618
|
const runtime = usePluginRuntimeOptional();
|
|
619
|
+
const fayzConnection = React3.useMemo(() => resolveFayzAgentConnection(), []);
|
|
283
620
|
const [message, setMessage] = React3.useState(void 0);
|
|
284
621
|
const [tab, setTab] = React3.useState("preview");
|
|
285
622
|
const [device, setDevice] = React3.useState("desktop");
|
|
@@ -421,7 +758,11 @@ function AutomationDetailPage({ eventKey, channel, store, backTo = "/automations
|
|
|
421
758
|
current.subject
|
|
422
759
|
] })
|
|
423
760
|
] }),
|
|
424
|
-
tab === "runs" ?
|
|
761
|
+
tab === "runs" ? (
|
|
762
|
+
// Atrás de um projeto Fayz o histórico verdadeiro é o da plataforma —
|
|
763
|
+
// é ela quem executa. Fora dele, o coletor local continua valendo.
|
|
764
|
+
fayzConnection ? /* @__PURE__ */ jsx(FayzRunLog, { connection: fayzConnection, eventKey: event.name, tenantId, enabled: message.enabled }) : /* @__PURE__ */ jsx(RunLog, { eventKey: event.name, tenantId, enabled: message.enabled })
|
|
765
|
+
) : tab === "preview" ? /* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
|
|
425
766
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 border-b border-border px-4 py-2.5", children: [
|
|
426
767
|
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Pr\xE9via" }),
|
|
427
768
|
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: ["desktop", "mobile"].map((d) => /* @__PURE__ */ jsx(
|
|
@@ -542,7 +883,8 @@ function createSupabaseTemplateStore() {
|
|
|
542
883
|
|
|
543
884
|
// src/index.ts
|
|
544
885
|
function createAutomationsPlugin(options) {
|
|
545
|
-
const
|
|
886
|
+
const connection = resolveFayzAgentConnection();
|
|
887
|
+
const store = options?.store ?? (connection ? createFayzTemplateStore(connection) : createSupabaseTemplateStore());
|
|
546
888
|
startEventLog();
|
|
547
889
|
const inSettings = options?.placement === "settings";
|
|
548
890
|
const ListPage = () => React3.createElement(AutomationsList, { store });
|
|
@@ -592,6 +934,6 @@ function createAutomationsPlugin(options) {
|
|
|
592
934
|
};
|
|
593
935
|
}
|
|
594
936
|
|
|
595
|
-
export { createAutomationsPlugin, createSupabaseTemplateStore };
|
|
937
|
+
export { createAutomationsPlugin, createFayzTemplateStore, createSupabaseTemplateStore };
|
|
596
938
|
//# sourceMappingURL=index.js.map
|
|
597
939
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/runtime.ts","../src/views/AutomationsList.tsx","../src/views/RunLog.tsx","../src/views/AutomationDetailPage.tsx","../src/data/templates.ts","../src/index.ts"],"names":["React","jsxs","jsx","ChevronRight","Card","CHANNEL_LABEL","iconFor","Zap","LucideIcons","usePluginRuntimeOptional","adminNavigateTo","Mail","Button","toast","Badge","Switch","HeaderTabs","Smartphone"],"mappings":"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","file":"index.js","sourcesContent":["import { useOrganizationStore } from '@fayz-ai/admin'\n\n// Re-exports para as views não precisarem saber de onde vem cada peça.\nexport {\n resolveMessages, resolveMessage, renderMessageTemplate,\n getEventsWithoutMessages,\n} from '@fayz-ai/core'\n\n/** Conta ativa — todo modelo é escopado nela. */\nexport function useOrganizationStoreLike(): string | undefined {\n return useOrganizationStore((s) => s.currentOrg?.id)\n}\n","import React from 'react'\nimport * as LucideIcons from 'lucide-react'\nimport { ChevronRight, Mail, MessageCircle, MessageSquare, Smartphone, Zap } from 'lucide-react'\nimport { Card, HeaderTabs, Switch, toast } from '@fayz-ai/ui'\nimport { adminNavigateTo } from '@fayz-ai/admin'\nimport { resolveMessages, useOrganizationStoreLike } from '../lib/runtime'\nimport { usePluginRuntimeOptional } from '@fayz-ai/core'\nimport type { MessageChannel, MessageKind, ResolvedMessage } from '@fayz-ai/core'\nimport type { MessageTemplateStore } from '../data/templates'\n\n// ---------------------------------------------------------------------------\n// Automações — quando ISTO acontece, mande AQUILO.\n//\n// Cada linha é uma automação inteira: o gatilho à esquerda, o canal na\n// pastilha, o interruptor à direita. Não existe \"modelo\" separado do \"fluxo\" —\n// um texto sem gatilho nunca sai, e um fluxo de um passo é o texto com o\n// gatilho escrito na frente.\n//\n// Agrupado por MÓDULO (Loja, CRM, Agenda) e não por canal, porque é assim que a\n// pergunta chega: \"o que a gente manda quando um pedido é enviado?\" — e a\n// resposta pode ser um e-mail, um WhatsApp, ou os dois. Separar por canal, como\n// fazia a tela de e-mails, obriga a visitar dois menus para responder isso.\n//\n// Cada linha é um par evento×canal. O evento aparece uma vez, com uma pastilha\n// por canal ofertado: é o desenho que o RD Station e o Kommo usam para não\n// esconder que \"confirmação de pedido\" e \"confirmação por WhatsApp\" são o mesmo\n// gatilho com duas saídas.\n// ---------------------------------------------------------------------------\n\nconst CHANNEL_ICON: Record<MessageChannel, React.ComponentType<{ className?: string }>> = {\n email: Mail,\n whatsapp: MessageCircle,\n sms: Smartphone,\n push: MessageSquare,\n webchat: MessageSquare,\n}\n\nconst CHANNEL_LABEL: Record<MessageChannel, string> = {\n email: 'E-mail', whatsapp: 'WhatsApp', sms: 'SMS', push: 'Push', webchat: 'Chat',\n}\n\nconst KIND_TABS: { value: MessageKind | 'all'; label: string }[] = [\n { value: 'all', label: 'Todos' },\n { value: 'transactional', label: 'Transacionais' },\n { value: 'marketing', label: 'Marketing' },\n]\n\nconst KIND_HINT: Record<string, string> = {\n all: 'Tudo que o produto sabe enviar, por qualquer canal.',\n transactional: 'Disparados por uma ação da pessoa. Não precisam de opt-in.',\n marketing: 'Iniciativa da empresa. Só para quem aceitou receber.',\n}\n\nfunction iconFor(name?: string): React.ComponentType<{ className?: string }> {\n if (!name) return Zap\n const icons = LucideIcons as unknown as Record<string, React.ComponentType<{ className?: string }>>\n return icons[name] ?? Zap\n}\n\nexport function AutomationsList({ store }: { store: MessageTemplateStore }) {\n const tenantId = useOrganizationStoreLike()\n // Os eventos vêm do runtime: só os plugins ATIVOS anunciam fatos.\n const runtime = usePluginRuntimeOptional()\n const [messages, setMessages] = React.useState<ResolvedMessage[] | null>(null)\n const [kind, setKind] = React.useState<MessageKind | 'all'>('all')\n\n const reload = React.useCallback(async () => {\n // Uma leitura que falha ainda mostra o catálogo inteiro nos padrões: os\n // eventos são código, então \"sem personalização\" é um estado válido e\n // completo, não uma tela vazia.\n let overrides: Awaited<ReturnType<MessageTemplateStore['list']>> = []\n try {\n overrides = await store.list(tenantId)\n } catch (err) {\n console.warn('[automations] could not load template overrides; showing defaults', err)\n }\n setMessages(resolveMessages(overrides, runtime?.events ?? []))\n }, [store, tenantId, runtime])\n\n React.useEffect(() => { void reload() }, [reload])\n\n const toggle = async (m: ResolvedMessage, enabled: boolean) => {\n setMessages((prev) => prev?.map((x) =>\n x.event.name === m.event.name && x.channel === m.channel ? { ...x, enabled } : x) ?? null)\n try {\n await store.upsert({ eventKey: m.event.name, channel: m.channel, enabled }, tenantId)\n await reload()\n } catch (err) {\n console.warn('[automations] toggle failed', err)\n toast.error('Não foi possível salvar')\n await reload()\n }\n }\n\n const visible = (messages ?? []).filter((m) => kind === 'all' || m.kind === kind)\n const activeCount = (messages ?? []).filter((m) => m.enabled).length\n\n // Agrupa por módulo preservando a ordem de registro dos plugins.\n const groups: { module: string; label: string; items: ResolvedMessage[] }[] = []\n for (const m of visible) {\n let g = groups.find((x) => x.module === m.event.pluginId)\n if (!g) { g = { module: m.event.pluginId, label: m.event.pluginName, items: [] }; groups.push(g) }\n g.items.push(m)\n }\n\n return (\n <div className=\"space-y-6\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <HeaderTabs tabs={KIND_TABS} value={kind} onChange={setKind} aria-label=\"Automações\" />\n {messages !== null && (\n <span className=\"text-sm text-muted-foreground\">\n {activeCount} de {messages.length} automações ativas\n </span>\n )}\n </div>\n\n <p className=\"text-sm text-muted-foreground\">{KIND_HINT[kind]}</p>\n\n {messages === null ? (\n <div className=\"space-y-3\">\n {Array.from({ length: 4 }).map((_, i) => (\n <Card key={i} className=\"p-4\">\n <div className=\"h-4 w-40 animate-pulse rounded bg-muted\" />\n <div className=\"mt-2 h-3 w-64 animate-pulse rounded bg-muted\" />\n </Card>\n ))}\n </div>\n ) : groups.length === 0 ? (\n <Card className=\"flex flex-col items-center gap-1 p-12 text-center\">\n <Zap className=\"mb-2 h-9 w-9 text-muted-foreground/40\" strokeWidth={1.5} />\n <p className=\"text-base font-semibold\">Nenhuma automação nesta aba</p>\n <p className=\"max-w-sm text-sm text-muted-foreground\">\n Os eventos vêm dos módulos instalados — a loja traz os do pedido, o CRM os do funil.\n </p>\n </Card>\n ) : groups.map((group) => (\n <div key={group.module} className=\"space-y-3\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n {group.label}\n </p>\n {group.items.map((m) => {\n const Icon = iconFor(m.event.icon ?? m.event.pluginIcon)\n const ChannelIcon = CHANNEL_ICON[m.channel]\n const href = `/automations/${encodeURIComponent(m.event.name)}/${m.channel}`\n return (\n <Card\n key={`${m.event.name}:${m.channel}`}\n role=\"button\"\n tabIndex={0}\n onClick={() => adminNavigateTo(href)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); adminNavigateTo(href) }\n }}\n className=\"cursor-pointer overflow-hidden transition-colors hover:border-primary/40 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <div className=\"flex items-start gap-4 p-4\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border text-muted-foreground\">\n <Icon className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"font-medium\">{m.override?.name ?? m.event.title ?? m.event.name}</p>\n <span className=\"inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-[11px] text-muted-foreground\">\n <ChannelIcon className=\"h-3 w-3\" />\n {CHANNEL_LABEL[m.channel]}\n </span>\n {m.customized && (\n <span className=\"rounded-full bg-primary/10 px-2 py-0.5 text-[11px] text-primary\">\n personalizado\n </span>\n )}\n </div>\n <p className=\"text-sm text-muted-foreground\">{m.event.description}</p>\n <div className=\"mt-2 flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground\">\n <span className=\"inline-flex items-center gap-1\">\n <Zap className=\"h-3 w-3\" />\n {m.event.trigger}\n </span>\n {m.subject && <span className=\"truncate\">Assunto: {m.subject}</span>}\n </div>\n </div>\n <div className=\"flex shrink-0 items-center gap-3\">\n {/* Switch e não checkbox: isto vale na hora, não quando\n algum Salvar for clicado. */}\n <Switch\n checked={m.enabled}\n onCheckedChange={(next) => void toggle(m, next)}\n label={m.enabled ? 'Ativo' : 'Inativo'}\n aria-label={`${m.event.title} — ${CHANNEL_LABEL[m.channel]}`}\n />\n <ChevronRight className=\"h-4 w-4 text-muted-foreground\" />\n </div>\n </div>\n </Card>\n )\n })}\n </div>\n ))}\n </div>\n )\n}\n","import React from 'react'\nimport { AlertTriangle, ChevronRight, CircleCheck, CircleSlash, History, RefreshCw } from 'lucide-react'\nimport { Badge, Button, Card } from '@fayz-ai/ui'\nimport { loadEventRuns, type EventRun, type EventRunStatus } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// As últimas execuções deste gatilho.\n//\n// A tela dizia o que DEVERIA acontecer; faltava o que ACONTECEU. Sem isso, a\n// única forma de testar uma automação era esperar um cliente reclamar — e a\n// reclamação não distingue \"não disparou\" de \"disparou e o envio falhou\", que\n// são defeitos em lugares diferentes.\n//\n// O payload fica visível (recolhido) de propósito: é ele que responde \"por que\n// saiu com o nome errado?\" sem ninguém precisar reproduzir o caso.\n//\n// Vale para QUALQUER gatilho: a lista é lida por chave de evento, e todo evento\n// emitido passa pelo mesmo coletor. Um módulo novo aparece aqui sem tocar nesta\n// tela.\n// ---------------------------------------------------------------------------\n\nconst STATUS: Record<EventRunStatus, {\n label: string; hint: string; variant: 'success' | 'info' | 'warning' | 'destructive'\n Icon: React.ComponentType<{ className?: string }>\n}> = {\n sent: { label: 'Enviado', hint: 'A mensagem saiu.', variant: 'success', Icon: CircleCheck },\n recorded: {\n label: 'Disparou',\n // O estado honesto de hoje: o gatilho funciona, o envio ainda não existe.\n hint: 'O gatilho disparou e ficou registrado. O envio automático ainda não está ligado neste ambiente.',\n variant: 'info', Icon: History,\n },\n skipped: { label: 'Ignorado', hint: 'O gatilho disparou, mas nada foi enviado — automação desligada ou sem canal.', variant: 'warning', Icon: CircleSlash },\n failed: { label: 'Falhou', hint: 'A tentativa de envio quebrou. O erro está na linha.', variant: 'destructive', Icon: AlertTriangle },\n}\n\nfunction when(iso: string): string {\n const then = new Date(iso).getTime()\n const diff = Date.now() - then\n const min = Math.round(diff / 60000)\n if (min < 1) return 'agora'\n if (min < 60) return `há ${min} min`\n const h = Math.round(min / 60)\n if (h < 24) return `há ${h} h`\n return new Date(iso).toLocaleString('pt-BR', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })\n}\n\nfunction RunRow({ run }: { run: EventRun }) {\n const [open, setOpen] = React.useState(false)\n const cfg = STATUS[run.status] ?? STATUS.recorded\n const { Icon } = cfg\n\n return (\n <div className=\"border-b border-border last:border-b-0\">\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className=\"flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors hover:bg-muted/40\"\n >\n <ChevronRight className={`h-3.5 w-3.5 shrink-0 text-muted-foreground transition-transform ${open ? 'rotate-90' : ''}`} />\n <Icon className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <Badge variant={cfg.variant}>{cfg.label}</Badge>\n <span className=\"min-w-0 flex-1 truncate text-sm text-muted-foreground\">\n {typeof run.payload.record_name === 'string' ? run.payload.record_name\n : typeof run.payload.customer_name === 'string' ? run.payload.customer_name\n : typeof run.payload.contact_name === 'string' ? run.payload.contact_name\n : run.subjectId ?? '—'}\n </span>\n <span className=\"shrink-0 text-xs text-muted-foreground\">{when(run.occurredAt)}</span>\n </button>\n\n {open && (\n <div className=\"space-y-3 bg-muted/20 px-4 pb-4 pt-1\">\n <p className=\"text-xs text-muted-foreground\">{cfg.hint}</p>\n <div>\n <p className=\"mb-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n Dados do disparo\n </p>\n <pre className=\"overflow-x-auto rounded-md border border-border bg-card p-3 font-mono text-[11px] leading-relaxed\">\n{JSON.stringify(run.payload, null, 2)}\n </pre>\n </div>\n {run.result && (\n <div>\n <p className=\"mb-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n Resultado\n </p>\n <pre className=\"overflow-x-auto rounded-md border border-border bg-card p-3 font-mono text-[11px] leading-relaxed\">\n{JSON.stringify(run.result, null, 2)}\n </pre>\n </div>\n )}\n {run.error && (\n <p className=\"rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 font-mono text-[11px] text-destructive\">\n {run.error}\n </p>\n )}\n </div>\n )}\n </div>\n )\n}\n\nexport function RunLog({ eventKey, tenantId, enabled }: {\n eventKey: string\n tenantId?: string\n /** Estado atual da automação — muda o que o vazio significa. */\n enabled: boolean\n}) {\n const [runs, setRuns] = React.useState<EventRun[] | null>(null)\n const [loading, setLoading] = React.useState(false)\n\n const load = React.useCallback(async () => {\n setLoading(true)\n setRuns(await loadEventRuns(eventKey, { tenantId, limit: 20 }))\n setLoading(false)\n }, [eventKey, tenantId])\n\n React.useEffect(() => { void load() }, [load])\n\n return (\n <Card className=\"overflow-hidden\">\n <div className=\"flex items-center justify-between gap-3 border-b border-border px-4 py-2.5\">\n <div className=\"min-w-0\">\n <span className=\"text-sm font-medium\">Execuções recentes</span>\n <p className=\"text-xs text-muted-foreground\">Cada vez que este gatilho disparou nesta conta.</p>\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void load()} disabled={loading}>\n <RefreshCw className={`h-3.5 w-3.5 ${loading ? 'animate-spin' : ''}`} />\n </Button>\n </div>\n\n {runs === null ? (\n <div className=\"space-y-2 p-4\">\n {[1, 2, 3].map((i) => <div key={i} className=\"h-8 animate-pulse rounded bg-muted/40\" />)}\n </div>\n ) : runs.length === 0 ? (\n <div className=\"flex flex-col items-center gap-1 px-4 py-10 text-center\">\n <History className=\"h-7 w-7 text-muted-foreground/40\" strokeWidth={1.5} />\n <p className=\"text-sm font-medium\">Nenhum disparo ainda</p>\n <p className=\"max-w-sm text-xs text-muted-foreground\">\n {enabled\n ? 'Assim que este evento acontecer, ele aparece aqui — mesmo antes de existir envio.'\n : 'A automação está desligada. O gatilho continua sendo registrado aqui quando o evento acontecer.'}\n </p>\n </div>\n ) : (\n <div>{runs.map((run) => <RunRow key={run.id} run={run} />)}</div>\n )}\n </Card>\n )\n}\n","import React from 'react'\nimport * as LucideIcons from 'lucide-react'\nimport { Clock, Mail, Monitor, RotateCcw, Smartphone, Zap } from 'lucide-react'\nimport { Badge, Button, Card, HeaderTabs, Hint, SubpageHeader, Switch, toast } from '@fayz-ai/ui'\nimport { adminNavigateTo } from '@fayz-ai/admin'\nimport type { MessageChannel, ResolvedMessage } from '@fayz-ai/core'\nimport { usePluginRuntimeOptional } from '@fayz-ai/core'\nimport { resolveMessage, renderMessageTemplate, useOrganizationStoreLike } from '../lib/runtime'\nimport { RunLog } from './RunLog'\nimport type { MessageTemplateStore } from '../data/templates'\n\n// ---------------------------------------------------------------------------\n// Um modelo, em tela cheia. Duas visões do MESMO texto:\n// Prévia o que a pessoa recebe, com os campos já substituídos\n// Código o texto-fonte, onde se edita\n//\n// A substituição da prévia é a de @fayz-ai/core (renderMessageTemplate), não um\n// replace local: prévia e envio precisam concordar, senão aprova-se um texto e\n// entrega-se outro.\n//\n// \"Igual ao padrão\" é gravado como AUSÊNCIA de personalização (null), não como\n// cópia — assim melhorias no texto padrão continuam chegando a quem nunca\n// mexeu. É o mesmo motivo pelo qual \"Restaurar padrão\" APAGA a linha em vez de\n// escrever o texto de fábrica nela.\n// ---------------------------------------------------------------------------\n\ntype ViewTab = 'preview' | 'code' | 'runs'\n\nconst TABS: { value: ViewTab; label: string }[] = [\n { value: 'preview', label: 'Prévia' },\n { value: 'code', label: 'Código' },\n // O que já aconteceu. Fica ao lado do texto, e não numa tela à parte, porque\n // é a mesma pergunta em dois tempos: o que vai sair, e o que saiu.\n { value: 'runs', label: 'Execuções' },\n]\n\nconst CHANNEL_LABEL: Record<MessageChannel, string> = {\n email: 'E-mail', whatsapp: 'WhatsApp', sms: 'SMS', push: 'Push', webchat: 'Chat',\n}\n\n/** Dados de exemplo da prévia. Não são de ninguém — a tela diz isso. */\nconst SAMPLE: Record<string, string> = {\n store_name: 'Sua Loja', company_name: 'Sua Empresa',\n customer_name: 'Maria Silva', contact_name: 'Maria Silva', lead_name: 'Maria Silva',\n order_number: '1042', order_total: 'R$ 189,90',\n order_items: '1 × Camiseta Clássica — R$ 89,90\\n2 × Caneca Esmaltada — R$ 100,00',\n tracking_code: 'BR123456789BR', cart_url: 'https://sualoja.com.br/carrinho',\n deal_name: 'Proposta — Reforma da fachada', deal_value: 'R$ 12.400,00',\n stage_name: 'Negociação', owner_name: 'João Pereira',\n appointment_date: '12/08/2026', appointment_time: '14:30',\n}\n\nfunction iconFor(name?: string): React.ComponentType<{ className?: string }> {\n if (!name) return Zap\n const icons = LucideIcons as unknown as Record<string, React.ComponentType<{ className?: string }>>\n return icons[name] ?? Zap\n}\n\nexport interface AutomationDetailPageProps {\n eventKey?: string\n channel?: string\n store: MessageTemplateStore\n /** Para onde o \"voltar\" leva — a lista pode morar no menu ou nas\n * configurações, e a pessoa tem que voltar por onde entrou. */\n backTo?: string\n}\n\nexport function AutomationDetailPage({ eventKey, channel, store, backTo = '/automations' }: AutomationDetailPageProps) {\n const tenantId = useOrganizationStoreLike()\n const runtime = usePluginRuntimeOptional()\n const [message, setMessage] = React.useState<ResolvedMessage | null | undefined>(undefined)\n const [tab, setTab] = React.useState<ViewTab>('preview')\n const [device, setDevice] = React.useState<'desktop' | 'mobile'>('desktop')\n const [draft, setDraft] = React.useState<{ subject: string; body: string } | null>(null)\n const [saving, setSaving] = React.useState(false)\n\n const back = React.useCallback(() => adminNavigateTo(backTo), [backTo])\n\n const reload = React.useCallback(async () => {\n if (!eventKey || !channel) { setMessage(null); return }\n let overrides: Awaited<ReturnType<MessageTemplateStore['list']>> = []\n try {\n overrides = await store.list(tenantId)\n } catch (err) {\n console.warn('[automations] could not load overrides; showing defaults', err)\n }\n const found = resolveMessage(decodeURIComponent(eventKey), channel as MessageChannel, overrides, runtime?.events ?? [])\n setMessage(found)\n if (found) setDraft({ subject: found.subject, body: found.body })\n }, [eventKey, channel, store, tenantId, runtime])\n\n React.useEffect(() => { void reload() }, [reload])\n\n const header = (\n <SubpageHeader\n title={message === undefined ? '' : (message?.override?.name ?? message?.event.title ?? message?.event.name ?? 'Automação')}\n parentLabel=\"Automações\"\n onBack={back}\n />\n )\n\n if (message === undefined) {\n return (\n <div className=\"space-y-4\">\n {header}\n <div className=\"h-8 w-64 animate-pulse rounded bg-muted\" />\n <Card className=\"h-96 animate-pulse\" />\n </div>\n )\n }\n\n if (!message) {\n return (\n <>\n {header}\n <Card className=\"flex flex-col items-center gap-2 p-12 text-center\">\n <Mail className=\"h-9 w-9 text-muted-foreground/40\" strokeWidth={1.5} />\n <p className=\"font-semibold\">Automação não encontrada</p>\n <p className=\"max-w-sm text-sm text-muted-foreground\">\n O evento <code className=\"font-mono\">{eventKey}</code> não está no catálogo — o módulo\n que o registra pode não estar instalado nesta conta.\n </p>\n <Button variant=\"outline\" className=\"mt-2\" onClick={back}>Voltar para Automações</Button>\n </Card>\n </>\n )\n }\n\n const event = message.event\n // O texto de fábrica: o que \"restaurar padrão\" devolve. Vem do registro de\n // padrões, não do evento — o evento é o fato, não a mensagem.\n const fallback = { subject: message.override ? undefined : message.subject, body: message.body }\n const Icon = iconFor(event.icon)\n const current = draft ?? { subject: message.subject, body: message.body }\n const dirty = current.subject !== message.subject || current.body !== message.body\n const hasSubject = message.channel === 'email'\n\n const patch = async (input: Parameters<MessageTemplateStore['upsert']>[0]) => {\n setSaving(true)\n try {\n await store.upsert(input, tenantId)\n await reload()\n } catch (err) {\n console.warn('[automations] save failed', err)\n toast.error('Não foi possível salvar')\n } finally {\n setSaving(false)\n }\n }\n\n const save = () => void patch({\n eventKey: event.name,\n channel: message.channel,\n // Igual ao padrão volta a ser \"sem personalização\", não uma cópia.\n subject: current.subject.trim() === (fallback?.subject ?? '') ? null : current.subject.trim() || null,\n body: current.body.trim() === fallback?.body ? null : current.body.trim() || null,\n })\n\n const reset = async () => {\n setDraft({ subject: fallback?.subject ?? '', body: fallback?.body ?? '' })\n setSaving(true)\n try {\n // Apaga a linha inteira: com ela fora, o padrão volta a valer e melhorias\n // no texto de fábrica voltam a chegar aqui.\n await store.reset(event.name, message.channel, tenantId)\n await reload()\n toast.success('Texto restaurado')\n } catch (err) {\n console.warn('[automations] reset failed', err)\n toast.error('Não foi possível restaurar')\n } finally {\n setSaving(false)\n }\n }\n\n const previewSubject = renderMessageTemplate(current.subject, SAMPLE)\n const previewBody = renderMessageTemplate(current.body, SAMPLE)\n\n return (\n <div className=\"space-y-5\">\n {header}\n\n <div className=\"flex flex-wrap items-start gap-3\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border text-muted-foreground\">\n <Icon className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{CHANNEL_LABEL[message.channel]}</Badge>\n <Badge variant=\"outline\">{message.kind === 'marketing' ? 'Marketing' : 'Transacional'}</Badge>\n {message.customized && <Badge variant=\"info\">Personalizado</Badge>}\n </div>\n <p className=\"mt-0.5 text-sm text-muted-foreground\">{event.description}</p>\n </div>\n\n <div className=\"flex shrink-0 flex-wrap items-center gap-2\">\n <Hint label=\"Descarta o texto personalizado e volta ao padrão do produto.\">\n <span>\n <Button variant=\"outline\" onClick={() => void reset()} disabled={!message.customized || saving}>\n <RotateCcw className=\"mr-2 h-4 w-4\" />\n Restaurar padrão\n </Button>\n </span>\n </Hint>\n {/* O mesmo interruptor da lista: liga na hora, sem passar pelo Salvar\n — que aqui é só do TEXTO. */}\n <Switch\n size=\"md\"\n checked={message.enabled}\n onCheckedChange={(next) => void patch({ eventKey: event.name, channel: message.channel, enabled: next })}\n disabled={saving}\n label={message.enabled ? 'Ativa' : 'Inativa'}\n />\n <Button onClick={save} disabled={!dirty || saving}>\n {saving ? 'Salvando…' : dirty ? 'Salvar' : 'Salvo'}\n </Button>\n </div>\n </div>\n\n <HeaderTabs tabs={TABS} value={tab} onChange={setTab} aria-label=\"Visualização\" />\n\n <div className=\"flex flex-wrap items-center gap-x-6 gap-y-2 border-b border-border pb-4 text-xs text-muted-foreground\">\n <span className=\"inline-flex items-center gap-1.5\">\n <Zap className=\"h-3.5 w-3.5\" />\n Gatilho:\n <code className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-foreground\">{event.name}</code>\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <Clock className=\"h-3.5 w-3.5\" />\n {event.trigger}\n </span>\n {hasSubject && current.subject && <span className=\"min-w-0 truncate\">Assunto: {current.subject}</span>}\n </div>\n\n {tab === 'runs' ? (\n <RunLog eventKey={event.name} tenantId={tenantId} enabled={message.enabled} />\n ) : tab === 'preview' ? (\n <Card className=\"overflow-hidden\">\n <div className=\"flex items-center justify-between gap-3 border-b border-border px-4 py-2.5\">\n <span className=\"text-sm font-medium\">Prévia</span>\n <div className=\"flex items-center gap-1\">\n {(['desktop', 'mobile'] as const).map((d) => (\n <button\n key={d}\n type=\"button\"\n onClick={() => setDevice(d)}\n aria-label={d === 'desktop' ? 'Computador' : 'Celular'}\n className={`flex h-7 w-7 items-center justify-center rounded-md transition-colors ${\n device === d ? 'bg-muted text-foreground' : 'text-muted-foreground hover:bg-muted/60'\n }`}\n >\n {d === 'desktop' ? <Monitor className=\"h-4 w-4\" /> : <Smartphone className=\"h-4 w-4\" />}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"bg-muted/30 p-6\">\n {/* WhatsApp/SMS não têm assunto nem cabeçalho de remetente — mostrar\n a moldura de e-mail neles prometeria uma forma que o canal não\n tem. */}\n <div\n className={`mx-auto rounded-lg border border-border bg-card shadow-sm transition-[max-width] ${\n device === 'mobile' ? 'max-w-[380px]' : hasSubject ? 'max-w-[600px]' : 'max-w-[420px]'\n }`}\n >\n {hasSubject ? (\n <>\n <div className=\"border-b border-border px-6 py-4 text-sm font-semibold\">{SAMPLE.store_name}</div>\n <div className=\"space-y-1 border-b border-border px-6 py-3\">\n <p className=\"text-[11px] uppercase tracking-wide text-muted-foreground\">Assunto</p>\n <p className=\"text-sm font-medium\">{previewSubject}</p>\n </div>\n <div className=\"whitespace-pre-wrap px-6 py-5 text-sm leading-relaxed\">{previewBody}</div>\n </>\n ) : (\n <div className=\"p-4\">\n <div className=\"whitespace-pre-wrap rounded-2xl rounded-tl-sm bg-[#dcf8c6] px-3 py-2 text-sm leading-relaxed text-[#111b21]\">\n {previewBody}\n </div>\n </div>\n )}\n </div>\n <p className=\"mt-4 text-center text-xs text-muted-foreground\">\n Dados de exemplo — nenhum registro real foi usado.\n </p>\n </div>\n </Card>\n ) : (\n <Card className=\"space-y-4 p-4\">\n {hasSubject && (\n <div>\n <label className=\"mb-1 block text-xs font-medium text-muted-foreground\">Assunto</label>\n <input\n value={current.subject}\n onChange={(e) => setDraft({ ...current, subject: e.target.value })}\n className=\"w-full rounded-input border border-input bg-card px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n )}\n <div>\n <label className=\"mb-1 block text-xs font-medium text-muted-foreground\">Mensagem</label>\n <textarea\n rows={14}\n value={current.body}\n onChange={(e) => setDraft({ ...current, body: e.target.value })}\n className=\"w-full rounded-input border border-input bg-card px-3 py-2 font-mono text-xs leading-relaxed focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n <div>\n <p className=\"mb-1.5 text-xs font-medium text-muted-foreground\">\n Campos deste evento — o envio substitui pelo dado real\n </p>\n <div className=\"flex flex-wrap gap-1\">\n {message.placeholders.map((p) => (\n <span key={p} className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-muted-foreground\">\n {p}\n </span>\n ))}\n </div>\n </div>\n </Card>\n )}\n </div>\n )\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport type { MessageTemplate, UpsertMessageTemplateInput } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Acesso aos modelos personalizados. Só as PERSONALIZAÇÕES: o catálogo é\n// código, e uma leitura que falha ainda deve mostrar a lista inteira nos\n// padrões — ver `resolveMessages`.\n// ---------------------------------------------------------------------------\n\nconst TABLE = 'plg_automations_templates'\n\nfunction rowToTemplate(row: any): MessageTemplate {\n return {\n id: row.id,\n tenantId: row.tenant_id,\n eventKey: row.event_key,\n channel: row.channel ?? 'email',\n // NULL fica NULL: quem decide o padrão é o catálogo, não este mapeamento.\n // Colapsar para `false` aqui desligaria em silêncio todo modelo cuja linha\n // só existe porque o texto foi editado.\n enabled: row.enabled ?? null,\n // String vazia e NULL significam a mesma coisa — \"sem personalização\" —,\n // senão um assunto apagado sairia em branco em vez de voltar ao padrão.\n subject: row.subject || null,\n body: row.body || null,\n name: row.name || null,\n updatedAt: row.updated_at ?? row.created_at,\n }\n}\n\nexport interface MessageTemplateStore {\n list(tenantId?: string): Promise<MessageTemplate[]>\n upsert(input: UpsertMessageTemplateInput, tenantId?: string): Promise<MessageTemplate>\n /** Descarta a personalização inteira — a linha some e o padrão volta a valer. */\n reset(eventKey: string, channel: string, tenantId?: string): Promise<void>\n}\n\nexport function createSupabaseTemplateStore(): MessageTemplateStore {\n const db = () => {\n const client = getSupabaseClientOptional()\n if (!client) throw new Error('@fayz-ai/plugin-automations: Supabase client not initialized')\n return client as any\n }\n\n return {\n async list(tenantId) {\n let q = db().from(TABLE).select('*')\n if (tenantId) q = q.eq('tenant_id', tenantId)\n const { data, error } = await q\n if (error) throw error\n return (data ?? []).map(rowToTemplate)\n },\n\n async upsert(input, tenantId) {\n const payload: Record<string, unknown> = {\n tenant_id: tenantId,\n event_key: input.eventKey,\n channel: input.channel,\n }\n // Só o que veio: omitir uma chave tem de significar \"não mexa nisso\",\n // senão salvar o texto apagaria o ligado/desligado junto.\n if (input.enabled !== undefined) payload.enabled = input.enabled\n if (input.subject !== undefined) payload.subject = input.subject\n if (input.body !== undefined) payload.body = input.body\n if (input.name !== undefined) payload.name = input.name\n\n const { data, error } = await db()\n .from(TABLE)\n .upsert(payload, { onConflict: 'tenant_id,event_key,channel' })\n .select().single()\n if (error) throw error\n return rowToTemplate(data)\n },\n\n async reset(eventKey, channel, tenantId) {\n let q = db().from(TABLE).delete().eq('event_key', eventKey).eq('channel', channel)\n if (tenantId) q = q.eq('tenant_id', tenantId)\n const { error } = await q\n if (error) throw error\n },\n }\n}\n","import React from 'react'\nimport type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'\nimport { startEventLog } from '@fayz-ai/core'\nimport { AutomationsList } from './views/AutomationsList'\nimport { AutomationDetailPage } from './views/AutomationDetailPage'\nimport { createSupabaseTemplateStore, type MessageTemplateStore } from './data/templates'\n\n// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-automations — everything the product SENDS, in one place.\n//\n// ONE automation = when THIS happens, send THAT over THIS channel.\n//\n// Events do NOT live here. Each module DECLARES them in its own manifest\n// (`events`) and the runtime aggregates the active plugins' — the store brings\n// the order's, the CRM the pipeline's. If this screen had to import store and\n// CRM, an app installing only the CRM would carry the store catalog too, and\n// every new module would mean another import in here.\n//\n// The same catalog feeds integrations (webhooks) and audit: three readers of the\n// SAME fact, which is why the message text is not part of it.\n// ---------------------------------------------------------------------------\n\nexport interface AutomationsPluginOptions {\n navPosition?: number\n navSection?: 'main' | 'secondary' | 'settings'\n navLabel?: string\n /**\n * Where the list lives.\n *\n * 'nav' its own menu item (default) — for apps where sending is daily\n * routine, like the store.\n * 'settings' a tab inside settings, no menu item. In a salon the calendar is\n * what runs all day; automations are configured once, and a fixed\n * top-level item charges attention daily for a monthly screen.\n */\n placement?: 'nav' | 'settings'\n scope?: PluginScope\n verticalId?: VerticalId\n /** Swaps data access (tests, mock mode). */\n store?: MessageTemplateStore\n}\n\nexport function createAutomationsPlugin(options?: AutomationsPluginOptions): PluginManifest {\n // Built once per manifest: the store holds no state, and rebuilding it every\n // render would remount the effects that depend on it.\n const store = options?.store ?? createSupabaseTemplateStore()\n\n // Turns on the trigger history. Idempotent, and from here on EVERY event the\n // app emits is recorded, not only those with a message — it is the same\n // history webhooks and audit read.\n startEventLog()\n\n const inSettings = options?.placement === 'settings'\n\n const ListPage: React.ComponentType<unknown> = () =>\n React.createElement(AutomationsList, { store })\n ListPage.displayName = 'AutomationsList'\n\n const DetailPage: React.ComponentType<unknown> = (props) =>\n React.createElement(AutomationDetailPage, {\n ...(props as { eventKey?: string; channel?: string }),\n store,\n // \"Back\" must return you through the door you came in: opening the list\n // inside settings must not drop you on a loose page that app's menu does\n // not have.\n backTo: inSettings ? '/settings/automations' : '/automations',\n })\n DetailPage.displayName = 'AutomationDetail'\n\n const READ = { feature: 'automations', action: 'read' as const }\n\n return {\n id: 'automations',\n name: options?.navLabel ?? 'Automações',\n icon: 'Zap',\n version: '2.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [{ id: 'automations', label: 'Automations', group: 'Automate' }],\n navigation: inSettings ? [] : [\n {\n section: options?.navSection ?? 'main',\n position: options?.navPosition ?? 6,\n label: options?.navLabel ?? 'Automações',\n route: '/automations',\n icon: 'Zap',\n permission: READ,\n indexChild: false,\n },\n ],\n // The SAME list, served inside settings — not a second screen.\n settings: inSettings ? [\n { id: 'automations', label: options?.navLabel ?? 'Automações', icon: 'Zap', component: ListPage, permission: READ },\n ] : [],\n routes: [\n { path: '/automations', component: ListPage, permission: READ },\n // One automation's detail. Off-menu: it is a row of the list. Its back\n // link comes from `backTo`.\n { path: '/automations/:eventKey/:channel', component: DetailPage, permission: READ },\n ],\n widgets: [],\n }\n}\n\nexport { createSupabaseTemplateStore }\nexport type { MessageTemplateStore }\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/runtime.ts","../src/lib/connector-automations.ts","../src/views/ConnectorAutomations.tsx","../src/views/AutomationsList.tsx","../src/data/fayz.ts","../src/views/RunLog.tsx","../src/views/AutomationDetailPage.tsx","../src/data/templates.ts","../src/index.ts"],"names":["React","jsxs","jsx","Card","adminNavigateTo","ChevronRight","row","CHANNEL_LABEL","iconFor","Zap","LucideIcons","usePluginRuntimeOptional","Fragment","Mail","Button","toast","Badge","Switch","HeaderTabs","Smartphone","resolveFayzAgentConnection"],"mappings":"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","file":"index.js","sourcesContent":["import { useOrganizationStore } from '@fayz-ai/admin'\n\n// Re-exports para as views não precisarem saber de onde vem cada peça.\nexport {\n resolveMessages, resolveMessage, renderMessageTemplate,\n getEventsWithoutMessages,\n} from '@fayz-ai/core'\n\n/** Conta ativa — todo modelo é escopado nela. */\nexport function useOrganizationStoreLike(): string | undefined {\n return useOrganizationStore((s) => s.currentOrg?.id)\n}\n","import type { UnifiedConnector } from '@fayz-ai/admin'\nimport type { ConnectorDelivery } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// As automações que a INTEGRAÇÃO é dona.\n//\n// A tela de automações lia uma fonte só: mensagens. \"Quando um horário é\n// agendado → manda um e-mail\" é uma preferência que alguém escolheu, mora numa\n// linha de `plg_automations_templates` e pode ser apagada. \"Quando um horário é\n// agendado → cria o evento no Google Calendar\" não é preferência nenhuma: é o\n// que a integração É. Por isso é uma SEGUNDA fonte de linhas, e não um texto\n// padrão fingido — um texto padrão viraria uma linha que o usuário pode apagar,\n// deixando a integração conectada e meio ligada em silêncio.\n//\n// Elas existem só enquanto a conexão está viva. Desconectar é a saída, e é a\n// única — o contrato está em ConnectorManagedAutomation (@fayz-ai/core).\n// ---------------------------------------------------------------------------\n\nexport interface ConnectorAutomationRow {\n connectorId: string\n connectorName: string\n /** Onde a integração é configurada — para onde a linha leva. */\n hostPluginId?: string\n /** A cara da integração, resolvida como em qualquer outra tela (ConnectorMark). */\n icon?: string\n logoUrl?: string\n eventKey: string\n label: string\n /** O locatário pode desligar esta e seguir conectado. */\n optional: boolean\n /** Registro a registro: o que chegou no provedor. Ausente = a integração não conta. */\n listDeliveries?: (options?: { eventKey?: string; limit?: number }) => Promise<ConnectorDelivery[]>\n}\n\n/** As linhas de automação dos conectores CONECTADOS. Nada dos demais. */\nexport function connectorAutomationRows(connectors: UnifiedConnector[]): ConnectorAutomationRow[] {\n const out: ConnectorAutomationRow[] = []\n for (const connector of connectors) {\n if (connector.state !== 'connected') continue\n for (const auto of connector.definition?.managedAutomations ?? []) {\n out.push({\n connectorId: connector.id,\n connectorName: connector.name,\n hostPluginId: connector.hostPluginId,\n icon: connector.icon,\n logoUrl: connector.logoUrl,\n eventKey: auto.eventKey,\n label: auto.label,\n optional: auto.optional ?? false,\n ...(connector.definition?.listDeliveries\n ? { listDeliveries: connector.definition.listDeliveries.bind(connector.definition) }\n : {}),\n })\n }\n }\n return out\n}\n\n/** Agrupadas por conector: o dono precisa estar escrito em cima das linhas. */\nexport function groupConnectorAutomations(\n rows: ConnectorAutomationRow[],\n): {\n connectorId: string\n connectorName: string\n hostPluginId?: string\n icon?: string\n logoUrl?: string\n items: ConnectorAutomationRow[]\n}[] {\n const groups: ReturnType<typeof groupConnectorAutomations> = []\n for (const row of rows) {\n let group = groups.find((g) => g.connectorId === row.connectorId)\n if (!group) {\n group = {\n connectorId: row.connectorId,\n connectorName: row.connectorName,\n hostPluginId: row.hostPluginId,\n icon: row.icon,\n logoUrl: row.logoUrl,\n items: [],\n }\n groups.push(group)\n }\n group.items.push(row)\n }\n return groups\n}\n","import React from 'react'\nimport { ChevronRight } from 'lucide-react'\nimport { Card } from '@fayz-ai/ui'\nimport { adminNavigateTo, connectorRoute, ConnectorDeliveries, ConnectorMark } from '@fayz-ai/admin'\nimport {\n groupConnectorAutomations,\n type ConnectorAutomationRow,\n} from '../lib/connector-automations'\n\n// ---------------------------------------------------------------------------\n// As linhas que a integração é dona.\n//\n// Sem interruptor e sem lixeira, de propósito: uma linha apagada deixaria a\n// integração conectada e meio ligada, e semanas depois isso chega como \"o\n// Google Calendar parou de funcionar\". A saída é desconectar, e a linha diz\n// isso em texto — não em botão cinza, que se lê como algo que o usuário poderia\n// consertar (mesmo padrão de ConnectorDetail → \"faz parte do app\").\n// ---------------------------------------------------------------------------\n\nexport function ConnectorAutomations({ rows }: { rows: ConnectorAutomationRow[] }) {\n if (rows.length === 0) return null\n\n return (\n <>\n {groupConnectorAutomations(rows).map((group) => {\n const href = connectorRoute({ hostPluginId: group.hostPluginId })\n return (\n <div key={group.connectorId} className=\"space-y-3\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n {group.connectorName}\n </p>\n {group.items.map((row) => (\n <AutomationCard\n key={`${group.connectorId}:${row.eventKey}`}\n row={row}\n group={group}\n href={href}\n />\n ))}\n </div>\n )\n })}\n </>\n )\n}\n\n/**\n * Uma linha da integração, e — quando a integração sabe responder — o que de\n * fato chegou lá.\n *\n * A tela dizia que o gatilho existe. Não dizia se o pedido subiu, que é a\n * pergunta que alguém tem depois de cadastrar. As duas metades eram contadas por\n * sistemas diferentes e nenhum conhecia o outro.\n */\nfunction AutomationCard({\n row,\n group,\n href,\n}: {\n row: ConnectorAutomationRow\n group: { connectorId: string; connectorName: string; icon?: string; logoUrl?: string }\n href: string\n}) {\n const [open, setOpen] = React.useState(false)\n\n return (\n <Card className=\"overflow-hidden\">\n <div\n role=\"button\"\n tabIndex={0}\n onClick={() => adminNavigateTo(href)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); adminNavigateTo(href) }\n }}\n className=\"flex cursor-pointer items-start gap-4 p-4 transition-colors hover:bg-muted/30 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {/* A mesma cara que a integração tem em qualquer outra tela: um plugue\n cinza aqui e o logo do Bling na tela de conectores é a mesma coisa\n parecendo duas. */}\n <ConnectorMark\n connector={{\n id: group.connectorId,\n name: group.connectorName,\n icon: group.icon,\n logoUrl: group.logoUrl,\n }}\n size=\"sm\"\n />\n <div className=\"min-w-0 flex-1\">\n <p className=\"font-medium\">{row.label}</p>\n <p className=\"text-sm text-muted-foreground\">\n Quando <code className=\"font-mono text-xs\">{row.eventKey}</code> acontece aqui.\n </p>\n </div>\n <span className=\"shrink-0 pt-0.5 text-right text-xs text-muted-foreground\">\n {row.optional\n ? `Opcional — desligue em ${group.connectorName}`\n : `Ligada pela integração · sai ao desconectar ${group.connectorName}`}\n </span>\n </div>\n\n {row.listDeliveries && (\n <>\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n aria-expanded={open}\n className=\"flex w-full items-center gap-2 border-t border-border px-4 py-2 text-left transition-colors hover:bg-muted/40\"\n >\n <ChevronRight className={`h-3.5 w-3.5 shrink-0 text-muted-foreground transition-transform ${open ? 'rotate-90' : ''}`} />\n <span className=\"text-xs font-medium\">O que já foi para o {group.connectorName}</span>\n </button>\n {open && (\n <div className=\"border-t border-border p-4\">\n <ConnectorDeliveries\n load={(options) => row.listDeliveries!({ ...options, eventKey: row.eventKey })}\n providerName={group.connectorName}\n />\n </div>\n )}\n </>\n )}\n </Card>\n )\n}\n","import React from 'react'\nimport * as LucideIcons from 'lucide-react'\nimport { ChevronRight, Mail, MessageCircle, MessageSquare, Smartphone, Zap } from 'lucide-react'\nimport { Card, HeaderTabs, Switch, toast } from '@fayz-ai/ui'\nimport { adminNavigateTo, useConnectors } from '@fayz-ai/admin'\nimport { resolveMessages, useOrganizationStoreLike } from '../lib/runtime'\nimport { usePluginRuntimeOptional } from '@fayz-ai/core'\nimport type { MessageChannel, MessageKind, ResolvedMessage } from '@fayz-ai/core'\nimport type { MessageTemplateStore } from '../data/templates'\nimport { connectorAutomationRows } from '../lib/connector-automations'\nimport { ConnectorAutomations } from './ConnectorAutomations'\n\n// ---------------------------------------------------------------------------\n// Automações — quando ISTO acontece, mande AQUILO.\n//\n// Cada linha é uma automação inteira: o gatilho à esquerda, o canal na\n// pastilha, o interruptor à direita. Não existe \"modelo\" separado do \"fluxo\" —\n// um texto sem gatilho nunca sai, e um fluxo de um passo é o texto com o\n// gatilho escrito na frente.\n//\n// Agrupado por MÓDULO (Loja, CRM, Agenda) e não por canal, porque é assim que a\n// pergunta chega: \"o que a gente manda quando um pedido é enviado?\" — e a\n// resposta pode ser um e-mail, um WhatsApp, ou os dois. Separar por canal, como\n// fazia a tela de e-mails, obriga a visitar dois menus para responder isso.\n//\n// Cada linha é um par evento×canal. O evento aparece uma vez, com uma pastilha\n// por canal ofertado: é o desenho que o RD Station e o Kommo usam para não\n// esconder que \"confirmação de pedido\" e \"confirmação por WhatsApp\" são o mesmo\n// gatilho com duas saídas.\n//\n// Duas fontes de linha, e não uma: além das mensagens, as automações que uma\n// integração conectada é dona — ../lib/connector-automations.ts diz por quê.\n// ---------------------------------------------------------------------------\n\nconst CHANNEL_ICON: Record<MessageChannel, React.ComponentType<{ className?: string }>> = {\n email: Mail,\n whatsapp: MessageCircle,\n sms: Smartphone,\n push: MessageSquare,\n webchat: MessageSquare,\n}\n\nconst CHANNEL_LABEL: Record<MessageChannel, string> = {\n email: 'E-mail', whatsapp: 'WhatsApp', sms: 'SMS', push: 'Push', webchat: 'Chat',\n}\n\nconst KIND_TABS: { value: MessageKind | 'all'; label: string }[] = [\n { value: 'all', label: 'Todos' },\n { value: 'transactional', label: 'Transacionais' },\n { value: 'marketing', label: 'Marketing' },\n]\n\nconst KIND_HINT: Record<string, string> = {\n all: 'Tudo que o produto sabe enviar, por qualquer canal.',\n transactional: 'Disparados por uma ação da pessoa. Não precisam de opt-in.',\n marketing: 'Iniciativa da empresa. Só para quem aceitou receber.',\n}\n\nfunction iconFor(name?: string): React.ComponentType<{ className?: string }> {\n if (!name) return Zap\n const icons = LucideIcons as unknown as Record<string, React.ComponentType<{ className?: string }>>\n return icons[name] ?? Zap\n}\n\nexport function AutomationsList({ store }: { store: MessageTemplateStore }) {\n const tenantId = useOrganizationStoreLike()\n // Os eventos vêm do runtime: só os plugins ATIVOS anunciam fatos.\n const runtime = usePluginRuntimeOptional()\n const [messages, setMessages] = React.useState<ResolvedMessage[] | null>(null)\n const [kind, setKind] = React.useState<MessageKind | 'all'>('all')\n // A segunda fonte de linhas: as automações que a integração é dona. Mesmo\n // loader dos conectores — duas leituras seriam duas respostas para \"o Google\n // Calendar está ligado?\". Sem grants e sem catálogo: nada disso vira linha\n // aqui, e assim a tela não faz rede nenhuma.\n const { connectors } = useConnectors({ includeGrants: false, includeCatalog: false })\n const owned = React.useMemo(() => connectorAutomationRows(connectors ?? []), [connectors])\n\n const reload = React.useCallback(async () => {\n // Uma leitura que falha ainda mostra o catálogo inteiro nos padrões: os\n // eventos são código, então \"sem personalização\" é um estado válido e\n // completo, não uma tela vazia.\n let overrides: Awaited<ReturnType<MessageTemplateStore['list']>> = []\n try {\n overrides = await store.list(tenantId)\n } catch (err) {\n console.warn('[automations] could not load template overrides; showing defaults', err)\n }\n setMessages(resolveMessages(overrides, runtime?.events ?? []))\n }, [store, tenantId, runtime])\n\n React.useEffect(() => { void reload() }, [reload])\n\n const toggle = async (m: ResolvedMessage, enabled: boolean) => {\n setMessages((prev) => prev?.map((x) =>\n x.event.name === m.event.name && x.channel === m.channel ? { ...x, enabled } : x) ?? null)\n try {\n await store.upsert({ eventKey: m.event.name, channel: m.channel, enabled }, tenantId)\n await reload()\n } catch (err) {\n console.warn('[automations] toggle failed', err)\n toast.error('Não foi possível salvar')\n await reload()\n }\n }\n\n const visible = (messages ?? []).filter((m) => kind === 'all' || m.kind === kind)\n // As linhas do conector não são mensagens, então não têm \"kind\" — aparecem na\n // aba Todos. Contam no total porque estão rodando: omiti-las faria o contador\n // dizer menos automações ativas do que o negócio tem.\n const ownedVisible = kind === 'all' ? owned : []\n const activeCount = (messages ?? []).filter((m) => m.enabled).length + owned.length\n const totalCount = (messages?.length ?? 0) + owned.length\n\n // Agrupa por módulo preservando a ordem de registro dos plugins.\n const groups: { module: string; label: string; items: ResolvedMessage[] }[] = []\n for (const m of visible) {\n let g = groups.find((x) => x.module === m.event.pluginId)\n if (!g) { g = { module: m.event.pluginId, label: m.event.pluginName, items: [] }; groups.push(g) }\n g.items.push(m)\n }\n\n return (\n <div className=\"space-y-6\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <HeaderTabs tabs={KIND_TABS} value={kind} onChange={setKind} aria-label=\"Automações\" />\n {messages !== null && (\n <span className=\"text-sm text-muted-foreground\">\n {activeCount} de {totalCount} automações ativas\n </span>\n )}\n </div>\n\n <p className=\"text-sm text-muted-foreground\">{KIND_HINT[kind]}</p>\n\n {messages === null ? (\n <div className=\"space-y-3\">\n {Array.from({ length: 4 }).map((_, i) => (\n <Card key={i} className=\"p-4\">\n <div className=\"h-4 w-40 animate-pulse rounded bg-muted\" />\n <div className=\"mt-2 h-3 w-64 animate-pulse rounded bg-muted\" />\n </Card>\n ))}\n </div>\n ) : groups.length === 0 && ownedVisible.length === 0 ? (\n <Card className=\"flex flex-col items-center gap-1 p-12 text-center\">\n <Zap className=\"mb-2 h-9 w-9 text-muted-foreground/40\" strokeWidth={1.5} />\n <p className=\"text-base font-semibold\">Nenhuma automação nesta aba</p>\n <p className=\"max-w-sm text-sm text-muted-foreground\">\n Os eventos vêm dos módulos instalados — a loja traz os do pedido, o CRM os do funil.\n </p>\n </Card>\n ) : groups.map((group) => (\n <div key={group.module} className=\"space-y-3\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n {group.label}\n </p>\n {group.items.map((m) => {\n const Icon = iconFor(m.event.icon ?? m.event.pluginIcon)\n const ChannelIcon = CHANNEL_ICON[m.channel]\n const href = `/automations/${encodeURIComponent(m.event.name)}/${m.channel}`\n return (\n <Card\n key={`${m.event.name}:${m.channel}`}\n role=\"button\"\n tabIndex={0}\n onClick={() => adminNavigateTo(href)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); adminNavigateTo(href) }\n }}\n className=\"cursor-pointer overflow-hidden transition-colors hover:border-primary/40 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <div className=\"flex items-start gap-4 p-4\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border text-muted-foreground\">\n <Icon className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"font-medium\">{m.override?.name ?? m.event.title ?? m.event.name}</p>\n <span className=\"inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-[11px] text-muted-foreground\">\n <ChannelIcon className=\"h-3 w-3\" />\n {CHANNEL_LABEL[m.channel]}\n </span>\n {m.customized && (\n <span className=\"rounded-full bg-primary/10 px-2 py-0.5 text-[11px] text-primary\">\n personalizado\n </span>\n )}\n </div>\n <p className=\"text-sm text-muted-foreground\">{m.event.description}</p>\n <div className=\"mt-2 flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground\">\n <span className=\"inline-flex items-center gap-1\">\n <Zap className=\"h-3 w-3\" />\n {m.event.trigger}\n </span>\n {m.subject && <span className=\"truncate\">Assunto: {m.subject}</span>}\n </div>\n </div>\n <div className=\"flex shrink-0 items-center gap-3\">\n {/* Switch e não checkbox: isto vale na hora, não quando\n algum Salvar for clicado. */}\n <Switch\n checked={m.enabled}\n onCheckedChange={(next) => void toggle(m, next)}\n label={m.enabled ? 'Ativo' : 'Inativo'}\n aria-label={`${m.event.title} — ${CHANNEL_LABEL[m.channel]}`}\n />\n <ChevronRight className=\"h-4 w-4 text-muted-foreground\" />\n </div>\n </div>\n </Card>\n )\n })}\n </div>\n ))}\n\n {messages !== null && <ConnectorAutomations rows={ownedVisible} />}\n </div>\n )\n}\n","import { getFayzSupabaseClientOptional } from '@fayz-ai/admin'\nimport type { ResolvedFayzAgentConnection } from '@fayz-ai/admin'\nimport { getMessageDefaults } from '@fayz-ai/core'\nimport type { MessageChannel, MessageTemplate } from '@fayz-ai/core'\nimport {\n createFayzAutomationsClient,\n FayzAutomationsError,\n type FayzAutomation,\n type FayzAutomationsClient,\n} from '@fayz-ai/sdk/automations'\nimport type { MessageTemplateStore } from './templates'\n\n// ---------------------------------------------------------------------------\n// The SAME contract as `templates.ts`, served by the platform: behind a Fayz\n// project the platform is what runs the automations, so the customisation has\n// to live there — a local row the platform never reads is a fake switch.\n// ---------------------------------------------------------------------------\n\nfunction toTemplate(automation: FayzAutomation): MessageTemplate | null {\n const eventKey = automation.triggerConfig?.eventKey\n // No eventKey means it isn't a catalogue automation — standalone platform\n // flows have no row on this screen.\n if (!eventKey) return null\n const action = automation.actions?.[0]\n return {\n id: automation.id,\n tenantId: automation.tenantId ?? '',\n eventKey,\n channel: (automation.triggerConfig.sourceChannel ?? 'email') as MessageChannel,\n enabled: automation.enabled,\n // Empty and absent mean the same — \"no customisation\", the catalogue default.\n subject: action?.config?.subject || null,\n body: action?.config?.body || null,\n // The automation name belongs to the platform, not a user rename: the\n // catalogue title still owns the screen.\n name: null,\n updatedAt: automation.updatedAt,\n }\n}\n\nfunction catalogDefaultEnabled(eventKey: string, channel: MessageChannel): boolean {\n const def = getMessageDefaults().find((d) => d.eventKey === eventKey)\n return def?.defaultEnabled?.[channel] ?? false\n}\n\nasync function defaultSessionToken(): Promise<string | null> {\n const session = (await getFayzSupabaseClientOptional()?.auth.getSession())?.data.session\n return session?.access_token ?? null\n}\n\nexport interface FayzTemplateStoreDeps {\n client?: FayzAutomationsClient\n getSessionToken?: () => Promise<string | null>\n}\n\nexport function createFayzTemplateStore(\n connection: ResolvedFayzAgentConnection,\n deps: FayzTemplateStoreDeps = {},\n): MessageTemplateStore {\n const client = deps.client ?? createFayzAutomationsClient({\n baseUrl: connection.apiBaseUrl,\n projectId: connection.projectId,\n publishableKey: connection.publishableKey,\n })\n const getSessionToken = deps.getSessionToken ?? defaultSessionToken\n\n // (event_key, channel) → platform automation id, repopulated on every list.\n const ids = new Map<string, string>()\n const keyOf = (eventKey: string, channel: string) => `${eventKey}:${channel}`\n\n async function refresh(tenantId: string): Promise<MessageTemplate[]> {\n const automations = await client.list({ tenantId })\n ids.clear()\n const rows: MessageTemplate[] = []\n for (const automation of automations) {\n const row = toTemplate(automation)\n if (!row) continue\n ids.set(keyOf(row.eventKey, row.channel), automation.id)\n rows.push(row)\n }\n return rows\n }\n\n // One screen mounts several views of the same catalogue (list, detail, CRM ⚡)\n // and StrictMode doubles effects in dev — unshared, opening it costs 8+ identical\n // GETs. One flight per tenant, short-lived; writes invalidate.\n const LIST_TTL_MS = 30_000\n let cache: { tenantId: string; at: number; promise: Promise<MessageTemplate[]> } | null = null\n\n function invalidate(): void {\n cache = null\n }\n\n function load(tenantId: string): Promise<MessageTemplate[]> {\n if (cache && cache.tenantId === tenantId && Date.now() - cache.at < LIST_TTL_MS) return cache.promise\n const promise = refresh(tenantId)\n promise.catch(() => {\n if (cache?.promise === promise) cache = null // a failure must not stay cached for 30s\n })\n cache = { tenantId, at: Date.now(), promise }\n return promise\n }\n\n async function requireToken(): Promise<string> {\n const token = await getSessionToken()\n // Writing needs the app session — same message as the rest of the admin.\n if (!token) throw new Error('Sessão expirada — entre de novo.')\n return token\n }\n\n async function resolveId(eventKey: string, channel: string, tenantId: string): Promise<string | undefined> {\n const key = keyOf(eventKey, channel)\n if (!ids.has(key)) await load(tenantId)\n return ids.get(key)\n }\n\n return {\n async list(tenantId) {\n // No account yet, nothing to ask — the catalogue at its defaults is a\n // complete state, same as the local store when the read fails.\n if (!tenantId) return []\n return load(tenantId)\n },\n\n async upsert(input, tenantId) {\n if (!tenantId) throw new Error('@fayz-ai/plugin-automations: tenantId is required')\n const appSessionToken = await requireToken()\n const key = keyOf(input.eventKey, input.channel)\n let id = await resolveId(input.eventKey, input.channel, tenantId)\n\n if (!id) {\n const action: { subject?: string; body?: string } = {}\n if (input.subject != null) action.subject = input.subject\n if (input.body != null) action.body = input.body\n try {\n const created = await client.create({\n tenantId,\n appSessionToken,\n eventKey: input.eventKey,\n sourceChannel: input.channel,\n // The platform has no \"inherit from catalogue\": materialise the default.\n enabled: input.enabled ?? catalogDefaultEnabled(input.eventKey, input.channel),\n ...(Object.keys(action).length ? { action } : {}),\n })\n ids.set(key, created.id)\n invalidate()\n const row = toTemplate(created)\n if (!row) throw new Error('@fayz-ai/plugin-automations: platform did not round-trip eventKey')\n return row\n } catch (err) {\n // 409: someone created it first — turn it into an update.\n if (!(err instanceof FayzAutomationsError) || err.status !== 409) throw err\n invalidate()\n await refresh(tenantId)\n id = ids.get(key)\n if (!id) throw err\n }\n }\n\n const updated = await client.update({\n id,\n tenantId,\n appSessionToken,\n // Only what was sent: omitting has to mean \"leave it alone\", as in the local store.\n ...(typeof input.enabled === 'boolean' ? { enabled: input.enabled } : {}),\n ...(input.subject !== undefined || input.body !== undefined\n ? {\n action: {\n ...(input.subject !== undefined ? { subject: input.subject } : {}),\n ...(input.body !== undefined ? { body: input.body } : {}),\n },\n }\n : {}),\n })\n invalidate()\n const row = toTemplate(updated)\n if (!row) throw new Error('@fayz-ai/plugin-automations: platform did not round-trip eventKey')\n return row\n },\n\n async reset(eventKey, channel, tenantId) {\n if (!tenantId) return\n const id = await resolveId(eventKey, channel, tenantId)\n // Never customised: the default already applies, nothing to clear.\n if (!id) return\n const appSessionToken = await requireToken()\n // The automation stays (the on/off belongs to it); only the text goes back\n // to the catalogue — null clears the field on the server.\n await client.update({ id, tenantId, appSessionToken, action: { subject: null, body: null } })\n invalidate()\n },\n }\n}\n\nlet cachedClient: { key: string; client: FayzAutomationsClient } | null = null\n\n/** One client per connection — RunLog and the store read the same surface. */\nexport function getFayzAutomationsClient(connection: ResolvedFayzAgentConnection): FayzAutomationsClient {\n const key = `${connection.apiBaseUrl}|${connection.projectId}|${connection.publishableKey}`\n if (cachedClient?.key === key) return cachedClient.client\n const client = createFayzAutomationsClient({\n baseUrl: connection.apiBaseUrl,\n projectId: connection.projectId,\n publishableKey: connection.publishableKey,\n })\n cachedClient = { key, client }\n return client\n}\n","import React from 'react'\nimport { AlertTriangle, ChevronRight, CircleCheck, CircleSlash, History, RefreshCw } from 'lucide-react'\nimport { Badge, Button, Card } from '@fayz-ai/ui'\nimport { loadEventRuns, type EventRun, type EventRunStatus } from '@fayz-ai/core'\nimport type { ResolvedFayzAgentConnection } from '@fayz-ai/admin'\nimport type { FayzAutomationExecution } from '@fayz-ai/sdk/automations'\nimport { getFayzAutomationsClient } from '../data/fayz'\n\n// ---------------------------------------------------------------------------\n// The last runs of this trigger.\n//\n// The screen said what SHOULD happen, never what DID — so testing an automation\n// meant waiting for a customer complaint, and a complaint can't tell \"never\n// fired\" from \"fired and the send failed\", which are defects in different\n// places. The payload stays visible (collapsed) on purpose: it answers \"why did\n// it go out with the wrong name?\" without reproducing the case.\n//\n// Works for ANY trigger: the list is read by event key and every emitted event\n// goes through the same collector, so a new module shows up here untouched.\n// ---------------------------------------------------------------------------\n\nconst STATUS: Record<EventRunStatus, {\n label: string; hint: string; variant: 'success' | 'info' | 'warning' | 'destructive'\n Icon: React.ComponentType<{ className?: string }>\n}> = {\n sent: { label: 'Enviado', hint: 'A mensagem saiu.', variant: 'success', Icon: CircleCheck },\n recorded: {\n label: 'Disparou',\n // Today's honest state: the trigger works, the send doesn't exist yet.\n hint: 'O gatilho disparou e ficou registrado. O envio automático ainda não está ligado neste ambiente.',\n variant: 'info', Icon: History,\n },\n skipped: { label: 'Ignorado', hint: 'O gatilho disparou, mas nada foi enviado — automação desligada ou sem canal.', variant: 'warning', Icon: CircleSlash },\n failed: { label: 'Falhou', hint: 'A tentativa de envio quebrou. O erro está na linha.', variant: 'destructive', Icon: AlertTriangle },\n}\n\nfunction when(iso: string): string {\n const then = new Date(iso).getTime()\n const diff = Date.now() - then\n const min = Math.round(diff / 60000)\n if (min < 1) return 'agora'\n if (min < 60) return `há ${min} min`\n const h = Math.round(min / 60)\n if (h < 24) return `há ${h} h`\n return new Date(iso).toLocaleString('pt-BR', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })\n}\n\nfunction RunRow({ run }: { run: EventRun }) {\n const [open, setOpen] = React.useState(false)\n const cfg = STATUS[run.status] ?? STATUS.recorded\n const { Icon } = cfg\n\n return (\n <div className=\"border-b border-border last:border-b-0\">\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className=\"flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors hover:bg-muted/40\"\n >\n <ChevronRight className={`h-3.5 w-3.5 shrink-0 text-muted-foreground transition-transform ${open ? 'rotate-90' : ''}`} />\n <Icon className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <Badge variant={cfg.variant}>{cfg.label}</Badge>\n <span className=\"min-w-0 flex-1 truncate text-sm text-muted-foreground\">\n {typeof run.payload.record_name === 'string' ? run.payload.record_name\n : typeof run.payload.customer_name === 'string' ? run.payload.customer_name\n : typeof run.payload.contact_name === 'string' ? run.payload.contact_name\n : run.subjectId ?? '—'}\n </span>\n <span className=\"shrink-0 text-xs text-muted-foreground\">{when(run.occurredAt)}</span>\n </button>\n\n {open && (\n <div className=\"space-y-3 bg-muted/20 px-4 pb-4 pt-1\">\n <p className=\"text-xs text-muted-foreground\">{cfg.hint}</p>\n <div>\n <p className=\"mb-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n Dados do disparo\n </p>\n <pre className=\"overflow-x-auto rounded-md border border-border bg-card p-3 font-mono text-[11px] leading-relaxed\">\n{JSON.stringify(run.payload, null, 2)}\n </pre>\n </div>\n {run.result && (\n <div>\n <p className=\"mb-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n Resultado\n </p>\n <pre className=\"overflow-x-auto rounded-md border border-border bg-card p-3 font-mono text-[11px] leading-relaxed\">\n{JSON.stringify(run.result, null, 2)}\n </pre>\n </div>\n )}\n {run.error && (\n <p className=\"rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 font-mono text-[11px] text-destructive\">\n {run.error}\n </p>\n )}\n </div>\n )}\n </div>\n )\n}\n\nexport function RunLog({ eventKey, tenantId, enabled }: {\n eventKey: string\n tenantId?: string\n /** Current automation state — changes what the empty state means. */\n enabled: boolean\n}) {\n const [runs, setRuns] = React.useState<EventRun[] | null>(null)\n const [loading, setLoading] = React.useState(false)\n\n const load = React.useCallback(async () => {\n setLoading(true)\n setRuns(await loadEventRuns(eventKey, { tenantId, limit: 20 }))\n setLoading(false)\n }, [eventKey, tenantId])\n\n React.useEffect(() => { void load() }, [load])\n\n return (\n <Card className=\"overflow-hidden\">\n <div className=\"flex items-center justify-between gap-3 border-b border-border px-4 py-2.5\">\n <div className=\"min-w-0\">\n <span className=\"text-sm font-medium\">Execuções recentes</span>\n <p className=\"text-xs text-muted-foreground\">Cada vez que este gatilho disparou nesta conta.</p>\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void load()} disabled={loading}>\n <RefreshCw className={`h-3.5 w-3.5 ${loading ? 'animate-spin' : ''}`} />\n </Button>\n </div>\n\n {runs === null ? (\n <div className=\"space-y-2 p-4\">\n {[1, 2, 3].map((i) => <div key={i} className=\"h-8 animate-pulse rounded bg-muted/40\" />)}\n </div>\n ) : runs.length === 0 ? (\n <div className=\"flex flex-col items-center gap-1 px-4 py-10 text-center\">\n <History className=\"h-7 w-7 text-muted-foreground/40\" strokeWidth={1.5} />\n <p className=\"text-sm font-medium\">Nenhum disparo ainda</p>\n <p className=\"max-w-sm text-xs text-muted-foreground\">\n {enabled\n ? 'Assim que este evento acontecer, ele aparece aqui — mesmo antes de existir envio.'\n : 'A automação está desligada. O gatilho continua sendo registrado aqui quando o evento acontecer.'}\n </p>\n </div>\n ) : (\n <div>{runs.map((run) => <RunRow key={run.id} run={run} />)}</div>\n )}\n </Card>\n )\n}\n\n// ---------------------------------------------------------------------------\n// The PLATFORM's runs. Behind a Fayz project the send runs there, so the real\n// history is the platform's — the local collector only knows the trigger fired,\n// not what the platform did with it.\n// ---------------------------------------------------------------------------\n\nconst EXEC_STATUS: Record<string, {\n label: string; variant: 'success' | 'info' | 'destructive'\n Icon: React.ComponentType<{ className?: string }>\n}> = {\n success: { label: 'Executada', variant: 'success', Icon: CircleCheck },\n error: { label: 'Falhou', variant: 'destructive', Icon: AlertTriangle },\n}\n\nfunction ExecutionRow({ execution }: { execution: FayzAutomationExecution }) {\n const cfg = EXEC_STATUS[execution.status]\n ?? { label: execution.status, variant: 'info' as const, Icon: History }\n const { Icon } = cfg\n return (\n <div className=\"border-b border-border px-4 py-2.5 last:border-b-0\">\n <div className=\"flex items-center gap-3\">\n <Icon className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <Badge variant={cfg.variant}>{cfg.label}</Badge>\n <span className=\"min-w-0 flex-1 truncate text-sm text-muted-foreground\">\n {execution.automationName}\n </span>\n <span className=\"shrink-0 text-xs text-muted-foreground\">{when(execution.executedAt)}</span>\n </div>\n {execution.error && (\n <p className=\"ml-6 mt-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 font-mono text-[11px] text-destructive\">\n {execution.error}\n </p>\n )}\n </div>\n )\n}\n\nexport function FayzRunLog({ connection, eventKey, tenantId, enabled }: {\n connection: ResolvedFayzAgentConnection\n eventKey: string\n tenantId?: string\n /** Current automation state — changes what the empty state means. */\n enabled: boolean\n}) {\n const [executions, setExecutions] = React.useState<FayzAutomationExecution[] | null>(null)\n const [loading, setLoading] = React.useState(false)\n\n const load = React.useCallback(async () => {\n if (!tenantId) return\n setLoading(true)\n try {\n setExecutions(await getFayzAutomationsClient(connection).listExecutions({ tenantId, eventKey, limit: 20 }))\n } catch (err) {\n console.warn('[automations] could not load platform executions', err)\n setExecutions([])\n } finally {\n setLoading(false)\n }\n }, [connection, eventKey, tenantId])\n\n React.useEffect(() => { void load() }, [load])\n\n return (\n <Card className=\"overflow-hidden\">\n <div className=\"flex items-center justify-between gap-3 border-b border-border px-4 py-2.5\">\n <div className=\"min-w-0\">\n <span className=\"text-sm font-medium\">Execuções recentes</span>\n <p className=\"text-xs text-muted-foreground\">\n O que a plataforma Fayz executou para este gatilho nesta conta.\n </p>\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void load()} disabled={loading}>\n <RefreshCw className={`h-3.5 w-3.5 ${loading ? 'animate-spin' : ''}`} />\n </Button>\n </div>\n\n {executions === null ? (\n <div className=\"space-y-2 p-4\">\n {[1, 2, 3].map((i) => <div key={i} className=\"h-8 animate-pulse rounded bg-muted/40\" />)}\n </div>\n ) : executions.length === 0 ? (\n <div className=\"flex flex-col items-center gap-1 px-4 py-10 text-center\">\n <History className=\"h-7 w-7 text-muted-foreground/40\" strokeWidth={1.5} />\n <p className=\"text-sm font-medium\">Nenhuma execução ainda</p>\n <p className=\"max-w-sm text-xs text-muted-foreground\">\n {enabled\n ? 'Assim que este evento acontecer, a plataforma executa a automação e o resultado aparece aqui.'\n : 'A automação está desligada — a plataforma não executa nada para este gatilho.'}\n </p>\n </div>\n ) : (\n <div>{executions.map((e) => <ExecutionRow key={e.id} execution={e} />)}</div>\n )}\n </Card>\n )\n}\n","import React from 'react'\nimport * as LucideIcons from 'lucide-react'\nimport { Clock, Mail, Monitor, RotateCcw, Smartphone, Zap } from 'lucide-react'\nimport { Badge, Button, Card, HeaderTabs, Hint, SubpageHeader, Switch, toast } from '@fayz-ai/ui'\nimport { adminNavigateTo, resolveFayzAgentConnection } from '@fayz-ai/admin'\nimport type { MessageChannel, ResolvedMessage } from '@fayz-ai/core'\nimport { usePluginRuntimeOptional } from '@fayz-ai/core'\nimport { resolveMessage, renderMessageTemplate, useOrganizationStoreLike } from '../lib/runtime'\nimport { FayzRunLog, RunLog } from './RunLog'\nimport type { MessageTemplateStore } from '../data/templates'\n\n// ---------------------------------------------------------------------------\n// Um modelo, em tela cheia. Duas visões do MESMO texto:\n// Prévia o que a pessoa recebe, com os campos já substituídos\n// Código o texto-fonte, onde se edita\n//\n// A substituição da prévia é a de @fayz-ai/core (renderMessageTemplate), não um\n// replace local: prévia e envio precisam concordar, senão aprova-se um texto e\n// entrega-se outro.\n//\n// \"Igual ao padrão\" é gravado como AUSÊNCIA de personalização (null), não como\n// cópia — assim melhorias no texto padrão continuam chegando a quem nunca\n// mexeu. É o mesmo motivo pelo qual \"Restaurar padrão\" APAGA a linha em vez de\n// escrever o texto de fábrica nela.\n// ---------------------------------------------------------------------------\n\ntype ViewTab = 'preview' | 'code' | 'runs'\n\nconst TABS: { value: ViewTab; label: string }[] = [\n { value: 'preview', label: 'Prévia' },\n { value: 'code', label: 'Código' },\n // O que já aconteceu. Fica ao lado do texto, e não numa tela à parte, porque\n // é a mesma pergunta em dois tempos: o que vai sair, e o que saiu.\n { value: 'runs', label: 'Execuções' },\n]\n\nconst CHANNEL_LABEL: Record<MessageChannel, string> = {\n email: 'E-mail', whatsapp: 'WhatsApp', sms: 'SMS', push: 'Push', webchat: 'Chat',\n}\n\n/** Dados de exemplo da prévia. Não são de ninguém — a tela diz isso. */\nconst SAMPLE: Record<string, string> = {\n store_name: 'Sua Loja', company_name: 'Sua Empresa',\n customer_name: 'Maria Silva', contact_name: 'Maria Silva', lead_name: 'Maria Silva',\n order_number: '1042', order_total: 'R$ 189,90',\n order_items: '1 × Camiseta Clássica — R$ 89,90\\n2 × Caneca Esmaltada — R$ 100,00',\n tracking_code: 'BR123456789BR', cart_url: 'https://sualoja.com.br/carrinho',\n deal_name: 'Proposta — Reforma da fachada', deal_value: 'R$ 12.400,00',\n stage_name: 'Negociação', owner_name: 'João Pereira',\n appointment_date: '12/08/2026', appointment_time: '14:30',\n}\n\nfunction iconFor(name?: string): React.ComponentType<{ className?: string }> {\n if (!name) return Zap\n const icons = LucideIcons as unknown as Record<string, React.ComponentType<{ className?: string }>>\n return icons[name] ?? Zap\n}\n\nexport interface AutomationDetailPageProps {\n eventKey?: string\n channel?: string\n store: MessageTemplateStore\n /** Para onde o \"voltar\" leva — a lista pode morar no menu ou nas\n * configurações, e a pessoa tem que voltar por onde entrou. */\n backTo?: string\n}\n\nexport function AutomationDetailPage({ eventKey, channel, store, backTo = '/automations' }: AutomationDetailPageProps) {\n const tenantId = useOrganizationStoreLike()\n const runtime = usePluginRuntimeOptional()\n const fayzConnection = React.useMemo(() => resolveFayzAgentConnection(), [])\n const [message, setMessage] = React.useState<ResolvedMessage | null | undefined>(undefined)\n const [tab, setTab] = React.useState<ViewTab>('preview')\n const [device, setDevice] = React.useState<'desktop' | 'mobile'>('desktop')\n const [draft, setDraft] = React.useState<{ subject: string; body: string } | null>(null)\n const [saving, setSaving] = React.useState(false)\n\n const back = React.useCallback(() => adminNavigateTo(backTo), [backTo])\n\n const reload = React.useCallback(async () => {\n if (!eventKey || !channel) { setMessage(null); return }\n let overrides: Awaited<ReturnType<MessageTemplateStore['list']>> = []\n try {\n overrides = await store.list(tenantId)\n } catch (err) {\n console.warn('[automations] could not load overrides; showing defaults', err)\n }\n const found = resolveMessage(decodeURIComponent(eventKey), channel as MessageChannel, overrides, runtime?.events ?? [])\n setMessage(found)\n if (found) setDraft({ subject: found.subject, body: found.body })\n }, [eventKey, channel, store, tenantId, runtime])\n\n React.useEffect(() => { void reload() }, [reload])\n\n const header = (\n <SubpageHeader\n title={message === undefined ? '' : (message?.override?.name ?? message?.event.title ?? message?.event.name ?? 'Automação')}\n parentLabel=\"Automações\"\n onBack={back}\n />\n )\n\n if (message === undefined) {\n return (\n <div className=\"space-y-4\">\n {header}\n <div className=\"h-8 w-64 animate-pulse rounded bg-muted\" />\n <Card className=\"h-96 animate-pulse\" />\n </div>\n )\n }\n\n if (!message) {\n return (\n <>\n {header}\n <Card className=\"flex flex-col items-center gap-2 p-12 text-center\">\n <Mail className=\"h-9 w-9 text-muted-foreground/40\" strokeWidth={1.5} />\n <p className=\"font-semibold\">Automação não encontrada</p>\n <p className=\"max-w-sm text-sm text-muted-foreground\">\n O evento <code className=\"font-mono\">{eventKey}</code> não está no catálogo — o módulo\n que o registra pode não estar instalado nesta conta.\n </p>\n <Button variant=\"outline\" className=\"mt-2\" onClick={back}>Voltar para Automações</Button>\n </Card>\n </>\n )\n }\n\n const event = message.event\n // O texto de fábrica: o que \"restaurar padrão\" devolve. Vem do registro de\n // padrões, não do evento — o evento é o fato, não a mensagem.\n const fallback = { subject: message.override ? undefined : message.subject, body: message.body }\n const Icon = iconFor(event.icon)\n const current = draft ?? { subject: message.subject, body: message.body }\n const dirty = current.subject !== message.subject || current.body !== message.body\n const hasSubject = message.channel === 'email'\n\n const patch = async (input: Parameters<MessageTemplateStore['upsert']>[0]) => {\n setSaving(true)\n try {\n await store.upsert(input, tenantId)\n await reload()\n } catch (err) {\n console.warn('[automations] save failed', err)\n toast.error('Não foi possível salvar')\n } finally {\n setSaving(false)\n }\n }\n\n const save = () => void patch({\n eventKey: event.name,\n channel: message.channel,\n // Igual ao padrão volta a ser \"sem personalização\", não uma cópia.\n subject: current.subject.trim() === (fallback?.subject ?? '') ? null : current.subject.trim() || null,\n body: current.body.trim() === fallback?.body ? null : current.body.trim() || null,\n })\n\n const reset = async () => {\n setDraft({ subject: fallback?.subject ?? '', body: fallback?.body ?? '' })\n setSaving(true)\n try {\n // Apaga a linha inteira: com ela fora, o padrão volta a valer e melhorias\n // no texto de fábrica voltam a chegar aqui.\n await store.reset(event.name, message.channel, tenantId)\n await reload()\n toast.success('Texto restaurado')\n } catch (err) {\n console.warn('[automations] reset failed', err)\n toast.error('Não foi possível restaurar')\n } finally {\n setSaving(false)\n }\n }\n\n const previewSubject = renderMessageTemplate(current.subject, SAMPLE)\n const previewBody = renderMessageTemplate(current.body, SAMPLE)\n\n return (\n <div className=\"space-y-5\">\n {header}\n\n <div className=\"flex flex-wrap items-start gap-3\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border text-muted-foreground\">\n <Icon className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{CHANNEL_LABEL[message.channel]}</Badge>\n <Badge variant=\"outline\">{message.kind === 'marketing' ? 'Marketing' : 'Transacional'}</Badge>\n {message.customized && <Badge variant=\"info\">Personalizado</Badge>}\n </div>\n <p className=\"mt-0.5 text-sm text-muted-foreground\">{event.description}</p>\n </div>\n\n <div className=\"flex shrink-0 flex-wrap items-center gap-2\">\n <Hint label=\"Descarta o texto personalizado e volta ao padrão do produto.\">\n <span>\n <Button variant=\"outline\" onClick={() => void reset()} disabled={!message.customized || saving}>\n <RotateCcw className=\"mr-2 h-4 w-4\" />\n Restaurar padrão\n </Button>\n </span>\n </Hint>\n {/* O mesmo interruptor da lista: liga na hora, sem passar pelo Salvar\n — que aqui é só do TEXTO. */}\n <Switch\n size=\"md\"\n checked={message.enabled}\n onCheckedChange={(next) => void patch({ eventKey: event.name, channel: message.channel, enabled: next })}\n disabled={saving}\n label={message.enabled ? 'Ativa' : 'Inativa'}\n />\n <Button onClick={save} disabled={!dirty || saving}>\n {saving ? 'Salvando…' : dirty ? 'Salvar' : 'Salvo'}\n </Button>\n </div>\n </div>\n\n <HeaderTabs tabs={TABS} value={tab} onChange={setTab} aria-label=\"Visualização\" />\n\n <div className=\"flex flex-wrap items-center gap-x-6 gap-y-2 border-b border-border pb-4 text-xs text-muted-foreground\">\n <span className=\"inline-flex items-center gap-1.5\">\n <Zap className=\"h-3.5 w-3.5\" />\n Gatilho:\n <code className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-foreground\">{event.name}</code>\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <Clock className=\"h-3.5 w-3.5\" />\n {event.trigger}\n </span>\n {hasSubject && current.subject && <span className=\"min-w-0 truncate\">Assunto: {current.subject}</span>}\n </div>\n\n {tab === 'runs' ? (\n // Atrás de um projeto Fayz o histórico verdadeiro é o da plataforma —\n // é ela quem executa. Fora dele, o coletor local continua valendo.\n fayzConnection ? (\n <FayzRunLog connection={fayzConnection} eventKey={event.name} tenantId={tenantId} enabled={message.enabled} />\n ) : (\n <RunLog eventKey={event.name} tenantId={tenantId} enabled={message.enabled} />\n )\n ) : tab === 'preview' ? (\n <Card className=\"overflow-hidden\">\n <div className=\"flex items-center justify-between gap-3 border-b border-border px-4 py-2.5\">\n <span className=\"text-sm font-medium\">Prévia</span>\n <div className=\"flex items-center gap-1\">\n {(['desktop', 'mobile'] as const).map((d) => (\n <button\n key={d}\n type=\"button\"\n onClick={() => setDevice(d)}\n aria-label={d === 'desktop' ? 'Computador' : 'Celular'}\n className={`flex h-7 w-7 items-center justify-center rounded-md transition-colors ${\n device === d ? 'bg-muted text-foreground' : 'text-muted-foreground hover:bg-muted/60'\n }`}\n >\n {d === 'desktop' ? <Monitor className=\"h-4 w-4\" /> : <Smartphone className=\"h-4 w-4\" />}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"bg-muted/30 p-6\">\n {/* WhatsApp/SMS não têm assunto nem cabeçalho de remetente — mostrar\n a moldura de e-mail neles prometeria uma forma que o canal não\n tem. */}\n <div\n className={`mx-auto rounded-lg border border-border bg-card shadow-sm transition-[max-width] ${\n device === 'mobile' ? 'max-w-[380px]' : hasSubject ? 'max-w-[600px]' : 'max-w-[420px]'\n }`}\n >\n {hasSubject ? (\n <>\n <div className=\"border-b border-border px-6 py-4 text-sm font-semibold\">{SAMPLE.store_name}</div>\n <div className=\"space-y-1 border-b border-border px-6 py-3\">\n <p className=\"text-[11px] uppercase tracking-wide text-muted-foreground\">Assunto</p>\n <p className=\"text-sm font-medium\">{previewSubject}</p>\n </div>\n <div className=\"whitespace-pre-wrap px-6 py-5 text-sm leading-relaxed\">{previewBody}</div>\n </>\n ) : (\n <div className=\"p-4\">\n <div className=\"whitespace-pre-wrap rounded-2xl rounded-tl-sm bg-[#dcf8c6] px-3 py-2 text-sm leading-relaxed text-[#111b21]\">\n {previewBody}\n </div>\n </div>\n )}\n </div>\n <p className=\"mt-4 text-center text-xs text-muted-foreground\">\n Dados de exemplo — nenhum registro real foi usado.\n </p>\n </div>\n </Card>\n ) : (\n <Card className=\"space-y-4 p-4\">\n {hasSubject && (\n <div>\n <label className=\"mb-1 block text-xs font-medium text-muted-foreground\">Assunto</label>\n <input\n value={current.subject}\n onChange={(e) => setDraft({ ...current, subject: e.target.value })}\n className=\"w-full rounded-input border border-input bg-card px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n )}\n <div>\n <label className=\"mb-1 block text-xs font-medium text-muted-foreground\">Mensagem</label>\n <textarea\n rows={14}\n value={current.body}\n onChange={(e) => setDraft({ ...current, body: e.target.value })}\n className=\"w-full rounded-input border border-input bg-card px-3 py-2 font-mono text-xs leading-relaxed focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n <div>\n <p className=\"mb-1.5 text-xs font-medium text-muted-foreground\">\n Campos deste evento — o envio substitui pelo dado real\n </p>\n <div className=\"flex flex-wrap gap-1\">\n {message.placeholders.map((p) => (\n <span key={p} className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-muted-foreground\">\n {p}\n </span>\n ))}\n </div>\n </div>\n </Card>\n )}\n </div>\n )\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport type { MessageTemplate, UpsertMessageTemplateInput } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Acesso aos modelos personalizados. Só as PERSONALIZAÇÕES: o catálogo é\n// código, e uma leitura que falha ainda deve mostrar a lista inteira nos\n// padrões — ver `resolveMessages`.\n// ---------------------------------------------------------------------------\n\nconst TABLE = 'plg_automations_templates'\n\nfunction rowToTemplate(row: any): MessageTemplate {\n return {\n id: row.id,\n tenantId: row.tenant_id,\n eventKey: row.event_key,\n channel: row.channel ?? 'email',\n // NULL fica NULL: quem decide o padrão é o catálogo, não este mapeamento.\n // Colapsar para `false` aqui desligaria em silêncio todo modelo cuja linha\n // só existe porque o texto foi editado.\n enabled: row.enabled ?? null,\n // String vazia e NULL significam a mesma coisa — \"sem personalização\" —,\n // senão um assunto apagado sairia em branco em vez de voltar ao padrão.\n subject: row.subject || null,\n body: row.body || null,\n name: row.name || null,\n updatedAt: row.updated_at ?? row.created_at,\n }\n}\n\nexport interface MessageTemplateStore {\n list(tenantId?: string): Promise<MessageTemplate[]>\n upsert(input: UpsertMessageTemplateInput, tenantId?: string): Promise<MessageTemplate>\n /** Descarta a personalização inteira — a linha some e o padrão volta a valer. */\n reset(eventKey: string, channel: string, tenantId?: string): Promise<void>\n}\n\nexport function createSupabaseTemplateStore(): MessageTemplateStore {\n const db = () => {\n const client = getSupabaseClientOptional()\n if (!client) throw new Error('@fayz-ai/plugin-automations: Supabase client not initialized')\n return client as any\n }\n\n return {\n async list(tenantId) {\n let q = db().from(TABLE).select('*')\n if (tenantId) q = q.eq('tenant_id', tenantId)\n const { data, error } = await q\n if (error) throw error\n return (data ?? []).map(rowToTemplate)\n },\n\n async upsert(input, tenantId) {\n const payload: Record<string, unknown> = {\n tenant_id: tenantId,\n event_key: input.eventKey,\n channel: input.channel,\n }\n // Só o que veio: omitir uma chave tem de significar \"não mexa nisso\",\n // senão salvar o texto apagaria o ligado/desligado junto.\n if (input.enabled !== undefined) payload.enabled = input.enabled\n if (input.subject !== undefined) payload.subject = input.subject\n if (input.body !== undefined) payload.body = input.body\n if (input.name !== undefined) payload.name = input.name\n\n const { data, error } = await db()\n .from(TABLE)\n .upsert(payload, { onConflict: 'tenant_id,event_key,channel' })\n .select().single()\n if (error) throw error\n return rowToTemplate(data)\n },\n\n async reset(eventKey, channel, tenantId) {\n let q = db().from(TABLE).delete().eq('event_key', eventKey).eq('channel', channel)\n if (tenantId) q = q.eq('tenant_id', tenantId)\n const { error } = await q\n if (error) throw error\n },\n }\n}\n","import React from 'react'\nimport type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'\nimport { startEventLog } from '@fayz-ai/core'\nimport { resolveFayzAgentConnection } from '@fayz-ai/admin'\nimport { AutomationsList } from './views/AutomationsList'\nimport { AutomationDetailPage } from './views/AutomationDetailPage'\nimport { createSupabaseTemplateStore, type MessageTemplateStore } from './data/templates'\nimport { createFayzTemplateStore } from './data/fayz'\n\n// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-automations — everything the product SENDS, in one place.\n//\n// ONE automation = when THIS happens, send THAT over THIS channel.\n//\n// Events do NOT live here. Each module DECLARES them in its own manifest\n// (`events`) and the runtime aggregates the active plugins' — the store brings\n// the order's, the CRM the pipeline's. If this screen had to import store and\n// CRM, an app installing only the CRM would carry the store catalog too, and\n// every new module would mean another import in here.\n//\n// The same catalog feeds integrations (webhooks) and audit: three readers of the\n// SAME fact, which is why the message text is not part of it.\n// ---------------------------------------------------------------------------\n\nexport interface AutomationsPluginOptions {\n navPosition?: number\n navSection?: 'main' | 'secondary' | 'settings'\n navLabel?: string\n /**\n * Where the list lives.\n *\n * 'nav' its own menu item (default) — for apps where sending is daily\n * routine, like the store.\n * 'settings' a tab inside settings, no menu item. In a salon the calendar is\n * what runs all day; automations are configured once, and a fixed\n * top-level item charges attention daily for a monthly screen.\n */\n placement?: 'nav' | 'settings'\n scope?: PluginScope\n verticalId?: VerticalId\n /** Swaps data access (tests, mock mode). */\n store?: MessageTemplateStore\n}\n\nexport function createAutomationsPlugin(options?: AutomationsPluginOptions): PluginManifest {\n // Built once per manifest: the store holds no state, and rebuilding it every\n // render would remount the effects that depend on it.\n // Behind a Fayz project the platform executes the automations, so the\n // customisations live there; outside one, the local table keeps working.\n const connection = resolveFayzAgentConnection()\n const store = options?.store\n ?? (connection ? createFayzTemplateStore(connection) : createSupabaseTemplateStore())\n\n // Turns on the trigger history. Idempotent, and from here on EVERY event the\n // app emits is recorded, not only those with a message — it is the same\n // history webhooks and audit read.\n startEventLog()\n\n const inSettings = options?.placement === 'settings'\n\n const ListPage: React.ComponentType<unknown> = () =>\n React.createElement(AutomationsList, { store })\n ListPage.displayName = 'AutomationsList'\n\n const DetailPage: React.ComponentType<unknown> = (props) =>\n React.createElement(AutomationDetailPage, {\n ...(props as { eventKey?: string; channel?: string }),\n store,\n // \"Back\" must return you through the door you came in: opening the list\n // inside settings must not drop you on a loose page that app's menu does\n // not have.\n backTo: inSettings ? '/settings/automations' : '/automations',\n })\n DetailPage.displayName = 'AutomationDetail'\n\n const READ = { feature: 'automations', action: 'read' as const }\n\n return {\n id: 'automations',\n name: options?.navLabel ?? 'Automações',\n icon: 'Zap',\n version: '2.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [{ id: 'automations', label: 'Automations', group: 'Automate' }],\n navigation: inSettings ? [] : [\n {\n section: options?.navSection ?? 'main',\n position: options?.navPosition ?? 6,\n label: options?.navLabel ?? 'Automações',\n route: '/automations',\n icon: 'Zap',\n permission: READ,\n indexChild: false,\n },\n ],\n // The SAME list, served inside settings — not a second screen.\n settings: inSettings ? [\n { id: 'automations', label: options?.navLabel ?? 'Automações', icon: 'Zap', component: ListPage, permission: READ },\n ] : [],\n routes: [\n { path: '/automations', component: ListPage, permission: READ },\n // One automation's detail. Off-menu: it is a row of the list. Its back\n // link comes from `backTo`.\n { path: '/automations/:eventKey/:channel', component: DetailPage, permission: READ },\n ],\n widgets: [],\n }\n}\n\nexport { createSupabaseTemplateStore }\nexport { createFayzTemplateStore } from './data/fayz'\nexport type { MessageTemplateStore }\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { UnifiedConnector } from '@fayz-ai/admin';
|
|
2
|
+
import type { ConnectorDelivery } from '@fayz-ai/core';
|
|
3
|
+
export interface ConnectorAutomationRow {
|
|
4
|
+
connectorId: string;
|
|
5
|
+
connectorName: string;
|
|
6
|
+
/** Onde a integração é configurada — para onde a linha leva. */
|
|
7
|
+
hostPluginId?: string;
|
|
8
|
+
/** A cara da integração, resolvida como em qualquer outra tela (ConnectorMark). */
|
|
9
|
+
icon?: string;
|
|
10
|
+
logoUrl?: string;
|
|
11
|
+
eventKey: string;
|
|
12
|
+
label: string;
|
|
13
|
+
/** O locatário pode desligar esta e seguir conectado. */
|
|
14
|
+
optional: boolean;
|
|
15
|
+
/** Registro a registro: o que chegou no provedor. Ausente = a integração não conta. */
|
|
16
|
+
listDeliveries?: (options?: {
|
|
17
|
+
eventKey?: string;
|
|
18
|
+
limit?: number;
|
|
19
|
+
}) => Promise<ConnectorDelivery[]>;
|
|
20
|
+
}
|
|
21
|
+
/** As linhas de automação dos conectores CONECTADOS. Nada dos demais. */
|
|
22
|
+
export declare function connectorAutomationRows(connectors: UnifiedConnector[]): ConnectorAutomationRow[];
|
|
23
|
+
/** Agrupadas por conector: o dono precisa estar escrito em cima das linhas. */
|
|
24
|
+
export declare function groupConnectorAutomations(rows: ConnectorAutomationRow[]): {
|
|
25
|
+
connectorId: string;
|
|
26
|
+
connectorName: string;
|
|
27
|
+
hostPluginId?: string;
|
|
28
|
+
icon?: string;
|
|
29
|
+
logoUrl?: string;
|
|
30
|
+
items: ConnectorAutomationRow[];
|
|
31
|
+
}[];
|
|
32
|
+
//# sourceMappingURL=connector-automations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connector-automations.d.ts","sourceRoot":"","sources":["../../src/lib/connector-automations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAiBtD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,QAAQ,EAAE,OAAO,CAAA;IACjB,uFAAuF;IACvF,cAAc,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAA;CACnG;AAED,yEAAyE;AACzE,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,gBAAgB,EAAE,GAAG,sBAAsB,EAAE,CAqBhG;AAED,+EAA+E;AAC/E,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,sBAAsB,EAAE,GAC7B;IACD,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,sBAAsB,EAAE,CAAA;CAChC,EAAE,CAkBF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutomationDetailPage.d.ts","sourceRoot":"","sources":["../../src/views/AutomationDetailPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAiD7D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,oBAAoB,CAAA;IAC3B;oEACgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,oBAAoB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,MAAuB,EAAE,EAAE,yBAAyB,
|
|
1
|
+
{"version":3,"file":"AutomationDetailPage.d.ts","sourceRoot":"","sources":["../../src/views/AutomationDetailPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAiD7D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,oBAAoB,CAAA;IAC3B;oEACgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,oBAAoB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,MAAuB,EAAE,EAAE,yBAAyB,qBAyQpH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutomationsList.d.ts","sourceRoot":"","sources":["../../src/views/AutomationsList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"AutomationsList.d.ts","sourceRoot":"","sources":["../../src/views/AutomationsList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAwD7D,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,oBAAoB,CAAA;CAAE,qBA0JzE"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type ConnectorAutomationRow } from '../lib/connector-automations';
|
|
3
|
+
export declare function ConnectorAutomations({ rows }: {
|
|
4
|
+
rows: ConnectorAutomationRow[];
|
|
5
|
+
}): React.JSX.Element | null;
|
|
6
|
+
//# sourceMappingURL=ConnectorAutomations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConnectorAutomations.d.ts","sourceRoot":"","sources":["../../src/views/ConnectorAutomations.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,8BAA8B,CAAA;AAYrC,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,sBAAsB,EAAE,CAAA;CAAE,4BAyBhF"}
|
package/dist/views/RunLog.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { ResolvedFayzAgentConnection } from '@fayz-ai/admin';
|
|
2
3
|
export declare function RunLog({ eventKey, tenantId, enabled }: {
|
|
3
4
|
eventKey: string;
|
|
4
5
|
tenantId?: string;
|
|
5
|
-
/**
|
|
6
|
+
/** Current automation state — changes what the empty state means. */
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
}): React.JSX.Element;
|
|
9
|
+
export declare function FayzRunLog({ connection, eventKey, tenantId, enabled }: {
|
|
10
|
+
connection: ResolvedFayzAgentConnection;
|
|
11
|
+
eventKey: string;
|
|
12
|
+
tenantId?: string;
|
|
13
|
+
/** Current automation state — changes what the empty state means. */
|
|
6
14
|
enabled: boolean;
|
|
7
15
|
}): React.JSX.Element;
|
|
8
16
|
//# sourceMappingURL=RunLog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RunLog.d.ts","sourceRoot":"","sources":["../../src/views/RunLog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"RunLog.d.ts","sourceRoot":"","sources":["../../src/views/RunLog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAA;AAmGjE,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;IACtD,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qEAAqE;IACrE,OAAO,EAAE,OAAO,CAAA;CACjB,qBA2CA;AAuCD,wBAAgB,UAAU,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;IACtE,UAAU,EAAE,2BAA2B,CAAA;IACvC,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qEAAqE;IACrE,OAAO,EAAE,OAAO,CAAA;CACjB,qBAoDA"}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"fayz": {
|
|
4
4
|
"status": "preview"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.10.1",
|
|
7
7
|
"description": "[experimental] Fayz SDK — workflows & automations plugin",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"sideEffects": false,
|
|
@@ -25,15 +25,17 @@
|
|
|
25
25
|
"lucide-react": ">=0.400.0 <1.0.0"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@fayz-ai/core": "^0.
|
|
29
|
-
"@fayz-ai/admin": "^0.
|
|
30
|
-
"@fayz-ai/
|
|
28
|
+
"@fayz-ai/core": "^0.12.0",
|
|
29
|
+
"@fayz-ai/admin": "^0.12.0",
|
|
30
|
+
"@fayz-ai/sdk": "^0.12.0",
|
|
31
|
+
"@fayz-ai/ui": "^0.12.0"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@types/react": "^18.3.0",
|
|
34
35
|
"react": "^18.3.0",
|
|
35
36
|
"tsup": "^8.2.0",
|
|
36
37
|
"typescript": "^5.5.0",
|
|
38
|
+
"vitest": "^4.1.5",
|
|
37
39
|
"@types/react-dom": "^18.3.0",
|
|
38
40
|
"lucide-react": "^0.400.0"
|
|
39
41
|
},
|
|
@@ -50,6 +52,7 @@
|
|
|
50
52
|
"build": "tsup && tsc --emitDeclarationOnly --declaration --declarationMap --noEmit false",
|
|
51
53
|
"dev": "tsup --watch",
|
|
52
54
|
"typecheck": "tsc --noEmit",
|
|
55
|
+
"test": "vitest run",
|
|
53
56
|
"clean": "rm -rf dist"
|
|
54
57
|
}
|
|
55
58
|
}
|