refactor: deprecate extension type implementation (#1677)
* refactor: deprecate extension type implementation * chore: update README.md * refactor: EventName to use the events defined in /types
This commit is contained in:
parent
99d083d84a
commit
a50ea4a634
395
core/README.md
395
core/README.md
@ -1,348 +1,69 @@
|
|||||||
## @janhq/core
|
## @janhq/core
|
||||||
|
|
||||||
> The module includes functions for communicating with core APIs, registering plugin extensions, and exporting type definitions.
|
> This module includes functions for communicating with core APIs, registering app extensions, and exporting type definitions.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Import the package
|
### Import the package
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// javascript
|
// Web / extension runtime
|
||||||
const core = require("@janhq/core");
|
|
||||||
|
|
||||||
// typescript
|
|
||||||
import * as core from "@janhq/core";
|
import * as core from "@janhq/core";
|
||||||
|
|
||||||
|
// Node runtime
|
||||||
|
import * as node from "@janhq/core/node";
|
||||||
```
|
```
|
||||||
|
|
||||||
### Register Plugin Extensions
|
## Build an Extension
|
||||||
|
|
||||||
Every plugin must define an `init` function in its main entry file to initialize the plugin and register its extensions with the Jan platform.
|
1. Download an extension template, for example, [https://github.com/janhq/extension-template](https://github.com/janhq/extension-template).
|
||||||
|
|
||||||
You can `register` any function as a plugin extension using `CoreServiceAPI` below. For example, the `DataService.GetConversations` entry name can be used to register a function that retrieves conversations.
|
2. Update the source code:
|
||||||
|
1. Open `index.ts` in your code editor.
|
||||||
Once the extension is registered, it can be used by other plugins or components in the Jan platform. For example, a UI component might use the DataService.GetConversations extension to retrieve a list of conversations to display to the user.
|
2. Rename the extension class from `SampleExtension` to your preferred extension name.
|
||||||
|
3. Import modules from the core package.
|
||||||
```js
|
```ts
|
||||||
import { RegisterExtensionPoint, DataService } from "@janhq/core";
|
import * as core from "@janhq/core";
|
||||||
|
```
|
||||||
function getConversations() {
|
4. In the `onLoad()` method, add your code:
|
||||||
// Your logic here
|
```ts
|
||||||
}
|
// Example of listening to app events and providing customized inference logic:
|
||||||
|
import * as core from "@janhq/core";
|
||||||
export function init({ register }: { register: RegisterExtensionPoint }) {
|
|
||||||
register(DataService.GetConversations, getConversations.name, getConversations);
|
export default class MyExtension extends BaseExtension {
|
||||||
}
|
// On extension load
|
||||||
```
|
onLoad() {
|
||||||
|
core.events.on(MessageEvent.OnMessageSent, (data) => MyExtension.inference(data, this));
|
||||||
### Interact with Local Data Storage
|
}
|
||||||
|
|
||||||
The Core API allows you to interact with local data storage. Here are a couple of examples of how you can use it:
|
// Customized inference logic
|
||||||
|
private static inference(incomingMessage: MessageRequestData) {
|
||||||
#### Insert Data
|
|
||||||
|
// Prepare customized message content
|
||||||
You can use the store.insertOne function to insert data into a specific collection in the local data store.
|
const content: ThreadContent = {
|
||||||
|
type: ContentType.Text,
|
||||||
```js
|
text: {
|
||||||
import { store } from "@janhq/core";
|
value: "I'm Jan Assistant!",
|
||||||
|
annotations: [],
|
||||||
function insertData() {
|
},
|
||||||
store.insertOne("conversations", { name: "meow" });
|
};
|
||||||
// Insert a new document with { name: "meow" } into the "conversations" collection.
|
|
||||||
}
|
// Modify message and send out
|
||||||
```
|
const outGoingMessage: ThreadMessage = {
|
||||||
|
...incomingMessage,
|
||||||
#### Get Data
|
content
|
||||||
|
};
|
||||||
To retrieve data from a collection in the local data store, you can use the `store.findOne` or `store.findMany` function. It allows you to filter and retrieve documents based on specific criteria.
|
}
|
||||||
|
}
|
||||||
store.getOne(collectionName, key) retrieves a single document that matches the provided key in the specified collection.
|
```
|
||||||
store.getMany(collectionName, selector, sort) retrieves multiple documents that match the provided selector in the specified collection.
|
3. Build the extension:
|
||||||
|
1. Navigate to the extension directory.
|
||||||
```js
|
2. Install dependencies.
|
||||||
import { store } from "@janhq/core";
|
```bash
|
||||||
|
yarn install
|
||||||
function getData() {
|
```
|
||||||
const selector = { name: "meow" };
|
3. Compile the source code. The following command keeps running in the terminal and rebuilds the extension when you modify the source code.
|
||||||
const data = store.findMany("conversations", selector);
|
```bash
|
||||||
// Retrieve documents from the "conversations" collection that match the filter.
|
yarn build
|
||||||
}
|
```
|
||||||
```
|
4. Select the generated .tgz from Jan > Settings > Extension > Manual Installation.
|
||||||
|
|
||||||
#### Update Data
|
|
||||||
|
|
||||||
You can update data in the local store using these functions:
|
|
||||||
|
|
||||||
store.updateOne(collectionName, key, update) updates a single document that matches the provided key in the specified collection.
|
|
||||||
store.updateMany(collectionName, selector, update) updates multiple documents that match the provided selector in the specified collection.
|
|
||||||
|
|
||||||
```js
|
|
||||||
function updateData() {
|
|
||||||
const selector = { name: "meow" };
|
|
||||||
const update = { name: "newName" };
|
|
||||||
store.updateOne("conversations", selector, update);
|
|
||||||
// Update a document in the "conversations" collection.
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Delete Data
|
|
||||||
|
|
||||||
You can delete data from the local data store using these functions:
|
|
||||||
|
|
||||||
store.deleteOne(collectionName, key) deletes a single document that matches the provided key in the specified collection.
|
|
||||||
store.deleteMany(collectionName, selector) deletes multiple documents that match the provided selector in the specified collection.
|
|
||||||
|
|
||||||
```js
|
|
||||||
function deleteData() {
|
|
||||||
const selector = { name: "meow" };
|
|
||||||
store.deleteOne("conversations", selector);
|
|
||||||
// Delete a document from the "conversations" collection.
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Events
|
|
||||||
|
|
||||||
You can subscribe to NewMessageRequest events by defining a function to handle the event and registering it with the events object:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { events } from "@janhq/core";
|
|
||||||
|
|
||||||
function handleMessageRequest(message: NewMessageRequest) {
|
|
||||||
// Your logic here. For example:
|
|
||||||
// const response = openai.createChatCompletion({...})
|
|
||||||
}
|
|
||||||
function registerListener() {
|
|
||||||
events.on(EventName.OnNewMessageRequest, handleMessageRequest);
|
|
||||||
}
|
|
||||||
// Register the listener function with the relevant extension points.
|
|
||||||
export function init({ register }) {
|
|
||||||
registerListener();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
In this example, we're defining a function called handleMessageRequest that takes a NewMessageRequest object as its argument. We're also defining a function called registerListener that registers the handleMessageRequest function as a listener for NewMessageRequest events using the on method of the events object.
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { events } from "@janhq/core";
|
|
||||||
|
|
||||||
function handleMessageRequest(data: NewMessageRequest) {
|
|
||||||
// Your logic here. For example:
|
|
||||||
const response = openai.createChatCompletion({...})
|
|
||||||
const message: NewMessageResponse = {
|
|
||||||
...data,
|
|
||||||
message: response.data.choices[0].message.content
|
|
||||||
}
|
|
||||||
// Now emit event so the app can display in the conversation
|
|
||||||
events.emit(EventName.OnNewMessageResponse, message)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Preferences
|
|
||||||
|
|
||||||
To register plugin preferences, you can use the preferences object from the @janhq/core package. Here's an example of how to register and retrieve plugin preferences:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { PluginService, preferences } from "@janhq/core";
|
|
||||||
|
|
||||||
const pluginName = "your-first-plugin";
|
|
||||||
const preferenceKey = "";
|
|
||||||
const preferenceName = "Your First Preference";
|
|
||||||
const preferenceDescription = "This is for example only";
|
|
||||||
const defaultValue = "";
|
|
||||||
|
|
||||||
export function init({ register }: { register: RegisterExtensionPoint }) {
|
|
||||||
// Register preference update handlers. E.g. update plugin instance with new configuration
|
|
||||||
register(PluginService.OnPreferencesUpdate, pluginName, onPreferencesUpdate);
|
|
||||||
|
|
||||||
// Register plugin preferences. E.g. Plugin need apiKey to connect to your service
|
|
||||||
preferences.registerPreferences <
|
|
||||||
string >
|
|
||||||
(register, pluginName, preferenceKey, preferenceName, preferenceDescription, defaultValue);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
In this example, we're registering preference update handlers and plugin preferences using the preferences object. We're also defining a PluginName constant to use as the name of the plugin.
|
|
||||||
|
|
||||||
To retrieve the values of the registered preferences, we're using the get method of the preferences object and passing in the name of the plugin and the name of the preference.
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { preferences } from "@janhq/core";
|
|
||||||
|
|
||||||
const pluginName = "your-first-plugin";
|
|
||||||
const preferenceKey = "apiKey";
|
|
||||||
|
|
||||||
const setup = async () => {
|
|
||||||
// Retrieve apiKey
|
|
||||||
const apiKey: string = (await preferences.get(pluginName, preferenceKey)) ?? "";
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Access Core API
|
|
||||||
|
|
||||||
To access the Core API in your plugin, you can follow the code examples and explanations provided below.
|
|
||||||
|
|
||||||
##### Import Core API and Store Module
|
|
||||||
|
|
||||||
In your main entry code (e.g., `index.ts`), start by importing the necessary modules and functions from the `@janhq/core` library.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// index.ts
|
|
||||||
import * as core from "@janhq/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Perform File Operations
|
|
||||||
|
|
||||||
The Core API also provides functions to perform file operations. Here are a couple of examples:
|
|
||||||
|
|
||||||
#### Download a File
|
|
||||||
|
|
||||||
You can download a file from a specified URL and save it with a given file name using the core.downloadFile function.
|
|
||||||
|
|
||||||
```js
|
|
||||||
function downloadModel(url: string, fileName: string, network?: { proxy?: string, ignoreSSL?: boolean }) {
|
|
||||||
core.downloadFile(url, fileName, network);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Delete a File
|
|
||||||
|
|
||||||
To delete a file, you can use the core.deleteFile function, providing the path to the file you want to delete.
|
|
||||||
|
|
||||||
```js
|
|
||||||
function deleteModel(filePath: string) {
|
|
||||||
core.deleteFile(path);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Execute plugin module in main process
|
|
||||||
|
|
||||||
To execute a plugin module in the main process of your application, you can follow the steps outlined below.
|
|
||||||
|
|
||||||
##### Import the `core` Object
|
|
||||||
|
|
||||||
In your main process code (e.g., `index.ts`), start by importing the `core` object from the `@janhq/core` library.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// index.ts
|
|
||||||
import * as core from "@janhq/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Define the Module Path
|
|
||||||
|
|
||||||
Specify the path to the plugin module you want to execute. This path should lead to the module file (e.g., module.js) that contains the functions you wish to call.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// index.ts
|
|
||||||
const MODULE_PATH = "data-plugin/dist/module.js";
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Define the Function to Execute
|
|
||||||
|
|
||||||
Create a function that will execute a function defined in your plugin module. In the example provided, the function `getConversationMessages` is created to invoke the `getConvMessages` function from the plugin module.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// index.ts
|
|
||||||
function getConversationMessages(id: number) {
|
|
||||||
return core.invokePluginFunc(MODULE_PATH, "getConvMessages", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function init({ register }: { register: RegisterExtensionPoint }) {
|
|
||||||
register(DataService.GetConversationMessages, getConversationMessages.name, getConversationMessages);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Define Your Plugin Module
|
|
||||||
|
|
||||||
In your plugin module (e.g., module.ts), define the logic for the function you wish to execute. In the example, the function getConvMessages is defined with a placeholder comment indicating where your logic should be implemented.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// module.ts
|
|
||||||
function getConvMessages(id: number) {
|
|
||||||
// Your logic here
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getConvMessages,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## CoreService API
|
|
||||||
|
|
||||||
The `CoreService` type is an exported union type that includes:
|
|
||||||
|
|
||||||
- `StoreService`
|
|
||||||
- `DataService`
|
|
||||||
- `InferenceService`
|
|
||||||
- `ModelManagementService`
|
|
||||||
- `SystemMonitoringService`
|
|
||||||
- `PreferenceService`
|
|
||||||
|
|
||||||
## StoreService
|
|
||||||
|
|
||||||
The `StoreService` enum represents available methods for managing the database store. It includes the following methods:
|
|
||||||
|
|
||||||
- `CreateCollection`: Creates a new collection in the data store.
|
|
||||||
- `DeleteCollection`: Deletes an existing collection from the data store.
|
|
||||||
- `InsertOne`: Inserts a new value into an existing collection in the data store.
|
|
||||||
- `UpdateOne`: Updates an existing value in an existing collection in the data store.
|
|
||||||
- `UpdateMany`: Updates multiple records in a collection in the data store.
|
|
||||||
- `DeleteOne`: Deletes an existing value from an existing collection in the data store.
|
|
||||||
- `DeleteMany`: Deletes multiple records in a collection in the data store.
|
|
||||||
- `FindMany`: Retrieves multiple records from a collection in the data store.
|
|
||||||
- `FindOne`: Retrieves a single record from a collection in the data store.
|
|
||||||
|
|
||||||
## DataService
|
|
||||||
|
|
||||||
The `DataService` enum represents methods related to managing conversations and messages. It includes the following methods:
|
|
||||||
|
|
||||||
- `GetConversations`: Gets a list of conversations from the data store.
|
|
||||||
- `CreateConversation`: Creates a new conversation in the data store.
|
|
||||||
- `DeleteConversation`: Deletes an existing conversation from the data store.
|
|
||||||
- `CreateMessage`: Creates a new message in an existing conversation in the data store.
|
|
||||||
- `UpdateMessage`: Updates an existing message in an existing conversation in the data store.
|
|
||||||
- `GetConversationMessages`: Gets a list of messages for an existing conversation from the data store.
|
|
||||||
|
|
||||||
## InferenceService
|
|
||||||
|
|
||||||
The `InferenceService` enum exports:
|
|
||||||
|
|
||||||
- `InitModel`: Initializes a model for inference.
|
|
||||||
- `StopModel`: Stops a running inference model.
|
|
||||||
|
|
||||||
## ModelManagementService
|
|
||||||
|
|
||||||
The `ModelManagementService` enum provides methods for managing models:
|
|
||||||
|
|
||||||
- `GetDownloadedModels`: Gets a list of downloaded models.
|
|
||||||
- `GetAvailableModels`: Gets a list of available models from data store.
|
|
||||||
- `DeleteModel`: Deletes a downloaded model.
|
|
||||||
- `DownloadModel`: Downloads a model from the server.
|
|
||||||
- `SearchModels`: Searches for models on the server.
|
|
||||||
- `GetConfiguredModels`: Gets configured models from the data store.
|
|
||||||
- `StoreModel`: Stores a model in the data store.
|
|
||||||
- `UpdateFinishedDownloadAt`: Updates the finished download time for a model in the data store.
|
|
||||||
- `GetUnfinishedDownloadModels`: Gets a list of unfinished download models from the data store.
|
|
||||||
- `GetFinishedDownloadModels`: Gets a list of finished download models from the data store.
|
|
||||||
- `DeleteDownloadModel`: Deletes a downloaded model from the data store.
|
|
||||||
- `GetModelById`: Gets a model by its ID from the data store.
|
|
||||||
|
|
||||||
## PreferenceService
|
|
||||||
|
|
||||||
The `PreferenceService` enum provides methods for managing plugin preferences:
|
|
||||||
|
|
||||||
- `ExperimentComponent`: Represents the UI experiment component for a testing function.
|
|
||||||
|
|
||||||
## SystemMonitoringService
|
|
||||||
|
|
||||||
The `SystemMonitoringService` enum includes methods for monitoring system resources:
|
|
||||||
|
|
||||||
- `GetResourcesInfo`: Gets information about system resources.
|
|
||||||
- `GetCurrentLoad`: Gets the current system load.
|
|
||||||
|
|
||||||
## PluginService
|
|
||||||
|
|
||||||
The `PluginService` enum includes plugin cycle handlers:
|
|
||||||
|
|
||||||
- `OnStart`: Handler for starting. E.g. Create a collection.
|
|
||||||
- `OnPreferencesUpdate`: Handler for preferences update. E.g. Update instances with new configurations.
|
|
||||||
|
|
||||||
For more detailed information on each of these components, please refer to the source code.
|
|
||||||
@ -1,28 +1,3 @@
|
|||||||
// TODO: refactor EventName to use the events defined in /types
|
|
||||||
/**
|
|
||||||
* The `EventName` enumeration contains the names of all the available events in the Jan platform.
|
|
||||||
*/
|
|
||||||
export enum EventName {
|
|
||||||
/** The `OnMessageSent` event is emitted when a message is sent. */
|
|
||||||
OnMessageSent = 'OnMessageSent',
|
|
||||||
/** The `OnMessageResponse` event is emitted when a message is received. */
|
|
||||||
OnMessageResponse = 'OnMessageResponse',
|
|
||||||
/** The `OnMessageUpdate` event is emitted when a message is updated. */
|
|
||||||
OnMessageUpdate = 'OnMessageUpdate',
|
|
||||||
/** The `OnModelInit` event is emitted when a model inits. */
|
|
||||||
OnModelInit = 'OnModelInit',
|
|
||||||
/** The `OnModelReady` event is emitted when a model ready. */
|
|
||||||
OnModelReady = 'OnModelReady',
|
|
||||||
/** The `OnModelFail` event is emitted when a model fails loading. */
|
|
||||||
OnModelFail = 'OnModelFail',
|
|
||||||
/** The `OnModelStop` event is emitted when a model start to stop. */
|
|
||||||
OnModelStop = 'OnModelStop',
|
|
||||||
/** The `OnModelStopped` event is emitted when a model stopped ok. */
|
|
||||||
OnModelStopped = 'OnModelStopped',
|
|
||||||
/** The `OnInferenceStopped` event is emitted when a inference is stopped. */
|
|
||||||
OnInferenceStopped = 'OnInferenceStopped',
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an observer for an event.
|
* Adds an observer for an event.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
export enum ExtensionType {
|
export enum ExtensionTypeEnum {
|
||||||
Assistant = "assistant",
|
Assistant = "assistant",
|
||||||
Conversational = "conversational",
|
Conversational = "conversational",
|
||||||
Inference = "inference",
|
Inference = "inference",
|
||||||
@ -6,17 +6,22 @@ export enum ExtensionType {
|
|||||||
SystemMonitoring = "systemMonitoring",
|
SystemMonitoring = "systemMonitoring",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ExtensionType {
|
||||||
|
type(): ExtensionTypeEnum | undefined;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Represents a base extension.
|
* Represents a base extension.
|
||||||
* This class should be extended by any class that represents an extension.
|
* This class should be extended by any class that represents an extension.
|
||||||
*/
|
*/
|
||||||
export abstract class BaseExtension {
|
export abstract class BaseExtension implements ExtensionType {
|
||||||
/**
|
/**
|
||||||
* Returns the type of the extension.
|
* Returns the type of the extension.
|
||||||
* @returns {ExtensionType} The type of the extension
|
* @returns {ExtensionType} The type of the extension
|
||||||
* Undefined means its not extending any known extension by the application.
|
* Undefined means its not extending any known extension by the application.
|
||||||
*/
|
*/
|
||||||
abstract type(): ExtensionType | undefined;
|
type(): ExtensionTypeEnum | undefined {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Called when the extension is loaded.
|
* Called when the extension is loaded.
|
||||||
* Any initialization logic for the extension should be put here.
|
* Any initialization logic for the extension should be put here.
|
||||||
|
|||||||
@ -1,12 +1,19 @@
|
|||||||
import { Assistant, AssistantInterface } from '../index'
|
import { Assistant, AssistantInterface } from "../index";
|
||||||
import { BaseExtension } from '../extension'
|
import { BaseExtension, ExtensionTypeEnum } from "../extension";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assistant extension for managing assistants.
|
* Assistant extension for managing assistants.
|
||||||
* @extends BaseExtension
|
* @extends BaseExtension
|
||||||
*/
|
*/
|
||||||
export abstract class AssistantExtension extends BaseExtension implements AssistantInterface {
|
export abstract class AssistantExtension extends BaseExtension implements AssistantInterface {
|
||||||
abstract createAssistant(assistant: Assistant): Promise<void>
|
/**
|
||||||
abstract deleteAssistant(assistant: Assistant): Promise<void>
|
* Assistant extension type.
|
||||||
abstract getAssistants(): Promise<Assistant[]>
|
*/
|
||||||
|
type(): ExtensionTypeEnum | undefined {
|
||||||
|
return ExtensionTypeEnum.Assistant;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract createAssistant(assistant: Assistant): Promise<void>;
|
||||||
|
abstract deleteAssistant(assistant: Assistant): Promise<void>;
|
||||||
|
abstract getAssistants(): Promise<Assistant[]>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Thread, ThreadInterface, ThreadMessage, MessageInterface } from '../index'
|
import { Thread, ThreadInterface, ThreadMessage, MessageInterface } from '../index'
|
||||||
import { BaseExtension } from '../extension'
|
import { BaseExtension, ExtensionTypeEnum } from '../extension'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conversational extension. Persists and retrieves conversations.
|
* Conversational extension. Persists and retrieves conversations.
|
||||||
@ -10,6 +10,13 @@ export abstract class ConversationalExtension
|
|||||||
extends BaseExtension
|
extends BaseExtension
|
||||||
implements ThreadInterface, MessageInterface
|
implements ThreadInterface, MessageInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Conversation extension type.
|
||||||
|
*/
|
||||||
|
type(): ExtensionTypeEnum | undefined {
|
||||||
|
return ExtensionTypeEnum.Conversational;
|
||||||
|
}
|
||||||
|
|
||||||
abstract getThreads(): Promise<Thread[]>
|
abstract getThreads(): Promise<Thread[]>
|
||||||
abstract saveThread(thread: Thread): Promise<void>
|
abstract saveThread(thread: Thread): Promise<void>
|
||||||
abstract deleteThread(threadId: string): Promise<void>
|
abstract deleteThread(threadId: string): Promise<void>
|
||||||
|
|||||||
@ -1,9 +1,16 @@
|
|||||||
import { InferenceInterface, MessageRequest, ThreadMessage } from '../index'
|
import { InferenceInterface, MessageRequest, ThreadMessage } from "../index";
|
||||||
import { BaseExtension } from '../extension'
|
import { BaseExtension, ExtensionTypeEnum } from "../extension";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inference extension. Start, stop and inference models.
|
* Inference extension. Start, stop and inference models.
|
||||||
*/
|
*/
|
||||||
export abstract class InferenceExtension extends BaseExtension implements InferenceInterface {
|
export abstract class InferenceExtension extends BaseExtension implements InferenceInterface {
|
||||||
abstract inference(data: MessageRequest): Promise<ThreadMessage>
|
/**
|
||||||
|
* Inference extension type.
|
||||||
|
*/
|
||||||
|
type(): ExtensionTypeEnum | undefined {
|
||||||
|
return ExtensionTypeEnum.Inference;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract inference(data: MessageRequest): Promise<ThreadMessage>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,24 @@
|
|||||||
import { BaseExtension } from '../extension'
|
import { BaseExtension, ExtensionTypeEnum } from "../extension";
|
||||||
import { Model, ModelInterface } from '../index'
|
import { Model, ModelInterface } from "../index";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model extension for managing models.
|
* Model extension for managing models.
|
||||||
*/
|
*/
|
||||||
export abstract class ModelExtension extends BaseExtension implements ModelInterface {
|
export abstract class ModelExtension extends BaseExtension implements ModelInterface {
|
||||||
abstract downloadModel(model: Model, network?: { proxy: string, ignoreSSL?: boolean }): Promise<void>
|
/**
|
||||||
abstract cancelModelDownload(modelId: string): Promise<void>
|
* Model extension type.
|
||||||
abstract deleteModel(modelId: string): Promise<void>
|
*/
|
||||||
abstract saveModel(model: Model): Promise<void>
|
type(): ExtensionTypeEnum | undefined {
|
||||||
abstract getDownloadedModels(): Promise<Model[]>
|
return ExtensionTypeEnum.Model;
|
||||||
abstract getConfiguredModels(): Promise<Model[]>
|
}
|
||||||
|
|
||||||
|
abstract downloadModel(
|
||||||
|
model: Model,
|
||||||
|
network?: { proxy: string; ignoreSSL?: boolean },
|
||||||
|
): Promise<void>;
|
||||||
|
abstract cancelModelDownload(modelId: string): Promise<void>;
|
||||||
|
abstract deleteModel(modelId: string): Promise<void>;
|
||||||
|
abstract saveModel(model: Model): Promise<void>;
|
||||||
|
abstract getDownloadedModels(): Promise<Model[]>;
|
||||||
|
abstract getConfiguredModels(): Promise<Model[]>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
import { BaseExtension } from '../extension'
|
import { BaseExtension, ExtensionTypeEnum } from "../extension";
|
||||||
import { MonitoringInterface } from '../index'
|
import { MonitoringInterface } from "../index";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Monitoring extension for system monitoring.
|
* Monitoring extension for system monitoring.
|
||||||
* @extends BaseExtension
|
* @extends BaseExtension
|
||||||
*/
|
*/
|
||||||
export abstract class MonitoringExtension extends BaseExtension implements MonitoringInterface {
|
export abstract class MonitoringExtension extends BaseExtension implements MonitoringInterface {
|
||||||
abstract getResourcesInfo(): Promise<any>
|
/**
|
||||||
abstract getCurrentLoad(): Promise<any>
|
* Monitoring extension type.
|
||||||
|
*/
|
||||||
|
type(): ExtensionTypeEnum | undefined {
|
||||||
|
return ExtensionTypeEnum.SystemMonitoring;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract getResourcesInfo(): Promise<any>;
|
||||||
|
abstract getCurrentLoad(): Promise<any>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,10 @@
|
|||||||
import { ExtensionType, fs, Assistant } from "@janhq/core";
|
import { fs, Assistant } from "@janhq/core";
|
||||||
import { AssistantExtension } from "@janhq/core";
|
import { AssistantExtension } from "@janhq/core";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
|
|
||||||
export default class JanAssistantExtension implements AssistantExtension {
|
export default class JanAssistantExtension extends AssistantExtension {
|
||||||
private static readonly _homeDir = "file://assistants";
|
private static readonly _homeDir = "file://assistants";
|
||||||
|
|
||||||
type(): ExtensionType {
|
|
||||||
return ExtensionType.Assistant;
|
|
||||||
}
|
|
||||||
|
|
||||||
async onLoad() {
|
async onLoad() {
|
||||||
// making the assistant directory
|
// making the assistant directory
|
||||||
if (!(await fs.existsSync(JanAssistantExtension._homeDir)))
|
if (!(await fs.existsSync(JanAssistantExtension._homeDir)))
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
ExtensionType,
|
|
||||||
fs,
|
fs,
|
||||||
joinPath,
|
joinPath,
|
||||||
ConversationalExtension,
|
ConversationalExtension,
|
||||||
@ -12,19 +11,12 @@ import {
|
|||||||
* functionality for managing threads.
|
* functionality for managing threads.
|
||||||
*/
|
*/
|
||||||
export default class JSONConversationalExtension
|
export default class JSONConversationalExtension
|
||||||
implements ConversationalExtension
|
extends ConversationalExtension
|
||||||
{
|
{
|
||||||
private static readonly _homeDir = 'file://threads'
|
private static readonly _homeDir = 'file://threads'
|
||||||
private static readonly _threadInfoFileName = 'thread.json'
|
private static readonly _threadInfoFileName = 'thread.json'
|
||||||
private static readonly _threadMessagesFileName = 'messages.jsonl'
|
private static readonly _threadMessagesFileName = 'messages.jsonl'
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of the extension.
|
|
||||||
*/
|
|
||||||
type(): ExtensionType {
|
|
||||||
return ExtensionType.Conversational
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the extension is loaded.
|
* Called when the extension is loaded.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -9,10 +9,8 @@
|
|||||||
import {
|
import {
|
||||||
ChatCompletionRole,
|
ChatCompletionRole,
|
||||||
ContentType,
|
ContentType,
|
||||||
EventName,
|
|
||||||
MessageRequest,
|
MessageRequest,
|
||||||
MessageStatus,
|
MessageStatus,
|
||||||
ExtensionType,
|
|
||||||
ThreadContent,
|
ThreadContent,
|
||||||
ThreadMessage,
|
ThreadMessage,
|
||||||
events,
|
events,
|
||||||
@ -23,6 +21,9 @@ import {
|
|||||||
InferenceExtension,
|
InferenceExtension,
|
||||||
log,
|
log,
|
||||||
InferenceEngine,
|
InferenceEngine,
|
||||||
|
MessageEvent,
|
||||||
|
ModelEvent,
|
||||||
|
InferenceEvent,
|
||||||
} from "@janhq/core";
|
} from "@janhq/core";
|
||||||
import { requestInference } from "./helpers/sse";
|
import { requestInference } from "./helpers/sse";
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
@ -32,7 +33,7 @@ import { ulid } from "ulid";
|
|||||||
* The class provides methods for initializing and stopping a model, and for making inference requests.
|
* The class provides methods for initializing and stopping a model, and for making inference requests.
|
||||||
* It also subscribes to events emitted by the @janhq/core package and handles new message requests.
|
* It also subscribes to events emitted by the @janhq/core package and handles new message requests.
|
||||||
*/
|
*/
|
||||||
export default class JanInferenceNitroExtension implements InferenceExtension {
|
export default class JanInferenceNitroExtension extends InferenceExtension {
|
||||||
private static readonly _homeDir = "file://engines";
|
private static readonly _homeDir = "file://engines";
|
||||||
private static readonly _settingsDir = "file://settings";
|
private static readonly _settingsDir = "file://settings";
|
||||||
private static readonly _engineMetadataFileName = "nitro.json";
|
private static readonly _engineMetadataFileName = "nitro.json";
|
||||||
@ -66,14 +67,6 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
|
|||||||
*/
|
*/
|
||||||
private nitroProcessInfo: any = undefined;
|
private nitroProcessInfo: any = undefined;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of the extension.
|
|
||||||
* @returns {ExtensionType} The type of the extension.
|
|
||||||
*/
|
|
||||||
type(): ExtensionType {
|
|
||||||
return ExtensionType.Inference;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribes to events emitted by the @janhq/core package.
|
* Subscribes to events emitted by the @janhq/core package.
|
||||||
*/
|
*/
|
||||||
@ -89,15 +82,15 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
|
|||||||
this.writeDefaultEngineSettings();
|
this.writeDefaultEngineSettings();
|
||||||
|
|
||||||
// Events subscription
|
// Events subscription
|
||||||
events.on(EventName.OnMessageSent, (data: MessageRequest) =>
|
events.on(MessageEvent.OnMessageSent, (data: MessageRequest) =>
|
||||||
this.onMessageRequest(data)
|
this.onMessageRequest(data)
|
||||||
);
|
);
|
||||||
|
|
||||||
events.on(EventName.OnModelInit, (model: Model) => this.onModelInit(model));
|
events.on(ModelEvent.OnModelInit, (model: Model) => this.onModelInit(model));
|
||||||
|
|
||||||
events.on(EventName.OnModelStop, (model: Model) => this.onModelStop(model));
|
events.on(ModelEvent.OnModelStop, (model: Model) => this.onModelStop(model));
|
||||||
|
|
||||||
events.on(EventName.OnInferenceStopped, () => this.onInferenceStopped());
|
events.on(InferenceEvent.OnInferenceStopped, () => this.onInferenceStopped());
|
||||||
|
|
||||||
// Attempt to fetch nvidia info
|
// Attempt to fetch nvidia info
|
||||||
await executeOnMain(NODE, "updateNvidiaInfo", {});
|
await executeOnMain(NODE, "updateNvidiaInfo", {});
|
||||||
@ -140,12 +133,12 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (nitroInitResult?.error) {
|
if (nitroInitResult?.error) {
|
||||||
events.emit(EventName.OnModelFail, model);
|
events.emit(ModelEvent.OnModelFail, model);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._currentModel = model;
|
this._currentModel = model;
|
||||||
events.emit(EventName.OnModelReady, model);
|
events.emit(ModelEvent.OnModelReady, model);
|
||||||
|
|
||||||
this.getNitroProcesHealthIntervalId = setInterval(
|
this.getNitroProcesHealthIntervalId = setInterval(
|
||||||
() => this.periodicallyGetNitroHealth(),
|
() => this.periodicallyGetNitroHealth(),
|
||||||
@ -157,7 +150,7 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
|
|||||||
if (model.engine !== "nitro") return;
|
if (model.engine !== "nitro") return;
|
||||||
|
|
||||||
await executeOnMain(NODE, "stopModel");
|
await executeOnMain(NODE, "stopModel");
|
||||||
events.emit(EventName.OnModelStopped, {});
|
events.emit(ModelEvent.OnModelStopped, {});
|
||||||
|
|
||||||
// stop the periocally health check
|
// stop the periocally health check
|
||||||
if (this.getNitroProcesHealthIntervalId) {
|
if (this.getNitroProcesHealthIntervalId) {
|
||||||
@ -175,7 +168,7 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
|
|||||||
const isRunning = this.nitroProcessInfo?.isRunning ?? false;
|
const isRunning = this.nitroProcessInfo?.isRunning ?? false;
|
||||||
if (isRunning && health.isRunning === false) {
|
if (isRunning && health.isRunning === false) {
|
||||||
console.debug("Nitro process is stopped");
|
console.debug("Nitro process is stopped");
|
||||||
events.emit(EventName.OnModelStopped, {});
|
events.emit(ModelEvent.OnModelStopped, {});
|
||||||
}
|
}
|
||||||
this.nitroProcessInfo = health;
|
this.nitroProcessInfo = health;
|
||||||
}
|
}
|
||||||
@ -241,7 +234,7 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
|
|||||||
updated: timestamp,
|
updated: timestamp,
|
||||||
object: "thread.message",
|
object: "thread.message",
|
||||||
};
|
};
|
||||||
events.emit(EventName.OnMessageResponse, message);
|
events.emit(MessageEvent.OnMessageResponse, message);
|
||||||
|
|
||||||
this.isCancelled = false;
|
this.isCancelled = false;
|
||||||
this.controller = new AbortController();
|
this.controller = new AbortController();
|
||||||
@ -261,22 +254,22 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
message.content = [messageContent];
|
message.content = [messageContent];
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
},
|
},
|
||||||
complete: async () => {
|
complete: async () => {
|
||||||
message.status = message.content.length
|
message.status = message.content.length
|
||||||
? MessageStatus.Ready
|
? MessageStatus.Ready
|
||||||
: MessageStatus.Error;
|
: MessageStatus.Error;
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
},
|
},
|
||||||
error: async (err) => {
|
error: async (err) => {
|
||||||
if (this.isCancelled || message.content.length) {
|
if (this.isCancelled || message.content.length) {
|
||||||
message.status = MessageStatus.Stopped;
|
message.status = MessageStatus.Stopped;
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
message.status = MessageStatus.Error;
|
message.status = MessageStatus.Error;
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
log(`[APP]::Error: ${err.message}`);
|
log(`[APP]::Error: ${err.message}`);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,16 +9,17 @@
|
|||||||
import {
|
import {
|
||||||
ChatCompletionRole,
|
ChatCompletionRole,
|
||||||
ContentType,
|
ContentType,
|
||||||
EventName,
|
|
||||||
MessageRequest,
|
MessageRequest,
|
||||||
MessageStatus,
|
MessageStatus,
|
||||||
ExtensionType,
|
|
||||||
ThreadContent,
|
ThreadContent,
|
||||||
ThreadMessage,
|
ThreadMessage,
|
||||||
events,
|
events,
|
||||||
fs,
|
fs,
|
||||||
|
BaseExtension,
|
||||||
|
MessageEvent,
|
||||||
|
ModelEvent,
|
||||||
|
InferenceEvent,
|
||||||
} from "@janhq/core";
|
} from "@janhq/core";
|
||||||
import { InferenceExtension } from "@janhq/core";
|
|
||||||
import { requestInference } from "./helpers/sse";
|
import { requestInference } from "./helpers/sse";
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
@ -28,7 +29,7 @@ import { join } from "path";
|
|||||||
* The class provides methods for initializing and stopping a model, and for making inference requests.
|
* The class provides methods for initializing and stopping a model, and for making inference requests.
|
||||||
* It also subscribes to events emitted by the @janhq/core package and handles new message requests.
|
* It also subscribes to events emitted by the @janhq/core package and handles new message requests.
|
||||||
*/
|
*/
|
||||||
export default class JanInferenceOpenAIExtension implements InferenceExtension {
|
export default class JanInferenceOpenAIExtension extends BaseExtension {
|
||||||
private static readonly _homeDir = "file://engines";
|
private static readonly _homeDir = "file://engines";
|
||||||
private static readonly _engineMetadataFileName = "openai.json";
|
private static readonly _engineMetadataFileName = "openai.json";
|
||||||
|
|
||||||
@ -42,14 +43,6 @@ export default class JanInferenceOpenAIExtension implements InferenceExtension {
|
|||||||
controller = new AbortController();
|
controller = new AbortController();
|
||||||
isCancelled = false;
|
isCancelled = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of the extension.
|
|
||||||
* @returns {ExtensionType} The type of the extension.
|
|
||||||
*/
|
|
||||||
// TODO: To fix
|
|
||||||
type(): ExtensionType {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Subscribes to events emitted by the @janhq/core package.
|
* Subscribes to events emitted by the @janhq/core package.
|
||||||
*/
|
*/
|
||||||
@ -63,18 +56,18 @@ export default class JanInferenceOpenAIExtension implements InferenceExtension {
|
|||||||
JanInferenceOpenAIExtension.writeDefaultEngineSettings();
|
JanInferenceOpenAIExtension.writeDefaultEngineSettings();
|
||||||
|
|
||||||
// Events subscription
|
// Events subscription
|
||||||
events.on(EventName.OnMessageSent, (data) =>
|
events.on(MessageEvent.OnMessageSent, (data) =>
|
||||||
JanInferenceOpenAIExtension.handleMessageRequest(data, this)
|
JanInferenceOpenAIExtension.handleMessageRequest(data, this)
|
||||||
);
|
);
|
||||||
|
|
||||||
events.on(EventName.OnModelInit, (model: OpenAIModel) => {
|
events.on(ModelEvent.OnModelInit, (model: OpenAIModel) => {
|
||||||
JanInferenceOpenAIExtension.handleModelInit(model);
|
JanInferenceOpenAIExtension.handleModelInit(model);
|
||||||
});
|
});
|
||||||
|
|
||||||
events.on(EventName.OnModelStop, (model: OpenAIModel) => {
|
events.on(ModelEvent.OnModelStop, (model: OpenAIModel) => {
|
||||||
JanInferenceOpenAIExtension.handleModelStop(model);
|
JanInferenceOpenAIExtension.handleModelStop(model);
|
||||||
});
|
});
|
||||||
events.on(EventName.OnInferenceStopped, () => {
|
events.on(InferenceEvent.OnInferenceStopped, () => {
|
||||||
JanInferenceOpenAIExtension.handleInferenceStopped(this);
|
JanInferenceOpenAIExtension.handleInferenceStopped(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -104,43 +97,6 @@ export default class JanInferenceOpenAIExtension implements InferenceExtension {
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a single response inference request.
|
|
||||||
* @param {MessageRequest} data - The data for the inference request.
|
|
||||||
* @returns {Promise<any>} A promise that resolves with the inference response.
|
|
||||||
*/
|
|
||||||
async inference(data: MessageRequest): Promise<ThreadMessage> {
|
|
||||||
const timestamp = Date.now();
|
|
||||||
|
|
||||||
const message: ThreadMessage = {
|
|
||||||
thread_id: data.threadId,
|
|
||||||
created: timestamp,
|
|
||||||
updated: timestamp,
|
|
||||||
status: MessageStatus.Ready,
|
|
||||||
id: "",
|
|
||||||
role: ChatCompletionRole.Assistant,
|
|
||||||
object: "thread.message",
|
|
||||||
content: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
requestInference(
|
|
||||||
data.messages ?? [],
|
|
||||||
JanInferenceOpenAIExtension._engineSettings,
|
|
||||||
JanInferenceOpenAIExtension._currentModel
|
|
||||||
).subscribe({
|
|
||||||
next: (_content) => {},
|
|
||||||
complete: async () => {
|
|
||||||
resolve(message);
|
|
||||||
},
|
|
||||||
error: async (err) => {
|
|
||||||
reject(err);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async handleModelInit(model: OpenAIModel) {
|
private static async handleModelInit(model: OpenAIModel) {
|
||||||
if (model.engine !== "openai") {
|
if (model.engine !== "openai") {
|
||||||
return;
|
return;
|
||||||
@ -148,7 +104,7 @@ export default class JanInferenceOpenAIExtension implements InferenceExtension {
|
|||||||
JanInferenceOpenAIExtension._currentModel = model;
|
JanInferenceOpenAIExtension._currentModel = model;
|
||||||
JanInferenceOpenAIExtension.writeDefaultEngineSettings();
|
JanInferenceOpenAIExtension.writeDefaultEngineSettings();
|
||||||
// Todo: Check model list with API key
|
// Todo: Check model list with API key
|
||||||
events.emit(EventName.OnModelReady, model);
|
events.emit(ModelEvent.OnModelReady, model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +112,7 @@ export default class JanInferenceOpenAIExtension implements InferenceExtension {
|
|||||||
if (model.engine !== "openai") {
|
if (model.engine !== "openai") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
events.emit(EventName.OnModelStopped, model);
|
events.emit(ModelEvent.OnModelStopped, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async handleInferenceStopped(
|
private static async handleInferenceStopped(
|
||||||
@ -192,7 +148,7 @@ export default class JanInferenceOpenAIExtension implements InferenceExtension {
|
|||||||
updated: timestamp,
|
updated: timestamp,
|
||||||
object: "thread.message",
|
object: "thread.message",
|
||||||
};
|
};
|
||||||
events.emit(EventName.OnMessageResponse, message);
|
events.emit(MessageEvent.OnMessageResponse, message);
|
||||||
|
|
||||||
instance.isCancelled = false;
|
instance.isCancelled = false;
|
||||||
instance.controller = new AbortController();
|
instance.controller = new AbortController();
|
||||||
@ -215,18 +171,18 @@ export default class JanInferenceOpenAIExtension implements InferenceExtension {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
message.content = [messageContent];
|
message.content = [messageContent];
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
},
|
},
|
||||||
complete: async () => {
|
complete: async () => {
|
||||||
message.status = message.content.length
|
message.status = message.content.length
|
||||||
? MessageStatus.Ready
|
? MessageStatus.Ready
|
||||||
: MessageStatus.Error;
|
: MessageStatus.Error;
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
},
|
},
|
||||||
error: async (err) => {
|
error: async (err) => {
|
||||||
if (instance.isCancelled || message.content.length > 0) {
|
if (instance.isCancelled || message.content.length > 0) {
|
||||||
message.status = MessageStatus.Error;
|
message.status = MessageStatus.Error;
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const messageContent: ThreadContent = {
|
const messageContent: ThreadContent = {
|
||||||
@ -238,7 +194,7 @@ export default class JanInferenceOpenAIExtension implements InferenceExtension {
|
|||||||
};
|
};
|
||||||
message.content = [messageContent];
|
message.content = [messageContent];
|
||||||
message.status = MessageStatus.Ready;
|
message.status = MessageStatus.Ready;
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,18 +9,18 @@
|
|||||||
import {
|
import {
|
||||||
ChatCompletionRole,
|
ChatCompletionRole,
|
||||||
ContentType,
|
ContentType,
|
||||||
EventName,
|
|
||||||
MessageRequest,
|
MessageRequest,
|
||||||
MessageStatus,
|
MessageStatus,
|
||||||
ModelSettingParams,
|
ModelSettingParams,
|
||||||
ExtensionType,
|
|
||||||
ThreadContent,
|
ThreadContent,
|
||||||
ThreadMessage,
|
ThreadMessage,
|
||||||
events,
|
events,
|
||||||
fs,
|
fs,
|
||||||
Model,
|
Model,
|
||||||
|
BaseExtension,
|
||||||
|
MessageEvent,
|
||||||
|
ModelEvent,
|
||||||
} from "@janhq/core";
|
} from "@janhq/core";
|
||||||
import { InferenceExtension } from "@janhq/core";
|
|
||||||
import { requestInference } from "./helpers/sse";
|
import { requestInference } from "./helpers/sse";
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
@ -32,7 +32,7 @@ import { EngineSettings } from "./@types/global";
|
|||||||
* It also subscribes to events emitted by the @janhq/core package and handles new message requests.
|
* It also subscribes to events emitted by the @janhq/core package and handles new message requests.
|
||||||
*/
|
*/
|
||||||
export default class JanInferenceTritonTrtLLMExtension
|
export default class JanInferenceTritonTrtLLMExtension
|
||||||
implements InferenceExtension
|
extends BaseExtension
|
||||||
{
|
{
|
||||||
private static readonly _homeDir = "file://engines";
|
private static readonly _homeDir = "file://engines";
|
||||||
private static readonly _engineMetadataFileName = "triton_trtllm.json";
|
private static readonly _engineMetadataFileName = "triton_trtllm.json";
|
||||||
@ -46,14 +46,6 @@ export default class JanInferenceTritonTrtLLMExtension
|
|||||||
controller = new AbortController();
|
controller = new AbortController();
|
||||||
isCancelled = false;
|
isCancelled = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of the extension.
|
|
||||||
* @returns {ExtensionType} The type of the extension.
|
|
||||||
*/
|
|
||||||
// TODO: To fix
|
|
||||||
type(): ExtensionType {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Subscribes to events emitted by the @janhq/core package.
|
* Subscribes to events emitted by the @janhq/core package.
|
||||||
*/
|
*/
|
||||||
@ -62,15 +54,15 @@ export default class JanInferenceTritonTrtLLMExtension
|
|||||||
JanInferenceTritonTrtLLMExtension.writeDefaultEngineSettings();
|
JanInferenceTritonTrtLLMExtension.writeDefaultEngineSettings();
|
||||||
|
|
||||||
// Events subscription
|
// Events subscription
|
||||||
events.on(EventName.OnMessageSent, (data) =>
|
events.on(MessageEvent.OnMessageSent, (data) =>
|
||||||
JanInferenceTritonTrtLLMExtension.handleMessageRequest(data, this)
|
JanInferenceTritonTrtLLMExtension.handleMessageRequest(data, this)
|
||||||
);
|
);
|
||||||
|
|
||||||
events.on(EventName.OnModelInit, (model: Model) => {
|
events.on(ModelEvent.OnModelInit, (model: Model) => {
|
||||||
JanInferenceTritonTrtLLMExtension.handleModelInit(model);
|
JanInferenceTritonTrtLLMExtension.handleModelInit(model);
|
||||||
});
|
});
|
||||||
|
|
||||||
events.on(EventName.OnModelStop, (model: Model) => {
|
events.on(ModelEvent.OnModelStop, (model: Model) => {
|
||||||
JanInferenceTritonTrtLLMExtension.handleModelStop(model);
|
JanInferenceTritonTrtLLMExtension.handleModelStop(model);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -131,41 +123,6 @@ export default class JanInferenceTritonTrtLLMExtension
|
|||||||
this.controller?.abort();
|
this.controller?.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a single response inference request.
|
|
||||||
* @param {MessageRequest} data - The data for the inference request.
|
|
||||||
* @returns {Promise<any>} A promise that resolves with the inference response.
|
|
||||||
*/
|
|
||||||
async inference(data: MessageRequest): Promise<ThreadMessage> {
|
|
||||||
const timestamp = Date.now();
|
|
||||||
const message: ThreadMessage = {
|
|
||||||
thread_id: data.threadId,
|
|
||||||
created: timestamp,
|
|
||||||
updated: timestamp,
|
|
||||||
status: MessageStatus.Ready,
|
|
||||||
id: "",
|
|
||||||
role: ChatCompletionRole.Assistant,
|
|
||||||
object: "thread.message",
|
|
||||||
content: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
requestInference(
|
|
||||||
data.messages ?? [],
|
|
||||||
JanInferenceTritonTrtLLMExtension._engineSettings,
|
|
||||||
JanInferenceTritonTrtLLMExtension._currentModel
|
|
||||||
).subscribe({
|
|
||||||
next: (_content) => {},
|
|
||||||
complete: async () => {
|
|
||||||
resolve(message);
|
|
||||||
},
|
|
||||||
error: async (err) => {
|
|
||||||
reject(err);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async handleModelInit(model: Model) {
|
private static async handleModelInit(model: Model) {
|
||||||
if (model.engine !== "triton_trtllm") {
|
if (model.engine !== "triton_trtllm") {
|
||||||
return;
|
return;
|
||||||
@ -173,8 +130,7 @@ export default class JanInferenceTritonTrtLLMExtension
|
|||||||
JanInferenceTritonTrtLLMExtension._currentModel = model;
|
JanInferenceTritonTrtLLMExtension._currentModel = model;
|
||||||
JanInferenceTritonTrtLLMExtension.writeDefaultEngineSettings();
|
JanInferenceTritonTrtLLMExtension.writeDefaultEngineSettings();
|
||||||
// Todo: Check model list with API key
|
// Todo: Check model list with API key
|
||||||
events.emit(EventName.OnModelReady, model);
|
events.emit(ModelEvent.OnModelReady, model);
|
||||||
// events.emit(EventName.OnModelFail, model)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +138,7 @@ export default class JanInferenceTritonTrtLLMExtension
|
|||||||
if (model.engine !== "triton_trtllm") {
|
if (model.engine !== "triton_trtllm") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
events.emit(EventName.OnModelStopped, model);
|
events.emit(ModelEvent.OnModelStopped, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -211,7 +167,7 @@ export default class JanInferenceTritonTrtLLMExtension
|
|||||||
updated: timestamp,
|
updated: timestamp,
|
||||||
object: "thread.message",
|
object: "thread.message",
|
||||||
};
|
};
|
||||||
events.emit(EventName.OnMessageResponse, message);
|
events.emit(MessageEvent.OnMessageResponse, message);
|
||||||
|
|
||||||
instance.isCancelled = false;
|
instance.isCancelled = false;
|
||||||
instance.controller = new AbortController();
|
instance.controller = new AbortController();
|
||||||
@ -234,18 +190,18 @@ export default class JanInferenceTritonTrtLLMExtension
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
message.content = [messageContent];
|
message.content = [messageContent];
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
},
|
},
|
||||||
complete: async () => {
|
complete: async () => {
|
||||||
message.status = message.content.length
|
message.status = message.content.length
|
||||||
? MessageStatus.Ready
|
? MessageStatus.Ready
|
||||||
: MessageStatus.Error;
|
: MessageStatus.Error;
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
},
|
},
|
||||||
error: async (err) => {
|
error: async (err) => {
|
||||||
if (instance.isCancelled || message.content.length) {
|
if (instance.isCancelled || message.content.length) {
|
||||||
message.status = MessageStatus.Error;
|
message.status = MessageStatus.Error;
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const messageContent: ThreadContent = {
|
const messageContent: ThreadContent = {
|
||||||
@ -257,7 +213,7 @@ export default class JanInferenceTritonTrtLLMExtension
|
|||||||
};
|
};
|
||||||
message.content = [messageContent];
|
message.content = [messageContent];
|
||||||
message.status = MessageStatus.Ready;
|
message.status = MessageStatus.Ready;
|
||||||
events.emit(EventName.OnMessageUpdate, message);
|
events.emit(MessageEvent.OnMessageUpdate, message);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
ExtensionType,
|
|
||||||
fs,
|
fs,
|
||||||
downloadFile,
|
downloadFile,
|
||||||
abortDownload,
|
abortDownload,
|
||||||
@ -14,7 +13,7 @@ import {
|
|||||||
/**
|
/**
|
||||||
* A extension for models
|
* A extension for models
|
||||||
*/
|
*/
|
||||||
export default class JanModelExtension implements ModelExtension {
|
export default class JanModelExtension extends ModelExtension {
|
||||||
private static readonly _homeDir = 'file://models'
|
private static readonly _homeDir = 'file://models'
|
||||||
private static readonly _modelMetadataFileName = 'model.json'
|
private static readonly _modelMetadataFileName = 'model.json'
|
||||||
private static readonly _supportedModelFormat = '.gguf'
|
private static readonly _supportedModelFormat = '.gguf'
|
||||||
@ -24,15 +23,6 @@ export default class JanModelExtension implements ModelExtension {
|
|||||||
private static readonly _configDirName = 'config'
|
private static readonly _configDirName = 'config'
|
||||||
private static readonly _defaultModelFileName = 'default-model.json'
|
private static readonly _defaultModelFileName = 'default-model.json'
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements type from JanExtension.
|
|
||||||
* @override
|
|
||||||
* @returns The type of the extension.
|
|
||||||
*/
|
|
||||||
type(): ExtensionType {
|
|
||||||
return ExtensionType.Model
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the extension is loaded.
|
* Called when the extension is loaded.
|
||||||
* @override
|
* @override
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { ExtensionType } from "@janhq/core";
|
|
||||||
import { MonitoringExtension } from "@janhq/core";
|
import { MonitoringExtension } from "@janhq/core";
|
||||||
import { executeOnMain } from "@janhq/core";
|
import { executeOnMain } from "@janhq/core";
|
||||||
|
|
||||||
@ -6,15 +5,7 @@ import { executeOnMain } from "@janhq/core";
|
|||||||
* JanMonitoringExtension is a extension that provides system monitoring functionality.
|
* JanMonitoringExtension is a extension that provides system monitoring functionality.
|
||||||
* It implements the MonitoringExtension interface from the @janhq/core package.
|
* It implements the MonitoringExtension interface from the @janhq/core package.
|
||||||
*/
|
*/
|
||||||
export default class JanMonitoringExtension implements MonitoringExtension {
|
export default class JanMonitoringExtension extends MonitoringExtension {
|
||||||
/**
|
|
||||||
* Returns the type of the extension.
|
|
||||||
* @returns The ExtensionType.SystemMonitoring value.
|
|
||||||
*/
|
|
||||||
type(): ExtensionType {
|
|
||||||
return ExtensionType.SystemMonitoring;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the extension is loaded.
|
* Called when the extension is loaded.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -3,12 +3,13 @@ import { ReactNode, useEffect, useRef } from 'react'
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
events,
|
events,
|
||||||
EventName,
|
|
||||||
ThreadMessage,
|
ThreadMessage,
|
||||||
ExtensionType,
|
ExtensionTypeEnum,
|
||||||
MessageStatus,
|
MessageStatus,
|
||||||
Model,
|
Model,
|
||||||
ConversationalExtension,
|
ConversationalExtension,
|
||||||
|
MessageEvent,
|
||||||
|
ModelEvent,
|
||||||
} from '@janhq/core'
|
} from '@janhq/core'
|
||||||
import { useAtomValue, useSetAtom } from 'jotai'
|
import { useAtomValue, useSetAtom } from 'jotai'
|
||||||
|
|
||||||
@ -100,14 +101,14 @@ export default function EventHandler({ children }: { children: ReactNode }) {
|
|||||||
lastMessage: messageContent,
|
lastMessage: messageContent,
|
||||||
}
|
}
|
||||||
extensionManager
|
extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.saveThread({
|
?.saveThread({
|
||||||
...thread,
|
...thread,
|
||||||
metadata,
|
metadata,
|
||||||
})
|
})
|
||||||
|
|
||||||
extensionManager
|
extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.addNewMessage(message)
|
?.addNewMessage(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,19 +116,19 @@ export default function EventHandler({ children }: { children: ReactNode }) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (window.core?.events) {
|
if (window.core?.events) {
|
||||||
events.on(EventName.OnMessageResponse, handleNewMessageResponse)
|
events.on(MessageEvent.OnMessageResponse, handleNewMessageResponse)
|
||||||
events.on(EventName.OnMessageUpdate, handleMessageResponseUpdate)
|
events.on(MessageEvent.OnMessageUpdate, handleMessageResponseUpdate)
|
||||||
events.on(EventName.OnModelReady, handleModelReady)
|
events.on(ModelEvent.OnModelReady, handleModelReady)
|
||||||
events.on(EventName.OnModelFail, handleModelFail)
|
events.on(ModelEvent.OnModelFail, handleModelFail)
|
||||||
events.on(EventName.OnModelStopped, handleModelStopped)
|
events.on(ModelEvent.OnModelStopped, handleModelStopped)
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
events.off(EventName.OnMessageResponse, handleNewMessageResponse)
|
events.off(MessageEvent.OnMessageResponse, handleNewMessageResponse)
|
||||||
events.off(EventName.OnMessageUpdate, handleMessageResponseUpdate)
|
events.off(MessageEvent.OnMessageUpdate, handleMessageResponseUpdate)
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
import { BaseExtension, ExtensionType } from '@janhq/core'
|
import { BaseExtension, ExtensionTypeEnum } from '@janhq/core'
|
||||||
|
|
||||||
import Extension from './Extension'
|
import Extension from './Extension'
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ export class ExtensionManager {
|
|||||||
* @param type - The type of the extension to retrieve.
|
* @param type - The type of the extension to retrieve.
|
||||||
* @returns The extension, if found.
|
* @returns The extension, if found.
|
||||||
*/
|
*/
|
||||||
get<T extends BaseExtension>(type: ExtensionType): T | undefined {
|
get<T extends BaseExtension>(type: ExtensionTypeEnum): T | undefined {
|
||||||
return this.extensions.get(type) as T | undefined
|
return this.extensions.get(type) as T | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
import { events, Model, ModelEvent } from '@janhq/core'
|
||||||
import { EventName, events, Model } from '@janhq/core'
|
|
||||||
import { atom, useAtom, useAtomValue } from 'jotai'
|
import { atom, useAtom, useAtomValue } from 'jotai'
|
||||||
|
|
||||||
import { toaster } from '@/containers/Toast'
|
import { toaster } from '@/containers/Toast'
|
||||||
@ -64,14 +63,14 @@ export function useActiveModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem(LAST_USED_MODEL_ID, model.id)
|
localStorage.setItem(LAST_USED_MODEL_ID, model.id)
|
||||||
events.emit(EventName.OnModelInit, model)
|
events.emit(ModelEvent.OnModelInit, model)
|
||||||
}
|
}
|
||||||
|
|
||||||
const stopModel = async () => {
|
const stopModel = async () => {
|
||||||
if (activeModel) {
|
if (activeModel) {
|
||||||
setActiveModel(undefined)
|
setActiveModel(undefined)
|
||||||
setStateModel({ state: 'stop', loading: true, model: activeModel.id })
|
setStateModel({ state: 'stop', loading: true, model: activeModel.id })
|
||||||
events.emit(EventName.OnModelStop, activeModel)
|
events.emit(ModelEvent.OnModelStop, activeModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
Assistant,
|
Assistant,
|
||||||
ConversationalExtension,
|
ConversationalExtension,
|
||||||
ExtensionType,
|
ExtensionTypeEnum,
|
||||||
Thread,
|
Thread,
|
||||||
ThreadAssistantInfo,
|
ThreadAssistantInfo,
|
||||||
ThreadState,
|
ThreadState,
|
||||||
@ -104,7 +104,7 @@ export const useCreateNewThread = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extensionManager
|
extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.saveThread(thread)
|
?.saveThread(thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ExtensionType, ModelExtension, Model } from '@janhq/core'
|
import { ExtensionTypeEnum, ModelExtension, Model } from '@janhq/core'
|
||||||
|
|
||||||
import { toaster } from '@/containers/Toast'
|
import { toaster } from '@/containers/Toast'
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ export default function useDeleteModel() {
|
|||||||
|
|
||||||
const deleteModel = async (model: Model) => {
|
const deleteModel = async (model: Model) => {
|
||||||
await extensionManager
|
await extensionManager
|
||||||
.get<ModelExtension>(ExtensionType.Model)
|
.get<ModelExtension>(ExtensionTypeEnum.Model)
|
||||||
?.deleteModel(model.id)
|
?.deleteModel(model.id)
|
||||||
|
|
||||||
// reload models
|
// reload models
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
ChatCompletionRole,
|
ChatCompletionRole,
|
||||||
ExtensionType,
|
ExtensionTypeEnum,
|
||||||
ConversationalExtension,
|
ConversationalExtension,
|
||||||
} from '@janhq/core'
|
} from '@janhq/core'
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ export default function useDeleteThread() {
|
|||||||
|
|
||||||
if (thread) {
|
if (thread) {
|
||||||
await extensionManager
|
await extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.writeMessages(
|
?.writeMessages(
|
||||||
threadId,
|
threadId,
|
||||||
messages.filter((msg) => msg.role === ChatCompletionRole.System)
|
messages.filter((msg) => msg.role === ChatCompletionRole.System)
|
||||||
@ -61,7 +61,7 @@ export default function useDeleteThread() {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await extensionManager
|
await extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.deleteThread(threadId)
|
?.deleteThread(threadId)
|
||||||
const availableThreads = threads.filter((c) => c.id !== threadId)
|
const availableThreads = threads.filter((c) => c.id !== threadId)
|
||||||
setThreads(availableThreads)
|
setThreads(availableThreads)
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { useContext } from 'react'
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Model,
|
Model,
|
||||||
ExtensionType,
|
ExtensionTypeEnum,
|
||||||
ModelExtension,
|
ModelExtension,
|
||||||
abortDownload,
|
abortDownload,
|
||||||
joinPath,
|
joinPath,
|
||||||
@ -43,7 +43,7 @@ export default function useDownloadModel() {
|
|||||||
addNewDownloadingModel(model)
|
addNewDownloadingModel(model)
|
||||||
|
|
||||||
await extensionManager
|
await extensionManager
|
||||||
.get<ModelExtension>(ExtensionType.Model)
|
.get<ModelExtension>(ExtensionTypeEnum.Model)
|
||||||
?.downloadModel(model, { ignoreSSL, proxy })
|
?.downloadModel(model, { ignoreSSL, proxy })
|
||||||
}
|
}
|
||||||
const abortModelDownload = async (model: Model) => {
|
const abortModelDownload = async (model: Model) => {
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
import { Assistant, ExtensionType, AssistantExtension } from '@janhq/core'
|
import { Assistant, ExtensionTypeEnum, AssistantExtension } from '@janhq/core'
|
||||||
|
|
||||||
import { extensionManager } from '@/extension/ExtensionManager'
|
import { extensionManager } from '@/extension/ExtensionManager'
|
||||||
|
|
||||||
export const getAssistants = async (): Promise<Assistant[]> =>
|
export const getAssistants = async (): Promise<Assistant[]> =>
|
||||||
extensionManager
|
extensionManager
|
||||||
.get<AssistantExtension>(ExtensionType.Assistant)
|
.get<AssistantExtension>(ExtensionTypeEnum.Assistant)
|
||||||
?.getAssistants() ?? []
|
?.getAssistants() ?? []
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
import { ExtensionType, ModelExtension } from '@janhq/core'
|
import { ExtensionTypeEnum, ModelExtension } from '@janhq/core'
|
||||||
import { Model } from '@janhq/core'
|
import { Model } from '@janhq/core'
|
||||||
|
|
||||||
import { extensionManager } from '@/extension/ExtensionManager'
|
import { extensionManager } from '@/extension/ExtensionManager'
|
||||||
@ -11,7 +11,7 @@ export function useGetConfiguredModels() {
|
|||||||
|
|
||||||
const getConfiguredModels = async (): Promise<Model[]> => {
|
const getConfiguredModels = async (): Promise<Model[]> => {
|
||||||
const models = await extensionManager
|
const models = await extensionManager
|
||||||
.get<ModelExtension>(ExtensionType.Model)
|
.get<ModelExtension>(ExtensionTypeEnum.Model)
|
||||||
?.getConfiguredModels()
|
?.getConfiguredModels()
|
||||||
return models ?? []
|
return models ?? []
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
import { ExtensionType, ModelExtension, Model } from '@janhq/core'
|
import { ExtensionTypeEnum, ModelExtension, Model } from '@janhq/core'
|
||||||
|
|
||||||
import { atom, useAtom } from 'jotai'
|
import { atom, useAtom } from 'jotai'
|
||||||
|
|
||||||
@ -22,5 +22,5 @@ export function useGetDownloadedModels() {
|
|||||||
|
|
||||||
export const getDownloadedModels = async (): Promise<Model[]> =>
|
export const getDownloadedModels = async (): Promise<Model[]> =>
|
||||||
extensionManager
|
extensionManager
|
||||||
.get<ModelExtension>(ExtensionType.Model)
|
.get<ModelExtension>(ExtensionTypeEnum.Model)
|
||||||
?.getDownloadedModels() ?? []
|
?.getDownloadedModels() ?? []
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
import { ExtensionType } from '@janhq/core'
|
import { ExtensionTypeEnum } from '@janhq/core'
|
||||||
import { MonitoringExtension } from '@janhq/core'
|
import { MonitoringExtension } from '@janhq/core'
|
||||||
|
|
||||||
import { useSetAtom } from 'jotai'
|
import { useSetAtom } from 'jotai'
|
||||||
@ -21,12 +21,14 @@ export default function useGetSystemResources() {
|
|||||||
|
|
||||||
const getSystemResources = async () => {
|
const getSystemResources = async () => {
|
||||||
if (
|
if (
|
||||||
!extensionManager.get<MonitoringExtension>(ExtensionType.SystemMonitoring)
|
!extensionManager.get<MonitoringExtension>(
|
||||||
|
ExtensionTypeEnum.SystemMonitoring
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const monitoring = extensionManager.get<MonitoringExtension>(
|
const monitoring = extensionManager.get<MonitoringExtension>(
|
||||||
ExtensionType.SystemMonitoring
|
ExtensionTypeEnum.SystemMonitoring
|
||||||
)
|
)
|
||||||
const resourceInfor = await monitoring?.getResourcesInfo()
|
const resourceInfor = await monitoring?.getResourcesInfo()
|
||||||
const currentLoadInfor = await monitoring?.getCurrentLoad()
|
const currentLoadInfor = await monitoring?.getCurrentLoad()
|
||||||
|
|||||||
@ -4,15 +4,15 @@ import {
|
|||||||
ChatCompletionMessage,
|
ChatCompletionMessage,
|
||||||
ChatCompletionRole,
|
ChatCompletionRole,
|
||||||
ContentType,
|
ContentType,
|
||||||
EventName,
|
|
||||||
MessageRequest,
|
MessageRequest,
|
||||||
MessageStatus,
|
MessageStatus,
|
||||||
ExtensionType,
|
ExtensionTypeEnum,
|
||||||
Thread,
|
Thread,
|
||||||
ThreadMessage,
|
ThreadMessage,
|
||||||
events,
|
events,
|
||||||
Model,
|
Model,
|
||||||
ConversationalExtension,
|
ConversationalExtension,
|
||||||
|
MessageEvent,
|
||||||
} from '@janhq/core'
|
} from '@janhq/core'
|
||||||
import { useAtom, useAtomValue, useSetAtom } from 'jotai'
|
import { useAtom, useAtomValue, useSetAtom } from 'jotai'
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ export default function useSendChatMessage() {
|
|||||||
await WaitForModelStarting(modelId)
|
await WaitForModelStarting(modelId)
|
||||||
setQueuedMessage(false)
|
setQueuedMessage(false)
|
||||||
}
|
}
|
||||||
events.emit(EventName.OnMessageSent, messageRequest)
|
events.emit(MessageEvent.OnMessageSent, messageRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Refactor @louis
|
// TODO: Refactor @louis
|
||||||
@ -181,7 +181,7 @@ export default function useSendChatMessage() {
|
|||||||
updateThread(updatedThread)
|
updateThread(updatedThread)
|
||||||
|
|
||||||
await extensionManager
|
await extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.saveThread(updatedThread)
|
?.saveThread(updatedThread)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ export default function useSendChatMessage() {
|
|||||||
addNewMessage(threadMessage)
|
addNewMessage(threadMessage)
|
||||||
|
|
||||||
await extensionManager
|
await extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.addNewMessage(threadMessage)
|
?.addNewMessage(threadMessage)
|
||||||
|
|
||||||
const modelId = selectedModel?.id ?? activeThread.assistants[0].model.id
|
const modelId = selectedModel?.id ?? activeThread.assistants[0].model.id
|
||||||
@ -265,7 +265,7 @@ export default function useSendChatMessage() {
|
|||||||
setQueuedMessage(false)
|
setQueuedMessage(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
events.emit(EventName.OnMessageSent, messageRequest)
|
events.emit(MessageEvent.OnMessageSent, messageRequest)
|
||||||
|
|
||||||
setReloadModel(false)
|
setReloadModel(false)
|
||||||
setEngineParamsUpdate(false)
|
setEngineParamsUpdate(false)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
EventName,
|
InferenceEvent,
|
||||||
ExtensionType,
|
ExtensionTypeEnum,
|
||||||
Thread,
|
Thread,
|
||||||
events,
|
events,
|
||||||
ConversationalExtension,
|
ConversationalExtension,
|
||||||
@ -29,11 +29,11 @@ export default function useSetActiveThread() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
events.emit(EventName.OnInferenceStopped, thread.id)
|
events.emit(InferenceEvent.OnInferenceStopped, thread.id)
|
||||||
|
|
||||||
// load the corresponding messages
|
// load the corresponding messages
|
||||||
const messages = await extensionManager
|
const messages = await extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.getAllMessages(thread.id)
|
?.getAllMessages(thread.id)
|
||||||
setThreadMessage(thread.id, messages ?? [])
|
setThreadMessage(thread.id, messages ?? [])
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
ExtensionType,
|
ExtensionTypeEnum,
|
||||||
Thread,
|
Thread,
|
||||||
ThreadState,
|
ThreadState,
|
||||||
ConversationalExtension,
|
ConversationalExtension,
|
||||||
@ -99,7 +99,7 @@ const useThreads = () => {
|
|||||||
|
|
||||||
const getLocalThreads = async (): Promise<Thread[]> =>
|
const getLocalThreads = async (): Promise<Thread[]> =>
|
||||||
(await extensionManager
|
(await extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.getThreads()) ?? []
|
?.getThreads()) ?? []
|
||||||
|
|
||||||
export default useThreads
|
export default useThreads
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import {
|
import {
|
||||||
ConversationalExtension,
|
ConversationalExtension,
|
||||||
ExtensionType,
|
ExtensionTypeEnum,
|
||||||
Thread,
|
Thread,
|
||||||
ThreadAssistantInfo,
|
ThreadAssistantInfo,
|
||||||
} from '@janhq/core'
|
} from '@janhq/core'
|
||||||
@ -73,7 +73,7 @@ export default function useUpdateModelParameters() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await extensionManager
|
await extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.saveThread(updatedThread)
|
?.saveThread(updatedThread)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ChatCompletionRole,
|
ChatCompletionRole,
|
||||||
ConversationalExtension,
|
ConversationalExtension,
|
||||||
ExtensionType,
|
ExtensionTypeEnum,
|
||||||
MessageStatus,
|
MessageStatus,
|
||||||
ThreadMessage,
|
ThreadMessage,
|
||||||
} from '@janhq/core'
|
} from '@janhq/core'
|
||||||
@ -32,7 +32,7 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
|
|||||||
deleteMessage(message.id ?? '')
|
deleteMessage(message.id ?? '')
|
||||||
if (thread) {
|
if (thread) {
|
||||||
await extensionManager
|
await extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.writeMessages(
|
?.writeMessages(
|
||||||
thread.id,
|
thread.id,
|
||||||
messages.filter((msg) => msg.id !== message.id)
|
messages.filter((msg) => msg.id !== message.id)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
MessageStatus,
|
MessageStatus,
|
||||||
ExtensionType,
|
ExtensionTypeEnum,
|
||||||
ThreadMessage,
|
ThreadMessage,
|
||||||
ChatCompletionRole,
|
ChatCompletionRole,
|
||||||
} from '@janhq/core'
|
} from '@janhq/core'
|
||||||
@ -31,7 +31,7 @@ const MessageToolbar = ({ message }: { message: ThreadMessage }) => {
|
|||||||
deleteMessage(message.id ?? '')
|
deleteMessage(message.id ?? '')
|
||||||
if (thread) {
|
if (thread) {
|
||||||
await extensionManager
|
await extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionType.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.writeMessages(
|
?.writeMessages(
|
||||||
thread.id,
|
thread.id,
|
||||||
messages.filter((msg) => msg.id !== message.id)
|
messages.filter((msg) => msg.id !== message.id)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ChangeEvent, Fragment, KeyboardEvent, useEffect, useRef } from 'react'
|
import { ChangeEvent, Fragment, KeyboardEvent, useEffect, useRef } from 'react'
|
||||||
|
|
||||||
import { EventName, MessageStatus, events } from '@janhq/core'
|
import { InferenceEvent, MessageStatus, events } from '@janhq/core'
|
||||||
import { Button, Textarea } from '@janhq/uikit'
|
import { Button, Textarea } from '@janhq/uikit'
|
||||||
|
|
||||||
import { useAtom, useAtomValue } from 'jotai'
|
import { useAtom, useAtomValue } from 'jotai'
|
||||||
@ -104,7 +104,7 @@ const ChatScreen = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const onStopInferenceClick = async () => {
|
const onStopInferenceClick = async () => {
|
||||||
events.emit(EventName.OnInferenceStopped, {})
|
events.emit(InferenceEvent.OnInferenceStopped, {})
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
'use client'
|
'use client'
|
||||||
import { ExtensionType } from '@janhq/core'
|
import { ExtensionTypeEnum } from '@janhq/core'
|
||||||
|
|
||||||
import { extensionManager } from '@/extension/ExtensionManager'
|
import { extensionManager } from '@/extension/ExtensionManager'
|
||||||
|
|
||||||
export const isCoreExtensionInstalled = () => {
|
export const isCoreExtensionInstalled = () => {
|
||||||
if (!extensionManager.get(ExtensionType.Conversational)) {
|
if (!extensionManager.get(ExtensionTypeEnum.Conversational)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (!extensionManager.get(ExtensionType.Inference)) return false
|
if (!extensionManager.get(ExtensionTypeEnum.Inference)) return false
|
||||||
if (!extensionManager.get(ExtensionType.Model)) {
|
if (!extensionManager.get(ExtensionTypeEnum.Model)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -21,9 +21,9 @@ export const setupBaseExtensions = async () => {
|
|||||||
const baseExtensions = await window.core?.api.baseExtensions()
|
const baseExtensions = await window.core?.api.baseExtensions()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!extensionManager.get(ExtensionType.Conversational) ||
|
!extensionManager.get(ExtensionTypeEnum.Conversational) ||
|
||||||
!extensionManager.get(ExtensionType.Inference) ||
|
!extensionManager.get(ExtensionTypeEnum.Inference) ||
|
||||||
!extensionManager.get(ExtensionType.Model)
|
!extensionManager.get(ExtensionTypeEnum.Model)
|
||||||
) {
|
) {
|
||||||
const installed = await extensionManager.install(baseExtensions)
|
const installed = await extensionManager.install(baseExtensions)
|
||||||
if (installed) {
|
if (installed) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user