scalemax 0.1.24 → 0.1.25
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
CHANGED
|
@@ -148,7 +148,7 @@ ScaleMax configures the official Codex custom-provider interface in `~/.codex/co
|
|
|
148
148
|
|
|
149
149
|
### Claude Code
|
|
150
150
|
|
|
151
|
-
ScaleMax updates `~/.claude/settings.json` with `ANTHROPIC_BASE_URL=https://api.scalemax.pro`, gateway model discovery, and a cached `apiKeyHelper` that reads a private `~/.claude/scalemax.key` file. The raw key is not stored in the settings JSON. The Anthropic base URL intentionally has no `/v1` suffix because Claude Code adds `/v1/messages` itself. The CLI preserves unrelated settings, selects a live main model from the authenticated catalog (preferring `claude-opus-4-8`), pins authenticated Haiku for lightweight background work when available, and sets `CLAUDE_CODE_DISABLE_THINKING=1` because third-party Anthropic-compatible providers do not support Claude Code's proprietary extended-thinking control envelope. It verifies a one-token Messages request and, if verification fails, removes only the ScaleMax-managed changes. Claude Code picker aliases such as `claude-opus-4-8[1m]` are normalized by the gateway.
|
|
151
|
+
ScaleMax updates `~/.claude/settings.json` with `ANTHROPIC_BASE_URL=https://api.scalemax.pro`, gateway model discovery, and a cached `apiKeyHelper` that reads a private `~/.claude/scalemax.key` file. The raw key is not stored in the settings JSON. Because Claude Code's gateway discovery only accepts IDs beginning with `claude` or `anthropic`, a catalog that includes Fable also receives a managed `ANTHROPIC_CUSTOM_MODEL_OPTION=fable-5` entry (with a friendly name and description), making `/model fable-5` selectable; any prior custom picker values are restored when ScaleMax configuration is removed. The Anthropic base URL intentionally has no `/v1` suffix because Claude Code adds `/v1/messages` itself. The CLI preserves unrelated settings, selects a live main model from the authenticated catalog (preferring `claude-opus-4-8`), pins authenticated Haiku for lightweight background work when available, and sets `CLAUDE_CODE_DISABLE_THINKING=1` because third-party Anthropic-compatible providers do not support Claude Code's proprietary extended-thinking control envelope. It verifies a one-token Messages request and, if verification fails, removes only the ScaleMax-managed changes. Claude Code picker aliases such as `claude-opus-4-8[1m]` are normalized by the gateway.
|
|
152
152
|
|
|
153
153
|
### OpenCode
|
|
154
154
|
|
package/dist/configure/claude.js
CHANGED
|
@@ -14,7 +14,29 @@ const discoveryKey = 'CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY';
|
|
|
14
14
|
const fastModelKey = 'ANTHROPIC_DEFAULT_HAIKU_MODEL';
|
|
15
15
|
const helperTtlKey = 'CLAUDE_CODE_API_KEY_HELPER_TTL_MS';
|
|
16
16
|
const disableThinkingKey = 'CLAUDE_CODE_DISABLE_THINKING';
|
|
17
|
-
|
|
17
|
+
// Claude Code's gateway discovery intentionally ignores model IDs that do not
|
|
18
|
+
// start with `claude` or `anthropic`. Fable's public ScaleMax ID is
|
|
19
|
+
// deliberately `fable-5`, so keep it selectable with the supported custom
|
|
20
|
+
// picker entry as well as the normal discovery feed.
|
|
21
|
+
const customModelOptionKey = 'ANTHROPIC_CUSTOM_MODEL_OPTION';
|
|
22
|
+
const customModelOptionNameKey = 'ANTHROPIC_CUSTOM_MODEL_OPTION_NAME';
|
|
23
|
+
const customModelOptionDescriptionKey = 'ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION';
|
|
24
|
+
const fableModelId = 'fable-5';
|
|
25
|
+
const fableModelName = 'Fable 5';
|
|
26
|
+
const fableModelDescription = 'Fable 5 via ScaleMax';
|
|
27
|
+
const managedEnvKeys = [
|
|
28
|
+
'ANTHROPIC_AUTH_TOKEN',
|
|
29
|
+
'ANTHROPIC_API_KEY',
|
|
30
|
+
'ANTHROPIC_BASE_URL',
|
|
31
|
+
'ANTHROPIC_MODEL',
|
|
32
|
+
customModelOptionKey,
|
|
33
|
+
customModelOptionNameKey,
|
|
34
|
+
customModelOptionDescriptionKey,
|
|
35
|
+
discoveryKey,
|
|
36
|
+
fastModelKey,
|
|
37
|
+
helperTtlKey,
|
|
38
|
+
disableThinkingKey
|
|
39
|
+
];
|
|
18
40
|
function secretPath(home) { return path.join(home, '.claude', 'scalemax.key'); }
|
|
19
41
|
function helperCommand(home, platform) {
|
|
20
42
|
const file = secretPath(home);
|
|
@@ -25,10 +47,17 @@ function helperCommand(home, platform) {
|
|
|
25
47
|
function asRecord(value) {
|
|
26
48
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
27
49
|
}
|
|
50
|
+
function hasFableModel(ctx) {
|
|
51
|
+
return (ctx.models || []).some(model => {
|
|
52
|
+
const id = String(model.id || '').trim().toLowerCase();
|
|
53
|
+
return id === fableModelId || id === 'claude-fable-5';
|
|
54
|
+
});
|
|
55
|
+
}
|
|
28
56
|
export async function configure(ctx) {
|
|
29
57
|
const file = clientConfigPath(id, ctx.home, ctx.platform);
|
|
30
58
|
const model = preferredModel(ctx);
|
|
31
59
|
const quick = fastModel(ctx);
|
|
60
|
+
const fable = hasFableModel(ctx);
|
|
32
61
|
const baseUrl = anthropicOrigin(ctx.baseUrl);
|
|
33
62
|
const apiKeyHelper = helperCommand(ctx.home, ctx.platform);
|
|
34
63
|
const secret = await writeClientSecret(secretPath(ctx.home), ctx);
|
|
@@ -51,6 +80,25 @@ export async function configure(ctx) {
|
|
|
51
80
|
[helperTtlKey]: '900000',
|
|
52
81
|
[disableThinkingKey]: '1'
|
|
53
82
|
};
|
|
83
|
+
if (fable) {
|
|
84
|
+
// This is a public model ID, not an upstream/provider alias. Claude
|
|
85
|
+
// Code's custom option bypasses its `claude*` discovery filter while
|
|
86
|
+
// still sending exactly `fable-5` to the configured gateway.
|
|
87
|
+
nextEnv[customModelOptionKey] = fableModelId;
|
|
88
|
+
nextEnv[customModelOptionNameKey] = fableModelName;
|
|
89
|
+
nextEnv[customModelOptionDescriptionKey] = fableModelDescription;
|
|
90
|
+
}
|
|
91
|
+
else if (oldMetadata.managedBy === 'ScaleMax CLI') {
|
|
92
|
+
// A key can be reconfigured from a Fable-enabled catalog to one that
|
|
93
|
+
// does not include Fable. Remove only the values this CLI previously
|
|
94
|
+
// managed, restoring any user values captured on the first configure.
|
|
95
|
+
for (const key of [customModelOptionKey, customModelOptionNameKey, customModelOptionDescriptionKey]) {
|
|
96
|
+
if (Object.prototype.hasOwnProperty.call(previousEnv, key))
|
|
97
|
+
nextEnv[key] = previousEnv[key];
|
|
98
|
+
else if (nextEnv[key] === fableModelId || nextEnv[key] === fableModelName || nextEnv[key] === fableModelDescription)
|
|
99
|
+
delete nextEnv[key];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
54
102
|
delete nextEnv.ANTHROPIC_AUTH_TOKEN;
|
|
55
103
|
delete nextEnv.ANTHROPIC_API_KEY;
|
|
56
104
|
if (quick)
|
|
@@ -70,6 +118,9 @@ export async function configure(ctx) {
|
|
|
70
118
|
fastModel: quick || null,
|
|
71
119
|
helperTtl: '900000',
|
|
72
120
|
disableThinking: '1',
|
|
121
|
+
customModelOption: fable ? fableModelId : null,
|
|
122
|
+
customModelOptionName: fable ? fableModelName : null,
|
|
123
|
+
customModelOptionDescription: fable ? fableModelDescription : null,
|
|
73
124
|
apiKeyHelper,
|
|
74
125
|
authTokenSha256: crypto.createHash('sha256').update(ctx.apiKey).digest('hex'),
|
|
75
126
|
previousEnv,
|
|
@@ -89,7 +140,12 @@ export async function verify(ctx) {
|
|
|
89
140
|
const settings = await fs.readJson(file);
|
|
90
141
|
const env = asRecord(settings?.env);
|
|
91
142
|
const model = String(env.ANTHROPIC_MODEL || '');
|
|
92
|
-
|
|
143
|
+
const fable = hasFableModel(ctx);
|
|
144
|
+
const customModelMatches = !fable
|
|
145
|
+
|| (env[customModelOptionKey] === fableModelId
|
|
146
|
+
&& env[customModelOptionNameKey] === fableModelName
|
|
147
|
+
&& env[customModelOptionDescriptionKey] === fableModelDescription);
|
|
148
|
+
if (!modelIds(ctx).includes(model) || !customModelMatches || env.ANTHROPIC_BASE_URL !== anthropicOrigin(ctx.baseUrl) || settings.apiKeyHelper !== helperCommand(ctx.home, ctx.platform) || env.ANTHROPIC_AUTH_TOKEN || env.ANTHROPIC_API_KEY || env[discoveryKey] !== '1' || env[disableThinkingKey] !== '1') {
|
|
93
149
|
throw new Error('Claude Code settings do not match the authenticated ScaleMax model catalog.');
|
|
94
150
|
}
|
|
95
151
|
await verifyClientSecret(secretPath(ctx.home), ctx);
|
|
@@ -143,6 +199,12 @@ export async function remove(ctx) {
|
|
|
143
199
|
restore(helperTtlKey);
|
|
144
200
|
if (env[disableThinkingKey] === managed.disableThinking)
|
|
145
201
|
restore(disableThinkingKey);
|
|
202
|
+
if (env[customModelOptionKey] === managed.customModelOption)
|
|
203
|
+
restore(customModelOptionKey);
|
|
204
|
+
if (env[customModelOptionNameKey] === managed.customModelOptionName)
|
|
205
|
+
restore(customModelOptionNameKey);
|
|
206
|
+
if (env[customModelOptionDescriptionKey] === managed.customModelOptionDescription)
|
|
207
|
+
restore(customModelOptionDescriptionKey);
|
|
146
208
|
if (!Object.prototype.hasOwnProperty.call(env, 'ANTHROPIC_AUTH_TOKEN'))
|
|
147
209
|
restore('ANTHROPIC_AUTH_TOKEN');
|
|
148
210
|
if (!Object.prototype.hasOwnProperty.call(env, 'ANTHROPIC_API_KEY'))
|
package/dist/configure/models.js
CHANGED
|
@@ -11,7 +11,7 @@ export function jsonConfig(client, apiKey, baseUrl, extra = {}) {
|
|
|
11
11
|
}, null, 2) + '\n';
|
|
12
12
|
}
|
|
13
13
|
export function continueConfig(apiKey, baseUrl) {
|
|
14
|
-
const models = ['
|
|
14
|
+
const models = ['gpt-5.6-sol', 'gpt-5.6-luna', 'gpt-5.6-terra', 'gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.3-codex', 'codex-auto-review'];
|
|
15
15
|
return JSON.stringify({
|
|
16
16
|
models: models.map(model => ({
|
|
17
17
|
title: `ScaleMax ${model}`,
|
|
@@ -5,7 +5,7 @@ const id = 'trae-solo';
|
|
|
5
5
|
const name = 'TRAE SOLO';
|
|
6
6
|
export async function configure(ctx) {
|
|
7
7
|
const file = clientConfigPath(id, ctx.home, ctx.platform);
|
|
8
|
-
const content = jsonConfig(name, '$SCALEMAX_API_KEY', ctx.baseUrl, { "officialSetup": ["Settings > Models > Add Model", "API format: OpenAI Chat Completions", `Request URL: ${ctx.baseUrl}/chat/completions or base URL ${ctx.baseUrl}`, "Use only a model ID returned by the authenticated catalog"], "recommendedModel": "
|
|
8
|
+
const content = jsonConfig(name, '$SCALEMAX_API_KEY', ctx.baseUrl, { "officialSetup": ["Settings > Models > Add Model", "API format: OpenAI Chat Completions", `Request URL: ${ctx.baseUrl}/chat/completions or base URL ${ctx.baseUrl}`, "Use only a model ID returned by the authenticated catalog"], "recommendedModel": "gpt-5.4-mini" });
|
|
9
9
|
const result = await writeManagedConfig(ctx, id, name, file, content);
|
|
10
10
|
return { ...result, message: 'setup guide written; enter these values in TRAE SOLO custom model settings' };
|
|
11
11
|
}
|