openzoo 0.50.19 → 0.50.21

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/grokcli.js CHANGED
@@ -98,6 +98,112 @@ ${body}
98
98
  `;
99
99
  }
100
100
 
101
+ /**
102
+ * `openzoo bot` — Grok Bot.app on the zoo, no sudo, no /etc/hosts.
103
+ *
104
+ * CURSOR_API_BASE_URL (and SAND_BACKEND_URL) are what the Electron MAIN
105
+ * process actually reads. Chromium --host-resolver-rules do not. Measured:
106
+ * a bare `127.0.0.1:443` is HTTP and logs ERR_SSL_HTTP_REQUEST; the URL
107
+ * must be https://127.0.0.1:8443. The TLS warning on launch is Node
108
+ * complaining about NODE_TLS_REJECT_UNAUTHORIZED=0 — expected, the cert
109
+ * is ours and self-signed.
110
+ *
111
+ * We bind 8443 ourselves (unprivileged). :443 is the old root takeover and
112
+ * stubs oauth if it is the unpatched npx copy — do not point the app there.
113
+ */
114
+ export async function runBot(argv = []) {
115
+ const port = 8443;
116
+ const url = `https://127.0.0.1:${port}`;
117
+ const bin = `${APP}/Contents/MacOS/Grok Bot`;
118
+ if (!existsSync(bin)) {
119
+ console.error('openzoo: Grok Bot.app not found at', APP);
120
+ process.exit(1);
121
+ }
122
+
123
+ const proxyBase = `http://localhost:${config.port}/v1`;
124
+ let up = false;
125
+ try { up = (await fetch(`${proxyBase}/models`, { signal: AbortSignal.timeout(2000) })).ok; } catch { up = false; }
126
+ if (!up) {
127
+ console.error('openzoo: starting proxy on', proxyBase);
128
+ const { startProxy } = await import('./proxy.js');
129
+ await startProxy({ silent: true, autoTunnel: process.env.OPENZOO_NO_TUNNEL === '1' ? false : true });
130
+ }
131
+
132
+ process.env.OPENZOO_BYOK = '1';
133
+ const sniff = argv.includes('--sniff') || argv.includes('--passthru');
134
+ if (sniff) {
135
+ // REAL pod, we only sit in the middle. EnsureSandBox is rewritten so
136
+ // /api/sendPrompt and getAgentTranscriptTail land here, then we proxy
137
+ // them to cursorvm and dump the live JSON. That is the comparison
138
+ // surface — hijack guesses have been wrong twice.
139
+ delete process.env.OZ_HIJACK_POD;
140
+ process.env.OPENZOO_PASSTHRU = '1';
141
+ process.env.OPENZOO_SNIFF = '1';
142
+ process.env.OZ_SNIFF_SELF = url;
143
+ } else {
144
+ // Do NOT hand Grok Bot a real cursorvm pod — inference then never leaves
145
+ // Anysphere (measured: EnsureSandBox -> REAL api2, then StreamUnifiedChat
146
+ // never arrives). Point the sandbox URLs at THIS aiserver; StreamUnifiedChat
147
+ // is answered from :8402 (x402).
148
+ process.env.OZ_HIJACK_POD = JSON.stringify({
149
+ region: 'local',
150
+ accountId: 'openzoo',
151
+ podId: 'openzoo-local',
152
+ token: 'openzoo',
153
+ agent: url,
154
+ vnc: url,
155
+ p1340: url,
156
+ p6081: url,
157
+ });
158
+ process.env.OZ_SNIFF_SELF = url;
159
+ }
160
+ const { startCursorBackend } = await import('./cursorbackend.js');
161
+ const models = [
162
+ 'gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'gpt-4.1', 'gpt-4.1-mini', 'gpt-3.5-turbo',
163
+ ].map((n) => ({ name: n, label: n }));
164
+ const log = (m) => console.error(' backend:', m);
165
+ try {
166
+ startCursorBackend({ port, models, log });
167
+ } catch (e) {
168
+ console.error('openzoo: 8443 already bound — reusing it (', e.message, ')');
169
+ }
170
+ await new Promise((r) => setTimeout(r, 400));
171
+ console.error(`openzoo: aiserver on ${url}`);
172
+ console.error(' oauth + /sand-box creds -> real api2');
173
+ if (sniff) {
174
+ console.error(' SNIFF: real EnsureSandBox, /api/* proxied, dump ~/.openzoo/grokbot-sniff.jsonl');
175
+ console.error(' send a message in Grok Bot — it should paint for real');
176
+ } else {
177
+ console.error(' EnsureSandBox HIJACKED here; StreamUnifiedChat -> :8402 (x402)');
178
+ }
179
+
180
+ try { execSync('osascript -e \'tell application "Grok Bot" to quit\'', { stdio: 'ignore' }); } catch { /* ok */ }
181
+ await new Promise((r) => setTimeout(r, 1500));
182
+
183
+ console.error('openzoo: launching Grok Bot');
184
+ console.error(` CURSOR_API_BASE_URL=${url}`);
185
+ spawn(bin, ['--ignore-certificate-errors'], {
186
+ stdio: 'ignore',
187
+ detached: true,
188
+ env: {
189
+ ...process.env,
190
+ NODE_TLS_REJECT_UNAUTHORIZED: '0',
191
+ CURSOR_API_BASE_URL: url,
192
+ SAND_BACKEND_URL: url,
193
+ // Helper daemon (local-exec-daemon/main.cjs) uses Node fetch, not Chromium.
194
+ // Without these it dials the cached cursorvm 1337 URL / dies on our
195
+ // self-signed cert and GET /local-exec/requests never arrives.
196
+ SAND_HOST_GATEWAY_URL: url,
197
+ SAND_HOST_GATEWAY_TOKEN: 'openzoo',
198
+ SAND_HOST_GATEWAY_NETWORK_TOKEN: 'openzoo',
199
+ },
200
+ }).unref();
201
+
202
+ console.error('openzoo: leave this running. ctrl-c stops the backend.');
203
+ if (argv.includes('--once')) return;
204
+ await new Promise(() => {});
205
+ }
206
+
101
207
  export async function setupGrokBot(argv = []) {
102
208
  const base = `http://localhost:${config.port}/v1`;
103
209
  const launch = !argv.includes('--no-launch');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.50.19",
3
+ "version": "0.50.21",
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",