@hermespilot/link 0.7.5 → 0.7.6
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.
|
@@ -2314,6 +2314,9 @@ function resolveHermesProfilesDir() {
|
|
|
2314
2314
|
function resolveHermesConfigPath(profileName = "default") {
|
|
2315
2315
|
return path3.join(resolveHermesProfileDir(profileName), "config.yaml");
|
|
2316
2316
|
}
|
|
2317
|
+
function resolveHermesEnvPath(profileName = "default") {
|
|
2318
|
+
return path3.join(resolveHermesProfileDir(profileName), ".env");
|
|
2319
|
+
}
|
|
2317
2320
|
async function readHermesSessionsDir(profileName = "default", configPath = resolveHermesConfigPath(profileName)) {
|
|
2318
2321
|
const profileDir = resolveHermesProfileDir(profileName);
|
|
2319
2322
|
const { config } = await readHermesConfigDocument(configPath);
|
|
@@ -2946,7 +2949,9 @@ async function readHermesProfilePermissions(profileName = "default", configPath
|
|
|
2946
2949
|
}
|
|
2947
2950
|
async function saveHermesProfilePermissions(profileName, input, configPath = resolveHermesConfigPath(profileName)) {
|
|
2948
2951
|
const { document, config, existingRaw } = await readHermesConfigDocument(configPath);
|
|
2952
|
+
let configTouched = false;
|
|
2949
2953
|
if (input.approvals) {
|
|
2954
|
+
configTouched = true;
|
|
2950
2955
|
const approvals = ensureRecord(config, "approvals");
|
|
2951
2956
|
if (input.approvals.mode !== void 0) {
|
|
2952
2957
|
approvals.mode = normalizeApprovalMode(input.approvals.mode);
|
|
@@ -2962,6 +2967,7 @@ async function saveHermesProfilePermissions(profileName, input, configPath = res
|
|
|
2962
2967
|
}
|
|
2963
2968
|
}
|
|
2964
2969
|
if (input.terminal) {
|
|
2970
|
+
configTouched = true;
|
|
2965
2971
|
const terminal = ensureRecord(config, "terminal");
|
|
2966
2972
|
if (input.terminal.backend !== void 0) {
|
|
2967
2973
|
terminal.backend = normalizeTerminalBackend(input.terminal.backend);
|
|
@@ -2991,7 +2997,24 @@ async function saveHermesProfilePermissions(profileName, input, configPath = res
|
|
|
2991
2997
|
terminal.container_persistent = input.terminal.containerPersistent;
|
|
2992
2998
|
}
|
|
2993
2999
|
}
|
|
3000
|
+
let envChanged = false;
|
|
3001
|
+
if (input.sudo) {
|
|
3002
|
+
if (input.sudo.clear) {
|
|
3003
|
+
envChanged = await deleteHermesEnvValue(profileName, "SUDO_PASSWORD") || envChanged;
|
|
3004
|
+
const terminal = toRecord(config.terminal);
|
|
3005
|
+
if (terminal.sudo_password !== void 0) {
|
|
3006
|
+
delete terminal.sudo_password;
|
|
3007
|
+
configTouched = true;
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
if (input.sudo.password !== void 0) {
|
|
3011
|
+
const password = normalizeSudoPassword(input.sudo.password);
|
|
3012
|
+
await writeHermesEnvValue(profileName, "SUDO_PASSWORD", password);
|
|
3013
|
+
envChanged = true;
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
2994
3016
|
if (input.toolsets) {
|
|
3017
|
+
configTouched = true;
|
|
2995
3018
|
const env = await readHermesEnvFile(profileName);
|
|
2996
3019
|
const currentPermissions = profilePermissionsFromConfig(
|
|
2997
3020
|
profileName,
|
|
@@ -3019,16 +3042,16 @@ async function saveHermesProfilePermissions(profileName, input, configPath = res
|
|
|
3019
3042
|
}
|
|
3020
3043
|
platformToolsets.api_server = next;
|
|
3021
3044
|
}
|
|
3022
|
-
const backupPath = await writeHermesConfigDocument({
|
|
3045
|
+
const backupPath = configTouched ? await writeHermesConfigDocument({
|
|
3023
3046
|
configPath,
|
|
3024
3047
|
document,
|
|
3025
3048
|
config,
|
|
3026
3049
|
existingRaw
|
|
3027
|
-
});
|
|
3050
|
+
}) : null;
|
|
3028
3051
|
return {
|
|
3029
3052
|
...await readHermesProfilePermissions(profileName, configPath),
|
|
3030
3053
|
backupPath,
|
|
3031
|
-
requiresGatewayReload:
|
|
3054
|
+
requiresGatewayReload: configTouched || envChanged,
|
|
3032
3055
|
restartHint: PROFILE_PERMISSIONS_RESTART_HINT
|
|
3033
3056
|
};
|
|
3034
3057
|
}
|
|
@@ -4947,6 +4970,7 @@ function readPositiveInteger(value) {
|
|
|
4947
4970
|
function profilePermissionsFromConfig(profileName, configPath, config, env) {
|
|
4948
4971
|
const approvals = toRecord(config.approvals);
|
|
4949
4972
|
const terminal = toRecord(config.terminal);
|
|
4973
|
+
const envPath = resolveHermesEnvPath(profileName);
|
|
4950
4974
|
const platformToolsets = toRecord(config.platform_toolsets);
|
|
4951
4975
|
const apiServerToolsets = readStringList(platformToolsets.api_server);
|
|
4952
4976
|
const hasExplicitToolsets = apiServerToolsets.some(
|
|
@@ -4960,6 +4984,7 @@ function profilePermissionsFromConfig(profileName, configPath, config, env) {
|
|
|
4960
4984
|
return {
|
|
4961
4985
|
profileName,
|
|
4962
4986
|
configPath,
|
|
4987
|
+
envPath,
|
|
4963
4988
|
approvals: {
|
|
4964
4989
|
mode: readApprovalMode(approvals.mode),
|
|
4965
4990
|
timeout: readPositiveInteger(approvals.timeout) ?? 60,
|
|
@@ -4973,6 +4998,11 @@ function profilePermissionsFromConfig(profileName, configPath, config, env) {
|
|
|
4973
4998
|
containerDisk: readPositiveInteger(terminal.container_disk) ?? null,
|
|
4974
4999
|
containerPersistent: terminal.container_persistent !== false
|
|
4975
5000
|
},
|
|
5001
|
+
sudo: {
|
|
5002
|
+
configured: isEnvValueConfigured(env.SUDO_PASSWORD) || isEnvValueConfigured(readString2(terminal.sudo_password)),
|
|
5003
|
+
envKey: "SUDO_PASSWORD",
|
|
5004
|
+
envPath
|
|
5005
|
+
},
|
|
4976
5006
|
toolsets: {
|
|
4977
5007
|
items: PROFILE_PERMISSION_TOOLSETS.map((toolset) => {
|
|
4978
5008
|
const configState = readToolsetConfigState(toolset.key, config, env);
|
|
@@ -5175,6 +5205,15 @@ function normalizeCronApprovalMode(value) {
|
|
|
5175
5205
|
}
|
|
5176
5206
|
throw new Error("approvals.cron_mode must be deny or approve");
|
|
5177
5207
|
}
|
|
5208
|
+
function normalizeSudoPassword(value) {
|
|
5209
|
+
if (!value) {
|
|
5210
|
+
throw new Error("sudo.password must be non-empty");
|
|
5211
|
+
}
|
|
5212
|
+
if (value.includes("\n") || value.includes("\r") || value.includes("\0")) {
|
|
5213
|
+
throw new Error("sudo.password must not contain line breaks");
|
|
5214
|
+
}
|
|
5215
|
+
return value;
|
|
5216
|
+
}
|
|
5178
5217
|
function normalizeTerminalBackend(value) {
|
|
5179
5218
|
const backend = value.trim().toLowerCase();
|
|
5180
5219
|
if (TERMINAL_BACKENDS.has(backend)) {
|
|
@@ -5932,7 +5971,7 @@ async function readHermesApiServerEnvOverrides(profileName) {
|
|
|
5932
5971
|
};
|
|
5933
5972
|
}
|
|
5934
5973
|
async function readHermesEnvFile(profileName) {
|
|
5935
|
-
const envPath =
|
|
5974
|
+
const envPath = resolveHermesEnvPath(profileName);
|
|
5936
5975
|
const raw = await readFile2(envPath, "utf8").catch((error) => {
|
|
5937
5976
|
if (isNodeError3(error, "ENOENT")) {
|
|
5938
5977
|
return "";
|
|
@@ -5956,7 +5995,7 @@ async function readHermesEnvFile(profileName) {
|
|
|
5956
5995
|
return values;
|
|
5957
5996
|
}
|
|
5958
5997
|
async function writeHermesEnvValue(profileName, key, value) {
|
|
5959
|
-
const envPath =
|
|
5998
|
+
const envPath = resolveHermesEnvPath(profileName);
|
|
5960
5999
|
const existingRaw = await readFile2(envPath, "utf8").catch(
|
|
5961
6000
|
(error) => {
|
|
5962
6001
|
if (isNodeError3(error, "ENOENT")) {
|
|
@@ -5991,8 +6030,32 @@ async function writeHermesEnvValue(profileName, key, value) {
|
|
|
5991
6030
|
}
|
|
5992
6031
|
await atomicWriteFilePreservingMetadata(envPath, nextRaw);
|
|
5993
6032
|
}
|
|
6033
|
+
async function deleteHermesEnvValue(profileName, key) {
|
|
6034
|
+
const envPath = resolveHermesEnvPath(profileName);
|
|
6035
|
+
const raw = await readFile2(envPath, "utf8").catch((error) => {
|
|
6036
|
+
if (isNodeError3(error, "ENOENT")) {
|
|
6037
|
+
return "";
|
|
6038
|
+
}
|
|
6039
|
+
throw error;
|
|
6040
|
+
});
|
|
6041
|
+
if (!raw) {
|
|
6042
|
+
return false;
|
|
6043
|
+
}
|
|
6044
|
+
const keyPattern = new RegExp(`^(?:export\\s+)?${escapeRegExp(key)}=`, "u");
|
|
6045
|
+
const lines = raw.split(/\r?\n/u);
|
|
6046
|
+
const nextLines = lines.filter((line) => !keyPattern.test(line.trim()));
|
|
6047
|
+
const nextRaw = nextLines.join("\n").replace(/\n*$/u, "\n");
|
|
6048
|
+
if (nextRaw === raw) {
|
|
6049
|
+
return false;
|
|
6050
|
+
}
|
|
6051
|
+
await atomicWriteFilePreservingMetadata(`${envPath}.bak.${Date.now()}`, raw, {
|
|
6052
|
+
metadataSourcePath: envPath
|
|
6053
|
+
});
|
|
6054
|
+
await atomicWriteFilePreservingMetadata(envPath, nextRaw);
|
|
6055
|
+
return true;
|
|
6056
|
+
}
|
|
5994
6057
|
async function writeHermesApiServerEnv(profileName, config, options = {}) {
|
|
5995
|
-
const envPath =
|
|
6058
|
+
const envPath = resolveHermesEnvPath(profileName);
|
|
5996
6059
|
const existingRaw = await readFile2(envPath, "utf8").catch(
|
|
5997
6060
|
(error) => {
|
|
5998
6061
|
if (isNodeError3(error, "ENOENT")) {
|
|
@@ -6016,7 +6079,7 @@ async function writeHermesApiServerEnv(profileName, config, options = {}) {
|
|
|
6016
6079
|
);
|
|
6017
6080
|
}
|
|
6018
6081
|
async function writeHermesEnvValues(profileName, values, existingRaw) {
|
|
6019
|
-
const envPath =
|
|
6082
|
+
const envPath = resolveHermesEnvPath(profileName);
|
|
6020
6083
|
const raw = existingRaw ?? await readFile2(envPath, "utf8").catch((error) => {
|
|
6021
6084
|
if (isNodeError3(error, "ENOENT")) {
|
|
6022
6085
|
return "";
|
|
@@ -6510,7 +6573,7 @@ function isConversationMissingError(error) {
|
|
|
6510
6573
|
}
|
|
6511
6574
|
|
|
6512
6575
|
// src/constants.ts
|
|
6513
|
-
var LINK_VERSION = "0.7.
|
|
6576
|
+
var LINK_VERSION = "0.7.6";
|
|
6514
6577
|
var LINK_COMMAND = "hermeslink";
|
|
6515
6578
|
var LINK_DEFAULT_PORT = 52379;
|
|
6516
6579
|
var LINK_RUNTIME_DIR_NAME = ".hermeslink";
|
|
@@ -27375,6 +27438,17 @@ function readProfilePermissionsInput(body) {
|
|
|
27375
27438
|
)
|
|
27376
27439
|
};
|
|
27377
27440
|
}
|
|
27441
|
+
const sudo = readOptionalObject(body, "sudo");
|
|
27442
|
+
if (sudo) {
|
|
27443
|
+
const clear = readBoolean3(sudo.clear ?? sudo.remove ?? sudo.delete);
|
|
27444
|
+
const sudoInput = {
|
|
27445
|
+
password: readRawString(sudo, "password") ?? readRawString(sudo, "sudo_password") ?? readRawString(sudo, "sudoPassword") ?? void 0,
|
|
27446
|
+
clear: clear === true ? true : void 0
|
|
27447
|
+
};
|
|
27448
|
+
if (sudoInput.password !== void 0 || sudoInput.clear !== void 0) {
|
|
27449
|
+
input.sudo = sudoInput;
|
|
27450
|
+
}
|
|
27451
|
+
}
|
|
27378
27452
|
const toolsets = readOptionalObject(body, "toolsets");
|
|
27379
27453
|
if (toolsets) {
|
|
27380
27454
|
input.toolsets = {
|
|
@@ -27408,6 +27482,10 @@ function readOptionalObject(body, key) {
|
|
|
27408
27482
|
}
|
|
27409
27483
|
return value;
|
|
27410
27484
|
}
|
|
27485
|
+
function readRawString(body, key) {
|
|
27486
|
+
const value = body[key];
|
|
27487
|
+
return typeof value === "string" ? value : null;
|
|
27488
|
+
}
|
|
27411
27489
|
function readStringListValue(value, field) {
|
|
27412
27490
|
if (value === void 0) {
|
|
27413
27491
|
return null;
|
package/dist/cli/index.js
CHANGED
package/dist/http/app.js
CHANGED