diff --git a/install.md b/install.md index 2f3eea4..d72fc57 100644 --- a/install.md +++ b/install.md @@ -87,9 +87,9 @@ Pre-pulling is required. MCP servers have a short initialization timeout - if Do Hyperstack enforces a **singleton container policy**. If a `hyperstack-mcp` container exists OR any container is running from the `hyperstack:main` image, it must be removed before starting a fresh one to ensure no stale state persists. -Run the provided singleton enforcement script: +Run the provided cross-platform singleton enforcement script (requires Bun): ```bash -bash scripts/ensure-singleton.sh +bun scripts/ensure-singleton.ts ``` Or run the hard check manually: diff --git a/package.json b/package.json index 59c01f4..efb71b2 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "test": "bun test", "start": "bun src/index.ts", "dev": "bun --watch src/index.ts", - "docker:run": "bash scripts/ensure-singleton.sh" + "docker:run": "bun scripts/ensure-singleton.ts" }, "author": "Orkait", "license": "MIT", diff --git a/scripts/ensure-singleton.sh b/scripts/ensure-singleton.sh deleted file mode 100755 index 51933d6..0000000 --- a/scripts/ensure-singleton.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -# Hard check to ensure only one Hyperstack container is running. -# Removes all previous instances (by name or image) before starting a fresh one. - -IMAGE="ghcr.io/orkait/hyperstack:main" -CONTAINER_NAME="hyperstack-mcp" - -echo "Checking for existing Hyperstack containers..." - -# 1. Find containers by the specific image -BY_IMAGE=$(docker ps -aq --filter "ancestor=$IMAGE") - -# 2. Find containers by name -BY_NAME=$(docker ps -aq --filter "name=$CONTAINER_NAME") - -# Combine and remove duplicates -ALL_STALE=$(echo "$BY_IMAGE $BY_NAME" | xargs -n1 | sort -u) - -if [ -n "$ALL_STALE" ]; then - echo "Removing stale Hyperstack containers: $ALL_STALE" - docker rm -f $ALL_STALE 2>/dev/null -else - echo "No stale containers found." -fi - -echo "Starting fresh Hyperstack container: $CONTAINER_NAME" -docker run -d --name "$CONTAINER_NAME" --restart unless-stopped \ - --memory=512m --cpus=1 \ - --entrypoint sleep \ - "$IMAGE" infinity - -echo "Verification:" -docker ps --filter name="$CONTAINER_NAME" diff --git a/scripts/ensure-singleton.ts b/scripts/ensure-singleton.ts new file mode 100644 index 0000000..635f519 --- /dev/null +++ b/scripts/ensure-singleton.ts @@ -0,0 +1,44 @@ +import { execSync } from "child_process"; + +const IMAGE = "ghcr.io/orkait/hyperstack:main"; +const CONTAINER_NAME = "hyperstack-mcp"; + +function run() { + console.log("Checking for existing Hyperstack containers (cross-platform)..."); + + try { + // 1. Find containers by image and name + const byImage = execSync(`docker ps -aq --filter "ancestor=${IMAGE}"`).toString().trim().split(/\s+/).filter(Boolean); + const byName = execSync(`docker ps -aq --filter "name=${CONTAINER_NAME}"`).toString().trim().split(/\s+/).filter(Boolean); + + // 2. Combine and uniq + const allStale = Array.from(new Set([...byImage, ...byName])); + + if (allStale.length > 0) { + console.log(`Removing stale Hyperstack containers: ${allStale.join(", ")}`); + // We use a loop or join with space since 'docker rm -f' accepts multiple IDs + execSync(`docker rm -f ${allStale.join(" ")}`, { stdio: "inherit" }); + } else { + console.log("No stale containers found."); + } + + // 3. Start fresh container + console.log(`Starting fresh Hyperstack container: ${CONTAINER_NAME}`); + execSync( + `docker run -d --name ${CONTAINER_NAME} --restart unless-stopped \ + --memory=512m --cpus=1 \ + --entrypoint sleep \ + ${IMAGE} infinity`, + { stdio: "inherit" } + ); + + console.log("\nVerification:"); + execSync(`docker ps --filter name=${CONTAINER_NAME}`, { stdio: "inherit" }); + + } catch (error: any) { + console.error("Error ensuring singleton container:", error.message); + process.exit(1); + } +} + +run();