@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.
64 lines (63 loc) • 2.3 kB
JavaScript
/**
* Frozen `_meta` keys for the chart App.
* chart-app reads this contract. It does not invent keys.
*
* `_meta.trace` is the decision record.
* `_meta.proposal` is optional and present only when an action is held.
* `ui.resourceUri` stays `ui://ui9000/chart`.
*/
export const META_RESOURCE_URI = 'ui://ui9000/chart';
export const FROZEN_META_KEYS = ['_meta.trace', '_meta.proposal', 'ui.resourceUri'];
const ROW_KEYS = new Set(['rows', 'data']);
/** The object chart-app is allowed to read. Resource URI is not renamed. */
export function workspaceMeta(input) {
return {
ui: {
resourceUri: input.resourceUri,
visibility: ['model', 'app'],
csp: input.csp,
},
'ui/resourceUri': input.resourceUri,
chartType: input.chartType,
dataUrl: input.dataUrl,
chartId: input.chartId,
...(input.trace ? { trace: input.trace } : {}),
...(input.proposal ? { proposal: input.proposal } : {}),
};
}
const DECISION_KEYS = new Set(['trace', 'proposal', 'proposals']);
/**
* Drops dataset `rows` everywhere.
* Drops a `data` array only inside a decision record (`trace`, `proposal`, `proposals`).
* A `data` array on the tool result itself is left alone.
*/
export function omitRowArrays(value, insideDecision = false) {
if (Array.isArray(value)) {
return value.map((item) => omitRowArrays(item, insideDecision));
}
if (!value || typeof value !== 'object')
return value;
const next = {};
for (const [key, child] of Object.entries(value)) {
if (Array.isArray(child) && key === 'rows')
continue;
if (Array.isArray(child) && key === 'data' && insideDecision)
continue;
const childInside = insideDecision || DECISION_KEYS.has(key);
next[key] = omitRowArrays(child, childInside);
}
return next;
}
export function containsRowArrays(value) {
if (Array.isArray(value))
return value.some(containsRowArrays);
if (!value || typeof value !== 'object')
return false;
for (const [key, child] of Object.entries(value)) {
if (ROW_KEYS.has(key) && Array.isArray(child))
return true;
if (containsRowArrays(child))
return true;
}
return false;
}