From 97543bb937f88d2957124c0a2e88670402f6df72 Mon Sep 17 00:00:00 2001 From: Hakancan Date: Tue, 17 Mar 2026 14:58:07 +0000 Subject: [PATCH 1/3] fix: normalize sandbox names to lowercase to prevent creation failures --- nemoclaw-blueprint/orchestrator/runner.py | 23 +++++- nemoclaw/dist/index.d.ts.map | 2 +- nemoclaw/dist/index.js | 23 +++++- nemoclaw/dist/index.js.map | 2 +- nemoclaw/src/index.ts | 28 ++++++- test/sandbox-name.test.js | 93 +++++++++++++++++++++++ 6 files changed, 159 insertions(+), 12 deletions(-) create mode 100644 test/sandbox-name.test.js diff --git a/nemoclaw-blueprint/orchestrator/runner.py b/nemoclaw-blueprint/orchestrator/runner.py index 432c228c3be..4234392111f 100644 --- a/nemoclaw-blueprint/orchestrator/runner.py +++ b/nemoclaw-blueprint/orchestrator/runner.py @@ -17,6 +17,7 @@ import argparse import json import os +import re import shutil import subprocess import sys @@ -72,6 +73,17 @@ def openshell_available() -> bool: return shutil.which("openshell") is not None +def normalize_sandbox_name(name: str) -> str: + """Normalize sandbox name to lowercase and validate it.""" + normalized = name.lower() + # Only lowercase letters, numbers, and hyphens allowed + if not re.match(r'^[a-z0-9-]+$', normalized): + raise ValueError(f"Invalid sandbox name: '{name}'. Only lowercase letters, numbers, and hyphens are allowed.") + if len(normalized) > 64: + raise ValueError(f"Sandbox name too long: '{name}'. Must be 64 characters or less.") + return normalized + + # --------------------------------------------------------------------------- # Actions # --------------------------------------------------------------------------- @@ -109,12 +121,15 @@ def action_plan( if endpoint_url: inference_cfg = {**inference_cfg, "endpoint": endpoint_url} + # Normalize sandbox name to lowercase + sandbox_name = normalize_sandbox_name(sandbox_cfg.get("name", "openclaw")) + plan: dict[str, Any] = { "run_id": rid, "profile": profile, "sandbox": { "image": sandbox_cfg.get("image", "openclaw"), - "name": sandbox_cfg.get("name", "openclaw"), + "name": sandbox_name, "forward_ports": sandbox_cfg.get("forward_ports", [18789]), }, "inference": { @@ -160,7 +175,8 @@ def action_apply( sandbox_cfg: dict[str, Any] = blueprint.get("components", {}).get("sandbox", {}) - sandbox_name: str = sandbox_cfg.get("name", "openclaw") + # Normalize sandbox name to lowercase + sandbox_name: str = normalize_sandbox_name(sandbox_cfg.get("name", "openclaw")) sandbox_image: str = sandbox_cfg.get("image", "openclaw") forward_ports: list[int] = sandbox_cfg.get("forward_ports", [18789]) @@ -282,7 +298,8 @@ def action_rollback(rid: str) -> None: plan_file = state_dir / "plan.json" if plan_file.exists(): plan = json.loads(plan_file.read_text()) - sandbox_name = plan.get("sandbox_name", "openclaw") + # Normalize sandbox name from plan (in case it was saved before normalization) + sandbox_name = normalize_sandbox_name(plan.get("sandbox_name", "openclaw")) progress(30, f"Stopping sandbox {sandbox_name}") run_cmd( diff --git a/nemoclaw/dist/index.d.ts.map b/nemoclaw/dist/index.d.ts.map index be261bffe08..d53d959925f 100644 --- a/nemoclaw/dist/index.d.ts.map +++ b/nemoclaw/dist/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/dist/index.js b/nemoclaw/dist/index.js index 058f2303085..55450d8d7d1 100644 --- a/nemoclaw/dist/index.js +++ b/nemoclaw/dist/index.js @@ -64,6 +64,25 @@ const DEFAULT_PLUGIN_CONFIG = { sandboxName: "openclaw", inferenceProvider: "nvidia", }; +/** + * Normalizes a sandbox name to lowercase and validates it. + * Returns the normalized name or the default if invalid. + */ +function normalizeSandboxName(name, defaultName) { + if (typeof name !== "string" || !name) { + return defaultName; + } + // Normalize to lowercase + const normalized = name.toLowerCase(); + // Validate: only lowercase letters, numbers, and hyphens allowed + if (!/^[a-z0-9-]+$/.test(normalized)) { + return defaultName; + } + if (normalized.length > 64) { + return defaultName; + } + return normalized; +} function getPluginConfig(api) { const raw = api.pluginConfig ?? {}; return { @@ -73,9 +92,7 @@ function getPluginConfig(api) { blueprintRegistry: typeof raw["blueprintRegistry"] === "string" ? raw["blueprintRegistry"] : DEFAULT_PLUGIN_CONFIG.blueprintRegistry, - sandboxName: typeof raw["sandboxName"] === "string" - ? raw["sandboxName"] - : DEFAULT_PLUGIN_CONFIG.sandboxName, + sandboxName: normalizeSandboxName(raw["sandboxName"], DEFAULT_PLUGIN_CONFIG.sandboxName), inferenceProvider: typeof raw["inferenceProvider"] === "string" ? raw["inferenceProvider"] : DEFAULT_PLUGIN_CONFIG.inferenceProvider, diff --git a/nemoclaw/dist/index.js.map b/nemoclaw/dist/index.js.map index 1c22a36ec3e..f416a8b1c6a 100644 --- a/nemoclaw/dist/index.js.map +++ b/nemoclaw/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/src/index.ts b/nemoclaw/src/index.ts index f6defcd41b5..e5ee3ce26c2 100644 --- a/nemoclaw/src/index.ts +++ b/nemoclaw/src/index.ts @@ -213,6 +213,26 @@ const DEFAULT_PLUGIN_CONFIG: NemoClawConfig = { inferenceProvider: "nvidia", }; +/** + * Normalizes a sandbox name to lowercase and validates it. + * Returns the normalized name or the default if invalid. + */ +function normalizeSandboxName(name: string | unknown, defaultName: string): string { + if (typeof name !== "string" || !name) { + return defaultName; + } + // Normalize to lowercase + const normalized = name.toLowerCase(); + // Validate: only lowercase letters, numbers, and hyphens allowed + if (!/^[a-z0-9-]+$/.test(normalized)) { + return defaultName; + } + if (normalized.length > 64) { + return defaultName; + } + return normalized; +} + export function getPluginConfig(api: OpenClawPluginApi): NemoClawConfig { const raw = api.pluginConfig ?? {}; return { @@ -224,10 +244,10 @@ export function getPluginConfig(api: OpenClawPluginApi): NemoClawConfig { typeof raw["blueprintRegistry"] === "string" ? raw["blueprintRegistry"] : DEFAULT_PLUGIN_CONFIG.blueprintRegistry, - sandboxName: - typeof raw["sandboxName"] === "string" - ? raw["sandboxName"] - : DEFAULT_PLUGIN_CONFIG.sandboxName, + sandboxName: normalizeSandboxName( + raw["sandboxName"], + DEFAULT_PLUGIN_CONFIG.sandboxName, + ), inferenceProvider: typeof raw["inferenceProvider"] === "string" ? raw["inferenceProvider"] diff --git a/test/sandbox-name.test.js b/test/sandbox-name.test.js new file mode 100644 index 00000000000..89def65edba --- /dev/null +++ b/test/sandbox-name.test.js @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +const { describe, it } = require("node:test"); +const assert = require("node:assert/strict"); + +// Import the validateSandboxName function from onboard.js +// We need to extract it for testing +const fs = require("fs"); +const path = require("path"); + +// Read and evaluate the onboard.js file to extract the validateSandboxName function +const onboardPath = path.join(__dirname, "..", "bin", "lib", "onboard.js"); +const onboardCode = fs.readFileSync(onboardPath, "utf-8"); + +// Extract just the validateSandboxName function using regex +const validateSandboxNameMatch = onboardCode.match( + /function validateSandboxName\(name\) \{[\s\S]*?\n\}/ +); +assert.ok(validateSandboxNameMatch, "validateSandboxName function not found"); + +// Create a function from the extracted code +const validateSandboxName = new Function( + "return " + validateSandboxNameMatch[0] +)(); + +describe("validateSandboxName", () => { + it("accepts valid lowercase names", () => { + const result = validateSandboxName("my-assistant"); + assert.equal(result.valid, true); + assert.equal(result.normalized, "my-assistant"); + }); + + it("normalizes uppercase letters to lowercase", () => { + const result = validateSandboxName("My-Assistant"); + assert.equal(result.valid, true); + assert.equal(result.normalized, "my-assistant"); + }); + + it("normalizes all uppercase names to lowercase", () => { + const result = validateSandboxName("MY-ASSISTANT"); + assert.equal(result.valid, true); + assert.equal(result.normalized, "my-assistant"); + }); + + it("accepts names with numbers", () => { + const result = validateSandboxName("assistant-123"); + assert.equal(result.valid, true); + assert.equal(result.normalized, "assistant-123"); + }); + + it("accepts names starting with numbers", () => { + const result = validateSandboxName("123-assistant"); + assert.equal(result.valid, true); + assert.equal(result.normalized, "123-assistant"); + }); + + it("rejects names with special characters", () => { + const result = validateSandboxName("my_assistant"); + assert.equal(result.valid, false); + assert.ok(result.error.includes("lowercase letters, numbers, and hyphens")); + }); + + it("rejects names with spaces", () => { + const result = validateSandboxName("my assistant"); + assert.equal(result.valid, false); + }); + + it("rejects empty names", () => { + const result = validateSandboxName(""); + assert.equal(result.valid, false); + }); + + it("rejects names longer than 64 characters", () => { + const longName = "a".repeat(65); + const result = validateSandboxName(longName); + assert.equal(result.valid, false); + assert.ok(result.error.includes("64 characters")); + }); + + it("accepts names exactly 64 characters", () => { + const name64 = "a".repeat(64); + const result = validateSandboxName(name64); + assert.equal(result.valid, true); + assert.equal(result.normalized, name64); + }); + + it("normalizes mixed case with numbers and hyphens", () => { + const result = validateSandboxName("My-Assistant-123-Test"); + assert.equal(result.valid, true); + assert.equal(result.normalized, "my-assistant-123-test"); + }); +}); From 33c8551f57e11b370b21de4883eb3679147a7118 Mon Sep 17 00:00:00 2001 From: Hakancan Date: Sat, 21 Mar 2026 09:23:36 +0000 Subject: [PATCH 2/3] refactor: export normalizeSandboxName and guard against non-string input - Export normalizeSandboxName from index.ts so it can be imported by callers - Add isinstance check in Python normalize_sandbox_name to handle non-string inputs (e.g. None) with a clear error instead of AttributeError - Wrap all normalize_sandbox_name call sites in runner.py with try/except to surface validation errors as clean CLI messages instead of tracebacks --- nemoclaw-blueprint/orchestrator/runner.py | 19 +++++++++++++++---- nemoclaw/src/index.ts | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/nemoclaw-blueprint/orchestrator/runner.py b/nemoclaw-blueprint/orchestrator/runner.py index 4234392111f..4c2293bd712 100644 --- a/nemoclaw-blueprint/orchestrator/runner.py +++ b/nemoclaw-blueprint/orchestrator/runner.py @@ -73,8 +73,10 @@ def openshell_available() -> bool: return shutil.which("openshell") is not None -def normalize_sandbox_name(name: str) -> str: +def normalize_sandbox_name(name: object) -> str: """Normalize sandbox name to lowercase and validate it.""" + if not isinstance(name, str): + raise ValueError(f"Invalid sandbox name: expected string, got {type(name).__name__!r}.") normalized = name.lower() # Only lowercase letters, numbers, and hyphens allowed if not re.match(r'^[a-z0-9-]+$', normalized): @@ -122,7 +124,10 @@ def action_plan( inference_cfg = {**inference_cfg, "endpoint": endpoint_url} # Normalize sandbox name to lowercase - sandbox_name = normalize_sandbox_name(sandbox_cfg.get("name", "openclaw")) + try: + sandbox_name = normalize_sandbox_name(sandbox_cfg.get("name", "openclaw")) + except ValueError as exc: + sys.exit(f"Error: {exc}") plan: dict[str, Any] = { "run_id": rid, @@ -176,7 +181,10 @@ def action_apply( sandbox_cfg: dict[str, Any] = blueprint.get("components", {}).get("sandbox", {}) # Normalize sandbox name to lowercase - sandbox_name: str = normalize_sandbox_name(sandbox_cfg.get("name", "openclaw")) + try: + sandbox_name: str = normalize_sandbox_name(sandbox_cfg.get("name", "openclaw")) + except ValueError as exc: + sys.exit(f"Error: {exc}") sandbox_image: str = sandbox_cfg.get("image", "openclaw") forward_ports: list[int] = sandbox_cfg.get("forward_ports", [18789]) @@ -299,7 +307,10 @@ def action_rollback(rid: str) -> None: if plan_file.exists(): plan = json.loads(plan_file.read_text()) # Normalize sandbox name from plan (in case it was saved before normalization) - sandbox_name = normalize_sandbox_name(plan.get("sandbox_name", "openclaw")) + try: + sandbox_name = normalize_sandbox_name(plan.get("sandbox_name", "openclaw")) + except ValueError as exc: + sys.exit(f"Error: {exc}") progress(30, f"Stopping sandbox {sandbox_name}") run_cmd( diff --git a/nemoclaw/src/index.ts b/nemoclaw/src/index.ts index e5ee3ce26c2..0b77ee44c11 100644 --- a/nemoclaw/src/index.ts +++ b/nemoclaw/src/index.ts @@ -217,7 +217,7 @@ const DEFAULT_PLUGIN_CONFIG: NemoClawConfig = { * Normalizes a sandbox name to lowercase and validates it. * Returns the normalized name or the default if invalid. */ -function normalizeSandboxName(name: string | unknown, defaultName: string): string { +export function normalizeSandboxName(name: string | unknown, defaultName: string): string { if (typeof name !== "string" || !name) { return defaultName; } From bd7a5f922cdb12ee6a043e595dc2bdd75ea486cb Mon Sep 17 00:00:00 2001 From: Hakancan Date: Sat, 28 Mar 2026 23:55:28 +0000 Subject: [PATCH 3/3] fix: update test to validate actual implementations and rebuild dist - Update test/sandbox-name.test.js to test the actual implementations: - TypeScript normalizeSandboxName in nemoclaw/src/index.ts - Python normalize_sandbox_name in nemoclaw-blueprint/orchestrator/runner.py - Rebuild nemoclaw dist to export normalizeSandboxName function - All 23 tests now pass --- nemoclaw/dist/index.d.ts | 5 + nemoclaw/dist/index.d.ts.map | 2 +- nemoclaw/dist/index.js | 1 + nemoclaw/dist/index.js.map | 2 +- test/sandbox-name.test.js | 274 ++++++++++++++++++++++++----------- 5 files changed, 199 insertions(+), 85 deletions(-) diff --git a/nemoclaw/dist/index.d.ts b/nemoclaw/dist/index.d.ts index 1ad200e605c..a48e982213e 100644 --- a/nemoclaw/dist/index.d.ts +++ b/nemoclaw/dist/index.d.ts @@ -121,6 +121,11 @@ export interface NemoClawConfig { sandboxName: string; inferenceProvider: string; } +/** + * Normalizes a sandbox name to lowercase and validates it. + * Returns the normalized name or the default if invalid. + */ +export declare function normalizeSandboxName(name: string | unknown, defaultName: string): string; export declare function getPluginConfig(api: OpenClawPluginApi): NemoClawConfig; export default function register(api: OpenClawPluginApi): void; //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/nemoclaw/dist/index.d.ts.map b/nemoclaw/dist/index.d.ts.map index d53d959925f..aa8dcf50cca 100644 --- a/nemoclaw/dist/index.d.ts.map +++ b/nemoclaw/dist/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/dist/index.js b/nemoclaw/dist/index.js index 55450d8d7d1..64d587f5d61 100644 --- a/nemoclaw/dist/index.js +++ b/nemoclaw/dist/index.js @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 Object.defineProperty(exports, "__esModule", { value: true }); +exports.normalizeSandboxName = normalizeSandboxName; exports.getPluginConfig = getPluginConfig; exports.default = register; const cli_js_1 = require("./cli.js"); diff --git a/nemoclaw/dist/index.js.map b/nemoclaw/dist/index.js.map index f416a8b1c6a..c887d000e0c 100644 --- a/nemoclaw/dist/index.js.map +++ b/nemoclaw/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/test/sandbox-name.test.js b/test/sandbox-name.test.js index 89def65edba..d0a0d932e1e 100644 --- a/test/sandbox-name.test.js +++ b/test/sandbox-name.test.js @@ -3,91 +3,199 @@ const { describe, it } = require("node:test"); const assert = require("node:assert/strict"); - -// Import the validateSandboxName function from onboard.js -// We need to extract it for testing -const fs = require("fs"); +const { execSync } = require("child_process"); const path = require("path"); - -// Read and evaluate the onboard.js file to extract the validateSandboxName function -const onboardPath = path.join(__dirname, "..", "bin", "lib", "onboard.js"); -const onboardCode = fs.readFileSync(onboardPath, "utf-8"); - -// Extract just the validateSandboxName function using regex -const validateSandboxNameMatch = onboardCode.match( - /function validateSandboxName\(name\) \{[\s\S]*?\n\}/ -); -assert.ok(validateSandboxNameMatch, "validateSandboxName function not found"); - -// Create a function from the extracted code -const validateSandboxName = new Function( - "return " + validateSandboxNameMatch[0] -)(); - -describe("validateSandboxName", () => { - it("accepts valid lowercase names", () => { - const result = validateSandboxName("my-assistant"); - assert.equal(result.valid, true); - assert.equal(result.normalized, "my-assistant"); - }); - - it("normalizes uppercase letters to lowercase", () => { - const result = validateSandboxName("My-Assistant"); - assert.equal(result.valid, true); - assert.equal(result.normalized, "my-assistant"); - }); - - it("normalizes all uppercase names to lowercase", () => { - const result = validateSandboxName("MY-ASSISTANT"); - assert.equal(result.valid, true); - assert.equal(result.normalized, "my-assistant"); - }); - - it("accepts names with numbers", () => { - const result = validateSandboxName("assistant-123"); - assert.equal(result.valid, true); - assert.equal(result.normalized, "assistant-123"); - }); - - it("accepts names starting with numbers", () => { - const result = validateSandboxName("123-assistant"); - assert.equal(result.valid, true); - assert.equal(result.normalized, "123-assistant"); - }); - - it("rejects names with special characters", () => { - const result = validateSandboxName("my_assistant"); - assert.equal(result.valid, false); - assert.ok(result.error.includes("lowercase letters, numbers, and hyphens")); - }); - - it("rejects names with spaces", () => { - const result = validateSandboxName("my assistant"); - assert.equal(result.valid, false); - }); - - it("rejects empty names", () => { - const result = validateSandboxName(""); - assert.equal(result.valid, false); - }); - - it("rejects names longer than 64 characters", () => { - const longName = "a".repeat(65); - const result = validateSandboxName(longName); - assert.equal(result.valid, false); - assert.ok(result.error.includes("64 characters")); - }); - - it("accepts names exactly 64 characters", () => { - const name64 = "a".repeat(64); - const result = validateSandboxName(name64); - assert.equal(result.valid, true); - assert.equal(result.normalized, name64); +const fs = require("fs"); +const os = require("os"); + +// Path to nemoclaw dist directory +const NEMOCLAW_DIST_PATH = path.join(__dirname, "..", "nemoclaw", "dist"); +const RUNNER_PY_PATH = path.join(__dirname, "..", "nemoclaw-blueprint", "orchestrator", "runner.py"); + +describe("Sandbox Name Normalization", () => { + describe("TypeScript normalizeSandboxName (nemoclaw/src/index.ts)", () => { + const indexPath = path.join(NEMOCLAW_DIST_PATH, "index.js"); + + function runNormalizeSandboxName(name, defaultName = "openclaw") { + // Create a temporary test script file + const testScriptPath = path.join(os.tmpdir(), `test-sandbox-${Date.now()}.js`); + const scriptContent = ` +const { normalizeSandboxName } = require('${indexPath.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'); +const result = normalizeSandboxName(${JSON.stringify(name)}, ${JSON.stringify(defaultName)}); +console.log(JSON.stringify(result)); +`; + fs.writeFileSync(testScriptPath, scriptContent); + try { + const result = execSync(`node "${testScriptPath}"`, { encoding: "utf-8", cwd: path.join(__dirname, "..") }); + return JSON.parse(result.trim()); + } finally { + fs.unlinkSync(testScriptPath); + } + } + + it("accepts valid lowercase names", () => { + const result = runNormalizeSandboxName("my-assistant"); + assert.equal(result, "my-assistant"); + }); + + it("normalizes uppercase letters to lowercase", () => { + const result = runNormalizeSandboxName("My-Assistant"); + assert.equal(result, "my-assistant"); + }); + + it("normalizes all uppercase names to lowercase", () => { + const result = runNormalizeSandboxName("MY-ASSISTANT"); + assert.equal(result, "my-assistant"); + }); + + it("accepts names with numbers", () => { + const result = runNormalizeSandboxName("assistant-123"); + assert.equal(result, "assistant-123"); + }); + + it("accepts names starting with numbers", () => { + const result = runNormalizeSandboxName("123-assistant"); + assert.equal(result, "123-assistant"); + }); + + it("returns default for names with special characters", () => { + const result = runNormalizeSandboxName("my_assistant", "default-sandbox"); + assert.equal(result, "default-sandbox"); + }); + + it("returns default for names with spaces", () => { + const result = runNormalizeSandboxName("my assistant", "default-sandbox"); + assert.equal(result, "default-sandbox"); + }); + + it("returns default for empty names", () => { + const result = runNormalizeSandboxName("", "default-sandbox"); + assert.equal(result, "default-sandbox"); + }); + + it("returns default for names longer than 64 characters", () => { + const longName = "a".repeat(65); + const result = runNormalizeSandboxName(longName, "default-sandbox"); + assert.equal(result, "default-sandbox"); + }); + + it("accepts names exactly 64 characters", () => { + const name64 = "a".repeat(64); + const result = runNormalizeSandboxName(name64); + assert.equal(result, name64); + }); + + it("normalizes mixed case with numbers and hyphens", () => { + const result = runNormalizeSandboxName("My-Assistant-123-Test"); + assert.equal(result, "my-assistant-123-test"); + }); + + it("returns default for non-string input", () => { + const result = runNormalizeSandboxName(null, "default-sandbox"); + assert.equal(result, "default-sandbox"); + }); }); - it("normalizes mixed case with numbers and hyphens", () => { - const result = validateSandboxName("My-Assistant-123-Test"); - assert.equal(result.valid, true); - assert.equal(result.normalized, "my-assistant-123-test"); + describe("Python normalize_sandbox_name (runner.py)", () => { + function runNormalizeSandboxName(name) { + const testScriptPath = path.join(os.tmpdir(), `test-sandbox-py-${Date.now()}.py`); + const scriptContent = ` +import sys +sys.path.insert(0, '${path.dirname(RUNNER_PY_PATH).replace(/\\/g, '\\\\').replace(/'/g, "\\'")}') +from runner import normalize_sandbox_name +result = normalize_sandbox_name(${JSON.stringify(name)}) +print(result) +`; + fs.writeFileSync(testScriptPath, scriptContent); + try { + return execSync(`python3 "${testScriptPath}"`, { encoding: "utf-8" }).trim(); + } finally { + fs.unlinkSync(testScriptPath); + } + } + + function runNormalizeSandboxNameError(name) { + const testScriptPath = path.join(os.tmpdir(), `test-sandbox-py-err-${Date.now()}.py`); + // Handle null specially since JSON.stringify(null) becomes "null" not None in Python + const pythonName = name === null ? "None" : JSON.stringify(name); + const scriptContent = ` +import sys +sys.path.insert(0, '${path.dirname(RUNNER_PY_PATH).replace(/\\/g, '\\\\').replace(/'/g, "\\'")}') +from runner import normalize_sandbox_name +try: + normalize_sandbox_name(${pythonName}) + print("NO_ERROR") +except ValueError as e: + print("ERROR: " + str(e)) +except Exception as e: + print("ERROR: " + str(e)) +`; + fs.writeFileSync(testScriptPath, scriptContent); + try { + return execSync(`python3 "${testScriptPath}"`, { encoding: "utf-8" }).trim(); + } finally { + fs.unlinkSync(testScriptPath); + } + } + + it("accepts valid lowercase names", () => { + const result = runNormalizeSandboxName("my-assistant"); + assert.equal(result, "my-assistant"); + }); + + it("normalizes uppercase letters to lowercase", () => { + const result = runNormalizeSandboxName("My-Assistant"); + assert.equal(result, "my-assistant"); + }); + + it("normalizes all uppercase names to lowercase", () => { + const result = runNormalizeSandboxName("MY-ASSISTANT"); + assert.equal(result, "my-assistant"); + }); + + it("accepts names with numbers", () => { + const result = runNormalizeSandboxName("assistant-123"); + assert.equal(result, "assistant-123"); + }); + + it("accepts names starting with numbers", () => { + const result = runNormalizeSandboxName("123-assistant"); + assert.equal(result, "123-assistant"); + }); + + it("rejects names with special characters", () => { + const result = runNormalizeSandboxNameError("my_assistant"); + assert.ok(result.startsWith("ERROR:")); + assert.ok(result.includes("lowercase letters, numbers, and hyphens")); + }); + + it("rejects names with spaces", () => { + const result = runNormalizeSandboxNameError("my assistant"); + assert.ok(result.startsWith("ERROR:")); + }); + + it("rejects non-string input", () => { + const result = runNormalizeSandboxNameError(null); + assert.ok(result.startsWith("ERROR:")); + assert.ok(result.includes("expected") || result.includes("Invalid")); + }); + + it("rejects names longer than 64 characters", () => { + const longName = "a".repeat(65); + const result = runNormalizeSandboxNameError(longName); + assert.ok(result.startsWith("ERROR:")); + assert.ok(result.includes("64 characters")); + }); + + it("accepts names exactly 64 characters", () => { + const name64 = "a".repeat(64); + const result = runNormalizeSandboxName(name64); + assert.equal(result, name64); + }); + + it("normalizes mixed case with numbers and hyphens", () => { + const result = runNormalizeSandboxName("My-Assistant-123-Test"); + assert.equal(result, "my-assistant-123-test"); + }); }); });