@aivue/tabular-intelligence 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,18 +1,425 @@
1
- import { ref as M } from "vue";
2
- class N {
3
- constructor(s) {
1
+ import { ref as C, defineComponent as F, createElementBlock as d, openBlock as p, createElementVNode as m, createCommentVNode as T, withDirectives as Y, withKeys as j, withModifiers as L, vModelText as W, toDisplayString as v, normalizeClass as X, createTextVNode as Z, Fragment as O, renderList as Q, computed as ee } from "vue";
2
+ function I(l, n) {
3
+ if (l.length === 0)
4
+ return { columns: [], rowCount: 0, name: n };
5
+ const a = l[0];
6
+ return {
7
+ columns: Object.keys(a).map((t) => {
8
+ const s = B(l, t);
9
+ return {
10
+ name: t,
11
+ type: s,
12
+ nullable: l.some((r) => r[t] == null)
13
+ };
14
+ }),
15
+ rowCount: l.length,
16
+ name: n
17
+ };
18
+ }
19
+ function B(l, n) {
20
+ const a = l.map((t) => t[n]).filter((t) => t != null);
21
+ if (a.length === 0) return "string";
22
+ if (a.every((t) => typeof t == "number" || !isNaN(Number(t))))
23
+ return "number";
24
+ if (a.every((t) => typeof t == "boolean" || t === "true" || t === "false"))
25
+ return "boolean";
26
+ if (a.every((t) => !isNaN(Date.parse(t))))
27
+ return "date";
28
+ const e = new Set(a);
29
+ return e.size < a.length * 0.5 && e.size < 20 ? "categorical" : "string";
30
+ }
31
+ function H(l, n, a) {
32
+ const e = l.map((o) => o[n]).filter((o) => o != null), t = e.length, s = l.length - t, r = {
33
+ column: n,
34
+ count: t,
35
+ nullCount: s
36
+ };
37
+ if (a === "number") {
38
+ const o = e.map(Number).filter((i) => !isNaN(i));
39
+ if (o.length > 0) {
40
+ const i = [...o].sort((h, w) => h - w), u = o.reduce((h, w) => h + w, 0);
41
+ r.mean = u / o.length, r.median = i[Math.floor(i.length / 2)], r.min = i[0], r.max = i[i.length - 1];
42
+ const g = o.reduce((h, w) => h + Math.pow(w - r.mean, 2), 0) / o.length;
43
+ r.std = Math.sqrt(g), r.percentiles = {
44
+ 25: i[Math.floor(i.length * 0.25)],
45
+ 50: r.median,
46
+ 75: i[Math.floor(i.length * 0.75)],
47
+ 90: i[Math.floor(i.length * 0.9)]
48
+ };
49
+ }
50
+ } else {
51
+ const o = new Set(e);
52
+ r.uniqueValues = o.size;
53
+ const i = {};
54
+ e.forEach((g) => {
55
+ const h = String(g);
56
+ i[h] = (i[h] || 0) + 1;
57
+ });
58
+ const u = Math.max(...Object.values(i));
59
+ r.mode = Object.keys(i).find((g) => i[g] === u);
60
+ }
61
+ return r;
62
+ }
63
+ function te(l, n, a = 0.5) {
64
+ const e = [], t = 1.5 + (1 - a) * 1.5;
65
+ return n.forEach((s) => {
66
+ const r = l.map((A, b) => ({ value: Number(A[s]), idx: b })).filter((A) => !isNaN(A.value));
67
+ if (r.length === 0) return;
68
+ const o = [...r].sort((A, b) => A.value - b.value), i = o[Math.floor(o.length * 0.25)].value, u = o[Math.floor(o.length * 0.75)].value, g = u - i, h = i - t * g, w = u + t * g;
69
+ r.forEach(({ value: A, idx: b }) => {
70
+ if (A < h || A > w) {
71
+ const _ = e.find((x) => x.rowIndex === b), k = A < h ? `${s}: ${A.toFixed(2)} < ${h.toFixed(2)}` : `${s}: ${A.toFixed(2)} > ${w.toFixed(2)}`;
72
+ _ ? (_.reasons.push(k), _.affectedColumns.push(s), _.score = Math.min(1, _.score + 0.2)) : e.push({
73
+ rowIndex: b,
74
+ row: l[b],
75
+ score: 0.7,
76
+ reasons: [k],
77
+ affectedColumns: [s]
78
+ });
79
+ }
80
+ });
81
+ }), e.sort((s, r) => r.score - s.score);
82
+ }
83
+ class P {
84
+ constructor(n) {
4
85
  this.config = {
5
- timeout: 3e4,
6
- ...s
86
+ maxTokens: 1e3,
87
+ temperature: 0.3,
88
+ ...n
89
+ };
90
+ }
91
+ /**
92
+ * Answer a question about the table data
93
+ */
94
+ async answerQuestion(n) {
95
+ const a = Date.now();
96
+ try {
97
+ const { question: e, schema: t, data: s = [], sampleSize: r = 100, includeAggregates: o = !0 } = n, i = s.length > r ? this.sampleData(s, r) : s, u = o ? this.calculateAggregates(s, t) : void 0, g = this.buildPrompt(e, t, i, u, s.length), h = await this.callLLM(g);
98
+ return {
99
+ answer: this.parseResponse(h, e, s.length > r),
100
+ processingTime: Date.now() - a
101
+ };
102
+ } catch (e) {
103
+ return console.error("Q&A error:", e), {
104
+ answer: {
105
+ questionId: this.generateId(),
106
+ text: "I encountered an error while processing your question. Please try again.",
107
+ timestamp: /* @__PURE__ */ new Date(),
108
+ confidence: 0,
109
+ cannotAnswer: !0,
110
+ reason: e instanceof Error ? e.message : "Unknown error"
111
+ },
112
+ processingTime: Date.now() - a
113
+ };
114
+ }
115
+ }
116
+ /**
117
+ * Sample data for large datasets
118
+ */
119
+ sampleData(n, a) {
120
+ if (n.length <= a)
121
+ return n;
122
+ const e = Math.floor(n.length / a), t = [];
123
+ for (let s = 0; s < n.length && t.length < a; s += e)
124
+ t.push(n[s]);
125
+ return t;
126
+ }
127
+ /**
128
+ * Calculate aggregates for numeric columns
129
+ */
130
+ calculateAggregates(n, a) {
131
+ const e = {};
132
+ for (const t of a.columns)
133
+ if (t.type === "number" && n.length > 0)
134
+ try {
135
+ const s = H(n, t.name, "number");
136
+ e[t.name] = {
137
+ mean: s.mean,
138
+ median: s.median,
139
+ min: s.min,
140
+ max: s.max,
141
+ count: s.count
142
+ };
143
+ } catch {
144
+ }
145
+ else if (t.type === "categorical" || t.type === "string") {
146
+ const s = n.map((o) => o[t.name]).filter((o) => o != null), r = new Set(s);
147
+ e[t.name] = {
148
+ uniqueCount: r.size,
149
+ totalCount: s.length,
150
+ topValues: this.getTopValues(s, 5)
151
+ };
152
+ }
153
+ return e;
154
+ }
155
+ /**
156
+ * Get top N most frequent values
157
+ */
158
+ getTopValues(n, a) {
159
+ const e = /* @__PURE__ */ new Map();
160
+ for (const t of n)
161
+ e.set(t, (e.get(t) || 0) + 1);
162
+ return Array.from(e.entries()).map(([t, s]) => ({ value: t, count: s })).sort((t, s) => s.count - t.count).slice(0, a);
163
+ }
164
+ /**
165
+ * Build prompt for LLM
166
+ */
167
+ buildPrompt(n, a, e, t, s) {
168
+ const r = s && s > e.length;
169
+ let o = `You are a data analyst assistant. Answer the following question about a table dataset.
170
+
171
+ `;
172
+ o += `**Table Schema:**
173
+ `, o += `Table: ${a.name}
174
+ `, o += `Columns:
175
+ `;
176
+ for (const i of a.columns)
177
+ o += `- ${i.name} (${i.type})
178
+ `;
179
+ return o += `
180
+ `, t && Object.keys(t).length > 0 && (o += `**Summary Statistics:**
181
+ `, o += JSON.stringify(t, null, 2), o += `
182
+
183
+ `), o += `**Sample Data** (${e.length} rows${r ? ` out of ${s} total` : ""}):
184
+ `, o += JSON.stringify(e.slice(0, 10), null, 2), o += `
185
+
186
+ `, o += `**Question:** ${n}
187
+
188
+ `, o += `**Instructions:**
189
+ `, o += `1. Answer ONLY based on the data provided above.
190
+ `, o += `2. If the question cannot be answered from the available data, clearly state "I cannot answer this question from the available data" and explain why.
191
+ `, o += `3. Provide a clear, concise answer.
192
+ `, o += `4. Include specific numbers or examples from the data when relevant.
193
+ `, o += `5. If the answer is based on sampled data, mention that it's an approximation.
194
+ `, o += `6. Format your response as JSON with the following structure:
195
+ `, o += `{
196
+ `, o += ` "answer": "Your answer text here",
197
+ `, o += ` "confidence": 0.0-1.0,
198
+ `, o += ` "cannotAnswer": false,
199
+ `, o += ` "isApproximate": ${r},
200
+ `, o += ` "supportingData": { "key": "value" } // optional
201
+ `, o += `}
202
+ `, o;
203
+ }
204
+ /**
205
+ * Call LLM API
206
+ */
207
+ async callLLM(n) {
208
+ const { provider: a, apiKey: e, baseUrl: t, model: s, maxTokens: r, temperature: o } = this.config;
209
+ if (a === "openai")
210
+ return this.callOpenAI(n, e, s || "gpt-4-turbo-preview", r, o);
211
+ if (a === "anthropic")
212
+ return this.callAnthropic(n, e, s || "claude-3-5-sonnet-20241022", r, o);
213
+ if (a === "custom" && t)
214
+ return this.callCustomAPI(n, t, e);
215
+ throw new Error(`Unsupported provider: ${a}`);
216
+ }
217
+ /**
218
+ * Call OpenAI API
219
+ */
220
+ async callOpenAI(n, a, e, t, s) {
221
+ var i, u;
222
+ const r = await fetch("https://api.openai.com/v1/chat/completions", {
223
+ method: "POST",
224
+ headers: {
225
+ "Content-Type": "application/json",
226
+ Authorization: `Bearer ${a}`
227
+ },
228
+ body: JSON.stringify({
229
+ model: e,
230
+ messages: [{ role: "user", content: n }],
231
+ max_tokens: t,
232
+ temperature: s,
233
+ response_format: { type: "json_object" }
234
+ })
235
+ });
236
+ if (!r.ok)
237
+ throw new Error(`OpenAI API error: ${r.statusText}`);
238
+ return ((u = (i = (await r.json()).choices[0]) == null ? void 0 : i.message) == null ? void 0 : u.content) || "";
239
+ }
240
+ /**
241
+ * Call Anthropic API
242
+ */
243
+ async callAnthropic(n, a, e, t, s) {
244
+ var i;
245
+ const r = await fetch("https://api.anthropic.com/v1/messages", {
246
+ method: "POST",
247
+ headers: {
248
+ "Content-Type": "application/json",
249
+ "x-api-key": a,
250
+ "anthropic-version": "2023-06-01"
251
+ },
252
+ body: JSON.stringify({
253
+ model: e,
254
+ max_tokens: t,
255
+ temperature: s,
256
+ messages: [{ role: "user", content: n }]
257
+ })
258
+ });
259
+ if (!r.ok)
260
+ throw new Error(`Anthropic API error: ${r.statusText}`);
261
+ return ((i = (await r.json()).content[0]) == null ? void 0 : i.text) || "";
262
+ }
263
+ /**
264
+ * Call custom API
265
+ */
266
+ async callCustomAPI(n, a, e) {
267
+ const t = {
268
+ "Content-Type": "application/json"
7
269
  };
270
+ e && (t.Authorization = `Bearer ${e}`);
271
+ const s = await fetch(a, {
272
+ method: "POST",
273
+ headers: t,
274
+ body: JSON.stringify({ prompt: n })
275
+ });
276
+ if (!s.ok)
277
+ throw new Error(`Custom API error: ${s.statusText}`);
278
+ const r = await s.json();
279
+ return r.response || r.answer || JSON.stringify(r);
280
+ }
281
+ /**
282
+ * Parse LLM response
283
+ */
284
+ parseResponse(n, a, e) {
285
+ try {
286
+ const t = JSON.parse(n);
287
+ return {
288
+ questionId: this.generateId(),
289
+ text: t.answer || t.text || n,
290
+ timestamp: /* @__PURE__ */ new Date(),
291
+ confidence: t.confidence || 0.8,
292
+ cannotAnswer: t.cannotAnswer || !1,
293
+ isApproximate: t.isApproximate !== void 0 ? t.isApproximate : e,
294
+ supportingData: t.supportingData,
295
+ reason: t.reason
296
+ };
297
+ } catch {
298
+ return {
299
+ questionId: this.generateId(),
300
+ text: n,
301
+ timestamp: /* @__PURE__ */ new Date(),
302
+ confidence: 0.7,
303
+ isApproximate: e
304
+ };
305
+ }
306
+ }
307
+ /**
308
+ * Generate unique ID
309
+ */
310
+ generateId() {
311
+ return `qa_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
312
+ }
313
+ }
314
+ function ne(l = {}) {
315
+ const {
316
+ selector: n = "table",
317
+ includeHeaders: a = !0,
318
+ maxRows: e,
319
+ inferTypes: t = !0,
320
+ skipEmptyRows: s = !0
321
+ } = l, r = document.querySelector(n);
322
+ if (!r || r.tagName !== "TABLE")
323
+ return console.warn(`No table found with selector: ${n}`), null;
324
+ const i = Array.from(r.rows);
325
+ if (i.length === 0)
326
+ return null;
327
+ let u = [], g = 0;
328
+ if (a && i[0]) {
329
+ const b = i[0];
330
+ u = Array.from(b.cells).map((_, k) => {
331
+ var S;
332
+ return ((S = _.textContent) == null ? void 0 : S.trim()) || "" || `Column${k + 1}`;
333
+ }), g = 1;
334
+ } else {
335
+ const b = i[0];
336
+ u = Array.from(b.cells).map((_, k) => `Column${k + 1}`);
337
+ }
338
+ const h = [], w = e ? i.slice(g, g + e) : i.slice(g);
339
+ for (const b of w) {
340
+ const _ = Array.from(b.cells);
341
+ if (s && _.every((x) => {
342
+ var S;
343
+ return !((S = x.textContent) != null && S.trim());
344
+ }))
345
+ continue;
346
+ const k = {};
347
+ _.forEach((x, S) => {
348
+ var M;
349
+ const z = u[S] || `Column${S + 1}`;
350
+ let q = ((M = x.textContent) == null ? void 0 : M.trim()) || "";
351
+ if (t && q) {
352
+ const N = parseFloat(q);
353
+ !isNaN(N) && q === N.toString() && (q = N);
354
+ }
355
+ k[z] = q;
356
+ }), h.push(k);
357
+ }
358
+ return {
359
+ schema: t && h.length > 0 ? I(h, "Extracted Table") : ae(u, h.length),
360
+ data: h,
361
+ source: "dom",
362
+ metadata: {
363
+ selector: n,
364
+ rowCount: h.length,
365
+ columnCount: u.length,
366
+ extractedAt: /* @__PURE__ */ new Date()
367
+ }
368
+ };
369
+ }
370
+ function se(l, n, a = {}) {
371
+ const { maxRows: e, inferTypes: t = !0 } = a, s = e ? l.slice(0, e) : l;
372
+ let r;
373
+ return n && n.length > 0 ? r = {
374
+ name: "Vue Data Grid",
375
+ columns: n.map((o) => ({
376
+ name: o.field,
377
+ type: t && s.length > 0 ? B(s, o.field) : "string",
378
+ nullable: !0
379
+ })),
380
+ rowCount: s.length
381
+ } : s.length > 0 ? r = I(s, "Vue Data Grid") : r = { name: "Vue Data Grid", columns: [], rowCount: 0 }, {
382
+ schema: r,
383
+ data: s,
384
+ source: "vue",
385
+ metadata: {
386
+ rowCount: s.length,
387
+ columnCount: r.columns.length,
388
+ extractedAt: /* @__PURE__ */ new Date()
389
+ }
390
+ };
391
+ }
392
+ function ae(l, n = 0) {
393
+ return {
394
+ name: "Extracted Table",
395
+ columns: l.map((a) => ({
396
+ name: a,
397
+ type: "string",
398
+ nullable: !0
399
+ })),
400
+ rowCount: n
401
+ };
402
+ }
403
+ class oe {
404
+ constructor(n, a) {
405
+ this.config = {
406
+ timeout: 3e4,
407
+ ...n
408
+ }, a && (this.qaEngine = new P(a));
409
+ }
410
+ /**
411
+ * Initialize or update Q&A engine
412
+ */
413
+ initializeQA(n) {
414
+ this.qaEngine = new P(n);
8
415
  }
9
416
  /**
10
417
  * Generic API call to TFM endpoint
11
418
  */
12
- async callTFM(s) {
13
- const e = Date.now();
419
+ async callTFM(n) {
420
+ const a = Date.now();
14
421
  try {
15
- const n = await fetch(this.config.baseUrl, {
422
+ const e = await fetch(this.config.baseUrl, {
16
423
  method: "POST",
17
424
  headers: {
18
425
  "Content-Type": "application/json",
@@ -20,31 +427,31 @@ class N {
20
427
  ...this.config.headers
21
428
  },
22
429
  body: JSON.stringify({
23
- ...s,
430
+ ...n,
24
431
  model: this.config.model
25
432
  }),
26
433
  signal: AbortSignal.timeout(this.config.timeout || 3e4)
27
434
  });
28
- if (!n.ok) {
29
- const r = await n.text();
30
- throw new Error(`TFM API error: ${n.status} - ${r}`);
435
+ if (!e.ok) {
436
+ const r = await e.text();
437
+ throw new Error(`TFM API error: ${e.status} - ${r}`);
31
438
  }
32
- const t = await n.json(), i = Date.now() - e;
439
+ const t = await e.json(), s = Date.now() - a;
33
440
  return {
34
441
  success: !0,
35
442
  result: t.result || t,
36
443
  metadata: {
37
- processingTime: i,
444
+ processingTime: s,
38
445
  model: this.config.model || "unknown",
39
446
  version: t.version
40
447
  }
41
448
  };
42
- } catch (n) {
449
+ } catch (e) {
43
450
  return {
44
451
  success: !1,
45
- error: n instanceof Error ? n.message : "Unknown error",
452
+ error: e instanceof Error ? e.message : "Unknown error",
46
453
  metadata: {
47
- processingTime: Date.now() - e,
454
+ processingTime: Date.now() - a,
48
455
  model: this.config.model || "unknown"
49
456
  }
50
457
  };
@@ -53,255 +460,467 @@ class N {
53
460
  /**
54
461
  * Perform analysis on tabular data
55
462
  */
56
- async analyze(s) {
57
- const e = {
58
- operation: s.type,
59
- data: s.data,
60
- schema: s.schema,
61
- parameters: s.options
62
- }, n = await this.callTFM(e);
63
- if (!n.success)
64
- throw new Error(n.error || "Analysis failed");
65
- return this.parseAnalysisResult(s.type, n.result, n.metadata);
463
+ async analyze(n) {
464
+ const a = {
465
+ operation: n.type,
466
+ data: n.data,
467
+ schema: n.schema,
468
+ parameters: n.options
469
+ }, e = await this.callTFM(a);
470
+ if (!e.success)
471
+ throw new Error(e.error || "Analysis failed");
472
+ return this.parseAnalysisResult(n.type, e.result, e.metadata);
66
473
  }
67
474
  /**
68
475
  * Parse TFM response into structured AnalysisResult
69
476
  */
70
- parseAnalysisResult(s, e, n) {
477
+ parseAnalysisResult(n, a, e) {
71
478
  const t = {
72
- type: s,
479
+ type: n,
73
480
  timestamp: /* @__PURE__ */ new Date(),
74
- summary: e.summary || "",
75
- insights: e.insights || [],
76
- recommendations: e.recommendations,
77
- confidence: e.confidence || 0.8,
78
- processingTime: n == null ? void 0 : n.processingTime
481
+ summary: a.summary || "",
482
+ insights: a.insights || [],
483
+ recommendations: a.recommendations,
484
+ confidence: a.confidence || 0.8,
485
+ processingTime: e == null ? void 0 : e.processingTime
79
486
  };
80
- switch (s) {
487
+ switch (n) {
81
488
  case "descriptive_stats":
82
489
  return {
83
490
  ...t,
84
- descriptiveStats: e.stats || e.descriptiveStats
491
+ descriptiveStats: a.stats || a.descriptiveStats
85
492
  };
86
493
  case "anomaly_detection":
87
494
  return {
88
495
  ...t,
89
- anomalies: e.anomalies || []
496
+ anomalies: a.anomalies || []
90
497
  };
91
498
  case "segmentation":
92
499
  case "clustering":
93
500
  return {
94
501
  ...t,
95
- clusters: e.clusters || []
502
+ clusters: a.clusters || []
96
503
  };
97
504
  case "prediction":
98
505
  return {
99
506
  ...t,
100
- predictions: e.predictions || e
507
+ predictions: a.predictions || a
101
508
  };
102
509
  case "correlation":
103
510
  return {
104
511
  ...t,
105
- correlations: e.correlations || e
512
+ correlations: a.correlations || a
513
+ };
514
+ case "summary":
515
+ return {
516
+ ...t,
517
+ aiSummary: a.summary || a
518
+ };
519
+ case "qa":
520
+ return {
521
+ ...t,
522
+ qaAnswer: a.answer || a
106
523
  };
107
524
  default:
108
525
  return t;
109
526
  }
110
527
  }
528
+ /**
529
+ * Ask a question about the data (Q&A)
530
+ */
531
+ async askQuestion(n) {
532
+ if (!this.qaEngine)
533
+ throw new Error("Q&A engine not initialized. Call initializeQA() first.");
534
+ return this.qaEngine.answerQuestion(n);
535
+ }
536
+ /**
537
+ * Generate AI summary of table data
538
+ */
539
+ async generateSummary(n, a) {
540
+ const e = {
541
+ type: "summary",
542
+ data: n,
543
+ schema: a
544
+ }, t = await this.analyze(e);
545
+ if (!t.aiSummary)
546
+ throw new Error("Failed to generate summary");
547
+ return t.aiSummary;
548
+ }
549
+ /**
550
+ * Extract table from DOM
551
+ */
552
+ extractFromDOM(n) {
553
+ return ne(n);
554
+ }
555
+ /**
556
+ * Normalize Vue data grid data
557
+ */
558
+ normalizeVueData(n, a, e) {
559
+ return se(n, a, e);
560
+ }
111
561
  /**
112
562
  * Update configuration
113
563
  */
114
- updateConfig(s) {
115
- this.config = { ...this.config, ...s };
564
+ updateConfig(n) {
565
+ this.config = { ...this.config, ...n };
116
566
  }
117
567
  /**
118
568
  * Get current configuration (without sensitive data)
119
569
  */
120
570
  getConfig() {
121
- const { apiKey: s, ...e } = this.config;
122
- return e;
571
+ const { apiKey: n, ...a } = this.config;
572
+ return a;
123
573
  }
124
574
  }
125
- function T(c, s) {
126
- if (c.length === 0)
127
- return { columns: [], rowCount: 0, name: s };
128
- const e = c[0];
129
- return {
130
- columns: Object.keys(e).map((t) => {
131
- const i = $(c, t);
132
- return {
133
- name: t,
134
- type: i,
135
- nullable: c.some((r) => r[t] == null)
136
- };
137
- }),
138
- rowCount: c.length,
139
- name: s
140
- };
141
- }
142
- function $(c, s) {
143
- const e = c.map((t) => t[s]).filter((t) => t != null);
144
- if (e.length === 0) return "string";
145
- if (e.every((t) => typeof t == "number" || !isNaN(Number(t))))
146
- return "number";
147
- if (e.every((t) => typeof t == "boolean" || t === "true" || t === "false"))
148
- return "boolean";
149
- if (e.every((t) => !isNaN(Date.parse(t))))
150
- return "date";
151
- const n = new Set(e);
152
- return n.size < e.length * 0.5 && n.size < 20 ? "categorical" : "string";
153
- }
154
- function A(c, s, e) {
155
- const n = c.map((l) => l[s]).filter((l) => l != null), t = n.length, i = c.length - t, r = {
156
- column: s,
157
- count: t,
158
- nullCount: i
159
- };
160
- if (e === "number") {
161
- const l = n.map(Number).filter((o) => !isNaN(o));
162
- if (l.length > 0) {
163
- const o = [...l].sort((u, d) => u - d), p = l.reduce((u, d) => u + d, 0);
164
- r.mean = p / l.length, r.median = o[Math.floor(o.length / 2)], r.min = o[0], r.max = o[o.length - 1];
165
- const h = l.reduce((u, d) => u + Math.pow(d - r.mean, 2), 0) / l.length;
166
- r.std = Math.sqrt(h), r.percentiles = {
167
- 25: o[Math.floor(o.length * 0.25)],
168
- 50: r.median,
169
- 75: o[Math.floor(o.length * 0.75)],
170
- 90: o[Math.floor(o.length * 0.9)]
171
- };
172
- }
173
- } else {
174
- const l = new Set(n);
175
- r.uniqueValues = l.size;
176
- const o = {};
177
- n.forEach((h) => {
178
- const u = String(h);
179
- o[u] = (o[u] || 0) + 1;
180
- });
181
- const p = Math.max(...Object.values(o));
182
- r.mode = Object.keys(o).find((h) => o[h] === p);
183
- }
184
- return r;
185
- }
186
- function F(c, s, e = 0.5) {
187
- const n = [], t = 1.5 + (1 - e) * 1.5;
188
- return s.forEach((i) => {
189
- const r = c.map((m, g) => ({ value: Number(m[i]), idx: g })).filter((m) => !isNaN(m.value));
190
- if (r.length === 0) return;
191
- const l = [...r].sort((m, g) => m.value - g.value), o = l[Math.floor(l.length * 0.25)].value, p = l[Math.floor(l.length * 0.75)].value, h = p - o, u = o - t * h, d = p + t * h;
192
- r.forEach(({ value: m, idx: g }) => {
193
- if (m < u || m > d) {
194
- const v = n.find((a) => a.rowIndex === g), S = m < u ? `${i}: ${m.toFixed(2)} < ${u.toFixed(2)}` : `${i}: ${m.toFixed(2)} > ${d.toFixed(2)}`;
195
- v ? (v.reasons.push(S), v.affectedColumns.push(i), v.score = Math.min(1, v.score + 0.2)) : n.push({
196
- rowIndex: g,
197
- row: c[g],
198
- score: 0.7,
199
- reasons: [S],
200
- affectedColumns: [i]
201
- });
202
- }
203
- });
204
- }), n.sort((i, r) => r.score - i.score);
205
- }
206
- function E(c) {
207
- const s = new N(c.config), e = M(!1), n = M(null), t = M(null), i = c.data || M([]), r = c.schema || M(null), l = c.useLocalFallback !== !1;
208
- async function o(a, f) {
209
- e.value = !0, n.value = null;
575
+ function Be(l) {
576
+ const n = new oe(l.config, l.qaConfig), a = C(!1), e = C(null), t = C(null), s = l.data || C([]), r = l.schema || C(null), o = C([]), i = C([]), u = C(null), g = l.maxQuestionHistory || 50, h = l.useLocalFallback !== !1;
577
+ async function w(c, f) {
578
+ a.value = !0, e.value = null;
210
579
  try {
211
580
  const y = {
212
- type: a,
213
- data: i.value,
581
+ type: c,
582
+ data: s.value,
214
583
  schema: r.value || void 0,
215
584
  options: f
216
- }, w = await s.analyze(y);
217
- return t.value = w, w;
585
+ }, $ = await n.analyze(y);
586
+ return t.value = $, $;
218
587
  } catch (y) {
219
- if (n.value = y instanceof Error ? y : new Error("Analysis failed"), l)
220
- return p(a, f);
221
- throw n.value;
588
+ if (e.value = y instanceof Error ? y : new Error("Analysis failed"), h)
589
+ return A(c, f);
590
+ throw e.value;
222
591
  } finally {
223
- e.value = !1;
592
+ a.value = !1;
224
593
  }
225
594
  }
226
- function p(a, f) {
227
- const y = r.value || T(i.value);
228
- switch (a) {
595
+ function A(c, f) {
596
+ const y = r.value || I(s.value);
597
+ switch (c) {
229
598
  case "descriptive_stats": {
230
- const w = y.columns.map(
231
- (b) => A(i.value, b.name, b.type)
599
+ const $ = y.columns.map(
600
+ (E) => H(s.value, E.name, E.type)
232
601
  );
233
602
  return {
234
- type: a,
603
+ type: c,
235
604
  timestamp: /* @__PURE__ */ new Date(),
236
- descriptiveStats: w,
237
- summary: `Calculated statistics for ${w.length} columns`,
605
+ descriptiveStats: $,
606
+ summary: `Calculated statistics for ${$.length} columns`,
238
607
  insights: [],
239
608
  confidence: 0.9
240
609
  };
241
610
  }
242
611
  case "anomaly_detection": {
243
- const w = y.columns.filter((C) => C.type === "number").map((C) => C.name), b = F(
244
- i.value,
245
- w,
612
+ const $ = y.columns.filter((D) => D.type === "number").map((D) => D.name), E = te(
613
+ s.value,
614
+ $,
246
615
  f == null ? void 0 : f.sensitivity
247
616
  );
248
617
  return {
249
- type: a,
618
+ type: c,
250
619
  timestamp: /* @__PURE__ */ new Date(),
251
- anomalies: b,
252
- summary: `Found ${b.length} anomalies`,
253
- insights: b.slice(0, 3).map((C) => C.reasons[0]),
620
+ anomalies: E,
621
+ summary: `Found ${E.length} anomalies`,
622
+ insights: E.slice(0, 3).map((D) => D.reasons[0]),
254
623
  confidence: 0.8
255
624
  };
256
625
  }
257
626
  default:
258
- throw new Error(`Local analysis not supported for type: ${a}`);
627
+ throw new Error(`Local analysis not supported for type: ${c}`);
259
628
  }
260
629
  }
261
- async function h() {
262
- return (await o("descriptive_stats")).descriptiveStats || [];
630
+ async function b() {
631
+ return (await w("descriptive_stats")).descriptiveStats || [];
263
632
  }
264
- async function u(a, f) {
265
- return (await o("anomaly_detection", { sensitivity: f, features: a })).anomalies || [];
633
+ async function _(c, f) {
634
+ return (await w("anomaly_detection", { sensitivity: f, features: c })).anomalies || [];
266
635
  }
267
- async function d(a, f = 3) {
268
- return o("clustering", { features: a, numClusters: f });
636
+ async function k(c, f = 3) {
637
+ return w("clustering", { features: c, numClusters: f });
269
638
  }
270
- async function m(a, f) {
271
- return o("prediction", { targetColumn: a, ...f });
639
+ async function x(c, f) {
640
+ return w("prediction", { targetColumn: c, ...f });
272
641
  }
273
- function g(a) {
274
- s.updateConfig(a);
642
+ function S(c) {
643
+ n.updateConfig(c);
275
644
  }
276
- function v(a, f = !0) {
277
- i.value = a, f && (r.value = T(a));
645
+ function z(c, f = !0) {
646
+ s.value = c, f && (r.value = I(c));
278
647
  }
279
- function S() {
280
- e.value = !1, n.value = null, t.value = null;
648
+ function q() {
649
+ a.value = !1, e.value = null, t.value = null, o.value = [], i.value = [], u.value = null;
650
+ }
651
+ async function M(c, f) {
652
+ a.value = !0, e.value = null;
653
+ try {
654
+ const y = r.value || I(s.value), $ = {
655
+ question: c,
656
+ schema: y,
657
+ data: s.value,
658
+ sampleSize: 100,
659
+ includeAggregates: !0,
660
+ ...f
661
+ }, D = (await n.askQuestion($)).answer, G = {
662
+ id: D.questionId,
663
+ text: c,
664
+ timestamp: /* @__PURE__ */ new Date(),
665
+ context: {
666
+ tableSchema: y,
667
+ rowCount: s.value.length
668
+ }
669
+ };
670
+ return o.value.push(G), i.value.push(D), u.value = D, o.value.length > g && (o.value.shift(), i.value.shift()), D;
671
+ } catch (y) {
672
+ throw e.value = y instanceof Error ? y : new Error("Q&A failed"), e.value;
673
+ } finally {
674
+ a.value = !1;
675
+ }
676
+ }
677
+ async function N() {
678
+ a.value = !0, e.value = null;
679
+ try {
680
+ const c = r.value || I(s.value);
681
+ return await n.generateSummary(s.value, c);
682
+ } catch (c) {
683
+ throw e.value = c instanceof Error ? c : new Error("Summary generation failed"), e.value;
684
+ } finally {
685
+ a.value = !1;
686
+ }
687
+ }
688
+ function R() {
689
+ o.value = [], i.value = [], u.value = null;
690
+ }
691
+ function J(c) {
692
+ const f = n.extractFromDOM(c);
693
+ return f && (s.value = f.data, r.value = f.schema), f;
694
+ }
695
+ function K(c, f, y) {
696
+ const $ = n.normalizeVueData(c, f, y);
697
+ s.value = $.data, r.value = $.schema;
698
+ }
699
+ function U(c) {
700
+ n.initializeQA(c);
281
701
  }
282
702
  return {
283
- client: s,
284
- loading: e,
285
- error: n,
703
+ client: n,
704
+ loading: a,
705
+ error: e,
286
706
  lastResult: t,
287
- data: i,
707
+ data: s,
288
708
  schema: r,
289
- analyze: o,
290
- getDescriptiveStats: h,
291
- detectAnomalies: u,
292
- performClustering: d,
293
- predict: m,
294
- updateConfig: g,
295
- setData: v,
296
- reset: S
709
+ questionHistory: o,
710
+ answerHistory: i,
711
+ lastAnswer: u,
712
+ analyze: w,
713
+ getDescriptiveStats: b,
714
+ detectAnomalies: _,
715
+ performClustering: k,
716
+ predict: x,
717
+ askQuestion: M,
718
+ generateSummary: N,
719
+ clearHistory: R,
720
+ extractFromDOM: J,
721
+ loadFromVueGrid: K,
722
+ updateConfig: S,
723
+ initializeQA: U,
724
+ setData: z,
725
+ reset: q
297
726
  };
298
727
  }
728
+ const re = { class: "ti-question-input" }, ie = { class: "ti-input-wrapper" }, le = ["placeholder", "disabled", "onKeydown"], ce = ["disabled"], ue = { key: 0 }, me = {
729
+ key: 1,
730
+ class: "ti-loading"
731
+ }, de = {
732
+ key: 0,
733
+ class: "ti-hint"
734
+ }, pe = /* @__PURE__ */ F({
735
+ __name: "QuestionInput",
736
+ props: {
737
+ placeholder: { default: "Ask a question about this data..." },
738
+ submitLabel: { default: "Ask" },
739
+ loadingLabel: { default: "Processing..." },
740
+ hint: { default: "Press Enter to submit, Shift+Enter for new line" },
741
+ showHint: { type: Boolean, default: !0 },
742
+ disabled: { type: Boolean, default: !1 },
743
+ loading: { type: Boolean, default: !1 }
744
+ },
745
+ emits: ["submit"],
746
+ setup(l, { emit: n }) {
747
+ const a = l, e = n, t = C("");
748
+ function s() {
749
+ t.value.trim() && !a.disabled && !a.loading && (e("submit", t.value.trim()), t.value = "");
750
+ }
751
+ function r(o) {
752
+ }
753
+ return (o, i) => (p(), d("div", re, [
754
+ m("div", ie, [
755
+ Y(m("textarea", {
756
+ "onUpdate:modelValue": i[0] || (i[0] = (u) => t.value = u),
757
+ placeholder: o.placeholder,
758
+ disabled: o.disabled,
759
+ class: "ti-textarea",
760
+ rows: "2",
761
+ onKeydown: [
762
+ j(L(s, ["exact", "prevent"]), ["enter"]),
763
+ j(L(r, ["shift"]), ["enter"])
764
+ ]
765
+ }, null, 40, le), [
766
+ [W, t.value]
767
+ ]),
768
+ m("button", {
769
+ disabled: o.disabled || !t.value.trim(),
770
+ class: "ti-submit-btn",
771
+ onClick: s
772
+ }, [
773
+ o.loading ? (p(), d("span", me, v(o.loadingLabel), 1)) : (p(), d("span", ue, v(o.submitLabel), 1))
774
+ ], 8, ce)
775
+ ]),
776
+ o.showHint ? (p(), d("div", de, v(o.hint), 1)) : T("", !0)
777
+ ]));
778
+ }
779
+ }), V = (l, n) => {
780
+ const a = l.__vccOpts || l;
781
+ for (const [e, t] of n)
782
+ a[e] = t;
783
+ return a;
784
+ }, He = /* @__PURE__ */ V(pe, [["__scopeId", "data-v-90db5921"]]), he = { class: "ti-answer-header" }, fe = { class: "ti-answer-icon" }, ge = { key: 0 }, we = { key: 1 }, ye = { class: "ti-answer-meta" }, ve = { class: "ti-confidence" }, be = { class: "ti-timestamp" }, Ae = { class: "ti-answer-text" }, _e = {
785
+ key: 0,
786
+ class: "ti-approximate-notice"
787
+ }, $e = {
788
+ key: 1,
789
+ class: "ti-reason"
790
+ }, ke = {
791
+ key: 2,
792
+ class: "ti-supporting-data"
793
+ }, Se = {
794
+ key: 0,
795
+ class: "ti-supporting-content"
796
+ }, De = {
797
+ key: 0,
798
+ class: "ti-aggregates"
799
+ }, Ce = {
800
+ key: 1,
801
+ class: "ti-rows"
802
+ }, Te = { class: "ti-table-wrapper" }, xe = { class: "ti-table" }, qe = /* @__PURE__ */ F({
803
+ __name: "AnswerDisplay",
804
+ props: {
805
+ answer: {}
806
+ },
807
+ setup(l) {
808
+ const n = C(!1);
809
+ function a(e) {
810
+ return new Date(e).toLocaleTimeString();
811
+ }
812
+ return (e, t) => (p(), d("div", {
813
+ class: X(["ti-answer-display", { "ti-cannot-answer": e.answer.cannotAnswer }])
814
+ }, [
815
+ m("div", he, [
816
+ m("div", fe, [
817
+ e.answer.cannotAnswer ? (p(), d("span", we, "⚠️")) : (p(), d("span", ge, "💡"))
818
+ ]),
819
+ m("div", ye, [
820
+ m("div", ve, " Confidence: " + v(Math.round(e.answer.confidence * 100)) + "% ", 1),
821
+ m("div", be, v(a(e.answer.timestamp)), 1)
822
+ ])
823
+ ]),
824
+ m("div", Ae, v(e.answer.text), 1),
825
+ e.answer.isApproximate ? (p(), d("div", _e, " ℹ️ This answer is based on sampled data and may be approximate. ")) : T("", !0),
826
+ e.answer.reason && e.answer.cannotAnswer ? (p(), d("div", $e, [
827
+ t[1] || (t[1] = m("strong", null, "Reason:", -1)),
828
+ Z(" " + v(e.answer.reason), 1)
829
+ ])) : T("", !0),
830
+ e.answer.supportingData ? (p(), d("div", ke, [
831
+ m("button", {
832
+ class: "ti-toggle-btn",
833
+ onClick: t[0] || (t[0] = (s) => n.value = !n.value)
834
+ }, v(n.value ? "▼" : "▶") + " Supporting Data ", 1),
835
+ n.value ? (p(), d("div", Se, [
836
+ e.answer.supportingData.aggregates ? (p(), d("div", De, [
837
+ t[2] || (t[2] = m("h4", null, "Aggregates:", -1)),
838
+ m("pre", null, v(JSON.stringify(e.answer.supportingData.aggregates, null, 2)), 1)
839
+ ])) : T("", !0),
840
+ e.answer.supportingData.rows && e.answer.supportingData.rows.length > 0 ? (p(), d("div", Ce, [
841
+ m("h4", null, "Sample Rows (" + v(e.answer.supportingData.rows.length) + "):", 1),
842
+ m("div", Te, [
843
+ m("table", xe, [
844
+ m("thead", null, [
845
+ m("tr", null, [
846
+ (p(!0), d(O, null, Q(Object.keys(e.answer.supportingData.rows[0]), (s, r) => (p(), d("th", { key: r }, v(s), 1))), 128))
847
+ ])
848
+ ]),
849
+ m("tbody", null, [
850
+ (p(!0), d(O, null, Q(e.answer.supportingData.rows.slice(0, 5), (s, r) => (p(), d("tr", { key: r }, [
851
+ (p(!0), d(O, null, Q(Object.keys(s), (o, i) => (p(), d("td", { key: i }, v(s[o]), 1))), 128))
852
+ ]))), 128))
853
+ ])
854
+ ])
855
+ ])
856
+ ])) : T("", !0)
857
+ ])) : T("", !0)
858
+ ])) : T("", !0)
859
+ ], 2));
860
+ }
861
+ }), Re = /* @__PURE__ */ V(qe, [["__scopeId", "data-v-d1aaae1d"]]), Ee = { class: "ti-question-history" }, Ie = { class: "ti-history-header" }, Ne = {
862
+ key: 0,
863
+ class: "ti-empty-state"
864
+ }, Me = {
865
+ key: 1,
866
+ class: "ti-history-list"
867
+ }, Oe = ["onClick"], Qe = { class: "ti-question-header" }, ze = { class: "ti-question-number" }, Fe = { class: "ti-question-time" }, Ve = { class: "ti-question-text" }, je = {
868
+ key: 0,
869
+ class: "ti-question-context"
870
+ }, Le = /* @__PURE__ */ F({
871
+ __name: "QuestionHistory",
872
+ props: {
873
+ questions: {}
874
+ },
875
+ emits: ["clear", "select"],
876
+ setup(l, { emit: n }) {
877
+ const a = l, e = ee(() => [...a.questions].reverse());
878
+ function t(s) {
879
+ const r = new Date(s), i = (/* @__PURE__ */ new Date()).getTime() - r.getTime(), u = Math.floor(i / 6e4), g = Math.floor(i / 36e5), h = Math.floor(i / 864e5);
880
+ return u < 1 ? "Just now" : u < 60 ? `${u}m ago` : g < 24 ? `${g}h ago` : `${h}d ago`;
881
+ }
882
+ return (s, r) => (p(), d("div", Ee, [
883
+ m("div", Ie, [
884
+ r[1] || (r[1] = m("h3", null, "Question History", -1)),
885
+ s.questions.length > 0 ? (p(), d("button", {
886
+ key: 0,
887
+ class: "ti-clear-btn",
888
+ onClick: r[0] || (r[0] = (o) => s.$emit("clear"))
889
+ }, " Clear History ")) : T("", !0)
890
+ ]),
891
+ s.questions.length === 0 ? (p(), d("div", Ne, r[2] || (r[2] = [
892
+ m("div", { class: "ti-empty-icon" }, "💬", -1),
893
+ m("p", null, "No questions asked yet", -1),
894
+ m("p", { class: "ti-empty-hint" }, "Ask a question about your data to get started", -1)
895
+ ]))) : (p(), d("div", Me, [
896
+ (p(!0), d(O, null, Q(e.value, (o, i) => (p(), d("div", {
897
+ key: o.id,
898
+ class: "ti-history-item",
899
+ onClick: (u) => s.$emit("select", o)
900
+ }, [
901
+ m("div", Qe, [
902
+ m("span", ze, "#" + v(s.questions.length - i), 1),
903
+ m("span", Fe, v(t(o.timestamp)), 1)
904
+ ]),
905
+ m("div", Ve, v(o.text), 1),
906
+ o.context ? (p(), d("div", je, v(o.context.rowCount) + " rows ", 1)) : T("", !0)
907
+ ], 8, Oe))), 128))
908
+ ]))
909
+ ]));
910
+ }
911
+ }), Je = /* @__PURE__ */ V(Le, [["__scopeId", "data-v-c66393d9"]]);
299
912
  export {
300
- N as TabularIntelligence,
301
- A as calculateStats,
302
- F as detectAnomalies,
303
- $ as inferColumnType,
304
- T as inferSchema,
305
- E as useTabularIntelligence
913
+ Re as AnswerDisplay,
914
+ P as QAEngine,
915
+ Je as QuestionHistory,
916
+ He as QuestionInput,
917
+ oe as TabularIntelligence,
918
+ H as calculateStats,
919
+ te as detectAnomalies,
920
+ ne as extractFromDOM,
921
+ B as inferColumnType,
922
+ I as inferSchema,
923
+ se as normalizeVueData,
924
+ Be as useTabularIntelligence
306
925
  };
307
926
  //# sourceMappingURL=index.mjs.map