openzoo 0.21.8 → 0.22.0

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.
Files changed (2) hide show
  1. package/lib/setup.js +27 -11
  2. package/package.json +1 -1
package/lib/setup.js CHANGED
@@ -52,21 +52,37 @@ async function catalogModels(base) {
52
52
  if (process.env.OPENZOO_MODELS) {
53
53
  return process.env.OPENZOO_MODELS.split(',').map((m) => m.trim()).filter(Boolean);
54
54
  }
55
+ // NAMES THE EDITOR WILL ACCEPT — this is the whole ballgame.
56
+ //
57
+ // We used to write `openzoo-<model>` twins here, on the theory that a name the
58
+ // editor recognises gets claimed by its own backend. That theory was never
59
+ // actually tested: it rested on "zero connections reached the proxy", which was
60
+ // equally true of both naming schemes, so it discriminated nothing. The real
61
+ // cause of zero connections was a stale pin trigger rewriting the base URL.
62
+ //
63
+ // MEASURED, on two machines: with openzoo-* names Cursor refuses before any
64
+ // request leaves the process — "Model name is not valid" — because it validates
65
+ // the name against its OWN catalog. The custom-OpenAI-endpoint setting only
66
+ // accepts OpenAI-branded ids. Those same ids route through us correctly
67
+ // (verified over the live tunnel: gpt-4o -> openai/gpt-4o-2024-11-20,
68
+ // gpt-4-turbo -> openai/gpt-4-turbo, o3 -> openai/o3-pro), because
69
+ // lib/models.js publishes them in /v1/models and maps them on the way through.
70
+ //
71
+ // OPENZOO_EDITOR_MODELS overrides the list; the zoo model each one lands on is
72
+ // still steerable per-request, and OPENZOO_DEFAULT_MODEL pins them all.
73
+ const fallback = ['gpt-4o', 'gpt-4.1', 'gpt-4-turbo', 'o3', 'o3-mini', 'o4-mini', 'gpt-4o-mini'];
74
+ if (process.env.OPENZOO_EDITOR_MODELS) {
75
+ return process.env.OPENZOO_EDITOR_MODELS.split(',').map((m) => m.trim()).filter(Boolean);
76
+ }
55
77
  try {
56
78
  const r = await fetch(`${base}/models`, { signal: AbortSignal.timeout(15000) });
57
79
  const d = await r.json();
58
- const twins = (d.data || []).map((m) => m.id).filter((id) => id.startsWith('openzoo-'));
59
- // Full-strength first: :free/:batch variants are opt-in, not what someone
60
- // wants preselected, and a flagship should be the default entry.
61
- const plain = twins.filter((t) => !t.includes(':'));
62
- const rest = twins.filter((t) => t.includes(':'));
63
- const preferred = ['openzoo-claude-opus-5', 'openzoo-claude-sonnet-5', 'openzoo-gpt-5.6-sol-pro'];
64
- const head = preferred.filter((p) => plain.includes(p));
65
- const ordered = [...head, ...plain.filter((t) => !head.includes(t)), ...rest];
66
- const limit = Number(process.env.OPENZOO_MODEL_LIMIT || 0);
67
- return limit > 0 ? ordered.slice(0, limit) : ordered;
80
+ const have = new Set((d.data || []).map((m) => m.id));
81
+ // Only offer ids the proxy actually serves, so a pick can never 404.
82
+ const usable = fallback.filter((id) => have.has(id));
83
+ return usable.length ? usable : fallback;
68
84
  } catch {
69
- return ['openzoo-claude-opus-5', 'openzoo-deepseek-v4-pro-0813']; // catalog unreachable
85
+ return fallback;
70
86
  }
71
87
  }
72
88
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.21.8",
3
+ "version": "0.22.0",
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",