@eshal-bot/chat-widget 0.1.92 → 0.1.94

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.
@@ -89272,12 +89272,6 @@
89272
89272
  const MONTH_NAMES = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
89273
89273
  const CURRENCY_KEY_RE = /(^|[_\W])(price|salary|cost|amount|revenue|expense|total|value|budget|spend|income|sale|balance)/i;
89274
89274
  const MONTH_KEY_RE = /(^|[_\W])month/i;
89275
- const USD_FORMATTER = new Intl.NumberFormat('en-US', {
89276
- style: 'currency',
89277
- currency: 'USD',
89278
- minimumFractionDigits: 2,
89279
- maximumFractionDigits: 2
89280
- });
89281
89275
  function prettifyLabel(value) {
89282
89276
  if (value === null || value === undefined) return '';
89283
89277
  const s = String(value);
@@ -89340,31 +89334,52 @@
89340
89334
  }
89341
89335
 
89342
89336
  // Numeric string under a money column, e.g. "81,200" / "105444" / "-1,250.50".
89343
- // Markdown tables (the common concierge path) arrive as text cells, so a
89344
- // salary value is the STRING "81,200" - not a number - and skips the
89345
- // USD_FORMATTER branch below. We prefix "$" while keeping the source's own
89346
- // grouping/decimals so it reads "$81,200" (not "$81,200.00"). A leading "$"
89347
- // already present makes the regex miss, so we never double-prefix.
89348
- const _NUMERIC_STRING_RE = /^-?\d[\d,]*(\.\d+)?$/;
89337
+ // Table-cell formatting, kept IN LOCKSTEP with the Testing-Lab (frontend
89338
+ // chartShared.tsx: formatDateCell / formatCurrencyCellString) and SDK copies so
89339
+ // all three surfaces render DB tables identically. Two rules:
89340
+ // 1. ISO date/datetime → "Dec 9, 2021" (parity with Testing Lab).
89341
+ // 2. Bare numeric string in a money-named column → comma-group, and NEVER
89342
+ // synthesize a currency symbol — the DB is the source of truth for "$".
89343
+ // A value that already carries a symbol ("$71000", "₹560") fails
89344
+ // _BARE_NUMBER_RE and is passed through verbatim, so we don't double-format.
89345
+ const _BARE_NUMBER_RE = /^-?\d+(\.\d+)?$/;
89346
+ const _MONTH_NAMES = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
89347
+ const _ISO_DATETIME_CELL_RE = /^\d{4}-\d{2}-\d{2}([T ]\d{2}:\d{2}(:\d{2})?(\.\d+)?(Z|[+-]\d{2}:?\d{2})?)?$/;
89348
+ function _formatDateCell(value) {
89349
+ if (typeof value !== 'string') return null;
89350
+ if (!_ISO_DATETIME_CELL_RE.test(value.trim())) return null;
89351
+ const d = new Date(value);
89352
+ if (isNaN(d.getTime())) return null;
89353
+ const hasTime = /[T ]\d{2}:\d{2}/.test(value) && (d.getUTCHours() !== 0 || d.getUTCMinutes() !== 0 || d.getUTCSeconds() !== 0);
89354
+ const dateStr = "".concat(_MONTH_NAMES[d.getUTCMonth()], " ").concat(d.getUTCDate(), ", ").concat(d.getUTCFullYear());
89355
+ if (!hasTime) return dateStr;
89356
+ const h = d.getUTCHours();
89357
+ const ampm = h >= 12 ? 'PM' : 'AM';
89358
+ const h12 = h % 12 || 12;
89359
+ const mm = String(d.getUTCMinutes()).padStart(2, '0');
89360
+ return "".concat(dateStr, ", ").concat(h12, ":").concat(mm, " ").concat(ampm);
89361
+ }
89362
+ function _commaGroup(n) {
89363
+ return Number.isInteger(n) ? n.toLocaleString('en-US') : Number(n.toFixed(2)).toLocaleString('en-US');
89364
+ }
89349
89365
  function formatCell(v, columnKey) {
89350
89366
  if (v == null) return '';
89351
89367
  if (typeof v === 'number') {
89352
- // Currency-keyed numeric cells in tables also get $ + decimals so
89353
- // the table next to a chart agrees on its number formatting.
89354
- if (isCurrencyKey(columnKey)) return USD_FORMATTER.format(v);
89355
- return Number.isInteger(v) ? String(v) : v.toFixed(2);
89368
+ // Comma-group; NEVER synthesize a currency symbol (DB owns symbols).
89369
+ return _commaGroup(v);
89356
89370
  }
89357
89371
  if (typeof v === 'object') return JSON.stringify(v);
89358
- // Numeric string under a money-named column → prefix "$" (Bug: concierge
89359
- // salary table showed "81,200" with no currency symbol).
89360
- if (isCurrencyKey(columnKey) && _NUMERIC_STRING_RE.test(String(v).trim())) {
89361
- return "$".concat(String(v).trim());
89362
- }
89363
- // String cells: prettify snake_case category labels (e.g.
89364
- // `office_supplies` → "Office Supplies") so the table reads
89365
- // consistently with the chart's X-axis ticks on the same data.
89366
- // Conservative: anything not a clean lowercase_underscore token is
89367
- // returned verbatim, so paths/IDs/emails/slugs are preserved.
89372
+ const s = String(v).trim();
89373
+ // 1. ISO date/datetime → friendly date.
89374
+ const dateCell = _formatDateCell(s);
89375
+ if (dateCell) return dateCell;
89376
+ // 2. Bare numeric string in a money column → comma-group, NO "$".
89377
+ if (isCurrencyKey(columnKey) && _BARE_NUMBER_RE.test(s)) {
89378
+ const n = Number(s);
89379
+ if (Number.isFinite(n)) return _commaGroup(n);
89380
+ }
89381
+ // 3. Everything else: prettify snake_case labels; IDs/paths/emails/slugs and
89382
+ // any DB value already carrying a symbol pass through verbatim.
89368
89383
  return prettifyCategoryCell(v);
89369
89384
  }
