labgate 0.5.45 → 0.5.46
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 +2 -0
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/lib/config.d.ts +1 -1
- package/dist/lib/config.js +1 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/container.d.ts +4 -0
- package/dist/lib/container.js +127 -3
- package/dist/lib/container.js.map +1 -1
- package/dist/lib/init.js +1 -1
- package/dist/mcp-bundles/dataset-mcp.bundle.mjs +1 -1
- package/dist/mcp-bundles/display-mcp.bundle.mjs +1 -1
- package/dist/mcp-bundles/explorer-mcp.bundle.mjs +1 -1
- package/dist/mcp-bundles/results-mcp.bundle.mjs +1 -1
- package/dist/mcp-bundles/slurm-mcp.bundle.mjs +1 -1
- package/package.json +1 -1
package/dist/lib/container.js
CHANGED
|
@@ -36,6 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.shouldUseDangerousPermissionsByDefault = shouldUseDangerousPermissionsByDefault;
|
|
39
40
|
exports.computeMountFingerprint = computeMountFingerprint;
|
|
40
41
|
exports.prepareMcpServers = prepareMcpServers;
|
|
41
42
|
exports.imageToSifName = imageToSifName;
|
|
@@ -68,6 +69,20 @@ const slurm_poller_js_1 = require("./slurm-poller.js");
|
|
|
68
69
|
const slurm_cli_passthrough_js_1 = require("./slurm-cli-passthrough.js");
|
|
69
70
|
const startup_stage_lock_js_1 = require("./startup-stage-lock.js");
|
|
70
71
|
const log = __importStar(require("./log.js"));
|
|
72
|
+
function isTruthyEnvFlag(value) {
|
|
73
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
74
|
+
return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';
|
|
75
|
+
}
|
|
76
|
+
function shouldUseDangerousPermissionsByDefault(agent, options = {}) {
|
|
77
|
+
if (agent !== 'codex')
|
|
78
|
+
return false;
|
|
79
|
+
if (String(options.linkedWebTerminalId || '').trim().length > 0)
|
|
80
|
+
return false;
|
|
81
|
+
const env = options.env ?? process.env;
|
|
82
|
+
if (isTruthyEnvFlag(env.LABGATE_CODEX_STANDARD_PERMISSIONS))
|
|
83
|
+
return false;
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
71
86
|
/**
|
|
72
87
|
* Compute a deterministic fingerprint of mount-affecting config fields.
|
|
73
88
|
* Used to detect when running sessions need a restart after config changes.
|
|
@@ -1710,6 +1725,112 @@ function buildEntrypoint(agent, options = {}) {
|
|
|
1710
1725
|
' chmod +x "$HOME/.labgate-bin/$_cmd"',
|
|
1711
1726
|
' done',
|
|
1712
1727
|
'fi',
|
|
1728
|
+
'labgate_install_bzip2_shims() {',
|
|
1729
|
+
' local needs_bzip2="0"',
|
|
1730
|
+
' local py=""',
|
|
1731
|
+
' for _cmd in bzip2 bunzip2 bzcat; do',
|
|
1732
|
+
' if ! command -v "$_cmd" >/dev/null 2>&1; then',
|
|
1733
|
+
' needs_bzip2="1"',
|
|
1734
|
+
' break',
|
|
1735
|
+
' fi',
|
|
1736
|
+
' done',
|
|
1737
|
+
' [ "$needs_bzip2" = "1" ] || return 0',
|
|
1738
|
+
' if ! command -v python3 >/dev/null 2>&1; then',
|
|
1739
|
+
' return 0',
|
|
1740
|
+
' fi',
|
|
1741
|
+
' cat > "$HOME/.labgate-bin/bzip2" <<\'EOF\'',
|
|
1742
|
+
'#!/usr/bin/env python3',
|
|
1743
|
+
'import bz2',
|
|
1744
|
+
'import os',
|
|
1745
|
+
'import sys',
|
|
1746
|
+
'',
|
|
1747
|
+
'prog = os.path.basename(sys.argv[0])',
|
|
1748
|
+
'args = sys.argv[1:]',
|
|
1749
|
+
'decompress = prog in ("bunzip2", "bzcat")',
|
|
1750
|
+
'stdout_mode = prog == "bzcat"',
|
|
1751
|
+
'keep = prog == "bzcat"',
|
|
1752
|
+
'force = False',
|
|
1753
|
+
'files = []',
|
|
1754
|
+
'',
|
|
1755
|
+
'def fail(message: str, code: int = 2) -> None:',
|
|
1756
|
+
' sys.stderr.write(message + "\\n")',
|
|
1757
|
+
' raise SystemExit(code)',
|
|
1758
|
+
'',
|
|
1759
|
+
'def read_bytes(path: str | None) -> bytes:',
|
|
1760
|
+
' if not path or path == "-":',
|
|
1761
|
+
' return sys.stdin.buffer.read()',
|
|
1762
|
+
' with open(path, "rb") as handle:',
|
|
1763
|
+
' return handle.read()',
|
|
1764
|
+
'',
|
|
1765
|
+
'def write_bytes(path: str | None, data: bytes) -> None:',
|
|
1766
|
+
' if not path or path == "-":',
|
|
1767
|
+
' sys.stdout.buffer.write(data)',
|
|
1768
|
+
' return',
|
|
1769
|
+
' with open(path, "wb") as handle:',
|
|
1770
|
+
' handle.write(data)',
|
|
1771
|
+
'',
|
|
1772
|
+
'while args:',
|
|
1773
|
+
' arg = args.pop(0)',
|
|
1774
|
+
' if arg == "--":',
|
|
1775
|
+
' files.extend(args)',
|
|
1776
|
+
' break',
|
|
1777
|
+
' if arg == "-":',
|
|
1778
|
+
' files.append(arg)',
|
|
1779
|
+
' continue',
|
|
1780
|
+
' if arg.startswith("-") and arg != "-":',
|
|
1781
|
+
' for flag in arg[1:]:',
|
|
1782
|
+
' if flag == "d":',
|
|
1783
|
+
' decompress = True',
|
|
1784
|
+
' elif flag == "z":',
|
|
1785
|
+
' decompress = False',
|
|
1786
|
+
' elif flag == "c":',
|
|
1787
|
+
' stdout_mode = True',
|
|
1788
|
+
' elif flag == "k":',
|
|
1789
|
+
' keep = True',
|
|
1790
|
+
' elif flag == "f":',
|
|
1791
|
+
' force = True',
|
|
1792
|
+
' else:',
|
|
1793
|
+
' fail(f"bzip2 shim: unsupported option -{flag}")',
|
|
1794
|
+
' continue',
|
|
1795
|
+
' files.append(arg)',
|
|
1796
|
+
'',
|
|
1797
|
+
'if not files:',
|
|
1798
|
+
' files = ["-"]',
|
|
1799
|
+
'',
|
|
1800
|
+
'exit_code = 0',
|
|
1801
|
+
'for path in files:',
|
|
1802
|
+
' try:',
|
|
1803
|
+
' raw = read_bytes(path)',
|
|
1804
|
+
' data = bz2.decompress(raw) if decompress else bz2.compress(raw)',
|
|
1805
|
+
' if stdout_mode or path == "-":',
|
|
1806
|
+
' write_bytes(None, data)',
|
|
1807
|
+
' continue',
|
|
1808
|
+
' if decompress:',
|
|
1809
|
+
' target = path[:-4] if path.endswith(".bz2") else path + ".out"',
|
|
1810
|
+
' else:',
|
|
1811
|
+
' target = path + ".bz2"',
|
|
1812
|
+
' if os.path.exists(target) and not force:',
|
|
1813
|
+
' sys.stderr.write(f"{target} already exists; use -f to overwrite\\n")',
|
|
1814
|
+
' exit_code = 1',
|
|
1815
|
+
' continue',
|
|
1816
|
+
' write_bytes(target, data)',
|
|
1817
|
+
' if not keep:',
|
|
1818
|
+
' try:',
|
|
1819
|
+
' os.unlink(path)',
|
|
1820
|
+
' except OSError:',
|
|
1821
|
+
' pass',
|
|
1822
|
+
' except Exception as exc:',
|
|
1823
|
+
' label = "stdin" if path == "-" else path',
|
|
1824
|
+
' sys.stderr.write(f"{label}: {exc}\\n")',
|
|
1825
|
+
' exit_code = 1',
|
|
1826
|
+
'',
|
|
1827
|
+
'raise SystemExit(exit_code)',
|
|
1828
|
+
'EOF',
|
|
1829
|
+
' chmod +x "$HOME/.labgate-bin/bzip2"',
|
|
1830
|
+
' ln -sf "$HOME/.labgate-bin/bzip2" "$HOME/.labgate-bin/bunzip2"',
|
|
1831
|
+
' ln -sf "$HOME/.labgate-bin/bzip2" "$HOME/.labgate-bin/bzcat"',
|
|
1832
|
+
'}',
|
|
1833
|
+
'labgate_install_bzip2_shims',
|
|
1713
1834
|
'',
|
|
1714
1835
|
// Minimal progress indicator for first-run npm installs (keeps logs quiet, avoids "nothing happening" UX).
|
|
1715
1836
|
'labgate_npm_install_global() {',
|
|
@@ -1747,10 +1868,10 @@ function buildEntrypoint(agent, options = {}) {
|
|
|
1747
1868
|
'',
|
|
1748
1869
|
];
|
|
1749
1870
|
const preLaunchLines = [];
|
|
1871
|
+
if (ensureCommands.length > 0) {
|
|
1872
|
+
preLaunchLines.push('labgate_install_system_package() {', ' local manager="${1:-}"', ' local pkg="${2:-}"', ' [ -n "$manager" ] && [ -n "$pkg" ] || return 1', ' case "$manager" in', ' apt-get) apt-get install -y "$pkg" >/dev/null 2>&1 ;;', ' apk) apk add --no-cache "$pkg" >/dev/null 2>&1 ;;', ' dnf) dnf install -y "$pkg" >/dev/null 2>&1 ;;', ' yum) yum install -y "$pkg" >/dev/null 2>&1 ;;', ' microdnf) microdnf install -y "$pkg" >/dev/null 2>&1 ;;', ' *) return 1 ;;', ' esac', '}', 'labgate_candidate_packages_for_command() {', ' local cmd="${1:-}"', ' case "$cmd" in', ' rg) echo "ripgrep rg" ;;', ' fd) echo "fd-find fd" ;;', ' pip) echo "python3-pip py3-pip pip" ;;', ' python) echo "python3 python" ;;', ' *) echo "$cmd" ;;', ' esac', '}', 'labgate_ensure_commands() {', ` local required=(${ensureCommands.map((cmd) => JSON.stringify(cmd)).join(' ')})`, ' local missing=()', ' local cmd=""', ' for cmd in "${required[@]}"; do', ' if ! command -v "$cmd" >/dev/null 2>&1; then', ' missing+=("$cmd")', ' fi', ' done', ' if [ "${#missing[@]}" -eq 0 ]; then', ' return 0', ' fi', ' if [ "$(id -u)" != "0" ]; then', ' echo "[labgate] Warning: missing container command(s): ${missing[*]}." >&2', ' echo "[labgate] Configure an image with required tools preinstalled for reliable startup." >&2', ' return 0', ' fi', ' local manager=""', ' if command -v apt-get >/dev/null 2>&1; then', ' manager="apt-get"', ' export DEBIAN_FRONTEND=noninteractive', ' apt-get update >/dev/null 2>&1 || true', ' elif command -v apk >/dev/null 2>&1; then', ' manager="apk"', ' elif command -v dnf >/dev/null 2>&1; then', ' manager="dnf"', ' elif command -v yum >/dev/null 2>&1; then', ' manager="yum"', ' elif command -v microdnf >/dev/null 2>&1; then', ' manager="microdnf"', ' fi', ' if [ -z "$manager" ]; then', ' echo "[labgate] Warning: cannot install missing commands (${missing[*]}); no known package manager found." >&2', ' return 0', ' fi', ' echo "[labgate] Installing missing container tools: ${missing[*]}..."', ' local candidate=""', ' local installed="0"', ' for cmd in "${missing[@]}"; do', ' installed="0"', ' for candidate in $(labgate_candidate_packages_for_command "$cmd"); do', ' if labgate_install_system_package "$manager" "$candidate"; then', ' installed="1"', ' if command -v "$cmd" >/dev/null 2>&1; then', ' break', ' fi', ' fi', ' done', ' if [ "$installed" != "1" ]; then', ' echo "[labgate] Warning: failed to install command ${cmd}." >&2', ' fi', ' done', ' local still_missing=()', ' for cmd in "${required[@]}"; do', ' if ! command -v "$cmd" >/dev/null 2>&1; then', ' still_missing+=("$cmd")', ' fi', ' done', ' if [ "${#still_missing[@]}" -gt 0 ]; then', ' echo "[labgate] Warning: command(s) still unavailable after install attempt: ${still_missing[*]}." >&2', ' echo "[labgate] Configure an image with these tools preinstalled for reliable startup." >&2', ' fi', '}', 'labgate_ensure_commands', '');
|
|
1873
|
+
}
|
|
1750
1874
|
if (agent === 'claude') {
|
|
1751
|
-
if (ensureCommands.length > 0) {
|
|
1752
|
-
preLaunchLines.push('labgate_install_system_package() {', ' local manager="${1:-}"', ' local pkg="${2:-}"', ' [ -n "$manager" ] && [ -n "$pkg" ] || return 1', ' case "$manager" in', ' apt-get) apt-get install -y "$pkg" >/dev/null 2>&1 ;;', ' apk) apk add --no-cache "$pkg" >/dev/null 2>&1 ;;', ' dnf) dnf install -y "$pkg" >/dev/null 2>&1 ;;', ' yum) yum install -y "$pkg" >/dev/null 2>&1 ;;', ' microdnf) microdnf install -y "$pkg" >/dev/null 2>&1 ;;', ' *) return 1 ;;', ' esac', '}', 'labgate_candidate_packages_for_command() {', ' local cmd="${1:-}"', ' case "$cmd" in', ' rg) echo "ripgrep rg" ;;', ' fd) echo "fd-find fd" ;;', ' pip) echo "python3-pip py3-pip pip" ;;', ' python) echo "python3 python" ;;', ' *) echo "$cmd" ;;', ' esac', '}', 'labgate_ensure_commands() {', ` local required=(${ensureCommands.map((cmd) => JSON.stringify(cmd)).join(' ')})`, ' local missing=()', ' local cmd=""', ' for cmd in "${required[@]}"; do', ' if ! command -v "$cmd" >/dev/null 2>&1; then', ' missing+=("$cmd")', ' fi', ' done', ' if [ "${#missing[@]}" -eq 0 ]; then', ' return 0', ' fi', ' if [ "$(id -u)" != "0" ]; then', ' echo "[labgate] Warning: missing container command(s): ${missing[*]}." >&2', ' echo "[labgate] Configure an image with required tools preinstalled for best Claude UX." >&2', ' return 0', ' fi', ' local manager=""', ' if command -v apt-get >/dev/null 2>&1; then', ' manager="apt-get"', ' export DEBIAN_FRONTEND=noninteractive', ' apt-get update >/dev/null 2>&1 || true', ' elif command -v apk >/dev/null 2>&1; then', ' manager="apk"', ' elif command -v dnf >/dev/null 2>&1; then', ' manager="dnf"', ' elif command -v yum >/dev/null 2>&1; then', ' manager="yum"', ' elif command -v microdnf >/dev/null 2>&1; then', ' manager="microdnf"', ' fi', ' if [ -z "$manager" ]; then', ' echo "[labgate] Warning: cannot install missing commands (${missing[*]}); no known package manager found." >&2', ' return 0', ' fi', ' echo "[labgate] Installing missing container tools: ${missing[*]}..."', ' local candidate=""', ' local installed="0"', ' for cmd in "${missing[@]}"; do', ' installed="0"', ' for candidate in $(labgate_candidate_packages_for_command "$cmd"); do', ' if labgate_install_system_package "$manager" "$candidate"; then', ' installed="1"', ' if command -v "$cmd" >/dev/null 2>&1; then', ' break', ' fi', ' fi', ' done', ' if [ "$installed" != "1" ]; then', ' echo "[labgate] Warning: failed to install command ${cmd}." >&2', ' fi', ' done', ' local still_missing=()', ' for cmd in "${required[@]}"; do', ' if ! command -v "$cmd" >/dev/null 2>&1; then', ' still_missing+=("$cmd")', ' fi', ' done', ' if [ "${#still_missing[@]}" -gt 0 ]; then', ' echo "[labgate] Warning: command(s) still unavailable after install attempt: ${still_missing[*]}." >&2', ' echo "[labgate] Configure an image with these tools preinstalled for reliable startup." >&2', ' fi', '}', 'labgate_ensure_commands', '');
|
|
1753
|
-
}
|
|
1754
1875
|
if (disableClaudeStatusLine) {
|
|
1755
1876
|
// Set the statusLine to a no-op command so Claude Code renders an empty
|
|
1756
1877
|
// status bar instead of falling back to its default "time ➜ at host |".
|
|
@@ -3038,6 +3159,9 @@ async function restartSession(id, opts) {
|
|
|
3038
3159
|
config,
|
|
3039
3160
|
dryRun: false,
|
|
3040
3161
|
footerMode: 'once',
|
|
3162
|
+
dangerouslySkipPermissions: shouldUseDangerousPermissionsByDefault(agent, {
|
|
3163
|
+
linkedWebTerminalId: sessionData.webTerminalId,
|
|
3164
|
+
}),
|
|
3041
3165
|
sharedSessionsDir: effective.sharedSessionsDir,
|
|
3042
3166
|
sharedAuditDir: effective.sharedAuditDir,
|
|
3043
3167
|
});
|