windows-development-sandbox 1.23.2 → 1.25.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/config.example.json +0 -1
- package/dist/bin/agent-sandbox.js +2 -2
- package/dist/bin/{chunk-USTRSHIE.js → chunk-IZRGTSQ5.js} +158 -131
- package/dist/bin/{chunk-QFSJX2KW.js → chunk-KH4MI2U5.js} +1 -1
- package/dist/bin/{chunk-7YPEDAJD.js → chunk-SUYYVIDW.js} +1 -1
- 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/core/config/defaults.js +0 -1
- package/dist/core/detect/toolchains.js +0 -6
- package/dist/core/schema/config.d.ts +1 -2
- package/dist/core/schema/toolchains.d.ts +1 -2
- package/dist/core/schema/toolchains.js +3 -6
- package/dist/guest/agents/agent-files.d.ts +11 -7
- package/dist/guest/agents/agent-files.js +37 -11
- package/dist/guest/agents/local-state.d.ts +2 -1
- package/dist/guest/agents/local-state.js +2 -1
- package/dist/guest/boot/boot-console.d.ts +28 -0
- package/dist/guest/boot/boot-console.js +98 -0
- package/dist/guest/boot/boot.d.ts +8 -1
- package/dist/guest/boot/boot.js +66 -42
- package/dist/guest/boot/graph.d.ts +9 -5
- package/dist/guest/boot/graph.js +8 -2
- package/dist/guest/boot/progress-view.d.ts +116 -0
- package/dist/guest/boot/progress-view.js +456 -0
- package/dist/guest/boot/runner.d.ts +20 -10
- package/dist/guest/boot/runner.js +39 -47
- package/dist/guest/runtime/log-line.d.ts +7 -0
- package/dist/guest/runtime/log-line.js +18 -0
- package/dist/guest/runtime/log.d.ts +17 -4
- package/dist/guest/runtime/log.js +40 -17
- package/dist/guest/runtime/process.d.ts +9 -0
- package/dist/guest/runtime/process.js +69 -8
- package/dist/guest/setup/environment.js +9 -4
- package/dist/guest/setup/hooks.d.ts +2 -0
- package/dist/guest/setup/hooks.js +4 -0
- package/dist/guest/setup/path-plan.d.ts +12 -0
- package/dist/guest/setup/path-plan.js +18 -0
- package/dist/guest/toolchains/native/unreal.js +4 -6
- package/dist/guest/toolchains/native/visual-studio.d.ts +14 -14
- package/dist/guest/toolchains/native/visual-studio.js +145 -174
- package/dist/guest/toolchains/native/vs-persist.d.ts +189 -0
- package/dist/guest/toolchains/native/vs-persist.js +256 -0
- package/dist/guest/toolchains/native/vs-request.d.ts +6 -26
- package/dist/guest/toolchains/native/vs-request.js +16 -50
- package/dist/guest/toolchains/plan.js +11 -14
- package/dist/host/migrate/migrations/drop-vs-install-files.d.ts +5 -0
- package/dist/host/migrate/migrations/drop-vs-install-files.js +34 -0
- package/dist/host/migrate/registry.js +7 -1
- package/dist/runtime/agent.js +67 -26
- package/dist/runtime/daemon.js +958 -716
- package/dist/runtime/db.js +67 -26
- package/dist/runtime/main.js +1792 -1038
- package/dist/runtime/netproxy.js +3 -6
- package/dist/runtime/tool.js +44 -24
- package/dist/runtime/view.js +4 -7
- package/dist/selftest/agent-paths.test.js +17 -1
- package/dist/selftest/agent-settings.test.js +36 -5
- package/dist/selftest/boot-console.test.d.ts +2 -0
- package/dist/selftest/boot-console.test.js +291 -0
- package/dist/selftest/boot-runner.test.js +10 -12
- package/dist/selftest/guest-boot.test.js +7 -1
- package/dist/selftest/index.js +2 -0
- package/dist/selftest/layout.test.js +4 -0
- package/dist/selftest/migrate.test.js +21 -0
- package/dist/selftest/persisted-installs.test.js +169 -33
- package/dist/selftest/support/engine-golden.js +2 -0
- package/dist/selftest/support/fixtures.d.ts +1 -2
- package/dist/shared/channel/schema.d.ts +3 -6
- package/dist/shared/pty/terminal.js +2 -1
- package/dist/sync/watcher.js +5 -1
- 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/sandbox/scripts/restore-visual-studio.ps1 +78 -0
- package/sandbox/scripts/save-visual-studio.ps1 +106 -0
- package/schemas/config.schema.json +3 -7
- package/schemas/sandbox-config.schema.json +3 -7
- package/dist/guest/toolchains/native/autosdk.d.ts +0 -3
- package/dist/guest/toolchains/native/autosdk.js +0 -50
package/dist/bin/claude-host.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-SUYYVIDW.js";
|
|
6
|
+
import "./chunk-IZRGTSQ5.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/claude-host.ts
|
|
9
9
|
var args = process.argv.slice(2);
|
package/dist/bin/claude-sbx.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-SUYYVIDW.js";
|
|
6
|
+
import "./chunk-IZRGTSQ5.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/claude-sbx.ts
|
|
9
9
|
run(process.argv.slice(2), { harness: "claude" });
|
package/dist/bin/codex-sbx.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-SUYYVIDW.js";
|
|
6
|
+
import "./chunk-IZRGTSQ5.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/codex-sbx.ts
|
|
9
9
|
run(process.argv.slice(2), { harness: "codex" });
|
package/dist/bin/gemini-sbx.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-SUYYVIDW.js";
|
|
6
|
+
import "./chunk-IZRGTSQ5.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/gemini-sbx.ts
|
|
9
9
|
run(process.argv.slice(2), { harness: "gemini" });
|
package/dist/bin/sandbox.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-SUYYVIDW.js";
|
|
6
|
+
import "./chunk-IZRGTSQ5.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/sandbox.ts
|
|
9
9
|
run(process.argv.slice(2));
|
package/dist/bin/sbx-hide.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-SUYYVIDW.js";
|
|
6
|
+
import "./chunk-IZRGTSQ5.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/sbx-hide.ts
|
|
9
9
|
run(process.argv.slice(2), { command: "hide" });
|
package/dist/bin/sbx-show.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-SUYYVIDW.js";
|
|
6
|
+
import "./chunk-IZRGTSQ5.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/sbx-show.ts
|
|
9
9
|
run(process.argv.slice(2), { command: "show" });
|
|
@@ -127,15 +127,9 @@ function applyImplications(settings, result) {
|
|
|
127
127
|
imply(settings, result, 'android', 'React Native builds for Android');
|
|
128
128
|
if (result.godot.on && settings.godot.dotnet === true)
|
|
129
129
|
imply(settings, result, 'dotnet', "Godot's .NET build");
|
|
130
|
-
if (result.unreal.on && settings.unreal.visualStudio === 'autosdk')
|
|
131
|
-
imply(settings, result, 'msvc', 'Unreal builds from the portable MSVC (AutoSDK)');
|
|
132
|
-
// Unreal's licence acceptance covers the MSVC it builds from (the same Visual Studio terms).
|
|
133
|
-
const autosdkLicence = settings.unreal.visualStudio === 'autosdk' && settings.unreal.acceptLicense;
|
|
134
130
|
for (const name of LICENSED_TOOLCHAINS) {
|
|
135
131
|
if (settings[name].enabled !== 'auto' || !result[name].on || settings[name].acceptLicense)
|
|
136
132
|
continue;
|
|
137
|
-
if (name === 'msvc' && autosdkLicence)
|
|
138
|
-
continue;
|
|
139
133
|
result[name] = {
|
|
140
134
|
on: false,
|
|
141
135
|
reason: 'would be used (' + result[name].reason + '); set toolchains.' + name + '.acceptLicense to install it',
|
|
@@ -195,10 +195,9 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
195
195
|
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
196
196
|
acceptLicense: z.ZodBoolean;
|
|
197
197
|
components: z.ZodArray<z.ZodString>;
|
|
198
|
-
keepInstallFiles: z.ZodBoolean;
|
|
199
198
|
visualStudio: z.ZodEnum<{
|
|
200
199
|
full: "full";
|
|
201
|
-
|
|
200
|
+
buildtools: "buildtools";
|
|
202
201
|
}>;
|
|
203
202
|
persistEngines: z.ZodBoolean;
|
|
204
203
|
derivedDataCache: z.ZodEnum<{
|
|
@@ -38,10 +38,9 @@ export declare const ToolchainsSchema: z.ZodObject<{
|
|
|
38
38
|
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
39
39
|
acceptLicense: z.ZodBoolean;
|
|
40
40
|
components: z.ZodArray<z.ZodString>;
|
|
41
|
-
keepInstallFiles: z.ZodBoolean;
|
|
42
41
|
visualStudio: z.ZodEnum<{
|
|
43
42
|
full: "full";
|
|
44
|
-
|
|
43
|
+
buildtools: "buildtools";
|
|
45
44
|
}>;
|
|
46
45
|
persistEngines: z.ZodBoolean;
|
|
47
46
|
derivedDataCache: z.ZodEnum<{
|
|
@@ -54,17 +54,14 @@ export const ToolchainsSchema = z.strictObject({
|
|
|
54
54
|
sdkVersion: z.string().min(1).describe('"latest" or a Windows SDK build, e.g. "26100" or "10.0.22621".'),
|
|
55
55
|
}),
|
|
56
56
|
unreal: z.strictObject({
|
|
57
|
-
enabled: enabled('Unreal Engine development: Visual Studio Community 2022 with the C++ game workload (MSVC, a Windows 11 SDK, .NET Framework targeting packs, Unreal integration and the Epic Games Launcher) and the DirectX End-User Runtime.
|
|
57
|
+
enabled: enabled('Unreal Engine development: Visual Studio Community 2022 with the C++ game workload (MSVC, a Windows 11 SDK, .NET Framework targeting packs, Unreal integration and the Epic Games Launcher) and the DirectX End-User Runtime. Visual Studio is installed once and kept on the data disk (~6.5 GB); later boots put it back in seconds. The engine itself comes from the Epic Games Launcher or its source.', 'a .uproject or .uplugin'),
|
|
58
58
|
acceptLicense: z
|
|
59
59
|
.boolean()
|
|
60
60
|
.describe('Required to install: you accept the Visual Studio Community licence terms (https://visualstudio.microsoft.com/license-terms/) and the DirectX End-User Runtime licence.'),
|
|
61
61
|
components: StringsSchema.describe('More Visual Studio workload or component IDs to add, e.g. ["Microsoft.VisualStudio.Component.VC.Llvm.Clang"].'),
|
|
62
|
-
keepInstallFiles: z
|
|
63
|
-
.boolean()
|
|
64
|
-
.describe('Keep an offline copy of the Visual Studio install files in tools\\visualstudio (~10 GB, made once), so later boots install without downloading them again. Skipped while that disk has too little room.'),
|
|
65
62
|
visualStudio: z
|
|
66
|
-
.enum(['full', '
|
|
67
|
-
.describe('"full":
|
|
63
|
+
.enum(['full', 'buildtools'])
|
|
64
|
+
.describe('"full": Visual Studio Community with the C++ game workload (the IDE, its debugger and Unreal integration). "buildtools": only the Visual Studio Build Tools (MSVC, the Windows SDK and the .NET Framework parts UnrealBuildTool needs; no IDE). Either is installed once and kept on the data disk (tools\\visualstudio\\persist, ~6.5 GB for Community); later boots put it back in seconds.'),
|
|
68
65
|
persistEngines: z
|
|
69
66
|
.boolean()
|
|
70
67
|
.describe('Engines the Epic Games Launcher installs go to tools\\unreal\\engines (kept between sandboxes, 40-60 GB each) and are registered with the launcher again every boot. Off: they go on the sandbox disk and are lost when it closes. Engines installed on this PC can be mapped instead (pcInstalls.unrealEngines).'),
|
|
@@ -52,9 +52,10 @@ export declare function bootResetPaths(agents: Readonly<Record<string, Harness>>
|
|
|
52
52
|
}[];
|
|
53
53
|
type CodexSettings = Config['codex'];
|
|
54
54
|
/**
|
|
55
|
-
* The flags every Codex start gets
|
|
56
|
-
*
|
|
57
|
-
* setup for
|
|
55
|
+
* The flags every Codex start through the sandbox gets (the codex.cmd shim, the daemon's sessions). Flags beat
|
|
56
|
+
* config.toml and a resumed thread's saved permissions; config.toml carries the same settings for a start without
|
|
57
|
+
* them (codexConfigOwned). Full access with no questions is the one flag that skips Codex's Windows sandbox setup for
|
|
58
|
+
* certain. Pure.
|
|
58
59
|
*/
|
|
59
60
|
export declare function codexArguments(c: CodexSettings): string[];
|
|
60
61
|
/** The arguments an agent always starts with: its own, and for codex the sandbox's settings. */
|
|
@@ -62,10 +63,13 @@ export declare function agentArguments(name: string, harness: Harness, codex: Co
|
|
|
62
63
|
/** The largest config.toml the sandbox edits. */
|
|
63
64
|
export declare const MAX_CODEX_CONFIG_BYTES: number;
|
|
64
65
|
/**
|
|
65
|
-
* Codex's config.toml as the sandbox wants it, every other line byte for byte
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
66
|
+
* Codex's config.toml as the sandbox wants it, every other line byte for byte. Above the first table, under the
|
|
67
|
+
* marker comment: sandbox_mode, approval_policy (and model, model_reasoning_effort when set), so ANY start of Codex
|
|
68
|
+
* obeys the codex settings, also one without the shim's flags (a copy installed with npm -g). The marked lines are
|
|
69
|
+
* replaced each time; a key the user set on a line of their own above the first table is left to them.
|
|
70
|
+
* `[windows] sandbox` follows windowsSandbox ("off" removes the line, which Codex adds back after its own setup, so it
|
|
71
|
+
* does not set up its own sandbox users), and mcp_oauth_credentials_store = "file" is added when it is not set.
|
|
72
|
+
* Keeps the file's line endings; running it again changes nothing. Pure.
|
|
69
73
|
*/
|
|
70
74
|
export declare function codexConfigOwned(toml: string, c: CodexSettings): string;
|
|
71
75
|
/**
|
|
@@ -63,10 +63,17 @@ export function bootResetPaths(agents, stateDir) {
|
|
|
63
63
|
}
|
|
64
64
|
/** The marker the sandbox puts above the lines it writes into config.toml. */
|
|
65
65
|
const CODEX_MARKER = '# Set by the sandbox';
|
|
66
|
+
/** The full marker line: what it is and where to change it. */
|
|
67
|
+
const CODEX_MARKER_LINE = CODEX_MARKER + ' from its codex settings (`sandbox config`); a line of your own without it wins.';
|
|
68
|
+
/** Markers whose lines count as the sandbox's: CODEX_MARKER, and a hand-made fix's (`# agent-sandbox:`). */
|
|
69
|
+
const CODEX_MARKERS = [CODEX_MARKER, '# agent-sandbox:'];
|
|
70
|
+
/** The top-level keys the sandbox writes under its marker. */
|
|
71
|
+
const CODEX_OWNED_KEYS = ['sandbox_mode', 'approval_policy', 'model', 'model_reasoning_effort'];
|
|
66
72
|
/**
|
|
67
|
-
* The flags every Codex start gets
|
|
68
|
-
*
|
|
69
|
-
* setup for
|
|
73
|
+
* The flags every Codex start through the sandbox gets (the codex.cmd shim, the daemon's sessions). Flags beat
|
|
74
|
+
* config.toml and a resumed thread's saved permissions; config.toml carries the same settings for a start without
|
|
75
|
+
* them (codexConfigOwned). Full access with no questions is the one flag that skips Codex's Windows sandbox setup for
|
|
76
|
+
* certain. Pure.
|
|
70
77
|
*/
|
|
71
78
|
export function codexArguments(c) {
|
|
72
79
|
const out = c.sandboxMode === 'danger-full-access' && c.approvalPolicy === 'never'
|
|
@@ -85,10 +92,13 @@ export function agentArguments(name, harness, codex) {
|
|
|
85
92
|
/** The largest config.toml the sandbox edits. */
|
|
86
93
|
export const MAX_CODEX_CONFIG_BYTES = 1024 * 1024;
|
|
87
94
|
/**
|
|
88
|
-
* Codex's config.toml as the sandbox wants it, every other line byte for byte
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
95
|
+
* Codex's config.toml as the sandbox wants it, every other line byte for byte. Above the first table, under the
|
|
96
|
+
* marker comment: sandbox_mode, approval_policy (and model, model_reasoning_effort when set), so ANY start of Codex
|
|
97
|
+
* obeys the codex settings, also one without the shim's flags (a copy installed with npm -g). The marked lines are
|
|
98
|
+
* replaced each time; a key the user set on a line of their own above the first table is left to them.
|
|
99
|
+
* `[windows] sandbox` follows windowsSandbox ("off" removes the line, which Codex adds back after its own setup, so it
|
|
100
|
+
* does not set up its own sandbox users), and mcp_oauth_credentials_store = "file" is added when it is not set.
|
|
101
|
+
* Keeps the file's line endings; running it again changes nothing. Pure.
|
|
92
102
|
*/
|
|
93
103
|
export function codexConfigOwned(toml, c) {
|
|
94
104
|
const eol = toml.includes('\r\n') ? '\r\n' : '\n';
|
|
@@ -96,15 +106,31 @@ export function codexConfigOwned(toml, c) {
|
|
|
96
106
|
let top = firstTable < 0 ? toml : toml.slice(0, firstTable);
|
|
97
107
|
const tables = firstTable < 0 ? '' : toml.slice(firstTable);
|
|
98
108
|
top = top.replace(MARKED_LINES, '');
|
|
99
|
-
if (c.mcpLoginsInFile &&
|
|
109
|
+
if (c.mcpLoginsInFile && !hasKey(top, 'mcp_oauth_credentials_store')) {
|
|
100
110
|
if (top && !top.endsWith('\n'))
|
|
101
111
|
top += eol;
|
|
102
112
|
top += 'mcp_oauth_credentials_store = "file"' + eol + (tables ? eol : '');
|
|
103
113
|
}
|
|
104
|
-
|
|
114
|
+
const values = {
|
|
115
|
+
sandbox_mode: c.sandboxMode,
|
|
116
|
+
approval_policy: c.approvalPolicy,
|
|
117
|
+
model: c.model,
|
|
118
|
+
model_reasoning_effort: c.reasoningEffort === 'default' ? '' : c.reasoningEffort,
|
|
119
|
+
};
|
|
120
|
+
const lines = CODEX_OWNED_KEYS.filter((k) => values[k] && !hasKey(top, k)).map((k) => k + ' = ' + JSON.stringify(values[k]));
|
|
121
|
+
const marked = lines.length ? [CODEX_MARKER_LINE, ...lines].join(eol) + eol + (top || tables ? eol : '') : '';
|
|
122
|
+
return marked + top + codexWindowsSandbox(tables, c.windowsSandbox, eol);
|
|
123
|
+
}
|
|
124
|
+
/** True when the top of config.toml sets the key on a line of its own. */
|
|
125
|
+
function hasKey(top, key) {
|
|
126
|
+
return new RegExp('^[ \t]*' + key + '[ \t]*=', 'm').test(top);
|
|
105
127
|
}
|
|
106
|
-
/** The lines
|
|
107
|
-
const MARKED_LINES = new RegExp('^
|
|
128
|
+
/** The lines the sandbox wrote above the first table: a marker comment, the keys it owns, then one blank line. */
|
|
129
|
+
const MARKED_LINES = new RegExp('^(?:' +
|
|
130
|
+
CODEX_MARKERS.join('|') +
|
|
131
|
+
')[^\r\n]*\r?\n(?:(?:' +
|
|
132
|
+
CODEX_OWNED_KEYS.join('|') +
|
|
133
|
+
')[ \t]*=[^\r\n]*(?:\r?\n|$))*(?:[ \t]*\r?\n)?', 'm');
|
|
108
134
|
/** The tables of config.toml (from the first one on) with `[windows] sandbox` set to the mode, or removed for "off". */
|
|
109
135
|
function codexWindowsSandbox(tables, mode, eol) {
|
|
110
136
|
const setting = 'sandbox = "' + mode + '"';
|
|
@@ -7,7 +7,8 @@ export declare function localStateVars(): Record<string, string>;
|
|
|
7
7
|
export declare function resetMachineBound(): void;
|
|
8
8
|
/**
|
|
9
9
|
* Boot: Codex's config.toml follows the codex settings (codexConfigOwned): no Windows sandbox setup of its own, its MCP
|
|
10
|
-
* logins in a file
|
|
10
|
+
* logins in a file, the sandbox mode and approval policy for a start without the launch flags (codexArguments, which
|
|
11
|
+
* beat this file and still go on every start through the sandbox).
|
|
11
12
|
*/
|
|
12
13
|
export declare function codexBootConfig(): void;
|
|
13
14
|
/** Boot: the saved databases of every configured agent are copied to the sandbox's disk, where the agent runs them. */
|
|
@@ -104,7 +104,8 @@ export function resetMachineBound() {
|
|
|
104
104
|
}
|
|
105
105
|
/**
|
|
106
106
|
* Boot: Codex's config.toml follows the codex settings (codexConfigOwned): no Windows sandbox setup of its own, its MCP
|
|
107
|
-
* logins in a file
|
|
107
|
+
* logins in a file, the sandbox mode and approval policy for a start without the launch flags (codexArguments, which
|
|
108
|
+
* beat this file and still go on every start through the sandbox).
|
|
108
109
|
*/
|
|
109
110
|
export function codexBootConfig() {
|
|
110
111
|
if (dryRun || !session.agents?.codex || !session.codex)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type ReadyInfo, type ViewStage, type ViewTask } from './progress-view.js';
|
|
2
|
+
import type { BootTaskDef, RunnerObserver, TaskOutcome } from './runner.js';
|
|
3
|
+
export declare class BootConsole implements RunnerObserver {
|
|
4
|
+
private readonly view;
|
|
5
|
+
private readonly live;
|
|
6
|
+
private timer;
|
|
7
|
+
private open;
|
|
8
|
+
private constructor();
|
|
9
|
+
/** `plain`: ordered lines even on a terminal (a dry run). */
|
|
10
|
+
static create(stages: readonly ViewStage[], tasks: readonly ViewTask[], o: {
|
|
11
|
+
plain: boolean;
|
|
12
|
+
}): BootConsole;
|
|
13
|
+
/** Prints the header and takes the console. */
|
|
14
|
+
start(header: string): void;
|
|
15
|
+
started(task: BootTaskDef): void;
|
|
16
|
+
finished(task: BootTaskDef, outcome: TaskOutcome): void;
|
|
17
|
+
/** What a running task's place on its row says (null: its title). */
|
|
18
|
+
detail(taskId: string, text: string | null): void;
|
|
19
|
+
/** The tool summary: to the file now, to the console once the boot is ready. */
|
|
20
|
+
summary(lines: readonly string[]): void;
|
|
21
|
+
/** Runs `work` that writes to the terminal itself (the hooks). */
|
|
22
|
+
aside<T>(work: () => T): T;
|
|
23
|
+
/**
|
|
24
|
+
* The final summary (`ready`, or null when the boot failed); the console is the log's own again. Programs' output
|
|
25
|
+
* keeps going to the log (the background runs quiet: file only).
|
|
26
|
+
*/
|
|
27
|
+
release(ready: ReadyInfo | null): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// The boot's console on the sandbox's terminal: the live progress block when it is a terminal, ordered plain lines
|
|
2
|
+
// otherwise (and in a dry run). While it is open it takes the log's console lines and the output of the programs the
|
|
3
|
+
// boot starts; it is released, with the final summary, right before the first session takes the window.
|
|
4
|
+
import { log, record, routeConsole } from '../runtime/log.js';
|
|
5
|
+
import { routeOutput } from '../runtime/process.js';
|
|
6
|
+
import { CONSOLE_GLYPHS, ProgressView, readyLines, RICH_GLYPHS, } from './progress-view.js';
|
|
7
|
+
/** The spinner's pace (the elapsed times change every tenth of a second too). */
|
|
8
|
+
const FRAME_MS = 100;
|
|
9
|
+
const COLUMNS = 80;
|
|
10
|
+
const SHOW_CURSOR = '\x1b[?25h';
|
|
11
|
+
export class BootConsole {
|
|
12
|
+
view;
|
|
13
|
+
live;
|
|
14
|
+
timer = null;
|
|
15
|
+
open = false;
|
|
16
|
+
constructor(view, live) {
|
|
17
|
+
this.view = view;
|
|
18
|
+
this.live = live;
|
|
19
|
+
}
|
|
20
|
+
/** `plain`: ordered lines even on a terminal (a dry run). */
|
|
21
|
+
static create(stages, tasks, o) {
|
|
22
|
+
const live = !o.plain && process.stdout.isTTY === true;
|
|
23
|
+
// Windows Terminal sets WT_SESSION; the classic console's font has no braille or check marks.
|
|
24
|
+
const rich = live && Boolean(process.env.WT_SESSION);
|
|
25
|
+
const view = new ProgressView(stages, tasks, {
|
|
26
|
+
live,
|
|
27
|
+
glyphs: rich ? RICH_GLYPHS : CONSOLE_GLYPHS,
|
|
28
|
+
now: () => Date.now(),
|
|
29
|
+
screen: {
|
|
30
|
+
write: (text) => void process.stdout.write(text),
|
|
31
|
+
columns: () => process.stdout.columns ?? COLUMNS,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
return new BootConsole(view, live);
|
|
35
|
+
}
|
|
36
|
+
/** Prints the header and takes the console. */
|
|
37
|
+
start(header) {
|
|
38
|
+
record(header);
|
|
39
|
+
this.open = true;
|
|
40
|
+
this.view.start(header);
|
|
41
|
+
routeConsole({
|
|
42
|
+
line: (message, stage) => this.view.line(message, stage),
|
|
43
|
+
warning: (message) => this.view.warning(message),
|
|
44
|
+
notice: (message) => this.view.notice(message),
|
|
45
|
+
});
|
|
46
|
+
// Programs the boot starts would draw over the block (or between the plain stages): their output goes to the log;
|
|
47
|
+
// the hooks keep the terminal. After the release too: the background steps must not write into the session.
|
|
48
|
+
routeOutput({ capturing: () => !this.open || this.view.capturing, line: (text) => log(text) });
|
|
49
|
+
if (!this.live)
|
|
50
|
+
return;
|
|
51
|
+
this.timer = setInterval(() => this.view.tick(), FRAME_MS);
|
|
52
|
+
this.timer.unref();
|
|
53
|
+
// A crash must not leave the terminal without its cursor.
|
|
54
|
+
process.once('exit', () => {
|
|
55
|
+
if (this.open)
|
|
56
|
+
process.stdout.write(SHOW_CURSOR);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
started(task) {
|
|
60
|
+
this.view.started(task);
|
|
61
|
+
this.view.tick();
|
|
62
|
+
}
|
|
63
|
+
finished(task, outcome) {
|
|
64
|
+
this.view.finished(task, outcome);
|
|
65
|
+
this.view.tick();
|
|
66
|
+
}
|
|
67
|
+
/** What a running task's place on its row says (null: its title). */
|
|
68
|
+
detail(taskId, text) {
|
|
69
|
+
this.view.detail(taskId, text);
|
|
70
|
+
}
|
|
71
|
+
/** The tool summary: to the file now, to the console once the boot is ready. */
|
|
72
|
+
summary(lines) {
|
|
73
|
+
for (const line of lines)
|
|
74
|
+
record(' ' + line);
|
|
75
|
+
this.view.summary(lines);
|
|
76
|
+
}
|
|
77
|
+
/** Runs `work` that writes to the terminal itself (the hooks). */
|
|
78
|
+
aside(work) {
|
|
79
|
+
return this.view.aside(work);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The final summary (`ready`, or null when the boot failed); the console is the log's own again. Programs' output
|
|
83
|
+
* keeps going to the log (the background runs quiet: file only).
|
|
84
|
+
*/
|
|
85
|
+
release(ready) {
|
|
86
|
+
if (!this.open)
|
|
87
|
+
return;
|
|
88
|
+
this.open = false;
|
|
89
|
+
if (this.timer)
|
|
90
|
+
clearInterval(this.timer);
|
|
91
|
+
this.timer = null;
|
|
92
|
+
routeConsole(null);
|
|
93
|
+
if (ready)
|
|
94
|
+
for (const line of readyLines(ready))
|
|
95
|
+
record(line);
|
|
96
|
+
this.view.release(ready);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -15,6 +15,9 @@ export declare class Boot {
|
|
|
15
15
|
private secrets;
|
|
16
16
|
private basePath;
|
|
17
17
|
private readonly startedAt;
|
|
18
|
+
private readonly who;
|
|
19
|
+
/** The console while the boot runs: the stage rows, warnings and summary (released before the first session). */
|
|
20
|
+
private readonly progress;
|
|
18
21
|
private openGate;
|
|
19
22
|
private readonly gate;
|
|
20
23
|
/** The boot is ready: the runner no longer writes the status (the session owns it). */
|
|
@@ -24,9 +27,13 @@ export declare class Boot {
|
|
|
24
27
|
private stepsDone;
|
|
25
28
|
private stepsTotal;
|
|
26
29
|
run(): Promise<void>;
|
|
30
|
+
/** The prelude, then every foreground task (the console shows them). */
|
|
31
|
+
private foreground;
|
|
27
32
|
private stageTitle;
|
|
28
|
-
/** The
|
|
33
|
+
/** The toolchain steps that go on after the boot is ready (Visual Studio and what needs it), in plan order. */
|
|
29
34
|
private backgroundNames;
|
|
35
|
+
/** Runs a stage's hooks; they write to the terminal themselves, so the progress block steps aside for them. */
|
|
36
|
+
private hooks;
|
|
30
37
|
/**
|
|
31
38
|
* The host's one-shot file, read once. Your saved service sign-ins (accounts.<kind>.share) go to their tools before
|
|
32
39
|
* anything opens them, and leave memory at once; what they give the agent (EXPO_TOKEN ...) joins its environment
|