@memohai/cloud-runtime 0.1.0 → 2026.9.12-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/bridge.proto +29 -1
- package/dist/cli.mjs +1260 -300
- package/package.json +9 -8
- package/scripts/build.mjs +4 -3
- package/src/bootstrap.ts +4 -4
- package/src/cloud.ts +22 -6
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// @memohai/cloud-runtime
|
|
2
|
+
// @memohai/cloud-runtime 2026.9.12-1 — bundles @memohai/runtime 0.19.0 (memoh cc440cea)
|
|
3
3
|
import { createRequire as __memohCreateRequire } from 'node:module'
|
|
4
4
|
const require = __memohCreateRequire(import.meta.url)
|
|
5
5
|
var __create = Object.create;
|
|
@@ -1382,14 +1382,14 @@ var require_receiver = __commonJS({
|
|
|
1382
1382
|
* @return {(Error|RangeError)} The error
|
|
1383
1383
|
* @private
|
|
1384
1384
|
*/
|
|
1385
|
-
createError(ErrorCtor, message, prefix, statusCode,
|
|
1385
|
+
createError(ErrorCtor, message, prefix, statusCode, errorCode2) {
|
|
1386
1386
|
this._loop = false;
|
|
1387
1387
|
this._errored = true;
|
|
1388
1388
|
const err = new ErrorCtor(
|
|
1389
1389
|
prefix ? `Invalid WebSocket frame: ${message}` : message
|
|
1390
1390
|
);
|
|
1391
1391
|
Error.captureStackTrace(err, this.createError);
|
|
1392
|
-
err.code =
|
|
1392
|
+
err.code = errorCode2;
|
|
1393
1393
|
err[kStatusCode] = statusCode;
|
|
1394
1394
|
return err;
|
|
1395
1395
|
}
|
|
@@ -2129,7 +2129,7 @@ var require_extension = __commonJS({
|
|
|
2129
2129
|
if (dest[name] === void 0) dest[name] = [elem];
|
|
2130
2130
|
else dest[name].push(elem);
|
|
2131
2131
|
}
|
|
2132
|
-
function
|
|
2132
|
+
function parse2(header) {
|
|
2133
2133
|
const offers = /* @__PURE__ */ Object.create(null);
|
|
2134
2134
|
let params = /* @__PURE__ */ Object.create(null);
|
|
2135
2135
|
let mustUnescape = false;
|
|
@@ -2269,7 +2269,7 @@ var require_extension = __commonJS({
|
|
|
2269
2269
|
}).join(", ");
|
|
2270
2270
|
}).join(", ");
|
|
2271
2271
|
}
|
|
2272
|
-
module.exports = { format, parse };
|
|
2272
|
+
module.exports = { format, parse: parse2 };
|
|
2273
2273
|
}
|
|
2274
2274
|
});
|
|
2275
2275
|
|
|
@@ -2303,7 +2303,7 @@ var require_websocket = __commonJS({
|
|
|
2303
2303
|
var {
|
|
2304
2304
|
EventTarget: { addEventListener, removeEventListener }
|
|
2305
2305
|
} = require_event_target();
|
|
2306
|
-
var { format, parse } = require_extension();
|
|
2306
|
+
var { format, parse: parse2 } = require_extension();
|
|
2307
2307
|
var { toBuffer } = require_buffer_util();
|
|
2308
2308
|
var kAborted = /* @__PURE__ */ Symbol("kAborted");
|
|
2309
2309
|
var protocolVersions = [8, 13];
|
|
@@ -2980,7 +2980,7 @@ var require_websocket = __commonJS({
|
|
|
2980
2980
|
}
|
|
2981
2981
|
let extensions;
|
|
2982
2982
|
try {
|
|
2983
|
-
extensions =
|
|
2983
|
+
extensions = parse2(secWebSocketExtensions);
|
|
2984
2984
|
} catch (err) {
|
|
2985
2985
|
const message = "Invalid Sec-WebSocket-Extensions header";
|
|
2986
2986
|
abortHandshake(websocket, socket, message);
|
|
@@ -3231,7 +3231,7 @@ var require_stream = __commonJS({
|
|
|
3231
3231
|
};
|
|
3232
3232
|
duplex._final = function(callback) {
|
|
3233
3233
|
if (ws.readyState === ws.CONNECTING) {
|
|
3234
|
-
ws.once("open", function
|
|
3234
|
+
ws.once("open", function open3() {
|
|
3235
3235
|
duplex._final(callback);
|
|
3236
3236
|
});
|
|
3237
3237
|
return;
|
|
@@ -3252,7 +3252,7 @@ var require_stream = __commonJS({
|
|
|
3252
3252
|
};
|
|
3253
3253
|
duplex._write = function(chunk, encoding, callback) {
|
|
3254
3254
|
if (ws.readyState === ws.CONNECTING) {
|
|
3255
|
-
ws.once("open", function
|
|
3255
|
+
ws.once("open", function open3() {
|
|
3256
3256
|
duplex._write(chunk, encoding, callback);
|
|
3257
3257
|
});
|
|
3258
3258
|
return;
|
|
@@ -3272,7 +3272,7 @@ var require_subprotocol = __commonJS({
|
|
|
3272
3272
|
"../memoh/node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/subprotocol.js"(exports, module) {
|
|
3273
3273
|
"use strict";
|
|
3274
3274
|
var { tokenChars } = require_validation();
|
|
3275
|
-
function
|
|
3275
|
+
function parse2(header) {
|
|
3276
3276
|
const protocols = /* @__PURE__ */ new Set();
|
|
3277
3277
|
let start = -1;
|
|
3278
3278
|
let end = -1;
|
|
@@ -3308,7 +3308,7 @@ var require_subprotocol = __commonJS({
|
|
|
3308
3308
|
protocols.add(protocol);
|
|
3309
3309
|
return protocols;
|
|
3310
3310
|
}
|
|
3311
|
-
module.exports = { parse };
|
|
3311
|
+
module.exports = { parse: parse2 };
|
|
3312
3312
|
}
|
|
3313
3313
|
});
|
|
3314
3314
|
|
|
@@ -4255,7 +4255,7 @@ var require_call_credentials = __commonJS({
|
|
|
4255
4255
|
if (isCurrentOauth2Client(googleCredentials)) {
|
|
4256
4256
|
getHeaders = googleCredentials.getRequestHeaders(options.service_url);
|
|
4257
4257
|
} else {
|
|
4258
|
-
getHeaders = new Promise((
|
|
4258
|
+
getHeaders = new Promise((resolve5, reject) => {
|
|
4259
4259
|
googleCredentials.getRequestMetadata(options.service_url, (err, headers) => {
|
|
4260
4260
|
if (err) {
|
|
4261
4261
|
reject(err);
|
|
@@ -4265,7 +4265,7 @@ var require_call_credentials = __commonJS({
|
|
|
4265
4265
|
reject(new Error("Headers not set by metadata plugin"));
|
|
4266
4266
|
return;
|
|
4267
4267
|
}
|
|
4268
|
-
|
|
4268
|
+
resolve5(headers);
|
|
4269
4269
|
});
|
|
4270
4270
|
});
|
|
4271
4271
|
}
|
|
@@ -4318,10 +4318,10 @@ var require_call_credentials = __commonJS({
|
|
|
4318
4318
|
this.metadataGenerator = metadataGenerator;
|
|
4319
4319
|
}
|
|
4320
4320
|
generateMetadata(options) {
|
|
4321
|
-
return new Promise((
|
|
4321
|
+
return new Promise((resolve5, reject) => {
|
|
4322
4322
|
this.metadataGenerator(options, (err, metadata) => {
|
|
4323
4323
|
if (metadata !== void 0) {
|
|
4324
|
-
|
|
4324
|
+
resolve5(metadata);
|
|
4325
4325
|
} else {
|
|
4326
4326
|
reject(err);
|
|
4327
4327
|
}
|
|
@@ -4637,7 +4637,7 @@ var require_channel_credentials = __commonJS({
|
|
|
4637
4637
|
};
|
|
4638
4638
|
function getConnectionOptions(secureContext, verifyOptions, channelTarget, options) {
|
|
4639
4639
|
var _a, _b;
|
|
4640
|
-
const
|
|
4640
|
+
const connectionOptions2 = {
|
|
4641
4641
|
secureContext
|
|
4642
4642
|
};
|
|
4643
4643
|
let realTarget = channelTarget;
|
|
@@ -4650,44 +4650,44 @@ var require_channel_credentials = __commonJS({
|
|
|
4650
4650
|
const targetPath = (0, resolver_1.getDefaultAuthority)(realTarget);
|
|
4651
4651
|
const hostPort = (0, uri_parser_1.splitHostPort)(targetPath);
|
|
4652
4652
|
const remoteHost = (_a = hostPort === null || hostPort === void 0 ? void 0 : hostPort.host) !== null && _a !== void 0 ? _a : targetPath;
|
|
4653
|
-
|
|
4653
|
+
connectionOptions2.host = remoteHost;
|
|
4654
4654
|
if (verifyOptions.checkServerIdentity) {
|
|
4655
|
-
|
|
4655
|
+
connectionOptions2.checkServerIdentity = verifyOptions.checkServerIdentity;
|
|
4656
4656
|
}
|
|
4657
4657
|
if (verifyOptions.rejectUnauthorized !== void 0) {
|
|
4658
|
-
|
|
4658
|
+
connectionOptions2.rejectUnauthorized = verifyOptions.rejectUnauthorized;
|
|
4659
4659
|
}
|
|
4660
|
-
|
|
4660
|
+
connectionOptions2.ALPNProtocols = ["h2"];
|
|
4661
4661
|
if (options["grpc.ssl_target_name_override"]) {
|
|
4662
4662
|
const sslTargetNameOverride = options["grpc.ssl_target_name_override"];
|
|
4663
|
-
const originalCheckServerIdentity = (_b =
|
|
4664
|
-
|
|
4663
|
+
const originalCheckServerIdentity = (_b = connectionOptions2.checkServerIdentity) !== null && _b !== void 0 ? _b : tls_1.checkServerIdentity;
|
|
4664
|
+
connectionOptions2.checkServerIdentity = (host, cert) => {
|
|
4665
4665
|
return originalCheckServerIdentity(sslTargetNameOverride, cert);
|
|
4666
4666
|
};
|
|
4667
|
-
|
|
4667
|
+
connectionOptions2.servername = sslTargetNameOverride;
|
|
4668
4668
|
} else {
|
|
4669
|
-
|
|
4669
|
+
connectionOptions2.servername = remoteHost;
|
|
4670
4670
|
}
|
|
4671
4671
|
if (options["grpc-node.tls_enable_trace"]) {
|
|
4672
|
-
|
|
4672
|
+
connectionOptions2.enableTrace = true;
|
|
4673
4673
|
}
|
|
4674
|
-
return
|
|
4674
|
+
return connectionOptions2;
|
|
4675
4675
|
}
|
|
4676
4676
|
var SecureConnectorImpl = class {
|
|
4677
|
-
constructor(
|
|
4678
|
-
this.connectionOptions =
|
|
4677
|
+
constructor(connectionOptions2, callCredentials) {
|
|
4678
|
+
this.connectionOptions = connectionOptions2;
|
|
4679
4679
|
this.callCredentials = callCredentials;
|
|
4680
4680
|
}
|
|
4681
4681
|
connect(socket) {
|
|
4682
4682
|
const tlsConnectOptions = Object.assign({ socket }, this.connectionOptions);
|
|
4683
|
-
return new Promise((
|
|
4683
|
+
return new Promise((resolve5, reject) => {
|
|
4684
4684
|
const tlsSocket = (0, tls_1.connect)(tlsConnectOptions, () => {
|
|
4685
4685
|
var _a;
|
|
4686
4686
|
if (((_a = this.connectionOptions.rejectUnauthorized) !== null && _a !== void 0 ? _a : true) && !tlsSocket.authorized) {
|
|
4687
4687
|
reject(tlsSocket.authorizationError);
|
|
4688
4688
|
return;
|
|
4689
4689
|
}
|
|
4690
|
-
|
|
4690
|
+
resolve5({
|
|
4691
4691
|
socket: tlsSocket,
|
|
4692
4692
|
secure: true
|
|
4693
4693
|
});
|
|
@@ -4726,8 +4726,8 @@ var require_channel_credentials = __commonJS({
|
|
|
4726
4726
|
}
|
|
4727
4727
|
}
|
|
4728
4728
|
_createSecureConnector(channelTarget, options, callCredentials) {
|
|
4729
|
-
const
|
|
4730
|
-
return new SecureConnectorImpl(
|
|
4729
|
+
const connectionOptions2 = getConnectionOptions(this.secureContext, this.verifyOptions, channelTarget, options);
|
|
4730
|
+
return new SecureConnectorImpl(connectionOptions2, callCredentials !== null && callCredentials !== void 0 ? callCredentials : call_credentials_1.CallCredentials.createEmpty());
|
|
4731
4731
|
}
|
|
4732
4732
|
};
|
|
4733
4733
|
var CertificateProviderChannelCredentialsImpl = class _CertificateProviderChannelCredentialsImpl extends ChannelCredentials {
|
|
@@ -4806,8 +4806,8 @@ var require_channel_credentials = __commonJS({
|
|
|
4806
4806
|
if (this.hasReceivedUpdates()) {
|
|
4807
4807
|
return Promise.resolve(this.getLatestSecureContext());
|
|
4808
4808
|
} else {
|
|
4809
|
-
return new Promise((
|
|
4810
|
-
this.secureContextWatchers.push(
|
|
4809
|
+
return new Promise((resolve5) => {
|
|
4810
|
+
this.secureContextWatchers.push(resolve5);
|
|
4811
4811
|
});
|
|
4812
4812
|
}
|
|
4813
4813
|
}
|
|
@@ -4840,7 +4840,7 @@ var require_channel_credentials = __commonJS({
|
|
|
4840
4840
|
this.callCredentials = callCredentials;
|
|
4841
4841
|
}
|
|
4842
4842
|
connect(socket) {
|
|
4843
|
-
return new Promise((
|
|
4843
|
+
return new Promise((resolve5, reject) => {
|
|
4844
4844
|
const secureContext = this.parent.getLatestSecureContext();
|
|
4845
4845
|
if (!secureContext) {
|
|
4846
4846
|
reject(new Error("Failed to load credentials"));
|
|
@@ -4865,7 +4865,7 @@ var require_channel_credentials = __commonJS({
|
|
|
4865
4865
|
reject(tlsSocket.authorizationError);
|
|
4866
4866
|
return;
|
|
4867
4867
|
}
|
|
4868
|
-
|
|
4868
|
+
resolve5({
|
|
4869
4869
|
socket: tlsSocket,
|
|
4870
4870
|
secure: true
|
|
4871
4871
|
});
|
|
@@ -5736,7 +5736,7 @@ var require_resolving_load_balancer = __commonJS({
|
|
|
5736
5736
|
"SERVICE",
|
|
5737
5737
|
"EMPTY"
|
|
5738
5738
|
];
|
|
5739
|
-
function hasMatchingName(
|
|
5739
|
+
function hasMatchingName(service2, method, methodConfig, matchLevel) {
|
|
5740
5740
|
for (const name of methodConfig.name) {
|
|
5741
5741
|
switch (matchLevel) {
|
|
5742
5742
|
case "EMPTY":
|
|
@@ -5745,21 +5745,21 @@ var require_resolving_load_balancer = __commonJS({
|
|
|
5745
5745
|
}
|
|
5746
5746
|
break;
|
|
5747
5747
|
case "SERVICE":
|
|
5748
|
-
if (name.service ===
|
|
5748
|
+
if (name.service === service2 && !name.method) {
|
|
5749
5749
|
return true;
|
|
5750
5750
|
}
|
|
5751
5751
|
break;
|
|
5752
5752
|
case "SERVICE_AND_METHOD":
|
|
5753
|
-
if (name.service ===
|
|
5753
|
+
if (name.service === service2 && name.method === method) {
|
|
5754
5754
|
return true;
|
|
5755
5755
|
}
|
|
5756
5756
|
}
|
|
5757
5757
|
}
|
|
5758
5758
|
return false;
|
|
5759
5759
|
}
|
|
5760
|
-
function findMatchingConfig(
|
|
5760
|
+
function findMatchingConfig(service2, method, methodConfigs, matchLevel) {
|
|
5761
5761
|
for (const config of methodConfigs) {
|
|
5762
|
-
if (hasMatchingName(
|
|
5762
|
+
if (hasMatchingName(service2, method, config, matchLevel)) {
|
|
5763
5763
|
return config;
|
|
5764
5764
|
}
|
|
5765
5765
|
}
|
|
@@ -5770,11 +5770,11 @@ var require_resolving_load_balancer = __commonJS({
|
|
|
5770
5770
|
invoke(methodName, metadata) {
|
|
5771
5771
|
var _a, _b;
|
|
5772
5772
|
const splitName = methodName.split("/").filter((x) => x.length > 0);
|
|
5773
|
-
const
|
|
5773
|
+
const service2 = (_a = splitName[0]) !== null && _a !== void 0 ? _a : "";
|
|
5774
5774
|
const method = (_b = splitName[1]) !== null && _b !== void 0 ? _b : "";
|
|
5775
5775
|
if (serviceConfig && serviceConfig.methodConfig) {
|
|
5776
5776
|
for (const matchLevel of NAME_MATCH_LEVEL_ORDER) {
|
|
5777
|
-
const matchingConfig = findMatchingConfig(
|
|
5777
|
+
const matchingConfig = findMatchingConfig(service2, method, serviceConfig.methodConfig, matchLevel);
|
|
5778
5778
|
if (matchingConfig) {
|
|
5779
5779
|
return {
|
|
5780
5780
|
methodConfig: matchingConfig,
|
|
@@ -8032,7 +8032,7 @@ var require_make_client = __commonJS({
|
|
|
8032
8032
|
const result = {};
|
|
8033
8033
|
for (const serviceFqn in packageDef) {
|
|
8034
8034
|
if (Object.prototype.hasOwnProperty.call(packageDef, serviceFqn)) {
|
|
8035
|
-
const
|
|
8035
|
+
const service2 = packageDef[serviceFqn];
|
|
8036
8036
|
const nameComponents = serviceFqn.split(".");
|
|
8037
8037
|
if (nameComponents.some((comp) => isPrototypePolluted(comp))) {
|
|
8038
8038
|
continue;
|
|
@@ -8045,10 +8045,10 @@ var require_make_client = __commonJS({
|
|
|
8045
8045
|
}
|
|
8046
8046
|
current = current[packageName];
|
|
8047
8047
|
}
|
|
8048
|
-
if (isProtobufTypeDefinition(
|
|
8049
|
-
current[serviceName] =
|
|
8048
|
+
if (isProtobufTypeDefinition(service2)) {
|
|
8049
|
+
current[serviceName] = service2;
|
|
8050
8050
|
} else {
|
|
8051
|
-
current[serviceName] = makeClientConstructor(
|
|
8051
|
+
current[serviceName] = makeClientConstructor(service2, serviceName, {});
|
|
8052
8052
|
}
|
|
8053
8053
|
}
|
|
8054
8054
|
}
|
|
@@ -8441,7 +8441,7 @@ var require_aspromise = __commonJS({
|
|
|
8441
8441
|
var params = new Array(arguments.length - 1), offset = 0, index = 2, pending = true;
|
|
8442
8442
|
while (index < arguments.length)
|
|
8443
8443
|
params[offset++] = arguments[index++];
|
|
8444
|
-
return new Promise(function executor(
|
|
8444
|
+
return new Promise(function executor(resolve5, reject) {
|
|
8445
8445
|
params[offset] = function callback(err) {
|
|
8446
8446
|
if (pending) {
|
|
8447
8447
|
pending = false;
|
|
@@ -8451,7 +8451,7 @@ var require_aspromise = __commonJS({
|
|
|
8451
8451
|
var params2 = new Array(arguments.length - 1), offset2 = 0;
|
|
8452
8452
|
while (offset2 < params2.length)
|
|
8453
8453
|
params2[offset2++] = arguments[offset2];
|
|
8454
|
-
|
|
8454
|
+
resolve5.apply(null, params2);
|
|
8455
8455
|
}
|
|
8456
8456
|
}
|
|
8457
8457
|
};
|
|
@@ -10956,13 +10956,13 @@ var require_path = __commonJS({
|
|
|
10956
10956
|
"../memoh/node_modules/.pnpm/@protobufjs+path@1.1.2/node_modules/@protobufjs/path/index.js"(exports) {
|
|
10957
10957
|
"use strict";
|
|
10958
10958
|
var path = exports;
|
|
10959
|
-
var
|
|
10959
|
+
var isAbsolute4 = (
|
|
10960
10960
|
/**
|
|
10961
10961
|
* Tests if the specified path is absolute.
|
|
10962
10962
|
* @param {string} path Path to test
|
|
10963
10963
|
* @returns {boolean} `true` if path is absolute
|
|
10964
10964
|
*/
|
|
10965
|
-
path.isAbsolute = function
|
|
10965
|
+
path.isAbsolute = function isAbsolute5(path2) {
|
|
10966
10966
|
return /^(?:\/|\w+:)/.test(path2);
|
|
10967
10967
|
}
|
|
10968
10968
|
);
|
|
@@ -10974,7 +10974,7 @@ var require_path = __commonJS({
|
|
|
10974
10974
|
*/
|
|
10975
10975
|
path.normalize = function normalize2(path2) {
|
|
10976
10976
|
path2 = path2.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
|
|
10977
|
-
var parts = path2.split("/"), absolute =
|
|
10977
|
+
var parts = path2.split("/"), absolute = isAbsolute4(path2), prefix = "";
|
|
10978
10978
|
if (absolute)
|
|
10979
10979
|
prefix = parts.shift() + "/";
|
|
10980
10980
|
for (var i = 0; i < parts.length; ) {
|
|
@@ -10993,10 +10993,10 @@ var require_path = __commonJS({
|
|
|
10993
10993
|
return prefix + parts.join("/");
|
|
10994
10994
|
}
|
|
10995
10995
|
);
|
|
10996
|
-
path.resolve = function
|
|
10996
|
+
path.resolve = function resolve5(originPath, includePath, alreadyNormalized) {
|
|
10997
10997
|
if (!alreadyNormalized)
|
|
10998
10998
|
includePath = normalize(includePath);
|
|
10999
|
-
if (
|
|
10999
|
+
if (isAbsolute4(includePath))
|
|
11000
11000
|
return includePath;
|
|
11001
11001
|
if (!alreadyNormalized)
|
|
11002
11002
|
originPath = normalize(originPath);
|
|
@@ -11350,7 +11350,7 @@ var require_mapfield = __commonJS({
|
|
|
11350
11350
|
keepComments ? this.comment : void 0
|
|
11351
11351
|
]);
|
|
11352
11352
|
};
|
|
11353
|
-
MapField.prototype.resolve = function
|
|
11353
|
+
MapField.prototype.resolve = function resolve5() {
|
|
11354
11354
|
if (this.resolved)
|
|
11355
11355
|
return this;
|
|
11356
11356
|
if (types.mapKey[this.keyType] === void 0)
|
|
@@ -11427,7 +11427,7 @@ var require_method = __commonJS({
|
|
|
11427
11427
|
this.parsedOptions
|
|
11428
11428
|
]);
|
|
11429
11429
|
};
|
|
11430
|
-
Method.prototype.resolve = function
|
|
11430
|
+
Method.prototype.resolve = function resolve5() {
|
|
11431
11431
|
if (this.resolved)
|
|
11432
11432
|
return this;
|
|
11433
11433
|
this.resolvedRequestType = this.parent.lookupType(this.requestType);
|
|
@@ -11454,17 +11454,17 @@ var require_service2 = __commonJS({
|
|
|
11454
11454
|
}
|
|
11455
11455
|
Service.fromJSON = function fromJSON(name, json, depth) {
|
|
11456
11456
|
depth = util.checkDepth(depth);
|
|
11457
|
-
var
|
|
11457
|
+
var service2 = new Service(name, json.options);
|
|
11458
11458
|
if (json.methods)
|
|
11459
11459
|
for (var names = Object.keys(json.methods), i = 0; i < names.length; ++i)
|
|
11460
|
-
|
|
11460
|
+
service2.add(Method.fromJSON(names[i], json.methods[names[i]]));
|
|
11461
11461
|
if (json.nested)
|
|
11462
|
-
|
|
11462
|
+
service2.addJSON(json.nested, depth);
|
|
11463
11463
|
if (json.edition)
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
return
|
|
11464
|
+
service2._edition = json.edition;
|
|
11465
|
+
service2.comment = json.comment;
|
|
11466
|
+
service2._defaultEdition = "proto3";
|
|
11467
|
+
return service2;
|
|
11468
11468
|
};
|
|
11469
11469
|
Service.prototype.toJSON = function toJSON(toJSONOptions) {
|
|
11470
11470
|
var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
|
|
@@ -11488,9 +11488,9 @@ var require_service2 = __commonJS({
|
|
|
11488
11488
|
return this._methodsArray || (this._methodsArray = util.toArray(this.methods));
|
|
11489
11489
|
}
|
|
11490
11490
|
});
|
|
11491
|
-
function clearCache(
|
|
11492
|
-
|
|
11493
|
-
return
|
|
11491
|
+
function clearCache(service2) {
|
|
11492
|
+
service2._methodsArray = null;
|
|
11493
|
+
return service2;
|
|
11494
11494
|
}
|
|
11495
11495
|
Service.prototype.get = function get(name) {
|
|
11496
11496
|
return Object.prototype.hasOwnProperty.call(this.methods, name) ? this.methods[name] : Namespace.prototype.get.call(this, name);
|
|
@@ -12382,7 +12382,7 @@ var require_root = __commonJS({
|
|
|
12382
12382
|
var OneOf = require_oneof();
|
|
12383
12383
|
var util = require_util();
|
|
12384
12384
|
var Type;
|
|
12385
|
-
var
|
|
12385
|
+
var parse2;
|
|
12386
12386
|
var common;
|
|
12387
12387
|
function Root(options) {
|
|
12388
12388
|
Namespace.call(this, "", options);
|
|
@@ -12446,8 +12446,8 @@ var require_root = __commonJS({
|
|
|
12446
12446
|
if (!util.isString(source))
|
|
12447
12447
|
self2.setOptions(source.options).addJSON(source.nested);
|
|
12448
12448
|
else {
|
|
12449
|
-
|
|
12450
|
-
var parsed =
|
|
12449
|
+
parse2.filename = filename2;
|
|
12450
|
+
var parsed = parse2(source, self2, options), resolved2, i2 = 0;
|
|
12451
12451
|
if (parsed.imports) {
|
|
12452
12452
|
for (; i2 < parsed.imports.length; ++i2)
|
|
12453
12453
|
if (resolved2 = getBundledFileName(parsed.imports[i2]) || self2.resolvePath(filename2, parsed.imports[i2]))
|
|
@@ -12620,7 +12620,7 @@ var require_root = __commonJS({
|
|
|
12620
12620
|
};
|
|
12621
12621
|
Root._configure = function(Type_, parse_, common_) {
|
|
12622
12622
|
Type = Type_;
|
|
12623
|
-
|
|
12623
|
+
parse2 = parse_;
|
|
12624
12624
|
common = common_;
|
|
12625
12625
|
};
|
|
12626
12626
|
}
|
|
@@ -13040,7 +13040,7 @@ var require_field = __commonJS({
|
|
|
13040
13040
|
keepComments ? this.comment : void 0
|
|
13041
13041
|
]);
|
|
13042
13042
|
};
|
|
13043
|
-
Field.prototype.resolve = function
|
|
13043
|
+
Field.prototype.resolve = function resolve5() {
|
|
13044
13044
|
if (this.resolved)
|
|
13045
13045
|
return this;
|
|
13046
13046
|
if ((this.typeDefault = types.defaults[this.type]) === void 0) {
|
|
@@ -13313,7 +13313,7 @@ var require_object = __commonJS({
|
|
|
13313
13313
|
this.parent = null;
|
|
13314
13314
|
this.resolved = false;
|
|
13315
13315
|
};
|
|
13316
|
-
ReflectionObject.prototype.resolve = function
|
|
13316
|
+
ReflectionObject.prototype.resolve = function resolve5() {
|
|
13317
13317
|
if (this.resolved)
|
|
13318
13318
|
return this;
|
|
13319
13319
|
if (this.root instanceof Root)
|
|
@@ -13893,9 +13893,9 @@ var require_tokenize = __commonJS({
|
|
|
13893
13893
|
var require_parse = __commonJS({
|
|
13894
13894
|
"../memoh/node_modules/.pnpm/protobufjs@7.6.5/node_modules/protobufjs/src/parse.js"(exports, module) {
|
|
13895
13895
|
"use strict";
|
|
13896
|
-
module.exports =
|
|
13897
|
-
|
|
13898
|
-
|
|
13896
|
+
module.exports = parse2;
|
|
13897
|
+
parse2.filename = null;
|
|
13898
|
+
parse2.defaults = { keepCase: false };
|
|
13899
13899
|
var tokenize = require_tokenize();
|
|
13900
13900
|
var Root = require_root();
|
|
13901
13901
|
var Type = require_type();
|
|
@@ -13917,13 +13917,13 @@ var require_parse = __commonJS({
|
|
|
13917
13917
|
var numberRe = util.patterns.numberRe;
|
|
13918
13918
|
var nameRe = /^[a-zA-Z_][a-zA-Z_0-9]*$/;
|
|
13919
13919
|
var typeRefRe = util.patterns.typeRefRe;
|
|
13920
|
-
function
|
|
13920
|
+
function parse2(source, root, options) {
|
|
13921
13921
|
if (!(root instanceof Root)) {
|
|
13922
13922
|
options = root;
|
|
13923
13923
|
root = new Root();
|
|
13924
13924
|
}
|
|
13925
13925
|
if (!options)
|
|
13926
|
-
options =
|
|
13926
|
+
options = parse2.defaults;
|
|
13927
13927
|
var preferTrailingComment = options.preferTrailingComment || false;
|
|
13928
13928
|
var tn = tokenize(source, options.alternateCommentMode || false), next = tn.next, push = tn.push, peek = tn.peek, skip = tn.skip, cmnt = tn.cmnt;
|
|
13929
13929
|
var head = true, pkg, imports, weakImports, edition = "proto2";
|
|
@@ -13943,9 +13943,9 @@ var require_parse = __commonJS({
|
|
|
13943
13943
|
});
|
|
13944
13944
|
}
|
|
13945
13945
|
function illegal(token2, name, insideTryCatch) {
|
|
13946
|
-
var filename =
|
|
13946
|
+
var filename = parse2.filename;
|
|
13947
13947
|
if (!insideTryCatch)
|
|
13948
|
-
|
|
13948
|
+
parse2.filename = null;
|
|
13949
13949
|
return Error("illegal " + (name || "token") + " '" + token2 + "' (" + (filename ? filename + ", " : "") + "line " + tn.line + ")");
|
|
13950
13950
|
}
|
|
13951
13951
|
function readString() {
|
|
@@ -14145,7 +14145,7 @@ var require_parse = __commonJS({
|
|
|
14145
14145
|
if (typeof obj.comment !== "string") {
|
|
14146
14146
|
obj.comment = cmnt();
|
|
14147
14147
|
}
|
|
14148
|
-
obj.filename =
|
|
14148
|
+
obj.filename = parse2.filename;
|
|
14149
14149
|
}
|
|
14150
14150
|
if (skip("{", true)) {
|
|
14151
14151
|
var token2;
|
|
@@ -14271,7 +14271,7 @@ var require_parse = __commonJS({
|
|
|
14271
14271
|
var type = new Type(name);
|
|
14272
14272
|
type.group = true;
|
|
14273
14273
|
var field = new Field(fieldName, id, name, rule);
|
|
14274
|
-
field.filename =
|
|
14274
|
+
field.filename = parse2.filename;
|
|
14275
14275
|
ifBlock(type, function parseGroup_block(token2) {
|
|
14276
14276
|
switch (token2) {
|
|
14277
14277
|
case "option":
|
|
@@ -14510,19 +14510,19 @@ var require_parse = __commonJS({
|
|
|
14510
14510
|
throw Error("max depth exceeded");
|
|
14511
14511
|
if (!nameRe.test(token2 = next()))
|
|
14512
14512
|
throw illegal(token2, "service name");
|
|
14513
|
-
var
|
|
14514
|
-
ifBlock(
|
|
14515
|
-
if (parseCommon(
|
|
14513
|
+
var service2 = new Service(token2);
|
|
14514
|
+
ifBlock(service2, function parseService_block(token3) {
|
|
14515
|
+
if (parseCommon(service2, token3, depth)) {
|
|
14516
14516
|
return;
|
|
14517
14517
|
}
|
|
14518
14518
|
if (token3 === "rpc")
|
|
14519
|
-
parseMethod(
|
|
14519
|
+
parseMethod(service2, token3);
|
|
14520
14520
|
else
|
|
14521
14521
|
throw illegal(token3);
|
|
14522
14522
|
});
|
|
14523
|
-
parent.add(
|
|
14523
|
+
parent.add(service2);
|
|
14524
14524
|
if (parent === ptr) {
|
|
14525
|
-
topLevelObjects.push(
|
|
14525
|
+
topLevelObjects.push(service2);
|
|
14526
14526
|
}
|
|
14527
14527
|
}
|
|
14528
14528
|
function parseMethod(parent, token2) {
|
|
@@ -14619,7 +14619,7 @@ var require_parse = __commonJS({
|
|
|
14619
14619
|
}
|
|
14620
14620
|
}
|
|
14621
14621
|
resolveFileFeatures();
|
|
14622
|
-
|
|
14622
|
+
parse2.filename = null;
|
|
14623
14623
|
return {
|
|
14624
14624
|
"package": pkg,
|
|
14625
14625
|
"imports": imports,
|
|
@@ -16706,13 +16706,13 @@ var require_descriptor2 = __commonJS({
|
|
|
16706
16706
|
Service.fromDescriptor = function fromDescriptor(descriptor, edition, nested) {
|
|
16707
16707
|
if (typeof descriptor.length === "number")
|
|
16708
16708
|
descriptor = exports.ServiceDescriptorProto.decode(descriptor);
|
|
16709
|
-
var
|
|
16709
|
+
var service2 = new Service(descriptor.name && descriptor.name.length ? descriptor.name : "Service" + unnamedServiceIndex++, fromDescriptorOptions(descriptor.options, exports.ServiceOptions));
|
|
16710
16710
|
if (!nested)
|
|
16711
|
-
|
|
16711
|
+
service2._edition = edition;
|
|
16712
16712
|
if (descriptor.method)
|
|
16713
16713
|
for (var i = 0; i < descriptor.method.length; ++i)
|
|
16714
|
-
|
|
16715
|
-
return
|
|
16714
|
+
service2.add(Method.fromDescriptor(descriptor.method[i]));
|
|
16715
|
+
return service2;
|
|
16716
16716
|
};
|
|
16717
16717
|
Service.prototype.toDescriptor = function toDescriptor() {
|
|
16718
16718
|
var methods = [];
|
|
@@ -17496,9 +17496,9 @@ var require_src2 = __commonJS({
|
|
|
17496
17496
|
options: mapMethodOptions(method.parsedOptions)
|
|
17497
17497
|
};
|
|
17498
17498
|
}
|
|
17499
|
-
function createServiceDefinition(
|
|
17499
|
+
function createServiceDefinition(service2, name, options, fileDescriptors) {
|
|
17500
17500
|
const def = {};
|
|
17501
|
-
for (const method of
|
|
17501
|
+
for (const method of service2.methodsArray) {
|
|
17502
17502
|
def[method.name] = createMethodDefinition(method, name, options, fileDescriptors);
|
|
17503
17503
|
}
|
|
17504
17504
|
return def;
|
|
@@ -18284,18 +18284,18 @@ var require_compression_filter = __commonJS({
|
|
|
18284
18284
|
this.maxRecvMessageLength = maxRecvMessageLength;
|
|
18285
18285
|
}
|
|
18286
18286
|
compressMessage(message) {
|
|
18287
|
-
return new Promise((
|
|
18287
|
+
return new Promise((resolve5, reject) => {
|
|
18288
18288
|
zlib.deflate(message, (err, output) => {
|
|
18289
18289
|
if (err) {
|
|
18290
18290
|
reject(err);
|
|
18291
18291
|
} else {
|
|
18292
|
-
|
|
18292
|
+
resolve5(output);
|
|
18293
18293
|
}
|
|
18294
18294
|
});
|
|
18295
18295
|
});
|
|
18296
18296
|
}
|
|
18297
18297
|
decompressMessage(message) {
|
|
18298
|
-
return new Promise((
|
|
18298
|
+
return new Promise((resolve5, reject) => {
|
|
18299
18299
|
let totalLength = 0;
|
|
18300
18300
|
const messageParts = [];
|
|
18301
18301
|
const decompresser = zlib.createInflate();
|
|
@@ -18317,7 +18317,7 @@ var require_compression_filter = __commonJS({
|
|
|
18317
18317
|
}
|
|
18318
18318
|
});
|
|
18319
18319
|
decompresser.on("end", () => {
|
|
18320
|
-
|
|
18320
|
+
resolve5(Buffer.concat(messageParts));
|
|
18321
18321
|
});
|
|
18322
18322
|
decompresser.write(message);
|
|
18323
18323
|
decompresser.end();
|
|
@@ -18330,18 +18330,18 @@ var require_compression_filter = __commonJS({
|
|
|
18330
18330
|
this.maxRecvMessageLength = maxRecvMessageLength;
|
|
18331
18331
|
}
|
|
18332
18332
|
compressMessage(message) {
|
|
18333
|
-
return new Promise((
|
|
18333
|
+
return new Promise((resolve5, reject) => {
|
|
18334
18334
|
zlib.gzip(message, (err, output) => {
|
|
18335
18335
|
if (err) {
|
|
18336
18336
|
reject(err);
|
|
18337
18337
|
} else {
|
|
18338
|
-
|
|
18338
|
+
resolve5(output);
|
|
18339
18339
|
}
|
|
18340
18340
|
});
|
|
18341
18341
|
});
|
|
18342
18342
|
}
|
|
18343
18343
|
decompressMessage(message) {
|
|
18344
|
-
return new Promise((
|
|
18344
|
+
return new Promise((resolve5, reject) => {
|
|
18345
18345
|
let totalLength = 0;
|
|
18346
18346
|
const messageParts = [];
|
|
18347
18347
|
const decompresser = zlib.createGunzip();
|
|
@@ -18363,7 +18363,7 @@ var require_compression_filter = __commonJS({
|
|
|
18363
18363
|
}
|
|
18364
18364
|
});
|
|
18365
18365
|
decompresser.on("end", () => {
|
|
18366
|
-
|
|
18366
|
+
resolve5(Buffer.concat(messageParts));
|
|
18367
18367
|
});
|
|
18368
18368
|
decompresser.write(message);
|
|
18369
18369
|
decompresser.end();
|
|
@@ -19698,7 +19698,7 @@ var require_http_proxy = __commonJS({
|
|
|
19698
19698
|
options.headers = headers;
|
|
19699
19699
|
const proxyAddressString = (0, subchannel_address_1.subchannelAddressToString)(address);
|
|
19700
19700
|
trace("Using proxy " + proxyAddressString + " to connect to " + options.path);
|
|
19701
|
-
return new Promise((
|
|
19701
|
+
return new Promise((resolve5, reject) => {
|
|
19702
19702
|
const request = http.request(options);
|
|
19703
19703
|
request.once("connect", (res, socket, head) => {
|
|
19704
19704
|
request.removeAllListeners();
|
|
@@ -19709,7 +19709,7 @@ var require_http_proxy = __commonJS({
|
|
|
19709
19709
|
socket.unshift(head);
|
|
19710
19710
|
}
|
|
19711
19711
|
trace("Successfully established a plaintext connection to " + options.path + " through proxy " + proxyAddressString);
|
|
19712
|
-
|
|
19712
|
+
resolve5(socket);
|
|
19713
19713
|
} else {
|
|
19714
19714
|
(0, logging_1.log)(constants_1.LogVerbosity.ERROR, "Failed to connect to " + options.path + " through proxy " + proxyAddressString + " with status " + res.statusCode);
|
|
19715
19715
|
reject();
|
|
@@ -20289,12 +20289,12 @@ var require_transport = __commonJS({
|
|
|
20289
20289
|
this.trace("session closed");
|
|
20290
20290
|
this.handleDisconnect();
|
|
20291
20291
|
});
|
|
20292
|
-
session.once("goaway", (
|
|
20292
|
+
session.once("goaway", (errorCode2, lastStreamID, opaqueData) => {
|
|
20293
20293
|
let tooManyPings = false;
|
|
20294
|
-
if (
|
|
20294
|
+
if (errorCode2 === http2.constants.NGHTTP2_ENHANCE_YOUR_CALM && opaqueData && opaqueData.equals(tooManyPingsData)) {
|
|
20295
20295
|
tooManyPings = true;
|
|
20296
20296
|
}
|
|
20297
|
-
this.trace("connection closed by GOAWAY with code " +
|
|
20297
|
+
this.trace("connection closed by GOAWAY with code " + errorCode2 + " and data " + (opaqueData === null || opaqueData === void 0 ? void 0 : opaqueData.toString()));
|
|
20298
20298
|
this.reportDisconnectToOwner(tooManyPings);
|
|
20299
20299
|
});
|
|
20300
20300
|
session.once("error", (error) => {
|
|
@@ -20609,7 +20609,7 @@ var require_transport = __commonJS({
|
|
|
20609
20609
|
if (secureConnectResult.socket.closed) {
|
|
20610
20610
|
return Promise.reject("Connection closed before starting HTTP/2 handshake");
|
|
20611
20611
|
}
|
|
20612
|
-
return new Promise((
|
|
20612
|
+
return new Promise((resolve5, reject) => {
|
|
20613
20613
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
20614
20614
|
let remoteName = null;
|
|
20615
20615
|
let realTarget = this.channelTarget;
|
|
@@ -20678,7 +20678,7 @@ var require_transport = __commonJS({
|
|
|
20678
20678
|
session.removeAllListeners();
|
|
20679
20679
|
secureConnectResult.socket.removeListener("close", closeHandler);
|
|
20680
20680
|
secureConnectResult.socket.removeListener("error", errorHandler);
|
|
20681
|
-
|
|
20681
|
+
resolve5(new Http2Transport(session, address, options, remoteName));
|
|
20682
20682
|
this.session = null;
|
|
20683
20683
|
});
|
|
20684
20684
|
session.once("close", closeHandler);
|
|
@@ -20692,7 +20692,7 @@ var require_transport = __commonJS({
|
|
|
20692
20692
|
if (proxiedSocket) {
|
|
20693
20693
|
return proxiedSocket;
|
|
20694
20694
|
} else {
|
|
20695
|
-
return new Promise((
|
|
20695
|
+
return new Promise((resolve5, reject) => {
|
|
20696
20696
|
const closeCallback = () => {
|
|
20697
20697
|
reject(new Error("Socket closed"));
|
|
20698
20698
|
};
|
|
@@ -20702,7 +20702,7 @@ var require_transport = __commonJS({
|
|
|
20702
20702
|
const socket = net.connect(address, () => {
|
|
20703
20703
|
socket.removeListener("close", closeCallback);
|
|
20704
20704
|
socket.removeListener("error", errorCallback);
|
|
20705
|
-
|
|
20705
|
+
resolve5(socket);
|
|
20706
20706
|
});
|
|
20707
20707
|
socket.once("close", closeCallback);
|
|
20708
20708
|
socket.once("error", errorCallback);
|
|
@@ -24004,7 +24004,7 @@ var require_server_interceptors = __commonJS({
|
|
|
24004
24004
|
} else {
|
|
24005
24005
|
decompresser = zlib.createGunzip();
|
|
24006
24006
|
}
|
|
24007
|
-
return new Promise((
|
|
24007
|
+
return new Promise((resolve5, reject) => {
|
|
24008
24008
|
let totalLength = 0;
|
|
24009
24009
|
const messageParts = [];
|
|
24010
24010
|
decompresser.on("error", (error) => {
|
|
@@ -24025,7 +24025,7 @@ var require_server_interceptors = __commonJS({
|
|
|
24025
24025
|
}
|
|
24026
24026
|
});
|
|
24027
24027
|
decompresser.on("end", () => {
|
|
24028
|
-
|
|
24028
|
+
resolve5(Buffer.concat(messageParts));
|
|
24029
24029
|
});
|
|
24030
24030
|
decompresser.write(messageContents);
|
|
24031
24031
|
decompresser.end();
|
|
@@ -24485,16 +24485,16 @@ var require_server = __commonJS({
|
|
|
24485
24485
|
addProtoService() {
|
|
24486
24486
|
throw new Error("Not implemented. Use addService() instead");
|
|
24487
24487
|
}
|
|
24488
|
-
addService(
|
|
24489
|
-
if (
|
|
24488
|
+
addService(service2, implementation) {
|
|
24489
|
+
if (service2 === null || typeof service2 !== "object" || implementation === null || typeof implementation !== "object") {
|
|
24490
24490
|
throw new Error("addService() requires two objects as arguments");
|
|
24491
24491
|
}
|
|
24492
|
-
const serviceKeys = Object.keys(
|
|
24492
|
+
const serviceKeys = Object.keys(service2);
|
|
24493
24493
|
if (serviceKeys.length === 0) {
|
|
24494
24494
|
throw new Error("Cannot add an empty service to a server");
|
|
24495
24495
|
}
|
|
24496
24496
|
serviceKeys.forEach((name) => {
|
|
24497
|
-
const attrs =
|
|
24497
|
+
const attrs = service2[name];
|
|
24498
24498
|
let methodType;
|
|
24499
24499
|
if (attrs.requestStream) {
|
|
24500
24500
|
if (attrs.responseStream) {
|
|
@@ -24525,13 +24525,13 @@ var require_server = __commonJS({
|
|
|
24525
24525
|
}
|
|
24526
24526
|
});
|
|
24527
24527
|
}
|
|
24528
|
-
removeService(
|
|
24529
|
-
if (
|
|
24528
|
+
removeService(service2) {
|
|
24529
|
+
if (service2 === null || typeof service2 !== "object") {
|
|
24530
24530
|
throw new Error("removeService() requires object as argument");
|
|
24531
24531
|
}
|
|
24532
|
-
const serviceKeys = Object.keys(
|
|
24532
|
+
const serviceKeys = Object.keys(service2);
|
|
24533
24533
|
serviceKeys.forEach((name) => {
|
|
24534
|
-
const attrs =
|
|
24534
|
+
const attrs = service2[name];
|
|
24535
24535
|
this.unregister(attrs.path);
|
|
24536
24536
|
});
|
|
24537
24537
|
}
|
|
@@ -24615,10 +24615,10 @@ var require_server = __commonJS({
|
|
|
24615
24615
|
bindOneAddress(address, boundPortObject) {
|
|
24616
24616
|
this.trace("Attempting to bind " + (0, subchannel_address_1.subchannelAddressToString)(address));
|
|
24617
24617
|
const http2Server = this.createHttp2Server(boundPortObject.credentials);
|
|
24618
|
-
return new Promise((
|
|
24618
|
+
return new Promise((resolve5, reject) => {
|
|
24619
24619
|
const onError = (err) => {
|
|
24620
24620
|
this.trace("Failed to bind " + (0, subchannel_address_1.subchannelAddressToString)(address) + " with error " + err.message);
|
|
24621
|
-
|
|
24621
|
+
resolve5({
|
|
24622
24622
|
port: "port" in address ? address.port : 1,
|
|
24623
24623
|
error: err.message
|
|
24624
24624
|
});
|
|
@@ -24646,7 +24646,7 @@ var require_server = __commonJS({
|
|
|
24646
24646
|
});
|
|
24647
24647
|
boundPortObject.listeningServers.add(http2Server);
|
|
24648
24648
|
this.trace("Successfully bound " + (0, subchannel_address_1.subchannelAddressToString)(boundSubchannelAddress));
|
|
24649
|
-
|
|
24649
|
+
resolve5({
|
|
24650
24650
|
port: "port" in boundSubchannelAddress ? boundSubchannelAddress.port : 1
|
|
24651
24651
|
});
|
|
24652
24652
|
http2Server.removeListener("error", onError);
|
|
@@ -24699,7 +24699,7 @@ var require_server = __commonJS({
|
|
|
24699
24699
|
}
|
|
24700
24700
|
}
|
|
24701
24701
|
resolvePort(port) {
|
|
24702
|
-
return new Promise((
|
|
24702
|
+
return new Promise((resolve5, reject) => {
|
|
24703
24703
|
let seenResolution = false;
|
|
24704
24704
|
const resolverListener = (endpointList, attributes, serviceConfig, resolutionNote) => {
|
|
24705
24705
|
if (seenResolution) {
|
|
@@ -24715,7 +24715,7 @@ var require_server = __commonJS({
|
|
|
24715
24715
|
reject(new Error(`No addresses resolved for port ${port}`));
|
|
24716
24716
|
return true;
|
|
24717
24717
|
}
|
|
24718
|
-
|
|
24718
|
+
resolve5(addressList);
|
|
24719
24719
|
return true;
|
|
24720
24720
|
};
|
|
24721
24721
|
const resolver = (0, resolver_1.createResolver)(port, resolverListener, this.options);
|
|
@@ -27894,9 +27894,9 @@ var require_src3 = __commonJS({
|
|
|
27894
27894
|
});
|
|
27895
27895
|
|
|
27896
27896
|
// src/build-info.ts
|
|
27897
|
-
var cloudRuntimeVersion = true ? "
|
|
27898
|
-
var upstreamRuntimeVersion = true ? "0.
|
|
27899
|
-
var upstreamRuntimeCommit = true ? "
|
|
27897
|
+
var cloudRuntimeVersion = true ? "2026.9.12-1" : unknownStamp;
|
|
27898
|
+
var upstreamRuntimeVersion = true ? "0.19.0" : unknownStamp;
|
|
27899
|
+
var upstreamRuntimeCommit = true ? "cc440cea" : unknownStamp;
|
|
27900
27900
|
function versionReport() {
|
|
27901
27901
|
return [
|
|
27902
27902
|
`@memohai/cloud-runtime ${cloudRuntimeVersion}`,
|
|
@@ -27908,6 +27908,9 @@ function versionReport() {
|
|
|
27908
27908
|
var cloudDefaultServerUrl = "https://app.memoh.net/api/memoh";
|
|
27909
27909
|
var serverUrlEnvVar = "MEMOH_RUNTIME_SERVER";
|
|
27910
27910
|
function applyCloudDefaults(args2, env) {
|
|
27911
|
+
if (!args2.some((arg) => arg === "--key" || arg.startsWith("--key=")) && !env.MEMOH_RUNTIME_KEY?.trim()) {
|
|
27912
|
+
return;
|
|
27913
|
+
}
|
|
27911
27914
|
if (args2.some((arg) => arg === "--server" || arg.startsWith("--server="))) {
|
|
27912
27915
|
return;
|
|
27913
27916
|
}
|
|
@@ -27916,11 +27919,28 @@ function applyCloudDefaults(args2, env) {
|
|
|
27916
27919
|
}
|
|
27917
27920
|
env[serverUrlEnvVar] = cloudDefaultServerUrl;
|
|
27918
27921
|
}
|
|
27919
|
-
function cloudUsage() {
|
|
27922
|
+
function cloudUsage(args2 = []) {
|
|
27923
|
+
const command = args2[0];
|
|
27924
|
+
if (command === "service") {
|
|
27925
|
+
return "Usage: memoh-cloud-runtime service <install|start|stop|restart|status|uninstall>\nInstall registers a stopped service. Use enroll first; status supports --json.";
|
|
27926
|
+
}
|
|
27927
|
+
if (command === "enroll") {
|
|
27928
|
+
return `Usage: memoh-cloud-runtime enroll --key <key> [--server <url>] [--team-id <uuid>] [--replace]
|
|
27929
|
+
Or use enroll --config <file>. Saves enrollment for future runs.
|
|
27930
|
+
--server defaults to ${cloudDefaultServerUrl} (or $MEMOH_RUNTIME_SERVER).`;
|
|
27931
|
+
}
|
|
27932
|
+
if (command === "run") {
|
|
27933
|
+
return `Usage: memoh-cloud-runtime run [--key <key> [--server <url>] | --config <file>] [--log <file>]
|
|
27934
|
+
Reads saved enrollment when no new connection is supplied. Never saves or changes a service.
|
|
27935
|
+
--server defaults to ${cloudDefaultServerUrl} when a new key is supplied.`;
|
|
27936
|
+
}
|
|
27920
27937
|
return [
|
|
27921
|
-
"Usage: memoh-cloud-runtime
|
|
27938
|
+
"Usage: memoh-cloud-runtime <enroll|run|service|version>",
|
|
27939
|
+
" memoh-cloud-runtime --key <key> [--team-id <uuid>] [--server <url>] [--insecure-localhost]",
|
|
27922
27940
|
"",
|
|
27923
27941
|
"Connects this machine to Memoh Cloud as a remote runtime.",
|
|
27942
|
+
"Use <command> --help for enrollment and user-service commands.",
|
|
27943
|
+
"Running without connection flags reads the saved enrollment.",
|
|
27924
27944
|
"",
|
|
27925
27945
|
` --server defaults to ${cloudDefaultServerUrl}`,
|
|
27926
27946
|
" (or $MEMOH_RUNTIME_SERVER when exported)",
|
|
@@ -27932,33 +27952,227 @@ function cloudUsage() {
|
|
|
27932
27952
|
|
|
27933
27953
|
// src/bootstrap.ts
|
|
27934
27954
|
var args = process.argv.slice(2);
|
|
27935
|
-
if (args.includes("--help") || args.includes("-h")) {
|
|
27936
|
-
console.error(cloudUsage());
|
|
27955
|
+
if (args[0] === "help" || args.includes("--help") || args.includes("-h")) {
|
|
27956
|
+
console.error(cloudUsage(args));
|
|
27937
27957
|
process.exit(0);
|
|
27938
27958
|
}
|
|
27939
|
-
if (args.includes("--version") || args.includes("-v")) {
|
|
27959
|
+
if (args[0] === "version" || args.includes("--version") || args.includes("-v")) {
|
|
27940
27960
|
console.log(versionReport());
|
|
27941
27961
|
process.exit(0);
|
|
27942
27962
|
}
|
|
27943
27963
|
applyCloudDefaults(args, process.env);
|
|
27944
27964
|
|
|
27945
|
-
// ../memoh/packages/runtime/src/cli.ts
|
|
27965
|
+
// ../memoh/packages/runtime/src/cli-main.ts
|
|
27966
|
+
import { access as access5, appendFile, mkdir as mkdir4 } from "node:fs/promises";
|
|
27967
|
+
import { homedir as homedir2 } from "node:os";
|
|
27968
|
+
import { dirname as dirname6, join as join6, resolve as resolve4 } from "node:path";
|
|
27969
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
27970
|
+
import { parseArgs } from "node:util";
|
|
27971
|
+
|
|
27972
|
+
// ../memoh/packages/runtime/src/daemon/index.ts
|
|
27973
|
+
import { access as access2, stat } from "node:fs/promises";
|
|
27974
|
+
import { constants as constants2 } from "node:fs";
|
|
27975
|
+
import { isAbsolute as isAbsolute2, join as join3 } from "node:path";
|
|
27976
|
+
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
27977
|
+
|
|
27978
|
+
// ../memoh/packages/runtime/src/daemon/launchd.ts
|
|
27979
|
+
import { access, rm as rm2 } from "node:fs/promises";
|
|
27980
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
27981
|
+
|
|
27982
|
+
// ../memoh/packages/runtime/src/runtime-config.ts
|
|
27983
|
+
import { lstat as lstat2 } from "node:fs/promises";
|
|
27946
27984
|
import { homedir } from "node:os";
|
|
27985
|
+
import { dirname as dirname2, join as join2, resolve as resolve2 } from "node:path";
|
|
27947
27986
|
|
|
27948
|
-
// ../memoh/packages/runtime/src/
|
|
27949
|
-
import {
|
|
27950
|
-
import {
|
|
27987
|
+
// ../memoh/packages/runtime/src/secure-files.ts
|
|
27988
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
27989
|
+
import { promisify as promisify2 } from "node:util";
|
|
27990
|
+
import { randomUUID } from "node:crypto";
|
|
27991
|
+
import { constants } from "node:fs";
|
|
27992
|
+
import { chmod, lstat, mkdir, open, realpath, rename, rm } from "node:fs/promises";
|
|
27993
|
+
import { userInfo } from "node:os";
|
|
27994
|
+
import { dirname, join, parse, resolve } from "node:path";
|
|
27951
27995
|
|
|
27952
|
-
// ../memoh/
|
|
27953
|
-
|
|
27954
|
-
|
|
27955
|
-
|
|
27956
|
-
|
|
27957
|
-
|
|
27958
|
-
|
|
27959
|
-
|
|
27960
|
-
|
|
27961
|
-
|
|
27996
|
+
// ../memoh/packages/runtime/src/windows-file-security.ts
|
|
27997
|
+
import { execFile } from "node:child_process";
|
|
27998
|
+
import { promisify } from "node:util";
|
|
27999
|
+
|
|
28000
|
+
// ../memoh/packages/runtime/src/windows-powershell.ts
|
|
28001
|
+
function windowsPowerShellEnv(env = process.env) {
|
|
28002
|
+
return Object.fromEntries(Object.entries(env).filter(([key]) => key.toUpperCase() !== "PSMODULEPATH"));
|
|
28003
|
+
}
|
|
28004
|
+
|
|
28005
|
+
// ../memoh/packages/runtime/src/windows-file-security.ts
|
|
28006
|
+
async function powershell(script) {
|
|
28007
|
+
await promisify(execFile)("powershell.exe", ["-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(script, "utf16le").toString("base64")], { timeout: 3e4, windowsHide: true, env: windowsPowerShellEnv() });
|
|
28008
|
+
}
|
|
28009
|
+
async function checkWindowsAccess(path, privateFile) {
|
|
28010
|
+
await powershell(`
|
|
28011
|
+
$ErrorActionPreference = 'Stop'
|
|
28012
|
+
$path = '${path.replaceAll("'", "''")}'
|
|
28013
|
+
$sid = [Security.Principal.WindowsIdentity]::GetCurrent().User.Value
|
|
28014
|
+
$trusted = @($sid, 'S-1-5-18', 'S-1-5-32-544', 'S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464')
|
|
28015
|
+
$item = Get-Item -LiteralPath $path -Force
|
|
28016
|
+
$leaf = $true
|
|
28017
|
+
while ($null -ne $item) {
|
|
28018
|
+
if ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) { throw 'Runtime path cannot be a reparse point' }
|
|
28019
|
+
$acl = Get-Acl -LiteralPath $item.FullName
|
|
28020
|
+
if ($trusted -notcontains $acl.GetOwner([Security.Principal.SecurityIdentifier]).Value) { throw 'Runtime path has an untrusted owner' }
|
|
28021
|
+
foreach ($rule in $acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier])) {
|
|
28022
|
+
if ($rule.AccessControlType -ne 'Allow' -or $trusted -contains $rule.IdentityReference.Value -or ($rule.PropagationFlags -band [Security.AccessControl.PropagationFlags]::InheritOnly)) { continue }
|
|
28023
|
+
$unsafe = [Security.AccessControl.FileSystemRights]::Delete -bor [Security.AccessControl.FileSystemRights]::DeleteSubdirectoriesAndFiles -bor [Security.AccessControl.FileSystemRights]::ChangePermissions -bor [Security.AccessControl.FileSystemRights]::TakeOwnership
|
|
28024
|
+
if ($leaf) {
|
|
28025
|
+
$unsafe = $unsafe -bor [Security.AccessControl.FileSystemRights]::Write -bor [Security.AccessControl.FileSystemRights]::Delete
|
|
28026
|
+
if (${privateFile ? "$true" : "$false"}) { $unsafe = $unsafe -bor [Security.AccessControl.FileSystemRights]::ReadData }
|
|
28027
|
+
}
|
|
28028
|
+
if ($rule.FileSystemRights -band $unsafe) { throw 'Runtime path grants unsafe access to another account' }
|
|
28029
|
+
}
|
|
28030
|
+
$leaf = $false
|
|
28031
|
+
if ($item -is [IO.FileInfo]) { $item = $item.Directory } else { $item = $item.Parent }
|
|
28032
|
+
}
|
|
28033
|
+
`);
|
|
28034
|
+
}
|
|
28035
|
+
async function protectWindowsFile(path) {
|
|
28036
|
+
await protectWindowsPath(path, false);
|
|
28037
|
+
}
|
|
28038
|
+
async function protectWindowsDirectory(path) {
|
|
28039
|
+
await protectWindowsPath(path, true);
|
|
28040
|
+
}
|
|
28041
|
+
async function protectWindowsPath(path, directory) {
|
|
28042
|
+
const inheritance = directory ? "'ContainerInherit,ObjectInherit', 'None', " : "";
|
|
28043
|
+
await powershell(`
|
|
28044
|
+
$ErrorActionPreference = 'Stop'
|
|
28045
|
+
$sid = [Security.Principal.WindowsIdentity]::GetCurrent().User
|
|
28046
|
+
$acl = New-Object Security.AccessControl.${directory ? "DirectorySecurity" : "FileSecurity"}
|
|
28047
|
+
$acl.SetOwner($sid)
|
|
28048
|
+
$acl.SetAccessRuleProtection($true, $false)
|
|
28049
|
+
foreach ($identity in @($sid.Value, 'S-1-5-18', 'S-1-5-32-544')) {
|
|
28050
|
+
$principal = New-Object Security.Principal.SecurityIdentifier($identity)
|
|
28051
|
+
$rule = New-Object Security.AccessControl.FileSystemAccessRule($principal, 'FullControl', ${inheritance}'Allow')
|
|
28052
|
+
$acl.AddAccessRule($rule)
|
|
28053
|
+
}
|
|
28054
|
+
# The .NET API persists the modified owner/DACL without requesting SACL access.
|
|
28055
|
+
[IO.${directory ? "Directory" : "File"}]::SetAccessControl('${path.replaceAll("'", "''")}', $acl)
|
|
28056
|
+
`);
|
|
28057
|
+
}
|
|
28058
|
+
|
|
28059
|
+
// ../memoh/packages/runtime/src/secure-files.ts
|
|
28060
|
+
var directoryWriteRights = ["write", "append", "delete", "add_file", "add_subdirectory", "writeattr", "writeextattr", "writesecurity", "chown", "delete_child"];
|
|
28061
|
+
var fileWriteRights = ["write", "append", "delete", "writeattr", "writeextattr", "writesecurity", "chown"];
|
|
28062
|
+
var privateFileRights = ["read", ...fileWriteRights];
|
|
28063
|
+
async function checkDirectory(path) {
|
|
28064
|
+
const absolute = resolve(path);
|
|
28065
|
+
if (process.platform === "win32") {
|
|
28066
|
+
const info = await lstat(absolute);
|
|
28067
|
+
if (!info.isDirectory() || info.isSymbolicLink()) throw new Error(`unsafe runtime directory: ${absolute}`);
|
|
28068
|
+
return checkWindowsAccess(absolute, false);
|
|
28069
|
+
}
|
|
28070
|
+
const checked = /* @__PURE__ */ new Set();
|
|
28071
|
+
await inspectDirectory(absolute, checked);
|
|
28072
|
+
if (process.platform === "darwin" && await grantsOthers([...checked], directoryWriteRights)) {
|
|
28073
|
+
throw new Error(`runtime directory chain has a writable extended ACL: ${absolute}`);
|
|
28074
|
+
}
|
|
28075
|
+
}
|
|
28076
|
+
async function grantsOthers(paths, rights) {
|
|
28077
|
+
const { stdout } = await promisify2(execFile2)("/bin/ls", ["-lde", ...paths]);
|
|
28078
|
+
const self2 = userInfo().username;
|
|
28079
|
+
for (const line of stdout.split("\n").filter((line2) => /^\s*\d+:/.test(line2))) {
|
|
28080
|
+
const entry = line.match(/^\s*\d+:\s+(user|group):(.+?)\s+(?:inherited\s+)?(allow|deny)\s+(\S+)\s*$/);
|
|
28081
|
+
if (!entry) throw new Error(`could not verify macOS ACL entry for runtime path: ${paths.join(", ")}`);
|
|
28082
|
+
const [, kind, principal, access6, granted] = entry;
|
|
28083
|
+
if (access6 === "deny") continue;
|
|
28084
|
+
if (kind === "user" && principal === self2) continue;
|
|
28085
|
+
if (granted.split(",").some((right) => rights.includes(right))) return true;
|
|
28086
|
+
}
|
|
28087
|
+
return false;
|
|
28088
|
+
}
|
|
28089
|
+
async function inspectDirectory(absolute, checked) {
|
|
28090
|
+
if (checked.has(absolute)) return;
|
|
28091
|
+
checked.add(absolute);
|
|
28092
|
+
const parent = dirname(absolute);
|
|
28093
|
+
if (parent !== absolute) await inspectDirectory(parent, checked);
|
|
28094
|
+
const info = await lstat(absolute);
|
|
28095
|
+
if (info.isSymbolicLink() && info.uid === 0) {
|
|
28096
|
+
return inspectDirectory(await realpath(absolute), checked);
|
|
28097
|
+
}
|
|
28098
|
+
if (!info.isDirectory() || info.isSymbolicLink()) throw new Error(`unsafe runtime directory: ${absolute}`);
|
|
28099
|
+
const uid = process.getuid();
|
|
28100
|
+
const trustedOwner = info.uid === uid || info.uid === 0;
|
|
28101
|
+
const stickyRoot = info.uid === 0 && (info.mode & 512) !== 0;
|
|
28102
|
+
if (!trustedOwner || (info.mode & 18) !== 0 && !stickyRoot) {
|
|
28103
|
+
throw new Error(`runtime directory must be owned by you or root and not writable by other users: ${absolute}`);
|
|
28104
|
+
}
|
|
28105
|
+
}
|
|
28106
|
+
async function ensureDirectory(path) {
|
|
28107
|
+
const absolute = resolve(path);
|
|
28108
|
+
try {
|
|
28109
|
+
await checkDirectory(absolute);
|
|
28110
|
+
} catch (error) {
|
|
28111
|
+
if (errorCode(error) !== "ENOENT") throw error;
|
|
28112
|
+
const parent = dirname(absolute);
|
|
28113
|
+
if (parent === absolute || absolute === parse(absolute).root) throw error;
|
|
28114
|
+
await ensureDirectory(parent);
|
|
28115
|
+
try {
|
|
28116
|
+
await mkdir(absolute, { mode: 448 });
|
|
28117
|
+
} catch (error2) {
|
|
28118
|
+
if (errorCode(error2) !== "EEXIST") throw error2;
|
|
28119
|
+
}
|
|
28120
|
+
await checkDirectory(absolute);
|
|
28121
|
+
}
|
|
28122
|
+
}
|
|
28123
|
+
async function readPrivateFile(path) {
|
|
28124
|
+
await checkDirectory(dirname(path));
|
|
28125
|
+
const info = await lstat(path);
|
|
28126
|
+
if (!info.isFile() || info.isSymbolicLink() || process.platform !== "win32" && (info.uid !== process.getuid() || (info.mode & 63) !== 0)) {
|
|
28127
|
+
throw new Error(`runtime file must be a private regular file owned by you: ${path}`);
|
|
28128
|
+
}
|
|
28129
|
+
if (process.platform === "darwin" && await grantsOthers([path], privateFileRights)) {
|
|
28130
|
+
throw new Error(`runtime file has an unsafe extended ACL: ${path}`);
|
|
28131
|
+
}
|
|
28132
|
+
if (process.platform === "win32") await checkWindowsAccess(path, true);
|
|
28133
|
+
const handle = await open(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
28134
|
+
try {
|
|
28135
|
+
const opened = await handle.stat();
|
|
28136
|
+
if (opened.dev !== info.dev || opened.ino !== info.ino) throw new Error(`runtime file changed while opening: ${path}`);
|
|
28137
|
+
return await handle.readFile("utf8");
|
|
28138
|
+
} finally {
|
|
28139
|
+
await handle.close();
|
|
28140
|
+
}
|
|
28141
|
+
}
|
|
28142
|
+
async function writeFileAtomic(path, content, mode) {
|
|
28143
|
+
await ensureDirectory(dirname(path));
|
|
28144
|
+
const staging = join(dirname(path), `.${randomUUID()}.tmp`);
|
|
28145
|
+
await mkdir(staging, { mode: 448 });
|
|
28146
|
+
const temporary = join(staging, "content");
|
|
28147
|
+
try {
|
|
28148
|
+
if (process.platform === "darwin") await promisify2(execFile2)("/bin/chmod", ["-N", staging]);
|
|
28149
|
+
if (process.platform === "win32") await protectWindowsDirectory(staging);
|
|
28150
|
+
const handle = await open(temporary, "wx", mode);
|
|
28151
|
+
try {
|
|
28152
|
+
if (process.platform === "darwin") await promisify2(execFile2)("/bin/chmod", ["-N", temporary]);
|
|
28153
|
+
if (process.platform === "win32") await protectWindowsFile(temporary);
|
|
28154
|
+
await handle.writeFile(content);
|
|
28155
|
+
await handle.sync();
|
|
28156
|
+
} finally {
|
|
28157
|
+
await handle.close();
|
|
28158
|
+
}
|
|
28159
|
+
await chmod(temporary, mode);
|
|
28160
|
+
await rename(temporary, path);
|
|
28161
|
+
if (process.platform !== "win32") {
|
|
28162
|
+
const directory = await open(dirname(path), constants.O_RDONLY);
|
|
28163
|
+
try {
|
|
28164
|
+
await directory.sync();
|
|
28165
|
+
} finally {
|
|
28166
|
+
await directory.close();
|
|
28167
|
+
}
|
|
28168
|
+
}
|
|
28169
|
+
} finally {
|
|
28170
|
+
await rm(staging, { recursive: true, force: true });
|
|
28171
|
+
}
|
|
28172
|
+
}
|
|
28173
|
+
function errorCode(error) {
|
|
28174
|
+
return error && typeof error === "object" && "code" in error ? String(error.code) : void 0;
|
|
28175
|
+
}
|
|
27962
28176
|
|
|
27963
28177
|
// ../memoh/packages/runtime/src/config.ts
|
|
27964
28178
|
import { isAbsolute } from "node:path";
|
|
@@ -28017,10 +28231,620 @@ function validateConfig(config) {
|
|
|
28017
28231
|
}
|
|
28018
28232
|
}
|
|
28019
28233
|
|
|
28234
|
+
// ../memoh/packages/runtime/src/server-url.ts
|
|
28235
|
+
function normalizeRuntimeServerUrl(serverUrl) {
|
|
28236
|
+
const url = new URL(serverUrl.trim());
|
|
28237
|
+
if (url.protocol === "ws:") {
|
|
28238
|
+
url.protocol = "http:";
|
|
28239
|
+
} else if (url.protocol === "wss:") {
|
|
28240
|
+
url.protocol = "https:";
|
|
28241
|
+
}
|
|
28242
|
+
url.pathname = url.pathname.replace(/\/+$/, "") || "/";
|
|
28243
|
+
url.search = "";
|
|
28244
|
+
url.hash = "";
|
|
28245
|
+
return url.href;
|
|
28246
|
+
}
|
|
28247
|
+
function runtimeConnectUrl(serverUrl) {
|
|
28248
|
+
const url = new URL(serverUrl);
|
|
28249
|
+
if (url.protocol === "http:") {
|
|
28250
|
+
url.protocol = "ws:";
|
|
28251
|
+
} else if (url.protocol === "https:") {
|
|
28252
|
+
url.protocol = "wss:";
|
|
28253
|
+
}
|
|
28254
|
+
const basePath = url.pathname.replace(/\/+$/, "");
|
|
28255
|
+
url.pathname = `${basePath}/runtimes/connect`;
|
|
28256
|
+
url.search = "";
|
|
28257
|
+
url.hash = "";
|
|
28258
|
+
return url;
|
|
28259
|
+
}
|
|
28260
|
+
function assertSecureRuntimeUrl(url, insecureLocalhost = false) {
|
|
28261
|
+
if (url.username || url.password) {
|
|
28262
|
+
throw new Error("runtime connection URL must not contain credentials");
|
|
28263
|
+
}
|
|
28264
|
+
if (url.protocol === "wss:") {
|
|
28265
|
+
return;
|
|
28266
|
+
}
|
|
28267
|
+
const hostname2 = url.hostname.replace(/^\[|\]$/g, "");
|
|
28268
|
+
const local = hostname2 === "127.0.0.1" || hostname2 === "localhost" || hostname2 === "::1";
|
|
28269
|
+
if (url.protocol === "ws:" && insecureLocalhost && local) {
|
|
28270
|
+
return;
|
|
28271
|
+
}
|
|
28272
|
+
throw new Error("runtime connections require wss://; use --insecure-localhost only for localhost development");
|
|
28273
|
+
}
|
|
28274
|
+
|
|
28275
|
+
// ../memoh/packages/runtime/src/runtime-config.ts
|
|
28276
|
+
var runtimeEnrollmentSchemaVersion = 1;
|
|
28277
|
+
function resolveRuntimePaths(options = {}) {
|
|
28278
|
+
const home = resolve2(options.home ?? homedir());
|
|
28279
|
+
const runtimeHome = join2(home, ".memoh", "runtime");
|
|
28280
|
+
const configPath = join2(home, ".memoh", "runtime.json");
|
|
28281
|
+
const serviceDir = join2(runtimeHome, "service");
|
|
28282
|
+
return {
|
|
28283
|
+
home,
|
|
28284
|
+
runtimeHome,
|
|
28285
|
+
configPath,
|
|
28286
|
+
logsDir: join2(runtimeHome, "logs"),
|
|
28287
|
+
serviceDir,
|
|
28288
|
+
launchdPlistPath: join2(home, "Library", "LaunchAgents", "ai.memoh.runtime.plist"),
|
|
28289
|
+
systemdUnitPath: join2(serviceDir, "memoh-runtime.service"),
|
|
28290
|
+
windowsTaskXMLPath: join2(serviceDir, "memoh-runtime-task.xml")
|
|
28291
|
+
};
|
|
28292
|
+
}
|
|
28293
|
+
function normalizeRuntimeEnrollment(input, workspaceBase = homedir()) {
|
|
28294
|
+
const rawServerUrl = input.serverUrl.trim();
|
|
28295
|
+
const key = input.key.trim();
|
|
28296
|
+
const teamId = input.teamId === void 0 ? void 0 : normalizeRuntimeTeamId(input.teamId);
|
|
28297
|
+
const insecureLocalhost = input.insecureLocalhost === true;
|
|
28298
|
+
validateConfig({
|
|
28299
|
+
serverUrl: rawServerUrl,
|
|
28300
|
+
key,
|
|
28301
|
+
teamId,
|
|
28302
|
+
workspaceBase,
|
|
28303
|
+
insecureLocalhost
|
|
28304
|
+
});
|
|
28305
|
+
assertSecureRuntimeUrl(runtimeConnectUrl(rawServerUrl), insecureLocalhost);
|
|
28306
|
+
const serverUrl = normalizeRuntimeServerUrl(rawServerUrl);
|
|
28307
|
+
return {
|
|
28308
|
+
schemaVersion: runtimeEnrollmentSchemaVersion,
|
|
28309
|
+
serverUrl,
|
|
28310
|
+
key,
|
|
28311
|
+
teamId,
|
|
28312
|
+
insecureLocalhost
|
|
28313
|
+
};
|
|
28314
|
+
}
|
|
28315
|
+
async function readRuntimeEnrollment(path, workspaceBase = homedir()) {
|
|
28316
|
+
let raw;
|
|
28317
|
+
try {
|
|
28318
|
+
raw = await readPrivateFile(path);
|
|
28319
|
+
} catch (error) {
|
|
28320
|
+
if (nodeErrorCode(error) === "ENOENT") {
|
|
28321
|
+
throw new Error(`runtime configuration was not found at ${path}`);
|
|
28322
|
+
}
|
|
28323
|
+
throw new Error(`runtime configuration could not be read safely at ${path}`);
|
|
28324
|
+
}
|
|
28325
|
+
let parsed;
|
|
28326
|
+
try {
|
|
28327
|
+
parsed = JSON.parse(raw);
|
|
28328
|
+
} catch {
|
|
28329
|
+
throw new Error(`runtime configuration at ${path} is not valid JSON`);
|
|
28330
|
+
}
|
|
28331
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
28332
|
+
throw new Error(`runtime configuration at ${path} must be an object`);
|
|
28333
|
+
}
|
|
28334
|
+
const record = parsed;
|
|
28335
|
+
if (record.schemaVersion !== runtimeEnrollmentSchemaVersion) {
|
|
28336
|
+
throw new Error(`runtime configuration at ${path} has an unsupported schema version`);
|
|
28337
|
+
}
|
|
28338
|
+
if (typeof record.serverUrl !== "string" || typeof record.key !== "string") {
|
|
28339
|
+
throw new Error(`runtime configuration at ${path} is missing serverUrl or key`);
|
|
28340
|
+
}
|
|
28341
|
+
if (record.teamId !== void 0 && typeof record.teamId !== "string") {
|
|
28342
|
+
throw new Error(`runtime configuration at ${path} has an invalid teamId`);
|
|
28343
|
+
}
|
|
28344
|
+
if (record.insecureLocalhost !== void 0 && typeof record.insecureLocalhost !== "boolean") {
|
|
28345
|
+
throw new Error(`runtime configuration at ${path} has an invalid insecureLocalhost value`);
|
|
28346
|
+
}
|
|
28347
|
+
try {
|
|
28348
|
+
return normalizeRuntimeEnrollment({
|
|
28349
|
+
serverUrl: record.serverUrl,
|
|
28350
|
+
key: record.key,
|
|
28351
|
+
teamId: record.teamId,
|
|
28352
|
+
insecureLocalhost: record.insecureLocalhost
|
|
28353
|
+
}, workspaceBase);
|
|
28354
|
+
} catch (error) {
|
|
28355
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
28356
|
+
throw new Error(`runtime configuration at ${path} is invalid: ${message}`);
|
|
28357
|
+
}
|
|
28358
|
+
}
|
|
28359
|
+
async function readRuntimeEnrollmentIfExists(path, workspaceBase = homedir()) {
|
|
28360
|
+
try {
|
|
28361
|
+
await lstat2(path);
|
|
28362
|
+
} catch (error) {
|
|
28363
|
+
if (nodeErrorCode(error) === "ENOENT") return void 0;
|
|
28364
|
+
throw error;
|
|
28365
|
+
}
|
|
28366
|
+
return readRuntimeEnrollment(path, workspaceBase);
|
|
28367
|
+
}
|
|
28368
|
+
async function writeRuntimeEnrollment(path, enrollment) {
|
|
28369
|
+
const normalized = normalizeRuntimeEnrollment(enrollment);
|
|
28370
|
+
await ensureDirectory(dirname2(path));
|
|
28371
|
+
await writeFileAtomic(path, `${JSON.stringify(normalized, null, 2)}
|
|
28372
|
+
`, 384);
|
|
28373
|
+
}
|
|
28374
|
+
function sameEnrollment(left, right) {
|
|
28375
|
+
return left.serverUrl === right.serverUrl && left.key === right.key && left.teamId === right.teamId && left.insecureLocalhost === right.insecureLocalhost;
|
|
28376
|
+
}
|
|
28377
|
+
function parseBooleanEnvironment(value, name) {
|
|
28378
|
+
const normalized = value?.trim().toLowerCase();
|
|
28379
|
+
if (!normalized) return void 0;
|
|
28380
|
+
if (["1", "true", "yes", "on"].includes(normalized)) return true;
|
|
28381
|
+
if (["0", "false", "no", "off"].includes(normalized)) return false;
|
|
28382
|
+
throw new Error(`${name} must be true or false`);
|
|
28383
|
+
}
|
|
28384
|
+
function nodeErrorCode(error) {
|
|
28385
|
+
return error && typeof error === "object" && "code" in error ? String(error.code) : void 0;
|
|
28386
|
+
}
|
|
28387
|
+
|
|
28388
|
+
// ../memoh/packages/runtime/src/daemon/types.ts
|
|
28389
|
+
import { spawn } from "node:child_process";
|
|
28390
|
+
var maxCommandOutputBytes = 64 * 1024;
|
|
28391
|
+
var spawnCommand = (command, args2, options = {}) => new Promise((resolve5, reject) => {
|
|
28392
|
+
const child = spawn(command, args2, {
|
|
28393
|
+
env: options.env,
|
|
28394
|
+
shell: false,
|
|
28395
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
28396
|
+
windowsHide: true
|
|
28397
|
+
});
|
|
28398
|
+
let stdout = "";
|
|
28399
|
+
let stderr = "";
|
|
28400
|
+
child.stdout.setEncoding("utf8");
|
|
28401
|
+
child.stderr.setEncoding("utf8");
|
|
28402
|
+
child.stdout.on("data", (chunk) => {
|
|
28403
|
+
if (stdout.length < maxCommandOutputBytes) stdout += chunk.slice(0, maxCommandOutputBytes - stdout.length);
|
|
28404
|
+
});
|
|
28405
|
+
child.stderr.on("data", (chunk) => {
|
|
28406
|
+
if (stderr.length < maxCommandOutputBytes) stderr += chunk.slice(0, maxCommandOutputBytes - stderr.length);
|
|
28407
|
+
});
|
|
28408
|
+
const timer = setTimeout(() => {
|
|
28409
|
+
child.kill();
|
|
28410
|
+
reject(new Error(`${command} timed out`));
|
|
28411
|
+
}, 3e4);
|
|
28412
|
+
timer.unref();
|
|
28413
|
+
child.once("error", (error) => {
|
|
28414
|
+
clearTimeout(timer);
|
|
28415
|
+
reject(error);
|
|
28416
|
+
});
|
|
28417
|
+
child.once("close", (code) => {
|
|
28418
|
+
clearTimeout(timer);
|
|
28419
|
+
resolve5({ code: code ?? 1, stdout, stderr });
|
|
28420
|
+
});
|
|
28421
|
+
});
|
|
28422
|
+
async function requireCommand(runner, command, args2, options = {}) {
|
|
28423
|
+
const result = await runner(command, args2, { env: options.env });
|
|
28424
|
+
const allowed = options.allowedExitCodes ?? [0];
|
|
28425
|
+
if (!allowed.includes(result.code)) {
|
|
28426
|
+
const detail = result.stderr.trim() || result.stdout.trim() || `exit code ${result.code}`;
|
|
28427
|
+
throw new Error(`${command} ${args2.join(" ")} failed: ${detail}`);
|
|
28428
|
+
}
|
|
28429
|
+
return result;
|
|
28430
|
+
}
|
|
28431
|
+
function serviceExecutablePath(nodePath, environmentPath, platform2 = process.platform) {
|
|
28432
|
+
const separator = platform2 === "win32" ? ";" : ":";
|
|
28433
|
+
const nodeDirectory = nodePath.replace(/[\\/][^\\/]+$/, "");
|
|
28434
|
+
const defaults = platform2 === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"] : ["/usr/local/bin", "/usr/bin", "/bin"];
|
|
28435
|
+
const values = [nodeDirectory, ...environmentPath?.split(separator) ?? [], ...defaults].map((value) => value.trim()).filter((value) => value && !value.includes("\0") && !value.includes("\n") && !value.includes("\r"));
|
|
28436
|
+
return [...new Set(values)].join(separator);
|
|
28437
|
+
}
|
|
28438
|
+
|
|
28439
|
+
// ../memoh/packages/runtime/src/daemon/launchd.ts
|
|
28440
|
+
var launchdLabel = "ai.memoh.runtime";
|
|
28441
|
+
var bootstrapAttempts = 5;
|
|
28442
|
+
var defaultBootstrapRetryDelayMs = 300;
|
|
28443
|
+
var bootoutWaitAttempts = 50;
|
|
28444
|
+
function renderLaunchdPlist(spec) {
|
|
28445
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
28446
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
28447
|
+
<plist version="1.0">
|
|
28448
|
+
<dict>
|
|
28449
|
+
<key>Label</key>
|
|
28450
|
+
<string>${xmlEscape(launchdLabel)}</string>
|
|
28451
|
+
<key>ProgramArguments</key>
|
|
28452
|
+
<array>
|
|
28453
|
+
<string>${xmlEscape(spec.nodePath)}</string>
|
|
28454
|
+
<string>${xmlEscape(spec.entryPath)}</string>
|
|
28455
|
+
<string>run</string>
|
|
28456
|
+
<string>--config</string>
|
|
28457
|
+
<string>${xmlEscape(spec.configPath)}</string>
|
|
28458
|
+
</array>
|
|
28459
|
+
<key>EnvironmentVariables</key>
|
|
28460
|
+
<dict>
|
|
28461
|
+
<key>PATH</key>
|
|
28462
|
+
<string>${xmlEscape(spec.servicePath)}</string>
|
|
28463
|
+
</dict>
|
|
28464
|
+
<key>WorkingDirectory</key>
|
|
28465
|
+
<string>${xmlEscape(spec.workingDirectory)}</string>
|
|
28466
|
+
<key>RunAtLoad</key>
|
|
28467
|
+
<true/>
|
|
28468
|
+
<key>KeepAlive</key>
|
|
28469
|
+
<true/>
|
|
28470
|
+
<key>ThrottleInterval</key>
|
|
28471
|
+
<integer>5</integer>
|
|
28472
|
+
<key>StandardOutPath</key>
|
|
28473
|
+
<string>${xmlEscape(`${spec.logsDir}/runtime.log`)}</string>
|
|
28474
|
+
<key>StandardErrorPath</key>
|
|
28475
|
+
<string>${xmlEscape(`${spec.logsDir}/runtime-error.log`)}</string>
|
|
28476
|
+
</dict>
|
|
28477
|
+
</plist>
|
|
28478
|
+
`;
|
|
28479
|
+
}
|
|
28480
|
+
function createLaunchdServiceManager(paths, runner, uid, options = {}) {
|
|
28481
|
+
const launchctl = "/bin/launchctl";
|
|
28482
|
+
const domain = `gui/${uid}`;
|
|
28483
|
+
const target = `${domain}/${launchdLabel}`;
|
|
28484
|
+
const retryDelayMs = options.bootstrapRetryDelayMs ?? defaultBootstrapRetryDelayMs;
|
|
28485
|
+
const loaded = async () => (await runner(launchctl, ["print", target])).code === 0;
|
|
28486
|
+
const bootstrap = async () => {
|
|
28487
|
+
for (let attempt = 1; ; attempt++) {
|
|
28488
|
+
try {
|
|
28489
|
+
await requireCommand(runner, launchctl, ["bootstrap", domain, paths.launchdPlistPath]);
|
|
28490
|
+
return;
|
|
28491
|
+
} catch (error) {
|
|
28492
|
+
if (attempt >= bootstrapAttempts) throw error;
|
|
28493
|
+
await sleep(retryDelayMs);
|
|
28494
|
+
}
|
|
28495
|
+
}
|
|
28496
|
+
};
|
|
28497
|
+
const bootstrapIfUnloaded = async () => {
|
|
28498
|
+
if (await loaded()) return;
|
|
28499
|
+
await bootstrap();
|
|
28500
|
+
};
|
|
28501
|
+
const bootout = async () => {
|
|
28502
|
+
await requireCommand(runner, launchctl, ["bootout", target], { allowedExitCodes: [0, 3] });
|
|
28503
|
+
for (let attempt = 0; attempt < bootoutWaitAttempts && await loaded(); attempt++) {
|
|
28504
|
+
await sleep(retryDelayMs / 3);
|
|
28505
|
+
}
|
|
28506
|
+
if (await loaded()) throw new Error("launchd job did not stop before the deadline");
|
|
28507
|
+
};
|
|
28508
|
+
return {
|
|
28509
|
+
backend: "launchd-user",
|
|
28510
|
+
async register(spec) {
|
|
28511
|
+
await ensureDirectory(spec.logsDir);
|
|
28512
|
+
await writeFileAtomic(paths.launchdPlistPath, renderLaunchdPlist(spec), 384);
|
|
28513
|
+
await requireCommand(runner, "/usr/bin/plutil", ["-lint", paths.launchdPlistPath]);
|
|
28514
|
+
},
|
|
28515
|
+
async start() {
|
|
28516
|
+
await bootstrapIfUnloaded();
|
|
28517
|
+
},
|
|
28518
|
+
async stop() {
|
|
28519
|
+
await bootout();
|
|
28520
|
+
},
|
|
28521
|
+
async status() {
|
|
28522
|
+
const result = await runner(launchctl, ["print", target]);
|
|
28523
|
+
if (result.code === 0) {
|
|
28524
|
+
return {
|
|
28525
|
+
backend: "launchd-user",
|
|
28526
|
+
state: /\bstate\s*=\s*running\b/.test(result.stdout) ? "running" : "stopped"
|
|
28527
|
+
};
|
|
28528
|
+
}
|
|
28529
|
+
try {
|
|
28530
|
+
await access(paths.launchdPlistPath);
|
|
28531
|
+
return { backend: "launchd-user", state: "stopped" };
|
|
28532
|
+
} catch {
|
|
28533
|
+
return { backend: "launchd-user", state: "not-installed" };
|
|
28534
|
+
}
|
|
28535
|
+
},
|
|
28536
|
+
async uninstall() {
|
|
28537
|
+
await bootout();
|
|
28538
|
+
await rm2(paths.launchdPlistPath, { force: true });
|
|
28539
|
+
}
|
|
28540
|
+
};
|
|
28541
|
+
}
|
|
28542
|
+
function xmlEscape(value) {
|
|
28543
|
+
if (value.includes("\0")) throw new Error("launchd service value contains a null byte");
|
|
28544
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
28545
|
+
}
|
|
28546
|
+
|
|
28547
|
+
// ../memoh/packages/runtime/src/daemon/systemd.ts
|
|
28548
|
+
import { rm as rm3 } from "node:fs/promises";
|
|
28549
|
+
var unitName = "memoh-runtime.service";
|
|
28550
|
+
function renderSystemdUnit(spec) {
|
|
28551
|
+
return `[Unit]
|
|
28552
|
+
Description=Memoh Runtime
|
|
28553
|
+
|
|
28554
|
+
[Service]
|
|
28555
|
+
Type=simple
|
|
28556
|
+
Environment=${systemdQuote(`PATH=${spec.servicePath}`, false)}
|
|
28557
|
+
ExecStart=${systemdQuote(spec.nodePath, false)} ${systemdQuote(spec.entryPath)} run --config ${systemdQuote(spec.configPath)}
|
|
28558
|
+
WorkingDirectory=${systemdPath(spec.workingDirectory)}
|
|
28559
|
+
UMask=0077
|
|
28560
|
+
Restart=always
|
|
28561
|
+
RestartSec=5
|
|
28562
|
+
TimeoutStopSec=30
|
|
28563
|
+
|
|
28564
|
+
[Install]
|
|
28565
|
+
WantedBy=default.target
|
|
28566
|
+
`;
|
|
28567
|
+
}
|
|
28568
|
+
function createSystemdServiceManager(paths, runner) {
|
|
28569
|
+
const systemctl = "systemctl";
|
|
28570
|
+
const baseArgs = ["--user"];
|
|
28571
|
+
const run2 = (args2, allowedExitCodes) => requireCommand(runner, systemctl, [...baseArgs, ...args2], { allowedExitCodes });
|
|
28572
|
+
return {
|
|
28573
|
+
backend: "systemd-user",
|
|
28574
|
+
async register(spec) {
|
|
28575
|
+
await writeFileAtomic(paths.systemdUnitPath, renderSystemdUnit(spec), 384);
|
|
28576
|
+
await requireCommand(runner, "systemd-analyze", ["--user", "verify", paths.systemdUnitPath]);
|
|
28577
|
+
await run2(["daemon-reload"]);
|
|
28578
|
+
await run2(["enable", paths.systemdUnitPath]);
|
|
28579
|
+
},
|
|
28580
|
+
async start() {
|
|
28581
|
+
await run2(["start", unitName]);
|
|
28582
|
+
},
|
|
28583
|
+
async stop() {
|
|
28584
|
+
await run2(["stop", unitName], [0, 5]);
|
|
28585
|
+
},
|
|
28586
|
+
async status() {
|
|
28587
|
+
const result = await runner(systemctl, [...baseArgs, "show", unitName, "--property=LoadState,ActiveState,SubState,MainPID"]);
|
|
28588
|
+
const fields = Object.fromEntries(result.stdout.trim().split("\n").map((line) => line.split("=")));
|
|
28589
|
+
if (fields.LoadState === "not-found") return { backend: "systemd-user", state: "not-installed" };
|
|
28590
|
+
if (result.code !== 0 || fields.LoadState !== "loaded") {
|
|
28591
|
+
return { backend: "systemd-user", state: "unknown", detail: result.stderr.trim() || fields.LoadState };
|
|
28592
|
+
}
|
|
28593
|
+
const pid = Number(fields.MainPID);
|
|
28594
|
+
return {
|
|
28595
|
+
backend: "systemd-user",
|
|
28596
|
+
state: fields.ActiveState === "active" && fields.SubState === "running" && pid > 0 ? "running" : ["inactive", "failed"].includes(fields.ActiveState) ? "stopped" : "unknown",
|
|
28597
|
+
pid: pid > 0 ? pid : void 0,
|
|
28598
|
+
detail: fields.SubState
|
|
28599
|
+
};
|
|
28600
|
+
},
|
|
28601
|
+
async uninstall() {
|
|
28602
|
+
await run2(["disable", "--now", unitName], [0, 1, 5]);
|
|
28603
|
+
try {
|
|
28604
|
+
await rm3(paths.systemdUnitPath, { force: true });
|
|
28605
|
+
} catch (error) {
|
|
28606
|
+
if (nodeErrorCode(error) !== "ENOENT") throw error;
|
|
28607
|
+
}
|
|
28608
|
+
await run2(["daemon-reload"]);
|
|
28609
|
+
await run2(["reset-failed", unitName], [0, 1, 5]);
|
|
28610
|
+
}
|
|
28611
|
+
};
|
|
28612
|
+
}
|
|
28613
|
+
function systemdQuote(value, expandDollar = true) {
|
|
28614
|
+
if (expandDollar) value = value.replaceAll("$", () => "$$");
|
|
28615
|
+
if (value.includes("\0") || value.includes("\n") || value.includes("\r")) {
|
|
28616
|
+
throw new Error("systemd service value contains unsupported control characters");
|
|
28617
|
+
}
|
|
28618
|
+
return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("%", "%%")}"`;
|
|
28619
|
+
}
|
|
28620
|
+
function systemdPath(value) {
|
|
28621
|
+
if (!value.startsWith("/") || value.trim() !== value || /[\\\0\n\r]/.test(value)) throw new Error("invalid systemd working directory");
|
|
28622
|
+
return value.replaceAll("%", "%%");
|
|
28623
|
+
}
|
|
28624
|
+
|
|
28625
|
+
// ../memoh/packages/runtime/src/daemon/windows.ts
|
|
28626
|
+
import { rm as rm4 } from "node:fs/promises";
|
|
28627
|
+
function renderWindowsTaskXML(spec, userId) {
|
|
28628
|
+
const argumentsValue = [
|
|
28629
|
+
windowsQuoteArgument(spec.entryPath),
|
|
28630
|
+
"run",
|
|
28631
|
+
"--config",
|
|
28632
|
+
windowsQuoteArgument(spec.configPath),
|
|
28633
|
+
"--log",
|
|
28634
|
+
windowsQuoteArgument(`${spec.logsDir}\\runtime.log`)
|
|
28635
|
+
].join(" ");
|
|
28636
|
+
return `<?xml version="1.0" encoding="UTF-16"?>
|
|
28637
|
+
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
|
28638
|
+
<RegistrationInfo>
|
|
28639
|
+
<Description>Memoh Runtime</Description>
|
|
28640
|
+
</RegistrationInfo>
|
|
28641
|
+
<Triggers>
|
|
28642
|
+
<LogonTrigger>
|
|
28643
|
+
<Enabled>true</Enabled>
|
|
28644
|
+
<UserId>${xmlEscape2(userId)}</UserId>
|
|
28645
|
+
</LogonTrigger>
|
|
28646
|
+
</Triggers>
|
|
28647
|
+
<Principals>
|
|
28648
|
+
<Principal id="Author">
|
|
28649
|
+
<UserId>${xmlEscape2(userId)}</UserId>
|
|
28650
|
+
<LogonType>InteractiveToken</LogonType>
|
|
28651
|
+
<RunLevel>LeastPrivilege</RunLevel>
|
|
28652
|
+
</Principal>
|
|
28653
|
+
</Principals>
|
|
28654
|
+
<Settings>
|
|
28655
|
+
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
|
|
28656
|
+
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
|
|
28657
|
+
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
|
|
28658
|
+
<AllowHardTerminate>true</AllowHardTerminate>
|
|
28659
|
+
<StartWhenAvailable>true</StartWhenAvailable>
|
|
28660
|
+
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
|
|
28661
|
+
<AllowStartOnDemand>true</AllowStartOnDemand>
|
|
28662
|
+
<Enabled>true</Enabled>
|
|
28663
|
+
<Hidden>false</Hidden>
|
|
28664
|
+
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
|
28665
|
+
<WakeToRun>false</WakeToRun>
|
|
28666
|
+
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
|
|
28667
|
+
<RestartOnFailure>
|
|
28668
|
+
<Interval>PT1M</Interval>
|
|
28669
|
+
<Count>255</Count>
|
|
28670
|
+
</RestartOnFailure>
|
|
28671
|
+
</Settings>
|
|
28672
|
+
<Actions Context="Author">
|
|
28673
|
+
<Exec>
|
|
28674
|
+
<Command>${xmlEscape2(spec.nodePath)}</Command>
|
|
28675
|
+
<Arguments>${xmlEscape2(argumentsValue)}</Arguments>
|
|
28676
|
+
<WorkingDirectory>${xmlEscape2(spec.workingDirectory)}</WorkingDirectory>
|
|
28677
|
+
</Exec>
|
|
28678
|
+
</Actions>
|
|
28679
|
+
</Task>
|
|
28680
|
+
`;
|
|
28681
|
+
}
|
|
28682
|
+
function createWindowsTaskServiceManager(paths, runner) {
|
|
28683
|
+
const schtasks = "schtasks.exe";
|
|
28684
|
+
let identity;
|
|
28685
|
+
const userID = () => identity ??= currentWindowsUserID(runner);
|
|
28686
|
+
const taskName = async () => `\\Memoh\\Runtime-${await userID()}`;
|
|
28687
|
+
const inspect = async () => {
|
|
28688
|
+
const sid = await userID();
|
|
28689
|
+
const result = await requireCommand(runner, "powershell.exe", [
|
|
28690
|
+
"-NoProfile",
|
|
28691
|
+
"-NonInteractive",
|
|
28692
|
+
"-Command",
|
|
28693
|
+
`$ErrorActionPreference = 'Stop'; $task = Get-ScheduledTask | Where-Object { $_.TaskPath -eq '\\Memoh\\' -and $_.TaskName -eq 'Runtime-${sid}' }; if ($null -eq $task) { 'not-installed' } else { $owner = $task.Principal.UserId; if ($owner -notmatch '^S-1-') { $owner = ([System.Security.Principal.NTAccount]::new($owner)).Translate([System.Security.Principal.SecurityIdentifier]).Value }; if ($owner -ne '${sid}') { throw 'Runtime task belongs to another account' }; $task.State.ToString() }`
|
|
28694
|
+
], { env: windowsPowerShellEnv() });
|
|
28695
|
+
const state = result.stdout.trim().toLowerCase();
|
|
28696
|
+
if (!["not-installed", "running", "ready", "disabled", "queued", "unknown"].includes(state)) {
|
|
28697
|
+
throw new Error("could not determine the Windows runtime task state");
|
|
28698
|
+
}
|
|
28699
|
+
return state;
|
|
28700
|
+
};
|
|
28701
|
+
const run2 = async (args2, allowedExitCodes) => requireCommand(runner, schtasks, [...args2, "/tn", await taskName()], { allowedExitCodes });
|
|
28702
|
+
const stop = async () => {
|
|
28703
|
+
if (["running", "queued", "unknown"].includes(await inspect())) await run2(["/end"]);
|
|
28704
|
+
};
|
|
28705
|
+
const start = async () => {
|
|
28706
|
+
if (await inspect() === "not-installed") throw new Error("Windows runtime task is not installed");
|
|
28707
|
+
await run2(["/run"]);
|
|
28708
|
+
};
|
|
28709
|
+
return {
|
|
28710
|
+
backend: "windows-task-scheduler",
|
|
28711
|
+
async register(spec) {
|
|
28712
|
+
const userId = await userID();
|
|
28713
|
+
await inspect();
|
|
28714
|
+
await ensureDirectory(spec.logsDir);
|
|
28715
|
+
const xml = renderWindowsTaskXML(spec, userId);
|
|
28716
|
+
const utf16 = Buffer.concat([Buffer.from([255, 254]), Buffer.from(xml, "utf16le")]);
|
|
28717
|
+
await writeFileAtomic(paths.windowsTaskXMLPath, utf16, 384);
|
|
28718
|
+
await run2(["/create", "/xml", paths.windowsTaskXMLPath, "/f"]);
|
|
28719
|
+
},
|
|
28720
|
+
start,
|
|
28721
|
+
stop,
|
|
28722
|
+
async status() {
|
|
28723
|
+
try {
|
|
28724
|
+
const state = await inspect();
|
|
28725
|
+
return {
|
|
28726
|
+
backend: "windows-task-scheduler",
|
|
28727
|
+
state: state === "running" ? "running" : state === "not-installed" ? "not-installed" : ["ready", "disabled"].includes(state) ? "stopped" : "unknown"
|
|
28728
|
+
};
|
|
28729
|
+
} catch {
|
|
28730
|
+
return { backend: "windows-task-scheduler", state: "unknown" };
|
|
28731
|
+
}
|
|
28732
|
+
},
|
|
28733
|
+
async uninstall() {
|
|
28734
|
+
if (await inspect() !== "not-installed") {
|
|
28735
|
+
await stop();
|
|
28736
|
+
await run2(["/delete", "/f"]);
|
|
28737
|
+
}
|
|
28738
|
+
await rm4(paths.windowsTaskXMLPath, { force: true });
|
|
28739
|
+
}
|
|
28740
|
+
};
|
|
28741
|
+
}
|
|
28742
|
+
async function currentWindowsUserID(runner) {
|
|
28743
|
+
const result = await requireCommand(runner, "whoami.exe", ["/user", "/fo", "csv", "/nh"]);
|
|
28744
|
+
const fields = [...result.stdout.matchAll(/"([^"]*)"/g)].map((match) => match[1]);
|
|
28745
|
+
const sid = fields.find((field) => /^S-1-(?:[0-9]+-)*[0-9]+$/i.test(field));
|
|
28746
|
+
if (sid) return sid;
|
|
28747
|
+
throw new Error("could not determine the current Windows account");
|
|
28748
|
+
}
|
|
28749
|
+
function windowsQuoteArgument(value) {
|
|
28750
|
+
if (value.includes("\0") || value.includes('"')) {
|
|
28751
|
+
throw new Error("Windows service path contains unsupported characters");
|
|
28752
|
+
}
|
|
28753
|
+
return `"${value}"`;
|
|
28754
|
+
}
|
|
28755
|
+
function xmlEscape2(value) {
|
|
28756
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
28757
|
+
}
|
|
28758
|
+
|
|
28759
|
+
// ../memoh/packages/runtime/src/daemon/index.ts
|
|
28760
|
+
function createRuntimeServiceManager(options) {
|
|
28761
|
+
switch (options.platform) {
|
|
28762
|
+
case "darwin":
|
|
28763
|
+
if (options.uid === void 0) throw new Error("launchd service installation requires a user ID");
|
|
28764
|
+
return createLaunchdServiceManager(options.paths, options.runner, options.uid);
|
|
28765
|
+
case "linux":
|
|
28766
|
+
return createSystemdServiceManager(options.paths, options.runner);
|
|
28767
|
+
case "win32":
|
|
28768
|
+
return createWindowsTaskServiceManager(options.paths, options.runner);
|
|
28769
|
+
default:
|
|
28770
|
+
throw new Error(`background services are not supported on ${options.platform}`);
|
|
28771
|
+
}
|
|
28772
|
+
}
|
|
28773
|
+
async function findNodeExecutable(envPath, platform2) {
|
|
28774
|
+
for (const directory of envPath?.split(platform2 === "win32" ? ";" : ":") ?? []) {
|
|
28775
|
+
if (!isAbsolute2(directory)) continue;
|
|
28776
|
+
const path = join3(directory, platform2 === "win32" ? "node.exe" : "node");
|
|
28777
|
+
try {
|
|
28778
|
+
if (!(await stat(path)).isFile()) continue;
|
|
28779
|
+
await access2(path, platform2 === "win32" ? constants2.R_OK : constants2.X_OK);
|
|
28780
|
+
return path;
|
|
28781
|
+
} catch {
|
|
28782
|
+
}
|
|
28783
|
+
}
|
|
28784
|
+
throw new Error("Node was not found in PATH; install Node and rerun service install");
|
|
28785
|
+
}
|
|
28786
|
+
async function waitForService(manager, target) {
|
|
28787
|
+
const deadline = Date.now() + 15e3;
|
|
28788
|
+
let observations = 0;
|
|
28789
|
+
do {
|
|
28790
|
+
const { state } = await manager.status();
|
|
28791
|
+
const matched = state === target || target === "stopped" && state === "not-installed";
|
|
28792
|
+
observations = matched ? observations + 1 : 0;
|
|
28793
|
+
if (observations >= (target === "running" ? 2 : 1)) return;
|
|
28794
|
+
await sleep2(250);
|
|
28795
|
+
} while (Date.now() < deadline);
|
|
28796
|
+
throw new Error(`runtime service did not reach ${target}; inspect the service logs`);
|
|
28797
|
+
}
|
|
28798
|
+
|
|
28799
|
+
// ../memoh/packages/runtime/src/enrollment-lock.ts
|
|
28800
|
+
import { mkdir as mkdir2, rm as rm5 } from "node:fs/promises";
|
|
28801
|
+
import { dirname as dirname3, join as join4 } from "node:path";
|
|
28802
|
+
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
28803
|
+
async function withEnrollmentLock(configPath, action, timeoutMs = 3e4) {
|
|
28804
|
+
await ensureDirectory(dirname3(configPath));
|
|
28805
|
+
const lockPath = `${configPath}.lock`;
|
|
28806
|
+
const deadline = Date.now() + timeoutMs;
|
|
28807
|
+
for (; ; ) {
|
|
28808
|
+
try {
|
|
28809
|
+
await mkdir2(lockPath, { mode: 448 });
|
|
28810
|
+
break;
|
|
28811
|
+
} catch (error) {
|
|
28812
|
+
if (errorCode(error) !== "EEXIST") throw error;
|
|
28813
|
+
if (Date.now() >= deadline) {
|
|
28814
|
+
throw new Error(`another enrollment operation holds ${lockPath}; inspect owner.json and remove the lock only after confirming that process has exited`);
|
|
28815
|
+
}
|
|
28816
|
+
await sleep3(100);
|
|
28817
|
+
}
|
|
28818
|
+
}
|
|
28819
|
+
try {
|
|
28820
|
+
if (process.platform === "win32") await protectWindowsDirectory(lockPath);
|
|
28821
|
+
await writeFileAtomic(join4(lockPath, "owner.json"), `${JSON.stringify({ pid: process.pid })}
|
|
28822
|
+
`, 384);
|
|
28823
|
+
return await action();
|
|
28824
|
+
} finally {
|
|
28825
|
+
await rm5(lockPath, { recursive: true, force: true });
|
|
28826
|
+
}
|
|
28827
|
+
}
|
|
28828
|
+
|
|
28829
|
+
// ../memoh/packages/runtime/src/session.ts
|
|
28830
|
+
import { arch, hostname, platform } from "node:os";
|
|
28831
|
+
import { realpath as realpath3 } from "node:fs/promises";
|
|
28832
|
+
|
|
28833
|
+
// ../memoh/node_modules/.pnpm/ws@8.21.0/node_modules/ws/wrapper.mjs
|
|
28834
|
+
var import_stream = __toESM(require_stream(), 1);
|
|
28835
|
+
var import_extension = __toESM(require_extension(), 1);
|
|
28836
|
+
var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
|
|
28837
|
+
var import_receiver = __toESM(require_receiver(), 1);
|
|
28838
|
+
var import_sender = __toESM(require_sender(), 1);
|
|
28839
|
+
var import_subprotocol = __toESM(require_subprotocol(), 1);
|
|
28840
|
+
var import_websocket = __toESM(require_websocket(), 1);
|
|
28841
|
+
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
28842
|
+
var wrapper_default = import_websocket.default;
|
|
28843
|
+
|
|
28020
28844
|
// ../memoh/packages/runtime/src/pipe/grpc-websocket.ts
|
|
28021
28845
|
function bridgeWebSocketToGrpc(websocket, grpc) {
|
|
28022
28846
|
const stream = (0, import_stream.default)(websocket, { encoding: void 0 });
|
|
28023
|
-
return new Promise((
|
|
28847
|
+
return new Promise((resolve5, reject) => {
|
|
28024
28848
|
let settled = false;
|
|
28025
28849
|
const finish = (error) => {
|
|
28026
28850
|
if (settled) {
|
|
@@ -28035,7 +28859,7 @@ function bridgeWebSocketToGrpc(websocket, grpc) {
|
|
|
28035
28859
|
if (error) {
|
|
28036
28860
|
reject(error);
|
|
28037
28861
|
} else {
|
|
28038
|
-
|
|
28862
|
+
resolve5();
|
|
28039
28863
|
}
|
|
28040
28864
|
};
|
|
28041
28865
|
websocket.once("close", () => finish());
|
|
@@ -28062,11 +28886,11 @@ function bridgeWebSocketToGrpc(websocket, grpc) {
|
|
|
28062
28886
|
// ../memoh/packages/runtime/src/service.ts
|
|
28063
28887
|
var import_grpc_js6 = __toESM(require_src3(), 1);
|
|
28064
28888
|
var import_proto_loader = __toESM(require_src2(), 1);
|
|
28065
|
-
import { access as
|
|
28889
|
+
import { access as access4 } from "node:fs/promises";
|
|
28066
28890
|
import { fileURLToPath } from "node:url";
|
|
28067
28891
|
|
|
28068
28892
|
// ../memoh/packages/runtime/src/children.ts
|
|
28069
|
-
import { execFile } from "node:child_process";
|
|
28893
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
28070
28894
|
|
|
28071
28895
|
// ../memoh/packages/runtime/src/core/shell.ts
|
|
28072
28896
|
import { win32 } from "node:path";
|
|
@@ -28225,10 +29049,10 @@ async function terminateWindowsProcessTree(pid) {
|
|
|
28225
29049
|
return;
|
|
28226
29050
|
}
|
|
28227
29051
|
const executable = windowsSystemExecutable("taskkill.exe");
|
|
28228
|
-
await new Promise((
|
|
28229
|
-
|
|
29052
|
+
await new Promise((resolve5, reject) => {
|
|
29053
|
+
execFile3(executable, ["/pid", String(pid), "/t", "/f"], { windowsHide: true }, (error) => {
|
|
28230
29054
|
if (!error || !processExists(pid)) {
|
|
28231
|
-
|
|
29055
|
+
resolve5();
|
|
28232
29056
|
} else {
|
|
28233
29057
|
reject(error);
|
|
28234
29058
|
}
|
|
@@ -28247,7 +29071,7 @@ async function waitForChildExit(child, timeout) {
|
|
|
28247
29071
|
if (child.exitCode !== null || child.signalCode !== null) {
|
|
28248
29072
|
return true;
|
|
28249
29073
|
}
|
|
28250
|
-
return new Promise((
|
|
29074
|
+
return new Promise((resolve5) => {
|
|
28251
29075
|
let settled = false;
|
|
28252
29076
|
const finish = (exited) => {
|
|
28253
29077
|
if (settled) {
|
|
@@ -28256,7 +29080,7 @@ async function waitForChildExit(child, timeout) {
|
|
|
28256
29080
|
settled = true;
|
|
28257
29081
|
clearTimeout(timer);
|
|
28258
29082
|
child.off("exit", onExit);
|
|
28259
|
-
|
|
29083
|
+
resolve5(exited);
|
|
28260
29084
|
};
|
|
28261
29085
|
const onExit = () => finish(true);
|
|
28262
29086
|
const timer = setTimeout(() => finish(child.exitCode !== null || child.signalCode !== null), timeout);
|
|
@@ -28287,7 +29111,7 @@ async function waitForProcessGroupExit(pgid, timeout) {
|
|
|
28287
29111
|
if (!processGroupExists(pgid)) {
|
|
28288
29112
|
return true;
|
|
28289
29113
|
}
|
|
28290
|
-
await new Promise((
|
|
29114
|
+
await new Promise((resolve5) => setTimeout(resolve5, 25));
|
|
28291
29115
|
}
|
|
28292
29116
|
return !processGroupExists(pgid);
|
|
28293
29117
|
}
|
|
@@ -28303,7 +29127,7 @@ function safeError(error) {
|
|
|
28303
29127
|
|
|
28304
29128
|
// ../memoh/packages/runtime/src/core/exec.ts
|
|
28305
29129
|
var import_grpc_js3 = __toESM(require_src3(), 1);
|
|
28306
|
-
import { spawn } from "node:child_process";
|
|
29130
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
28307
29131
|
import { constants as osConstants } from "node:os";
|
|
28308
29132
|
|
|
28309
29133
|
// ../memoh/packages/runtime/src/rpc.ts
|
|
@@ -28319,7 +29143,7 @@ function mapNodeError(error, operation) {
|
|
|
28319
29143
|
if (isServiceError(error)) {
|
|
28320
29144
|
return error;
|
|
28321
29145
|
}
|
|
28322
|
-
const code =
|
|
29146
|
+
const code = nodeErrorCode2(error);
|
|
28323
29147
|
switch (code) {
|
|
28324
29148
|
case "ENOENT":
|
|
28325
29149
|
return rpcError(import_grpc_js.status.NOT_FOUND, `${operation}: not found`);
|
|
@@ -28335,7 +29159,7 @@ function mapNodeError(error, operation) {
|
|
|
28335
29159
|
return rpcError(import_grpc_js.status.INTERNAL, `${operation} failed`);
|
|
28336
29160
|
}
|
|
28337
29161
|
}
|
|
28338
|
-
function
|
|
29162
|
+
function nodeErrorCode2(error) {
|
|
28339
29163
|
return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
28340
29164
|
}
|
|
28341
29165
|
function isServiceError(error) {
|
|
@@ -28577,7 +29401,7 @@ var WorkspaceExecService = class {
|
|
|
28577
29401
|
});
|
|
28578
29402
|
assertExecAdmissionActive(call, admissionActive);
|
|
28579
29403
|
const shell = shellSpawnSpec(command);
|
|
28580
|
-
const child =
|
|
29404
|
+
const child = spawn2(shell.command, shell.args, {
|
|
28581
29405
|
cwd: workDirectory,
|
|
28582
29406
|
env: environment,
|
|
28583
29407
|
detached: shell.detached,
|
|
@@ -28589,8 +29413,8 @@ var WorkspaceExecService = class {
|
|
|
28589
29413
|
const registration = this.children.register(child);
|
|
28590
29414
|
void registration.catch(() => void 0);
|
|
28591
29415
|
try {
|
|
28592
|
-
await new Promise((
|
|
28593
|
-
child.once("spawn",
|
|
29416
|
+
await new Promise((resolve5, reject) => {
|
|
29417
|
+
child.once("spawn", resolve5);
|
|
28594
29418
|
child.once("error", reject);
|
|
28595
29419
|
});
|
|
28596
29420
|
await registration;
|
|
@@ -28603,8 +29427,8 @@ var WorkspaceExecService = class {
|
|
|
28603
29427
|
throw rpcError(import_grpc_js3.status.CANCELLED, "exec was cancelled before process admission completed");
|
|
28604
29428
|
}
|
|
28605
29429
|
child.stdin.on("error", () => void 0);
|
|
28606
|
-
const closed = new Promise((
|
|
28607
|
-
child.once("close", (code, signal) =>
|
|
29430
|
+
const closed = new Promise((resolve5) => {
|
|
29431
|
+
child.once("close", (code, signal) => resolve5({ code, signal }));
|
|
28608
29432
|
});
|
|
28609
29433
|
const stdoutDone = pipeOutput(child.stdout, call, stdoutStream, () => void this.children.terminate(child));
|
|
28610
29434
|
const stderrDone = pipeOutput(child.stderr, call, stderrStream, () => void this.children.terminate(child));
|
|
@@ -28643,12 +29467,12 @@ function assertExecAdmissionActive(call, admissionActive) {
|
|
|
28643
29467
|
}
|
|
28644
29468
|
}
|
|
28645
29469
|
function pipeOutput(source, call, stream, onFailure) {
|
|
28646
|
-
return new Promise((
|
|
29470
|
+
return new Promise((resolve5) => {
|
|
28647
29471
|
let finished = false;
|
|
28648
29472
|
const finish = () => {
|
|
28649
29473
|
if (!finished) {
|
|
28650
29474
|
finished = true;
|
|
28651
|
-
|
|
29475
|
+
resolve5();
|
|
28652
29476
|
}
|
|
28653
29477
|
};
|
|
28654
29478
|
source.on("data", (chunk) => {
|
|
@@ -28718,19 +29542,19 @@ function scheduleLongTimeout(milliseconds, callback) {
|
|
|
28718
29542
|
|
|
28719
29543
|
// ../memoh/packages/runtime/src/core/fs.ts
|
|
28720
29544
|
var import_grpc_js4 = __toESM(require_src3(), 1);
|
|
28721
|
-
import { constants } from "node:fs";
|
|
29545
|
+
import { constants as constants3 } from "node:fs";
|
|
28722
29546
|
import { randomBytes } from "node:crypto";
|
|
28723
29547
|
import {
|
|
28724
|
-
lstat,
|
|
28725
|
-
open,
|
|
29548
|
+
lstat as lstat3,
|
|
29549
|
+
open as open2,
|
|
28726
29550
|
readdir,
|
|
28727
29551
|
rename as renamePath,
|
|
28728
|
-
rm,
|
|
29552
|
+
rm as rm6,
|
|
28729
29553
|
rmdir,
|
|
28730
|
-
stat,
|
|
29554
|
+
stat as stat2,
|
|
28731
29555
|
unlink
|
|
28732
29556
|
} from "node:fs/promises";
|
|
28733
|
-
import { basename, dirname, join, relative, sep } from "node:path";
|
|
29557
|
+
import { basename, dirname as dirname4, join as join5, relative, sep } from "node:path";
|
|
28734
29558
|
var binaryProbeBytes = 8 * 1024;
|
|
28735
29559
|
var readMaxLines = 2e3;
|
|
28736
29560
|
var listMaxEntries = 200;
|
|
@@ -28744,7 +29568,7 @@ var WorkspaceFileService = class {
|
|
|
28744
29568
|
const requested = requiredPath(request.path);
|
|
28745
29569
|
const target = await this.paths.resolve(requested);
|
|
28746
29570
|
await this.paths.revalidate(target);
|
|
28747
|
-
const handle = await openNoFollow(target,
|
|
29571
|
+
const handle = await openNoFollow(target, constants3.O_RDONLY, 0).catch((error) => {
|
|
28748
29572
|
throw mapNodeError(error, "open");
|
|
28749
29573
|
});
|
|
28750
29574
|
try {
|
|
@@ -28789,13 +29613,13 @@ var WorkspaceFileService = class {
|
|
|
28789
29613
|
async writeFile(request) {
|
|
28790
29614
|
const requested = requiredPath(request.path);
|
|
28791
29615
|
const target = await this.paths.prepareWrite(requested);
|
|
28792
|
-
const temporary =
|
|
28793
|
-
|
|
29616
|
+
const temporary = join5(
|
|
29617
|
+
dirname4(target),
|
|
28794
29618
|
`.${basename(target)}.tmp-${randomBytes(8).toString("hex")}`
|
|
28795
29619
|
);
|
|
28796
29620
|
const handle = await openNoFollow(
|
|
28797
29621
|
temporary,
|
|
28798
|
-
|
|
29622
|
+
constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL,
|
|
28799
29623
|
384
|
|
28800
29624
|
).catch((error) => {
|
|
28801
29625
|
throw mapNodeError(error, "open");
|
|
@@ -28809,7 +29633,7 @@ var WorkspaceFileService = class {
|
|
|
28809
29633
|
throw mapNodeError(error, "write");
|
|
28810
29634
|
} finally {
|
|
28811
29635
|
await handle.close().catch(() => void 0);
|
|
28812
|
-
await
|
|
29636
|
+
await rm6(temporary, { force: true }).catch(() => void 0);
|
|
28813
29637
|
}
|
|
28814
29638
|
return {};
|
|
28815
29639
|
}
|
|
@@ -28840,7 +29664,7 @@ var WorkspaceFileService = class {
|
|
|
28840
29664
|
const target = await this.paths.resolve(requiredPath(request.path));
|
|
28841
29665
|
await this.paths.revalidate(target);
|
|
28842
29666
|
try {
|
|
28843
|
-
const info = await
|
|
29667
|
+
const info = await stat2(target);
|
|
28844
29668
|
return { entry: fileEntry(basename(target), info) };
|
|
28845
29669
|
} catch (error) {
|
|
28846
29670
|
throw mapNodeError(error, "stat");
|
|
@@ -28870,7 +29694,7 @@ var WorkspaceFileService = class {
|
|
|
28870
29694
|
followFinalSymlink: false
|
|
28871
29695
|
});
|
|
28872
29696
|
try {
|
|
28873
|
-
const info = await
|
|
29697
|
+
const info = await lstat3(target);
|
|
28874
29698
|
if (info.isSymbolicLink()) {
|
|
28875
29699
|
await unlink(target);
|
|
28876
29700
|
return {};
|
|
@@ -28879,12 +29703,12 @@ var WorkspaceFileService = class {
|
|
|
28879
29703
|
if (info.isDirectory() && !request.recursive) {
|
|
28880
29704
|
await rmdir(target);
|
|
28881
29705
|
} else if (info.isDirectory()) {
|
|
28882
|
-
await
|
|
29706
|
+
await rm6(target, { recursive: true, force: true });
|
|
28883
29707
|
} else {
|
|
28884
29708
|
await unlink(target);
|
|
28885
29709
|
}
|
|
28886
29710
|
} catch (error) {
|
|
28887
|
-
if (
|
|
29711
|
+
if (nodeErrorCode2(error) !== "ENOENT" && !(isServiceError(error) && error.code === import_grpc_js4.status.NOT_FOUND)) {
|
|
28888
29712
|
throw mapNodeError(error, "delete");
|
|
28889
29713
|
}
|
|
28890
29714
|
}
|
|
@@ -28893,7 +29717,7 @@ var WorkspaceFileService = class {
|
|
|
28893
29717
|
async openReadRaw(requestedPath) {
|
|
28894
29718
|
const target = await this.paths.resolve(requiredPath(requestedPath));
|
|
28895
29719
|
await this.paths.revalidate(target);
|
|
28896
|
-
return openNoFollow(target,
|
|
29720
|
+
return openNoFollow(target, constants3.O_RDONLY, 0).catch((error) => {
|
|
28897
29721
|
throw mapNodeError(error, "open");
|
|
28898
29722
|
});
|
|
28899
29723
|
}
|
|
@@ -28902,7 +29726,7 @@ var WorkspaceFileService = class {
|
|
|
28902
29726
|
await this.paths.revalidate(target, { allowMissing: true });
|
|
28903
29727
|
return openNoFollow(
|
|
28904
29728
|
target,
|
|
28905
|
-
|
|
29729
|
+
constants3.O_WRONLY | constants3.O_CREAT | constants3.O_TRUNC,
|
|
28906
29730
|
384
|
|
28907
29731
|
).catch((error) => {
|
|
28908
29732
|
throw mapNodeError(error, "open");
|
|
@@ -28918,9 +29742,9 @@ var WorkspaceFileService = class {
|
|
|
28918
29742
|
children.sort((left, right) => compareGoFilenames(left.name, right.name));
|
|
28919
29743
|
const entries = [];
|
|
28920
29744
|
for (const child of children) {
|
|
28921
|
-
const target =
|
|
29745
|
+
const target = join5(directory, child.name);
|
|
28922
29746
|
try {
|
|
28923
|
-
const info = await
|
|
29747
|
+
const info = await lstat3(target);
|
|
28924
29748
|
entries.push(fileEntry(child.name, info));
|
|
28925
29749
|
} catch {
|
|
28926
29750
|
}
|
|
@@ -28938,9 +29762,9 @@ var WorkspaceFileService = class {
|
|
|
28938
29762
|
}
|
|
28939
29763
|
children.sort((left, right) => compareGoFilenames(left.name, right.name));
|
|
28940
29764
|
for (const child of children) {
|
|
28941
|
-
const target =
|
|
29765
|
+
const target = join5(current, child.name);
|
|
28942
29766
|
try {
|
|
28943
|
-
const info = await
|
|
29767
|
+
const info = await lstat3(target);
|
|
28944
29768
|
const name = relative(directory, target).split(sep).join("/");
|
|
28945
29769
|
entries.push(fileEntry(name, info));
|
|
28946
29770
|
if (info.isDirectory() && !info.isSymbolicLink()) {
|
|
@@ -28962,8 +29786,8 @@ function requiredPath(value, field = "path") {
|
|
|
28962
29786
|
return value;
|
|
28963
29787
|
}
|
|
28964
29788
|
function openNoFollow(path, flags, mode) {
|
|
28965
|
-
const noFollow = process.platform === "win32" ? 0 :
|
|
28966
|
-
return
|
|
29789
|
+
const noFollow = process.platform === "win32" ? 0 : constants3.O_NOFOLLOW;
|
|
29790
|
+
return open2(path, flags | noFollow, mode);
|
|
28967
29791
|
}
|
|
28968
29792
|
function fileEntry(path, info) {
|
|
28969
29793
|
return {
|
|
@@ -29033,15 +29857,15 @@ function formatMode(mode, directory = false, symbolicLink = false) {
|
|
|
29033
29857
|
prefix = "-";
|
|
29034
29858
|
}
|
|
29035
29859
|
const permissions = [
|
|
29036
|
-
[
|
|
29037
|
-
[
|
|
29038
|
-
[
|
|
29039
|
-
[
|
|
29040
|
-
[
|
|
29041
|
-
[
|
|
29042
|
-
[
|
|
29043
|
-
[
|
|
29044
|
-
[
|
|
29860
|
+
[constants3.S_IRUSR, "r"],
|
|
29861
|
+
[constants3.S_IWUSR, "w"],
|
|
29862
|
+
[constants3.S_IXUSR, "x"],
|
|
29863
|
+
[constants3.S_IRGRP, "r"],
|
|
29864
|
+
[constants3.S_IWGRP, "w"],
|
|
29865
|
+
[constants3.S_IXGRP, "x"],
|
|
29866
|
+
[constants3.S_IROTH, "r"],
|
|
29867
|
+
[constants3.S_IWOTH, "w"],
|
|
29868
|
+
[constants3.S_IXOTH, "x"]
|
|
29045
29869
|
];
|
|
29046
29870
|
return prefix + permissions.map(([bit, value]) => mode & bit ? value : "-").join("");
|
|
29047
29871
|
}
|
|
@@ -29119,20 +29943,20 @@ function decodeLine(line) {
|
|
|
29119
29943
|
|
|
29120
29944
|
// ../memoh/packages/runtime/src/core/paths.ts
|
|
29121
29945
|
var import_grpc_js5 = __toESM(require_src3(), 1);
|
|
29122
|
-
import { constants as
|
|
29123
|
-
import { access, lstat as
|
|
29124
|
-
import { dirname as
|
|
29946
|
+
import { constants as constants4 } from "node:fs";
|
|
29947
|
+
import { access as access3, lstat as lstat4, mkdir as mkdir3, realpath as realpath2, stat as stat3 } from "node:fs/promises";
|
|
29948
|
+
import { dirname as dirname5, isAbsolute as isAbsolute3, resolve as resolve3, sep as sep2 } from "node:path";
|
|
29125
29949
|
var HostPathResolver = class _HostPathResolver {
|
|
29126
29950
|
defaultDirectory;
|
|
29127
29951
|
constructor(defaultDirectory) {
|
|
29128
29952
|
this.defaultDirectory = defaultDirectory;
|
|
29129
29953
|
}
|
|
29130
29954
|
static async create(defaultDirectory) {
|
|
29131
|
-
if (!defaultDirectory.trim() || !
|
|
29955
|
+
if (!defaultDirectory.trim() || !isAbsolute3(defaultDirectory)) {
|
|
29132
29956
|
throw new Error("default directory must be an absolute path");
|
|
29133
29957
|
}
|
|
29134
|
-
const canonical = await
|
|
29135
|
-
const info = await
|
|
29958
|
+
const canonical = await realpath2(resolve3(defaultDirectory));
|
|
29959
|
+
const info = await stat3(canonical);
|
|
29136
29960
|
if (!info.isDirectory()) {
|
|
29137
29961
|
throw new Error("default directory must be a directory");
|
|
29138
29962
|
}
|
|
@@ -29151,20 +29975,20 @@ var HostPathResolver = class _HostPathResolver {
|
|
|
29151
29975
|
if (missingSegments.length > 0 && !options.allowMissing) {
|
|
29152
29976
|
throw rpcError(import_grpc_js5.status.NOT_FOUND, "path does not exist");
|
|
29153
29977
|
}
|
|
29154
|
-
let canonicalAncestor = await
|
|
29978
|
+
let canonicalAncestor = await realpath2(ancestor).catch((error) => {
|
|
29155
29979
|
throw mapNodeError(error, "realpath");
|
|
29156
29980
|
});
|
|
29157
29981
|
if (missingSegments.length === 0 && options.followFinalSymlink === false) {
|
|
29158
|
-
const info = await
|
|
29982
|
+
const info = await lstat4(candidate).catch((error) => {
|
|
29159
29983
|
throw mapNodeError(error, "lstat");
|
|
29160
29984
|
});
|
|
29161
29985
|
if (info.isSymbolicLink()) {
|
|
29162
29986
|
canonicalAncestor = candidate;
|
|
29163
29987
|
}
|
|
29164
29988
|
}
|
|
29165
|
-
const resolvedPath =
|
|
29989
|
+
const resolvedPath = resolve3(canonicalAncestor, ...missingSegments);
|
|
29166
29990
|
if (missingSegments.length === 0) {
|
|
29167
|
-
const target = await
|
|
29991
|
+
const target = await stat3(resolvedPath).catch((error) => {
|
|
29168
29992
|
throw mapNodeError(error, "stat");
|
|
29169
29993
|
});
|
|
29170
29994
|
if (options.requireDirectory && !target.isDirectory()) {
|
|
@@ -29179,7 +30003,7 @@ var HostPathResolver = class _HostPathResolver {
|
|
|
29179
30003
|
}
|
|
29180
30004
|
async prepareWrite(requestedPath) {
|
|
29181
30005
|
const initial = await this.resolve(requestedPath, { allowMissing: true });
|
|
29182
|
-
await this.ensureDirectory(
|
|
30006
|
+
await this.ensureDirectory(dirname5(initial));
|
|
29183
30007
|
const checked = await this.resolve(initial, { allowMissing: true });
|
|
29184
30008
|
if (checked !== initial) {
|
|
29185
30009
|
throw rpcError(import_grpc_js5.status.PERMISSION_DENIED, "path changed while it was being checked");
|
|
@@ -29196,9 +30020,9 @@ var HostPathResolver = class _HostPathResolver {
|
|
|
29196
30020
|
async ensureDirectory(requestedPath) {
|
|
29197
30021
|
const target = await this.resolve(requestedPath, { allowMissing: true });
|
|
29198
30022
|
try {
|
|
29199
|
-
await
|
|
30023
|
+
await mkdir3(target, { recursive: true, mode: 488 });
|
|
29200
30024
|
} catch (error) {
|
|
29201
|
-
if (
|
|
30025
|
+
if (nodeErrorCode2(error) !== "EEXIST") {
|
|
29202
30026
|
throw mapNodeError(error, "mkdir");
|
|
29203
30027
|
}
|
|
29204
30028
|
}
|
|
@@ -29210,15 +30034,15 @@ var HostPathResolver = class _HostPathResolver {
|
|
|
29210
30034
|
return this.defaultDirectory;
|
|
29211
30035
|
}
|
|
29212
30036
|
if (bridgePath.startsWith("~/")) {
|
|
29213
|
-
return
|
|
30037
|
+
return resolve3(this.defaultDirectory, bridgePath.slice(2));
|
|
29214
30038
|
}
|
|
29215
30039
|
if (bridgePath.startsWith("/data/")) {
|
|
29216
|
-
return
|
|
30040
|
+
return resolve3(this.defaultDirectory, bridgePath.slice("/data/".length));
|
|
29217
30041
|
}
|
|
29218
|
-
if (
|
|
29219
|
-
return
|
|
30042
|
+
if (isAbsolute3(value)) {
|
|
30043
|
+
return resolve3(value);
|
|
29220
30044
|
}
|
|
29221
|
-
return
|
|
30045
|
+
return resolve3(this.defaultDirectory, value);
|
|
29222
30046
|
}
|
|
29223
30047
|
};
|
|
29224
30048
|
async function nearestExistingAncestor(candidate) {
|
|
@@ -29226,13 +30050,13 @@ async function nearestExistingAncestor(candidate) {
|
|
|
29226
30050
|
let current = candidate;
|
|
29227
30051
|
for (; ; ) {
|
|
29228
30052
|
try {
|
|
29229
|
-
await
|
|
30053
|
+
await access3(current, constants4.F_OK);
|
|
29230
30054
|
return { ancestor: current, missingSegments };
|
|
29231
30055
|
} catch (error) {
|
|
29232
|
-
if (
|
|
30056
|
+
if (nodeErrorCode2(error) !== "ENOENT" && nodeErrorCode2(error) !== "ENOTDIR") {
|
|
29233
30057
|
throw mapNodeError(error, "access");
|
|
29234
30058
|
}
|
|
29235
|
-
const parent =
|
|
30059
|
+
const parent = dirname5(current);
|
|
29236
30060
|
if (parent === current) {
|
|
29237
30061
|
throw mapNodeError(error, "access");
|
|
29238
30062
|
}
|
|
@@ -29284,15 +30108,15 @@ async function startRuntimeGrpcServer(options) {
|
|
|
29284
30108
|
}
|
|
29285
30109
|
connections.clear();
|
|
29286
30110
|
await children.close();
|
|
29287
|
-
await new Promise((
|
|
30111
|
+
await new Promise((resolve5) => {
|
|
29288
30112
|
const timer = setTimeout(() => {
|
|
29289
30113
|
server.forceShutdown();
|
|
29290
|
-
|
|
30114
|
+
resolve5();
|
|
29291
30115
|
}, 2e3);
|
|
29292
30116
|
timer.unref();
|
|
29293
30117
|
server.tryShutdown(() => {
|
|
29294
30118
|
clearTimeout(timer);
|
|
29295
|
-
|
|
30119
|
+
resolve5();
|
|
29296
30120
|
});
|
|
29297
30121
|
});
|
|
29298
30122
|
})();
|
|
@@ -29470,14 +30294,14 @@ function waitForDrainOrCancellation(call) {
|
|
|
29470
30294
|
if (call.cancelled) {
|
|
29471
30295
|
return Promise.resolve();
|
|
29472
30296
|
}
|
|
29473
|
-
return new Promise((
|
|
30297
|
+
return new Promise((resolve5) => {
|
|
29474
30298
|
let settled = false;
|
|
29475
30299
|
const finish = () => {
|
|
29476
30300
|
if (!settled) {
|
|
29477
30301
|
settled = true;
|
|
29478
30302
|
call.off("drain", onDrain);
|
|
29479
30303
|
call.off("cancelled", onCancelled);
|
|
29480
|
-
|
|
30304
|
+
resolve5();
|
|
29481
30305
|
}
|
|
29482
30306
|
};
|
|
29483
30307
|
const onDrain = () => finish();
|
|
@@ -29503,7 +30327,7 @@ async function locateBridgeProto() {
|
|
|
29503
30327
|
];
|
|
29504
30328
|
for (const candidate of candidates) {
|
|
29505
30329
|
try {
|
|
29506
|
-
await
|
|
30330
|
+
await access4(candidate);
|
|
29507
30331
|
return candidate;
|
|
29508
30332
|
} catch {
|
|
29509
30333
|
}
|
|
@@ -29514,10 +30338,10 @@ async function locateBridgeProto() {
|
|
|
29514
30338
|
// ../memoh/packages/runtime/package.json
|
|
29515
30339
|
var package_default = {
|
|
29516
30340
|
name: "@memohai/runtime",
|
|
29517
|
-
version: "0.
|
|
30341
|
+
version: "0.19.0",
|
|
29518
30342
|
repository: {
|
|
29519
30343
|
type: "git",
|
|
29520
|
-
url: "git+https://github.com/
|
|
30344
|
+
url: "git+https://github.com/felinics/Memoh.git",
|
|
29521
30345
|
directory: "packages/runtime"
|
|
29522
30346
|
},
|
|
29523
30347
|
description: "Embeddable Memoh Remote Runtime SDK and CLI",
|
|
@@ -29565,33 +30389,6 @@ var runtimeTeamIDHeader = "X-Team-ID";
|
|
|
29565
30389
|
var runtimeMetadataMaxBytes = 8 * 1024;
|
|
29566
30390
|
var runtimeHandshakeErrorMaxBytes = 8 * 1024;
|
|
29567
30391
|
var runtimeHandshakeErrorReadTimeoutMs = 2e3;
|
|
29568
|
-
function runtimeConnectUrl(serverUrl) {
|
|
29569
|
-
const url = new URL(serverUrl);
|
|
29570
|
-
if (url.protocol === "http:") {
|
|
29571
|
-
url.protocol = "ws:";
|
|
29572
|
-
} else if (url.protocol === "https:") {
|
|
29573
|
-
url.protocol = "wss:";
|
|
29574
|
-
}
|
|
29575
|
-
const basePath = url.pathname.replace(/\/+$/, "");
|
|
29576
|
-
url.pathname = `${basePath}/runtimes/connect`;
|
|
29577
|
-
url.search = "";
|
|
29578
|
-
url.hash = "";
|
|
29579
|
-
return url;
|
|
29580
|
-
}
|
|
29581
|
-
function assertSecureRuntimeUrl(url, insecureLocalhost = false) {
|
|
29582
|
-
if (url.username || url.password) {
|
|
29583
|
-
throw new Error("runtime connection URL must not contain credentials");
|
|
29584
|
-
}
|
|
29585
|
-
if (url.protocol === "wss:") {
|
|
29586
|
-
return;
|
|
29587
|
-
}
|
|
29588
|
-
const hostname2 = url.hostname.replace(/^\[|\]$/g, "");
|
|
29589
|
-
const local = hostname2 === "127.0.0.1" || hostname2 === "localhost" || hostname2 === "::1";
|
|
29590
|
-
if (url.protocol === "ws:" && insecureLocalhost && local) {
|
|
29591
|
-
return;
|
|
29592
|
-
}
|
|
29593
|
-
throw new Error("runtime connections require wss://; use --insecure-localhost only for localhost development");
|
|
29594
|
-
}
|
|
29595
30392
|
function createHandshakeMetadata(workspaceBase, version = runtimeClientVersion, machine = {
|
|
29596
30393
|
hostname: hostname(),
|
|
29597
30394
|
os: platform(),
|
|
@@ -29665,7 +30462,7 @@ var RuntimeSession = class {
|
|
|
29665
30462
|
try {
|
|
29666
30463
|
const url = runtimeConnectUrl(this.config.serverUrl);
|
|
29667
30464
|
assertSecureRuntimeUrl(url, this.config.insecureLocalhost);
|
|
29668
|
-
const workspaceBase = await
|
|
30465
|
+
const workspaceBase = await realpath3(this.config.workspaceBase);
|
|
29669
30466
|
let retry = 1e3;
|
|
29670
30467
|
let lastError;
|
|
29671
30468
|
while (!this.stopped && !controller.signal.aborted) {
|
|
@@ -29750,7 +30547,7 @@ var RuntimeSession = class {
|
|
|
29750
30547
|
}
|
|
29751
30548
|
};
|
|
29752
30549
|
function waitForOpen(websocket) {
|
|
29753
|
-
return new Promise((
|
|
30550
|
+
return new Promise((resolve5, reject) => {
|
|
29754
30551
|
const cleanup = () => {
|
|
29755
30552
|
websocket.off("open", onOpen);
|
|
29756
30553
|
websocket.off("error", onError);
|
|
@@ -29759,7 +30556,7 @@ function waitForOpen(websocket) {
|
|
|
29759
30556
|
};
|
|
29760
30557
|
const onOpen = () => {
|
|
29761
30558
|
cleanup();
|
|
29762
|
-
|
|
30559
|
+
resolve5();
|
|
29763
30560
|
};
|
|
29764
30561
|
const onError = (error) => {
|
|
29765
30562
|
cleanup();
|
|
@@ -29783,7 +30580,7 @@ function waitForOpen(websocket) {
|
|
|
29783
30580
|
});
|
|
29784
30581
|
}
|
|
29785
30582
|
function readHandshakeError(response) {
|
|
29786
|
-
return new Promise((
|
|
30583
|
+
return new Promise((resolve5) => {
|
|
29787
30584
|
const chunks = [];
|
|
29788
30585
|
let size = 0;
|
|
29789
30586
|
let settled = false;
|
|
@@ -29800,7 +30597,7 @@ function readHandshakeError(response) {
|
|
|
29800
30597
|
settled = true;
|
|
29801
30598
|
cleanup();
|
|
29802
30599
|
response.resume();
|
|
29803
|
-
|
|
30600
|
+
resolve5(
|
|
29804
30601
|
Buffer.concat(chunks).toString("utf8").replace(/\s+/g, " ").trim()
|
|
29805
30602
|
);
|
|
29806
30603
|
};
|
|
@@ -29853,10 +30650,10 @@ function abortableDelay(milliseconds, signal) {
|
|
|
29853
30650
|
if (signal?.aborted) {
|
|
29854
30651
|
return Promise.resolve();
|
|
29855
30652
|
}
|
|
29856
|
-
return new Promise((
|
|
30653
|
+
return new Promise((resolve5) => {
|
|
29857
30654
|
const finish = () => {
|
|
29858
30655
|
signal?.removeEventListener("abort", onAbort);
|
|
29859
|
-
|
|
30656
|
+
resolve5();
|
|
29860
30657
|
};
|
|
29861
30658
|
const timer = setTimeout(finish, milliseconds);
|
|
29862
30659
|
const onAbort = () => {
|
|
@@ -29878,60 +30675,223 @@ function sanitizeError(error, key) {
|
|
|
29878
30675
|
return message.replaceAll(key, "<redacted>").replace(/mrk_[0-9a-f]{64}/g, "<redacted>").slice(0, 1024);
|
|
29879
30676
|
}
|
|
29880
30677
|
|
|
29881
|
-
// ../memoh/packages/runtime/src/cli.ts
|
|
29882
|
-
|
|
29883
|
-
|
|
29884
|
-
|
|
30678
|
+
// ../memoh/packages/runtime/src/cli-main.ts
|
|
30679
|
+
var connectionOptions = {
|
|
30680
|
+
server: { type: "string" },
|
|
30681
|
+
key: { type: "string" },
|
|
30682
|
+
"team-id": { type: "string" },
|
|
30683
|
+
config: { type: "string" },
|
|
30684
|
+
"insecure-localhost": { type: "boolean" },
|
|
30685
|
+
help: { type: "boolean", short: "h" }
|
|
30686
|
+
};
|
|
30687
|
+
async function runCLI(args2, overrides = {}) {
|
|
30688
|
+
const entryPath = overrides.entryPath ?? fileURLToPath2(import.meta.url);
|
|
30689
|
+
const context = {
|
|
30690
|
+
platform: process.platform,
|
|
30691
|
+
env: process.env,
|
|
30692
|
+
home: homedir2(),
|
|
30693
|
+
entryPath,
|
|
30694
|
+
uid: process.getuid?.(),
|
|
30695
|
+
runner: spawnCommand,
|
|
30696
|
+
createSession: (config, options) => new RuntimeSession(config, options),
|
|
30697
|
+
stdout: (message) => console.log(message),
|
|
30698
|
+
stderr: (message) => console.error(message),
|
|
30699
|
+
...overrides
|
|
30700
|
+
};
|
|
30701
|
+
const [command, ...rest] = args2;
|
|
30702
|
+
if (["help", "--help", "-h"].includes(command)) {
|
|
30703
|
+
context.stdout("Usage: memoh-runtime <enroll|run|service|version>\nUse <command> --help for details.");
|
|
30704
|
+
return 0;
|
|
29885
30705
|
}
|
|
29886
|
-
if (
|
|
29887
|
-
|
|
30706
|
+
if (command === "version" || command === "--version") {
|
|
30707
|
+
context.stdout(runtimeClientVersion);
|
|
30708
|
+
return 0;
|
|
29888
30709
|
}
|
|
29889
|
-
|
|
29890
|
-
|
|
29891
|
-
|
|
29892
|
-
if (!
|
|
29893
|
-
|
|
30710
|
+
if (command === "enroll") return enroll(rest, context);
|
|
30711
|
+
if (command === "service") return service(rest, context);
|
|
30712
|
+
if (command === "run") return run(rest, context);
|
|
30713
|
+
if (!command || command.startsWith("-")) return run(args2, context);
|
|
30714
|
+
throw new Error(`unknown command: ${command}`);
|
|
30715
|
+
}
|
|
30716
|
+
async function run(args2, context) {
|
|
30717
|
+
const { values } = parseArgs({ args: args2, options: { ...connectionOptions, log: { type: "string" } }, strict: true });
|
|
30718
|
+
if (values.help) {
|
|
30719
|
+
context.stdout("Usage: memoh-runtime run [--server <url> --key <key> | --config <file>] [--log <file>]\nReads saved enrollment when no connection is supplied. Never saves or changes a service.");
|
|
30720
|
+
return 0;
|
|
29894
30721
|
}
|
|
29895
|
-
const
|
|
30722
|
+
const log = createLogFile(stringValue(values.log), context.stderr);
|
|
29896
30723
|
const controller = new AbortController();
|
|
29897
30724
|
const stop = () => controller.abort();
|
|
29898
30725
|
process.once("SIGINT", stop);
|
|
29899
30726
|
process.once("SIGTERM", stop);
|
|
29900
30727
|
try {
|
|
29901
|
-
const
|
|
29902
|
-
|
|
29903
|
-
|
|
29904
|
-
|
|
29905
|
-
|
|
29906
|
-
|
|
29907
|
-
|
|
29908
|
-
|
|
29909
|
-
|
|
29910
|
-
|
|
29911
|
-
|
|
30728
|
+
const enrollment = await resolveEnrollment(values, context);
|
|
30729
|
+
await context.createSession({ ...enrollment, workspaceBase: context.home }, {
|
|
30730
|
+
onStatus: (status7, error) => {
|
|
30731
|
+
const line = error ? `${status7}: ${error}` : status7;
|
|
30732
|
+
context.stdout(line);
|
|
30733
|
+
log.write(line);
|
|
30734
|
+
},
|
|
30735
|
+
warn: (message) => {
|
|
30736
|
+
context.stderr(message);
|
|
30737
|
+
log.write(message);
|
|
30738
|
+
}
|
|
30739
|
+
}).start(controller.signal);
|
|
30740
|
+
} catch (error) {
|
|
30741
|
+
log.write(`error: ${formatCLIError(error)}`);
|
|
30742
|
+
throw error;
|
|
29912
30743
|
} finally {
|
|
29913
30744
|
process.off("SIGINT", stop);
|
|
29914
30745
|
process.off("SIGTERM", stop);
|
|
30746
|
+
await log.flush();
|
|
30747
|
+
}
|
|
30748
|
+
return 0;
|
|
30749
|
+
}
|
|
30750
|
+
function createLogFile(path, warn) {
|
|
30751
|
+
let queue = Promise.resolve();
|
|
30752
|
+
let reported = false;
|
|
30753
|
+
return {
|
|
30754
|
+
write(line) {
|
|
30755
|
+
if (!path) return;
|
|
30756
|
+
queue = queue.then(async () => {
|
|
30757
|
+
try {
|
|
30758
|
+
await mkdir4(dirname6(path), { recursive: true, mode: 448 });
|
|
30759
|
+
await appendFile(path, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
30760
|
+
`, { mode: 384 });
|
|
30761
|
+
} catch (error) {
|
|
30762
|
+
if (!reported) {
|
|
30763
|
+
reported = true;
|
|
30764
|
+
warn(`could not write log file ${path}: ${formatCLIError(error)}`);
|
|
30765
|
+
}
|
|
30766
|
+
}
|
|
30767
|
+
});
|
|
30768
|
+
},
|
|
30769
|
+
flush: () => queue
|
|
30770
|
+
};
|
|
30771
|
+
}
|
|
30772
|
+
async function enroll(args2, context) {
|
|
30773
|
+
const { values } = parseArgs({ args: args2, strict: true, options: { ...connectionOptions, replace: { type: "boolean" } } });
|
|
30774
|
+
if (values.help) {
|
|
30775
|
+
context.stdout("Usage: memoh-runtime enroll [--server <url> --key <key> | --config <file>] [--replace]\nSaves the enrollment used by future runs. A running service changes only after an explicit restart.");
|
|
30776
|
+
return 0;
|
|
29915
30777
|
}
|
|
30778
|
+
assertManagedPaths(context);
|
|
30779
|
+
const paths = resolveRuntimePaths({ home: context.home });
|
|
30780
|
+
const enrollment = await resolveEnrollment(values, context);
|
|
30781
|
+
await withEnrollmentLock(paths.configPath, async () => {
|
|
30782
|
+
if (!values.replace) {
|
|
30783
|
+
let current;
|
|
30784
|
+
try {
|
|
30785
|
+
current = await readRuntimeEnrollmentIfExists(paths.configPath, context.home);
|
|
30786
|
+
} catch (error) {
|
|
30787
|
+
throw new Error(`${formatCLIError(error)}; pass --replace to overwrite it`);
|
|
30788
|
+
}
|
|
30789
|
+
if (current && !sameEnrollment(current, enrollment)) throw new Error("saved enrollment differs; pass --replace to replace it");
|
|
30790
|
+
}
|
|
30791
|
+
await writeRuntimeEnrollment(paths.configPath, enrollment);
|
|
30792
|
+
});
|
|
30793
|
+
context.stdout(`saved enrollment to ${paths.configPath}; restart a running service to apply it`);
|
|
30794
|
+
return 0;
|
|
29916
30795
|
}
|
|
29917
|
-
function
|
|
29918
|
-
const
|
|
29919
|
-
if (
|
|
29920
|
-
|
|
30796
|
+
async function service(args2, context) {
|
|
30797
|
+
const [action, ...rest] = args2;
|
|
30798
|
+
if (!action || ["help", "--help", "-h"].includes(action)) {
|
|
30799
|
+
context.stdout("Usage: memoh-runtime service <install|start|stop|restart|status|uninstall>\nInstall registers a stopped service. Enrollment is managed separately with enroll.");
|
|
30800
|
+
return 0;
|
|
29921
30801
|
}
|
|
29922
|
-
|
|
29923
|
-
|
|
29924
|
-
|
|
30802
|
+
if (!["install", "start", "stop", "restart", "status", "uninstall"].includes(action)) throw new Error(`unknown service command: ${action}`);
|
|
30803
|
+
const { values } = parseArgs({ args: rest, strict: true, options: {
|
|
30804
|
+
help: { type: "boolean", short: "h" },
|
|
30805
|
+
...action === "status" ? { json: { type: "boolean" } } : {}
|
|
30806
|
+
} });
|
|
30807
|
+
if (values.help) {
|
|
30808
|
+
context.stdout(`Usage: memoh-runtime service ${action}${action === "status" ? " [--json]" : ""}`);
|
|
30809
|
+
return 0;
|
|
29925
30810
|
}
|
|
29926
|
-
|
|
30811
|
+
assertManagedPaths(context);
|
|
30812
|
+
const paths = resolveRuntimePaths({ home: context.home });
|
|
30813
|
+
const manager = createRuntimeServiceManager({ platform: context.platform, paths, runner: context.runner, uid: context.uid });
|
|
30814
|
+
if (action === "status") {
|
|
30815
|
+
const status7 = await manager.status();
|
|
30816
|
+
context.stdout(values.json ? JSON.stringify(status7) : `Memoh Runtime service: ${status7.state} (${status7.backend})${status7.detail ? `: ${status7.detail}` : ""}`);
|
|
30817
|
+
return status7.state === "running" ? 0 : 1;
|
|
30818
|
+
}
|
|
30819
|
+
switch (action) {
|
|
30820
|
+
case "install": {
|
|
30821
|
+
const nodePath = await findNodeExecutable(context.env.PATH, context.platform);
|
|
30822
|
+
await access5(context.entryPath);
|
|
30823
|
+
await access5(join6(dirname6(context.entryPath), "bridge.proto"));
|
|
30824
|
+
await manager.stop();
|
|
30825
|
+
await waitForService(manager, "stopped");
|
|
30826
|
+
await manager.register({
|
|
30827
|
+
nodePath,
|
|
30828
|
+
entryPath: context.entryPath,
|
|
30829
|
+
configPath: paths.configPath,
|
|
30830
|
+
logsDir: paths.logsDir,
|
|
30831
|
+
workingDirectory: context.home,
|
|
30832
|
+
servicePath: serviceExecutablePath(nodePath, context.env.PATH, context.platform)
|
|
30833
|
+
});
|
|
30834
|
+
break;
|
|
30835
|
+
}
|
|
30836
|
+
case "stop":
|
|
30837
|
+
await manager.stop();
|
|
30838
|
+
await waitForService(manager, "stopped");
|
|
30839
|
+
break;
|
|
30840
|
+
case "uninstall":
|
|
30841
|
+
await manager.uninstall();
|
|
30842
|
+
await waitForService(manager, "not-installed");
|
|
30843
|
+
break;
|
|
30844
|
+
case "start":
|
|
30845
|
+
case "restart":
|
|
30846
|
+
await readRuntimeEnrollment(paths.configPath, context.home);
|
|
30847
|
+
if (action === "restart") {
|
|
30848
|
+
await manager.stop();
|
|
30849
|
+
await waitForService(manager, "stopped");
|
|
30850
|
+
}
|
|
30851
|
+
await manager.start();
|
|
30852
|
+
await waitForService(manager, "running");
|
|
30853
|
+
break;
|
|
30854
|
+
}
|
|
30855
|
+
context.stdout(action === "install" ? "installed Memoh Runtime service (stopped); run service start to connect" : action === "uninstall" ? "uninstalled Memoh Runtime service; saved enrollment was retained" : action === "stop" ? "stopped Memoh Runtime service; it starts again at the next login unless you run service uninstall" : `${action === "restart" ? "restarted" : "started"} Memoh Runtime service`);
|
|
30856
|
+
return 0;
|
|
30857
|
+
}
|
|
30858
|
+
async function resolveEnrollment(values, context) {
|
|
30859
|
+
const explicitConfig = stringValue(values.config);
|
|
30860
|
+
if (explicitConfig) {
|
|
30861
|
+
if (["server", "key", "team-id", "insecure-localhost"].some((key2) => values[key2] !== void 0)) throw new Error("--config cannot be combined with connection flags");
|
|
30862
|
+
return readRuntimeEnrollment(resolve4(explicitConfig), context.home);
|
|
30863
|
+
}
|
|
30864
|
+
const serverUrl = stringValue(values.server) ?? context.env.MEMOH_RUNTIME_SERVER;
|
|
30865
|
+
const key = stringValue(values.key) ?? context.env.MEMOH_RUNTIME_KEY;
|
|
30866
|
+
if (serverUrl || key) {
|
|
30867
|
+
if (!serverUrl || !key) throw new Error("--server and --key must be provided together");
|
|
30868
|
+
return normalizeRuntimeEnrollment({
|
|
30869
|
+
serverUrl,
|
|
30870
|
+
key,
|
|
30871
|
+
teamId: stringValue(values["team-id"]) ?? context.env.MEMOH_RUNTIME_TEAM_ID,
|
|
30872
|
+
insecureLocalhost: values["insecure-localhost"] === true || parseBooleanEnvironment(context.env.MEMOH_RUNTIME_INSECURE_LOCALHOST, "MEMOH_RUNTIME_INSECURE_LOCALHOST") === true
|
|
30873
|
+
}, context.home);
|
|
30874
|
+
}
|
|
30875
|
+
if (["team-id", "insecure-localhost"].some((key2) => values[key2] !== void 0)) throw new Error("connection options require --server and --key");
|
|
30876
|
+
const input = context.env.MEMOH_RUNTIME_CONFIG ?? resolveRuntimePaths({ home: context.home }).configPath;
|
|
30877
|
+
return readRuntimeEnrollment(resolve4(input), context.home);
|
|
30878
|
+
}
|
|
30879
|
+
function assertManagedPaths(context) {
|
|
30880
|
+
if (context.env.MEMOH_RUNTIME_HOME) throw new Error("MEMOH_RUNTIME_HOME is not supported for managed enrollment or services; use the fixed user runtime directory");
|
|
30881
|
+
}
|
|
30882
|
+
function stringValue(value) {
|
|
30883
|
+
return typeof value === "string" ? value : void 0;
|
|
29927
30884
|
}
|
|
29928
|
-
function
|
|
29929
|
-
|
|
29930
|
-
process.exit(exitCode);
|
|
30885
|
+
function formatCLIError(error) {
|
|
30886
|
+
return error instanceof Error ? error.message : String(error);
|
|
29931
30887
|
}
|
|
29932
|
-
|
|
29933
|
-
|
|
29934
|
-
|
|
30888
|
+
|
|
30889
|
+
// ../memoh/packages/runtime/src/cli.ts
|
|
30890
|
+
runCLI(process.argv.slice(2)).then((code) => {
|
|
30891
|
+
process.exitCode = code;
|
|
30892
|
+
}).catch((error) => {
|
|
30893
|
+
console.error(formatCLIError(error));
|
|
30894
|
+
process.exitCode = 1;
|
|
29935
30895
|
});
|
|
29936
30896
|
/*! Bundled license information:
|
|
29937
30897
|
|