ocb-cli 1.0.3 → 1.0.4
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/proxy.js +70 -8
- package/package.json +1 -1
- package/src/proxy.ts +73 -8
package/dist/proxy.js
CHANGED
|
@@ -111,7 +111,8 @@ app.use(express.json());
|
|
|
111
111
|
app.use((req, res, next) => {
|
|
112
112
|
res.header("Access-Control-Allow-Origin", "*");
|
|
113
113
|
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
114
|
-
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
114
|
+
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, x-api-key");
|
|
115
|
+
res.header("Content-Type", "application/json");
|
|
115
116
|
if (req.method === "OPTIONS")
|
|
116
117
|
return res.sendStatus(200);
|
|
117
118
|
next();
|
|
@@ -160,16 +161,77 @@ app.post("/api/reset-stats", (req, res) => {
|
|
|
160
161
|
totalRequests = 0;
|
|
161
162
|
res.json({ success: true });
|
|
162
163
|
});
|
|
164
|
+
const modelAliases = {
|
|
165
|
+
"claude-opus-4-5": "opencode/minimax-m2.5-free",
|
|
166
|
+
"claude-opus-4-5-thinking": "opencode/minimax-m2.5-free",
|
|
167
|
+
"claude-opus-4-6": "opencode/minimax-m2.5-free",
|
|
168
|
+
"claude-opus-4-6-thinking": "opencode/minimax-m2.5-free",
|
|
169
|
+
"claude-sonnet-4-5": "opencode/minimax-m2.5-free",
|
|
170
|
+
"claude-sonnet-4-5-thinking": "opencode/minimax-m2.5-free",
|
|
171
|
+
"claude-sonnet-4-5-20250929": "opencode/minimax-m2.5-free",
|
|
172
|
+
"claude-sonnet-4-5-20250929-thinking": "opencode/minimax-m2.5-free",
|
|
173
|
+
"claude-haiku-4-5": "opencode/minimax-m2.5-free",
|
|
174
|
+
"claude-haiku-4-5-20251001": "opencode/minimax-m2.5-free",
|
|
175
|
+
};
|
|
163
176
|
app.post("/api/reset-session", async (req, res) => {
|
|
164
177
|
currentSessionId = await createSession(process.cwd());
|
|
165
178
|
res.json({ success: true, sessionId: currentSessionId });
|
|
166
179
|
});
|
|
167
180
|
app.get("/v1/authenticate", (req, res) => res.json({ type: "authentication", authenticated: true }));
|
|
168
181
|
app.get("/v1/whoami", (req, res) => res.json({ type: "user", id: "opencode-user", email: "opencode@local" }));
|
|
169
|
-
app.get("/v1/models", (req, res) =>
|
|
170
|
-
|
|
182
|
+
app.get("/v1/models", (req, res) => {
|
|
183
|
+
const aliasModels = Object.keys(modelAliases).map(id => ({
|
|
184
|
+
id,
|
|
185
|
+
type: "model",
|
|
186
|
+
name: id,
|
|
187
|
+
display_name: id,
|
|
188
|
+
supports_cached_previews: true,
|
|
189
|
+
supports_system_instructions: true,
|
|
190
|
+
supports_reasoning: true,
|
|
191
|
+
supports_vision: false
|
|
192
|
+
}));
|
|
193
|
+
const allModels = [...aliasModels, ...availableModels.map(m => ({
|
|
194
|
+
id: m.id,
|
|
195
|
+
type: "model",
|
|
196
|
+
name: m.name,
|
|
197
|
+
display_name: m.name,
|
|
198
|
+
supports_cached_previews: true,
|
|
199
|
+
supports_system_instructions: true,
|
|
200
|
+
supports_reasoning: true,
|
|
201
|
+
supports_vision: false
|
|
202
|
+
}))];
|
|
203
|
+
res.json({ data: allModels });
|
|
204
|
+
});
|
|
205
|
+
app.get("/v1/models/list", (req, res) => {
|
|
206
|
+
const aliasModels = Object.keys(modelAliases).map(id => ({
|
|
207
|
+
id,
|
|
208
|
+
type: "model",
|
|
209
|
+
name: id,
|
|
210
|
+
display_name: id,
|
|
211
|
+
supports_cached_previews: true,
|
|
212
|
+
supports_system_instructions: true,
|
|
213
|
+
supports_reasoning: true,
|
|
214
|
+
supports_vision: false
|
|
215
|
+
}));
|
|
216
|
+
const allModels = [...aliasModels, ...availableModels.map(m => ({
|
|
217
|
+
id: m.id,
|
|
218
|
+
type: "model",
|
|
219
|
+
name: m.name,
|
|
220
|
+
display_name: m.name,
|
|
221
|
+
supports_cached_previews: true,
|
|
222
|
+
supports_system_instructions: true,
|
|
223
|
+
supports_reasoning: true,
|
|
224
|
+
supports_vision: false
|
|
225
|
+
}))];
|
|
226
|
+
res.json({ data: allModels });
|
|
227
|
+
});
|
|
171
228
|
app.post("/v1/messages", async (req, res) => {
|
|
172
229
|
try {
|
|
230
|
+
const requestedModel = req.body?.model || currentModel;
|
|
231
|
+
const actualModel = modelAliases[requestedModel] || requestedModel;
|
|
232
|
+
if (modelAliases[requestedModel]) {
|
|
233
|
+
currentModel = modelAliases[requestedModel];
|
|
234
|
+
}
|
|
173
235
|
if (req.body?.max_tokens === undefined && req.body?.messages) {
|
|
174
236
|
let totalTokens = 0;
|
|
175
237
|
for (const msg of req.body.messages) {
|
|
@@ -182,7 +244,7 @@ app.post("/v1/messages", async (req, res) => {
|
|
|
182
244
|
const { text, tokens } = await sendMessage(currentSessionId, req.body.messages);
|
|
183
245
|
totalRequests++;
|
|
184
246
|
totalTokensUsed += tokens;
|
|
185
|
-
res.json({ id: `msg_${Date.now()}`, type: "message", role: "assistant", content: [{ type: "text", text }], model:
|
|
247
|
+
res.json({ id: `msg_${Date.now()}`, type: "message", role: "assistant", content: [{ type: "text", text }], model: actualModel, stop_reason: "end_turn", usage: { input_tokens: Math.ceil(JSON.stringify(req.body.messages).length / 4), output_tokens: Math.ceil(text.length / 4) } });
|
|
186
248
|
}
|
|
187
249
|
catch (error) {
|
|
188
250
|
res.status(500).json({ error: { type: "api_error", message: error instanceof Error ? error.message : String(error) } });
|
|
@@ -332,9 +394,9 @@ function generateHTML() {
|
|
|
332
394
|
<div class="bg-zinc-950 rounded-xl p-4 font-mono text-sm text-zinc-300 overflow-x-auto">
|
|
333
395
|
<pre id="configJson">{
|
|
334
396
|
"env": {
|
|
335
|
-
"ANTHROPIC_BASE_URL": "http://localhost:8300
|
|
336
|
-
"
|
|
337
|
-
"ANTHROPIC_MODEL": "
|
|
397
|
+
"ANTHROPIC_BASE_URL": "http://localhost:8300",
|
|
398
|
+
"ANTHROPIC_API_KEY": "test",
|
|
399
|
+
"ANTHROPIC_MODEL": "claude-sonnet-4-5"
|
|
338
400
|
}
|
|
339
401
|
}</pre>
|
|
340
402
|
</div>
|
|
@@ -462,7 +524,7 @@ function generateHTML() {
|
|
|
462
524
|
currentModelId = modelId;
|
|
463
525
|
loadStatus();
|
|
464
526
|
renderModels(currentProvider === 'all' ? allModels : (groupedModels[currentProvider] || []));
|
|
465
|
-
document.getElementById('configJson').textContent = JSON.stringify({ env: { ANTHROPIC_BASE_URL: "http://localhost:8300
|
|
527
|
+
document.getElementById('configJson').textContent = JSON.stringify({ env: { ANTHROPIC_BASE_URL: "http://localhost:8300", ANTHROPIC_API_KEY: "test", ANTHROPIC_MODEL: modelId } }, null, 2);
|
|
466
528
|
}
|
|
467
529
|
}
|
|
468
530
|
|
package/package.json
CHANGED
package/src/proxy.ts
CHANGED
|
@@ -139,7 +139,8 @@ app.use(express.json());
|
|
|
139
139
|
app.use((req, res, next) => {
|
|
140
140
|
res.header("Access-Control-Allow-Origin", "*");
|
|
141
141
|
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
142
|
-
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
142
|
+
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, x-api-key");
|
|
143
|
+
res.header("Content-Type", "application/json");
|
|
143
144
|
if (req.method === "OPTIONS") return res.sendStatus(200);
|
|
144
145
|
next();
|
|
145
146
|
});
|
|
@@ -193,6 +194,19 @@ app.post("/api/reset-stats", (req, res) => {
|
|
|
193
194
|
res.json({ success: true });
|
|
194
195
|
});
|
|
195
196
|
|
|
197
|
+
const modelAliases: Record<string, string> = {
|
|
198
|
+
"claude-opus-4-5": "opencode/minimax-m2.5-free",
|
|
199
|
+
"claude-opus-4-5-thinking": "opencode/minimax-m2.5-free",
|
|
200
|
+
"claude-opus-4-6": "opencode/minimax-m2.5-free",
|
|
201
|
+
"claude-opus-4-6-thinking": "opencode/minimax-m2.5-free",
|
|
202
|
+
"claude-sonnet-4-5": "opencode/minimax-m2.5-free",
|
|
203
|
+
"claude-sonnet-4-5-thinking": "opencode/minimax-m2.5-free",
|
|
204
|
+
"claude-sonnet-4-5-20250929": "opencode/minimax-m2.5-free",
|
|
205
|
+
"claude-sonnet-4-5-20250929-thinking": "opencode/minimax-m2.5-free",
|
|
206
|
+
"claude-haiku-4-5": "opencode/minimax-m2.5-free",
|
|
207
|
+
"claude-haiku-4-5-20251001": "opencode/minimax-m2.5-free",
|
|
208
|
+
};
|
|
209
|
+
|
|
196
210
|
app.post("/api/reset-session", async (req, res) => {
|
|
197
211
|
currentSessionId = await createSession(process.cwd());
|
|
198
212
|
res.json({ success: true, sessionId: currentSessionId });
|
|
@@ -201,11 +215,62 @@ app.post("/api/reset-session", async (req, res) => {
|
|
|
201
215
|
app.get("/v1/authenticate", (req, res) => res.json({ type: "authentication", authenticated: true }));
|
|
202
216
|
app.get("/v1/whoami", (req, res) => res.json({ type: "user", id: "opencode-user", email: "opencode@local" }));
|
|
203
217
|
|
|
204
|
-
app.get("/v1/models", (req, res) =>
|
|
205
|
-
|
|
218
|
+
app.get("/v1/models", (req, res) => {
|
|
219
|
+
const aliasModels = Object.keys(modelAliases).map(id => ({
|
|
220
|
+
id,
|
|
221
|
+
type: "model" as const,
|
|
222
|
+
name: id,
|
|
223
|
+
display_name: id,
|
|
224
|
+
supports_cached_previews: true,
|
|
225
|
+
supports_system_instructions: true,
|
|
226
|
+
supports_reasoning: true,
|
|
227
|
+
supports_vision: false
|
|
228
|
+
}));
|
|
229
|
+
const allModels = [...aliasModels, ...availableModels.map(m => ({
|
|
230
|
+
id: m.id,
|
|
231
|
+
type: "model" as const,
|
|
232
|
+
name: m.name,
|
|
233
|
+
display_name: m.name,
|
|
234
|
+
supports_cached_previews: true,
|
|
235
|
+
supports_system_instructions: true,
|
|
236
|
+
supports_reasoning: true,
|
|
237
|
+
supports_vision: false
|
|
238
|
+
}))];
|
|
239
|
+
res.json({ data: allModels });
|
|
240
|
+
});
|
|
241
|
+
app.get("/v1/models/list", (req, res) => {
|
|
242
|
+
const aliasModels = Object.keys(modelAliases).map(id => ({
|
|
243
|
+
id,
|
|
244
|
+
type: "model" as const,
|
|
245
|
+
name: id,
|
|
246
|
+
display_name: id,
|
|
247
|
+
supports_cached_previews: true,
|
|
248
|
+
supports_system_instructions: true,
|
|
249
|
+
supports_reasoning: true,
|
|
250
|
+
supports_vision: false
|
|
251
|
+
}));
|
|
252
|
+
const allModels = [...aliasModels, ...availableModels.map(m => ({
|
|
253
|
+
id: m.id,
|
|
254
|
+
type: "model" as const,
|
|
255
|
+
name: m.name,
|
|
256
|
+
display_name: m.name,
|
|
257
|
+
supports_cached_previews: true,
|
|
258
|
+
supports_system_instructions: true,
|
|
259
|
+
supports_reasoning: true,
|
|
260
|
+
supports_vision: false
|
|
261
|
+
}))];
|
|
262
|
+
res.json({ data: allModels });
|
|
263
|
+
});
|
|
206
264
|
|
|
207
265
|
app.post("/v1/messages", async (req, res) => {
|
|
208
266
|
try {
|
|
267
|
+
const requestedModel = req.body?.model || currentModel;
|
|
268
|
+
const actualModel = modelAliases[requestedModel] || requestedModel;
|
|
269
|
+
|
|
270
|
+
if (modelAliases[requestedModel]) {
|
|
271
|
+
currentModel = modelAliases[requestedModel];
|
|
272
|
+
}
|
|
273
|
+
|
|
209
274
|
if (req.body?.max_tokens === undefined && req.body?.messages) {
|
|
210
275
|
let totalTokens = 0;
|
|
211
276
|
for (const msg of req.body.messages) {
|
|
@@ -217,7 +282,7 @@ app.post("/v1/messages", async (req, res) => {
|
|
|
217
282
|
const { text, tokens } = await sendMessage(currentSessionId, req.body.messages);
|
|
218
283
|
totalRequests++;
|
|
219
284
|
totalTokensUsed += tokens;
|
|
220
|
-
res.json({ id: `msg_${Date.now()}`, type: "message", role: "assistant", content: [{ type: "text", text }], model:
|
|
285
|
+
res.json({ id: `msg_${Date.now()}`, type: "message", role: "assistant", content: [{ type: "text", text }], model: actualModel, stop_reason: "end_turn", usage: { input_tokens: Math.ceil(JSON.stringify(req.body.messages).length / 4), output_tokens: Math.ceil(text.length / 4) } });
|
|
221
286
|
} catch (error) {
|
|
222
287
|
res.status(500).json({ error: { type: "api_error", message: error instanceof Error ? error.message : String(error) } });
|
|
223
288
|
}
|
|
@@ -368,9 +433,9 @@ function generateHTML() {
|
|
|
368
433
|
<div class="bg-zinc-950 rounded-xl p-4 font-mono text-sm text-zinc-300 overflow-x-auto">
|
|
369
434
|
<pre id="configJson">{
|
|
370
435
|
"env": {
|
|
371
|
-
"ANTHROPIC_BASE_URL": "http://localhost:8300
|
|
372
|
-
"
|
|
373
|
-
"ANTHROPIC_MODEL": "
|
|
436
|
+
"ANTHROPIC_BASE_URL": "http://localhost:8300",
|
|
437
|
+
"ANTHROPIC_API_KEY": "test",
|
|
438
|
+
"ANTHROPIC_MODEL": "claude-sonnet-4-5"
|
|
374
439
|
}
|
|
375
440
|
}</pre>
|
|
376
441
|
</div>
|
|
@@ -498,7 +563,7 @@ function generateHTML() {
|
|
|
498
563
|
currentModelId = modelId;
|
|
499
564
|
loadStatus();
|
|
500
565
|
renderModels(currentProvider === 'all' ? allModels : (groupedModels[currentProvider] || []));
|
|
501
|
-
document.getElementById('configJson').textContent = JSON.stringify({ env: { ANTHROPIC_BASE_URL: "http://localhost:8300
|
|
566
|
+
document.getElementById('configJson').textContent = JSON.stringify({ env: { ANTHROPIC_BASE_URL: "http://localhost:8300", ANTHROPIC_API_KEY: "test", ANTHROPIC_MODEL: modelId } }, null, 2);
|
|
502
567
|
}
|
|
503
568
|
}
|
|
504
569
|
|