Skip to content

Commit cc2ef44

Browse files
committed
feat: class-based plugin manager
1 parent d29d076 commit cc2ef44

32 files changed

+845
-352
lines changed

core/core.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,23 @@
77
* @returns Promise<any>
88
*
99
*/
10-
const invokePluginFunc: (plugin: string, method: string, ...args: any[]) => Promise<any> = (plugin, method, ...args) =>
10+
const executeOnMain: (
11+
plugin: string,
12+
method: string,
13+
...args: any[]
14+
) => Promise<any> = (plugin, method, ...args) =>
15+
window.coreAPI?.invokePluginFunc(plugin, method, ...args) ??
16+
window.electronAPI?.invokePluginFunc(plugin, method, ...args);
17+
18+
/**
19+
* @deprecated This object is deprecated and should not be used.
20+
* Use individual functions instead.
21+
*/
22+
const invokePluginFunc: (
23+
plugin: string,
24+
method: string,
25+
...args: any[]
26+
) => Promise<any> = (plugin, method, ...args) =>
1127
window.coreAPI?.invokePluginFunc(plugin, method, ...args) ??
1228
window.electronAPI?.invokePluginFunc(plugin, method, ...args);
1329

@@ -17,8 +33,12 @@ const invokePluginFunc: (plugin: string, method: string, ...args: any[]) => Prom
1733
* @param {string} fileName - The name to use for the downloaded file.
1834
* @returns {Promise<any>} A promise that resolves when the file is downloaded.
1935
*/
20-
const downloadFile: (url: string, fileName: string) => Promise<any> = (url, fileName) =>
21-
window.coreAPI?.downloadFile(url, fileName) ?? window.electronAPI?.downloadFile(url, fileName);
36+
const downloadFile: (url: string, fileName: string) => Promise<any> = (
37+
url,
38+
fileName
39+
) =>
40+
window.coreAPI?.downloadFile(url, fileName) ??
41+
window.electronAPI?.downloadFile(url, fileName);
2242

