openzoo 0.38.4 → 0.38.6
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/bin/openzoo.js +5 -3
- package/lib/grokbot.js +57 -2
- package/package.json +1 -1
package/bin/openzoo.js
CHANGED
|
@@ -25,9 +25,11 @@ usage:
|
|
|
25
25
|
(claude, aider...) already pointed at the zoo
|
|
26
26
|
npx openzoo grokbot point Grok Bot / the grok CLI at the zoo — GROK MODELS ONLY,
|
|
27
27
|
paid per call by x402 instead of xAI first-party billing,
|
|
28
|
-
then
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
then TAKE OVER the app's backend: pins api2.cursor.sh in
|
|
29
|
+
/etc/hosts, serves it locally on :443 with byok_enabled,
|
|
30
|
+
and launches Grok Bot with Node TLS override (sudo required;
|
|
31
|
+
ctrl-c restores /etc/hosts).
|
|
32
|
+
--no-takeover plain launch · --no-launch config only
|
|
31
33
|
npx openzoo mcp stdio MCP server (tools: zoo_ask, zoo_bind, zoo_models, zoo_wallet, zoo_contexts)
|
|
32
34
|
npx openzoo unblock restore the editor's own backend in the hosts file
|
|
33
35
|
npx openzoo tunnel public-url-only mode (everything key-gated, no keyless localhost)
|
package/lib/grokbot.js
CHANGED
|
@@ -147,6 +147,54 @@ export async function setupGrokBot(argv = []) {
|
|
|
147
147
|
// model table, and the APP — the thing you actually look at — keeps talking
|
|
148
148
|
// to Cursor's cloud, which is the whole problem it was meant to solve.
|
|
149
149
|
// --no-byok drops back to plain launch.
|
|
150
|
+
// TAKEOVER IS THE DEFAULT. The --host-resolver-rules probe below is kept
|
|
151
|
+
// only for reference: it was PROVED not to intercept this app (flags present,
|
|
152
|
+
// backend listening, zero connections). Nothing routes without the hosts pin.
|
|
153
|
+
if (!argv.includes('--no-takeover')) {
|
|
154
|
+
// TAKEOVER — the Cursor recipe, because it is the only one that works.
|
|
155
|
+
//
|
|
156
|
+
// WHY NOT --host-resolver-rules: PROVED not to work here. The flag was
|
|
157
|
+
// verified present in the running process args for all four cursor hosts,
|
|
158
|
+
// the backend was listening, and ZERO connections arrived — the app kept
|
|
159
|
+
// talking to the real api2.cursor.sh (cert CN confirmed on its live
|
|
160
|
+
// sockets). That flag only steers CHROMIUM's stack; Grok Bot's Connect/gRPC
|
|
161
|
+
// transport runs in the Electron MAIN process on Node's DNS + Node's TLS,
|
|
162
|
+
// which ignore it. Same reason setup.js sets NODE_TLS_REJECT_UNAUTHORIZED
|
|
163
|
+
// for Cursor takeover.
|
|
164
|
+
//
|
|
165
|
+
// So: /etc/hosts (Node reads the OS resolver) + Node-side TLS override,
|
|
166
|
+
// and the app is spawned DIRECTLY rather than via `open`, because `open`
|
|
167
|
+
// does not pass an environment to the app.
|
|
168
|
+
const { blockBackend, unblockBackend, isBlocked } = await import('./hosts.js');
|
|
169
|
+
const { startCursorBackend } = await import('./cursorbackend.js');
|
|
170
|
+
const port = 443; // Node's DNS gives no port control — we must own :443
|
|
171
|
+
|
|
172
|
+
process.env.OPENZOO_BYOK = '1';
|
|
173
|
+
process.env.OPENZOO_FORCE_BLOCK = '1'; // our own guard refuses otherwise
|
|
174
|
+
console.error('openzoo: TAKEOVER — pinning api2.cursor.sh and serving it locally.');
|
|
175
|
+
console.error(' sudo will ask for your password (hosts file + :443).');
|
|
176
|
+
if (!isBlocked()) blockBackend();
|
|
177
|
+
|
|
178
|
+
startCursorBackend({ port, log: (m) => console.error(` backend: ${m}`) });
|
|
179
|
+
|
|
180
|
+
const restore = () => {
|
|
181
|
+
try { unblockBackend(); console.error('openzoo: /etc/hosts restored.'); } catch { /* best effort */ }
|
|
182
|
+
};
|
|
183
|
+
process.on('SIGINT', () => { restore(); process.exit(0); });
|
|
184
|
+
process.on('exit', restore);
|
|
185
|
+
|
|
186
|
+
console.error('openzoo: launching Grok Bot with Node TLS override...');
|
|
187
|
+
spawn(`${APP}/Contents/MacOS/Grok Bot`, ['--ignore-certificate-errors'], {
|
|
188
|
+
stdio: 'ignore',
|
|
189
|
+
detached: true,
|
|
190
|
+
env: { ...process.env, NODE_TLS_REJECT_UNAUTHORIZED: '0' },
|
|
191
|
+
}).unref();
|
|
192
|
+
|
|
193
|
+
console.error('openzoo: ctrl-c to stop and RESTORE /etc/hosts (do not just close the terminal).');
|
|
194
|
+
await new Promise(() => {});
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
150
198
|
if (!argv.includes('--no-byok')) {
|
|
151
199
|
// BYOK PROBE — NO /etc/hosts, NO sudo.
|
|
152
200
|
//
|
|
@@ -166,7 +214,7 @@ export async function setupGrokBot(argv = []) {
|
|
|
166
214
|
// nothing — and silence looked identical to success. Every arriving method
|
|
167
215
|
// is printed so "did it connect at all" is answerable at a glance.
|
|
168
216
|
startCursorBackend({ port, log: (m) => console.error(` backend: ${m}`) });
|
|
169
|
-
console.error('openzoo: BYOK probe — impersonating api2.cursor.sh on :' + port);
|
|
217
|
+
console.error('openzoo: BYOK probe — impersonating api2/api3/api4/repo42.cursor.sh on :' + port);
|
|
170
218
|
console.error(' scoped to this launch only (no /etc/hosts, no sudo)');
|
|
171
219
|
console.error(' WATCH: if StreamChat starts arriving at the proxy, inference moved.');
|
|
172
220
|
console.error(' If only a BYOK settings pane appears, it is xAI-key-only and buys nothing.');
|
|
@@ -180,9 +228,16 @@ export async function setupGrokBot(argv = []) {
|
|
|
180
228
|
} catch { /* not running is fine */ }
|
|
181
229
|
// give it a moment to actually exit before relaunching
|
|
182
230
|
await new Promise((r) => setTimeout(r, 2500));
|
|
231
|
+
// MAP EVERY CURSOR HOST, NOT JUST api2.
|
|
232
|
+
// MEASURED: mapping api2 alone applied cleanly (verified in the running
|
|
233
|
+
// process args) and still produced ZERO requests, because Grok Bot's own
|
|
234
|
+
// surface is api3 — the bundle carries `https://api3.cursor.sh/tev1/v1`.
|
|
235
|
+
// The self-signed cert already covers all four names, so map them all.
|
|
236
|
+
const hosts = ['api2.cursor.sh', 'api3.cursor.sh', 'api4.cursor.sh', 'repo42.cursor.sh'];
|
|
237
|
+
const rules = hosts.map((h) => `MAP ${h} 127.0.0.1:${port}`).join(',');
|
|
183
238
|
spawn('open', ['-n', '-a', APP, '--args',
|
|
184
239
|
'--ignore-certificate-errors',
|
|
185
|
-
`--host-resolver-rules
|
|
240
|
+
`--host-resolver-rules=${rules}`,
|
|
186
241
|
], { stdio: 'ignore', detached: true }).unref();
|
|
187
242
|
// keep this process alive so the backend keeps answering
|
|
188
243
|
console.error('openzoo: leave this running while Grok Bot is open. ctrl-c stops the');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.6",
|
|
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",
|