From dda2552126f44675d68a4c560d62e2f8b90befc4 Mon Sep 17 00:00:00 2001 From: Index Date: Mon, 3 Nov 2025 22:11:12 -0600 Subject: [PATCH] feat: use jetstream instead of firehose --- .env.example | 4 ++-- docker-compose.yml | 2 +- src/core.ts | 48 ++++++++++++++++++++++++++++++++++++++-- src/env.ts | 6 +++-- src/handlers/messages.ts | 8 +++---- src/index.ts | 2 +- 6 files changed, 58 insertions(+), 12 deletions(-) diff --git a/.env.example b/.env.example index 4080d2d..53f604c 100644 --- a/.env.example +++ b/.env.example @@ -11,10 +11,10 @@ DID="" HANDLE="" # https://bsky.app/settings/app-passwords -BSKY_PASSWORD="" +APP_PASSWORD="" # https://aistudio.google.com/apikey GEMINI_API_KEY="" DAILY_QUERY_LIMIT=15 -USE_FIREHOSE=false \ No newline at end of file +USE_JETSTREAM=false \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 84827b6..a8b2412 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: - "GEMINI_MODEL=${GEMINI_MODEL:-gemini-2.5-flash}" - "DID=${DID:?}" - "HANDLE=${HANDLE:?}" - - "BSKY_PASSWORD=${BSKY_PASSWORD:?}" + - "APP_PASSWORD=${APP_PASSWORD:?}" - "GEMINI_API_KEY=${GEMINI_API_KEY:?}" volumes: - aero_db:/sqlite.db diff --git a/src/core.ts b/src/core.ts index 9faaa8b..d78400d 100644 --- a/src/core.ts +++ b/src/core.ts @@ -1,13 +1,57 @@ import { GoogleGenAI } from "@google/genai"; import { Bot, EventStrategy } from "@skyware/bot"; import { env } from "./env"; +import type { BinaryType } from "bun"; + +// Websocket patch was written by Claude, hopefully it doesn't suck +const OriginalWebSocket = global.WebSocket; +const binaryTypeDescriptor = Object.getOwnPropertyDescriptor( + OriginalWebSocket.prototype, + "binaryType", +); + +const originalSetter = binaryTypeDescriptor?.set; + +if (OriginalWebSocket && originalSetter) { + global.WebSocket = new Proxy(OriginalWebSocket, { + construct(target, args) { + //@ts-ignore + const ws = new target(...args) as WebSocket & { + _binaryType?: BinaryType; + }; + + Object.defineProperty(ws, "binaryType", { + get(): BinaryType { + return ws._binaryType || + (binaryTypeDescriptor.get + ? binaryTypeDescriptor.get.call(ws) + : "arraybuffer"); + }, + set(value: BinaryType) { + //@ts-ignore + if (value === "blob") { + originalSetter.call(ws, "arraybuffer"); + //@ts-ignore + ws._binaryType = "blob"; + } else { + originalSetter.call(ws, value); + ws._binaryType = value; + } + }, + configurable: true, + }); + + return ws; + }, + }) as typeof WebSocket; +} export const bot = new Bot({ service: env.SERVICE, emitChatEvents: true, eventEmitterOptions: { - strategy: env.USE_FIREHOSE - ? EventStrategy.Firehose + strategy: env.USE_JETSTREAM + ? EventStrategy.Jetstream : EventStrategy.Polling, }, }); diff --git a/src/env.ts b/src/env.ts index 2d622a5..9dcab0f 100644 --- a/src/env.ts +++ b/src/env.ts @@ -11,9 +11,11 @@ const envSchema = z.object({ DB_PATH: z.string().default("sqlite.db"), GEMINI_MODEL: z.string().default("gemini-2.5-flash"), + ADMIN_DID: z.string().optional(), + DID: z.string(), HANDLE: z.string(), - BSKY_PASSWORD: z.string(), + APP_PASSWORD: z.string(), GEMINI_API_KEY: z.string(), DAILY_QUERY_LIMIT: z.preprocess( @@ -21,7 +23,7 @@ const envSchema = z.object({ (typeof val === "string" && val.trim() !== "") ? Number(val) : undefined, z.number().int().positive().default(15), ), - USE_FIREHOSE: z.preprocess( + USE_JETSTREAM: z.preprocess( (val) => val === "true", z.boolean().default(false), ), diff --git a/src/handlers/messages.ts b/src/handlers/messages.ts index 28a3a1f..be02328 100644 --- a/src/handlers/messages.ts +++ b/src/handlers/messages.ts @@ -170,12 +170,12 @@ export async function handler(message: ChatMessage): Promise { throw new Error("Failed to generate text. Returned undefined."); } - logger.success("Generated text:", inference.text); - - saveMessage(conversation, env.DID, inference.text!); - const responseText = inference.text; + if (responseText) { + logger.success("Generated text:", inference.text); + saveMessage(conversation, env.DID, inference.text!); + await sendResponse(conversation, responseText); } } catch (error) { diff --git a/src/index.ts b/src/index.ts index eafbc4e..94ccb5b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,7 +11,7 @@ logger.info("Logging in.."); try { await bot.login({ identifier: env.HANDLE, - password: env.BSKY_PASSWORD, + password: env.APP_PASSWORD, }); logger.success(`Logged in as @${env.HANDLE} (${env.DID})`);