@barivia/barmesh-mcp 0.3.0 → 0.4.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/README.md CHANGED
@@ -13,7 +13,14 @@ form on a shared self-organizing map (SOM)**:
13
13
  - **`barmesh_mesh_convergence`** — trains one SOM on all meshes (joint-normalized), projects
14
14
  each mesh to a volume-weighted fingerprint, and computes **symmetric KL** and
15
15
  **Wasserstein-1 (EMD)** distances stepwise and against a reference mesh, with publication
16
- figures and an advisory convergence reading.
16
+ figures and an advisory convergence reading. The SOM features are preprocessed by the
17
+ same staged pipeline as barsom training, so any dataset (small or large, CSV/gzip/Parquet)
18
+ is handled out-of-core by default; optional `transforms`, `normalize`,
19
+ `normalization_methods`, and `row_range` give the same preprocessing controls. Submit
20
+ enqueues **`prepare_training_matrix`** on worker-io when the dataset is staged; the proxy
21
+ auto-polls `prepare_job_id` before the mesh job runs. Default **`defer_figures=true`** →
22
+ **`cfd_finalize`** on worker-io; **`barmesh_jobs(status)`** auto-polls **`finalize_job_id`**
23
+ when figures are deferred.
17
24
  - **`barmesh_richardson`** — classical three-level Richardson extrapolation / Grid
18
25
  Convergence Index (GCI) on scalar quantities of interest.
19
26
 
@@ -48,7 +55,7 @@ API key; otherwise the analysis calls return HTTP 403. Contact Barivia to enable
48
55
  | `barmesh_datasets` | Upload / preview / list the mesh CSV. |
49
56
  | `barmesh_mesh_convergence` | SOM fingerprint distances (async job). |
50
57
  | `barmesh_richardson` | Richardson/GCI on scalar QoIs (async job). |
51
- | `barmesh_jobs` | Poll job status / list jobs. |
58
+ | `barmesh_jobs` | Poll job status / list jobs (auto-polls CFD prepare + finalize when applicable). |
52
59
  | `barmesh_results` | Distances, convergence reading, and figures. |
53
60
  | `barmesh_send_feedback` | Send a short note or bug report to the Barivia team. |
54
61
 
