@barivia/barsom-mcp 0.22.2 → 0.22.4
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/index.js +1 -1
- package/dist/prepare_training_prompt.js +1 -0
- package/dist/shared.js +62 -7
- package/dist/tools/account.js +7 -1
- package/dist/tools/datasets.js +8 -6
- package/dist/tools/explore_map.js +37 -18
- package/dist/tools/results.js +7 -1
- package/dist/tools/train.js +11 -4
- package/dist/tools/training_core.js +6 -1
- package/dist/tools/training_monitor.js +80 -37
- package/dist/train_submit_message.js +5 -7
- package/dist/training_monitor_curve.js +32 -0
- package/dist/ui-delivery.js +185 -0
- package/dist/views/src/views/results-explorer/index.html +16 -13
- package/dist/views/src/views/training-monitor/index.html +30 -18
- package/dist/viz_links.js +25 -0
- package/package.json +1 -1
|
@@ -83,3 +83,35 @@ export function lastEpochTeFromCurves(data) {
|
|
|
83
83
|
}
|
|
84
84
|
return null;
|
|
85
85
|
}
|
|
86
|
+
export function isTerminalJobStatus(status) {
|
|
87
|
+
return status === "completed" || status === "failed" || status === "cancelled";
|
|
88
|
+
}
|
|
89
|
+
/** True when compute + finalize (if any) are done — safe to open results_explorer. */
|
|
90
|
+
export function isFullyComplete(data) {
|
|
91
|
+
const status = String(data.status ?? "");
|
|
92
|
+
if (status !== "completed")
|
|
93
|
+
return isTerminalJobStatus(status);
|
|
94
|
+
const finalizeId = data.finalize_job_id != null && String(data.finalize_job_id) !== ""
|
|
95
|
+
? String(data.finalize_job_id)
|
|
96
|
+
: null;
|
|
97
|
+
if (!finalizeId)
|
|
98
|
+
return true;
|
|
99
|
+
return String(data.finalize_status ?? "") === "completed";
|
|
100
|
+
}
|
|
101
|
+
/** Keep polling while finalize is still running after parent compute completed. */
|
|
102
|
+
export function shouldKeepPollingJob(data) {
|
|
103
|
+
const status = String(data.status ?? "");
|
|
104
|
+
if (!isTerminalJobStatus(status))
|
|
105
|
+
return true;
|
|
106
|
+
if (status !== "completed")
|
|
107
|
+
return false;
|
|
108
|
+
if (data.finalize_failed === true)
|
|
109
|
+
return false;
|
|
110
|
+
const finalizeId = data.finalize_job_id != null && String(data.finalize_job_id) !== ""
|
|
111
|
+
? String(data.finalize_job_id)
|
|
112
|
+
: null;
|
|
113
|
+
const finalizeStatus = data.finalize_status != null && String(data.finalize_status) !== ""
|
|
114
|
+
? String(data.finalize_status)
|
|
115
|
+
: null;
|
|
116
|
+
return finalizeId != null && finalizeStatus !== "completed";
|
|
117
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-capability adaptation for MCP App tools (training_monitor, results_explorer).
|
|
3
|
+
* Respects BARIVIA_UI_DELIVERY override and emits a structured block agents can rely on.
|
|
4
|
+
*/
|
|
5
|
+
import { apiRawCall, getClientSupportsMcpApps, getVizPort, mimeForFilename, resetInlineAttachBudget, } from "./shared.js";
|
|
6
|
+
import { buildVizStandaloneUrl } from "./viz_links.js";
|
|
7
|
+
export function parseUiDeliveryOverride() {
|
|
8
|
+
const raw = (process.env.BARIVIA_UI_DELIVERY ?? "auto").trim().toLowerCase();
|
|
9
|
+
if (raw === "apps" || raw === "localhost" || raw === "inline" || raw === "auto") {
|
|
10
|
+
return raw;
|
|
11
|
+
}
|
|
12
|
+
return "auto";
|
|
13
|
+
}
|
|
14
|
+
function vizPortPinned() {
|
|
15
|
+
return Boolean(process.env.BARIVIA_VIZ_PORT?.trim());
|
|
16
|
+
}
|
|
17
|
+
function viewForTool(tool) {
|
|
18
|
+
return tool === "training_monitor" ? "training-monitor" : "results-explorer";
|
|
19
|
+
}
|
|
20
|
+
/** Prefer viz_links (single URL builder) so train/monitor/explorer stay consistent. */
|
|
21
|
+
export function buildStandaloneVizUrl(view, jobId) {
|
|
22
|
+
return buildVizStandaloneUrl(viewForTool(view), jobId);
|
|
23
|
+
}
|
|
24
|
+
export function buildHealthUrl(jobId) {
|
|
25
|
+
const port = getVizPort();
|
|
26
|
+
if (!port)
|
|
27
|
+
return undefined;
|
|
28
|
+
const base = `http://localhost:${port}/api/health`;
|
|
29
|
+
return jobId ? `${base}?job_id=${encodeURIComponent(jobId)}` : base;
|
|
30
|
+
}
|
|
31
|
+
function hintForTier(tier, tool, opts) {
|
|
32
|
+
const label = tool === "training_monitor" ? "training monitor" : "results explorer";
|
|
33
|
+
switch (tier) {
|
|
34
|
+
case "embedded":
|
|
35
|
+
return `The ${label} MCP App panel is embedded in this client. Also mention the standalone URL if the user may open a browser tab.`;
|
|
36
|
+
case "localhost":
|
|
37
|
+
return opts.standaloneUrl
|
|
38
|
+
? `AGENT: Post a clickable markdown link to the user (e.g. "[Open ${label}](${opts.standaloneUrl})") — do not bury it in tool output or use broken workspace file paths. Re-post after the job completes if status was running.`
|
|
39
|
+
: `AGENT: Viz server unavailable — use jobs(status) and results(get) for progress and figures.`;
|
|
40
|
+
case "inline_image":
|
|
41
|
+
return `AGENT: Inline raster figure(s) are attached below. Summarize metrics in your reply; offer results_explorer or results(get) for additional figures.`;
|
|
42
|
+
case "text_only":
|
|
43
|
+
return `AGENT: No embedded panel or localhost viz — use jobs(status) for training progress and results(get) or results_explorer for figures.`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function resolveUiDelivery(options) {
|
|
47
|
+
const override = parseUiDeliveryOverride();
|
|
48
|
+
const mcpApps = getClientSupportsMcpApps();
|
|
49
|
+
const port = getVizPort() || null;
|
|
50
|
+
const standaloneUrl = buildStandaloneVizUrl(options.tool, options.jobId);
|
|
51
|
+
let delivery;
|
|
52
|
+
if (override === "apps") {
|
|
53
|
+
delivery = mcpApps ? "embedded" : port ? "localhost" : "text_only";
|
|
54
|
+
}
|
|
55
|
+
else if (override === "localhost") {
|
|
56
|
+
delivery = port ? "localhost" : options.inlineImageAttached ? "inline_image" : "text_only";
|
|
57
|
+
}
|
|
58
|
+
else if (override === "inline") {
|
|
59
|
+
delivery = options.inlineImageAttached ? "inline_image" : "text_only";
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// auto
|
|
63
|
+
if (mcpApps) {
|
|
64
|
+
delivery = "embedded";
|
|
65
|
+
}
|
|
66
|
+
else if (port) {
|
|
67
|
+
delivery = "localhost";
|
|
68
|
+
}
|
|
69
|
+
else if (options.inlineImageAttached) {
|
|
70
|
+
delivery = "inline_image";
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
delivery = "text_only";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const urls = [];
|
|
77
|
+
if (standaloneUrl && (delivery === "embedded" || delivery === "localhost")) {
|
|
78
|
+
urls.push(standaloneUrl);
|
|
79
|
+
}
|
|
80
|
+
const healthUrl = buildHealthUrl(options.jobId);
|
|
81
|
+
if (healthUrl && delivery === "localhost") {
|
|
82
|
+
urls.push(healthUrl);
|
|
83
|
+
}
|
|
84
|
+
const crossLink = options.tool === "training_monitor" && options.jobStatus === "completed"
|
|
85
|
+
? buildStandaloneVizUrl("results_explorer", options.jobId)
|
|
86
|
+
: options.tool === "results_explorer"
|
|
87
|
+
? buildStandaloneVizUrl("training_monitor", options.jobId)
|
|
88
|
+
: undefined;
|
|
89
|
+
if (crossLink && !urls.includes(crossLink)) {
|
|
90
|
+
urls.push(crossLink);
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
delivery,
|
|
94
|
+
urls: urls.length > 0 ? urls : undefined,
|
|
95
|
+
hint_for_agent: hintForTier(delivery, options.tool, { standaloneUrl, jobStatus: options.jobStatus }),
|
|
96
|
+
mcp_apps_supported: mcpApps,
|
|
97
|
+
viz_port: port,
|
|
98
|
+
port_pinned: vizPortPinned(),
|
|
99
|
+
override,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Prepend prominent standalone URL (hosts may advertise Apps but not mount them),
|
|
104
|
+
* then structured ui_delivery JSON + agent hint.
|
|
105
|
+
*/
|
|
106
|
+
export function appendUiDeliveryContent(content, block, options) {
|
|
107
|
+
const primary = options?.primaryUrl ?? block.urls?.[0];
|
|
108
|
+
const label = options?.linkLabel ?? "Open interactive view";
|
|
109
|
+
const prefix = [];
|
|
110
|
+
if (primary) {
|
|
111
|
+
const embedNote = block.delivery === "embedded"
|
|
112
|
+
? "Embedded panel if your host supports MCP Apps — otherwise open the standalone URL below (expected on some Cursor builds)."
|
|
113
|
+
: "Open the standalone URL below when no inline panel appears.";
|
|
114
|
+
prefix.push({
|
|
115
|
+
type: "text",
|
|
116
|
+
text: `${embedNote}\n` +
|
|
117
|
+
`Standalone URL (copy if Open is blocked):\n${primary}\n` +
|
|
118
|
+
`[${label}](${primary})\n` +
|
|
119
|
+
`${block.hint_for_agent}`,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
prefix.push({
|
|
123
|
+
type: "text",
|
|
124
|
+
text: "```json\n" + JSON.stringify({ ui_delivery: block }, null, 2) + "\n```",
|
|
125
|
+
});
|
|
126
|
+
if (primary && !block.port_pinned && block.delivery !== "text_only") {
|
|
127
|
+
prefix.push({
|
|
128
|
+
type: "text",
|
|
129
|
+
text: "Tip: set BARIVIA_VIZ_PORT in MCP env for a session-stable localhost port; re-run this tool if the page stops updating.",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
content.unshift(...prefix);
|
|
133
|
+
}
|
|
134
|
+
export async function tryAttachLearningCurve(content, jobId) {
|
|
135
|
+
for (const ext of ["png", "svg"]) {
|
|
136
|
+
try {
|
|
137
|
+
const filename = `learning_curve.${ext}`;
|
|
138
|
+
const { data: buf } = await apiRawCall(`/v1/results/${jobId}/image/${filename}`);
|
|
139
|
+
content.push({
|
|
140
|
+
type: "image",
|
|
141
|
+
data: buf.toString("base64"),
|
|
142
|
+
mimeType: mimeForFilename(filename),
|
|
143
|
+
annotations: { audience: ["user"], priority: 0.75 },
|
|
144
|
+
});
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
export function getMcpClientDiagnostics() {
|
|
154
|
+
const override = parseUiDeliveryOverride();
|
|
155
|
+
const mcpApps = getClientSupportsMcpApps();
|
|
156
|
+
const port = getVizPort() || null;
|
|
157
|
+
let activeTier = "text_only";
|
|
158
|
+
if (override === "apps") {
|
|
159
|
+
activeTier = mcpApps ? "embedded" : port ? "localhost" : "text_only";
|
|
160
|
+
}
|
|
161
|
+
else if (override === "localhost") {
|
|
162
|
+
activeTier = port ? "localhost" : "text_only";
|
|
163
|
+
}
|
|
164
|
+
else if (override === "inline") {
|
|
165
|
+
activeTier = "inline_image";
|
|
166
|
+
}
|
|
167
|
+
else if (mcpApps) {
|
|
168
|
+
activeTier = "embedded";
|
|
169
|
+
}
|
|
170
|
+
else if (port) {
|
|
171
|
+
activeTier = "localhost";
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
mcp_apps_supported: mcpApps,
|
|
175
|
+
viz_port: port,
|
|
176
|
+
viz_port_pinned: vizPortPinned(),
|
|
177
|
+
ui_delivery_override: override,
|
|
178
|
+
active_delivery_tier: activeTier,
|
|
179
|
+
health_url: buildHealthUrl(),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/** Reset inline budget at tool entry when attaching fallback images. */
|
|
183
|
+
export function beginInlineFallback() {
|
|
184
|
+
resetInlineAttachBudget();
|
|
185
|
+
}
|