kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: add initial event logging implementation
rodzic
f8bd19bdda
commit
29207be8a7
|
@ -42,6 +42,7 @@
|
|||
"@inquirer/checkbox": "^1.3.0",
|
||||
"@inquirer/editor": "^1.1.0",
|
||||
"@inquirer/select": "^1.2.0",
|
||||
"debug": "^4.3.4",
|
||||
"handlebars": "^4.7.7",
|
||||
"js-tiktoken": "^1.0.6",
|
||||
"jsonrepair": "^3.1.0",
|
||||
|
@ -52,6 +53,7 @@
|
|||
"p-timeout": "^6.1.1",
|
||||
"quick-lru": "^6.1.1",
|
||||
"ts-dedent": "^2.2.0",
|
||||
"uuid": "^9.0.0",
|
||||
"zod": "^3.21.4",
|
||||
"zod-to-ts": "^1.1.4",
|
||||
"zod-validation-error": "^1.3.0"
|
||||
|
@ -59,8 +61,10 @@
|
|||
"devDependencies": {
|
||||
"@keyv/redis": "^2.5.8",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
|
||||
"@types/debug": "^4.1.8",
|
||||
"@types/node": "^20.2.5",
|
||||
"@types/sinon": "^10.0.15",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.8",
|
||||
"@typescript-eslint/parser": "^5.59.8",
|
||||
"ava": "^5.3.0",
|
||||
|
|
|
@ -17,6 +17,9 @@ dependencies:
|
|||
'@inquirer/select':
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0
|
||||
debug:
|
||||
specifier: ^4.3.4
|
||||
version: 4.3.4
|
||||
handlebars:
|
||||
specifier: ^4.7.7
|
||||
version: 4.7.7
|
||||
|
@ -47,6 +50,9 @@ dependencies:
|
|||
ts-dedent:
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
uuid:
|
||||
specifier: ^9.0.0
|
||||
version: 9.0.0
|
||||
zod:
|
||||
specifier: ^3.21.4
|
||||
version: 3.21.4
|
||||
|
@ -64,12 +70,18 @@ devDependencies:
|
|||
'@trivago/prettier-plugin-sort-imports':
|
||||
specifier: ^4.1.1
|
||||
version: 4.1.1(prettier@2.8.8)
|
||||
'@types/debug':
|
||||
specifier: ^4.1.8
|
||||
version: 4.1.8
|
||||
'@types/node':
|
||||
specifier: ^20.2.5
|
||||
version: 20.2.5
|
||||
'@types/sinon':
|
||||
specifier: ^10.0.15
|
||||
version: 10.0.15
|
||||
'@types/uuid':
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^5.59.8
|
||||
version: 5.59.8(@typescript-eslint/parser@5.59.8)(eslint@8.41.0)(typescript@5.0.4)
|
||||
|
@ -715,6 +727,12 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@types/debug@4.1.8:
|
||||
resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==}
|
||||
dependencies:
|
||||
'@types/ms': 0.7.31
|
||||
dev: true
|
||||
|
||||
/@types/json-schema@7.0.12:
|
||||
resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
|
||||
dev: true
|
||||
|
@ -723,6 +741,10 @@ packages:
|
|||
resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
|
||||
dev: true
|
||||
|
||||
/@types/ms@0.7.31:
|
||||
resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==}
|
||||
dev: true
|
||||
|
||||
/@types/node@20.2.5:
|
||||
resolution: {integrity: sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==}
|
||||
dev: true
|
||||
|
@ -749,6 +771,10 @@ packages:
|
|||
resolution: {integrity: sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==}
|
||||
dev: true
|
||||
|
||||
/@types/uuid@9.0.1:
|
||||
resolution: {integrity: sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==}
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/eslint-plugin@5.59.8(@typescript-eslint/parser@5.59.8)(eslint@8.41.0)(typescript@5.0.4):
|
||||
resolution: {integrity: sha512-JDMOmhXteJ4WVKOiHXGCoB96ADWg9q7efPWHRViT/f09bA8XOMLAVHHju3l0MkZnG1izaWXYmgvQcUjTRcpShQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
@ -1409,7 +1435,6 @@ packages:
|
|||
optional: true
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
dev: true
|
||||
|
||||
/decamelize-keys@1.1.1:
|
||||
resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==}
|
||||
|
@ -2762,7 +2787,6 @@ packages:
|
|||
|
||||
/ms@2.1.2:
|
||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
dev: true
|
||||
|
||||
/ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
@ -3927,6 +3951,11 @@ packages:
|
|||
punycode: 2.3.0
|
||||
dev: true
|
||||
|
||||
/uuid@9.0.0:
|
||||
resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/validate-npm-package-license@3.0.4:
|
||||
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
|
||||
dependencies:
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
import logger from 'debug'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
/**
|
||||
* Type of events that can occur within the library.
|
||||
*/
|
||||
export enum EventType {
|
||||
LLM_CALL = 'LLM_CALL',
|
||||
LLM_COMPLETION = 'LLM_COMPLETION'
|
||||
}
|
||||
|
||||
/**
|
||||
* Severity levels of an event.
|
||||
*/
|
||||
export enum EventSeverity {
|
||||
DEBUG,
|
||||
INFO,
|
||||
WARNING,
|
||||
ERROR,
|
||||
CRITICAL
|
||||
}
|
||||
|
||||
/*
|
||||
* Define minimum LOG_LEVEL, defaulting to EventSeverity.INFO if not provided or if an invalid value is provided. Any events below that level won't be logged to the console.
|
||||
*/
|
||||
let LOG_LEVEL: EventSeverity = EventSeverity.INFO
|
||||
if (
|
||||
process.env.DEBUG_LOG_LEVEL &&
|
||||
EventSeverity[process.env.DEBUG_LOG_LEVEL.toUpperCase()] !== undefined
|
||||
) {
|
||||
LOG_LEVEL = EventSeverity[process.env.DEBUG_LOG_LEVEL.toUpperCase()]
|
||||
} else if (process.env.DEBUG_LOG_LEVEL) {
|
||||
throw new Error(`Invalid value for LOG_LEVEL: ${process.env.DEBUG_LOG_LEVEL}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Define loggers for each severity level such that logs can be filtered by severity.
|
||||
*/
|
||||
const LOGGERS: Record<EventSeverity, ReturnType<typeof logger>> = {
|
||||
[EventSeverity.CRITICAL]: logger('agentic:events:critical'),
|
||||
[EventSeverity.ERROR]: logger('agentic:events:error'),
|
||||
[EventSeverity.WARNING]: logger('agentic:events:warning'),
|
||||
[EventSeverity.INFO]: logger('agentic:events:info'),
|
||||
[EventSeverity.DEBUG]: logger('agentic:events:debug')
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload of an event.
|
||||
*/
|
||||
interface EventPayload {
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* Data required to create a new Event object.
|
||||
*/
|
||||
interface EventData {
|
||||
parentId?: string
|
||||
id?: string
|
||||
timestamp?: Date
|
||||
payload?: EventPayload
|
||||
severity?: EventSeverity
|
||||
version?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Events that occur within the library (should be treated as immutable).
|
||||
*/
|
||||
export class Event {
|
||||
public readonly type: EventType
|
||||
public readonly parentId?: string
|
||||
public readonly id: string
|
||||
public readonly timestamp: Date
|
||||
public readonly payload?: EventPayload
|
||||
public readonly severity?: EventSeverity
|
||||
public readonly version: number
|
||||
|
||||
constructor(type: EventType, data: EventData = {}) {
|
||||
this.type = type
|
||||
this.parentId = data.parentId ?? null
|
||||
this.id = data.id ?? uuidv4()
|
||||
this.timestamp = data.timestamp ?? new Date()
|
||||
this.payload = data.payload ? { ...data.payload } : {} // Only doing a shallow instead of a deep copy for performance reasons..
|
||||
this.severity = data.severity ?? EventSeverity.INFO
|
||||
this.version = data.version ?? 1 // Default to version 1 if not provided...
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a JSON string representation of an event back into an Event object.
|
||||
*/
|
||||
static fromJSON(json: string): Event {
|
||||
const { type, ...data } = JSON.parse(json)
|
||||
|
||||
// Convert the timestamp back into a Date object, since `JSON.parse()` will have turned it into a string:
|
||||
data.timestamp = new Date(data.timestamp)
|
||||
const event = new Event(type, data)
|
||||
return event
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the event to a JSON string representation.
|
||||
*
|
||||
* @returns JSON representation
|
||||
*/
|
||||
toJSON(): string {
|
||||
return JSON.stringify({
|
||||
type: this.type,
|
||||
parentId: this.parentId,
|
||||
id: this.id,
|
||||
timestamp: this.timestamp.toISOString(),
|
||||
payload: this.payload,
|
||||
severity: this.severity,
|
||||
version: this.version
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the event to a human-readable string representation suitable for logging.
|
||||
*
|
||||
* @returns string representation
|
||||
*/
|
||||
toString(): string {
|
||||
return `Event { type: ${this.type}, parentId: ${this.parentId}, id: ${
|
||||
this.id
|
||||
}, timestamp: ${this.timestamp.toISOString()}, payload: ${JSON.stringify(
|
||||
this.payload
|
||||
)}, severity: ${this.severity} }`
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the event to the console.
|
||||
*/
|
||||
log(): void {
|
||||
if (this.severity >= LOG_LEVEL) {
|
||||
const logger = LOGGERS[this.severity]
|
||||
logger(this.toString())
|
||||
}
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue