@daghis/teamcity-mcp 1.8.1 → 1.8.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.8.2](https://github.com/Daghis/teamcity-mcp/compare/v1.8.1...v1.8.2) (2025-09-20)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **tools:** harden batch artifact streaming outputs ([#177](https://github.com/Daghis/teamcity-mcp/issues/177)) ([0874325](https://github.com/Daghis/teamcity-mcp/commit/0874325c77aa2a79050cff57fced0aeec5a55ba0))
9
+
3
10
  ## [1.8.1](https://github.com/Daghis/teamcity-mcp/compare/v1.8.0...v1.8.1) (2025-09-20)
4
11
 
5
12
 
package/dist/index.js CHANGED
@@ -1308,7 +1308,7 @@ var ArtifactManager = class _ArtifactManager {
1308
1308
  }
1309
1309
  }
1310
1310
  async delay(ms) {
1311
- await new Promise((resolve) => setTimeout(resolve, ms));
1311
+ await new Promise((resolve2) => setTimeout(resolve2, ms));
1312
1312
  }
1313
1313
  };
1314
1314
 
@@ -2836,13 +2836,13 @@ async function handleRetry(axiosInstance, currentState, error2, config2) {
2836
2836
  if (config2.signal?.aborted) {
2837
2837
  return Promise.resolve(axiosInstance(config2));
2838
2838
  }
2839
- return new Promise((resolve) => {
2839
+ return new Promise((resolve2) => {
2840
2840
  const abortListener = () => {
2841
2841
  clearTimeout(timeout);
2842
- resolve(axiosInstance(config2));
2842
+ resolve2(axiosInstance(config2));
2843
2843
  };
2844
2844
  const timeout = setTimeout(() => {
2845
- resolve(axiosInstance(config2));
2845
+ resolve2(axiosInstance(config2));
2846
2846
  if (config2.signal?.removeEventListener) {
2847
2847
  config2.signal.removeEventListener("abort", abortListener);
2848
2848
  }
@@ -36890,12 +36890,13 @@ var ensureUniquePath = async (candidate) => {
36890
36890
  const probe = async (attempt) => {
36891
36891
  const next = attempt === 0 ? candidate : `${stem}-${attempt}${ext}`;
36892
36892
  try {
36893
- await import_node_fs.promises.access(next);
36894
- return probe(attempt + 1);
36893
+ const handle = await import_node_fs.promises.open(next, "wx");
36894
+ await handle.close();
36895
+ return next;
36895
36896
  } catch (error2) {
36896
36897
  const err = error2;
36897
- if (err?.code === "ENOENT") {
36898
- return next;
36898
+ if (err?.code === "EEXIST") {
36899
+ return probe(attempt + 1);
36899
36900
  }
36900
36901
  throw error2;
36901
36902
  }
@@ -36912,7 +36913,12 @@ var resolveStreamOutputPath = async (artifact, options) => {
36912
36913
  const segments = sanitizePathSegments(artifact.path, artifact.name);
36913
36914
  const parts = segments.slice(0, -1);
36914
36915
  const fileName = segments[segments.length - 1] ?? sanitizeFileName(artifact.name).sanitizedBase;
36915
- const candidate = (0, import_node_path.join)(options.outputDir, ...parts, fileName);
36916
+ const baseDir = (0, import_node_path.resolve)(options.outputDir);
36917
+ const candidate = (0, import_node_path.resolve)(baseDir, ...parts, fileName);
36918
+ const relativePath = (0, import_node_path.relative)(baseDir, candidate);
36919
+ if (relativePath.startsWith("..") || (0, import_node_path.isAbsolute)(relativePath)) {
36920
+ throw new Error("Resolved artifact path escapes the configured output directory");
36921
+ }
36916
36922
  await import_node_fs.promises.mkdir((0, import_node_path.dirname)(candidate), { recursive: true });
36917
36923
  return ensureUniquePath(candidate);
36918
36924
  }
@@ -37594,8 +37600,8 @@ var DEV_TOOLS = [
37594
37600
  }
37595
37601
  return new Error(String(error2));
37596
37602
  };
37597
- const wait = (ms) => new Promise((resolve) => {
37598
- setTimeout(resolve, ms);
37603
+ const wait = (ms) => new Promise((resolve2) => {
37604
+ setTimeout(resolve2, ms);
37599
37605
  });
37600
37606
  const attemptBuffered = async () => {
37601
37607
  if (typed.tail) {