scalemax 0.1.43 → 0.1.45
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/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 = ['gpt-6-astra', 'gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.3-codex', 'codex-auto-review', 'deepseek-v4-flash'];
|
|
14
|
+
const models = ['gpt-6-astra', 'gpt-6-sol', 'gpt-6-luna', 'gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.3-codex', 'codex-auto-review', 'deepseek-v4-flash'];
|
|
15
15
|
return JSON.stringify({
|
|
16
16
|
models: models.map(model => ({
|
|
17
17
|
title: model === 'deepseek-v4-flash' ? 'ScaleMax DeepSeek V4 Flash' : `ScaleMax ${model}`,
|
package/dist/install/codex.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
export declare function parseCodexSemver(text?: string): string | undefined;
|
|
2
|
+
export declare function compareCodexSemver(a: string, b: string): number;
|
|
1
3
|
export declare function isCodexExecutableAvailable(): Promise<boolean>;
|
|
2
4
|
export declare function getCodexVersion(): Promise<string | undefined>;
|
|
5
|
+
export declare function resolveLatestCodexVersion(): Promise<string | undefined>;
|
|
3
6
|
export declare function installCodexWithNpm(): Promise<{
|
|
4
7
|
ok: boolean;
|
|
5
8
|
message: string;
|
package/dist/install/codex.js
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
import { confirm, isCancel } from '@clack/prompts';
|
|
2
2
|
import { execa } from 'execa';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
3
5
|
import { commandExists } from '../utils/exec.js';
|
|
6
|
+
const PKG = '@openai/codex';
|
|
7
|
+
const NPMJS = 'https://registry.npmjs.org/';
|
|
8
|
+
function npmCmd() { return process.platform === 'win32' ? 'npm.cmd' : 'npm'; }
|
|
9
|
+
function specFor(ver) { return ver ? `${PKG}@${ver}` : `${PKG}@latest`; }
|
|
10
|
+
function installHint(ver) { return `npm install -g ${specFor(ver)} --prefer-online`; }
|
|
11
|
+
export function parseCodexSemver(text) {
|
|
12
|
+
const m = String(text ?? '').match(/(?<![\d.])(\d+\.\d+\.\d+)(?![\d.])/);
|
|
13
|
+
return m?.[1];
|
|
14
|
+
}
|
|
15
|
+
export function compareCodexSemver(a, b) {
|
|
16
|
+
const pa = a.replace(/^v/, '').split('.').map(n => parseInt(n, 10) || 0);
|
|
17
|
+
const pb = b.replace(/^v/, '').split('.').map(n => parseInt(n, 10) || 0);
|
|
18
|
+
for (let i = 0; i < 3; i++) {
|
|
19
|
+
const d = (pa[i] || 0) - (pb[i] || 0);
|
|
20
|
+
if (d)
|
|
21
|
+
return d;
|
|
22
|
+
}
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
4
25
|
export async function isCodexExecutableAvailable() { return commandExists('codex'); }
|
|
5
26
|
export async function getCodexVersion() { try {
|
|
6
27
|
return (await execa('codex', ['--version'], { reject: false })).stdout.trim();
|
|
@@ -8,32 +29,140 @@ export async function getCodexVersion() { try {
|
|
|
8
29
|
catch {
|
|
9
30
|
return undefined;
|
|
10
31
|
} }
|
|
32
|
+
async function viewLatest(useNpmjs) {
|
|
33
|
+
const args = ['view', `${PKG}@latest`, 'version', '--prefer-online'];
|
|
34
|
+
if (useNpmjs)
|
|
35
|
+
args.push(`--registry=${NPMJS}`);
|
|
36
|
+
try {
|
|
37
|
+
const res = await execa(npmCmd(), args, { reject: false, timeout: 15000 });
|
|
38
|
+
if (res.exitCode !== 0)
|
|
39
|
+
return undefined;
|
|
40
|
+
return parseCodexSemver(res.stdout);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function resolveLatestCodexVersion() {
|
|
47
|
+
return (await viewLatest(true)) ?? (await viewLatest(false));
|
|
48
|
+
}
|
|
49
|
+
async function npmInstall(spec, registry) {
|
|
50
|
+
const args = ['install', '-g', spec, '--prefer-online'];
|
|
51
|
+
if (registry)
|
|
52
|
+
args.push(`--registry=${registry}`);
|
|
53
|
+
return execa(npmCmd(), args, { all: true, reject: false, stdio: 'pipe' });
|
|
54
|
+
}
|
|
55
|
+
async function npmGlobalBinDir() {
|
|
56
|
+
try {
|
|
57
|
+
const prefix = (await execa(npmCmd(), ['prefix', '-g'], { reject: false })).stdout.trim();
|
|
58
|
+
if (!prefix)
|
|
59
|
+
return undefined;
|
|
60
|
+
return process.platform === 'win32' ? prefix : path.join(prefix, 'bin');
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function npmGlobalCodexPath(binDir) {
|
|
67
|
+
return path.join(binDir, process.platform === 'win32' ? 'codex.cmd' : 'codex');
|
|
68
|
+
}
|
|
69
|
+
async function whichCodex() {
|
|
70
|
+
try {
|
|
71
|
+
if (process.platform === 'win32') {
|
|
72
|
+
const res = await execa('where', ['codex'], { reject: false });
|
|
73
|
+
return res.stdout.trim().split(/\r?\n/)[0] || undefined;
|
|
74
|
+
}
|
|
75
|
+
const res = await execa('which', ['codex'], { reject: false });
|
|
76
|
+
return res.stdout.trim() || undefined;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function versionAt(bin) {
|
|
83
|
+
try {
|
|
84
|
+
return parseCodexSemver((await execa(bin, ['--version'], { reject: false })).stdout);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function inspectNpmCodex() {
|
|
91
|
+
const binDir = await npmGlobalBinDir();
|
|
92
|
+
if (!binDir)
|
|
93
|
+
return {};
|
|
94
|
+
const bin = npmGlobalCodexPath(binDir);
|
|
95
|
+
if (!fs.existsSync(bin))
|
|
96
|
+
return { binDir };
|
|
97
|
+
return { binDir, bin, version: await versionAt(bin) };
|
|
98
|
+
}
|
|
11
99
|
export async function installCodexWithNpm() {
|
|
12
|
-
const
|
|
13
|
-
const
|
|
100
|
+
const target = await resolveLatestCodexVersion();
|
|
101
|
+
const spec = specFor(target);
|
|
102
|
+
const hint = installHint(target);
|
|
14
103
|
try {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
104
|
+
let res = await npmInstall(spec);
|
|
105
|
+
let inspected = await inspectNpmCodex();
|
|
106
|
+
let pathVer = parseCodexSemver(await getCodexVersion());
|
|
107
|
+
const yielded = inspected.version ?? pathVer;
|
|
108
|
+
const older = Boolean(target && yielded && compareCodexSemver(yielded, target) < 0);
|
|
109
|
+
if (res.exitCode !== 0 || older) {
|
|
110
|
+
const retry = await npmInstall(spec, NPMJS);
|
|
111
|
+
if (retry.exitCode === 0) {
|
|
112
|
+
res = retry;
|
|
113
|
+
inspected = await inspectNpmCodex();
|
|
114
|
+
pathVer = parseCodexSemver(await getCodexVersion());
|
|
115
|
+
}
|
|
116
|
+
else if (res.exitCode !== 0) {
|
|
117
|
+
return { ok: false, message: `npm install exited with ${retry.exitCode}.`, output: retry.all };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
pathVer = parseCodexSemver(await getCodexVersion());
|
|
121
|
+
if (target && pathVer && compareCodexSemver(pathVer, target) < 0) {
|
|
122
|
+
const npmVer = inspected.version;
|
|
123
|
+
if (inspected.bin && inspected.binDir && npmVer && compareCodexSemver(npmVer, target) >= 0) {
|
|
124
|
+
const shadowed = (await whichCodex()) || 'codex';
|
|
125
|
+
return { ok: true, message: `Codex ${npmVer} installed at ${inspected.bin}, but an older Codex (${pathVer}) at ${shadowed} is shadowing it on PATH. Remove the older binary or put ${inspected.binDir} first on PATH.`, output: res.all };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (res.exitCode !== 0)
|
|
129
|
+
return { ok: false, message: `npm install exited with ${res.exitCode}.`, output: res.all };
|
|
130
|
+
return { ok: true, message: 'Codex installed with npm.', output: res.all };
|
|
19
131
|
}
|
|
20
132
|
catch (err) {
|
|
21
|
-
return { ok: false, message: `Could not run
|
|
133
|
+
return { ok: false, message: `Could not run ${hint}: ${err instanceof Error ? err.message : String(err)}` };
|
|
22
134
|
}
|
|
23
135
|
}
|
|
24
136
|
export async function ensureCodexInstalled(interactive = true) {
|
|
25
|
-
if (await isCodexExecutableAvailable())
|
|
26
|
-
|
|
137
|
+
if (await isCodexExecutableAvailable()) {
|
|
138
|
+
const raw = await getCodexVersion();
|
|
139
|
+
const current = parseCodexSemver(raw);
|
|
140
|
+
const latest = await resolveLatestCodexVersion().catch(() => undefined);
|
|
141
|
+
if (!latest || !current || compareCodexSemver(current, latest) >= 0) {
|
|
142
|
+
return { ok: true, installed: false, message: `Codex detected${raw ? ` (${raw})` : ''}.` };
|
|
143
|
+
}
|
|
144
|
+
if (!interactive) {
|
|
145
|
+
return { ok: true, installed: false, message: `Codex detected (${raw ?? current}). Update available: ${latest}. Run ${installHint(latest)} to update.` };
|
|
146
|
+
}
|
|
147
|
+
const ans = await confirm({ message: `Codex ${current} is installed; update to latest ${latest}?`, initialValue: true });
|
|
148
|
+
if (isCancel(ans) || ans === false)
|
|
149
|
+
return { ok: true, installed: false, message: `Codex detected (${raw ?? current}).` };
|
|
150
|
+
const res = await installCodexWithNpm();
|
|
151
|
+
if (!res.ok)
|
|
152
|
+
return { ok: false, installed: false, message: `${res.message}\nIf this is a permission issue, install Node with nvm/fnm/volta or run: ${installHint(latest)}` };
|
|
153
|
+
return { ok: true, installed: true, message: res.message.includes('shadowing') ? res.message : 'Codex installed and detected.' };
|
|
154
|
+
}
|
|
27
155
|
if (!interactive)
|
|
28
156
|
return { ok: false, installed: false, message: 'Codex executable was not found on PATH.' };
|
|
29
|
-
const
|
|
157
|
+
const latest = await resolveLatestCodexVersion().catch(() => undefined);
|
|
158
|
+
const hint = installHint(latest);
|
|
159
|
+
const ans = await confirm({ message: `Codex CLI is not installed. Install it now with ${hint}?`, initialValue: true });
|
|
30
160
|
if (isCancel(ans) || ans === false)
|
|
31
161
|
return { ok: false, installed: false, message: 'Codex installation skipped.' };
|
|
32
162
|
const res = await installCodexWithNpm();
|
|
33
163
|
if (!res.ok)
|
|
34
|
-
return { ok: false, installed: false, message: `${res.message}
|
|
35
|
-
If this is a permission issue, install Node with nvm/fnm/volta or run: npm install -g @openai/codex@latest` };
|
|
164
|
+
return { ok: false, installed: false, message: `${res.message}\nIf this is a permission issue, install Node with nvm/fnm/volta or run: ${hint}` };
|
|
36
165
|
if (!(await isCodexExecutableAvailable()))
|
|
37
166
|
return { ok: false, installed: true, message: 'Codex install finished but codex is not on PATH. Open a new terminal or refresh PATH, then rerun npx scalemax.' };
|
|
38
|
-
return { ok: true, installed: true, message: 'Codex installed and detected.' };
|
|
167
|
+
return { ok: true, installed: true, message: res.message.includes('shadowing') ? res.message : 'Codex installed and detected.' };
|
|
39
168
|
}
|
package/dist/types/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type ClientId = 'codex' | 'cursor' | 'roo-code' | 'cline' | 'continue' | 'trae-solo' | 'claude' | 'opencode' | 'openclaw' | 'hermes' | 'cherry-studio' | 'api-code';
|
|
2
2
|
/** Keep this mirror aligned with shared/constants/api-key-scopes.ts. */
|
|
3
|
-
export declare const API_KEY_SCOPE_VALUES: readonly ["openai", "anthropic", "both", "deepseek-v4-flash", "glm-5.2", "deepseek-v4-pro", "auto-api", "reseller", "gemini", "grok", "qwen", "deepseek", "mimo", "local"];
|
|
3
|
+
export declare const API_KEY_SCOPE_VALUES: readonly ["openai", "anthropic", "both", "deepseek-v4-flash", "glm-5.2", "deepseek-v4-pro", "auto-api", "reseller", "gemini", "grok", "qwen", "deepseek", "mimo", "local", "voice"];
|
|
4
4
|
export type ProviderScope = (typeof API_KEY_SCOPE_VALUES)[number];
|
|
5
5
|
export declare function isProviderScope(value: unknown): value is ProviderScope;
|
|
6
6
|
export interface ClientDefinition {
|
package/dist/types/client.js
CHANGED