From 9b73abe0467476a8ad4efa8a88a2d516f39d7e10 Mon Sep 17 00:00:00 2001
From: Bram Adams <3282661+bramses@users.noreply.github.com>
Date: Sat, 18 Mar 2023 20:00:11 -0400
Subject: [PATCH] stream cleanup
---
main.ts | 66 +------------------
stream.ts | 191 ++++++++++++++++++++++++++++--------------------------
2 files changed, 101 insertions(+), 156 deletions(-)
diff --git a/main.ts b/main.ts
index c4af763..280e661 100644
--- a/main.ts
+++ b/main.ts
@@ -89,8 +89,6 @@ export default class ChatGPT_MD extends Plugin {
};
editor.setCursor(newCursor);
- let fullstr = "";
-
const options = {
model: model,
messages: messages,
@@ -113,7 +111,7 @@ export default class ChatGPT_MD extends Plugin {
this.settings.generateAtCursor
);
- console.log("response", response);
+ console.log("response from stream", response);
return { fullstr: response, mode: "streaming" }
} else {
@@ -161,68 +159,6 @@ export default class ChatGPT_MD extends Plugin {
}
const response = responseUrl.text;
-
- // if (stream) {
- // // split response by new line
- // const responseLines = response.split("\n\n");
-
- // if (responseLines.length == 0) {
- // throw new Error("[ChatGPT MD] no response");
- // }
-
- // // remove data: from each line
- // for (let i = 0; i < responseLines.length; i++) {
- // responseLines[i] = responseLines[i].split("data: ")[1];
- // }
-
- // const newLine = `\n\n
\n\nrole::assistant\n\n`;
- // editor.replaceRange(newLine, editor.getCursor());
-
- // // move cursor to end of line
- // const cursor = editor.getCursor();
- // const newCursor = {
- // line: cursor.line,
- // ch: cursor.ch + newLine.length,
- // };
- // editor.setCursor(newCursor);
-
- // let fullstr = "";
-
- // // loop through response lines
- // for (const responseLine of responseLines) {
- // // if response line is not [DONE] then parse json and append delta to file
- // if (responseLine && !responseLine.includes("[DONE]")) {
- // const responseJSON = JSON.parse(responseLine);
- // const delta = responseJSON.choices[0].delta.content;
-
- // // if delta is not undefined then append delta to file
- // if (delta) {
- // const cursor = editor.getCursor();
- // if (delta === "`") {
- // editor.replaceRange(delta, cursor);
- // await new Promise((r) => setTimeout(r, 82)); // what in the actual fuck -- why does this work
- // } else {
- // editor.replaceRange(delta, cursor);
- // await new Promise((r) =>
- // setTimeout(r, this.settings.streamSpeed)
- // );
- // }
-
- // const newCursor = {
- // line: cursor.line,
- // ch: cursor.ch + delta.length,
- // };
- // editor.setCursor(newCursor);
-
- // fullstr += delta;
- // }
- // }
- // }
-
- // console.log(fullstr);
-
- // return { fullstr: fullstr, mode: "streaming" };
- // } else {
const responseJSON = JSON.parse(response);
return responseJSON.choices[0].message.content;
}
diff --git a/stream.ts b/stream.ts
index fff994c..abde23c 100644
--- a/stream.ts
+++ b/stream.ts
@@ -29,95 +29,104 @@ export const streamSSE = async (
options: OpenAIStreamPayload,
setAtCursor: boolean
) => {
- console.log("streamSSE", options);
-
- const url = "https://api.openai.com/v1/chat/completions";
-
- const source = new SSE(url, {
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${apiKey}`,
- },
- method: "POST",
- payload: JSON.stringify(options),
- });
-
- let txt = "";
- const initialCursorPosCh = editor.getCursor().ch;
- const initialCursorPosLine = editor.getCursor().line;
- source.addEventListener("message", (e: any) => {
- if (e.data != "[DONE]") {
- const payload = JSON.parse(e.data);
- const text = payload.choices[0].delta.content;
-
- // if text undefined, then do nothing
- if (!text) {
- return;
- }
-
- const cursor = editor.getCursor();
- const convPos = editor.posToOffset(cursor);
-
- const cm6 = editor.cm;
- const transaction = cm6.state.update({
- changes: { from: convPos, to: convPos, insert: text },
- });
- cm6.dispatch(transaction);
-
-
- txt += text;
-
- const newCursor = {
- line: cursor.line,
- ch: cursor.ch + text.length,
- };
- editor.setCursor(newCursor);
- } else {
- source.close();
- console.log("txt", txt);
-
- // replace the text from initialCursor to fix any formatting issues from streaming
- const cursor = editor.getCursor();
- editor.replaceRange(
- txt,
- { line: initialCursorPosLine, ch: initialCursorPosCh },
- cursor
- );
-
- // set cursor to end of replacement text
- const newCursor = {
- line: initialCursorPosLine,
- ch: initialCursorPosCh + txt.length,
- };
- editor.setCursor(newCursor);
-
- // remove extraneous text
- // const textAfterCursor = editor.getRange(newCursor, {
- // line: Infinity,
- // ch: Infinity,
- // });
-
- if (!setAtCursor) {
- // remove the text after the cursor
- editor.replaceRange("", newCursor, {
- line: Infinity,
- ch: Infinity,
- });
- } else {
- new Notice(
- "[ChatGPT MD] Text pasted at cursor may leave artifacts. Please remove them manually. ChatGPT MD cannot safely remove text when pasting at cursor."
- );
- }
-
- return txt;
- }
- });
-
- source.addEventListener("readystatechange", (e: any) => {
- if (e.readyState >= 2) {
- console.log("ReadyState: " + e.readyState);
- }
- });
-
- source.stream();
+ return new Promise((resolve, reject) => {
+ try {
+ console.log("streamSSE", options);
+
+ const url = "https://api.openai.com/v1/chat/completions";
+
+ const source = new SSE(url, {
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${apiKey}`,
+ },
+ method: "POST",
+ payload: JSON.stringify(options),
+ });
+
+ let txt = "";
+ const initialCursorPosCh = editor.getCursor().ch;
+ const initialCursorPosLine = editor.getCursor().line;
+ source.addEventListener("message", (e: any) => {
+ if (e.data != "[DONE]") {
+ const payload = JSON.parse(e.data);
+ const text = payload.choices[0].delta.content;
+
+ // if text undefined, then do nothing
+ if (!text) {
+ return;
+ }
+
+ const cursor = editor.getCursor();
+ const convPos = editor.posToOffset(cursor);
+
+ // @ts-ignore
+ const cm6 = editor.cm;
+ const transaction = cm6.state.update({
+ changes: { from: convPos, to: convPos, insert: text },
+ });
+ cm6.dispatch(transaction);
+
+
+ txt += text;
+
+ const newCursor = {
+ line: cursor.line,
+ ch: cursor.ch + text.length,
+ };
+ editor.setCursor(newCursor);
+ } else {
+ source.close();
+
+ // replace the text from initialCursor to fix any formatting issues from streaming
+ const cursor = editor.getCursor();
+ editor.replaceRange(
+ txt,
+ { line: initialCursorPosLine, ch: initialCursorPosCh },
+ cursor
+ );
+
+ // set cursor to end of replacement text
+ const newCursor = {
+ line: initialCursorPosLine,
+ ch: initialCursorPosCh + txt.length,
+ };
+ editor.setCursor(newCursor);
+
+ // remove extraneous text
+ // const textAfterCursor = editor.getRange(newCursor, {
+ // line: Infinity,
+ // ch: Infinity,
+ // });
+
+ if (!setAtCursor) {
+ // remove the text after the cursor
+ editor.replaceRange("", newCursor, {
+ line: Infinity,
+ ch: Infinity,
+ });
+ } else {
+ new Notice(
+ "[ChatGPT MD] Text pasted at cursor may leave artifacts. Please remove them manually. ChatGPT MD cannot safely remove text when pasting at cursor."
+ );
+ }
+
+ resolve(txt);
+ // return txt;
+ }
+ });
+
+ source.addEventListener("readystatechange", (e: any) => {
+ if (e.readyState >= 2) {
+ console.log("ReadyState: " + e.readyState);
+ }
+ });
+
+ source.stream();
+ } catch (err) {
+ console.error(err);
+ new Notice("[ChatGPT MD] Error streaming text. Please check console.");
+ reject(err);
+ }
+ });
};