Spaces:
Paused
Paused
djmuted
commited on
Commit
•
0e39520
1
Parent(s):
d899182
Add multiple slack support
Browse files- .gitignore +3 -1
- Dockerfile +2 -2
- src/config.json.example +11 -0
- src/openai.js +24 -8
- src/slack.js +7 -8
.gitignore
CHANGED
@@ -127,4 +127,6 @@ dist
|
|
127 |
.yarn/unplugged
|
128 |
.yarn/build-state.yml
|
129 |
.yarn/install-state.gz
|
130 |
-
.pnp.*
|
|
|
|
|
|
127 |
.yarn/unplugged
|
128 |
.yarn/build-state.yml
|
129 |
.yarn/install-state.gz
|
130 |
+
.pnp.*
|
131 |
+
|
132 |
+
src/config.json
|
Dockerfile
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
FROM node:18-bullseye-slim
|
2 |
COPY . /app
|
3 |
WORKDIR /app
|
4 |
-
RUN --mount=type=secret,id=
|
5 |
-
cat /run/secrets/
|
6 |
EXPOSE 7860
|
7 |
ENV NODE_ENV=production
|
8 |
CMD [ "yarn", "start" ]
|
|
|
1 |
FROM node:18-bullseye-slim
|
2 |
COPY . /app
|
3 |
WORKDIR /app
|
4 |
+
RUN --mount=type=secret,id=CONFIG,mode=0444,required=true \
|
5 |
+
cat /run/secrets/CONFIG > /app/src/config.json && yarn install
|
6 |
EXPOSE 7860
|
7 |
ENV NODE_ENV=production
|
8 |
CMD [ "yarn", "start" ]
|
src/config.json.example
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"slacks": [
|
3 |
+
{
|
4 |
+
"token": "",
|
5 |
+
"cookie": "",
|
6 |
+
"teamId": "",
|
7 |
+
"claudeId": ""
|
8 |
+
}
|
9 |
+
],
|
10 |
+
"apiKey": ""
|
11 |
+
}
|
src/openai.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
const { Router } = require('express');
|
2 |
const bodyParser = require('body-parser');
|
3 |
-
const config = require('./config');
|
4 |
const slack = require('./slack');
|
5 |
const yup = require('yup');
|
6 |
const { splitJsonArray, dataToResponse, buildPrompt } = require("./utils");
|
@@ -29,12 +29,18 @@ openaiRouter.get("/models", (req, res) => {
|
|
29 |
]);
|
30 |
});
|
31 |
|
32 |
-
const parallelQueries =
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
const myq = new Queue(parallelQueries, 100);
|
34 |
|
35 |
openaiRouter.post("/chat/completions", jsonParser, async (req, res) => {
|
36 |
try {
|
37 |
-
if (req.token !== config.
|
38 |
res.status(401).json({ error: "Unauthorized" });
|
39 |
return;
|
40 |
}
|
@@ -45,9 +51,6 @@ openaiRouter.post("/chat/completions", jsonParser, async (req, res) => {
|
|
45 |
return;
|
46 |
}
|
47 |
|
48 |
-
const id = `chatcmpl-${(Math.random().toString(36).slice(2))}`;
|
49 |
-
const created = Math.floor(Date.now() / 1000);
|
50 |
-
|
51 |
const messagesSplit = splitJsonArray(messages, 12000);
|
52 |
|
53 |
if (stream) {
|
@@ -74,8 +77,21 @@ openaiRouter.post("/chat/completions", jsonParser, async (req, res) => {
|
|
74 |
};
|
75 |
|
76 |
const result = await myq.run(async () => {
|
77 |
-
|
78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
});
|
80 |
|
81 |
if (stream) {
|
|
|
1 |
const { Router } = require('express');
|
2 |
const bodyParser = require('body-parser');
|
3 |
+
const config = require('./config.json');
|
4 |
const slack = require('./slack');
|
5 |
const yup = require('yup');
|
6 |
const { splitJsonArray, dataToResponse, buildPrompt } = require("./utils");
|
|
|
29 |
]);
|
30 |
});
|
31 |
|
32 |
+
const parallelQueries = config.slacks.length;
|
33 |
+
const slacks = config.slacks.map((slackConfig) => {
|
34 |
+
return {
|
35 |
+
...slackConfig,
|
36 |
+
locked: false,
|
37 |
+
};
|
38 |
+
});
|
39 |
const myq = new Queue(parallelQueries, 100);
|
40 |
|
41 |
openaiRouter.post("/chat/completions", jsonParser, async (req, res) => {
|
42 |
try {
|
43 |
+
if (config.apiKey && req.token !== config.apiKey) {
|
44 |
res.status(401).json({ error: "Unauthorized" });
|
45 |
return;
|
46 |
}
|
|
|
51 |
return;
|
52 |
}
|
53 |
|
|
|
|
|
|
|
54 |
const messagesSplit = splitJsonArray(messages, 12000);
|
55 |
|
56 |
if (stream) {
|
|
|
77 |
};
|
78 |
|
79 |
const result = await myq.run(async () => {
|
80 |
+
let slackConfig = slacks.find((slack) => !slack.locked);
|
81 |
+
if (!slackConfig) {
|
82 |
+
throw new Error('Queue full');
|
83 |
+
}
|
84 |
+
slackConfig.locked = true;
|
85 |
+
try {
|
86 |
+
await slack.sendChatReset(slackConfig);
|
87 |
+
const response = await slack.waitForWebSocketResponse(slackConfig, messagesSplit, onData);
|
88 |
+
slackConfig.locked = false;
|
89 |
+
return response;
|
90 |
+
} catch (error) {
|
91 |
+
slackConfig.locked = false;
|
92 |
+
console.error(error);
|
93 |
+
throw new Error('Slack error');
|
94 |
+
}
|
95 |
});
|
96 |
|
97 |
if (stream) {
|
src/slack.js
CHANGED
@@ -3,10 +3,9 @@ const { v4: uuidv4 } = require('uuid');
|
|
3 |
const https = require('https');
|
4 |
const WebSocket = require('ws');
|
5 |
|
6 |
-
const { TOKEN, COOKIE, TEAM_ID } = require('./config');
|
7 |
const { readBody, headers, createBaseForm, convertToUnixTime, currentTime, buildPrompt } = require('./utils');
|
8 |
|
9 |
-
async function sendPromptMessage(prompt) {
|
10 |
const form = createBaseForm();
|
11 |
|
12 |
form.append('ts', convertToUnixTime(new Date()));
|
@@ -26,7 +25,7 @@ async function sendPromptMessage(prompt) {
|
|
26 |
},
|
27 |
};
|
28 |
|
29 |
-
const req = https.request(`https://${
|
30 |
try {
|
31 |
const response = await readBody(res, true);
|
32 |
console.log(response);
|
@@ -42,7 +41,7 @@ async function sendPromptMessage(prompt) {
|
|
42 |
form.pipe(req);
|
43 |
}
|
44 |
|
45 |
-
async function sendChatReset() {
|
46 |
const form = createBaseForm();
|
47 |
|
48 |
form.append('command', '/reset');
|
@@ -58,7 +57,7 @@ async function sendChatReset() {
|
|
58 |
},
|
59 |
};
|
60 |
|
61 |
-
const req = https.request(`https://${
|
62 |
try {
|
63 |
const response = await readBody(res, true);
|
64 |
console.log(response);
|
@@ -74,9 +73,9 @@ async function sendChatReset() {
|
|
74 |
form.pipe(req);
|
75 |
}
|
76 |
|
77 |
-
async function waitForWebSocketResponse(messages, onData) {
|
78 |
return new Promise(async (resolve, reject) => {
|
79 |
-
const websocketURL = `wss://wss-primary.slack.com/?token=${
|
80 |
|
81 |
const websocket = new WebSocket(websocketURL, {
|
82 |
headers: headers,
|
@@ -95,7 +94,7 @@ async function waitForWebSocketResponse(messages, onData) {
|
|
95 |
const sendNextPrompt = async () => {
|
96 |
if (messageIndex < messages.length) {
|
97 |
const prompt = buildPrompt(messages[messageIndex]);
|
98 |
-
await sendPromptMessage(prompt);
|
99 |
messageIndex++;
|
100 |
}
|
101 |
};
|
|
|
3 |
const https = require('https');
|
4 |
const WebSocket = require('ws');
|
5 |
|
|
|
6 |
const { readBody, headers, createBaseForm, convertToUnixTime, currentTime, buildPrompt } = require('./utils');
|
7 |
|
8 |
+
async function sendPromptMessage(config, prompt) {
|
9 |
const form = createBaseForm();
|
10 |
|
11 |
form.append('ts', convertToUnixTime(new Date()));
|
|
|
25 |
},
|
26 |
};
|
27 |
|
28 |
+
const req = https.request(`https://${config.teamId}.slack.com/api/chat.postMessage`, options, async (res) => {
|
29 |
try {
|
30 |
const response = await readBody(res, true);
|
31 |
console.log(response);
|
|
|
41 |
form.pipe(req);
|
42 |
}
|
43 |
|
44 |
+
async function sendChatReset(config) {
|
45 |
const form = createBaseForm();
|
46 |
|
47 |
form.append('command', '/reset');
|
|
|
57 |
},
|
58 |
};
|
59 |
|
60 |
+
const req = https.request(`https://${config.teamId}.slack.com/api/chat.command`, options, async (res) => {
|
61 |
try {
|
62 |
const response = await readBody(res, true);
|
63 |
console.log(response);
|
|
|
73 |
form.pipe(req);
|
74 |
}
|
75 |
|
76 |
+
async function waitForWebSocketResponse(config, messages, onData) {
|
77 |
return new Promise(async (resolve, reject) => {
|
78 |
+
const websocketURL = `wss://wss-primary.slack.com/?token=${config.token}`;
|
79 |
|
80 |
const websocket = new WebSocket(websocketURL, {
|
81 |
headers: headers,
|
|
|
94 |
const sendNextPrompt = async () => {
|
95 |
if (messageIndex < messages.length) {
|
96 |
const prompt = buildPrompt(messages[messageIndex]);
|
97 |
+
await sendPromptMessage(config, prompt);
|
98 |
messageIndex++;
|
99 |
}
|
100 |
};
|