labgate 0.5.39 → 0.5.42

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.
Files changed (47) hide show
  1. package/README.md +132 -248
  2. package/dist/cli.js +9 -33
  3. package/dist/cli.js.map +1 -1
  4. package/dist/lib/config.d.ts +19 -3
  5. package/dist/lib/config.js +154 -75
  6. package/dist/lib/config.js.map +1 -1
  7. package/dist/lib/container.d.ts +11 -9
  8. package/dist/lib/container.js +749 -282
  9. package/dist/lib/container.js.map +1 -1
  10. package/dist/lib/dataset-mcp.js +2 -9
  11. package/dist/lib/dataset-mcp.js.map +1 -1
  12. package/dist/lib/display-mcp.d.ts +2 -2
  13. package/dist/lib/display-mcp.js +17 -38
  14. package/dist/lib/display-mcp.js.map +1 -1
  15. package/dist/lib/doctor.js +8 -0
  16. package/dist/lib/doctor.js.map +1 -1
  17. package/dist/lib/explorer-claude.js +36 -1
  18. package/dist/lib/explorer-claude.js.map +1 -1
  19. package/dist/lib/explorer-eval.js +3 -2
  20. package/dist/lib/explorer-eval.js.map +1 -1
  21. package/dist/lib/image-pull-lock.d.ts +18 -0
  22. package/dist/lib/image-pull-lock.js +167 -0
  23. package/dist/lib/image-pull-lock.js.map +1 -0
  24. package/dist/lib/init.js +22 -19
  25. package/dist/lib/init.js.map +1 -1
  26. package/dist/lib/slurm-cli-passthrough.d.ts +12 -2
  27. package/dist/lib/slurm-cli-passthrough.js +401 -143
  28. package/dist/lib/slurm-cli-passthrough.js.map +1 -1
  29. package/dist/lib/startup-stage-lock.d.ts +21 -0
  30. package/dist/lib/startup-stage-lock.js +196 -0
  31. package/dist/lib/startup-stage-lock.js.map +1 -0
  32. package/dist/lib/ui.d.ts +40 -0
  33. package/dist/lib/ui.html +4953 -3366
  34. package/dist/lib/ui.js +1771 -297
  35. package/dist/lib/ui.js.map +1 -1
  36. package/dist/lib/web-terminal-startup-readiness.d.ts +8 -0
  37. package/dist/lib/web-terminal-startup-readiness.js +29 -0
  38. package/dist/lib/web-terminal-startup-readiness.js.map +1 -0
  39. package/dist/lib/web-terminal.d.ts +51 -0
  40. package/dist/lib/web-terminal.js +171 -1
  41. package/dist/lib/web-terminal.js.map +1 -1
  42. package/dist/mcp-bundles/dataset-mcp.bundle.mjs +144 -93
  43. package/dist/mcp-bundles/display-mcp.bundle.mjs +35 -43
  44. package/dist/mcp-bundles/explorer-mcp.bundle.mjs +263 -146
  45. package/dist/mcp-bundles/results-mcp.bundle.mjs +39 -41
  46. package/dist/mcp-bundles/slurm-mcp.bundle.mjs +19 -21
  47. package/package.json +1 -1
