Skip to content

Commit 23012d1

Browse files
authored
feat: render markdown in the Electron example (#234)
* feat: render markdown in the Electron example * fix: only build practical targets by default in the Electron example
1 parent 56749c7 commit 23012d1

File tree

10 files changed

+349
-65
lines changed

10 files changed

+349
-65
lines changed

templates/electron-typescript-react/electron-builder.ts

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,13 @@ export default {
6060
artifactName: "${name}.macOS.${version}.${arch}.${ext}"
6161
},
6262
win: {
63-
target: [
64-
{
65-
target: "nsis",
66-
arch: [
67-
"x64",
68-
"arm64"
69-
]
70-
},
71-
{
72-
target: "appx",
73-
arch: [
74-
"x64",
75-
"arm64"
76-
]
77-
}
78-
],
63+
target: [{
64+
target: "nsis",
65+
arch: [
66+
"x64",
67+
"arm64"
68+
]
69+
}],
7970

8071
artifactName: "${name}.Windows.${version}.${arch}.${ext}"
8172
},
@@ -99,8 +90,7 @@ export default {
9990
}, {
10091
target: "snap",
10192
arch: [
102-
"x64",
103-
"arm64"
93+
"x64"
10494
]
10595
}, {
10696
target: "deb",

templates/electron-typescript-react/electron/rpc/llmRpc.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,16 @@ export class ElectronLlmRpc {
2828
if (!res.canceled && res.filePaths.length > 0) {
2929
llmState.state = {
3030
...llmState.state,
31-
selectedModelFilePath: path.resolve(res.filePaths[0])
31+
selectedModelFilePath: path.resolve(res.filePaths[0]),
32+
chatSession: {
33+
loaded: false,
34+
generatingResult: false,
35+
simplifiedChat: [],
36+
draftPrompt: {
37+
prompt: llmState.state.chatSession.draftPrompt.prompt,
38+
completion: ""
39+
}
40+
}
3241
};
3342

3443
if (!llmState.state.llama.loaded)

templates/electron-typescript-react/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,15 @@
2424
"dependencies": {
2525
"birpc": "^0.2.17",
2626
"classnames": "^2.5.1",
27+
"highlight.js": "^11.9.0",
2728
"lifecycle-utils": "^1.4.1",
29+
"markdown-it": "^14.1.0",
2830
"node-llama-cpp": "file:../..",
2931
"react": "^18.3.1",
3032
"react-dom": "^18.3.1"
3133
},
3234
"devDependencies": {
35+
"@types/markdown-it": "^14.1.1",
3336
"@types/react": "^18.3.3",
3437
"@types/react-dom": "^18.3.0",
3538
"@typescript-eslint/eslint-plugin": "^7.12.0",

templates/electron-typescript-react/src/App/App.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ export function App() {
158158
/>
159159
}
160160
<InputRow
161-
disabled={!state.model.loaded}
161+
disabled={!state.model.loaded || !state.contextSequence.loaded}
162162
stopGeneration={
163163
generatingResult
164164
? stopActivePrompt
@@ -167,7 +167,6 @@ export function App() {
167167
onPromptInput={onPromptInput}
168168
sendPrompt={sendPrompt}
169169
generatingResult={generatingResult}
170-
contextSequenceLoaded={state.contextSequence.loaded}
171170
autocompleteInputDraft={state.chatSession.draftPrompt.prompt}
172171
autocompleteCompletion={state.chatSession.draftPrompt.completion}
173172
/>

templates/electron-typescript-react/src/App/components/ChatHistory/ChatHistory.css

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,52 @@
66
overflow: auto;
77
padding: 24px 0px;
88

9-
> .message.user {
10-
align-self: flex-end;
11-
background-color: var(--user-message-background-color);
12-
padding: 8px 12px;
13-
border-radius: 12px;
14-
margin-bottom: 12px;
15-
margin-inline-start: 48px;
16-
margin-inline-end: 12px;
17-
color: var(--user-message-text-color);
18-
white-space: pre-wrap;
19-
20-
&:not(:first-child) {
21-
margin-top: 36px;
9+
> .message {
10+
&.user {
11+
align-self: flex-end;
12+
background-color: var(--user-message-background-color);
13+
padding: 8px 12px;
14+
border-radius: 12px;
15+
margin-bottom: 12px;
16+
margin-inline-start: 48px;
17+
margin-inline-end: 12px;
18+
color: var(--user-message-text-color);
19+
20+
&:not(:first-child) {
21+
margin-top: 36px;
22+
}
2223
}
23-
}
2424

25-
> .message.model {
26-
align-self: flex-start;
27-
margin-inline-end: 48px;
28-
padding-inline-start: 24px;
29-
white-space: pre-wrap;
30-
31-
&.active {
32-
&:after {
33-
content: "";
34-
position: static;
35-
display: inline-block;
36-
background-color: currentColor;
37-
width: 8px;
38-
height: 8px;
39-
translate: 0px -2px;
40-
border-radius: 9999px;
41-
margin-inline-start: 8px;
42-
vertical-align: middle;
43-
44-
animation: activeModelMessageIndicator 2s infinite ease-in-out;
25+
&.model {
26+
align-self: flex-start;
27+
margin-inline-end: 48px;
28+
padding-inline-start: 24px;
29+
30+
&.active {
31+
&:after {
32+
content: "";
33+
position: static;
34+
display: inline-block;
35+
background-color: currentColor;
36+
width: 8px;
37+
height: 8px;
38+
translate: 0px -2px;
39+
border-radius: 9999px;
40+
margin-inline-start: 8px;
41+
vertical-align: middle;
42+
43+
animation: activeModelMessageIndicator 2s infinite ease-in-out;
44+
}
4545
}
4646
}
47+
48+
> :first-child {
49+
margin-top: 0px;
50+
}
51+
52+
> :last-child {
53+
margin-bottom: 0px;
54+
}
4755
}
4856
}
4957

templates/electron-typescript-react/src/App/components/ChatHistory/ChatHistory.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import classNames from "classnames";
22
import {LlmState} from "../../../../electron/state/llmState.ts";
3+
import {MarkdownContent} from "../MarkdownContent/MarkdownContent.js";
34

45
import "./ChatHistory.css";
56

@@ -10,14 +11,14 @@ export function ChatHistory({simplifiedChat, generatingResult}: ChatHistoryProps
1011
simplifiedChat.map((item, index) => {
1112
if (item.type === "model") {
1213
const isActive = index === simplifiedChat.length - 1 && generatingResult;
13-
return <div key={index} className={classNames("message", "model", isActive && "active")}>
14+
return <MarkdownContent key={index} className={classNames("message", "model", isActive && "active")}>
1415
{item.message}
15-
</div>;
16+
</MarkdownContent>;
1617

1718
} else if (item.type === "user")
18-
return <div key={index} className="message user">
19+
return <MarkdownContent key={index} className="message user">
1920
{item.message}
20-
</div>;
21+
</MarkdownContent>;
2122

2223
return null;
2324
})

templates/electron-typescript-react/src/App/components/InputRow/InputRow.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ import "./InputRow.css";
77

88

99
export function InputRow({
10-
disabled = false, stopGeneration, sendPrompt, onPromptInput, autocompleteInputDraft, autocompleteCompletion, generatingResult,
11-
contextSequenceLoaded
10+
disabled = false, stopGeneration, sendPrompt, onPromptInput, autocompleteInputDraft, autocompleteCompletion, generatingResult
1211
}: InputRowProps) {
1312
const [inputText, setInputText] = useState<string>("");
1413
const inputRef = useRef<HTMLTextAreaElement>(null);
@@ -95,7 +94,7 @@ export function InputRow({
9594
className="input"
9695
autoComplete="off"
9796
spellCheck
98-
disabled={disabled || !contextSequenceLoaded}
97+
disabled={disabled}
9998
onScroll={resizeInput}
10099
placeholder={
101100
autocompleteText === ""
@@ -120,7 +119,7 @@ export function InputRow({
120119
</button>
121120
<button
122121
className="sendButton"
123-
disabled={disabled || !contextSequenceLoaded || inputText === "" || generatingResult}
122+
disabled={disabled || inputText === "" || generatingResult}
124123
onClick={submitPrompt}
125124
>
126125
<AddMessageIconSVG className="icon" />
@@ -135,6 +134,5 @@ type InputRowProps = {
135134
onPromptInput?(currentText: string): void,
136135
autocompleteInputDraft?: string,
137136
autocompleteCompletion?: string,
138-
generatingResult: boolean,
139-
contextSequenceLoaded: boolean
137+
generatingResult: boolean
140138
};

0 commit comments

Comments
 (0)