Skip to content

Commit

Permalink
refactor: deprecate extension type implementation (janhq#1677)
Browse files Browse the repository at this point in the history
* refactor: deprecate extension type implementation

* chore: update README.md

* refactor: EventName to use the events defined in /types
  • Loading branch information
louis-jan authored Jan 22, 2024
1 parent 99d083d commit a50ea4a
Show file tree
Hide file tree
Showing 34 changed files with 242 additions and 627 deletions.
397 changes: 59 additions & 338 deletions core/README.md

Large diffs are not rendered by default.

25 changes: 0 additions & 25 deletions core/src/events.ts
Original file line number Diff line number Diff line change
@@ -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.
*
Expand Down
11 changes: 8 additions & 3 deletions core/src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
export enum ExtensionType {
export enum ExtensionTypeEnum {
Assistant = "assistant",
Conversational = "conversational",
Inference = "inference",
Model = "model",
SystemMonitoring = "systemMonitoring",
}

export interface ExtensionType {
type(): ExtensionTypeEnum | undefined;
}
/**
* Represents a base 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 {ExtensionType} The type of the extension
* 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.
* Any initialization logic for the extension should be put here.
Expand Down
17 changes: 12 additions & 5 deletions core/src/extensions/assistant.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { Assistant, AssistantInterface } from '../index'
import { BaseExtension } from '../extension'
import { Assistant, AssistantInterface } from "../index";
import { BaseExtension, ExtensionTypeEnum } from "../extension";

/**
* Assistant extension for managing assistants.
* @extends BaseExtension
*/
export abstract class AssistantExtension extends BaseExtension implements AssistantInterface {
abstract createAssistant(assistant: Assistant): Promise<void>
abstract deleteAssistant(assistant: Assistant): Promise<void>
abstract getAssistants(): Promise<Assistant[]>
/**
* Assistant extension type.
*/
type(): ExtensionTypeEnum | undefined {
return ExtensionTypeEnum.Assistant;
}

abstract createAssistant(assistant: Assistant): Promise<void>;
abstract deleteAssistant(assistant: Assistant): Promise<void>;
abstract getAssistants(): Promise<Assistant[]>;
}
9 changes: 8 additions & 1 deletion core/src/extensions/conversational.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Thread, ThreadInterface, ThreadMessage, MessageInterface } from '../index'
import { BaseExtension } from '../extension'
import { BaseExtension, ExtensionTypeEnum } from '../extension'

/**
* Conversational extension. Persists and retrieves conversations.
Expand All @@ -10,6 +10,13 @@ export abstract class ConversationalExtension
extends BaseExtension
implements ThreadInterface, MessageInterface
{
/**
* Conversation extension type.
*/
type(): ExtensionTypeEnum | undefined {
return ExtensionTypeEnum.Conversational;
}

abstract getThreads(): Promise<Thread[]>
abstract saveThread(thread: Thread): Promise<void>
abstract deleteThread(threadId: string): Promise<void>
Expand Down
13 changes: 10 additions & 3 deletions core/src/extensions/inference.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { InferenceInterface, MessageRequest, ThreadMessage } from '../index'
import { BaseExtension } from '../extension'
import { InferenceInterface, MessageRequest, ThreadMessage } from "../index";
import { BaseExtension, ExtensionTypeEnum } from "../extension";

/**
* Inference extension. Start, stop and inference models.
*/
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>;
}
26 changes: 18 additions & 8 deletions core/src/extensions/model.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import { BaseExtension } from '../extension'
import { Model, ModelInterface } from '../index'
import { BaseExtension, ExtensionTypeEnum } from "../extension";
import { Model, ModelInterface } from "../index";

/**
* Model extension for managing models.
*/
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>
abstract deleteModel(modelId: string): Promise<void>
abstract saveModel(model: Model): Promise<void>
abstract getDownloadedModels(): Promise<Model[]>
abstract getConfiguredModels(): Promise<Model[]>
/**
* Model extension type.
*/
type(): ExtensionTypeEnum | undefined {
return ExtensionTypeEnum.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[]>;
}
15 changes: 11 additions & 4 deletions core/src/extensions/monitoring.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { BaseExtension } from '../extension'
import { MonitoringInterface } from '../index'
import { BaseExtension, ExtensionTypeEnum } from "../extension";
import { MonitoringInterface } from "../index";

/**
* Monitoring extension for system monitoring.
* @extends BaseExtension
*/
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>;
}
8 changes: 2 additions & 6 deletions extensions/assistant-extension/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { ExtensionType, fs, Assistant } from "@janhq/core";
import { fs, Assistant } from "@janhq/core";
import { AssistantExtension } from "@janhq/core";
import { join } from "path";