89370
89385
 
@@ -91218,6 +91233,20 @@
91218
91233
  return lines.slice(0, start).join('\n');
91219
91234
  }
91220
91235
 
91236
+ // EV-2782: SQL aggregates (AVG(salary), etc.) come back from Postgres as a
91237
+ // NUMERIC with a fixed decimal scale, so the DB tool round-trips it as e.g.
91238
+ // `106500.00000000000` - trailing zero padding from the column's declared
91239
+ // precision, not a real value the agent computed. The agent quotes it
91240
+ // verbatim into its prose, so it reaches here as plain text. Collapse any
91241
+ // decimal whose digits past the 2nd place are ALL zero down to 2 decimals -
91242
+ // safe because a genuinely precise value (19.99, 3.14159) never has an
91243
+ // all-zero tail past position 2, so this only ever fires on exactly this
91244
+ // padding artifact. Mirrors the same fix in the frontend's
91245
+ // StreamingMarkdown.tsx (Testing Lab renderer).
91246
+ function sanitizeExcessDecimalPrecision(text) {
91247
+ return text.replace(/(\d+\.\d{2})0+(?!\d)/g, '$1');
91248
+ }
91249
+
91221
91250
  // The rich markdown renderer. Receives the already-animated `content`
91222
91251
  // (displayedContent from StreamingMarkdown) plus styling props. Renders only
91223
91252
  // the ReactMarkdown tree - the outer wrapper <div> and the streaming cursor
@@ -91665,7 +91694,7 @@
91665
91694
  }));
91666
91695
  }
91667
91696
  },
91668
- children: sanitizeStreamingContent(content, isStreaming)
91697
+ children: sanitizeExcessDecimalPrecision(sanitizeStreamingContent(content, isStreaming))
91669
91698
  });
91670
91699
  }
91671
91700