A chill Bluesky bot, with responses powered by Gemini.
1import { exceedsGraphemes, multipartResponse } from "../utils/thread";
2import { AtUri } from "@atproto/syntax";
3import { Type } from "@google/genai";
4import { env } from "../env";
5import bot from "../bot";
6import z from "zod";
7
8export const definition = {
9 name: "create_post",
10 description:
11 "Creates a new Bluesky post/thread and returns the URL. Only do this if the user specifically requests a new thread.",
12 parameters: {
13 type: Type.OBJECT,
14 properties: {
15 text: {
16 type: Type.STRING,
17 description: "The text of the post.",
18 },
19 },
20 required: ["text"],
21 },
22};
23
24export const validator = z.object({
25 text: z.string(),
26});
27
28export async function handler(args: z.infer<typeof validator>) {
29 let uri: string | null = null;
30 if (exceedsGraphemes(args.text)) {
31 uri = await multipartResponse(args.text);
32 } else {
33 const post = await bot.post({
34 text: args.text,
35 });
36
37 uri = post.uri;
38 }
39
40 return {
41 link: `https://bsky.app/profile/${env.HANDLE}/${new AtUri(uri).rkey}`,
42 };
43}