windows-development-sandbox 1.27.1 → 1.27.3
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/dist/app/context.d.ts +5 -0
- package/dist/app/context.js +13 -0
- package/dist/app/features/accounts/accounts.def.d.ts +16 -0
- package/dist/app/features/accounts/accounts.run.d.ts +4 -0
- package/dist/app/features/accounts/services.def.d.ts +15 -1
- package/dist/app/features/accounts/services.def.js +67 -31
- package/dist/app/features/accounts/services.run.d.ts +7 -2
- package/dist/app/features/accounts/services.run.js +25 -6
- package/dist/app/features/defs.d.ts +17 -0
- package/dist/app/registry.d.ts +1 -1
- package/dist/app/registry.js +15 -2
- package/dist/bin/agent-sandbox.js +2 -2
- package/dist/bin/{chunk-QUHNXHVG.js → chunk-4M5SZZ5P.js} +46 -41
- package/dist/bin/{chunk-4TLSWPG7.js → chunk-FA5VWLP4.js} +1 -1
- package/dist/bin/{chunk-RSIX7C6D.js → chunk-RU7XRN62.js} +249 -101
- package/dist/bin/claude-host.js +2 -2
- package/dist/bin/claude-sbx.js +2 -2
- package/dist/bin/codex-sbx.js +2 -2
- package/dist/bin/gemini-sbx.js +2 -2
- package/dist/bin/sandbox.js +2 -2
- package/dist/bin/sbx-hide.js +2 -2
- package/dist/bin/sbx-show.js +2 -2
- package/dist/cli/menu/menu.js +6 -1
- package/dist/cli/menu/pages/accounts-page.js +9 -5
- package/dist/guest/apps/app-installer.js +7 -5
- package/dist/guest/apps/comet-unpack.js +2 -2
- package/dist/guest/runtime/pools.d.ts +4 -4
- package/dist/guest/runtime/pools.js +4 -15
- package/dist/guest/runtime/process.d.ts +5 -2
- package/dist/guest/runtime/process.js +23 -3
- package/dist/guest/toolchains/engines/epic-launcher.d.ts +6 -0
- package/dist/guest/toolchains/engines/epic-launcher.js +19 -1
- package/dist/guest/toolchains/engines/unreal-engines.js +2 -1
- package/dist/guest/toolchains/installers.d.ts +3 -3
- package/dist/guest/toolchains/installers.js +5 -5
- package/dist/guest/toolchains/native/vcruntime.js +2 -2
- package/dist/guest/toolchains/native/vs-persist.d.ts +2 -2
- package/dist/guest/toolchains/signature.d.ts +2 -0
- package/dist/guest/toolchains/signature.js +9 -2
- package/dist/guest/toolchains/step-scheduler.js +1 -1
- package/dist/host/accounts/deliver.js +15 -7
- package/dist/host/pc-installs/discover.js +5 -2
- package/dist/host/pc-installs/unreal.d.ts +3 -1
- package/dist/host/pc-installs/unreal.js +27 -1
- package/dist/runtime/agent.js +34 -22
- package/dist/runtime/daemon.js +96 -51
- package/dist/runtime/db.js +32 -16
- package/dist/runtime/main.js +98 -53
- package/dist/runtime/netproxy.js +26 -12
- package/dist/runtime/tool.js +32 -15
- package/dist/runtime/view.js +26 -12
- package/dist/selftest/app.test.js +20 -2
- package/dist/selftest/boot-runner.test.js +15 -1
- package/dist/selftest/engines.test.js +22 -1
- package/dist/selftest/menu-screens.js +52 -1
- package/dist/selftest/menu.test.js +29 -3
- package/dist/selftest/service-accounts.test.js +77 -2
- package/dist/selftest/ui-text.test.js +4 -0
- package/dist/shared/accounts/kinds.js +9 -9
- package/dist/shared/apps/catalogue-gamedev.js +1 -0
- package/dist/shared/apps/catalogue.d.ts +2 -0
- package/dist/shared/concurrency/pools.js +1 -1
- package/dist/shared/download/archive.js +4 -2
- package/dist/shared/download/index.d.ts +1 -1
- package/dist/shared/download/index.js +1 -1
- package/dist/shared/download/spawn.d.ts +7 -1
- package/dist/shared/download/spawn.js +16 -1
- package/dist/shared/paths/pc-installs.d.ts +8 -0
- package/dist/shared/unreal/launcher-files.d.ts +7 -0
- package/dist/shared/unreal/launcher-files.js +32 -1
- package/dist/web/index.html +1 -1
- package/dist/web/{main-VPMYTSUL.js → main-NKM7ECSB.js} +59 -59
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
- package/package.json +1 -1
- package/schemas/config.schema.json +9 -9
- package/schemas/sandbox-config.schema.json +9 -9
package/dist/runtime/netproxy.js
CHANGED
|
@@ -26121,6 +26121,7 @@ var GAMEDEV_APPS = [
|
|
|
26121
26121
|
size: "100 MB",
|
|
26122
26122
|
source: { github: "f3d-app/f3d", asset: "^F3D-[\\d.]+-Windows-x86_64\\.zip$" },
|
|
26123
26123
|
exe: "f3d.exe",
|
|
26124
|
+
onPath: true,
|
|
26124
26125
|
needs: ["mesa"]
|
|
26125
26126
|
},
|
|
26126
26127
|
{
|
|
@@ -27220,7 +27221,7 @@ var SERVICE_SPECS = {
|
|
|
27220
27221
|
},
|
|
27221
27222
|
steam: {
|
|
27222
27223
|
kind: "steam",
|
|
27223
|
-
label: "Steam
|
|
27224
|
+
label: "Steam",
|
|
27224
27225
|
usedBy: ["steam"],
|
|
27225
27226
|
sources: ["file", "sandbox"],
|
|
27226
27227
|
singleHolder: true,
|
|
@@ -27256,7 +27257,7 @@ var SERVICE_SPECS = {
|
|
|
27256
27257
|
},
|
|
27257
27258
|
cfx: {
|
|
27258
27259
|
kind: "cfx",
|
|
27259
|
-
label: "
|
|
27260
|
+
label: "FiveM key",
|
|
27260
27261
|
usedBy: ["fivem"],
|
|
27261
27262
|
sources: ["typed", "file"],
|
|
27262
27263
|
singleHolder: false,
|
|
@@ -27285,7 +27286,7 @@ var SERVICE_SPECS = {
|
|
|
27285
27286
|
},
|
|
27286
27287
|
keystore: {
|
|
27287
27288
|
kind: "keystore",
|
|
27288
|
-
label: "Android
|
|
27289
|
+
label: "Android keystore",
|
|
27289
27290
|
usedBy: ["android"],
|
|
27290
27291
|
sources: ["file"],
|
|
27291
27292
|
singleHolder: false,
|
|
@@ -27300,7 +27301,7 @@ var SERVICE_SPECS = {
|
|
|
27300
27301
|
},
|
|
27301
27302
|
play: {
|
|
27302
27303
|
kind: "play",
|
|
27303
|
-
label: "Google Play
|
|
27304
|
+
label: "Google Play",
|
|
27304
27305
|
usedBy: ["android"],
|
|
27305
27306
|
sources: ["file"],
|
|
27306
27307
|
singleHolder: false,
|
|
@@ -27311,7 +27312,7 @@ var SERVICE_SPECS = {
|
|
|
27311
27312
|
},
|
|
27312
27313
|
expo: {
|
|
27313
27314
|
kind: "expo",
|
|
27314
|
-
label: "Expo
|
|
27315
|
+
label: "Expo",
|
|
27315
27316
|
usedBy: ["reactNative"],
|
|
27316
27317
|
sources: ["typed"],
|
|
27317
27318
|
singleHolder: false,
|
|
@@ -27322,7 +27323,7 @@ var SERVICE_SPECS = {
|
|
|
27322
27323
|
},
|
|
27323
27324
|
appstore: {
|
|
27324
27325
|
kind: "appstore",
|
|
27325
|
-
label: "App Store Connect
|
|
27326
|
+
label: "App Store Connect",
|
|
27326
27327
|
usedBy: ["reactNative", "flutter"],
|
|
27327
27328
|
sources: ["file", "typed"],
|
|
27328
27329
|
singleHolder: false,
|
|
@@ -27336,7 +27337,7 @@ var SERVICE_SPECS = {
|
|
|
27336
27337
|
},
|
|
27337
27338
|
perplexity: {
|
|
27338
27339
|
kind: "perplexity",
|
|
27339
|
-
label: "Perplexity API
|
|
27340
|
+
label: "Perplexity API",
|
|
27340
27341
|
usedBy: ["perplexity"],
|
|
27341
27342
|
sources: ["pc", "file", "typed"],
|
|
27342
27343
|
singleHolder: false,
|
|
@@ -27360,7 +27361,7 @@ var SERVICE_SPECS = {
|
|
|
27360
27361
|
},
|
|
27361
27362
|
comet: {
|
|
27362
27363
|
kind: "comet",
|
|
27363
|
-
label: "Comet
|
|
27364
|
+
label: "Comet",
|
|
27364
27365
|
usedBy: ["comet"],
|
|
27365
27366
|
sources: ["sandbox"],
|
|
27366
27367
|
singleHolder: false,
|
|
@@ -27376,7 +27377,7 @@ var SERVICE_SPECS = {
|
|
|
27376
27377
|
},
|
|
27377
27378
|
perplexityapp: {
|
|
27378
27379
|
kind: "perplexityapp",
|
|
27379
|
-
label: "Perplexity
|
|
27380
|
+
label: "Perplexity app",
|
|
27380
27381
|
usedBy: ["perplexityapp"],
|
|
27381
27382
|
sources: ["sandbox"],
|
|
27382
27383
|
singleHolder: false,
|
|
@@ -28124,10 +28125,20 @@ function scriptArgs(name, args = []) {
|
|
|
28124
28125
|
}
|
|
28125
28126
|
|
|
28126
28127
|
// src/shared/download/spawn.ts
|
|
28128
|
+
import os3 from "node:os";
|
|
28127
28129
|
import { spawn } from "node:child_process";
|
|
28130
|
+
function lowerPriority(pid) {
|
|
28131
|
+
if (pid === void 0) return;
|
|
28132
|
+
try {
|
|
28133
|
+
os3.setPriority(pid, os3.constants.priority.PRIORITY_BELOW_NORMAL);
|
|
28134
|
+
} catch {
|
|
28135
|
+
}
|
|
28136
|
+
}
|
|
28128
28137
|
function spawnAsync(file2, args, options = {}) {
|
|
28138
|
+
const { lowPriority, ...spawnOptions } = options;
|
|
28129
28139
|
return new Promise((resolve, reject) => {
|
|
28130
|
-
const child = spawn(file2, args, { stdio: "ignore", windowsHide: true, ...
|
|
28140
|
+
const child = spawn(file2, args, { stdio: "ignore", windowsHide: true, ...spawnOptions });
|
|
28141
|
+
if (lowPriority) lowerPriority(child.pid);
|
|
28131
28142
|
child.once("error", reject);
|
|
28132
28143
|
child.once("close", (code) => resolve(code ?? -1));
|
|
28133
28144
|
});
|
|
@@ -28148,13 +28159,16 @@ function extractArchive(archive, destination, members2 = []) {
|
|
|
28148
28159
|
}
|
|
28149
28160
|
async function extract(archive, destination, members2) {
|
|
28150
28161
|
fs6.mkdirSync(destination, { recursive: true });
|
|
28151
|
-
let status = await spawnAsync(SYSTEM.tar(), ["-xf", archive, "-C", destination, ...members2]
|
|
28162
|
+
let status = await spawnAsync(SYSTEM.tar(), ["-xf", archive, "-C", destination, ...members2], {
|
|
28163
|
+
lowPriority: true
|
|
28164
|
+
});
|
|
28152
28165
|
if (status !== 0 && /\.(zip|nupkg)$/i.test(archive)) {
|
|
28153
28166
|
const zip = archive.endsWith(".zip") ? archive : archive + ".zip";
|
|
28154
28167
|
if (zip !== archive) fs6.copyFileSync(archive, zip);
|
|
28155
28168
|
status = await spawnAsync(
|
|
28156
28169
|
SYSTEM.powershell(),
|
|
28157
|
-
scriptArgs("expand-archive.ps1", ["-Archive", zip, "-Destination", destination])
|
|
28170
|
+
scriptArgs("expand-archive.ps1", ["-Archive", zip, "-Destination", destination]),
|
|
28171
|
+
{ lowPriority: true }
|
|
28158
28172
|
);
|
|
28159
28173
|
}
|
|
28160
28174
|
if (status !== 0) throw new Error("Could not extract " + archive);
|
package/dist/runtime/tool.js
CHANGED
|
@@ -5551,7 +5551,7 @@ var androidTool = {
|
|
|
5551
5551
|
|
|
5552
5552
|
// src/guest/devtools/fivem.ts
|
|
5553
5553
|
import fs17 from "node:fs";
|
|
5554
|
-
import
|
|
5554
|
+
import os4 from "node:os";
|
|
5555
5555
|
import path20 from "node:path";
|
|
5556
5556
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
5557
5557
|
|
|
@@ -5831,10 +5831,20 @@ function scriptArgs(name2, args2 = []) {
|
|
|
5831
5831
|
}
|
|
5832
5832
|
|
|
5833
5833
|
// src/shared/download/spawn.ts
|
|
5834
|
+
import os3 from "node:os";
|
|
5834
5835
|
import { spawn } from "node:child_process";
|
|
5836
|
+
function lowerPriority(pid) {
|
|
5837
|
+
if (pid === void 0) return;
|
|
5838
|
+
try {
|
|
5839
|
+
os3.setPriority(pid, os3.constants.priority.PRIORITY_BELOW_NORMAL);
|
|
5840
|
+
} catch {
|
|
5841
|
+
}
|
|
5842
|
+
}
|
|
5835
5843
|
function spawnAsync(file2, args2, options = {}) {
|
|
5844
|
+
const { lowPriority, ...spawnOptions } = options;
|
|
5836
5845
|
return new Promise((resolve, reject) => {
|
|
5837
|
-
const child = spawn(file2, args2, { stdio: "ignore", windowsHide: true, ...
|
|
5846
|
+
const child = spawn(file2, args2, { stdio: "ignore", windowsHide: true, ...spawnOptions });
|
|
5847
|
+
if (lowPriority) lowerPriority(child.pid);
|
|
5838
5848
|
child.once("error", reject);
|
|
5839
5849
|
child.once("close", (code) => resolve(code ?? -1));
|
|
5840
5850
|
});
|
|
@@ -5855,13 +5865,16 @@ function extractArchive(archive, destination, members2 = []) {
|
|
|
5855
5865
|
}
|
|
5856
5866
|
async function extract(archive, destination, members2) {
|
|
5857
5867
|
fs7.mkdirSync(destination, { recursive: true });
|
|
5858
|
-
let status = await spawnAsync(SYSTEM.tar(), ["-xf", archive, "-C", destination, ...members2]
|
|
5868
|
+
let status = await spawnAsync(SYSTEM.tar(), ["-xf", archive, "-C", destination, ...members2], {
|
|
5869
|
+
lowPriority: true
|
|
5870
|
+
});
|
|
5859
5871
|
if (status !== 0 && /\.(zip|nupkg)$/i.test(archive)) {
|
|
5860
5872
|
const zip = archive.endsWith(".zip") ? archive : archive + ".zip";
|
|
5861
5873
|
if (zip !== archive) fs7.copyFileSync(archive, zip);
|
|
5862
5874
|
status = await spawnAsync(
|
|
5863
5875
|
SYSTEM.powershell(),
|
|
5864
|
-
scriptArgs("expand-archive.ps1", ["-Archive", zip, "-Destination", destination])
|
|
5876
|
+
scriptArgs("expand-archive.ps1", ["-Archive", zip, "-Destination", destination]),
|
|
5877
|
+
{ lowPriority: true }
|
|
5865
5878
|
);
|
|
5866
5879
|
}
|
|
5867
5880
|
if (status !== 0) throw new Error("Could not extract " + archive);
|
|
@@ -26494,6 +26507,7 @@ var GAMEDEV_APPS = [
|
|
|
26494
26507
|
size: "100 MB",
|
|
26495
26508
|
source: { github: "f3d-app/f3d", asset: "^F3D-[\\d.]+-Windows-x86_64\\.zip$" },
|
|
26496
26509
|
exe: "f3d.exe",
|
|
26510
|
+
onPath: true,
|
|
26497
26511
|
needs: ["mesa"]
|
|
26498
26512
|
},
|
|
26499
26513
|
{
|
|
@@ -27593,7 +27607,7 @@ var SERVICE_SPECS = {
|
|
|
27593
27607
|
},
|
|
27594
27608
|
steam: {
|
|
27595
27609
|
kind: "steam",
|
|
27596
|
-
label: "Steam
|
|
27610
|
+
label: "Steam",
|
|
27597
27611
|
usedBy: ["steam"],
|
|
27598
27612
|
sources: ["file", "sandbox"],
|
|
27599
27613
|
singleHolder: true,
|
|
@@ -27629,7 +27643,7 @@ var SERVICE_SPECS = {
|
|
|
27629
27643
|
},
|
|
27630
27644
|
cfx: {
|
|
27631
27645
|
kind: "cfx",
|
|
27632
|
-
label: "
|
|
27646
|
+
label: "FiveM key",
|
|
27633
27647
|
usedBy: ["fivem"],
|
|
27634
27648
|
sources: ["typed", "file"],
|
|
27635
27649
|
singleHolder: false,
|
|
@@ -27658,7 +27672,7 @@ var SERVICE_SPECS = {
|
|
|
27658
27672
|
},
|
|
27659
27673
|
keystore: {
|
|
27660
27674
|
kind: "keystore",
|
|
27661
|
-
label: "Android
|
|
27675
|
+
label: "Android keystore",
|
|
27662
27676
|
usedBy: ["android"],
|
|
27663
27677
|
sources: ["file"],
|
|
27664
27678
|
singleHolder: false,
|
|
@@ -27673,7 +27687,7 @@ var SERVICE_SPECS = {
|
|
|
27673
27687
|
},
|
|
27674
27688
|
play: {
|
|
27675
27689
|
kind: "play",
|
|
27676
|
-
label: "Google Play
|
|
27690
|
+
label: "Google Play",
|
|
27677
27691
|
usedBy: ["android"],
|
|
27678
27692
|
sources: ["file"],
|
|
27679
27693
|
singleHolder: false,
|
|
@@ -27684,7 +27698,7 @@ var SERVICE_SPECS = {
|
|
|
27684
27698
|
},
|
|
27685
27699
|
expo: {
|
|
27686
27700
|
kind: "expo",
|
|
27687
|
-
label: "Expo
|
|
27701
|
+
label: "Expo",
|
|
27688
27702
|
usedBy: ["reactNative"],
|
|
27689
27703
|
sources: ["typed"],
|
|
27690
27704
|
singleHolder: false,
|
|
@@ -27695,7 +27709,7 @@ var SERVICE_SPECS = {
|
|
|
27695
27709
|
},
|
|
27696
27710
|
appstore: {
|
|
27697
27711
|
kind: "appstore",
|
|
27698
|
-
label: "App Store Connect
|
|
27712
|
+
label: "App Store Connect",
|
|
27699
27713
|
usedBy: ["reactNative", "flutter"],
|
|
27700
27714
|
sources: ["file", "typed"],
|
|
27701
27715
|
singleHolder: false,
|
|
@@ -27709,7 +27723,7 @@ var SERVICE_SPECS = {
|
|
|
27709
27723
|
},
|
|
27710
27724
|
perplexity: {
|
|
27711
27725
|
kind: "perplexity",
|
|
27712
|
-
label: "Perplexity API
|
|
27726
|
+
label: "Perplexity API",
|
|
27713
27727
|
usedBy: ["perplexity"],
|
|
27714
27728
|
sources: ["pc", "file", "typed"],
|
|
27715
27729
|
singleHolder: false,
|
|
@@ -27733,7 +27747,7 @@ var SERVICE_SPECS = {
|
|
|
27733
27747
|
},
|
|
27734
27748
|
comet: {
|
|
27735
27749
|
kind: "comet",
|
|
27736
|
-
label: "Comet
|
|
27750
|
+
label: "Comet",
|
|
27737
27751
|
usedBy: ["comet"],
|
|
27738
27752
|
sources: ["sandbox"],
|
|
27739
27753
|
singleHolder: false,
|
|
@@ -27749,7 +27763,7 @@ var SERVICE_SPECS = {
|
|
|
27749
27763
|
},
|
|
27750
27764
|
perplexityapp: {
|
|
27751
27765
|
kind: "perplexityapp",
|
|
27752
|
-
label: "Perplexity
|
|
27766
|
+
label: "Perplexity app",
|
|
27753
27767
|
usedBy: ["perplexityapp"],
|
|
27754
27768
|
sources: ["sandbox"],
|
|
27755
27769
|
singleHolder: false,
|
|
@@ -28484,7 +28498,10 @@ function warn(message) {
|
|
|
28484
28498
|
// src/guest/toolchains/signature.ts
|
|
28485
28499
|
var SignatureSchema = external_exports.object({ subject: external_exports.string().max(4096), issuer: external_exports.string().max(4096) });
|
|
28486
28500
|
function signatureOf(file2) {
|
|
28487
|
-
|
|
28501
|
+
return parseSignature(scriptOutput("get-signature.ps1", ["-Path", file2]));
|
|
28502
|
+
}
|
|
28503
|
+
function parseSignature(output2) {
|
|
28504
|
+
const text = output2.trim();
|
|
28488
28505
|
if (!text) return null;
|
|
28489
28506
|
try {
|
|
28490
28507
|
const parsed = SignatureSchema.safeParse(JSON.parse(text));
|
|
@@ -29014,7 +29031,7 @@ function parse3(args2) {
|
|
|
29014
29031
|
return { positionals, flags, dir: dir === void 0 ? void 0 : path20.resolve(dir) };
|
|
29015
29032
|
}
|
|
29016
29033
|
function addresses() {
|
|
29017
|
-
return Object.values(
|
|
29034
|
+
return Object.values(os4.networkInterfaces()).flat().filter((a) => Boolean(a && a.family === "IPv4" && !a.internal)).map((a) => a.address);
|
|
29018
29035
|
}
|
|
29019
29036
|
function mariadbClient() {
|
|
29020
29037
|
const root = path20.join(toolsDir, "mariadb");
|
package/dist/runtime/view.js
CHANGED
|
@@ -26697,6 +26697,7 @@ var GAMEDEV_APPS = [
|
|
|
26697
26697
|
size: "100 MB",
|
|
26698
26698
|
source: { github: "f3d-app/f3d", asset: "^F3D-[\\d.]+-Windows-x86_64\\.zip$" },
|
|
26699
26699
|
exe: "f3d.exe",
|
|
26700
|
+
onPath: true,
|
|
26700
26701
|
needs: ["mesa"]
|
|
26701
26702
|
},
|
|
26702
26703
|
{
|
|
@@ -27796,7 +27797,7 @@ var SERVICE_SPECS = {
|
|
|
27796
27797
|
},
|
|
27797
27798
|
steam: {
|
|
27798
27799
|
kind: "steam",
|
|
27799
|
-
label: "Steam
|
|
27800
|
+
label: "Steam",
|
|
27800
27801
|
usedBy: ["steam"],
|
|
27801
27802
|
sources: ["file", "sandbox"],
|
|
27802
27803
|
singleHolder: true,
|
|
@@ -27832,7 +27833,7 @@ var SERVICE_SPECS = {
|
|
|
27832
27833
|
},
|
|
27833
27834
|
cfx: {
|
|
27834
27835
|
kind: "cfx",
|
|
27835
|
-
label: "
|
|
27836
|
+
label: "FiveM key",
|
|
27836
27837
|
usedBy: ["fivem"],
|
|
27837
27838
|
sources: ["typed", "file"],
|
|
27838
27839
|
singleHolder: false,
|
|
@@ -27861,7 +27862,7 @@ var SERVICE_SPECS = {
|
|
|
27861
27862
|
},
|
|
27862
27863
|
keystore: {
|
|
27863
27864
|
kind: "keystore",
|
|
27864
|
-
label: "Android
|
|
27865
|
+
label: "Android keystore",
|
|
27865
27866
|
usedBy: ["android"],
|
|
27866
27867
|
sources: ["file"],
|
|
27867
27868
|
singleHolder: false,
|
|
@@ -27876,7 +27877,7 @@ var SERVICE_SPECS = {
|
|
|
27876
27877
|
},
|
|
27877
27878
|
play: {
|
|
27878
27879
|
kind: "play",
|
|
27879
|
-
label: "Google Play
|
|
27880
|
+
label: "Google Play",
|
|
27880
27881
|
usedBy: ["android"],
|
|
27881
27882
|
sources: ["file"],
|
|
27882
27883
|
singleHolder: false,
|
|
@@ -27887,7 +27888,7 @@ var SERVICE_SPECS = {
|
|
|
27887
27888
|
},
|
|
27888
27889
|
expo: {
|
|
27889
27890
|
kind: "expo",
|
|
27890
|
-
label: "Expo
|
|
27891
|
+
label: "Expo",
|
|
27891
27892
|
usedBy: ["reactNative"],
|
|
27892
27893
|
sources: ["typed"],
|
|
27893
27894
|
singleHolder: false,
|
|
@@ -27898,7 +27899,7 @@ var SERVICE_SPECS = {
|
|
|
27898
27899
|
},
|
|
27899
27900
|
appstore: {
|
|
27900
27901
|
kind: "appstore",
|
|
27901
|
-
label: "App Store Connect
|
|
27902
|
+
label: "App Store Connect",
|
|
27902
27903
|
usedBy: ["reactNative", "flutter"],
|
|
27903
27904
|
sources: ["file", "typed"],
|
|
27904
27905
|
singleHolder: false,
|
|
@@ -27912,7 +27913,7 @@ var SERVICE_SPECS = {
|
|
|
27912
27913
|
},
|
|
27913
27914
|
perplexity: {
|
|
27914
27915
|
kind: "perplexity",
|
|
27915
|
-
label: "Perplexity API
|
|
27916
|
+
label: "Perplexity API",
|
|
27916
27917
|
usedBy: ["perplexity"],
|
|
27917
27918
|
sources: ["pc", "file", "typed"],
|
|
27918
27919
|
singleHolder: false,
|
|
@@ -27936,7 +27937,7 @@ var SERVICE_SPECS = {
|
|
|
27936
27937
|
},
|
|
27937
27938
|
comet: {
|
|
27938
27939
|
kind: "comet",
|
|
27939
|
-
label: "Comet
|
|
27940
|
+
label: "Comet",
|
|
27940
27941
|
usedBy: ["comet"],
|
|
27941
27942
|
sources: ["sandbox"],
|
|
27942
27943
|
singleHolder: false,
|
|
@@ -27952,7 +27953,7 @@ var SERVICE_SPECS = {
|
|
|
27952
27953
|
},
|
|
27953
27954
|
perplexityapp: {
|
|
27954
27955
|
kind: "perplexityapp",
|
|
27955
|
-
label: "Perplexity
|
|
27956
|
+
label: "Perplexity app",
|
|
27956
27957
|
usedBy: ["perplexityapp"],
|
|
27957
27958
|
sources: ["sandbox"],
|
|
27958
27959
|
singleHolder: false,
|
|
@@ -28650,10 +28651,20 @@ import path7 from "node:path";
|
|
|
28650
28651
|
import crypto from "node:crypto";
|
|
28651
28652
|
|
|
28652
28653
|
// src/shared/download/spawn.ts
|
|
28654
|
+
import os3 from "node:os";
|
|
28653
28655
|
import { spawn as spawn2 } from "node:child_process";
|
|
28656
|
+
function lowerPriority(pid) {
|
|
28657
|
+
if (pid === void 0) return;
|
|
28658
|
+
try {
|
|
28659
|
+
os3.setPriority(pid, os3.constants.priority.PRIORITY_BELOW_NORMAL);
|
|
28660
|
+
} catch {
|
|
28661
|
+
}
|
|
28662
|
+
}
|
|
28654
28663
|
function spawnAsync(file2, args, options = {}) {
|
|
28664
|
+
const { lowPriority, ...spawnOptions } = options;
|
|
28655
28665
|
return new Promise((resolve, reject) => {
|
|
28656
|
-
const child = spawn2(file2, args, { stdio: "ignore", windowsHide: true, ...
|
|
28666
|
+
const child = spawn2(file2, args, { stdio: "ignore", windowsHide: true, ...spawnOptions });
|
|
28667
|
+
if (lowPriority) lowerPriority(child.pid);
|
|
28657
28668
|
child.once("error", reject);
|
|
28658
28669
|
child.once("close", (code) => resolve(code ?? -1));
|
|
28659
28670
|
});
|
|
@@ -28674,13 +28685,16 @@ function extractArchive(archive, destination, members2 = []) {
|
|
|
28674
28685
|
}
|
|
28675
28686
|
async function extract(archive, destination, members2) {
|
|
28676
28687
|
fs6.mkdirSync(destination, { recursive: true });
|
|
28677
|
-
let status = await spawnAsync(SYSTEM.tar(), ["-xf", archive, "-C", destination, ...members2]
|
|
28688
|
+
let status = await spawnAsync(SYSTEM.tar(), ["-xf", archive, "-C", destination, ...members2], {
|
|
28689
|
+
lowPriority: true
|
|
28690
|
+
});
|
|
28678
28691
|
if (status !== 0 && /\.(zip|nupkg)$/i.test(archive)) {
|
|
28679
28692
|
const zip = archive.endsWith(".zip") ? archive : archive + ".zip";
|
|
28680
28693
|
if (zip !== archive) fs6.copyFileSync(archive, zip);
|
|
28681
28694
|
status = await spawnAsync(
|
|
28682
28695
|
SYSTEM.powershell(),
|
|
28683
|
-
scriptArgs("expand-archive.ps1", ["-Archive", zip, "-Destination", destination])
|
|
28696
|
+
scriptArgs("expand-archive.ps1", ["-Archive", zip, "-Destination", destination]),
|
|
28697
|
+
{ lowPriority: true }
|
|
28684
28698
|
);
|
|
28685
28699
|
}
|
|
28686
28700
|
if (status !== 0) throw new Error("Could not extract " + archive);
|
|
@@ -7,13 +7,13 @@ import path from 'node:path';
|
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import { agentNameProblem, agentsPage, agentsView } from '../app/features/agents/index.js';
|
|
9
9
|
import { DEFINITIONS, NAV, navSections, navViews, QUERIES, VIEWS, viewById } from '../app/features/defs.js';
|
|
10
|
-
import { accountsPage, agentPage, listAccounts } from '../app/features/accounts/index.js';
|
|
10
|
+
import { accountsPage, agentPage, listAccounts, listServices, } from '../app/features/accounts/index.js';
|
|
11
11
|
import { addProject, projectRoots, projectsPage } from '../app/features/projects/index.js';
|
|
12
12
|
import { cleanData, dataPage, showData } from '../app/features/data/index.js';
|
|
13
13
|
import { showStorage, storagePage, storageView, } from '../app/features/storage/index.js';
|
|
14
14
|
import { insideSandbox, isSandboxRunning } from '../host/sandbox/index.js';
|
|
15
15
|
import { CRASH, listLogs, logsPage, tailLog } from '../app/features/logs/index.js';
|
|
16
|
-
import { DEFAULTS } from '../core/config/index.js';
|
|
16
|
+
import { DEFAULTS, loadConfig } from '../core/config/index.js';
|
|
17
17
|
import { sandboxPage } from '../app/features/sandbox/index.js';
|
|
18
18
|
import { closeSession, sessionsPage, startShell, } from '../app/features/sessions/index.js';
|
|
19
19
|
import { APP_GROUPS, appsPage, listApps } from '../app/features/apps/index.js';
|
|
@@ -460,6 +460,24 @@ export const appSuite = {
|
|
|
460
460
|
storageRoot: t.at('app-apps', 'storage'),
|
|
461
461
|
dataPath: t.dir('app-apps', 'data'),
|
|
462
462
|
};
|
|
463
|
+
t.section('a page read after an action shows what the action saved');
|
|
464
|
+
const freshConfig = t.writeJson(t.at('app-fresh', 'config.json'), {
|
|
465
|
+
storage: { root: t.dir('app-fresh', 'storage') },
|
|
466
|
+
});
|
|
467
|
+
const freshCtx = {
|
|
468
|
+
loaded: loadConfig(freshConfig),
|
|
469
|
+
options: {},
|
|
470
|
+
storageRoot: t.at('app-fresh', 'storage'),
|
|
471
|
+
dataPath: t.dir('app-fresh', 'data'),
|
|
472
|
+
};
|
|
473
|
+
const shareOf = async () => (await readQuery(listServices, freshCtx, { name: 'comet' })).services[0]?.share;
|
|
474
|
+
t.check((await shareOf()) === false, 'a service starts not shared');
|
|
475
|
+
await runDefinition('settings.set', freshCtx, { scope: 'user', key: 'accounts.comet.share', value: true }, quiet);
|
|
476
|
+
t.check((await shareOf()) === true, 'after the share toggle runs, the service page reads it as shared');
|
|
477
|
+
await runDefinition('settings.set', freshCtx, { scope: 'user', key: 'accounts.comet.share', value: false }, quiet);
|
|
478
|
+
t.check((await shareOf()) === false, 'and as not shared again after the next toggle');
|
|
479
|
+
await runDefinition('apps.toggle', freshCtx, { id: 'perplexity-desktop', on: true }, quiet);
|
|
480
|
+
t.check(freshCtx.loaded.config.apps.install.includes('perplexity-desktop'), 'an app turned on in Apps is in the settings every page reads next');
|
|
463
481
|
await runDefinition('apps.toggle', appsCtx, { id: 'lazygit', on: true }, quiet);
|
|
464
482
|
const onText = fs.readFileSync(appsConfig, 'utf8');
|
|
465
483
|
await runDefinition('apps.toggle', appsCtx, { id: 'lazygit', on: false }, quiet);
|
|
@@ -4,7 +4,9 @@ import { BootRunner, checkGraph, duration } from '../guest/boot/runner.js';
|
|
|
4
4
|
import { BOOT_TASKS, STAGES, stageTitle } from '../guest/boot/graph.js';
|
|
5
5
|
import { backgroundNames, mergeParts, runSplit } from '../guest/toolchains/split.js';
|
|
6
6
|
import { StepScheduler } from '../guest/toolchains/step-scheduler.js';
|
|
7
|
-
import
|
|
7
|
+
import os from 'node:os';
|
|
8
|
+
import { Limiter, asBackground, installerRetry, INSTALLER_RETRIES, net, heavy, installer, } from '../shared/concurrency/index.js';
|
|
9
|
+
import { spawnAsync } from '../shared/download/index.js';
|
|
8
10
|
const deferred = () => {
|
|
9
11
|
let resolve = () => undefined;
|
|
10
12
|
let reject = (_) => undefined;
|
|
@@ -288,6 +290,18 @@ export const bootRunnerSuite = {
|
|
|
288
290
|
t.check(message.includes('nested pool') && again.includes('nested pool'), 'taking a second pool (or the same one) while holding one throws "nested pool"', message);
|
|
289
291
|
t.check((await a.run(() => 7)) === 7 && a.running === 0, 'the slot is free again after a nested-pool error');
|
|
290
292
|
}
|
|
293
|
+
{
|
|
294
|
+
// At most 3 downloads + 2 unpacks + 1 installer run at once, whatever the boot tasks, steps and apps ask for.
|
|
295
|
+
const busy = async (pool) => {
|
|
296
|
+
await Promise.all(Array.from({ length: 12 }, () => pool.run(() => sleep(5))));
|
|
297
|
+
return pool.peak;
|
|
298
|
+
};
|
|
299
|
+
t.check((await busy(net)) <= 3 && (await busy(heavy)) <= 2 && (await busy(installer)) <= 1, 'the shared pools cap at net 3, heavy 2 and installer 1', 'net ' + net.peak + ', heavy ' + heavy.peak + ', installer ' + installer.peak);
|
|
300
|
+
const script = 'setTimeout(() => process.exit(require("os").getPriority() > 0 ? 0 : 3), 400)';
|
|
301
|
+
const low = await spawnAsync(process.execPath, ['-e', script], { lowPriority: true });
|
|
302
|
+
const normal = await spawnAsync(process.execPath, ['-e', script]);
|
|
303
|
+
t.check(low === 0 && normal === 3 && os.getPriority() <= 0, 'lowPriority starts a program below normal priority; the default stays normal', 'low ' + low + ', normal ' + normal);
|
|
304
|
+
}
|
|
291
305
|
t.check(installerRetry(1618, 1) &&
|
|
292
306
|
installerRetry(1618, INSTALLER_RETRIES) &&
|
|
293
307
|
!installerRetry(1618, INSTALLER_RETRIES + 1) &&
|
|
@@ -12,7 +12,7 @@ import { isWin } from '../core/util/index.js';
|
|
|
12
12
|
import { ConfigSchema } from '../core/schema/index.js';
|
|
13
13
|
import { decodeText, encodeText, readBoundedFile } from '../shared/io/index.js';
|
|
14
14
|
import { SYSTEM } from '../shared/system.js';
|
|
15
|
-
import { chooseEngine, ddcVars, enginePlaceProblem, ENGINE_NEED_BYTES, engineAt, engineExtraDirs, engineToolDirs, engineVars, entriesUnder, fileAssociationPlan, findEngines, findUproject, hasMcpPlugin, incompleteDirs, isBuildId, installLocationOf, itemSizes, launcherEntriesFor, launcherEntry, launcherInstallations, mergeLauncherInstalled, parseBuildVersion, parseEngineAssociation, preferredInstalled, registryPlan, restoreItems, saveItems, setLauncherInstallLocation, stableBuildId, UNREAL_STATUS_FILE, unrealGuideLines, unrealSummaryLine, uprojectAssociation, vaultDirsFromIni, vaultPacks, vsVerdict, VsSetupReportSchema, withInstallLocation, } from '../shared/unreal/index.js';
|
|
15
|
+
import { chooseEngine, ddcVars, enginePlaceProblem, ENGINE_NEED_BYTES, engineAt, engineExtraDirs, engineToolDirs, engineVars, entriesUnder, fileAssociationPlan, findEngines, findUproject, hasMcpPlugin, incompleteDirs, isBuildId, installLocationOf, itemSizes, launcherEntriesFor, launcherEntry, launcherInstallations, mergeLauncherInstalled, parseBuildVersion, parseEngineAssociation, preferredInstalled, registryPlan, relocateItem, restoreItems, saveItems, setLauncherInstallLocation, stableBuildId, UNREAL_STATUS_FILE, unrealGuideLines, unrealSummaryLine, uprojectAssociation, vaultDirsFromIni, vaultPacks, vsVerdict, VsSetupReportSchema, withInstallLocation, } from '../shared/unreal/index.js';
|
|
16
16
|
import { discoverPcInstalls } from '../host/pc-installs/index.js';
|
|
17
17
|
import { findEngineFolders, findUnrealInstalls, pcSourceBuilds, regValues } from '../host/pc-installs/unreal.js';
|
|
18
18
|
import { findEpicGames } from '../host/pc-installs/epic.js';
|
|
@@ -436,6 +436,25 @@ export const enginesSuite = {
|
|
|
436
436
|
'relative',
|
|
437
437
|
]);
|
|
438
438
|
t.equal(folders.map((f) => [f.id, f.writable]), [['dir-UnrealEngine', true]], 'a registered folder is mapped writable; one without an engine is left out');
|
|
439
|
+
const pcManifests = t.dir('pc-pcManifests');
|
|
440
|
+
const itemText = JSON.stringify({
|
|
441
|
+
AppName: 'UE_5.4',
|
|
442
|
+
InstallLocation: pcLauncher.replace(/\\/g, '/'),
|
|
443
|
+
ManifestLocation: pcLauncher + '/.egstore',
|
|
444
|
+
StagingLocation: 'D:\\Elsewhere\\bps',
|
|
445
|
+
InstallSize: 123,
|
|
446
|
+
});
|
|
447
|
+
fs.writeFileSync(path.join(pcManifests, 'ABCDEF0123.item'), itemText);
|
|
448
|
+
fs.writeFileSync(path.join(pcManifests, 'notes.txt'), 'not a manifest');
|
|
449
|
+
const pcRegistered = findEngineFolders({ read: DISK.read, builds: '', launcherInstalled: dat, manifests: pcManifests, list: DISK.list }, [pcLauncher])[0];
|
|
450
|
+
t.check(pcRegistered?.launcher?.itemId === 'item54' && pcRegistered.launcherItem?.name === 'ABCDEF0123.item', 'a pcRegistered folder the launcher installed keeps its ids and its manifest');
|
|
451
|
+
const moved = relocateItem(itemText, pcLauncher, 'C:\\PcInstalls\\unreal\\dir-UE_5.4');
|
|
452
|
+
const movedItem = JSON.parse(moved ?? '{}');
|
|
453
|
+
t.check(movedItem.InstallLocation === 'C:\\PcInstalls\\unreal\\dir-UE_5.4' &&
|
|
454
|
+
movedItem.ManifestLocation === 'C:\\PcInstalls\\unreal\\dir-UE_5.4\\.egstore' &&
|
|
455
|
+
!('StagingLocation' in movedItem) &&
|
|
456
|
+
movedItem.InstallSize === 123, "the manifest names the sandbox's folder; a path elsewhere on this PC is dropped");
|
|
457
|
+
t.equal(relocateItem(itemText, path.join(pcRoot, 'other'), 'C:\\x'), null, 'a manifest of another folder: none');
|
|
439
458
|
t.equal(findEpicGames(dat, true).map((g) => g.id), ['Fortnite'], "the launcher's games are the epic-game installs (engines and the Fab plugin in one are not)");
|
|
440
459
|
t.equal(findEpicGames(dat, ['nothing']), [], 'a list maps only those games');
|
|
441
460
|
t.check(engineFolderProblem(pcSource, DISK.read) === null, 'Register an engine folder accepts an engine folder');
|
|
@@ -470,6 +489,8 @@ export const enginesSuite = {
|
|
|
470
489
|
t.check(new Set(ids).size === ids.length, 'every app id is used once');
|
|
471
490
|
t.equal(GAMEDEV_APPS.map((a) => a.id), ['krita', 'inkscape', 'audacity', 'renderdoc', 'f3d', 'imagemagick', 'nomacs', 'unity-mcp', 'openupm-cli'], 'Krita, Inkscape, Audacity, RenderDoc, F3D, ImageMagick, nomacs, then the Unity add-ons (Blender was there)');
|
|
472
491
|
t.check(ids.includes('blender'), 'Blender is in the catalogue');
|
|
492
|
+
const f3d = GAMEDEV_APPS.find((a) => a.id === 'f3d');
|
|
493
|
+
t.check(f3d.onPath === true && !f3d.cli, 'F3D is on PATH (the preview guide runs `f3d`) and keeps its shortcut');
|
|
473
494
|
t.check(GAMEDEV_APPS.every((a) => (a.category === 'gamedev' || a.id === 'unity-mcp') && a.exe && a.about.length > 20), 'each is a game-development app with its program');
|
|
474
495
|
const audacity = new RegExp(GAMEDEV_APPS.find((a) => a.id === 'audacity').source.asset);
|
|
475
496
|
t.check(audacity.test('audacity-win-4.0.2-x86_64.7z') &&
|
|
@@ -19,6 +19,7 @@ import { SECTION_LABELS } from '../cli/menu/shell.js';
|
|
|
19
19
|
import { Frame, ListScreen, OverlayScreen, Text } from '../cli/tui/index.js';
|
|
20
20
|
export const SIZES = [
|
|
21
21
|
{ width: 200, height: 60 },
|
|
22
|
+
{ width: 120, height: 30 },
|
|
22
23
|
{ width: 100, height: 30 },
|
|
23
24
|
{ width: 80, height: 24 },
|
|
24
25
|
{ width: 60, height: 20 },
|
|
@@ -38,6 +39,48 @@ const DATA_FOLDER_ROW = [
|
|
|
38
39
|
const ACCOUNTS = {
|
|
39
40
|
agent: 'claude',
|
|
40
41
|
services: [
|
|
42
|
+
{
|
|
43
|
+
kind: 'epic',
|
|
44
|
+
label: SERVICE_SPECS.epic.label,
|
|
45
|
+
share: true,
|
|
46
|
+
state: 'none',
|
|
47
|
+
source: null,
|
|
48
|
+
savedAt: null,
|
|
49
|
+
summary: null,
|
|
50
|
+
heldBy: null,
|
|
51
|
+
usedBy: ['unreal'],
|
|
52
|
+
usedFor: 'unreal',
|
|
53
|
+
warnings: [...SERVICE_SPECS.epic.warnings],
|
|
54
|
+
canImport: true,
|
|
55
|
+
canLogin: false,
|
|
56
|
+
needsFile: false,
|
|
57
|
+
fromPc: true,
|
|
58
|
+
hasFileSource: false,
|
|
59
|
+
onPc: true,
|
|
60
|
+
sandboxOnly: false,
|
|
61
|
+
ready: true,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
kind: 'keystore',
|
|
65
|
+
label: SERVICE_SPECS.keystore.label,
|
|
66
|
+
share: false,
|
|
67
|
+
state: 'none',
|
|
68
|
+
source: null,
|
|
69
|
+
savedAt: null,
|
|
70
|
+
summary: null,
|
|
71
|
+
heldBy: null,
|
|
72
|
+
usedBy: ['flutter'],
|
|
73
|
+
usedFor: 'flutter',
|
|
74
|
+
warnings: [...SERVICE_SPECS.keystore.warnings],
|
|
75
|
+
canImport: true,
|
|
76
|
+
canLogin: false,
|
|
77
|
+
needsFile: true,
|
|
78
|
+
fromPc: false,
|
|
79
|
+
hasFileSource: true,
|
|
80
|
+
onPc: null,
|
|
81
|
+
sandboxOnly: false,
|
|
82
|
+
ready: false,
|
|
83
|
+
},
|
|
41
84
|
{
|
|
42
85
|
kind: 'perplexity',
|
|
43
86
|
label: SERVICE_SPECS.perplexity.label,
|
|
@@ -53,6 +96,10 @@ const ACCOUNTS = {
|
|
|
53
96
|
canImport: true,
|
|
54
97
|
canLogin: true,
|
|
55
98
|
needsFile: false,
|
|
99
|
+
fromPc: true,
|
|
100
|
+
hasFileSource: true,
|
|
101
|
+
onPc: true,
|
|
102
|
+
sandboxOnly: false,
|
|
56
103
|
ready: true,
|
|
57
104
|
},
|
|
58
105
|
{
|
|
@@ -70,6 +117,10 @@ const ACCOUNTS = {
|
|
|
70
117
|
canImport: false,
|
|
71
118
|
canLogin: false,
|
|
72
119
|
needsFile: false,
|
|
120
|
+
fromPc: false,
|
|
121
|
+
hasFileSource: false,
|
|
122
|
+
onPc: null,
|
|
123
|
+
sandboxOnly: true,
|
|
73
124
|
ready: true,
|
|
74
125
|
},
|
|
75
126
|
],
|
|
@@ -423,7 +474,7 @@ export function renderScreens(dir) {
|
|
|
423
474
|
],
|
|
424
475
|
escape: 'cancel',
|
|
425
476
|
});
|
|
426
|
-
out.push(block('5 Settings: Save / Discard / Cancel', Frame.render({ ...dialog.render(bodySize), nav }, size.width, size.height).map((l) => Text.strip(l).replace(/\s+$/, '')), size), block('6 Accounts', draw(5, accountsOptions(ACCOUNTS), size, status), size), block('6 Accounts · codex', draw(5, { ...accountsOptions(ACCOUNTS), startCategory: 'codex' }, size, status), size), block('6 Accounts · opencode (login not kept)', draw(5, { ...accountsOptions(ACCOUNTS), startCategory: 'opencode' }, size, status), size));
|
|
477
|
+
out.push(block('5 Settings: Save / Discard / Cancel', Frame.render({ ...dialog.render(bodySize), nav }, size.width, size.height).map((l) => Text.strip(l).replace(/\s+$/, '')), size), block('6 Accounts', draw(5, accountsOptions(ACCOUNTS), size, status), size), ...['epic', 'perplexity', 'comet'].map((kind) => block('6 Accounts · ' + kind, draw(5, { ...accountsOptions(ACCOUNTS), startCategory: 'service:' + kind }, size, status), size)), block('6 Accounts · codex', draw(5, { ...accountsOptions(ACCOUNTS), startCategory: 'codex' }, size, status), size), block('6 Accounts · opencode (login not kept)', draw(5, { ...accountsOptions(ACCOUNTS), startCategory: 'opencode' }, size, status), size));
|
|
427
478
|
for (const category of ['updates', 'data', 'health', 'logs', 'more'])
|
|
428
479
|
out.push(block('7 Maintenance · ' + category, draw(6, { ...maintenanceOptions(maintenance), startCategory: category }, size, status), size));
|
|
429
480
|
}
|