-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.ts
More file actions
95 lines (80 loc) · 2.35 KB
/
Copy pathindex.ts
File metadata and controls
95 lines (80 loc) · 2.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { Chat, toAiMessages } from "chat";
import { createSlackAdapter } from "@chat-adapter/slack";
import { createRedisState } from "@chat-adapter/state-redis";
const slackAdapter = createSlackAdapter();
async function* streamCodex(prompt: string): AsyncIterable<string> {
const proc = Bun.spawn(
["codex", "exec", "--ephemeral", "-s", "read-only", "--json", "-"],
{ stdin: "pipe", stdout: "pipe", stderr: "ignore" },
);
proc.stdin.write(prompt);
proc.stdin.end();
const decoder = new TextDecoder();
let buffer = "";
let messageCount = 0;
for await (const chunk of proc.stdout) {
buffer += decoder.decode(chunk, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() ?? "";
for (const line of lines) {
if (!line.trim()) continue;
try {
const event = JSON.parse(line);
if (
event.type === "item.completed" &&
event.item?.type === "agent_message" &&
event.item.text
) {
if (messageCount > 0) yield "\n\n---\n\n";
yield event.item.text;
messageCount++;
}
} catch {}
}
}
if (buffer.trim()) {
try {
const event = JSON.parse(buffer);
if (
event.type === "item.completed" &&
event.item?.type === "agent_message" &&
event.item.text
) {
if (messageCount > 0) yield "\n\n---\n\n";
yield event.item.text;
}
} catch {}
}
}
const bot = new Chat({
userName: "edison-bot",
adapters: {
slack: slackAdapter,
},
state: createRedisState(),
});
bot.onNewMention(async (thread, message) => {
await thread.startTyping();
const result = await thread.adapter.fetchMessages(thread.id, { limit: 20 });
const history = await toAiMessages(result.messages, { includeNames: true });
const prompt = history
.map((m) => `${m.role}: ${typeof m.content === "string" ? m.content : JSON.stringify(m.content)}`)
.join("\n");
await thread.post(streamCodex(prompt));
});
await bot.initialize();
const port = 3123;
Bun.serve({
port,
routes: {
"/api/webhooks/slack": {
POST: async (req) => {
return slackAdapter.handleWebhook(req);
},
},
},
fetch(req) {
return new Response("Not found", { status: 404 });
},
});
console.log("Bot is running! Webhook listening on http://localhost:3123/api/webhooks/slack");