2343
/**
2444
* Deletes a file from the local file system.
@@ -51,6 +71,7 @@ export type RegisterExtensionPoint = (
5171
*/
5272
export const core = {
5373
invokePluginFunc,
74+
executeOnMain,
5475
downloadFile,
5576
deleteFile,
5677
appDataPath,
@@ -59,4 +80,10 @@ export const core = {
5980
/**
6081
* Functions exports
6182
*/
62-
export { invokePluginFunc, downloadFile, deleteFile, appDataPath };
83+
export {
84+
invokePluginFunc,
85+
executeOnMain,
86+
downloadFile,
87+
deleteFile,
88+
appDataPath,
89+
};

core/events.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@ export enum EventName {
66
OnNewMessageRequest = "onNewMessageRequest",
77
OnNewMessageResponse = "onNewMessageResponse",
88
OnMessageResponseUpdate = "onMessageResponseUpdate",
9-
OnMessageResponseFinished = "OnMessageResponseFinished",
9+
OnMessageResponseFinished = "onMessageResponseFinished",
1010
OnDownloadUpdate = "onDownloadUpdate",
1111
OnDownloadSuccess = "onDownloadSuccess",
1212
OnDownloadError = "onDownloadError",
1313
}
1414

15+
export type MessageHistory = {
16+
role: string;
17+
content: string;
18+
};
1519
/**
1620
* The `NewMessageRequest` type defines the shape of a new message request object.
1721
*/
@@ -23,6 +27,7 @@ export type NewMessageRequest = {
2327
message?: string;
2428
createdAt?: string;
2529
updatedAt?: string;
30+
history?: MessageHistory[];
2631
};
2732

2833
/**

core/fs.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Writes data to a file at the specified path.
3+
* @param {string} path - The path to the file.
4+
* @param {string} data - The data to write to the file.
5+
* @returns {Promise<any>} A Promise that resolves when the file is written successfully.
6+
*/
7+
const writeFile: (path: string, data: string) => Promise<any> = (path, data) =>
8+
window.coreAPI?.writeFile(path, data) ??
9+
window.electronAPI?.writeFile(path, data);
10+
11+
/**
12+
* Reads the contents of a file at the specified path.
13+
* @param {string} path - The path of the file to read.
14+
* @returns {Promise<any>} A Promise that resolves with the contents of the file.
15+
*/
16+
const readFile: (path: string) => Promise<any> = (path) =>
17+
window.coreAPI?.readFile(path) ?? window.electronAPI?.readFile(path);
18+
19+
/**
20+
* List the directory files
21+
* @param {string} path - The path of the directory to list files.
22+
* @returns {Promise<any>} A Promise that resolves with the contents of the directory.
23+
*/
24+
const listFiles: (path: string) => Promise<any> = (path) =>
25+
window.coreAPI?.listFiles(path) ?? window.electronAPI?.listFiles(path);
26+
27+
/**
28+
* Creates a directory at the specified path.
29+
* @param {string} path - The path of the directory to create.
30+
* @returns {Promise<any>} A Promise that resolves when the directory is created successfully.
31+
*/
32+
const mkdir: (path: string) => Promise<any> = (path) =>
33+
window.coreAPI?.mkdir(path) ?? window.electronAPI?.mkdir(path);
34+
35+
/**
36+
* Deletes a file from the local file system.
37+
* @param {string} path - The path of the file to delete.
38+
* @returns {Promise<any>} A Promise that resolves when the file is deleted.
39+
*/
40+
const deleteFile: (path: string) => Promise<any> = (path) =>
41+
window.coreAPI?.deleteFile(path) ?? window.electronAPI?.deleteFile(path);
42+
43+
export const fs = {
44+
writeFile,
45+
readFile,
46+
listFiles,
47+
mkdir,
48+
deleteFile,
49+
};

core/index.ts

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -67,46 +67,6 @@ export enum StoreService {
6767
* @enum {string}
6868
*/
6969
export enum DataService {
70-
/**
71-
* Gets a list of conversations.
72-
*/
73-
GetConversations = "getConversations",
74-
75-
/**
76-
* Creates a new conversation.
77-
*/
78-
CreateConversation = "createConversation",
79-
80-
/**
81-
* Updates an existing conversation.
82-
*/
83-
UpdateConversation = "updateConversation",
84-
85-
/**
86-
* Deletes an existing conversation.
87-
*/
88-
DeleteConversation = "deleteConversation",
89-
90-
/**
91-
* Creates a new message in an existing conversation.
92-
*/
93-
CreateMessage = "createMessage",
94-
95-
/**
96-
* Updates an existing message in an existing conversation.
97-
*/
98-
UpdateMessage = "updateMessage",
99-
100-
/**
101-
* Gets a list of messages for an existing conversation.
102-
*/
103-
GetConversationMessages = "getConversationMessages",
104-
105-
/**
106-
* Gets a conversation matching an ID.
107-
*/
108-
GetConversationById = "getConversationById",
109-
11070
/**
11171
* Creates a new conversation using the prompt instruction.
11272
*/
@@ -131,11 +91,6 @@ export enum DataService {
13191
* Updates a bot matching an ID.
13292
*/
13393
UpdateBot = "updateBot",
134-
135-
/**
136-
* Gets the plugin manifest.
137-
*/
138-
GetPluginManifest = "getPluginManifest",
13994
}
14095

14196
/**
@@ -283,6 +238,7 @@ export {
283238
RegisterExtensionPoint,
284239
deleteFile,
285240
downloadFile,
241+
executeOnMain,
286242
invokePluginFunc,
287243
} from "./core";
288244

@@ -295,10 +251,19 @@ export {
295251
EventName,
296252
NewMessageRequest,
297253
NewMessageResponse,
254+
MessageHistory,
298255
} from "./events";
299256

300257
/**
301258
* Preferences module exports.
302259
* @module
303260
*/
304261
export { preferences } from "./preferences";
262+
export { fs } from "./fs";
263+
264+
export { JanPlugin, PluginType } from "./plugin";
265+
export {
266+
ConversationalPlugin,
267+
Conversation,
268+
Message,
269+
} from "./plugins/conversational";

core/plugin.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export enum PluginType {
2+
Conversational = "conversational",
3+
Inference = "inference",
4+
Preference = "preference",
5+
SystemMonitoring = "systemMonitoring",
6+
}
7+
8+
export abstract class JanPlugin {
9+
abstract type(): PluginType;
10+
abstract onLoad(): void;
11+
abstract onUnload(): void;
12+
}

core/plugins/conversational.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { JanPlugin, PluginType } from "../plugin";
2+
3+
export interface Conversation {
4+
_id: string;
5+
modelId?: string;
6+
botId?: string;
7+
name: string;
8+
message?: string;
9+
summary?: string;
10+
createdAt?: string;
11+
updatedAt?: string;
12+
messages: Message[];
13+
}
14+
export interface Message {
15+
message?: string;
16+
user?: string;
17+
_id: string;
18+
createdAt?: string;
19+
updatedAt?: string;
20+
}
21+
22+
export abstract class ConversationalPlugin extends JanPlugin {
23+
abstract getConversations(): Promise<any[]>;
24+
abstract saveConversation(conversation: Conversation): Promise<void>;
25+
abstract deleteConversation(conversationId: string): Promise<void>;
26+
}

electron/handlers/fs.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { app, ipcMain } from "electron";
2+
import * as fs from "fs";
3+
import { join } from "path";
4+
5+
/**
6+
* Handles file system operations.
7+
*/
8+
export function handleFs() {
9+
/**
10+
* Reads a file from the user data directory.
11+
* @param event - The event object.
12+
* @param path - The path of the file to read.
13+
* @returns A promise that resolves with the contents of the file.
14+
*/
15+
ipcMain.handle("readFile", async (event, path: string): Promise<string> => {
16+
return new Promise((resolve, reject) => {
17+
fs.readFile(join(app.getPath("userData"), path), "utf8", (err, data) => {
18+
if (err) {
19+
reject(err);
20+
} else {
21+
resolve(data);
22+
}
23+
});
24+
});
25+
});
26+
27+
/**
28+
* Writes data to a file in the user data directory.
29+
* @param event - The event object.
30+
* @param path - The path of the file to write to.
31+
* @param data - The data to write to the file.
32+
* @returns A promise that resolves when the file has been written.
33+
*/
34+
ipcMain.handle(
35+
"writeFile",
36+
async (event, path: string, data: string): Promise<void> => {
37+
return new Promise((resolve, reject) => {
38+
fs.writeFile(
39+
join(app.getPath("userData"), path),
40+
data,
41+
"utf8",
42+
(err) => {
43+
if (err) {
44+
reject(err);
45+
} else {
46+
resolve();
47+
}
48+
}
49+
);
50+
});
51+
}
52+
);
53+
54+
/**
55+
* Creates a directory in the user data directory.
56+
* @param event - The event object.
57+
* @param path - The path of the directory to create.
58+
* @returns A promise that resolves when the directory has been created.
59+
*/
60+
ipcMain.handle("mkdir", async (event, path: string): Promise<void> => {
61+
return new Promise((resolve, reject) => {
62+
fs.mkdir(
63+
join(app.getPath("userData"), path),
64+
{ recursive: true },
65+
(err) => {
66+
if (err) {
67+
reject(err);
68+
} else {
69+
resolve();
70+
}
71+
}
72+
);
73+
});
74+
});
75+
76+
/**
77+
* Lists the files in a directory in the user data directory.
78+
* @param event - The event object.
79+
* @param path - The path of the directory to list files from.
80+
* @returns A promise that resolves with an array of file names.
81+
*/
82+
ipcMain.handle(
83+
"listFiles",
84+
async (event, path: string): Promise<string[]> => {
85+
return new Promise((resolve, reject) => {
86+
fs.readdir(join(app.getPath("userData"), path), (err, files) => {
87+
if (err) {
88+
reject(err);
89+
} else {
90+
resolve(files);
91+
}
92+
});
93+
});
94+
}
95+
);
96+
}

electron/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { rmdir, unlink, createWriteStream } from "fs";
1212
import { init } from "./core/plugin/index";
1313
import { setupMenu } from "./utils/menu";
1414
import { dispose } from "./utils/disposable";
15+
import { handleFs } from "./handlers/fs";
1516

1617
const pacote = require("pacote");
1718
const request = require("request");
@@ -127,6 +128,7 @@ function handleAppUpdates() {
127128
* Handles various IPC messages from the renderer process.
128129
*/
129130
function handleIPCs() {
131+
handleFs();
130132
/**
131133
* Handles the "setNativeThemeLight" IPC message by setting the native theme source to "light".
132134
* This will change the appearance of the app to the light theme.

0 commit comments

Comments
 (0)