Socket
Socket
Sign inDemoInstall

@musaid.qa/openai-socket

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@musaid.qa/openai-socket - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

src/types.ts

3

package.json
{
"name": "@musaid.qa/openai-socket",
"version": "0.0.1",
"version": "0.0.2",
"description": "A wrapper for the OpenAI API using sockets",

@@ -38,3 +38,2 @@ "author": "Mohamed Ali <m.ali@mymusaid.com>",

"rimraf": "^3.0.2",
"socket.io-client": "^4.7.2",
"ts-node": "^9.1.1",

@@ -41,0 +40,0 @@ "typedoc": "^0.25.4",

@@ -5,3 +5,3 @@ # OpenAI Socket

[![npm version](https://img.shields.io/npm/v/@musaid.qa/openai-socket.svg)](https://www.npmjs.com/package/openai-socket)
[![npm version](https://img.shields.io/npm/v/@musaid.qa/openai-socket.svg)](https://www.npmjs.com/package/@musaid.qa/openai-socket)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)

@@ -75,3 +75,3 @@

For more see [basic example](/src/examples/basic/) or [Docs](https://mymusaid.github.io/openai-stream)
For more see [basic example](/src/examples/basic/) or [Docs](https://openai-socket.docs.mymusaid.com)

@@ -78,0 +78,0 @@ ## License

@@ -1,56 +0,19 @@

import { Socket, Server } from 'socket.io';
import { ClientOptions, OpenAI } from 'openai';
import OpenAI from 'openai';
import { Server } from 'socket.io';
import {
ChatCompletionSnapshot,
ChatCompletionStreamParams,
} from 'openai/lib/ChatCompletionStream';
import {
ChatCompletion,
ChatCompletionChunk,
ChatCompletionMessage,
ChatCompletionMessageParam,
CompletionUsage,
} from 'openai/resources';
import { OpenAIError, APIUserAbortError } from 'openai/error';
export type Options = {
verbose: boolean;
client?: ClientOptions;
chat: Omit<ChatCompletionStreamParams, 'messages'>;
initMessages: ChatCompletionMessageParam[];
};
Client,
ChatCompletionEvents,
Options,
Message,
ClientOptions,
EmitEvents,
ListenEvents,
EventsMap,
} from './types';
export interface ChatCompletionEvents {
content: (contentDelta: string, contentSnapshot: string) => void;
chunk: (chunk: ChatCompletionChunk, snapshot: ChatCompletionSnapshot) => void;
connect: () => void;
functionCall: (functionCall: ChatCompletionMessage.FunctionCall) => void;
message: (message: ChatCompletionMessageParam) => void;
chatCompletion: (completion: ChatCompletion) => void;
finalContent: (contentSnapshot: string) => void;
finalMessage: (message: ChatCompletionMessageParam) => void;
finalChatCompletion: (completion: ChatCompletion) => void;
finalFunctionCall: (functionCall: ChatCompletionMessage.FunctionCall) => void;
functionCallResult: (content: string) => void;
finalFunctionCallResult: (content: string) => void;
error: (error: OpenAIError) => void;
abort: (error: APIUserAbortError) => void;
end: () => void;
totalUsage: (usage: CompletionUsage) => void;
}
export type EmitEvents = {
'new-message': (message: string) => void;
} & ChatCompletionEvents;
export type ListenEvents = {
'new-message': (message: string) => void;
};
export type CustomSocket = Socket<ListenEvents, EmitEvents>;
export class OpenAISocket {
class OpenAISocket {
/**
* Socket clients
*/
public clients: Map<string, CustomSocket> = new Map<string, CustomSocket>();
public clients: Map<string, Client> = new Map<string, Client>();

@@ -60,6 +23,3 @@ /**

*/
public messages: Map<string, ChatCompletionMessageParam[]> = new Map<
string,
ChatCompletionMessageParam[]
>();
public messages: Map<string, Message[]> = new Map<string, Message[]>();

@@ -71,20 +31,2 @@ /**

/**
* List of events to lisent for OpenAI.beta.chat.completions.stream
*/
public static eventsToListen: (keyof ChatCompletionEvents)[] = [
'abort',
'chatCompletion',
'chunk',
'content',
'end',
'error',
'finalChatCompletion',
'finalContent',
'finalFunctionCall',
'finalFunctionCallResult',
'finalMessage',
'totalUsage',
'message',
];

@@ -107,22 +49,23 @@ /**

this.openai = new OpenAI(this.options.client);
io.on('connection', (socket: CustomSocket) => {
this.registerClient(socket);
this.registerEvents(socket);
});
}
io.on('connection', (client: Client) => {
const { id } = client;
client.data.chat = this.options.chat;
client.data.initMessages = this.options.initMessages;
this.clients.set(id, client);
this.messages.set(id, []);
this.logger(`Client connected: ${id}`);
client.on('disconnect', () => this.onDisconnect(client));
client.on('new-message', (message) => this.onNewMessage(client, message));
client.on('set-options', (options) => {
if (options.chat) client.data.chat = options.chat;
if (options.initMessages)
client.data.initMessages = options.initMessages;
});
/**
* Register a new socket client.
* @param {CustomSocket} socket - The client socket object.
* @returns {void}
*/
registerClient(socket: CustomSocket): void {
const { id } = socket;
this.clients.set(id, socket);
this.messages.set(id, []);
this.logger(`Client connected: ${id}`);
socket.on('disconnect', () => {
this.clients.delete(id);
this.messages.delete(id);
this.logger(`Client disconnected: ${id}`);
client.on('abort', () => {
if (client.data.currentChatStream) {
client.data.currentChatStream.controller.abort();
client.data.currentChatStream = undefined;
}
});
});

@@ -132,30 +75,25 @@ }

/**
* Register listener for new-message event and push messages to the chat history
* for a given socket, and stream the chat completions events to the client.
* @param {CustomSocket} socket - The client socket object.
* @returns {void}
* Handles a new message received from a client.
*
* @param {Client} client - The client object.
* @param {string | Message} message - The message received from the client.
* @return {void} This function does not return anything.
*/
registerEvents(socket: CustomSocket): void {
socket.on('new-message', (message) => {
this.pushMessageToHistory(socket.id, message);
this.logger(`received message from ${socket.id}`);
const chat = this.openai.beta.chat.completions.stream({
...this.options.chat,
messages: [
...this.options.initMessages,
...this.getMessages(socket.id),
],
onNewMessage(client: Client, message: string | Message): void {
if (typeof message === 'object') {
this.pushToChatHistory(client.id, message);
} else {
this.pushToChatHistory(client.id, {
role: 'user',
content: message,
});
}
this.processNewMessage(client);
}
OpenAISocket.eventsToListen.forEach((event) => {
chat.on(event, (arg: any) => {
this.logger(
`event ${event} triggered for ${
socket.id
} with arg: ${JSON.stringify(arg, null, 2)}`,
);
socket.emit(event, arg);
});
});
});
onDisconnect(socket: Client): void {
const { id } = socket;
this.logger(`Client disconnected: ${id}`);
this.clients.delete(id);
this.messages.delete(id);
}

@@ -180,9 +118,5 @@

*/
private pushMessageToHistory(socketId: string, message: string): void {
private pushToChatHistory(socketId: string, message: Message): void {
if (this.messages.has(socketId)) {
this.logger(`pushing ${message} message to ${socketId} history`);
this.messages.get(socketId)?.push({
role: 'user',
content: message,
});
this.messages.get(socketId)?.push(message);
}

@@ -194,7 +128,78 @@ }

* @param {string} socketId - The ID of the socket.
* @returns {ChatCompletionMessageParam[]}
* @returns {Message[]}
*/
private getMessages(socketId: string): ChatCompletionMessageParam[] {
private getChatHistory(socketId: string): Message[] {
return this.messages.get(socketId) ?? [];
}
/**
* Process a new message from the client.
*
* @param {Client} client - The client object.
* @return {void} This function does not return anything.
*/
private processNewMessage(client: Client): void {
const { id, data } = client;
client.data.currentChatStream = this.openai.beta.chat.completions.stream({
...client.data.chat,
messages: [...data.initMessages, ...this.getChatHistory(id)],
});
const streamHandlers = {
content: (contentDelta, contentSnapshot) =>
client.emit('content', contentDelta, contentSnapshot),
finalContent: (contentSnapshot) =>
client.emit('finalContent', contentSnapshot),
chunk: (chunk, snapshot) => client.emit('chunk', chunk, snapshot),
chatCompletion: (completion) => client.emit('chatCompletion', completion),
finalChatCompletion: (completion) =>
client.emit('finalChatCompletion', completion),
message: (message) => client.emit('message', message),
finalMessage: (message) => {
this.pushToChatHistory(id, message);
client.emit('finalMessage', message);
},
functionCall: (functionCall) => client.emit('functionCall', functionCall),
finalFunctionCall: (finalFunctionCall) =>
client.emit('finalFunctionCall', finalFunctionCall),
functionCallResult: (finalFunctionCallResult) =>
client.emit('finalFunctionCallResult', finalFunctionCallResult),
finalFunctionCallResult: (finalFunctionCallResult) =>
client.emit('finalFunctionCallResult', finalFunctionCallResult),
totalUsage: (usage) => client.emit('totalUsage', usage),
error: (error) => {
client.emit('error', error);
client.data.currentChatStream = undefined;
},
end: () => {
client.emit('end');
client.data.currentChatStream = undefined;
},
} as ChatCompletionEvents;
Object.entries(streamHandlers).forEach(([event, handler]) => {
client.data.currentChatStream?.on(
event as keyof typeof streamHandlers,
(...args: any) => {
this.logger(
`Event: ${event}, Args: ${JSON.stringify(args, null, 2)}`,
);
handler(...args);
},
);
});
}
}
export {
OpenAISocket,
Client,
ChatCompletionEvents,
Options,
Message,
ClientOptions,
EmitEvents,
ListenEvents,
EventsMap,
};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc