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/bin/openzoo.js +7 -0
- package/lib/cursorapi.js +78 -3
- package/lib/cursorbackend.js +1180 -58
- package/lib/grokcli.js +106 -0
- package/package.json +1 -1
package/bin/openzoo.js
CHANGED
|
@@ -89,6 +89,10 @@ const HELP = `openzoo — local x402-paying proxy + MCP server for openzoo.fun
|
|
|
89
89
|
usage:
|
|
90
90
|
npx openzoo start the proxy: http://localhost:8402/v1 (keyless) PLUS a
|
|
91
91
|
public HTTPS url for cloud IDEs (key required, printed at start)
|
|
92
|
+
npx openzoo bot Grok Bot.app on the zoo. Starts :8402 + aiserver on
|
|
93
|
+
:8443, then launches the app with
|
|
94
|
+
CURSOR_API_BASE_URL=https://127.0.0.1:8443
|
|
95
|
+
(no sudo, no /etc/hosts). Leave it running.
|
|
92
96
|
npx openzoo cursor [dir] start proxy+tunnel, write MCP config + every model
|
|
93
97
|
into the picker, and LAUNCH Cursor on [dir]
|
|
94
98
|
(defaults to the current directory; ~ works;
|
|
@@ -164,6 +168,9 @@ async function main() {
|
|
|
164
168
|
case 'start':
|
|
165
169
|
await (await import('../lib/proxy.js')).startProxy({ autoTunnel: true });
|
|
166
170
|
break;
|
|
171
|
+
case 'bot':
|
|
172
|
+
await (await import('../lib/grokcli.js')).runBot(process.argv.slice(3));
|
|
173
|
+
break;
|
|
167
174
|
case 'editor':
|
|
168
175
|
case 'cursor':
|
|
169
176
|
case 'vscode':
|
package/lib/cursorapi.js
CHANGED
|
@@ -177,6 +177,11 @@ export function encodeForMethod(method, models) {
|
|
|
177
177
|
return encodeEnsureSandBox(pod);
|
|
178
178
|
} catch { return null; }
|
|
179
179
|
}
|
|
180
|
+
case 'GetGrokBotSendStatus':
|
|
181
|
+
// Empty body decodes status=UNSPECIFIED → UI "Failed to send".
|
|
182
|
+
// ACCEPTED=2 (aiserver.v1.GrokBotSendStatus). echo_entry_id (field 2)
|
|
183
|
+
// must echo the request's message_id or the overlay never reconciles.
|
|
184
|
+
return encodeGetGrokBotSendStatus();
|
|
180
185
|
case 'GetPlanInfo': return encodeGetPlanInfo();
|
|
181
186
|
case 'GetMe': return encodeGetMe();
|
|
182
187
|
case 'GetDefaultModel': return encodeGetDefaultModel(models);
|
|
@@ -204,10 +209,80 @@ export function encodeForMethod(method, models) {
|
|
|
204
209
|
* those. This encoder is the redirect; whether the box satisfies the protocol
|
|
205
210
|
* is a separate, unfinished problem — point it at a logging box first.
|
|
206
211
|
*/
|
|
207
|
-
|
|
212
|
+
/** GetGrokBotSendStatusResponse { status=ACCEPTED, echo_entry_id, accepted_at_ms } */
|
|
213
|
+
export function encodeGetGrokBotSendStatus(echoId = `oz-${Date.now()}`) {
|
|
214
|
+
return new Buf()
|
|
215
|
+
.int(1, 2) // GROK_BOT_SEND_STATUS_ACCEPTED
|
|
216
|
+
.str(2, echoId)
|
|
217
|
+
.int(4, Date.now())
|
|
218
|
+
.done();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Strip Connect-RPC 5-byte envelope if present (flags=0, big-endian length). */
|
|
222
|
+
export function unwrapConnect(buf) {
|
|
223
|
+
const b = Buffer.isBuffer(buf) ? buf : Buffer.from(buf || []);
|
|
224
|
+
if (b.length >= 5 && (b[0] === 0 || b[0] === 2)) {
|
|
225
|
+
const n = b.readUInt32BE(1);
|
|
226
|
+
if (n > 0 && 5 + n <= b.length) return b.subarray(5, 5 + n);
|
|
227
|
+
}
|
|
228
|
+
return b;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Bare protobuf → {fieldNumber: string|number}. Enough for GetGrokBotSendStatusRequest
|
|
232
|
+
* {1 agent_id, 2 message_id} (measured body=76b = two uuid strings). */
|
|
233
|
+
export function decodeProtoFields(buf) {
|
|
234
|
+
const b = unwrapConnect(buf);
|
|
235
|
+
const out = {};
|
|
236
|
+
let i = 0;
|
|
237
|
+
while (i < b.length) {
|
|
238
|
+
let key = 0;
|
|
239
|
+
let shift = 0;
|
|
240
|
+
while (i < b.length) {
|
|
241
|
+
const v = b[i++];
|
|
242
|
+
key |= (v & 0x7f) << shift;
|
|
243
|
+
if (!(v & 0x80)) break;
|
|
244
|
+
shift += 7;
|
|
245
|
+
if (shift > 28) return out;
|
|
246
|
+
}
|
|
247
|
+
const field = key >>> 3;
|
|
248
|
+
const wire = key & 7;
|
|
249
|
+
if (wire === 0) {
|
|
250
|
+
let n = 0;
|
|
251
|
+
shift = 0;
|
|
252
|
+
while (i < b.length) {
|
|
253
|
+
const v = b[i++];
|
|
254
|
+
n |= (v & 0x7f) << shift;
|
|
255
|
+
if (!(v & 0x80)) break;
|
|
256
|
+
shift += 7;
|
|
257
|
+
}
|
|
258
|
+
out[field] = n;
|
|
259
|
+
} else if (wire === 2) {
|
|
260
|
+
let len = 0;
|
|
261
|
+
shift = 0;
|
|
262
|
+
while (i < b.length) {
|
|
263
|
+
const v = b[i++];
|
|
264
|
+
len |= (v & 0x7f) << shift;
|
|
265
|
+
if (!(v & 0x80)) break;
|
|
266
|
+
shift += 7;
|
|
267
|
+
}
|
|
268
|
+
if (i + len > b.length) break;
|
|
269
|
+
out[field] = b.subarray(i, i + len).toString('utf8');
|
|
270
|
+
i += len;
|
|
271
|
+
} else {
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return out;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export function encodeEnsureSandBox({ region = 'us1', accountId, podId, token, accessToken, agent, vnc, vncPath, p1340, p6081 }) {
|
|
208
279
|
// per-port URLs — field 6 is the agent (1337), field 7 the VNC desktop
|
|
209
280
|
// (6080), matching the live cursorvm response. RunPod fronts each port at
|
|
210
281
|
// https://<id>-<port>.proxy.runpod.net, so agent !== vnc.
|
|
282
|
+
// Field 4 = network_token (nto-…); field 11 = agent HTTP bearer. Mixing
|
|
283
|
+
// them 401s /api/* on the real pod (measured sniff 2026-08-29).
|
|
284
|
+
const auth = accessToken || token;
|
|
285
|
+
const vncUrl = vncPath || `${vnc}/vnc.html?network_token=${token}&resume_lower_s=900&resume_upper_s=18000&path=websockify%3Fnetwork_token%3D${token}`;
|
|
211
286
|
return new Buf()
|
|
212
287
|
.str(1, region)
|
|
213
288
|
.str(2, accountId)
|
|
@@ -215,11 +290,11 @@ export function encodeEnsureSandBox({ region = 'us1', accountId, podId, token, a
|
|
|
215
290
|
.str(4, token)
|
|
216
291
|
.str(5, 'local')
|
|
217
292
|
.str(6, agent)
|
|
218
|
-
.str(7,
|
|
293
|
+
.str(7, vncUrl)
|
|
219
294
|
.str(8, '/workspace/terminals')
|
|
220
295
|
.int(9, 1)
|
|
221
296
|
.str(10, p1340 || agent)
|
|
222
|
-
.str(11,
|
|
297
|
+
.str(11, auth)
|
|
223
298
|
.str(12, p6081 || vnc)
|
|
224
299
|
.done();
|
|
225
300
|
}
|