openzoo 0.50.97 → 0.50.99

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.
@@ -45,5 +45,5 @@ process.on('unhandledRejection', (e) => {
45
45
  log(`cursor-backend: UNHANDLED REJECTION ${e && e.message ? e.message : e}`);
46
46
  });
47
47
 
48
- startCursorBackend({ port, models, log });
48
+ await startCursorBackend({ port, models, log });
49
49
  log(`cursor-backend: standalone up on :${port} (${models.length} models)`);
package/bin/openzoo.js CHANGED
@@ -96,7 +96,16 @@ usage:
96
96
  After a reboot the login item comes back without
97
97
  that env — bot bounces it so send works. Already-
98
98
  hijacked sessions are left alone.
99
+ Missing Grok Bot is fetched from the grokbot-v*
100
+ multiarch GitHub release (vendor feed fallback).
99
101
  --quit force bounce · --no-quit never bounce
102
+ --no-fetch do not download Grok Bot if missing
103
+ --daemon / -d fork the sidecar to background
104
+ (pid ~/.openzoo/bot.pid, log bot.log)
105
+ then launch Grok Bot. Needed from the
106
+ OpenZoo Bot AppImage so this process
107
+ is not the GUI.
108
+ --stop kill the --daemon sidecar
100
109
  --verbose print every request the app makes
101
110
  (default is quiet: milestones + problems)
102
111
  --web serve the renderer in a browser instead of
package/lib/cursorapi.js CHANGED
@@ -305,3 +305,68 @@ export function connectFrame(payload) {
305
305
  head.writeUInt32BE(payload.length, 1);
306
306
  return Buffer.concat([head, payload]);
307
307
  }
308
+
309
+ /**
310
+ * Fake Cursor login. Grok Bot polls GET /auth/poll until the JSON has
311
+ * accessToken + refreshToken (asar SandBackendLoginManager.waitForResult).
312
+ * empty-ok `{}` is a 200 without those keys → login fails → "Log in with Cursor".
313
+ * accessToken is JWT-decoded for sub/email/exp (createLoggedInStatus).
314
+ */
315
+ export function fakeCursorJwt({
316
+ sub = 'openzoo-user',
317
+ email = 'user@openzoo.local',
318
+ name = 'openzoo',
319
+ now = Math.floor(Date.now() / 1000),
320
+ } = {}) {
321
+ const b64url = (obj) => Buffer.from(JSON.stringify(obj)).toString('base64url');
322
+ return `${b64url({ alg: 'none', typ: 'JWT' })}.${b64url({
323
+ sub, email, name, exp: now + 365 * 86400, iat: now,
324
+ })}.oz`;
325
+ }
326
+
327
+ export function fakeCursorTokens() {
328
+ const accessToken = fakeCursorJwt();
329
+ const refreshToken = fakeCursorJwt();
330
+ return { accessToken, refreshToken, authId: 'openzoo-user' };
331
+ }
332
+
333
+ const LOGIN_DEEP_HTML = `<!doctype html>
334
+ <html lang="en"><head>
335
+ <meta charset="utf-8">
336
+ <meta http-equiv="refresh" content="0;url=about:blank">
337
+ <title></title>
338
+ </head>
339
+ <body data-component="oz-fake-login">
340
+ <script>
341
+ try { window.open('', '_self'); } catch (e) {}
342
+ try { window.close(); } catch (e) {}
343
+ try { location.replace('about:blank'); } catch (e) {}
344
+ </script>
345
+ </body></html>
346
+ `;
347
+
348
+ /** Path without query. Returns a reply descriptor or null. */
349
+ export function fakeCursorAuthReply(urlPath, { passthrough = false } = {}) {
350
+ if (passthrough) return null;
351
+ const path0 = String(urlPath || '').split('?')[0];
352
+ const tok = fakeCursorTokens();
353
+ if (path0 === '/auth/poll') {
354
+ return { kind: 'poll', contentType: 'application/json', body: JSON.stringify(tok) };
355
+ }
356
+ if (path0 === '/oauth/token') {
357
+ return {
358
+ kind: 'oauth',
359
+ contentType: 'application/json',
360
+ body: JSON.stringify({
361
+ access_token: tok.accessToken,
362
+ refresh_token: tok.refreshToken,
363
+ token_type: 'Bearer',
364
+ expires_in: 365 * 86400,
365
+ }),
366
+ };
367
+ }
368
+ if (path0 === '/loginDeepControl') {
369
+ return { kind: 'login-page', contentType: 'text/html; charset=utf-8', body: LOGIN_DEEP_HTML };
370
+ }
371
+ return null;
372
+ }