UNPKG

@fusedashlabs/ui9000-workspace

Version:

UI9000 workspace MCP. One tool, show_workspace, draws a chart from your table. Set TYPESAFE_API_KEY to let Jev choose the chart.

110 lines (109 loc) • 3.06 kB
/** * Column-oriented view of one dataset — the profiler's only input. * * A Table is the parsed shape of a CSV: header names plus raw cell text in row * order. The profiler never sees typed rows, so a fixture CSV and a live * dataset go through exactly the same classification. */ /** Rows in the table — the longest column wins if a CSV row was short. */ export function tableRowCount(table) { let rows = 0; for (const column of table.columns) { if (column.values.length > rows) rows = column.values.length; } return rows; } /** Row-oriented copy of a Table. Used to persist / profile, not as MCP tool output. */ export function tableToRows(table) { const rowCount = tableRowCount(table); const rows = []; for (let i = 0; i < rowCount; i += 1) { const row = {}; for (const column of table.columns) { row[column.name] = column.values[i] ?? ''; } rows.push(row); } return rows; } /** Header text reduced to letters and digits: `Created At` and `created_at` match. */ export function normalizeName(name) { return name.toLowerCase().replace(/[^a-z0-9]/g, ''); } /** * Minimal RFC 4180 reader: quoted fields, `""` escapes, CR/LF or LF, blank * lines skipped. Enough for fixtures; the profiler owns no other parsing. */ export function parseCsvTable(text) { const rows = parseRows(text); const header = rows.shift(); if (!header) return { columns: [] }; const columns = header.map((name) => ({ name: name.trim(), values: [] })); for (const row of rows) { for (const [index, column] of columns.entries()) { column.values.push(row[index] ?? ''); } } return { columns }; } function parseRows(text) { const rows = []; let row = []; let field = ''; let quoted = false; let i = 0; const endField = () => { row.push(field); field = ''; }; const endRow = () => { endField(); if (row.length > 1 || row[0] !== '') rows.push(row); row = []; }; while (i < text.length) { const char = text[i]; if (quoted) { if (char === '"') { if (text[i + 1] === '"') { field += '"'; i += 2; continue; } quoted = false; i += 1; continue; } field += char; i += 1; continue; } if (char === '"') { quoted = true; i += 1; continue; } if (char === ',') { endField(); i += 1; continue; } if (char === '\r') { i += 1; continue; } if (char === '\n') { endRow(); i += 1; continue; } field += char; i += 1; } if (field !== '' || row.length > 0) endRow(); return rows; }