@hermespilot/link 0.7.5-beta.0 → 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);
|
|
@@ -2618,16 +2621,20 @@ async function saveHermesModelConfig(input, profileName = "default", configPath
|
|
|
2618
2621
|
const shouldUpdateReasoningEffort = input.reasoningEffort !== void 0;
|
|
2619
2622
|
const { document, config, existingRaw } = await readHermesConfigDocument(configPath);
|
|
2620
2623
|
const providers = ensureProvidersRecordWithLegacyMigration(config);
|
|
2621
|
-
const originalModelId = input.originalModelId?.trim()
|
|
2624
|
+
const originalModelId = input.originalModelId?.trim();
|
|
2622
2625
|
const originalProvider = input.originalProvider?.trim();
|
|
2623
2626
|
const originalBaseUrl = input.originalBaseUrl?.trim();
|
|
2624
2627
|
const originalApiMode = input.originalApiMode?.trim();
|
|
2625
|
-
const
|
|
2626
|
-
id: originalModelId,
|
|
2628
|
+
const originalIdentity = {
|
|
2629
|
+
id: originalModelId || normalized.id,
|
|
2627
2630
|
provider: originalProvider,
|
|
2628
2631
|
baseUrl: originalBaseUrl,
|
|
2629
2632
|
apiMode: originalApiMode
|
|
2630
|
-
}
|
|
2633
|
+
};
|
|
2634
|
+
const hasOriginalIdentity = Boolean(
|
|
2635
|
+
originalModelId || originalProvider || originalBaseUrl || originalApiMode
|
|
2636
|
+
);
|
|
2637
|
+
const existingProviderKey = (hasOriginalIdentity ? findProviderConfigKeyByModelIdentity(providers, originalIdentity) : null) ?? (originalProvider && originalBaseUrl ? findProviderConfigKeyByEndpoint(providers, {
|
|
2631
2638
|
provider: originalProvider,
|
|
2632
2639
|
baseUrl: originalBaseUrl,
|
|
2633
2640
|
apiMode: originalApiMode
|
|
@@ -2647,7 +2654,7 @@ async function saveHermesModelConfig(input, profileName = "default", configPath
|
|
|
2647
2654
|
await writeHermesEnvValue(profileName, keyEnv, normalized.apiKey);
|
|
2648
2655
|
}
|
|
2649
2656
|
writeProviderEndpointConfig(entry, normalized, keyEnv);
|
|
2650
|
-
ensureEntryModelConfig(entry,
|
|
2657
|
+
ensureEntryModelConfig(entry, originalIdentity.id, normalized.id);
|
|
2651
2658
|
writeEntryModelContextLength(entry, normalized.id, normalized.contextLength);
|
|
2652
2659
|
writeEntryModelSupportsVision(entry, normalized.id, input.supportsVision);
|
|
2653
2660
|
if (shouldUpdateReasoningEffort) {
|
|
@@ -2662,15 +2669,29 @@ async function saveHermesModelConfig(input, profileName = "default", configPath
|
|
|
2662
2669
|
const currentDefaultConfig = readModelConfig(modelConfig);
|
|
2663
2670
|
const currentDefault = currentDefaultConfig.model;
|
|
2664
2671
|
const currentDefaultReasoningEffort = readProfileReasoningEffort(config);
|
|
2665
|
-
|
|
2666
|
-
|
|
2672
|
+
const currentDefaultMatchesOriginal = hasOriginalIdentity && modelConfigMatchesModelIdentity(currentDefaultConfig, originalIdentity);
|
|
2673
|
+
const currentDefaultMatchesNext = modelConfigMatchesModelIdentity(
|
|
2674
|
+
currentDefaultConfig,
|
|
2675
|
+
{
|
|
2676
|
+
id: normalized.id,
|
|
2677
|
+
provider: providerKey,
|
|
2678
|
+
baseUrl: normalized.baseUrl,
|
|
2679
|
+
apiMode: inferApiMode(
|
|
2680
|
+
providerKey,
|
|
2681
|
+
normalized.baseUrl,
|
|
2682
|
+
normalized.apiMode
|
|
2683
|
+
)
|
|
2684
|
+
}
|
|
2685
|
+
);
|
|
2686
|
+
if (normalized.setDefault || !currentDefault || currentDefaultMatchesOriginal) {
|
|
2687
|
+
if (normalized.setDefault && currentDefault && !currentDefaultMatchesNext && !currentDefaultMatchesOriginal) {
|
|
2667
2688
|
retainModelDefaultAsProvider(providers, {
|
|
2668
2689
|
...currentDefaultConfig,
|
|
2669
2690
|
...currentDefaultReasoningEffort ? { reasoningEffort: currentDefaultReasoningEffort } : {}
|
|
2670
2691
|
});
|
|
2671
2692
|
}
|
|
2672
|
-
const defaultKeyEnv = keyEnv ?? (
|
|
2673
|
-
const defaultApiKey = normalized.apiKey ?? (!defaultKeyEnv &&
|
|
2693
|
+
const defaultKeyEnv = keyEnv ?? (currentDefaultMatchesOriginal ? currentDefaultConfig.keyEnv : void 0);
|
|
2694
|
+
const defaultApiKey = normalized.apiKey ?? (!defaultKeyEnv && currentDefaultMatchesOriginal ? currentDefaultConfig.apiKey : void 0);
|
|
2674
2695
|
writeDefaultModelConfig(modelConfig, {
|
|
2675
2696
|
...normalized,
|
|
2676
2697
|
provider: providerKey,
|
|
@@ -2858,7 +2879,12 @@ async function saveHermesModelDefaults(input, profileName = "default", configPat
|
|
|
2858
2879
|
const modelConfig = ensureRecord(config, "model");
|
|
2859
2880
|
const currentDefaultConfig = readModelConfig(modelConfig);
|
|
2860
2881
|
const currentDefaultReasoningEffort = readProfileReasoningEffort(config);
|
|
2861
|
-
if (currentDefaultConfig.model && currentDefaultConfig
|
|
2882
|
+
if (currentDefaultConfig.model && !modelConfigMatchesModelIdentity(currentDefaultConfig, {
|
|
2883
|
+
id: selected.id,
|
|
2884
|
+
provider: selected.provider,
|
|
2885
|
+
baseUrl: selected.baseUrl,
|
|
2886
|
+
apiMode: selected.apiMode
|
|
2887
|
+
})) {
|
|
2862
2888
|
retainModelDefaultAsProvider(providers, {
|
|
2863
2889
|
...currentDefaultConfig,
|
|
2864
2890
|
...currentDefaultReasoningEffort ? { reasoningEffort: currentDefaultReasoningEffort } : {}
|
|
@@ -2923,7 +2949,9 @@ async function readHermesProfilePermissions(profileName = "default", configPath
|
|
|
2923
2949
|
}
|
|
2924
2950
|
async function saveHermesProfilePermissions(profileName, input, configPath = resolveHermesConfigPath(profileName)) {
|
|
2925
2951
|
const { document, config, existingRaw } = await readHermesConfigDocument(configPath);
|
|
2952
|
+
let configTouched = false;
|
|
2926
2953
|
if (input.approvals) {
|
|
2954
|
+
configTouched = true;
|
|
2927
2955
|
const approvals = ensureRecord(config, "approvals");
|
|
2928
2956
|
if (input.approvals.mode !== void 0) {
|
|
2929
2957
|
approvals.mode = normalizeApprovalMode(input.approvals.mode);
|
|
@@ -2939,6 +2967,7 @@ async function saveHermesProfilePermissions(profileName, input, configPath = res
|
|
|
2939
2967
|
}
|
|
2940
2968
|
}
|
|
2941
2969
|
if (input.terminal) {
|
|
2970
|
+
configTouched = true;
|
|
2942
2971
|
const terminal = ensureRecord(config, "terminal");
|
|
2943
2972
|
if (input.terminal.backend !== void 0) {
|
|
2944
2973
|
terminal.backend = normalizeTerminalBackend(input.terminal.backend);
|
|
@@ -2968,7 +2997,24 @@ async function saveHermesProfilePermissions(profileName, input, configPath = res
|
|
|
2968
2997
|
terminal.container_persistent = input.terminal.containerPersistent;
|
|
2969
2998
|
}
|
|
2970
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
|
+
}
|
|
2971
3016
|
if (input.toolsets) {
|
|
3017
|
+
configTouched = true;
|
|
2972
3018
|
const env = await readHermesEnvFile(profileName);
|
|
2973
3019
|
const currentPermissions = profilePermissionsFromConfig(
|
|
2974
3020
|
profileName,
|
|
@@ -2996,16 +3042,16 @@ async function saveHermesProfilePermissions(profileName, input, configPath = res
|
|
|
2996
3042
|
}
|
|
2997
3043
|
platformToolsets.api_server = next;
|
|
2998
3044
|
}
|
|
2999
|
-
const backupPath = await writeHermesConfigDocument({
|
|
3045
|
+
const backupPath = configTouched ? await writeHermesConfigDocument({
|
|
3000
3046
|
configPath,
|
|
3001
3047
|
document,
|
|
3002
3048
|
config,
|
|
3003
3049
|
existingRaw
|
|
3004
|
-
});
|
|
3050
|
+
}) : null;
|
|
3005
3051
|
return {
|
|
3006
3052
|
...await readHermesProfilePermissions(profileName, configPath),
|
|
3007
3053
|
backupPath,
|
|
3008
|
-
requiresGatewayReload:
|
|
3054
|
+
requiresGatewayReload: configTouched || envChanged,
|
|
3009
3055
|
restartHint: PROFILE_PERMISSIONS_RESTART_HINT
|
|
3010
3056
|
};
|
|
3011
3057
|
}
|
|
@@ -3472,6 +3518,11 @@ function providerConfigToLegacyEntry(providerKey, entry) {
|
|
|
3472
3518
|
}
|
|
3473
3519
|
function ensureProvidersRecordWithLegacyMigration(config) {
|
|
3474
3520
|
const providers = ensureRecord(config, "providers");
|
|
3521
|
+
for (const [key, rawEntry] of Object.entries(providers)) {
|
|
3522
|
+
const entry = toRecord(rawEntry);
|
|
3523
|
+
normalizeProviderCredentialReference(entry);
|
|
3524
|
+
providers[key] = entry;
|
|
3525
|
+
}
|
|
3475
3526
|
const customProviders = Array.isArray(config.custom_providers) ? config.custom_providers : [];
|
|
3476
3527
|
for (const rawEntry of customProviders) {
|
|
3477
3528
|
const entry = toRecord(rawEntry);
|
|
@@ -3609,7 +3660,7 @@ function legacyEntryToProviderConfig(entry, baseUrl) {
|
|
|
3609
3660
|
const apiKey = readString2(entry.api_key);
|
|
3610
3661
|
const keyEnv = readString2(entry.key_env) ?? parseEnvReference(apiKey);
|
|
3611
3662
|
if (keyEnv) {
|
|
3612
|
-
next.
|
|
3663
|
+
next.api_key = `\${${keyEnv}}`;
|
|
3613
3664
|
} else if (apiKey) {
|
|
3614
3665
|
next.api_key = apiKey;
|
|
3615
3666
|
}
|
|
@@ -3643,6 +3694,15 @@ function legacyEntryToProviderConfig(entry, baseUrl) {
|
|
|
3643
3694
|
}
|
|
3644
3695
|
return next;
|
|
3645
3696
|
}
|
|
3697
|
+
function normalizeProviderCredentialReference(entry) {
|
|
3698
|
+
const apiKey = readString2(entry.api_key);
|
|
3699
|
+
const keyEnv = readString2(entry.key_env) ?? parseEnvReference(apiKey);
|
|
3700
|
+
if (!keyEnv) {
|
|
3701
|
+
return;
|
|
3702
|
+
}
|
|
3703
|
+
entry.api_key = `\${${keyEnv}}`;
|
|
3704
|
+
delete entry.key_env;
|
|
3705
|
+
}
|
|
3646
3706
|
function normalizeEntryModelsMap(entry) {
|
|
3647
3707
|
const models = entry.models;
|
|
3648
3708
|
if (typeof models === "object" && models !== null && !Array.isArray(models)) {
|
|
@@ -3780,8 +3840,8 @@ function writeProviderEndpointConfig(entry, input, keyEnv) {
|
|
|
3780
3840
|
delete entry.contextLength;
|
|
3781
3841
|
}
|
|
3782
3842
|
if (keyEnv) {
|
|
3783
|
-
entry.
|
|
3784
|
-
delete entry.
|
|
3843
|
+
entry.api_key = `\${${keyEnv}}`;
|
|
3844
|
+
delete entry.key_env;
|
|
3785
3845
|
} else {
|
|
3786
3846
|
delete entry.key_env;
|
|
3787
3847
|
}
|
|
@@ -4041,22 +4101,18 @@ function managedModelPreferenceScore(model) {
|
|
|
4041
4101
|
return (model.isDefault ? 1e3 : 0) + (model.credentialState === "configured" ? 200 : 0) + (model.credentialState === "missing" ? 50 : 0) + (model.source === "auth_store" ? 100 : 0) + (model.credentialSource !== "unknown" ? 40 : 0) + (model.isReadOnly ? 10 : 0);
|
|
4042
4102
|
}
|
|
4043
4103
|
function matchesDefaultModelConfig(input) {
|
|
4044
|
-
if (!input.defaultModel
|
|
4045
|
-
return false;
|
|
4046
|
-
}
|
|
4047
|
-
const defaultApiMode = input.modelConfig.apiMode?.trim();
|
|
4048
|
-
if (defaultApiMode && input.apiMode !== defaultApiMode) {
|
|
4104
|
+
if (!input.defaultModel) {
|
|
4049
4105
|
return false;
|
|
4050
4106
|
}
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4107
|
+
return modelConfigMatchesModelIdentity(
|
|
4108
|
+
{ ...input.modelConfig, model: input.defaultModel },
|
|
4109
|
+
{
|
|
4110
|
+
id: input.id,
|
|
4111
|
+
provider: input.provider,
|
|
4112
|
+
baseUrl: input.baseUrl,
|
|
4113
|
+
apiMode: input.apiMode
|
|
4114
|
+
}
|
|
4115
|
+
);
|
|
4060
4116
|
}
|
|
4061
4117
|
function providerEntryMatchesManagedModel(entry, model) {
|
|
4062
4118
|
const providerName = readString2(entry.name) ?? readString2(entry.provider_name) ?? readString2(entry.provider_key) ?? "Custom Provider";
|
|
@@ -4266,6 +4322,29 @@ function resolveCompressionModel(config, models) {
|
|
|
4266
4322
|
function findManagedModelById(models, id) {
|
|
4267
4323
|
return models.find((model) => model.id === id);
|
|
4268
4324
|
}
|
|
4325
|
+
function modelConfigMatchesModelIdentity(modelConfig, input) {
|
|
4326
|
+
if (modelConfig.model !== input.id) {
|
|
4327
|
+
return false;
|
|
4328
|
+
}
|
|
4329
|
+
const provider = input.provider?.trim();
|
|
4330
|
+
const configProvider = modelConfig.provider?.trim();
|
|
4331
|
+
if (provider && configProvider && configProvider !== provider) {
|
|
4332
|
+
return false;
|
|
4333
|
+
}
|
|
4334
|
+
const baseUrl = input.baseUrl?.trim();
|
|
4335
|
+
if (baseUrl !== void 0 && normalizeBaseUrl(modelConfig.baseUrl ?? "") !== normalizeBaseUrl(baseUrl)) {
|
|
4336
|
+
return false;
|
|
4337
|
+
}
|
|
4338
|
+
const apiMode = input.apiMode?.trim();
|
|
4339
|
+
if (apiMode) {
|
|
4340
|
+
const providerForApiMode = configProvider ?? provider ?? "default";
|
|
4341
|
+
const configBaseUrl = modelConfig.baseUrl ?? baseUrl ?? "";
|
|
4342
|
+
if (inferApiMode(providerForApiMode, configBaseUrl, modelConfig.apiMode) !== apiMode) {
|
|
4343
|
+
return false;
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
return true;
|
|
4347
|
+
}
|
|
4269
4348
|
function findManagedModel(models, input) {
|
|
4270
4349
|
const provider = input.provider?.trim();
|
|
4271
4350
|
const baseUrl = input.baseUrl?.trim();
|
|
@@ -4430,7 +4509,7 @@ function retainModelDefaultAsProvider(providers, model) {
|
|
|
4430
4509
|
writeEntryModelSupportsVision(entry, id, model.supportsVision);
|
|
4431
4510
|
}
|
|
4432
4511
|
if (model.keyEnv) {
|
|
4433
|
-
entry.
|
|
4512
|
+
entry.api_key = `\${${model.keyEnv}}`;
|
|
4434
4513
|
} else if (model.apiKey) {
|
|
4435
4514
|
entry.api_key = model.apiKey;
|
|
4436
4515
|
}
|
|
@@ -4891,6 +4970,7 @@ function readPositiveInteger(value) {
|
|
|
4891
4970
|
function profilePermissionsFromConfig(profileName, configPath, config, env) {
|
|
4892
4971
|
const approvals = toRecord(config.approvals);
|
|
4893
4972
|
const terminal = toRecord(config.terminal);
|
|
4973
|
+
const envPath = resolveHermesEnvPath(profileName);
|
|
4894
4974
|
const platformToolsets = toRecord(config.platform_toolsets);
|
|
4895
4975
|
const apiServerToolsets = readStringList(platformToolsets.api_server);
|
|
4896
4976
|
const hasExplicitToolsets = apiServerToolsets.some(
|
|
@@ -4904,6 +4984,7 @@ function profilePermissionsFromConfig(profileName, configPath, config, env) {
|
|
|
4904
4984
|
return {
|
|
4905
4985
|
profileName,
|
|
4906
4986
|
configPath,
|
|
4987
|
+
envPath,
|
|
4907
4988
|
approvals: {
|
|
4908
4989
|
mode: readApprovalMode(approvals.mode),
|
|
4909
4990
|
timeout: readPositiveInteger(approvals.timeout) ?? 60,
|
|
@@ -4917,6 +4998,11 @@ function profilePermissionsFromConfig(profileName, configPath, config, env) {
|
|
|
4917
4998
|
containerDisk: readPositiveInteger(terminal.container_disk) ?? null,
|
|
4918
4999
|
containerPersistent: terminal.container_persistent !== false
|
|
4919
5000
|
},
|
|
5001
|
+
sudo: {
|
|
5002
|
+
configured: isEnvValueConfigured(env.SUDO_PASSWORD) || isEnvValueConfigured(readString2(terminal.sudo_password)),
|
|
5003
|
+
envKey: "SUDO_PASSWORD",
|
|
5004
|
+
envPath
|
|
5005
|
+
},
|
|
4920
5006
|
toolsets: {
|
|
4921
5007
|
items: PROFILE_PERMISSION_TOOLSETS.map((toolset) => {
|
|
4922
5008
|
const configState = readToolsetConfigState(toolset.key, config, env);
|
|
@@ -5119,6 +5205,15 @@ function normalizeCronApprovalMode(value) {
|
|
|
5119
5205
|
}
|
|
5120
5206
|
throw new Error("approvals.cron_mode must be deny or approve");
|
|
5121
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
|
+
}
|
|
5122
5217
|
function normalizeTerminalBackend(value) {
|
|
5123
5218
|
const backend = value.trim().toLowerCase();
|
|
5124
5219
|
if (TERMINAL_BACKENDS.has(backend)) {
|
|
@@ -5876,7 +5971,7 @@ async function readHermesApiServerEnvOverrides(profileName) {
|
|
|
5876
5971
|
};
|
|
5877
5972
|
}
|
|
5878
5973
|
async function readHermesEnvFile(profileName) {
|
|
5879
|
-
const envPath =
|
|
5974
|
+
const envPath = resolveHermesEnvPath(profileName);
|
|
5880
5975
|
const raw = await readFile2(envPath, "utf8").catch((error) => {
|
|
5881
5976
|
if (isNodeError3(error, "ENOENT")) {
|
|
5882
5977
|
return "";
|
|
@@ -5900,7 +5995,7 @@ async function readHermesEnvFile(profileName) {
|
|
|
5900
5995
|
return values;
|
|
5901
5996
|
}
|
|
5902
5997
|
async function writeHermesEnvValue(profileName, key, value) {
|
|
5903
|
-
const envPath =
|
|
5998
|
+
const envPath = resolveHermesEnvPath(profileName);
|
|
5904
5999
|
const existingRaw = await readFile2(envPath, "utf8").catch(
|
|
5905
6000
|
(error) => {
|
|
5906
6001
|
if (isNodeError3(error, "ENOENT")) {
|
|
@@ -5935,8 +6030,32 @@ async function writeHermesEnvValue(profileName, key, value) {
|
|
|
5935
6030
|
}
|
|
5936
6031
|
await atomicWriteFilePreservingMetadata(envPath, nextRaw);
|
|
5937
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
|
+
}
|
|
5938
6057
|
async function writeHermesApiServerEnv(profileName, config, options = {}) {
|
|
5939
|
-
const envPath =
|
|
6058
|
+
const envPath = resolveHermesEnvPath(profileName);
|
|
5940
6059
|
const existingRaw = await readFile2(envPath, "utf8").catch(
|
|
5941
6060
|
(error) => {
|
|
5942
6061
|
if (isNodeError3(error, "ENOENT")) {
|
|
@@ -5960,7 +6079,7 @@ async function writeHermesApiServerEnv(profileName, config, options = {}) {
|
|
|
5960
6079
|
);
|
|
5961
6080
|
}
|
|
5962
6081
|
async function writeHermesEnvValues(profileName, values, existingRaw) {
|
|
5963
|
-
const envPath =
|
|
6082
|
+
const envPath = resolveHermesEnvPath(profileName);
|
|
5964
6083
|
const raw = existingRaw ?? await readFile2(envPath, "utf8").catch((error) => {
|
|
5965
6084
|
if (isNodeError3(error, "ENOENT")) {
|
|
5966
6085
|
return "";
|
|
@@ -6454,7 +6573,7 @@ function isConversationMissingError(error) {
|
|
|
6454
6573
|
}
|
|
6455
6574
|
|
|
6456
6575
|
// src/constants.ts
|
|
6457
|
-
var LINK_VERSION = "0.7.
|
|
6576
|
+
var LINK_VERSION = "0.7.6";
|
|
6458
6577
|
var LINK_COMMAND = "hermeslink";
|
|
6459
6578
|
var LINK_DEFAULT_PORT = 52379;
|
|
6460
6579
|
var LINK_RUNTIME_DIR_NAME = ".hermeslink";
|
|
@@ -25802,7 +25921,9 @@ function registerModelConfigRoutes(router, options) {
|
|
|
25802
25921
|
const body = await readJsonBody(ctx.req);
|
|
25803
25922
|
try {
|
|
25804
25923
|
const result = await saveHermesModelConfig(readModelConfigInput(body));
|
|
25805
|
-
ctx.body = shouldReloadGatewayAfterModelConfigChange(body
|
|
25924
|
+
ctx.body = shouldReloadGatewayAfterModelConfigChange(body, {
|
|
25925
|
+
defaultReload: true
|
|
25926
|
+
}) ? await reloadGatewayAfterModelConfigChange(result, {
|
|
25806
25927
|
paths,
|
|
25807
25928
|
logger
|
|
25808
25929
|
}) : markModelConfigAppliedWithoutGatewayReload(result);
|
|
@@ -25848,7 +25969,9 @@ function registerModelConfigRoutes(router, options) {
|
|
|
25848
25969
|
readModelConfigInput(body),
|
|
25849
25970
|
ctx.params.name
|
|
25850
25971
|
);
|
|
25851
|
-
ctx.body = shouldReloadGatewayAfterModelConfigChange(body
|
|
25972
|
+
ctx.body = shouldReloadGatewayAfterModelConfigChange(body, {
|
|
25973
|
+
defaultReload: true
|
|
25974
|
+
}) ? await reloadGatewayAfterProfileModelConfigChange(result, {
|
|
25852
25975
|
paths,
|
|
25853
25976
|
logger,
|
|
25854
25977
|
profileName: ctx.params.name
|
|
@@ -26001,15 +26124,20 @@ function readModelConfigImportInput(body) {
|
|
|
26001
26124
|
setDefault: readBoolean3(body.set_default ?? body.setDefault)
|
|
26002
26125
|
};
|
|
26003
26126
|
}
|
|
26004
|
-
function shouldReloadGatewayAfterModelConfigChange(body) {
|
|
26005
|
-
|
|
26006
|
-
|
|
26127
|
+
function shouldReloadGatewayAfterModelConfigChange(body, options = {}) {
|
|
26128
|
+
if (readBoolean3(body.skip_gateway_reload ?? body.skipGatewayReload) === true) {
|
|
26129
|
+
return false;
|
|
26130
|
+
}
|
|
26131
|
+
if (readBoolean3(body.reload_gateway ?? body.reloadGateway) === true) {
|
|
26132
|
+
return true;
|
|
26133
|
+
}
|
|
26134
|
+
return options.defaultReload === true;
|
|
26007
26135
|
}
|
|
26008
26136
|
function markModelConfigAppliedWithoutGatewayReload(result) {
|
|
26009
26137
|
return {
|
|
26010
26138
|
...result,
|
|
26011
26139
|
requiresGatewayReload: false,
|
|
26012
|
-
restartHint: "\u6A21\u578B\u914D\u7F6E\u5DF2\u4FDD\u5B58\
|
|
26140
|
+
restartHint: "\u6A21\u578B\u914D\u7F6E\u5DF2\u4FDD\u5B58\uFF0C\u5DF2\u6309\u8BF7\u6C42\u8DF3\u8FC7 Hermes Gateway \u91CD\u8F7D\u3002\u82E5\u521A\u4FEE\u6539 API Key\u3001Base URL \u6216 API Mode\uFF0C\u8BF7\u624B\u52A8\u91CD\u8F7D Gateway \u540E\u518D\u5F00\u59CB\u65B0\u7684 Run\u3002"
|
|
26013
26141
|
};
|
|
26014
26142
|
}
|
|
26015
26143
|
function toModelConfigHttpError(error) {
|
|
@@ -27310,6 +27438,17 @@ function readProfilePermissionsInput(body) {
|
|
|
27310
27438
|
)
|
|
27311
27439
|
};
|
|
27312
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
|
+
}
|
|
27313
27452
|
const toolsets = readOptionalObject(body, "toolsets");
|
|
27314
27453
|
if (toolsets) {
|
|
27315
27454
|
input.toolsets = {
|
|
@@ -27343,6 +27482,10 @@ function readOptionalObject(body, key) {
|
|
|
27343
27482
|
}
|
|
27344
27483
|
return value;
|
|
27345
27484
|
}
|
|
27485
|
+
function readRawString(body, key) {
|
|
27486
|
+
const value = body[key];
|
|
27487
|
+
return typeof value === "string" ? value : null;
|
|
27488
|
+
}
|
|
27346
27489
|
function readStringListValue(value, field) {
|
|
27347
27490
|
if (value === void 0) {
|
|
27348
27491
|
return null;
|
package/dist/cli/index.js
CHANGED
package/dist/http/app.js
CHANGED