windows-development-sandbox 1.11.7 → 1.13.0
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 +13 -6
- package/config.example.json +15 -4
- package/dist/app/features/access/access.def.d.ts +190 -0
- package/dist/app/features/access/access.def.js +273 -0
- package/dist/app/features/access/access.run.d.ts +79 -0
- package/dist/app/features/access/access.run.js +129 -0
- package/dist/app/features/access/index.d.ts +2 -0
- package/dist/app/features/access/index.js +3 -0
- package/dist/app/features/agents/agent-entry.js +5 -0
- package/dist/app/features/agents/agents.def.js +1 -0
- package/dist/app/features/apps/apps-rows.d.ts +4 -1
- package/dist/app/features/apps/apps-rows.js +7 -2
- package/dist/app/features/apps/apps.def.d.ts +19 -0
- package/dist/app/features/apps/apps.def.js +50 -12
- package/dist/app/features/apps/apps.run.d.ts +2 -0
- package/dist/app/features/apps/apps.run.js +1 -1
- package/dist/app/features/audit/audit.def.d.ts +350 -0
- package/dist/app/features/audit/audit.def.js +457 -0
- package/dist/app/features/audit/audit.run.d.ts +110 -0
- package/dist/app/features/audit/audit.run.js +133 -0
- package/dist/app/features/audit/index.d.ts +2 -0
- package/dist/app/features/audit/index.js +3 -0
- package/dist/app/features/defs.d.ts +349 -4
- package/dist/app/features/defs.js +16 -1
- package/dist/app/features/files/files.def.js +1 -0
- package/dist/app/features/health/health.def.js +1 -0
- package/dist/app/features/sandbox/sandbox.def.js +3 -0
- package/dist/app/features/sessions/sessions.def.d.ts +36 -0
- package/dist/app/features/sessions/sessions.def.js +77 -9
- package/dist/app/features/sessions/sessions.run.d.ts +25 -2
- package/dist/app/features/sessions/sessions.run.js +71 -3
- package/dist/app/features/settings/settings.def.d.ts +8 -0
- package/dist/app/features/settings/settings.def.js +17 -0
- package/dist/app/features/settings/settings.run.d.ts +3 -0
- package/dist/app/features/settings/settings.run.js +16 -2
- package/dist/app/features/web/web.def.d.ts +9 -0
- package/dist/app/features/web/web.def.js +26 -1
- package/dist/app/features/web/web.run.d.ts +3 -0
- package/dist/app/features/web/web.run.js +11 -3
- package/dist/app/kernel/access.d.ts +33 -0
- package/dist/app/kernel/access.js +44 -0
- package/dist/app/kernel/define.d.ts +26 -2
- package/dist/app/kernel/index.d.ts +1 -0
- package/dist/app/kernel/index.js +1 -0
- package/dist/app/kernel/rpc.d.ts +5 -2
- package/dist/app/registry.d.ts +4 -1
- package/dist/app/registry.js +26 -4
- package/dist/cli/args.d.ts +0 -3
- package/dist/cli/args.js +3 -4
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/launch/prepare.js +1 -1
- package/dist/cli/commands/maintenance/index.d.ts +0 -1
- package/dist/cli/commands/maintenance/index.js +0 -1
- package/dist/cli/commands/registry.js +3 -2
- package/dist/cli/commands/remote.d.ts +2 -0
- package/dist/cli/commands/remote.js +49 -0
- package/dist/cli/commands/sessions/reopen.js +3 -0
- package/dist/cli/commands/web.js +66 -0
- package/dist/cli/manifest.d.ts +63 -45
- package/dist/cli/manifest.js +33 -18
- package/dist/cli/menu/io-menu.d.ts +5 -3
- package/dist/cli/menu/io-menu.js +12 -5
- package/dist/cli/menu/pages/apps-page.js +2 -15
- package/dist/cli/menu/pages/maintenance-page.d.ts +4 -0
- package/dist/cli/menu/pages/maintenance-page.js +51 -8
- package/dist/cli/menu/remote-menu.d.ts +19 -0
- package/dist/cli/menu/remote-menu.js +108 -0
- package/dist/cli/menu/views.js +4 -0
- package/dist/cli/operations/handler.js +15 -1
- package/dist/cli/services/remote-client.d.ts +16 -0
- package/dist/cli/services/remote-client.js +141 -0
- package/dist/cli/services/sessions-service.d.ts +5 -0
- package/dist/cli/services/sessions-service.js +17 -1
- package/dist/core/config/defaults.js +12 -2
- package/dist/core/local-config/file.js +16 -2
- package/dist/core/local-config/overrides.js +7 -0
- package/dist/core/run/versions.js +9 -8
- package/dist/core/schema/apps.d.ts +9 -0
- package/dist/core/schema/apps.js +9 -0
- package/dist/core/schema/config.d.ts +23 -3
- package/dist/core/schema/config.js +42 -5
- package/dist/core/schema/sandbox.d.ts +1 -0
- package/dist/core/schema/sandbox.js +11 -3
- package/dist/core/schema/web.d.ts +51 -0
- package/dist/core/schema/web.js +46 -1
- package/dist/core/util/fs.d.ts +5 -0
- package/dist/core/util/fs.js +23 -0
- package/dist/core/util/index.d.ts +1 -1
- package/dist/core/util/index.js +1 -1
- package/dist/guest/apps/app-installer.js +50 -4
- package/dist/guest/apps/index.d.ts +1 -1
- package/dist/guest/apps/index.js +1 -1
- package/dist/guest/apps/sources.js +1 -1
- package/dist/guest/audit/parse.d.ts +32 -2
- package/dist/guest/audit/parse.js +43 -5
- package/dist/guest/audit/process-audit.d.ts +3 -1
- package/dist/guest/audit/process-audit.js +9 -6
- package/dist/guest/boot/boot.js +12 -3
- package/dist/guest/boot/guide.d.ts +1 -1
- package/dist/guest/boot/guide.js +27 -3
- package/dist/guest/daemon/daemon.js +2 -0
- package/dist/guest/daemon/idle-shutdown.js +2 -1
- package/dist/guest/daemon/sessions.d.ts +23 -2
- package/dist/guest/daemon/sessions.js +151 -20
- package/dist/guest/entries/daemon.js +2 -1
- package/dist/guest/git/decision.js +7 -0
- package/dist/guest/sessions/cmdline.d.ts +14 -0
- package/dist/guest/sessions/cmdline.js +10 -0
- package/dist/guest/setup/addon-mcp.d.ts +2 -0
- package/dist/guest/setup/addon-mcp.js +49 -0
- package/dist/guest/setup/agent-addons.d.ts +9 -0
- package/dist/guest/setup/agent-addons.js +22 -0
- package/dist/guest/setup/headroom.d.ts +7 -0
- package/dist/guest/setup/headroom.js +60 -0
- package/dist/guest/setup/managed-policy.d.ts +2 -1
- package/dist/guest/setup/managed-policy.js +15 -6
- package/dist/guest/toolchains/plan.js +8 -3
- package/dist/guest/toolchains/setup.js +3 -0
- package/dist/host/audit/attribute.d.ts +46 -0
- package/dist/host/audit/attribute.js +76 -0
- package/dist/host/audit/collect.d.ts +29 -3
- package/dist/host/audit/collect.js +256 -61
- package/dist/host/audit/git-commits.d.ts +29 -0
- package/dist/host/audit/git-commits.js +157 -0
- package/dist/host/audit/index.d.ts +5 -0
- package/dist/host/audit/index.js +6 -0
- package/dist/host/audit/log.d.ts +45 -7
- package/dist/host/audit/log.js +148 -45
- package/dist/host/audit/redact.d.ts +2 -0
- package/dist/host/audit/redact.js +67 -0
- package/dist/host/channel/channel.d.ts +5 -1
- package/dist/host/channel/channel.js +12 -0
- package/dist/host/guard/agent-files.js +7 -1
- package/dist/host/guard/commands.js +13 -1
- package/dist/host/guard/git-config.js +27 -7
- package/dist/host/guard/git-dirs.js +78 -3
- package/dist/host/guard/mark-of-the-web.js +3 -1
- package/dist/host/guard/nested-repos.js +7 -2
- package/dist/host/guard/store.js +1 -0
- package/dist/host/guard/types.d.ts +2 -0
- package/dist/host/launch/mappings.js +11 -1
- package/dist/host/launch/project-scan.js +2 -21
- package/dist/host/launch/stage.js +4 -0
- package/dist/host/life/session-ledger.js +2 -1
- package/dist/host/remote/access-store.d.ts +156 -0
- package/dist/host/remote/access-store.js +308 -0
- package/dist/host/remote/cert.d.ts +20 -0
- package/dist/host/remote/cert.js +103 -0
- package/dist/host/remote/door-client.d.ts +13 -0
- package/dist/host/remote/door-client.js +54 -0
- package/dist/host/remote/firewall.d.ts +44 -0
- package/dist/host/remote/firewall.js +118 -0
- package/dist/host/remote/gate.d.ts +125 -0
- package/dist/host/remote/gate.js +391 -0
- package/dist/host/remote/index.d.ts +8 -0
- package/dist/host/remote/index.js +10 -0
- package/dist/host/remote/lan.d.ts +24 -0
- package/dist/host/remote/lan.js +88 -0
- package/dist/host/remote/tls-store.d.ts +22 -0
- package/dist/host/remote/tls-store.js +63 -0
- package/dist/host/remote/windows-helper.d.ts +67 -0
- package/dist/host/remote/windows-helper.js +129 -0
- package/dist/host/web/bridge.d.ts +5 -1
- package/dist/host/web/bridge.js +6 -2
- package/dist/host/web/browser.js +1 -1
- package/dist/host/web/control.d.ts +4 -1
- package/dist/host/web/control.js +28 -4
- package/dist/host/web/rpc.d.ts +16 -2
- package/dist/host/web/rpc.js +37 -4
- package/dist/host/web/runner.d.ts +4 -0
- package/dist/host/web/runner.js +12 -0
- package/dist/host/web/server.d.ts +18 -2
- package/dist/host/web/server.js +97 -24
- package/dist/host/web/state.d.ts +5 -0
- package/dist/host/web/state.js +8 -0
- package/dist/runtime/agent.js +184 -18
- package/dist/runtime/daemon.js +772 -338
- package/dist/runtime/db.js +184 -18
- package/dist/runtime/gitguard.js +6 -0
- package/dist/runtime/main.js +966 -553
- package/dist/runtime/netproxy.js +184 -18
- package/dist/runtime/view.js +186 -18
- package/dist/selftest/app.test.js +66 -7
- package/dist/selftest/audit.test.js +354 -47
- package/dist/selftest/channel.test.js +16 -0
- package/dist/selftest/cmdline.test.js +16 -0
- package/dist/selftest/git-access.test.js +8 -0
- package/dist/selftest/hcs.test.js +35 -0
- package/dist/selftest/hostile-input.test.js +12 -1
- package/dist/selftest/index.js +2 -0
- package/dist/selftest/live-daemon.test.js +25 -0
- package/dist/selftest/local-config.test.js +30 -0
- package/dist/selftest/menu-screens.js +1 -1
- package/dist/selftest/menu.test.js +3 -3
- package/dist/selftest/remote.test.d.ts +2 -0
- package/dist/selftest/remote.test.js +536 -0
- package/dist/selftest/repo-guard.test.js +56 -2
- package/dist/selftest/resume.test.js +2 -1
- package/dist/selftest/sharing.test.js +9 -2
- package/dist/selftest/support/engine-golden.js +9 -0
- package/dist/selftest/support/fixtures.d.ts +14 -0
- package/dist/selftest/support/web-preview.js +157 -0
- package/dist/selftest/toolchains.test.js +147 -2
- package/dist/selftest/web.test.js +2 -0
- package/dist/shared/apps/agent-addons.d.ts +64 -0
- package/dist/shared/apps/agent-addons.js +95 -0
- package/dist/shared/apps/catalogue.d.ts +33 -2
- package/dist/shared/apps/catalogue.js +102 -11
- package/dist/shared/apps/index.d.ts +3 -2
- package/dist/shared/apps/index.js +3 -2
- package/dist/shared/apps/selection.d.ts +2 -0
- package/dist/shared/apps/selection.js +7 -0
- package/dist/shared/channel/schema.d.ts +23 -0
- package/dist/shared/channel/schema.js +8 -0
- package/dist/shared/pty/protocol.d.ts +2 -0
- package/dist/shared/pty/protocol.js +2 -0
- package/dist/sync/watcher.js +9 -1
- package/dist/web/index.html +2 -2
- package/dist/web/{main-RQFN4WBY.css → main-UAQPI5XD.css} +1 -1
- package/dist/web/main-Z2WYAE2Z.js +221 -0
- package/native/csharp/HcsHost/AssemblyInfo.cs +5 -3
- package/native/csharp/HcsHost/Hcs.cs +9 -0
- package/native/csharp/HcsHost/Program.cs +26 -1
- package/native/csharp/HcsHost/Share.cs +173 -0
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/Program.cs +17 -1
- package/native/csharp/HostTools/WebHelper.cs +499 -0
- package/native/scripts/get-network-profile.ps1 +19 -0
- package/native/scripts/set-folder-access.ps1 +11 -0
- package/native/scripts/set-web-firewall.ps1 +103 -0
- package/package.json +1 -1
- package/sandbox/addons/ccusage/package-lock.json +111 -0
- package/sandbox/addons/ccusage/package.json +7 -0
- package/sandbox/addons/context7/package-lock.json +1313 -0
- package/sandbox/addons/context7/package.json +7 -0
- package/sandbox/addons/headroom/requirements.in +1 -0
- package/sandbox/addons/headroom/requirements.txt +2922 -0
- package/sandbox/addons/playwright-mcp/package-lock.json +56 -0
- package/sandbox/addons/playwright-mcp/package.json +7 -0
- package/sandbox/csharp/PtyHost.cs +20 -0
- package/schemas/config.schema.json +78 -4
- package/schemas/sandbox-config.schema.json +2 -20
- package/dist/cli/commands/maintenance/audit.d.ts +0 -3
- package/dist/cli/commands/maintenance/audit.js +0 -58
- package/dist/web/main-K2JMCAZI.js +0 -219
package/dist/runtime/main.js
CHANGED
|
@@ -1363,11 +1363,11 @@ var require_lodash = __commonJS({
|
|
|
1363
1363
|
return isFunction(object2[key]);
|
|
1364
1364
|
});
|
|
1365
1365
|
}
|
|
1366
|
-
function baseGet(object2,
|
|
1367
|
-
|
|
1368
|
-
var index = 0, length =
|
|
1366
|
+
function baseGet(object2, path77) {
|
|
1367
|
+
path77 = castPath(path77, object2);
|
|
1368
|
+
var index = 0, length = path77.length;
|
|
1369
1369
|
while (object2 != null && index < length) {
|
|
1370
|
-
object2 = object2[toKey(
|
|
1370
|
+
object2 = object2[toKey(path77[index++])];
|
|
1371
1371
|
}
|
|
1372
1372
|
return index && index == length ? object2 : undefined2;
|
|
1373
1373
|
}
|
|
@@ -1431,10 +1431,10 @@ var require_lodash = __commonJS({
|
|
|
1431
1431
|
});
|
|
1432
1432
|
return accumulator;
|
|
1433
1433
|
}
|
|
1434
|
-
function baseInvoke(object2,
|
|
1435
|
-
|
|
1436
|
-
object2 = parent(object2,
|
|
1437
|
-
var func = object2 == null ? object2 : object2[toKey(last(
|
|
1434
|
+
function baseInvoke(object2, path77, args) {
|
|
1435
|
+
path77 = castPath(path77, object2);
|
|
1436
|
+
object2 = parent(object2, path77);
|
|
1437
|
+
var func = object2 == null ? object2 : object2[toKey(last(path77))];
|
|
1438
1438
|
return func == null ? undefined2 : apply(func, object2, args);
|
|
1439
1439
|
}
|
|
1440
1440
|
function baseIsArguments(value) {
|
|
@@ -1590,13 +1590,13 @@ var require_lodash = __commonJS({
|
|
|
1590
1590
|
return object2 === source || baseIsMatch(object2, source, matchData);
|
|
1591
1591
|
};
|
|
1592
1592
|
}
|
|
1593
|
-
function baseMatchesProperty(
|
|
1594
|
-
if (isKey(
|
|
1595
|
-
return matchesStrictComparable(toKey(
|
|
1593
|
+
function baseMatchesProperty(path77, srcValue) {
|
|
1594
|
+
if (isKey(path77) && isStrictComparable(srcValue)) {
|
|
1595
|
+
return matchesStrictComparable(toKey(path77), srcValue);
|
|
1596
1596
|
}
|
|
1597
1597
|
return function(object2) {
|
|
1598
|
-
var objValue = get(object2,
|
|
1599
|
-
return objValue === undefined2 && objValue === srcValue ? hasIn(object2,
|
|
1598
|
+
var objValue = get(object2, path77);
|
|
1599
|
+
return objValue === undefined2 && objValue === srcValue ? hasIn(object2, path77) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
|
|
1600
1600
|
};
|
|
1601
1601
|
}
|
|
1602
1602
|
function baseMerge(object2, source, srcIndex, customizer, stack) {
|
|
@@ -1693,23 +1693,23 @@ var require_lodash = __commonJS({
|
|
|
1693
1693
|
});
|
|
1694
1694
|
}
|
|
1695
1695
|
function basePick(object2, paths) {
|
|
1696
|
-
return basePickBy(object2, paths, function(value,
|
|
1697
|
-
return hasIn(object2,
|
|
1696
|
+
return basePickBy(object2, paths, function(value, path77) {
|
|
1697
|
+
return hasIn(object2, path77);
|
|
1698
1698
|
});
|
|
1699
1699
|
}
|
|
1700
1700
|
function basePickBy(object2, paths, predicate) {
|
|
1701
1701
|
var index = -1, length = paths.length, result2 = {};
|
|
1702
1702
|
while (++index < length) {
|
|
1703
|
-
var
|
|
1704
|
-
if (predicate(value,
|
|
1705
|
-
baseSet(result2, castPath(
|
|
1703
|
+
var path77 = paths[index], value = baseGet(object2, path77);
|
|
1704
|
+
if (predicate(value, path77)) {
|
|
1705
|
+
baseSet(result2, castPath(path77, object2), value);
|
|
1706
1706
|
}
|
|
1707
1707
|
}
|
|
1708
1708
|
return result2;
|
|
1709
1709
|
}
|
|
1710
|
-
function basePropertyDeep(
|
|
1710
|
+
function basePropertyDeep(path77) {
|
|
1711
1711
|
return function(object2) {
|
|
1712
|
-
return baseGet(object2,
|
|
1712
|
+
return baseGet(object2, path77);
|
|
1713
1713
|
};
|
|
1714
1714
|
}
|
|
1715
1715
|
function basePullAll(array2, values2, iteratee2, comparator) {
|
|
@@ -1783,14 +1783,14 @@ var require_lodash = __commonJS({
|
|
|
1783
1783
|
var array2 = values(collection);
|
|
1784
1784
|
return shuffleSelf(array2, baseClamp(n, 0, array2.length));
|
|
1785
1785
|
}
|
|
1786
|
-
function baseSet(object2,
|
|
1786
|
+
function baseSet(object2, path77, value, customizer) {
|
|
1787
1787
|
if (!isObject2(object2)) {
|
|
1788
1788
|
return object2;
|
|
1789
1789
|
}
|
|
1790
|
-
|
|
1791
|
-
var index = -1, length =
|
|
1790
|
+
path77 = castPath(path77, object2);
|
|
1791
|
+
var index = -1, length = path77.length, lastIndex = length - 1, nested = object2;
|
|
1792
1792
|
while (nested != null && ++index < length) {
|
|
1793
|
-
var key = toKey(
|
|
1793
|
+
var key = toKey(path77[index]), newValue = value;
|
|
1794
1794
|
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
1795
1795
|
return object2;
|
|
1796
1796
|
}
|
|
@@ -1798,7 +1798,7 @@ var require_lodash = __commonJS({
|
|
|
1798
1798
|
var objValue = nested[key];
|
|
1799
1799
|
newValue = customizer ? customizer(objValue, key, nested) : undefined2;
|
|
1800
1800
|
if (newValue === undefined2) {
|
|
1801
|
-
newValue = isObject2(objValue) ? objValue : isIndex(
|
|
1801
|
+
newValue = isObject2(objValue) ? objValue : isIndex(path77[index + 1]) ? [] : {};
|
|
1802
1802
|
}
|
|
1803
1803
|
}
|
|
1804
1804
|
assignValue(nested, key, newValue);
|
|
@@ -1964,14 +1964,14 @@ var require_lodash = __commonJS({
|
|
|
1964
1964
|
}
|
|
1965
1965
|
return result2;
|
|
1966
1966
|
}
|
|
1967
|
-
function baseUnset(object2,
|
|
1968
|
-
|
|
1969
|
-
var index = -1, length =
|
|
1967
|
+
function baseUnset(object2, path77) {
|
|
1968
|
+
path77 = castPath(path77, object2);
|
|
1969
|
+
var index = -1, length = path77.length;
|
|
1970
1970
|
if (!length) {
|
|
1971
1971
|
return true;
|
|
1972
1972
|
}
|
|
1973
1973
|
while (++index < length) {
|
|
1974
|
-
var key = toKey(
|
|
1974
|
+
var key = toKey(path77[index]);
|
|
1975
1975
|
if (key === "__proto__" && !hasOwnProperty.call(object2, "__proto__")) {
|
|
1976
1976
|
return false;
|
|
1977
1977
|
}
|
|
@@ -1979,11 +1979,11 @@ var require_lodash = __commonJS({
|
|
|
1979
1979
|
return false;
|
|
1980
1980
|
}
|
|
1981
1981
|
}
|
|
1982
|
-
var obj = parent(object2,
|
|
1983
|
-
return obj == null || delete obj[toKey(last(
|
|
1982
|
+
var obj = parent(object2, path77);
|
|
1983
|
+
return obj == null || delete obj[toKey(last(path77))];
|
|
1984
1984
|
}
|
|
1985
|
-
function baseUpdate(object2,
|
|
1986
|
-
return baseSet(object2,
|
|
1985
|
+
function baseUpdate(object2, path77, updater, customizer) {
|
|
1986
|
+
return baseSet(object2, path77, updater(baseGet(object2, path77)), customizer);
|
|
1987
1987
|
}
|
|
1988
1988
|
function baseWhile(array2, predicate, isDrop, fromRight) {
|
|
1989
1989
|
var length = array2.length, index = fromRight ? length : -1;
|
|
@@ -2866,11 +2866,11 @@ var require_lodash = __commonJS({
|
|
|
2866
2866
|
var match = source.match(reWrapDetails);
|
|
2867
2867
|
return match ? match[1].split(reSplitDetails) : [];
|
|
2868
2868
|
}
|
|
2869
|
-
function hasPath(object2,
|
|
2870
|
-
|
|
2871
|
-
var index = -1, length =
|
|
2869
|
+
function hasPath(object2, path77, hasFunc) {
|
|
2870
|
+
path77 = castPath(path77, object2);
|
|
2871
|
+
var index = -1, length = path77.length, result2 = false;
|
|
2872
2872
|
while (++index < length) {
|
|
2873
|
-
var key = toKey(
|
|
2873
|
+
var key = toKey(path77[index]);
|
|
2874
2874
|
if (!(result2 = object2 != null && hasFunc(object2, key))) {
|
|
2875
2875
|
break;
|
|
2876
2876
|
}
|
|
@@ -3072,8 +3072,8 @@ var require_lodash = __commonJS({
|
|
|
3072
3072
|
return apply(func, this, otherArgs);
|
|
3073
3073
|
};
|
|
3074
3074
|
}
|
|
3075
|
-
function parent(object2,
|
|
3076
|
-
return
|
|
3075
|
+
function parent(object2, path77) {
|
|
3076
|
+
return path77.length < 2 ? object2 : baseGet(object2, baseSlice(path77, 0, -1));
|
|
3077
3077
|
}
|
|
3078
3078
|
function reorder(array2, indexes) {
|
|
3079
3079
|
var arrLength = array2.length, length = nativeMin(indexes.length, arrLength), oldArray = copyArray(array2);
|
|
@@ -3708,10 +3708,10 @@ var require_lodash = __commonJS({
|
|
|
3708
3708
|
}
|
|
3709
3709
|
return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1;
|
|
3710
3710
|
}
|
|
3711
|
-
var invokeMap = baseRest(function(collection,
|
|
3712
|
-
var index = -1, isFunc = typeof
|
|
3711
|
+
var invokeMap = baseRest(function(collection, path77, args) {
|
|
3712
|
+
var index = -1, isFunc = typeof path77 == "function", result2 = isArrayLike(collection) ? Array2(collection.length) : [];
|
|
3713
3713
|
baseEach(collection, function(value) {
|
|
3714
|
-
result2[++index] = isFunc ? apply(
|
|
3714
|
+
result2[++index] = isFunc ? apply(path77, value, args) : baseInvoke(value, path77, args);
|
|
3715
3715
|
});
|
|
3716
3716
|
return result2;
|
|
3717
3717
|
});
|
|
@@ -4363,15 +4363,15 @@ var require_lodash = __commonJS({
|
|
|
4363
4363
|
function functionsIn(object2) {
|
|
4364
4364
|
return object2 == null ? [] : baseFunctions(object2, keysIn(object2));
|
|
4365
4365
|
}
|
|
4366
|
-
function get(object2,
|
|
4367
|
-
var result2 = object2 == null ? undefined2 : baseGet(object2,
|
|
4366
|
+
function get(object2, path77, defaultValue) {
|
|
4367
|
+
var result2 = object2 == null ? undefined2 : baseGet(object2, path77);
|
|
4368
4368
|
return result2 === undefined2 ? defaultValue : result2;
|
|
4369
4369
|
}
|
|
4370
|
-
function has(object2,
|
|
4371
|
-
return object2 != null && hasPath(object2,
|
|
4370
|
+
function has(object2, path77) {
|
|
4371
|
+
return object2 != null && hasPath(object2, path77, baseHas);
|
|
4372
4372
|
}
|
|
4373
|
-
function hasIn(object2,
|
|
4374
|
-
return object2 != null && hasPath(object2,
|
|
4373
|
+
function hasIn(object2, path77) {
|
|
4374
|
+
return object2 != null && hasPath(object2, path77, baseHasIn);
|
|
4375
4375
|
}
|
|
4376
4376
|
var invert = createInverter(function(result2, value, key) {
|
|
4377
4377
|
if (value != null && typeof value.toString != "function") {
|
|
@@ -4424,10 +4424,10 @@ var require_lodash = __commonJS({
|
|
|
4424
4424
|
return result2;
|
|
4425
4425
|
}
|
|
4426
4426
|
var isDeep = false;
|
|
4427
|
-
paths = arrayMap(paths, function(
|
|
4428
|
-
|
|
4429
|
-
isDeep || (isDeep =
|
|
4430
|
-
return
|
|
4427
|
+
paths = arrayMap(paths, function(path77) {
|
|
4428
|
+
path77 = castPath(path77, object2);
|
|
4429
|
+
isDeep || (isDeep = path77.length > 1);
|
|
4430
|
+
return path77;
|
|
4431
4431
|
});
|
|
4432
4432
|
copyObject(object2, getAllKeysIn(object2), result2);
|
|
4433
4433
|
if (isDeep) {
|
|
@@ -4453,19 +4453,19 @@ var require_lodash = __commonJS({
|
|
|
4453
4453
|
return [prop];
|
|
4454
4454
|
});
|
|
4455
4455
|
predicate = getIteratee(predicate);
|
|
4456
|
-
return basePickBy(object2, props, function(value,
|
|
4457
|
-
return predicate(value,
|
|
4456
|
+
return basePickBy(object2, props, function(value, path77) {
|
|
4457
|
+
return predicate(value, path77[0]);
|
|
4458
4458
|
});
|
|
4459
4459
|
}
|
|
4460
|
-
function result(object2,
|
|
4461
|
-
|
|
4462
|
-
var index = -1, length =
|
|
4460
|
+
function result(object2, path77, defaultValue) {
|
|
4461
|
+
path77 = castPath(path77, object2);
|
|
4462
|
+
var index = -1, length = path77.length;
|
|
4463
4463
|
if (!length) {
|
|
4464
4464
|
length = 1;
|
|
4465
4465
|
object2 = undefined2;
|
|
4466
4466
|
}
|
|
4467
4467
|
while (++index < length) {
|
|
4468
|
-
var value = object2 == null ? undefined2 : object2[toKey(
|
|
4468
|
+
var value = object2 == null ? undefined2 : object2[toKey(path77[index])];
|
|
4469
4469
|
if (value === undefined2) {
|
|
4470
4470
|
index = length;
|
|
4471
4471
|
value = defaultValue;
|
|
@@ -4474,12 +4474,12 @@ var require_lodash = __commonJS({
|
|
|
4474
4474
|
}
|
|
4475
4475
|
return object2;
|
|
4476
4476
|
}
|
|
4477
|
-
function set2(object2,
|
|
4478
|
-
return object2 == null ? object2 : baseSet(object2,
|
|
4477
|
+
function set2(object2, path77, value) {
|
|
4478
|
+
return object2 == null ? object2 : baseSet(object2, path77, value);
|
|
4479
4479
|
}
|
|
4480
|
-
function setWith(object2,
|
|
4480
|
+
function setWith(object2, path77, value, customizer) {
|
|
4481
4481
|
customizer = typeof customizer == "function" ? customizer : undefined2;
|
|
4482
|
-
return object2 == null ? object2 : baseSet(object2,
|
|
4482
|
+
return object2 == null ? object2 : baseSet(object2, path77, value, customizer);
|
|
4483
4483
|
}
|
|
4484
4484
|
var toPairs = createToPairs(keys);
|
|
4485
4485
|
var toPairsIn = createToPairs(keysIn);
|
|
@@ -4501,15 +4501,15 @@ var require_lodash = __commonJS({
|
|
|
4501
4501
|
});
|
|
4502
4502
|
return accumulator;
|
|
4503
4503
|
}
|
|
4504
|
-
function unset(object2,
|
|
4505
|
-
return object2 == null ? true : baseUnset(object2,
|
|
4504
|
+
function unset(object2, path77) {
|
|
4505
|
+
return object2 == null ? true : baseUnset(object2, path77);
|
|
4506
4506
|
}
|
|
4507
|
-
function update(object2,
|
|
4508
|
-
return object2 == null ? object2 : baseUpdate(object2,
|
|
4507
|
+
function update(object2, path77, updater) {
|
|
4508
|
+
return object2 == null ? object2 : baseUpdate(object2, path77, castFunction(updater));
|
|
4509
4509
|
}
|
|
4510
|
-
function updateWith(object2,
|
|
4510
|
+
function updateWith(object2, path77, updater, customizer) {
|
|
4511
4511
|
customizer = typeof customizer == "function" ? customizer : undefined2;
|
|
4512
|
-
return object2 == null ? object2 : baseUpdate(object2,
|
|
4512
|
+
return object2 == null ? object2 : baseUpdate(object2, path77, castFunction(updater), customizer);
|
|
4513
4513
|
}
|
|
4514
4514
|
function values(object2) {
|
|
4515
4515
|
return object2 == null ? [] : baseValues(object2, keys(object2));
|
|
@@ -4895,17 +4895,17 @@ var require_lodash = __commonJS({
|
|
|
4895
4895
|
function matches(source) {
|
|
4896
4896
|
return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
|
|
4897
4897
|
}
|
|
4898
|
-
function matchesProperty(
|
|
4899
|
-
return baseMatchesProperty(
|
|
4898
|
+
function matchesProperty(path77, srcValue) {
|
|
4899
|
+
return baseMatchesProperty(path77, baseClone(srcValue, CLONE_DEEP_FLAG));
|
|
4900
4900
|
}
|
|
4901
|
-
var method = baseRest(function(
|
|
4901
|
+
var method = baseRest(function(path77, args) {
|
|
4902
4902
|
return function(object2) {
|
|
4903
|
-
return baseInvoke(object2,
|
|
4903
|
+
return baseInvoke(object2, path77, args);
|
|
4904
4904
|
};
|
|
4905
4905
|
});
|
|
4906
4906
|
var methodOf = baseRest(function(object2, args) {
|
|
4907
|
-
return function(
|
|
4908
|
-
return baseInvoke(object2,
|
|
4907
|
+
return function(path77) {
|
|
4908
|
+
return baseInvoke(object2, path77, args);
|
|
4909
4909
|
};
|
|
4910
4910
|
});
|
|
4911
4911
|
function mixin(object2, source, options) {
|
|
@@ -4952,12 +4952,12 @@ var require_lodash = __commonJS({
|
|
|
4952
4952
|
var over = createOver(arrayMap);
|
|
4953
4953
|
var overEvery = createOver(arrayEvery);
|
|
4954
4954
|
var overSome = createOver(arraySome);
|
|
4955
|
-
function property(
|
|
4956
|
-
return isKey(
|
|
4955
|
+
function property(path77) {
|
|
4956
|
+
return isKey(path77) ? baseProperty(toKey(path77)) : basePropertyDeep(path77);
|
|
4957
4957
|
}
|
|
4958
4958
|
function propertyOf(object2) {
|
|
4959
|
-
return function(
|
|
4960
|
-
return object2 == null ? undefined2 : baseGet(object2,
|
|
4959
|
+
return function(path77) {
|
|
4960
|
+
return object2 == null ? undefined2 : baseGet(object2, path77);
|
|
4961
4961
|
};
|
|
4962
4962
|
}
|
|
4963
4963
|
var range = createRange();
|
|
@@ -5410,12 +5410,12 @@ var require_lodash = __commonJS({
|
|
|
5410
5410
|
LazyWrapper.prototype.findLast = function(predicate) {
|
|
5411
5411
|
return this.reverse().find(predicate);
|
|
5412
5412
|
};
|
|
5413
|
-
LazyWrapper.prototype.invokeMap = baseRest(function(
|
|
5414
|
-
if (typeof
|
|
5413
|
+
LazyWrapper.prototype.invokeMap = baseRest(function(path77, args) {
|
|
5414
|
+
if (typeof path77 == "function") {
|
|
5415
5415
|
return new LazyWrapper(this);
|
|
5416
5416
|
}
|
|
5417
5417
|
return this.map(function(value) {
|
|
5418
|
-
return baseInvoke(value,
|
|
5418
|
+
return baseInvoke(value, path77, args);
|
|
5419
5419
|
});
|
|
5420
5420
|
});
|
|
5421
5421
|
LazyWrapper.prototype.reject = function(predicate) {
|
|
@@ -5532,8 +5532,8 @@ var require_lodash = __commonJS({
|
|
|
5532
5532
|
});
|
|
5533
5533
|
|
|
5534
5534
|
// src/guest/entries/main.ts
|
|
5535
|
-
import
|
|
5536
|
-
import
|
|
5535
|
+
import fs63 from "node:fs";
|
|
5536
|
+
import path76 from "node:path";
|
|
5537
5537
|
|
|
5538
5538
|
// src/guest/runtime/paths.ts
|
|
5539
5539
|
import path7 from "node:path";
|
|
@@ -6358,10 +6358,10 @@ function mergeDefs(...defs) {
|
|
|
6358
6358
|
function cloneDef(schema) {
|
|
6359
6359
|
return mergeDefs(schema._zod.def);
|
|
6360
6360
|
}
|
|
6361
|
-
function getElementAtPath(obj,
|
|
6362
|
-
if (!
|
|
6361
|
+
function getElementAtPath(obj, path77) {
|
|
6362
|
+
if (!path77)
|
|
6363
6363
|
return obj;
|
|
6364
|
-
return
|
|
6364
|
+
return path77.reduce((acc, key) => acc?.[key], obj);
|
|
6365
6365
|
}
|
|
6366
6366
|
function promiseAllObject(promisesObj) {
|
|
6367
6367
|
const keys = Object.keys(promisesObj);
|
|
@@ -6701,11 +6701,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
6701
6701
|
}
|
|
6702
6702
|
return false;
|
|
6703
6703
|
}
|
|
6704
|
-
function prefixIssues(
|
|
6704
|
+
function prefixIssues(path77, issues) {
|
|
6705
6705
|
return issues.map((iss) => {
|
|
6706
6706
|
var _a3;
|
|
6707
6707
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
6708
|
-
iss.path.unshift(
|
|
6708
|
+
iss.path.unshift(path77);
|
|
6709
6709
|
return iss;
|
|
6710
6710
|
});
|
|
6711
6711
|
}
|
|
@@ -7155,16 +7155,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
|
|
|
7155
7155
|
}
|
|
7156
7156
|
function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
7157
7157
|
const fieldErrors = { _errors: [] };
|
|
7158
|
-
const processError = (error63,
|
|
7158
|
+
const processError = (error63, path77 = []) => {
|
|
7159
7159
|
for (const issue2 of error63.issues) {
|
|
7160
7160
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
7161
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
7161
|
+
issue2.errors.map((issues) => processError({ issues }, [...path77, ...issue2.path]));
|
|
7162
7162
|
} else if (issue2.code === "invalid_key") {
|
|
7163
|
-
processError({ issues: issue2.issues }, [...
|
|
7163
|
+
processError({ issues: issue2.issues }, [...path77, ...issue2.path]);
|
|
7164
7164
|
} else if (issue2.code === "invalid_element") {
|
|
7165
|
-
processError({ issues: issue2.issues }, [...
|
|
7165
|
+
processError({ issues: issue2.issues }, [...path77, ...issue2.path]);
|
|
7166
7166
|
} else {
|
|
7167
|
-
const fullpath = [...
|
|
7167
|
+
const fullpath = [...path77, ...issue2.path];
|
|
7168
7168
|
if (fullpath.length === 0) {
|
|
7169
7169
|
fieldErrors._errors.push(mapper(issue2));
|
|
7170
7170
|
} else {
|
|
@@ -7203,17 +7203,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
|
7203
7203
|
}
|
|
7204
7204
|
function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
7205
7205
|
const result = { errors: [] };
|
|
7206
|
-
const processError = (error63,
|
|
7206
|
+
const processError = (error63, path77 = []) => {
|
|
7207
7207
|
var _a3;
|
|
7208
7208
|
for (const issue2 of error63.issues) {
|
|
7209
7209
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
7210
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
7210
|
+
issue2.errors.map((issues) => processError({ issues }, [...path77, ...issue2.path]));
|
|
7211
7211
|
} else if (issue2.code === "invalid_key") {
|
|
7212
|
-
processError({ issues: issue2.issues }, [...
|
|
7212
|
+
processError({ issues: issue2.issues }, [...path77, ...issue2.path]);
|
|
7213
7213
|
} else if (issue2.code === "invalid_element") {
|
|
7214
|
-
processError({ issues: issue2.issues }, [...
|
|
7214
|
+
processError({ issues: issue2.issues }, [...path77, ...issue2.path]);
|
|
7215
7215
|
} else {
|
|
7216
|
-
const fullpath = [...
|
|
7216
|
+
const fullpath = [...path77, ...issue2.path];
|
|
7217
7217
|
if (fullpath.length === 0) {
|
|
7218
7218
|
result.errors.push(mapper(issue2));
|
|
7219
7219
|
continue;
|
|
@@ -7252,8 +7252,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
|
7252
7252
|
}
|
|
7253
7253
|
function toDotPath(_path) {
|
|
7254
7254
|
const segs = [];
|
|
7255
|
-
const
|
|
7256
|
-
for (const seg of
|
|
7255
|
+
const path77 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
7256
|
+
for (const seg of path77) {
|
|
7257
7257
|
if (typeof seg === "number")
|
|
7258
7258
|
segs.push(`[${seg}]`);
|
|
7259
7259
|
else if (typeof seg === "symbol")
|
|
@@ -24355,13 +24355,13 @@ function resolveRef(ref, ctx) {
|
|
|
24355
24355
|
if (!ref.startsWith("#")) {
|
|
24356
24356
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
24357
24357
|
}
|
|
24358
|
-
const
|
|
24359
|
-
if (
|
|
24358
|
+
const path77 = ref.slice(1).split("/").filter(Boolean);
|
|
24359
|
+
if (path77.length === 0) {
|
|
24360
24360
|
return ctx.rootSchema;
|
|
24361
24361
|
}
|
|
24362
24362
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
24363
|
-
if (
|
|
24364
|
-
const key =
|
|
24363
|
+
if (path77[0] === defsKey) {
|
|
24364
|
+
const key = path77[1] === void 0 ? void 0 : decodeJSONPointerSegment(path77[1]);
|
|
24365
24365
|
if (!key || !ctx.defs[key]) {
|
|
24366
24366
|
throw new Error(`Reference not found: ${ref}`);
|
|
24367
24367
|
}
|
|
@@ -25534,14 +25534,19 @@ var NetworkSchema = external_exports.strictObject({
|
|
|
25534
25534
|
});
|
|
25535
25535
|
var AuditSchema = external_exports.strictObject({
|
|
25536
25536
|
enabled: external_exports.boolean().describe(
|
|
25537
|
-
"Keep an audit log on this PC of what
|
|
25537
|
+
"Keep an audit log on this PC of what your agents did: programs started (with their command lines, secrets hidden), files changed in the projects, git commits, sessions, and what the repo guard caught, each linked to the agent session that did it where that can be known. The sandbox cannot change it. Read it with sandbox audit or on the Activity page."
|
|
25538
|
+
),
|
|
25539
|
+
days: external_exports.number().int().min(1).max(365).describe(
|
|
25540
|
+
"Days the audit log is kept (1 to 30; a larger number keeps 30); older days are deleted when a sandbox starts and once a day."
|
|
25538
25541
|
),
|
|
25539
|
-
days: external_exports.number().int().min(1).max(365).describe("Days the audit log is kept."),
|
|
25540
25542
|
maxMb: external_exports.number().int().min(5).max(5e3).describe("Most space the audit log may take, in MB (older days go first). Days before today are compressed."),
|
|
25541
25543
|
processes: external_exports.boolean().describe(
|
|
25542
25544
|
"Record every program started in the sandbox with its command line (Windows process auditing; repeated runs are counted, not listed)."
|
|
25543
25545
|
),
|
|
25544
|
-
files: external_exports.boolean().describe("Record the files changed in the
|
|
25546
|
+
files: external_exports.boolean().describe("Record the files changed in the projects while the sandbox runs."),
|
|
25547
|
+
commits: external_exports.boolean().describe(
|
|
25548
|
+
"Record the git commits made in the projects while the sandbox runs (read from each project's .git folder on this PC)."
|
|
25549
|
+
)
|
|
25545
25550
|
});
|
|
25546
25551
|
var WorkspaceFilterSchema = external_exports.strictObject({
|
|
25547
25552
|
enabled: external_exports.boolean().describe(
|
|
@@ -25744,7 +25749,100 @@ var ToolchainsSchema = external_exports.strictObject({
|
|
|
25744
25749
|
|
|
25745
25750
|
// src/shared/apps/catalogue.ts
|
|
25746
25751
|
var gh = (github, asset) => ({ github, asset });
|
|
25752
|
+
var RTK_VERSION = "1.0.1";
|
|
25753
|
+
var RTK_URL = "https://github.com/rtk-ai/rtk/releases/download/v" + RTK_VERSION + "/rtk-oss-x86_64-pc-windows-msvc.zip";
|
|
25754
|
+
var RTK_SHA256 = "0e53e2eca471e15fbd3636e64e6bc0b182cbc278ed0339c80450a2dd03f4cd6b";
|
|
25755
|
+
var HEADROOM_VERSION = "0.41.0";
|
|
25756
|
+
var CCUSAGE_VERSION = "20.0.36";
|
|
25757
|
+
var PLAYWRIGHT_MCP_VERSION = "0.0.83";
|
|
25758
|
+
var CONTEXT7_MCP_VERSION = "4.4.2";
|
|
25747
25759
|
var APPS = [
|
|
25760
|
+
// ---- agent add-ons
|
|
25761
|
+
{
|
|
25762
|
+
id: "rtk",
|
|
25763
|
+
name: "rtk (Rust Token Killer)",
|
|
25764
|
+
category: "agents",
|
|
25765
|
+
about: "Compacts the output of shell commands (git, tests, builds, ls ...) before the agent reads it, so it uses fewer tokens. Claude Code's Bash commands go through it on their own.",
|
|
25766
|
+
size: "6 MB",
|
|
25767
|
+
source: { url: RTK_URL, sha256: RTK_SHA256 },
|
|
25768
|
+
exe: "rtk.exe",
|
|
25769
|
+
cli: true,
|
|
25770
|
+
plugsInto: "Claude Code through a hook in the sandbox's managed settings; other agents are told to use it",
|
|
25771
|
+
userOnly: true
|
|
25772
|
+
},
|
|
25773
|
+
{
|
|
25774
|
+
id: "headroom",
|
|
25775
|
+
name: "Headroom",
|
|
25776
|
+
category: "agents",
|
|
25777
|
+
about: "Compresses what Claude Code sends to the model (tool output, logs, files) so it uses fewer tokens: a local proxy on 127.0.0.1:8787 that sits in Claude Code's API path, offline apart from forwarding to api.anthropic.com.",
|
|
25778
|
+
size: "150 MB",
|
|
25779
|
+
source: { locked: "uv", package: "headroom-ai", version: HEADROOM_VERSION },
|
|
25780
|
+
exe: "headroom.exe",
|
|
25781
|
+
service: true,
|
|
25782
|
+
plugsInto: "Claude Code: the sandbox starts the proxy and points Claude Code at it (managed settings)",
|
|
25783
|
+
userOnly: true
|
|
25784
|
+
},
|
|
25785
|
+
{
|
|
25786
|
+
id: "ccusage",
|
|
25787
|
+
name: "ccusage",
|
|
25788
|
+
category: "agents",
|
|
25789
|
+
about: "Reports the agents' token use and cost by day, month or session from their logs in the sandbox (`ccusage daily`; add --offline to skip fetching prices).",
|
|
25790
|
+
size: "5 MB",
|
|
25791
|
+
source: { locked: "npm", package: "ccusage", version: CCUSAGE_VERSION },
|
|
25792
|
+
exe: "ccusage.cmd",
|
|
25793
|
+
cli: true,
|
|
25794
|
+
plugsInto: "Reads Claude Code's session logs in the sandbox; changes nothing",
|
|
25795
|
+
userOnly: true
|
|
25796
|
+
},
|
|
25797
|
+
{
|
|
25798
|
+
id: "playwright-mcp",
|
|
25799
|
+
name: "Playwright MCP",
|
|
25800
|
+
category: "agents",
|
|
25801
|
+
about: "Lets Claude Code drive a browser (Microsoft Edge, already in the sandbox) to open pages, click, fill forms and take screenshots: the MCP server of microsoft/playwright-mcp.",
|
|
25802
|
+
size: "20 MB",
|
|
25803
|
+
source: { locked: "npm", package: "@playwright/mcp", version: PLAYWRIGHT_MCP_VERSION },
|
|
25804
|
+
exe: "playwright-mcp.cmd",
|
|
25805
|
+
service: true,
|
|
25806
|
+
mcp: { name: "sbx-playwright", script: "node_modules/@playwright/mcp/cli.js", args: ["--browser", "msedge"] },
|
|
25807
|
+
plugsInto: "Claude Code as the MCP server sbx-playwright (the sandbox's Claude settings)",
|
|
25808
|
+
userOnly: true
|
|
25809
|
+
},
|
|
25810
|
+
{
|
|
25811
|
+
id: "context7",
|
|
25812
|
+
name: "Context7 MCP",
|
|
25813
|
+
category: "agents",
|
|
25814
|
+
about: "Up-to-date documentation and code examples for libraries, looked up by Claude Code while it works (upstash/context7). The library names and questions go to Upstash's context7.com.",
|
|
25815
|
+
size: "55 MB",
|
|
25816
|
+
source: { locked: "npm", package: "@upstash/context7-mcp", version: CONTEXT7_MCP_VERSION },
|
|
25817
|
+
exe: "context7-mcp.cmd",
|
|
25818
|
+
service: true,
|
|
25819
|
+
mcp: { name: "sbx-context7", script: "node_modules/@upstash/context7-mcp/dist/index.js" },
|
|
25820
|
+
plugsInto: "Claude Code as the MCP server sbx-context7 (the sandbox's Claude settings)",
|
|
25821
|
+
userOnly: true
|
|
25822
|
+
},
|
|
25823
|
+
{
|
|
25824
|
+
id: "claude-mem",
|
|
25825
|
+
name: "claude-mem",
|
|
25826
|
+
category: "agents",
|
|
25827
|
+
about: "Persistent memory for Claude Code (a plugin you install on this PC): its database is brought into the sandbox.",
|
|
25828
|
+
size: "",
|
|
25829
|
+
source: { resolve: "setting" },
|
|
25830
|
+
exe: "",
|
|
25831
|
+
setting: "claudeProfile.syncClaudeMem",
|
|
25832
|
+
plugsInto: "Claude Code, with your Claude settings copied from this PC",
|
|
25833
|
+
userOnly: true
|
|
25834
|
+
},
|
|
25835
|
+
{
|
|
25836
|
+
id: "rea",
|
|
25837
|
+
name: "REA (Reverse Engineer Anything)",
|
|
25838
|
+
category: "agents",
|
|
25839
|
+
about: "Agent-driven reverse engineering (MCP server and CLI, by morluto). Run `rea setup` once to add it to Claude Code and Codex. Native binaries need Ghidra; needs Node 22.19+.",
|
|
25840
|
+
size: "8 MB",
|
|
25841
|
+
source: { npm: "rea-agents" },
|
|
25842
|
+
exe: "rea.cmd",
|
|
25843
|
+
cli: true,
|
|
25844
|
+
plugsInto: "Claude Code and Codex as an MCP server, after `rea setup`"
|
|
25845
|
+
},
|
|
25748
25846
|
// ---- editors
|
|
25749
25847
|
{
|
|
25750
25848
|
id: "vscode",
|
|
@@ -26206,16 +26304,6 @@ var APPS = [
|
|
|
26206
26304
|
cli: true
|
|
26207
26305
|
},
|
|
26208
26306
|
// ---- reverse engineering
|
|
26209
|
-
{
|
|
26210
|
-
id: "rea",
|
|
26211
|
-
name: "REA (Reverse Engineer Anything)",
|
|
26212
|
-
category: "reversing",
|
|
26213
|
-
about: "Agent-driven reverse engineering (MCP server and CLI, by morluto). Run `rea setup` once to add it to Claude Code and Codex. Native binaries need Ghidra; needs Node 22.19+.",
|
|
26214
|
-
size: "8 MB",
|
|
26215
|
-
source: { npm: "rea-agents" },
|
|
26216
|
-
exe: "rea.cmd",
|
|
26217
|
-
cli: true
|
|
26218
|
-
},
|
|
26219
26307
|
{
|
|
26220
26308
|
id: "ghidra",
|
|
26221
26309
|
name: "Ghidra",
|
|
@@ -26528,13 +26616,87 @@ function appsToInstall(apps, gitAccess) {
|
|
|
26528
26616
|
const needs7zip = allowed.some((e) => e.needs?.includes("7zip") || e.unpack === "nsis") && !allowed.some((e) => e.id === "7zip");
|
|
26529
26617
|
return { entries: [...needs7zip ? [appById("7zip")] : [], ...allowed], skipped };
|
|
26530
26618
|
}
|
|
26619
|
+
function appsNeedUv(apps) {
|
|
26620
|
+
return Boolean(
|
|
26621
|
+
apps?.install.some((id) => {
|
|
26622
|
+
const source = appById(id)?.source;
|
|
26623
|
+
return source !== void 0 && "locked" in source && source.locked === "uv";
|
|
26624
|
+
})
|
|
26625
|
+
);
|
|
26626
|
+
}
|
|
26531
26627
|
function appsNeedMesa(apps) {
|
|
26532
26628
|
return Boolean(apps?.install.some((id) => appById(id)?.needs?.includes("mesa")));
|
|
26533
26629
|
}
|
|
26534
26630
|
|
|
26631
|
+
// src/shared/apps/agent-addons.ts
|
|
26632
|
+
function rtkHookCommand(exe) {
|
|
26633
|
+
return '"' + exe.replace(/\\/g, "/") + '" hook claude';
|
|
26634
|
+
}
|
|
26635
|
+
function claudeManagedSettings(deny, rtkExe, headroomUrl2 = null) {
|
|
26636
|
+
if (!deny.length && !rtkExe && !headroomUrl2) return null;
|
|
26637
|
+
return {
|
|
26638
|
+
...deny.length ? { permissions: { deny } } : {},
|
|
26639
|
+
...rtkExe ? { hooks: { PreToolUse: [{ matcher: "Bash", hooks: [{ type: "command", command: rtkHookCommand(rtkExe) }] }] } } : {},
|
|
26640
|
+
...headroomUrl2 ? { env: { ANTHROPIC_BASE_URL: headroomUrl2 } } : {}
|
|
26641
|
+
};
|
|
26642
|
+
}
|
|
26643
|
+
var RTK_GUIDE_LINE = "- rtk is on PATH and compacts command output: Claude Code's Bash commands go through it on their own; in other agents prefix shell commands with `rtk` (`rtk git status`, `rtk cargo test`, `rtk ls`).";
|
|
26644
|
+
var HEADROOM_PORT = 8787;
|
|
26645
|
+
var HEADROOM_UPSTREAM = "https://api.anthropic.com";
|
|
26646
|
+
function headroomUrl(port = HEADROOM_PORT) {
|
|
26647
|
+
return "http://127.0.0.1:" + port;
|
|
26648
|
+
}
|
|
26649
|
+
function headroomArgs(port = HEADROOM_PORT) {
|
|
26650
|
+
return [
|
|
26651
|
+
"proxy",
|
|
26652
|
+
"--host",
|
|
26653
|
+
"127.0.0.1",
|
|
26654
|
+
"--port",
|
|
26655
|
+
String(port),
|
|
26656
|
+
"--anthropic-api-url",
|
|
26657
|
+
HEADROOM_UPSTREAM,
|
|
26658
|
+
"--no-telemetry"
|
|
26659
|
+
];
|
|
26660
|
+
}
|
|
26661
|
+
var HEADROOM_ENV = {
|
|
26662
|
+
HEADROOM_OFFLINE: "1",
|
|
26663
|
+
HEADROOM_TELEMETRY: "off",
|
|
26664
|
+
HEADROOM_BEACON: "off",
|
|
26665
|
+
HEADROOM_UPDATE_CHECK: "off",
|
|
26666
|
+
DO_NOT_TRACK: "1",
|
|
26667
|
+
HF_HUB_OFFLINE: "1",
|
|
26668
|
+
PYTHONIOENCODING: "utf-8"
|
|
26669
|
+
};
|
|
26670
|
+
var SECRET_NAME = /(KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH)/i;
|
|
26671
|
+
function headroomEnv(base) {
|
|
26672
|
+
const env = {};
|
|
26673
|
+
for (const [name, value] of Object.entries(base))
|
|
26674
|
+
if (value !== void 0 && !SECRET_NAME.test(name) && !/^(ANTHROPIC|OPENAI|CLAUDE)_/i.test(name)) env[name] = value;
|
|
26675
|
+
return { ...env, ...HEADROOM_ENV };
|
|
26676
|
+
}
|
|
26677
|
+
function headroomGuideLine(logFile2) {
|
|
26678
|
+
return "- Headroom compresses Claude Code's requests: Claude Code reaches the API through its proxy on " + headroomUrl() + " (log: `" + logFile2 + "`). If Claude Code cannot reach the API, the proxy stopped: it starts again with the next sandbox, or turn Headroom off in Apps.";
|
|
26679
|
+
}
|
|
26680
|
+
function addonMcpServer(folder, mcp) {
|
|
26681
|
+
const script = folder.replace(/[\\/]+$/, "") + "\\" + mcp.script.replace(/\//g, "\\");
|
|
26682
|
+
return { type: "stdio", command: "node", args: [script, ...mcp.args ?? []], env: {} };
|
|
26683
|
+
}
|
|
26684
|
+
function withAddonMcpServers(current, servers, known) {
|
|
26685
|
+
const kept = Object.fromEntries(Object.entries(current).filter(([name]) => !known.includes(name) || name in servers));
|
|
26686
|
+
return { ...kept, ...servers };
|
|
26687
|
+
}
|
|
26688
|
+
function addonGuideLine(mcpNames, ccusage) {
|
|
26689
|
+
return [
|
|
26690
|
+
...mcpNames.length ? ["- MCP servers in Claude Code from Apps: " + mcpNames.join(", ") + "."] : [],
|
|
26691
|
+
...ccusage ? ["- ccusage is on PATH: `ccusage daily` (or `monthly`, `session`) reports token use and cost."] : []
|
|
26692
|
+
];
|
|
26693
|
+
}
|
|
26694
|
+
|
|
26535
26695
|
// src/core/schema/apps.ts
|
|
26536
26696
|
var CATALOGUE_IDS = APPS.filter((a) => !a.setting).map((a) => a.id);
|
|
26537
26697
|
var AppIdSchema = external_exports.enum(CATALOGUE_IDS);
|
|
26698
|
+
var PROJECT_IDS = APPS.filter((a) => !a.setting && !a.userOnly).map((a) => a.id);
|
|
26699
|
+
var ProjectAppIdSchema = external_exports.enum(PROJECT_IDS);
|
|
26538
26700
|
var CustomAppIdSchema = external_exports.string().regex(/^[a-z0-9][a-z0-9-]{0,40}$/, "lower-case letters, digits and - only");
|
|
26539
26701
|
var compiles = (pattern) => {
|
|
26540
26702
|
try {
|
|
@@ -26558,6 +26720,11 @@ var CustomAppSchema = external_exports.strictObject({
|
|
|
26558
26720
|
}).refine((a) => a.github && a.asset ? !a.url : Boolean(a.url) && !a.github && !a.asset, {
|
|
26559
26721
|
message: "give github + asset, or url (not both)"
|
|
26560
26722
|
});
|
|
26723
|
+
var ProjectAppsSchema = external_exports.strictObject({
|
|
26724
|
+
install: external_exports.array(ProjectAppIdSchema).describe(
|
|
26725
|
+
"Apps from the catalogue this project adds to yours (agent add-ons such as rtk, Headroom and the MCP servers are set in your own settings only)."
|
|
26726
|
+
)
|
|
26727
|
+
});
|
|
26561
26728
|
var AppsSchema = external_exports.strictObject({
|
|
26562
26729
|
install: external_exports.array(AppIdSchema).describe(
|
|
26563
26730
|
"Apps from the catalogue to install in every sandbox (the Apps screen in the menu lists them by category). Each is downloaded once and kept."
|
|
@@ -26598,12 +26765,39 @@ var ResumeSchema = external_exports.strictObject({
|
|
|
26598
26765
|
});
|
|
26599
26766
|
|
|
26600
26767
|
// src/core/schema/web.ts
|
|
26768
|
+
var REMOTE_ROLES = ["view", "control"];
|
|
26769
|
+
var WindowsUserNameSchema = external_exports.string().trim().min(1).max(120).regex(
|
|
26770
|
+
/^(?:[A-Za-z0-9][A-Za-z0-9._ -]{0,62}\\)?[^\\/"[\]:;|=,+*?<>@]{1,64}$/,
|
|
26771
|
+
"a Windows user name (name or DOMAIN\\name)"
|
|
26772
|
+
);
|
|
26773
|
+
var RemoteUserSchema = external_exports.strictObject({
|
|
26774
|
+
name: WindowsUserNameSchema.describe("The Windows user (name, or DOMAIN\\name)"),
|
|
26775
|
+
role: external_exports.enum(REMOTE_ROLES).describe("view: sees everything, terminals read-only. control: everything but remote access, logins and tokens.")
|
|
26776
|
+
});
|
|
26777
|
+
var WebLanSchema = external_exports.strictObject({
|
|
26778
|
+
enabled: external_exports.boolean().describe(
|
|
26779
|
+
"(Beta) Devices on your network (a phone): an HTTPS address on this PC for devices you pair with a one-time code (sandbox web pair). Needs a firewall rule (sandbox web lan on asks Windows once). Off: every paired device is signed out."
|
|
26780
|
+
),
|
|
26781
|
+
port: external_exports.number().int().min(1024).max(65535).describe("HTTPS port for paired devices on your network."),
|
|
26782
|
+
address: external_exports.string().trim().max(15).regex(/^$|^\d{1,3}(\.\d{1,3}){3}$/, "an IPv4 address or empty").describe("This PC's private address to listen on. Empty: the one of its network adapter (never a public one).")
|
|
26783
|
+
});
|
|
26784
|
+
var WebRemoteSchema = external_exports.strictObject({
|
|
26785
|
+
windowsSignIn: external_exports.boolean().describe(
|
|
26786
|
+
"(Beta) Other Windows users of this PC named in web.remote.users sign in to your web UI (and sandbox remote) with their own Windows account: no password, no link."
|
|
26787
|
+
),
|
|
26788
|
+
users: external_exports.array(RemoteUserSchema).max(32).describe("Who else may sign in with Windows, and their role (view or control)."),
|
|
26789
|
+
rememberDays: external_exports.number().int().min(1).max(90).describe(
|
|
26790
|
+
"How many days a paired device or a Windows sign-in stays signed in (from when it signed in, not renewed)."
|
|
26791
|
+
),
|
|
26792
|
+
lan: WebLanSchema
|
|
26793
|
+
});
|
|
26601
26794
|
var WebSchema = external_exports.strictObject({
|
|
26602
26795
|
enabled: external_exports.boolean().describe(
|
|
26603
26796
|
"(Beta) The web UI: your sandbox sessions in a browser on this PC (http://127.0.0.1:<port>, this PC only). On: every sandbox start also starts it in the background (it keeps running until sandbox web stop or a restart of the PC). Off: only sandbox web start runs it. Open it signed in with sandbox web open."
|
|
26604
26797
|
),
|
|
26605
26798
|
port: external_exports.number().int().min(1024).max(65535).describe("Port of the web UI on 127.0.0.1 (this PC only). Pick another when it is taken."),
|
|
26606
|
-
openOnLaunch: external_exports.boolean().describe("(Beta) With the web UI on: open it in your browser, already signed in, every time a sandbox starts.")
|
|
26799
|
+
openOnLaunch: external_exports.boolean().describe("(Beta) With the web UI on: open it in your browser, already signed in, every time a sandbox starts."),
|
|
26800
|
+
remote: WebRemoteSchema.describe("(Beta) Access for other Windows users of this PC and for paired devices.")
|
|
26607
26801
|
});
|
|
26608
26802
|
|
|
26609
26803
|
// src/core/schema/vpn.ts
|
|
@@ -26633,6 +26827,36 @@ var GithubSchema = external_exports.strictObject({
|
|
|
26633
26827
|
});
|
|
26634
26828
|
|
|
26635
26829
|
// src/core/schema/config.ts
|
|
26830
|
+
var RESERVED_ENV_PREFIX = /^(AGENT_|GIT_|GH_|GITHUB_|NODE_|NPM_CONFIG_(USERCONFIG|GLOBALCONFIG|PREFIX|SCRIPT_SHELL)|SSL_|CLAUDE|ANTHROPIC_|OPENAI_|CODEX_|GEMINI_|GOOGLE_|COPILOT_|AWS_|AZURE_)/i;
|
|
26831
|
+
var RESERVED_ENV_SUFFIX = /(_PROXY|_BASE_URL|_ENDPOINT|_CA_BUNDLE|_CA_CERTS)$/i;
|
|
26832
|
+
var RESERVED_ENV_NAMES = new Set(
|
|
26833
|
+
[
|
|
26834
|
+
"PATH",
|
|
26835
|
+
"PATHEXT",
|
|
26836
|
+
"BASH_ENV",
|
|
26837
|
+
"ENV",
|
|
26838
|
+
"COMSPEC",
|
|
26839
|
+
"PSMODULEPATH",
|
|
26840
|
+
"PYTHONPATH",
|
|
26841
|
+
"PYTHONSTARTUP",
|
|
26842
|
+
"PERL5OPT",
|
|
26843
|
+
"RUBYOPT",
|
|
26844
|
+
"JAVA_TOOL_OPTIONS",
|
|
26845
|
+
"LD_PRELOAD",
|
|
26846
|
+
"SYSTEMROOT",
|
|
26847
|
+
"WINDIR",
|
|
26848
|
+
"HOME",
|
|
26849
|
+
"USERPROFILE",
|
|
26850
|
+
"APPDATA",
|
|
26851
|
+
"LOCALAPPDATA",
|
|
26852
|
+
"PROGRAMDATA",
|
|
26853
|
+
"TEMP",
|
|
26854
|
+
"TMP"
|
|
26855
|
+
].map((n) => n.toUpperCase())
|
|
26856
|
+
);
|
|
26857
|
+
function reservedEnvName(name) {
|
|
26858
|
+
return RESERVED_ENV_PREFIX.test(name) || RESERVED_ENV_SUFFIX.test(name) || RESERVED_ENV_NAMES.has(name.toUpperCase());
|
|
26859
|
+
}
|
|
26636
26860
|
var ConfigSchema = external_exports.strictObject({
|
|
26637
26861
|
$schema: SchemaRefSchema.optional(),
|
|
26638
26862
|
defaultHarness: NameSchema.describe("Agent started by `sandbox launch` (sandbox claude always runs claude)."),
|
|
@@ -26699,10 +26923,14 @@ var LocalOverridesSchema = external_exports.strictObject({
|
|
|
26699
26923
|
scripts: StringsSchema.describe(
|
|
26700
26924
|
"Scripts (.ps1 / .mjs / .cmd, relative to this file) run inside the sandbox before the agent."
|
|
26701
26925
|
),
|
|
26702
|
-
// This PC's resources are yours to share: CPU
|
|
26926
|
+
// This PC's resources are yours to share: CPU, paging file (this PC's disk) and the RAM kept for this PC are not a
|
|
26927
|
+
// project's to set.
|
|
26703
26928
|
sandbox: SandboxSchema.omit({
|
|
26704
26929
|
cpuLimit: true,
|
|
26705
26930
|
pageFileMb: true,
|
|
26931
|
+
reserveHostMb: true,
|
|
26932
|
+
maxMemoryPercent: true,
|
|
26933
|
+
maxMemoryMb: true,
|
|
26706
26934
|
engine: true,
|
|
26707
26935
|
agentMemoryHeadroomMb: true,
|
|
26708
26936
|
pressureResponse: true
|
|
@@ -26716,14 +26944,17 @@ var LocalOverridesSchema = external_exports.strictObject({
|
|
|
26716
26944
|
// Every toolchain setting, each one optional (a project usually only switches languages on or pins a version).
|
|
26717
26945
|
toolchains: external_exports.strictObject({
|
|
26718
26946
|
...import_lodash.default.mapValues(import_lodash.default.omit(ToolchainsSchema.shape, "environment"), (shape) => shape.partial()),
|
|
26719
|
-
environment: ToolchainsSchema.shape.environment
|
|
26947
|
+
environment: ToolchainsSchema.shape.environment.refine(
|
|
26948
|
+
(env) => !Object.keys(env).some(reservedEnvName),
|
|
26949
|
+
"names the sandbox sets or that carry logins (AGENT_*, GIT_*, PATH, BASH_ENV, NODE_*, proxies, ANTHROPIC_*, CLAUDE_* ...) cannot be set by a project"
|
|
26950
|
+
)
|
|
26720
26951
|
}).partial(),
|
|
26721
26952
|
databases: external_exports.strictObject(import_lodash.default.mapValues(DatabasesSchema.shape, (shape) => shape.partial())).partial(),
|
|
26722
26953
|
attach: AttachSchema.partial(),
|
|
26723
26954
|
personalization: toggle("Copy your desktop look into the sandbox.").partial(),
|
|
26724
26955
|
// Catalogue apps only (a vetted list): your own programs (apps.custom) download anything, so a repo cannot add
|
|
26725
|
-
// them.
|
|
26726
|
-
apps:
|
|
26956
|
+
// them, nor agent add-ons that are yours only (rtk hooks every agent command, Headroom sits in its API path).
|
|
26957
|
+
apps: ProjectAppsSchema.partial(),
|
|
26727
26958
|
claudeProfile: ClaudeProfileSchema.pick({
|
|
26728
26959
|
enabled: true,
|
|
26729
26960
|
overwrite: true,
|
|
@@ -26786,6 +27017,7 @@ var ProjectSpecSchema = external_exports.strictObject({
|
|
|
26786
27017
|
/** Its hooks were staged in C:\AgentLaunch\projects\<name>\hooks. */
|
|
26787
27018
|
hooks: external_exports.boolean()
|
|
26788
27019
|
});
|
|
27020
|
+
var ShellChoiceSchema = external_exports.enum(["auto", "pwsh", "powershell", "cmd"]);
|
|
26789
27021
|
var GuestRequestSchema = external_exports.discriminatedUnion("kind", [
|
|
26790
27022
|
external_exports.strictObject({
|
|
26791
27023
|
kind: external_exports.literal("session"),
|
|
@@ -26795,8 +27027,12 @@ var GuestRequestSchema = external_exports.discriminatedUnion("kind", [
|
|
|
26795
27027
|
cwd: Text(),
|
|
26796
27028
|
project: ProjectSpecSchema.optional(),
|
|
26797
27029
|
harnessSpec: HarnessSchema.optional(),
|
|
27030
|
+
/** A plain shell instead of an agent (harness is then "shell" and args are ignored). */
|
|
27031
|
+
shell: ShellChoiceSchema.optional(),
|
|
26798
27032
|
createdAt: TimeSchema
|
|
26799
27033
|
}),
|
|
27034
|
+
/** End a running session (an agent or a shell) and everything it started. */
|
|
27035
|
+
external_exports.strictObject({ kind: external_exports.literal("close"), id: IdSchema, session: IdSchema, createdAt: TimeSchema }),
|
|
26800
27036
|
/** Provision a registered project without starting an agent (sandbox start / exec / db from its folder). */
|
|
26801
27037
|
external_exports.strictObject({ kind: external_exports.literal("project"), id: IdSchema, project: ProjectSpecSchema, createdAt: TimeSchema }),
|
|
26802
27038
|
external_exports.strictObject({
|
|
@@ -26862,6 +27098,8 @@ var SessionStatusSchema = external_exports.object({
|
|
|
26862
27098
|
id: IdSchema,
|
|
26863
27099
|
launchId: Text(64),
|
|
26864
27100
|
harness: Text(64),
|
|
27101
|
+
/** A plain shell (harness is then the shell: pwsh, powershell or cmd); absent: an agent. */
|
|
27102
|
+
kind: external_exports.enum(["agent", "shell"]).optional(),
|
|
26865
27103
|
cwd: Text(),
|
|
26866
27104
|
/** The project it runs in: its hub name, or the launch folder's for the first project. */
|
|
26867
27105
|
project: Text(64).optional(),
|
|
@@ -27531,92 +27769,52 @@ function writeStatus(phase, message) {
|
|
|
27531
27769
|
}
|
|
27532
27770
|
|
|
27533
27771
|
// src/guest/boot/boot.ts
|
|
27534
|
-
import
|
|
27535
|
-
import
|
|
27536
|
-
import { spawn as
|
|
27772
|
+
import fs62 from "node:fs";
|
|
27773
|
+
import path75 from "node:path";
|
|
27774
|
+
import { spawn as spawn10 } from "node:child_process";
|
|
27537
27775
|
|
|
27538
27776
|
// src/guest/boot/guide.ts
|
|
27777
|
+
import fs12 from "node:fs";
|
|
27778
|
+
import path17 from "node:path";
|
|
27779
|
+
|
|
27780
|
+
// src/guest/apps/find-exe.ts
|
|
27539
27781
|
import fs10 from "node:fs";
|
|
27540
27782
|
import path14 from "node:path";
|
|
27541
|
-
var
|
|
27542
|
-
var
|
|
27543
|
-
var
|
|
27544
|
-
|
|
27545
|
-
|
|
27546
|
-
|
|
27547
|
-
|
|
27548
|
-
|
|
27549
|
-
|
|
27550
|
-
|
|
27551
|
-
|
|
27552
|
-
|
|
27553
|
-
|
|
27554
|
-
|
|
27555
|
-
|
|
27556
|
-
|
|
27557
|
-
|
|
27558
|
-
|
|
27559
|
-
|
|
27560
|
-
|
|
27561
|
-
|
|
27562
|
-
|
|
27563
|
-
|
|
27564
|
-
|
|
27565
|
-
|
|
27566
|
-
|
|
27567
|
-
|
|
27568
|
-
|
|
27569
|
-
].join("\n");
|
|
27570
|
-
}
|
|
27571
|
-
function upsertGuide(file3, guide) {
|
|
27572
|
-
fs10.mkdirSync(path14.dirname(file3), { recursive: true });
|
|
27573
|
-
const current = fs10.existsSync(file3) ? fs10.readFileSync(file3, "utf8") : "";
|
|
27574
|
-
const start = current.indexOf(BEGIN);
|
|
27575
|
-
const end = current.indexOf(END);
|
|
27576
|
-
const without = start >= 0 && end > start ? current.slice(0, start) + current.slice(end + END.length) : current;
|
|
27577
|
-
fs10.writeFileSync(file3, without.trimEnd() + (without.trim() ? "\n\n" : "") + guide + "\n", "utf8");
|
|
27578
|
-
}
|
|
27579
|
-
function managedClaudeMd() {
|
|
27580
|
-
return path14.join(
|
|
27581
|
-
process.env.AGENT_MANAGED_DIR ?? path14.join(process.env.ProgramFiles ?? "C:\\Program Files", "ClaudeCode"),
|
|
27582
|
-
"CLAUDE.md"
|
|
27583
|
-
);
|
|
27584
|
-
}
|
|
27585
|
-
function writeGuides(toolSummary, lan, projects = []) {
|
|
27586
|
-
const guide = sandboxGuide(toolSummary, lan, projects);
|
|
27587
|
-
const managed = managedClaudeMd();
|
|
27588
|
-
fs10.mkdirSync(path14.dirname(managed), { recursive: true });
|
|
27589
|
-
fs10.writeFileSync(managed, guide + "\n", "utf8");
|
|
27590
|
-
fs10.writeFileSync(path14.join(dataDir, "SANDBOX.md"), guide + "\n", "utf8");
|
|
27591
|
-
upsertGuide(path14.join(stateDir, "codex", "AGENTS.md"), guide);
|
|
27592
|
-
upsertGuide(path14.join(stateDir, "gemini", ".gemini", "GEMINI.md"), guide);
|
|
27593
|
-
removeGuide(path14.join(claudeDir, "CLAUDE.md"));
|
|
27594
|
-
return managed;
|
|
27595
|
-
}
|
|
27596
|
-
var removeGuide = (file3) => {
|
|
27597
|
-
if (!fs10.existsSync(file3)) return;
|
|
27598
|
-
const current = fs10.readFileSync(file3, "utf8");
|
|
27599
|
-
const start = current.indexOf(BEGIN);
|
|
27600
|
-
const end = current.indexOf(END);
|
|
27601
|
-
if (start >= 0 && end > start)
|
|
27602
|
-
fs10.writeFileSync(file3, (current.slice(0, start) + current.slice(end + END.length)).trim() + "\n", "utf8");
|
|
27603
|
-
};
|
|
27604
|
-
|
|
27605
|
-
// src/guest/runtime/fs.ts
|
|
27606
|
-
import fs11 from "node:fs";
|
|
27607
|
-
function exists(p) {
|
|
27608
|
-
return fs11.existsSync(p);
|
|
27609
|
-
}
|
|
27610
|
-
function mkdirp(p) {
|
|
27611
|
-
fs11.mkdirSync(p, { recursive: true });
|
|
27612
|
-
return p;
|
|
27783
|
+
var MAX_DEPTH = 7;
|
|
27784
|
+
var MAX_ENTRIES = 5e4;
|
|
27785
|
+
var X64_FOLDER = /(^|[\\/])(amd64|x64|x86_64|win64)([\\/]|$)/i;
|
|
27786
|
+
function findExe(root, exe) {
|
|
27787
|
+
const match = exeMatcher(exe);
|
|
27788
|
+
const best = (hits) => hits.find((h) => X64_FOLDER.test(path14.relative(root, h))) ?? hits[0] ?? null;
|
|
27789
|
+
let queue = [root];
|
|
27790
|
+
let seen = 0;
|
|
27791
|
+
for (let depth = 0; depth < MAX_DEPTH && queue.length; depth++) {
|
|
27792
|
+
const next = [];
|
|
27793
|
+
const hits = [];
|
|
27794
|
+
for (const dir of queue) {
|
|
27795
|
+
let entries3;
|
|
27796
|
+
try {
|
|
27797
|
+
entries3 = fs10.readdirSync(dir, { withFileTypes: true });
|
|
27798
|
+
} catch {
|
|
27799
|
+
continue;
|
|
27800
|
+
}
|
|
27801
|
+
const hit = entries3.find((e) => e.isFile() && match(e.name));
|
|
27802
|
+
if (hit) hits.push(path14.join(dir, hit.name));
|
|
27803
|
+
else
|
|
27804
|
+
next.push(...entries3.filter((e) => e.isDirectory() && !e.isSymbolicLink()).map((e) => path14.join(dir, e.name)));
|
|
27805
|
+
if ((seen += entries3.length) > MAX_ENTRIES) return best(hits);
|
|
27806
|
+
}
|
|
27807
|
+
if (hits.length) return best(hits);
|
|
27808
|
+
queue = next;
|
|
27809
|
+
}
|
|
27810
|
+
return null;
|
|
27613
27811
|
}
|
|
27614
27812
|
|
|
27615
27813
|
// src/guest/toolchains/tool-env.ts
|
|
27616
27814
|
import path16 from "node:path";
|
|
27617
27815
|
|
|
27618
27816
|
// src/guest/runtime/process.ts
|
|
27619
|
-
import
|
|
27817
|
+
import fs11 from "node:fs";
|
|
27620
27818
|
import os4 from "node:os";
|
|
27621
27819
|
import path15 from "node:path";
|
|
27622
27820
|
import { spawnSync } from "node:child_process";
|
|
@@ -27651,24 +27849,24 @@ function scriptOutput(name, args = [], options = {}) {
|
|
|
27651
27849
|
return execOutput(SYSTEM.powershell(), scriptArgs(name, args), options);
|
|
27652
27850
|
}
|
|
27653
27851
|
function runScriptWithJson(name, param, data, args = []) {
|
|
27654
|
-
const dir =
|
|
27852
|
+
const dir = fs11.mkdtempSync(path15.join(os4.tmpdir(), "sbx-"));
|
|
27655
27853
|
const file3 = path15.join(dir, "input.json");
|
|
27656
27854
|
try {
|
|
27657
|
-
|
|
27855
|
+
fs11.writeFileSync(file3, JSON.stringify(data), "utf8");
|
|
27658
27856
|
runScript(name, ["-" + param, file3, ...args]);
|
|
27659
27857
|
} finally {
|
|
27660
|
-
|
|
27858
|
+
fs11.rmSync(dir, { recursive: true, force: true });
|
|
27661
27859
|
}
|
|
27662
27860
|
}
|
|
27663
27861
|
function robocopy(from, to, files = []) {
|
|
27664
27862
|
if (!isWin) {
|
|
27665
27863
|
if (!files.length) {
|
|
27666
|
-
|
|
27864
|
+
fs11.cpSync(from, to, { recursive: true });
|
|
27667
27865
|
return;
|
|
27668
27866
|
}
|
|
27669
|
-
|
|
27670
|
-
for (const f of files.filter((f2) =>
|
|
27671
|
-
|
|
27867
|
+
fs11.mkdirSync(to, { recursive: true });
|
|
27868
|
+
for (const f of files.filter((f2) => fs11.existsSync(path15.join(from, f2))))
|
|
27869
|
+
fs11.copyFileSync(path15.join(from, f), path15.join(to, f));
|
|
27672
27870
|
return;
|
|
27673
27871
|
}
|
|
27674
27872
|
const what = files.length ? files : ["/E"];
|
|
@@ -27729,13 +27927,216 @@ function versionOf(exe, args = ["--version"], options = {}) {
|
|
|
27729
27927
|
return /\d+\.\d+\.\d+\S*/.exec(execOutput(exe, args, options))?.[0] ?? "installed";
|
|
27730
27928
|
}
|
|
27731
27929
|
|
|
27930
|
+
// src/guest/setup/agent-addons.ts
|
|
27931
|
+
function installedAddon(id) {
|
|
27932
|
+
const entry = appById(id);
|
|
27933
|
+
if (dryRun || !entry || !(session.apps?.install ?? []).includes(id)) return null;
|
|
27934
|
+
return findExe(tool("apps", id), entry.exe);
|
|
27935
|
+
}
|
|
27936
|
+
function installedRtk() {
|
|
27937
|
+
return installedAddon("rtk");
|
|
27938
|
+
}
|
|
27939
|
+
function installedMcpAddons() {
|
|
27940
|
+
return APPS.filter((a) => a.mcp && installedAddon(a.id)).map((a) => ({ id: a.id, folder: tool("apps", a.id) }));
|
|
27941
|
+
}
|
|
27942
|
+
|
|
27943
|
+
// src/guest/boot/guide.ts
|
|
27944
|
+
var BEGIN = "<!-- agent-sandbox:begin (generated every boot, do not edit) -->";
|
|
27945
|
+
var END = "<!-- agent-sandbox:end -->";
|
|
27946
|
+
var mirrorLine = () => {
|
|
27947
|
+
const drives = (session.substDrives ?? []).filter((d) => fs12.existsSync(d.letter + ":\\"));
|
|
27948
|
+
if (!drives.length) return [];
|
|
27949
|
+
return [
|
|
27950
|
+
"- " + drives.map((d) => d.letter + ":").join(", ") + " = mapped folders at their PC paths (subst onto `" + drives.map((d) => d.target).join("`, `") + "`; real-path tools may print that form)."
|
|
27951
|
+
];
|
|
27952
|
+
};
|
|
27953
|
+
function sandboxGuide(toolSummary, lan = "blocked", projects = [], addons = []) {
|
|
27954
|
+
return [
|
|
27955
|
+
BEGIN,
|
|
27956
|
+
"## Sandbox manifest \u2014 you are in a DISPOSABLE Windows Sandbox",
|
|
27957
|
+
"Wiped on close: everything except the paths below (installers, winget/choco, C:\\Users, Program Files, registry).",
|
|
27958
|
+
"- RW, persists: `" + workspace + "` = host folder " + session.workspaceHost,
|
|
27959
|
+
// Projects started from other folders while this sandbox runs: every agent here can see them.
|
|
27960
|
+
...projects.map(
|
|
27961
|
+
(p) => "- RW, persists: `" + p.guest + "` = host folder " + p.host + " (another project in this sandbox; your own is `%AGENT_WORKSPACE%`)"
|
|
27962
|
+
),
|
|
27963
|
+
"- RW, persists: `" + toolsDir + "` (toolchains) \u2014 put portable exes in `" + path17.join(toolsDir, "bin") + "` (on PATH)",
|
|
27964
|
+
"- RW, persists: `" + stateDir + "` (agent config/history; do not edit logins) \xB7 logs: `" + path17.join(dataDir, "logs") + "`",
|
|
27965
|
+
"- RO: `" + launchDir + "` (this boot's scripts) \xB7 lost on close: everything else, incl. `C:\\nvm` (Node symlink)",
|
|
27966
|
+
...mirrorLine(),
|
|
27967
|
+
"- Tools: " + toolSummary.join(" \xB7 "),
|
|
27968
|
+
// Agent add-ons that change how the agent works (rtk, Headroom, MCP servers, ccusage).
|
|
27969
|
+
...addons,
|
|
27970
|
+
"- Persistent installs: `npm i -g` (per nvm version), `pip`, `cargo install`, `dotnet tool -g`, `uv tool`, `bun add -g`. Real installers must re-run each boot via a hook (ask the user).",
|
|
27971
|
+
"- Mapped folders (workspace, C:\\AgentData) allow NO symlinks or junctions: pnpm runs hoisted (set), npm workspaces / `file:` deps and deno node_modules dirs fail there (use a folder on C:\\ outside them), bun cannot save its lockfile there (`bun install --no-save`).",
|
|
27972
|
+
"- Network: " + (lan === "offline" ? "OFF" : lan === "blocked" ? "internet yes, host LAN blocked" : "internet yes, host LAN NOT blocked this time") + ". Other sessions may share this workspace; the user may be typing from the host.",
|
|
27973
|
+
END
|
|
27974
|
+
].join("\n");
|
|
27975
|
+
}
|
|
27976
|
+
function upsertGuide(file3, guide) {
|
|
27977
|
+
fs12.mkdirSync(path17.dirname(file3), { recursive: true });
|
|
27978
|
+
const current = fs12.existsSync(file3) ? fs12.readFileSync(file3, "utf8") : "";
|
|
27979
|
+
const start = current.indexOf(BEGIN);
|
|
27980
|
+
const end = current.indexOf(END);
|
|
27981
|
+
const without = start >= 0 && end > start ? current.slice(0, start) + current.slice(end + END.length) : current;
|
|
27982
|
+
fs12.writeFileSync(file3, without.trimEnd() + (without.trim() ? "\n\n" : "") + guide + "\n", "utf8");
|
|
27983
|
+
}
|
|
27984
|
+
function managedClaudeMd() {
|
|
27985
|
+
return path17.join(
|
|
27986
|
+
process.env.AGENT_MANAGED_DIR ?? path17.join(process.env.ProgramFiles ?? "C:\\Program Files", "ClaudeCode"),
|
|
27987
|
+
"CLAUDE.md"
|
|
27988
|
+
);
|
|
27989
|
+
}
|
|
27990
|
+
var headroomRuns = () => {
|
|
27991
|
+
try {
|
|
27992
|
+
const file3 = path17.join(path17.dirname(managedClaudeMd()), "managed-settings.json");
|
|
27993
|
+
const settings = JSON.parse(fs12.readFileSync(file3, "utf8"));
|
|
27994
|
+
return typeof settings.env?.ANTHROPIC_BASE_URL === "string";
|
|
27995
|
+
} catch {
|
|
27996
|
+
return false;
|
|
27997
|
+
}
|
|
27998
|
+
};
|
|
27999
|
+
function addonLines() {
|
|
28000
|
+
const mcp = APPS.flatMap((a) => a.mcp && installedAddon(a.id) ? [a.mcp.name] : []);
|
|
28001
|
+
return [
|
|
28002
|
+
...installedRtk() ? [RTK_GUIDE_LINE] : [],
|
|
28003
|
+
...installedAddon("headroom") && headroomRuns() ? [headroomGuideLine(path17.join(logsDir, "headroom.log"))] : [],
|
|
28004
|
+
...addonGuideLine(mcp, Boolean(installedAddon("ccusage")))
|
|
28005
|
+
];
|
|
28006
|
+
}
|
|
28007
|
+
function writeGuides(toolSummary, lan, projects = []) {
|
|
28008
|
+
const guide = sandboxGuide(toolSummary, lan, projects, addonLines());
|
|
28009
|
+
const managed = managedClaudeMd();
|
|
28010
|
+
fs12.mkdirSync(path17.dirname(managed), { recursive: true });
|
|
28011
|
+
fs12.writeFileSync(managed, guide + "\n", "utf8");
|
|
28012
|
+
fs12.writeFileSync(path17.join(dataDir, "SANDBOX.md"), guide + "\n", "utf8");
|
|
28013
|
+
upsertGuide(path17.join(stateDir, "codex", "AGENTS.md"), guide);
|
|
28014
|
+
upsertGuide(path17.join(stateDir, "gemini", ".gemini", "GEMINI.md"), guide);
|
|
28015
|
+
removeGuide(path17.join(claudeDir, "CLAUDE.md"));
|
|
28016
|
+
return managed;
|
|
28017
|
+
}
|
|
28018
|
+
var removeGuide = (file3) => {
|
|
28019
|
+
if (!fs12.existsSync(file3)) return;
|
|
28020
|
+
const current = fs12.readFileSync(file3, "utf8");
|
|
28021
|
+
const start = current.indexOf(BEGIN);
|
|
28022
|
+
const end = current.indexOf(END);
|
|
28023
|
+
if (start >= 0 && end > start)
|
|
28024
|
+
fs12.writeFileSync(file3, (current.slice(0, start) + current.slice(end + END.length)).trim() + "\n", "utf8");
|
|
28025
|
+
};
|
|
28026
|
+
|
|
28027
|
+
// src/guest/runtime/fs.ts
|
|
28028
|
+
import fs13 from "node:fs";
|
|
28029
|
+
function exists(p) {
|
|
28030
|
+
return fs13.existsSync(p);
|
|
28031
|
+
}
|
|
28032
|
+
function mkdirp(p) {
|
|
28033
|
+
fs13.mkdirSync(p, { recursive: true });
|
|
28034
|
+
return p;
|
|
28035
|
+
}
|
|
28036
|
+
|
|
27732
28037
|
// src/guest/apps/app-installer.ts
|
|
27733
|
-
import
|
|
27734
|
-
import
|
|
28038
|
+
import fs17 from "node:fs";
|
|
28039
|
+
import path22 from "node:path";
|
|
28040
|
+
|
|
28041
|
+
// src/guest/toolchains/runtimes.ts
|
|
28042
|
+
import path18 from "node:path";
|
|
28043
|
+
|
|
28044
|
+
// src/guest/toolchains/install.ts
|
|
28045
|
+
import fs14 from "node:fs";
|
|
28046
|
+
async function downloadFile(url2, file3, sha256 = null) {
|
|
28047
|
+
const part = file3 + ".part";
|
|
28048
|
+
try {
|
|
28049
|
+
await downloader.file(url2, part, sha256);
|
|
28050
|
+
fs14.rmSync(file3, { force: true });
|
|
28051
|
+
fs14.renameSync(part, file3);
|
|
28052
|
+
} finally {
|
|
28053
|
+
fs14.rmSync(part, { force: true });
|
|
28054
|
+
}
|
|
28055
|
+
}
|
|
28056
|
+
async function installFromGithub(repo, pattern, o) {
|
|
28057
|
+
const asset = await githubAsset(repo, pattern, o.searchOlder);
|
|
28058
|
+
log("Downloading " + (typeof o.what === "string" ? o.what : o.what(asset)) + " ...");
|
|
28059
|
+
await downloader.archive(asset.url, o.dest, {
|
|
28060
|
+
sha256: asset.sha256,
|
|
28061
|
+
fileName: asset.name,
|
|
28062
|
+
...o.locate ? { locate: o.locate } : {},
|
|
28063
|
+
...o.up ? { up: o.up } : {}
|
|
28064
|
+
});
|
|
28065
|
+
}
|
|
28066
|
+
|
|
28067
|
+
// src/guest/toolchains/runtimes.ts
|
|
28068
|
+
async function setupSingleExe(env, name, repo, pattern, exeName, dir, options = {}) {
|
|
28069
|
+
if (dryRun) {
|
|
28070
|
+
log("(dry run) would provision " + name);
|
|
28071
|
+
return;
|
|
28072
|
+
}
|
|
28073
|
+
const bin = options.subdir ? path18.join(dir, options.subdir) : dir;
|
|
28074
|
+
const exe = path18.join(bin, exeName);
|
|
28075
|
+
if (!exists(exe) || options.refresh) {
|
|
28076
|
+
const size = options.size ? ", ~" + options.size : "";
|
|
28077
|
+
await installFromGithub(repo, pattern, {
|
|
28078
|
+
dest: dir,
|
|
28079
|
+
what: (a) => name + " (" + a.name + size + " once)",
|
|
28080
|
+
...options.subdir ? {} : { locate: exeName }
|
|
28081
|
+
});
|
|
28082
|
+
}
|
|
28083
|
+
if (!exists(exe)) throw new Error(exeName + " missing after installing " + name);
|
|
28084
|
+
env.prepend.push(bin);
|
|
28085
|
+
env.summary.push(name + ": " + versionOf(exe, options.versionArgs) + (options.note ?? ""));
|
|
28086
|
+
}
|
|
28087
|
+
async function setupBun(env) {
|
|
28088
|
+
await setupSingleExe(
|
|
28089
|
+
env,
|
|
28090
|
+
"bun",
|
|
28091
|
+
"oven-sh/bun",
|
|
28092
|
+
arch === "arm64" ? /^bun-windows-aarch64\.zip$/ : /^bun-windows-x64\.zip$/,
|
|
28093
|
+
"bun.exe",
|
|
28094
|
+
tool("bun", "bin"),
|
|
28095
|
+
{ size: "35 MB" }
|
|
28096
|
+
);
|
|
28097
|
+
Object.assign(env.vars, {
|
|
28098
|
+
BUN_INSTALL: tool("bun"),
|
|
28099
|
+
BUN_INSTALL_CACHE_DIR: path18.join(localDir, "bun-cache"),
|
|
28100
|
+
BUN_TMPDIR: path18.join(localDir, "bun-tmp")
|
|
28101
|
+
});
|
|
28102
|
+
}
|
|
28103
|
+
async function setupDeno(env) {
|
|
28104
|
+
await setupSingleExe(
|
|
28105
|
+
env,
|
|
28106
|
+
"deno",
|
|
28107
|
+
"denoland/deno",
|
|
28108
|
+
arch === "arm64" ? /^deno-aarch64-pc-windows-msvc[.]zip$/ : /^deno-x86_64-pc-windows-msvc[.]zip$/,
|
|
28109
|
+
"deno.exe",
|
|
28110
|
+
tool("deno", "bin"),
|
|
28111
|
+
{ size: "40 MB" }
|
|
28112
|
+
);
|
|
28113
|
+
Object.assign(env.vars, { DENO_DIR: tool("deno-cache"), DENO_INSTALL_ROOT: tool("deno"), DENO_NO_UPDATE_CHECK: "1" });
|
|
28114
|
+
}
|
|
28115
|
+
function uvVars() {
|
|
28116
|
+
return {
|
|
28117
|
+
UV_CACHE_DIR: tool("uv-cache"),
|
|
28118
|
+
UV_PYTHON_INSTALL_DIR: tool("uv-python"),
|
|
28119
|
+
UV_TOOL_DIR: tool("uv-tools"),
|
|
28120
|
+
UV_TOOL_BIN_DIR: tool("uv-bin")
|
|
28121
|
+
};
|
|
28122
|
+
}
|
|
28123
|
+
async function setupUv(env) {
|
|
28124
|
+
await setupSingleExe(
|
|
28125
|
+
env,
|
|
28126
|
+
"uv",
|
|
28127
|
+
"astral-sh/uv",
|
|
28128
|
+
arch === "arm64" ? /^uv-aarch64-pc-windows-msvc\.zip$/ : /^uv-x86_64-pc-windows-msvc\.zip$/,
|
|
28129
|
+
"uv.exe",
|
|
28130
|
+
tool("uv"),
|
|
28131
|
+
{ size: "20 MB" }
|
|
28132
|
+
);
|
|
28133
|
+
Object.assign(env.vars, uvVars());
|
|
28134
|
+
env.prepend.push(mkdirp(tool("uv-bin")));
|
|
28135
|
+
}
|
|
27735
28136
|
|
|
27736
28137
|
// src/guest/apps/after-install.ts
|
|
27737
|
-
import
|
|
27738
|
-
import
|
|
28138
|
+
import fs15 from "node:fs";
|
|
28139
|
+
import path19 from "node:path";
|
|
27739
28140
|
var SYSINTERNALS_TOOLS = [
|
|
27740
28141
|
"Process Explorer",
|
|
27741
28142
|
"Process Monitor",
|
|
@@ -27756,16 +28157,16 @@ var SYSINTERNALS_TOOLS = [
|
|
|
27756
28157
|
"ZoomIt"
|
|
27757
28158
|
];
|
|
27758
28159
|
async function afterInstall(entry, exe) {
|
|
27759
|
-
const dir =
|
|
28160
|
+
const dir = path19.dirname(exe);
|
|
27760
28161
|
if (entry.needs?.includes("mesa")) {
|
|
27761
28162
|
const mesa = tool("mesa", arch === "arm64" ? "arm64" : "x64");
|
|
27762
28163
|
for (const dll of ["opengl32.dll", "libgallium_wgl.dll", "dxil.dll"]) {
|
|
27763
|
-
if (exists(
|
|
27764
|
-
|
|
28164
|
+
if (exists(path19.join(mesa, dll)) && !exists(path19.join(dir, dll)))
|
|
28165
|
+
fs15.copyFileSync(path19.join(mesa, dll), path19.join(dir, dll));
|
|
27765
28166
|
}
|
|
27766
28167
|
}
|
|
27767
|
-
if (entry.id === "godot" && !exists(
|
|
27768
|
-
if (entry.id === "sublime") mkdirp(
|
|
28168
|
+
if (entry.id === "godot" && !exists(path19.join(dir, "._sc_"))) fs15.writeFileSync(path19.join(dir, "._sc_"), "");
|
|
28169
|
+
if (entry.id === "sublime") mkdirp(path19.join(dir, "Data"));
|
|
27769
28170
|
if (entry.id === "sysinternals") {
|
|
27770
28171
|
for (const name of SYSINTERNALS_TOOLS) {
|
|
27771
28172
|
await execAsync(
|
|
@@ -27777,47 +28178,14 @@ async function afterInstall(entry, exe) {
|
|
|
27777
28178
|
}
|
|
27778
28179
|
}
|
|
27779
28180
|
|
|
27780
|
-
// src/guest/apps/find-exe.ts
|
|
27781
|
-
import fs14 from "node:fs";
|
|
27782
|
-
import path18 from "node:path";
|
|
27783
|
-
var MAX_DEPTH = 7;
|
|
27784
|
-
var MAX_ENTRIES = 5e4;
|
|
27785
|
-
var X64_FOLDER = /(^|[\\/])(amd64|x64|x86_64|win64)([\\/]|$)/i;
|
|
27786
|
-
function findExe(root, exe) {
|
|
27787
|
-
const match = exeMatcher(exe);
|
|
27788
|
-
const best = (hits) => hits.find((h) => X64_FOLDER.test(path18.relative(root, h))) ?? hits[0] ?? null;
|
|
27789
|
-
let queue = [root];
|
|
27790
|
-
let seen = 0;
|
|
27791
|
-
for (let depth = 0; depth < MAX_DEPTH && queue.length; depth++) {
|
|
27792
|
-
const next = [];
|
|
27793
|
-
const hits = [];
|
|
27794
|
-
for (const dir of queue) {
|
|
27795
|
-
let entries3;
|
|
27796
|
-
try {
|
|
27797
|
-
entries3 = fs14.readdirSync(dir, { withFileTypes: true });
|
|
27798
|
-
} catch {
|
|
27799
|
-
continue;
|
|
27800
|
-
}
|
|
27801
|
-
const hit = entries3.find((e) => e.isFile() && match(e.name));
|
|
27802
|
-
if (hit) hits.push(path18.join(dir, hit.name));
|
|
27803
|
-
else
|
|
27804
|
-
next.push(...entries3.filter((e) => e.isDirectory() && !e.isSymbolicLink()).map((e) => path18.join(dir, e.name)));
|
|
27805
|
-
if ((seen += entries3.length) > MAX_ENTRIES) return best(hits);
|
|
27806
|
-
}
|
|
27807
|
-
if (hits.length) return best(hits);
|
|
27808
|
-
queue = next;
|
|
27809
|
-
}
|
|
27810
|
-
return null;
|
|
27811
|
-
}
|
|
27812
|
-
|
|
27813
28181
|
// src/guest/apps/shortcuts.ts
|
|
27814
28182
|
import os5 from "node:os";
|
|
27815
|
-
import
|
|
28183
|
+
import path20 from "node:path";
|
|
27816
28184
|
function shortcuts(apps) {
|
|
27817
28185
|
if (!apps.length) return;
|
|
27818
|
-
const desktop =
|
|
27819
|
-
const start =
|
|
27820
|
-
process.env.APPDATA ??
|
|
28186
|
+
const desktop = path20.join(os5.homedir(), "Desktop");
|
|
28187
|
+
const start = path20.join(
|
|
28188
|
+
process.env.APPDATA ?? path20.join(os5.homedir(), "AppData", "Roaming"),
|
|
27821
28189
|
"Microsoft",
|
|
27822
28190
|
"Windows",
|
|
27823
28191
|
"Start Menu",
|
|
@@ -27827,9 +28195,9 @@ function shortcuts(apps) {
|
|
|
27827
28195
|
const links = apps.flatMap((app) => {
|
|
27828
28196
|
const name = app.name.replace(/[\\/:*?"<>|]/g, "");
|
|
27829
28197
|
return [desktop, start].map((folder) => ({
|
|
27830
|
-
link:
|
|
28198
|
+
link: path20.join(folder, name + ".lnk"),
|
|
27831
28199
|
target: app.exe,
|
|
27832
|
-
workingDirectory:
|
|
28200
|
+
workingDirectory: path20.dirname(app.exe)
|
|
27833
28201
|
}));
|
|
27834
28202
|
});
|
|
27835
28203
|
runScriptWithJson("new-shortcuts.ps1", "ListFile", links);
|
|
@@ -27954,19 +28322,19 @@ async function resolve(entry) {
|
|
|
27954
28322
|
}
|
|
27955
28323
|
if ("url" in s) {
|
|
27956
28324
|
const name = decodeURIComponent(new URL(s.url).pathname.split("/").pop() || entry.id);
|
|
27957
|
-
return { url: s.url, fileName: /\.\w{2,5}$/.test(name) ? name : name + ".zip" };
|
|
28325
|
+
return { url: s.url, fileName: /\.\w{2,5}$/.test(name) ? name : name + ".zip", sha256: s.sha256 };
|
|
27958
28326
|
}
|
|
27959
28327
|
if ("resolve" in s && RESOLVERS[s.resolve]) return RESOLVERS[s.resolve]();
|
|
27960
28328
|
throw new Error("no download source for " + entry.name);
|
|
27961
28329
|
}
|
|
27962
28330
|
|
|
27963
28331
|
// src/guest/apps/unpack.ts
|
|
27964
|
-
import
|
|
27965
|
-
import
|
|
28332
|
+
import fs16 from "node:fs";
|
|
28333
|
+
import path21 from "node:path";
|
|
27966
28334
|
var sevenZip = () => tool("apps", "7zip", "7z.exe");
|
|
27967
28335
|
async function unpack(entry, file3, out, d) {
|
|
27968
28336
|
if (entry.id === "7zip") {
|
|
27969
|
-
const sevenZr =
|
|
28337
|
+
const sevenZr = path21.join(path21.dirname(file3), "7zr.exe");
|
|
27970
28338
|
const zr = await githubAsset("ip7z/7zip", /^7zr\.exe$/);
|
|
27971
28339
|
await downloader.file(zr.url, sevenZr, zr.sha256);
|
|
27972
28340
|
await execAsync(sevenZr, ["x", "-y", "-o" + out, file3], { stdio: "ignore" });
|
|
@@ -27975,17 +28343,17 @@ async function unpack(entry, file3, out, d) {
|
|
|
27975
28343
|
switch (entry.unpack ?? "archive") {
|
|
27976
28344
|
case "file": {
|
|
27977
28345
|
mkdirp(out);
|
|
27978
|
-
|
|
28346
|
+
fs16.renameSync(file3, path21.join(out, /^\//.test(entry.exe) ? path21.basename(file3) : entry.exe));
|
|
27979
28347
|
return;
|
|
27980
28348
|
}
|
|
27981
28349
|
case "nsis": {
|
|
27982
28350
|
if (!exists(sevenZip()))
|
|
27983
28351
|
throw new Error("7-Zip is needed to unpack " + entry.name + " and could not be installed");
|
|
27984
|
-
const raw =
|
|
28352
|
+
const raw = path21.join(path21.dirname(out), "raw");
|
|
27985
28353
|
await execAsync(sevenZip(), ["x", "-y", "-o" + raw, file3], { stdio: "ignore" });
|
|
27986
28354
|
const inner = findExe(raw, "/^app-64\\.7z$/");
|
|
27987
28355
|
if (inner) await execAsync(sevenZip(), ["x", "-y", "-o" + out, inner], { stdio: "ignore" });
|
|
27988
|
-
else
|
|
28356
|
+
else fs16.renameSync(raw, out);
|
|
27989
28357
|
return;
|
|
27990
28358
|
}
|
|
27991
28359
|
case "msi": {
|
|
@@ -28035,12 +28403,12 @@ var AppInstaller = class {
|
|
|
28035
28403
|
async installOne(entry) {
|
|
28036
28404
|
try {
|
|
28037
28405
|
const dest = tool("apps", ...entry.id.split("/"));
|
|
28038
|
-
if (!exists(
|
|
28406
|
+
if (!exists(path22.join(dest, MARKER)) || this.options.refresh) await this.download(entry, dest);
|
|
28039
28407
|
const exe = findExe(dest, entry.exe);
|
|
28040
28408
|
if (!exe) throw new Error(entry.exe + " not found in the download");
|
|
28041
28409
|
await afterInstall(entry, exe);
|
|
28042
|
-
if (entry.cli || entry.id === "sysinternals") this.env.prepend.push(
|
|
28043
|
-
if (!entry.cli) this.gui.push({ name: entry.name, exe });
|
|
28410
|
+
if (!entry.service && (entry.cli || entry.id === "sysinternals")) this.env.prepend.push(path22.dirname(exe));
|
|
28411
|
+
if (!entry.cli && !entry.service) this.gui.push({ name: entry.name, exe });
|
|
28044
28412
|
this.installed.push(entry.name);
|
|
28045
28413
|
} catch (e) {
|
|
28046
28414
|
warn(
|
|
@@ -28052,10 +28420,13 @@ var AppInstaller = class {
|
|
|
28052
28420
|
/** Downloads and unpacks one entry into its folder (replaced in one step: never half there). */
|
|
28053
28421
|
async download(entry, dest) {
|
|
28054
28422
|
const work = stagingFolder(dest);
|
|
28055
|
-
const out =
|
|
28423
|
+
const out = path22.join(work, "out");
|
|
28056
28424
|
try {
|
|
28057
|
-
if ("
|
|
28058
|
-
|
|
28425
|
+
if ("locked" in entry.source) {
|
|
28426
|
+
log("Installing " + entry.name + " " + entry.source.version + " (pinned, every file checked) ...");
|
|
28427
|
+
await installLocked(entry.id, entry.source.locked, mkdirp(out));
|
|
28428
|
+
} else if ("npm" in entry.source) {
|
|
28429
|
+
const npmCli = path22.join(path22.dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
|
|
28059
28430
|
log("Installing " + entry.name + " (npm) ...");
|
|
28060
28431
|
await execAsync(process.execPath, [
|
|
28061
28432
|
npmCli,
|
|
@@ -28070,17 +28441,60 @@ var AppInstaller = class {
|
|
|
28070
28441
|
} else {
|
|
28071
28442
|
const d = await resolve(entry);
|
|
28072
28443
|
log("Downloading " + entry.name + " (" + d.fileName + ", ~" + entry.size + " once) ...");
|
|
28073
|
-
const file3 =
|
|
28444
|
+
const file3 = path22.join(mkdirp(work), d.fileName.replace(/[\\/:*?"<>|]/g, "_"));
|
|
28074
28445
|
await downloader.file(d.url, file3, { sha256: d.sha256 ?? null });
|
|
28075
28446
|
await unpack(entry, file3, out, d);
|
|
28076
28447
|
}
|
|
28077
|
-
|
|
28448
|
+
fs17.writeFileSync(path22.join(out, MARKER), JSON.stringify({ id: entry.id, at: (/* @__PURE__ */ new Date()).toISOString() }));
|
|
28078
28449
|
moveIntoPlace(out, dest);
|
|
28079
28450
|
} finally {
|
|
28080
|
-
safeRemove(work,
|
|
28451
|
+
safeRemove(work, path22.dirname(work));
|
|
28081
28452
|
}
|
|
28082
28453
|
}
|
|
28083
28454
|
};
|
|
28455
|
+
var LOCKED_PYTHON = "3.13";
|
|
28456
|
+
async function installLocked(id, kind, out) {
|
|
28457
|
+
const lock = path22.join(launchDir, "sandbox", "addons", id);
|
|
28458
|
+
if (kind === "npm") {
|
|
28459
|
+
for (const f of ["package.json", "package-lock.json"]) fs17.copyFileSync(path22.join(lock, f), path22.join(out, f));
|
|
28460
|
+
const npmCli = path22.join(path22.dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
|
|
28461
|
+
await execAsync(
|
|
28462
|
+
process.execPath,
|
|
28463
|
+
[npmCli, "ci", "--ignore-scripts", "--no-audit", "--no-fund", "--loglevel=error"],
|
|
28464
|
+
{ cwd: out }
|
|
28465
|
+
);
|
|
28466
|
+
return;
|
|
28467
|
+
}
|
|
28468
|
+
const uv = findExe(tool("uv"), "uv.exe");
|
|
28469
|
+
if (!uv) throw new Error("uv is not installed (the uv step failed)");
|
|
28470
|
+
const env = { ...process.env, ...uvVars() };
|
|
28471
|
+
const venv = path22.join(out, "venv");
|
|
28472
|
+
await execAsync(
|
|
28473
|
+
uv,
|
|
28474
|
+
["venv", "--relocatable", "--python", LOCKED_PYTHON, "--python-preference", "only-managed", venv],
|
|
28475
|
+
{
|
|
28476
|
+
env
|
|
28477
|
+
}
|
|
28478
|
+
);
|
|
28479
|
+
await execAsync(
|
|
28480
|
+
uv,
|
|
28481
|
+
[
|
|
28482
|
+
"pip",
|
|
28483
|
+
"install",
|
|
28484
|
+
"--python",
|
|
28485
|
+
path22.join(venv, "Scripts", "python.exe"),
|
|
28486
|
+
"--require-hashes",
|
|
28487
|
+
"--no-deps",
|
|
28488
|
+
"--only-binary",
|
|
28489
|
+
":all:",
|
|
28490
|
+
"--link-mode",
|
|
28491
|
+
"copy",
|
|
28492
|
+
"-r",
|
|
28493
|
+
path22.join(lock, "requirements.txt")
|
|
28494
|
+
],
|
|
28495
|
+
{ env }
|
|
28496
|
+
);
|
|
28497
|
+
}
|
|
28084
28498
|
async function setupApps(env, apps, o) {
|
|
28085
28499
|
const { entries: entries3, skipped } = appsToInstall(apps, o.gitAccess);
|
|
28086
28500
|
for (const s of skipped) env.summary.push("app skipped: " + s);
|
|
@@ -28092,8 +28506,8 @@ async function setupApps(env, apps, o) {
|
|
|
28092
28506
|
}
|
|
28093
28507
|
|
|
28094
28508
|
// src/guest/toolchains/detect.ts
|
|
28095
|
-
import
|
|
28096
|
-
import
|
|
28509
|
+
import fs18 from "node:fs";
|
|
28510
|
+
import path23 from "node:path";
|
|
28097
28511
|
|
|
28098
28512
|
// src/guest/runtime/project-context.ts
|
|
28099
28513
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -28235,14 +28649,14 @@ function workspaceEntries() {
|
|
|
28235
28649
|
if (known) return known;
|
|
28236
28650
|
const list = (dir) => {
|
|
28237
28651
|
try {
|
|
28238
|
-
return
|
|
28652
|
+
return fs18.readdirSync(dir, { withFileTypes: true });
|
|
28239
28653
|
} catch {
|
|
28240
28654
|
return [];
|
|
28241
28655
|
}
|
|
28242
28656
|
};
|
|
28243
28657
|
const top = list(workspace2);
|
|
28244
28658
|
const below = top.filter((d) => d.isDirectory() && !d.name.startsWith(".") && !SKIP_DIRS.has(d.name.toLowerCase())).flatMap(
|
|
28245
|
-
(d) => list(
|
|
28659
|
+
(d) => list(path23.join(workspace2, d.name)).filter((f) => f.isFile()).map((f) => d.name + "/" + f.name)
|
|
28246
28660
|
);
|
|
28247
28661
|
const found = [...top.filter((d) => d.isFile()).map((d) => d.name), ...below];
|
|
28248
28662
|
entries.set(workspace2.toLowerCase(), found);
|
|
@@ -28253,9 +28667,9 @@ function wanted(setting, toolchain) {
|
|
|
28253
28667
|
}
|
|
28254
28668
|
function versionFromFiles(files, parse5 = (t) => specFromVersionFile(t)) {
|
|
28255
28669
|
for (const name of files) {
|
|
28256
|
-
const file3 =
|
|
28670
|
+
const file3 = path23.join(projectWorkspace(), name);
|
|
28257
28671
|
if (!exists(file3)) continue;
|
|
28258
|
-
const spec = parse5(
|
|
28672
|
+
const spec = parse5(fs18.readFileSync(file3, "utf8"), name);
|
|
28259
28673
|
if (spec) return { spec, source: name };
|
|
28260
28674
|
}
|
|
28261
28675
|
return null;
|
|
@@ -28318,22 +28732,22 @@ var DatabaseServer = class {
|
|
|
28318
28732
|
};
|
|
28319
28733
|
|
|
28320
28734
|
// src/guest/databases/dynamodb.ts
|
|
28321
|
-
import
|
|
28322
|
-
import
|
|
28735
|
+
import fs23 from "node:fs";
|
|
28736
|
+
import path26 from "node:path";
|
|
28323
28737
|
import { spawn as spawn3 } from "node:child_process";
|
|
28324
28738
|
|
|
28325
28739
|
// src/guest/toolchains/languages/java.ts
|
|
28326
|
-
import
|
|
28327
|
-
import
|
|
28740
|
+
import fs21 from "node:fs";
|
|
28741
|
+
import path24 from "node:path";
|
|
28328
28742
|
|
|
28329
28743
|
// src/guest/toolchains/version-cache.ts
|
|
28330
|
-
import
|
|
28744
|
+
import fs20 from "node:fs";
|
|
28331
28745
|
|
|
28332
28746
|
// src/guest/toolchains/state-file.ts
|
|
28333
|
-
import
|
|
28747
|
+
import fs19 from "node:fs";
|
|
28334
28748
|
function readState(file3, schema, empty) {
|
|
28335
28749
|
try {
|
|
28336
|
-
return schema.safeParse(JSON.parse(
|
|
28750
|
+
return schema.safeParse(JSON.parse(fs19.readFileSync(file3, "utf8").replace(/^\uFEFF/, ""))).data ?? empty;
|
|
28337
28751
|
} catch {
|
|
28338
28752
|
return empty;
|
|
28339
28753
|
}
|
|
@@ -28368,7 +28782,7 @@ var VersionCache = class {
|
|
|
28368
28782
|
return cached2.value;
|
|
28369
28783
|
try {
|
|
28370
28784
|
const value = await resolve2();
|
|
28371
|
-
|
|
28785
|
+
fs20.mkdirSync(toolsDir, { recursive: true });
|
|
28372
28786
|
writeJsonAtomic(this.file(), { ...this.remembered(), [key]: { value, at: Date.now() } });
|
|
28373
28787
|
return value;
|
|
28374
28788
|
} catch (e) {
|
|
@@ -28421,7 +28835,7 @@ var setupJdk = async (env, config2) => {
|
|
|
28421
28835
|
const { major, source } = await javaMajor(config2);
|
|
28422
28836
|
const release = await resolveCached("java:" + major, async () => (await temurin(major)).release_name);
|
|
28423
28837
|
const home = tool("java", release.replace(/[^A-Za-z0-9.-]/g, "_"));
|
|
28424
|
-
if (!exists(
|
|
28838
|
+
if (!exists(path24.join(home, "bin", "java.exe"))) {
|
|
28425
28839
|
const asset = await temurin(major);
|
|
28426
28840
|
log("Downloading Java " + release + " (JDK, ~200 MB once) ...");
|
|
28427
28841
|
await downloader.archive(asset.binary.package.link, home, {
|
|
@@ -28431,13 +28845,13 @@ var setupJdk = async (env, config2) => {
|
|
|
28431
28845
|
});
|
|
28432
28846
|
}
|
|
28433
28847
|
env.vars.JAVA_HOME = home;
|
|
28434
|
-
env.prepend.push(
|
|
28848
|
+
env.prepend.push(path24.join(home, "bin"));
|
|
28435
28849
|
env.summary.push("java: " + release + " (Temurin, from " + source + ")");
|
|
28436
28850
|
};
|
|
28437
28851
|
async function ensureJdk() {
|
|
28438
28852
|
const root = tool("java");
|
|
28439
|
-
const installed = exists(root) ?
|
|
28440
|
-
if (installed.length) return
|
|
28853
|
+
const installed = exists(root) ? fs21.readdirSync(root).filter((d) => exists(path24.join(root, d, "bin", "java.exe"))).sort((a, b) => b.localeCompare(a, void 0, { numeric: true })) : [];
|
|
28854
|
+
if (installed.length) return path24.join(root, installed[0]);
|
|
28441
28855
|
const scratch = emptyEnv();
|
|
28442
28856
|
await setupJdk(scratch, { enabled: true, version: "lts", maven: false, gradle: false });
|
|
28443
28857
|
return scratch.vars.JAVA_HOME;
|
|
@@ -28450,7 +28864,7 @@ var setupMaven = async (env) => {
|
|
|
28450
28864
|
return pickPackageVersion(versions, "3") ?? Promise.reject(new Error("No Maven 3 release found"));
|
|
28451
28865
|
});
|
|
28452
28866
|
const home = tool("maven", version2);
|
|
28453
|
-
if (!exists(
|
|
28867
|
+
if (!exists(path24.join(home, "bin", "mvn.cmd"))) {
|
|
28454
28868
|
const url2 = MAVEN + version2 + "/apache-maven-" + version2 + "-bin.zip";
|
|
28455
28869
|
log("Downloading Maven " + version2 + " (~10 MB once) ...");
|
|
28456
28870
|
await downloader.archive(url2, home, {
|
|
@@ -28460,7 +28874,7 @@ var setupMaven = async (env) => {
|
|
|
28460
28874
|
}
|
|
28461
28875
|
const repo = tool("maven-repository");
|
|
28462
28876
|
Object.assign(env.vars, { MAVEN_HOME: home, M2_HOME: home, MAVEN_OPTS: "-Dmaven.repo.local=" + repo });
|
|
28463
|
-
env.prepend.push(
|
|
28877
|
+
env.prepend.push(path24.join(home, "bin"));
|
|
28464
28878
|
env.summary.push("maven: " + version2);
|
|
28465
28879
|
};
|
|
28466
28880
|
var setupGradle = async (env) => {
|
|
@@ -28472,7 +28886,7 @@ var setupGradle = async (env) => {
|
|
|
28472
28886
|
async () => current?.version ?? Promise.reject(new Error("Gradle version lookup failed"))
|
|
28473
28887
|
);
|
|
28474
28888
|
const home = tool("gradle", version2);
|
|
28475
|
-
if (!exists(
|
|
28889
|
+
if (!exists(path24.join(home, "bin", "gradle.bat"))) {
|
|
28476
28890
|
if (!current || current.version !== version2)
|
|
28477
28891
|
throw new Error("Gradle " + version2 + " is not installed and cannot be downloaded right now");
|
|
28478
28892
|
log("Downloading Gradle " + version2 + " (~130 MB once) ...");
|
|
@@ -28483,13 +28897,13 @@ var setupGradle = async (env) => {
|
|
|
28483
28897
|
});
|
|
28484
28898
|
}
|
|
28485
28899
|
const userHome = tool("gradle-home");
|
|
28486
|
-
|
|
28900
|
+
fs21.mkdirSync(userHome, { recursive: true });
|
|
28487
28901
|
Object.assign(env.vars, {
|
|
28488
28902
|
GRADLE_HOME: home,
|
|
28489
28903
|
GRADLE_USER_HOME: userHome,
|
|
28490
28904
|
GRADLE_OPTS: "-Dorg.gradle.vfs.watch=false"
|
|
28491
28905
|
});
|
|
28492
|
-
env.prepend.push(
|
|
28906
|
+
env.prepend.push(path24.join(home, "bin"));
|
|
28493
28907
|
env.summary.push("gradle: " + version2);
|
|
28494
28908
|
};
|
|
28495
28909
|
async function setupJava(env, config2) {
|
|
@@ -28513,29 +28927,29 @@ async function setupJava(env, config2) {
|
|
|
28513
28927
|
}
|
|
28514
28928
|
|
|
28515
28929
|
// src/guest/databases/server.ts
|
|
28516
|
-
import
|
|
28517
|
-
import
|
|
28930
|
+
import fs22 from "node:fs";
|
|
28931
|
+
import path25 from "node:path";
|
|
28518
28932
|
import { spawn as spawn2 } from "node:child_process";
|
|
28519
28933
|
function dataFor(name) {
|
|
28520
|
-
return
|
|
28934
|
+
return path25.join(dataDir, "databases", name);
|
|
28521
28935
|
}
|
|
28522
28936
|
async function startServer(name, exe, args, port) {
|
|
28523
28937
|
if (await portOpen(port)) throw new Error("port " + port + " is already in use (change databases." + name + ".port)");
|
|
28524
|
-
const logFile2 =
|
|
28525
|
-
const out =
|
|
28938
|
+
const logFile2 = path25.join(logsDir, name + ".log");
|
|
28939
|
+
const out = fs22.openSync(logFile2, "a");
|
|
28526
28940
|
spawn2(exe, args, { detached: true, stdio: ["ignore", out, out], windowsHide: true }).unref();
|
|
28527
|
-
|
|
28941
|
+
fs22.closeSync(out);
|
|
28528
28942
|
if (!await waitForPort(port, 60))
|
|
28529
28943
|
throw new Error(name + " did not start listening on port " + port + "; see " + logFile2);
|
|
28530
28944
|
}
|
|
28531
28945
|
async function clearStaleLocks(dir, files, port) {
|
|
28532
28946
|
if (await portOpen(port)) return;
|
|
28533
|
-
for (const f of files)
|
|
28947
|
+
for (const f of files) fs22.rmSync(path25.join(dir, f), { force: true });
|
|
28534
28948
|
}
|
|
28535
28949
|
async function createOnce(data, marker, create) {
|
|
28536
|
-
if (exists(
|
|
28950
|
+
if (exists(path25.join(data, marker))) return;
|
|
28537
28951
|
const existed = exists(data);
|
|
28538
|
-
mkdirp(
|
|
28952
|
+
mkdirp(path25.dirname(data));
|
|
28539
28953
|
try {
|
|
28540
28954
|
await create();
|
|
28541
28955
|
} catch (e) {
|
|
@@ -28559,9 +28973,9 @@ var DynamoServer = class extends DatabaseServer {
|
|
|
28559
28973
|
* local endpoint up from AWS_ENDPOINT_URL_DYNAMODB, with dummy credentials (real ones never reach the sandbox).
|
|
28560
28974
|
*/
|
|
28561
28975
|
async start(env, plan2) {
|
|
28562
|
-
const java =
|
|
28976
|
+
const java = path26.join(await ensureJdk(), "bin", "java.exe");
|
|
28563
28977
|
const home = tool("dynamodb-local");
|
|
28564
|
-
if (!exists(
|
|
28978
|
+
if (!exists(path26.join(home, "DynamoDBLocal.jar"))) {
|
|
28565
28979
|
log("Downloading DynamoDB Local (~60 MB once) ...");
|
|
28566
28980
|
const sha256 = (await fetchText(DYNAMO_ZIP + ".sha256")).trim().split(/\s+/)[0];
|
|
28567
28981
|
await downloader.archive(DYNAMO_ZIP, home, {
|
|
@@ -28575,9 +28989,9 @@ var DynamoServer = class extends DatabaseServer {
|
|
|
28575
28989
|
"dynamodb",
|
|
28576
28990
|
java,
|
|
28577
28991
|
[
|
|
28578
|
-
"-Djava.library.path=" +
|
|
28992
|
+
"-Djava.library.path=" + path26.join(home, "DynamoDBLocal_lib"),
|
|
28579
28993
|
"-jar",
|
|
28580
|
-
|
|
28994
|
+
path26.join(home, "DynamoDBLocal.jar"),
|
|
28581
28995
|
"-sharedDb",
|
|
28582
28996
|
"-dbPath",
|
|
28583
28997
|
data,
|
|
@@ -28601,10 +29015,10 @@ var DynamoServer = class extends DatabaseServer {
|
|
|
28601
29015
|
);
|
|
28602
29016
|
if (!plan2.adminPort) return;
|
|
28603
29017
|
const prefix = tool("dynamodb-admin");
|
|
28604
|
-
const script =
|
|
29018
|
+
const script = path26.join(prefix, "node_modules", "dynamodb-admin", "dist", "dynamodb-admin.js");
|
|
28605
29019
|
if (!exists(script)) {
|
|
28606
29020
|
log("Installing dynamodb-admin, the DynamoDB web UI (~20 MB once) ...");
|
|
28607
|
-
const npmCli =
|
|
29021
|
+
const npmCli = path26.join(path26.dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
|
|
28608
29022
|
await execAsync(
|
|
28609
29023
|
process.execPath,
|
|
28610
29024
|
[npmCli, "install", "--global", "--prefix", prefix, "dynamodb-admin", "--no-fund", "--no-audit"],
|
|
@@ -28617,15 +29031,15 @@ var DynamoServer = class extends DatabaseServer {
|
|
|
28617
29031
|
);
|
|
28618
29032
|
return;
|
|
28619
29033
|
}
|
|
28620
|
-
const out =
|
|
29034
|
+
const out = fs23.openSync(path26.join(logsDir, "dynamodb-admin.log"), "a");
|
|
28621
29035
|
spawn3(
|
|
28622
29036
|
process.execPath,
|
|
28623
29037
|
[script, "--port", String(plan2.adminPort), "--dynamo-endpoint", endpoint, "--skip-default-credentials"],
|
|
28624
29038
|
{ detached: true, stdio: ["ignore", out, out], windowsHide: true, env: { ...process.env, ...aws } }
|
|
28625
29039
|
).unref();
|
|
28626
|
-
|
|
29040
|
+
fs23.closeSync(out);
|
|
28627
29041
|
if (!await waitForPort(plan2.adminPort, 30))
|
|
28628
|
-
throw new Error("dynamodb-admin did not start; see " +
|
|
29042
|
+
throw new Error("dynamodb-admin did not start; see " + path26.join(logsDir, "dynamodb-admin.log"));
|
|
28629
29043
|
env.summary.push(
|
|
28630
29044
|
"dynamodb-admin: http://localhost:" + plan2.adminPort + " (browse and edit tables in the sandbox's browser)"
|
|
28631
29045
|
);
|
|
@@ -28633,32 +29047,7 @@ var DynamoServer = class extends DatabaseServer {
|
|
|
28633
29047
|
};
|
|
28634
29048
|
|
|
28635
29049
|
// src/guest/databases/mongodb.ts
|
|
28636
|
-
import
|
|
28637
|
-
|
|
28638
|
-
// src/guest/toolchains/install.ts
|
|
28639
|
-
import fs23 from "node:fs";
|
|
28640
|
-
async function downloadFile(url2, file3, sha256 = null) {
|
|
28641
|
-
const part = file3 + ".part";
|
|
28642
|
-
try {
|
|
28643
|
-
await downloader.file(url2, part, sha256);
|
|
28644
|
-
fs23.rmSync(file3, { force: true });
|
|
28645
|
-
fs23.renameSync(part, file3);
|
|
28646
|
-
} finally {
|
|
28647
|
-
fs23.rmSync(part, { force: true });
|
|
28648
|
-
}
|
|
28649
|
-
}
|
|
28650
|
-
async function installFromGithub(repo, pattern, o) {
|
|
28651
|
-
const asset = await githubAsset(repo, pattern, o.searchOlder);
|
|
28652
|
-
log("Downloading " + (typeof o.what === "string" ? o.what : o.what(asset)) + " ...");
|
|
28653
|
-
await downloader.archive(asset.url, o.dest, {
|
|
28654
|
-
sha256: asset.sha256,
|
|
28655
|
-
fileName: asset.name,
|
|
28656
|
-
...o.locate ? { locate: o.locate } : {},
|
|
28657
|
-
...o.up ? { up: o.up } : {}
|
|
28658
|
-
});
|
|
28659
|
-
}
|
|
28660
|
-
|
|
28661
|
-
// src/guest/databases/mongodb.ts
|
|
29050
|
+
import path27 from "node:path";
|
|
28662
29051
|
var MongoServer = class extends DatabaseServer {
|
|
28663
29052
|
id = "mongodb";
|
|
28664
29053
|
async start(env, plan2) {
|
|
@@ -28673,13 +29062,13 @@ var MongoServer = class extends DatabaseServer {
|
|
|
28673
29062
|
};
|
|
28674
29063
|
const version2 = await resolveCached("mongodb:" + plan2.version, async () => (await find()).version);
|
|
28675
29064
|
const home = tool("mongodb", version2);
|
|
28676
|
-
if (!exists(
|
|
29065
|
+
if (!exists(path27.join(home, "bin", "mongod.exe"))) {
|
|
28677
29066
|
const { archive } = await find();
|
|
28678
29067
|
log("Downloading MongoDB " + version2 + " (~400 MB once) ...");
|
|
28679
29068
|
await downloader.archive(archive.url, home, { sha256: archive.sha256, locate: "mongod.exe", up: 1 });
|
|
28680
29069
|
}
|
|
28681
29070
|
const shell = tool("mongosh");
|
|
28682
|
-
if (!exists(
|
|
29071
|
+
if (!exists(path27.join(shell, "mongosh.exe"))) {
|
|
28683
29072
|
await installFromGithub("mongodb-js/mongosh", /^mongosh-[\d.]+-win32-x64\.zip$/, {
|
|
28684
29073
|
dest: shell,
|
|
28685
29074
|
what: "mongosh, the MongoDB shell (~50 MB once)",
|
|
@@ -28690,17 +29079,17 @@ var MongoServer = class extends DatabaseServer {
|
|
|
28690
29079
|
await clearStaleLocks(data, ["mongod.lock"], plan2.port);
|
|
28691
29080
|
await startServer(
|
|
28692
29081
|
"mongodb",
|
|
28693
|
-
|
|
29082
|
+
path27.join(home, "bin", "mongod.exe"),
|
|
28694
29083
|
["--dbpath", data, "--bind_ip", "127.0.0.1", "--port", String(plan2.port)],
|
|
28695
29084
|
plan2.port
|
|
28696
29085
|
);
|
|
28697
|
-
env.prepend.push(
|
|
29086
|
+
env.prepend.push(path27.join(home, "bin"), shell);
|
|
28698
29087
|
env.summary.push("mongodb " + version2 + ": mongodb://127.0.0.1:" + plan2.port + " (mongosh on PATH)");
|
|
28699
29088
|
}
|
|
28700
29089
|
};
|
|
28701
29090
|
|
|
28702
29091
|
// src/guest/databases/mysql.ts
|
|
28703
|
-
import
|
|
29092
|
+
import path28 from "node:path";
|
|
28704
29093
|
var MARIA = "https://downloads.mariadb.org/rest-api/mariadb/";
|
|
28705
29094
|
var MysqlServer = class extends DatabaseServer {
|
|
28706
29095
|
id = "mysql";
|
|
@@ -28718,8 +29107,8 @@ var MysqlServer = class extends DatabaseServer {
|
|
|
28718
29107
|
};
|
|
28719
29108
|
const version2 = await resolveCached("mariadb-version:" + series, async () => (await latest()).version);
|
|
28720
29109
|
const home = tool("mariadb", version2);
|
|
28721
|
-
const bin =
|
|
28722
|
-
if (!exists(
|
|
29110
|
+
const bin = path28.join(home, "bin");
|
|
29111
|
+
if (!exists(path28.join(bin, "mariadbd.exe"))) {
|
|
28723
29112
|
const { zip } = await latest();
|
|
28724
29113
|
log("Downloading MariaDB " + version2 + " (~90 MB once) ...");
|
|
28725
29114
|
await downloader.archive(zip.file_download_url.replace(/^http:/, "https:"), home, {
|
|
@@ -28732,13 +29121,13 @@ var MysqlServer = class extends DatabaseServer {
|
|
|
28732
29121
|
const data = dataFor("mariadb");
|
|
28733
29122
|
await createOnce(data, "mysql", async () => {
|
|
28734
29123
|
log("Creating the MariaDB database (first start) ...");
|
|
28735
|
-
await execAsync(
|
|
29124
|
+
await execAsync(path28.join(bin, "mariadb-install-db.exe"), ["--datadir=" + data, "--port=" + plan2.port], {
|
|
28736
29125
|
stdio: "ignore"
|
|
28737
29126
|
});
|
|
28738
29127
|
});
|
|
28739
29128
|
await startServer(
|
|
28740
29129
|
"mysql",
|
|
28741
|
-
|
|
29130
|
+
path28.join(bin, "mariadbd.exe"),
|
|
28742
29131
|
["--datadir=" + data, "--port=" + plan2.port, "--bind-address=127.0.0.1", "--console"],
|
|
28743
29132
|
plan2.port
|
|
28744
29133
|
);
|
|
@@ -28752,7 +29141,7 @@ var MysqlServer = class extends DatabaseServer {
|
|
|
28752
29141
|
|
|
28753
29142
|
// src/guest/databases/postgres.ts
|
|
28754
29143
|
import fs24 from "node:fs";
|
|
28755
|
-
import
|
|
29144
|
+
import path29 from "node:path";
|
|
28756
29145
|
function postgresData(version2) {
|
|
28757
29146
|
return dataFor("postgres-" + version2.split(".")[0]);
|
|
28758
29147
|
}
|
|
@@ -28767,8 +29156,8 @@ var PostgresServer = class extends DatabaseServer {
|
|
|
28767
29156
|
return hit ? hit.major + "." + hit.latestMinor : Promise.reject(new Error("No supported PostgreSQL " + plan2.version));
|
|
28768
29157
|
});
|
|
28769
29158
|
const home = tool("postgres", exact);
|
|
28770
|
-
const bin =
|
|
28771
|
-
if (!exists(
|
|
29159
|
+
const bin = path29.join(home, "bin");
|
|
29160
|
+
if (!exists(path29.join(bin, "pg_ctl.exe"))) {
|
|
28772
29161
|
log("Downloading PostgreSQL " + exact + " (~330 MB once) ...");
|
|
28773
29162
|
await downloader.archive(
|
|
28774
29163
|
"https://get.enterprisedb.com/postgresql/postgresql-" + exact + "-1-windows-x64-binaries.zip",
|
|
@@ -28785,7 +29174,7 @@ var PostgresServer = class extends DatabaseServer {
|
|
|
28785
29174
|
await createOnce(data, "PG_VERSION", async () => {
|
|
28786
29175
|
log("Creating the PostgreSQL database (first start) ...");
|
|
28787
29176
|
await execAsync(
|
|
28788
|
-
|
|
29177
|
+
path29.join(bin, "initdb.exe"),
|
|
28789
29178
|
["-D", data, "-U", "postgres", "-A", "trust", "-E", "UTF8", "--locale=C"],
|
|
28790
29179
|
{ stdio: "ignore" }
|
|
28791
29180
|
);
|
|
@@ -28794,7 +29183,7 @@ var PostgresServer = class extends DatabaseServer {
|
|
|
28794
29183
|
throw new Error("port " + plan2.port + " is already in use (change databases.postgres.port)");
|
|
28795
29184
|
await clearStaleLocks(data, ["postmaster.pid"], plan2.port);
|
|
28796
29185
|
await execAsync(
|
|
28797
|
-
|
|
29186
|
+
path29.join(bin, "pg_ctl.exe"),
|
|
28798
29187
|
[
|
|
28799
29188
|
"start",
|
|
28800
29189
|
"-D",
|
|
@@ -28803,7 +29192,7 @@ var PostgresServer = class extends DatabaseServer {
|
|
|
28803
29192
|
"-t",
|
|
28804
29193
|
"60",
|
|
28805
29194
|
"-l",
|
|
28806
|
-
|
|
29195
|
+
path29.join(logsDir, "postgres.log"),
|
|
28807
29196
|
"-o",
|
|
28808
29197
|
"-p " + plan2.port + " -c listen_addresses=localhost"
|
|
28809
29198
|
],
|
|
@@ -28820,8 +29209,8 @@ var PostgresServer = class extends DatabaseServer {
|
|
|
28820
29209
|
if (exists(tool("postgres"))) {
|
|
28821
29210
|
for (const version2 of fs24.readdirSync(tool("postgres"))) {
|
|
28822
29211
|
const data = postgresData(version2);
|
|
28823
|
-
const pgCtl =
|
|
28824
|
-
if (exists(
|
|
29212
|
+
const pgCtl = path29.join(tool("postgres", version2), "bin", "pg_ctl.exe");
|
|
29213
|
+
if (exists(path29.join(data, "postmaster.pid")) && exists(pgCtl))
|
|
28825
29214
|
await execAsync(pgCtl, ["stop", "-D", data, "-m", "fast", "-w"], { stdio: "ignore" });
|
|
28826
29215
|
}
|
|
28827
29216
|
}
|
|
@@ -28830,12 +29219,12 @@ var PostgresServer = class extends DatabaseServer {
|
|
|
28830
29219
|
};
|
|
28831
29220
|
|
|
28832
29221
|
// src/guest/databases/redis.ts
|
|
28833
|
-
import
|
|
29222
|
+
import path30 from "node:path";
|
|
28834
29223
|
var RedisServer = class extends DatabaseServer {
|
|
28835
29224
|
id = "redis";
|
|
28836
29225
|
async start(env, plan2) {
|
|
28837
29226
|
const home = tool("redis");
|
|
28838
|
-
if (!exists(
|
|
29227
|
+
if (!exists(path30.join(home, "redis-server.exe"))) {
|
|
28839
29228
|
await installFromGithub("redis-windows/redis-windows", /^Redis-[\d.]+-Windows-x64-msys2\.zip$/, {
|
|
28840
29229
|
dest: home,
|
|
28841
29230
|
what: (a) => "Redis (" + a.name + ", ~10 MB once)",
|
|
@@ -28845,7 +29234,7 @@ var RedisServer = class extends DatabaseServer {
|
|
|
28845
29234
|
const data = mkdirp(dataFor("redis"));
|
|
28846
29235
|
await startServer(
|
|
28847
29236
|
"redis",
|
|
28848
|
-
|
|
29237
|
+
path30.join(home, "redis-server.exe"),
|
|
28849
29238
|
["--port", String(plan2.port), "--bind", "127.0.0.1", "--dir", data.replace(/\\/g, "/"), "--appendonly", "yes"],
|
|
28850
29239
|
plan2.port
|
|
28851
29240
|
);
|
|
@@ -28884,15 +29273,15 @@ async function setupDatabase(env, plan2) {
|
|
|
28884
29273
|
|
|
28885
29274
|
// src/guest/toolchains/tools/git.ts
|
|
28886
29275
|
import fs26 from "node:fs";
|
|
28887
|
-
import
|
|
29276
|
+
import path32 from "node:path";
|
|
28888
29277
|
|
|
28889
29278
|
// src/guest/runtime/csc.ts
|
|
28890
29279
|
import fs25 from "node:fs";
|
|
28891
29280
|
import os6 from "node:os";
|
|
28892
|
-
import
|
|
29281
|
+
import path31 from "node:path";
|
|
28893
29282
|
import crypto3 from "node:crypto";
|
|
28894
29283
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
28895
|
-
var CSC =
|
|
29284
|
+
var CSC = path31.join(process.env.WINDIR ?? "C:\\Windows", "Microsoft.NET", "Framework64", "v4.0.30319", "csc.exe");
|
|
28896
29285
|
var SOURCES = {
|
|
28897
29286
|
ptyhost: "PtyHost.cs",
|
|
28898
29287
|
gitshim: "GitShim.cs",
|
|
@@ -28904,17 +29293,17 @@ var SOURCES = {
|
|
|
28904
29293
|
memgov: "MemGov.cs"
|
|
28905
29294
|
};
|
|
28906
29295
|
function sourceOf(name) {
|
|
28907
|
-
return
|
|
29296
|
+
return path31.join(launchDir, "sandbox", "csharp", SOURCES[name]);
|
|
28908
29297
|
}
|
|
28909
29298
|
function sourceHash(name) {
|
|
28910
29299
|
return crypto3.createHash("sha256").update(fs25.readFileSync(sourceOf(name))).digest("hex").slice(0, 12);
|
|
28911
29300
|
}
|
|
28912
29301
|
function ensureCompiled(name) {
|
|
28913
|
-
const exe =
|
|
29302
|
+
const exe = path31.join(os6.tmpdir(), "agent-sandbox", name + "-" + sourceHash(name) + ".exe");
|
|
28914
29303
|
if (exists(exe)) return exe;
|
|
28915
29304
|
if (!exists(CSC))
|
|
28916
29305
|
throw new Error("The .NET Framework C# compiler was not found at " + CSC + " (it ships with Windows 10/11).");
|
|
28917
|
-
mkdirp(
|
|
29306
|
+
mkdirp(path31.dirname(exe));
|
|
28918
29307
|
const result = spawnSync3(CSC, ["/nologo", "/optimize", "/target:exe", "/out:" + exe, sourceOf(name)], {
|
|
28919
29308
|
encoding: "utf8",
|
|
28920
29309
|
windowsHide: true
|
|
@@ -28953,18 +29342,18 @@ var installPortableGit = async (root) => {
|
|
|
28953
29342
|
};
|
|
28954
29343
|
var installGuard = (env, access, realGit) => {
|
|
28955
29344
|
const dir = mkdirp(tool("gitguard"));
|
|
28956
|
-
const guard =
|
|
28957
|
-
if (duringSession() && (exists(
|
|
29345
|
+
const guard = path32.join(launchDir, "runtime", "gitguard.js");
|
|
29346
|
+
if (duringSession() && (exists(path32.join(dir, "git.exe")) || exists(path32.join(dir, "git.cmd")))) {
|
|
28958
29347
|
} else
|
|
28959
29348
|
try {
|
|
28960
|
-
fs26.copyFileSync(ensureCompiled("gitshim"),
|
|
28961
|
-
fs26.rmSync(
|
|
29349
|
+
fs26.copyFileSync(ensureCompiled("gitshim"), path32.join(dir, "git.exe"));
|
|
29350
|
+
fs26.rmSync(path32.join(dir, "git.cmd"), { force: true });
|
|
28962
29351
|
} catch (e) {
|
|
28963
29352
|
warn("git guard: falling back to git.cmd (" + errMsg(e) + ")");
|
|
28964
|
-
fs26.writeFileSync(
|
|
29353
|
+
fs26.writeFileSync(path32.join(dir, "git.cmd"), '@"' + process.execPath + '" "' + guard + '" %*\r\n');
|
|
28965
29354
|
}
|
|
28966
29355
|
fs26.writeFileSync(
|
|
28967
|
-
|
|
29356
|
+
path32.join(dir, "bashenv.sh"),
|
|
28968
29357
|
'git() { "' + posix(process.execPath) + '" "' + posix(guard) + '" "$@"; }\nexport -f git\n'
|
|
28969
29358
|
);
|
|
28970
29359
|
env.prepend.unshift(dir);
|
|
@@ -28973,13 +29362,13 @@ var installGuard = (env, access, realGit) => {
|
|
|
28973
29362
|
AGENT_REAL_GIT: access === "readonly" ? realGit : "",
|
|
28974
29363
|
AGENT_GUARD_NODE: process.execPath,
|
|
28975
29364
|
AGENT_GUARD_SCRIPT: guard,
|
|
28976
|
-
BASH_ENV: posix(
|
|
29365
|
+
BASH_ENV: posix(path32.join(dir, "bashenv.sh"))
|
|
28977
29366
|
});
|
|
28978
29367
|
if (access === "readonly") {
|
|
28979
|
-
const hooks = mkdirp(
|
|
29368
|
+
const hooks = mkdirp(path32.join(dir, "hooks"));
|
|
28980
29369
|
for (const hook of BLOCKED_HOOKS)
|
|
28981
29370
|
fs26.writeFileSync(
|
|
28982
|
-
|
|
29371
|
+
path32.join(hooks, hook),
|
|
28983
29372
|
'#!/bin/sh\necho "git is read-only in this sandbox: ' + hook + ' refused." >&2\nexit 1\n'
|
|
28984
29373
|
);
|
|
28985
29374
|
Object.assign(env.vars, {
|
|
@@ -28988,12 +29377,12 @@ var installGuard = (env, access, realGit) => {
|
|
|
28988
29377
|
GIT_CONFIG_VALUE_0: posix(hooks)
|
|
28989
29378
|
});
|
|
28990
29379
|
} else {
|
|
28991
|
-
env.vars.GIT_DIR =
|
|
29380
|
+
env.vars.GIT_DIR = path32.join(dataDir, "git-disabled");
|
|
28992
29381
|
}
|
|
28993
29382
|
};
|
|
28994
29383
|
var pointAtOwnCertificates = (root) => {
|
|
28995
|
-
const config2 =
|
|
28996
|
-
const bundle =
|
|
29384
|
+
const config2 = path32.join(root, "etc", "gitconfig");
|
|
29385
|
+
const bundle = path32.join(root, "mingw64", "etc", "ssl", "certs", "ca-bundle.crt");
|
|
28997
29386
|
if (!exists(config2) || !exists(bundle)) return;
|
|
28998
29387
|
const text = fs26.readFileSync(config2, "utf8");
|
|
28999
29388
|
const fixed = text.replace(/^(\s*sslCAInfo\s*=\s*).*$/gim, (_m, key) => key + posix(bundle));
|
|
@@ -29001,9 +29390,9 @@ var pointAtOwnCertificates = (root) => {
|
|
|
29001
29390
|
};
|
|
29002
29391
|
async function setupGit(env, hostCopy, refresh, access) {
|
|
29003
29392
|
const root = tool("git");
|
|
29004
|
-
const bash =
|
|
29005
|
-
const gitExe =
|
|
29006
|
-
const hostGit =
|
|
29393
|
+
const bash = path32.join(root, "bin", "bash.exe");
|
|
29394
|
+
const gitExe = path32.join(root, "cmd", "git.exe");
|
|
29395
|
+
const hostGit = path32.join(hostToolsDir, "git");
|
|
29007
29396
|
if (exists(root) && !exists(bash)) {
|
|
29008
29397
|
log("Replacing the old MinGit (no bash) with full Git for Windows.");
|
|
29009
29398
|
safeRemove(root, toolsDir);
|
|
@@ -29017,11 +29406,11 @@ async function setupGit(env, hostCopy, refresh, access) {
|
|
|
29017
29406
|
}
|
|
29018
29407
|
const work = stagingFolder(root);
|
|
29019
29408
|
try {
|
|
29020
|
-
if (hostCopy && exists(
|
|
29409
|
+
if (hostCopy && exists(path32.join(hostGit, "bin", "bash.exe"))) {
|
|
29021
29410
|
log("Copying Git for Windows from this PC ...");
|
|
29022
29411
|
robocopy(hostGit, work);
|
|
29023
29412
|
} else await installPortableGit(work);
|
|
29024
|
-
if (!exists(
|
|
29413
|
+
if (!exists(path32.join(work, "bin", "bash.exe"))) throw new Error("bash.exe missing after installing Git");
|
|
29025
29414
|
moveIntoPlace(work, root);
|
|
29026
29415
|
} finally {
|
|
29027
29416
|
safeRemove(work, toolsDir);
|
|
@@ -29030,10 +29419,10 @@ async function setupGit(env, hostCopy, refresh, access) {
|
|
|
29030
29419
|
if (!exists(bash)) throw new Error("bash.exe missing after installing Git");
|
|
29031
29420
|
pointAtOwnCertificates(root);
|
|
29032
29421
|
env.vars.CLAUDE_CODE_GIT_BASH_PATH = bash;
|
|
29033
|
-
env.append.push(
|
|
29422
|
+
env.append.push(path32.join(root, "usr", "bin"));
|
|
29034
29423
|
const version2 = execOutput(gitExe, ["--version"]).replace(/^git version /, "");
|
|
29035
29424
|
if (access === "full") {
|
|
29036
|
-
env.prepend.push(
|
|
29425
|
+
env.prepend.push(path32.join(root, "cmd"));
|
|
29037
29426
|
env.summary.push("git: " + version2);
|
|
29038
29427
|
return;
|
|
29039
29428
|
}
|
|
@@ -29045,7 +29434,7 @@ async function setupGit(env, hostCopy, refresh, access) {
|
|
|
29045
29434
|
|
|
29046
29435
|
// src/guest/toolchains/languages/go.ts
|
|
29047
29436
|
import fs27 from "node:fs";
|
|
29048
|
-
import
|
|
29437
|
+
import path33 from "node:path";
|
|
29049
29438
|
|
|
29050
29439
|
// src/guest/toolchains/package-ledger.ts
|
|
29051
29440
|
var LedgerSchema = external_exports.record(external_exports.string(), external_exports.string());
|
|
@@ -29099,7 +29488,7 @@ async function setupGo(env, config2) {
|
|
|
29099
29488
|
}
|
|
29100
29489
|
const version2 = await resolveCached("go:" + config2.version, async () => (await findRelease(config2.version)).version);
|
|
29101
29490
|
const root = tool("go", version2);
|
|
29102
|
-
if (!exists(
|
|
29491
|
+
if (!exists(path33.join(root, "bin", "go.exe"))) {
|
|
29103
29492
|
const goArch = arch === "arm64" ? "arm64" : "amd64";
|
|
29104
29493
|
const file3 = (await findRelease(version2)).files.find(
|
|
29105
29494
|
(f) => f.os === "windows" && f.arch === goArch && f.kind === "archive"
|
|
@@ -29116,16 +29505,16 @@ async function setupGo(env, config2) {
|
|
|
29116
29505
|
const vars = {
|
|
29117
29506
|
GOROOT: root,
|
|
29118
29507
|
GOPATH,
|
|
29119
|
-
GOBIN:
|
|
29120
|
-
GOMODCACHE:
|
|
29508
|
+
GOBIN: path33.join(GOPATH, "bin"),
|
|
29509
|
+
GOMODCACHE: path33.join(GOPATH, "pkg", "mod"),
|
|
29121
29510
|
GOCACHE: tool("go-cache"),
|
|
29122
29511
|
GOTOOLCHAIN: "auto",
|
|
29123
29512
|
GOTELEMETRY: "off"
|
|
29124
29513
|
};
|
|
29125
29514
|
fs27.mkdirSync(vars.GOBIN, { recursive: true });
|
|
29126
29515
|
Object.assign(env.vars, vars);
|
|
29127
|
-
env.prepend.push(
|
|
29128
|
-
const go =
|
|
29516
|
+
env.prepend.push(path33.join(root, "bin"), vars.GOBIN);
|
|
29517
|
+
const go = path33.join(root, "bin", "go.exe");
|
|
29129
29518
|
env.summary.push("go: " + versionOf(go, ["version"]));
|
|
29130
29519
|
await installOnce(
|
|
29131
29520
|
env,
|
|
@@ -29183,77 +29572,6 @@ function decideCli(settings, ctx) {
|
|
|
29183
29572
|
return Object.fromEntries(CLI_NAMES.map((name) => [name, decide(name)]));
|
|
29184
29573
|
}
|
|
29185
29574
|
|
|
29186
|
-
// src/guest/toolchains/runtimes.ts
|
|
29187
|
-
import path33 from "node:path";
|
|
29188
|
-
async function setupSingleExe(env, name, repo, pattern, exeName, dir, options = {}) {
|
|
29189
|
-
if (dryRun) {
|
|
29190
|
-
log("(dry run) would provision " + name);
|
|
29191
|
-
return;
|
|
29192
|
-
}
|
|
29193
|
-
const bin = options.subdir ? path33.join(dir, options.subdir) : dir;
|
|
29194
|
-
const exe = path33.join(bin, exeName);
|
|
29195
|
-
if (!exists(exe) || options.refresh) {
|
|
29196
|
-
const size = options.size ? ", ~" + options.size : "";
|
|
29197
|
-
await installFromGithub(repo, pattern, {
|
|
29198
|
-
dest: dir,
|
|
29199
|
-
what: (a) => name + " (" + a.name + size + " once)",
|
|
29200
|
-
...options.subdir ? {} : { locate: exeName }
|
|
29201
|
-
});
|
|
29202
|
-
}
|
|
29203
|
-
if (!exists(exe)) throw new Error(exeName + " missing after installing " + name);
|
|
29204
|
-
env.prepend.push(bin);
|
|
29205
|
-
env.summary.push(name + ": " + versionOf(exe, options.versionArgs) + (options.note ?? ""));
|
|
29206
|
-
}
|
|
29207
|
-
async function setupBun(env) {
|
|
29208
|
-
await setupSingleExe(
|
|
29209
|
-
env,
|
|
29210
|
-
"bun",
|
|
29211
|
-
"oven-sh/bun",
|
|
29212
|
-
arch === "arm64" ? /^bun-windows-aarch64\.zip$/ : /^bun-windows-x64\.zip$/,
|
|
29213
|
-
"bun.exe",
|
|
29214
|
-
tool("bun", "bin"),
|
|
29215
|
-
{ size: "35 MB" }
|
|
29216
|
-
);
|
|
29217
|
-
Object.assign(env.vars, {
|
|
29218
|
-
BUN_INSTALL: tool("bun"),
|
|
29219
|
-
BUN_INSTALL_CACHE_DIR: path33.join(localDir, "bun-cache"),
|
|
29220
|
-
BUN_TMPDIR: path33.join(localDir, "bun-tmp")
|
|
29221
|
-
});
|
|
29222
|
-
}
|
|
29223
|
-
async function setupDeno(env) {
|
|
29224
|
-
await setupSingleExe(
|
|
29225
|
-
env,
|
|
29226
|
-
"deno",
|
|
29227
|
-
"denoland/deno",
|
|
29228
|
-
arch === "arm64" ? /^deno-aarch64-pc-windows-msvc[.]zip$/ : /^deno-x86_64-pc-windows-msvc[.]zip$/,
|
|
29229
|
-
"deno.exe",
|
|
29230
|
-
tool("deno", "bin"),
|
|
29231
|
-
{ size: "40 MB" }
|
|
29232
|
-
);
|
|
29233
|
-
Object.assign(env.vars, { DENO_DIR: tool("deno-cache"), DENO_INSTALL_ROOT: tool("deno"), DENO_NO_UPDATE_CHECK: "1" });
|
|
29234
|
-
}
|
|
29235
|
-
function uvVars() {
|
|
29236
|
-
return {
|
|
29237
|
-
UV_CACHE_DIR: tool("uv-cache"),
|
|
29238
|
-
UV_PYTHON_INSTALL_DIR: tool("uv-python"),
|
|
29239
|
-
UV_TOOL_DIR: tool("uv-tools"),
|
|
29240
|
-
UV_TOOL_BIN_DIR: tool("uv-bin")
|
|
29241
|
-
};
|
|
29242
|
-
}
|
|
29243
|
-
async function setupUv(env) {
|
|
29244
|
-
await setupSingleExe(
|
|
29245
|
-
env,
|
|
29246
|
-
"uv",
|
|
29247
|
-
"astral-sh/uv",
|
|
29248
|
-
arch === "arm64" ? /^uv-aarch64-pc-windows-msvc\.zip$/ : /^uv-x86_64-pc-windows-msvc\.zip$/,
|
|
29249
|
-
"uv.exe",
|
|
29250
|
-
tool("uv"),
|
|
29251
|
-
{ size: "20 MB" }
|
|
29252
|
-
);
|
|
29253
|
-
Object.assign(env.vars, uvVars());
|
|
29254
|
-
env.prepend.push(mkdirp(tool("uv-bin")));
|
|
29255
|
-
}
|
|
29256
|
-
|
|
29257
29575
|
// src/guest/toolchains/tools/cli.ts
|
|
29258
29576
|
function ghConfigDir() {
|
|
29259
29577
|
return path34.join(stateDir, "gh");
|
|
@@ -31286,12 +31604,12 @@ function parseTree(text, errors = [], options = ParseOptions.DEFAULT) {
|
|
|
31286
31604
|
}
|
|
31287
31605
|
return result;
|
|
31288
31606
|
}
|
|
31289
|
-
function findNodeAtLocation(root,
|
|
31607
|
+
function findNodeAtLocation(root, path77) {
|
|
31290
31608
|
if (!root) {
|
|
31291
31609
|
return void 0;
|
|
31292
31610
|
}
|
|
31293
31611
|
let node2 = root;
|
|
31294
|
-
for (let segment of
|
|
31612
|
+
for (let segment of path77) {
|
|
31295
31613
|
if (typeof segment === "string") {
|
|
31296
31614
|
if (node2.type !== "object" || !Array.isArray(node2.children)) {
|
|
31297
31615
|
return void 0;
|
|
@@ -31645,14 +31963,14 @@ function getNodeType(value) {
|
|
|
31645
31963
|
|
|
31646
31964
|
// node_modules/jsonc-parser/lib/esm/impl/edit.js
|
|
31647
31965
|
function setProperty(text, originalPath, value, options) {
|
|
31648
|
-
const
|
|
31966
|
+
const path77 = originalPath.slice();
|
|
31649
31967
|
const errors = [];
|
|
31650
31968
|
const root = parseTree(text, errors);
|
|
31651
31969
|
let parent = void 0;
|
|
31652
31970
|
let lastSegment = void 0;
|
|
31653
|
-
while (
|
|
31654
|
-
lastSegment =
|
|
31655
|
-
parent = findNodeAtLocation(root,
|
|
31971
|
+
while (path77.length > 0) {
|
|
31972
|
+
lastSegment = path77.pop();
|
|
31973
|
+
parent = findNodeAtLocation(root, path77);
|
|
31656
31974
|
if (parent === void 0 && value !== void 0) {
|
|
31657
31975
|
if (typeof lastSegment === "string") {
|
|
31658
31976
|
value = { [lastSegment]: value };
|
|
@@ -31838,8 +32156,8 @@ var ParseErrorCode;
|
|
|
31838
32156
|
ParseErrorCode2[ParseErrorCode2["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
|
|
31839
32157
|
ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
31840
32158
|
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
31841
|
-
function modify(text,
|
|
31842
|
-
return setProperty(text,
|
|
32159
|
+
function modify(text, path77, value, options) {
|
|
32160
|
+
return setProperty(text, path77, value, options);
|
|
31843
32161
|
}
|
|
31844
32162
|
function applyEdits(text, edits) {
|
|
31845
32163
|
let sortedEdits = edits.slice(0).sort((a, b) => {
|
|
@@ -32232,7 +32550,12 @@ function plan(config2, versions, o) {
|
|
|
32232
32550
|
},
|
|
32233
32551
|
{ name: "Deno", enabled: wanted(config2.deno.enabled, "deno"), install: (env) => setupDeno(env) },
|
|
32234
32552
|
{ name: "Bun", enabled: wanted(config2.bun.enabled, "bun"), install: (env) => setupBun(env) },
|
|
32235
|
-
|
|
32553
|
+
// Headroom (an agent add-on) installs with uv: the uv step runs for it too, before the apps.
|
|
32554
|
+
{
|
|
32555
|
+
name: "uv",
|
|
32556
|
+
enabled: wanted(config2.uv.enabled, "uv") || appsNeedUv(o.apps),
|
|
32557
|
+
install: (env) => setupUv(env)
|
|
32558
|
+
},
|
|
32236
32559
|
{ name: "PowerShell 7", enabled: wanted(config2.pwsh.enabled, "pwsh"), install: (env) => setupPwsh(env, o.refresh) },
|
|
32237
32560
|
// The openssl tool comes from Git's install: after Git.
|
|
32238
32561
|
{
|
|
@@ -32258,7 +32581,7 @@ function plan(config2, versions, o) {
|
|
|
32258
32581
|
name: "Apps",
|
|
32259
32582
|
enabled: apps,
|
|
32260
32583
|
shared: true,
|
|
32261
|
-
after: ["Mesa 3D", "Visual C++ runtime"],
|
|
32584
|
+
after: ["Mesa 3D", "Visual C++ runtime", "uv"],
|
|
32262
32585
|
install: (env) => setupApps(env, o.apps, { gitAccess: o.gitAccess, refresh: o.refresh })
|
|
32263
32586
|
},
|
|
32264
32587
|
{
|
|
@@ -32399,6 +32722,7 @@ async function setupToolchains(config2, versions, options, run3 = {}) {
|
|
|
32399
32722
|
env.summary.push(...part.summary);
|
|
32400
32723
|
}
|
|
32401
32724
|
Object.assign(env.vars, config2.environment);
|
|
32725
|
+
Object.assign(env.vars, envs.get("Git")?.vars);
|
|
32402
32726
|
log("Set up " + steps.length + " toolchains and databases.");
|
|
32403
32727
|
return env;
|
|
32404
32728
|
}
|
|
@@ -33496,42 +33820,124 @@ function gitDenyRules(access) {
|
|
|
33496
33820
|
function managedSettingsFile() {
|
|
33497
33821
|
return path63.join(path63.dirname(managedClaudeMd()), "managed-settings.json");
|
|
33498
33822
|
}
|
|
33499
|
-
function writeManagedSettings2(access) {
|
|
33823
|
+
function writeManagedSettings2(access, headroom = null) {
|
|
33500
33824
|
const file3 = managedSettingsFile();
|
|
33501
|
-
const
|
|
33502
|
-
|
|
33825
|
+
const rtk = installedRtk();
|
|
33826
|
+
const settings = claudeManagedSettings(gitDenyRules(access), rtk, headroom);
|
|
33827
|
+
if (!settings) {
|
|
33503
33828
|
fs50.rmSync(file3, { force: true });
|
|
33504
33829
|
return;
|
|
33505
33830
|
}
|
|
33506
33831
|
fs50.mkdirSync(path63.dirname(file3), { recursive: true });
|
|
33507
|
-
fs50.writeFileSync(file3, JSON.stringify(
|
|
33832
|
+
fs50.writeFileSync(file3, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
33833
|
+
if (rtk) log("rtk: Claude Code's Bash commands go through it (hook in " + file3 + ")");
|
|
33508
33834
|
}
|
|
33509
33835
|
|
|
33510
|
-
// src/guest/setup/
|
|
33836
|
+
// src/guest/setup/addon-mcp.ts
|
|
33511
33837
|
import fs51 from "node:fs";
|
|
33512
|
-
import os10 from "node:os";
|
|
33513
33838
|
import path64 from "node:path";
|
|
33839
|
+
var ADDON_MCP_NAMES = APPS.flatMap((a) => a.mcp ? [a.mcp.name] : []);
|
|
33840
|
+
function writeAddonMcpServers() {
|
|
33841
|
+
const servers = {};
|
|
33842
|
+
for (const { id, folder } of installedMcpAddons()) {
|
|
33843
|
+
const mcp = APPS.find((a) => a.id === id)?.mcp;
|
|
33844
|
+
if (mcp) servers[mcp.name] = addonMcpServer(folder, mcp);
|
|
33845
|
+
}
|
|
33846
|
+
const file3 = path64.join(claudeDir, ".claude.json");
|
|
33847
|
+
let state = {};
|
|
33848
|
+
if (fs51.existsSync(file3)) {
|
|
33849
|
+
try {
|
|
33850
|
+
const text = fs51.readFileSync(file3, "utf8");
|
|
33851
|
+
state = JSON.parse(text.charCodeAt(0) === 65279 ? text.slice(1) : text);
|
|
33852
|
+
} catch {
|
|
33853
|
+
warn("Claude Code MCP servers from Apps: " + file3 + " is not valid JSON, left as it is");
|
|
33854
|
+
return [];
|
|
33855
|
+
}
|
|
33856
|
+
} else if (!Object.keys(servers).length) return [];
|
|
33857
|
+
if (typeof state !== "object" || state === null || Array.isArray(state)) return [];
|
|
33858
|
+
const current = state.mcpServers;
|
|
33859
|
+
const before = current && typeof current === "object" && !Array.isArray(current) ? current : {};
|
|
33860
|
+
const after = withAddonMcpServers(before, servers, ADDON_MCP_NAMES);
|
|
33861
|
+
if (JSON.stringify(before) !== JSON.stringify(after)) {
|
|
33862
|
+
fs51.mkdirSync(claudeDir, { recursive: true });
|
|
33863
|
+
writeJsonAtomic(file3, { ...state, mcpServers: after });
|
|
33864
|
+
}
|
|
33865
|
+
const names = Object.keys(servers);
|
|
33866
|
+
if (names.length) log("Claude Code MCP servers from Apps: " + names.join(", "));
|
|
33867
|
+
return names;
|
|
33868
|
+
}
|
|
33869
|
+
|
|
33870
|
+
// src/guest/setup/headroom.ts
|
|
33871
|
+
import fs52 from "node:fs";
|
|
33872
|
+
import http from "node:http";
|
|
33873
|
+
import path65 from "node:path";
|
|
33874
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
33875
|
+
var HEADROOM_LOG = path65.join(logsDir, "headroom.log");
|
|
33876
|
+
function answersAsHeadroom(port) {
|
|
33877
|
+
return new Promise((resolve2) => {
|
|
33878
|
+
const req = http.get({ host: "127.0.0.1", port, path: "/livez", timeout: 3e3 }, (res) => {
|
|
33879
|
+
let body = "";
|
|
33880
|
+
res.setEncoding("utf8");
|
|
33881
|
+
res.on("data", (chunk) => {
|
|
33882
|
+
if (body.length < 4096) body += chunk;
|
|
33883
|
+
});
|
|
33884
|
+
res.on("end", () => resolve2(res.statusCode === 200 && /"service"\s*:\s*"headroom-proxy"/.test(body)));
|
|
33885
|
+
});
|
|
33886
|
+
req.on("timeout", () => req.destroy());
|
|
33887
|
+
req.on("error", () => resolve2(false));
|
|
33888
|
+
});
|
|
33889
|
+
}
|
|
33890
|
+
async function startHeadroom(env) {
|
|
33891
|
+
const exe = installedAddon("headroom");
|
|
33892
|
+
if (!exe) return null;
|
|
33893
|
+
if (env.ANTHROPIC_BASE_URL) {
|
|
33894
|
+
log("Headroom: not used, ANTHROPIC_BASE_URL is set in the agent environment (" + env.ANTHROPIC_BASE_URL + ")");
|
|
33895
|
+
return null;
|
|
33896
|
+
}
|
|
33897
|
+
const port = HEADROOM_PORT;
|
|
33898
|
+
if (!await portOpen(port)) {
|
|
33899
|
+
const out = fs52.openSync(HEADROOM_LOG, "a");
|
|
33900
|
+
spawn7(exe, headroomArgs(port), {
|
|
33901
|
+
detached: true,
|
|
33902
|
+
stdio: ["ignore", out, out],
|
|
33903
|
+
windowsHide: true,
|
|
33904
|
+
env: headroomEnv(env)
|
|
33905
|
+
}).unref();
|
|
33906
|
+
fs52.closeSync(out);
|
|
33907
|
+
if (!await waitForPort(port, 90))
|
|
33908
|
+
throw new Error("the Headroom proxy did not start on port " + port + "; see " + HEADROOM_LOG);
|
|
33909
|
+
}
|
|
33910
|
+
if (!await answersAsHeadroom(port))
|
|
33911
|
+
throw new Error("port " + port + " is taken by another program; Claude Code talks to the API directly");
|
|
33912
|
+
log("Headroom: Claude Code reaches the API through " + headroomUrl(port) + " (log: " + HEADROOM_LOG + ")");
|
|
33913
|
+
return headroomUrl(port);
|
|
33914
|
+
}
|
|
33915
|
+
|
|
33916
|
+
// src/guest/setup/desktop.ts
|
|
33917
|
+
import fs53 from "node:fs";
|
|
33918
|
+
import os10 from "node:os";
|
|
33919
|
+
import path66 from "node:path";
|
|
33514
33920
|
function applyPersonalization() {
|
|
33515
|
-
const dir =
|
|
33921
|
+
const dir = path66.join(launchDir, "personalize");
|
|
33516
33922
|
if (!session.personalization || !exists(dir) || dryRun || !isWin) return;
|
|
33517
|
-
exec(SYSTEM.reg(), ["import",
|
|
33518
|
-
const wallpaper =
|
|
33519
|
-
const local = wallpaper ?
|
|
33520
|
-
if (wallpaper && local)
|
|
33923
|
+
exec(SYSTEM.reg(), ["import", path66.join(dir, "personalize.reg")], { stdio: "ignore" });
|
|
33924
|
+
const wallpaper = fs53.readdirSync(dir).find((f) => f.startsWith("wallpaper"));
|
|
33925
|
+
const local = wallpaper ? path66.join(mkdirp(path66.join(os10.homedir(), "Pictures")), wallpaper) : null;
|
|
33926
|
+
if (wallpaper && local) fs53.copyFileSync(path66.join(dir, wallpaper), local);
|
|
33521
33927
|
runScript("set-desktop.ps1", local ? ["-Wallpaper", local] : []);
|
|
33522
33928
|
log("Desktop personalisation applied from this PC.");
|
|
33523
33929
|
}
|
|
33524
33930
|
|
|
33525
33931
|
// src/guest/setup/git-identity.ts
|
|
33526
|
-
import
|
|
33932
|
+
import fs54 from "node:fs";
|
|
33527
33933
|
import os11 from "node:os";
|
|
33528
|
-
import
|
|
33934
|
+
import path67 from "node:path";
|
|
33529
33935
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
33530
33936
|
function setupGitConfig(env) {
|
|
33531
33937
|
if (dryRun) return;
|
|
33532
|
-
const source =
|
|
33533
|
-
if (exists(source))
|
|
33534
|
-
const git =
|
|
33938
|
+
const source = path67.join(launchDir, "home", ".gitconfig");
|
|
33939
|
+
if (exists(source)) fs54.copyFileSync(source, path67.join(os11.homedir(), ".gitconfig"));
|
|
33940
|
+
const git = path67.join(toolsDir, "git", "cmd", "git.exe");
|
|
33535
33941
|
if (!exists(git)) return;
|
|
33536
33942
|
const { GIT_DIR: _gitDir, ...rest } = env;
|
|
33537
33943
|
spawnSync7(git, ["config", "--global", "--add", "safe.directory", "*"], {
|
|
@@ -33544,7 +33950,7 @@ function setupGitConfig(env) {
|
|
|
33544
33950
|
}
|
|
33545
33951
|
|
|
33546
33952
|
// src/guest/setup/github-token.ts
|
|
33547
|
-
import
|
|
33953
|
+
import fs55 from "node:fs";
|
|
33548
33954
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
33549
33955
|
|
|
33550
33956
|
// src/shared/github/token.ts
|
|
@@ -33590,7 +33996,7 @@ function ghOutputText(text, token) {
|
|
|
33590
33996
|
var GH_TIMEOUT_MS = 6e4;
|
|
33591
33997
|
function prepareGithubFolder(token) {
|
|
33592
33998
|
const dir = deliveredGhConfigDir();
|
|
33593
|
-
|
|
33999
|
+
fs55.rmSync(dir, { recursive: true, force: true });
|
|
33594
34000
|
if (!token) return false;
|
|
33595
34001
|
mkdirp(dir);
|
|
33596
34002
|
return true;
|
|
@@ -33618,7 +34024,7 @@ function loginGithub(token, env) {
|
|
|
33618
34024
|
const gh2 = ghExePath();
|
|
33619
34025
|
const dir = deliveredGhConfigDir();
|
|
33620
34026
|
if (!exists(gh2) || env.GH_CONFIG_DIR !== dir) {
|
|
33621
|
-
|
|
34027
|
+
fs55.rmSync(dir, { recursive: true, force: true });
|
|
33622
34028
|
log("A GitHub token arrived, but gh is not set up in this sandbox (toolchains.cli.gh), so it is not used.");
|
|
33623
34029
|
return;
|
|
33624
34030
|
}
|
|
@@ -33626,7 +34032,7 @@ function loginGithub(token, env) {
|
|
|
33626
34032
|
runGh(ghLoginCommand(gh2, dir, token, env), token, "gh auth login");
|
|
33627
34033
|
runGh(ghSetupGitCommand(gh2, dir, env), token, "gh auth setup-git");
|
|
33628
34034
|
} catch (e) {
|
|
33629
|
-
|
|
34035
|
+
fs55.rmSync(dir, { recursive: true, force: true });
|
|
33630
34036
|
env.GH_CONFIG_DIR = mkdirp(ghConfigDir());
|
|
33631
34037
|
addMachineEnvironment({ GH_CONFIG_DIR: env.GH_CONFIG_DIR }, []);
|
|
33632
34038
|
throw e;
|
|
@@ -33640,35 +34046,35 @@ function ensurePtyHost() {
|
|
|
33640
34046
|
}
|
|
33641
34047
|
|
|
33642
34048
|
// src/guest/toolchains/leftovers.ts
|
|
33643
|
-
import
|
|
33644
|
-
import
|
|
34049
|
+
import fs56 from "node:fs";
|
|
34050
|
+
import path68 from "node:path";
|
|
33645
34051
|
var STAGING = /\.staging-[0-9a-f]+$/i;
|
|
33646
34052
|
var entries2 = (dir) => {
|
|
33647
34053
|
try {
|
|
33648
|
-
return
|
|
34054
|
+
return fs56.readdirSync(dir, { withFileTypes: true });
|
|
33649
34055
|
} catch {
|
|
33650
34056
|
return [];
|
|
33651
34057
|
}
|
|
33652
34058
|
};
|
|
33653
34059
|
function pruneToolLeftovers() {
|
|
33654
|
-
for (const legacy of ["ptyhost", "gitshim"]) safeRemove(
|
|
34060
|
+
for (const legacy of ["ptyhost", "gitshim"]) safeRemove(path68.join(toolsDir, legacy), toolsDir);
|
|
33655
34061
|
for (const top of entries2(toolsDir)) {
|
|
33656
|
-
const dir =
|
|
34062
|
+
const dir = path68.join(toolsDir, top.name);
|
|
33657
34063
|
if (STAGING.test(top.name)) safeRemove(dir, toolsDir);
|
|
33658
34064
|
else if (top.isDirectory())
|
|
33659
|
-
for (const sub of entries2(dir).filter((e) => STAGING.test(e.name))) safeRemove(
|
|
34065
|
+
for (const sub of entries2(dir).filter((e) => STAGING.test(e.name))) safeRemove(path68.join(dir, sub.name), dir);
|
|
33660
34066
|
}
|
|
33661
34067
|
}
|
|
33662
34068
|
|
|
33663
34069
|
// src/guest/audit/process-audit.ts
|
|
33664
|
-
import
|
|
34070
|
+
import path69 from "node:path";
|
|
33665
34071
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
33666
34072
|
var PROCESS_CREATION = "{0CCE922B-69AE-11D9-BED3-505054503030}";
|
|
33667
34073
|
var auditOn = () => Boolean(session.auditProcesses) && isWin && !dryRun;
|
|
33668
34074
|
function enableProcessAudit() {
|
|
33669
34075
|
if (!auditOn()) return;
|
|
33670
34076
|
spawnSync9(
|
|
33671
|
-
|
|
34077
|
+
path69.join(process.env.WINDIR ?? "C:\\Windows", "System32", "auditpol.exe"),
|
|
33672
34078
|
["/set", "/subcategory:" + PROCESS_CREATION, "/success:enable"],
|
|
33673
34079
|
{ windowsHide: true, stdio: "ignore" }
|
|
33674
34080
|
);
|
|
@@ -33692,10 +34098,10 @@ function enableProcessAudit() {
|
|
|
33692
34098
|
|
|
33693
34099
|
// src/guest/vpn/vpn.ts
|
|
33694
34100
|
import dns2 from "node:dns";
|
|
33695
|
-
import
|
|
34101
|
+
import fs60 from "node:fs";
|
|
33696
34102
|
import net3 from "node:net";
|
|
33697
34103
|
import os14 from "node:os";
|
|
33698
|
-
import
|
|
34104
|
+
import path73 from "node:path";
|
|
33699
34105
|
|
|
33700
34106
|
// src/shared/vpn/ovpn.ts
|
|
33701
34107
|
var PROGRAM_DIRECTIVES = [
|
|
@@ -34218,8 +34624,8 @@ function tunnelAddressFromLog(log2) {
|
|
|
34218
34624
|
|
|
34219
34625
|
// src/guest/vpn/openvpn.ts
|
|
34220
34626
|
import crypto4 from "node:crypto";
|
|
34221
|
-
import
|
|
34222
|
-
import
|
|
34627
|
+
import fs57 from "node:fs";
|
|
34628
|
+
import path70 from "node:path";
|
|
34223
34629
|
|
|
34224
34630
|
// src/shared/vpn/download.ts
|
|
34225
34631
|
var OPENVPN_MSI = {
|
|
@@ -34249,7 +34655,7 @@ var WIREGUARD_MSI = {
|
|
|
34249
34655
|
|
|
34250
34656
|
// src/guest/vpn/openvpn.ts
|
|
34251
34657
|
function openvpnExe(env = process.env) {
|
|
34252
|
-
return
|
|
34658
|
+
return path70.join(env.ProgramFiles ?? "C:\\Program Files", "OpenVPN", "bin", "openvpn.exe");
|
|
34253
34659
|
}
|
|
34254
34660
|
function openvpnDownload(arch2 = process.arch) {
|
|
34255
34661
|
const entry = arch2 === "arm64" ? OPENVPN_MSI.arm64 : OPENVPN_MSI.x64;
|
|
@@ -34260,20 +34666,20 @@ function repairServiceQueries() {
|
|
|
34260
34666
|
if (did === "removed") log("VPN: repaired the Windows service queries installers use (a Windows Sandbox gap).");
|
|
34261
34667
|
else if (did !== "absent" && did !== "kept") warn("VPN: could not check the Windows service queries installers use.");
|
|
34262
34668
|
}
|
|
34263
|
-
var hasHash = (file3, sha256) => crypto4.createHash("sha256").update(
|
|
34669
|
+
var hasHash = (file3, sha256) => crypto4.createHash("sha256").update(fs57.readFileSync(file3)).digest("hex") === sha256;
|
|
34264
34670
|
async function ensureOpenVpn() {
|
|
34265
34671
|
const exe = openvpnExe();
|
|
34266
34672
|
if (!isWin || dryRun) return exe;
|
|
34267
34673
|
if (exists(exe)) return exe;
|
|
34268
34674
|
const dl = openvpnDownload();
|
|
34269
|
-
const msi =
|
|
34675
|
+
const msi = path70.join(mkdirp(path70.join(toolsDir, "downloads")), dl.file);
|
|
34270
34676
|
if (!exists(msi) || !hasHash(msi, dl.sha256)) {
|
|
34271
34677
|
log("VPN: downloading OpenVPN " + OPENVPN_MSI.version + " (about 6 MB)");
|
|
34272
34678
|
await downloader.file(dl.url, msi, dl.sha256);
|
|
34273
34679
|
}
|
|
34274
34680
|
repairServiceQueries();
|
|
34275
34681
|
log("VPN: installing OpenVPN");
|
|
34276
|
-
const logFile2 =
|
|
34682
|
+
const logFile2 = path70.join(toolsDir, "downloads", "openvpn-install.log");
|
|
34277
34683
|
const code = await spawnAsync(SYSTEM.msiexec(), ["/i", msi, "/qn", "/norestart", "/l*v", logFile2], {
|
|
34278
34684
|
stdio: "ignore"
|
|
34279
34685
|
});
|
|
@@ -34284,10 +34690,10 @@ async function ensureOpenVpn() {
|
|
|
34284
34690
|
}
|
|
34285
34691
|
|
|
34286
34692
|
// src/guest/vpn/tunnel.ts
|
|
34287
|
-
import { spawn as
|
|
34288
|
-
import
|
|
34693
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
34694
|
+
import fs58 from "node:fs";
|
|
34289
34695
|
import os12 from "node:os";
|
|
34290
|
-
import
|
|
34696
|
+
import path71 from "node:path";
|
|
34291
34697
|
var DONE = "Initialization Sequence Completed";
|
|
34292
34698
|
function failureReason(text) {
|
|
34293
34699
|
if (/AUTH_FAILED/i.test(text))
|
|
@@ -34303,19 +34709,19 @@ function failureReason(text) {
|
|
|
34303
34709
|
}
|
|
34304
34710
|
var tail = (text, lines = 12) => text.trim().split(/\r?\n/).slice(-lines).join("\n");
|
|
34305
34711
|
async function startTunnel(o) {
|
|
34306
|
-
const dir =
|
|
34307
|
-
const auth =
|
|
34308
|
-
const logFile2 =
|
|
34712
|
+
const dir = fs58.mkdtempSync(path71.join(os12.tmpdir(), "sbx-vpn-"));
|
|
34713
|
+
const auth = path71.join(dir, "login.txt");
|
|
34714
|
+
const logFile2 = path71.join(dir, "openvpn.log");
|
|
34309
34715
|
const keepLog = () => {
|
|
34310
34716
|
try {
|
|
34311
|
-
|
|
34312
|
-
|
|
34717
|
+
fs58.mkdirSync(logsDir, { recursive: true });
|
|
34718
|
+
fs58.copyFileSync(logFile2, path71.join(logsDir, "openvpn.log"));
|
|
34313
34719
|
} catch {
|
|
34314
34720
|
}
|
|
34315
34721
|
};
|
|
34316
|
-
|
|
34722
|
+
fs58.writeFileSync(auth, o.username + "\r\n" + o.password + "\r\n", "utf8");
|
|
34317
34723
|
try {
|
|
34318
|
-
const child =
|
|
34724
|
+
const child = spawn8(
|
|
34319
34725
|
o.exe,
|
|
34320
34726
|
["--config", o.profile, "--auth-user-pass", auth, "--auth-nocache", "--verb", "3", "--log", logFile2],
|
|
34321
34727
|
{ detached: true, stdio: "ignore", windowsHide: true }
|
|
@@ -34331,7 +34737,7 @@ async function startTunnel(o) {
|
|
|
34331
34737
|
child.unref();
|
|
34332
34738
|
const deadline = Date.now() + (o.timeoutMs ?? 9e4);
|
|
34333
34739
|
for (; ; ) {
|
|
34334
|
-
const text =
|
|
34740
|
+
const text = fs58.existsSync(logFile2) ? fs58.readFileSync(logFile2, "utf8") : "";
|
|
34335
34741
|
if (text.includes(DONE)) {
|
|
34336
34742
|
keepLog();
|
|
34337
34743
|
const tunnelIp = tunnelAddressFromLog(text) ?? void 0;
|
|
@@ -34351,41 +34757,41 @@ async function startTunnel(o) {
|
|
|
34351
34757
|
await new Promise((r) => setTimeout(r, 500));
|
|
34352
34758
|
}
|
|
34353
34759
|
} finally {
|
|
34354
|
-
|
|
34760
|
+
fs58.rmSync(auth, { force: true });
|
|
34355
34761
|
}
|
|
34356
34762
|
}
|
|
34357
34763
|
|
|
34358
34764
|
// src/guest/vpn/wireguard.ts
|
|
34359
34765
|
import { execFile } from "node:child_process";
|
|
34360
34766
|
import crypto5 from "node:crypto";
|
|
34361
|
-
import
|
|
34767
|
+
import fs59 from "node:fs";
|
|
34362
34768
|
import os13 from "node:os";
|
|
34363
|
-
import
|
|
34769
|
+
import path72 from "node:path";
|
|
34364
34770
|
var WIREGUARD_TUNNEL = "sandbox";
|
|
34365
34771
|
function wireguardDir(env = process.env) {
|
|
34366
|
-
return
|
|
34772
|
+
return path72.join(env.ProgramFiles ?? "C:\\Program Files", "WireGuard");
|
|
34367
34773
|
}
|
|
34368
34774
|
function wireguardExe(env = process.env) {
|
|
34369
|
-
return
|
|
34775
|
+
return path72.join(wireguardDir(env), "wireguard.exe");
|
|
34370
34776
|
}
|
|
34371
34777
|
function wireguardDownload(arch2 = process.arch) {
|
|
34372
34778
|
const entry = arch2 === "arm64" ? WIREGUARD_MSI.arm64 : WIREGUARD_MSI.x64;
|
|
34373
34779
|
return { ...entry, url: WIREGUARD_MSI.base + entry.file };
|
|
34374
34780
|
}
|
|
34375
|
-
var hasHash2 = (file3, sha256) => crypto5.createHash("sha256").update(
|
|
34781
|
+
var hasHash2 = (file3, sha256) => crypto5.createHash("sha256").update(fs59.readFileSync(file3)).digest("hex") === sha256;
|
|
34376
34782
|
async function ensureWireguard() {
|
|
34377
34783
|
const exe = wireguardExe();
|
|
34378
34784
|
if (!isWin || dryRun) return exe;
|
|
34379
34785
|
if (exists(exe)) return exe;
|
|
34380
34786
|
const dl = wireguardDownload();
|
|
34381
|
-
const msi =
|
|
34787
|
+
const msi = path72.join(mkdirp(path72.join(toolsDir, "downloads")), dl.file);
|
|
34382
34788
|
if (!exists(msi) || !hasHash2(msi, dl.sha256)) {
|
|
34383
34789
|
log("VPN: downloading WireGuard " + WIREGUARD_MSI.version + " (about 3 MB)");
|
|
34384
34790
|
await downloader.file(dl.url, msi, dl.sha256);
|
|
34385
34791
|
}
|
|
34386
34792
|
repairServiceQueries();
|
|
34387
34793
|
log("VPN: installing WireGuard");
|
|
34388
|
-
const logFile2 =
|
|
34794
|
+
const logFile2 = path72.join(toolsDir, "downloads", "wireguard-install.log");
|
|
34389
34795
|
const code = await spawnAsync(
|
|
34390
34796
|
SYSTEM.msiexec(),
|
|
34391
34797
|
["/i", msi, "/qn", "/norestart", "DO_NOT_LAUNCH=1", "/l*v", logFile2],
|
|
@@ -34417,10 +34823,10 @@ async function removeWireguardTunnel(exe) {
|
|
|
34417
34823
|
}
|
|
34418
34824
|
}
|
|
34419
34825
|
async function startWireguardTunnel(o) {
|
|
34420
|
-
const root =
|
|
34421
|
-
const dir =
|
|
34422
|
-
const file3 =
|
|
34423
|
-
|
|
34826
|
+
const root = path72.join(process.env.SystemRoot ?? "C:\\Windows", "Temp");
|
|
34827
|
+
const dir = fs59.mkdtempSync(path72.join(fs59.existsSync(root) ? root : os13.tmpdir(), "sbx-wg-"));
|
|
34828
|
+
const file3 = path72.join(dir, WIREGUARD_TUNNEL + ".conf");
|
|
34829
|
+
fs59.writeFileSync(file3, o.config, "utf8");
|
|
34424
34830
|
const fail = async (message) => {
|
|
34425
34831
|
await removeWireguardTunnel(o.exe);
|
|
34426
34832
|
return { ok: false, message };
|
|
@@ -34441,11 +34847,11 @@ async function startWireguardTunnel(o) {
|
|
|
34441
34847
|
await sleep(500);
|
|
34442
34848
|
}
|
|
34443
34849
|
} finally {
|
|
34444
|
-
|
|
34850
|
+
fs59.rmSync(dir, { recursive: true, force: true });
|
|
34445
34851
|
}
|
|
34446
34852
|
}
|
|
34447
34853
|
async function waitForHandshake(exe, poke, timeoutMs = 3e4) {
|
|
34448
|
-
const wg =
|
|
34854
|
+
const wg = path72.join(path72.dirname(exe), "wg.exe");
|
|
34449
34855
|
if (!exists(wg)) return { ok: true, message: "the tunnel service is running (no wg.exe to check the handshake)" };
|
|
34450
34856
|
const deadline = Date.now() + timeoutMs;
|
|
34451
34857
|
for (; ; ) {
|
|
@@ -34580,8 +34986,8 @@ async function setupVpn(secrets, ptyHostExe) {
|
|
|
34580
34986
|
} else {
|
|
34581
34987
|
const credentials = secrets.vpn;
|
|
34582
34988
|
if (!credentials) throw new Error("the VPN login did not arrive (start the sandbox again)");
|
|
34583
|
-
const profile =
|
|
34584
|
-
const remotes = assertSafeOvpn(
|
|
34989
|
+
const profile = path73.join(launchDir, "vpn", "server.ovpn");
|
|
34990
|
+
const remotes = assertSafeOvpn(fs60.readFileSync(profile, "utf8"), vpn.server);
|
|
34585
34991
|
const exe = await ensureOpenVpn();
|
|
34586
34992
|
const servers = await serverAddresses(remotes);
|
|
34587
34993
|
if (servers.length === 0) throw new Error("the VPN server addresses could not be found");
|
|
@@ -34630,6 +35036,8 @@ var FrameType = {
|
|
|
34630
35036
|
Resize: 3,
|
|
34631
35037
|
Restart: 4,
|
|
34632
35038
|
Ping: 5,
|
|
35039
|
+
/** Ends the program and everything it started, and with it the session. */
|
|
35040
|
+
Close: 6,
|
|
34633
35041
|
Output: 16,
|
|
34634
35042
|
Exit: 17,
|
|
34635
35043
|
Error: 18,
|
|
@@ -34834,7 +35242,7 @@ var OutputFilter = class {
|
|
|
34834
35242
|
};
|
|
34835
35243
|
|
|
34836
35244
|
// src/shared/pty/console-input.ts
|
|
34837
|
-
import { spawn as
|
|
35245
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
34838
35246
|
function enableVtInput() {
|
|
34839
35247
|
if (process.platform !== "win32" || !process.stdin.isTTY)
|
|
34840
35248
|
return { ready: Promise.resolve(false), stop: () => Promise.resolve() };
|
|
@@ -34842,7 +35250,7 @@ function enableVtInput() {
|
|
|
34842
35250
|
let exited = Promise.resolve();
|
|
34843
35251
|
const ready = new Promise((resolve2) => {
|
|
34844
35252
|
try {
|
|
34845
|
-
child =
|
|
35253
|
+
child = spawn9(SYSTEM.powershell(), scriptArgs("enable-vt-input.ps1", ["-ProcessId", String(process.pid)]), {
|
|
34846
35254
|
stdio: "ignore",
|
|
34847
35255
|
windowsHide: true
|
|
34848
35256
|
});
|
|
@@ -35091,7 +35499,7 @@ async function viewSession(id) {
|
|
|
35091
35499
|
}
|
|
35092
35500
|
|
|
35093
35501
|
// src/guest/boot/boot-env.ts
|
|
35094
|
-
import
|
|
35502
|
+
import path74 from "node:path";
|
|
35095
35503
|
|
|
35096
35504
|
// src/guest/boot/project-env.ts
|
|
35097
35505
|
var EnvSchema = external_exports.object({
|
|
@@ -35110,7 +35518,7 @@ var BootEnvSchema = external_exports.object({
|
|
|
35110
35518
|
});
|
|
35111
35519
|
|
|
35112
35520
|
// src/guest/boot/boot-env.ts
|
|
35113
|
-
var file2 = () =>
|
|
35521
|
+
var file2 = () => path74.join(localDir, "boot-env.json");
|
|
35114
35522
|
function saveBootEnv(value) {
|
|
35115
35523
|
try {
|
|
35116
35524
|
writeJsonAtomic(file2(), value);
|
|
@@ -35139,7 +35547,7 @@ function saveProjectStatus(name, workspace2, phase, message, databases, summary)
|
|
|
35139
35547
|
}
|
|
35140
35548
|
|
|
35141
35549
|
// src/guest/runtime/secrets.ts
|
|
35142
|
-
import
|
|
35550
|
+
import fs61 from "node:fs";
|
|
35143
35551
|
|
|
35144
35552
|
// src/shared/channel/secrets.ts
|
|
35145
35553
|
var Environment = external_exports.record(external_exports.string().max(256), external_exports.string().max(65536));
|
|
@@ -35167,12 +35575,12 @@ function takeSecrets(id) {
|
|
|
35167
35575
|
const file3 = run.secretFile(id);
|
|
35168
35576
|
let text;
|
|
35169
35577
|
try {
|
|
35170
|
-
if (
|
|
35171
|
-
text =
|
|
35578
|
+
if (fs61.statSync(file3).size > MAX_BYTES) throw new Error("too big");
|
|
35579
|
+
text = fs61.readFileSync(file3, "utf8").replace(/^\uFEFF/, "");
|
|
35172
35580
|
} catch {
|
|
35173
35581
|
return {};
|
|
35174
35582
|
} finally {
|
|
35175
|
-
|
|
35583
|
+
fs61.rmSync(file3, { force: true });
|
|
35176
35584
|
}
|
|
35177
35585
|
try {
|
|
35178
35586
|
const parsed = SecretsFileSchema.safeParse(JSON.parse(text));
|
|
@@ -35210,7 +35618,7 @@ async function soft(what, work) {
|
|
|
35210
35618
|
}
|
|
35211
35619
|
}
|
|
35212
35620
|
function startDaemon(env, secrets) {
|
|
35213
|
-
|
|
35621
|
+
spawn10(process.execPath, [path75.join(path75.dirname(process.argv[1]), "daemon.js")], {
|
|
35214
35622
|
detached: true,
|
|
35215
35623
|
stdio: "ignore",
|
|
35216
35624
|
windowsHide: true,
|
|
@@ -35223,20 +35631,20 @@ function startDaemon(env, secrets) {
|
|
|
35223
35631
|
}).unref();
|
|
35224
35632
|
}
|
|
35225
35633
|
function writeDbCommand() {
|
|
35226
|
-
const dir = mkdirp(
|
|
35227
|
-
const db =
|
|
35228
|
-
|
|
35229
|
-
|
|
35634
|
+
const dir = mkdirp(path75.join(localDir, "bin"));
|
|
35635
|
+
const db = path75.join(path75.dirname(process.argv[1]), "db.js");
|
|
35636
|
+
fs62.writeFileSync(
|
|
35637
|
+
path75.join(dir, "sbx-db.cmd"),
|
|
35230
35638
|
'@setlocal\r\n@set AGENT_LOG_PREFIX=db\r\n@"' + process.execPath + '" "' + db + '" %*\r\n'
|
|
35231
35639
|
);
|
|
35232
35640
|
writeAgentCommands(dir);
|
|
35233
35641
|
return dir;
|
|
35234
35642
|
}
|
|
35235
35643
|
function writeAgentCommands(dir) {
|
|
35236
|
-
const install = { node: process.execPath, script:
|
|
35644
|
+
const install = { node: process.execPath, script: path75.join(path75.dirname(process.argv[1]), "agent.js") };
|
|
35237
35645
|
for (const shim3 of agentShims(toolsDir, session.agents ?? {}))
|
|
35238
|
-
|
|
35239
|
-
|
|
35646
|
+
fs62.writeFileSync(path75.join(dir, shim3.command + ".cmd"), shimText(shim3, install));
|
|
35647
|
+
fs62.writeFileSync(path75.join(dir, "sbx-agent.cmd"), sbxAgentText(install));
|
|
35240
35648
|
}
|
|
35241
35649
|
async function waitForPrimary() {
|
|
35242
35650
|
for (let i = 0; i < PRIMARY_POLLS; i++) {
|
|
@@ -35264,7 +35672,7 @@ var Boot = class {
|
|
|
35264
35672
|
log(
|
|
35265
35673
|
"Agent sandbox: " + session.project + " | workspace " + workspace + " | agent " + session.harnessName + " | log " + logPath
|
|
35266
35674
|
);
|
|
35267
|
-
if (!
|
|
35675
|
+
if (!fs62.statSync(workspace, { throwIfNoEntry: false })?.isDirectory())
|
|
35268
35676
|
throw new Error("Workspace folder is missing in the sandbox: " + workspace);
|
|
35269
35677
|
mkdirp(toolsDir);
|
|
35270
35678
|
mkdirp(run.root);
|
|
@@ -35276,7 +35684,7 @@ var Boot = class {
|
|
|
35276
35684
|
const { tools, env } = await this.developerTools();
|
|
35277
35685
|
await this.vpn();
|
|
35278
35686
|
await this.gitIdentity(env);
|
|
35279
|
-
await this.claude(tools);
|
|
35687
|
+
await this.claude(tools, env);
|
|
35280
35688
|
await this.agent(env);
|
|
35281
35689
|
this.preAgentHooks(env);
|
|
35282
35690
|
await this.start(env);
|
|
@@ -35359,15 +35767,20 @@ var Boot = class {
|
|
|
35359
35767
|
await soft("GitHub token", () => loginGithub(token, env));
|
|
35360
35768
|
}
|
|
35361
35769
|
}
|
|
35362
|
-
async claude(tools) {
|
|
35770
|
+
async claude(tools, env) {
|
|
35363
35771
|
step(6, "Claude settings, history and claude-mem");
|
|
35364
35772
|
if (session.harnessName === "claude")
|
|
35365
35773
|
await soft("Claude settings", () => syncClaudeProfile(this.secrets.claudeCredentials));
|
|
35366
35774
|
await soft("claude-mem restore", restoreClaudeMem);
|
|
35367
35775
|
await soft("Agent files of the last sandbox", resetMachineBound);
|
|
35368
35776
|
await soft("Agent databases restore", restoreLocalState);
|
|
35777
|
+
let headroom = null;
|
|
35778
|
+
await soft("MCP servers from Apps", writeAddonMcpServers);
|
|
35779
|
+
await soft("Headroom proxy", async () => {
|
|
35780
|
+
headroom = await startHeadroom(env);
|
|
35781
|
+
});
|
|
35782
|
+
await soft("Claude managed settings", () => writeManagedSettings2(this.gitAccess, headroom));
|
|
35369
35783
|
await soft("Sandbox guide for the agent", () => writeGuides(tools.summary, this.lan));
|
|
35370
|
-
await soft("Claude managed settings", () => writeManagedSettings2(this.gitAccess));
|
|
35371
35784
|
}
|
|
35372
35785
|
async agent(env) {
|
|
35373
35786
|
step(7, "Agent: " + session.harnessName);
|
|
@@ -35419,11 +35832,11 @@ runBoot().catch((e) => {
|
|
|
35419
35832
|
const message = errMsg(e) + (e instanceof Error && e.stack ? "\n" + e.stack : "");
|
|
35420
35833
|
try {
|
|
35421
35834
|
setSandboxStatus("failed", errMsg(e));
|
|
35422
|
-
|
|
35835
|
+
fs63.writeFileSync(path76.join(logsDir, "guest-error.txt"), message);
|
|
35423
35836
|
} catch {
|
|
35424
35837
|
}
|
|
35425
35838
|
console.error(
|
|
35426
|
-
"\n\x1B[31mThe sandbox could not start: " + errMsg(e) + "\x1B[0m\nDetails: " +
|
|
35839
|
+
"\n\x1B[31mThe sandbox could not start: " + errMsg(e) + "\x1B[0m\nDetails: " + path76.join(logsDir, "guest-error.txt")
|
|
35427
35840
|
);
|
|
35428
35841
|
process.exitCode = 1;
|
|
35429
35842
|
});
|