@lupaflow/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +31 -0
- package/src/errors.ts +67 -0
- package/src/events.ts +64 -0
- package/src/index.ts +3 -0
- package/src/utils.ts +47 -0
- package/tsconfig.json +8 -0
- package/tsup.config.ts +9 -0
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lupaflow/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"require": "./dist/index.js",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup",
|
|
21
|
+
"dev": "tsup --watch"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@lupaflow/types": "workspace:*",
|
|
25
|
+
"ulid": "^2.3.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"tsup": "^8.3.0",
|
|
29
|
+
"typescript": "^5.6.0"
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export class LupaError extends Error {
|
|
2
|
+
public code: string
|
|
3
|
+
public details?: Record<string, unknown>
|
|
4
|
+
|
|
5
|
+
constructor(message: string, code: string, details?: Record<string, unknown>) {
|
|
6
|
+
super(message)
|
|
7
|
+
this.name = "LupaError"
|
|
8
|
+
this.code = code
|
|
9
|
+
this.details = details
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class ProviderError extends LupaError {
|
|
14
|
+
public provider: string
|
|
15
|
+
|
|
16
|
+
constructor(provider: string, message: string, details?: Record<string, unknown>) {
|
|
17
|
+
super(`[${provider}] ${message}`, "PROVIDER_ERROR", details)
|
|
18
|
+
this.name = "ProviderError"
|
|
19
|
+
this.provider = provider
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class ToolError extends LupaError {
|
|
24
|
+
public tool: string
|
|
25
|
+
|
|
26
|
+
constructor(tool: string, message: string, details?: Record<string, unknown>) {
|
|
27
|
+
super(`[${tool}] ${message}`, "TOOL_ERROR", details)
|
|
28
|
+
this.name = "ToolError"
|
|
29
|
+
this.tool = tool
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class MemoryError extends LupaError {
|
|
34
|
+
constructor(message: string, details?: Record<string, unknown>) {
|
|
35
|
+
super(message, "MEMORY_ERROR", details)
|
|
36
|
+
this.name = "MemoryError"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class ConfigError extends LupaError {
|
|
41
|
+
constructor(message: string, details?: Record<string, unknown>) {
|
|
42
|
+
super(message, "CONFIG_ERROR", details)
|
|
43
|
+
this.name = "ConfigError"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class WorkflowError extends LupaError {
|
|
48
|
+
public stepId?: string
|
|
49
|
+
|
|
50
|
+
constructor(message: string, stepId?: string, details?: Record<string, unknown>) {
|
|
51
|
+
super(message, "WORKFLOW_ERROR", { stepId, ...details })
|
|
52
|
+
this.name = "WorkflowError"
|
|
53
|
+
this.stepId = stepId
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class RetryError extends LupaError {
|
|
58
|
+
public attempts: number
|
|
59
|
+
public lastError: Error
|
|
60
|
+
|
|
61
|
+
constructor(message: string, attempts: number, lastError: Error) {
|
|
62
|
+
super(message, "RETRY_ERROR", { attempts, lastError: lastError.message })
|
|
63
|
+
this.name = "RetryError"
|
|
64
|
+
this.attempts = attempts
|
|
65
|
+
this.lastError = lastError
|
|
66
|
+
}
|
|
67
|
+
}
|
package/src/events.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ulid } from "ulid"
|
|
2
|
+
import type { LupaEvent } from "@lupaflow/types"
|
|
3
|
+
|
|
4
|
+
type EventHandler = (event: LupaEvent) => void | Promise<void>
|
|
5
|
+
|
|
6
|
+
export class EventBus {
|
|
7
|
+
private handlers: Map<string, Set<EventHandler>> = new Map()
|
|
8
|
+
private wildcardHandlers: Set<EventHandler> = new Set()
|
|
9
|
+
private history: LupaEvent[] = []
|
|
10
|
+
private maxHistory: number = 1000
|
|
11
|
+
|
|
12
|
+
on(name: string, handler: EventHandler): () => void {
|
|
13
|
+
if (!this.handlers.has(name)) {
|
|
14
|
+
this.handlers.set(name, new Set())
|
|
15
|
+
}
|
|
16
|
+
this.handlers.get(name)!.add(handler)
|
|
17
|
+
return () => this.handlers.get(name)?.delete(handler)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
onAny(handler: EventHandler): () => void {
|
|
21
|
+
this.wildcardHandlers.add(handler)
|
|
22
|
+
return () => this.wildcardHandlers.delete(handler)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async emit(name: string, data: Partial<LupaEvent>): Promise<void> {
|
|
26
|
+
const event: LupaEvent = {
|
|
27
|
+
id: ulid(),
|
|
28
|
+
name,
|
|
29
|
+
timestamp: Date.now(),
|
|
30
|
+
...data,
|
|
31
|
+
} as LupaEvent
|
|
32
|
+
|
|
33
|
+
this.history.push(event)
|
|
34
|
+
if (this.history.length > this.maxHistory) {
|
|
35
|
+
this.history.shift()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const handlers = this.handlers.get(name)
|
|
39
|
+
if (handlers) {
|
|
40
|
+
for (const handler of handlers) {
|
|
41
|
+
await handler(event)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for (const handler of this.wildcardHandlers) {
|
|
46
|
+
await handler(event)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
getHistory(): LupaEvent[] {
|
|
51
|
+
return [...this.history]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
clearHistory(): void {
|
|
55
|
+
this.history = []
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
removeAllListeners(): void {
|
|
59
|
+
this.handlers.clear()
|
|
60
|
+
this.wildcardHandlers.clear()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const globalEventBus = new EventBus()
|
package/src/index.ts
ADDED
package/src/utils.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ulid } from "ulid"
|
|
2
|
+
|
|
3
|
+
export function generateId(): string {
|
|
4
|
+
return ulid()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function delay(ms: number): Promise<void> {
|
|
8
|
+
return new Promise((resolve) => setTimeout(resolve, ms))
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function truncate(str: string, maxLength: number): string {
|
|
12
|
+
if (str.length <= maxLength) return str
|
|
13
|
+
return str.slice(0, maxLength - 3) + "..."
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function estimateTokens(text: string | null | undefined): number {
|
|
17
|
+
return Math.ceil((text || "").length / 4)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function deepMerge<T extends Record<string, unknown>, S extends Record<string, unknown>>(target: T, source: S): T & S {
|
|
21
|
+
const result = { ...target } as Record<string, unknown>
|
|
22
|
+
for (const key of Object.keys(source)) {
|
|
23
|
+
const sourceVal = (source as Record<string, unknown>)[key]
|
|
24
|
+
const targetVal = result[key]
|
|
25
|
+
if (
|
|
26
|
+
sourceVal &&
|
|
27
|
+
targetVal &&
|
|
28
|
+
typeof sourceVal === "object" &&
|
|
29
|
+
!Array.isArray(sourceVal) &&
|
|
30
|
+
typeof targetVal === "object" &&
|
|
31
|
+
!Array.isArray(targetVal)
|
|
32
|
+
) {
|
|
33
|
+
result[key] = deepMerge(targetVal as Record<string, unknown>, sourceVal as Record<string, unknown>)
|
|
34
|
+
} else if (sourceVal !== undefined) {
|
|
35
|
+
result[key] = sourceVal
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return result as T & S
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function chunkArray<T>(arr: T[], size: number): T[][] {
|
|
42
|
+
const chunks: T[][] = []
|
|
43
|
+
for (let i = 0; i < arr.length; i += size) {
|
|
44
|
+
chunks.push(arr.slice(i, i + size))
|
|
45
|
+
}
|
|
46
|
+
return chunks
|
|
47
|
+
}
|
package/tsconfig.json
ADDED