@barivia/barsom-mcp 0.9.0 → 0.10.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/shared.js +1 -1
- package/dist/tools/jobs.js +25 -7
- package/dist/tools/results.js +1 -1
- package/package.json +1 -1
package/dist/shared.js
CHANGED
|
@@ -19,7 +19,7 @@ export const RETRYABLE_STATUS = new Set([502, 503, 504]);
|
|
|
19
19
|
* X-Barsom-Client-Version so the server can annotate tool guidance with the
|
|
20
20
|
* wrapper version each action requires. Keep in sync with package.json on bump.
|
|
21
21
|
*/
|
|
22
|
-
export const CLIENT_VERSION = "0.
|
|
22
|
+
export const CLIENT_VERSION = "0.10.0";
|
|
23
23
|
/** User-facing links; keep aligned with barivia.se / api.barivia.se. */
|
|
24
24
|
export const PUBLIC_SITE_ORIGIN = "https://barivia.se";
|
|
25
25
|
/** Poll window for datasets(add_expression) / derive jobs (server-side work can exceed 30s). */
|
package/dist/tools/jobs.js
CHANGED
|
@@ -8,6 +8,7 @@ export const JOBS_DESCRIPTION_BASE = `Manage and inspect jobs.
|
|
|
8
8
|
| list | Finding job IDs, checking what is pending/completed, reviewing hyperparameters. Response includes job_type (train_map, report, recolor, project, transition_flow, compare, predict, impute_column, annotated_dataset, reduce_spectral) to filter or display. |
|
|
9
9
|
| compare | Picking the best training run from a set of completed jobs |
|
|
10
10
|
| train_map | Submitting a new map training job — returns job_id for polling |
|
|
11
|
+
| train_impute | Sparse training data: train a map AND impute missing cells in one job (accelerated missSOM) — returns map + imputed.csv |
|
|
11
12
|
| train_siom_map | Submitting a self-interacting map training job — same map flow with SIOM coverage control |
|
|
12
13
|
| train_floop_siom | Submitting a FLooP-SIOM job (growing manifold; default topology=free / CHL) — requires Premium or Enterprise plan (all_algorithms) |
|
|
13
14
|
| train_floop_chain | Deprecated alias for train_floop_siom — same behavior; prefer train_floop_siom |
|
|
@@ -31,6 +32,7 @@ ESCALATION (action=status):
|
|
|
31
32
|
- NaN error: user must clean the dataset
|
|
32
33
|
|
|
33
34
|
action=train_map / train_siom_map: Submits a grid-map training job. Returns job_id — poll with jobs(action=status, job_id=...).
|
|
35
|
+
action=train_impute: Submits missing-tolerant map training on a dataset with holes in the feature matrix. Use when many cells are missing across training columns; use inference(impute_column) instead when you already have a complete-case map and need to fill one held-out column. Plain numeric columns only (no cyclic/temporal/categorical). Returns map artifacts plus imputed.csv (dense matrix). Same grid/epochs/backend params as train_map.
|
|
34
36
|
Presets: quick | standard | refined | high_res — use preset=... for grid/epochs/batch defaults; call training_guidance for details.
|
|
35
37
|
Presets refined/high_res may use GPU. On CPU-only hosts pass backend=cpu. API expects strings "cpu" | "gpu" | "gpu_graphs" (no colon). Future backends (e.g. non-CUDA) may be added under the same contract.
|
|
36
38
|
normalize: "auto" (default) = scale only non-cyclic features; "all" = scale every feature. Use "auto" when using cyclic_features.
|
|
@@ -224,7 +226,7 @@ export function buildTrainMapParams(args, presets) {
|
|
|
224
226
|
export function registerJobsTool(server, description) {
|
|
225
227
|
server.tool("jobs", description, {
|
|
226
228
|
action: z
|
|
227
|
-
.enum(["status", "list", "compare", "cancel", "delete", "train_map", "train_siom_map", "train_floop_siom", "train_floop_chain", "batch_predict", "run_baseline_study"])
|
|
229
|
+
.enum(["status", "list", "compare", "cancel", "delete", "train_map", "train_impute", "train_siom_map", "train_floop_siom", "train_floop_chain", "batch_predict", "run_baseline_study"])
|
|
228
230
|
.describe("status: check progress; list: see all jobs; compare: metrics table; cancel: stop job; delete: remove job + files; train_map: submit standard map training; train_siom_map: submit SIOM map training; train_floop_siom: submit FLooP-SIOM (preferred); train_floop_chain: deprecated alias for train_floop_siom; batch_predict: submit multiple predict jobs at once; run_baseline_study: auto-configure and train a baseline SOM"),
|
|
229
231
|
job_id: z
|
|
230
232
|
.string()
|
|
@@ -306,6 +308,8 @@ export function registerJobsTool(server, description) {
|
|
|
306
308
|
output_dpi: z.enum(["standard", "retina", "print"]).optional().default("retina"),
|
|
307
309
|
colormap: z.string().optional(),
|
|
308
310
|
row_range: z.tuple([z.number().int().min(1), z.number().int().min(1)]).optional(),
|
|
311
|
+
cv_folds: z.number().int().min(0).max(20).optional()
|
|
312
|
+
.describe("train_impute only: held-out MAE/RMSE/R2 per column (0=off, 2..20) → quality.csv"),
|
|
309
313
|
gamma: z.preprocess((v) => (v !== undefined && v !== null && typeof v === "string") ? parseFloat(v) : v, z.number().optional()),
|
|
310
314
|
gamma_f: z.preprocess((v) => (v !== undefined && v !== null && typeof v === "string") ? parseFloat(v) : v, z.number().optional()),
|
|
311
315
|
siom_decay: z.preprocess((v) => (v !== undefined && v !== null && typeof v === "string") ? parseFloat(v) : v, z.number().optional()),
|
|
@@ -361,8 +365,8 @@ export function registerJobsTool(server, description) {
|
|
|
361
365
|
const jid = String(data.id ?? "");
|
|
362
366
|
return { content: [{ type: "text", text: `Baseline study submitted. Job ID: ${jid}\nGrid size: ${side}x${side}\nNormalization: MAD\n\nPoll with jobs(action=status, job_id="${jid}") until complete, then retrieve with results(action=get, job_id="${jid}"). Optional: training_monitor(job_id="${jid}") for a visual panel—not required.` }] };
|
|
363
367
|
}
|
|
364
|
-
if (action === "train_map" || action === "train_siom_map") {
|
|
365
|
-
const { preset, grid_x, grid_y, epochs, model, periodic, columns, cyclic_features, temporal_features, feature_weights, transforms, auto_log_transforms, time_delay_embeddings, categorical_features, normalize, sigma_f, learning_rate, batch_size, quality_metrics, backend, output_format, output_dpi, colormap, row_range, gamma, gamma_f, siom_decay, siom_penalty, penalty_alpha, reset_per_epoch, siom_feature_geometry, siom_qe_backend, siom_qe_batch_size, label, } = args;
|
|
368
|
+
if (action === "train_map" || action === "train_siom_map" || action === "train_impute") {
|
|
369
|
+
const { preset, grid_x, grid_y, epochs, model, periodic, columns, cyclic_features, temporal_features, feature_weights, transforms, auto_log_transforms, time_delay_embeddings, categorical_features, normalize, sigma_f, learning_rate, batch_size, quality_metrics, backend, output_format, output_dpi, colormap, row_range, gamma, gamma_f, siom_decay, siom_penalty, penalty_alpha, reset_per_epoch, siom_feature_geometry, siom_qe_backend, siom_qe_batch_size, label, cv_folds, } = args;
|
|
366
370
|
let PRESETS = {};
|
|
367
371
|
try {
|
|
368
372
|
PRESETS = await fetchTrainingPresets();
|
|
@@ -375,7 +379,7 @@ export function registerJobsTool(server, description) {
|
|
|
375
379
|
}
|
|
376
380
|
}
|
|
377
381
|
if (!dataset_id)
|
|
378
|
-
throw new Error(
|
|
382
|
+
throw new Error(`jobs(${action}) requires dataset_id`);
|
|
379
383
|
const { params, paramSummary, effectiveGrid } = buildTrainMapParams({
|
|
380
384
|
preset, grid_x, grid_y, epochs, model, periodic, columns, cyclic_features,
|
|
381
385
|
temporal_features, feature_weights, transforms, auto_log_transforms,
|
|
@@ -383,6 +387,18 @@ export function registerJobsTool(server, description) {
|
|
|
383
387
|
normalize, sigma_f, learning_rate, batch_size, quality_metrics, backend,
|
|
384
388
|
output_format, output_dpi, colormap, row_range,
|
|
385
389
|
}, PRESETS);
|
|
390
|
+
if (action === "train_impute") {
|
|
391
|
+
params._job_type = "train_impute";
|
|
392
|
+
if (cv_folds !== undefined)
|
|
393
|
+
params.cv_folds = cv_folds;
|
|
394
|
+
// Plain numeric path only — strip unsupported keys if caller passed them
|
|
395
|
+
delete params.cyclic_features;
|
|
396
|
+
delete params.temporal_features;
|
|
397
|
+
delete params.categorical_features;
|
|
398
|
+
delete params.transforms;
|
|
399
|
+
delete params.auto_log_transforms;
|
|
400
|
+
delete params.time_delay_embeddings;
|
|
401
|
+
}
|
|
386
402
|
if (action === "train_siom_map") {
|
|
387
403
|
params._job_type = "train_siom";
|
|
388
404
|
if (gamma !== undefined)
|
|
@@ -415,7 +431,9 @@ export function registerJobsTool(server, description) {
|
|
|
415
431
|
submitBody.label = label;
|
|
416
432
|
const data = (await apiCall("POST", "/v1/jobs", submitBody));
|
|
417
433
|
const newJobId = data.id;
|
|
418
|
-
const variantPrefix = action === "train_siom_map" ? "variant=siom"
|
|
434
|
+
const variantPrefix = action === "train_siom_map" ? "variant=siom"
|
|
435
|
+
: action === "train_impute" ? "variant=train_impute"
|
|
436
|
+
: "variant=som";
|
|
419
437
|
data.effective_params = `${variantPrefix}, ${paramSummary}`;
|
|
420
438
|
try {
|
|
421
439
|
const sys = (await apiCall("GET", "/v1/system/info"));
|
|
@@ -426,7 +444,7 @@ export function registerJobsTool(server, description) {
|
|
|
426
444
|
let msg = `Job submitted (${variantPrefix}, ${paramSummary}). `;
|
|
427
445
|
if (waitMinutes > 1)
|
|
428
446
|
msg += `You are #${pending + 1} in queue. Estimated wait: ~${waitMinutes} min. `;
|
|
429
|
-
msg += `Poll with jobs(action=status, job_id="${newJobId}"). When status is completed, use results(action=get, job_id="${newJobId}") to view the map and metrics.`;
|
|
447
|
+
msg += `Poll with jobs(action=status, job_id="${newJobId}"). When status is completed, use results(action=get, job_id="${newJobId}") to view the map${action === "train_impute" ? " and imputed.csv" : ""} and metrics.`;
|
|
430
448
|
msg += ` Optional: training_monitor(job_id="${newJobId}") for charts—not required.`;
|
|
431
449
|
if (effectiveGrid && totalRows > 0 && effectiveGrid[0] * effectiveGrid[1] > totalRows * 0.75) {
|
|
432
450
|
msg += ` Note: Grid may be large for ${totalRows} rows (consider grid=auto for fewer dead nodes).`;
|
|
@@ -434,7 +452,7 @@ export function registerJobsTool(server, description) {
|
|
|
434
452
|
data.message = msg;
|
|
435
453
|
}
|
|
436
454
|
catch {
|
|
437
|
-
let msg = `Job submitted (${variantPrefix}, ${paramSummary}). Poll with jobs(action=status, job_id="${newJobId}"). When status is completed, use results(action=get, job_id="${newJobId}") to view the map and metrics.`;
|
|
455
|
+
let msg = `Job submitted (${variantPrefix}, ${paramSummary}). Poll with jobs(action=status, job_id="${newJobId}"). When status is completed, use results(action=get, job_id="${newJobId}") to view the map${action === "train_impute" ? " and imputed.csv" : ""} and metrics.`;
|
|
438
456
|
msg += ` Optional: training_monitor(job_id="${newJobId}") for charts—not required.`;
|
|
439
457
|
if (effectiveGrid && totalRows > 0 && effectiveGrid[0] * effectiveGrid[1] > totalRows * 0.75) {
|
|
440
458
|
msg += ` Note: Grid may be large for ${totalRows} rows (consider grid=auto for fewer dead nodes).`;
|
package/dist/tools/results.js
CHANGED
|
@@ -393,7 +393,7 @@ NOT FOR: Jobs that haven't completed. Use jobs(action=status) to check first.`,
|
|
|
393
393
|
return "";
|
|
394
394
|
return `Columns not used in training: ${excluded.join(", ")}. You can project them onto this map with inference(action=project_columns, job_id=${job_id}, dataset_id=<dataset_id>, columns=[${excluded.map((c) => `"${c}"`).join(", ")}]) to see how they distribute across the topology. If you ran datasets(action=analyze) before training, any columns it recommended as "project later" are especially good candidates.`;
|
|
395
395
|
})(),
|
|
396
|
-
...((jobType === "train_som" || jobType === "train_siom") ? ["", `Next: results(action=export, export_type=training_log) for learning curve; results(action=download) to save figures; jobs(action=compare, job_ids=[...]) to compare runs; inference(action=predict) to score new data; inference(action=project_columns) to project other variables onto the map.`] : []),
|
|
396
|
+
...((jobType === "train_som" || jobType === "train_siom" || jobType === "train_impute") ? ["", `Next: results(action=export, export_type=training_log) for learning curve; results(action=download) to save figures${jobType === "train_impute" ? " (includes imputed.csv)" : ""}; jobs(action=compare, job_ids=[...]) to compare runs; inference(action=predict) to score new data; inference(action=project_columns) to project other variables onto the map.`] : []),
|
|
397
397
|
].filter((l) => l !== "").join("\n");
|
|
398
398
|
content.push({ type: "text", text: textSummary });
|
|
399
399
|
const imagesToFetch = getResultsImagesToFetch(jobType, summary, figures, include_individual);
|