@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 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
@@ -0,0 +1,3 @@
1
+ export { EventBus, globalEventBus } from "./events"
2
+ export { LupaError, ProviderError, ToolError, MemoryError, ConfigError, WorkflowError, RetryError } from "./errors"
3
+ export { generateId, delay, truncate, estimateTokens, deepMerge, chunkArray } from "./utils"
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
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src"]
8
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from "tsup"
2
+ export default defineConfig({
3
+ entry: { index: "src/index.ts" },
4
+ format: ["cjs", "esm"],
5
+ dts: true,
6
+ sourcemap: true,
7
+ clean: true,
8
+ external: [/node_modules/],
9
+ })