export default class JanAssistantExtension implements AssistantExtension {
export default class JanAssistantExtension extends AssistantExtension {
private static readonly _homeDir = "file://assistants";

type(): ExtensionType {
return ExtensionType.Assistant;
}

async onLoad() {
// making the assistant directory
if (!(await fs.existsSync(JanAssistantExtension._homeDir)))
Expand Down
10 changes: 1 addition & 9 deletions extensions/conversational-extension/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
ExtensionType,
fs,
joinPath,
ConversationalExtension,
Expand All @@ -12,19 +11,12 @@ import {
* functionality for managing threads.
*/
export default class JSONConversationalExtension
implements ConversationalExtension
extends ConversationalExtension
{
private static readonly _homeDir = 'file://threads'
private static readonly _threadInfoFileName = 'thread.json'
private static readonly _threadMessagesFileName = 'messages.jsonl'

/**
* Returns the type of the extension.
*/
type(): ExtensionType {
return ExtensionType.Conversational
}

/**
* Called when the extension is loaded.
*/
Expand Down
41 changes: 17 additions & 24 deletions extensions/inference-nitro-extension/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
import {
ChatCompletionRole,
ContentType,
EventName,
MessageRequest,
MessageStatus,
ExtensionType,
ThreadContent,
ThreadMessage,
events,
Expand All @@ -23,6 +21,9 @@ import {
InferenceExtension,
log,
InferenceEngine,
MessageEvent,
ModelEvent,
InferenceEvent,
} from "@janhq/core";
import { requestInference } from "./helpers/sse";
import { ulid } from "ulid";
Expand All @@ -32,7 +33,7 @@ import { ulid } from "ulid";
* 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.
*/
export default class JanInferenceNitroExtension implements InferenceExtension {
export default class JanInferenceNitroExtension extends InferenceExtension {
private static readonly _homeDir = "file://engines";
private static readonly _settingsDir = "file://settings";
private static readonly _engineMetadataFileName = "nitro.json";
Expand Down Expand Up @@ -66,14 +67,6 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
*/
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.
*/
Expand All @@ -89,15 +82,15 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
this.writeDefaultEngineSettings();

// Events subscription
events.on(EventName.OnMessageSent, (data: MessageRequest) =>
events.on(MessageEvent.OnMessageSent, (data: MessageRequest) =>
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
await executeOnMain(NODE, "updateNvidiaInfo", {});
Expand Down Expand Up @@ -140,12 +133,12 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
});

if (nitroInitResult?.error) {
events.emit(EventName.OnModelFail, model);
events.emit(ModelEvent.OnModelFail, model);
return;
}

this._currentModel = model;
events.emit(EventName.OnModelReady, model);
events.emit(ModelEvent.OnModelReady, model);

this.getNitroProcesHealthIntervalId = setInterval(
() => this.periodicallyGetNitroHealth(),
Expand All @@ -157,7 +150,7 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
if (model.engine !== "nitro") return;

await executeOnMain(NODE, "stopModel");
events.emit(EventName.OnModelStopped, {});
events.emit(ModelEvent.OnModelStopped, {});

// stop the periocally health check
if (this.getNitroProcesHealthIntervalId) {
Expand All @@ -175,7 +168,7 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
const isRunning = this.nitroProcessInfo?.isRunning ?? false;
if (isRunning && health.isRunning === false) {
console.debug("Nitro process is stopped");
events.emit(EventName.OnModelStopped, {});
events.emit(ModelEvent.OnModelStopped, {});
}
this.nitroProcessInfo = health;
}
Expand Down Expand Up @@ -241,7 +234,7 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
updated: timestamp,
object: "thread.message",
};
events.emit(EventName.OnMessageResponse, message);
events.emit(MessageEvent.OnMessageResponse, message);

this.isCancelled = false;
this.controller = new AbortController();
Expand All @@ -261,22 +254,22 @@ export default class JanInferenceNitroExtension implements InferenceExtension {
},
};
message.content = [messageContent];
events.emit(EventName.OnMessageUpdate, message);
events.emit(MessageEvent.OnMessageUpdate, message);
},
complete: async () => {
message.status = message.content.length
? MessageStatus.Ready
: MessageStatus.Error;
events.emit(EventName.OnMessageUpdate, message);
events.emit(MessageEvent.OnMessageUpdate, message);
},
error: async (err) => {
if (this.isCancelled || message.content.length) {
message.status = MessageStatus.Stopped;
events.emit(EventName.OnMessageUpdate, message);
events.emit(MessageEvent.OnMessageUpdate, message);
return;
}
message.status = MessageStatus.Error;
events.emit(EventName.OnMessageUpdate, message);
events.emit(MessageEvent.OnMessageUpdate, message);
log(`[APP]::Error: ${err.message}`);
},
});
Expand Down
Loading

0 comments on commit a50ea4a

Please sign in to comment.