sleev 0.0.11 → 0.0.12
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/apps/codex.js +70 -46
- package/package.json +1 -1
package/dist/apps/codex.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
// Codex setup owns global TOML patching for the OpenAI-compatible proxy provider.
|
|
2
|
-
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { dirname, join } from 'node:path';
|
|
5
5
|
import { field, success } from '../terminal.js';
|
|
6
|
+
const PROVIDER = 'sleev';
|
|
7
|
+
const HARNESS = 'codex cli';
|
|
8
|
+
const OLD_HARNESS = 'codex';
|
|
6
9
|
export async function setupCodex(auth, path = codexPath()) {
|
|
7
10
|
const result = await patchCodex(auth, path);
|
|
8
11
|
success(process.stdout, 'Configured Codex');
|
|
@@ -12,8 +15,7 @@ export async function setupCodex(auth, path = codexPath()) {
|
|
|
12
15
|
export async function patchCodex(auth, path = codexPath()) {
|
|
13
16
|
const existing = await readText(path);
|
|
14
17
|
const config = patchCodexConfig(existing, auth);
|
|
15
|
-
await
|
|
16
|
-
await writeFile(path, config, { mode: 0o600 });
|
|
18
|
+
await writeText(path, config);
|
|
17
19
|
return { path };
|
|
18
20
|
}
|
|
19
21
|
export async function unpatchCodex(path = codexPath()) {
|
|
@@ -21,25 +23,25 @@ export async function unpatchCodex(path = codexPath()) {
|
|
|
21
23
|
if (!existing)
|
|
22
24
|
return;
|
|
23
25
|
const config = unpatchCodexConfig(existing);
|
|
24
|
-
await
|
|
25
|
-
await writeFile(path, config, { mode: 0o600 });
|
|
26
|
+
await writeText(path, config);
|
|
26
27
|
}
|
|
27
28
|
export function codexPath(env = process.env) {
|
|
28
29
|
return join(env.CODEX_HOME || join(homedir(), '.codex'), 'config.toml');
|
|
29
30
|
}
|
|
30
31
|
export function patchCodexConfig(input, auth) {
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
return `${patchProvider(root, target, auth, base).trimEnd()}\n`;
|
|
32
|
+
const previous = previousProvider(input);
|
|
33
|
+
const stale = removeTable(removeTable(input.trimEnd(), table(PROVIDER)), 'sleev.codex');
|
|
34
|
+
const clean = removeRootKey(stale, 'model_provider');
|
|
35
|
+
const root = insertRootKey(clean.trimEnd(), 'model_provider', PROVIDER);
|
|
36
|
+
const meta = previous ? `\n\n[sleev.codex]\nprevious_model_provider = "${toml(previous)}"` : '';
|
|
37
|
+
return `${patchProvider(root, auth).trimEnd()}${meta}\n`;
|
|
38
38
|
}
|
|
39
39
|
export function unpatchCodexConfig(input) {
|
|
40
|
+
const previous = backup(input);
|
|
40
41
|
const provider = rootString(input, 'model_provider') ?? 'openai';
|
|
41
|
-
const clean = removeTable(removeRootKey(input.trimEnd(), 'model_provider'), '
|
|
42
|
-
const
|
|
42
|
+
const clean = removeTable(removeTable(removeRootKey(input.trimEnd(), 'model_provider'), table(PROVIDER)), 'sleev.codex');
|
|
43
|
+
const restored = previous ? insertRootKey(clean.trimEnd(), 'model_provider', previous) : clean;
|
|
44
|
+
const config = provider === PROVIDER ? restored : removeSleevKeys(input, provider);
|
|
43
45
|
return `${config.trimEnd()}\n`;
|
|
44
46
|
}
|
|
45
47
|
function insertRootKey(input, key, value) {
|
|
@@ -73,11 +75,11 @@ function removeRootKey(input, key) {
|
|
|
73
75
|
}
|
|
74
76
|
return next.join('\n');
|
|
75
77
|
}
|
|
76
|
-
function removeTable(input,
|
|
78
|
+
function removeTable(input, name) {
|
|
77
79
|
const lines = input.split('\n');
|
|
78
80
|
const next = [];
|
|
79
81
|
let skip = false;
|
|
80
|
-
const header = new RegExp(`^\\s*\\[\\s*${escape(
|
|
82
|
+
const header = new RegExp(`^\\s*\\[\\s*${escape(name)}(?:\\.|\\s*\\])`);
|
|
81
83
|
for (const line of lines) {
|
|
82
84
|
if (header.test(line)) {
|
|
83
85
|
skip = true;
|
|
@@ -90,38 +92,23 @@ function removeTable(input, table) {
|
|
|
90
92
|
}
|
|
91
93
|
return next.join('\n');
|
|
92
94
|
}
|
|
93
|
-
function patchProvider(input,
|
|
94
|
-
|
|
95
|
-
const clean = removeTable(input, `${table}.http_headers`);
|
|
96
|
-
const lines = clean.split('\n');
|
|
97
|
-
const header = new RegExp(`^\\s*\\[\\s*${escape(table)}\\s*\\]\\s*(#.*)?$`);
|
|
98
|
-
const index = lines.findIndex((line) => header.test(line));
|
|
99
|
-
const keys = providerKeys(auth, url);
|
|
100
|
-
if (index === -1)
|
|
101
|
-
return `${clean.trimEnd()}\n\n[${table}]\nname = "Sleev"\n${keys.join('\n')}`;
|
|
102
|
-
const next = [];
|
|
103
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
104
|
-
const line = lines[i] ?? '';
|
|
105
|
-
const inside = i > index && !/^\s*\[/.test(line);
|
|
106
|
-
if (inside && /^\s*(base_url|wire_api|http_headers)\s*=/.test(line))
|
|
107
|
-
continue;
|
|
108
|
-
next.push(line);
|
|
109
|
-
if (i === index)
|
|
110
|
-
next.push(...keys);
|
|
111
|
-
}
|
|
112
|
-
return next.join('\n');
|
|
95
|
+
function patchProvider(input, auth) {
|
|
96
|
+
return `${input.trimEnd()}\n\n[${table(PROVIDER)}]\nname = "Sleev"\n${providerKeys(auth).join('\n')}`;
|
|
113
97
|
}
|
|
114
|
-
function providerKeys(auth
|
|
98
|
+
function providerKeys(auth) {
|
|
115
99
|
return [
|
|
116
|
-
`base_url = "${toml(
|
|
100
|
+
`base_url = "${toml(baseUrl(auth.proxyUrl))}"`,
|
|
117
101
|
'wire_api = "responses"',
|
|
118
|
-
|
|
102
|
+
'',
|
|
103
|
+
`[${table(PROVIDER)}.http_headers]`,
|
|
104
|
+
`"sleeve-token" = "${toml(auth.token)}"`,
|
|
105
|
+
'"sleeve-provider" = "openai"',
|
|
106
|
+
`"sleeve-harness" = "${HARNESS}"`,
|
|
119
107
|
];
|
|
120
108
|
}
|
|
121
109
|
function removeSleevKeys(input, provider) {
|
|
122
|
-
const table = `model_providers.${provider}`;
|
|
123
110
|
const lines = input.split('\n');
|
|
124
|
-
const header = new RegExp(`^\\s*\\[\\s*${escape(table)}\\s*\\]\\s*(#.*)?$`);
|
|
111
|
+
const header = new RegExp(`^\\s*\\[\\s*${escape(table(provider))}\\s*\\]\\s*(#.*)?$`);
|
|
125
112
|
const index = lines.findIndex((line) => header.test(line));
|
|
126
113
|
if (index === -1)
|
|
127
114
|
return input;
|
|
@@ -132,7 +119,7 @@ function removeSleevKeys(input, provider) {
|
|
|
132
119
|
break;
|
|
133
120
|
current.push(line);
|
|
134
121
|
}
|
|
135
|
-
if (!current.some((line) => line
|
|
122
|
+
if (!current.some((line) => owned(line)))
|
|
136
123
|
return input;
|
|
137
124
|
return lines
|
|
138
125
|
.filter((line, i) => {
|
|
@@ -143,20 +130,40 @@ function removeSleevKeys(input, provider) {
|
|
|
143
130
|
})
|
|
144
131
|
.join('\n');
|
|
145
132
|
}
|
|
133
|
+
function previousProvider(input) {
|
|
134
|
+
const current = rootString(input, 'model_provider');
|
|
135
|
+
return backup(input) ?? (current && current !== PROVIDER ? current : null);
|
|
136
|
+
}
|
|
137
|
+
function backup(input) {
|
|
138
|
+
return tableString(input, 'sleev.codex', 'previous_model_provider');
|
|
139
|
+
}
|
|
140
|
+
function tableString(input, name, key) {
|
|
141
|
+
const lines = input.split('\n');
|
|
142
|
+
const header = new RegExp(`^\\s*\\[\\s*${escape(name)}\\s*\\]\\s*(#.*)?$`);
|
|
143
|
+
const index = lines.findIndex((line) => header.test(line));
|
|
144
|
+
if (index === -1)
|
|
145
|
+
return null;
|
|
146
|
+
for (let i = index + 1; i < lines.length; i += 1) {
|
|
147
|
+
const line = lines[i] ?? '';
|
|
148
|
+
if (/^\s*\[/.test(line))
|
|
149
|
+
return null;
|
|
150
|
+
const match = new RegExp(`^\\s*${escape(key)}\\s*=\\s*(["'])([^"']+)\\1`).exec(line);
|
|
151
|
+
if (match?.[2])
|
|
152
|
+
return match[2];
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
146
156
|
function rootString(input, key) {
|
|
147
157
|
const lines = input.split('\n');
|
|
148
158
|
for (const line of lines) {
|
|
149
159
|
if (/^\s*\[/.test(line))
|
|
150
160
|
return null;
|
|
151
|
-
const match = new RegExp(`^\\s*${escape(key)}\\s*=\\s*([
|
|
161
|
+
const match = new RegExp(`^\\s*${escape(key)}\\s*=\\s*(["'])([^"']+)\\1`).exec(line);
|
|
152
162
|
if (match?.[2])
|
|
153
163
|
return match[2];
|
|
154
164
|
}
|
|
155
165
|
return null;
|
|
156
166
|
}
|
|
157
|
-
function reserved(provider) {
|
|
158
|
-
return provider === 'openai' || provider === 'ollama' || provider === 'lmstudio';
|
|
159
|
-
}
|
|
160
167
|
async function readText(path) {
|
|
161
168
|
try {
|
|
162
169
|
return await readFile(path, 'utf8');
|
|
@@ -176,6 +183,23 @@ function escape(value) {
|
|
|
176
183
|
function trim(url) {
|
|
177
184
|
return url.replace(/\/+$/, '');
|
|
178
185
|
}
|
|
186
|
+
function baseUrl(url) {
|
|
187
|
+
const clean = trim(url);
|
|
188
|
+
if (clean.endsWith('/v1'))
|
|
189
|
+
return clean;
|
|
190
|
+
return `${clean}/v1`;
|
|
191
|
+
}
|
|
192
|
+
function table(provider) {
|
|
193
|
+
return `model_providers.${provider}`;
|
|
194
|
+
}
|
|
195
|
+
function owned(line) {
|
|
196
|
+
return line.includes(`"sleeve-harness" = "${HARNESS}"`) || line.includes(`"sleeve-harness" = "${OLD_HARNESS}"`);
|
|
197
|
+
}
|
|
198
|
+
async function writeText(path, config) {
|
|
199
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
200
|
+
await writeFile(path, config, { mode: 0o600 });
|
|
201
|
+
await chmod(path, 0o600);
|
|
202
|
+
}
|
|
179
203
|
function code(err) {
|
|
180
204
|
if (typeof err !== 'object' || err === null || !('code' in err))
|
|
181
205
|
return undefined;
|