@hermespilot/link 0.7.5-beta.0 → 0.7.5
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.
|
@@ -2618,16 +2618,20 @@ async function saveHermesModelConfig(input, profileName = "default", configPath
|
|
|
2618
2618
|
const shouldUpdateReasoningEffort = input.reasoningEffort !== void 0;
|
|
2619
2619
|
const { document, config, existingRaw } = await readHermesConfigDocument(configPath);
|
|
2620
2620
|
const providers = ensureProvidersRecordWithLegacyMigration(config);
|
|
2621
|
-
const originalModelId = input.originalModelId?.trim()
|
|
2621
|
+
const originalModelId = input.originalModelId?.trim();
|
|
2622
2622
|
const originalProvider = input.originalProvider?.trim();
|
|
2623
2623
|
const originalBaseUrl = input.originalBaseUrl?.trim();
|
|
2624
2624
|
const originalApiMode = input.originalApiMode?.trim();
|
|
2625
|
-
const
|
|
2626
|
-
id: originalModelId,
|
|
2625
|
+
const originalIdentity = {
|
|
2626
|
+
id: originalModelId || normalized.id,
|
|
2627
2627
|
provider: originalProvider,
|
|
2628
2628
|
baseUrl: originalBaseUrl,
|
|
2629
2629
|
apiMode: originalApiMode
|
|
2630
|
-
}
|
|
2630
|
+
};
|
|
2631
|
+
const hasOriginalIdentity = Boolean(
|
|
2632
|
+
originalModelId || originalProvider || originalBaseUrl || originalApiMode
|
|
2633
|
+
);
|
|
2634
|
+
const existingProviderKey = (hasOriginalIdentity ? findProviderConfigKeyByModelIdentity(providers, originalIdentity) : null) ?? (originalProvider && originalBaseUrl ? findProviderConfigKeyByEndpoint(providers, {
|
|
2631
2635
|
provider: originalProvider,
|
|
2632
2636
|
baseUrl: originalBaseUrl,
|
|
2633
2637
|
apiMode: originalApiMode
|
|
@@ -2647,7 +2651,7 @@ async function saveHermesModelConfig(input, profileName = "default", configPath
|
|
|
2647
2651
|
await writeHermesEnvValue(profileName, keyEnv, normalized.apiKey);
|
|
2648
2652
|
}
|
|
2649
2653
|
writeProviderEndpointConfig(entry, normalized, keyEnv);
|
|
2650
|
-
ensureEntryModelConfig(entry,
|
|
2654
|
+
ensureEntryModelConfig(entry, originalIdentity.id, normalized.id);
|
|
2651
2655
|
writeEntryModelContextLength(entry, normalized.id, normalized.contextLength);
|
|
2652
2656
|
writeEntryModelSupportsVision(entry, normalized.id, input.supportsVision);
|
|
2653
2657
|
if (shouldUpdateReasoningEffort) {
|
|
@@ -2662,15 +2666,29 @@ async function saveHermesModelConfig(input, profileName = "default", configPath
|
|
|
2662
2666
|
const currentDefaultConfig = readModelConfig(modelConfig);
|
|
2663
2667
|
const currentDefault = currentDefaultConfig.model;
|
|
2664
2668
|
const currentDefaultReasoningEffort = readProfileReasoningEffort(config);
|
|
2665
|
-
|
|
2666
|
-
|
|
2669
|
+
const currentDefaultMatchesOriginal = hasOriginalIdentity && modelConfigMatchesModelIdentity(currentDefaultConfig, originalIdentity);
|
|
2670
|
+
const currentDefaultMatchesNext = modelConfigMatchesModelIdentity(
|
|
2671
|
+
currentDefaultConfig,
|
|
2672
|
+
{
|
|
2673
|
+
id: normalized.id,
|
|
2674
|
+
provider: providerKey,
|
|
2675
|
+
baseUrl: normalized.baseUrl,
|
|
2676
|
+
apiMode: inferApiMode(
|
|
2677
|
+
providerKey,
|
|
2678
|
+
normalized.baseUrl,
|
|
2679
|
+
normalized.apiMode
|
|
2680
|
+
)
|
|
2681
|
+
}
|
|
2682
|
+
);
|
|
2683
|
+
if (normalized.setDefault || !currentDefault || currentDefaultMatchesOriginal) {
|
|
2684
|
+
if (normalized.setDefault && currentDefault && !currentDefaultMatchesNext && !currentDefaultMatchesOriginal) {
|
|
2667
2685
|
retainModelDefaultAsProvider(providers, {
|
|
2668
2686
|
...currentDefaultConfig,
|
|
2669
2687
|
...currentDefaultReasoningEffort ? { reasoningEffort: currentDefaultReasoningEffort } : {}
|
|
2670
2688
|
});
|
|
2671
2689
|
}
|
|
2672
|
-
const defaultKeyEnv = keyEnv ?? (
|
|
2673
|
-
const defaultApiKey = normalized.apiKey ?? (!defaultKeyEnv &&
|
|
2690
|
+
const defaultKeyEnv = keyEnv ?? (currentDefaultMatchesOriginal ? currentDefaultConfig.keyEnv : void 0);
|
|
2691
|
+
const defaultApiKey = normalized.apiKey ?? (!defaultKeyEnv && currentDefaultMatchesOriginal ? currentDefaultConfig.apiKey : void 0);
|
|
2674
2692
|
writeDefaultModelConfig(modelConfig, {
|
|
2675
2693
|
...normalized,
|
|
2676
2694
|
provider: providerKey,
|
|
@@ -2858,7 +2876,12 @@ async function saveHermesModelDefaults(input, profileName = "default", configPat
|
|
|
2858
2876
|
const modelConfig = ensureRecord(config, "model");
|
|
2859
2877
|
const currentDefaultConfig = readModelConfig(modelConfig);
|
|
2860
2878
|
const currentDefaultReasoningEffort = readProfileReasoningEffort(config);
|
|
2861
|
-
if (currentDefaultConfig.model && currentDefaultConfig
|
|
2879
|
+
if (currentDefaultConfig.model && !modelConfigMatchesModelIdentity(currentDefaultConfig, {
|
|
2880
|
+
id: selected.id,
|
|
2881
|
+
provider: selected.provider,
|
|
2882
|
+
baseUrl: selected.baseUrl,
|
|
2883
|
+
apiMode: selected.apiMode
|
|
2884
|
+
})) {
|
|
2862
2885
|
retainModelDefaultAsProvider(providers, {
|
|
2863
2886
|
...currentDefaultConfig,
|
|
2864
2887
|
...currentDefaultReasoningEffort ? { reasoningEffort: currentDefaultReasoningEffort } : {}
|
|
@@ -3472,6 +3495,11 @@ function providerConfigToLegacyEntry(providerKey, entry) {
|
|
|
3472
3495
|
}
|
|
3473
3496
|
function ensureProvidersRecordWithLegacyMigration(config) {
|
|
3474
3497
|
const providers = ensureRecord(config, "providers");
|
|
3498
|
+
for (const [key, rawEntry] of Object.entries(providers)) {
|
|
3499
|
+
const entry = toRecord(rawEntry);
|
|
3500
|
+
normalizeProviderCredentialReference(entry);
|
|
3501
|
+
providers[key] = entry;
|
|
3502
|
+
}
|
|
3475
3503
|
const customProviders = Array.isArray(config.custom_providers) ? config.custom_providers : [];
|
|
3476
3504
|
for (const rawEntry of customProviders) {
|
|
3477
3505
|
const entry = toRecord(rawEntry);
|
|
@@ -3609,7 +3637,7 @@ function legacyEntryToProviderConfig(entry, baseUrl) {
|
|
|
3609
3637
|
const apiKey = readString2(entry.api_key);
|
|
3610
3638
|
const keyEnv = readString2(entry.key_env) ?? parseEnvReference(apiKey);
|
|
3611
3639
|
if (keyEnv) {
|
|
3612
|
-
next.
|
|
3640
|
+
next.api_key = `\${${keyEnv}}`;
|
|
3613
3641
|
} else if (apiKey) {
|
|
3614
3642
|
next.api_key = apiKey;
|
|
3615
3643
|
}
|
|
@@ -3643,6 +3671,15 @@ function legacyEntryToProviderConfig(entry, baseUrl) {
|
|
|
3643
3671
|
}
|
|
3644
3672
|
return next;
|
|
3645
3673
|
}
|
|
3674
|
+
function normalizeProviderCredentialReference(entry) {
|
|
3675
|
+
const apiKey = readString2(entry.api_key);
|
|
3676
|
+
const keyEnv = readString2(entry.key_env) ?? parseEnvReference(apiKey);
|
|
3677
|
+
if (!keyEnv) {
|
|
3678
|
+
return;
|
|
3679
|
+
}
|
|
3680
|
+
entry.api_key = `\${${keyEnv}}`;
|
|
3681
|
+
delete entry.key_env;
|
|
3682
|
+
}
|
|
3646
3683
|
function normalizeEntryModelsMap(entry) {
|
|
3647
3684
|
const models = entry.models;
|
|
3648
3685
|
if (typeof models === "object" && models !== null && !Array.isArray(models)) {
|
|
@@ -3780,8 +3817,8 @@ function writeProviderEndpointConfig(entry, input, keyEnv) {
|
|
|
3780
3817
|
delete entry.contextLength;
|
|
3781
3818
|
}
|
|
3782
3819
|
if (keyEnv) {
|
|
3783
|
-
entry.
|
|
3784
|
-
delete entry.
|
|
3820
|
+
entry.api_key = `\${${keyEnv}}`;
|
|
3821
|
+
delete entry.key_env;
|
|
3785
3822
|
} else {
|
|
3786
3823
|
delete entry.key_env;
|
|
3787
3824
|
}
|
|
@@ -4041,22 +4078,18 @@ function managedModelPreferenceScore(model) {
|
|
|
4041
4078
|
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
4079
|
}
|
|
4043
4080
|
function matchesDefaultModelConfig(input) {
|
|
4044
|
-
if (!input.defaultModel
|
|
4045
|
-
return false;
|
|
4046
|
-
}
|
|
4047
|
-
const defaultApiMode = input.modelConfig.apiMode?.trim();
|
|
4048
|
-
if (defaultApiMode && input.apiMode !== defaultApiMode) {
|
|
4081
|
+
if (!input.defaultModel) {
|
|
4049
4082
|
return false;
|
|
4050
4083
|
}
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4084
|
+
return modelConfigMatchesModelIdentity(
|
|
4085
|
+
{ ...input.modelConfig, model: input.defaultModel },
|
|
4086
|
+
{
|
|
4087
|
+
id: input.id,
|
|
4088
|
+
provider: input.provider,
|
|
4089
|
+
baseUrl: input.baseUrl,
|
|
4090
|
+
apiMode: input.apiMode
|
|
4091
|
+
}
|
|
4092
|
+
);
|
|
4060
4093
|
}
|
|
4061
4094
|
function providerEntryMatchesManagedModel(entry, model) {
|
|
4062
4095
|
const providerName = readString2(entry.name) ?? readString2(entry.provider_name) ?? readString2(entry.provider_key) ?? "Custom Provider";
|
|
@@ -4266,6 +4299,29 @@ function resolveCompressionModel(config, models) {
|
|
|
4266
4299
|
function findManagedModelById(models, id) {
|
|
4267
4300
|
return models.find((model) => model.id === id);
|
|
4268
4301
|
}
|
|
4302
|
+
function modelConfigMatchesModelIdentity(modelConfig, input) {
|
|
4303
|
+
if (modelConfig.model !== input.id) {
|
|
4304
|
+
return false;
|
|
4305
|
+
}
|
|
4306
|
+
const provider = input.provider?.trim();
|
|
4307
|
+
const configProvider = modelConfig.provider?.trim();
|
|
4308
|
+
if (provider && configProvider && configProvider !== provider) {
|
|
4309
|
+
return false;
|
|
4310
|
+
}
|
|
4311
|
+
const baseUrl = input.baseUrl?.trim();
|
|
4312
|
+
if (baseUrl !== void 0 && normalizeBaseUrl(modelConfig.baseUrl ?? "") !== normalizeBaseUrl(baseUrl)) {
|
|
4313
|
+
return false;
|
|
4314
|
+
}
|
|
4315
|
+
const apiMode = input.apiMode?.trim();
|
|
4316
|
+
if (apiMode) {
|
|
4317
|
+
const providerForApiMode = configProvider ?? provider ?? "default";
|
|
4318
|
+
const configBaseUrl = modelConfig.baseUrl ?? baseUrl ?? "";
|
|
4319
|
+
if (inferApiMode(providerForApiMode, configBaseUrl, modelConfig.apiMode) !== apiMode) {
|
|
4320
|
+
return false;
|
|
4321
|
+
}
|
|
4322
|
+
}
|
|
4323
|
+
return true;
|
|
4324
|
+
}
|
|
4269
4325
|
function findManagedModel(models, input) {
|
|
4270
4326
|
const provider = input.provider?.trim();
|
|
4271
4327
|
const baseUrl = input.baseUrl?.trim();
|
|
@@ -4430,7 +4486,7 @@ function retainModelDefaultAsProvider(providers, model) {
|
|
|
4430
4486
|
writeEntryModelSupportsVision(entry, id, model.supportsVision);
|
|
4431
4487
|
}
|
|
4432
4488
|
if (model.keyEnv) {
|
|
4433
|
-
entry.
|
|
4489
|
+
entry.api_key = `\${${model.keyEnv}}`;
|
|
4434
4490
|
} else if (model.apiKey) {
|
|
4435
4491
|
entry.api_key = model.apiKey;
|
|
4436
4492
|
}
|
|
@@ -6454,7 +6510,7 @@ function isConversationMissingError(error) {
|
|
|
6454
6510
|
}
|
|
6455
6511
|
|
|
6456
6512
|
// src/constants.ts
|
|
6457
|
-
var LINK_VERSION = "0.7.5
|
|
6513
|
+
var LINK_VERSION = "0.7.5";
|
|
6458
6514
|
var LINK_COMMAND = "hermeslink";
|
|
6459
6515
|
var LINK_DEFAULT_PORT = 52379;
|
|
6460
6516
|
var LINK_RUNTIME_DIR_NAME = ".hermeslink";
|
|
@@ -25802,7 +25858,9 @@ function registerModelConfigRoutes(router, options) {
|
|
|
25802
25858
|
const body = await readJsonBody(ctx.req);
|
|
25803
25859
|
try {
|
|
25804
25860
|
const result = await saveHermesModelConfig(readModelConfigInput(body));
|
|
25805
|
-
ctx.body = shouldReloadGatewayAfterModelConfigChange(body
|
|
25861
|
+
ctx.body = shouldReloadGatewayAfterModelConfigChange(body, {
|
|
25862
|
+
defaultReload: true
|
|
25863
|
+
}) ? await reloadGatewayAfterModelConfigChange(result, {
|
|
25806
25864
|
paths,
|
|
25807
25865
|
logger
|
|
25808
25866
|
}) : markModelConfigAppliedWithoutGatewayReload(result);
|
|
@@ -25848,7 +25906,9 @@ function registerModelConfigRoutes(router, options) {
|
|
|
25848
25906
|
readModelConfigInput(body),
|
|
25849
25907
|
ctx.params.name
|
|
25850
25908
|
);
|
|
25851
|
-
ctx.body = shouldReloadGatewayAfterModelConfigChange(body
|
|
25909
|
+
ctx.body = shouldReloadGatewayAfterModelConfigChange(body, {
|
|
25910
|
+
defaultReload: true
|
|
25911
|
+
}) ? await reloadGatewayAfterProfileModelConfigChange(result, {
|
|
25852
25912
|
paths,
|
|
25853
25913
|
logger,
|
|
25854
25914
|
profileName: ctx.params.name
|
|
@@ -26001,15 +26061,20 @@ function readModelConfigImportInput(body) {
|
|
|
26001
26061
|
setDefault: readBoolean3(body.set_default ?? body.setDefault)
|
|
26002
26062
|
};
|
|
26003
26063
|
}
|
|
26004
|
-
function shouldReloadGatewayAfterModelConfigChange(body) {
|
|
26005
|
-
|
|
26006
|
-
|
|
26064
|
+
function shouldReloadGatewayAfterModelConfigChange(body, options = {}) {
|
|
26065
|
+
if (readBoolean3(body.skip_gateway_reload ?? body.skipGatewayReload) === true) {
|
|
26066
|
+
return false;
|
|
26067
|
+
}
|
|
26068
|
+
if (readBoolean3(body.reload_gateway ?? body.reloadGateway) === true) {
|
|
26069
|
+
return true;
|
|
26070
|
+
}
|
|
26071
|
+
return options.defaultReload === true;
|
|
26007
26072
|
}
|
|
26008
26073
|
function markModelConfigAppliedWithoutGatewayReload(result) {
|
|
26009
26074
|
return {
|
|
26010
26075
|
...result,
|
|
26011
26076
|
requiresGatewayReload: false,
|
|
26012
|
-
restartHint: "\u6A21\u578B\u914D\u7F6E\u5DF2\u4FDD\u5B58\
|
|
26077
|
+
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
26078
|
};
|
|
26014
26079
|
}
|
|
26015
26080
|
function toModelConfigHttpError(error) {
|
package/dist/cli/index.js
CHANGED
package/dist/http/app.js
CHANGED