omnibot3000 1.8.2 → 1.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,8 @@
1
1
  import {Fragment, memo, useEffect, useState} from "react";
2
2
  import {useNavigate, useParams} from "react-router-dom";
3
3
 
4
- import {
5
- ChatCompletionChunk,
6
- ChatCompletionMessageParam,
7
- } from "openai/resources/index.mjs";
8
- import {Stream} from "openai/streaming.mjs";
9
-
10
- import getData, {getChatTitle, getSystemConfig} from "@api/api";
4
+ import {getChatTitle} from "@api/api";
5
+ import getStream from "@api/utils/getStream";
11
6
  import Container from "@layout/Container";
12
7
 
13
8
  import useStorage from "@hooks/useStorage";
@@ -41,6 +36,44 @@ const Chat = () => {
41
36
  const {id} = useParams();
42
37
  const chatId = chatStore.getChatId();
43
38
 
39
+ const completionCallback = (
40
+ id: string,
41
+ created: number,
42
+ model: string,
43
+ query: string,
44
+ ) => {
45
+ setCompletion({
46
+ id: formatCompletionId(id),
47
+ created: created,
48
+ model: model,
49
+ prompt: query,
50
+ message: "",
51
+ index: 0,
52
+ children: [],
53
+ parentCompletion: completionId,
54
+ });
55
+ setCompletionId(id);
56
+ };
57
+
58
+ const submitHandler = (input: string) => {
59
+ setLoading(true);
60
+ setQuery(input);
61
+ getStream(
62
+ setLoading,
63
+ setResponse,
64
+ [
65
+ "keep your message short and concise, do not repeat yourself",
66
+ "do not present yourself again, focus on answering the user prompt",
67
+ "end your answer with an acid but funny haiku about humankind",
68
+ "this comment length must be less than 256 characters long",
69
+ "you must separate each part with a line or empty line",
70
+ ],
71
+ prompt,
72
+ chatStore.getMessages(id),
73
+ completionCallback,
74
+ );
75
+ };
76
+
44
77
  const setTitle = async (id: ChatId) => {
45
78
  const title = await getChatTitle(chatStore.getMessages(id));
46
79
  chatStore.updateChatTitle(id, title);
@@ -74,92 +107,30 @@ const Chat = () => {
74
107
  return () => unsubscribe();
75
108
  }, []);
76
109
 
77
- const getCompletion = async (query: string) => {
78
- setQuery(query); /* save the query before reset */
79
-
80
- if (String(query).replace("\n", "").trim() === "") return;
81
-
82
- setLoading(true);
83
-
84
- const messages: ChatCompletionMessageParam[] = [getSystemConfig()];
85
-
86
- messages.push({
87
- role: "developer",
88
- content: `\
89
- end all messages with a short, acid and fun commment about humankind weakness. \
90
- keep your message short, do not write more than 256 characters as comment. \
91
- you must separate each part of your answer with an empty line.`,
110
+ useEffect(() => {
111
+ if (!completion) return;
112
+ setCompletion((prev) => {
113
+ if (!prev) return;
114
+ prev.message = response;
115
+ return prev;
92
116
  });
93
-
94
- /* add chat history to the messages array to give context */
95
- if (chatId) {
96
- messages.push(...chatStore.getMessages(chatId));
97
- }
98
-
99
- /* append current query */
100
- messages.push({role: "user", content: query});
101
-
102
- const stream = (await getData(messages)) as Stream<ChatCompletionChunk>;
103
-
104
- try {
105
- for await (const chunk of stream) {
106
- const choice = chunk.choices?.[0] || {};
107
- const finish_reason = choice.finish_reason;
108
- const text = choice.delta?.content || "";
109
-
110
- if (finish_reason) {
111
- setLoading(false);
112
- if (finish_reason === "length") {
113
- setResponse((prev) => `${prev}\n\n[max tokens length reached]\n`);
114
- }
115
- setCompletion({
116
- id: formatCompletionId(chunk.id),
117
- created: chunk.created,
118
- model: chunk.model,
119
- prompt: query,
120
- message: "",
121
- index: 0,
122
- children: [],
123
- parentCompletion: completionId,
124
- });
125
- setCompletionId(chunk.id);
126
- }
127
-
128
- if (text) {
129
- setResponse((prev) => `${prev}${text}`);
130
- }
131
- }
132
- } catch (error) {
133
- console.error("Error reading stream:", error);
134
- setLoading(false);
117
+ if (!chatId) {
118
+ chatStore.setCompletions();
119
+ chatStore.createChat(completion);
120
+ setTitle(chatStore.getChatId());
135
121
  }
136
- };
137
-
138
- useEffect(() => {
139
- if (completion) {
140
- setCompletion((prev) => {
141
- if (!prev) return;
142
- prev.message = response;
143
- return prev;
144
- });
145
- if (!chatId) {
146
- chatStore.setCompletions();
147
- chatStore.createChat(completion);
148
- setTitle(chatStore.getChatId());
149
- }
150
- chatStore.addCompletion(completion);
151
- if (chatId) {
152
- chatStore.updateCompletions(chatId);
153
- setTitle(chatId);
154
- }
155
- /* reset values once the completion is saved in the store */
156
- setCompletion(undefined);
157
- setResponse("");
122
+ chatStore.addCompletion(completion);
123
+ if (chatId) {
124
+ chatStore.updateCompletions(chatId);
125
+ setTitle(chatId);
158
126
  }
127
+ /* reset values once the completion is saved in the store */
128
+ setCompletion(undefined);
129
+ setResponse("");
159
130
  }, [completion]);
160
131
 
161
132
  return (
162
- <div className={styles.root}>
133
+ <section className={styles.root}>
163
134
  <Container>
164
135
  {chatStore.getCompletions(chatId).map((completion: Completion) => (
165
136
  <Fragment key={`chat-completion-${completion.id}`}>
@@ -179,9 +150,9 @@ you must separate each part of your answer with an empty line.`,
179
150
  loading={loading}
180
151
  prompt={prompt}
181
152
  setPrompt={setPrompt}
182
- submitHandler={getCompletion}
153
+ submitHandler={submitHandler}
183
154
  />
184
- </div>
155
+ </section>
185
156
  );
186
157
  };
187
158
 
@@ -20,13 +20,13 @@ const Message = (props: {
20
20
  const isUser = Boolean(role === "user");
21
21
 
22
22
  return (
23
- <div className={styles.root}>
23
+ <article className={styles.root}>
24
24
  {isUser ? (
25
25
  <div className={styles.user}>
26
26
  <div className={styles["user-pill"]}>{">"}</div>
27
- <div>
27
+ <h1>
28
28
  <RenderCli command={content.split("\n")} line={-1} caret={0} />
29
- </div>
29
+ </h1>
30
30
  </div>
31
31
  ) : (
32
32
  <div className={styles.bot}>
@@ -38,7 +38,7 @@ const Message = (props: {
38
38
  <OmnibotSpeak truth={content} hasCaret={hasCaret} />
39
39
  </div>
40
40
  )}
41
- </div>
41
+ </article>
42
42
  );
43
43
  };
44
44
 
@@ -26,7 +26,7 @@ const Toolbar = (props: {completion: Completion}) => {
26
26
  const {completion} = props;
27
27
 
28
28
  return (
29
- <div className={styles.root}>
29
+ <footer className={styles.root}>
30
30
  <div className={styles.corner}>+</div>
31
31
  <Line variant="horizontal" className={styles["line"]} />
32
32
  <div className={cls("text", styles.toolbar)}>
@@ -37,7 +37,7 @@ const Toolbar = (props: {completion: Completion}) => {
37
37
  }}
38
38
  />
39
39
  </div>
40
- </div>
40
+ </footer>
41
41
  );
42
42
  };
43
43
 
@@ -36,7 +36,6 @@
36
36
  cursor: text !important;
37
37
  text-wrap: wrap;
38
38
  white-space: pre-wrap;
39
- word-break: break-all;
40
39
  }
41
40
 
42
41
  .placeholder {
@@ -1,10 +1,6 @@
1
1
  import {memo, useEffect, useRef, useState} from "react";
2
2
 
3
- import {ChatCompletionMessageParam} from "openai/resources";
4
- import {ChatCompletionChunk} from "openai/resources/index.mjs";
5
- import {Stream} from "openai/streaming.mjs";
6
-
7
- import getData, {getSystemConfig} from "@api/api";
3
+ import getStream from "@api/utils/getStream";
8
4
  import OmnibotSpeak from "@commons/OmnibotSpeak";
9
5
  import Container from "@layout/Container";
10
6
 
@@ -20,48 +16,25 @@ const Help = () => {
20
16
  const [response, setResponse] = useState<string>("");
21
17
  const [loading, setLoading] = useState<boolean>(false);
22
18
 
23
- const getResponse = async () => {
24
- try {
25
- const messages: ChatCompletionMessageParam[] = [getSystemConfig()];
26
-
27
- messages.push({
28
- role: "developer",
29
- content: `\
30
- make a list of all available config commands. \
31
- add a description of each command to help the user. \
32
- you can give a single example for commands that need parameter. \
33
- highlight the command in bold and keep all comments short.`,
34
- });
35
-
36
- const response = (await getData(messages)) as Stream<ChatCompletionChunk>;
37
-
38
- for await (const chunk of response) {
39
- const choice = chunk.choices?.[0] || {};
40
- const finish_reason = choice.finish_reason;
41
- const text = choice.delta?.content || "";
42
- if (finish_reason) {
43
- setLoading(false);
44
- if (finish_reason === "length")
45
- setResponse((prev) => `${prev}\n\n[max tokens length reached]\n`);
46
- break;
47
- }
48
- if (!text) continue;
49
- setResponse((prev) => `${prev}${text}`);
50
- }
51
- } catch (error) {
52
- console.error("Error reading stream:", error);
53
- setLoading(false);
54
- setResponse("no signal");
55
- }
56
- };
57
-
58
19
  useEffect(() => {
59
20
  if (hasRunOnce.current) return;
60
21
  hasRunOnce.current = true;
61
22
 
62
23
  chatStore.resetChat();
63
24
  setLoading(true);
64
- getResponse();
25
+ getStream(
26
+ setLoading,
27
+ setResponse,
28
+ [
29
+ "you can give a single example for commands that need parameter",
30
+ "highlight the command in bold and keep all comments shorts",
31
+ ],
32
+ [
33
+ "make a list of all available config commands",
34
+ "add a description of each command to help the user",
35
+ "do not include commands that are not provided",
36
+ ],
37
+ );
65
38
  }, []);
66
39
 
67
40
  return (
@@ -1,11 +1,8 @@
1
1
  import {memo, useEffect, useRef, useState} from "react";
2
2
  import {useNavigate} from "react-router-dom";
3
3
 
4
- import {ChatCompletionMessageParam} from "openai/resources";
5
- import {ChatCompletionChunk} from "openai/resources/index.mjs";
6
- import {Stream} from "openai/streaming.mjs";
7
-
8
- import getData, {getStartButton, getSystemConfig} from "@api/api";
4
+ import {getStartButton} from "@api/api";
5
+ import getStream from "@api/utils/getStream";
9
6
  import OmnibotSpeak from "@commons/OmnibotSpeak";
10
7
  import Container from "@layout/Container";
11
8
  import Button from "@ui/Button";
@@ -31,40 +28,6 @@ const Home = () => {
31
28
  setStartButton(formatText(data));
32
29
  };
33
30
 
34
- const getResponse = async () => {
35
- try {
36
- const messages: ChatCompletionMessageParam[] = [getSystemConfig()];
37
-
38
- messages.push({
39
- role: "developer",
40
- content: `\
41
- write an intro message for the user. keep it short and to the point. \
42
- explain who are you, why you are here and how you can help the user. \
43
- separate each element with an empty line.`,
44
- });
45
-
46
- const response = (await getData(messages)) as Stream<ChatCompletionChunk>;
47
-
48
- for await (const chunk of response) {
49
- const choice = chunk.choices?.[0] || {};
50
- const finish_reason = choice.finish_reason;
51
- const text = choice.delta?.content || "";
52
- if (finish_reason) {
53
- setLoading(false);
54
- if (finish_reason === "length")
55
- setResponse((prev) => `${prev}\n\n[max tokens length reached]\n`);
56
- break;
57
- }
58
- if (!text) continue;
59
- setResponse((prev) => `${prev}${text}`);
60
- }
61
- } catch (error) {
62
- console.error("Error reading stream:", error);
63
- setLoading(false);
64
- setResponse("no signal");
65
- }
66
- };
67
-
68
31
  const newChat = () => {
69
32
  chatStore.setChatId();
70
33
  chatStore.setCompletionId();
@@ -78,7 +41,21 @@ separate each element with an empty line.`,
78
41
 
79
42
  chatStore.resetChat();
80
43
  setLoading(true);
81
- getResponse();
44
+ getStream(
45
+ setLoading,
46
+ setResponse,
47
+ [
48
+ "keep it short and straight to the point",
49
+ "do not repeat yourself",
50
+ "do not exceed 512 characters",
51
+ "separate each element with an empty line",
52
+ ],
53
+ [
54
+ "write an intro message for the user",
55
+ "explain who are you, why you are here and what you can do",
56
+ "it's not a help or documentation page",
57
+ ],
58
+ );
82
59
  updateStartButton();
83
60
  }, []);
84
61
 
@@ -10,8 +10,6 @@ import styles from "@help/Help.module.css";
10
10
 
11
11
  import cls from "classnames";
12
12
 
13
- console.info(JSON.stringify(import.meta.env, null, 2));
14
-
15
13
  const API_PORT = Number(import.meta.env.API_PORT) || 3001;
16
14
  const API_PATH = import.meta.env.API_PATH || "/api";
17
15
 
@@ -27,7 +25,7 @@ const Version = () => {
27
25
  const chatStore = useChatCompletionStore();
28
26
 
29
27
  const hasRunOnce = useRef(false);
30
- const [response, setResponse] = useState<string>("loading...");
28
+ const [response, setResponse] = useState<string>("");
31
29
  const [loading, setLoading] = useState<boolean>(false);
32
30
 
33
31
  const getResponse = async () => {
@@ -54,6 +52,10 @@ const Version = () => {
54
52
  setLoading(true);
55
53
  getResponse();
56
54
  displayPackageVersion();
55
+ console.info(
56
+ `%c${JSON.stringify(import.meta.env, null, 2)}`,
57
+ "color: #999",
58
+ );
57
59
  }, []);
58
60
 
59
61
  return (