@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.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.toolName || part.toolInvocation?.toolName || "unknown";
101
- const state = part.state || part.toolInvocation?.state || "input-available";
102
- const args = part.args || part.toolInvocation?.args;
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("div", { className: "rounded-lg border border-zinc-800 bg-zinc-900/50 overflow-hidden", children: [
110
- /* @__PURE__ */ jsxs(
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: () => args && setExpanded(!expanded),
115
- className: "flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-zinc-800/50 transition-colors",
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__ */ jsxs("div", { className: "relative", children: [
118
- /* @__PURE__ */ jsx2(ProviderIcon, { toolName, className: "h-4 w-4 text-zinc-400" }),
119
- isStreaming && /* @__PURE__ */ jsx2(Loader2, { className: "absolute -top-1 -right-1 h-3 w-3 text-blue-400 animate-spin" })
120
- ] }),
121
- /* @__PURE__ */ jsx2("span", { className: "text-xs text-zinc-500", children: providerLabel }),
122
- /* @__PURE__ */ jsx2("span", { className: "text-sm text-zinc-300 flex-1", children: actionLabel }),
123
- isDone && /* @__PURE__ */ jsx2(Check, { className: "h-3.5 w-3.5 text-green-400" }),
124
- isError && /* @__PURE__ */ jsx2(AlertCircle, { className: "h-3.5 w-3.5 text-red-400" }),
125
- isStreaming && /* @__PURE__ */ jsx2("span", { className: "text-xs text-zinc-500 animate-pulse", children: "Running..." }),
126
- args && (expanded ? /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3.5 w-3.5 text-zinc-500" }) : /* @__PURE__ */ jsx2(ChevronRight, { className: "h-3.5 w-3.5 text-zinc-500" }))
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
- expanded && args && /* @__PURE__ */ jsx2("div", { className: "border-t border-zinc-800 px-3 py-2", children: /* @__PURE__ */ jsx2("pre", { className: "text-xs text-zinc-400 overflow-x-auto", children: JSON.stringify(args, null, 2) }) })
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 jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
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
- return /* @__PURE__ */ jsxs2("div", { className: "rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-2", children: [
142
- /* @__PURE__ */ jsxs2("div", { className: "flex items-start gap-2", children: [
143
- /* @__PURE__ */ jsx3(Mail2, { className: "h-4 w-4 text-zinc-400 mt-0.5 shrink-0" }),
144
- /* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1", children: [
145
- /* @__PURE__ */ jsx3("p", { className: "text-sm font-medium text-zinc-200 truncate", children: email.subject || "No subject" }),
146
- email.from && /* @__PURE__ */ jsx3("p", { className: "text-xs text-zinc-400 truncate", children: email.from })
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
- email.hasAttachments && /* @__PURE__ */ jsx3(Paperclip, { className: "h-3.5 w-3.5 text-zinc-500 shrink-0" })
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.snippet && /* @__PURE__ */ jsx3("p", { className: "text-xs text-zinc-400 line-clamp-2", children: email.snippet }),
151
- email.date && /* @__PURE__ */ jsx3("p", { className: "text-xs text-zinc-500", children: email.date })
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__ */ jsx3(EmailCard, { email: data });
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__ */ jsx3("div", { className: "space-y-2", children: emails.map((email, i) => /* @__PURE__ */ jsx3(EmailCard, { email }, email.id || i)) });
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__ */ jsx3("div", { className: "space-y-2", children: emails.map((email, i) => /* @__PURE__ */ jsx3(EmailCard, { email }, email.id || i)) });
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__ */ jsx3("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
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 jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
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 formatDateTime(dt) {
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 = formatDateTime(event.start);
195
- const endStr = formatDateTime(event.end);
196
- return /* @__PURE__ */ jsxs3("div", { className: "rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-2", children: [
197
- /* @__PURE__ */ jsxs3("div", { className: "flex items-start gap-2", children: [
198
- /* @__PURE__ */ jsx4(Calendar2, { className: "h-4 w-4 text-zinc-400 mt-0.5 shrink-0" }),
199
- /* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
200
- /* @__PURE__ */ jsx4("p", { className: "text-sm font-medium text-zinc-200", children: event.summary || "Untitled event" }),
201
- startStr && /* @__PURE__ */ jsxs3("p", { className: "text-xs text-zinc-400", children: [
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__ */ jsxs3("div", { className: "flex items-center gap-1.5 text-xs text-zinc-400", children: [
208
- /* @__PURE__ */ jsx4(MapPin, { className: "h-3 w-3 shrink-0" }),
209
- /* @__PURE__ */ jsx4("span", { className: "truncate", children: event.location })
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__ */ jsxs3("div", { className: "flex items-center gap-1.5 text-xs text-zinc-400", children: [
212
- /* @__PURE__ */ jsx4(Users, { className: "h-3 w-3 shrink-0" }),
213
- /* @__PURE__ */ jsx4("span", { className: "truncate", children: event.attendees.map((a) => a.displayName || a.email).join(", ") })
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__ */ jsx4(EventCard, { event: data });
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__ */ jsx4("div", { className: "space-y-2", children: events.map((event, i) => /* @__PURE__ */ jsx4(EventCard, { event }, event.id || i)) });
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__ */ jsx4("div", { className: "space-y-2", children: calEvents.map((event, i) => /* @__PURE__ */ jsx4(EventCard, { event }, event.id || i)) });
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__ */ jsx4("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
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 jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
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__ */ jsxs4("div", { className: "rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-1.5", children: [
247
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
248
- /* @__PURE__ */ jsx5(MessageSquare2, { className: "h-4 w-4 text-zinc-400 shrink-0" }),
249
- message.channel && /* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-0.5 text-xs text-zinc-400", children: [
250
- /* @__PURE__ */ jsx5(Hash, { className: "h-3 w-3" }),
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__ */ jsx5("span", { className: "text-xs text-zinc-500", children: message.user })
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__ */ jsx5("p", { className: "text-sm text-zinc-300", children: message.text })
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__ */ jsx5(MessageBubble, { message: data });
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__ */ jsx5("div", { className: "space-y-2", children: messages.map((msg, i) => /* @__PURE__ */ jsx5(MessageBubble, { message: msg }, msg.ts || i)) });
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__ */ jsx5("div", { className: "space-y-2", children: slackMsgs.map((msg, i) => /* @__PURE__ */ jsx5(MessageBubble, { message: msg }, msg.ts || i)) });
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__ */ jsx5("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
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 jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
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 GithubCard({ item }) {
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
- const stateColor = item.state === "open" ? "text-green-400" : item.state === "closed" ? "text-red-400" : "text-zinc-400";
289
- return /* @__PURE__ */ jsxs5("div", { className: "rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-1.5", children: [
290
- /* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-2", children: [
291
- isPR ? /* @__PURE__ */ jsx6(GitPullRequest, { className: `h-4 w-4 mt-0.5 shrink-0 ${stateColor}` }) : /* @__PURE__ */ jsx6(CircleDot, { className: `h-4 w-4 mt-0.5 shrink-0 ${stateColor}` }),
292
- /* @__PURE__ */ jsxs5("div", { className: "min-w-0 flex-1", children: [
293
- /* @__PURE__ */ jsxs5("p", { className: "text-sm font-medium text-zinc-200", children: [
294
- item.title,
295
- item.number && /* @__PURE__ */ jsxs5("span", { className: "text-zinc-500 font-normal", children: [
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
- item.user?.login && /* @__PURE__ */ jsx6("p", { className: "text-xs text-zinc-400", children: item.user.login })
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.body && /* @__PURE__ */ jsx6("p", { className: "text-xs text-zinc-400 line-clamp-2", children: item.body })
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__ */ jsx6(GithubCard, { item: data });
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__ */ jsx6("div", { className: "space-y-2", children: items.map((item, i) => /* @__PURE__ */ jsx6(GithubCard, { item }, item.number || i)) });
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__ */ jsx6("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
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 jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
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
- return /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3 rounded-lg border border-zinc-800 bg-zinc-900/50 p-3", children: [
336
- /* @__PURE__ */ jsx7(Icon, { className: "h-4 w-4 text-zinc-400 shrink-0" }),
337
- /* @__PURE__ */ jsxs6("div", { className: "min-w-0 flex-1", children: [
338
- /* @__PURE__ */ jsx7("p", { className: "text-sm text-zinc-200 truncate", children: file.name || "Untitled" }),
339
- file.modifiedTime && /* @__PURE__ */ jsx7("p", { className: "text-xs text-zinc-500", children: new Date(file.modifiedTime).toLocaleDateString() })
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__ */ jsx7(FileCard, { file: data });
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__ */ jsx7("div", { className: "space-y-1.5", children: files.map((file, i) => /* @__PURE__ */ jsx7(FileCard, { file }, file.id || i)) });
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__ */ jsx7("div", { className: "space-y-1.5", children: driveFiles.map((file, i) => /* @__PURE__ */ jsx7(FileCard, { file }, file.id || i)) });
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__ */ jsx7("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
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/generic.tsx
366
- import { jsx as jsx8 } from "react/jsx-runtime";
367
- function GenericFormatter({ data }) {
368
- if (data === null || data === void 0) {
369
- return /* @__PURE__ */ jsx8("p", { className: "text-sm text-zinc-500 italic", children: "No data returned" });
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
- return /* @__PURE__ */ jsx8("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
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/tool-result.tsx
375
- import { jsx as jsx9 } from "react/jsx-runtime";
376
- function SupyagentToolResult({ part }) {
377
- const state = part.state ?? part.toolInvocation?.state;
378
- const result = "result" in part ? part.result : part.toolInvocation?.result;
379
- const toolName = part.toolName ?? part.toolInvocation?.toolName ?? "unknown";
380
- if (state !== "output-available" || result === void 0) {
381
- return null;
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
- const formatterType = getFormatterType(toolName);
384
- switch (formatterType) {
385
- case "email":
386
- return /* @__PURE__ */ jsx9(EmailFormatter, { data: result });
387
- case "calendar":
388
- return /* @__PURE__ */ jsx9(CalendarEventFormatter, { data: result });
389
- case "slack":
390
- return /* @__PURE__ */ jsx9(SlackMessageFormatter, { data: result });
391
- case "github":
392
- return /* @__PURE__ */ jsx9(GithubFormatter, { data: result });
393
- case "drive":
394
- return /* @__PURE__ */ jsx9(DriveFileFormatter, { data: result });
395
- default:
396
- return /* @__PURE__ */ jsx9(GenericFormatter, { data: result });
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