@supyagent/sdk 0.1.5 → 0.1.6

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