scalemax 0.1.50 → 0.1.51
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/dist/configure/hermes.js +18 -10
- package/dist/configure/models.js +1 -0
- package/dist/configure/paths.d.ts +7 -0
- package/dist/configure/paths.js +16 -2
- package/package.json +1 -1
package/dist/configure/hermes.js
CHANGED
|
@@ -2,7 +2,7 @@ import path from 'node:path';
|
|
|
2
2
|
import fs from 'fs-extra';
|
|
3
3
|
import { parseDocument } from 'yaml';
|
|
4
4
|
import { atomicWrite, backupFile, captureFileSnapshots, restoreFileSnapshots, snapshotRollback } from '../utils/fs.js';
|
|
5
|
-
import { clientConfigPath } from './paths.js';
|
|
5
|
+
import { clientConfigPath, hermesHome } from './paths.js';
|
|
6
6
|
import { isScaleMaxApiUrl, isScaleMaxManagedText } from './common.js';
|
|
7
7
|
import { anthropicModelIds, anthropicOrigin, deepSeekChatModelIds, modelIdKey, modelSupportsTools, openAiBaseUrl, openAiResponsesModelIds, preferredAnthropicModel, preferredOpenAiResponsesModel } from './models.js';
|
|
8
8
|
const id = 'hermes';
|
|
@@ -27,7 +27,7 @@ function exactChatLabel(ids) {
|
|
|
27
27
|
function asRecord(value) {
|
|
28
28
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
29
29
|
}
|
|
30
|
-
function envPath(
|
|
30
|
+
function envPath(ctx) { return path.join(hermesHome(ctx.home, ctx.platform, ctx.env), '.env'); }
|
|
31
31
|
function managedEnv(text, apiKey) {
|
|
32
32
|
const kept = text.split(/\r?\n/).filter(line => line.trim() !== envMarker && !line.startsWith(`${envKey}=`));
|
|
33
33
|
while (kept.length && !kept[kept.length - 1])
|
|
@@ -73,8 +73,8 @@ async function removeLegacyArtifact(ctx) {
|
|
|
73
73
|
return true;
|
|
74
74
|
}
|
|
75
75
|
export async function configure(ctx) {
|
|
76
|
-
const file = clientConfigPath(id, ctx.home, ctx.platform);
|
|
77
|
-
const secrets = envPath(ctx
|
|
76
|
+
const file = clientConfigPath(id, ctx.home, ctx.platform, ctx.env);
|
|
77
|
+
const secrets = envPath(ctx);
|
|
78
78
|
const legacy = path.join(ctx.home, '.hermes', 'config', 'scalemax.json');
|
|
79
79
|
const snapshots = await captureFileSnapshots([file, secrets, legacy]);
|
|
80
80
|
await fs.ensureDir(path.dirname(file), 0o700);
|
|
@@ -127,7 +127,12 @@ export async function configure(ctx) {
|
|
|
127
127
|
doc.set('custom_providers', providers);
|
|
128
128
|
const currentModel = asRecord(data.model);
|
|
129
129
|
const currentProvider = String(currentModel.provider || '');
|
|
130
|
-
|
|
130
|
+
// "auto" is Hermes's own unchosen default: the native Windows installer
|
|
131
|
+
// writes provider "auto" with an OpenRouter base_url into a fresh
|
|
132
|
+
// config.yaml, which left ScaleMax listed but never active ("No inference
|
|
133
|
+
// provider is configured yet"). A provider the user picked is left alone.
|
|
134
|
+
const unchosen = !currentProvider || currentProvider === 'auto';
|
|
135
|
+
const activatesScaleMax = unchosen || currentProvider.startsWith('custom:scalemax');
|
|
131
136
|
if (activatesScaleMax) {
|
|
132
137
|
const keepClaude = currentProvider === `custom:${claudeProviderName}` || claudeIds.includes(String(currentModel.default || ''));
|
|
133
138
|
const keepDeepSeek = currentProvider === `custom:${deepSeekProviderName}`
|
|
@@ -142,7 +147,10 @@ export async function configure(ctx) {
|
|
|
142
147
|
const activeModel = activeName === codexProviderName
|
|
143
148
|
? preferredOpenAiResponsesModel(ctx)
|
|
144
149
|
: activeName === chatProviderName ? deepSeekIds[0] : preferredAnthropicModel(ctx);
|
|
145
|
-
|
|
150
|
+
// The custom provider carries its own base_url; a leftover model.base_url
|
|
151
|
+
// from the "auto" template would point Hermes back at OpenRouter.
|
|
152
|
+
const { base_url: _unchosenBaseUrl, ...keptModel } = currentModel;
|
|
153
|
+
doc.set('model', { ...(unchosen ? keptModel : currentModel), provider: `custom:${activeName}`, default: activeModel, max_tokens: 4096 });
|
|
146
154
|
}
|
|
147
155
|
const nextConfig = String(doc);
|
|
148
156
|
const nextEnv = managedEnv(originalEnv, ctx.apiKey);
|
|
@@ -184,8 +192,8 @@ export async function configure(ctx) {
|
|
|
184
192
|
};
|
|
185
193
|
}
|
|
186
194
|
export async function verify(ctx) {
|
|
187
|
-
const file = clientConfigPath(id, ctx.home, ctx.platform);
|
|
188
|
-
const secrets = envPath(ctx
|
|
195
|
+
const file = clientConfigPath(id, ctx.home, ctx.platform, ctx.env);
|
|
196
|
+
const secrets = envPath(ctx);
|
|
189
197
|
const doc = parseYaml(await fs.readFile(file, 'utf8'));
|
|
190
198
|
const data = asRecord(doc.toJS());
|
|
191
199
|
const providers = Array.isArray(data.custom_providers) ? data.custom_providers : [];
|
|
@@ -215,8 +223,8 @@ export async function verify(ctx) {
|
|
|
215
223
|
return { id, name, changed: false, path: file, message: `verified ${codexIds.length} Codex/OpenAI, ${deepSeekIds.length} ${chatLabel}, and ${claudeIds.length} Claude models` };
|
|
216
224
|
}
|
|
217
225
|
export async function remove(ctx) {
|
|
218
|
-
const file = clientConfigPath(id, ctx.home, ctx.platform);
|
|
219
|
-
const secrets = envPath(ctx
|
|
226
|
+
const file = clientConfigPath(id, ctx.home, ctx.platform, ctx.env);
|
|
227
|
+
const secrets = envPath(ctx);
|
|
220
228
|
const currentEnv = await fs.readFile(secrets, 'utf8').catch(() => '');
|
|
221
229
|
if (!(await fs.pathExists(file))) {
|
|
222
230
|
const removedLegacy = await removeLegacyArtifact(ctx);
|
package/dist/configure/models.js
CHANGED
|
@@ -2,5 +2,12 @@ import { ClientId } from '../types/client.js';
|
|
|
2
2
|
export declare function codexDir(home: string): string;
|
|
3
3
|
export declare function codexConfigPath(home: string): string;
|
|
4
4
|
export declare function codexAuthPath(home: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Hermes Agent's home: HERMES_HOME when set, else its platform default.
|
|
7
|
+
* Native Windows Hermes keeps config.yaml and .env in %LOCALAPPDATA%\\hermes
|
|
8
|
+
* and never reads ~/.hermes (hermes_constants._get_platform_default_hermes_home),
|
|
9
|
+
* so writing ~/.hermes there left Hermes with no ScaleMax provider.
|
|
10
|
+
*/
|
|
11
|
+
export declare function hermesHome(home: string, platform: NodeJS.Platform, env?: NodeJS.ProcessEnv): string;
|
|
5
12
|
export declare function clientConfigPath(id: ClientId, home: string, platform: NodeJS.Platform, env?: NodeJS.ProcessEnv): string;
|
|
6
13
|
export declare function installHints(id: ClientId, home: string, platform: NodeJS.Platform, env?: NodeJS.ProcessEnv): string[];
|
package/dist/configure/paths.js
CHANGED
|
@@ -3,6 +3,20 @@ import { configRoot } from '../utils/paths.js';
|
|
|
3
3
|
export function codexDir(home) { return path.join(home, '.codex'); }
|
|
4
4
|
export function codexConfigPath(home) { return path.join(codexDir(home), 'config.toml'); }
|
|
5
5
|
export function codexAuthPath(home) { return path.join(codexDir(home), 'auth.json'); }
|
|
6
|
+
/**
|
|
7
|
+
* Hermes Agent's home: HERMES_HOME when set, else its platform default.
|
|
8
|
+
* Native Windows Hermes keeps config.yaml and .env in %LOCALAPPDATA%\\hermes
|
|
9
|
+
* and never reads ~/.hermes (hermes_constants._get_platform_default_hermes_home),
|
|
10
|
+
* so writing ~/.hermes there left Hermes with no ScaleMax provider.
|
|
11
|
+
*/
|
|
12
|
+
export function hermesHome(home, platform, env = process.env) {
|
|
13
|
+
const explicit = env.HERMES_HOME?.trim();
|
|
14
|
+
if (explicit)
|
|
15
|
+
return explicit;
|
|
16
|
+
if (platform === 'win32')
|
|
17
|
+
return path.join(env.LOCALAPPDATA?.trim() || path.join(home, 'AppData', 'Local'), 'hermes');
|
|
18
|
+
return path.join(home, '.hermes');
|
|
19
|
+
}
|
|
6
20
|
export function clientConfigPath(id, home, platform, env = process.env) {
|
|
7
21
|
const app = configRoot(home, platform, env);
|
|
8
22
|
const linux = env.XDG_CONFIG_HOME || path.join(home, '.config');
|
|
@@ -23,7 +37,7 @@ export function clientConfigPath(id, home, platform, env = process.env) {
|
|
|
23
37
|
case 'claude': return path.join(home, '.claude', 'settings.json');
|
|
24
38
|
case 'opencode': return path.join(linux, 'opencode', 'opencode.json');
|
|
25
39
|
case 'openclaw': return path.join(home, '.openclaw', 'openclaw.json');
|
|
26
|
-
case 'hermes': return path.join(home,
|
|
40
|
+
case 'hermes': return path.join(hermesHome(home, platform, env), 'config.yaml');
|
|
27
41
|
case 'cherry-studio': return path.join(home, '.scalemax', 'cherry-studio.setup.json');
|
|
28
42
|
case 'api-code': return path.join(home, '.scalemax', 'api-code.examples.json');
|
|
29
43
|
}
|
|
@@ -41,7 +55,7 @@ export function installHints(id, home, platform, env = process.env) {
|
|
|
41
55
|
case 'claude': return [path.join(home, '.claude')];
|
|
42
56
|
case 'opencode': return [path.join(linux, 'opencode')];
|
|
43
57
|
case 'openclaw': return [path.join(home, '.openclaw'), path.join(linux, 'openclaw')];
|
|
44
|
-
case 'hermes': return [path.join(home, '.hermes')];
|
|
58
|
+
case 'hermes': return [...new Set([hermesHome(home, platform, env), path.join(home, '.hermes')])];
|
|
45
59
|
case 'cherry-studio': return [platform === 'darwin' ? '/Applications/Cherry Studio.app' : path.join(app, 'Cherry Studio'), path.join(linux, 'CherryStudio')];
|
|
46
60
|
case 'api-code': return [path.join(home, '.scalemax')];
|
|
47
61
|
}
|