openzoo 0.22.2 → 0.23.1
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/lib/cursorcfg.js +42 -2
- package/lib/models.js +35 -0
- package/package.json +1 -1
package/lib/cursorcfg.js
CHANGED
|
@@ -87,6 +87,46 @@ export async function quitEditor(which) {
|
|
|
87
87
|
* should offer. Returns what changed, or null when the store is unavailable
|
|
88
88
|
* (a fresh install with no globalStorage yet).
|
|
89
89
|
*/
|
|
90
|
+
/**
|
|
91
|
+
* PRETTY NAMES IN THE PICKER, WITHOUT LOSING VALIDATION.
|
|
92
|
+
*
|
|
93
|
+
* The editor validates `name` against its OWN catalog and refuses anything else
|
|
94
|
+
* ("Model name is not valid" / "Max Mode Required"), so `name` MUST stay a bland
|
|
95
|
+
* id it already knows. But the picker renders `inputboxShortModelName`, which it
|
|
96
|
+
* does not validate — so the row can read "Opus 5" while the id stays gpt-4o.
|
|
97
|
+
*
|
|
98
|
+
* The zoo model that actually answers is chosen by the proxy, so a slot is a
|
|
99
|
+
* (bland id -> real model -> label) triple. Override with OPENZOO_EDITOR_MAP:
|
|
100
|
+
* OPENZOO_EDITOR_MAP="gpt-4o=x-ai/grok-4.6:Grok 4.6,gpt-4.1=anthropic/claude-sonnet-5:Sonnet 5"
|
|
101
|
+
*/
|
|
102
|
+
const DEFAULT_SLOTS = {
|
|
103
|
+
'gpt-4o': { served: 'anthropic/claude-opus-5', label: 'Opus 5' },
|
|
104
|
+
'gpt-4.1': { served: 'anthropic/claude-sonnet-5', label: 'Sonnet 5' },
|
|
105
|
+
'gpt-4-turbo': { served: 'x-ai/grok-4.6', label: 'Grok 4.6' },
|
|
106
|
+
'gpt-4o-mini': { served: 'google/gemini-3.7-flash', label: 'Gemini 3.7 Flash' },
|
|
107
|
+
'gpt-4.1-mini': { served: 'deepseek/deepseek-v4-pro-0813', label: 'DeepSeek V4 Pro' },
|
|
108
|
+
'gpt-3.5-turbo': { served: 'qwen/qwen3.8-2.4t-a95b', label: 'Qwen3.8 2.4T' },
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export function slotFor(id) {
|
|
112
|
+
// KILL SWITCH: if a custom label ever makes the editor treat a row as
|
|
113
|
+
// unavailable, OPENZOO_NO_LABELS=1 puts the bland id back as the label. The
|
|
114
|
+
// mapping (which zoo model answers) is unaffected — only the text changes.
|
|
115
|
+
if (process.env.OPENZOO_NO_LABELS === '1') {
|
|
116
|
+
return { served: (DEFAULT_SLOTS[id] || {}).served || id, label: id };
|
|
117
|
+
}
|
|
118
|
+
const env = process.env.OPENZOO_EDITOR_MAP;
|
|
119
|
+
if (env) {
|
|
120
|
+
for (const part of env.split(',')) {
|
|
121
|
+
const [lhs, rhs] = part.split('=');
|
|
122
|
+
if ((lhs || '').trim() !== id || !rhs) continue;
|
|
123
|
+
const [served, ...lbl] = rhs.split(':');
|
|
124
|
+
return { served: served.trim(), label: (lbl.join(':') || served).trim() };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return DEFAULT_SLOTS[id] || { served: id, label: id };
|
|
128
|
+
}
|
|
129
|
+
|
|
90
130
|
export function writeEditorProviderConfig(which, { baseUrl, models }) {
|
|
91
131
|
const db = storagePath(which);
|
|
92
132
|
if (!fs.existsSync(db)) return null;
|
|
@@ -132,11 +172,11 @@ export function writeEditorProviderConfig(which, { baseUrl, models }) {
|
|
|
132
172
|
supportsMaxMode: true,
|
|
133
173
|
supportsNonMaxMode: true,
|
|
134
174
|
serverModelName: m,
|
|
175
|
+
inputboxShortModelName: slotFor(m).label,
|
|
135
176
|
isRecommendedForBackgroundComposer: false,
|
|
136
177
|
supportsPlanMode: true,
|
|
137
178
|
supportsSandboxing: true,
|
|
138
179
|
isUserAdded: true,
|
|
139
|
-
inputboxShortModelName: m,
|
|
140
180
|
parameterDefinitions: [],
|
|
141
181
|
variants: [],
|
|
142
182
|
legacySlugs: [],
|
|
@@ -214,7 +254,7 @@ export function pinEditorProviderConfig(which, { baseUrl, models }) {
|
|
|
214
254
|
supportsThinking: true, supportsImages: true, supportsMaxMode: true,
|
|
215
255
|
supportsNonMaxMode: true, serverModelName: m,
|
|
216
256
|
isRecommendedForBackgroundComposer: false, supportsPlanMode: true,
|
|
217
|
-
supportsSandboxing: true, isUserAdded: true, inputboxShortModelName: m,
|
|
257
|
+
supportsSandboxing: true, isUserAdded: true, inputboxShortModelName: slotFor(m).label,
|
|
218
258
|
parameterDefinitions: [], variants: [], legacySlugs: [], idAliases: [],
|
|
219
259
|
namedModelSectionIndex: 1, cloudAgentEffortModes: [], modelPickerBadges: [],
|
|
220
260
|
}))));
|
package/lib/models.js
CHANGED
|
@@ -19,6 +19,31 @@ import { config } from './config.js';
|
|
|
19
19
|
* cached briefly, so new zoo models resolve without shipping this package.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* The editor-slot map: bland id the editor accepts -> the zoo model that should
|
|
24
|
+
* actually answer it. Mirrors DEFAULT_SLOTS in cursorcfg.js; OPENZOO_EDITOR_MAP
|
|
25
|
+
* overrides both ("gpt-4o=x-ai/grok-4.6:Grok 4.6,...").
|
|
26
|
+
*/
|
|
27
|
+
const DEFAULT_SLOT_MODELS = {
|
|
28
|
+
'gpt-4o': 'anthropic/claude-opus-5',
|
|
29
|
+
'gpt-4.1': 'anthropic/claude-sonnet-5',
|
|
30
|
+
'gpt-4-turbo': 'x-ai/grok-4.6',
|
|
31
|
+
'gpt-4o-mini': 'google/gemini-3.7-flash',
|
|
32
|
+
'gpt-4.1-mini': 'deepseek/deepseek-v4-pro-0813',
|
|
33
|
+
'gpt-3.5-turbo': 'qwen/qwen3.8-2.4t-a95b',
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function editorSlot(id) {
|
|
37
|
+
const env = process.env.OPENZOO_EDITOR_MAP;
|
|
38
|
+
if (env) {
|
|
39
|
+
for (const part of env.split(',')) {
|
|
40
|
+
const [lhs, rhs] = part.split('=');
|
|
41
|
+
if ((lhs || '').trim() === id && rhs) return rhs.split(':')[0].trim();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return DEFAULT_SLOT_MODELS[id] || null;
|
|
45
|
+
}
|
|
46
|
+
|
|
22
47
|
const CATALOG_TTL_MS = 5 * 60 * 1000;
|
|
23
48
|
let cache = { at: 0, ids: null };
|
|
24
49
|
|
|
@@ -114,9 +139,19 @@ export function resolveModel(requested, ids) {
|
|
|
114
139
|
if (exact) return exact;
|
|
115
140
|
requested = bare;
|
|
116
141
|
}
|
|
142
|
+
// An explicit OPENZOO_DEFAULT_MODEL is a deliberate act and outranks
|
|
143
|
+
// everything below it, including the editor slots.
|
|
117
144
|
const env = process.env.OPENZOO_DEFAULT_MODEL;
|
|
118
145
|
if (env && ids.includes(env)) return env;
|
|
119
146
|
|
|
147
|
+
// SLOT MAP. The editor only accepts a handful of bland ids it already knows,
|
|
148
|
+
// so the shim writes those as slots and shows a real label for each (slotFor
|
|
149
|
+
// in cursorcfg.js). That label would be a LIE if the id then fell through to
|
|
150
|
+
// the similarity scorer, so the same mapping is honoured here: gpt-4o really
|
|
151
|
+
// is served by claude-opus-5. One source of truth, OPENZOO_EDITOR_MAP.
|
|
152
|
+
const slot = editorSlot(requested);
|
|
153
|
+
if (slot && ids.includes(slot)) return slot;
|
|
154
|
+
|
|
120
155
|
const reqTier = tierOf(requested);
|
|
121
156
|
const reqCode = CODE_RE.test(requested);
|
|
122
157
|
const reqToks = new Set(tokensOf(requested));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.1",
|
|
4
4
|
"description": "Local x402-paying proxy + MCP server for openzoo.fun — point any OpenAI-compatible harness (Cursor, Claude Code, aider, SDKs) at localhost and it pays per call from a local burner wallet. Solana and Base rails live; Robinhood experimental.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|