agl 1.0.17 → 21.0.2
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/.smartconfig.json +55 -0
- package/changelog.md +1026 -0
- package/cli.js +14 -0
- package/dist_serve/bundle.js +44778 -0
- package/dist_serve/index.html +13 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.authmodels.d.ts +126 -0
- package/dist_ts/classes.authmodels.js +1422 -0
- package/dist_ts/classes.authstore.d.ts +160 -0
- package/dist_ts/classes.authstore.js +2483 -0
- package/dist_ts/classes.browserresourcehost.d.ts +85 -0
- package/dist_ts/classes.browserresourcehost.js +912 -0
- package/dist_ts/classes.cli.d.ts +21 -0
- package/dist_ts/classes.cli.js +1082 -0
- package/dist_ts/classes.config.d.ts +23 -0
- package/dist_ts/classes.config.js +267 -0
- package/dist_ts/classes.controller.d.ts +523 -0
- package/dist_ts/classes.controller.js +10611 -0
- package/dist_ts/classes.controllermanagement.d.ts +32 -0
- package/dist_ts/classes.controllermanagement.js +222 -0
- package/dist_ts/classes.draftmanager.d.ts +30 -0
- package/dist_ts/classes.draftmanager.js +179 -0
- package/dist_ts/classes.embeddeddb.d.ts +30 -0
- package/dist_ts/classes.embeddeddb.js +159 -0
- package/dist_ts/classes.flexframedtransport.d.ts +56 -0
- package/dist_ts/classes.flexframedtransport.js +275 -0
- package/dist_ts/classes.flexmodels.private.d.ts +231 -0
- package/dist_ts/classes.flexmodels.private.js +985 -0
- package/dist_ts/classes.flexmodels.public.d.ts +207 -0
- package/dist_ts/classes.flexmodels.public.js +885 -0
- package/dist_ts/classes.flexprojectionreader.d.ts +89 -0
- package/dist_ts/classes.flexprojectionreader.js +580 -0
- package/dist_ts/classes.flexservice.d.ts +196 -0
- package/dist_ts/classes.flexservice.js +3704 -0
- package/dist_ts/classes.flexstore.d.ts +174 -0
- package/dist_ts/classes.flexstore.js +3400 -0
- package/dist_ts/classes.flexsupervisor.d.ts +105 -0
- package/dist_ts/classes.flexsupervisor.js +1191 -0
- package/dist_ts/classes.gitreversion.d.ts +431 -0
- package/dist_ts/classes.gitreversion.js +10592 -0
- package/dist_ts/classes.harnessoperationmanager.d.ts +113 -0
- package/dist_ts/classes.harnessoperationmanager.js +602 -0
- package/dist_ts/classes.opencodeclient.d.ts +146 -0
- package/dist_ts/classes.opencodeclient.js +3003 -0
- package/dist_ts/classes.opencodesupervisor.d.ts +60 -0
- package/dist_ts/classes.opencodesupervisor.js +1003 -0
- package/dist_ts/classes.passkeymanager.d.ts +34 -0
- package/dist_ts/classes.passkeymanager.js +456 -0
- package/dist_ts/classes.processinspection.d.ts +50 -0
- package/dist_ts/classes.processinspection.js +484 -0
- package/dist_ts/classes.resourcecoordinator.d.ts +64 -0
- package/dist_ts/classes.resourcecoordinator.js +294 -0
- package/dist_ts/classes.sessionintelligencereader.d.ts +13 -0
- package/dist_ts/classes.sessionintelligencereader.js +40 -0
- package/dist_ts/classes.systemmetricssampler.d.ts +53 -0
- package/dist_ts/classes.systemmetricssampler.js +168 -0
- package/dist_ts/classes.terminalmanager.d.ts +95 -0
- package/dist_ts/classes.terminalmanager.js +981 -0
- package/dist_ts/classes.terminalresourcehost.d.ts +20 -0
- package/dist_ts/classes.terminalresourcehost.js +84 -0
- package/dist_ts/classes.upgradecoordinator.d.ts +244 -0
- package/dist_ts/classes.upgradecoordinator.js +2155 -0
- package/dist_ts/classes.upgradetransaction.d.ts +92 -0
- package/dist_ts/classes.upgradetransaction.js +2125 -0
- package/dist_ts/classes.uploadmanager.d.ts +24 -0
- package/dist_ts/classes.uploadmanager.js +210 -0
- package/dist_ts/classes.validation.d.ts +91 -0
- package/dist_ts/classes.validation.js +1087 -0
- package/dist_ts/flexharness.child.d.ts +1 -0
- package/dist_ts/flexharness.child.js +28 -0
- package/dist_ts/functions.canonicaldirectory.d.ts +21 -0
- package/dist_ts/functions.canonicaldirectory.js +144 -0
- package/dist_ts/functions.controllerdataroot.d.ts +15 -0
- package/dist_ts/functions.controllerdataroot.js +76 -0
- package/dist_ts/functions.embeddeddb.d.ts +2 -0
- package/dist_ts/functions.embeddeddb.js +21 -0
- package/dist_ts/functions.flexcredentialstore.d.ts +16 -0
- package/dist_ts/functions.flexcredentialstore.js +93 -0
- package/dist_ts/functions.opencodeauth.d.ts +3 -0
- package/dist_ts/functions.opencodeauth.js +31 -0
- package/dist_ts/functions.runtimeenvironment.d.ts +2 -0
- package/dist_ts/functions.runtimeenvironment.js +79 -0
- package/dist_ts/functions.upgradefollower.d.ts +3 -0
- package/dist_ts/functions.upgradefollower.js +95 -0
- package/dist_ts/index.d.ts +24 -0
- package/dist_ts/index.js +25 -0
- package/dist_ts/interfaces.auth.d.ts +181 -0
- package/dist_ts/interfaces.auth.js +82 -0
- package/dist_ts/interfaces.config.d.ts +34 -0
- package/dist_ts/interfaces.config.js +2 -0
- package/dist_ts/interfaces.flexipc.d.ts +939 -0
- package/dist_ts/interfaces.flexipc.js +1492 -0
- package/dist_ts/interfaces.gitreversion.d.ts +246 -0
- package/dist_ts/interfaces.gitreversion.js +2 -0
- package/dist_ts/interfaces.lifecycle.d.ts +37 -0
- package/dist_ts/interfaces.lifecycle.js +2 -0
- package/dist_ts/interfaces.opencode.d.ts +101 -0
- package/dist_ts/interfaces.opencode.js +3 -0
- package/dist_ts/interfaces.projects.d.ts +156 -0
- package/dist_ts/interfaces.projects.js +5 -0
- package/dist_ts/plugins.d.ts +36 -0
- package/dist_ts/plugins.js +40 -0
- package/dist_ts_interfaces/index.d.ts +2 -0
- package/dist_ts_interfaces/index.js +3 -0
- package/dist_ts_interfaces/interfaces.d.ts +747 -0
- package/dist_ts_interfaces/interfaces.js +47 -0
- package/dist_ts_interfaces/plugins.d.ts +4 -0
- package/dist_ts_interfaces/plugins.js +3 -0
- package/dist_ts_interfaces/requests.d.ts +806 -0
- package/dist_ts_interfaces/requests.js +2 -0
- package/dist_ts_migration/classes.documentmigrationrunner.d.ts +8 -0
- package/dist_ts_migration/classes.documentmigrationrunner.js +24 -0
- package/dist_ts_migration/classes.flexmigrationrunner.d.ts +11 -0
- package/dist_ts_migration/classes.flexmigrationrunner.js +25 -0
- package/dist_ts_migration/classes.flexpostharnessmigrationrunner.d.ts +10 -0
- package/dist_ts_migration/classes.flexpostharnessmigrationrunner.js +15 -0
- package/dist_ts_migration/classes.migrationrunner.d.ts +8 -0
- package/dist_ts_migration/classes.migrationrunner.js +34 -0
- package/dist_ts_migration/index.d.ts +12 -0
- package/dist_ts_migration/index.js +13 -0
- package/dist_ts_migration/v10_flexharnessv3migration.d.ts +11 -0
- package/dist_ts_migration/v10_flexharnessv3migration.js +23 -0
- package/dist_ts_migration/v13_flexprojectionorder.d.ts +11 -0
- package/dist_ts_migration/v13_flexprojectionorder.js +23 -0
- package/dist_ts_migration/v16_flexprovidercredentials.d.ts +22 -0
- package/dist_ts_migration/v16_flexprovidercredentials.js +149 -0
- package/dist_ts_migration/v18_resourcelayout.d.ts +22 -0
- package/dist_ts_migration/v18_resourcelayout.js +23 -0
- package/dist_ts_migration/v18_resourcelayoutmigration.d.ts +6 -0
- package/dist_ts_migration/v18_resourcelayoutmigration.js +61 -0
- package/dist_ts_migration/v19_flexprojectmanagement.d.ts +11 -0
- package/dist_ts_migration/v19_flexprojectmanagement.js +21 -0
- package/dist_ts_migration/v1_embeddeddatabaselocation.d.ts +28 -0
- package/dist_ts_migration/v1_embeddeddatabaselocation.js +415 -0
- package/dist_ts_migration/v22_projectfilesystemidentitymigration.d.ts +7 -0
- package/dist_ts_migration/v22_projectfilesystemidentitymigration.js +105 -0
- package/dist_ts_migration/v2_controllerdataroot.d.ts +130 -0
- package/dist_ts_migration/v2_controllerdataroot.js +1887 -0
- package/dist_ts_migration/v6_protocoldocumentmigration.d.ts +7 -0
- package/dist_ts_migration/v6_protocoldocumentmigration.js +100 -0
- package/dist_ts_migration/v6_protocoldocuments.d.ts +7 -0
- package/dist_ts_migration/v6_protocoldocuments.js +138 -0
- package/html/index.html +13 -0
- package/{LICENSE → license.md} +2 -2
- package/package.json +86 -48
- package/readme.md +480 -0
- package/readme.plan.md +188 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.authmodels.ts +1245 -0
- package/ts/classes.authstore.ts +3274 -0
- package/ts/classes.browserresourcehost.ts +1205 -0
- package/ts/classes.cli.ts +1254 -0
- package/ts/classes.config.ts +351 -0
- package/ts/classes.controller.ts +14426 -0
- package/ts/classes.controllermanagement.ts +330 -0
- package/ts/classes.draftmanager.ts +232 -0
- package/ts/classes.embeddeddb.ts +166 -0
- package/ts/classes.flexframedtransport.ts +283 -0
- package/ts/classes.flexmodels.private.ts +823 -0
- package/ts/classes.flexmodels.public.ts +732 -0
- package/ts/classes.flexprojectionreader.ts +816 -0
- package/ts/classes.flexservice.ts +4302 -0
- package/ts/classes.flexstore.ts +4565 -0
- package/ts/classes.flexsupervisor.ts +1453 -0
- package/ts/classes.gitreversion.ts +13353 -0
- package/ts/classes.harnessoperationmanager.ts +870 -0
- package/ts/classes.opencodeclient.ts +4110 -0
- package/ts/classes.opencodesupervisor.ts +1280 -0
- package/ts/classes.passkeymanager.ts +570 -0
- package/ts/classes.processinspection.ts +623 -0
- package/ts/classes.resourcecoordinator.ts +436 -0
- package/ts/classes.sessionintelligencereader.ts +52 -0
- package/ts/classes.systemmetricssampler.ts +215 -0
- package/ts/classes.terminalmanager.ts +1207 -0
- package/ts/classes.terminalresourcehost.ts +122 -0
- package/ts/classes.upgradecoordinator.ts +2675 -0
- package/ts/classes.upgradetransaction.ts +2900 -0
- package/ts/classes.uploadmanager.ts +240 -0
- package/ts/classes.validation.ts +1409 -0
- package/ts/flexharness.child.ts +35 -0
- package/ts/functions.canonicaldirectory.ts +213 -0
- package/ts/functions.controllerdataroot.ts +107 -0
- package/ts/functions.embeddeddb.ts +22 -0
- package/ts/functions.flexcredentialstore.ts +128 -0
- package/ts/functions.opencodeauth.ts +34 -0
- package/ts/functions.runtimeenvironment.ts +90 -0
- package/ts/functions.upgradefollower.ts +115 -0
- package/ts/index.ts +36 -6
- package/ts/interfaces.auth.ts +316 -0
- package/ts/interfaces.config.ts +37 -0
- package/ts/interfaces.flexipc.ts +2586 -0
- package/ts/interfaces.gitreversion.ts +336 -0
- package/ts/interfaces.lifecycle.ts +46 -0
- package/ts/interfaces.opencode.ts +153 -0
- package/ts/interfaces.projects.ts +182 -0
- package/ts/plugins.ts +64 -0
- package/ts_interfaces/index.ts +2 -0
- package/ts_interfaces/interfaces.ts +827 -0
- package/ts_interfaces/plugins.ts +15 -0
- package/ts_interfaces/requests.ts +1186 -0
- package/ts_migration/classes.documentmigrationrunner.ts +32 -0
- package/ts_migration/classes.flexmigrationrunner.ts +33 -0
- package/ts_migration/classes.flexpostharnessmigrationrunner.ts +22 -0
- package/ts_migration/classes.migrationrunner.ts +40 -0
- package/ts_migration/index.ts +12 -0
- package/ts_migration/v10_flexharnessv3migration.ts +35 -0
- package/ts_migration/v13_flexprojectionorder.ts +33 -0
- package/ts_migration/v16_flexprovidercredentials.ts +196 -0
- package/ts_migration/v18_resourcelayout.ts +55 -0
- package/ts_migration/v18_resourcelayoutmigration.ts +68 -0
- package/ts_migration/v19_flexprojectmanagement.ts +28 -0
- package/ts_migration/v1_embeddeddatabaselocation.ts +560 -0
- package/ts_migration/v22_projectfilesystemidentitymigration.ts +121 -0
- package/ts_migration/v2_controllerdataroot.ts +2349 -0
- package/ts_migration/v6_protocoldocumentmigration.ts +144 -0
- package/ts_migration/v6_protocoldocuments.ts +198 -0
- package/ts_web/00_commitinfo_data.ts +8 -0
- package/ts_web/classes.controllersocketclient.ts +517 -0
- package/ts_web/classes.sessiondraftsync.ts +390 -0
- package/ts_web/elements.harnesscontrollerapp.ts +11494 -0
- package/ts_web/index.ts +2 -0
- package/ts_web/plugins.ts +31 -0
- package/.gitlab-ci.yml +0 -71
- package/.npmignore +0 -5
- package/README.md +0 -40
- package/dist/cli.js +0 -2
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -9
- package/dist/mod_bundle/index.d.ts +0 -1
- package/dist/mod_bundle/index.js +0 -18
- package/dist/mod_bundle/mod.plugins.d.ts +0 -4
- package/dist/mod_bundle/mod.plugins.js +0 -11
- package/dist/mod_install/index.d.ts +0 -4
- package/dist/mod_install/index.js +0 -21
- package/dist/mod_install/mod.plugins.d.ts +0 -1
- package/dist/mod_install/mod.plugins.js +0 -7
- package/dist/mod_standard/index.d.ts +0 -4
- package/dist/mod_standard/index.js +0 -21
- package/dist/mod_standard/mod.browser.d.ts +0 -6
- package/dist/mod_standard/mod.browser.js +0 -14
- package/dist/mod_standard/mod.clean.d.ts +0 -4
- package/dist/mod_standard/mod.clean.js +0 -12
- package/dist/mod_standard/mod.compile.d.ts +0 -4
- package/dist/mod_standard/mod.compile.js +0 -21
- package/dist/mod_standard/mod.plugins.d.ts +0 -8
- package/dist/mod_standard/mod.plugins.js +0 -19
- package/dist/mod_standard/mod.test.d.ts +0 -4
- package/dist/mod_standard/mod.test.js +0 -12
- package/dist/plr.cli.d.ts +0 -3
- package/dist/plr.cli.js +0 -57
- package/dist/plr.config.d.ts +0 -11
- package/dist/plr.config.js +0 -26
- package/dist/plr.mods.d.ts +0 -17
- package/dist/plr.mods.js +0 -17
- package/dist/plr.paths.d.ts +0 -19
- package/dist/plr.paths.js +0 -26
- package/dist/plr.plugins.d.ts +0 -8
- package/dist/plr.plugins.js +0 -16
- package/npmextra.json +0 -10
- package/ts/mod_bundle/index.ts +0 -20
- package/ts/mod_bundle/mod.plugins.ts +0 -9
- package/ts/mod_install/index.ts +0 -20
- package/ts/mod_install/mod.plugins.ts +0 -1
- package/ts/mod_standard/index.ts +0 -23
- package/ts/mod_standard/mod.browser.ts +0 -17
- package/ts/mod_standard/mod.clean.ts +0 -13
- package/ts/mod_standard/mod.compile.ts +0 -23
- package/ts/mod_standard/mod.plugins.ts +0 -17
- package/ts/mod_standard/mod.test.ts +0 -13
- package/ts/plr.cli.ts +0 -60
- package/ts/plr.config.ts +0 -36
- package/ts/plr.mods.ts +0 -25
- package/ts/plr.paths.ts +0 -29
- package/ts/plr.plugins.ts +0 -17
- package/tslint.json +0 -3
- package/yarn.lock +0 -3464
|
@@ -0,0 +1,981 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { createSanitizedRuntimeEnvironment } from './functions.runtimeenvironment.js';
|
|
3
|
+
const maxTerminals = 32;
|
|
4
|
+
const maxTerminalsPerProject = 8;
|
|
5
|
+
const maxScrollbackBytes = 2 * 1024 * 1024;
|
|
6
|
+
const maxPtyCaptureBytes = 4 * 1024 * 1024;
|
|
7
|
+
const maxInputBytes = 8 * 1024;
|
|
8
|
+
const maxOutputFrameBytes = 64 * 1024;
|
|
9
|
+
const maxPeersPerTerminal = 32;
|
|
10
|
+
const maxPendingControlOperations = 256;
|
|
11
|
+
const defaultCleanupTimeoutMs = 10_000;
|
|
12
|
+
const normalizeError = (errorArg) => errorArg instanceof Error ? errorArg : new Error(String(errorArg));
|
|
13
|
+
const toTerminalDto = (terminalArg) => ({
|
|
14
|
+
...terminalArg,
|
|
15
|
+
id: { ...terminalArg.id },
|
|
16
|
+
});
|
|
17
|
+
const appendBoundedChunk = (slabsArg, currentBytesArg, chunkArg) => {
|
|
18
|
+
if (chunkArg.byteLength === 0)
|
|
19
|
+
return currentBytesArg;
|
|
20
|
+
let sourceOffset = 0;
|
|
21
|
+
let currentBytes = currentBytesArg;
|
|
22
|
+
if (chunkArg.byteLength >= maxScrollbackBytes) {
|
|
23
|
+
slabsArg.splice(0, slabsArg.length);
|
|
24
|
+
sourceOffset = chunkArg.byteLength - maxScrollbackBytes;
|
|
25
|
+
currentBytes = 0;
|
|
26
|
+
}
|
|
27
|
+
while (sourceOffset < chunkArg.byteLength) {
|
|
28
|
+
let slab = slabsArg.at(-1);
|
|
29
|
+
if (!slab || slab.end >= slab.buffer.byteLength) {
|
|
30
|
+
slab = {
|
|
31
|
+
buffer: Buffer.allocUnsafe(maxOutputFrameBytes),
|
|
32
|
+
start: 0,
|
|
33
|
+
end: 0,
|
|
34
|
+
};
|
|
35
|
+
slabsArg.push(slab);
|
|
36
|
+
}
|
|
37
|
+
const copyBytes = Math.min(chunkArg.byteLength - sourceOffset, slab.buffer.byteLength - slab.end);
|
|
38
|
+
chunkArg.copy(slab.buffer, slab.end, sourceOffset, sourceOffset + copyBytes);
|
|
39
|
+
slab.end += copyBytes;
|
|
40
|
+
sourceOffset += copyBytes;
|
|
41
|
+
currentBytes += copyBytes;
|
|
42
|
+
}
|
|
43
|
+
let excess = currentBytes - maxScrollbackBytes;
|
|
44
|
+
while (excess > 0) {
|
|
45
|
+
const first = slabsArg[0];
|
|
46
|
+
const firstBytes = first.end - first.start;
|
|
47
|
+
if (firstBytes <= excess) {
|
|
48
|
+
slabsArg.shift();
|
|
49
|
+
currentBytes -= firstBytes;
|
|
50
|
+
excess -= firstBytes;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
first.start += excess;
|
|
54
|
+
currentBytes -= excess;
|
|
55
|
+
excess = 0;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return currentBytes;
|
|
59
|
+
};
|
|
60
|
+
const appendOutput = (outputArg, chunkArg) => {
|
|
61
|
+
if (chunkArg.byteLength === 0)
|
|
62
|
+
return;
|
|
63
|
+
outputArg.end += chunkArg.byteLength;
|
|
64
|
+
outputArg.bytes = appendBoundedChunk(outputArg.slabs, outputArg.bytes, chunkArg);
|
|
65
|
+
outputArg.start = outputArg.end - outputArg.bytes;
|
|
66
|
+
};
|
|
67
|
+
const validateExecutable = async (candidateArg, platformArg) => {
|
|
68
|
+
const pathApi = platformArg === 'win32' ? plugins.path.win32 : plugins.path.posix;
|
|
69
|
+
if (!pathApi.isAbsolute(candidateArg)) {
|
|
70
|
+
throw new Error('The terminal shell executable must be an absolute path.');
|
|
71
|
+
}
|
|
72
|
+
const executable = await plugins.fs.promises.realpath(candidateArg);
|
|
73
|
+
const stats = await plugins.fs.promises.stat(executable);
|
|
74
|
+
if (!stats.isFile())
|
|
75
|
+
throw new Error('The terminal shell executable is not a file.');
|
|
76
|
+
if (platformArg !== 'win32') {
|
|
77
|
+
await plugins.fs.promises.access(executable, plugins.fs.constants.X_OK);
|
|
78
|
+
}
|
|
79
|
+
return executable;
|
|
80
|
+
};
|
|
81
|
+
export const resolveControllerTerminalShell = async (environmentArg = process.env, platformArg = process.platform, validateExecutableArg = validateExecutable) => {
|
|
82
|
+
const environment = createSanitizedRuntimeEnvironment(environmentArg);
|
|
83
|
+
if (platformArg === 'win32') {
|
|
84
|
+
const candidates = [];
|
|
85
|
+
if (environmentArg.COMSPEC && plugins.path.win32.isAbsolute(environmentArg.COMSPEC)) {
|
|
86
|
+
candidates.push(environmentArg.COMSPEC);
|
|
87
|
+
}
|
|
88
|
+
const systemRoot = environmentArg.SystemRoot ?? environmentArg.SYSTEMROOT;
|
|
89
|
+
if (systemRoot && plugins.path.win32.isAbsolute(systemRoot)) {
|
|
90
|
+
candidates.push(plugins.path.win32.join(systemRoot, 'System32', 'cmd.exe'));
|
|
91
|
+
}
|
|
92
|
+
for (const candidate of [...new Set(candidates)]) {
|
|
93
|
+
try {
|
|
94
|
+
const executable = await validateExecutableArg(candidate, platformArg);
|
|
95
|
+
delete environment.SHELL;
|
|
96
|
+
environment.COMSPEC = executable;
|
|
97
|
+
return { executable, args: [], environment };
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// Try the trusted SystemRoot fallback before failing closed.
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
throw new Error('No trusted Windows terminal shell executable is available.');
|
|
104
|
+
}
|
|
105
|
+
const candidates = [
|
|
106
|
+
...(environmentArg.SHELL && plugins.path.posix.isAbsolute(environmentArg.SHELL)
|
|
107
|
+
? [environmentArg.SHELL]
|
|
108
|
+
: []),
|
|
109
|
+
'/bin/sh',
|
|
110
|
+
];
|
|
111
|
+
for (const candidate of [...new Set(candidates)]) {
|
|
112
|
+
try {
|
|
113
|
+
const executable = await validateExecutableArg(candidate, platformArg);
|
|
114
|
+
delete environment.COMSPEC;
|
|
115
|
+
environment.SHELL = executable;
|
|
116
|
+
return { executable, args: [], environment };
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Fall through to /bin/sh, then fail closed.
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
throw new Error('No trusted POSIX terminal shell executable is available.');
|
|
123
|
+
};
|
|
124
|
+
const waitUntil = async (promiseArg, deadlineAtArg) => {
|
|
125
|
+
const remainingMs = deadlineAtArg - Date.now();
|
|
126
|
+
if (remainingMs <= 0)
|
|
127
|
+
throw new Error('Terminal cleanup exceeded its deadline.');
|
|
128
|
+
let timeout;
|
|
129
|
+
try {
|
|
130
|
+
await Promise.race([
|
|
131
|
+
promiseArg,
|
|
132
|
+
new Promise((_resolve, reject) => {
|
|
133
|
+
timeout = setTimeout(() => reject(new Error('Terminal cleanup exceeded its deadline.')), remainingMs);
|
|
134
|
+
}),
|
|
135
|
+
]);
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
if (timeout)
|
|
139
|
+
clearTimeout(timeout);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
export class ControllerTerminalManager {
|
|
143
|
+
options;
|
|
144
|
+
ptySpawner;
|
|
145
|
+
resolveShell;
|
|
146
|
+
cleanupTimeoutMs;
|
|
147
|
+
entries = new Map();
|
|
148
|
+
projectStates = new Map();
|
|
149
|
+
activeRetirements = new Set();
|
|
150
|
+
pendingRemovalCleanups = new Map();
|
|
151
|
+
state = 'new';
|
|
152
|
+
shell;
|
|
153
|
+
initPromise;
|
|
154
|
+
closePromise;
|
|
155
|
+
pendingCreates = 0;
|
|
156
|
+
pendingCreatesByProject = new Map();
|
|
157
|
+
peerGeneration = 0;
|
|
158
|
+
constructor(options) {
|
|
159
|
+
this.options = options;
|
|
160
|
+
this.ptySpawner = options.ptySpawner ?? new plugins.smartshell.Smartshell({
|
|
161
|
+
executor: 'sh',
|
|
162
|
+
sourceFilePaths: [],
|
|
163
|
+
});
|
|
164
|
+
this.resolveShell = options.resolveShell ?? (() => resolveControllerTerminalShell());
|
|
165
|
+
this.cleanupTimeoutMs = options.cleanupTimeoutMs ?? defaultCleanupTimeoutMs;
|
|
166
|
+
if (!Number.isSafeInteger(this.cleanupTimeoutMs)
|
|
167
|
+
|| this.cleanupTimeoutMs < 1
|
|
168
|
+
|| this.cleanupTimeoutMs > 60_000) {
|
|
169
|
+
throw new Error('cleanupTimeoutMs must be an integer between 1 and 60000.');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async init() {
|
|
173
|
+
if (this.state === 'open')
|
|
174
|
+
return;
|
|
175
|
+
if (this.initPromise)
|
|
176
|
+
return this.initPromise;
|
|
177
|
+
if (this.state !== 'new')
|
|
178
|
+
throw new Error('The terminal manager cannot be initialized now.');
|
|
179
|
+
const initPromise = (async () => {
|
|
180
|
+
const [shell] = await Promise.all([
|
|
181
|
+
this.resolveShell(),
|
|
182
|
+
this.ptySpawner.ensurePtySupport(),
|
|
183
|
+
]);
|
|
184
|
+
if (this.state !== 'new')
|
|
185
|
+
throw new Error('Terminal manager initialization was cancelled.');
|
|
186
|
+
this.shell = shell;
|
|
187
|
+
this.state = 'open';
|
|
188
|
+
})();
|
|
189
|
+
this.initPromise = initPromise;
|
|
190
|
+
try {
|
|
191
|
+
await initPromise;
|
|
192
|
+
}
|
|
193
|
+
finally {
|
|
194
|
+
if (this.initPromise === initPromise)
|
|
195
|
+
this.initPromise = undefined;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async listTerminals(projectIdArg) {
|
|
199
|
+
return this.runProjectOperation(projectIdArg, async () => {
|
|
200
|
+
await this.options.resolveProjectDirectory(projectIdArg);
|
|
201
|
+
return [...this.entries.values()]
|
|
202
|
+
.filter((entry) => entry.projectId === projectIdArg && entry.finalState !== 'exited')
|
|
203
|
+
.map((entry) => toTerminalDto(entry.terminal));
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
async createTerminal(projectIdArg, titleArg) {
|
|
207
|
+
return this.runProjectOperation(projectIdArg, async () => {
|
|
208
|
+
this.reserveCreate(projectIdArg);
|
|
209
|
+
try {
|
|
210
|
+
const directory = await this.options.resolveProjectDirectory(projectIdArg);
|
|
211
|
+
const shell = this.requireShell();
|
|
212
|
+
const terminalNativeId = this.createTerminalId();
|
|
213
|
+
return this.spawnTerminal({
|
|
214
|
+
projectId: projectIdArg,
|
|
215
|
+
terminalNativeId,
|
|
216
|
+
title: titleArg ?? plugins.path.basename(shell.executable),
|
|
217
|
+
command: shell.executable,
|
|
218
|
+
args: [...shell.args],
|
|
219
|
+
cwd: directory,
|
|
220
|
+
environment: { ...shell.environment },
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
this.releaseCreate(projectIdArg);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
async resolveTerminalResourceMetadata(projectIdArg, titleArg) {
|
|
229
|
+
const directory = await this.options.resolveProjectDirectory(projectIdArg);
|
|
230
|
+
const shell = this.requireShell();
|
|
231
|
+
return {
|
|
232
|
+
title: titleArg ?? plugins.path.basename(shell.executable),
|
|
233
|
+
terminal: {
|
|
234
|
+
command: shell.executable,
|
|
235
|
+
args: [...shell.args],
|
|
236
|
+
cwd: directory,
|
|
237
|
+
stoppedAt: new Date(),
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
async startTerminalResource(resourceArg) {
|
|
242
|
+
if (resourceArg.kind !== 'terminal' || !resourceArg.terminal) {
|
|
243
|
+
throw new Error('The resource is not a terminal.');
|
|
244
|
+
}
|
|
245
|
+
const terminal = resourceArg.terminal;
|
|
246
|
+
return this.runProjectOperation(resourceArg.projectId, async () => {
|
|
247
|
+
this.reserveCreate(resourceArg.projectId);
|
|
248
|
+
try {
|
|
249
|
+
if (this.entries.has(resourceArg.id)) {
|
|
250
|
+
throw new Error('The terminal resource is already running.');
|
|
251
|
+
}
|
|
252
|
+
const directory = await this.options.resolveProjectDirectory(resourceArg.projectId);
|
|
253
|
+
if (directory !== terminal.cwd) {
|
|
254
|
+
throw new Error('The terminal resource project directory binding changed.');
|
|
255
|
+
}
|
|
256
|
+
const shell = this.requireShell();
|
|
257
|
+
return this.spawnTerminal({
|
|
258
|
+
projectId: resourceArg.projectId,
|
|
259
|
+
terminalNativeId: resourceArg.id,
|
|
260
|
+
title: resourceArg.title,
|
|
261
|
+
command: terminal.command,
|
|
262
|
+
args: [...terminal.args],
|
|
263
|
+
cwd: directory,
|
|
264
|
+
environment: { ...shell.environment },
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
finally {
|
|
268
|
+
this.releaseCreate(resourceArg.projectId);
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
async stopTerminalResource(projectIdArg, resourceIdArg) {
|
|
273
|
+
const entry = this.entries.get(resourceIdArg);
|
|
274
|
+
if (!entry || entry.projectId !== projectIdArg)
|
|
275
|
+
return;
|
|
276
|
+
await this.runProjectOperation(projectIdArg, async () => {
|
|
277
|
+
await this.closeEntry(entry, Date.now() + this.cleanupTimeoutMs);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
isTerminalRunning(projectIdArg, resourceIdArg) {
|
|
281
|
+
const entry = this.entries.get(resourceIdArg);
|
|
282
|
+
return entry?.projectId === projectIdArg && entry.finalState === 'running';
|
|
283
|
+
}
|
|
284
|
+
async spawnTerminal(inputArg) {
|
|
285
|
+
let entry;
|
|
286
|
+
const output = {
|
|
287
|
+
slabs: [],
|
|
288
|
+
start: 0,
|
|
289
|
+
end: 0,
|
|
290
|
+
bytes: 0,
|
|
291
|
+
};
|
|
292
|
+
const execution = await this.ptySpawner.execSpawnStreamingInteractiveControlPty(inputArg.command, [...inputArg.args], {
|
|
293
|
+
cwd: inputArg.cwd,
|
|
294
|
+
env: { ...inputArg.environment },
|
|
295
|
+
maxBuffer: maxPtyCaptureBytes,
|
|
296
|
+
ptyCols: 120,
|
|
297
|
+
ptyRows: 30,
|
|
298
|
+
ptyTerm: 'xterm-256color',
|
|
299
|
+
onData: (chunkArg) => {
|
|
300
|
+
const chunk = Buffer.from(chunkArg, 'utf8');
|
|
301
|
+
if (entry)
|
|
302
|
+
this.appendOutput(entry, chunk);
|
|
303
|
+
else
|
|
304
|
+
appendOutput(output, chunk);
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
let resolveRootExit;
|
|
308
|
+
const rootExitPromise = new Promise((resolve) => {
|
|
309
|
+
resolveRootExit = resolve;
|
|
310
|
+
});
|
|
311
|
+
const createdEntry = {
|
|
312
|
+
projectId: inputArg.projectId,
|
|
313
|
+
terminal: {
|
|
314
|
+
id: { harnessId: 'controller', nativeId: inputArg.terminalNativeId },
|
|
315
|
+
title: inputArg.title,
|
|
316
|
+
command: inputArg.command,
|
|
317
|
+
cwd: inputArg.cwd,
|
|
318
|
+
},
|
|
319
|
+
execution,
|
|
320
|
+
peers: new Map(),
|
|
321
|
+
sizesByPeer: new Map(),
|
|
322
|
+
output,
|
|
323
|
+
controlQueue: Promise.resolve(),
|
|
324
|
+
pendingControlOperations: 0,
|
|
325
|
+
sizeRevision: 0,
|
|
326
|
+
sizeReconciliationActive: false,
|
|
327
|
+
closing: false,
|
|
328
|
+
finalState: 'running',
|
|
329
|
+
rootExitPromise,
|
|
330
|
+
resolveRootExit,
|
|
331
|
+
};
|
|
332
|
+
entry = createdEntry;
|
|
333
|
+
this.entries.set(inputArg.terminalNativeId, createdEntry);
|
|
334
|
+
createdEntry.exitSubscription = execution.ptyProcess.onExit((eventArg) => this.confirmRootExit(createdEntry, eventArg.exitCode));
|
|
335
|
+
if (createdEntry.finalState === 'exited')
|
|
336
|
+
createdEntry.exitSubscription.dispose();
|
|
337
|
+
void execution.finalPromise.then((resultArg) => this.confirmRootExit(createdEntry, resultArg.exitCode), (errorArg) => {
|
|
338
|
+
if (createdEntry.finalState === 'running')
|
|
339
|
+
createdEntry.finalState = 'failed-unconfirmed';
|
|
340
|
+
createdEntry.finalError = normalizeError(errorArg);
|
|
341
|
+
});
|
|
342
|
+
if (createdEntry.finalState === 'exited' || this.state !== 'open') {
|
|
343
|
+
await this.closeEntry(createdEntry, Date.now() + this.cleanupTimeoutMs);
|
|
344
|
+
throw new Error('The terminal exited while it was being created.');
|
|
345
|
+
}
|
|
346
|
+
const projectState = this.projectState(inputArg.projectId);
|
|
347
|
+
if (projectState.retiring || projectState.retired) {
|
|
348
|
+
await this.closeEntry(createdEntry, Date.now() + this.cleanupTimeoutMs);
|
|
349
|
+
throw new Error('The project stopped accepting terminal operations.');
|
|
350
|
+
}
|
|
351
|
+
this.options.onTerminalsChanged(inputArg.projectId);
|
|
352
|
+
return toTerminalDto(createdEntry.terminal);
|
|
353
|
+
}
|
|
354
|
+
async renameTerminal(projectIdArg, terminalIdArg, titleArg) {
|
|
355
|
+
const entry = this.requireEntry(projectIdArg, terminalIdArg);
|
|
356
|
+
return this.runProjectOperation(projectIdArg, () => (this.runEntryControl(entry, async () => {
|
|
357
|
+
this.assertEntryRunning(entry);
|
|
358
|
+
entry.terminal.title = titleArg;
|
|
359
|
+
this.options.onTerminalsChanged(projectIdArg);
|
|
360
|
+
return toTerminalDto(entry.terminal);
|
|
361
|
+
})));
|
|
362
|
+
}
|
|
363
|
+
async renameTerminalResource(projectIdArg, terminalIdArg, titleArg) {
|
|
364
|
+
const entry = this.entries.get(terminalIdArg);
|
|
365
|
+
if (!entry || entry.projectId !== projectIdArg || entry.finalState === 'exited')
|
|
366
|
+
return;
|
|
367
|
+
await this.runProjectOperation(projectIdArg, () => (this.runEntryControl(entry, async () => {
|
|
368
|
+
this.assertEntryRunning(entry);
|
|
369
|
+
entry.terminal.title = titleArg;
|
|
370
|
+
this.options.onTerminalsChanged(projectIdArg);
|
|
371
|
+
})));
|
|
372
|
+
}
|
|
373
|
+
async removeTerminal(projectIdArg, terminalIdArg) {
|
|
374
|
+
const entry = this.entries.get(terminalIdArg);
|
|
375
|
+
return this.runProjectOperation(projectIdArg, async () => {
|
|
376
|
+
if (!entry || entry.projectId !== projectIdArg)
|
|
377
|
+
return false;
|
|
378
|
+
await this.closeEntry(entry, Date.now() + this.cleanupTimeoutMs);
|
|
379
|
+
return true;
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
async attach(peerIdArg, projectIdArg, terminalIdArg, isPeerConnectedArg = () => true) {
|
|
383
|
+
const entry = this.requireEntry(projectIdArg, terminalIdArg);
|
|
384
|
+
return this.runProjectOperation(projectIdArg, () => (this.runEntryControl(entry, async () => {
|
|
385
|
+
this.assertEntryRunning(entry);
|
|
386
|
+
if (!isPeerConnectedArg())
|
|
387
|
+
throw new Error('The terminal peer disconnected before attach.');
|
|
388
|
+
const previous = entry.peers.get(peerIdArg);
|
|
389
|
+
if (previous) {
|
|
390
|
+
this.detachPeerState(entry, previous);
|
|
391
|
+
if (previous.deliveryPromise) {
|
|
392
|
+
await waitUntil(previous.deliveryPromise.catch(() => undefined), Date.now() + this.cleanupTimeoutMs).catch(() => undefined);
|
|
393
|
+
}
|
|
394
|
+
await this.applyMinimumSizeUntilStable(entry);
|
|
395
|
+
}
|
|
396
|
+
if (entry.peers.size >= maxPeersPerTerminal) {
|
|
397
|
+
throw new Error(`At most ${maxPeersPerTerminal} peers may attach to one terminal.`);
|
|
398
|
+
}
|
|
399
|
+
const peer = {
|
|
400
|
+
peerId: peerIdArg,
|
|
401
|
+
generation: ++this.peerGeneration,
|
|
402
|
+
cursor: entry.output.start,
|
|
403
|
+
detaching: false,
|
|
404
|
+
finalizing: false,
|
|
405
|
+
};
|
|
406
|
+
entry.peers.set(peerIdArg, peer);
|
|
407
|
+
try {
|
|
408
|
+
await this.schedulePeerDelivery(entry, peer, true);
|
|
409
|
+
if (!isPeerConnectedArg() || entry.peers.get(peerIdArg) !== peer) {
|
|
410
|
+
throw new Error('The terminal peer disconnected during attach.');
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
catch (errorArg) {
|
|
414
|
+
this.detachPeerState(entry, peer);
|
|
415
|
+
throw errorArg;
|
|
416
|
+
}
|
|
417
|
+
})));
|
|
418
|
+
}
|
|
419
|
+
async detach(peerIdArg, projectIdArg, terminalIdArg) {
|
|
420
|
+
const entry = this.entries.get(terminalIdArg);
|
|
421
|
+
return this.runProjectOperation(projectIdArg, () => {
|
|
422
|
+
if (!entry || entry.projectId !== projectIdArg)
|
|
423
|
+
return Promise.resolve();
|
|
424
|
+
return this.runEntryControl(entry, async () => {
|
|
425
|
+
const peer = entry.peers.get(peerIdArg);
|
|
426
|
+
if (!peer)
|
|
427
|
+
return;
|
|
428
|
+
this.detachPeerState(entry, peer);
|
|
429
|
+
if (peer.deliveryPromise) {
|
|
430
|
+
await waitUntil(peer.deliveryPromise.catch(() => undefined), Date.now() + this.cleanupTimeoutMs).catch(() => undefined);
|
|
431
|
+
}
|
|
432
|
+
await this.applyMinimumSizeUntilStable(entry);
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
async detachPeer(peerIdArg) {
|
|
437
|
+
const reconciliations = [];
|
|
438
|
+
for (const entry of this.entries.values()) {
|
|
439
|
+
const peer = entry.peers.get(peerIdArg);
|
|
440
|
+
if (!peer)
|
|
441
|
+
continue;
|
|
442
|
+
this.detachPeerState(entry, peer);
|
|
443
|
+
reconciliations.push(this.requestSizeReconciliation(entry));
|
|
444
|
+
}
|
|
445
|
+
await Promise.allSettled(reconciliations);
|
|
446
|
+
}
|
|
447
|
+
async input(peerIdArg, projectIdArg, terminalIdArg, dataArg) {
|
|
448
|
+
if (dataArg.byteLength > maxInputBytes) {
|
|
449
|
+
throw new Error('Terminal input exceeds the per-message limit.');
|
|
450
|
+
}
|
|
451
|
+
const entry = this.requireEntry(projectIdArg, terminalIdArg);
|
|
452
|
+
return this.runProjectOperation(projectIdArg, () => (this.runEntryControl(entry, async () => {
|
|
453
|
+
this.assertAttached(entry, peerIdArg);
|
|
454
|
+
await entry.execution.sendInput(dataArg.toString('utf8'));
|
|
455
|
+
})));
|
|
456
|
+
}
|
|
457
|
+
async resize(peerIdArg, projectIdArg, terminalIdArg, rowsArg, colsArg) {
|
|
458
|
+
const entry = this.requireEntry(projectIdArg, terminalIdArg);
|
|
459
|
+
return this.runProjectOperation(projectIdArg, () => (this.runEntryControl(entry, async () => {
|
|
460
|
+
this.assertAttached(entry, peerIdArg);
|
|
461
|
+
entry.sizesByPeer.set(peerIdArg, { rows: rowsArg, cols: colsArg });
|
|
462
|
+
entry.sizeRevision += 1;
|
|
463
|
+
await this.applyMinimumSizeUntilStable(entry);
|
|
464
|
+
})));
|
|
465
|
+
}
|
|
466
|
+
async retireProject(projectIdArg, retireArg) {
|
|
467
|
+
if (this.state !== 'open')
|
|
468
|
+
throw new Error('The terminal manager is not accepting operations.');
|
|
469
|
+
const projectState = this.projectState(projectIdArg);
|
|
470
|
+
if (projectState.retiring || projectState.retired) {
|
|
471
|
+
throw new Error('The project is already leaving terminal admission.');
|
|
472
|
+
}
|
|
473
|
+
projectState.retiring = true;
|
|
474
|
+
const deadlineAt = Date.now() + this.cleanupTimeoutMs;
|
|
475
|
+
const retirementPromise = (async () => {
|
|
476
|
+
await this.closeProjectEntries(projectIdArg, deadlineAt);
|
|
477
|
+
await waitUntil(this.waitForProjectDrain(projectState), deadlineAt);
|
|
478
|
+
await this.closeProjectEntries(projectIdArg, deadlineAt);
|
|
479
|
+
if ([...this.pendingRemovalCleanups.values()].includes(projectIdArg)) {
|
|
480
|
+
await waitUntil(this.waitForRemovalCleanups(projectIdArg), deadlineAt);
|
|
481
|
+
}
|
|
482
|
+
const retired = await retireArg();
|
|
483
|
+
projectState.retired = retired;
|
|
484
|
+
return retired;
|
|
485
|
+
})();
|
|
486
|
+
projectState.retirementPromise = retirementPromise;
|
|
487
|
+
this.activeRetirements.add(retirementPromise);
|
|
488
|
+
try {
|
|
489
|
+
return await retirementPromise;
|
|
490
|
+
}
|
|
491
|
+
finally {
|
|
492
|
+
this.activeRetirements.delete(retirementPromise);
|
|
493
|
+
if (projectState.retirementPromise === retirementPromise) {
|
|
494
|
+
projectState.retirementPromise = undefined;
|
|
495
|
+
}
|
|
496
|
+
projectState.retiring = false;
|
|
497
|
+
this.pruneProjectState(projectIdArg, projectState);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
async closeAll() {
|
|
501
|
+
if (this.state === 'closed')
|
|
502
|
+
return;
|
|
503
|
+
if (this.closePromise)
|
|
504
|
+
return this.closePromise;
|
|
505
|
+
this.state = 'closing';
|
|
506
|
+
const deadlineAt = Date.now() + this.cleanupTimeoutMs;
|
|
507
|
+
const closePromise = (async () => {
|
|
508
|
+
const initialClosures = [...this.entries.values()]
|
|
509
|
+
.map((entry) => this.closeEntry(entry, deadlineAt));
|
|
510
|
+
const coordination = Promise.all([
|
|
511
|
+
Promise.allSettled(initialClosures).then(() => undefined),
|
|
512
|
+
this.waitForAllProjectDrains(),
|
|
513
|
+
Promise.allSettled([...this.activeRetirements]).then(() => undefined),
|
|
514
|
+
]).then(() => this.waitForRemovalCleanups());
|
|
515
|
+
let coordinationError;
|
|
516
|
+
try {
|
|
517
|
+
await waitUntil(coordination, deadlineAt);
|
|
518
|
+
}
|
|
519
|
+
catch (errorArg) {
|
|
520
|
+
coordinationError = errorArg;
|
|
521
|
+
}
|
|
522
|
+
const finalOutcomes = await Promise.allSettled([...this.entries.values()].map((entry) => this.closeEntry(entry, deadlineAt)));
|
|
523
|
+
let cleanupError;
|
|
524
|
+
if (this.pendingRemovalCleanups.size > 0) {
|
|
525
|
+
try {
|
|
526
|
+
await waitUntil(this.waitForRemovalCleanups(), deadlineAt);
|
|
527
|
+
}
|
|
528
|
+
catch (errorArg) {
|
|
529
|
+
cleanupError = errorArg;
|
|
530
|
+
if (this.entries.size === 0)
|
|
531
|
+
this.pendingRemovalCleanups.clear();
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
const activeOperations = [...this.projectStates.values()]
|
|
535
|
+
.reduce((sum, projectState) => sum + projectState.activeOperations, 0);
|
|
536
|
+
const errors = [];
|
|
537
|
+
if (this.entries.size > 0) {
|
|
538
|
+
errors.push(new Error('One or more terminal roots remain unconfirmed.'));
|
|
539
|
+
}
|
|
540
|
+
if (activeOperations > 0) {
|
|
541
|
+
errors.push(new Error('One or more terminal operations remain active.'));
|
|
542
|
+
}
|
|
543
|
+
if (this.activeRetirements.size > 0) {
|
|
544
|
+
errors.push(new Error('One or more project retirements remain active.'));
|
|
545
|
+
}
|
|
546
|
+
if (this.pendingRemovalCleanups.size > 0) {
|
|
547
|
+
errors.push(new Error('One or more terminal layout cleanups remain active.'));
|
|
548
|
+
}
|
|
549
|
+
if (errors.length > 0 && coordinationError)
|
|
550
|
+
errors.push(coordinationError);
|
|
551
|
+
if (errors.length > 0 && cleanupError)
|
|
552
|
+
errors.push(cleanupError);
|
|
553
|
+
if (this.entries.size > 0) {
|
|
554
|
+
errors.push(...finalOutcomes.flatMap((outcome) => (outcome.status === 'rejected' ? [outcome.reason] : [])));
|
|
555
|
+
}
|
|
556
|
+
if (errors.length > 0) {
|
|
557
|
+
throw new AggregateError(errors, 'The terminal manager did not close every PTY.');
|
|
558
|
+
}
|
|
559
|
+
this.state = 'closed';
|
|
560
|
+
})();
|
|
561
|
+
this.closePromise = closePromise;
|
|
562
|
+
try {
|
|
563
|
+
await closePromise;
|
|
564
|
+
}
|
|
565
|
+
finally {
|
|
566
|
+
if (this.closePromise === closePromise)
|
|
567
|
+
this.closePromise = undefined;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
projectState(projectIdArg) {
|
|
571
|
+
let state = this.projectStates.get(projectIdArg);
|
|
572
|
+
if (!state) {
|
|
573
|
+
const newState = {
|
|
574
|
+
activeOperations: 0,
|
|
575
|
+
retiring: false,
|
|
576
|
+
retired: false,
|
|
577
|
+
};
|
|
578
|
+
this.projectStates.set(projectIdArg, newState);
|
|
579
|
+
state = newState;
|
|
580
|
+
}
|
|
581
|
+
return state;
|
|
582
|
+
}
|
|
583
|
+
pruneProjectState(projectIdArg, projectStateArg) {
|
|
584
|
+
if (this.projectStates.get(projectIdArg) === projectStateArg
|
|
585
|
+
&& projectStateArg.activeOperations === 0
|
|
586
|
+
&& !projectStateArg.retiring
|
|
587
|
+
&& !projectStateArg.retirementPromise) {
|
|
588
|
+
this.projectStates.delete(projectIdArg);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
async runProjectOperation(projectIdArg, operationArg) {
|
|
592
|
+
if (this.state !== 'open')
|
|
593
|
+
throw new Error('The terminal manager is not accepting operations.');
|
|
594
|
+
const projectState = this.projectState(projectIdArg);
|
|
595
|
+
if (projectState.retiring || projectState.retired) {
|
|
596
|
+
throw new Error('The project is not accepting terminal operations.');
|
|
597
|
+
}
|
|
598
|
+
if (projectState.activeOperations === 0) {
|
|
599
|
+
let resolveDrain;
|
|
600
|
+
projectState.drainPromise = new Promise((resolve) => {
|
|
601
|
+
resolveDrain = resolve;
|
|
602
|
+
});
|
|
603
|
+
projectState.resolveDrain = resolveDrain;
|
|
604
|
+
}
|
|
605
|
+
projectState.activeOperations += 1;
|
|
606
|
+
try {
|
|
607
|
+
return await operationArg();
|
|
608
|
+
}
|
|
609
|
+
finally {
|
|
610
|
+
projectState.activeOperations -= 1;
|
|
611
|
+
if (projectState.activeOperations === 0) {
|
|
612
|
+
projectState.resolveDrain?.();
|
|
613
|
+
projectState.resolveDrain = undefined;
|
|
614
|
+
projectState.drainPromise = undefined;
|
|
615
|
+
this.pruneProjectState(projectIdArg, projectState);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
waitForProjectDrain(projectStateArg) {
|
|
620
|
+
return projectStateArg.drainPromise ?? Promise.resolve();
|
|
621
|
+
}
|
|
622
|
+
async waitForAllProjectDrains() {
|
|
623
|
+
await Promise.all([...this.projectStates.values()].map((state) => this.waitForProjectDrain(state)));
|
|
624
|
+
}
|
|
625
|
+
async waitForRemovalCleanups(projectIdArg) {
|
|
626
|
+
while (true) {
|
|
627
|
+
const pending = [...this.pendingRemovalCleanups.entries()]
|
|
628
|
+
.filter(([, projectId]) => projectIdArg === undefined || projectId === projectIdArg)
|
|
629
|
+
.map(([cleanup]) => cleanup);
|
|
630
|
+
if (pending.length === 0)
|
|
631
|
+
return;
|
|
632
|
+
await Promise.all(pending);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
reserveCreate(projectIdArg) {
|
|
636
|
+
const activeForProject = [...this.entries.values()]
|
|
637
|
+
.filter((entry) => entry.projectId === projectIdArg && entry.finalState !== 'exited').length;
|
|
638
|
+
const pendingForProject = this.pendingCreatesByProject.get(projectIdArg) ?? 0;
|
|
639
|
+
if (this.entries.size + this.pendingCreates >= maxTerminals) {
|
|
640
|
+
throw new Error(`At most ${maxTerminals} controller terminals may run concurrently.`);
|
|
641
|
+
}
|
|
642
|
+
if (activeForProject + pendingForProject >= maxTerminalsPerProject) {
|
|
643
|
+
throw new Error(`At most ${maxTerminalsPerProject} terminals may run in one project.`);
|
|
644
|
+
}
|
|
645
|
+
this.pendingCreates += 1;
|
|
646
|
+
this.pendingCreatesByProject.set(projectIdArg, pendingForProject + 1);
|
|
647
|
+
}
|
|
648
|
+
releaseCreate(projectIdArg) {
|
|
649
|
+
this.pendingCreates -= 1;
|
|
650
|
+
const remaining = (this.pendingCreatesByProject.get(projectIdArg) ?? 1) - 1;
|
|
651
|
+
if (remaining <= 0)
|
|
652
|
+
this.pendingCreatesByProject.delete(projectIdArg);
|
|
653
|
+
else
|
|
654
|
+
this.pendingCreatesByProject.set(projectIdArg, remaining);
|
|
655
|
+
}
|
|
656
|
+
createTerminalId() {
|
|
657
|
+
for (let attempt = 0; attempt < 8; attempt += 1) {
|
|
658
|
+
const id = `terminal_${plugins.crypto.randomBytes(16).toString('base64url')}`;
|
|
659
|
+
if (!this.entries.has(id))
|
|
660
|
+
return id;
|
|
661
|
+
}
|
|
662
|
+
throw new Error('Unable to allocate a unique terminal identifier.');
|
|
663
|
+
}
|
|
664
|
+
requireShell() {
|
|
665
|
+
if (!this.shell || this.state !== 'open')
|
|
666
|
+
throw new Error('The terminal manager is not initialized.');
|
|
667
|
+
return this.shell;
|
|
668
|
+
}
|
|
669
|
+
requireEntry(projectIdArg, terminalIdArg) {
|
|
670
|
+
const entry = this.entries.get(terminalIdArg);
|
|
671
|
+
if (!entry || entry.projectId !== projectIdArg || entry.finalState === 'exited') {
|
|
672
|
+
throw new Error('The requested terminal does not exist in this project.');
|
|
673
|
+
}
|
|
674
|
+
return entry;
|
|
675
|
+
}
|
|
676
|
+
assertEntryRunning(entryArg) {
|
|
677
|
+
if (entryArg.closing || entryArg.finalState !== 'running') {
|
|
678
|
+
throw new Error('The terminal is not accepting operations.');
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
assertAttached(entryArg, peerIdArg) {
|
|
682
|
+
this.assertEntryRunning(entryArg);
|
|
683
|
+
const peer = entryArg.peers.get(peerIdArg);
|
|
684
|
+
if (!peer || peer.detaching)
|
|
685
|
+
throw new Error('The terminal is not attached by this peer.');
|
|
686
|
+
return peer;
|
|
687
|
+
}
|
|
688
|
+
runEntryControl(entryArg, operationArg, internalArg = false) {
|
|
689
|
+
if (!internalArg && entryArg.pendingControlOperations >= maxPendingControlOperations) {
|
|
690
|
+
return Promise.reject(new Error('The terminal control queue is full.'));
|
|
691
|
+
}
|
|
692
|
+
if (!internalArg)
|
|
693
|
+
entryArg.pendingControlOperations += 1;
|
|
694
|
+
const operation = entryArg.controlQueue.then(async () => {
|
|
695
|
+
if (entryArg.closing || entryArg.finalState !== 'running') {
|
|
696
|
+
throw new Error('The terminal is not accepting operations.');
|
|
697
|
+
}
|
|
698
|
+
return operationArg();
|
|
699
|
+
});
|
|
700
|
+
entryArg.controlQueue = operation.then(() => undefined, () => undefined);
|
|
701
|
+
if (internalArg)
|
|
702
|
+
return operation;
|
|
703
|
+
return operation.finally(() => {
|
|
704
|
+
entryArg.pendingControlOperations -= 1;
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
appendOutput(entryArg, chunkArg) {
|
|
708
|
+
if (chunkArg.byteLength === 0 || entryArg.finalState === 'exited')
|
|
709
|
+
return;
|
|
710
|
+
appendOutput(entryArg.output, chunkArg);
|
|
711
|
+
if (entryArg.closing)
|
|
712
|
+
return;
|
|
713
|
+
for (const peer of entryArg.peers.values()) {
|
|
714
|
+
if (!peer.deliveryPromise)
|
|
715
|
+
void this.schedulePeerDelivery(entryArg, peer);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
schedulePeerDelivery(entryArg, peerArg, forceResetArg = false) {
|
|
719
|
+
if (peerArg.detaching || peerArg.finalizing || entryArg.peers.get(peerArg.peerId) !== peerArg) {
|
|
720
|
+
return Promise.resolve();
|
|
721
|
+
}
|
|
722
|
+
if (peerArg.deliveryPromise)
|
|
723
|
+
return peerArg.deliveryPromise;
|
|
724
|
+
const targetEnd = entryArg.output.end;
|
|
725
|
+
const needsReset = forceResetArg || peerArg.cursor < entryArg.output.start;
|
|
726
|
+
const start = needsReset ? entryArg.output.start : Math.min(peerArg.cursor, targetEnd);
|
|
727
|
+
const delivery = this.deliverRange(entryArg, peerArg, start, targetEnd, needsReset);
|
|
728
|
+
peerArg.deliveryPromise = delivery;
|
|
729
|
+
void delivery.catch(() => {
|
|
730
|
+
if (entryArg.peers.get(peerArg.peerId) === peerArg) {
|
|
731
|
+
this.detachPeerState(entryArg, peerArg);
|
|
732
|
+
void this.requestSizeReconciliation(entryArg);
|
|
733
|
+
}
|
|
734
|
+
}).finally(() => {
|
|
735
|
+
if (peerArg.deliveryPromise === delivery)
|
|
736
|
+
peerArg.deliveryPromise = undefined;
|
|
737
|
+
if (!peerArg.detaching
|
|
738
|
+
&& !peerArg.finalizing
|
|
739
|
+
&& entryArg.peers.get(peerArg.peerId) === peerArg
|
|
740
|
+
&& peerArg.cursor < entryArg.output.end) {
|
|
741
|
+
void this.schedulePeerDelivery(entryArg, peerArg);
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
return delivery;
|
|
745
|
+
}
|
|
746
|
+
async deliverRange(entryArg, peerArg, startArg, endArg, resetArg, deadlineAtArg) {
|
|
747
|
+
let cursor = startArg;
|
|
748
|
+
let resetPending = resetArg;
|
|
749
|
+
let sentFrame = false;
|
|
750
|
+
while (cursor < endArg) {
|
|
751
|
+
if (peerArg.detaching || entryArg.peers.get(peerArg.peerId) !== peerArg)
|
|
752
|
+
return;
|
|
753
|
+
if (cursor < entryArg.output.start) {
|
|
754
|
+
cursor = entryArg.output.start;
|
|
755
|
+
peerArg.cursor = cursor;
|
|
756
|
+
resetPending = true;
|
|
757
|
+
}
|
|
758
|
+
if (cursor >= endArg)
|
|
759
|
+
break;
|
|
760
|
+
const frame = this.readOutputFrame(entryArg, cursor, endArg);
|
|
761
|
+
if (!frame || frame.byteLength === 0)
|
|
762
|
+
break;
|
|
763
|
+
const send = this.sendPeerOutput(entryArg, peerArg, frame, resetPending);
|
|
764
|
+
if (deadlineAtArg === undefined)
|
|
765
|
+
await send;
|
|
766
|
+
else
|
|
767
|
+
await waitUntil(send, deadlineAtArg);
|
|
768
|
+
if (peerArg.detaching || entryArg.peers.get(peerArg.peerId) !== peerArg)
|
|
769
|
+
return;
|
|
770
|
+
cursor += frame.byteLength;
|
|
771
|
+
peerArg.cursor = cursor;
|
|
772
|
+
resetPending = false;
|
|
773
|
+
sentFrame = true;
|
|
774
|
+
}
|
|
775
|
+
if (resetPending && !sentFrame) {
|
|
776
|
+
const send = this.sendPeerOutput(entryArg, peerArg, Buffer.alloc(0), true);
|
|
777
|
+
if (deadlineAtArg === undefined)
|
|
778
|
+
await send;
|
|
779
|
+
else
|
|
780
|
+
await waitUntil(send, deadlineAtArg);
|
|
781
|
+
peerArg.cursor = Math.max(peerArg.cursor, entryArg.output.start);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
readOutputFrame(entryArg, startArg, endArg) {
|
|
785
|
+
if (startArg >= endArg)
|
|
786
|
+
return undefined;
|
|
787
|
+
let slabStart = entryArg.output.start;
|
|
788
|
+
for (const slab of entryArg.output.slabs) {
|
|
789
|
+
const slabBytes = slab.end - slab.start;
|
|
790
|
+
const slabEnd = slabStart + slabBytes;
|
|
791
|
+
if (slabEnd <= startArg) {
|
|
792
|
+
slabStart = slabEnd;
|
|
793
|
+
continue;
|
|
794
|
+
}
|
|
795
|
+
if (slabStart >= endArg)
|
|
796
|
+
break;
|
|
797
|
+
const offset = Math.max(0, startArg - slabStart);
|
|
798
|
+
const frameBytes = Math.min(maxOutputFrameBytes, slabBytes - offset, endArg - startArg);
|
|
799
|
+
return slab.buffer.subarray(slab.start + offset, slab.start + offset + frameBytes);
|
|
800
|
+
}
|
|
801
|
+
return undefined;
|
|
802
|
+
}
|
|
803
|
+
async sendPeerOutput(entryArg, peerArg, dataArg, resetArg) {
|
|
804
|
+
if (peerArg.detaching || entryArg.peers.get(peerArg.peerId) !== peerArg)
|
|
805
|
+
return;
|
|
806
|
+
await this.options.sendOutput(peerArg.peerId, {
|
|
807
|
+
terminalId: { ...entryArg.terminal.id },
|
|
808
|
+
dataBase64: dataArg.toString('base64'),
|
|
809
|
+
...(resetArg ? { reset: true } : {}),
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
detachPeerState(entryArg, peerArg) {
|
|
813
|
+
peerArg.detaching = true;
|
|
814
|
+
if (entryArg.peers.get(peerArg.peerId) === peerArg) {
|
|
815
|
+
entryArg.peers.delete(peerArg.peerId);
|
|
816
|
+
if (entryArg.sizesByPeer.delete(peerArg.peerId))
|
|
817
|
+
entryArg.sizeRevision += 1;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
async applyMinimumSize(entryArg) {
|
|
821
|
+
if (entryArg.sizesByPeer.size === 0 || entryArg.closing)
|
|
822
|
+
return;
|
|
823
|
+
let rows = Number.POSITIVE_INFINITY;
|
|
824
|
+
let cols = Number.POSITIVE_INFINITY;
|
|
825
|
+
for (const size of entryArg.sizesByPeer.values()) {
|
|
826
|
+
rows = Math.min(rows, size.rows);
|
|
827
|
+
cols = Math.min(cols, size.cols);
|
|
828
|
+
}
|
|
829
|
+
if (Number.isFinite(rows) && Number.isFinite(cols)) {
|
|
830
|
+
await entryArg.execution.resize(cols, rows);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
async applyMinimumSizeUntilStable(entryArg) {
|
|
834
|
+
if (entryArg.sizeReconciliationActive || entryArg.closing)
|
|
835
|
+
return;
|
|
836
|
+
entryArg.sizeReconciliationActive = true;
|
|
837
|
+
try {
|
|
838
|
+
let appliedRevision;
|
|
839
|
+
do {
|
|
840
|
+
appliedRevision = entryArg.sizeRevision;
|
|
841
|
+
await this.applyMinimumSize(entryArg);
|
|
842
|
+
} while (!entryArg.closing && appliedRevision !== entryArg.sizeRevision);
|
|
843
|
+
}
|
|
844
|
+
finally {
|
|
845
|
+
entryArg.sizeReconciliationActive = false;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
requestSizeReconciliation(entryArg) {
|
|
849
|
+
if (entryArg.closing || entryArg.sizeReconciliationActive)
|
|
850
|
+
return Promise.resolve();
|
|
851
|
+
if (entryArg.sizeReconciliationPromise)
|
|
852
|
+
return entryArg.sizeReconciliationPromise;
|
|
853
|
+
const reconciliation = this.runEntryControl(entryArg, () => this.applyMinimumSizeUntilStable(entryArg), true);
|
|
854
|
+
entryArg.sizeReconciliationPromise = reconciliation;
|
|
855
|
+
void reconciliation.catch(() => undefined).finally(() => {
|
|
856
|
+
if (entryArg.sizeReconciliationPromise === reconciliation) {
|
|
857
|
+
entryArg.sizeReconciliationPromise = undefined;
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
return reconciliation;
|
|
861
|
+
}
|
|
862
|
+
confirmRootExit(entryArg, exitCodeArg) {
|
|
863
|
+
if (entryArg.finalState === 'exited')
|
|
864
|
+
return;
|
|
865
|
+
entryArg.finalState = 'exited';
|
|
866
|
+
if (exitCodeArg !== undefined)
|
|
867
|
+
entryArg.exitCode = exitCodeArg;
|
|
868
|
+
entryArg.exitSubscription?.dispose();
|
|
869
|
+
entryArg.resolveRootExit();
|
|
870
|
+
entryArg.finalizePromise = this.finalizeExitedEntry(entryArg, entryArg.finalizationDeadlineAt ?? Date.now() + this.cleanupTimeoutMs);
|
|
871
|
+
}
|
|
872
|
+
async finalizeExitedPeer(entryArg, peerArg, finalOutputEndArg, deadlineAtArg) {
|
|
873
|
+
if (peerArg.detaching || entryArg.peers.get(peerArg.peerId) !== peerArg)
|
|
874
|
+
return;
|
|
875
|
+
peerArg.finalizing = true;
|
|
876
|
+
try {
|
|
877
|
+
if (peerArg.deliveryPromise) {
|
|
878
|
+
await waitUntil(peerArg.deliveryPromise, deadlineAtArg);
|
|
879
|
+
}
|
|
880
|
+
if (peerArg.detaching || entryArg.peers.get(peerArg.peerId) !== peerArg)
|
|
881
|
+
return;
|
|
882
|
+
const needsReset = peerArg.cursor < entryArg.output.start;
|
|
883
|
+
await this.deliverRange(entryArg, peerArg, needsReset ? entryArg.output.start : peerArg.cursor, finalOutputEndArg, needsReset, deadlineAtArg);
|
|
884
|
+
if (peerArg.detaching
|
|
885
|
+
|| entryArg.peers.get(peerArg.peerId) !== peerArg
|
|
886
|
+
|| peerArg.cursor < finalOutputEndArg)
|
|
887
|
+
return;
|
|
888
|
+
await waitUntil(this.options.sendOutput(peerArg.peerId, {
|
|
889
|
+
terminalId: { ...entryArg.terminal.id },
|
|
890
|
+
dataBase64: '',
|
|
891
|
+
ended: true,
|
|
892
|
+
}), deadlineAtArg);
|
|
893
|
+
}
|
|
894
|
+
catch {
|
|
895
|
+
// A stalled peer is detached without an ended frame; output can never race ended.
|
|
896
|
+
}
|
|
897
|
+
finally {
|
|
898
|
+
this.detachPeerState(entryArg, peerArg);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
async finalizeExitedEntry(entryArg, deadlineAtArg) {
|
|
902
|
+
if (this.entries.get(entryArg.terminal.id.nativeId) !== entryArg)
|
|
903
|
+
return;
|
|
904
|
+
const finalOutputEnd = entryArg.output.end;
|
|
905
|
+
await Promise.allSettled([...entryArg.peers.values()].map((peer) => (this.finalizeExitedPeer(entryArg, peer, finalOutputEnd, deadlineAtArg))));
|
|
906
|
+
this.entries.delete(entryArg.terminal.id.nativeId);
|
|
907
|
+
entryArg.peers.clear();
|
|
908
|
+
entryArg.sizesByPeer.clear();
|
|
909
|
+
const terminalId = { ...entryArg.terminal.id };
|
|
910
|
+
const removalCleanup = Promise.resolve()
|
|
911
|
+
.then(() => this.options.onTerminalStopped(entryArg.projectId, terminalId, entryArg.exitCode))
|
|
912
|
+
.catch(() => undefined);
|
|
913
|
+
this.pendingRemovalCleanups.set(removalCleanup, entryArg.projectId);
|
|
914
|
+
try {
|
|
915
|
+
await waitUntil(removalCleanup, deadlineAtArg);
|
|
916
|
+
}
|
|
917
|
+
catch {
|
|
918
|
+
// Resource ownership is already released; startup pruning recovers a timed-out cleanup.
|
|
919
|
+
}
|
|
920
|
+
finally {
|
|
921
|
+
this.pendingRemovalCleanups.delete(removalCleanup);
|
|
922
|
+
}
|
|
923
|
+
try {
|
|
924
|
+
this.options.onTerminalsChanged(entryArg.projectId);
|
|
925
|
+
}
|
|
926
|
+
catch {
|
|
927
|
+
// Root ownership is already released; a notification callback cannot restore it.
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
async closeEntry(entryArg, deadlineAtArg) {
|
|
931
|
+
if (this.entries.get(entryArg.terminal.id.nativeId) !== entryArg)
|
|
932
|
+
return;
|
|
933
|
+
if (entryArg.finalState === 'exited') {
|
|
934
|
+
await waitUntil(entryArg.finalizePromise ?? Promise.resolve(), deadlineAtArg);
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
if (!entryArg.closeLifecyclePromise) {
|
|
938
|
+
entryArg.closing = true;
|
|
939
|
+
entryArg.finalizationDeadlineAt = deadlineAtArg;
|
|
940
|
+
const lifecycle = (async () => {
|
|
941
|
+
await entryArg.rootExitPromise;
|
|
942
|
+
await entryArg.finalizePromise;
|
|
943
|
+
})();
|
|
944
|
+
entryArg.closeLifecyclePromise = lifecycle;
|
|
945
|
+
try {
|
|
946
|
+
const signal = entryArg.execution.kill();
|
|
947
|
+
void signal.catch((errorArg) => {
|
|
948
|
+
entryArg.signalError = normalizeError(errorArg);
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
catch (errorArg) {
|
|
952
|
+
entryArg.signalError = normalizeError(errorArg);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
try {
|
|
956
|
+
await waitUntil(entryArg.closeLifecyclePromise, deadlineAtArg);
|
|
957
|
+
}
|
|
958
|
+
catch (errorArg) {
|
|
959
|
+
if (this.entries.get(entryArg.terminal.id.nativeId) !== entryArg)
|
|
960
|
+
return;
|
|
961
|
+
throw entryArg.signalError
|
|
962
|
+
? new AggregateError([entryArg.signalError, errorArg], 'The terminal root could not be confirmed stopped.')
|
|
963
|
+
: errorArg;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
async closeProjectEntries(projectIdArg, deadlineAtArg) {
|
|
967
|
+
const outcomes = await Promise.allSettled([...this.entries.values()]
|
|
968
|
+
.filter((entry) => entry.projectId === projectIdArg)
|
|
969
|
+
.map((entry) => this.closeEntry(entry, deadlineAtArg)));
|
|
970
|
+
const errors = outcomes.flatMap((outcome) => (outcome.status === 'rejected' ? [outcome.reason] : []));
|
|
971
|
+
const remaining = [...this.entries.values()]
|
|
972
|
+
.filter((entry) => entry.projectId === projectIdArg);
|
|
973
|
+
if (remaining.length > 0) {
|
|
974
|
+
errors.push(new Error('One or more project terminal roots remain unconfirmed.'));
|
|
975
|
+
}
|
|
976
|
+
if (errors.length > 0) {
|
|
977
|
+
throw new AggregateError(errors, 'The project terminal roots could not all be confirmed stopped.');
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy50ZXJtaW5hbG1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9jbGFzc2VzLnRlcm1pbmFsbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUd4QyxPQUFPLEVBQUUsaUNBQWlDLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQXNHdEYsTUFBTSxZQUFZLEdBQUcsRUFBRSxDQUFDO0FBQ3hCLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxDQUFDO0FBQ2pDLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFDM0MsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQztBQUMzQyxNQUFNLGFBQWEsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDO0FBQy9CLE1BQU0sbUJBQW1CLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUN0QyxNQUFNLG1CQUFtQixHQUFHLEVBQUUsQ0FBQztBQUMvQixNQUFNLDJCQUEyQixHQUFHLEdBQUcsQ0FBQztBQUN4QyxNQUFNLHVCQUF1QixHQUFHLE1BQU0sQ0FBQztBQUV2QyxNQUFNLGNBQWMsR0FBRyxDQUFDLFFBQWlCLEVBQVMsRUFBRSxDQUNsRCxRQUFRLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0FBRXJFLE1BQU0sYUFBYSxHQUFHLENBQUMsV0FBcUMsRUFBdUIsRUFBRSxDQUFDLENBQUM7SUFDckYsR0FBRyxXQUFXO0lBQ2QsRUFBRSxFQUFFLEVBQUUsR0FBRyxXQUFXLENBQUMsRUFBRSxFQUFFO0NBQzFCLENBQUMsQ0FBQztBQUVILE1BQU0sa0JBQWtCLEdBQUcsQ0FDekIsUUFBdUIsRUFDdkIsZUFBdUIsRUFDdkIsUUFB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
|