Biome fix
This commit is contained in:
60
index.ts
60
index.ts
@@ -1,7 +1,7 @@
|
||||
import { api } from "misskey-js";
|
||||
import Stream from "./misskey-js/streaming";
|
||||
import type { Stream as MisskeyStream } from "misskey-js";
|
||||
import type { Note, UserLite } from "misskey-js/entities.js";
|
||||
import Stream from "./misskey-js/streaming";
|
||||
|
||||
import OpenAI from "openai";
|
||||
import type { ChatCompletionMessageParam } from "openai/resources/index.js";
|
||||
@@ -16,7 +16,6 @@ const openai = new OpenAI({
|
||||
apiKey: Bun.env["OPENAI_API_KEY"],
|
||||
});
|
||||
|
||||
|
||||
// #region util
|
||||
|
||||
/** pick up to random N elements from array.
|
||||
@@ -37,42 +36,40 @@ const sleep = (msec: number) =>
|
||||
new Promise((resolve) => setTimeout(resolve, msec));
|
||||
// #endregion
|
||||
|
||||
|
||||
// #region misskey
|
||||
const me = await misskey.request("i", {});
|
||||
|
||||
/** check if a note is suitable as an input */
|
||||
const isSuitableAsInput = (n: Note) =>
|
||||
!n.user.isBot
|
||||
&& !n.replyId
|
||||
&& (!n.mentions || n.mentions.length === 0)
|
||||
&& n.text?.length && n.text.length > 0
|
||||
!n.user.isBot &&
|
||||
!n.replyId &&
|
||||
(!n.mentions || n.mentions.length === 0) &&
|
||||
n.text?.length &&
|
||||
n.text.length > 0;
|
||||
|
||||
/** randomly sample some notes from the timeline */
|
||||
async function getNotes() {
|
||||
|
||||
// randomly sample N local notes
|
||||
const localNotes = (count: number) =>
|
||||
misskey.request("notes/local-timeline", { limit: 100 })
|
||||
misskey
|
||||
.request("notes/local-timeline", { limit: 100 })
|
||||
.then((xs) => xs.filter(isSuitableAsInput))
|
||||
.then((xs) => sample(xs, count));
|
||||
|
||||
// randomly sample N global notes
|
||||
const globalNotes = (count: number) =>
|
||||
misskey.request("notes/global-timeline", { limit: 100 })
|
||||
misskey
|
||||
.request("notes/global-timeline", { limit: 100 })
|
||||
.then((xs) => xs.filter(isSuitableAsInput))
|
||||
.then((xs) => sample(xs, count));
|
||||
|
||||
// randomly sample N notes of mine
|
||||
const myNotes = (count: number) =>
|
||||
misskey.request("users/notes", { userId: me.id, limit: 100 })
|
||||
misskey
|
||||
.request("users/notes", { userId: me.id, limit: 100 })
|
||||
.then((xs) => sample(xs, count));
|
||||
|
||||
const notes = await Promise.all([
|
||||
localNotes(5),
|
||||
globalNotes(10),
|
||||
myNotes(2),
|
||||
]);
|
||||
const notes = await Promise.all([localNotes(5), globalNotes(10), myNotes(2)]);
|
||||
return sample(notes.flat());
|
||||
}
|
||||
|
||||
@@ -87,16 +84,20 @@ async function expandReplyTree(note: Note, acc: Note[] = [], cutoff = 5) {
|
||||
const noteToMessage = (note: Note): ChatCompletionMessageParam => ({
|
||||
role: note.userId === me.id ? ("assistant" as const) : ("user" as const),
|
||||
content: note.text?.replaceAll(`@${me.username}`, "") || "",
|
||||
})
|
||||
});
|
||||
// #endregion
|
||||
|
||||
|
||||
// #region job
|
||||
type Job =
|
||||
// read posts and post a note
|
||||
| { type: "post" }
|
||||
// reply to a specific note
|
||||
| { type: "reply"; id: string, visibility: Note["visibility"], replyTree: Note[] };
|
||||
| {
|
||||
type: "reply";
|
||||
id: string;
|
||||
visibility: Note["visibility"];
|
||||
replyTree: Note[];
|
||||
};
|
||||
|
||||
/** create a prompt for the job */
|
||||
async function preparePrompt(job: Job): Promise<ChatCompletionMessageParam[]> {
|
||||
@@ -154,7 +155,7 @@ user が SNS 上で、あなたへのメッセージを送ってきています
|
||||
|
||||
このような文体を真似して、user の発言に返答してください。`,
|
||||
},
|
||||
...(job.replyTree.map(noteToMessage))
|
||||
...job.replyTree.map(noteToMessage),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -187,7 +188,8 @@ async function processJob(job: Job) {
|
||||
console.log();
|
||||
|
||||
// concatenate the partial responses
|
||||
const text = responses.join("")
|
||||
const text = responses
|
||||
.join("")
|
||||
.replaceAll(/(\r\n|\r|\n)\s+/g, "\n\n") // remove extra newlines
|
||||
.replaceAll("@", ""); // remove mentions
|
||||
|
||||
@@ -221,8 +223,8 @@ function initializeStream() {
|
||||
token: Bun.env["MISSKEY_CREDENTIAL"] ?? "",
|
||||
},
|
||||
{
|
||||
binaryType: "arraybuffer"
|
||||
}
|
||||
binaryType: "arraybuffer",
|
||||
},
|
||||
) as unknown as MisskeyStream;
|
||||
channel = stream.useChannel("main");
|
||||
|
||||
@@ -241,7 +243,12 @@ function initializeStream() {
|
||||
if (e.text && e.userId !== me.id && !e.user.isBot) {
|
||||
const replyTree = await expandReplyTree(e);
|
||||
console.log(`* push: reply (${e.id}, ${replyTree.length} msgs)`);
|
||||
jobs.push({ type: "reply", id: e.id, visibility: e.visibility, replyTree });
|
||||
jobs.push({
|
||||
type: "reply",
|
||||
id: e.id,
|
||||
visibility: e.visibility,
|
||||
replyTree,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -276,7 +283,10 @@ async function pushJob() {
|
||||
while (true) {
|
||||
const now = new Date(Date.now());
|
||||
// push a post job every 15 minutes (XX:00, XX:15, XX:30, XX:45)
|
||||
if (now.getMinutes() % 15 < Number.EPSILON && !jobs.some((job) => job.type === "post")) {
|
||||
if (
|
||||
now.getMinutes() % 15 < Number.EPSILON &&
|
||||
!jobs.some((job) => job.type === "post")
|
||||
) {
|
||||
console.log("* push: post");
|
||||
jobs.push({ type: "post" });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user