@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.
185 lines (184 loc) • 9.37 kB
TypeScript
import type { EngineCatalog } from '../spec/engine-catalog.js';
import type { DataProfile } from '../spec/data-profile.js';
import { type WorkspaceSpec } from '../spec/workspace-spec.js';
import { type ClassifiedColumn } from '../profiler/roles.js';
import { type Table } from '../profiler/table.js';
import { type SignDataLink } from './data-channel.js';
import { type IngestOptions, type StoredDataset } from './ingest-table.js';
import { type Trace, type TraceProposal } from '../trace/trace.js';
import { type JevChartRequest, type JevChartResponse } from '../jev/chart-choice.js';
export declare const SHOW_WORKSPACE_NAME = "show_workspace";
export declare const SHOW_WORKSPACE_CODES: readonly ["invalid_args", "rows_in_args", "invalid_ingest", "dataset_not_found", "unknown_intent", "missing_context", "missing_signer", "signer_failed", "leaky_handle", "missing_binds", "no_winner", "chart_unbuilt", "invalid_spec", "map_unrenderable"];
export type ShowWorkspaceCode = (typeof SHOW_WORKSPACE_CODES)[number];
export type ShowWorkspaceOk = {
ok: true;
spec: WorkspaceSpec;
summary: string;
/** Why this chart was drawn. The model should say it to the user. */
chartWhy?: string;
/** Closer chart from the column reading. The drawn chart stays the one named. */
suggestion?: string;
suggestionWhy?: string;
/** FuseDash chartType for the hosted MCP App. Absent when the View cannot render. */
chartType?: string;
/** Opaque id for the ingested table. Pass it on the next intent instead of csv. */
datasetId?: string;
rowCount?: number;
columns?: string[];
trace: Trace;
traceId: string;
/** Present only when a catalog action is held. A preview, not an execution. */
proposal?: TraceProposal;
};
export type ShowWorkspaceFail = {
ok: false;
code: ShowWorkspaceCode;
reason: string;
};
export type ShowWorkspaceResult = ShowWorkspaceOk | ShowWorkspaceFail;
export type ShowWorkspaceContext = {
catalog: EngineCatalog;
profile: DataProfile;
/** Dataset payload for the handle. Never copied into the MCP result. */
payload?: unknown;
/** Column names / control labels — not row objects. Used to satisfy catalog dataRoles. */
fields?: readonly string[];
/**
* Profiler classification. When set, binds map catalog roles to those columns
* (category→team, metric→incidents) instead of CSV order.
*/
classified?: readonly ClassifiedColumn[];
/**
* Tests inject a stub. Production omits this so `attachDataHandle` calls
* migrate `signDataLink`. A non-function value is `missing_signer`.
*/
signDataLink?: SignDataLink;
/** Hosted/production: csv + datasetId only. */
allowRemoteSources?: boolean;
maxBytes?: number;
cwd?: string;
/** Optional jail for csv paths. See MCP_DATASET_ROOT. */
datasetRoot?: string;
fetchImpl?: IngestOptions['fetchImpl'];
loadDataset?: (id: string) => StoredDataset | undefined | Promise<StoredDataset | undefined>;
/** Stdio session: keep the last ingested table for later `{ intent }` calls. */
rememberTable?: (table: Table) => void;
/**
* Column names from the previous call on this session. Reapplied when the
* caller reuses the table and omits `columns`. A new csv/url/path without
* `columns` clears it.
*/
selectedColumns?: readonly string[];
rememberColumns?: (names: readonly string[] | undefined) => void;
/**
* Production sets this from TYPESAFE_API_KEY. Tests inject a stub.
* Absent: a named chart still draws, and an unnamed chart uses decide().
*/
askJev?: (request: JevChartRequest) => Promise<JevChartResponse>;
};
export declare const SHOW_WORKSPACE_INPUT_SCHEMA: {
readonly type: "object";
readonly additionalProperties: false;
readonly required: readonly ["intent"];
readonly properties: {
readonly intent: {
readonly type: "string";
readonly enum: readonly ["spatial", "comparison", "summary", "form", "evidence", "graph"];
readonly description: "Closed objective. One of spatial, comparison, summary, form, evidence, graph. Do not invent values.";
};
readonly csv: {
readonly type: "string";
readonly description: "Pasted CSV including the header row. Use this when the user attached or pasted a table. Empty string means omit.";
};
readonly url: {
readonly type: "string";
readonly description: "http(s) URL to a CSV. Local/dev only — rejected on hosted/production. Empty string means omit.";
};
readonly path: {
readonly type: "string";
readonly description: "Local CSV path (absolute, or relative to cwd). Local/dev only. Empty string means omit.";
};
readonly datasetId: {
readonly type: "string";
readonly description: "Id returned by an earlier show_workspace on this table. Use instead of csv/url/path.";
};
readonly columns: {
readonly type: "array";
readonly items: {
readonly type: "string";
};
readonly description: "Step 1. Column names the user asked to chart. Omit to use the whole table. Names only, not cell values.";
};
readonly utterance: {
readonly type: "string";
readonly description: "The user's words, for Jev. Pass the request as they wrote it. Empty string means omit.";
};
readonly requestedChart: {
readonly type: "string";
readonly description: "Step 3. The chart the user asked for, in their words or an id from a previous reply. Omit when they did not name a chart. On a new table, a known chart the utterance does not name is ignored. An unknown name is kept. A datasetId call with no new csv, url, or path keeps the id.";
};
readonly confirm: {
readonly type: "boolean";
readonly description: "Ignored. The next call draws the chart the user picks. Pass it as requestedChart with the same datasetId.";
};
};
};
/**
* ~2–3 KB. Lists intents, not the 20 engine component ids.
* The model may send a CSV source; it must not send chart `data[]` rows.
*/
export declare const SHOW_WORKSPACE_DESCRIPTION: string;
export declare const SHOW_WORKSPACE_TOOL: {
name: string;
description: string;
inputSchema: {
readonly type: "object";
readonly additionalProperties: false;
readonly required: readonly ["intent"];
readonly properties: {
readonly intent: {
readonly type: "string";
readonly enum: readonly ["spatial", "comparison", "summary", "form", "evidence", "graph"];
readonly description: "Closed objective. One of spatial, comparison, summary, form, evidence, graph. Do not invent values.";
};
readonly csv: {
readonly type: "string";
readonly description: "Pasted CSV including the header row. Use this when the user attached or pasted a table. Empty string means omit.";
};
readonly url: {
readonly type: "string";
readonly description: "http(s) URL to a CSV. Local/dev only — rejected on hosted/production. Empty string means omit.";
};
readonly path: {
readonly type: "string";
readonly description: "Local CSV path (absolute, or relative to cwd). Local/dev only. Empty string means omit.";
};
readonly datasetId: {
readonly type: "string";
readonly description: "Id returned by an earlier show_workspace on this table. Use instead of csv/url/path.";
};
readonly columns: {
readonly type: "array";
readonly items: {
readonly type: "string";
};
readonly description: "Step 1. Column names the user asked to chart. Omit to use the whole table. Names only, not cell values.";
};
readonly utterance: {
readonly type: "string";
readonly description: "The user's words, for Jev. Pass the request as they wrote it. Empty string means omit.";
};
readonly requestedChart: {
readonly type: "string";
readonly description: "Step 3. The chart the user asked for, in their words or an id from a previous reply. Omit when they did not name a chart. On a new table, a known chart the utterance does not name is ignored. An unknown name is kept. A datasetId call with no new csv, url, or path keeps the id.";
};
readonly confirm: {
readonly type: "boolean";
readonly description: "Ignored. The next call draws the chart the user picks. Pass it as requestedChart with the same datasetId.";
};
};
};
};
export declare function handleShowWorkspace(args: unknown, context: ShowWorkspaceContext): Promise<ShowWorkspaceResult>;
/** A later call that reuses datasetId and does not paste a new table. */
export declare function isDatasetFollowUp(raw: Record<string, unknown>): boolean;