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,1003 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { openCodeExpectedVersion, openCodeUsername, } from './interfaces.opencode.js';
|
|
3
|
+
import { createSanitizedRuntimeEnvironment } from './functions.runtimeenvironment.js';
|
|
4
|
+
const defaultStartupTimeoutMs = 20_000;
|
|
5
|
+
const defaultHealthRequestTimeoutMs = 1_500;
|
|
6
|
+
const defaultHealthPollIntervalMs = 150;
|
|
7
|
+
const defaultStopTimeoutMs = 5_000;
|
|
8
|
+
const defaultFinalStopTimeoutMs = 2_000;
|
|
9
|
+
const defaultLogEntryLimit = 200;
|
|
10
|
+
const defaultLogLineByteLimit = 8 * 1024;
|
|
11
|
+
const maxHealthResponseBytes = 32 * 1024;
|
|
12
|
+
const logTruncationSuffix = '… [truncated]';
|
|
13
|
+
const macOsLsofPath = '/usr/sbin/lsof';
|
|
14
|
+
class OpenCodeVersionMismatchError extends Error {
|
|
15
|
+
}
|
|
16
|
+
class OpenCodeListenerOwnershipError extends Error {
|
|
17
|
+
}
|
|
18
|
+
const validateIntegerOption = (value, fallback, name, minimum, maximum) => {
|
|
19
|
+
const selected = value ?? fallback;
|
|
20
|
+
if (!Number.isInteger(selected) || selected < minimum || selected > maximum) {
|
|
21
|
+
throw new Error(`${name} must be an integer between ${minimum} and ${maximum}.`);
|
|
22
|
+
}
|
|
23
|
+
return selected;
|
|
24
|
+
};
|
|
25
|
+
const waitForPauseOrLifecycle = async (milliseconds, lifecycle, signal) => {
|
|
26
|
+
let timeout;
|
|
27
|
+
let abortListener;
|
|
28
|
+
try {
|
|
29
|
+
const outcomes = [
|
|
30
|
+
new Promise((resolve) => {
|
|
31
|
+
timeout = setTimeout(() => resolve(undefined), milliseconds);
|
|
32
|
+
}),
|
|
33
|
+
lifecycle,
|
|
34
|
+
];
|
|
35
|
+
if (signal) {
|
|
36
|
+
outcomes.push(new Promise((resolve) => {
|
|
37
|
+
if (signal.aborted) {
|
|
38
|
+
resolve({ type: 'abort', reason: signal.reason });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
abortListener = () => resolve({ type: 'abort', reason: signal.reason });
|
|
42
|
+
signal.addEventListener('abort', abortListener, { once: true });
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
return await Promise.race(outcomes);
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
if (timeout) {
|
|
49
|
+
clearTimeout(timeout);
|
|
50
|
+
}
|
|
51
|
+
if (signal && abortListener) {
|
|
52
|
+
signal.removeEventListener('abort', abortListener);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const waitForStartupOperation = async (operation, lifecycle, signal) => {
|
|
57
|
+
let abortListener;
|
|
58
|
+
try {
|
|
59
|
+
const outcomes = [
|
|
60
|
+
operation.then((value) => ({ type: 'value', value }), (error) => ({ type: 'operationError', error })),
|
|
61
|
+
lifecycle.then((outcome) => ({ type: 'lifecycle', outcome })),
|
|
62
|
+
];
|
|
63
|
+
if (signal) {
|
|
64
|
+
outcomes.push(new Promise((resolve) => {
|
|
65
|
+
if (signal.aborted) {
|
|
66
|
+
resolve({ type: 'abort', reason: signal.reason });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
abortListener = () => resolve({ type: 'abort', reason: signal.reason });
|
|
70
|
+
signal.addEventListener('abort', abortListener, { once: true });
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
return await Promise.race(outcomes);
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
if (signal && abortListener) {
|
|
77
|
+
signal.removeEventListener('abort', abortListener);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const startupAbortError = (reason) => reason instanceof Error
|
|
82
|
+
? reason
|
|
83
|
+
: new Error('OpenCode startup was aborted.', { cause: reason });
|
|
84
|
+
const waitBounded = async (promise, timeoutMs) => {
|
|
85
|
+
let timeout;
|
|
86
|
+
try {
|
|
87
|
+
return await Promise.race([
|
|
88
|
+
promise.then(() => true),
|
|
89
|
+
new Promise((resolve) => {
|
|
90
|
+
timeout = setTimeout(() => resolve(false), timeoutMs);
|
|
91
|
+
}),
|
|
92
|
+
]);
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
if (timeout) {
|
|
96
|
+
clearTimeout(timeout);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const isMissingProcessError = (errorArg) => typeof errorArg === 'object'
|
|
101
|
+
&& errorArg !== null
|
|
102
|
+
&& 'code' in errorArg
|
|
103
|
+
&& errorArg.code === 'ESRCH';
|
|
104
|
+
const defaultProcessGroupController = {
|
|
105
|
+
isAlive: (processGroupIdArg) => {
|
|
106
|
+
try {
|
|
107
|
+
process.kill(-processGroupIdArg, 0);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
catch (errorArg) {
|
|
111
|
+
if (isMissingProcessError(errorArg))
|
|
112
|
+
return false;
|
|
113
|
+
throw errorArg;
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
signal: (processGroupIdArg, signalArg) => {
|
|
117
|
+
try {
|
|
118
|
+
process.kill(-processGroupIdArg, signalArg);
|
|
119
|
+
}
|
|
120
|
+
catch (errorArg) {
|
|
121
|
+
if (!isMissingProcessError(errorArg))
|
|
122
|
+
throw errorArg;
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
const waitForProcessGroupExit = async (processGroupControllerArg, processGroupIdArg, timeoutMsArg) => {
|
|
127
|
+
const deadline = Date.now() + timeoutMsArg;
|
|
128
|
+
while (await processGroupControllerArg.isAlive(processGroupIdArg)) {
|
|
129
|
+
const remainingMs = deadline - Date.now();
|
|
130
|
+
if (remainingMs <= 0)
|
|
131
|
+
return false;
|
|
132
|
+
await new Promise((resolve) => {
|
|
133
|
+
setTimeout(resolve, Math.min(20, remainingMs));
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
};
|
|
138
|
+
const truncateLogLine = (value, byteLimit) => {
|
|
139
|
+
if (Buffer.byteLength(value, 'utf8') <= byteLimit) {
|
|
140
|
+
return { line: value, truncated: false };
|
|
141
|
+
}
|
|
142
|
+
const suffixBytes = Buffer.byteLength(logTruncationSuffix, 'utf8');
|
|
143
|
+
const contentBytes = Math.max(0, byteLimit - suffixBytes);
|
|
144
|
+
let line = Buffer.from(value, 'utf8').subarray(0, contentBytes).toString('utf8');
|
|
145
|
+
line = line.replace(/\uFFFD$/u, '');
|
|
146
|
+
return {
|
|
147
|
+
line: `${line}${logTruncationSuffix}`,
|
|
148
|
+
truncated: true,
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
const readBoundedResponseText = async (response) => {
|
|
152
|
+
if (!response.body) {
|
|
153
|
+
return '';
|
|
154
|
+
}
|
|
155
|
+
const reader = response.body.getReader();
|
|
156
|
+
const chunks = [];
|
|
157
|
+
let byteLength = 0;
|
|
158
|
+
try {
|
|
159
|
+
while (true) {
|
|
160
|
+
const { done, value } = await reader.read();
|
|
161
|
+
if (done) {
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
byteLength += value.byteLength;
|
|
165
|
+
if (byteLength > maxHealthResponseBytes) {
|
|
166
|
+
await reader.cancel('OpenCode health response exceeded its size limit.');
|
|
167
|
+
throw new Error('OpenCode health response exceeded its size limit.');
|
|
168
|
+
}
|
|
169
|
+
chunks.push(value);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
finally {
|
|
173
|
+
reader.releaseLock();
|
|
174
|
+
}
|
|
175
|
+
const body = new Uint8Array(byteLength);
|
|
176
|
+
let offset = 0;
|
|
177
|
+
for (const chunk of chunks) {
|
|
178
|
+
body.set(chunk, offset);
|
|
179
|
+
offset += chunk.byteLength;
|
|
180
|
+
}
|
|
181
|
+
return new TextDecoder().decode(body);
|
|
182
|
+
};
|
|
183
|
+
const createOpenCodeEnvironment = (password) => {
|
|
184
|
+
const environment = createSanitizedRuntimeEnvironment();
|
|
185
|
+
environment.OPENCODE_SERVER_USERNAME = openCodeUsername;
|
|
186
|
+
environment.OPENCODE_SERVER_PASSWORD = password;
|
|
187
|
+
return environment;
|
|
188
|
+
};
|
|
189
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
190
|
+
const detectLinuxLibc = () => {
|
|
191
|
+
const report = process.report?.getReport();
|
|
192
|
+
if (isRecord(report)) {
|
|
193
|
+
const header = isRecord(report.header) ? report.header : undefined;
|
|
194
|
+
if (typeof header?.glibcVersionRuntime === 'string' &&
|
|
195
|
+
header.glibcVersionRuntime.length > 0) {
|
|
196
|
+
return 'glibc';
|
|
197
|
+
}
|
|
198
|
+
if (Array.isArray(report.sharedObjects) &&
|
|
199
|
+
report.sharedObjects.some((entry) => typeof entry === 'string' &&
|
|
200
|
+
(entry.includes('/ld-musl-') || entry.includes('/libc.musl-')))) {
|
|
201
|
+
return 'musl';
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (plugins.fs.existsSync('/etc/alpine-release')) {
|
|
205
|
+
return 'musl';
|
|
206
|
+
}
|
|
207
|
+
throw new Error('Unable to determine whether this Linux runtime uses glibc or musl.');
|
|
208
|
+
};
|
|
209
|
+
const resolvePlatformPackage = () => {
|
|
210
|
+
if (process.platform === 'linux') {
|
|
211
|
+
const libcSuffix = detectLinuxLibc() === 'musl' ? '-musl' : '';
|
|
212
|
+
if (process.arch === 'x64') {
|
|
213
|
+
return {
|
|
214
|
+
packageName: `opencode-linux-x64-baseline${libcSuffix}`,
|
|
215
|
+
binaryName: 'opencode',
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
if (process.arch === 'arm64') {
|
|
219
|
+
return {
|
|
220
|
+
packageName: `opencode-linux-arm64${libcSuffix}`,
|
|
221
|
+
binaryName: 'opencode',
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else if (process.platform === 'darwin') {
|
|
226
|
+
if (process.arch === 'x64') {
|
|
227
|
+
return {
|
|
228
|
+
packageName: 'opencode-darwin-x64-baseline',
|
|
229
|
+
binaryName: 'opencode',
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
if (process.arch === 'arm64') {
|
|
233
|
+
return {
|
|
234
|
+
packageName: 'opencode-darwin-arm64',
|
|
235
|
+
binaryName: 'opencode',
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else if (process.platform === 'win32') {
|
|
240
|
+
if (process.arch === 'x64') {
|
|
241
|
+
return {
|
|
242
|
+
packageName: 'opencode-windows-x64-baseline',
|
|
243
|
+
binaryName: 'opencode.exe',
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
if (process.arch === 'arm64') {
|
|
247
|
+
return {
|
|
248
|
+
packageName: 'opencode-windows-arm64',
|
|
249
|
+
binaryName: 'opencode.exe',
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
throw new Error(`OpenCode does not provide a supported package for ${process.platform}/${process.arch}.`);
|
|
254
|
+
};
|
|
255
|
+
const collectLinuxLoopbackListenerInodes = (port) => {
|
|
256
|
+
const portHex = port.toString(16).toUpperCase().padStart(4, '0');
|
|
257
|
+
const expectedAddress = `0100007F:${portHex}`;
|
|
258
|
+
const inodes = new Set();
|
|
259
|
+
const table = plugins.fs.readFileSync('/proc/net/tcp', 'utf8');
|
|
260
|
+
for (const line of table.split('\n').slice(1)) {
|
|
261
|
+
const fields = line.trim().split(/\s+/u);
|
|
262
|
+
if (fields.length >= 10 && fields[1] === expectedAddress && fields[3] === '0A') {
|
|
263
|
+
inodes.add(fields[9]);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return inodes;
|
|
267
|
+
};
|
|
268
|
+
const verifyLinuxListenerOwnership = (processId, port) => {
|
|
269
|
+
const listenerInodes = collectLinuxLoopbackListenerInodes(port);
|
|
270
|
+
if (listenerInodes.size === 0) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
const descriptorDirectory = `/proc/${processId}/fd`;
|
|
274
|
+
let descriptorNames;
|
|
275
|
+
try {
|
|
276
|
+
descriptorNames = plugins.fs.readdirSync(descriptorDirectory);
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
if (error.code === 'ENOENT') {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
throw new Error(`Unable to inspect OpenCode process ${processId} file descriptors.`, {
|
|
283
|
+
cause: error,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
for (const descriptorName of descriptorNames) {
|
|
287
|
+
let target;
|
|
288
|
+
try {
|
|
289
|
+
target = plugins.fs.readlinkSync(plugins.path.join(descriptorDirectory, descriptorName));
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
if (error.code === 'ENOENT') {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
throw new Error(`Unable to inspect OpenCode process ${processId} socket ownership.`, {
|
|
296
|
+
cause: error,
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
const match = /^socket:\[(\d+)\]$/u.exec(target);
|
|
300
|
+
if (match?.[1] && listenerInodes.has(match[1])) {
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return false;
|
|
305
|
+
};
|
|
306
|
+
const verifyMacOsListenerOwnership = (processId, port) => {
|
|
307
|
+
const result = plugins.childProcess.spawnSync(macOsLsofPath, [
|
|
308
|
+
'-nP',
|
|
309
|
+
'-a',
|
|
310
|
+
'-p',
|
|
311
|
+
String(processId),
|
|
312
|
+
`-iTCP@127.0.0.1:${port}`,
|
|
313
|
+
'-sTCP:LISTEN',
|
|
314
|
+
'-Fpn',
|
|
315
|
+
], {
|
|
316
|
+
encoding: 'utf8',
|
|
317
|
+
maxBuffer: 64 * 1024,
|
|
318
|
+
timeout: 1_500,
|
|
319
|
+
windowsHide: true,
|
|
320
|
+
});
|
|
321
|
+
if (result.error) {
|
|
322
|
+
throw new Error('Unable to inspect OpenCode listener ownership with lsof.', {
|
|
323
|
+
cause: result.error,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
if (result.status === 1) {
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
if (result.status !== 0) {
|
|
330
|
+
throw new Error(`lsof failed while inspecting OpenCode with status ${result.status}.`);
|
|
331
|
+
}
|
|
332
|
+
const lines = result.stdout.split(/\r?\n/u);
|
|
333
|
+
return (lines.includes(`p${processId}`) &&
|
|
334
|
+
lines.some((line) => line === `n127.0.0.1:${port}`));
|
|
335
|
+
};
|
|
336
|
+
const verifyWindowsListenerOwnership = (processId, port) => {
|
|
337
|
+
const systemRoot = process.env.SystemRoot;
|
|
338
|
+
if (!systemRoot || !plugins.path.isAbsolute(systemRoot)) {
|
|
339
|
+
throw new Error('SystemRoot is unavailable for Windows listener ownership verification.');
|
|
340
|
+
}
|
|
341
|
+
const resolvedSystemRoot = plugins.fs.realpathSync.native(systemRoot);
|
|
342
|
+
const netstatPath = plugins.fs.realpathSync.native(plugins.path.join(resolvedSystemRoot, 'System32', 'netstat.exe'));
|
|
343
|
+
const relativeNetstatPath = plugins.path.relative(resolvedSystemRoot, netstatPath);
|
|
344
|
+
if (relativeNetstatPath.startsWith(`..${plugins.path.sep}`) ||
|
|
345
|
+
relativeNetstatPath === '..' ||
|
|
346
|
+
plugins.path.isAbsolute(relativeNetstatPath)) {
|
|
347
|
+
throw new Error('The Windows netstat executable escaped SystemRoot.');
|
|
348
|
+
}
|
|
349
|
+
const result = plugins.childProcess.spawnSync(netstatPath, ['-ano', '-p', 'tcp'], {
|
|
350
|
+
encoding: 'utf8',
|
|
351
|
+
maxBuffer: 2 * 1024 * 1024,
|
|
352
|
+
timeout: 1_500,
|
|
353
|
+
windowsHide: true,
|
|
354
|
+
});
|
|
355
|
+
if (result.error) {
|
|
356
|
+
throw new Error('Unable to inspect OpenCode listener ownership with netstat.', {
|
|
357
|
+
cause: result.error,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
if (result.status !== 0) {
|
|
361
|
+
throw new Error(`netstat failed while inspecting OpenCode with status ${result.status}.`);
|
|
362
|
+
}
|
|
363
|
+
const expectedEndpoint = `127.0.0.1:${port}`;
|
|
364
|
+
return result.stdout.split(/\r?\n/u).some((line) => {
|
|
365
|
+
const fields = line.trim().split(/\s+/u);
|
|
366
|
+
return (fields.length >= 5 &&
|
|
367
|
+
fields[0]?.toUpperCase() === 'TCP' &&
|
|
368
|
+
fields[1] === expectedEndpoint &&
|
|
369
|
+
fields[3]?.toUpperCase() === 'LISTENING' &&
|
|
370
|
+
fields[4] === String(processId));
|
|
371
|
+
});
|
|
372
|
+
};
|
|
373
|
+
export const verifyOpenCodeListenerOwnership = (processId, port) => {
|
|
374
|
+
if (!Number.isSafeInteger(processId) || processId <= 0) {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
if (process.platform === 'linux') {
|
|
378
|
+
return verifyLinuxListenerOwnership(processId, port);
|
|
379
|
+
}
|
|
380
|
+
if (process.platform === 'darwin') {
|
|
381
|
+
return verifyMacOsListenerOwnership(processId, port);
|
|
382
|
+
}
|
|
383
|
+
if (process.platform === 'win32') {
|
|
384
|
+
return verifyWindowsListenerOwnership(processId, port);
|
|
385
|
+
}
|
|
386
|
+
throw new Error(`Listener ownership verification is unsupported on ${process.platform}.`);
|
|
387
|
+
};
|
|
388
|
+
export class OpenCodeSupervisor {
|
|
389
|
+
directory;
|
|
390
|
+
port;
|
|
391
|
+
baseUrl;
|
|
392
|
+
executablePath;
|
|
393
|
+
password;
|
|
394
|
+
startupTimeoutMs;
|
|
395
|
+
healthRequestTimeoutMs;
|
|
396
|
+
healthPollIntervalMs;
|
|
397
|
+
stopTimeoutMs;
|
|
398
|
+
finalStopTimeoutMs;
|
|
399
|
+
logEntryLimit;
|
|
400
|
+
logLineByteLimit;
|
|
401
|
+
spawnFactory;
|
|
402
|
+
fetchImplementation;
|
|
403
|
+
listenerOwnershipVerifier;
|
|
404
|
+
processGroupController;
|
|
405
|
+
onChildExit;
|
|
406
|
+
state = 'stopped';
|
|
407
|
+
healthy = false;
|
|
408
|
+
version;
|
|
409
|
+
startedAt;
|
|
410
|
+
child;
|
|
411
|
+
childLifecycle;
|
|
412
|
+
ownedProcessGroupId;
|
|
413
|
+
orphanedProcessGroupId;
|
|
414
|
+
orphanReapTask;
|
|
415
|
+
childExitCleanupPending = false;
|
|
416
|
+
startPromise;
|
|
417
|
+
stopPromise;
|
|
418
|
+
logs = [];
|
|
419
|
+
stdoutAccumulator = {
|
|
420
|
+
decoder: new TextDecoder(),
|
|
421
|
+
partial: '',
|
|
422
|
+
droppingUntilNewline: false,
|
|
423
|
+
};
|
|
424
|
+
stderrAccumulator = {
|
|
425
|
+
decoder: new TextDecoder(),
|
|
426
|
+
partial: '',
|
|
427
|
+
droppingUntilNewline: false,
|
|
428
|
+
};
|
|
429
|
+
constructor(options) {
|
|
430
|
+
this.directory = plugins.fs.realpathSync.native(options.directory);
|
|
431
|
+
const directoryStat = plugins.fs.statSync(this.directory);
|
|
432
|
+
if (!directoryStat.isDirectory()) {
|
|
433
|
+
throw new Error('The configured OpenCode working directory is not a directory.');
|
|
434
|
+
}
|
|
435
|
+
this.port = validateIntegerOption(options.port, options.port, 'OpenCode port', 1, 65_535);
|
|
436
|
+
this.baseUrl = `http://127.0.0.1:${this.port}`;
|
|
437
|
+
this.startupTimeoutMs = validateIntegerOption(options.startupTimeoutMs, defaultStartupTimeoutMs, 'OpenCode startup timeout', 1, 300_000);
|
|
438
|
+
this.healthRequestTimeoutMs = validateIntegerOption(options.healthRequestTimeoutMs, defaultHealthRequestTimeoutMs, 'OpenCode health request timeout', 1, 60_000);
|
|
439
|
+
this.healthPollIntervalMs = validateIntegerOption(options.healthPollIntervalMs, defaultHealthPollIntervalMs, 'OpenCode health poll interval', 1, 60_000);
|
|
440
|
+
this.stopTimeoutMs = validateIntegerOption(options.stopTimeoutMs, defaultStopTimeoutMs, 'OpenCode stop timeout', 1, 300_000);
|
|
441
|
+
this.finalStopTimeoutMs = validateIntegerOption(options.finalStopTimeoutMs, defaultFinalStopTimeoutMs, 'OpenCode final stop timeout', 1, 60_000);
|
|
442
|
+
this.logEntryLimit = validateIntegerOption(options.logEntryLimit, defaultLogEntryLimit, 'OpenCode log entry limit', 1, 10_000);
|
|
443
|
+
this.logLineByteLimit = validateIntegerOption(options.logLineByteLimit, defaultLogLineByteLimit, 'OpenCode log line byte limit', 16, 1024 * 1024);
|
|
444
|
+
this.spawnFactory = options.spawnFactory ?? plugins.childProcess.spawn;
|
|
445
|
+
this.fetchImplementation = options.fetchImplementation ?? globalThis.fetch;
|
|
446
|
+
this.listenerOwnershipVerifier =
|
|
447
|
+
options.listenerOwnershipVerifier ?? verifyOpenCodeListenerOwnership;
|
|
448
|
+
this.processGroupController = process.platform !== 'win32'
|
|
449
|
+
&& (options.spawnFactory === undefined || options.processGroupController !== undefined)
|
|
450
|
+
? (options.processGroupController ?? defaultProcessGroupController)
|
|
451
|
+
: undefined;
|
|
452
|
+
this.onChildExit = options.onChildExit;
|
|
453
|
+
this.password = plugins.crypto.randomBytes(32).toString('base64url');
|
|
454
|
+
this.executablePath = this.resolveExecutablePath();
|
|
455
|
+
}
|
|
456
|
+
getStatus() {
|
|
457
|
+
return {
|
|
458
|
+
state: this.state,
|
|
459
|
+
healthy: this.healthy,
|
|
460
|
+
...(this.child?.pid ? { pid: this.child.pid } : {}),
|
|
461
|
+
...(this.version ? { version: this.version } : {}),
|
|
462
|
+
...(this.startedAt ? { startedAt: this.startedAt } : {}),
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
getConnectionConfig() {
|
|
466
|
+
return {
|
|
467
|
+
baseUrl: this.baseUrl,
|
|
468
|
+
directory: this.directory,
|
|
469
|
+
username: openCodeUsername,
|
|
470
|
+
password: this.password,
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
getLogSnapshot() {
|
|
474
|
+
return this.logs.map((entry) => ({ ...entry }));
|
|
475
|
+
}
|
|
476
|
+
async start(signal) {
|
|
477
|
+
if (this.state === 'ready' && this.child) {
|
|
478
|
+
return this.getStatus();
|
|
479
|
+
}
|
|
480
|
+
if (this.startPromise) {
|
|
481
|
+
return this.startPromise;
|
|
482
|
+
}
|
|
483
|
+
if (this.state === 'stopping') {
|
|
484
|
+
throw new Error('OpenCode cannot start while it is stopping.');
|
|
485
|
+
}
|
|
486
|
+
const startPromise = this.performStart(signal);
|
|
487
|
+
this.startPromise = startPromise;
|
|
488
|
+
try {
|
|
489
|
+
return await startPromise;
|
|
490
|
+
}
|
|
491
|
+
finally {
|
|
492
|
+
if (this.startPromise === startPromise) {
|
|
493
|
+
this.startPromise = undefined;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
async checkHealth() {
|
|
498
|
+
try {
|
|
499
|
+
const health = await this.fetchHealth();
|
|
500
|
+
this.healthy = true;
|
|
501
|
+
this.version = health.version;
|
|
502
|
+
return health;
|
|
503
|
+
}
|
|
504
|
+
catch (error) {
|
|
505
|
+
this.healthy = false;
|
|
506
|
+
throw error;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
async stop() {
|
|
510
|
+
if (this.stopPromise) {
|
|
511
|
+
return this.stopPromise;
|
|
512
|
+
}
|
|
513
|
+
const child = this.child;
|
|
514
|
+
const lifecycle = this.childLifecycle;
|
|
515
|
+
if (!child || !lifecycle) {
|
|
516
|
+
if (this.ownedProcessGroupId !== undefined) {
|
|
517
|
+
throw new Error('OpenCode process-group ownership outlived child lifecycle tracking.');
|
|
518
|
+
}
|
|
519
|
+
await this.drainOrphanedProcessGroup();
|
|
520
|
+
this.child = undefined;
|
|
521
|
+
this.childLifecycle = undefined;
|
|
522
|
+
this.healthy = false;
|
|
523
|
+
this.state = 'stopped';
|
|
524
|
+
this.startedAt = undefined;
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
const stopPromise = this.performStop(child, lifecycle);
|
|
528
|
+
this.stopPromise = stopPromise;
|
|
529
|
+
try {
|
|
530
|
+
await stopPromise;
|
|
531
|
+
}
|
|
532
|
+
finally {
|
|
533
|
+
if (this.stopPromise === stopPromise) {
|
|
534
|
+
this.stopPromise = undefined;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
resolveExecutablePath() {
|
|
539
|
+
const require = plugins.createRequire(import.meta.url);
|
|
540
|
+
const platformPackage = resolvePlatformPackage();
|
|
541
|
+
const platformPackageJsonPath = plugins.fs.realpathSync.native(require.resolve(`${platformPackage.packageName}/package.json`));
|
|
542
|
+
const installedPackageJson = JSON.parse(plugins.fs.readFileSync(platformPackageJsonPath, 'utf8'));
|
|
543
|
+
if (!isRecord(installedPackageJson) ||
|
|
544
|
+
installedPackageJson.name !== platformPackage.packageName ||
|
|
545
|
+
installedPackageJson.version !== openCodeExpectedVersion) {
|
|
546
|
+
throw new Error(`Expected ${platformPackage.packageName} ${openCodeExpectedVersion}.`);
|
|
547
|
+
}
|
|
548
|
+
const packageDirectory = plugins.fs.realpathSync.native(plugins.path.dirname(platformPackageJsonPath));
|
|
549
|
+
const executablePath = plugins.fs.realpathSync.native(plugins.path.join(packageDirectory, 'bin', platformPackage.binaryName));
|
|
550
|
+
const relativeExecutablePath = plugins.path.relative(packageDirectory, executablePath);
|
|
551
|
+
if (relativeExecutablePath.startsWith(`..${plugins.path.sep}`) ||
|
|
552
|
+
relativeExecutablePath === '..' ||
|
|
553
|
+
plugins.path.isAbsolute(relativeExecutablePath)) {
|
|
554
|
+
throw new Error('The package-owned OpenCode executable escaped its package directory.');
|
|
555
|
+
}
|
|
556
|
+
const executableStat = plugins.fs.statSync(executablePath);
|
|
557
|
+
if (!executableStat.isFile() ||
|
|
558
|
+
(process.platform !== 'win32' && (executableStat.mode & 0o111) === 0)) {
|
|
559
|
+
throw new Error('The package-owned OpenCode executable is not a file.');
|
|
560
|
+
}
|
|
561
|
+
return executablePath;
|
|
562
|
+
}
|
|
563
|
+
async performStart(signal) {
|
|
564
|
+
this.state = 'starting';
|
|
565
|
+
this.healthy = false;
|
|
566
|
+
this.version = undefined;
|
|
567
|
+
this.startedAt = undefined;
|
|
568
|
+
try {
|
|
569
|
+
signal?.throwIfAborted();
|
|
570
|
+
const child = this.spawnFactory(this.executablePath, [
|
|
571
|
+
'serve',
|
|
572
|
+
'--hostname',
|
|
573
|
+
'127.0.0.1',
|
|
574
|
+
'--port',
|
|
575
|
+
String(this.port),
|
|
576
|
+
'--mdns=false',
|
|
577
|
+
'--print-logs',
|
|
578
|
+
], {
|
|
579
|
+
cwd: this.directory,
|
|
580
|
+
detached: this.processGroupController !== undefined,
|
|
581
|
+
shell: false,
|
|
582
|
+
windowsHide: true,
|
|
583
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
584
|
+
env: createOpenCodeEnvironment(this.password),
|
|
585
|
+
});
|
|
586
|
+
this.child = child;
|
|
587
|
+
this.childLifecycle = this.observeChild(child);
|
|
588
|
+
if (!child.pid) {
|
|
589
|
+
throw new Error('OpenCode did not provide a process ID after spawn.');
|
|
590
|
+
}
|
|
591
|
+
if (this.processGroupController) {
|
|
592
|
+
this.ownedProcessGroupId = child.pid;
|
|
593
|
+
}
|
|
594
|
+
const deadline = Date.now() + this.startupTimeoutMs;
|
|
595
|
+
let lastHealthError;
|
|
596
|
+
while (Date.now() < deadline) {
|
|
597
|
+
const lifecycle = this.childLifecycle;
|
|
598
|
+
if (!lifecycle) {
|
|
599
|
+
throw new Error('OpenCode child lifecycle tracking was lost.');
|
|
600
|
+
}
|
|
601
|
+
const ownershipOutcome = await waitForStartupOperation(Promise.resolve().then(() => this.listenerOwnershipVerifier(child.pid, this.port)), lifecycle, signal);
|
|
602
|
+
if (ownershipOutcome.type === 'abort') {
|
|
603
|
+
throw startupAbortError(ownershipOutcome.reason);
|
|
604
|
+
}
|
|
605
|
+
if (ownershipOutcome.type === 'lifecycle') {
|
|
606
|
+
throw this.lifecycleError(ownershipOutcome.outcome, 'OpenCode exited during startup.');
|
|
607
|
+
}
|
|
608
|
+
if (ownershipOutcome.type === 'operationError') {
|
|
609
|
+
throw new OpenCodeListenerOwnershipError('OpenCode listener ownership could not be verified.', { cause: ownershipOutcome.error });
|
|
610
|
+
}
|
|
611
|
+
const listenerOwned = ownershipOutcome.value;
|
|
612
|
+
if (!listenerOwned) {
|
|
613
|
+
lastHealthError = new OpenCodeListenerOwnershipError('The loopback listener is not owned by the spawned OpenCode process.');
|
|
614
|
+
const remainingMs = deadline - Date.now();
|
|
615
|
+
if (remainingMs <= 0) {
|
|
616
|
+
break;
|
|
617
|
+
}
|
|
618
|
+
const pauseOutcome = await waitForPauseOrLifecycle(Math.min(this.healthPollIntervalMs, remainingMs), lifecycle, signal);
|
|
619
|
+
if (pauseOutcome) {
|
|
620
|
+
if (pauseOutcome.type === 'abort') {
|
|
621
|
+
throw startupAbortError(pauseOutcome.reason);
|
|
622
|
+
}
|
|
623
|
+
throw this.lifecycleError(pauseOutcome, 'OpenCode exited during startup.');
|
|
624
|
+
}
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
const healthOutcome = await waitForStartupOperation(this.fetchHealth(signal), lifecycle, signal);
|
|
628
|
+
if (healthOutcome.type === 'abort') {
|
|
629
|
+
throw startupAbortError(healthOutcome.reason);
|
|
630
|
+
}
|
|
631
|
+
if (healthOutcome.type === 'lifecycle') {
|
|
632
|
+
throw this.lifecycleError(healthOutcome.outcome, 'OpenCode exited during startup.');
|
|
633
|
+
}
|
|
634
|
+
if (healthOutcome.type === 'value') {
|
|
635
|
+
const secondOwnershipOutcome = await waitForStartupOperation(Promise.resolve().then(() => this.listenerOwnershipVerifier(child.pid, this.port)), lifecycle, signal);
|
|
636
|
+
if (secondOwnershipOutcome.type === 'abort') {
|
|
637
|
+
throw startupAbortError(secondOwnershipOutcome.reason);
|
|
638
|
+
}
|
|
639
|
+
if (secondOwnershipOutcome.type === 'lifecycle') {
|
|
640
|
+
throw this.lifecycleError(secondOwnershipOutcome.outcome, 'OpenCode exited during startup.');
|
|
641
|
+
}
|
|
642
|
+
if (secondOwnershipOutcome.type === 'operationError') {
|
|
643
|
+
throw new OpenCodeListenerOwnershipError('OpenCode listener ownership could not be reverified.', { cause: secondOwnershipOutcome.error });
|
|
644
|
+
}
|
|
645
|
+
const stillOwned = secondOwnershipOutcome.value;
|
|
646
|
+
if (!stillOwned) {
|
|
647
|
+
throw new OpenCodeListenerOwnershipError('OpenCode lost ownership of its loopback listener during startup.');
|
|
648
|
+
}
|
|
649
|
+
if (child.exitCode !== null || child.signalCode !== null || this.child !== child) {
|
|
650
|
+
throw new Error('OpenCode exited while completing its health check.');
|
|
651
|
+
}
|
|
652
|
+
this.healthy = true;
|
|
653
|
+
this.version = healthOutcome.value.version;
|
|
654
|
+
this.startedAt = Date.now();
|
|
655
|
+
this.state = 'ready';
|
|
656
|
+
return this.getStatus();
|
|
657
|
+
}
|
|
658
|
+
lastHealthError = healthOutcome.error;
|
|
659
|
+
if (lastHealthError instanceof OpenCodeVersionMismatchError) {
|
|
660
|
+
throw lastHealthError;
|
|
661
|
+
}
|
|
662
|
+
const remainingMs = deadline - Date.now();
|
|
663
|
+
if (remainingMs <= 0) {
|
|
664
|
+
break;
|
|
665
|
+
}
|
|
666
|
+
const pauseOutcome = await waitForPauseOrLifecycle(Math.min(this.healthPollIntervalMs, remainingMs), lifecycle, signal);
|
|
667
|
+
if (pauseOutcome) {
|
|
668
|
+
if (pauseOutcome.type === 'abort') {
|
|
669
|
+
throw startupAbortError(pauseOutcome.reason);
|
|
670
|
+
}
|
|
671
|
+
throw this.lifecycleError(pauseOutcome, 'OpenCode exited during startup.');
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
throw new Error(`OpenCode did not become healthy within ${this.startupTimeoutMs}ms.`, {
|
|
675
|
+
cause: lastHealthError,
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
catch (error) {
|
|
679
|
+
let cleanupError;
|
|
680
|
+
try {
|
|
681
|
+
await this.stop();
|
|
682
|
+
}
|
|
683
|
+
catch (caughtCleanupError) {
|
|
684
|
+
cleanupError = caughtCleanupError;
|
|
685
|
+
}
|
|
686
|
+
this.state = 'failed';
|
|
687
|
+
this.healthy = false;
|
|
688
|
+
this.startedAt = undefined;
|
|
689
|
+
if (cleanupError) {
|
|
690
|
+
throw new AggregateError([error, cleanupError], 'OpenCode startup failed and its child process could not be cleaned up.');
|
|
691
|
+
}
|
|
692
|
+
throw new Error('OpenCode startup failed.', { cause: error });
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* best-effort reaping of group members that survived their leader's exit.
|
|
697
|
+
* Runs at exit time because that is when the pgid is still provably ours:
|
|
698
|
+
* living members keep it reserved, and an already-empty group answers ESRCH.
|
|
699
|
+
*/
|
|
700
|
+
async reapOrphanedGroup(processGroupIdArg) {
|
|
701
|
+
if (!this.processGroupController)
|
|
702
|
+
return;
|
|
703
|
+
if (!(await this.processGroupController.isAlive(processGroupIdArg)))
|
|
704
|
+
return;
|
|
705
|
+
await this.processGroupController.signal(processGroupIdArg, 'SIGTERM');
|
|
706
|
+
let exited = await waitForProcessGroupExit(this.processGroupController, processGroupIdArg, this.stopTimeoutMs);
|
|
707
|
+
if (!exited) {
|
|
708
|
+
await this.processGroupController.signal(processGroupIdArg, 'SIGKILL');
|
|
709
|
+
exited = await waitForProcessGroupExit(this.processGroupController, processGroupIdArg, this.finalStopTimeoutMs);
|
|
710
|
+
}
|
|
711
|
+
if (!exited)
|
|
712
|
+
throw new Error('An owned OpenCode process-group member survived SIGKILL.');
|
|
713
|
+
}
|
|
714
|
+
notifyChildExitCleanup() {
|
|
715
|
+
if (!this.childExitCleanupPending)
|
|
716
|
+
return;
|
|
717
|
+
this.childExitCleanupPending = false;
|
|
718
|
+
try {
|
|
719
|
+
this.onChildExit?.();
|
|
720
|
+
}
|
|
721
|
+
catch {
|
|
722
|
+
// Child lifecycle cleanup must not prevent lifecycle settlement.
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
async drainOrphanedProcessGroup() {
|
|
726
|
+
const orphanReapTask = this.orphanReapTask;
|
|
727
|
+
if (orphanReapTask)
|
|
728
|
+
await orphanReapTask;
|
|
729
|
+
const processGroupId = this.orphanedProcessGroupId;
|
|
730
|
+
if (processGroupId !== undefined) {
|
|
731
|
+
await this.reapOrphanedGroup(processGroupId);
|
|
732
|
+
if (this.orphanedProcessGroupId === processGroupId) {
|
|
733
|
+
this.orphanedProcessGroupId = undefined;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
this.notifyChildExitCleanup();
|
|
737
|
+
}
|
|
738
|
+
observeChild(child) {
|
|
739
|
+
child.stdout?.on('data', (chunk) => {
|
|
740
|
+
this.consumeLogChunk('stdout', chunk, this.stdoutAccumulator);
|
|
741
|
+
});
|
|
742
|
+
child.stderr?.on('data', (chunk) => {
|
|
743
|
+
this.consumeLogChunk('stderr', chunk, this.stderrAccumulator);
|
|
744
|
+
});
|
|
745
|
+
return new Promise((resolve) => {
|
|
746
|
+
let settled = false;
|
|
747
|
+
const finish = (outcome) => {
|
|
748
|
+
if (settled) {
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
settled = true;
|
|
752
|
+
this.flushLogAccumulator('stdout', this.stdoutAccumulator);
|
|
753
|
+
this.flushLogAccumulator('stderr', this.stderrAccumulator);
|
|
754
|
+
this.healthy = false;
|
|
755
|
+
// once the group leader is gone the kernel may recycle its pid, so a
|
|
756
|
+
// LATER stop() must never signal this group — but surviving group
|
|
757
|
+
// descendants must still be reaped NOW, while living members keep the
|
|
758
|
+
// pgid reserved and therefore safely targetable
|
|
759
|
+
const orphanedGroupId = this.ownedProcessGroupId;
|
|
760
|
+
this.ownedProcessGroupId = undefined;
|
|
761
|
+
this.childExitCleanupPending = true;
|
|
762
|
+
if (orphanedGroupId !== undefined && this.processGroupController) {
|
|
763
|
+
this.orphanedProcessGroupId = orphanedGroupId;
|
|
764
|
+
let reap;
|
|
765
|
+
reap = this.reapOrphanedGroup(orphanedGroupId).then(() => {
|
|
766
|
+
if (this.orphanedProcessGroupId === orphanedGroupId) {
|
|
767
|
+
this.orphanedProcessGroupId = undefined;
|
|
768
|
+
}
|
|
769
|
+
this.notifyChildExitCleanup();
|
|
770
|
+
}).finally(() => {
|
|
771
|
+
if (this.orphanReapTask === reap)
|
|
772
|
+
this.orphanReapTask = undefined;
|
|
773
|
+
});
|
|
774
|
+
this.orphanReapTask = reap;
|
|
775
|
+
void reap.catch(() => undefined);
|
|
776
|
+
}
|
|
777
|
+
else {
|
|
778
|
+
this.notifyChildExitCleanup();
|
|
779
|
+
}
|
|
780
|
+
if (this.state === 'stopping') {
|
|
781
|
+
this.state = 'stopped';
|
|
782
|
+
}
|
|
783
|
+
else if (this.state === 'starting' || this.state === 'ready') {
|
|
784
|
+
this.state = 'failed';
|
|
785
|
+
}
|
|
786
|
+
resolve(outcome);
|
|
787
|
+
};
|
|
788
|
+
child.once('exit', (code, signal) => {
|
|
789
|
+
finish({ type: 'exit', code, signal });
|
|
790
|
+
});
|
|
791
|
+
child.once('error', (error) => {
|
|
792
|
+
this.addLogEntry('stderr', `OpenCode process error: ${error.message}`, false);
|
|
793
|
+
if (!child.pid) {
|
|
794
|
+
finish({ type: 'error', error });
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
async fetchHealth(callerSignal) {
|
|
800
|
+
callerSignal?.throwIfAborted();
|
|
801
|
+
const requestAbortController = new AbortController();
|
|
802
|
+
const abortFromCaller = () => {
|
|
803
|
+
requestAbortController.abort(callerSignal?.reason);
|
|
804
|
+
};
|
|
805
|
+
callerSignal?.addEventListener('abort', abortFromCaller, { once: true });
|
|
806
|
+
if (callerSignal?.aborted) {
|
|
807
|
+
abortFromCaller();
|
|
808
|
+
}
|
|
809
|
+
const timeout = setTimeout(() => {
|
|
810
|
+
requestAbortController.abort(new Error(`OpenCode health request exceeded ${this.healthRequestTimeoutMs}ms.`));
|
|
811
|
+
}, this.healthRequestTimeoutMs);
|
|
812
|
+
timeout.unref();
|
|
813
|
+
const authorization = Buffer.from(`${openCodeUsername}:${this.password}`, 'utf8').toString('base64');
|
|
814
|
+
try {
|
|
815
|
+
const response = await this.fetchImplementation(`${this.baseUrl}/global/health`, {
|
|
816
|
+
method: 'GET',
|
|
817
|
+
headers: {
|
|
818
|
+
Accept: 'application/json',
|
|
819
|
+
Authorization: `Basic ${authorization}`,
|
|
820
|
+
},
|
|
821
|
+
redirect: 'error',
|
|
822
|
+
signal: requestAbortController.signal,
|
|
823
|
+
});
|
|
824
|
+
if (!response.ok) {
|
|
825
|
+
throw new Error(`OpenCode health check returned HTTP ${response.status}.`);
|
|
826
|
+
}
|
|
827
|
+
const body = await readBoundedResponseText(response);
|
|
828
|
+
let parsed;
|
|
829
|
+
try {
|
|
830
|
+
parsed = JSON.parse(body);
|
|
831
|
+
}
|
|
832
|
+
catch (error) {
|
|
833
|
+
throw new Error('OpenCode health check returned invalid JSON.', { cause: error });
|
|
834
|
+
}
|
|
835
|
+
if (typeof parsed !== 'object' ||
|
|
836
|
+
parsed === null ||
|
|
837
|
+
!('healthy' in parsed) ||
|
|
838
|
+
!('version' in parsed) ||
|
|
839
|
+
parsed.healthy !== true ||
|
|
840
|
+
typeof parsed.version !== 'string') {
|
|
841
|
+
throw new Error('OpenCode health check returned an invalid payload.');
|
|
842
|
+
}
|
|
843
|
+
if (parsed.version !== openCodeExpectedVersion) {
|
|
844
|
+
throw new OpenCodeVersionMismatchError(`OpenCode reported version ${parsed.version}; expected ${openCodeExpectedVersion}.`);
|
|
845
|
+
}
|
|
846
|
+
return {
|
|
847
|
+
healthy: true,
|
|
848
|
+
version: openCodeExpectedVersion,
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
finally {
|
|
852
|
+
clearTimeout(timeout);
|
|
853
|
+
callerSignal?.removeEventListener('abort', abortFromCaller);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
async performStop(child, lifecycle) {
|
|
857
|
+
this.state = 'stopping';
|
|
858
|
+
this.healthy = false;
|
|
859
|
+
// a leader that already exited cleared ownedProcessGroupId in observeChild
|
|
860
|
+
// and handed surviving members to reapOrphanedGroup, so this branch only
|
|
861
|
+
// ever signals a group whose leader is still ours
|
|
862
|
+
const ownedProcessGroupId = this.ownedProcessGroupId;
|
|
863
|
+
if (this.processGroupController && ownedProcessGroupId !== undefined) {
|
|
864
|
+
let exited = !(await this.processGroupController.isAlive(ownedProcessGroupId));
|
|
865
|
+
if (!exited) {
|
|
866
|
+
await this.processGroupController.signal(ownedProcessGroupId, 'SIGTERM');
|
|
867
|
+
exited = await waitForProcessGroupExit(this.processGroupController, ownedProcessGroupId, this.stopTimeoutMs);
|
|
868
|
+
}
|
|
869
|
+
if (!exited) {
|
|
870
|
+
await this.processGroupController.signal(ownedProcessGroupId, 'SIGKILL');
|
|
871
|
+
exited = await waitForProcessGroupExit(this.processGroupController, ownedProcessGroupId, this.finalStopTimeoutMs);
|
|
872
|
+
}
|
|
873
|
+
if (!exited) {
|
|
874
|
+
this.state = 'failed';
|
|
875
|
+
throw new Error('The owned OpenCode process group did not exit after SIGKILL.');
|
|
876
|
+
}
|
|
877
|
+
const lifecycleSettled = await waitBounded(lifecycle, this.finalStopTimeoutMs);
|
|
878
|
+
if (!lifecycleSettled) {
|
|
879
|
+
this.state = 'failed';
|
|
880
|
+
throw new Error('OpenCode process-group exit was not confirmed by the child lifecycle.');
|
|
881
|
+
}
|
|
882
|
+
this.ownedProcessGroupId = undefined;
|
|
883
|
+
}
|
|
884
|
+
else {
|
|
885
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
886
|
+
try {
|
|
887
|
+
child.kill('SIGTERM');
|
|
888
|
+
}
|
|
889
|
+
catch (error) {
|
|
890
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
891
|
+
throw new Error('Failed to send SIGTERM to OpenCode.', { cause: error });
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
let exited = await waitBounded(lifecycle, this.stopTimeoutMs);
|
|
896
|
+
if (!exited && child.exitCode === null && child.signalCode === null) {
|
|
897
|
+
try {
|
|
898
|
+
child.kill('SIGKILL');
|
|
899
|
+
}
|
|
900
|
+
catch (error) {
|
|
901
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
902
|
+
throw new Error('Failed to send SIGKILL to OpenCode.', { cause: error });
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
exited = await waitBounded(lifecycle, this.finalStopTimeoutMs);
|
|
906
|
+
}
|
|
907
|
+
if (!exited && child.exitCode === null && child.signalCode === null) {
|
|
908
|
+
this.state = 'failed';
|
|
909
|
+
throw new Error('OpenCode did not exit after SIGKILL.');
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
// a leader that exited on its own may have left a reap task running; stop()
|
|
913
|
+
// must not return while owned group members are still being signalled
|
|
914
|
+
await this.drainOrphanedProcessGroup();
|
|
915
|
+
if (this.child === child) {
|
|
916
|
+
this.child = undefined;
|
|
917
|
+
}
|
|
918
|
+
if (this.childLifecycle === lifecycle) {
|
|
919
|
+
this.childLifecycle = undefined;
|
|
920
|
+
}
|
|
921
|
+
this.state = 'stopped';
|
|
922
|
+
this.healthy = false;
|
|
923
|
+
this.startedAt = undefined;
|
|
924
|
+
}
|
|
925
|
+
lifecycleError(outcome, message) {
|
|
926
|
+
if (outcome.type === 'error') {
|
|
927
|
+
return new Error(message, { cause: outcome.error });
|
|
928
|
+
}
|
|
929
|
+
const detail = outcome.signal
|
|
930
|
+
? `signal ${outcome.signal}`
|
|
931
|
+
: `exit code ${String(outcome.code)}`;
|
|
932
|
+
return new Error(`${message} (${detail})`);
|
|
933
|
+
}
|
|
934
|
+
consumeLogChunk(stream, chunk, accumulator) {
|
|
935
|
+
let bytes;
|
|
936
|
+
if (typeof chunk === 'string') {
|
|
937
|
+
bytes = Buffer.from(chunk, 'utf8');
|
|
938
|
+
}
|
|
939
|
+
else if (chunk instanceof Uint8Array) {
|
|
940
|
+
bytes = chunk;
|
|
941
|
+
}
|
|
942
|
+
else {
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
let text = accumulator.decoder.decode(bytes, { stream: true });
|
|
946
|
+
while (text.length > 0) {
|
|
947
|
+
if (accumulator.droppingUntilNewline) {
|
|
948
|
+
const newlineIndex = text.indexOf('\n');
|
|
949
|
+
if (newlineIndex === -1) {
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
accumulator.droppingUntilNewline = false;
|
|
953
|
+
text = text.slice(newlineIndex + 1);
|
|
954
|
+
continue;
|
|
955
|
+
}
|
|
956
|
+
const newlineIndex = text.indexOf('\n');
|
|
957
|
+
if (newlineIndex !== -1) {
|
|
958
|
+
const completeLine = `${accumulator.partial}${text.slice(0, newlineIndex)}`.replace(/\r$/u, '');
|
|
959
|
+
accumulator.partial = '';
|
|
960
|
+
const bounded = truncateLogLine(completeLine, this.logLineByteLimit);
|
|
961
|
+
this.addLogEntry(stream, bounded.line, bounded.truncated);
|
|
962
|
+
text = text.slice(newlineIndex + 1);
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
const combined = `${accumulator.partial}${text}`;
|
|
966
|
+
if (Buffer.byteLength(combined, 'utf8') > this.logLineByteLimit) {
|
|
967
|
+
const bounded = truncateLogLine(combined, this.logLineByteLimit);
|
|
968
|
+
this.addLogEntry(stream, bounded.line, true);
|
|
969
|
+
accumulator.partial = '';
|
|
970
|
+
accumulator.droppingUntilNewline = true;
|
|
971
|
+
}
|
|
972
|
+
else {
|
|
973
|
+
accumulator.partial = combined;
|
|
974
|
+
}
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
flushLogAccumulator(stream, accumulator) {
|
|
979
|
+
const finalText = accumulator.decoder.decode();
|
|
980
|
+
if (finalText) {
|
|
981
|
+
this.consumeLogChunk(stream, finalText, accumulator);
|
|
982
|
+
}
|
|
983
|
+
if (accumulator.partial && !accumulator.droppingUntilNewline) {
|
|
984
|
+
const bounded = truncateLogLine(accumulator.partial, this.logLineByteLimit);
|
|
985
|
+
this.addLogEntry(stream, bounded.line, bounded.truncated);
|
|
986
|
+
}
|
|
987
|
+
accumulator.partial = '';
|
|
988
|
+
accumulator.droppingUntilNewline = false;
|
|
989
|
+
}
|
|
990
|
+
addLogEntry(stream, line, truncated) {
|
|
991
|
+
this.logs.push({
|
|
992
|
+
timestamp: Date.now(),
|
|
993
|
+
stream,
|
|
994
|
+
line,
|
|
995
|
+
truncated,
|
|
996
|
+
});
|
|
997
|
+
const excessEntries = this.logs.length - this.logEntryLimit;
|
|
998
|
+
if (excessEntries > 0) {
|
|
999
|
+
this.logs.splice(0, excessEntries);
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5vcGVuY29kZXN1cGVydmlzb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9jbGFzc2VzLm9wZW5jb2Rlc3VwZXJ2aXNvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGdCQUFnQixHQU9qQixNQUFNLDBCQUEwQixDQUFDO0FBQ2xDLE9BQU8sRUFBRSxpQ0FBaUMsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRXRGLE1BQU0sdUJBQXVCLEdBQUcsTUFBTSxDQUFDO0FBQ3ZDLE1BQU0sNkJBQTZCLEdBQUcsS0FBSyxDQUFDO0FBQzVDLE1BQU0sMkJBQTJCLEdBQUcsR0FBRyxDQUFDO0FBQ3hDLE1BQU0sb0JBQW9CLEdBQUcsS0FBSyxDQUFDO0FBQ25DLE1BQU0seUJBQXlCLEdBQUcsS0FBSyxDQUFDO0FBQ3hDLE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxDQUFDO0FBQ2pDLE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztBQUN6QyxNQUFNLHNCQUFzQixHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDekMsTUFBTSxtQkFBbUIsR0FBRyxlQUFlLENBQUM7QUFDNUMsTUFBTSxhQUFhLEdBQUcsZ0JBQWdCLENBQUM7QUFxQnZDLE1BQU0sNEJBQTZCLFNBQVEsS0FBSztDQUFHO0FBQ25ELE1BQU0sOEJBQStCLFNBQVEsS0FBSztDQUFHO0FBRXJELE1BQU0scUJBQXFCLEdBQUcsQ0FDNUIsS0FBeUIsRUFDekIsUUFBZ0IsRUFDaEIsSUFBWSxFQUNaLE9BQWUsRUFDZixPQUFlLEVBQ1AsRUFBRTtJQUNWLE1BQU0sUUFBUSxHQUFHLEtBQUssSUFBSSxRQUFRLENBQUM7SUFDbkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLElBQUksUUFBUSxHQUFHLE9BQU8sSUFBSSxR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
|