@@ -2979,7 +2979,7 @@ var require_compile = __commonJS({
2979
2979
  const schOrFunc = root.refs[ref];
2980
2980
  if (schOrFunc)
2981
2981
  return schOrFunc;
2982
- let _sch = resolve2.call(this, root, ref);
2982
+ let _sch = resolve3.call(this, root, ref);
2983
2983
  if (_sch === void 0) {
2984
2984
  const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
2985
2985
  const { schemaId } = this.opts;
@@ -3006,7 +3006,7 @@ var require_compile = __commonJS({
3006
3006
  function sameSchemaEnv(s1, s2) {
3007
3007
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
3008
3008
  }
3009
- function resolve2(root, ref) {
3009
+ function resolve3(root, ref) {
3010
3010
  let sch;
3011
3011
  while (typeof (sch = this.refs[ref]) == "string")
3012
3012
  ref = sch;
@@ -3581,7 +3581,7 @@ var require_fast_uri = __commonJS({
3581
3581
  }
3582
3582
  return uri;
3583
3583
  }
3584
- function resolve2(baseURI, relativeURI, options) {
3584
+ function resolve3(baseURI, relativeURI, options) {
3585
3585
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3586
3586
  const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
3587
3587
  schemelessOptions.skipEscape = true;
@@ -3808,7 +3808,7 @@ var require_fast_uri = __commonJS({
3808
3808
  var fastUri = {
3809
3809
  SCHEMES,
3810
3810
  normalize,
3811
- resolve: resolve2,
3811
+ resolve: resolve3,
3812
3812
  resolveComponent,
3813
3813
  equal,
3814
3814
  serialize,
@@ -27964,7 +27964,7 @@ var Protocol = class {
27964
27964
  return;
27965
27965
  }
27966
27966
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
27967
- await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
27967
+ await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
27968
27968
  options?.signal?.throwIfAborted();
27969
27969
  }
27970
27970
  } catch (error48) {
@@ -27981,7 +27981,7 @@ var Protocol = class {
27981
27981
  */
27982
27982
  request(request, resultSchema, options) {
27983
27983
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
27984
- return new Promise((resolve2, reject) => {
27984
+ return new Promise((resolve3, reject) => {
27985
27985
  const earlyReject = (error48) => {
27986
27986
  reject(error48);
27987
27987
  };
@@ -28059,7 +28059,7 @@ var Protocol = class {
28059
28059
  if (!parseResult.success) {
28060
28060
  reject(parseResult.error);
28061
28061
  } else {
28062
- resolve2(parseResult.data);
28062
+ resolve3(parseResult.data);
28063
28063
  }
28064
28064
  } catch (error48) {
28065
28065
  reject(error48);
@@ -28320,12 +28320,12 @@ var Protocol = class {
28320
28320
  }
28321
28321
  } catch {
28322
28322
  }
28323
- return new Promise((resolve2, reject) => {
28323
+ return new Promise((resolve3, reject) => {
28324
28324
  if (signal.aborted) {
28325
28325
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
28326
28326
  return;
28327
28327
  }
28328
- const timeoutId = setTimeout(resolve2, interval);
28328
+ const timeoutId = setTimeout(resolve3, interval);
28329
28329
  signal.addEventListener("abort", () => {
28330
28330
  clearTimeout(timeoutId);
28331
28331
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -29284,7 +29284,7 @@ var McpServer = class {
29284
29284
  let task = createTaskResult.task;
29285
29285
  const pollInterval = task.pollInterval ?? 5e3;
29286
29286
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
29287
- await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
29287
+ await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
29288
29288
  const updatedTask = await extra.taskStore.getTask(taskId);
29289
29289
  if (!updatedTask) {
29290
29290
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -29927,35 +29927,36 @@ var StdioServerTransport = class {
29927
29927
  this.onclose?.();
29928
29928
  }
29929
29929
  send(message) {
29930
- return new Promise((resolve2) => {
29930
+ return new Promise((resolve3) => {
29931
29931
  const json2 = serializeMessage(message);
29932
29932
  if (this._stdout.write(json2)) {
29933
- resolve2();
29933
+ resolve3();
29934
29934
  } else {
29935
- this._stdout.once("drain", resolve2);
29935
+ this._stdout.once("drain", resolve3);
29936
29936
  }
29937
29937
  });
29938
29938
  }
29939
29939
  };
29940
29940
 
29941
29941
  // src/lib/results-mcp.ts
29942
- import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
29943
- import { dirname as dirname2, isAbsolute, relative, resolve } from "path";
29942
+ import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
29943
+ import { dirname as dirname3, isAbsolute, relative, resolve as resolve2 } from "path";
29944
29944
  import { createHash } from "crypto";
29945
29945
  import { execFile } from "child_process";
29946
29946
  import { promisify } from "util";
29947
29947
 
29948
29948
  // src/lib/results-store.ts
29949
29949
  import { randomUUID } from "crypto";
29950
- import { existsSync as existsSync2, readFileSync as readFileSync2, renameSync, unlinkSync, writeFileSync } from "fs";
29951
- import { dirname, join as join2 } from "path";
29950
+ import { existsSync as existsSync2, readFileSync as readFileSync2, renameSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
29951
+ import { dirname as dirname2, join as join2 } from "path";
29952
29952
 
29953
29953
  // src/lib/config.ts
29954
- import { readFileSync, existsSync, chmodSync, mkdirSync } from "fs";
29955
- import { join } from "path";
29954
+ import { readFileSync, existsSync, chmodSync, mkdirSync, writeFileSync } from "fs";
29955
+ import { dirname, join, resolve } from "path";
29956
29956
  import { homedir } from "os";
29957
29957
  var DEFAULT_CONFIG = {
29958
29958
  runtime: "auto",
29959
+ images_dir: "",
29959
29960
  // Default sandbox image: includes python3 + basic build tools (git/make/g++).
29960
29961
  // Note: pip/venv are not included by default in Debian; users may still need a
29961
29962
  // custom image for richer Python workflows.
@@ -29988,7 +29989,8 @@ var DEFAULT_CONFIG = {
29988
29989
  "mkfs",
29989
29990
  "reboot",
29990
29991
  "shutdown"
29991
- ]
29992
+ ],
29993
+ ensure_commands: ["git"]
29992
29994
  },
29993
29995
  network: {
29994
29996
  mode: "host",
@@ -30014,13 +30016,9 @@ var DEFAULT_CONFIG = {
30014
30016
  },
30015
30017
  plugins: {
30016
30018
  files: true,
30019
+ activity: true,
30017
30020
  datasets: false,
30018
30021
  results: false,
30019
- charting: true,
30020
- molecular: true,
30021
- genomics: true,
30022
- phylogenetics: true,
30023
- network: true,
30024
30022
  slurm: true,
30025
30023
  explorer: true,
30026
30024
  automation: false
@@ -30041,7 +30039,7 @@ var DEFAULT_CONFIG = {
30041
30039
  max_tokens: 1024
30042
30040
  },
30043
30041
  headless: {
30044
- claude_run_with_allowed_permissions: true,
30042
+ claude_run_with_allowed_permissions: false,
30045
30043
  continuation_in_other_terminals: true,
30046
30044
  git_integration: false
30047
30045
  }
@@ -30594,9 +30592,9 @@ var ResultsStore = class {
30594
30592
  }
30595
30593
  }
30596
30594
  try {
30597
- ensurePrivateDir(dirname(this.dbPath));
30595
+ ensurePrivateDir(dirname2(this.dbPath));
30598
30596
  const normalizedRaw = legacyRaw.trimEnd();
30599
- writeFileSync(
30597
+ writeFileSync2(
30600
30598
  this.dbPath,
30601
30599
  (normalizedRaw || JSON.stringify({ version: 1, results: [] }, null, 2)) + "\n",
30602
30600
  {
@@ -30609,10 +30607,10 @@ var ResultsStore = class {
30609
30607
  }
30610
30608
  }
30611
30609
  ensureFile() {
30612
- ensurePrivateDir(dirname(this.dbPath));
30610
+ ensurePrivateDir(dirname2(this.dbPath));
30613
30611
  if (!existsSync2(this.dbPath)) {
30614
30612
  const initial = { version: 1, results: [] };
30615
- writeFileSync(this.dbPath, JSON.stringify(initial, null, 2) + "\n", {
30613
+ writeFileSync2(this.dbPath, JSON.stringify(initial, null, 2) + "\n", {
30616
30614
  encoding: "utf-8",
30617
30615
  mode: PRIVATE_FILE_MODE
30618
30616
  });
@@ -30666,8 +30664,8 @@ var ResultsStore = class {
30666
30664
  }
30667
30665
  writeFile(next) {
30668
30666
  const payload = JSON.stringify(next, null, 2) + "\n";
30669
- const tmpPath = join2(dirname(this.dbPath), `.${Date.now()}.${process.pid}.${randomUUID()}.results.tmp`);
30670
- writeFileSync(tmpPath, payload, {
30667
+ const tmpPath = join2(dirname2(this.dbPath), `.${Date.now()}.${process.pid}.${randomUUID()}.results.tmp`);
30668
+ writeFileSync2(tmpPath, payload, {
30671
30669
  encoding: "utf-8",
30672
30670
  mode: PRIVATE_FILE_MODE
30673
30671
  });
@@ -30682,7 +30680,7 @@ var ResultsStore = class {
30682
30680
  throw err;
30683
30681
  }
30684
30682
  try {
30685
- writeFileSync(this.dbPath, payload, {
30683
+ writeFileSync2(this.dbPath, payload, {
30686
30684
  encoding: "utf-8",
30687
30685
  mode: PRIVATE_FILE_MODE
30688
30686
  });
@@ -30759,9 +30757,9 @@ function isPathInside(rootPath, targetPath) {
30759
30757
  }
30760
30758
  function buildAllowedRoots(input) {
30761
30759
  const roots = [
30762
- input.executionWorkdir ? resolve(input.executionWorkdir) : "",
30763
- input.workdir ? resolve(input.workdir) : "",
30764
- resolve(process.cwd())
30760
+ input.executionWorkdir ? resolve2(input.executionWorkdir) : "",
30761
+ input.workdir ? resolve2(input.workdir) : "",
30762
+ resolve2(process.cwd())
30765
30763
  ].filter(Boolean);
30766
30764
  return [...new Set(roots)];
30767
30765
  }
@@ -30773,16 +30771,16 @@ function ensurePathAllowed(path, allowedRoots) {
30773
30771
  );
30774
30772
  }
30775
30773
  function ensureScriptOnDisk(scriptPath, allowedRoots, scriptContent) {
30776
- const resolvedPath = resolve(String(scriptPath || "").trim());
30774
+ const resolvedPath = resolve2(String(scriptPath || "").trim());
30777
30775
  if (!resolvedPath) {
30778
30776
  throw new Error("reproducibility.script_path is required.");
30779
30777
  }
30780
30778
  ensurePathAllowed(resolvedPath, allowedRoots);
30781
30779
  if (typeof scriptContent === "string") {
30782
- mkdirSync2(dirname2(resolvedPath), { recursive: true });
30780
+ mkdirSync2(dirname3(resolvedPath), { recursive: true });
30783
30781
  const normalized = scriptContent.endsWith("\n") ? scriptContent : `${scriptContent}
30784
30782
  `;
30785
- writeFileSync2(resolvedPath, normalized, "utf-8");
30783
+ writeFileSync3(resolvedPath, normalized, "utf-8");
30786
30784
  try {
30787
30785
  chmodSync2(resolvedPath, 493);
30788
30786
  } catch {
@@ -30807,7 +30805,7 @@ function makeDefaultExecution(strategy, runNow) {
30807
30805
  return { status: "not_run" };
30808
30806
  }
30809
30807
  async function executeLocalReproScript(input) {
30810
- const cwd = input.workdir ? resolve(input.workdir) : dirname2(input.scriptPath);
30808
+ const cwd = input.workdir ? resolve2(input.workdir) : dirname3(input.scriptPath);
30811
30809
  const timeoutMs = clampInt2(input.timeoutSeconds, DEFAULT_REPRO_TIMEOUT_SECONDS, 10, 86400) * 1e3;
30812
30810
  const start = Date.now();
30813
30811
  const scriptKind = String(input.scriptKind || "").toLowerCase();
@@ -30883,7 +30881,7 @@ async function executeLocalReproScript(input) {
30883
30881
  }
30884
30882
  }
30885
30883
  async function executeSlurmReproScript(input) {
30886
- const cwd = input.workdir ? resolve(input.workdir) : dirname2(input.scriptPath);
30884
+ const cwd = input.workdir ? resolve2(input.workdir) : dirname3(input.scriptPath);
30887
30885
  const timeoutMs = clampInt2(input.timeoutSeconds, DEFAULT_REPRO_TIMEOUT_SECONDS, 10, 86400) * 1e3;
30888
30886
  const start = Date.now();
30889
30887
  const useCustomCommand = typeof input.commandOverride === "string" && input.commandOverride.trim().length > 0;
@@ -2985,7 +2985,7 @@ var require_compile = __commonJS({
2985
2985
  const schOrFunc = root.refs[ref];
2986
2986
  if (schOrFunc)
2987
2987
  return schOrFunc;
2988
- let _sch = resolve.call(this, root, ref);
2988
+ let _sch = resolve2.call(this, root, ref);
2989
2989
  if (_sch === void 0) {
2990
2990
  const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
2991
2991
  const { schemaId } = this.opts;
@@ -3012,7 +3012,7 @@ var require_compile = __commonJS({
3012
3012
  function sameSchemaEnv(s1, s2) {
3013
3013
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
3014
3014
  }
3015
- function resolve(root, ref) {
3015
+ function resolve2(root, ref) {
3016
3016
  let sch;
3017
3017
  while (typeof (sch = this.refs[ref]) == "string")
3018
3018
  ref = sch;
@@ -3587,7 +3587,7 @@ var require_fast_uri = __commonJS({
3587
3587
  }
3588
3588
  return uri;
3589
3589
  }
3590
- function resolve(baseURI, relativeURI, options) {
3590
+ function resolve2(baseURI, relativeURI, options) {
3591
3591
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3592
3592
  const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
3593
3593
  schemelessOptions.skipEscape = true;
@@ -3814,7 +3814,7 @@ var require_fast_uri = __commonJS({
3814
3814
  var fastUri = {
3815
3815
  SCHEMES,
3816
3816
  normalize,
3817
- resolve,
3817
+ resolve: resolve2,
3818
3818
  resolveComponent,
3819
3819
  equal,
3820
3820
  serialize,
@@ -27970,7 +27970,7 @@ var Protocol = class {
27970
27970
  return;
27971
27971
  }
27972
27972
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
27973
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
27973
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
27974
27974
  options?.signal?.throwIfAborted();
27975
27975
  }
27976
27976
  } catch (error48) {
@@ -27987,7 +27987,7 @@ var Protocol = class {
27987
27987
  */
27988
27988
  request(request, resultSchema, options) {
27989
27989
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
27990
- return new Promise((resolve, reject) => {
27990
+ return new Promise((resolve2, reject) => {
27991
27991
  const earlyReject = (error48) => {
27992
27992
  reject(error48);
27993
27993
  };
@@ -28065,7 +28065,7 @@ var Protocol = class {
28065
28065
  if (!parseResult.success) {
28066
28066
  reject(parseResult.error);
28067
28067
  } else {
28068
- resolve(parseResult.data);
28068
+ resolve2(parseResult.data);
28069
28069
  }
28070
28070
  } catch (error48) {
28071
28071
  reject(error48);
@@ -28326,12 +28326,12 @@ var Protocol = class {
28326
28326
  }
28327
28327
  } catch {
28328
28328
  }
28329
- return new Promise((resolve, reject) => {
28329
+ return new Promise((resolve2, reject) => {
28330
28330
  if (signal.aborted) {
28331
28331
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
28332
28332
  return;
28333
28333
  }
28334
- const timeoutId = setTimeout(resolve, interval);
28334
+ const timeoutId = setTimeout(resolve2, interval);
28335
28335
  signal.addEventListener("abort", () => {
28336
28336
  clearTimeout(timeoutId);
28337
28337
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -29290,7 +29290,7 @@ var McpServer = class {
29290
29290
  let task = createTaskResult.task;
29291
29291
  const pollInterval = task.pollInterval ?? 5e3;
29292
29292
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
29293
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
29293
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
29294
29294
  const updatedTask = await extra.taskStore.getTask(taskId);
29295
29295
  if (!updatedTask) {
29296
29296
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -29933,12 +29933,12 @@ var StdioServerTransport = class {
29933
29933
  this.onclose?.();
29934
29934
  }
29935
29935
  send(message) {
29936
- return new Promise((resolve) => {
29936
+ return new Promise((resolve2) => {
29937
29937
  const json2 = serializeMessage(message);
29938
29938
  if (this._stdout.write(json2)) {
29939
- resolve();
29939
+ resolve2();
29940
29940
  } else {
29941
- this._stdout.once("drain", resolve);
29941
+ this._stdout.once("drain", resolve2);
29942
29942
  }
29943
29943
  });
29944
29944
  }
@@ -30312,10 +30312,11 @@ var SlurmJobDB = class {
30312
30312
  };
30313
30313
 
30314
30314
  // src/lib/config.ts
30315
- import { join } from "path";
30315
+ import { dirname as dirname2, join, resolve } from "path";
30316
30316
  import { homedir } from "os";
30317
30317
  var DEFAULT_CONFIG = {
30318
30318
  runtime: "auto",
30319
+ images_dir: "",
30319
30320
  // Default sandbox image: includes python3 + basic build tools (git/make/g++).
30320
30321
  // Note: pip/venv are not included by default in Debian; users may still need a
30321
30322
  // custom image for richer Python workflows.
@@ -30348,7 +30349,8 @@ var DEFAULT_CONFIG = {
30348
30349
  "mkfs",
30349
30350
  "reboot",
30350
30351
  "shutdown"
30351
- ]
30352
+ ],
30353
+ ensure_commands: ["git"]
30352
30354
  },
30353
30355
  network: {
30354
30356
  mode: "host",
@@ -30374,13 +30376,9 @@ var DEFAULT_CONFIG = {
30374
30376
  },
30375
30377
  plugins: {
30376
30378
  files: true,
30379
+ activity: true,
30377
30380
  datasets: false,
30378
30381
  results: false,
30379
- charting: true,
30380
- molecular: true,
30381
- genomics: true,
30382
- phylogenetics: true,
30383
- network: true,
30384
30382
  slurm: true,
30385
30383
  explorer: true,
30386
30384
  automation: false
@@ -30401,7 +30399,7 @@ var DEFAULT_CONFIG = {
30401
30399
  max_tokens: 1024
30402
30400
  },
30403
30401
  headless: {
30404
- claude_run_with_allowed_permissions: true,
30402
+ claude_run_with_allowed_permissions: false,
30405
30403
  continuation_in_other_terminals: true,
30406
30404
  git_integration: false
30407
30405
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "labgate",
3
- "version": "0.5.39",
3
+ "version": "0.5.42",
4
4
  "description": "Secure HPC wrapper for AI coding agents (Claude-first): policy controls, Apptainer sandboxes, and SLURM workflows — https://labgate.dev",
5
5
  "homepage": "https://labgate.dev",
6
6
  "keywords": [