@lupaflow/plugins 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/plugins",
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/core": "workspace:*",
25
+ "@lupaflow/types": "workspace:*"
26
+ },
27
+ "devDependencies": {
28
+ "tsup": "^8.3.0",
29
+ "typescript": "^5.6.0"
30
+ }
31
+ }
package/src/hooks.ts ADDED
@@ -0,0 +1,61 @@
1
+ import { pluginManager } from "./loader"
2
+
3
+ export function runBeforeAgentRunHooks(config: Record<string, unknown>): Record<string, unknown> {
4
+ let result = { ...config }
5
+ for (const plugin of pluginManager.list()) {
6
+ if (plugin.hooks?.beforeAgentRun) {
7
+ result = plugin.hooks.beforeAgentRun(result)
8
+ }
9
+ }
10
+ return result
11
+ }
12
+
13
+ export function runAfterAgentRunHooks(result: unknown): unknown {
14
+ let output = result
15
+ for (const plugin of pluginManager.list()) {
16
+ if (plugin.hooks?.afterAgentRun) {
17
+ output = plugin.hooks.afterAgentRun(output)
18
+ }
19
+ }
20
+ return output
21
+ }
22
+
23
+ export function runBeforeToolCallHooks(tool: string, args: Record<string, unknown>): Record<string, unknown> {
24
+ let result = { ...args }
25
+ for (const plugin of pluginManager.list()) {
26
+ if (plugin.hooks?.beforeToolCall) {
27
+ result = plugin.hooks.beforeToolCall(tool, result)
28
+ }
29
+ }
30
+ return result
31
+ }
32
+
33
+ export function runAfterToolCallHooks(result: unknown): unknown {
34
+ let output = result
35
+ for (const plugin of pluginManager.list()) {
36
+ if (plugin.hooks?.afterToolCall) {
37
+ output = plugin.hooks.afterToolCall(output)
38
+ }
39
+ }
40
+ return output
41
+ }
42
+
43
+ export function runBeforeProviderCallHooks(provider: string, request: Record<string, unknown>): Record<string, unknown> {
44
+ let result = { ...request }
45
+ for (const plugin of pluginManager.list()) {
46
+ if (plugin.hooks?.beforeProviderCall) {
47
+ result = plugin.hooks.beforeProviderCall(provider, result)
48
+ }
49
+ }
50
+ return result
51
+ }
52
+
53
+ export function runAfterProviderCallHooks(response: Record<string, unknown>): Record<string, unknown> {
54
+ let result = { ...response }
55
+ for (const plugin of pluginManager.list()) {
56
+ if (plugin.hooks?.afterProviderCall) {
57
+ result = plugin.hooks.afterProviderCall(result)
58
+ }
59
+ }
60
+ return result
61
+ }
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ export { pluginManager } from "./loader"
2
+ export type { LupaPlugin } from "./interface"
3
+ export {
4
+ runBeforeAgentRunHooks,
5
+ runAfterAgentRunHooks,
6
+ runBeforeToolCallHooks,
7
+ runAfterToolCallHooks,
8
+ runBeforeProviderCallHooks,
9
+ runAfterProviderCallHooks,
10
+ } from "./hooks"
@@ -0,0 +1,18 @@
1
+ import type { LupaEvent } from "@lupaflow/types"
2
+
3
+ export interface LupaPlugin {
4
+ name: string
5
+ version: string
6
+ description?: string
7
+ onLoad?: () => void | Promise<void>
8
+ onUnload?: () => void | Promise<void>
9
+ onEvent?: (event: LupaEvent) => void | Promise<void>
10
+ hooks?: {
11
+ beforeAgentRun?: (config: Record<string, unknown>) => Record<string, unknown>
12
+ afterAgentRun?: (result: unknown) => unknown
13
+ beforeToolCall?: (tool: string, args: Record<string, unknown>) => Record<string, unknown>
14
+ afterToolCall?: (result: unknown) => unknown
15
+ beforeProviderCall?: (provider: string, request: Record<string, unknown>) => Record<string, unknown>
16
+ afterProviderCall?: (response: Record<string, unknown>) => Record<string, unknown>
17
+ }
18
+ }
package/src/loader.ts ADDED
@@ -0,0 +1,67 @@
1
+ import { readdir } from "fs/promises"
2
+ import { join } from "path"
3
+ import type { LupaPlugin } from "./interface"
4
+ import { globalEventBus } from "@lupaflow/core"
5
+
6
+ class PluginManager {
7
+ private plugins: Map<string, LupaPlugin> = new Map()
8
+ private loaded = false
9
+
10
+ async load(plugin: LupaPlugin): Promise<void> {
11
+ if (this.plugins.has(plugin.name)) {
12
+ throw new Error(`Plugin "${plugin.name}" is already loaded`)
13
+ }
14
+ this.plugins.set(plugin.name, plugin)
15
+
16
+ if (plugin.onEvent) {
17
+ globalEventBus.onAny((event) => plugin.onEvent!(event))
18
+ }
19
+
20
+ if (plugin.onLoad) {
21
+ await plugin.onLoad()
22
+ }
23
+ }
24
+
25
+ async unload(name: string): Promise<void> {
26
+ const plugin = this.plugins.get(name)
27
+ if (!plugin) throw new Error(`Plugin "${name}" not found`)
28
+ if (plugin.onUnload) await plugin.onUnload()
29
+ this.plugins.delete(name)
30
+ }
31
+
32
+ async loadFromDirectory(dir: string): Promise<void> {
33
+ try {
34
+ const files = await readdir(dir)
35
+ for (const file of files) {
36
+ if (file.endsWith(".js") || file.endsWith(".mjs")) {
37
+ try {
38
+ const mod = await import(join(dir, file))
39
+ if (mod.default && mod.default.name) {
40
+ await this.load(mod.default)
41
+ }
42
+ } catch { /* ignore */ }
43
+ }
44
+ }
45
+ } catch { /* ignore */ }
46
+ }
47
+
48
+ get(name: string): LupaPlugin | undefined {
49
+ return this.plugins.get(name)
50
+ }
51
+
52
+ list(): LupaPlugin[] {
53
+ return Array.from(this.plugins.values())
54
+ }
55
+
56
+ isLoaded(name: string): boolean {
57
+ return this.plugins.has(name)
58
+ }
59
+
60
+ async unloadAll(): Promise<void> {
61
+ for (const [name] of this.plugins) {
62
+ await this.unload(name)
63
+ }
64
+ }
65
+ }
66
+
67
+ export const pluginManager = new PluginManager()
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
+ })