diff --git a/DevTools/Chat.ts b/DevTools/Chat.ts index 96530fa..570f773 100644 --- a/DevTools/Chat.ts +++ b/DevTools/Chat.ts @@ -1,18 +1,20 @@ import clipboard from "clipboardy"; import "dotenv/config"; -import { readFile, watch, writeFile } from "fs/promises"; +import { readFile, watch } from "fs/promises"; import { Configuration, OpenAIApi } from "openai"; import { Readable } from "stream"; import { TextDecoderStream, TransformStream, WritableStream } from "stream/web"; + const apiKey = process.env.OPENAI_API_KEY; const ai = new OpenAIApi(new Configuration({ apiKey })); +let ac = new AbortController(); console.log("chat loaded"); const context = ` // Context `; -const codeCompletorIndicator = ` +const codeCompletorPrompt = (input = "") => ` You are a typescript-react engineer. Your skill stack included: @@ -22,33 +24,57 @@ Please complete my TODOs comments placed in my code, I will send you the whole file contents with TODOs comments, and you shold reply your well styled code modifications segments near TODOs. -Don't explain your modifications, just give me code segment near TODOs. +${"```typescript"} +${input} +${"```"} + +And the Optimized typescript code is: -If you understand, reply yes. +${"```typescript"} `; -const anyToChineseTranslatorPrompt = ` +const anyToChineseTranslatorPrompt = (input = "") => ` You are a Chinese translator, you are translating any language article to Chinese. Please give me Chinese transcript of every message sent to you, -If you understand, reply yes. + +${"```plaintext"} +${input} +${"```"} + +${"```plaintext"} `; -const anyToJapaneseTranslatorPrompt = ` +const anyToJapaneseTranslatorPrompt = (input = "") => ` You are a Japanese translator, you are translating any language article to Japanese. Please give me Japanese transcript of every message sent to you, -If you understand, reply yes. + +${"```plaintext"} +${input} +${"```"} + +${"```plaintext"} +`; + +const anyToEnglishTranslatorPrompt = (input = "") => ` +You are a English translator, you are translating any language article to English. +Please give me English transcript of every message sent to you, + +${"```plaintext"} +${input} +${"```"} + +${"```plaintext"} `; -// prompt5.js -// enquirer -const clipFile = "./DevTools/clipboard.log"; +const clipFile = "./DevTools/clipboard.signal.log"; const clipOutFile = "./DevTools/clipboard-gpt.log"; const indicatorMapping = { + "--en": anyToEnglishTranslatorPrompt, "--jp": anyToJapaneseTranslatorPrompt, "--zh": anyToChineseTranslatorPrompt, - "--chat": "", - "--code": codeCompletorIndicator, + "--chat": (e = "") => e, + "--code": codeCompletorPrompt, }; async function main() { await onClipboardReceived(); @@ -94,37 +120,70 @@ async function onClipboardReceived() { const [params, ...contents] = content .replace(/\r\n/g, "\n") .split("\n---\n\n"); - const prompt = indicatorMapping[params.trim()] ?? params.trim(); - const question = contents.join("\n\n---\n\n"); - console.log("Got prompt: \n", prompt); + const input = contents.join("\n\n---\n\n"); + const question = indicatorMapping[params.trim()]?.(input) ?? input; console.log("Got question: \n", question); - await completion(prompt, question); + + // todo: implement appendToClipboard(token) here + let cp = ""; + async function appendToClipboard(token: string) { + cp += token; + await clipboard.write(cp).catch(() => null); + } + + (await completion2(question)) + .pipeTo( + new WritableStream({ + start: async () => { + console.clear(); + await appendToClipboard(""); + }, + write: async (token) => { + process.stdout.write(token); + await appendToClipboard(token); + }, + close: async () => { + process.stdout.write("\n"); + console.log("✅ clipboard written"); + await appendToClipboard(""); + }, + }), + ) + .catch((err) => console.error(err)); } +// async function onClipboardReceived() { +// console.clear(); + +// const content = +// (await readFile(clipFile, "utf-8").catch(() => null)) ?? +// (await clipboard.read().catch(() => null)) ?? +// null; +// const [params, ...contents] = content +// .replace(/\r\n/g, "\n") +// .split("\n---\n\n"); +// const prompt = indicatorMapping[params.trim()]?.(contents) ?? params.trim(); +// const question = contents.join("\n\n---\n\n"); +// console.log("Got prompt: \n", prompt); +// console.log("Got question: \n", question); +// await completion(prompt, question); +// } // -async function completion(indicator: string, content: any) { +const completion2 = async (content = "") => { + ac?.abort?.(); + ac = new AbortController(); + const signal = ac.signal; const r = await ai.createChatCompletion( { model: "gpt-4", - messages: indicator - ? [ - // { role: "system", content: context }, - { - role: "user", - content: indicator, - }, - { role: "assistant", content: "yes" }, - { role: "user", content }, - ] - : [{ role: "user", content }], + messages: [ + { role: "system", content: "You are AI assistant." }, + { role: "user", content }, + ], stream: true, }, - { - responseType: "stream", - }, + { responseType: "stream", signal }, ); - - let resp = ""; - await Readable.toWeb(r.data as Readable) + return Readable.toWeb(r.data as Readable) .pipeThrough(new TextDecoderStream()) .pipeThrough( new TransformStream({ @@ -136,29 +195,63 @@ async function completion(indicator: string, content: any) { .map((token) => controller.enqueue(token)); }, }), - ) - .pipeTo( - new WritableStream({ - start: () => { - console.clear(); - }, - write: (chunk) => { - process.stdout.write(chunk); - resp += chunk; - }, - close: () => { - process.stdout.write("\n"); - }, - }), ); - const respond = resp.replace( - /^```(?:typescript)?([\s\S]*)```$/, - (_, $1) => $1, - ); - // const respond = (r.data.choices.map(e => e.message.content).join('\n')) - // console.log(respond) - // await clipboard.write([await clipboard.read(), respond].join("\n\n\n")); - await writeFile(clipOutFile, respond); - await clipboard.write(respond); - console.log("✅ clipboard written"); -} +}; +// async function completion(indicator: string, content: any) { +// const r = await ai.createChatCompletion( +// { +// model: "gpt-4", +// messages: indicator +// ? [ +// // { role: "system", content: 'You are ai assistant that helps' }, +// { +// role: "user", +// content: indicator, +// }, +// { role: "assistant", content: "yes" }, +// { role: "user", content }, +// ] +// : [{ role: "user", content }], +// stream: true, +// }, +// { +// responseType: "stream", +// }, +// ); + +// let resp = ""; +// await Readable.toWeb(r.data as Readable) +// .pipeThrough(new TextDecoderStream()) +// .pipeThrough( +// new TransformStream({ +// transform(chunk, controller) { +// [...chunk.matchAll(/^data: ({.*)/gm)] +// .map((m) => m?.[1] ?? "{}") +// .flatMap((e) => JSON.parse(e)?.choices ?? []) +// .map((c) => c.delta?.content ?? "") +// .map((token) => controller.enqueue(token)); +// }, +// }), +// ) +// .pipeTo( +// new WritableStream({ +// start: () => { +// console.clear(); +// }, +// write: (chunk) => { +// process.stdout.write(chunk); +// resp += chunk; +// }, +// close: () => { +// process.stdout.write("\n"); +// }, +// }), +// ); +// const respond = resp.replace( +// /^```(?:typescript)?([\s\S]*)```$/, +// (_, $1) => $1, +// ); +// await writeFile(clipOutFile, respond); +// await clipboard.write(respond); +// console.log("✅ clipboard written"); +// } diff --git a/clx-docs/app/api/completions.ts b/clx-docs/app/api/completions.ts new file mode 100644 index 0000000..8a6b98d --- /dev/null +++ b/clx-docs/app/api/completions.ts @@ -0,0 +1,2 @@ +// TODO: post completions +export {} \ No newline at end of file