@@ -0,0 +1,23 @@
1
+ import { apiCall, pollUntilComplete } from "./shared.js";
2
+ /**
3
+ * When CFD compute finishes with defer_figures, cfd_finalize may still be rendering on worker-io.
4
+ */
5
+ export async function pollCfdFinalizeIfPresent(jobId, data, timeoutMs = 600_000) {
6
+ const finalizeJobId = data.finalize_job_id;
7
+ if (!finalizeJobId)
8
+ return { finalizeJobId: null, note: null };
9
+ const poll = await pollUntilComplete(finalizeJobId, timeoutMs);
10
+ if (poll.status === "failed") {
11
+ throw new Error(`CFD job ${jobId}: cfd_finalize ${finalizeJobId} failed: ${poll.error ?? "unknown error"}`);
12
+ }
13
+ if (poll.status !== "completed") {
14
+ throw new Error(`CFD job ${jobId}: cfd_finalize ${finalizeJobId} did not complete (status=${poll.status})`);
15
+ }
16
+ return {
17
+ finalizeJobId,
18
+ note: `Finalize job ${finalizeJobId} completed (figures uploaded).`,
19
+ };
20
+ }
21
+ export async function refreshJobAfterFinalize(jobId) {
22
+ return (await apiCall("GET", `/v1/jobs/${jobId}`));
23
+ }
@@ -0,0 +1,19 @@
1
+ import { pollUntilComplete } from "./shared.js";
2
+ /**
3
+ * Mesh-convergence on a staged dataset enqueues a preprocessing job
4
+ * (prepare_training_matrix) first; the submit response carries its id as
5
+ * `prepare_job_id`. Poll it to completion before the mesh job runs.
6
+ */
7
+ export async function pollCfdPrepareIfPresent(data, label, timeoutMs = 600_000) {
8
+ const prepareJobId = data.prepare_job_id;
9
+ if (!prepareJobId)
10
+ return null;
11
+ const poll = await pollUntilComplete(prepareJobId, timeoutMs);
12
+ if (poll.status === "failed") {
13
+ throw new Error(`${label}: data preparation job ${prepareJobId} failed: ${poll.error ?? "unknown error"}`);
14
+ }
15
+ if (poll.status !== "completed") {
16
+ throw new Error(`${label}: data preparation job ${prepareJobId} did not complete (status=${poll.status})`);
17
+ }
18
+ return prepareJobId;
19
+ }
package/dist/shared.js CHANGED
@@ -20,7 +20,7 @@ export const FETCH_TIMEOUT_MS = parseInt(process.env.BARIVIA_FETCH_TIMEOUT_MS ??
20
20
  export const MAX_RETRIES = 2;
21
21
  export const RETRYABLE_STATUS = new Set([502, 503, 504]);
22
22
  /** Single source of truth for the proxy version. Keep in sync with package.json on bump. */
23
- export const CLIENT_VERSION = "0.3.0";
23
+ export const CLIENT_VERSION = "0.4.0";
24
24
  export const PUBLIC_SITE_ORIGIN = "https://barivia.se";
25
25
  /** Large per-cell CSV uploads may exceed the default fetch timeout. */
26
26
  export const UPLOAD_DATASET_TIMEOUT_MS = 180_000;
package/dist/tools/cfd.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { registerAuditedTool } from "../audit.js";
3
3
  import { apiCall, textResult } from "../shared.js";
4
+ import { pollCfdPrepareIfPresent } from "../cfd_prepare.js";
4
5
  export function registerCfdTools(server) {
5
6
  registerAuditedTool(server, "barmesh_mesh_convergence", `Run SOM-based mesh-convergence analysis on an uploaded combined per-cell CSV.
6
7
 
@@ -26,6 +27,10 @@ COMMON MISTAKES: omitting feature_columns (required); choosing a reference_mesh
26
27
  emd_method: z.enum(["exact", "sinkhorn"]).optional().describe("EMD solver: exact LP (default) or sinkhorn (fast approximation for large grids)"),
27
28
  component_planes_physical: z.boolean().optional().describe("Physical-scale component-plane colorbars (default true)"),
28
29
  figures: z.boolean().optional().describe("Generate publication figures (default true)"),
30
+ transforms: z.record(z.enum(["log", "log1p", "log10", "sqrt", "square", "abs", "invert", "none"])).optional().describe("Per-feature transform applied before normalization (e.g. log1p to compress k/epsilon/omega). Same preprocessing engine as barsom training."),
31
+ normalize: z.union([z.enum(["all", "auto", "mad", "sigmoidal", "sepd"]), z.array(z.string())]).optional().describe("Normalization mode for SOM features (default auto = joint z-score of non-cyclic features). Use mad for heavy-tailed channels."),
32
+ normalization_methods: z.record(z.enum(["zscore", "mad", "sigmoidal", "sepd", "none"])).optional().describe("Per-feature normalization override; keys must be in feature_columns."),
33
+ row_range: z.tuple([z.number().int().min(1), z.number().int().min(1)]).optional().describe("1-based inclusive [start, end] row slice applied during preprocessing (and to mesh labels / cell volumes)."),
29
34
  label: z.string().optional().describe("Optional job label"),
30
35
  }, async (args) => {
31
36
  const { dataset_id, label, ...rest } = args;
@@ -38,9 +43,12 @@ COMMON MISTAKES: omitting feature_columns (required); choosing a reference_mesh
38
43
  if (typeof label === "string" && label.length > 0)
39
44
  body.label = label;
40
45
  const data = (await apiCall("POST", "/v1/cfd/mesh-convergence", body));
46
+ await pollCfdPrepareIfPresent(data, "barmesh_mesh_convergence");
41
47
  const id = data.id;
42
- if (id != null)
43
- data.suggested_next_step = `Poll barmesh_jobs(action=status, job_id=${id}); on completion call barmesh_results(action=get, job_id=${id}).`;
48
+ if (id != null) {
49
+ const prep = data.prepare_job_id != null ? " (dataset prepare complete)" : "";
50
+ data.suggested_next_step = `Poll barmesh_jobs(action=status, job_id=${id})${prep}; on completion call barmesh_results(action=get, job_id=${id}).`;
51
+ }
44
52
  return textResult(data);
45
53
  });
46
54
  registerAuditedTool(server, "barmesh_richardson", `Run classical Richardson extrapolation / Grid Convergence Index (GCI) on scalar quantities of interest.
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { registerAuditedTool } from "../audit.js";
3
3
  import { apiCall, textResult } from "../shared.js";
4
+ import { pollCfdFinalizeIfPresent, refreshJobAfterFinalize } from "../cfd_finalize.js";
4
5
  export function registerJobsTool(server) {
5
6
  registerAuditedTool(server, "barmesh_jobs", `Check job status or list jobs.
6
7
 
@@ -14,7 +15,20 @@ ESCALATION: status=failed returns an error message and (when available) a failur
14
15
  if (action === "status") {
15
16
  if (!job_id)
16
17
  throw new Error("barmesh_jobs(status) requires job_id.");
17
- const data = await apiCall("GET", `/v1/jobs/${job_id}`);
18
+ let data = (await apiCall("GET", `/v1/jobs/${job_id}`));
19
+ const status = String(data.status ?? "");
20
+ if (status === "completed" && data.finalize_job_id) {
21
+ const { note } = await pollCfdFinalizeIfPresent(job_id, data);
22
+ data = await refreshJobAfterFinalize(job_id);
23
+ const lines = [
24
+ `Job ${job_id}: ${String(data.status ?? "unknown")}`,
25
+ data.label != null ? `Label: ${String(data.label)}` : null,
26
+ data.progress != null ? `Progress: ${String(data.progress)}` : null,
27
+ data.result_ref != null ? `Results: ${String(data.result_ref)}` : null,
28
+ note,
29
+ ].filter(Boolean);
30
+ return textResult({ ...data, status_text: lines.join("\n") });
31
+ }
18
32
  return textResult(data);
19
33
  }
20
34
  const data = await apiCall("GET", "/v1/jobs");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barivia/barmesh-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "barmesh MCP proxy — SOM-based CFD mesh-convergence and Richardson/GCI analysis on the Barivia cloud API",
5
5
  "keywords": [
6
6
  "mcp",