@supyagent/sdk 0.1.5 → 0.1.7
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/react.cjs +2874 -130
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +194 -18
- package/dist/react.d.ts +194 -18
- package/dist/react.js +2842 -125
- package/dist/react.js.map +1 -1
- package/package.json +3 -2
package/dist/react.js
CHANGED
|
@@ -15,7 +15,21 @@ import {
|
|
|
15
15
|
Bell,
|
|
16
16
|
FileText,
|
|
17
17
|
Table2,
|
|
18
|
-
Presentation
|
|
18
|
+
Presentation,
|
|
19
|
+
Search,
|
|
20
|
+
Terminal,
|
|
21
|
+
Send,
|
|
22
|
+
CircleDot,
|
|
23
|
+
Briefcase,
|
|
24
|
+
Users,
|
|
25
|
+
CreditCard,
|
|
26
|
+
SquareKanban,
|
|
27
|
+
Cloud,
|
|
28
|
+
CalendarClock,
|
|
29
|
+
Phone,
|
|
30
|
+
MessageCircle,
|
|
31
|
+
UserCircle,
|
|
32
|
+
Monitor
|
|
19
33
|
} from "lucide-react";
|
|
20
34
|
|
|
21
35
|
// src/ui/utils.ts
|
|
@@ -49,12 +63,35 @@ var PROVIDER_LABELS = {
|
|
|
49
63
|
inbox: "Inbox",
|
|
50
64
|
docs: "Docs",
|
|
51
65
|
sheets: "Sheets",
|
|
52
|
-
slides: "Slides"
|
|
66
|
+
slides: "Slides",
|
|
67
|
+
search: "Search",
|
|
68
|
+
compute: "Compute",
|
|
69
|
+
resend: "Resend",
|
|
70
|
+
linear: "Linear",
|
|
71
|
+
pipedrive: "Pipedrive",
|
|
72
|
+
stripe: "Stripe",
|
|
73
|
+
jira: "Jira",
|
|
74
|
+
salesforce: "Salesforce",
|
|
75
|
+
brevo: "Brevo",
|
|
76
|
+
calendly: "Calendly",
|
|
77
|
+
twilio: "Twilio"
|
|
53
78
|
};
|
|
54
79
|
function getProviderLabel(provider) {
|
|
55
80
|
return PROVIDER_LABELS[provider] || provider.charAt(0).toUpperCase() + provider.slice(1);
|
|
56
81
|
}
|
|
82
|
+
var MICROSOFT_PREFIX_MAP = [
|
|
83
|
+
["microsoft_mail_", "email"],
|
|
84
|
+
["microsoft_email_", "email"],
|
|
85
|
+
["outlook_", "email"],
|
|
86
|
+
["microsoft_calendar_", "calendar"],
|
|
87
|
+
["microsoft_drive_", "drive"],
|
|
88
|
+
["onedrive_", "drive"]
|
|
89
|
+
];
|
|
57
90
|
function getFormatterType(toolName) {
|
|
91
|
+
const lower = toolName.toLowerCase();
|
|
92
|
+
for (const [prefix, type] of MICROSOFT_PREFIX_MAP) {
|
|
93
|
+
if (lower.startsWith(prefix)) return type;
|
|
94
|
+
}
|
|
58
95
|
const provider = getProviderFromToolName(toolName);
|
|
59
96
|
switch (provider) {
|
|
60
97
|
case "gmail":
|
|
@@ -67,6 +104,48 @@ function getFormatterType(toolName) {
|
|
|
67
104
|
return "github";
|
|
68
105
|
case "drive":
|
|
69
106
|
return "drive";
|
|
107
|
+
case "search":
|
|
108
|
+
return "search";
|
|
109
|
+
case "docs":
|
|
110
|
+
return "docs";
|
|
111
|
+
case "sheets":
|
|
112
|
+
return "sheets";
|
|
113
|
+
case "slides":
|
|
114
|
+
return "slides";
|
|
115
|
+
case "hubspot":
|
|
116
|
+
return "hubspot";
|
|
117
|
+
case "linear":
|
|
118
|
+
return "linear";
|
|
119
|
+
case "pipedrive":
|
|
120
|
+
return "pipedrive";
|
|
121
|
+
case "compute":
|
|
122
|
+
return "compute";
|
|
123
|
+
case "resend":
|
|
124
|
+
return "resend";
|
|
125
|
+
case "inbox":
|
|
126
|
+
return "inbox";
|
|
127
|
+
case "discord":
|
|
128
|
+
return "discord";
|
|
129
|
+
case "notion":
|
|
130
|
+
return "notion";
|
|
131
|
+
case "twitter":
|
|
132
|
+
return "twitter";
|
|
133
|
+
case "telegram":
|
|
134
|
+
return "telegram";
|
|
135
|
+
case "stripe":
|
|
136
|
+
return "stripe";
|
|
137
|
+
case "jira":
|
|
138
|
+
return "jira";
|
|
139
|
+
case "salesforce":
|
|
140
|
+
return "salesforce";
|
|
141
|
+
case "brevo":
|
|
142
|
+
return "brevo";
|
|
143
|
+
case "calendly":
|
|
144
|
+
return "calendly";
|
|
145
|
+
case "twilio":
|
|
146
|
+
return "twilio";
|
|
147
|
+
case "linkedin":
|
|
148
|
+
return "linkedin";
|
|
70
149
|
default:
|
|
71
150
|
return "generic";
|
|
72
151
|
}
|
|
@@ -85,7 +164,25 @@ var ICON_MAP = {
|
|
|
85
164
|
inbox: Bell,
|
|
86
165
|
docs: FileText,
|
|
87
166
|
sheets: Table2,
|
|
88
|
-
slides: Presentation
|
|
167
|
+
slides: Presentation,
|
|
168
|
+
search: Search,
|
|
169
|
+
compute: Terminal,
|
|
170
|
+
resend: Send,
|
|
171
|
+
linear: CircleDot,
|
|
172
|
+
pipedrive: Briefcase,
|
|
173
|
+
hubspot: Users,
|
|
174
|
+
stripe: CreditCard,
|
|
175
|
+
jira: SquareKanban,
|
|
176
|
+
salesforce: Cloud,
|
|
177
|
+
brevo: Send,
|
|
178
|
+
calendly: CalendarClock,
|
|
179
|
+
twilio: Phone,
|
|
180
|
+
twitter: MessageCircle,
|
|
181
|
+
linkedin: UserCircle,
|
|
182
|
+
microsoft: Monitor,
|
|
183
|
+
outlook: Mail,
|
|
184
|
+
onedrive: HardDrive,
|
|
185
|
+
telegram: Send
|
|
89
186
|
};
|
|
90
187
|
function ProviderIcon({ toolName, className = "h-4 w-4" }) {
|
|
91
188
|
const provider = getProviderFromToolName(toolName);
|
|
@@ -95,70 +192,622 @@ function ProviderIcon({ toolName, className = "h-4 w-4" }) {
|
|
|
95
192
|
|
|
96
193
|
// src/ui/tool-call.tsx
|
|
97
194
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
195
|
+
function extractToolName(part) {
|
|
196
|
+
if (part.type.startsWith("tool-") && part.type !== "tool-invocation") {
|
|
197
|
+
return part.type.slice(5);
|
|
198
|
+
}
|
|
199
|
+
if (part.type === "dynamic-tool" && part.toolName) {
|
|
200
|
+
return part.toolName;
|
|
201
|
+
}
|
|
202
|
+
if (part.toolName) return part.toolName;
|
|
203
|
+
if (part.toolInvocation?.toolName) return part.toolInvocation.toolName;
|
|
204
|
+
return "unknown";
|
|
205
|
+
}
|
|
206
|
+
function extractState(part) {
|
|
207
|
+
return part.state || part.toolInvocation?.state || "input-available";
|
|
208
|
+
}
|
|
209
|
+
function extractArgs(part) {
|
|
210
|
+
return part.input || part.args || part.toolInvocation?.args;
|
|
211
|
+
}
|
|
98
212
|
function SupyagentToolCall({ part }) {
|
|
99
213
|
const [expanded, setExpanded] = useState(false);
|
|
100
|
-
const toolName = part
|
|
101
|
-
const state = part
|
|
102
|
-
const args = part
|
|
214
|
+
const toolName = extractToolName(part);
|
|
215
|
+
const state = extractState(part);
|
|
216
|
+
const args = extractArgs(part);
|
|
103
217
|
const provider = getProviderFromToolName(toolName);
|
|
104
218
|
const providerLabel = getProviderLabel(provider);
|
|
105
219
|
const actionLabel = humanizeToolName(toolName);
|
|
106
220
|
const isStreaming = state === "input-streaming";
|
|
107
221
|
const isError = state === "output-error";
|
|
108
222
|
const isDone = state === "output-available";
|
|
109
|
-
return /* @__PURE__ */ jsxs(
|
|
110
|
-
|
|
223
|
+
return /* @__PURE__ */ jsxs(
|
|
224
|
+
"div",
|
|
225
|
+
{
|
|
226
|
+
className: "rounded-lg border border-border bg-card overflow-hidden",
|
|
227
|
+
"data-state": isDone ? "done" : isError ? "error" : isStreaming ? "streaming" : "pending",
|
|
228
|
+
children: [
|
|
229
|
+
/* @__PURE__ */ jsxs(
|
|
230
|
+
"button",
|
|
231
|
+
{
|
|
232
|
+
type: "button",
|
|
233
|
+
onClick: () => args && setExpanded(!expanded),
|
|
234
|
+
className: "flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-muted transition-colors",
|
|
235
|
+
children: [
|
|
236
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
237
|
+
/* @__PURE__ */ jsx2(ProviderIcon, { toolName, className: "h-4 w-4 text-muted-foreground" }),
|
|
238
|
+
isStreaming && /* @__PURE__ */ jsx2(Loader2, { className: "absolute -top-1 -right-1 h-3 w-3 text-primary animate-spin" })
|
|
239
|
+
] }),
|
|
240
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs text-muted-foreground", children: providerLabel }),
|
|
241
|
+
/* @__PURE__ */ jsx2("span", { className: "text-sm text-foreground flex-1", children: actionLabel }),
|
|
242
|
+
isDone && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-green-500/10 px-2 py-0.5 text-xs text-green-500", children: [
|
|
243
|
+
/* @__PURE__ */ jsx2(Check, { className: "h-3 w-3" }),
|
|
244
|
+
"Completed"
|
|
245
|
+
] }),
|
|
246
|
+
isError && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-destructive/10 px-2 py-0.5 text-xs text-destructive", children: [
|
|
247
|
+
/* @__PURE__ */ jsx2(AlertCircle, { className: "h-3 w-3" }),
|
|
248
|
+
"Error"
|
|
249
|
+
] }),
|
|
250
|
+
isStreaming && /* @__PURE__ */ jsx2("span", { className: "inline-flex items-center gap-1 rounded-full bg-primary/10 px-2 py-0.5 text-xs text-primary animate-pulse", children: "Calling..." }),
|
|
251
|
+
args && (expanded ? /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" }) : /* @__PURE__ */ jsx2(ChevronRight, { className: "h-3.5 w-3.5 text-muted-foreground" }))
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
),
|
|
255
|
+
expanded && args && /* @__PURE__ */ jsx2("div", { className: "border-t border-border px-3 py-2", children: /* @__PURE__ */ jsx2("pre", { className: "text-xs text-muted-foreground overflow-x-auto", children: JSON.stringify(args, null, 2) }) })
|
|
256
|
+
]
|
|
257
|
+
}
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// src/ui/collapsible-result.tsx
|
|
262
|
+
import { useState as useState2 } from "react";
|
|
263
|
+
import { ChevronDown as ChevronDown2, ChevronRight as ChevronRight2 } from "lucide-react";
|
|
264
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
265
|
+
var BADGE_STYLES = {
|
|
266
|
+
default: "bg-muted text-muted-foreground",
|
|
267
|
+
success: "bg-green-500/10 text-green-500",
|
|
268
|
+
error: "bg-destructive/10 text-destructive",
|
|
269
|
+
warning: "bg-yellow-500/10 text-yellow-600"
|
|
270
|
+
};
|
|
271
|
+
function CollapsibleResult({
|
|
272
|
+
toolName,
|
|
273
|
+
summary,
|
|
274
|
+
badge,
|
|
275
|
+
defaultExpanded = false,
|
|
276
|
+
children
|
|
277
|
+
}) {
|
|
278
|
+
const [expanded, setExpanded] = useState2(defaultExpanded);
|
|
279
|
+
const provider = getProviderFromToolName(toolName);
|
|
280
|
+
const providerLabel = getProviderLabel(provider);
|
|
281
|
+
return /* @__PURE__ */ jsxs2("div", { className: "rounded-lg border border-border bg-card overflow-hidden", children: [
|
|
282
|
+
/* @__PURE__ */ jsxs2(
|
|
111
283
|
"button",
|
|
112
284
|
{
|
|
113
285
|
type: "button",
|
|
114
|
-
onClick: () =>
|
|
115
|
-
className: "flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-
|
|
286
|
+
onClick: () => setExpanded(!expanded),
|
|
287
|
+
className: "flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-muted transition-colors",
|
|
116
288
|
children: [
|
|
117
|
-
/* @__PURE__ */
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
289
|
+
/* @__PURE__ */ jsx3(ProviderIcon, { toolName, className: "h-4 w-4 text-muted-foreground" }),
|
|
290
|
+
/* @__PURE__ */ jsx3("span", { className: "text-xs text-muted-foreground", children: providerLabel }),
|
|
291
|
+
/* @__PURE__ */ jsx3("span", { className: "text-sm text-foreground flex-1 truncate", children: summary }),
|
|
292
|
+
badge && /* @__PURE__ */ jsx3(
|
|
293
|
+
"span",
|
|
294
|
+
{
|
|
295
|
+
className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${BADGE_STYLES[badge.variant || "default"]}`,
|
|
296
|
+
children: badge.text
|
|
297
|
+
}
|
|
298
|
+
),
|
|
299
|
+
expanded ? /* @__PURE__ */ jsx3(ChevronDown2, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }) : /* @__PURE__ */ jsx3(ChevronRight2, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" })
|
|
127
300
|
]
|
|
128
301
|
}
|
|
129
302
|
),
|
|
130
|
-
|
|
303
|
+
/* @__PURE__ */ jsx3(
|
|
304
|
+
"div",
|
|
305
|
+
{
|
|
306
|
+
className: "grid transition-[grid-template-rows] duration-200 ease-out",
|
|
307
|
+
style: { gridTemplateRows: expanded ? "1fr" : "0fr" },
|
|
308
|
+
children: /* @__PURE__ */ jsx3("div", { className: "overflow-hidden", children: /* @__PURE__ */ jsx3("div", { className: "border-t border-border px-3 py-2", children }) })
|
|
309
|
+
}
|
|
310
|
+
)
|
|
131
311
|
] });
|
|
132
312
|
}
|
|
133
313
|
|
|
314
|
+
// src/ui/summaries.ts
|
|
315
|
+
function countItems(data, ...keys) {
|
|
316
|
+
if (Array.isArray(data)) return data.length;
|
|
317
|
+
if (typeof data === "object" && data !== null) {
|
|
318
|
+
for (const key of keys) {
|
|
319
|
+
const val = data[key];
|
|
320
|
+
if (Array.isArray(val)) return val.length;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return 0;
|
|
324
|
+
}
|
|
325
|
+
function actionFromToolName(toolName) {
|
|
326
|
+
const lower = toolName.toLowerCase();
|
|
327
|
+
if (lower.includes("send") || lower.includes("create") || lower.includes("post")) return "send";
|
|
328
|
+
if (lower.includes("list") || lower.includes("search") || lower.includes("fetch") || lower.includes("get_all")) return "list";
|
|
329
|
+
return "get";
|
|
330
|
+
}
|
|
331
|
+
function countBadge(n) {
|
|
332
|
+
return n > 0 ? { text: String(n), variant: "default" } : void 0;
|
|
333
|
+
}
|
|
334
|
+
function getEmailSummary(data, toolName) {
|
|
335
|
+
const action = actionFromToolName(toolName);
|
|
336
|
+
if (action === "send") {
|
|
337
|
+
const to = typeof data === "object" && data !== null && "to" in data ? String(data.to) : void 0;
|
|
338
|
+
return { text: to ? `Sent email to ${to}` : "Sent email", badge: { text: "Sent", variant: "success" } };
|
|
339
|
+
}
|
|
340
|
+
const n = countItems(data, "messages");
|
|
341
|
+
if (n > 0) return { text: `Listed ${n} emails`, badge: countBadge(n) };
|
|
342
|
+
if (typeof data === "object" && data !== null && "subject" in data) {
|
|
343
|
+
return { text: `Email: ${data.subject}` };
|
|
344
|
+
}
|
|
345
|
+
return { text: "Email result" };
|
|
346
|
+
}
|
|
347
|
+
function getCalendarSummary(data, toolName) {
|
|
348
|
+
const action = actionFromToolName(toolName);
|
|
349
|
+
if (action === "send") {
|
|
350
|
+
const summary = typeof data === "object" && data !== null && "summary" in data ? String(data.summary) : void 0;
|
|
351
|
+
return { text: summary ? `Created event: ${summary}` : "Created event", badge: { text: "Created", variant: "success" } };
|
|
352
|
+
}
|
|
353
|
+
const n = countItems(data, "events", "items");
|
|
354
|
+
if (n > 0) return { text: `Listed ${n} events`, badge: countBadge(n) };
|
|
355
|
+
if (typeof data === "object" && data !== null && "summary" in data) {
|
|
356
|
+
return { text: String(data.summary) };
|
|
357
|
+
}
|
|
358
|
+
return { text: "Calendar result" };
|
|
359
|
+
}
|
|
360
|
+
function getSlackSummary(data, toolName) {
|
|
361
|
+
const action = actionFromToolName(toolName);
|
|
362
|
+
if (typeof data === "object" && data !== null && "channels" in data) {
|
|
363
|
+
const n2 = Array.isArray(data.channels) ? data.channels.length : 0;
|
|
364
|
+
return { text: `Listed ${n2} channels`, badge: countBadge(n2) };
|
|
365
|
+
}
|
|
366
|
+
if (action === "send") {
|
|
367
|
+
const ch = typeof data === "object" && data !== null && "channel" in data ? String(data.channel) : void 0;
|
|
368
|
+
return { text: ch ? `Sent message to #${ch}` : "Sent message", badge: { text: "Sent", variant: "success" } };
|
|
369
|
+
}
|
|
370
|
+
const n = countItems(data, "messages");
|
|
371
|
+
if (n > 0) {
|
|
372
|
+
const ch = typeof data === "object" && data !== null && "channel" in data ? String(data.channel) : void 0;
|
|
373
|
+
return { text: ch ? `${n} messages in #${ch}` : `${n} messages`, badge: countBadge(n) };
|
|
374
|
+
}
|
|
375
|
+
return { text: "Slack result" };
|
|
376
|
+
}
|
|
377
|
+
function getGithubSummary(data, toolName) {
|
|
378
|
+
const n = countItems(data);
|
|
379
|
+
if (n > 0) {
|
|
380
|
+
const isPR = toolName.toLowerCase().includes("pull") || toolName.toLowerCase().includes("pr");
|
|
381
|
+
return { text: isPR ? `Listed ${n} pull requests` : `Listed ${n} issues`, badge: countBadge(n) };
|
|
382
|
+
}
|
|
383
|
+
if (typeof data === "object" && data !== null && "title" in data) {
|
|
384
|
+
const num = "number" in data ? ` #${data.number}` : "";
|
|
385
|
+
return { text: `${data.title}${num}` };
|
|
386
|
+
}
|
|
387
|
+
return { text: "GitHub result" };
|
|
388
|
+
}
|
|
389
|
+
function getDriveSummary(data, toolName) {
|
|
390
|
+
const n = countItems(data, "files");
|
|
391
|
+
if (n > 0) return { text: `Listed ${n} files`, badge: countBadge(n) };
|
|
392
|
+
if (typeof data === "object" && data !== null && "name" in data) {
|
|
393
|
+
return { text: String(data.name) };
|
|
394
|
+
}
|
|
395
|
+
return { text: "Drive result" };
|
|
396
|
+
}
|
|
397
|
+
function getSearchSummary(data) {
|
|
398
|
+
let n = 0;
|
|
399
|
+
if (typeof data === "object" && data !== null) {
|
|
400
|
+
const d = data;
|
|
401
|
+
if (Array.isArray(d.results)) n = d.results.length;
|
|
402
|
+
else if (Array.isArray(d.organic)) n = d.organic.length;
|
|
403
|
+
}
|
|
404
|
+
if (n > 0) return { text: `Found ${n} results`, badge: countBadge(n) };
|
|
405
|
+
return { text: "Search result" };
|
|
406
|
+
}
|
|
407
|
+
function getDocsSummary(data) {
|
|
408
|
+
if (typeof data === "object" && data !== null && "title" in data) {
|
|
409
|
+
return { text: `Document: ${data.title}` };
|
|
410
|
+
}
|
|
411
|
+
return { text: "Document result" };
|
|
412
|
+
}
|
|
413
|
+
function getSheetsSummary(data) {
|
|
414
|
+
if (typeof data === "object" && data !== null) {
|
|
415
|
+
const d = data;
|
|
416
|
+
if (d.updatedCells) return { text: `Updated ${d.updatedCells} cells`, badge: countBadge(Number(d.updatedCells)) };
|
|
417
|
+
if (d.title) return { text: `Spreadsheet: ${d.title}` };
|
|
418
|
+
}
|
|
419
|
+
return { text: "Sheets result" };
|
|
420
|
+
}
|
|
421
|
+
function getSlidesSummary(data) {
|
|
422
|
+
if (typeof data === "object" && data !== null) {
|
|
423
|
+
const d = data;
|
|
424
|
+
const slideCount = Array.isArray(d.slides) ? d.slides.length : void 0;
|
|
425
|
+
if (d.title) {
|
|
426
|
+
return { text: `Presentation: ${d.title}`, badge: slideCount ? countBadge(slideCount) : void 0 };
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return { text: "Slides result" };
|
|
430
|
+
}
|
|
431
|
+
function getHubspotSummary(data, toolName) {
|
|
432
|
+
const isCompany = toolName.toLowerCase().includes("compan");
|
|
433
|
+
const n = countItems(data, "results");
|
|
434
|
+
if (n > 0) return { text: isCompany ? `Listed ${n} companies` : `Listed ${n} contacts`, badge: countBadge(n) };
|
|
435
|
+
return { text: isCompany ? "Company result" : "Contact result" };
|
|
436
|
+
}
|
|
437
|
+
function getLinearSummary(data, toolName) {
|
|
438
|
+
const n = countItems(data, "nodes", "issues", "projects");
|
|
439
|
+
if (n > 0) return { text: `Listed ${n} issues`, badge: countBadge(n) };
|
|
440
|
+
if (typeof data === "object" && data !== null && "identifier" in data && "title" in data) {
|
|
441
|
+
return { text: `${data.identifier} ${data.title}` };
|
|
442
|
+
}
|
|
443
|
+
return { text: "Linear result" };
|
|
444
|
+
}
|
|
445
|
+
function getPipedriveSummary(data) {
|
|
446
|
+
const n = countItems(data, "data");
|
|
447
|
+
if (n > 0) return { text: `Listed ${n} deals`, badge: countBadge(n) };
|
|
448
|
+
if (typeof data === "object" && data !== null && "title" in data) {
|
|
449
|
+
return { text: String(data.title) };
|
|
450
|
+
}
|
|
451
|
+
return { text: "Pipedrive result" };
|
|
452
|
+
}
|
|
453
|
+
function getComputeSummary(data) {
|
|
454
|
+
if (typeof data === "object" && data !== null) {
|
|
455
|
+
const d = data;
|
|
456
|
+
const exitCode = d.exit_code ?? d.exitCode;
|
|
457
|
+
if (exitCode !== void 0 && exitCode !== 0) {
|
|
458
|
+
return { text: "Execution failed", badge: { text: `exit ${exitCode}`, variant: "error" } };
|
|
459
|
+
}
|
|
460
|
+
return { text: "Execution completed", badge: exitCode !== void 0 ? { text: `exit ${exitCode}`, variant: "success" } : void 0 };
|
|
461
|
+
}
|
|
462
|
+
return { text: "Compute result" };
|
|
463
|
+
}
|
|
464
|
+
function getResendSummary(data) {
|
|
465
|
+
const d = typeof data === "object" && data !== null && "data" in data ? data.data : data;
|
|
466
|
+
if (typeof d === "object" && d !== null && "to" in d) {
|
|
467
|
+
const to = Array.isArray(d.to) ? d.to.join(", ") : String(d.to);
|
|
468
|
+
return { text: `Sent email to ${to}`, badge: { text: "Sent", variant: "success" } };
|
|
469
|
+
}
|
|
470
|
+
return { text: "Email sent", badge: { text: "Sent", variant: "success" } };
|
|
471
|
+
}
|
|
472
|
+
function getInboxSummary(data) {
|
|
473
|
+
const n = countItems(data, "events");
|
|
474
|
+
if (n > 0) return { text: `Listed ${n} notifications`, badge: countBadge(n) };
|
|
475
|
+
if (typeof data === "object" && data !== null && "title" in data) {
|
|
476
|
+
return { text: String(data.title) };
|
|
477
|
+
}
|
|
478
|
+
return { text: "Inbox result" };
|
|
479
|
+
}
|
|
480
|
+
function getDiscordSummary(data, toolName) {
|
|
481
|
+
if (typeof data === "object" && data !== null) {
|
|
482
|
+
const d = data;
|
|
483
|
+
if (Array.isArray(d.guilds)) return { text: `Listed ${d.guilds.length} servers`, badge: countBadge(d.guilds.length) };
|
|
484
|
+
if (Array.isArray(d.channels)) return { text: `Listed ${d.channels.length} channels`, badge: countBadge(d.channels.length) };
|
|
485
|
+
}
|
|
486
|
+
const action = actionFromToolName(toolName);
|
|
487
|
+
if (action === "send") {
|
|
488
|
+
const ch = typeof data === "object" && data !== null && "channel" in data ? `#${data.channel}` : void 0;
|
|
489
|
+
return { text: ch ? `Message in ${ch}` : "Sent message", badge: { text: "Sent", variant: "success" } };
|
|
490
|
+
}
|
|
491
|
+
const n = countItems(data, "messages");
|
|
492
|
+
if (n > 0) return { text: `Listed ${n} messages`, badge: countBadge(n) };
|
|
493
|
+
return { text: "Discord result" };
|
|
494
|
+
}
|
|
495
|
+
function getNotionSummary(data, toolName) {
|
|
496
|
+
if (typeof data === "object" && data !== null) {
|
|
497
|
+
const d = data;
|
|
498
|
+
if (Array.isArray(d.pages)) return { text: `Listed ${d.pages.length} pages`, badge: countBadge(d.pages.length) };
|
|
499
|
+
if (Array.isArray(d.databases)) return { text: `Listed ${d.databases.length} databases`, badge: countBadge(d.databases.length) };
|
|
500
|
+
if (Array.isArray(d.results)) {
|
|
501
|
+
const n = d.results.length;
|
|
502
|
+
const isDB = toolName.toLowerCase().includes("database");
|
|
503
|
+
return { text: isDB ? `Listed ${n} databases` : `Listed ${n} pages`, badge: countBadge(n) };
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
if (typeof data === "object" && data !== null && "title" in data) {
|
|
507
|
+
return { text: `Page: ${data.title}` };
|
|
508
|
+
}
|
|
509
|
+
if (typeof data === "object" && data !== null && "properties" in data) {
|
|
510
|
+
return { text: "Page result" };
|
|
511
|
+
}
|
|
512
|
+
return { text: "Notion result" };
|
|
513
|
+
}
|
|
514
|
+
function getTwitterSummary(data) {
|
|
515
|
+
const n = countItems(data, "tweets", "data");
|
|
516
|
+
if (n > 0) return { text: `Listed ${n} tweets`, badge: countBadge(n) };
|
|
517
|
+
if (typeof data === "object" && data !== null) {
|
|
518
|
+
const d = data;
|
|
519
|
+
const author = d.author_username || d.username;
|
|
520
|
+
if (d.text && author) return { text: `Tweet by @${author}` };
|
|
521
|
+
}
|
|
522
|
+
return { text: "Twitter result" };
|
|
523
|
+
}
|
|
524
|
+
function getTelegramSummary(data, toolName) {
|
|
525
|
+
const action = actionFromToolName(toolName);
|
|
526
|
+
if (action === "send") {
|
|
527
|
+
const chat = typeof data === "object" && data !== null && "chat" in data ? data.chat?.title || data.chat?.username : void 0;
|
|
528
|
+
return { text: chat ? `Sent message to ${chat}` : "Sent message", badge: { text: "Sent", variant: "success" } };
|
|
529
|
+
}
|
|
530
|
+
const n = countItems(data, "messages", "result");
|
|
531
|
+
if (n > 0) return { text: `${n} messages`, badge: countBadge(n) };
|
|
532
|
+
return { text: "Telegram result" };
|
|
533
|
+
}
|
|
534
|
+
function getStripeSummary(data, toolName) {
|
|
535
|
+
if (typeof data === "object" && data !== null) {
|
|
536
|
+
const d = data;
|
|
537
|
+
if (Array.isArray(d.available) || Array.isArray(d.pending)) {
|
|
538
|
+
const amt = Array.isArray(d.available) && d.available.length > 0 ? `${(d.available[0].amount / 100).toFixed(2)} ${String(d.available[0].currency).toUpperCase()}` : void 0;
|
|
539
|
+
return { text: amt ? `Balance: ${amt}` : "Balance", badge: amt ? { text: amt, variant: "default" } : void 0 };
|
|
540
|
+
}
|
|
541
|
+
if (Array.isArray(d.data)) {
|
|
542
|
+
const n = d.data.length;
|
|
543
|
+
const lower = toolName.toLowerCase();
|
|
544
|
+
if (lower.includes("customer")) return { text: `Listed ${n} customers`, badge: countBadge(n) };
|
|
545
|
+
if (lower.includes("invoice")) return { text: `Listed ${n} invoices`, badge: countBadge(n) };
|
|
546
|
+
if (lower.includes("subscri")) return { text: `Listed ${n} subscriptions`, badge: countBadge(n) };
|
|
547
|
+
if (lower.includes("charge") || lower.includes("payment")) return { text: `Listed ${n} payments`, badge: countBadge(n) };
|
|
548
|
+
return { text: `Listed ${n} items`, badge: countBadge(n) };
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return { text: "Stripe result" };
|
|
552
|
+
}
|
|
553
|
+
function getJiraSummary(data) {
|
|
554
|
+
const n = countItems(data, "issues", "projects");
|
|
555
|
+
if (n > 0) return { text: `Listed ${n} issues`, badge: countBadge(n) };
|
|
556
|
+
if (typeof data === "object" && data !== null && "key" in data && "fields" in data) {
|
|
557
|
+
const fields = data.fields;
|
|
558
|
+
return { text: `${data.key}: ${fields?.summary || "Issue"}` };
|
|
559
|
+
}
|
|
560
|
+
return { text: "Jira result" };
|
|
561
|
+
}
|
|
562
|
+
function getSalesforceSummary(data, toolName) {
|
|
563
|
+
const n = countItems(data, "records");
|
|
564
|
+
const isOpp = toolName.toLowerCase().includes("opportunit");
|
|
565
|
+
if (n > 0) return { text: isOpp ? `Listed ${n} opportunities` : `Listed ${n} contacts`, badge: countBadge(n) };
|
|
566
|
+
return { text: "Salesforce result" };
|
|
567
|
+
}
|
|
568
|
+
function getBrevoSummary(data, toolName) {
|
|
569
|
+
const action = actionFromToolName(toolName);
|
|
570
|
+
if (action === "send") {
|
|
571
|
+
const to = typeof data === "object" && data !== null && "to" in data ? String(data.to) : void 0;
|
|
572
|
+
return { text: to ? `Sent email to ${to}` : "Sent email", badge: { text: "Sent", variant: "success" } };
|
|
573
|
+
}
|
|
574
|
+
const n = countItems(data, "contacts", "campaigns");
|
|
575
|
+
const isCampaign = toolName.toLowerCase().includes("campaign");
|
|
576
|
+
if (n > 0) return { text: isCampaign ? `Listed ${n} campaigns` : `Listed ${n} contacts`, badge: countBadge(n) };
|
|
577
|
+
return { text: "Brevo result" };
|
|
578
|
+
}
|
|
579
|
+
function getCalendlySummary(data) {
|
|
580
|
+
if (typeof data === "object" && data !== null) {
|
|
581
|
+
const d = data;
|
|
582
|
+
if (Array.isArray(d.collection)) {
|
|
583
|
+
const n = d.collection.length;
|
|
584
|
+
const first = n > 0 ? d.collection[0] : null;
|
|
585
|
+
const isType = first && ("duration" in first || "slug" in first);
|
|
586
|
+
return { text: isType ? `Listed ${n} event types` : `Listed ${n} events`, badge: countBadge(n) };
|
|
587
|
+
}
|
|
588
|
+
if (Array.isArray(d.scheduled_events)) return { text: `Listed ${d.scheduled_events.length} events`, badge: countBadge(d.scheduled_events.length) };
|
|
589
|
+
if (Array.isArray(d.event_types)) return { text: `Listed ${d.event_types.length} event types`, badge: countBadge(d.event_types.length) };
|
|
590
|
+
}
|
|
591
|
+
return { text: "Calendly result" };
|
|
592
|
+
}
|
|
593
|
+
function getTwilioSummary(data, toolName) {
|
|
594
|
+
const action = actionFromToolName(toolName);
|
|
595
|
+
if (action === "send") {
|
|
596
|
+
const to = typeof data === "object" && data !== null && "to" in data ? String(data.to) : void 0;
|
|
597
|
+
return { text: to ? `Sent SMS to ${to}` : "Sent SMS", badge: { text: "Sent", variant: "success" } };
|
|
598
|
+
}
|
|
599
|
+
const n = countItems(data, "messages");
|
|
600
|
+
if (n > 0) return { text: `Listed ${n} messages`, badge: countBadge(n) };
|
|
601
|
+
return { text: "Twilio result" };
|
|
602
|
+
}
|
|
603
|
+
function getLinkedinSummary(data) {
|
|
604
|
+
if (typeof data === "object" && data !== null) {
|
|
605
|
+
const d = data;
|
|
606
|
+
if (Array.isArray(d.posts) || Array.isArray(d.elements)) {
|
|
607
|
+
const n = (d.posts || d.elements).length;
|
|
608
|
+
return { text: `Listed ${n} posts`, badge: countBadge(n) };
|
|
609
|
+
}
|
|
610
|
+
if (d.localizedFirstName || d.firstName || d.name) {
|
|
611
|
+
const name = d.name || [d.localizedFirstName, d.localizedLastName].filter(Boolean).join(" ");
|
|
612
|
+
return { text: `Profile: ${name}` };
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return { text: "LinkedIn result" };
|
|
616
|
+
}
|
|
617
|
+
function getGenericSummary(_data, toolName) {
|
|
618
|
+
return { text: humanizeToolName(toolName) };
|
|
619
|
+
}
|
|
620
|
+
var SUMMARY_MAP = {
|
|
621
|
+
email: getEmailSummary,
|
|
622
|
+
calendar: getCalendarSummary,
|
|
623
|
+
slack: getSlackSummary,
|
|
624
|
+
github: getGithubSummary,
|
|
625
|
+
drive: getDriveSummary,
|
|
626
|
+
search: getSearchSummary,
|
|
627
|
+
docs: getDocsSummary,
|
|
628
|
+
sheets: getSheetsSummary,
|
|
629
|
+
slides: getSlidesSummary,
|
|
630
|
+
hubspot: getHubspotSummary,
|
|
631
|
+
linear: getLinearSummary,
|
|
632
|
+
pipedrive: getPipedriveSummary,
|
|
633
|
+
compute: getComputeSummary,
|
|
634
|
+
resend: getResendSummary,
|
|
635
|
+
inbox: getInboxSummary,
|
|
636
|
+
discord: getDiscordSummary,
|
|
637
|
+
notion: getNotionSummary,
|
|
638
|
+
twitter: getTwitterSummary,
|
|
639
|
+
telegram: getTelegramSummary,
|
|
640
|
+
stripe: getStripeSummary,
|
|
641
|
+
jira: getJiraSummary,
|
|
642
|
+
salesforce: getSalesforceSummary,
|
|
643
|
+
brevo: getBrevoSummary,
|
|
644
|
+
calendly: getCalendlySummary,
|
|
645
|
+
twilio: getTwilioSummary,
|
|
646
|
+
linkedin: getLinkedinSummary,
|
|
647
|
+
generic: getGenericSummary
|
|
648
|
+
};
|
|
649
|
+
function getSummary(formatterType, data, toolName) {
|
|
650
|
+
const fn = SUMMARY_MAP[formatterType] || getGenericSummary;
|
|
651
|
+
return fn(data, toolName);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// src/ui/normalizers.ts
|
|
655
|
+
function normalizeMailItem(msg) {
|
|
656
|
+
return {
|
|
657
|
+
id: msg.id,
|
|
658
|
+
subject: msg.subject,
|
|
659
|
+
from: typeof msg.from === "object" && msg.from !== null ? msg.from.emailAddress?.address || msg.from.emailAddress?.name : msg.from,
|
|
660
|
+
to: Array.isArray(msg.toRecipients) ? msg.toRecipients.map((r) => r.emailAddress?.address || r.emailAddress?.name).join(", ") : msg.to,
|
|
661
|
+
date: msg.receivedDateTime || msg.createdDateTime || msg.date,
|
|
662
|
+
snippet: msg.bodyPreview || msg.snippet,
|
|
663
|
+
body: typeof msg.body === "object" && msg.body !== null ? msg.body.content : msg.body,
|
|
664
|
+
hasAttachments: msg.hasAttachments
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
function normalizeCalendarItem(evt) {
|
|
668
|
+
const start = typeof evt.start === "object" && evt.start !== null ? { dateTime: evt.start.dateTime || evt.start.date, timeZone: evt.start.timeZone } : evt.start;
|
|
669
|
+
const end = typeof evt.end === "object" && evt.end !== null ? { dateTime: evt.end.dateTime || evt.end.date, timeZone: evt.end.timeZone } : evt.end;
|
|
670
|
+
return {
|
|
671
|
+
id: evt.id,
|
|
672
|
+
summary: evt.subject || evt.summary,
|
|
673
|
+
start,
|
|
674
|
+
end,
|
|
675
|
+
location: typeof evt.location === "object" && evt.location !== null ? evt.location.displayName : evt.location,
|
|
676
|
+
attendees: Array.isArray(evt.attendees) ? evt.attendees.map((a) => ({
|
|
677
|
+
email: a.emailAddress?.address,
|
|
678
|
+
displayName: a.emailAddress?.name,
|
|
679
|
+
responseStatus: a.status?.response
|
|
680
|
+
})) : evt.attendees,
|
|
681
|
+
status: evt.showAs || evt.status
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
function normalizeDriveItem(item) {
|
|
685
|
+
return {
|
|
686
|
+
id: item.id,
|
|
687
|
+
name: item.name,
|
|
688
|
+
mimeType: item.file && typeof item.file === "object" ? item.file.mimeType : item.mimeType,
|
|
689
|
+
modifiedTime: item.lastModifiedDateTime || item.modifiedTime,
|
|
690
|
+
size: item.size,
|
|
691
|
+
webViewLink: item.webUrl || item.webViewLink,
|
|
692
|
+
shared: item.shared !== void 0
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
function normalizeArray(items, normalizer) {
|
|
696
|
+
return items.map(
|
|
697
|
+
(item) => typeof item === "object" && item !== null ? normalizer(item) : item
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
function normalizeMicrosoftMail(data) {
|
|
701
|
+
if (typeof data !== "object" || data === null) return data;
|
|
702
|
+
const d = data;
|
|
703
|
+
if (Array.isArray(d.value)) {
|
|
704
|
+
return { messages: normalizeArray(d.value, normalizeMailItem) };
|
|
705
|
+
}
|
|
706
|
+
if (Array.isArray(d.messages)) {
|
|
707
|
+
return { messages: normalizeArray(d.messages, normalizeMailItem) };
|
|
708
|
+
}
|
|
709
|
+
if (d.subject || d.from || d.bodyPreview) {
|
|
710
|
+
return normalizeMailItem(d);
|
|
711
|
+
}
|
|
712
|
+
return data;
|
|
713
|
+
}
|
|
714
|
+
function normalizeMicrosoftCalendar(data) {
|
|
715
|
+
if (typeof data !== "object" || data === null) return data;
|
|
716
|
+
const d = data;
|
|
717
|
+
if (Array.isArray(d.value)) {
|
|
718
|
+
return { events: normalizeArray(d.value, normalizeCalendarItem) };
|
|
719
|
+
}
|
|
720
|
+
if (Array.isArray(d.events)) {
|
|
721
|
+
return { events: normalizeArray(d.events, normalizeCalendarItem) };
|
|
722
|
+
}
|
|
723
|
+
if (d.subject || d.start) {
|
|
724
|
+
return normalizeCalendarItem(d);
|
|
725
|
+
}
|
|
726
|
+
return data;
|
|
727
|
+
}
|
|
728
|
+
function normalizeMicrosoftDrive(data) {
|
|
729
|
+
if (typeof data !== "object" || data === null) return data;
|
|
730
|
+
const d = data;
|
|
731
|
+
if (Array.isArray(d.value)) {
|
|
732
|
+
return { files: normalizeArray(d.value, normalizeDriveItem) };
|
|
733
|
+
}
|
|
734
|
+
if (Array.isArray(d.files)) {
|
|
735
|
+
return { files: normalizeArray(d.files, normalizeDriveItem) };
|
|
736
|
+
}
|
|
737
|
+
if (d.name && (d.lastModifiedDateTime || d.webUrl)) {
|
|
738
|
+
return normalizeDriveItem(d);
|
|
739
|
+
}
|
|
740
|
+
return data;
|
|
741
|
+
}
|
|
742
|
+
|
|
134
743
|
// src/ui/formatters/email.tsx
|
|
135
|
-
import { Mail as Mail2, Paperclip } from "lucide-react";
|
|
136
|
-
import { jsx as
|
|
744
|
+
import { Mail as Mail2, Paperclip, Tag } from "lucide-react";
|
|
745
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
137
746
|
function isEmailData(data) {
|
|
138
747
|
return typeof data === "object" && data !== null && ("subject" in data || "from" in data || "snippet" in data);
|
|
139
748
|
}
|
|
749
|
+
function formatRelativeDate(dateStr) {
|
|
750
|
+
try {
|
|
751
|
+
const date = new Date(dateStr);
|
|
752
|
+
const now = /* @__PURE__ */ new Date();
|
|
753
|
+
const diffMs = now.getTime() - date.getTime();
|
|
754
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
755
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
756
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
757
|
+
if (diffMins < 1) return "Just now";
|
|
758
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
759
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
760
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
761
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
762
|
+
} catch {
|
|
763
|
+
return dateStr;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
function formatRecipients(to) {
|
|
767
|
+
if (!to) return null;
|
|
768
|
+
if (Array.isArray(to)) return to.join(", ");
|
|
769
|
+
return to;
|
|
770
|
+
}
|
|
140
771
|
function EmailCard({ email }) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
/* @__PURE__ */
|
|
145
|
-
|
|
146
|
-
|
|
772
|
+
const recipients = formatRecipients(email.to);
|
|
773
|
+
return /* @__PURE__ */ jsxs3("div", { className: "rounded-lg border border-border bg-card p-3 space-y-2", children: [
|
|
774
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-start gap-2", children: [
|
|
775
|
+
/* @__PURE__ */ jsx4(Mail2, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
776
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
|
|
777
|
+
/* @__PURE__ */ jsx4("p", { className: "text-sm font-medium text-foreground truncate", children: email.subject || "No subject" }),
|
|
778
|
+
email.from && /* @__PURE__ */ jsx4("p", { className: "text-xs text-muted-foreground truncate", children: email.from }),
|
|
779
|
+
recipients && /* @__PURE__ */ jsxs3("p", { className: "text-xs text-muted-foreground truncate", children: [
|
|
780
|
+
"To: ",
|
|
781
|
+
recipients
|
|
782
|
+
] })
|
|
147
783
|
] }),
|
|
148
|
-
|
|
784
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1.5 shrink-0", children: [
|
|
785
|
+
email.hasAttachments && /* @__PURE__ */ jsx4(Paperclip, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
786
|
+
email.date && /* @__PURE__ */ jsx4("span", { className: "text-xs text-muted-foreground", children: formatRelativeDate(email.date) })
|
|
787
|
+
] })
|
|
149
788
|
] }),
|
|
150
|
-
email.
|
|
151
|
-
|
|
789
|
+
email.labels && email.labels.length > 0 && /* @__PURE__ */ jsx4("div", { className: "flex items-center gap-1.5 flex-wrap", children: email.labels.map((label) => /* @__PURE__ */ jsxs3(
|
|
790
|
+
"span",
|
|
791
|
+
{
|
|
792
|
+
className: "inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground",
|
|
793
|
+
children: [
|
|
794
|
+
/* @__PURE__ */ jsx4(Tag, { className: "h-2.5 w-2.5" }),
|
|
795
|
+
label
|
|
796
|
+
]
|
|
797
|
+
},
|
|
798
|
+
label
|
|
799
|
+
)) }),
|
|
800
|
+
(email.snippet || email.body) && /* @__PURE__ */ jsx4("p", { className: "text-xs text-muted-foreground line-clamp-3", children: email.snippet || email.body })
|
|
152
801
|
] });
|
|
153
802
|
}
|
|
154
803
|
function EmailFormatter({ data }) {
|
|
155
804
|
if (isEmailData(data)) {
|
|
156
|
-
return /* @__PURE__ */
|
|
805
|
+
return /* @__PURE__ */ jsx4(EmailCard, { email: data });
|
|
157
806
|
}
|
|
158
807
|
if (Array.isArray(data)) {
|
|
159
808
|
const emails = data.filter(isEmailData);
|
|
160
809
|
if (emails.length > 0) {
|
|
161
|
-
return /* @__PURE__ */
|
|
810
|
+
return /* @__PURE__ */ jsx4("div", { className: "space-y-2", children: emails.map((email, i) => /* @__PURE__ */ jsx4(EmailCard, { email }, email.id || i)) });
|
|
162
811
|
}
|
|
163
812
|
}
|
|
164
813
|
if (typeof data === "object" && data !== null && "messages" in data) {
|
|
@@ -166,62 +815,94 @@ function EmailFormatter({ data }) {
|
|
|
166
815
|
if (Array.isArray(messages)) {
|
|
167
816
|
const emails = messages.filter(isEmailData);
|
|
168
817
|
if (emails.length > 0) {
|
|
169
|
-
return /* @__PURE__ */
|
|
818
|
+
return /* @__PURE__ */ jsx4("div", { className: "space-y-2", children: emails.map((email, i) => /* @__PURE__ */ jsx4(EmailCard, { email }, email.id || i)) });
|
|
170
819
|
}
|
|
171
820
|
}
|
|
172
821
|
}
|
|
173
|
-
return /* @__PURE__ */
|
|
822
|
+
return /* @__PURE__ */ jsx4("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
174
823
|
}
|
|
175
824
|
|
|
176
825
|
// src/ui/formatters/calendar-event.tsx
|
|
177
|
-
import { Calendar as Calendar2, MapPin, Users } from "lucide-react";
|
|
178
|
-
import { jsx as
|
|
826
|
+
import { Calendar as Calendar2, MapPin, Users as Users2, Check as Check2, X, HelpCircle } from "lucide-react";
|
|
827
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
179
828
|
function isCalendarEvent(data) {
|
|
180
829
|
return typeof data === "object" && data !== null && ("summary" in data || "start" in data);
|
|
181
830
|
}
|
|
182
|
-
function
|
|
831
|
+
function formatRelativeDateTime(dt) {
|
|
183
832
|
if (!dt) return "";
|
|
184
833
|
const raw = dt.dateTime || dt.date;
|
|
185
834
|
if (!raw) return "";
|
|
186
835
|
try {
|
|
187
836
|
const date = new Date(raw);
|
|
837
|
+
const now = /* @__PURE__ */ new Date();
|
|
838
|
+
const diffMs = date.getTime() - now.getTime();
|
|
839
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
840
|
+
const timeStr = dt.dateTime ? date.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" }) : "";
|
|
841
|
+
if (diffDays === 0) {
|
|
842
|
+
return timeStr ? `Today at ${timeStr}` : "Today";
|
|
843
|
+
}
|
|
844
|
+
if (diffDays === 1) {
|
|
845
|
+
return timeStr ? `Tomorrow at ${timeStr}` : "Tomorrow";
|
|
846
|
+
}
|
|
847
|
+
if (diffDays === -1) {
|
|
848
|
+
return timeStr ? `Yesterday at ${timeStr}` : "Yesterday";
|
|
849
|
+
}
|
|
850
|
+
if (diffDays > 1 && diffDays < 7) {
|
|
851
|
+
const dayName = date.toLocaleDateString(void 0, { weekday: "long" });
|
|
852
|
+
return timeStr ? `${dayName} at ${timeStr}` : dayName;
|
|
853
|
+
}
|
|
188
854
|
return dt.dateTime ? date.toLocaleString(void 0, { dateStyle: "medium", timeStyle: "short" }) : date.toLocaleDateString(void 0, { dateStyle: "medium" });
|
|
189
855
|
} catch {
|
|
190
856
|
return raw;
|
|
191
857
|
}
|
|
192
858
|
}
|
|
859
|
+
function ResponseStatusIcon({ status }) {
|
|
860
|
+
switch (status) {
|
|
861
|
+
case "accepted":
|
|
862
|
+
return /* @__PURE__ */ jsx5(Check2, { className: "h-3 w-3 text-green-500" });
|
|
863
|
+
case "declined":
|
|
864
|
+
return /* @__PURE__ */ jsx5(X, { className: "h-3 w-3 text-destructive" });
|
|
865
|
+
case "tentative":
|
|
866
|
+
return /* @__PURE__ */ jsx5(HelpCircle, { className: "h-3 w-3 text-yellow-500" });
|
|
867
|
+
default:
|
|
868
|
+
return /* @__PURE__ */ jsx5(HelpCircle, { className: "h-3 w-3 text-muted-foreground" });
|
|
869
|
+
}
|
|
870
|
+
}
|
|
193
871
|
function EventCard({ event }) {
|
|
194
|
-
const startStr =
|
|
195
|
-
const endStr =
|
|
196
|
-
return /* @__PURE__ */
|
|
197
|
-
/* @__PURE__ */
|
|
198
|
-
/* @__PURE__ */
|
|
199
|
-
/* @__PURE__ */
|
|
200
|
-
/* @__PURE__ */
|
|
201
|
-
startStr && /* @__PURE__ */
|
|
872
|
+
const startStr = formatRelativeDateTime(event.start);
|
|
873
|
+
const endStr = formatRelativeDateTime(event.end);
|
|
874
|
+
return /* @__PURE__ */ jsxs4("div", { className: "rounded-lg border border-border bg-card p-3 space-y-2", children: [
|
|
875
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-start gap-2", children: [
|
|
876
|
+
/* @__PURE__ */ jsx5(Calendar2, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
877
|
+
/* @__PURE__ */ jsxs4("div", { className: "min-w-0 flex-1", children: [
|
|
878
|
+
/* @__PURE__ */ jsx5("p", { className: "text-sm font-medium text-foreground", children: event.summary || "Untitled event" }),
|
|
879
|
+
startStr && /* @__PURE__ */ jsxs4("p", { className: "text-xs text-muted-foreground", children: [
|
|
202
880
|
startStr,
|
|
203
881
|
endStr ? ` \u2192 ${endStr}` : ""
|
|
204
882
|
] })
|
|
205
883
|
] })
|
|
206
884
|
] }),
|
|
207
|
-
event.location && /* @__PURE__ */
|
|
208
|
-
/* @__PURE__ */
|
|
209
|
-
/* @__PURE__ */
|
|
885
|
+
event.location && /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
886
|
+
/* @__PURE__ */ jsx5(MapPin, { className: "h-3 w-3 shrink-0" }),
|
|
887
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate", children: event.location })
|
|
210
888
|
] }),
|
|
211
|
-
event.attendees && event.attendees.length > 0 && /* @__PURE__ */
|
|
212
|
-
/* @__PURE__ */
|
|
213
|
-
/* @__PURE__ */
|
|
889
|
+
event.attendees && event.attendees.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "flex items-start gap-1.5 text-xs text-muted-foreground", children: [
|
|
890
|
+
/* @__PURE__ */ jsx5(Users2, { className: "h-3 w-3 shrink-0 mt-0.5" }),
|
|
891
|
+
/* @__PURE__ */ jsx5("div", { className: "flex flex-wrap gap-x-3 gap-y-1", children: event.attendees.map((a, i) => /* @__PURE__ */ jsxs4("span", { className: "inline-flex items-center gap-1", children: [
|
|
892
|
+
/* @__PURE__ */ jsx5(ResponseStatusIcon, { status: a.responseStatus }),
|
|
893
|
+
a.displayName || a.email
|
|
894
|
+
] }, i)) })
|
|
214
895
|
] })
|
|
215
896
|
] });
|
|
216
897
|
}
|
|
217
898
|
function CalendarEventFormatter({ data }) {
|
|
218
899
|
if (isCalendarEvent(data)) {
|
|
219
|
-
return /* @__PURE__ */
|
|
900
|
+
return /* @__PURE__ */ jsx5(EventCard, { event: data });
|
|
220
901
|
}
|
|
221
902
|
if (Array.isArray(data)) {
|
|
222
903
|
const events = data.filter(isCalendarEvent);
|
|
223
904
|
if (events.length > 0) {
|
|
224
|
-
return /* @__PURE__ */
|
|
905
|
+
return /* @__PURE__ */ jsx5("div", { className: "space-y-2", children: events.map((event, i) => /* @__PURE__ */ jsx5(EventCard, { event }, event.id || i)) });
|
|
225
906
|
}
|
|
226
907
|
}
|
|
227
908
|
if (typeof data === "object" && data !== null && "events" in data) {
|
|
@@ -229,40 +910,74 @@ function CalendarEventFormatter({ data }) {
|
|
|
229
910
|
if (Array.isArray(events)) {
|
|
230
911
|
const calEvents = events.filter(isCalendarEvent);
|
|
231
912
|
if (calEvents.length > 0) {
|
|
232
|
-
return /* @__PURE__ */
|
|
913
|
+
return /* @__PURE__ */ jsx5("div", { className: "space-y-2", children: calEvents.map((event, i) => /* @__PURE__ */ jsx5(EventCard, { event }, event.id || i)) });
|
|
233
914
|
}
|
|
234
915
|
}
|
|
235
916
|
}
|
|
236
|
-
return /* @__PURE__ */
|
|
917
|
+
return /* @__PURE__ */ jsx5("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
237
918
|
}
|
|
238
919
|
|
|
239
920
|
// src/ui/formatters/slack-message.tsx
|
|
240
|
-
import { MessageSquare as MessageSquare2, Hash } from "lucide-react";
|
|
241
|
-
import { jsx as
|
|
921
|
+
import { MessageSquare as MessageSquare2, Hash, Reply } from "lucide-react";
|
|
922
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
242
923
|
function isSlackMessage(data) {
|
|
243
924
|
return typeof data === "object" && data !== null && ("text" in data || "channel" in data);
|
|
244
925
|
}
|
|
926
|
+
function isChannelList(data) {
|
|
927
|
+
return typeof data === "object" && data !== null && "channels" in data && Array.isArray(data.channels);
|
|
928
|
+
}
|
|
245
929
|
function MessageBubble({ message }) {
|
|
246
|
-
return /* @__PURE__ */
|
|
247
|
-
/* @__PURE__ */
|
|
248
|
-
/* @__PURE__ */
|
|
249
|
-
message.channel && /* @__PURE__ */
|
|
250
|
-
/* @__PURE__ */
|
|
930
|
+
return /* @__PURE__ */ jsxs5("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
931
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
932
|
+
/* @__PURE__ */ jsx6(MessageSquare2, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
|
|
933
|
+
message.channel && /* @__PURE__ */ jsxs5("span", { className: "flex items-center gap-0.5 text-xs text-muted-foreground", children: [
|
|
934
|
+
/* @__PURE__ */ jsx6(Hash, { className: "h-3 w-3" }),
|
|
251
935
|
message.channel
|
|
252
936
|
] }),
|
|
253
|
-
message.user && /* @__PURE__ */
|
|
937
|
+
message.user && /* @__PURE__ */ jsx6("span", { className: "text-xs font-medium text-foreground", children: message.user }),
|
|
938
|
+
message.thread_ts && /* @__PURE__ */ jsxs5("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
939
|
+
/* @__PURE__ */ jsx6(Reply, { className: "h-3 w-3" }),
|
|
940
|
+
message.reply_count ? `${message.reply_count} replies` : "Thread"
|
|
941
|
+
] })
|
|
254
942
|
] }),
|
|
255
|
-
message.text && /* @__PURE__ */
|
|
943
|
+
message.text && /* @__PURE__ */ jsx6("p", { className: "text-sm text-foreground", children: message.text }),
|
|
944
|
+
message.reactions && message.reactions.length > 0 && /* @__PURE__ */ jsx6("div", { className: "flex flex-wrap gap-1.5 pt-1", children: message.reactions.map((reaction) => /* @__PURE__ */ jsxs5(
|
|
945
|
+
"span",
|
|
946
|
+
{
|
|
947
|
+
className: "inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground",
|
|
948
|
+
children: [
|
|
949
|
+
":",
|
|
950
|
+
reaction.name,
|
|
951
|
+
":",
|
|
952
|
+
reaction.count && reaction.count > 1 && /* @__PURE__ */ jsx6("span", { className: "font-medium", children: reaction.count })
|
|
953
|
+
]
|
|
954
|
+
},
|
|
955
|
+
reaction.name
|
|
956
|
+
)) })
|
|
957
|
+
] });
|
|
958
|
+
}
|
|
959
|
+
function ChannelCard({ channel }) {
|
|
960
|
+
return /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 rounded-lg border border-border bg-card p-3", children: [
|
|
961
|
+
/* @__PURE__ */ jsx6(Hash, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
|
|
962
|
+
/* @__PURE__ */ jsx6("span", { className: "text-sm text-foreground flex-1", children: channel.name || channel.id }),
|
|
963
|
+
channel.num_members !== void 0 && /* @__PURE__ */ jsxs5("span", { className: "text-xs text-muted-foreground", children: [
|
|
964
|
+
channel.num_members,
|
|
965
|
+
" members"
|
|
966
|
+
] })
|
|
256
967
|
] });
|
|
257
968
|
}
|
|
258
969
|
function SlackMessageFormatter({ data }) {
|
|
970
|
+
if (isChannelList(data)) {
|
|
971
|
+
const channels = data.channels;
|
|
972
|
+
return /* @__PURE__ */ jsx6("div", { className: "space-y-1.5", children: channels.map((ch, i) => /* @__PURE__ */ jsx6(ChannelCard, { channel: ch }, ch.id || i)) });
|
|
973
|
+
}
|
|
259
974
|
if (isSlackMessage(data)) {
|
|
260
|
-
return /* @__PURE__ */
|
|
975
|
+
return /* @__PURE__ */ jsx6(MessageBubble, { message: data });
|
|
261
976
|
}
|
|
262
977
|
if (Array.isArray(data)) {
|
|
263
978
|
const messages = data.filter(isSlackMessage);
|
|
264
979
|
if (messages.length > 0) {
|
|
265
|
-
return /* @__PURE__ */
|
|
980
|
+
return /* @__PURE__ */ jsx6("div", { className: "space-y-2", children: messages.map((msg, i) => /* @__PURE__ */ jsx6(MessageBubble, { message: msg }, msg.ts || i)) });
|
|
266
981
|
}
|
|
267
982
|
}
|
|
268
983
|
if (typeof data === "object" && data !== null && "messages" in data) {
|
|
@@ -270,55 +985,102 @@ function SlackMessageFormatter({ data }) {
|
|
|
270
985
|
if (Array.isArray(messages)) {
|
|
271
986
|
const slackMsgs = messages.filter(isSlackMessage);
|
|
272
987
|
if (slackMsgs.length > 0) {
|
|
273
|
-
return /* @__PURE__ */
|
|
988
|
+
return /* @__PURE__ */ jsx6("div", { className: "space-y-2", children: slackMsgs.map((msg, i) => /* @__PURE__ */ jsx6(MessageBubble, { message: msg }, msg.ts || i)) });
|
|
274
989
|
}
|
|
275
990
|
}
|
|
276
991
|
}
|
|
277
|
-
return /* @__PURE__ */
|
|
992
|
+
return /* @__PURE__ */ jsx6("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
278
993
|
}
|
|
279
994
|
|
|
280
995
|
// src/ui/formatters/github.tsx
|
|
281
|
-
import { CircleDot, GitPullRequest } from "lucide-react";
|
|
282
|
-
import { jsx as
|
|
996
|
+
import { CircleDot as CircleDot2, GitPullRequest, GitMerge, Clock } from "lucide-react";
|
|
997
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
283
998
|
function isGithubItem(data) {
|
|
284
999
|
return typeof data === "object" && data !== null && ("title" in data || "number" in data);
|
|
285
1000
|
}
|
|
286
|
-
function
|
|
1001
|
+
function formatRelativeDate2(dateStr) {
|
|
1002
|
+
try {
|
|
1003
|
+
const date = new Date(dateStr);
|
|
1004
|
+
const now = /* @__PURE__ */ new Date();
|
|
1005
|
+
const diffMs = now.getTime() - date.getTime();
|
|
1006
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
1007
|
+
if (diffDays === 0) return "today";
|
|
1008
|
+
if (diffDays === 1) return "yesterday";
|
|
1009
|
+
if (diffDays < 30) return `${diffDays}d ago`;
|
|
1010
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
1011
|
+
} catch {
|
|
1012
|
+
return dateStr;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
function getStateInfo(item) {
|
|
287
1016
|
const isPR = !!item.pull_request;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
1017
|
+
if (isPR && item.merged) {
|
|
1018
|
+
return { icon: GitMerge, color: "text-purple-500", label: "Merged" };
|
|
1019
|
+
}
|
|
1020
|
+
if (item.state === "open") {
|
|
1021
|
+
return {
|
|
1022
|
+
icon: isPR ? GitPullRequest : CircleDot2,
|
|
1023
|
+
color: "text-green-500",
|
|
1024
|
+
label: "Open"
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
return {
|
|
1028
|
+
icon: isPR ? GitPullRequest : CircleDot2,
|
|
1029
|
+
color: "text-destructive",
|
|
1030
|
+
label: "Closed"
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
function GithubCard({ item }) {
|
|
1034
|
+
const { icon: StateIcon, color: stateColor, label: stateLabel } = getStateInfo(item);
|
|
1035
|
+
return /* @__PURE__ */ jsxs6("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
1036
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-start gap-2", children: [
|
|
1037
|
+
/* @__PURE__ */ jsx7(StateIcon, { className: `h-4 w-4 mt-0.5 shrink-0 ${stateColor}` }),
|
|
1038
|
+
/* @__PURE__ */ jsxs6("div", { className: "min-w-0 flex-1", children: [
|
|
1039
|
+
/* @__PURE__ */ jsxs6("p", { className: "text-sm font-medium text-foreground", children: [
|
|
1040
|
+
item.html_url ? /* @__PURE__ */ jsx7("a", { href: item.html_url, target: "_blank", rel: "noopener noreferrer", className: "hover:underline", children: item.title }) : item.title,
|
|
1041
|
+
item.number && /* @__PURE__ */ jsxs6("span", { className: "text-muted-foreground font-normal", children: [
|
|
296
1042
|
" #",
|
|
297
1043
|
item.number
|
|
298
1044
|
] })
|
|
299
1045
|
] }),
|
|
300
|
-
|
|
1046
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 mt-0.5", children: [
|
|
1047
|
+
/* @__PURE__ */ jsx7("span", { className: `text-xs ${stateColor}`, children: stateLabel }),
|
|
1048
|
+
item.user?.login && /* @__PURE__ */ jsx7("span", { className: "text-xs text-muted-foreground", children: item.user.login }),
|
|
1049
|
+
item.created_at && /* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
1050
|
+
/* @__PURE__ */ jsx7(Clock, { className: "h-3 w-3" }),
|
|
1051
|
+
formatRelativeDate2(item.created_at)
|
|
1052
|
+
] })
|
|
1053
|
+
] })
|
|
301
1054
|
] })
|
|
302
1055
|
] }),
|
|
303
|
-
item.
|
|
1056
|
+
item.labels && item.labels.length > 0 && /* @__PURE__ */ jsx7("div", { className: "flex flex-wrap gap-1.5", children: item.labels.map((label) => /* @__PURE__ */ jsx7(
|
|
1057
|
+
"span",
|
|
1058
|
+
{
|
|
1059
|
+
className: "rounded-full border border-border px-2 py-0.5 text-xs text-muted-foreground",
|
|
1060
|
+
style: label.color ? { borderColor: `#${label.color}`, color: `#${label.color}` } : void 0,
|
|
1061
|
+
children: label.name
|
|
1062
|
+
},
|
|
1063
|
+
label.name
|
|
1064
|
+
)) }),
|
|
1065
|
+
item.body && /* @__PURE__ */ jsx7("p", { className: "text-xs text-muted-foreground line-clamp-2", children: item.body })
|
|
304
1066
|
] });
|
|
305
1067
|
}
|
|
306
1068
|
function GithubFormatter({ data }) {
|
|
307
1069
|
if (isGithubItem(data)) {
|
|
308
|
-
return /* @__PURE__ */
|
|
1070
|
+
return /* @__PURE__ */ jsx7(GithubCard, { item: data });
|
|
309
1071
|
}
|
|
310
1072
|
if (Array.isArray(data)) {
|
|
311
1073
|
const items = data.filter(isGithubItem);
|
|
312
1074
|
if (items.length > 0) {
|
|
313
|
-
return /* @__PURE__ */
|
|
1075
|
+
return /* @__PURE__ */ jsx7("div", { className: "space-y-2", children: items.map((item, i) => /* @__PURE__ */ jsx7(GithubCard, { item }, item.number || i)) });
|
|
314
1076
|
}
|
|
315
1077
|
}
|
|
316
|
-
return /* @__PURE__ */
|
|
1078
|
+
return /* @__PURE__ */ jsx7("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
317
1079
|
}
|
|
318
1080
|
|
|
319
1081
|
// src/ui/formatters/drive-file.tsx
|
|
320
|
-
import { FileText as FileText2, Folder, Image, Film, FileSpreadsheet } from "lucide-react";
|
|
321
|
-
import { jsx as
|
|
1082
|
+
import { FileText as FileText2, Folder, Image, Film, FileSpreadsheet, ExternalLink, Users as UsersIcon } from "lucide-react";
|
|
1083
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
322
1084
|
function isDriveFile(data) {
|
|
323
1085
|
return typeof data === "object" && data !== null && ("name" in data || "mimeType" in data);
|
|
324
1086
|
}
|
|
@@ -330,24 +1092,41 @@ function getFileIcon(mimeType) {
|
|
|
330
1092
|
if (mimeType.includes("spreadsheet") || mimeType.includes("excel")) return FileSpreadsheet;
|
|
331
1093
|
return FileText2;
|
|
332
1094
|
}
|
|
1095
|
+
function formatFileSize(size) {
|
|
1096
|
+
if (size === void 0) return null;
|
|
1097
|
+
const bytes = typeof size === "string" ? parseInt(size, 10) : size;
|
|
1098
|
+
if (isNaN(bytes)) return null;
|
|
1099
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
1100
|
+
if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1101
|
+
if (bytes < 1073741824) return `${(bytes / 1048576).toFixed(1)} MB`;
|
|
1102
|
+
return `${(bytes / 1073741824).toFixed(1)} GB`;
|
|
1103
|
+
}
|
|
333
1104
|
function FileCard({ file }) {
|
|
334
1105
|
const Icon = getFileIcon(file.mimeType);
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
/* @__PURE__ */
|
|
338
|
-
|
|
339
|
-
|
|
1106
|
+
const sizeStr = formatFileSize(file.size);
|
|
1107
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3 rounded-lg border border-border bg-card p-3", children: [
|
|
1108
|
+
/* @__PURE__ */ jsx8(Icon, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
|
|
1109
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
|
|
1110
|
+
/* @__PURE__ */ jsx8("p", { className: "text-sm text-foreground truncate", children: file.webViewLink ? /* @__PURE__ */ jsx8("a", { href: file.webViewLink, target: "_blank", rel: "noopener noreferrer", className: "hover:underline", children: file.name || "Untitled" }) : file.name || "Untitled" }),
|
|
1111
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
|
|
1112
|
+
file.modifiedTime && /* @__PURE__ */ jsx8("span", { className: "text-xs text-muted-foreground", children: new Date(file.modifiedTime).toLocaleDateString() }),
|
|
1113
|
+
sizeStr && /* @__PURE__ */ jsx8("span", { className: "text-xs text-muted-foreground", children: sizeStr })
|
|
1114
|
+
] })
|
|
1115
|
+
] }),
|
|
1116
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1.5 shrink-0", children: [
|
|
1117
|
+
file.shared && /* @__PURE__ */ jsx8("span", { title: "Shared", children: /* @__PURE__ */ jsx8(UsersIcon, { className: "h-3.5 w-3.5 text-muted-foreground" }) }),
|
|
1118
|
+
file.webViewLink && /* @__PURE__ */ jsx8("a", { href: file.webViewLink, target: "_blank", rel: "noopener noreferrer", className: "text-muted-foreground hover:text-foreground", children: /* @__PURE__ */ jsx8(ExternalLink, { className: "h-3.5 w-3.5" }) })
|
|
340
1119
|
] })
|
|
341
1120
|
] });
|
|
342
1121
|
}
|
|
343
1122
|
function DriveFileFormatter({ data }) {
|
|
344
1123
|
if (isDriveFile(data)) {
|
|
345
|
-
return /* @__PURE__ */
|
|
1124
|
+
return /* @__PURE__ */ jsx8(FileCard, { file: data });
|
|
346
1125
|
}
|
|
347
1126
|
if (Array.isArray(data)) {
|
|
348
1127
|
const files = data.filter(isDriveFile);
|
|
349
1128
|
if (files.length > 0) {
|
|
350
|
-
return /* @__PURE__ */
|
|
1129
|
+
return /* @__PURE__ */ jsx8("div", { className: "space-y-1.5", children: files.map((file, i) => /* @__PURE__ */ jsx8(FileCard, { file }, file.id || i)) });
|
|
351
1130
|
}
|
|
352
1131
|
}
|
|
353
1132
|
if (typeof data === "object" && data !== null && "files" in data) {
|
|
@@ -355,53 +1134,1991 @@ function DriveFileFormatter({ data }) {
|
|
|
355
1134
|
if (Array.isArray(files)) {
|
|
356
1135
|
const driveFiles = files.filter(isDriveFile);
|
|
357
1136
|
if (driveFiles.length > 0) {
|
|
358
|
-
return /* @__PURE__ */
|
|
1137
|
+
return /* @__PURE__ */ jsx8("div", { className: "space-y-1.5", children: driveFiles.map((file, i) => /* @__PURE__ */ jsx8(FileCard, { file }, file.id || i)) });
|
|
359
1138
|
}
|
|
360
1139
|
}
|
|
361
1140
|
}
|
|
362
|
-
return /* @__PURE__ */
|
|
1141
|
+
return /* @__PURE__ */ jsx8("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
363
1142
|
}
|
|
364
1143
|
|
|
365
|
-
// src/ui/formatters/
|
|
366
|
-
import {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
1144
|
+
// src/ui/formatters/search.tsx
|
|
1145
|
+
import { ExternalLink as ExternalLink2, Search as Search2 } from "lucide-react";
|
|
1146
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1147
|
+
function isSearchData(data) {
|
|
1148
|
+
if (typeof data !== "object" || data === null) return false;
|
|
1149
|
+
return "results" in data || "organic" in data || "answer" in data || "answerBox" in data;
|
|
1150
|
+
}
|
|
1151
|
+
function isSearchResult(data) {
|
|
1152
|
+
return typeof data === "object" && data !== null && ("title" in data || "link" in data || "url" in data);
|
|
1153
|
+
}
|
|
1154
|
+
function getDomain(url) {
|
|
1155
|
+
try {
|
|
1156
|
+
return new URL(url).hostname.replace("www.", "");
|
|
1157
|
+
} catch {
|
|
1158
|
+
return url;
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
function ResultCard({ result }) {
|
|
1162
|
+
const href = result.link || result.url;
|
|
1163
|
+
const snippet = result.snippet || result.description;
|
|
1164
|
+
return /* @__PURE__ */ jsxs8("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1", children: [
|
|
1165
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-start gap-2", children: [
|
|
1166
|
+
/* @__PURE__ */ jsxs8("div", { className: "min-w-0 flex-1", children: [
|
|
1167
|
+
href ? /* @__PURE__ */ jsx9(
|
|
1168
|
+
"a",
|
|
1169
|
+
{
|
|
1170
|
+
href,
|
|
1171
|
+
target: "_blank",
|
|
1172
|
+
rel: "noopener noreferrer",
|
|
1173
|
+
className: "text-sm font-medium text-primary hover:underline",
|
|
1174
|
+
children: result.title || href
|
|
1175
|
+
}
|
|
1176
|
+
) : /* @__PURE__ */ jsx9("p", { className: "text-sm font-medium text-foreground", children: result.title }),
|
|
1177
|
+
href && /* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground truncate", children: getDomain(href) })
|
|
1178
|
+
] }),
|
|
1179
|
+
href && /* @__PURE__ */ jsx9("a", { href, target: "_blank", rel: "noopener noreferrer", className: "shrink-0 text-muted-foreground hover:text-foreground", children: /* @__PURE__ */ jsx9(ExternalLink2, { className: "h-3.5 w-3.5" }) })
|
|
1180
|
+
] }),
|
|
1181
|
+
snippet && /* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground line-clamp-2", children: snippet })
|
|
1182
|
+
] });
|
|
1183
|
+
}
|
|
1184
|
+
function SearchFormatter({ data }) {
|
|
1185
|
+
if (isSearchData(data)) {
|
|
1186
|
+
const results = data.results || data.organic || [];
|
|
1187
|
+
const answerText = data.answer || data.answerBox?.answer || data.answerBox?.snippet;
|
|
1188
|
+
const related = data.relatedSearches || data.related_searches;
|
|
1189
|
+
return /* @__PURE__ */ jsxs8("div", { className: "space-y-3", children: [
|
|
1190
|
+
answerText && /* @__PURE__ */ jsxs8("div", { className: "rounded-lg border border-border bg-card p-3", children: [
|
|
1191
|
+
/* @__PURE__ */ jsx9("p", { className: "text-sm text-foreground", children: answerText }),
|
|
1192
|
+
data.answerBox?.title && /* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground mt-1", children: data.answerBox.title })
|
|
1193
|
+
] }),
|
|
1194
|
+
results.length > 0 && /* @__PURE__ */ jsx9("div", { className: "space-y-2", children: results.filter(isSearchResult).map((result, i) => /* @__PURE__ */ jsx9(ResultCard, { result }, result.link || result.url || i)) }),
|
|
1195
|
+
related && related.length > 0 && /* @__PURE__ */ jsx9("div", { className: "flex flex-wrap gap-1.5", children: related.map((r, i) => /* @__PURE__ */ jsxs8(
|
|
1196
|
+
"span",
|
|
1197
|
+
{
|
|
1198
|
+
className: "inline-flex items-center gap-1 rounded-full bg-muted px-2.5 py-1 text-xs text-muted-foreground",
|
|
1199
|
+
children: [
|
|
1200
|
+
/* @__PURE__ */ jsx9(Search2, { className: "h-3 w-3" }),
|
|
1201
|
+
r.query
|
|
1202
|
+
]
|
|
1203
|
+
},
|
|
1204
|
+
i
|
|
1205
|
+
)) })
|
|
1206
|
+
] });
|
|
370
1207
|
}
|
|
371
|
-
|
|
1208
|
+
if (Array.isArray(data)) {
|
|
1209
|
+
const results = data.filter(isSearchResult);
|
|
1210
|
+
if (results.length > 0) {
|
|
1211
|
+
return /* @__PURE__ */ jsx9("div", { className: "space-y-2", children: results.map((result, i) => /* @__PURE__ */ jsx9(ResultCard, { result }, result.link || result.url || i)) });
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
return /* @__PURE__ */ jsx9("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
372
1215
|
}
|
|
373
1216
|
|
|
374
|
-
// src/ui/
|
|
375
|
-
import {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
1217
|
+
// src/ui/formatters/docs.tsx
|
|
1218
|
+
import { FileText as FileText3, ExternalLink as ExternalLink3 } from "lucide-react";
|
|
1219
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1220
|
+
function isDocData(data) {
|
|
1221
|
+
return typeof data === "object" && data !== null && ("documentId" in data || "title" in data);
|
|
1222
|
+
}
|
|
1223
|
+
function extractTextContent(body) {
|
|
1224
|
+
if (!body || typeof body !== "object") return null;
|
|
1225
|
+
const content = body.content;
|
|
1226
|
+
if (!Array.isArray(content)) return null;
|
|
1227
|
+
const texts = [];
|
|
1228
|
+
for (const element of content) {
|
|
1229
|
+
if (element?.paragraph?.elements) {
|
|
1230
|
+
for (const el of element.paragraph.elements) {
|
|
1231
|
+
if (el?.textRun?.content) {
|
|
1232
|
+
texts.push(el.textRun.content);
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
382
1236
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
1237
|
+
return texts.length > 0 ? texts.join("").trim() : null;
|
|
1238
|
+
}
|
|
1239
|
+
function DocCard({ doc }) {
|
|
1240
|
+
const docUrl = doc.url || (doc.documentId ? `https://docs.google.com/document/d/${doc.documentId}` : null);
|
|
1241
|
+
const textContent = doc.content || extractTextContent(doc.body);
|
|
1242
|
+
return /* @__PURE__ */ jsxs9("div", { className: "rounded-lg border border-border bg-card p-3 space-y-2", children: [
|
|
1243
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-start gap-2", children: [
|
|
1244
|
+
/* @__PURE__ */ jsx10(FileText3, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
1245
|
+
/* @__PURE__ */ jsx10("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx10("p", { className: "text-sm font-medium text-foreground", children: docUrl ? /* @__PURE__ */ jsx10("a", { href: docUrl, target: "_blank", rel: "noopener noreferrer", className: "hover:underline", children: doc.title || "Untitled document" }) : doc.title || "Untitled document" }) }),
|
|
1246
|
+
docUrl && /* @__PURE__ */ jsx10("a", { href: docUrl, target: "_blank", rel: "noopener noreferrer", className: "shrink-0 text-muted-foreground hover:text-foreground", children: /* @__PURE__ */ jsx10(ExternalLink3, { className: "h-3.5 w-3.5" }) })
|
|
1247
|
+
] }),
|
|
1248
|
+
textContent && /* @__PURE__ */ jsx10("p", { className: "text-xs text-muted-foreground line-clamp-4 whitespace-pre-wrap", children: textContent })
|
|
1249
|
+
] });
|
|
1250
|
+
}
|
|
1251
|
+
function DocsFormatter({ data }) {
|
|
1252
|
+
if (isDocData(data)) {
|
|
1253
|
+
return /* @__PURE__ */ jsx10(DocCard, { doc: data });
|
|
1254
|
+
}
|
|
1255
|
+
if (Array.isArray(data)) {
|
|
1256
|
+
const docs = data.filter(isDocData);
|
|
1257
|
+
if (docs.length > 0) {
|
|
1258
|
+
return /* @__PURE__ */ jsx10("div", { className: "space-y-2", children: docs.map((doc, i) => /* @__PURE__ */ jsx10(DocCard, { doc }, doc.documentId || i)) });
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
return /* @__PURE__ */ jsx10("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
// src/ui/formatters/sheets.tsx
|
|
1265
|
+
import { Table2 as Table22, ExternalLink as ExternalLink4 } from "lucide-react";
|
|
1266
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1267
|
+
function isSheetsData(data) {
|
|
1268
|
+
return typeof data === "object" && data !== null && ("spreadsheetId" in data || "values" in data || "range" in data || "updatedRange" in data);
|
|
1269
|
+
}
|
|
1270
|
+
function SheetsTable({ values }) {
|
|
1271
|
+
if (values.length === 0) return null;
|
|
1272
|
+
const headers = values[0];
|
|
1273
|
+
const rows = values.slice(1);
|
|
1274
|
+
return /* @__PURE__ */ jsx11("div", { className: "overflow-x-auto rounded-lg border border-border", children: /* @__PURE__ */ jsxs10("table", { className: "w-full text-xs", children: [
|
|
1275
|
+
/* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsx11("tr", { className: "border-b border-border bg-muted", children: headers.map((header, i) => /* @__PURE__ */ jsx11("th", { className: "px-3 py-2 text-left font-medium text-foreground whitespace-nowrap", children: String(header) }, i)) }) }),
|
|
1276
|
+
/* @__PURE__ */ jsx11("tbody", { children: rows.map((row, rowIdx) => /* @__PURE__ */ jsx11("tr", { className: "border-b border-border last:border-0", children: headers.map((_, colIdx) => /* @__PURE__ */ jsx11("td", { className: "px-3 py-1.5 text-muted-foreground whitespace-nowrap", children: String(row[colIdx] ?? "") }, colIdx)) }, rowIdx)) })
|
|
1277
|
+
] }) });
|
|
1278
|
+
}
|
|
1279
|
+
function SheetsCard({ sheet }) {
|
|
1280
|
+
const sheetUrl = sheet.url || (sheet.spreadsheetId ? `https://docs.google.com/spreadsheets/d/${sheet.spreadsheetId}` : null);
|
|
1281
|
+
return /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
|
|
1282
|
+
/* @__PURE__ */ jsx11("div", { className: "rounded-lg border border-border bg-card p-3", children: /* @__PURE__ */ jsxs10("div", { className: "flex items-start gap-2", children: [
|
|
1283
|
+
/* @__PURE__ */ jsx11(Table22, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
1284
|
+
/* @__PURE__ */ jsxs10("div", { className: "min-w-0 flex-1", children: [
|
|
1285
|
+
/* @__PURE__ */ jsx11("p", { className: "text-sm font-medium text-foreground", children: sheetUrl ? /* @__PURE__ */ jsx11("a", { href: sheetUrl, target: "_blank", rel: "noopener noreferrer", className: "hover:underline", children: sheet.title || "Spreadsheet" }) : sheet.title || "Spreadsheet" }),
|
|
1286
|
+
(sheet.updatedRange || sheet.range) && /* @__PURE__ */ jsxs10("p", { className: "text-xs text-muted-foreground", children: [
|
|
1287
|
+
sheet.updatedRange || sheet.range,
|
|
1288
|
+
sheet.updatedCells !== void 0 && ` \xB7 ${sheet.updatedCells} cells updated`
|
|
1289
|
+
] })
|
|
1290
|
+
] }),
|
|
1291
|
+
sheetUrl && /* @__PURE__ */ jsx11("a", { href: sheetUrl, target: "_blank", rel: "noopener noreferrer", className: "shrink-0 text-muted-foreground hover:text-foreground", children: /* @__PURE__ */ jsx11(ExternalLink4, { className: "h-3.5 w-3.5" }) })
|
|
1292
|
+
] }) }),
|
|
1293
|
+
sheet.values && sheet.values.length > 0 && /* @__PURE__ */ jsx11(SheetsTable, { values: sheet.values })
|
|
1294
|
+
] });
|
|
1295
|
+
}
|
|
1296
|
+
function SheetsFormatter({ data }) {
|
|
1297
|
+
if (isSheetsData(data)) {
|
|
1298
|
+
return /* @__PURE__ */ jsx11(SheetsCard, { sheet: data });
|
|
1299
|
+
}
|
|
1300
|
+
return /* @__PURE__ */ jsx11("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
// src/ui/formatters/slides.tsx
|
|
1304
|
+
import { Presentation as Presentation2, ExternalLink as ExternalLink5 } from "lucide-react";
|
|
1305
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1306
|
+
function isSlidesData(data) {
|
|
1307
|
+
return typeof data === "object" && data !== null && ("presentationId" in data || "title" in data && "slides" in data);
|
|
1308
|
+
}
|
|
1309
|
+
function SlidesCard({ presentation }) {
|
|
1310
|
+
const slideUrl = presentation.url || (presentation.presentationId ? `https://docs.google.com/presentation/d/${presentation.presentationId}` : null);
|
|
1311
|
+
const slideCount = presentation.slides?.length;
|
|
1312
|
+
return /* @__PURE__ */ jsx12("div", { className: "rounded-lg border border-border bg-card p-3", children: /* @__PURE__ */ jsxs11("div", { className: "flex items-start gap-2", children: [
|
|
1313
|
+
/* @__PURE__ */ jsx12(Presentation2, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
1314
|
+
/* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
|
|
1315
|
+
/* @__PURE__ */ jsx12("p", { className: "text-sm font-medium text-foreground", children: slideUrl ? /* @__PURE__ */ jsx12("a", { href: slideUrl, target: "_blank", rel: "noopener noreferrer", className: "hover:underline", children: presentation.title || "Presentation" }) : presentation.title || "Presentation" }),
|
|
1316
|
+
slideCount !== void 0 && /* @__PURE__ */ jsxs11("p", { className: "text-xs text-muted-foreground", children: [
|
|
1317
|
+
slideCount,
|
|
1318
|
+
" ",
|
|
1319
|
+
slideCount === 1 ? "slide" : "slides"
|
|
1320
|
+
] })
|
|
1321
|
+
] }),
|
|
1322
|
+
slideUrl && /* @__PURE__ */ jsx12("a", { href: slideUrl, target: "_blank", rel: "noopener noreferrer", className: "shrink-0 text-muted-foreground hover:text-foreground", children: /* @__PURE__ */ jsx12(ExternalLink5, { className: "h-3.5 w-3.5" }) })
|
|
1323
|
+
] }) });
|
|
1324
|
+
}
|
|
1325
|
+
function SlidesFormatter({ data }) {
|
|
1326
|
+
if (isSlidesData(data)) {
|
|
1327
|
+
return /* @__PURE__ */ jsx12(SlidesCard, { presentation: data });
|
|
1328
|
+
}
|
|
1329
|
+
return /* @__PURE__ */ jsx12("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
// src/ui/formatters/hubspot.tsx
|
|
1333
|
+
import { Users as Users3, Building2, Mail as Mail3, Phone as Phone2 } from "lucide-react";
|
|
1334
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1335
|
+
function isHubspotContact(data) {
|
|
1336
|
+
if (typeof data !== "object" || data === null) return false;
|
|
1337
|
+
const props = data.properties;
|
|
1338
|
+
return props && ("firstname" in props || "lastname" in props || "email" in props);
|
|
1339
|
+
}
|
|
1340
|
+
function isHubspotCompany(data) {
|
|
1341
|
+
if (typeof data !== "object" || data === null) return false;
|
|
1342
|
+
const props = data.properties;
|
|
1343
|
+
return props && ("name" in props || "domain" in props);
|
|
1344
|
+
}
|
|
1345
|
+
function ContactCard({ contact }) {
|
|
1346
|
+
const p = contact.properties || {};
|
|
1347
|
+
const name = [p.firstname, p.lastname].filter(Boolean).join(" ") || "Unknown contact";
|
|
1348
|
+
return /* @__PURE__ */ jsxs12("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
1349
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-2", children: [
|
|
1350
|
+
/* @__PURE__ */ jsx13(Users3, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
1351
|
+
/* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
|
|
1352
|
+
/* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-foreground", children: name }),
|
|
1353
|
+
p.company && /* @__PURE__ */ jsx13("p", { className: "text-xs text-muted-foreground", children: p.company })
|
|
1354
|
+
] })
|
|
1355
|
+
] }),
|
|
1356
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap gap-x-4 gap-y-1 pl-6", children: [
|
|
1357
|
+
p.email && /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
1358
|
+
/* @__PURE__ */ jsx13(Mail3, { className: "h-3 w-3" }),
|
|
1359
|
+
p.email
|
|
1360
|
+
] }),
|
|
1361
|
+
p.phone && /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
1362
|
+
/* @__PURE__ */ jsx13(Phone2, { className: "h-3 w-3" }),
|
|
1363
|
+
p.phone
|
|
1364
|
+
] })
|
|
1365
|
+
] })
|
|
1366
|
+
] });
|
|
1367
|
+
}
|
|
1368
|
+
function CompanyCard({ company }) {
|
|
1369
|
+
const p = company.properties || {};
|
|
1370
|
+
return /* @__PURE__ */ jsxs12("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
1371
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-2", children: [
|
|
1372
|
+
/* @__PURE__ */ jsx13(Building2, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
1373
|
+
/* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
|
|
1374
|
+
/* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-foreground", children: p.name || "Unknown company" }),
|
|
1375
|
+
p.industry && /* @__PURE__ */ jsx13("p", { className: "text-xs text-muted-foreground", children: p.industry })
|
|
1376
|
+
] })
|
|
1377
|
+
] }),
|
|
1378
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap gap-x-4 gap-y-1 pl-6", children: [
|
|
1379
|
+
p.domain && /* @__PURE__ */ jsx13("span", { className: "text-xs text-muted-foreground", children: p.domain }),
|
|
1380
|
+
p.phone && /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
1381
|
+
/* @__PURE__ */ jsx13(Phone2, { className: "h-3 w-3" }),
|
|
1382
|
+
p.phone
|
|
1383
|
+
] })
|
|
1384
|
+
] })
|
|
1385
|
+
] });
|
|
1386
|
+
}
|
|
1387
|
+
function HubspotFormatter({ data }) {
|
|
1388
|
+
if (isHubspotContact(data)) {
|
|
1389
|
+
return /* @__PURE__ */ jsx13(ContactCard, { contact: data });
|
|
1390
|
+
}
|
|
1391
|
+
if (isHubspotCompany(data)) {
|
|
1392
|
+
return /* @__PURE__ */ jsx13(CompanyCard, { company: data });
|
|
1393
|
+
}
|
|
1394
|
+
if (Array.isArray(data)) {
|
|
1395
|
+
const contacts = data.filter(isHubspotContact);
|
|
1396
|
+
if (contacts.length > 0) {
|
|
1397
|
+
return /* @__PURE__ */ jsx13("div", { className: "space-y-2", children: contacts.map((c, i) => /* @__PURE__ */ jsx13(ContactCard, { contact: c }, c.id || i)) });
|
|
1398
|
+
}
|
|
1399
|
+
const companies = data.filter(isHubspotCompany);
|
|
1400
|
+
if (companies.length > 0) {
|
|
1401
|
+
return /* @__PURE__ */ jsx13("div", { className: "space-y-2", children: companies.map((c, i) => /* @__PURE__ */ jsx13(CompanyCard, { company: c }, c.id || i)) });
|
|
1402
|
+
}
|
|
397
1403
|
}
|
|
1404
|
+
if (typeof data === "object" && data !== null && "results" in data) {
|
|
1405
|
+
const results = data.results;
|
|
1406
|
+
if (Array.isArray(results)) {
|
|
1407
|
+
const contacts = results.filter(isHubspotContact);
|
|
1408
|
+
if (contacts.length > 0) {
|
|
1409
|
+
return /* @__PURE__ */ jsx13("div", { className: "space-y-2", children: contacts.map((c, i) => /* @__PURE__ */ jsx13(ContactCard, { contact: c }, c.id || i)) });
|
|
1410
|
+
}
|
|
1411
|
+
const companies = results.filter(isHubspotCompany);
|
|
1412
|
+
if (companies.length > 0) {
|
|
1413
|
+
return /* @__PURE__ */ jsx13("div", { className: "space-y-2", children: companies.map((c, i) => /* @__PURE__ */ jsx13(CompanyCard, { company: c }, c.id || i)) });
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
return /* @__PURE__ */ jsx13("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
// src/ui/formatters/linear.tsx
|
|
1421
|
+
import { CircleDot as CircleDot3, FolderKanban } from "lucide-react";
|
|
1422
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1423
|
+
function isLinearIssue(data) {
|
|
1424
|
+
if (typeof data !== "object" || data === null) return false;
|
|
1425
|
+
return "title" in data && ("identifier" in data || "state" in data || "priority" in data);
|
|
1426
|
+
}
|
|
1427
|
+
function isLinearProject(data) {
|
|
1428
|
+
if (typeof data !== "object" || data === null) return false;
|
|
1429
|
+
return "name" in data && ("progress" in data || "state" in data && typeof data.state === "string");
|
|
1430
|
+
}
|
|
1431
|
+
var PRIORITY_LABELS = {
|
|
1432
|
+
0: { label: "No priority", style: "text-muted-foreground" },
|
|
1433
|
+
1: { label: "Urgent", style: "text-destructive" },
|
|
1434
|
+
2: { label: "High", style: "text-orange-500" },
|
|
1435
|
+
3: { label: "Medium", style: "text-yellow-500" },
|
|
1436
|
+
4: { label: "Low", style: "text-muted-foreground" }
|
|
1437
|
+
};
|
|
1438
|
+
function IssueCard({ issue }) {
|
|
1439
|
+
const priorityInfo = issue.priority !== void 0 ? PRIORITY_LABELS[issue.priority] : null;
|
|
1440
|
+
const assigneeName = issue.assignee?.displayName || issue.assignee?.name;
|
|
1441
|
+
return /* @__PURE__ */ jsx14("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: /* @__PURE__ */ jsxs13("div", { className: "flex items-start gap-2", children: [
|
|
1442
|
+
/* @__PURE__ */ jsx14(
|
|
1443
|
+
CircleDot3,
|
|
1444
|
+
{
|
|
1445
|
+
className: "h-4 w-4 mt-0.5 shrink-0",
|
|
1446
|
+
style: issue.state?.color ? { color: issue.state.color } : void 0
|
|
1447
|
+
}
|
|
1448
|
+
),
|
|
1449
|
+
/* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
|
|
1450
|
+
/* @__PURE__ */ jsxs13("p", { className: "text-sm font-medium text-foreground", children: [
|
|
1451
|
+
issue.url ? /* @__PURE__ */ jsx14("a", { href: issue.url, target: "_blank", rel: "noopener noreferrer", className: "hover:underline", children: issue.title }) : issue.title,
|
|
1452
|
+
issue.identifier && /* @__PURE__ */ jsxs13("span", { className: "text-muted-foreground font-normal", children: [
|
|
1453
|
+
" ",
|
|
1454
|
+
issue.identifier
|
|
1455
|
+
] })
|
|
1456
|
+
] }),
|
|
1457
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 mt-0.5 flex-wrap", children: [
|
|
1458
|
+
issue.state?.name && /* @__PURE__ */ jsx14(
|
|
1459
|
+
"span",
|
|
1460
|
+
{
|
|
1461
|
+
className: "rounded-full bg-muted px-2 py-0.5 text-xs",
|
|
1462
|
+
style: issue.state.color ? { color: issue.state.color } : void 0,
|
|
1463
|
+
children: issue.state.name
|
|
1464
|
+
}
|
|
1465
|
+
),
|
|
1466
|
+
priorityInfo && /* @__PURE__ */ jsx14("span", { className: `text-xs ${priorityInfo.style}`, children: issue.priorityLabel || priorityInfo.label }),
|
|
1467
|
+
assigneeName && /* @__PURE__ */ jsx14("span", { className: "text-xs text-muted-foreground", children: assigneeName })
|
|
1468
|
+
] })
|
|
1469
|
+
] })
|
|
1470
|
+
] }) });
|
|
1471
|
+
}
|
|
1472
|
+
function ProjectCard({ project }) {
|
|
1473
|
+
const progressPercent = project.progress !== void 0 ? Math.round(project.progress * 100) : null;
|
|
1474
|
+
return /* @__PURE__ */ jsxs13("div", { className: "rounded-lg border border-border bg-card p-3 space-y-2", children: [
|
|
1475
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-start gap-2", children: [
|
|
1476
|
+
/* @__PURE__ */ jsx14(FolderKanban, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
1477
|
+
/* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
|
|
1478
|
+
/* @__PURE__ */ jsx14("p", { className: "text-sm font-medium text-foreground", children: project.url ? /* @__PURE__ */ jsx14("a", { href: project.url, target: "_blank", rel: "noopener noreferrer", className: "hover:underline", children: project.name }) : project.name }),
|
|
1479
|
+
project.state && /* @__PURE__ */ jsx14("span", { className: "text-xs text-muted-foreground", children: project.state })
|
|
1480
|
+
] })
|
|
1481
|
+
] }),
|
|
1482
|
+
progressPercent !== null && /* @__PURE__ */ jsxs13("div", { className: "space-y-1", children: [
|
|
1483
|
+
/* @__PURE__ */ jsx14("div", { className: "h-1.5 rounded-full bg-muted overflow-hidden", children: /* @__PURE__ */ jsx14(
|
|
1484
|
+
"div",
|
|
1485
|
+
{
|
|
1486
|
+
className: "h-full rounded-full bg-primary transition-all",
|
|
1487
|
+
style: { width: `${progressPercent}%` }
|
|
1488
|
+
}
|
|
1489
|
+
) }),
|
|
1490
|
+
/* @__PURE__ */ jsxs13("p", { className: "text-xs text-muted-foreground text-right", children: [
|
|
1491
|
+
progressPercent,
|
|
1492
|
+
"%"
|
|
1493
|
+
] })
|
|
1494
|
+
] })
|
|
1495
|
+
] });
|
|
1496
|
+
}
|
|
1497
|
+
function LinearFormatter({ data }) {
|
|
1498
|
+
if (isLinearIssue(data)) {
|
|
1499
|
+
return /* @__PURE__ */ jsx14(IssueCard, { issue: data });
|
|
1500
|
+
}
|
|
1501
|
+
if (isLinearProject(data)) {
|
|
1502
|
+
return /* @__PURE__ */ jsx14(ProjectCard, { project: data });
|
|
1503
|
+
}
|
|
1504
|
+
if (Array.isArray(data)) {
|
|
1505
|
+
const issues = data.filter(isLinearIssue);
|
|
1506
|
+
if (issues.length > 0) {
|
|
1507
|
+
return /* @__PURE__ */ jsx14("div", { className: "space-y-2", children: issues.map((issue, i) => /* @__PURE__ */ jsx14(IssueCard, { issue }, issue.id || i)) });
|
|
1508
|
+
}
|
|
1509
|
+
const projects = data.filter(isLinearProject);
|
|
1510
|
+
if (projects.length > 0) {
|
|
1511
|
+
return /* @__PURE__ */ jsx14("div", { className: "space-y-2", children: projects.map((project, i) => /* @__PURE__ */ jsx14(ProjectCard, { project }, project.id || i)) });
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
if (typeof data === "object" && data !== null) {
|
|
1515
|
+
const arr = data.nodes || data.issues || data.projects;
|
|
1516
|
+
if (Array.isArray(arr)) {
|
|
1517
|
+
const issues = arr.filter(isLinearIssue);
|
|
1518
|
+
if (issues.length > 0) {
|
|
1519
|
+
return /* @__PURE__ */ jsx14("div", { className: "space-y-2", children: issues.map((issue, i) => /* @__PURE__ */ jsx14(IssueCard, { issue }, issue.id || i)) });
|
|
1520
|
+
}
|
|
1521
|
+
const projects = arr.filter(isLinearProject);
|
|
1522
|
+
if (projects.length > 0) {
|
|
1523
|
+
return /* @__PURE__ */ jsx14("div", { className: "space-y-2", children: projects.map((project, i) => /* @__PURE__ */ jsx14(ProjectCard, { project }, project.id || i)) });
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
return /* @__PURE__ */ jsx14("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
// src/ui/formatters/pipedrive.tsx
|
|
1531
|
+
import { Briefcase as Briefcase2, DollarSign } from "lucide-react";
|
|
1532
|
+
import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1533
|
+
function isPipedriveDeal(data) {
|
|
1534
|
+
return typeof data === "object" && data !== null && ("title" in data || "value" in data || "status" in data) && !("subject" in data);
|
|
1535
|
+
}
|
|
1536
|
+
function formatCurrency(value, currency) {
|
|
1537
|
+
try {
|
|
1538
|
+
return new Intl.NumberFormat(void 0, {
|
|
1539
|
+
style: "currency",
|
|
1540
|
+
currency: currency || "USD",
|
|
1541
|
+
minimumFractionDigits: 0,
|
|
1542
|
+
maximumFractionDigits: 0
|
|
1543
|
+
}).format(value);
|
|
1544
|
+
} catch {
|
|
1545
|
+
return `${currency || "$"}${value.toLocaleString()}`;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
function getStatusBadge(status) {
|
|
1549
|
+
switch (status) {
|
|
1550
|
+
case "won":
|
|
1551
|
+
return { label: "Won", className: "text-green-500 bg-green-500/10" };
|
|
1552
|
+
case "lost":
|
|
1553
|
+
return { label: "Lost", className: "text-destructive bg-destructive/10" };
|
|
1554
|
+
case "open":
|
|
1555
|
+
return { label: "Open", className: "text-primary bg-primary/10" };
|
|
1556
|
+
case "deleted":
|
|
1557
|
+
return { label: "Deleted", className: "text-muted-foreground bg-muted" };
|
|
1558
|
+
default:
|
|
1559
|
+
return status ? { label: status, className: "text-muted-foreground bg-muted" } : null;
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
function DealCard({ deal }) {
|
|
1563
|
+
const statusBadge = getStatusBadge(deal.status);
|
|
1564
|
+
return /* @__PURE__ */ jsxs14("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
1565
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-2", children: [
|
|
1566
|
+
/* @__PURE__ */ jsx15(Briefcase2, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
1567
|
+
/* @__PURE__ */ jsxs14("div", { className: "min-w-0 flex-1", children: [
|
|
1568
|
+
/* @__PURE__ */ jsx15("p", { className: "text-sm font-medium text-foreground", children: deal.title || "Untitled deal" }),
|
|
1569
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2 mt-0.5 flex-wrap", children: [
|
|
1570
|
+
deal.value !== void 0 && /* @__PURE__ */ jsxs14("span", { className: "flex items-center gap-1 text-xs font-medium text-foreground", children: [
|
|
1571
|
+
/* @__PURE__ */ jsx15(DollarSign, { className: "h-3 w-3" }),
|
|
1572
|
+
formatCurrency(deal.value, deal.currency)
|
|
1573
|
+
] }),
|
|
1574
|
+
statusBadge && /* @__PURE__ */ jsx15("span", { className: `rounded-full px-2 py-0.5 text-xs ${statusBadge.className}`, children: statusBadge.label })
|
|
1575
|
+
] })
|
|
1576
|
+
] })
|
|
1577
|
+
] }),
|
|
1578
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex flex-wrap gap-x-4 gap-y-1 pl-6 text-xs text-muted-foreground", children: [
|
|
1579
|
+
deal.person_name && /* @__PURE__ */ jsx15("span", { children: deal.person_name }),
|
|
1580
|
+
deal.org_name && /* @__PURE__ */ jsx15("span", { children: deal.org_name }),
|
|
1581
|
+
deal.stage_name && /* @__PURE__ */ jsx15("span", { children: deal.stage_name })
|
|
1582
|
+
] })
|
|
1583
|
+
] });
|
|
1584
|
+
}
|
|
1585
|
+
function PipedriveFormatter({ data }) {
|
|
1586
|
+
if (isPipedriveDeal(data)) {
|
|
1587
|
+
return /* @__PURE__ */ jsx15(DealCard, { deal: data });
|
|
1588
|
+
}
|
|
1589
|
+
if (Array.isArray(data)) {
|
|
1590
|
+
const deals = data.filter(isPipedriveDeal);
|
|
1591
|
+
if (deals.length > 0) {
|
|
1592
|
+
return /* @__PURE__ */ jsx15("div", { className: "space-y-2", children: deals.map((deal, i) => /* @__PURE__ */ jsx15(DealCard, { deal }, deal.id || i)) });
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
if (typeof data === "object" && data !== null && "data" in data) {
|
|
1596
|
+
const items = data.data;
|
|
1597
|
+
if (Array.isArray(items)) {
|
|
1598
|
+
const deals = items.filter(isPipedriveDeal);
|
|
1599
|
+
if (deals.length > 0) {
|
|
1600
|
+
return /* @__PURE__ */ jsx15("div", { className: "space-y-2", children: deals.map((deal, i) => /* @__PURE__ */ jsx15(DealCard, { deal }, deal.id || i)) });
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
if (isPipedriveDeal(items)) {
|
|
1604
|
+
return /* @__PURE__ */ jsx15(DealCard, { deal: items });
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
return /* @__PURE__ */ jsx15("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
// src/ui/formatters/compute.tsx
|
|
1611
|
+
import { Terminal as Terminal2, AlertTriangle, Check as Check3, X as X2 } from "lucide-react";
|
|
1612
|
+
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1613
|
+
function isComputeData(data) {
|
|
1614
|
+
if (typeof data !== "object" || data === null) return false;
|
|
1615
|
+
return "stdout" in data || "stderr" in data || "exit_code" in data || "exitCode" in data || "output" in data;
|
|
1616
|
+
}
|
|
1617
|
+
function formatDuration(ms) {
|
|
1618
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
1619
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
1620
|
+
return `${(ms / 6e4).toFixed(1)}m`;
|
|
1621
|
+
}
|
|
1622
|
+
function ComputeFormatter({ data }) {
|
|
1623
|
+
if (!isComputeData(data)) {
|
|
1624
|
+
return /* @__PURE__ */ jsx16("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
1625
|
+
}
|
|
1626
|
+
const exitCode = data.exit_code ?? data.exitCode;
|
|
1627
|
+
const duration = data.duration_ms ?? data.duration;
|
|
1628
|
+
const stdout = data.stdout || data.output || "";
|
|
1629
|
+
const stderr = data.stderr || data.error || "";
|
|
1630
|
+
const success = exitCode === void 0 || exitCode === 0;
|
|
1631
|
+
return /* @__PURE__ */ jsxs15("div", { className: "space-y-2", children: [
|
|
1632
|
+
/* @__PURE__ */ jsxs15("div", { className: "rounded-lg border border-border bg-background overflow-hidden", children: [
|
|
1633
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-muted border-b border-border", children: [
|
|
1634
|
+
/* @__PURE__ */ jsx16(Terminal2, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
1635
|
+
/* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground flex-1", children: "Output" }),
|
|
1636
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
|
|
1637
|
+
duration !== void 0 && /* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground", children: formatDuration(duration) }),
|
|
1638
|
+
exitCode !== void 0 && /* @__PURE__ */ jsxs15("span", { className: `inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs ${success ? "text-green-500 bg-green-500/10" : "text-destructive bg-destructive/10"}`, children: [
|
|
1639
|
+
success ? /* @__PURE__ */ jsx16(Check3, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx16(X2, { className: "h-3 w-3" }),
|
|
1640
|
+
"exit ",
|
|
1641
|
+
exitCode
|
|
1642
|
+
] })
|
|
1643
|
+
] })
|
|
1644
|
+
] }),
|
|
1645
|
+
stdout && /* @__PURE__ */ jsx16("pre", { className: "p-3 text-xs text-foreground overflow-x-auto max-h-80 overflow-y-auto font-mono whitespace-pre-wrap", children: stdout }),
|
|
1646
|
+
stderr && /* @__PURE__ */ jsxs15("div", { className: "border-t border-border", children: [
|
|
1647
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-1.5 px-3 py-1 bg-destructive/5", children: [
|
|
1648
|
+
/* @__PURE__ */ jsx16(AlertTriangle, { className: "h-3 w-3 text-destructive" }),
|
|
1649
|
+
/* @__PURE__ */ jsx16("span", { className: "text-xs text-destructive", children: "stderr" })
|
|
1650
|
+
] }),
|
|
1651
|
+
/* @__PURE__ */ jsx16("pre", { className: "p-3 text-xs text-destructive overflow-x-auto max-h-40 overflow-y-auto font-mono whitespace-pre-wrap", children: stderr })
|
|
1652
|
+
] }),
|
|
1653
|
+
!stdout && !stderr && /* @__PURE__ */ jsx16("p", { className: "p-3 text-xs text-muted-foreground italic", children: "No output" })
|
|
1654
|
+
] }),
|
|
1655
|
+
data.files && data.files.length > 0 && /* @__PURE__ */ jsx16("div", { className: "space-y-1", children: data.files.map((file, i) => /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 rounded-lg border border-border bg-card p-2", children: [
|
|
1656
|
+
/* @__PURE__ */ jsx16(Terminal2, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }),
|
|
1657
|
+
file.url ? /* @__PURE__ */ jsx16("a", { href: file.url, target: "_blank", rel: "noopener noreferrer", className: "text-xs text-primary hover:underline truncate", children: file.name || file.url }) : /* @__PURE__ */ jsx16("span", { className: "text-xs text-foreground truncate", children: file.name })
|
|
1658
|
+
] }, i)) })
|
|
1659
|
+
] });
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
// src/ui/formatters/resend.tsx
|
|
1663
|
+
import { Send as Send2, Clock as Clock2 } from "lucide-react";
|
|
1664
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1665
|
+
function isResendData(data) {
|
|
1666
|
+
return typeof data === "object" && data !== null && ("id" in data || "to" in data) && ("subject" in data || "from" in data || "created_at" in data);
|
|
1667
|
+
}
|
|
1668
|
+
function formatRecipients2(to) {
|
|
1669
|
+
if (!to) return "Unknown";
|
|
1670
|
+
if (Array.isArray(to)) return to.join(", ");
|
|
1671
|
+
return to;
|
|
1672
|
+
}
|
|
1673
|
+
function formatTimestamp(dateStr) {
|
|
1674
|
+
try {
|
|
1675
|
+
const date = new Date(dateStr);
|
|
1676
|
+
return date.toLocaleString(void 0, { dateStyle: "medium", timeStyle: "short" });
|
|
1677
|
+
} catch {
|
|
1678
|
+
return dateStr;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
function ResendCard({ email }) {
|
|
1682
|
+
return /* @__PURE__ */ jsxs16("div", { className: "rounded-lg border border-border bg-card p-3 space-y-2", children: [
|
|
1683
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-start gap-2", children: [
|
|
1684
|
+
/* @__PURE__ */ jsx17("div", { className: "flex h-8 w-8 items-center justify-center rounded-full bg-green-500/10 shrink-0", children: /* @__PURE__ */ jsx17(Send2, { className: "h-4 w-4 text-green-500" }) }),
|
|
1685
|
+
/* @__PURE__ */ jsxs16("div", { className: "min-w-0 flex-1", children: [
|
|
1686
|
+
/* @__PURE__ */ jsx17("p", { className: "text-sm font-medium text-foreground", children: "Email sent" }),
|
|
1687
|
+
email.subject && /* @__PURE__ */ jsx17("p", { className: "text-xs text-muted-foreground truncate", children: email.subject })
|
|
1688
|
+
] })
|
|
1689
|
+
] }),
|
|
1690
|
+
/* @__PURE__ */ jsxs16("div", { className: "pl-10 space-y-1 text-xs text-muted-foreground", children: [
|
|
1691
|
+
/* @__PURE__ */ jsxs16("p", { children: [
|
|
1692
|
+
/* @__PURE__ */ jsx17("span", { className: "text-foreground", children: "To:" }),
|
|
1693
|
+
" ",
|
|
1694
|
+
formatRecipients2(email.to)
|
|
1695
|
+
] }),
|
|
1696
|
+
email.from && /* @__PURE__ */ jsxs16("p", { children: [
|
|
1697
|
+
/* @__PURE__ */ jsx17("span", { className: "text-foreground", children: "From:" }),
|
|
1698
|
+
" ",
|
|
1699
|
+
email.from
|
|
1700
|
+
] }),
|
|
1701
|
+
email.created_at && /* @__PURE__ */ jsxs16("p", { className: "flex items-center gap-1", children: [
|
|
1702
|
+
/* @__PURE__ */ jsx17(Clock2, { className: "h-3 w-3" }),
|
|
1703
|
+
formatTimestamp(email.created_at)
|
|
1704
|
+
] }),
|
|
1705
|
+
email.last_event && /* @__PURE__ */ jsx17("span", { className: "inline-block rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground capitalize", children: email.last_event })
|
|
1706
|
+
] })
|
|
1707
|
+
] });
|
|
1708
|
+
}
|
|
1709
|
+
function ResendFormatter({ data }) {
|
|
1710
|
+
if (isResendData(data)) {
|
|
1711
|
+
return /* @__PURE__ */ jsx17(ResendCard, { email: data });
|
|
1712
|
+
}
|
|
1713
|
+
if (typeof data === "object" && data !== null && "data" in data) {
|
|
1714
|
+
const inner = data.data;
|
|
1715
|
+
if (isResendData(inner)) {
|
|
1716
|
+
return /* @__PURE__ */ jsx17(ResendCard, { email: inner });
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
return /* @__PURE__ */ jsx17("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
// src/ui/formatters/inbox.tsx
|
|
1723
|
+
import { Bell as Bell2, Calendar as Calendar3, Mail as Mail4, MessageSquare as MessageSquare3 } from "lucide-react";
|
|
1724
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1725
|
+
function isInboxEvent(data) {
|
|
1726
|
+
return typeof data === "object" && data !== null && ("title" in data || "type" in data || "description" in data);
|
|
1727
|
+
}
|
|
1728
|
+
function getEventIcon(type) {
|
|
1729
|
+
switch (type) {
|
|
1730
|
+
case "email":
|
|
1731
|
+
return Mail4;
|
|
1732
|
+
case "message":
|
|
1733
|
+
return MessageSquare3;
|
|
1734
|
+
case "calendar":
|
|
1735
|
+
return Calendar3;
|
|
1736
|
+
default:
|
|
1737
|
+
return Bell2;
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
function formatTimestamp2(dateStr) {
|
|
1741
|
+
try {
|
|
1742
|
+
const date = new Date(dateStr);
|
|
1743
|
+
const now = /* @__PURE__ */ new Date();
|
|
1744
|
+
const diffMs = now.getTime() - date.getTime();
|
|
1745
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
1746
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
1747
|
+
if (diffHours < 1) return "Just now";
|
|
1748
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
1749
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
1750
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
1751
|
+
} catch {
|
|
1752
|
+
return dateStr;
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
function EventCard2({ event }) {
|
|
1756
|
+
const Icon = getEventIcon(event.type);
|
|
1757
|
+
const timestamp = event.timestamp || event.created_at;
|
|
1758
|
+
return /* @__PURE__ */ jsxs17("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
1759
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-start gap-2", children: [
|
|
1760
|
+
/* @__PURE__ */ jsx18(Icon, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
1761
|
+
/* @__PURE__ */ jsxs17("div", { className: "min-w-0 flex-1", children: [
|
|
1762
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
|
|
1763
|
+
event.type && /* @__PURE__ */ jsx18("span", { className: "rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground capitalize", children: event.type }),
|
|
1764
|
+
event.source && /* @__PURE__ */ jsx18("span", { className: "text-xs text-muted-foreground", children: event.source }),
|
|
1765
|
+
timestamp && /* @__PURE__ */ jsx18("span", { className: "text-xs text-muted-foreground ml-auto shrink-0", children: formatTimestamp2(timestamp) })
|
|
1766
|
+
] }),
|
|
1767
|
+
event.title && /* @__PURE__ */ jsx18("p", { className: "text-sm font-medium text-foreground mt-1", children: event.title })
|
|
1768
|
+
] })
|
|
1769
|
+
] }),
|
|
1770
|
+
event.description && /* @__PURE__ */ jsx18("p", { className: "text-xs text-muted-foreground line-clamp-2 pl-6", children: event.description })
|
|
1771
|
+
] });
|
|
1772
|
+
}
|
|
1773
|
+
function InboxFormatter({ data }) {
|
|
1774
|
+
if (isInboxEvent(data)) {
|
|
1775
|
+
return /* @__PURE__ */ jsx18(EventCard2, { event: data });
|
|
1776
|
+
}
|
|
1777
|
+
if (Array.isArray(data)) {
|
|
1778
|
+
const events = data.filter(isInboxEvent);
|
|
1779
|
+
if (events.length > 0) {
|
|
1780
|
+
return /* @__PURE__ */ jsx18("div", { className: "space-y-2", children: events.map((event, i) => /* @__PURE__ */ jsx18(EventCard2, { event }, event.id || i)) });
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
if (typeof data === "object" && data !== null && "events" in data) {
|
|
1784
|
+
const events = data.events;
|
|
1785
|
+
if (Array.isArray(events)) {
|
|
1786
|
+
const inboxEvents = events.filter(isInboxEvent);
|
|
1787
|
+
if (inboxEvents.length > 0) {
|
|
1788
|
+
return /* @__PURE__ */ jsx18("div", { className: "space-y-2", children: inboxEvents.map((event, i) => /* @__PURE__ */ jsx18(EventCard2, { event }, event.id || i)) });
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
return /* @__PURE__ */ jsx18("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
// src/ui/formatters/discord.tsx
|
|
1796
|
+
import { MessageSquare as MessageSquare4, Hash as Hash2, Shield, Users as Users4 } from "lucide-react";
|
|
1797
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1798
|
+
function isGuildData(data) {
|
|
1799
|
+
return typeof data === "object" && data !== null && "name" in data && ("owner" in data || "member_count" in data || "icon" in data);
|
|
1800
|
+
}
|
|
1801
|
+
function isChannelData(data) {
|
|
1802
|
+
return typeof data === "object" && data !== null && "name" in data && ("type" in data || "position" in data);
|
|
1803
|
+
}
|
|
1804
|
+
function isMessageData(data) {
|
|
1805
|
+
return typeof data === "object" && data !== null && ("content" in data || "author" in data) && "id" in data;
|
|
1806
|
+
}
|
|
1807
|
+
function formatRelativeDate3(dateStr) {
|
|
1808
|
+
try {
|
|
1809
|
+
const date = new Date(dateStr);
|
|
1810
|
+
const now = /* @__PURE__ */ new Date();
|
|
1811
|
+
const diffMs = now.getTime() - date.getTime();
|
|
1812
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
1813
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
1814
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
1815
|
+
if (diffMins < 1) return "Just now";
|
|
1816
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
1817
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
1818
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
1819
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
1820
|
+
} catch {
|
|
1821
|
+
return dateStr;
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
function GuildCard({ guild }) {
|
|
1825
|
+
return /* @__PURE__ */ jsxs18("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1", children: [
|
|
1826
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2", children: [
|
|
1827
|
+
/* @__PURE__ */ jsx19(Shield, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
|
|
1828
|
+
/* @__PURE__ */ jsx19("span", { className: "text-sm font-medium text-foreground flex-1", children: guild.name }),
|
|
1829
|
+
guild.owner && /* @__PURE__ */ jsx19("span", { className: "rounded-full bg-yellow-500/10 px-2 py-0.5 text-xs text-yellow-600", children: "Owner" })
|
|
1830
|
+
] }),
|
|
1831
|
+
guild.member_count !== void 0 && /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-1 pl-6 text-xs text-muted-foreground", children: [
|
|
1832
|
+
/* @__PURE__ */ jsx19(Users4, { className: "h-3 w-3" }),
|
|
1833
|
+
guild.member_count,
|
|
1834
|
+
" members"
|
|
1835
|
+
] })
|
|
1836
|
+
] });
|
|
1837
|
+
}
|
|
1838
|
+
function ChannelCard2({ channel }) {
|
|
1839
|
+
return /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2 rounded-lg border border-border bg-card p-3", children: [
|
|
1840
|
+
/* @__PURE__ */ jsx19(Hash2, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
|
|
1841
|
+
/* @__PURE__ */ jsx19("span", { className: "text-sm text-foreground flex-1", children: channel.name || channel.id }),
|
|
1842
|
+
channel.member_count !== void 0 && /* @__PURE__ */ jsxs18("span", { className: "text-xs text-muted-foreground", children: [
|
|
1843
|
+
channel.member_count,
|
|
1844
|
+
" members"
|
|
1845
|
+
] })
|
|
1846
|
+
] });
|
|
1847
|
+
}
|
|
1848
|
+
function MessageCard({ message }) {
|
|
1849
|
+
return /* @__PURE__ */ jsxs18("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
1850
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2", children: [
|
|
1851
|
+
/* @__PURE__ */ jsx19(MessageSquare4, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
|
|
1852
|
+
message.author?.username && /* @__PURE__ */ jsx19("span", { className: "text-xs font-medium text-foreground", children: message.author.username }),
|
|
1853
|
+
message.timestamp && /* @__PURE__ */ jsx19("span", { className: "text-xs text-muted-foreground ml-auto", children: formatRelativeDate3(message.timestamp) })
|
|
1854
|
+
] }),
|
|
1855
|
+
message.content && /* @__PURE__ */ jsx19("p", { className: "text-sm text-foreground line-clamp-3", children: message.content })
|
|
1856
|
+
] });
|
|
1857
|
+
}
|
|
1858
|
+
function DiscordFormatter({ data }) {
|
|
1859
|
+
if (typeof data === "object" && data !== null && "guilds" in data) {
|
|
1860
|
+
const guilds = data.guilds;
|
|
1861
|
+
if (Array.isArray(guilds)) {
|
|
1862
|
+
return /* @__PURE__ */ jsx19("div", { className: "space-y-1.5", children: guilds.filter(isGuildData).map((g, i) => /* @__PURE__ */ jsx19(GuildCard, { guild: g }, g.id || i)) });
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
if (typeof data === "object" && data !== null && "channels" in data) {
|
|
1866
|
+
const channels = data.channels;
|
|
1867
|
+
if (Array.isArray(channels)) {
|
|
1868
|
+
return /* @__PURE__ */ jsx19("div", { className: "space-y-1.5", children: channels.filter(isChannelData).map((c, i) => /* @__PURE__ */ jsx19(ChannelCard2, { channel: c }, c.id || i)) });
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
if (typeof data === "object" && data !== null && "messages" in data) {
|
|
1872
|
+
const messages = data.messages;
|
|
1873
|
+
if (Array.isArray(messages)) {
|
|
1874
|
+
return /* @__PURE__ */ jsx19("div", { className: "space-y-2", children: messages.filter(isMessageData).map((m, i) => /* @__PURE__ */ jsx19(MessageCard, { message: m }, m.id || i)) });
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
if (isMessageData(data)) return /* @__PURE__ */ jsx19(MessageCard, { message: data });
|
|
1878
|
+
if (Array.isArray(data)) {
|
|
1879
|
+
const guilds = data.filter(isGuildData);
|
|
1880
|
+
if (guilds.length > 0) {
|
|
1881
|
+
return /* @__PURE__ */ jsx19("div", { className: "space-y-1.5", children: guilds.map((g, i) => /* @__PURE__ */ jsx19(GuildCard, { guild: g }, g.id || i)) });
|
|
1882
|
+
}
|
|
1883
|
+
const messages = data.filter(isMessageData);
|
|
1884
|
+
if (messages.length > 0) {
|
|
1885
|
+
return /* @__PURE__ */ jsx19("div", { className: "space-y-2", children: messages.map((m, i) => /* @__PURE__ */ jsx19(MessageCard, { message: m }, m.id || i)) });
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
return /* @__PURE__ */ jsx19("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
// src/ui/formatters/notion.tsx
|
|
1892
|
+
import { FileText as FileText4, Database, ExternalLink as ExternalLink6, Clock as Clock3 } from "lucide-react";
|
|
1893
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1894
|
+
function isNotionPage(data) {
|
|
1895
|
+
if (typeof data !== "object" || data === null) return false;
|
|
1896
|
+
return "properties" in data || "id" in data && "url" in data && String(data.url || "").includes("notion");
|
|
1897
|
+
}
|
|
1898
|
+
function isNotionDatabase(data) {
|
|
1899
|
+
if (typeof data !== "object" || data === null) return false;
|
|
1900
|
+
return "title" in data && Array.isArray(data.title) && "id" in data;
|
|
1901
|
+
}
|
|
1902
|
+
function extractPageTitle(page) {
|
|
1903
|
+
if (page.title) return page.title;
|
|
1904
|
+
if (page.properties) {
|
|
1905
|
+
for (const val of Object.values(page.properties)) {
|
|
1906
|
+
if (typeof val === "object" && val !== null && "title" in val) {
|
|
1907
|
+
const titles = val.title;
|
|
1908
|
+
if (Array.isArray(titles) && titles.length > 0) {
|
|
1909
|
+
return titles.map((t) => t.plain_text || t.text?.content || "").join("");
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
const name = page.properties.Name || page.properties.name;
|
|
1914
|
+
if (typeof name === "object" && name !== null && "title" in name) {
|
|
1915
|
+
const titles = name.title;
|
|
1916
|
+
if (Array.isArray(titles) && titles.length > 0) {
|
|
1917
|
+
return titles.map((t) => t.plain_text || "").join("");
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
return "Untitled";
|
|
1922
|
+
}
|
|
1923
|
+
function formatRelativeDate4(dateStr) {
|
|
1924
|
+
try {
|
|
1925
|
+
const date = new Date(dateStr);
|
|
1926
|
+
const now = /* @__PURE__ */ new Date();
|
|
1927
|
+
const diffMs = now.getTime() - date.getTime();
|
|
1928
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
1929
|
+
if (diffDays === 0) return "today";
|
|
1930
|
+
if (diffDays === 1) return "yesterday";
|
|
1931
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
1932
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
1933
|
+
} catch {
|
|
1934
|
+
return dateStr;
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
function PageCard({ page }) {
|
|
1938
|
+
const title = extractPageTitle(page);
|
|
1939
|
+
return /* @__PURE__ */ jsx20("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1", children: /* @__PURE__ */ jsxs19("div", { className: "flex items-start gap-2", children: [
|
|
1940
|
+
/* @__PURE__ */ jsx20(FileText4, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
1941
|
+
/* @__PURE__ */ jsx20("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx20("p", { className: "text-sm font-medium text-foreground truncate", children: page.url ? /* @__PURE__ */ jsx20("a", { href: page.url, target: "_blank", rel: "noopener noreferrer", className: "hover:underline", children: title }) : title }) }),
|
|
1942
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-1.5 shrink-0", children: [
|
|
1943
|
+
page.last_edited_time && /* @__PURE__ */ jsxs19("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
1944
|
+
/* @__PURE__ */ jsx20(Clock3, { className: "h-3 w-3" }),
|
|
1945
|
+
formatRelativeDate4(page.last_edited_time)
|
|
1946
|
+
] }),
|
|
1947
|
+
page.url && /* @__PURE__ */ jsx20("a", { href: page.url, target: "_blank", rel: "noopener noreferrer", className: "text-muted-foreground hover:text-foreground", children: /* @__PURE__ */ jsx20(ExternalLink6, { className: "h-3 w-3" }) })
|
|
1948
|
+
] })
|
|
1949
|
+
] }) });
|
|
1950
|
+
}
|
|
1951
|
+
function DatabaseCard({ db }) {
|
|
1952
|
+
const title = Array.isArray(db.title) && db.title.length > 0 ? db.title.map((t) => t.plain_text || "").join("") : "Untitled database";
|
|
1953
|
+
const desc = Array.isArray(db.description) && db.description.length > 0 ? db.description.map((d) => d.plain_text || "").join("") : null;
|
|
1954
|
+
return /* @__PURE__ */ jsx20("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1", children: /* @__PURE__ */ jsxs19("div", { className: "flex items-start gap-2", children: [
|
|
1955
|
+
/* @__PURE__ */ jsx20(Database, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
1956
|
+
/* @__PURE__ */ jsxs19("div", { className: "min-w-0 flex-1", children: [
|
|
1957
|
+
/* @__PURE__ */ jsx20("p", { className: "text-sm font-medium text-foreground truncate", children: db.url ? /* @__PURE__ */ jsx20("a", { href: db.url, target: "_blank", rel: "noopener noreferrer", className: "hover:underline", children: title }) : title }),
|
|
1958
|
+
desc && /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground line-clamp-2", children: desc })
|
|
1959
|
+
] })
|
|
1960
|
+
] }) });
|
|
1961
|
+
}
|
|
1962
|
+
function NotionFormatter({ data }) {
|
|
1963
|
+
if (typeof data === "object" && data !== null && "pages" in data) {
|
|
1964
|
+
const pages = data.pages;
|
|
1965
|
+
if (Array.isArray(pages)) {
|
|
1966
|
+
return /* @__PURE__ */ jsx20("div", { className: "space-y-1.5", children: pages.filter(isNotionPage).map((p, i) => /* @__PURE__ */ jsx20(PageCard, { page: p }, p.id || i)) });
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
if (typeof data === "object" && data !== null && "databases" in data) {
|
|
1970
|
+
const dbs = data.databases;
|
|
1971
|
+
if (Array.isArray(dbs)) {
|
|
1972
|
+
return /* @__PURE__ */ jsx20("div", { className: "space-y-1.5", children: dbs.filter(isNotionDatabase).map((d, i) => /* @__PURE__ */ jsx20(DatabaseCard, { db: d }, d.id || i)) });
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
if (typeof data === "object" && data !== null && "results" in data) {
|
|
1976
|
+
const results = data.results;
|
|
1977
|
+
if (Array.isArray(results)) {
|
|
1978
|
+
const pages = results.filter(isNotionPage);
|
|
1979
|
+
if (pages.length > 0) {
|
|
1980
|
+
return /* @__PURE__ */ jsx20("div", { className: "space-y-1.5", children: pages.map((p, i) => /* @__PURE__ */ jsx20(PageCard, { page: p }, p.id || i)) });
|
|
1981
|
+
}
|
|
1982
|
+
const dbs = results.filter(isNotionDatabase);
|
|
1983
|
+
if (dbs.length > 0) {
|
|
1984
|
+
return /* @__PURE__ */ jsx20("div", { className: "space-y-1.5", children: dbs.map((d, i) => /* @__PURE__ */ jsx20(DatabaseCard, { db: d }, d.id || i)) });
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
if (isNotionPage(data)) return /* @__PURE__ */ jsx20(PageCard, { page: data });
|
|
1989
|
+
if (isNotionDatabase(data)) return /* @__PURE__ */ jsx20(DatabaseCard, { db: data });
|
|
1990
|
+
if (Array.isArray(data)) {
|
|
1991
|
+
const pages = data.filter(isNotionPage);
|
|
1992
|
+
if (pages.length > 0) {
|
|
1993
|
+
return /* @__PURE__ */ jsx20("div", { className: "space-y-1.5", children: pages.map((p, i) => /* @__PURE__ */ jsx20(PageCard, { page: p }, p.id || i)) });
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
return /* @__PURE__ */ jsx20("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
// src/ui/formatters/twitter.tsx
|
|
2000
|
+
import { MessageCircle as MessageCircle2, Heart, Repeat2, Clock as Clock4 } from "lucide-react";
|
|
2001
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2002
|
+
function isTweetData(data) {
|
|
2003
|
+
return typeof data === "object" && data !== null && "text" in data;
|
|
2004
|
+
}
|
|
2005
|
+
function formatRelativeDate5(dateStr) {
|
|
2006
|
+
try {
|
|
2007
|
+
const date = new Date(dateStr);
|
|
2008
|
+
const now = /* @__PURE__ */ new Date();
|
|
2009
|
+
const diffMs = now.getTime() - date.getTime();
|
|
2010
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
2011
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
2012
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
2013
|
+
if (diffMins < 1) return "Just now";
|
|
2014
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
2015
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
2016
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
2017
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
2018
|
+
} catch {
|
|
2019
|
+
return dateStr;
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
function TweetCard({ tweet }) {
|
|
2023
|
+
const username = tweet.author_username || tweet.username || tweet.author?.username;
|
|
2024
|
+
const likes = tweet.public_metrics?.like_count ?? tweet.like_count;
|
|
2025
|
+
const retweets = tweet.public_metrics?.retweet_count ?? tweet.retweet_count;
|
|
2026
|
+
const replies = tweet.public_metrics?.reply_count;
|
|
2027
|
+
return /* @__PURE__ */ jsxs20("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
2028
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
|
|
2029
|
+
/* @__PURE__ */ jsx21(MessageCircle2, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
|
|
2030
|
+
username && /* @__PURE__ */ jsxs20("span", { className: "text-xs font-medium text-foreground", children: [
|
|
2031
|
+
"@",
|
|
2032
|
+
username
|
|
2033
|
+
] }),
|
|
2034
|
+
tweet.author?.name && /* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground", children: tweet.author.name }),
|
|
2035
|
+
tweet.created_at && /* @__PURE__ */ jsxs20("span", { className: "flex items-center gap-1 text-xs text-muted-foreground ml-auto", children: [
|
|
2036
|
+
/* @__PURE__ */ jsx21(Clock4, { className: "h-3 w-3" }),
|
|
2037
|
+
formatRelativeDate5(tweet.created_at)
|
|
2038
|
+
] })
|
|
2039
|
+
] }),
|
|
2040
|
+
tweet.text && /* @__PURE__ */ jsx21("p", { className: "text-sm text-foreground line-clamp-4", children: tweet.text }),
|
|
2041
|
+
(likes !== void 0 || retweets !== void 0 || replies !== void 0) && /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-4 pt-0.5", children: [
|
|
2042
|
+
likes !== void 0 && /* @__PURE__ */ jsxs20("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2043
|
+
/* @__PURE__ */ jsx21(Heart, { className: "h-3 w-3" }),
|
|
2044
|
+
likes
|
|
2045
|
+
] }),
|
|
2046
|
+
retweets !== void 0 && /* @__PURE__ */ jsxs20("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2047
|
+
/* @__PURE__ */ jsx21(Repeat2, { className: "h-3 w-3" }),
|
|
2048
|
+
retweets
|
|
2049
|
+
] }),
|
|
2050
|
+
replies !== void 0 && /* @__PURE__ */ jsxs20("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2051
|
+
/* @__PURE__ */ jsx21(MessageCircle2, { className: "h-3 w-3" }),
|
|
2052
|
+
replies
|
|
2053
|
+
] })
|
|
2054
|
+
] })
|
|
2055
|
+
] });
|
|
2056
|
+
}
|
|
2057
|
+
function TwitterFormatter({ data }) {
|
|
2058
|
+
if (typeof data === "object" && data !== null && "tweets" in data) {
|
|
2059
|
+
const tweets = data.tweets;
|
|
2060
|
+
if (Array.isArray(tweets)) {
|
|
2061
|
+
return /* @__PURE__ */ jsx21("div", { className: "space-y-2", children: tweets.filter(isTweetData).map((t, i) => /* @__PURE__ */ jsx21(TweetCard, { tweet: t }, t.id || i)) });
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
if (typeof data === "object" && data !== null && "data" in data && Array.isArray(data.data)) {
|
|
2065
|
+
const tweets = data.data;
|
|
2066
|
+
return /* @__PURE__ */ jsx21("div", { className: "space-y-2", children: tweets.filter(isTweetData).map((t, i) => /* @__PURE__ */ jsx21(TweetCard, { tweet: t }, t.id || i)) });
|
|
2067
|
+
}
|
|
2068
|
+
if (isTweetData(data)) return /* @__PURE__ */ jsx21(TweetCard, { tweet: data });
|
|
2069
|
+
if (Array.isArray(data)) {
|
|
2070
|
+
const tweets = data.filter(isTweetData);
|
|
2071
|
+
if (tweets.length > 0) {
|
|
2072
|
+
return /* @__PURE__ */ jsx21("div", { className: "space-y-2", children: tweets.map((t, i) => /* @__PURE__ */ jsx21(TweetCard, { tweet: t }, t.id || i)) });
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
return /* @__PURE__ */ jsx21("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
// src/ui/formatters/telegram.tsx
|
|
2079
|
+
import { MessageSquare as MessageSquare5, User, Clock as Clock5 } from "lucide-react";
|
|
2080
|
+
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2081
|
+
function isTelegramMessage(data) {
|
|
2082
|
+
return typeof data === "object" && data !== null && ("text" in data || "message_id" in data);
|
|
2083
|
+
}
|
|
2084
|
+
function formatUnixDate(ts) {
|
|
2085
|
+
try {
|
|
2086
|
+
const date = new Date(ts * 1e3);
|
|
2087
|
+
const now = /* @__PURE__ */ new Date();
|
|
2088
|
+
const diffMs = now.getTime() - date.getTime();
|
|
2089
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
2090
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
2091
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
2092
|
+
if (diffMins < 1) return "Just now";
|
|
2093
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
2094
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
2095
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
2096
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
2097
|
+
} catch {
|
|
2098
|
+
return String(ts);
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
function MessageCard2({ message }) {
|
|
2102
|
+
const fromName = message.from ? [message.from.first_name, message.from.last_name].filter(Boolean).join(" ") || message.from.username : void 0;
|
|
2103
|
+
return /* @__PURE__ */ jsxs21("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
2104
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2", children: [
|
|
2105
|
+
/* @__PURE__ */ jsx22(MessageSquare5, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
|
|
2106
|
+
fromName && /* @__PURE__ */ jsxs21("span", { className: "flex items-center gap-1 text-xs font-medium text-foreground", children: [
|
|
2107
|
+
/* @__PURE__ */ jsx22(User, { className: "h-3 w-3" }),
|
|
2108
|
+
fromName
|
|
2109
|
+
] }),
|
|
2110
|
+
message.chat?.title && /* @__PURE__ */ jsx22("span", { className: "text-xs text-muted-foreground", children: message.chat.title }),
|
|
2111
|
+
message.date && /* @__PURE__ */ jsxs21("span", { className: "flex items-center gap-1 text-xs text-muted-foreground ml-auto", children: [
|
|
2112
|
+
/* @__PURE__ */ jsx22(Clock5, { className: "h-3 w-3" }),
|
|
2113
|
+
formatUnixDate(message.date)
|
|
2114
|
+
] })
|
|
2115
|
+
] }),
|
|
2116
|
+
message.text && /* @__PURE__ */ jsx22("p", { className: "text-sm text-foreground line-clamp-3", children: message.text })
|
|
2117
|
+
] });
|
|
2118
|
+
}
|
|
2119
|
+
function TelegramFormatter({ data }) {
|
|
2120
|
+
if (typeof data === "object" && data !== null && "messages" in data) {
|
|
2121
|
+
const msgs = data.messages;
|
|
2122
|
+
if (Array.isArray(msgs)) {
|
|
2123
|
+
return /* @__PURE__ */ jsx22("div", { className: "space-y-2", children: msgs.filter(isTelegramMessage).map((m, i) => /* @__PURE__ */ jsx22(MessageCard2, { message: m }, m.message_id || i)) });
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
if (typeof data === "object" && data !== null && "result" in data) {
|
|
2127
|
+
const result = data.result;
|
|
2128
|
+
if (Array.isArray(result)) {
|
|
2129
|
+
const msgs = result.filter(isTelegramMessage);
|
|
2130
|
+
if (msgs.length > 0) {
|
|
2131
|
+
return /* @__PURE__ */ jsx22("div", { className: "space-y-2", children: msgs.map((m, i) => /* @__PURE__ */ jsx22(MessageCard2, { message: m }, m.message_id || i)) });
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
if (isTelegramMessage(data)) return /* @__PURE__ */ jsx22(MessageCard2, { message: data });
|
|
2136
|
+
if (Array.isArray(data)) {
|
|
2137
|
+
const msgs = data.filter(isTelegramMessage);
|
|
2138
|
+
if (msgs.length > 0) {
|
|
2139
|
+
return /* @__PURE__ */ jsx22("div", { className: "space-y-2", children: msgs.map((m, i) => /* @__PURE__ */ jsx22(MessageCard2, { message: m }, m.message_id || i)) });
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
return /* @__PURE__ */ jsx22("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
// src/ui/formatters/stripe.tsx
|
|
2146
|
+
import { CreditCard as CreditCard2, User as User2, FileText as FileText5, Clock as Clock6, RefreshCw } from "lucide-react";
|
|
2147
|
+
import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2148
|
+
function isCustomer(data) {
|
|
2149
|
+
return typeof data === "object" && data !== null && ("email" in data || "name" in data) && !("amount_due" in data) && !("plan" in data);
|
|
2150
|
+
}
|
|
2151
|
+
function isInvoice(data) {
|
|
2152
|
+
return typeof data === "object" && data !== null && ("number" in data || "amount_due" in data);
|
|
2153
|
+
}
|
|
2154
|
+
function isSubscription(data) {
|
|
2155
|
+
return typeof data === "object" && data !== null && "plan" in data && "status" in data;
|
|
2156
|
+
}
|
|
2157
|
+
function isBalance(data) {
|
|
2158
|
+
return typeof data === "object" && data !== null && ("available" in data || "pending" in data);
|
|
2159
|
+
}
|
|
2160
|
+
function formatAmount(amount, currency) {
|
|
2161
|
+
try {
|
|
2162
|
+
return new Intl.NumberFormat(void 0, { style: "currency", currency: currency.toUpperCase() }).format(amount / 100);
|
|
2163
|
+
} catch {
|
|
2164
|
+
return `${(amount / 100).toFixed(2)} ${currency.toUpperCase()}`;
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
function formatUnixDate2(ts) {
|
|
2168
|
+
try {
|
|
2169
|
+
return new Date(ts * 1e3).toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" });
|
|
2170
|
+
} catch {
|
|
2171
|
+
return String(ts);
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
var STATUS_STYLES = {
|
|
2175
|
+
paid: "bg-green-500/10 text-green-500",
|
|
2176
|
+
active: "bg-green-500/10 text-green-500",
|
|
2177
|
+
open: "bg-blue-500/10 text-blue-500",
|
|
2178
|
+
draft: "bg-muted text-muted-foreground",
|
|
2179
|
+
void: "bg-muted text-muted-foreground",
|
|
2180
|
+
uncollectible: "bg-destructive/10 text-destructive",
|
|
2181
|
+
past_due: "bg-destructive/10 text-destructive",
|
|
2182
|
+
canceled: "bg-destructive/10 text-destructive",
|
|
2183
|
+
trialing: "bg-yellow-500/10 text-yellow-600"
|
|
2184
|
+
};
|
|
2185
|
+
function StatusBadge({ status }) {
|
|
2186
|
+
return /* @__PURE__ */ jsx23("span", { className: `rounded-full px-2 py-0.5 text-xs ${STATUS_STYLES[status] || "bg-muted text-muted-foreground"}`, children: status });
|
|
2187
|
+
}
|
|
2188
|
+
function CustomerCard({ customer }) {
|
|
2189
|
+
return /* @__PURE__ */ jsx23("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1", children: /* @__PURE__ */ jsxs22("div", { className: "flex items-start gap-2", children: [
|
|
2190
|
+
/* @__PURE__ */ jsx23(User2, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2191
|
+
/* @__PURE__ */ jsxs22("div", { className: "min-w-0 flex-1", children: [
|
|
2192
|
+
/* @__PURE__ */ jsx23("p", { className: "text-sm font-medium text-foreground", children: customer.name || "Unnamed customer" }),
|
|
2193
|
+
customer.email && /* @__PURE__ */ jsx23("p", { className: "text-xs text-muted-foreground", children: customer.email })
|
|
2194
|
+
] })
|
|
2195
|
+
] }) });
|
|
2196
|
+
}
|
|
2197
|
+
function InvoiceCard({ invoice }) {
|
|
2198
|
+
return /* @__PURE__ */ jsx23("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1", children: /* @__PURE__ */ jsxs22("div", { className: "flex items-start gap-2", children: [
|
|
2199
|
+
/* @__PURE__ */ jsx23(FileText5, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2200
|
+
/* @__PURE__ */ jsxs22("div", { className: "min-w-0 flex-1", children: [
|
|
2201
|
+
/* @__PURE__ */ jsx23("p", { className: "text-sm font-medium text-foreground", children: invoice.number || invoice.id }),
|
|
2202
|
+
invoice.customer_name && /* @__PURE__ */ jsx23("p", { className: "text-xs text-muted-foreground", children: invoice.customer_name })
|
|
2203
|
+
] }),
|
|
2204
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-1.5 shrink-0", children: [
|
|
2205
|
+
invoice.amount_due !== void 0 && invoice.currency && /* @__PURE__ */ jsx23("span", { className: "text-sm font-medium text-foreground", children: formatAmount(invoice.amount_due, invoice.currency) }),
|
|
2206
|
+
invoice.status && /* @__PURE__ */ jsx23(StatusBadge, { status: invoice.status })
|
|
2207
|
+
] })
|
|
2208
|
+
] }) });
|
|
2209
|
+
}
|
|
2210
|
+
function SubscriptionCard({ sub }) {
|
|
2211
|
+
return /* @__PURE__ */ jsx23("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1", children: /* @__PURE__ */ jsxs22("div", { className: "flex items-start gap-2", children: [
|
|
2212
|
+
/* @__PURE__ */ jsx23(RefreshCw, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2213
|
+
/* @__PURE__ */ jsxs22("div", { className: "min-w-0 flex-1", children: [
|
|
2214
|
+
/* @__PURE__ */ jsxs22("p", { className: "text-sm font-medium text-foreground", children: [
|
|
2215
|
+
sub.plan?.nickname || "Subscription",
|
|
2216
|
+
sub.plan?.amount !== void 0 && sub.plan?.currency && /* @__PURE__ */ jsxs22("span", { className: "text-muted-foreground font-normal", children: [
|
|
2217
|
+
" ",
|
|
2218
|
+
formatAmount(sub.plan.amount, sub.plan.currency),
|
|
2219
|
+
"/",
|
|
2220
|
+
sub.plan.interval
|
|
2221
|
+
] })
|
|
2222
|
+
] }),
|
|
2223
|
+
sub.current_period_end && /* @__PURE__ */ jsxs22("p", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2224
|
+
/* @__PURE__ */ jsx23(Clock6, { className: "h-3 w-3" }),
|
|
2225
|
+
"Renews ",
|
|
2226
|
+
formatUnixDate2(sub.current_period_end)
|
|
2227
|
+
] })
|
|
2228
|
+
] }),
|
|
2229
|
+
sub.status && /* @__PURE__ */ jsx23(StatusBadge, { status: sub.status })
|
|
2230
|
+
] }) });
|
|
2231
|
+
}
|
|
2232
|
+
function BalanceDisplay({ balance }) {
|
|
2233
|
+
return /* @__PURE__ */ jsxs22("div", { className: "rounded-lg border border-border bg-card p-3 space-y-2", children: [
|
|
2234
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2", children: [
|
|
2235
|
+
/* @__PURE__ */ jsx23(CreditCard2, { className: "h-4 w-4 text-muted-foreground" }),
|
|
2236
|
+
/* @__PURE__ */ jsx23("span", { className: "text-sm font-medium text-foreground", children: "Balance" })
|
|
2237
|
+
] }),
|
|
2238
|
+
/* @__PURE__ */ jsxs22("div", { className: "grid grid-cols-2 gap-4 pl-6", children: [
|
|
2239
|
+
balance.available && balance.available.length > 0 && /* @__PURE__ */ jsxs22("div", { children: [
|
|
2240
|
+
/* @__PURE__ */ jsx23("p", { className: "text-xs text-muted-foreground", children: "Available" }),
|
|
2241
|
+
balance.available.map((b, i) => /* @__PURE__ */ jsx23("p", { className: "text-sm font-medium text-foreground", children: formatAmount(b.amount, b.currency) }, i))
|
|
2242
|
+
] }),
|
|
2243
|
+
balance.pending && balance.pending.length > 0 && /* @__PURE__ */ jsxs22("div", { children: [
|
|
2244
|
+
/* @__PURE__ */ jsx23("p", { className: "text-xs text-muted-foreground", children: "Pending" }),
|
|
2245
|
+
balance.pending.map((b, i) => /* @__PURE__ */ jsx23("p", { className: "text-sm font-medium text-foreground", children: formatAmount(b.amount, b.currency) }, i))
|
|
2246
|
+
] })
|
|
2247
|
+
] })
|
|
2248
|
+
] });
|
|
2249
|
+
}
|
|
2250
|
+
function StripeFormatter({ data }) {
|
|
2251
|
+
if (isBalance(data)) return /* @__PURE__ */ jsx23(BalanceDisplay, { balance: data });
|
|
2252
|
+
if (typeof data === "object" && data !== null && "data" in data && Array.isArray(data.data)) {
|
|
2253
|
+
const items = data.data;
|
|
2254
|
+
const invoices = items.filter(isInvoice);
|
|
2255
|
+
if (invoices.length > 0) {
|
|
2256
|
+
return /* @__PURE__ */ jsx23("div", { className: "space-y-1.5", children: invoices.map((inv, i) => /* @__PURE__ */ jsx23(InvoiceCard, { invoice: inv }, inv.id || i)) });
|
|
2257
|
+
}
|
|
2258
|
+
const subs = items.filter(isSubscription);
|
|
2259
|
+
if (subs.length > 0) {
|
|
2260
|
+
return /* @__PURE__ */ jsx23("div", { className: "space-y-1.5", children: subs.map((s, i) => /* @__PURE__ */ jsx23(SubscriptionCard, { sub: s }, s.id || i)) });
|
|
2261
|
+
}
|
|
2262
|
+
const customers = items.filter(isCustomer);
|
|
2263
|
+
if (customers.length > 0) {
|
|
2264
|
+
return /* @__PURE__ */ jsx23("div", { className: "space-y-1.5", children: customers.map((c, i) => /* @__PURE__ */ jsx23(CustomerCard, { customer: c }, c.id || i)) });
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
if (isInvoice(data)) return /* @__PURE__ */ jsx23(InvoiceCard, { invoice: data });
|
|
2268
|
+
if (isSubscription(data)) return /* @__PURE__ */ jsx23(SubscriptionCard, { sub: data });
|
|
2269
|
+
if (isCustomer(data)) return /* @__PURE__ */ jsx23(CustomerCard, { customer: data });
|
|
2270
|
+
if (Array.isArray(data)) {
|
|
2271
|
+
const invoices = data.filter(isInvoice);
|
|
2272
|
+
if (invoices.length > 0) {
|
|
2273
|
+
return /* @__PURE__ */ jsx23("div", { className: "space-y-1.5", children: invoices.map((inv, i) => /* @__PURE__ */ jsx23(InvoiceCard, { invoice: inv }, inv.id || i)) });
|
|
2274
|
+
}
|
|
2275
|
+
const customers = data.filter(isCustomer);
|
|
2276
|
+
if (customers.length > 0) {
|
|
2277
|
+
return /* @__PURE__ */ jsx23("div", { className: "space-y-1.5", children: customers.map((c, i) => /* @__PURE__ */ jsx23(CustomerCard, { customer: c }, c.id || i)) });
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
return /* @__PURE__ */ jsx23("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2283
|
+
// src/ui/formatters/jira.tsx
|
|
2284
|
+
import { CircleDot as CircleDot4, SquareKanban as SquareKanban2, User as User3, ArrowUp, ArrowDown, Minus } from "lucide-react";
|
|
2285
|
+
import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2286
|
+
function isJiraIssue(data) {
|
|
2287
|
+
return typeof data === "object" && data !== null && "key" in data && "fields" in data;
|
|
2288
|
+
}
|
|
2289
|
+
function isJiraProject(data) {
|
|
2290
|
+
return typeof data === "object" && data !== null && "key" in data && "name" in data && "projectTypeKey" in data;
|
|
2291
|
+
}
|
|
2292
|
+
var STATUS_COLORS = {
|
|
2293
|
+
blue: "bg-blue-500",
|
|
2294
|
+
green: "bg-green-500",
|
|
2295
|
+
yellow: "bg-yellow-500",
|
|
2296
|
+
"blue-gray": "bg-slate-400",
|
|
2297
|
+
undefined: "bg-muted-foreground"
|
|
2298
|
+
};
|
|
2299
|
+
function PriorityIcon({ name }) {
|
|
2300
|
+
const lower = (name || "").toLowerCase();
|
|
2301
|
+
if (lower === "highest" || lower === "critical") return /* @__PURE__ */ jsx24(ArrowUp, { className: "h-3 w-3 text-destructive" });
|
|
2302
|
+
if (lower === "high") return /* @__PURE__ */ jsx24(ArrowUp, { className: "h-3 w-3 text-orange-500" });
|
|
2303
|
+
if (lower === "low") return /* @__PURE__ */ jsx24(ArrowDown, { className: "h-3 w-3 text-blue-500" });
|
|
2304
|
+
if (lower === "lowest") return /* @__PURE__ */ jsx24(ArrowDown, { className: "h-3 w-3 text-green-500" });
|
|
2305
|
+
return /* @__PURE__ */ jsx24(Minus, { className: "h-3 w-3 text-muted-foreground" });
|
|
2306
|
+
}
|
|
2307
|
+
function IssueCard2({ issue }) {
|
|
2308
|
+
const f = issue.fields || {};
|
|
2309
|
+
const statusColor = f.status?.statusCategory?.colorName || "undefined";
|
|
2310
|
+
return /* @__PURE__ */ jsx24("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: /* @__PURE__ */ jsxs23("div", { className: "flex items-start gap-2", children: [
|
|
2311
|
+
/* @__PURE__ */ jsx24(CircleDot4, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2312
|
+
/* @__PURE__ */ jsxs23("div", { className: "min-w-0 flex-1", children: [
|
|
2313
|
+
/* @__PURE__ */ jsxs23("p", { className: "text-sm font-medium text-foreground", children: [
|
|
2314
|
+
/* @__PURE__ */ jsx24("span", { className: "text-muted-foreground font-normal", children: issue.key }),
|
|
2315
|
+
" ",
|
|
2316
|
+
f.summary
|
|
2317
|
+
] }),
|
|
2318
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2 mt-0.5 flex-wrap", children: [
|
|
2319
|
+
f.status?.name && /* @__PURE__ */ jsxs23("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2320
|
+
/* @__PURE__ */ jsx24("span", { className: `h-1.5 w-1.5 rounded-full ${STATUS_COLORS[statusColor] || STATUS_COLORS.undefined}` }),
|
|
2321
|
+
f.status.name
|
|
2322
|
+
] }),
|
|
2323
|
+
f.priority?.name && /* @__PURE__ */ jsxs23("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2324
|
+
/* @__PURE__ */ jsx24(PriorityIcon, { name: f.priority.name }),
|
|
2325
|
+
f.priority.name
|
|
2326
|
+
] }),
|
|
2327
|
+
f.issuetype?.name && /* @__PURE__ */ jsx24("span", { className: "text-xs text-muted-foreground", children: f.issuetype.name }),
|
|
2328
|
+
f.assignee && /* @__PURE__ */ jsxs23("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2329
|
+
/* @__PURE__ */ jsx24(User3, { className: "h-3 w-3" }),
|
|
2330
|
+
f.assignee.displayName || f.assignee.name
|
|
2331
|
+
] })
|
|
2332
|
+
] })
|
|
2333
|
+
] })
|
|
2334
|
+
] }) });
|
|
2335
|
+
}
|
|
2336
|
+
function ProjectCard2({ project }) {
|
|
2337
|
+
return /* @__PURE__ */ jsx24("div", { className: "rounded-lg border border-border bg-card p-3", children: /* @__PURE__ */ jsxs23("div", { className: "flex items-start gap-2", children: [
|
|
2338
|
+
/* @__PURE__ */ jsx24(SquareKanban2, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2339
|
+
/* @__PURE__ */ jsxs23("div", { className: "min-w-0 flex-1", children: [
|
|
2340
|
+
/* @__PURE__ */ jsxs23("p", { className: "text-sm font-medium text-foreground", children: [
|
|
2341
|
+
/* @__PURE__ */ jsx24("span", { className: "text-muted-foreground font-normal", children: project.key }),
|
|
2342
|
+
" ",
|
|
2343
|
+
project.name
|
|
2344
|
+
] }),
|
|
2345
|
+
project.projectTypeKey && /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: project.projectTypeKey })
|
|
2346
|
+
] })
|
|
2347
|
+
] }) });
|
|
2348
|
+
}
|
|
2349
|
+
function JiraFormatter({ data }) {
|
|
2350
|
+
if (typeof data === "object" && data !== null && "issues" in data) {
|
|
2351
|
+
const issues = data.issues;
|
|
2352
|
+
if (Array.isArray(issues)) {
|
|
2353
|
+
return /* @__PURE__ */ jsx24("div", { className: "space-y-1.5", children: issues.filter(isJiraIssue).map((iss, i) => /* @__PURE__ */ jsx24(IssueCard2, { issue: iss }, iss.key || i)) });
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
if (typeof data === "object" && data !== null && "projects" in data) {
|
|
2357
|
+
const projects = data.projects;
|
|
2358
|
+
if (Array.isArray(projects)) {
|
|
2359
|
+
return /* @__PURE__ */ jsx24("div", { className: "space-y-1.5", children: projects.filter(isJiraProject).map((p, i) => /* @__PURE__ */ jsx24(ProjectCard2, { project: p }, p.key || i)) });
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
if (isJiraIssue(data)) return /* @__PURE__ */ jsx24(IssueCard2, { issue: data });
|
|
2363
|
+
if (isJiraProject(data)) return /* @__PURE__ */ jsx24(ProjectCard2, { project: data });
|
|
2364
|
+
if (Array.isArray(data)) {
|
|
2365
|
+
const issues = data.filter(isJiraIssue);
|
|
2366
|
+
if (issues.length > 0) {
|
|
2367
|
+
return /* @__PURE__ */ jsx24("div", { className: "space-y-1.5", children: issues.map((iss, i) => /* @__PURE__ */ jsx24(IssueCard2, { issue: iss }, iss.key || i)) });
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
return /* @__PURE__ */ jsx24("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
// src/ui/formatters/salesforce.tsx
|
|
2374
|
+
import { User as User4, Briefcase as Briefcase3, Mail as Mail5, Phone as Phone3, Building2 as Building22, Calendar as Calendar4 } from "lucide-react";
|
|
2375
|
+
import { jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2376
|
+
function isContact(data) {
|
|
2377
|
+
if (typeof data !== "object" || data === null) return false;
|
|
2378
|
+
return "Name" in data && ("Email" in data || "Phone" in data || "Title" in data);
|
|
2379
|
+
}
|
|
2380
|
+
function isOpportunity(data) {
|
|
2381
|
+
if (typeof data !== "object" || data === null) return false;
|
|
2382
|
+
return "Name" in data && ("StageName" in data || "Amount" in data || "CloseDate" in data);
|
|
2383
|
+
}
|
|
2384
|
+
function ContactCard2({ contact }) {
|
|
2385
|
+
const account = contact.AccountName || contact.Account?.Name;
|
|
2386
|
+
return /* @__PURE__ */ jsxs24("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
2387
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex items-start gap-2", children: [
|
|
2388
|
+
/* @__PURE__ */ jsx25(User4, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2389
|
+
/* @__PURE__ */ jsxs24("div", { className: "min-w-0 flex-1", children: [
|
|
2390
|
+
/* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-foreground", children: contact.Name }),
|
|
2391
|
+
contact.Title && /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted-foreground", children: contact.Title })
|
|
2392
|
+
] })
|
|
2393
|
+
] }),
|
|
2394
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex flex-wrap gap-x-4 gap-y-1 pl-6", children: [
|
|
2395
|
+
contact.Email && /* @__PURE__ */ jsxs24("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2396
|
+
/* @__PURE__ */ jsx25(Mail5, { className: "h-3 w-3" }),
|
|
2397
|
+
contact.Email
|
|
2398
|
+
] }),
|
|
2399
|
+
contact.Phone && /* @__PURE__ */ jsxs24("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2400
|
+
/* @__PURE__ */ jsx25(Phone3, { className: "h-3 w-3" }),
|
|
2401
|
+
contact.Phone
|
|
2402
|
+
] }),
|
|
2403
|
+
account && /* @__PURE__ */ jsxs24("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2404
|
+
/* @__PURE__ */ jsx25(Building22, { className: "h-3 w-3" }),
|
|
2405
|
+
account
|
|
2406
|
+
] })
|
|
2407
|
+
] })
|
|
2408
|
+
] });
|
|
2409
|
+
}
|
|
2410
|
+
function OpportunityCard({ opp }) {
|
|
2411
|
+
return /* @__PURE__ */ jsxs24("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
2412
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex items-start gap-2", children: [
|
|
2413
|
+
/* @__PURE__ */ jsx25(Briefcase3, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2414
|
+
/* @__PURE__ */ jsxs24("div", { className: "min-w-0 flex-1", children: [
|
|
2415
|
+
/* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-foreground", children: opp.Name }),
|
|
2416
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-2 mt-0.5 flex-wrap", children: [
|
|
2417
|
+
opp.Amount !== void 0 && /* @__PURE__ */ jsx25("span", { className: "text-xs font-medium text-foreground", children: new Intl.NumberFormat(void 0, { style: "currency", currency: "USD" }).format(opp.Amount) }),
|
|
2418
|
+
opp.StageName && /* @__PURE__ */ jsx25("span", { className: "rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground", children: opp.StageName }),
|
|
2419
|
+
opp.CloseDate && /* @__PURE__ */ jsxs24("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2420
|
+
/* @__PURE__ */ jsx25(Calendar4, { className: "h-3 w-3" }),
|
|
2421
|
+
opp.CloseDate
|
|
2422
|
+
] })
|
|
2423
|
+
] })
|
|
2424
|
+
] })
|
|
2425
|
+
] }),
|
|
2426
|
+
opp.Probability !== void 0 && /* @__PURE__ */ jsxs24("div", { className: "pl-6 space-y-0.5", children: [
|
|
2427
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex items-center justify-between", children: [
|
|
2428
|
+
/* @__PURE__ */ jsx25("span", { className: "text-xs text-muted-foreground", children: "Probability" }),
|
|
2429
|
+
/* @__PURE__ */ jsxs24("span", { className: "text-xs font-medium text-foreground", children: [
|
|
2430
|
+
opp.Probability,
|
|
2431
|
+
"%"
|
|
2432
|
+
] })
|
|
2433
|
+
] }),
|
|
2434
|
+
/* @__PURE__ */ jsx25("div", { className: "h-1.5 rounded-full bg-muted overflow-hidden", children: /* @__PURE__ */ jsx25(
|
|
2435
|
+
"div",
|
|
2436
|
+
{
|
|
2437
|
+
className: "h-full rounded-full bg-primary transition-all",
|
|
2438
|
+
style: { width: `${Math.min(100, opp.Probability)}%` }
|
|
2439
|
+
}
|
|
2440
|
+
) })
|
|
2441
|
+
] })
|
|
2442
|
+
] });
|
|
2443
|
+
}
|
|
2444
|
+
function SalesforceFormatter({ data }) {
|
|
2445
|
+
if (typeof data === "object" && data !== null && "records" in data) {
|
|
2446
|
+
const records = data.records;
|
|
2447
|
+
if (Array.isArray(records)) {
|
|
2448
|
+
const contacts = records.filter(isContact);
|
|
2449
|
+
const opps = records.filter(isOpportunity);
|
|
2450
|
+
if (opps.length > 0 && contacts.length === 0) {
|
|
2451
|
+
return /* @__PURE__ */ jsx25("div", { className: "space-y-1.5", children: opps.map((o, i) => /* @__PURE__ */ jsx25(OpportunityCard, { opp: o }, o.Id || i)) });
|
|
2452
|
+
}
|
|
2453
|
+
if (contacts.length > 0) {
|
|
2454
|
+
return /* @__PURE__ */ jsx25("div", { className: "space-y-1.5", children: contacts.map((c, i) => /* @__PURE__ */ jsx25(ContactCard2, { contact: c }, c.Id || i)) });
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
if (isOpportunity(data)) return /* @__PURE__ */ jsx25(OpportunityCard, { opp: data });
|
|
2459
|
+
if (isContact(data)) return /* @__PURE__ */ jsx25(ContactCard2, { contact: data });
|
|
2460
|
+
if (Array.isArray(data)) {
|
|
2461
|
+
const contacts = data.filter(isContact);
|
|
2462
|
+
if (contacts.length > 0) {
|
|
2463
|
+
return /* @__PURE__ */ jsx25("div", { className: "space-y-1.5", children: contacts.map((c, i) => /* @__PURE__ */ jsx25(ContactCard2, { contact: c }, c.Id || i)) });
|
|
2464
|
+
}
|
|
2465
|
+
const opps = data.filter(isOpportunity);
|
|
2466
|
+
if (opps.length > 0) {
|
|
2467
|
+
return /* @__PURE__ */ jsx25("div", { className: "space-y-1.5", children: opps.map((o, i) => /* @__PURE__ */ jsx25(OpportunityCard, { opp: o }, o.Id || i)) });
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
return /* @__PURE__ */ jsx25("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
// src/ui/formatters/brevo.tsx
|
|
2474
|
+
import { User as User5, Mail as Mail6, BarChart3 } from "lucide-react";
|
|
2475
|
+
import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2476
|
+
function isBrevoContact(data) {
|
|
2477
|
+
return typeof data === "object" && data !== null && "email" in data && ("attributes" in data || "id" in data);
|
|
2478
|
+
}
|
|
2479
|
+
function isBrevoCampaign(data) {
|
|
2480
|
+
return typeof data === "object" && data !== null && "name" in data && ("subject" in data || "status" in data);
|
|
2481
|
+
}
|
|
2482
|
+
var STATUS_STYLES2 = {
|
|
2483
|
+
sent: "bg-green-500/10 text-green-500",
|
|
2484
|
+
draft: "bg-muted text-muted-foreground",
|
|
2485
|
+
queued: "bg-blue-500/10 text-blue-500",
|
|
2486
|
+
suspended: "bg-yellow-500/10 text-yellow-600",
|
|
2487
|
+
archive: "bg-muted text-muted-foreground"
|
|
2488
|
+
};
|
|
2489
|
+
function ContactCard3({ contact }) {
|
|
2490
|
+
const name = contact.attributes ? [contact.attributes.FIRSTNAME, contact.attributes.LASTNAME].filter(Boolean).join(" ") : void 0;
|
|
2491
|
+
return /* @__PURE__ */ jsx26("div", { className: "rounded-lg border border-border bg-card p-3", children: /* @__PURE__ */ jsxs25("div", { className: "flex items-start gap-2", children: [
|
|
2492
|
+
/* @__PURE__ */ jsx26(User5, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2493
|
+
/* @__PURE__ */ jsxs25("div", { className: "min-w-0 flex-1", children: [
|
|
2494
|
+
name && /* @__PURE__ */ jsx26("p", { className: "text-sm font-medium text-foreground", children: name }),
|
|
2495
|
+
/* @__PURE__ */ jsxs25("p", { className: "text-xs text-muted-foreground flex items-center gap-1", children: [
|
|
2496
|
+
/* @__PURE__ */ jsx26(Mail6, { className: "h-3 w-3" }),
|
|
2497
|
+
contact.email
|
|
2498
|
+
] })
|
|
2499
|
+
] })
|
|
2500
|
+
] }) });
|
|
2501
|
+
}
|
|
2502
|
+
function CampaignCard({ campaign }) {
|
|
2503
|
+
const stats = campaign.statistics?.globalStats;
|
|
2504
|
+
return /* @__PURE__ */ jsxs25("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
2505
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex items-start gap-2", children: [
|
|
2506
|
+
/* @__PURE__ */ jsx26(Mail6, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2507
|
+
/* @__PURE__ */ jsxs25("div", { className: "min-w-0 flex-1", children: [
|
|
2508
|
+
/* @__PURE__ */ jsx26("p", { className: "text-sm font-medium text-foreground", children: campaign.name }),
|
|
2509
|
+
campaign.subject && /* @__PURE__ */ jsx26("p", { className: "text-xs text-muted-foreground", children: campaign.subject })
|
|
2510
|
+
] }),
|
|
2511
|
+
campaign.status && /* @__PURE__ */ jsx26("span", { className: `rounded-full px-2 py-0.5 text-xs ${STATUS_STYLES2[campaign.status] || "bg-muted text-muted-foreground"}`, children: campaign.status })
|
|
2512
|
+
] }),
|
|
2513
|
+
stats && /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-4 pl-6", children: [
|
|
2514
|
+
/* @__PURE__ */ jsxs25("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2515
|
+
/* @__PURE__ */ jsx26(BarChart3, { className: "h-3 w-3" }),
|
|
2516
|
+
stats.sent ?? 0,
|
|
2517
|
+
" sent"
|
|
2518
|
+
] }),
|
|
2519
|
+
stats.opened !== void 0 && /* @__PURE__ */ jsxs25("span", { className: "text-xs text-muted-foreground", children: [
|
|
2520
|
+
stats.opened,
|
|
2521
|
+
" opened"
|
|
2522
|
+
] }),
|
|
2523
|
+
stats.clicked !== void 0 && /* @__PURE__ */ jsxs25("span", { className: "text-xs text-muted-foreground", children: [
|
|
2524
|
+
stats.clicked,
|
|
2525
|
+
" clicked"
|
|
2526
|
+
] })
|
|
2527
|
+
] })
|
|
2528
|
+
] });
|
|
2529
|
+
}
|
|
2530
|
+
function BrevoFormatter({ data }) {
|
|
2531
|
+
if (typeof data === "object" && data !== null && "contacts" in data) {
|
|
2532
|
+
const contacts = data.contacts;
|
|
2533
|
+
if (Array.isArray(contacts)) {
|
|
2534
|
+
return /* @__PURE__ */ jsx26("div", { className: "space-y-1.5", children: contacts.filter(isBrevoContact).map((c, i) => /* @__PURE__ */ jsx26(ContactCard3, { contact: c }, c.id || i)) });
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
if (typeof data === "object" && data !== null && "campaigns" in data) {
|
|
2538
|
+
const campaigns = data.campaigns;
|
|
2539
|
+
if (Array.isArray(campaigns)) {
|
|
2540
|
+
return /* @__PURE__ */ jsx26("div", { className: "space-y-1.5", children: campaigns.filter(isBrevoCampaign).map((c, i) => /* @__PURE__ */ jsx26(CampaignCard, { campaign: c }, c.id || i)) });
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
if (isBrevoContact(data)) return /* @__PURE__ */ jsx26(ContactCard3, { contact: data });
|
|
2544
|
+
if (isBrevoCampaign(data)) return /* @__PURE__ */ jsx26(CampaignCard, { campaign: data });
|
|
2545
|
+
if (Array.isArray(data)) {
|
|
2546
|
+
const contacts = data.filter(isBrevoContact);
|
|
2547
|
+
if (contacts.length > 0) {
|
|
2548
|
+
return /* @__PURE__ */ jsx26("div", { className: "space-y-1.5", children: contacts.map((c, i) => /* @__PURE__ */ jsx26(ContactCard3, { contact: c }, c.id || i)) });
|
|
2549
|
+
}
|
|
2550
|
+
const campaigns = data.filter(isBrevoCampaign);
|
|
2551
|
+
if (campaigns.length > 0) {
|
|
2552
|
+
return /* @__PURE__ */ jsx26("div", { className: "space-y-1.5", children: campaigns.map((c, i) => /* @__PURE__ */ jsx26(CampaignCard, { campaign: c }, c.id || i)) });
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
return /* @__PURE__ */ jsx26("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
// src/ui/formatters/calendly.tsx
|
|
2559
|
+
import { Calendar as Calendar5, Clock as Clock7, MapPin as MapPin2 } from "lucide-react";
|
|
2560
|
+
import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2561
|
+
function isCalendlyEvent(data) {
|
|
2562
|
+
return typeof data === "object" && data !== null && "name" in data && ("start_time" in data || "status" in data);
|
|
2563
|
+
}
|
|
2564
|
+
function isCalendlyEventType(data) {
|
|
2565
|
+
return typeof data === "object" && data !== null && "name" in data && ("duration" in data || "slug" in data || "active" in data);
|
|
2566
|
+
}
|
|
2567
|
+
function formatDateTime(dateStr) {
|
|
2568
|
+
try {
|
|
2569
|
+
return new Date(dateStr).toLocaleString(void 0, {
|
|
2570
|
+
month: "short",
|
|
2571
|
+
day: "numeric",
|
|
2572
|
+
hour: "numeric",
|
|
2573
|
+
minute: "2-digit"
|
|
2574
|
+
});
|
|
2575
|
+
} catch {
|
|
2576
|
+
return dateStr;
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
var STATUS_STYLES3 = {
|
|
2580
|
+
active: "bg-green-500/10 text-green-500",
|
|
2581
|
+
canceled: "bg-destructive/10 text-destructive"
|
|
2582
|
+
};
|
|
2583
|
+
function EventCard3({ event }) {
|
|
2584
|
+
return /* @__PURE__ */ jsx27("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1", children: /* @__PURE__ */ jsxs26("div", { className: "flex items-start gap-2", children: [
|
|
2585
|
+
/* @__PURE__ */ jsx27(Calendar5, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2586
|
+
/* @__PURE__ */ jsxs26("div", { className: "min-w-0 flex-1", children: [
|
|
2587
|
+
/* @__PURE__ */ jsx27("p", { className: "text-sm font-medium text-foreground", children: event.name }),
|
|
2588
|
+
event.start_time && /* @__PURE__ */ jsxs26("p", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2589
|
+
/* @__PURE__ */ jsx27(Clock7, { className: "h-3 w-3" }),
|
|
2590
|
+
formatDateTime(event.start_time),
|
|
2591
|
+
event.end_time && ` - ${formatDateTime(event.end_time)}`
|
|
2592
|
+
] }),
|
|
2593
|
+
event.location?.location && /* @__PURE__ */ jsxs26("p", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2594
|
+
/* @__PURE__ */ jsx27(MapPin2, { className: "h-3 w-3" }),
|
|
2595
|
+
event.location.location
|
|
2596
|
+
] })
|
|
2597
|
+
] }),
|
|
2598
|
+
event.status && /* @__PURE__ */ jsx27("span", { className: `rounded-full px-2 py-0.5 text-xs ${STATUS_STYLES3[event.status] || "bg-muted text-muted-foreground"}`, children: event.status })
|
|
2599
|
+
] }) });
|
|
2600
|
+
}
|
|
2601
|
+
function EventTypeCard({ eventType }) {
|
|
2602
|
+
return /* @__PURE__ */ jsx27("div", { className: "rounded-lg border border-border bg-card p-3", children: /* @__PURE__ */ jsxs26("div", { className: "flex items-start gap-2", children: [
|
|
2603
|
+
/* @__PURE__ */ jsx27(Calendar5, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2604
|
+
/* @__PURE__ */ jsxs26("div", { className: "min-w-0 flex-1", children: [
|
|
2605
|
+
/* @__PURE__ */ jsx27("p", { className: "text-sm font-medium text-foreground", children: eventType.name }),
|
|
2606
|
+
eventType.description_plain && /* @__PURE__ */ jsx27("p", { className: "text-xs text-muted-foreground line-clamp-2", children: eventType.description_plain }),
|
|
2607
|
+
eventType.duration !== void 0 && /* @__PURE__ */ jsxs26("p", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2608
|
+
/* @__PURE__ */ jsx27(Clock7, { className: "h-3 w-3" }),
|
|
2609
|
+
eventType.duration,
|
|
2610
|
+
" min"
|
|
2611
|
+
] })
|
|
2612
|
+
] }),
|
|
2613
|
+
eventType.active !== void 0 && /* @__PURE__ */ jsx27("span", { className: `rounded-full px-2 py-0.5 text-xs ${eventType.active ? "bg-green-500/10 text-green-500" : "bg-muted text-muted-foreground"}`, children: eventType.active ? "Active" : "Inactive" })
|
|
2614
|
+
] }) });
|
|
2615
|
+
}
|
|
2616
|
+
function CalendlyFormatter({ data }) {
|
|
2617
|
+
if (typeof data === "object" && data !== null) {
|
|
2618
|
+
const d = data;
|
|
2619
|
+
if (Array.isArray(d.collection)) {
|
|
2620
|
+
const events = d.collection.filter(isCalendlyEvent);
|
|
2621
|
+
const types = d.collection.filter(isCalendlyEventType);
|
|
2622
|
+
if (types.length > 0 && events.length === 0) {
|
|
2623
|
+
return /* @__PURE__ */ jsx27("div", { className: "space-y-1.5", children: types.map((t, i) => /* @__PURE__ */ jsx27(EventTypeCard, { eventType: t }, t.uri || i)) });
|
|
2624
|
+
}
|
|
2625
|
+
if (events.length > 0) {
|
|
2626
|
+
return /* @__PURE__ */ jsx27("div", { className: "space-y-1.5", children: events.map((e, i) => /* @__PURE__ */ jsx27(EventCard3, { event: e }, e.uri || i)) });
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
if (Array.isArray(d.scheduled_events)) {
|
|
2630
|
+
return /* @__PURE__ */ jsx27("div", { className: "space-y-1.5", children: d.scheduled_events.filter(isCalendlyEvent).map((e, i) => /* @__PURE__ */ jsx27(EventCard3, { event: e }, e.uri || i)) });
|
|
2631
|
+
}
|
|
2632
|
+
if (Array.isArray(d.event_types)) {
|
|
2633
|
+
return /* @__PURE__ */ jsx27("div", { className: "space-y-1.5", children: d.event_types.filter(isCalendlyEventType).map((t, i) => /* @__PURE__ */ jsx27(EventTypeCard, { eventType: t }, t.uri || i)) });
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
if (isCalendlyEvent(data)) return /* @__PURE__ */ jsx27(EventCard3, { event: data });
|
|
2637
|
+
if (isCalendlyEventType(data)) return /* @__PURE__ */ jsx27(EventTypeCard, { eventType: data });
|
|
2638
|
+
if (Array.isArray(data)) {
|
|
2639
|
+
const events = data.filter(isCalendlyEvent);
|
|
2640
|
+
if (events.length > 0) {
|
|
2641
|
+
return /* @__PURE__ */ jsx27("div", { className: "space-y-1.5", children: events.map((e, i) => /* @__PURE__ */ jsx27(EventCard3, { event: e }, e.uri || i)) });
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
return /* @__PURE__ */ jsx27("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
// src/ui/formatters/twilio.tsx
|
|
2648
|
+
import { Phone as Phone4, ArrowUpRight, ArrowDownLeft, Clock as Clock8 } from "lucide-react";
|
|
2649
|
+
import { jsx as jsx28, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2650
|
+
function isTwilioMessage(data) {
|
|
2651
|
+
return typeof data === "object" && data !== null && ("body" in data || "sid" in data) && ("from" in data || "to" in data);
|
|
2652
|
+
}
|
|
2653
|
+
function formatRelativeDate6(dateStr) {
|
|
2654
|
+
try {
|
|
2655
|
+
const date = new Date(dateStr);
|
|
2656
|
+
const now = /* @__PURE__ */ new Date();
|
|
2657
|
+
const diffMs = now.getTime() - date.getTime();
|
|
2658
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
2659
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
2660
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
2661
|
+
if (diffMins < 1) return "Just now";
|
|
2662
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
2663
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
2664
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
2665
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
2666
|
+
} catch {
|
|
2667
|
+
return dateStr;
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
var STATUS_STYLES4 = {
|
|
2671
|
+
delivered: "bg-green-500/10 text-green-500",
|
|
2672
|
+
sent: "bg-green-500/10 text-green-500",
|
|
2673
|
+
received: "bg-blue-500/10 text-blue-500",
|
|
2674
|
+
failed: "bg-destructive/10 text-destructive",
|
|
2675
|
+
undelivered: "bg-destructive/10 text-destructive",
|
|
2676
|
+
queued: "bg-yellow-500/10 text-yellow-600",
|
|
2677
|
+
sending: "bg-blue-500/10 text-blue-500"
|
|
2678
|
+
};
|
|
2679
|
+
function MessageCard3({ message }) {
|
|
2680
|
+
const isInbound = message.direction?.includes("inbound");
|
|
2681
|
+
const DirectionIcon = isInbound ? ArrowDownLeft : ArrowUpRight;
|
|
2682
|
+
const dateStr = message.date_sent || message.date_created;
|
|
2683
|
+
return /* @__PURE__ */ jsxs27("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
2684
|
+
/* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2", children: [
|
|
2685
|
+
/* @__PURE__ */ jsx28(Phone4, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
|
|
2686
|
+
/* @__PURE__ */ jsx28(DirectionIcon, { className: "h-3 w-3 text-muted-foreground shrink-0" }),
|
|
2687
|
+
/* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-1.5 flex-1 min-w-0", children: [
|
|
2688
|
+
message.from && /* @__PURE__ */ jsx28("span", { className: "text-xs text-muted-foreground", children: message.from }),
|
|
2689
|
+
/* @__PURE__ */ jsx28("span", { className: "text-xs text-muted-foreground", children: "\u2192" }),
|
|
2690
|
+
message.to && /* @__PURE__ */ jsx28("span", { className: "text-xs text-muted-foreground", children: message.to })
|
|
2691
|
+
] }),
|
|
2692
|
+
/* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-1.5 shrink-0", children: [
|
|
2693
|
+
message.status && /* @__PURE__ */ jsx28("span", { className: `rounded-full px-2 py-0.5 text-xs ${STATUS_STYLES4[message.status] || "bg-muted text-muted-foreground"}`, children: message.status }),
|
|
2694
|
+
dateStr && /* @__PURE__ */ jsxs27("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2695
|
+
/* @__PURE__ */ jsx28(Clock8, { className: "h-3 w-3" }),
|
|
2696
|
+
formatRelativeDate6(dateStr)
|
|
2697
|
+
] })
|
|
2698
|
+
] })
|
|
2699
|
+
] }),
|
|
2700
|
+
message.body && /* @__PURE__ */ jsx28("p", { className: "text-sm text-foreground line-clamp-3", children: message.body })
|
|
2701
|
+
] });
|
|
2702
|
+
}
|
|
2703
|
+
function TwilioFormatter({ data }) {
|
|
2704
|
+
if (typeof data === "object" && data !== null && "messages" in data) {
|
|
2705
|
+
const msgs = data.messages;
|
|
2706
|
+
if (Array.isArray(msgs)) {
|
|
2707
|
+
return /* @__PURE__ */ jsx28("div", { className: "space-y-1.5", children: msgs.filter(isTwilioMessage).map((m, i) => /* @__PURE__ */ jsx28(MessageCard3, { message: m }, m.sid || i)) });
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
if (isTwilioMessage(data)) return /* @__PURE__ */ jsx28(MessageCard3, { message: data });
|
|
2711
|
+
if (Array.isArray(data)) {
|
|
2712
|
+
const msgs = data.filter(isTwilioMessage);
|
|
2713
|
+
if (msgs.length > 0) {
|
|
2714
|
+
return /* @__PURE__ */ jsx28("div", { className: "space-y-1.5", children: msgs.map((m, i) => /* @__PURE__ */ jsx28(MessageCard3, { message: m }, m.sid || i)) });
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
return /* @__PURE__ */ jsx28("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
2718
|
+
}
|
|
2719
|
+
|
|
2720
|
+
// src/ui/formatters/linkedin.tsx
|
|
2721
|
+
import { User as User6, FileText as FileText6, ExternalLink as ExternalLink7, Clock as Clock9 } from "lucide-react";
|
|
2722
|
+
import { jsx as jsx29, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2723
|
+
function isProfile(data) {
|
|
2724
|
+
if (typeof data !== "object" || data === null) return false;
|
|
2725
|
+
return "localizedFirstName" in data || "firstName" in data || "name" in data && "headline" in data;
|
|
2726
|
+
}
|
|
2727
|
+
function isPost(data) {
|
|
2728
|
+
if (typeof data !== "object" || data === null) return false;
|
|
2729
|
+
return ("text" in data || "commentary" in data) && !("localizedFirstName" in data);
|
|
2730
|
+
}
|
|
2731
|
+
function formatRelativeDate7(dateStr) {
|
|
2732
|
+
try {
|
|
2733
|
+
const date = typeof dateStr === "number" ? new Date(dateStr) : new Date(dateStr);
|
|
2734
|
+
const now = /* @__PURE__ */ new Date();
|
|
2735
|
+
const diffMs = now.getTime() - date.getTime();
|
|
2736
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
2737
|
+
if (diffDays === 0) return "today";
|
|
2738
|
+
if (diffDays === 1) return "yesterday";
|
|
2739
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
2740
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
2741
|
+
} catch {
|
|
2742
|
+
return String(dateStr);
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
function ProfileCard({ profile }) {
|
|
2746
|
+
const name = profile.name || [profile.localizedFirstName || profile.firstName, profile.localizedLastName || profile.lastName].filter(Boolean).join(" ");
|
|
2747
|
+
return /* @__PURE__ */ jsx29("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1", children: /* @__PURE__ */ jsxs28("div", { className: "flex items-start gap-2", children: [
|
|
2748
|
+
/* @__PURE__ */ jsx29(User6, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2749
|
+
/* @__PURE__ */ jsxs28("div", { className: "min-w-0 flex-1", children: [
|
|
2750
|
+
/* @__PURE__ */ jsx29("p", { className: "text-sm font-medium text-foreground", children: name || "LinkedIn Profile" }),
|
|
2751
|
+
profile.headline && /* @__PURE__ */ jsx29("p", { className: "text-xs text-muted-foreground line-clamp-2", children: profile.headline }),
|
|
2752
|
+
profile.vanityName && /* @__PURE__ */ jsxs28("p", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2753
|
+
/* @__PURE__ */ jsx29(ExternalLink7, { className: "h-3 w-3" }),
|
|
2754
|
+
"linkedin.com/in/",
|
|
2755
|
+
profile.vanityName
|
|
2756
|
+
] })
|
|
2757
|
+
] })
|
|
2758
|
+
] }) });
|
|
2759
|
+
}
|
|
2760
|
+
function PostCard({ post }) {
|
|
2761
|
+
const content = post.text || post.commentary;
|
|
2762
|
+
const time = post.created?.time || post.timestamp;
|
|
2763
|
+
return /* @__PURE__ */ jsxs28("div", { className: "rounded-lg border border-border bg-card p-3 space-y-1.5", children: [
|
|
2764
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2", children: [
|
|
2765
|
+
/* @__PURE__ */ jsx29(FileText6, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
|
|
2766
|
+
post.author && /* @__PURE__ */ jsx29("span", { className: "text-xs font-medium text-foreground", children: post.author }),
|
|
2767
|
+
time && /* @__PURE__ */ jsxs28("span", { className: "flex items-center gap-1 text-xs text-muted-foreground ml-auto", children: [
|
|
2768
|
+
/* @__PURE__ */ jsx29(Clock9, { className: "h-3 w-3" }),
|
|
2769
|
+
formatRelativeDate7(time)
|
|
2770
|
+
] })
|
|
2771
|
+
] }),
|
|
2772
|
+
content && /* @__PURE__ */ jsx29("p", { className: "text-sm text-foreground line-clamp-4", children: content })
|
|
2773
|
+
] });
|
|
2774
|
+
}
|
|
2775
|
+
function LinkedInFormatter({ data }) {
|
|
2776
|
+
if (isProfile(data)) return /* @__PURE__ */ jsx29(ProfileCard, { profile: data });
|
|
2777
|
+
if (typeof data === "object" && data !== null && "posts" in data) {
|
|
2778
|
+
const posts = data.posts;
|
|
2779
|
+
if (Array.isArray(posts)) {
|
|
2780
|
+
return /* @__PURE__ */ jsx29("div", { className: "space-y-1.5", children: posts.filter(isPost).map((p, i) => /* @__PURE__ */ jsx29(PostCard, { post: p }, p.id || i)) });
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
if (typeof data === "object" && data !== null && "elements" in data) {
|
|
2784
|
+
const elements = data.elements;
|
|
2785
|
+
if (Array.isArray(elements)) {
|
|
2786
|
+
const posts = elements.filter(isPost);
|
|
2787
|
+
if (posts.length > 0) {
|
|
2788
|
+
return /* @__PURE__ */ jsx29("div", { className: "space-y-1.5", children: posts.map((p, i) => /* @__PURE__ */ jsx29(PostCard, { post: p }, p.id || i)) });
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
if (isPost(data)) return /* @__PURE__ */ jsx29(PostCard, { post: data });
|
|
2793
|
+
if (Array.isArray(data)) {
|
|
2794
|
+
const posts = data.filter(isPost);
|
|
2795
|
+
if (posts.length > 0) {
|
|
2796
|
+
return /* @__PURE__ */ jsx29("div", { className: "space-y-1.5", children: posts.map((p, i) => /* @__PURE__ */ jsx29(PostCard, { post: p }, p.id || i)) });
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
return /* @__PURE__ */ jsx29("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
2800
|
+
}
|
|
2801
|
+
|
|
2802
|
+
// src/ui/formatters/generic.tsx
|
|
2803
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
2804
|
+
function GenericFormatter({ data }) {
|
|
2805
|
+
if (data === null || data === void 0) {
|
|
2806
|
+
return /* @__PURE__ */ jsx30("p", { className: "text-sm text-muted-foreground italic", children: "No data returned" });
|
|
2807
|
+
}
|
|
2808
|
+
return /* @__PURE__ */ jsx30("pre", { className: "rounded-lg border border-border bg-background p-3 text-xs text-foreground overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
// src/ui/tool-result.tsx
|
|
2812
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
2813
|
+
function extractToolName2(part) {
|
|
2814
|
+
if (part.type.startsWith("tool-") && part.type !== "tool-invocation") {
|
|
2815
|
+
return part.type.slice(5);
|
|
2816
|
+
}
|
|
2817
|
+
if (part.type === "dynamic-tool" && part.toolName) {
|
|
2818
|
+
return part.toolName;
|
|
2819
|
+
}
|
|
2820
|
+
if (part.toolName) return part.toolName;
|
|
2821
|
+
if (part.toolInvocation?.toolName) return part.toolInvocation.toolName;
|
|
2822
|
+
return "unknown";
|
|
2823
|
+
}
|
|
2824
|
+
function extractState2(part) {
|
|
2825
|
+
return part.state ?? part.toolInvocation?.state;
|
|
2826
|
+
}
|
|
2827
|
+
function unwrapSupyagentResult(result) {
|
|
2828
|
+
if (typeof result === "object" && result !== null && "ok" in result && "data" in result) {
|
|
2829
|
+
return result.data;
|
|
2830
|
+
}
|
|
2831
|
+
return result;
|
|
2832
|
+
}
|
|
2833
|
+
function extractArgs2(part) {
|
|
2834
|
+
if (part.input && typeof part.input === "object" && !Array.isArray(part.input)) {
|
|
2835
|
+
return part.input;
|
|
2836
|
+
}
|
|
2837
|
+
if (part.args) return part.args;
|
|
2838
|
+
return part.toolInvocation?.args;
|
|
2839
|
+
}
|
|
2840
|
+
function extractResult(part) {
|
|
2841
|
+
let raw;
|
|
2842
|
+
if ("output" in part && part.output !== void 0) raw = part.output;
|
|
2843
|
+
else if ("result" in part && part.result !== void 0) raw = part.result;
|
|
2844
|
+
else raw = part.toolInvocation?.result;
|
|
2845
|
+
return unwrapSupyagentResult(raw);
|
|
2846
|
+
}
|
|
2847
|
+
function maybeNormalize(toolName, formatterType, data) {
|
|
2848
|
+
const lower = toolName.toLowerCase();
|
|
2849
|
+
const isMicrosoft = lower.startsWith("microsoft_") || lower.startsWith("outlook_") || lower.startsWith("onedrive_");
|
|
2850
|
+
if (!isMicrosoft) return data;
|
|
2851
|
+
switch (formatterType) {
|
|
2852
|
+
case "email":
|
|
2853
|
+
return normalizeMicrosoftMail(data);
|
|
2854
|
+
case "calendar":
|
|
2855
|
+
return normalizeMicrosoftCalendar(data);
|
|
2856
|
+
case "drive":
|
|
2857
|
+
return normalizeMicrosoftDrive(data);
|
|
2858
|
+
default:
|
|
2859
|
+
return data;
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2862
|
+
function renderFormatter(formatterType, data) {
|
|
2863
|
+
switch (formatterType) {
|
|
2864
|
+
case "email":
|
|
2865
|
+
return /* @__PURE__ */ jsx31(EmailFormatter, { data });
|
|
2866
|
+
case "calendar":
|
|
2867
|
+
return /* @__PURE__ */ jsx31(CalendarEventFormatter, { data });
|
|
2868
|
+
case "slack":
|
|
2869
|
+
return /* @__PURE__ */ jsx31(SlackMessageFormatter, { data });
|
|
2870
|
+
case "github":
|
|
2871
|
+
return /* @__PURE__ */ jsx31(GithubFormatter, { data });
|
|
2872
|
+
case "drive":
|
|
2873
|
+
return /* @__PURE__ */ jsx31(DriveFileFormatter, { data });
|
|
2874
|
+
case "search":
|
|
2875
|
+
return /* @__PURE__ */ jsx31(SearchFormatter, { data });
|
|
2876
|
+
case "docs":
|
|
2877
|
+
return /* @__PURE__ */ jsx31(DocsFormatter, { data });
|
|
2878
|
+
case "sheets":
|
|
2879
|
+
return /* @__PURE__ */ jsx31(SheetsFormatter, { data });
|
|
2880
|
+
case "slides":
|
|
2881
|
+
return /* @__PURE__ */ jsx31(SlidesFormatter, { data });
|
|
2882
|
+
case "hubspot":
|
|
2883
|
+
return /* @__PURE__ */ jsx31(HubspotFormatter, { data });
|
|
2884
|
+
case "linear":
|
|
2885
|
+
return /* @__PURE__ */ jsx31(LinearFormatter, { data });
|
|
2886
|
+
case "pipedrive":
|
|
2887
|
+
return /* @__PURE__ */ jsx31(PipedriveFormatter, { data });
|
|
2888
|
+
case "compute":
|
|
2889
|
+
return /* @__PURE__ */ jsx31(ComputeFormatter, { data });
|
|
2890
|
+
case "resend":
|
|
2891
|
+
return /* @__PURE__ */ jsx31(ResendFormatter, { data });
|
|
2892
|
+
case "inbox":
|
|
2893
|
+
return /* @__PURE__ */ jsx31(InboxFormatter, { data });
|
|
2894
|
+
case "discord":
|
|
2895
|
+
return /* @__PURE__ */ jsx31(DiscordFormatter, { data });
|
|
2896
|
+
case "notion":
|
|
2897
|
+
return /* @__PURE__ */ jsx31(NotionFormatter, { data });
|
|
2898
|
+
case "twitter":
|
|
2899
|
+
return /* @__PURE__ */ jsx31(TwitterFormatter, { data });
|
|
2900
|
+
case "telegram":
|
|
2901
|
+
return /* @__PURE__ */ jsx31(TelegramFormatter, { data });
|
|
2902
|
+
case "stripe":
|
|
2903
|
+
return /* @__PURE__ */ jsx31(StripeFormatter, { data });
|
|
2904
|
+
case "jira":
|
|
2905
|
+
return /* @__PURE__ */ jsx31(JiraFormatter, { data });
|
|
2906
|
+
case "salesforce":
|
|
2907
|
+
return /* @__PURE__ */ jsx31(SalesforceFormatter, { data });
|
|
2908
|
+
case "brevo":
|
|
2909
|
+
return /* @__PURE__ */ jsx31(BrevoFormatter, { data });
|
|
2910
|
+
case "calendly":
|
|
2911
|
+
return /* @__PURE__ */ jsx31(CalendlyFormatter, { data });
|
|
2912
|
+
case "twilio":
|
|
2913
|
+
return /* @__PURE__ */ jsx31(TwilioFormatter, { data });
|
|
2914
|
+
case "linkedin":
|
|
2915
|
+
return /* @__PURE__ */ jsx31(LinkedInFormatter, { data });
|
|
2916
|
+
default:
|
|
2917
|
+
return /* @__PURE__ */ jsx31(GenericFormatter, { data });
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
function SupyagentToolResult({ part }) {
|
|
2921
|
+
const state = extractState2(part);
|
|
2922
|
+
const result = extractResult(part);
|
|
2923
|
+
const toolName = extractToolName2(part);
|
|
2924
|
+
if (state !== "output-available" || result === void 0) {
|
|
2925
|
+
return null;
|
|
2926
|
+
}
|
|
2927
|
+
const formatterType = getFormatterType(toolName);
|
|
2928
|
+
const data = maybeNormalize(toolName, formatterType, result);
|
|
2929
|
+
const summary = getSummary(formatterType, data, toolName);
|
|
2930
|
+
return /* @__PURE__ */ jsx31(
|
|
2931
|
+
CollapsibleResult,
|
|
2932
|
+
{
|
|
2933
|
+
toolName,
|
|
2934
|
+
summary: summary.text,
|
|
2935
|
+
badge: summary.badge,
|
|
2936
|
+
children: renderFormatter(formatterType, data)
|
|
2937
|
+
}
|
|
2938
|
+
);
|
|
2939
|
+
}
|
|
2940
|
+
|
|
2941
|
+
// src/ui/tool-action.tsx
|
|
2942
|
+
import { useState as useState3 } from "react";
|
|
2943
|
+
import { ChevronDown as ChevronDown3, ChevronRight as ChevronRight3, Check as Check4, AlertCircle as AlertCircle2, Loader2 as Loader22 } from "lucide-react";
|
|
2944
|
+
|
|
2945
|
+
// src/ui/tool-input.tsx
|
|
2946
|
+
import React3 from "react";
|
|
2947
|
+
import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2948
|
+
function formatValue(value) {
|
|
2949
|
+
if (value === null || value === void 0) {
|
|
2950
|
+
return { text: "null", muted: true };
|
|
2951
|
+
}
|
|
2952
|
+
if (typeof value === "boolean") {
|
|
2953
|
+
return { text: String(value), muted: true };
|
|
2954
|
+
}
|
|
2955
|
+
if (typeof value === "number") {
|
|
2956
|
+
return { text: String(value) };
|
|
2957
|
+
}
|
|
2958
|
+
if (typeof value === "string") {
|
|
2959
|
+
return { text: value };
|
|
2960
|
+
}
|
|
2961
|
+
if (Array.isArray(value)) {
|
|
2962
|
+
if (value.length === 0) return { text: "[]", muted: true };
|
|
2963
|
+
const allPrimitive = value.every(
|
|
2964
|
+
(v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean"
|
|
2965
|
+
);
|
|
2966
|
+
if (allPrimitive) {
|
|
2967
|
+
const joined = value.join(", ");
|
|
2968
|
+
return { text: joined.length > 80 ? joined.slice(0, 77) + "..." : joined };
|
|
2969
|
+
}
|
|
2970
|
+
return { text: `${value.length} items`, muted: true };
|
|
2971
|
+
}
|
|
2972
|
+
if (typeof value === "object") {
|
|
2973
|
+
const json = JSON.stringify(value);
|
|
2974
|
+
if (json.length <= 60) return { text: json, muted: true };
|
|
2975
|
+
return { text: json.slice(0, 57) + "...", muted: true };
|
|
2976
|
+
}
|
|
2977
|
+
return { text: String(value) };
|
|
2978
|
+
}
|
|
2979
|
+
function ToolInput({ args }) {
|
|
2980
|
+
if (!args || Object.keys(args).length === 0) return null;
|
|
2981
|
+
return /* @__PURE__ */ jsx32("div", { className: "grid grid-cols-[auto_1fr] gap-x-4 gap-y-1 text-sm", children: Object.entries(args).map(([key, value]) => {
|
|
2982
|
+
const formatted = formatValue(value);
|
|
2983
|
+
return /* @__PURE__ */ jsxs29(React3.Fragment, { children: [
|
|
2984
|
+
/* @__PURE__ */ jsx32("span", { className: "text-muted-foreground select-none", children: key }),
|
|
2985
|
+
/* @__PURE__ */ jsx32("span", { className: formatted.muted ? "text-muted-foreground" : "text-foreground", children: formatted.text })
|
|
2986
|
+
] }, key);
|
|
2987
|
+
}) });
|
|
2988
|
+
}
|
|
2989
|
+
|
|
2990
|
+
// src/ui/tool-action.tsx
|
|
2991
|
+
import { Fragment, jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2992
|
+
var BADGE_STYLES2 = {
|
|
2993
|
+
default: "bg-muted text-muted-foreground",
|
|
2994
|
+
success: "bg-green-500/10 text-green-500",
|
|
2995
|
+
error: "bg-destructive/10 text-destructive",
|
|
2996
|
+
warning: "bg-yellow-500/10 text-yellow-600"
|
|
2997
|
+
};
|
|
2998
|
+
function SupyagentToolAction({ part, defaultExpanded = false }) {
|
|
2999
|
+
const [expanded, setExpanded] = useState3(defaultExpanded);
|
|
3000
|
+
const toolName = extractToolName2(part);
|
|
3001
|
+
const state = extractState2(part);
|
|
3002
|
+
const args = extractArgs2(part);
|
|
3003
|
+
const provider = getProviderFromToolName(toolName);
|
|
3004
|
+
const providerLabel = getProviderLabel(provider);
|
|
3005
|
+
const actionLabel = humanizeToolName(toolName);
|
|
3006
|
+
const isStreaming = state === "input-streaming";
|
|
3007
|
+
const isError = state === "output-error";
|
|
3008
|
+
const isDone = state === "output-available";
|
|
3009
|
+
const hasResult = isDone || isError;
|
|
3010
|
+
let summary;
|
|
3011
|
+
let formatterOutput;
|
|
3012
|
+
if (hasResult) {
|
|
3013
|
+
const result = extractResult(part);
|
|
3014
|
+
if (result !== void 0) {
|
|
3015
|
+
const formatterType = getFormatterType(toolName);
|
|
3016
|
+
const data = maybeNormalize(toolName, formatterType, result);
|
|
3017
|
+
summary = getSummary(formatterType, data, toolName);
|
|
3018
|
+
formatterOutput = renderFormatter(formatterType, data);
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
const hasExpandableContent = args || formatterOutput;
|
|
3022
|
+
const canExpand = !isStreaming && hasExpandableContent;
|
|
3023
|
+
return /* @__PURE__ */ jsxs30(
|
|
3024
|
+
"div",
|
|
3025
|
+
{
|
|
3026
|
+
className: "rounded-lg border border-border bg-card overflow-hidden",
|
|
3027
|
+
"data-state": isDone ? "done" : isError ? "error" : isStreaming ? "streaming" : "pending",
|
|
3028
|
+
children: [
|
|
3029
|
+
/* @__PURE__ */ jsxs30(
|
|
3030
|
+
"button",
|
|
3031
|
+
{
|
|
3032
|
+
type: "button",
|
|
3033
|
+
onClick: () => canExpand && setExpanded(!expanded),
|
|
3034
|
+
className: `flex items-center gap-2 w-full px-3 py-2 text-left transition-colors ${canExpand ? "hover:bg-muted cursor-pointer" : "cursor-default"}`,
|
|
3035
|
+
children: [
|
|
3036
|
+
/* @__PURE__ */ jsxs30("div", { className: "relative shrink-0", children: [
|
|
3037
|
+
/* @__PURE__ */ jsx33(ProviderIcon, { toolName, className: "h-4 w-4 text-muted-foreground" }),
|
|
3038
|
+
isStreaming && /* @__PURE__ */ jsx33(Loader22, { className: "absolute -top-1 -right-1 h-3 w-3 text-primary animate-spin" })
|
|
3039
|
+
] }),
|
|
3040
|
+
/* @__PURE__ */ jsx33("span", { className: "text-xs text-muted-foreground", children: providerLabel }),
|
|
3041
|
+
/* @__PURE__ */ jsx33("span", { className: "text-sm text-foreground", children: actionLabel }),
|
|
3042
|
+
summary && /* @__PURE__ */ jsxs30(Fragment, { children: [
|
|
3043
|
+
/* @__PURE__ */ jsx33("span", { className: "text-muted-foreground text-xs", children: "\xB7" }),
|
|
3044
|
+
/* @__PURE__ */ jsx33("span", { className: "text-sm text-muted-foreground flex-1 truncate", children: summary.text })
|
|
3045
|
+
] }),
|
|
3046
|
+
!summary && /* @__PURE__ */ jsx33("span", { className: "flex-1" }),
|
|
3047
|
+
summary?.badge && /* @__PURE__ */ jsx33(
|
|
3048
|
+
"span",
|
|
3049
|
+
{
|
|
3050
|
+
className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium shrink-0 ${BADGE_STYLES2[summary.badge.variant || "default"]}`,
|
|
3051
|
+
children: summary.badge.text
|
|
3052
|
+
}
|
|
3053
|
+
),
|
|
3054
|
+
isDone && /* @__PURE__ */ jsx33(Check4, { className: "h-3.5 w-3.5 text-green-500 shrink-0" }),
|
|
3055
|
+
isError && /* @__PURE__ */ jsxs30("span", { className: "inline-flex items-center gap-1 rounded-full bg-destructive/10 px-2 py-0.5 text-xs text-destructive shrink-0", children: [
|
|
3056
|
+
/* @__PURE__ */ jsx33(AlertCircle2, { className: "h-3 w-3" }),
|
|
3057
|
+
"Error"
|
|
3058
|
+
] }),
|
|
3059
|
+
isStreaming && /* @__PURE__ */ jsx33("span", { className: "inline-flex items-center gap-1 rounded-full bg-primary/10 px-2 py-0.5 text-xs text-primary animate-pulse shrink-0", children: "Calling..." }),
|
|
3060
|
+
canExpand && (expanded ? /* @__PURE__ */ jsx33(ChevronDown3, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }) : /* @__PURE__ */ jsx33(ChevronRight3, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }))
|
|
3061
|
+
]
|
|
3062
|
+
}
|
|
3063
|
+
),
|
|
3064
|
+
/* @__PURE__ */ jsx33(
|
|
3065
|
+
"div",
|
|
3066
|
+
{
|
|
3067
|
+
className: "grid transition-[grid-template-rows] duration-200 ease-out",
|
|
3068
|
+
style: { gridTemplateRows: expanded ? "1fr" : "0fr" },
|
|
3069
|
+
children: /* @__PURE__ */ jsx33("div", { className: "overflow-hidden", children: /* @__PURE__ */ jsxs30("div", { className: "border-t border-border px-3 py-2 space-y-3", children: [
|
|
3070
|
+
args && Object.keys(args).length > 0 && /* @__PURE__ */ jsxs30("div", { children: [
|
|
3071
|
+
/* @__PURE__ */ jsx33("p", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground mb-1.5", children: "Input" }),
|
|
3072
|
+
/* @__PURE__ */ jsx33(ToolInput, { args })
|
|
3073
|
+
] }),
|
|
3074
|
+
formatterOutput && /* @__PURE__ */ jsxs30("div", { children: [
|
|
3075
|
+
/* @__PURE__ */ jsx33("p", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground mb-1.5", children: "Output" }),
|
|
3076
|
+
formatterOutput
|
|
3077
|
+
] })
|
|
3078
|
+
] }) })
|
|
3079
|
+
}
|
|
3080
|
+
)
|
|
3081
|
+
]
|
|
3082
|
+
}
|
|
3083
|
+
);
|
|
398
3084
|
}
|
|
399
3085
|
export {
|
|
3086
|
+
BrevoFormatter,
|
|
3087
|
+
CalendarEventFormatter,
|
|
3088
|
+
CalendlyFormatter,
|
|
3089
|
+
CollapsibleResult,
|
|
3090
|
+
ComputeFormatter,
|
|
3091
|
+
DiscordFormatter,
|
|
3092
|
+
DocsFormatter,
|
|
3093
|
+
DriveFileFormatter,
|
|
3094
|
+
EmailFormatter,
|
|
3095
|
+
GenericFormatter,
|
|
3096
|
+
GithubFormatter,
|
|
3097
|
+
HubspotFormatter,
|
|
3098
|
+
InboxFormatter,
|
|
3099
|
+
JiraFormatter,
|
|
3100
|
+
LinearFormatter,
|
|
3101
|
+
LinkedInFormatter,
|
|
3102
|
+
NotionFormatter,
|
|
3103
|
+
PipedriveFormatter,
|
|
400
3104
|
ProviderIcon,
|
|
3105
|
+
ResendFormatter,
|
|
3106
|
+
SalesforceFormatter,
|
|
3107
|
+
SearchFormatter,
|
|
3108
|
+
SheetsFormatter,
|
|
3109
|
+
SlackMessageFormatter,
|
|
3110
|
+
SlidesFormatter,
|
|
3111
|
+
StripeFormatter,
|
|
3112
|
+
SupyagentToolAction,
|
|
401
3113
|
SupyagentToolCall,
|
|
402
3114
|
SupyagentToolResult,
|
|
3115
|
+
TelegramFormatter,
|
|
3116
|
+
ToolInput,
|
|
3117
|
+
TwilioFormatter,
|
|
3118
|
+
TwitterFormatter,
|
|
403
3119
|
getProviderFromToolName,
|
|
404
3120
|
getProviderLabel,
|
|
3121
|
+
getSummary,
|
|
405
3122
|
humanizeToolName
|
|
406
3123
|
};
|
|
407
3124
|
//# sourceMappingURL=react.js.map
|