@barivia/barsom-mcp 0.20.1 → 0.20.2
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/job_monitor.js
CHANGED
|
@@ -91,7 +91,7 @@ export function formatSnapshotLine(s) {
|
|
|
91
91
|
if (s.qe != null)
|
|
92
92
|
parts.push(`QE ${s.qe.toFixed(4)}`);
|
|
93
93
|
if (s.te != null)
|
|
94
|
-
parts.push(`TE ${s.te.toFixed(4)}`);
|
|
94
|
+
parts.push(`Epoch TE ${s.te.toFixed(4)}`);
|
|
95
95
|
if (s.eta_sec != null)
|
|
96
96
|
parts.push(`ETA ~${s.eta_sec}s`);
|
|
97
97
|
if (s.ordering_errors_tail?.length) {
|
package/dist/shared.js
CHANGED
|
@@ -26,7 +26,7 @@ export const RETRYABLE_STATUS = new Set([502, 503, 504]);
|
|
|
26
26
|
* X-Barsom-Client-Version so the server can annotate tool guidance with the
|
|
27
27
|
* wrapper version each action requires. Keep in sync with package.json on bump.
|
|
28
28
|
*/
|
|
29
|
-
export const CLIENT_VERSION = "0.20.
|
|
29
|
+
export const CLIENT_VERSION = "0.20.2";
|
|
30
30
|
/** User-facing links; keep aligned with barivia.se / api.barivia.se. */
|
|
31
31
|
export const PUBLIC_SITE_ORIGIN = "https://barivia.se";
|
|
32
32
|
/** Self-serve account dashboard (manage plan, billing, and API keys). */
|
|
@@ -157,7 +157,10 @@ async function handleResultsExplorer(job_id) {
|
|
|
157
157
|
`This localhost port is assigned per MCP session and changes if the proxy restarts — if the page won't load, re-run results_explorer for a fresh URL, or set BARIVIA_VIZ_PORT in your MCP env for a persistent port.`,
|
|
158
158
|
});
|
|
159
159
|
}
|
|
160
|
-
return
|
|
160
|
+
return {
|
|
161
|
+
...structuredTextResult(payload, undefined, content),
|
|
162
|
+
_meta: { ui: { resourceUri: RESULTS_EXPLORER_URI } },
|
|
163
|
+
};
|
|
161
164
|
}
|
|
162
165
|
export function registerExploreMapTool(server) {
|
|
163
166
|
const toolConfig = {
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
3
3
|
import { runMcpToolAudit } from "../audit.js";
|
|
4
4
|
import { apiCall, getClientSupportsMcpApps, getVizPort, structuredTextResult, } from "../shared.js";
|
|
5
|
+
import { lastEpochTeFromCurves } from "../training_monitor_curve.js";
|
|
5
6
|
export const TRAINING_MONITOR_URI = "ui://barsom/training-monitor";
|
|
6
7
|
export const TRAINING_MONITOR_REFRESH_MS = 5000;
|
|
7
8
|
function hasCurveArrays(data) {
|
|
@@ -24,30 +25,59 @@ function buildStructuredContent(job_id, data) {
|
|
|
24
25
|
refresh_interval_ms: TRAINING_MONITOR_REFRESH_MS,
|
|
25
26
|
};
|
|
26
27
|
}
|
|
28
|
+
function hasTeCurveArrays(data) {
|
|
29
|
+
return ((Array.isArray(data.ordering_topographic_errors) &&
|
|
30
|
+
data.ordering_topographic_errors.length > 0) ||
|
|
31
|
+
(Array.isArray(data.convergence_topographic_errors) &&
|
|
32
|
+
data.convergence_topographic_errors.length > 0));
|
|
33
|
+
}
|
|
34
|
+
function needsTrainingLogEnrichment(data) {
|
|
35
|
+
const status = String(data.status ?? "");
|
|
36
|
+
if (status !== "completed" && status !== "failed" && status !== "cancelled")
|
|
37
|
+
return false;
|
|
38
|
+
if (!hasCurveArrays(data))
|
|
39
|
+
return true;
|
|
40
|
+
if (!hasTeCurveArrays(data))
|
|
41
|
+
return true;
|
|
42
|
+
if (data.map_topographic_error == null && data.topographic_error == null)
|
|
43
|
+
return true;
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
27
46
|
async function enrichWithTrainingLog(job_id, data) {
|
|
28
47
|
const status = String(data.status ?? "");
|
|
29
|
-
if (status !== "completed" && status !== "failed")
|
|
30
|
-
return data;
|
|
31
|
-
if (hasCurveArrays(data))
|
|
48
|
+
if (status !== "completed" && status !== "failed" && status !== "cancelled")
|
|
32
49
|
return data;
|
|
50
|
+
const epochTe = data.epoch_topographic_error ??
|
|
51
|
+
data.topographic_error ??
|
|
52
|
+
lastEpochTeFromCurves(data);
|
|
33
53
|
try {
|
|
34
54
|
const log = (await apiCall("GET", `/v1/results/${job_id}/training-log`));
|
|
35
|
-
|
|
55
|
+
const merged = {
|
|
36
56
|
...data,
|
|
37
57
|
ordering_errors: log.ordering_errors ?? data.ordering_errors,
|
|
38
58
|
convergence_errors: log.convergence_errors ?? data.convergence_errors,
|
|
39
59
|
ordering_topographic_errors: log.ordering_topographic_errors ?? data.ordering_topographic_errors,
|
|
40
60
|
convergence_topographic_errors: log.convergence_topographic_errors ?? data.convergence_topographic_errors,
|
|
41
61
|
quantization_error: log.quantization_error ?? data.quantization_error,
|
|
42
|
-
topographic_error: log.topographic_error ?? data.topographic_error,
|
|
43
62
|
grid: log.grid ?? data.grid,
|
|
44
63
|
model: log.model ?? data.model,
|
|
45
64
|
epochs: log.epochs ?? data.epochs,
|
|
46
65
|
n_samples: log.n_samples ?? data.n_samples,
|
|
47
66
|
n_features: log.n_features ?? data.n_features,
|
|
67
|
+
training_curve_source_batches: log.training_curve_source_batches ?? data.training_curve_source_batches,
|
|
48
68
|
};
|
|
69
|
+
const mapTe = log.topographic_error ?? data.map_topographic_error ?? data.topographic_error;
|
|
70
|
+
merged.epoch_topographic_error = epochTe ?? lastEpochTeFromCurves(merged);
|
|
71
|
+
merged.map_topographic_error = mapTe;
|
|
72
|
+
if (status === "completed" || status === "failed" || status === "cancelled") {
|
|
73
|
+
merged.topographic_error = mapTe;
|
|
74
|
+
}
|
|
75
|
+
return merged;
|
|
49
76
|
}
|
|
50
77
|
catch {
|
|
78
|
+
if (epochTe != null) {
|
|
79
|
+
return { ...data, epoch_topographic_error: epochTe };
|
|
80
|
+
}
|
|
51
81
|
return data;
|
|
52
82
|
}
|
|
53
83
|
}
|
|
@@ -67,8 +97,7 @@ export function registerTrainingMonitorTool(server) {
|
|
|
67
97
|
const { job_id, fetch_training_log } = args;
|
|
68
98
|
let data = (await apiCall("GET", `/v1/jobs/${job_id}`));
|
|
69
99
|
const jobStatus = String(data.status ?? "");
|
|
70
|
-
|
|
71
|
-
if (fetch_training_log || (terminal && !hasCurveArrays(data))) {
|
|
100
|
+
if (fetch_training_log || needsTrainingLogEnrichment(data)) {
|
|
72
101
|
data = await enrichWithTrainingLog(job_id, data);
|
|
73
102
|
}
|
|
74
103
|
const structuredContent = buildStructuredContent(job_id, data);
|
|
@@ -101,6 +130,9 @@ export function registerTrainingMonitorTool(server) {
|
|
|
101
130
|
`This localhost port is assigned per MCP session and changes if the proxy restarts — if the page stays at "running 0%" or stops updating, the link is stale: re-run training_monitor for a fresh URL, or set BARIVIA_VIZ_PORT in your MCP env for a persistent port. Health check: http://localhost:${port}/api/health?job_id=${encodeURIComponent(job_id)}`,
|
|
102
131
|
});
|
|
103
132
|
}
|
|
104
|
-
return
|
|
133
|
+
return {
|
|
134
|
+
...structuredTextResult(structuredContent, text, content),
|
|
135
|
+
_meta: { ui: { resourceUri: TRAINING_MONITOR_URI } },
|
|
136
|
+
};
|
|
105
137
|
}));
|
|
106
138
|
}
|
|
@@ -26,5 +26,35 @@ export function formatCurveSourceNote(data) {
|
|
|
26
26
|
}
|
|
27
27
|
if (parts.length === 0)
|
|
28
28
|
return null;
|
|
29
|
-
return `Displaying uniformly subsampled curves (≤1000 points/phase): ${parts.join("; ")}.`;
|
|
29
|
+
return `Displaying uniformly subsampled QE+TE curves (≤1000 points/phase, joint indices): ${parts.join("; ")}.`;
|
|
30
|
+
}
|
|
31
|
+
/** Map TE onto QE batch axis; when batch-aligned (same length), use values directly. */
|
|
32
|
+
export function alignTeToQeAxis(te, qeLen) {
|
|
33
|
+
if (qeLen <= 0)
|
|
34
|
+
return [];
|
|
35
|
+
if (te.length === qeLen)
|
|
36
|
+
return te;
|
|
37
|
+
if (te.length === 0)
|
|
38
|
+
return Array(qeLen).fill(null);
|
|
39
|
+
if (te.length >= qeLen)
|
|
40
|
+
return te.slice(0, qeLen);
|
|
41
|
+
const pad = qeLen - te.length;
|
|
42
|
+
return [...Array(pad).fill(null), ...te];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Last sampled TE point from the (batch-aligned) live TE curve. This is the most
|
|
46
|
+
* recent per-epoch TE estimate, distinct from the final trained-map TE in the summary.
|
|
47
|
+
*/
|
|
48
|
+
export function lastEpochTeFromCurves(data) {
|
|
49
|
+
const conv = data.convergence_topographic_errors;
|
|
50
|
+
if (Array.isArray(conv) && conv.length > 0) {
|
|
51
|
+
const v = Number(conv[conv.length - 1]);
|
|
52
|
+
return Number.isFinite(v) ? v : null;
|
|
53
|
+
}
|
|
54
|
+
const ord = data.ordering_topographic_errors;
|
|
55
|
+
if (Array.isArray(ord) && ord.length > 0) {
|
|
56
|
+
const v = Number(ord[ord.length - 1]);
|
|
57
|
+
return Number.isFinite(v) ? v : null;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
30
60
|
}
|