From c7221fef8c90dbe006afb55d9e8aae60ae57fb22 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 23 Jun 2025 20:28:19 +0800 Subject: [PATCH 1/8] refactor: revisit athena plugin system --- package.json | 3 +- packages/core/package.json | 14 + packages/core/src/index.ts | 78 ++++ packages/core/src/plugin.ts | 66 +++ packages/core/test/basic.test.ts | 24 ++ packages/core/tsconfig.json | 16 + pnpm-lock.yaml | 681 +++++++++++++++++++++++++++++++ pnpm-workspace.yaml | 2 + 8 files changed, 883 insertions(+), 1 deletion(-) create mode 100644 packages/core/package.json create mode 100644 packages/core/src/index.ts create mode 100644 packages/core/src/plugin.ts create mode 100644 packages/core/test/basic.test.ts create mode 100644 packages/core/tsconfig.json create mode 100644 pnpm-workspace.yaml diff --git a/package.json b/package.json index a5c1e1a..82a5a2c 100644 --- a/package.json +++ b/package.json @@ -65,5 +65,6 @@ "prettier": "^3.5.3", "tsx": "^4.19.3", "typescript": "^5.8.3" - } + }, + "packageManager": "pnpm@10.12.2" } diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 0000000..e583b9f --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,14 @@ +{ + "name": "@athena/core", + "scripts": {}, + "repository": { + "type": "git", + "url": "https://github.com/Athena-AI-Lab/athena-core.git" + }, + "dependencies": { + "@llama-flow/core": "^0.4.4" + }, + "devDependencies": { + "vitest": "^3.2.4" + } +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts new file mode 100644 index 0000000..6851abb --- /dev/null +++ b/packages/core/src/index.ts @@ -0,0 +1,78 @@ +import { + createWorkflow, workflowEvent +} from '@llama-flow/core' +import { + pluginRegisterEvent, + workflowAsyncContext, + Plugin, + PluginState, pluginUnregisterEvent +} from './plugin.js' + +export type AthenaConfig = { + add (plugin: Plugin): AthenaConfig; + run (): Athena +} + +export type Athena = { + get plugins (): ReadonlySet + stop (): Promise +} + +const haltEvent = workflowEvent() + +export function createAthena (): AthenaConfig { + const coreWorkflow = createWorkflow() + const pluginSet = new Set() + const pluginStateMap = new WeakMap() + coreWorkflow.handle([pluginRegisterEvent], (pluginRegister) => { + pluginSet.values().every((plugin) => { + const pluginState = pluginStateMap.get(plugin)! + const pluginWorkflow = pluginState.workflow + const { sendEvent } = pluginWorkflow.createContext() + sendEvent(pluginRegister) + }) + return haltEvent.with() + }) + coreWorkflow.handle([pluginUnregisterEvent], (pluginUnregister) => { + pluginSet.values().every((plugin) => { + const pluginState = pluginStateMap.get(plugin)! + const pluginWorkflow = pluginState.workflow + const { sendEvent } = pluginWorkflow.createContext() + sendEvent(pluginUnregister) + }) + return haltEvent.with() + }) + + const config: AthenaConfig = { + add: (plugin: Plugin) => { + pluginSet.add(plugin) + const pluginWorkflow = createWorkflow() + const pluginState: PluginState = { + description: null!, + workflow: pluginWorkflow + } + workflowAsyncContext.run(pluginState, () => plugin.setup()) + pluginStateMap.set(plugin, pluginState) + return config + }, + run: () => { + const { sendEvent, stream: registerStream } = coreWorkflow.createContext() + sendEvent(pluginRegisterEvent.with()) + return { + get plugins (): ReadonlySet { + return new Set(pluginSet) + }, + async stop (): Promise { + await registerStream.until(haltEvent).toArray() + const { + sendEvent, + stream: unregisterStream + } = coreWorkflow.createContext() + sendEvent(pluginUnregisterEvent.with()) + await unregisterStream.until(haltEvent).toArray() + } + } + } + } + return config +} \ No newline at end of file diff --git a/packages/core/src/plugin.ts b/packages/core/src/plugin.ts new file mode 100644 index 0000000..8360aa6 --- /dev/null +++ b/packages/core/src/plugin.ts @@ -0,0 +1,66 @@ +import { + InferWorkflowEventData, + Workflow, + workflowEvent, + WorkflowEventData +} from '@llama-flow/core' +import { AsyncLocalStorage } from 'node:async_hooks' + +export type Plugin = { + setup (): void +} + +/** + * @internal + */ +export type PluginState = { + description: string + workflow: Workflow +} + +/** + * @internal + */ +function usePluginState () { + const workflow = workflowAsyncContext.getStore() + if (!workflow) { + throw new Error('No workflow is available in the current context') + } + return workflow +} + +/** + * @internal + */ +export const workflowAsyncContext = new AsyncLocalStorage() + +/** + * @internal + */ +export const pluginRegisterEvent = workflowEvent() + +/** + * @internal + */ +export const pluginUnregisterEvent = workflowEvent() + +export function useDescription ( + description: string +) { + const pluginState = usePluginState() + pluginState.description = description +} + +export function onRegister ( + handler: (pluginRegister: WorkflowEventData>) => ReturnType +) { + const { workflow } = usePluginState() + workflow.handle([pluginRegisterEvent], handler) +} + +export function onUnregister ( + handler: (pluginUnregister: WorkflowEventData>) => void +) { + const { workflow } = usePluginState() + workflow.handle([pluginUnregisterEvent], handler) +} \ No newline at end of file diff --git a/packages/core/test/basic.test.ts b/packages/core/test/basic.test.ts new file mode 100644 index 0000000..023d694 --- /dev/null +++ b/packages/core/test/basic.test.ts @@ -0,0 +1,24 @@ +import { expect, test, vi } from 'vitest' +import { createAthena } from '../src/index.js' +import { + onRegister, + onUnregister, + Plugin, + useDescription +} from '../src/plugin.js' + +test('should able to setup athena', async () => { + const registerHandler = vi.fn() + const unregisterHandler = vi.fn() + const noopPlugin: Plugin = { + setup () { + useDescription('this plugin does nothing') + onRegister(registerHandler) + onUnregister(unregisterHandler) + } + } + const athena = createAthena().add(noopPlugin).run() + expect(registerHandler).toHaveBeenCalledOnce() + await athena.stop() + expect(unregisterHandler).toHaveBeenCalledOnce() +}) diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json new file mode 100644 index 0000000..c26dc40 --- /dev/null +++ b/packages/core/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "rootDir": ".", + "target": "esnext", + "module": "esnext", + "moduleResolution": "node16", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + }, + "include": [ + "./src", + "./test" + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 600133f..2295aab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -112,6 +112,16 @@ importers: specifier: ^5.8.3 version: 5.8.3 + packages/core: + dependencies: + '@llama-flow/core': + specifier: ^0.4.4 + version: 0.4.4(zod@3.24.2) + devDependencies: + vitest: + specifier: ^3.2.4 + version: 3.2.4(@types/node@22.14.1)(jsdom@26.1.0)(tsx@4.19.3)(yaml@2.7.1) + packages: '@alcalzone/ansi-tokenize@0.1.3': @@ -338,6 +348,32 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@llama-flow/core@0.4.4': + resolution: {integrity: sha512-hwK1EQ+atUG/E7XcDV3KsTaA8op29pb8gbpVurpsqbLnGFkdTT4F/6V7Hy1cC2o/yOY+DKc/rxoIsH1uJS0cZg==} + peerDependencies: + '@modelcontextprotocol/sdk': ^1.7.0 + hono: ^4.7.4 + next: ^15.2.2 + p-retry: ^6.2.1 + rxjs: ^7.8.2 + zod: ^3.24.2 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + hono: + optional: true + next: + optional: true + p-retry: + optional: true + rxjs: + optional: true + zod: + optional: true + '@napi-rs/nice-android-arm-eabi@1.0.1': resolution: {integrity: sha512-5qpvOu5IGwDo7MEKVqqyAxF90I6aLj4n07OzpARdgDRfz8UbBztTByBp0RC59r3J1Ij8uzYi6jI7r5Lws7nn6w==} engines: {node: '>= 10'} @@ -450,6 +486,106 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@rollup/rollup-android-arm-eabi@4.44.0': + resolution: {integrity: sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.44.0': + resolution: {integrity: sha512-uNSk/TgvMbskcHxXYHzqwiyBlJ/lGcv8DaUfcnNwict8ba9GTTNxfn3/FAoFZYgkaXXAdrAA+SLyKplyi349Jw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.44.0': + resolution: {integrity: sha512-VGF3wy0Eq1gcEIkSCr8Ke03CWT+Pm2yveKLaDvq51pPpZza3JX/ClxXOCmTYYq3us5MvEuNRTaeyFThCKRQhOA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.44.0': + resolution: {integrity: sha512-fBkyrDhwquRvrTxSGH/qqt3/T0w5Rg0L7ZIDypvBPc1/gzjJle6acCpZ36blwuwcKD/u6oCE/sRWlUAcxLWQbQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.44.0': + resolution: {integrity: sha512-u5AZzdQJYJXByB8giQ+r4VyfZP+walV+xHWdaFx/1VxsOn6eWJhK2Vl2eElvDJFKQBo/hcYIBg/jaKS8ZmKeNQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.44.0': + resolution: {integrity: sha512-qC0kS48c/s3EtdArkimctY7h3nHicQeEUdjJzYVJYR3ct3kWSafmn6jkNCA8InbUdge6PVx6keqjk5lVGJf99g==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.44.0': + resolution: {integrity: sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.44.0': + resolution: {integrity: sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.44.0': + resolution: {integrity: sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.44.0': + resolution: {integrity: sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.44.0': + resolution: {integrity: sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.44.0': + resolution: {integrity: sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.44.0': + resolution: {integrity: sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.44.0': + resolution: {integrity: sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.44.0': + resolution: {integrity: sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.44.0': + resolution: {integrity: sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.44.0': + resolution: {integrity: sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.44.0': + resolution: {integrity: sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.44.0': + resolution: {integrity: sha512-3XJ0NQtMAXTWFW8FqZKcw3gOQwBtVWP/u8TpHP3CRPXD7Pd6s8lLdH3sHWh8vqKCyyiI8xW5ltJScQmBU9j7WA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.44.0': + resolution: {integrity: sha512-Q2Mgwt+D8hd5FIPUuPDsvPR7Bguza6yTkJxspDGkZj7tBRn2y4KSWYuIXpftFSjBra76TbKerCV7rgFPQrn+wQ==} + cpu: [x64] + os: [win32] + '@sapphire/async-queue@1.5.5': resolution: {integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==} engines: {node: '>=v14.0.0', npm: '>=7.0.0'} @@ -590,6 +726,15 @@ packages: '@types/caseless@0.12.5': resolution: {integrity: sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==} + '@types/chai@5.2.2': + resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/follow-redirects@1.14.4': resolution: {integrity: sha512-GWXfsD0Jc1RWiFmMuMFCpXMzi9L7oPDVwxUnZdg89kDNnqsRfUKXEtUYtA98A6lig1WXH/CYY/fvPW9HuN5fTA==} @@ -638,6 +783,35 @@ packages: '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + + '@vitest/runner@3.2.4': + resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + + '@vitest/snapshot@3.2.4': + resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} + + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + '@vladfrangu/async_event_emitter@2.4.6': resolution: {integrity: sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==} engines: {node: '>=v14.0.0', npm: '>=7.0.0'} @@ -742,6 +916,10 @@ packages: resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} engines: {node: '>=0.8'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} @@ -812,6 +990,10 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + cacheable-lookup@7.0.0: resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} engines: {node: '>=14.16'} @@ -835,10 +1017,18 @@ packages: caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} + chalk@5.4.1: resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + cli-boxes@3.0.0: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} @@ -955,6 +1145,15 @@ packages: supports-color: optional: true + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decimal.js@10.5.0: resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} @@ -962,6 +1161,10 @@ packages: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} @@ -1055,6 +1258,9 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -1083,6 +1289,9 @@ packages: resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} engines: {node: '>=8'} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -1094,6 +1303,10 @@ packages: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} + expect-type@1.2.1: + resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} + engines: {node: '>=12.0.0'} + ext-list@2.2.2: resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==} engines: {node: '>=0.10.0'} @@ -1125,6 +1338,14 @@ packages: fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + fdir@6.4.6: + resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + fecha@4.2.3: resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} @@ -1539,6 +1760,9 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} @@ -1598,6 +1822,9 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + loupe@3.1.4: + resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==} + lowercase-keys@3.0.0: resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1612,6 +1839,9 @@ packages: magic-bytes.js@1.11.0: resolution: {integrity: sha512-nVmadqN9gam80tdnn74qjFCKgldwzv1+96XmeCvR3bY7wNn2PjHMnRakOWC6+32g133vgZOjUiYgswIxohffzA==} + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} @@ -1675,6 +1905,11 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -1774,6 +2009,13 @@ packages: resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} engines: {node: 20 || >=22} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + peberminta@0.9.0: resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} @@ -1787,10 +2029,17 @@ packages: performance-now@2.1.0: resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + piscina@4.9.2: resolution: {integrity: sha512-Fq0FERJWFEUpB4eSY59wSNwXD4RYqR+nR/WiEVcZW8IWfVBxJJafcgTEZDQo8k3w0sUarJ8RyVbbUF4GQ2LGbQ==} @@ -1808,6 +2057,10 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + prettier@3.5.3: resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} engines: {node: '>=14'} @@ -1911,6 +2164,11 @@ packages: engines: {node: 20 || >=22} hasBin: true + rollup@4.44.0: + resolution: {integrity: sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} @@ -2005,6 +2263,9 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -2035,6 +2296,10 @@ packages: resolution: {integrity: sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==} engines: {node: '>=0.10.0'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + source-map@0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} @@ -2079,6 +2344,12 @@ packages: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.9.0: + resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + stealthy-require@1.1.1: resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==} engines: {node: '>=0.10.0'} @@ -2131,6 +2402,9 @@ packages: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} + strip-literal@3.0.0: + resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} + strtok3@9.1.1: resolution: {integrity: sha512-FhwotcEqjr241ZbjFzjlIYg6c5/L/s4yBGWSMvJ9UoExiSqL+FnFA/CaeZx17WGaZMS/4SOZp8wH18jSS4R4lw==} engines: {node: '>=16'} @@ -2154,6 +2428,28 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@4.0.3: + resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} + engines: {node: '>=14.0.0'} + tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} @@ -2270,6 +2566,79 @@ packages: resolution: {integrity: sha512-gjb0ARm9qlcBAonU4zPwkl9ecKkas+tC2CGwFfptTCWWIVTWY1YUbT2zZKsOAF1jR/tNxxyLwwG0cb42XlYcTg==} engines: {node: '>=4'} + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@6.3.5: + resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@3.2.4: + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -2325,6 +2694,11 @@ packages: engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + widest-line@5.0.0: resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} engines: {node: '>=18'} @@ -2560,6 +2934,12 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@llama-flow/core@0.4.4(zod@3.24.2)': + optionalDependencies: + zod: 3.24.2 + '@napi-rs/nice-android-arm-eabi@1.0.1': optional: true @@ -2640,6 +3020,66 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 + '@rollup/rollup-android-arm-eabi@4.44.0': + optional: true + + '@rollup/rollup-android-arm64@4.44.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.44.0': + optional: true + + '@rollup/rollup-darwin-x64@4.44.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.44.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.44.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.44.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.44.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.44.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.44.0': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.44.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.44.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.44.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.44.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.44.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.44.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.44.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.44.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.44.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.44.0': + optional: true + '@sapphire/async-queue@1.5.5': {} '@sapphire/shapeshift@4.0.0': @@ -2773,6 +3213,14 @@ snapshots: '@types/caseless@0.12.5': {} + '@types/chai@5.2.2': + dependencies: + '@types/deep-eql': 4.0.2 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.8': {} + '@types/follow-redirects@1.14.4': dependencies: '@types/node': 22.14.1 @@ -2831,6 +3279,48 @@ snapshots: dependencies: '@types/node': 22.14.1 + '@vitest/expect@3.2.4': + dependencies: + '@types/chai': 5.2.2 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.2.0 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.14.1)(tsx@4.19.3)(yaml@2.7.1))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 6.3.5(@types/node@22.14.1)(tsx@4.19.3)(yaml@2.7.1) + + '@vitest/pretty-format@3.2.4': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.2.4': + dependencies: + '@vitest/utils': 3.2.4 + pathe: 2.0.3 + strip-literal: 3.0.0 + + '@vitest/snapshot@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + magic-string: 0.30.17 + pathe: 2.0.3 + + '@vitest/spy@3.2.4': + dependencies: + tinyspy: 4.0.3 + + '@vitest/utils@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + loupe: 3.1.4 + tinyrainbow: 2.0.0 + '@vladfrangu/async_event_emitter@2.4.6': {} '@xhmikosr/archive-type@7.0.0': @@ -2968,6 +3458,8 @@ snapshots: assert-plus@1.0.0: {} + assertion-error@2.0.1: {} + async-function@1.0.0: {} async@3.2.6: {} @@ -3034,6 +3526,8 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + cac@6.7.14: {} + cacheable-lookup@7.0.0: {} cacheable-request@10.2.14: @@ -3065,8 +3559,18 @@ snapshots: caseless@0.12.0: {} + chai@5.2.0: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.4 + pathval: 2.0.0 + chalk@5.4.1: {} + check-error@2.1.1: {} + cli-boxes@3.0.0: {} cli-cursor@4.0.0: @@ -3177,12 +3681,18 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.1: + dependencies: + ms: 2.1.3 + decimal.js@10.5.0: {} decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 + deep-eql@5.0.2: {} + deepmerge@4.3.1: {} defaults@3.0.0: {} @@ -3332,6 +3842,8 @@ snapshots: es-errors@1.3.0: {} + es-module-lexer@1.7.0: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -3385,6 +3897,10 @@ snapshots: escape-string-regexp@2.0.0: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + event-target-shim@5.0.1: {} eventemitter3@3.1.2: {} @@ -3401,6 +3917,8 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + expect-type@1.2.1: {} + ext-list@2.2.2: dependencies: mime-db: 1.54.0 @@ -3432,6 +3950,10 @@ snapshots: dependencies: reusify: 1.1.0 + fdir@6.4.6(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + fecha@4.2.3: {} fetch-blob@3.2.0: @@ -3886,6 +4408,8 @@ snapshots: js-tokens@4.0.0: {} + js-tokens@9.0.1: {} + jsbn@0.1.1: {} jsdom@26.1.0: @@ -3959,6 +4483,8 @@ snapshots: dependencies: js-tokens: 4.0.0 + loupe@3.1.4: {} + lowercase-keys@3.0.0: {} lru-cache@10.4.3: {} @@ -3969,6 +4495,10 @@ snapshots: dependencies: rimraf: 6.0.1 + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + make-dir@4.0.0: dependencies: semver: 7.7.1 @@ -4012,6 +4542,8 @@ snapshots: ms@2.1.3: {} + nanoid@3.3.11: {} + node-domexception@1.0.0: {} node-fetch@2.7.0: @@ -4116,6 +4648,10 @@ snapshots: lru-cache: 11.1.0 minipass: 7.1.2 + pathe@2.0.3: {} + + pathval@2.0.0: {} + peberminta@0.9.0: {} peek-readable@5.4.2: {} @@ -4124,8 +4660,12 @@ snapshots: performance-now@2.1.0: {} + picocolors@1.1.1: {} + picomatch@2.3.1: {} + picomatch@4.0.2: {} + piscina@4.9.2: optionalDependencies: '@napi-rs/nice': 1.0.1 @@ -4140,6 +4680,12 @@ snapshots: possible-typed-array-names@1.1.0: {} + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + prettier@3.5.3: {} process-nextick-args@2.0.1: {} @@ -4269,6 +4815,32 @@ snapshots: glob: 11.0.1 package-json-from-dist: 1.0.1 + rollup@4.44.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.44.0 + '@rollup/rollup-android-arm64': 4.44.0 + '@rollup/rollup-darwin-arm64': 4.44.0 + '@rollup/rollup-darwin-x64': 4.44.0 + '@rollup/rollup-freebsd-arm64': 4.44.0 + '@rollup/rollup-freebsd-x64': 4.44.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.44.0 + '@rollup/rollup-linux-arm-musleabihf': 4.44.0 + '@rollup/rollup-linux-arm64-gnu': 4.44.0 + '@rollup/rollup-linux-arm64-musl': 4.44.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.44.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.44.0 + '@rollup/rollup-linux-riscv64-gnu': 4.44.0 + '@rollup/rollup-linux-riscv64-musl': 4.44.0 + '@rollup/rollup-linux-s390x-gnu': 4.44.0 + '@rollup/rollup-linux-x64-gnu': 4.44.0 + '@rollup/rollup-linux-x64-musl': 4.44.0 + '@rollup/rollup-win32-arm64-msvc': 4.44.0 + '@rollup/rollup-win32-ia32-msvc': 4.44.0 + '@rollup/rollup-win32-x64-msvc': 4.44.0 + fsevents: 2.3.3 + rrweb-cssom@0.8.0: {} run-parallel@1.2.0: @@ -4382,6 +4954,8 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} + signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -4410,6 +4984,8 @@ snapshots: dependencies: is-plain-obj: 1.1.0 + source-map-js@1.2.1: {} + source-map@0.7.4: {} sqlite-vec-darwin-arm64@0.1.7-alpha.2: @@ -4453,6 +5029,10 @@ snapshots: dependencies: escape-string-regexp: 2.0.0 + stackback@0.0.2: {} + + std-env@3.9.0: {} + stealthy-require@1.1.1: {} streamx@2.22.0: @@ -4526,6 +5106,10 @@ snapshots: strip-final-newline@2.0.0: {} + strip-literal@3.0.0: + dependencies: + js-tokens: 9.0.1 + strtok3@9.1.1: dependencies: '@tokenizer/token': 0.3.0 @@ -4551,6 +5135,21 @@ snapshots: through@2.3.8: {} + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinyglobby@0.2.14: + dependencies: + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + + tinypool@1.1.1: {} + + tinyrainbow@2.0.0: {} + + tinyspy@4.0.3: {} + tldts-core@6.1.86: {} tldts@6.1.86: @@ -4673,6 +5272,83 @@ snapshots: version-range@4.14.0: {} + vite-node@3.2.4(@types/node@22.14.1)(tsx@4.19.3)(yaml@2.7.1): + dependencies: + cac: 6.7.14 + debug: 4.4.1 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 6.3.5(@types/node@22.14.1)(tsx@4.19.3)(yaml@2.7.1) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite@6.3.5(@types/node@22.14.1)(tsx@4.19.3)(yaml@2.7.1): + dependencies: + esbuild: 0.25.2 + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + postcss: 8.5.6 + rollup: 4.44.0 + tinyglobby: 0.2.14 + optionalDependencies: + '@types/node': 22.14.1 + fsevents: 2.3.3 + tsx: 4.19.3 + yaml: 2.7.1 + + vitest@3.2.4(@types/node@22.14.1)(jsdom@26.1.0)(tsx@4.19.3)(yaml@2.7.1): + dependencies: + '@types/chai': 5.2.2 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.14.1)(tsx@4.19.3)(yaml@2.7.1)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.2.0 + debug: 4.4.1 + expect-type: 1.2.1 + magic-string: 0.30.17 + pathe: 2.0.3 + picomatch: 4.0.2 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.14 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 6.3.5(@types/node@22.14.1)(tsx@4.19.3)(yaml@2.7.1) + vite-node: 3.2.4(@types/node@22.14.1)(tsx@4.19.3)(yaml@2.7.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.14.1 + jsdom: 26.1.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 @@ -4746,6 +5422,11 @@ snapshots: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + widest-line@5.0.0: dependencies: string-width: 7.2.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..18ec407 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - 'packages/*' From a0e3bfe2bcacf44159a16cb5a3c806c8c34ce585 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 23 Jun 2025 21:27:52 +0800 Subject: [PATCH 2/8] feat: init `@athena/priompt` --- packages/core/package.json | 1 + packages/core/src/plugin.ts | 23 +- packages/core/test/tool.spec.tsx | 31 ++ packages/core/tsconfig.json | 4 +- packages/priompt/package.json | 29 ++ packages/priompt/src/index.ts | 1 + packages/priompt/src/jsx-dev-runtime.ts | 5 + packages/priompt/src/jsx-runtime.ts | 5 + packages/priompt/src/lib.ts | 11 + packages/priompt/src/type.d.ts | 42 +++ packages/priompt/tsconfig.json | 17 + pnpm-lock.yaml | 446 +++++++++++++++++++++++- tsconfig.json | 18 - 13 files changed, 608 insertions(+), 25 deletions(-) create mode 100644 packages/core/test/tool.spec.tsx create mode 100644 packages/priompt/package.json create mode 100644 packages/priompt/src/index.ts create mode 100644 packages/priompt/src/jsx-dev-runtime.ts create mode 100644 packages/priompt/src/jsx-runtime.ts create mode 100644 packages/priompt/src/lib.ts create mode 100644 packages/priompt/src/type.d.ts create mode 100644 packages/priompt/tsconfig.json delete mode 100644 tsconfig.json diff --git a/packages/core/package.json b/packages/core/package.json index e583b9f..dfa16ab 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -6,6 +6,7 @@ "url": "https://github.com/Athena-AI-Lab/athena-core.git" }, "dependencies": { + "@athena/priompt": "workspace:*", "@llama-flow/core": "^0.4.4" }, "devDependencies": { diff --git a/packages/core/src/plugin.ts b/packages/core/src/plugin.ts index 8360aa6..cf2bead 100644 --- a/packages/core/src/plugin.ts +++ b/packages/core/src/plugin.ts @@ -1,6 +1,6 @@ import { InferWorkflowEventData, - Workflow, + Workflow, WorkflowEvent, workflowEvent, WorkflowEventData } from '@llama-flow/core' @@ -10,6 +10,12 @@ export type Plugin = { setup (): void } +export type Tool = { + readonly name: string; + readonly description: string; + readonly args: any +} + /** * @internal */ @@ -44,6 +50,21 @@ export const pluginRegisterEvent = workflowEvent() */ export const pluginUnregisterEvent = workflowEvent() +export function emitEvent () { + +} + +export function addTool () { + +} + +export function onEvent ( + event: WorkflowEvent, + handler: (data: WorkflowEventData) => void | WorkflowEventData | Promise | Promise> +) { + +} + export function useDescription ( description: string ) { diff --git a/packages/core/test/tool.spec.tsx b/packages/core/test/tool.spec.tsx new file mode 100644 index 0000000..346799c --- /dev/null +++ b/packages/core/test/tool.spec.tsx @@ -0,0 +1,31 @@ +import { expect, test } from 'vitest' +import { render } from '@athena/priompt' + +test('should able to create tool from jsx', () => { + const toolSpec = + + + + + ./example.js + + + console.log('Hello, world!'); + + + + + const result = render(toolSpec) + expect(result).toEqual(` + + + +Example: + +./example.js +console.log('Hello, world!'); +`) +}) diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index c26dc40..1be9ae9 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -7,7 +7,9 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true + "skipLibCheck": true, + "jsx": "react-jsx", + "jsxImportSource": "@athena/priompt" }, "include": [ "./src", diff --git a/packages/priompt/package.json b/packages/priompt/package.json new file mode 100644 index 0000000..4c58be4 --- /dev/null +++ b/packages/priompt/package.json @@ -0,0 +1,29 @@ +{ + "name": "@athena/priompt", + "version": "0.0.1", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./jsx-runtime": { + "types": "./dist/jsx-runtime.d.ts", + "default": "./dist/jsx-runtime.js" + }, + "./jsx-dev-runtime": { + "types": "./dist/jsx-dev-runtime.d.ts", + "default": "./dist/jsx-dev-runtime.js" + } + }, + "scripts": { + "build": "bunchee", + "dev": "bunchee --watch" + }, + "devDependencies": { + "bunchee": "^6.5.3" + }, + "repository": { + "type": "git", + "url": "https://github.com/Athena-AI-Lab/athena-core.git" + } +} diff --git a/packages/priompt/src/index.ts b/packages/priompt/src/index.ts new file mode 100644 index 0000000..f035f52 --- /dev/null +++ b/packages/priompt/src/index.ts @@ -0,0 +1 @@ +export * from './lib.js' diff --git a/packages/priompt/src/jsx-dev-runtime.ts b/packages/priompt/src/jsx-dev-runtime.ts new file mode 100644 index 0000000..c20f56d --- /dev/null +++ b/packages/priompt/src/jsx-dev-runtime.ts @@ -0,0 +1,5 @@ +export * from './type.d.js' + +export function jsxDEV (): any { + // todo +} diff --git a/packages/priompt/src/jsx-runtime.ts b/packages/priompt/src/jsx-runtime.ts new file mode 100644 index 0000000..5ba71e2 --- /dev/null +++ b/packages/priompt/src/jsx-runtime.ts @@ -0,0 +1,5 @@ +export * from './type.d.js' + +export function jsx () { + // todo +} diff --git a/packages/priompt/src/lib.ts b/packages/priompt/src/lib.ts new file mode 100644 index 0000000..13524e4 --- /dev/null +++ b/packages/priompt/src/lib.ts @@ -0,0 +1,11 @@ +import { ToolXMLElement } from './type.d.js' + +export function render ( + element: ToolXMLElement, + options?: { + tokenLimit?: number + } +): string { + // todo + return '' +} diff --git a/packages/priompt/src/type.d.ts b/packages/priompt/src/type.d.ts new file mode 100644 index 0000000..a2417d0 --- /dev/null +++ b/packages/priompt/src/type.d.ts @@ -0,0 +1,42 @@ +export type Node = + ArgProps + | ToolProps + | ExampleProps + | PrimitiveNode + +export type PrimitiveNode = string | number | boolean | null | undefined; + +export type ToolXMLElement = Node[] | Node; + +export type BaseProps = { + children?: ToolXMLElement[] | ToolXMLElement; +}; + +export type ExampleProps = { + children?: ToolXMLElement[] | ToolXMLElement +} + +export type ToolProps = { + name: string; + description?: string; + children?: ToolXMLElement[] | ToolXMLElement; +} + +export type ArgProps = { + name: string; + children?: ToolXMLElement[] | ToolXMLElement; +} + +export namespace JSX { + interface IntrinsicElements { + arg: ArgProps + tool: ToolProps + example: ExampleProps + } + + type Element = ToolXMLElement; + + interface ElementAttributesProperty { + props: BaseProps; + } +} diff --git a/packages/priompt/tsconfig.json b/packages/priompt/tsconfig.json new file mode 100644 index 0000000..2db64e9 --- /dev/null +++ b/packages/priompt/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "rootDir": ".", + "target": "esnext", + "module": "esnext", + "moduleResolution": "node16", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "jsx": "react", + "jsxImportSource": "toolxml", + }, + "include": [ + "./src" + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2295aab..068d1dd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,10 +74,10 @@ importers: devDependencies: '@swc/cli': specifier: ^0.6.0 - version: 0.6.0(@swc/core@1.11.21) + version: 0.6.0(@swc/core@1.11.21(@swc/helpers@0.5.17)) '@swc/core': specifier: ^1.11.21 - version: 1.11.21 + version: 1.11.21(@swc/helpers@0.5.17) '@types/follow-redirects': specifier: ^1.14.4 version: 1.14.4 @@ -114,6 +114,9 @@ importers: packages/core: dependencies: + '@athena/priompt': + specifier: workspace:* + version: link:../priompt '@llama-flow/core': specifier: ^0.4.4 version: 0.4.4(zod@3.24.2) @@ -122,6 +125,12 @@ importers: specifier: ^3.2.4 version: 3.2.4(@types/node@22.14.1)(jsdom@26.1.0)(tsx@4.19.3)(yaml@2.7.1) + packages/priompt: + devDependencies: + bunchee: + specifier: ^6.5.3 + version: 6.5.3(typescript@5.8.3) + packages: '@alcalzone/ansi-tokenize@0.1.3': @@ -131,6 +140,14 @@ packages: '@asamuzakjp/css-color@3.1.3': resolution: {integrity: sha512-u25AyjuNrRFGb1O7KmWEu0ExN6iJMlUmDSlOPW/11JF8khOrIGG6oCoYpC+4mZlthNVhFUahk68lNrNI91f6Yg==} + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + '@colors/colors@1.6.0': resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} @@ -344,6 +361,9 @@ packages: cpu: [x64] os: [win32] + '@fastify/deepmerge@1.3.0': + resolution: {integrity: sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -486,6 +506,60 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@rollup/plugin-commonjs@28.0.6': + resolution: {integrity: sha512-XSQB1K7FUU5QP+3lOQmVCE3I0FcbbNvmNT4VJSj93iUjayaARrTQeoRdiYQoftAJBLrR9t2agwAd3ekaTgHNlw==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-json@6.1.0': + resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@16.0.1': + resolution: {integrity: sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-replace@6.0.2': + resolution: {integrity: sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-wasm@6.2.2': + resolution: {integrity: sha512-gpC4R1G9Ni92ZIRTexqbhX7U+9estZrbhP+9SRb0DW9xpB9g7j34r+J2hqrcW/lRI7dJaU84MxZM0Rt82tqYPQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/pluginutils@5.2.0': + resolution: {integrity: sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/rollup-android-arm-eabi@4.44.0': resolution: {integrity: sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA==} cpu: [arm] @@ -713,6 +787,9 @@ packages: '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + '@swc/helpers@0.5.17': + resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} + '@swc/types@0.1.21': resolution: {integrity: sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==} @@ -774,6 +851,9 @@ packages: '@types/request@2.48.12': resolution: {integrity: sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==} + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} @@ -990,6 +1070,16 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + bunchee@6.5.3: + resolution: {integrity: sha512-TE5iAUjeO6gyIPVbHm0jSyrDHs8c7J+JGCbHfA5mtgcBYr5WAuUADA6g6zj7T8yudvpM+wOc8RIPMWuzXu6VIw==} + engines: {node: '>= 18.0.0'} + hasBin: true + peerDependencies: + typescript: ^4.1 || ^5.0 + peerDependenciesMeta: + typescript: + optional: true + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -1029,6 +1119,10 @@ packages: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} + clean-css@5.3.3: + resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} + engines: {node: '>= 10.0'} + cli-boxes@3.0.0: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} @@ -1037,10 +1131,22 @@ packages: resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + cli-truncate@4.0.0: resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} engines: {node: '>=18'} + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + code-excerpt@4.0.0: resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1079,6 +1185,9 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} @@ -1285,10 +1394,17 @@ packages: engines: {node: '>=18'} hasBin: true + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + escape-string-regexp@2.0.0: resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} engines: {node: '>=8'} + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -1447,6 +1563,10 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.3.0: resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} engines: {node: '>=18'} @@ -1630,6 +1750,10 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + is-data-view@1.0.2: resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} engines: {node: '>= 0.4'} @@ -1671,10 +1795,17 @@ packages: engines: {node: '>=18'} hasBin: true + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + is-number-object@1.1.1: resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} @@ -1690,6 +1821,9 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -1725,6 +1859,14 @@ packages: is-typedarray@1.0.0: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} @@ -1814,6 +1956,10 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + logform@2.7.0: resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} engines: {node: '>= 12.0.0'} @@ -1882,6 +2028,10 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} @@ -1968,6 +2118,10 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + openai@4.95.1: resolution: {integrity: sha512-IqJy+ymeW+k/Wq+2YVN3693OQMMcODRtHEYOlz263MdUwnN/Dwdl9c2EXSxLLtGEHkSHAfvzpDMHI5MaWJKXjQ==} hasBin: true @@ -1980,6 +2134,10 @@ packages: zod: optional: true + ora@8.2.0: + resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} + engines: {node: '>=18'} + own-keys@1.0.1: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} @@ -2005,6 +2163,9 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@2.0.0: resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} engines: {node: 20 || >=22} @@ -2066,6 +2227,10 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -2141,12 +2306,21 @@ packages: engines: {node: '>= 6'} deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + responselike@3.0.0: resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} engines: {node: '>=14.16'} @@ -2155,6 +2329,10 @@ packages: resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -2164,6 +2342,25 @@ packages: engines: {node: 20 || >=22} hasBin: true + rollup-plugin-dts@6.2.1: + resolution: {integrity: sha512-sR3CxYUl7i2CHa0O7bA45mCrgADyAQ0tVtGSqi3yvH28M+eg1+g5d7kQ9hLvEz5dorK3XVsH5L2jwHLQf72DzA==} + engines: {node: '>=16'} + peerDependencies: + rollup: ^3.29.4 || ^4 + typescript: ^4.5 || ^5.0 + + rollup-plugin-swc3@0.11.2: + resolution: {integrity: sha512-o1ih9B806fV2wBSNk46T0cYfTF2eiiKmYXRpWw3K4j/Cp3tCAt10UCVsTqvUhGP58pcB3/GZcAVl5e7TCSKN6Q==} + engines: {node: '>=12'} + peerDependencies: + '@swc/core': '>=1.2.165' + rollup: ^2.0.0 || ^3.0.0 || ^4.0.0 + + rollup-preserve-directives@1.1.3: + resolution: {integrity: sha512-oXqxd6ZzkoQej8Qt0k+S/yvO2+S4CEVEVv2g85oL15o0cjAKTKEuo2MzyA8FcsBBXbtytBzBMFAbhvQg4YyPUQ==} + peerDependencies: + rollup: ^2.0.0 || ^3.0.0 || ^4.0.0 + rollup@4.44.0: resolution: {integrity: sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -2300,6 +2497,10 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + source-map@0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} @@ -2350,6 +2551,10 @@ packages: std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} + stealthy-require@1.1.1: resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==} engines: {node: '>=0.10.0'} @@ -2409,6 +2614,10 @@ packages: resolution: {integrity: sha512-FhwotcEqjr241ZbjFzjlIYg6c5/L/s4yBGWSMvJ9UoExiSqL+FnFA/CaeZx17WGaZMS/4SOZp8wH18jSS4R4lw==} engines: {node: '>=16'} + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} @@ -2745,11 +2954,23 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + yaml@2.7.1: resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} engines: {node: '>= 14'} hasBin: true + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yauzl@3.2.0: resolution: {integrity: sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w==} engines: {node: '>=12'} @@ -2775,6 +2996,16 @@ snapshots: '@csstools/css-tokenizer': 3.0.3 lru-cache: 10.4.3 + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + optional: true + + '@babel/helper-validator-identifier@7.27.1': + optional: true + '@colors/colors@1.6.0': {} '@csstools/color-helpers@5.0.2': {} @@ -2925,6 +3156,8 @@ snapshots: '@esbuild/win32-x64@0.25.2': optional: true + '@fastify/deepmerge@1.3.0': {} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -3020,6 +3253,55 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 + '@rollup/plugin-commonjs@28.0.6(rollup@4.44.0)': + dependencies: + '@rollup/pluginutils': 5.2.0(rollup@4.44.0) + commondir: 1.0.1 + estree-walker: 2.0.2 + fdir: 6.4.6(picomatch@4.0.2) + is-reference: 1.2.1 + magic-string: 0.30.17 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.44.0 + + '@rollup/plugin-json@6.1.0(rollup@4.44.0)': + dependencies: + '@rollup/pluginutils': 5.2.0(rollup@4.44.0) + optionalDependencies: + rollup: 4.44.0 + + '@rollup/plugin-node-resolve@16.0.1(rollup@4.44.0)': + dependencies: + '@rollup/pluginutils': 5.2.0(rollup@4.44.0) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.10 + optionalDependencies: + rollup: 4.44.0 + + '@rollup/plugin-replace@6.0.2(rollup@4.44.0)': + dependencies: + '@rollup/pluginutils': 5.2.0(rollup@4.44.0) + magic-string: 0.30.17 + optionalDependencies: + rollup: 4.44.0 + + '@rollup/plugin-wasm@6.2.2(rollup@4.44.0)': + dependencies: + '@rollup/pluginutils': 5.2.0(rollup@4.44.0) + optionalDependencies: + rollup: 4.44.0 + + '@rollup/pluginutils@5.2.0(rollup@4.44.0)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.44.0 + '@rollup/rollup-android-arm-eabi@4.44.0': optional: true @@ -3140,9 +3422,9 @@ snapshots: - bufferutil - utf-8-validate - '@swc/cli@0.6.0(@swc/core@1.11.21)': + '@swc/cli@0.6.0(@swc/core@1.11.21(@swc/helpers@0.5.17))': dependencies: - '@swc/core': 1.11.21 + '@swc/core': 1.11.21(@swc/helpers@0.5.17) '@swc/counter': 0.1.3 '@xhmikosr/bin-wrapper': 13.0.5 commander: 8.3.0 @@ -3183,7 +3465,7 @@ snapshots: '@swc/core-win32-x64-msvc@1.11.21': optional: true - '@swc/core@1.11.21': + '@swc/core@1.11.21(@swc/helpers@0.5.17)': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.21 @@ -3198,9 +3480,14 @@ snapshots: '@swc/core-win32-arm64-msvc': 1.11.21 '@swc/core-win32-ia32-msvc': 1.11.21 '@swc/core-win32-x64-msvc': 1.11.21 + '@swc/helpers': 0.5.17 '@swc/counter@0.1.3': {} + '@swc/helpers@0.5.17': + dependencies: + tslib: 2.8.1 + '@swc/types@0.1.21': dependencies: '@swc/counter': 0.1.3 @@ -3271,6 +3558,8 @@ snapshots: '@types/tough-cookie': 4.0.5 form-data: 2.5.3 + '@types/resolve@1.20.2': {} + '@types/tough-cookie@4.0.5': {} '@types/triple-beam@1.3.5': {} @@ -3526,6 +3815,31 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + bunchee@6.5.3(typescript@5.8.3): + dependencies: + '@rollup/plugin-commonjs': 28.0.6(rollup@4.44.0) + '@rollup/plugin-json': 6.1.0(rollup@4.44.0) + '@rollup/plugin-node-resolve': 16.0.1(rollup@4.44.0) + '@rollup/plugin-replace': 6.0.2(rollup@4.44.0) + '@rollup/plugin-wasm': 6.2.2(rollup@4.44.0) + '@rollup/pluginutils': 5.2.0(rollup@4.44.0) + '@swc/core': 1.11.21(@swc/helpers@0.5.17) + '@swc/helpers': 0.5.17 + clean-css: 5.3.3 + fast-glob: 3.3.3 + magic-string: 0.30.17 + ora: 8.2.0 + picomatch: 4.0.2 + pretty-bytes: 5.6.0 + rollup: 4.44.0 + rollup-plugin-dts: 6.2.1(rollup@4.44.0)(typescript@5.8.3) + rollup-plugin-swc3: 0.11.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(rollup@4.44.0) + rollup-preserve-directives: 1.1.3(rollup@4.44.0) + tslib: 2.8.1 + yargs: 17.7.2 + optionalDependencies: + typescript: 5.8.3 + cac@6.7.14: {} cacheable-lookup@7.0.0: {} @@ -3571,17 +3885,33 @@ snapshots: check-error@2.1.1: {} + clean-css@5.3.3: + dependencies: + source-map: 0.6.1 + cli-boxes@3.0.0: {} cli-cursor@4.0.0: dependencies: restore-cursor: 4.0.0 + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@2.9.2: {} + cli-truncate@4.0.0: dependencies: slice-ansi: 5.0.0 string-width: 7.2.0 + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + code-excerpt@4.0.0: dependencies: convert-to-spaces: 2.0.1 @@ -3621,6 +3951,8 @@ snapshots: commander@8.3.0: {} + commondir@1.0.1: {} + content-disposition@0.5.4: dependencies: safe-buffer: 5.2.1 @@ -3895,8 +4227,12 @@ snapshots: '@esbuild/win32-ia32': 0.25.2 '@esbuild/win32-x64': 0.25.2 + escalade@3.2.0: {} + escape-string-regexp@2.0.0: {} + estree-walker@2.0.2: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.8 @@ -4052,6 +4388,8 @@ snapshots: functions-have-names@1.2.3: {} + get-caller-file@2.0.5: {} + get-east-asian-width@1.3.0: {} get-intrinsic@1.3.0: @@ -4292,6 +4630,10 @@ snapshots: is-callable@1.2.7: {} + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + is-data-view@1.0.2: dependencies: call-bound: 1.0.4 @@ -4330,8 +4672,12 @@ snapshots: is-in-ci@1.0.0: {} + is-interactive@2.0.0: {} + is-map@2.0.3: {} + is-module@1.0.0: {} + is-number-object@1.1.1: dependencies: call-bound: 1.0.4 @@ -4343,6 +4689,10 @@ snapshots: is-potential-custom-element-name@1.0.1: {} + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.8 + is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -4377,6 +4727,10 @@ snapshots: is-typedarray@1.0.0: {} + is-unicode-supported@1.3.0: {} + + is-unicode-supported@2.1.0: {} + is-weakmap@2.0.2: {} is-weakref@1.1.1: @@ -4470,6 +4824,11 @@ snapshots: lodash@4.17.21: {} + log-symbols@6.0.0: + dependencies: + chalk: 5.4.1 + is-unicode-supported: 1.3.0 + logform@2.7.0: dependencies: '@colors/colors': 1.6.0 @@ -4526,6 +4885,8 @@ snapshots: mimic-fn@2.1.0: {} + mimic-function@5.0.1: {} + mimic-response@3.1.0: {} mimic-response@4.0.0: {} @@ -4605,6 +4966,10 @@ snapshots: dependencies: mimic-fn: 2.1.0 + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + openai@4.95.1(ws@8.18.1)(zod@3.24.2): dependencies: '@types/node': 18.19.86 @@ -4620,6 +4985,18 @@ snapshots: transitivePeerDependencies: - encoding + ora@8.2.0: + dependencies: + chalk: 5.4.1 + cli-cursor: 5.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 + strip-ansi: 7.1.0 + own-keys@1.0.1: dependencies: get-intrinsic: 1.3.0 @@ -4643,6 +5020,8 @@ snapshots: path-key@3.1.1: {} + path-parse@1.0.7: {} + path-scurry@2.0.0: dependencies: lru-cache: 11.1.0 @@ -4688,6 +5067,8 @@ snapshots: prettier@3.5.3: {} + pretty-bytes@5.6.0: {} + process-nextick-args@2.0.1: {} psl@1.15.0: @@ -4795,10 +5176,18 @@ snapshots: tunnel-agent: 0.6.0 uuid: 3.4.0 + require-directory@2.1.1: {} + resolve-alpn@1.2.1: {} resolve-pkg-maps@1.0.0: {} + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + responselike@3.0.0: dependencies: lowercase-keys: 3.0.0 @@ -4808,6 +5197,11 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + reusify@1.1.0: {} rimraf@6.0.1: @@ -4815,6 +5209,28 @@ snapshots: glob: 11.0.1 package-json-from-dist: 1.0.1 + rollup-plugin-dts@6.2.1(rollup@4.44.0)(typescript@5.8.3): + dependencies: + magic-string: 0.30.17 + rollup: 4.44.0 + typescript: 5.8.3 + optionalDependencies: + '@babel/code-frame': 7.27.1 + + rollup-plugin-swc3@0.11.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(rollup@4.44.0): + dependencies: + '@fastify/deepmerge': 1.3.0 + '@rollup/pluginutils': 5.2.0(rollup@4.44.0) + '@swc/core': 1.11.21(@swc/helpers@0.5.17) + get-tsconfig: 4.10.0 + rollup: 4.44.0 + rollup-preserve-directives: 1.1.3(rollup@4.44.0) + + rollup-preserve-directives@1.1.3(rollup@4.44.0): + dependencies: + magic-string: 0.30.17 + rollup: 4.44.0 + rollup@4.44.0: dependencies: '@types/estree': 1.0.8 @@ -4986,6 +5402,8 @@ snapshots: source-map-js@1.2.1: {} + source-map@0.6.1: {} + source-map@0.7.4: {} sqlite-vec-darwin-arm64@0.1.7-alpha.2: @@ -5033,6 +5451,8 @@ snapshots: std-env@3.9.0: {} + stdin-discarder@0.2.2: {} + stealthy-require@1.1.1: {} streamx@2.22.0: @@ -5115,6 +5535,8 @@ snapshots: '@tokenizer/token': 0.3.0 peek-readable: 5.4.2 + supports-preserve-symlinks-flag@1.0.0: {} + symbol-tree@3.2.4: {} tar-stream@3.1.7: @@ -5477,8 +5899,22 @@ snapshots: xmlchars@2.2.0: {} + y18n@5.0.8: {} + yaml@2.7.1: {} + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yauzl@3.2.0: dependencies: buffer-crc32: 0.2.13 diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index d1ce7e0..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "esModuleInterop": true, - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "outDir": "dist", - "rootDir": "src", - "jsx": "react-jsx", - "lib": ["ESNext"], - "types": ["node"] - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] -} From 189943da71558bfcf51c580a71d419fb89dc97a6 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 23 Jun 2025 22:33:15 +0800 Subject: [PATCH 3/8] feat: workflow lifecycle --- packages/core/package.json | 1 - packages/core/src/index.ts | 56 +++++++---- packages/core/src/plugin.ts | 161 +++++++++++++++++++++++++------ packages/core/test/basic.test.ts | 20 ++-- packages/core/test/tool.spec.tsx | 64 ++++++------ packages/priompt/src/index.ts | 1 + packages/priompt/tsconfig.json | 4 +- 7 files changed, 209 insertions(+), 98 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index dfa16ab..e583b9f 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -6,7 +6,6 @@ "url": "https://github.com/Athena-AI-Lab/athena-core.git" }, "dependencies": { - "@athena/priompt": "workspace:*", "@llama-flow/core": "^0.4.4" }, "devDependencies": { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 6851abb..f5441fb 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -3,9 +3,10 @@ import { } from '@llama-flow/core' import { pluginRegisterEvent, - workflowAsyncContext, + pluginStateAsyncContext, Plugin, - PluginState, pluginUnregisterEvent + PluginState, + pluginUnregisterEvent } from './plugin.js' export type AthenaConfig = { @@ -24,21 +25,34 @@ export function createAthena (): AthenaConfig { const coreWorkflow = createWorkflow() const pluginSet = new Set() const pluginStateMap = new WeakMap() - coreWorkflow.handle([pluginRegisterEvent], (pluginRegister) => { + const { sendEvent, stream } = coreWorkflow.createContext() + // one trick to keep the latest stream + let latest = stream + + async function waitFn (handler: (s: typeof stream) => Promise) { + const [l, r] = latest.tee() + await handler(l) + latest = r + } + + coreWorkflow.handle([pluginRegisterEvent], () => { pluginSet.values().every((plugin) => { const pluginState = pluginStateMap.get(plugin)! - const pluginWorkflow = pluginState.workflow - const { sendEvent } = pluginWorkflow.createContext() - sendEvent(pluginRegister) + const cleanup = pluginStateAsyncContext.run(pluginState, + () => plugin.setup()) + if (cleanup) { + pluginState.cleanup = cleanup + } }) return haltEvent.with() }) - coreWorkflow.handle([pluginUnregisterEvent], (pluginUnregister) => { + + coreWorkflow.handle([pluginUnregisterEvent], () => { pluginSet.values().every((plugin) => { const pluginState = pluginStateMap.get(plugin)! - const pluginWorkflow = pluginState.workflow - const { sendEvent } = pluginWorkflow.createContext() - sendEvent(pluginUnregister) + if (pluginState.cleanup) { + pluginState.cleanup() + } }) return haltEvent.with() }) @@ -46,30 +60,30 @@ export function createAthena (): AthenaConfig { const config: AthenaConfig = { add: (plugin: Plugin) => { pluginSet.add(plugin) - const pluginWorkflow = createWorkflow() const pluginState: PluginState = { - description: null!, - workflow: pluginWorkflow + description: '', + tools: new Map(), + get context() { + return { + sendEvent, + handle: coreWorkflow.handle, + wait: waitFn + } + } } - workflowAsyncContext.run(pluginState, () => plugin.setup()) pluginStateMap.set(plugin, pluginState) return config }, run: () => { - const { sendEvent, stream: registerStream } = coreWorkflow.createContext() sendEvent(pluginRegisterEvent.with()) return { get plugins (): ReadonlySet { return new Set(pluginSet) }, async stop (): Promise { - await registerStream.until(haltEvent).toArray() - const { - sendEvent, - stream: unregisterStream - } = coreWorkflow.createContext() + await waitFn(s => s.until(haltEvent).toArray()) sendEvent(pluginUnregisterEvent.with()) - await unregisterStream.until(haltEvent).toArray() + await waitFn(s => s.until(haltEvent).toArray()) } } } diff --git a/packages/core/src/plugin.ts b/packages/core/src/plugin.ts index cf2bead..db25861 100644 --- a/packages/core/src/plugin.ts +++ b/packages/core/src/plugin.ts @@ -1,19 +1,93 @@ import { - InferWorkflowEventData, - Workflow, WorkflowEvent, + WorkflowEvent, workflowEvent, - WorkflowEventData + WorkflowEventData, + WorkflowContext, Workflow } from '@llama-flow/core' import { AsyncLocalStorage } from 'node:async_hooks' export type Plugin = { - setup (): void + name: string + setup (): (() => void) | void } -export type Tool = { - readonly name: string; - readonly description: string; - readonly args: any +type PrimitiveArgument = { + type: 'string' | 'number' | 'boolean'; + description: string; + required: boolean; +}; + +type Argument = + | PrimitiveArgument + | { + type: 'object' | 'array'; + description: string; + required: boolean; + of?: Record | Argument; +}; + +type ArgumentInstance = + T extends PrimitiveArgument + ? T['type'] extends 'string' + ? T['required'] extends true + ? string + : string | undefined + : T['type'] extends 'number' + ? T['required'] extends true + ? number + : number | undefined + : T['type'] extends 'boolean' + ? T['required'] extends true + ? boolean + : boolean | undefined + : never + : T extends { of: Record } + ? T['required'] extends true + ? { [K in keyof T['of']]: ArgumentInstance } + : + | { [K in keyof T['of']]: ArgumentInstance } + | undefined + : T extends { of: Argument } + ? T['required'] extends true + ? ArgumentInstance[] + : ArgumentInstance[] | undefined + : T extends { type: 'object' } + ? T['required'] extends true + ? { [K in keyof T['of']]: any } + : { [K in keyof T['of']]: any } | undefined + : T extends { type: 'array' } + ? T['required'] extends true + ? any[] + : (any | undefined)[] + : never; + +export interface Explanation { + summary: string; + details?: string; +} + +export interface AthenaTool< + Args extends Record = Record, + RetVals extends Argument | Record = Argument, +> { + name: string; + description: string; + args: Args; + retvals: RetVals; + fn: (args: { + [K in keyof Args]: Args[K] extends Argument + ? ArgumentInstance + : never; + }) => Promise : { + [K in keyof RetVals]: RetVals[K] extends Argument + ? ArgumentInstance + : never; + }>; + explainArgs?: (args: Record) => Explanation; + explainReturnVals?: ( + args: Record, + retvals: Record + ) => Explanation; } /** @@ -21,24 +95,32 @@ export type Tool = { */ export type PluginState = { description: string - workflow: Workflow + tools: Map + + get context (): { + handle: Workflow['handle']; + sendEvent: WorkflowContext['sendEvent']; + wait (handler: (stream: WorkflowContext['stream']) => Promise): Promise + } + + cleanup?: () => void } /** * @internal */ function usePluginState () { - const workflow = workflowAsyncContext.getStore() - if (!workflow) { + const pluginState = pluginStateAsyncContext.getStore() + if (!pluginState) { throw new Error('No workflow is available in the current context') } - return workflow + return pluginState } /** * @internal */ -export const workflowAsyncContext = new AsyncLocalStorage() +export const pluginStateAsyncContext = new AsyncLocalStorage() /** * @internal @@ -50,19 +132,48 @@ export const pluginRegisterEvent = workflowEvent() */ export const pluginUnregisterEvent = workflowEvent() -export function emitEvent () { - +export function useTool< + Args extends Record, + RetVals extends Argument | Record, + Tool extends AthenaTool, +> ( + name: string, + description: string, + config: { + args: Args; + returnVals: RetVals; + }, + impl: { + fn: Tool['fn']; + explainArgs?: Tool['explainArgs']; + explainReturnVals?: Tool['explainReturnVals']; + } +) { + const tool = { + name, + description, + ...config, + ...impl + } + const pluginState = usePluginState() + if (pluginState.tools.has(tool.name)) { + throw new Error(`Tool with name "${tool.name}" already exists`) + } + pluginState.tools.set(tool.name, tool as unknown as AthenaTool) } -export function addTool () { - +export function sendEvent (event: WorkflowEventData) { + const pluginState = usePluginState() + pluginState.context.sendEvent(event) } export function onEvent ( event: WorkflowEvent, handler: (data: WorkflowEventData) => void | WorkflowEventData | Promise | Promise> ) { - + const pluginState = usePluginState() + const { handle } = pluginState.context + handle([event], handler) } export function useDescription ( @@ -71,17 +182,3 @@ export function useDescription ( const pluginState = usePluginState() pluginState.description = description } - -export function onRegister ( - handler: (pluginRegister: WorkflowEventData>) => ReturnType -) { - const { workflow } = usePluginState() - workflow.handle([pluginRegisterEvent], handler) -} - -export function onUnregister ( - handler: (pluginUnregister: WorkflowEventData>) => void -) { - const { workflow } = usePluginState() - workflow.handle([pluginUnregisterEvent], handler) -} \ No newline at end of file diff --git a/packages/core/test/basic.test.ts b/packages/core/test/basic.test.ts index 023d694..f49e84d 100644 --- a/packages/core/test/basic.test.ts +++ b/packages/core/test/basic.test.ts @@ -1,24 +1,22 @@ import { expect, test, vi } from 'vitest' import { createAthena } from '../src/index.js' import { - onRegister, - onUnregister, Plugin, useDescription } from '../src/plugin.js' test('should able to setup athena', async () => { - const registerHandler = vi.fn() - const unregisterHandler = vi.fn() + const cleanupHandler = vi.fn() + const setupHandler = vi.fn(() => { + useDescription('this plugin does nothing') + return cleanupHandler + }) const noopPlugin: Plugin = { - setup () { - useDescription('this plugin does nothing') - onRegister(registerHandler) - onUnregister(unregisterHandler) - } + name: 'noop', + setup: setupHandler } const athena = createAthena().add(noopPlugin).run() - expect(registerHandler).toHaveBeenCalledOnce() + expect(setupHandler).toHaveBeenCalledOnce() await athena.stop() - expect(unregisterHandler).toHaveBeenCalledOnce() + expect(cleanupHandler).toHaveBeenCalledOnce() }) diff --git a/packages/core/test/tool.spec.tsx b/packages/core/test/tool.spec.tsx index 346799c..66203c9 100644 --- a/packages/core/test/tool.spec.tsx +++ b/packages/core/test/tool.spec.tsx @@ -1,31 +1,35 @@ -import { expect, test } from 'vitest' -import { render } from '@athena/priompt' +import { test } from 'vitest' +import { + useTool, onEvent, + Plugin, + useDescription +} from '../src/plugin.js' +import { createAthena } from '../src/index.js' -test('should able to create tool from jsx', () => { - const toolSpec = - - - - - ./example.js - - - console.log('Hello, world!'); - - - - - const result = render(toolSpec) - expect(result).toEqual(` - - - -Example: - -./example.js -console.log('Hello, world!'); -`) -}) +test('should able to add tool to plugin', async () => { + const noopPlugin: Plugin = { + name: 'noop', + setup () { + useDescription('this plugin does nothing') + useTool( + 'example-tool', 'this tool is just an example', + { + args: {}, + returnVals: { + type: 'string', + description: 'this return value is just an example', + required: true + } + }, + { + fn: async () => 'example result' + } + ) + // onEvent('', () => { + // + // }) + } + } + const athena = createAthena().add(noopPlugin).run() + await athena.stop() +}) \ No newline at end of file diff --git a/packages/priompt/src/index.ts b/packages/priompt/src/index.ts index f035f52..94f031e 100644 --- a/packages/priompt/src/index.ts +++ b/packages/priompt/src/index.ts @@ -1 +1,2 @@ export * from './lib.js' +export * from './type.d.js' diff --git a/packages/priompt/tsconfig.json b/packages/priompt/tsconfig.json index 2db64e9..681759c 100644 --- a/packages/priompt/tsconfig.json +++ b/packages/priompt/tsconfig.json @@ -7,9 +7,7 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true, - "jsx": "react", - "jsxImportSource": "toolxml", + "skipLibCheck": true }, "include": [ "./src" From 7e17ed2003cc016904a74fe51a079775b26406ba Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 23 Jun 2025 22:39:45 +0800 Subject: [PATCH 4/8] feat: event system --- packages/core/src/plugin.ts | 4 ++++ packages/core/test/tool.spec.tsx | 27 +++++++++++++++++---------- pnpm-workspace.yaml | 1 + 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/core/src/plugin.ts b/packages/core/src/plugin.ts index db25861..a223aa0 100644 --- a/packages/core/src/plugin.ts +++ b/packages/core/src/plugin.ts @@ -176,6 +176,10 @@ export function onEvent ( handle([event], handler) } +export { + workflowEvent as defineEvent +} + export function useDescription ( description: string ) { diff --git a/packages/core/test/tool.spec.tsx b/packages/core/test/tool.spec.tsx index 66203c9..a0908a2 100644 --- a/packages/core/test/tool.spec.tsx +++ b/packages/core/test/tool.spec.tsx @@ -1,14 +1,18 @@ -import { test } from 'vitest' +import { expect, test } from 'vitest' import { - useTool, onEvent, + useTool, + onEvent, Plugin, - useDescription + useDescription, + sendEvent, + defineEvent } from '../src/plugin.js' import { createAthena } from '../src/index.js' test('should able to add tool to plugin', async () => { - const noopPlugin: Plugin = { - name: 'noop', + const messageSentEvent = defineEvent() + const examplePlugin: Plugin = { + name: 'example', setup () { useDescription('this plugin does nothing') useTool( @@ -22,14 +26,17 @@ test('should able to add tool to plugin', async () => { } }, { - fn: async () => 'example result' + fn: async () => { + sendEvent(messageSentEvent.with('example result')) + return 'example result' + } } ) - // onEvent('', () => { - // - // }) + onEvent(messageSentEvent, ({ data }) => { + expect(data).toBe('example result') + }) } } - const athena = createAthena().add(noopPlugin).run() + const athena = createAthena().add(examplePlugin).run() await athena.stop() }) \ No newline at end of file diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 18ec407..ee3d700 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,3 @@ packages: - 'packages/*' + - 'packages/plugins/*' From 0c55d7c9bac475c1cf74602939e558f9897723c7 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Tue, 24 Jun 2025 02:35:46 +0800 Subject: [PATCH 5/8] draft! --- packages/core/package.json | 22 ++++- packages/core/src/index.ts | 51 ++++++++-- packages/core/src/plugin.ts | 93 ++++++++++++++---- packages/core/test/basic.test.ts | 6 +- packages/core/test/tool.spec.tsx | 7 +- packages/plugins/amadeus/package.json | 14 +++ packages/plugins/amadeus/src/index.ts | 124 ++++++++++++++++++++++++ packages/plugins/amadeus/src/type.d.ts | 1 + packages/plugins/amadeus/tsconfig.json | 15 +++ packages/plugins/cerebrum/package.json | 12 +++ packages/plugins/cerebrum/src/index.ts | 104 ++++++++++++++++++++ packages/plugins/cerebrum/src/type.d.ts | 1 + packages/plugins/cerebrum/tsconfig.json | 15 +++ pnpm-lock.yaml | 52 +++++++--- 14 files changed, 467 insertions(+), 50 deletions(-) create mode 100644 packages/plugins/amadeus/package.json create mode 100644 packages/plugins/amadeus/src/index.ts create mode 100644 packages/plugins/amadeus/src/type.d.ts create mode 100644 packages/plugins/amadeus/tsconfig.json create mode 100644 packages/plugins/cerebrum/package.json create mode 100644 packages/plugins/cerebrum/src/index.ts create mode 100644 packages/plugins/cerebrum/src/type.d.ts create mode 100644 packages/plugins/cerebrum/tsconfig.json diff --git a/packages/core/package.json b/packages/core/package.json index e583b9f..960c613 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,19 @@ { "name": "@athena/core", - "scripts": {}, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./plugin": { + "types": "./dist/plugin.d.ts", + "default": "./dist/plugin.js" + } + }, + "scripts": { + "build": "bunchee", + "dev": "bunchee --watch" + }, "repository": { "type": "git", "url": "https://github.com/Athena-AI-Lab/athena-core.git" @@ -8,7 +21,12 @@ "dependencies": { "@llama-flow/core": "^0.4.4" }, + "peerDependencies": { + "zod": "^3.25.0" + }, "devDependencies": { - "vitest": "^3.2.4" + "bunchee": "^6.5.3", + "vitest": "^3.2.4", + "zod": "^3.25.67" } } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index f5441fb..b2c3e8d 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,12 +1,18 @@ import { - createWorkflow, workflowEvent + createWorkflow, + Workflow, + WorkflowEvent, + workflowEvent, + eventSource, + WorkflowContext } from '@llama-flow/core' import { pluginRegisterEvent, pluginStateAsyncContext, Plugin, PluginState, - pluginUnregisterEvent + pluginUnregisterEvent, + AthenaTool } from './plugin.js' export type AthenaConfig = { @@ -23,13 +29,14 @@ const haltEvent = workflowEvent() export function createAthena (): AthenaConfig { const coreWorkflow = createWorkflow() + const toolsMap = new Map() const pluginSet = new Set() const pluginStateMap = new WeakMap() - const { sendEvent, stream } = coreWorkflow.createContext() + let sendEvent: WorkflowContext['sendEvent'] // one trick to keep the latest stream - let latest = stream + let latest: WorkflowContext['stream'] - async function waitFn (handler: (s: typeof stream) => Promise) { + async function waitFn (handler: (s: WorkflowContext['stream']) => Promise) { const [l, r] = latest.tee() await handler(l) latest = r @@ -39,7 +46,8 @@ export function createAthena (): AthenaConfig { pluginSet.values().every((plugin) => { const pluginState = pluginStateMap.get(plugin)! const cleanup = pluginStateAsyncContext.run(pluginState, - () => plugin.setup()) + () => plugin.setup({}) + ) if (cleanup) { pluginState.cleanup = cleanup } @@ -58,13 +66,32 @@ export function createAthena (): AthenaConfig { }) const config: AthenaConfig = { - add: (plugin: Plugin) => { + add: (plugin) => { pluginSet.add(plugin) const pluginState: PluginState = { - description: '', - tools: new Map(), - get context() { + get name() { + return plugin.name + }, + epoch: 0, + description: null, + get config () { + // todo: read from yaml file + return {} + }, + get tools () { + return toolsMap + }, + get athenaContext () { return { + get stream() { + const [l, r] = latest.tee() + latest = r + return l.filter( + ev => + eventSource(ev) !== pluginRegisterEvent && + eventSource(ev) !== pluginUnregisterEvent + ); + }, sendEvent, handle: coreWorkflow.handle, wait: waitFn @@ -75,8 +102,12 @@ export function createAthena (): AthenaConfig { return config }, run: () => { + ({ sendEvent, stream: latest } = coreWorkflow.createContext()) sendEvent(pluginRegisterEvent.with()) return { + get tools (): ReadonlyMap { + return toolsMap + }, get plugins (): ReadonlySet { return new Set(pluginSet) }, diff --git a/packages/core/src/plugin.ts b/packages/core/src/plugin.ts index a223aa0..470d25f 100644 --- a/packages/core/src/plugin.ts +++ b/packages/core/src/plugin.ts @@ -1,16 +1,37 @@ import { - WorkflowEvent, + eventSource, + Workflow, + WorkflowContext, workflowEvent, - WorkflowEventData, - WorkflowContext, Workflow + WorkflowEvent, + WorkflowEventData } from '@llama-flow/core' import { AsyncLocalStorage } from 'node:async_hooks' +import * as z from 'zod/v4/core' -export type Plugin = { +type BasePlugin = { name: string setup (): (() => void) | void } +type PluginWithSchema = { + name: string + config: Schema + setup (config: z.infer): (() => void) | void +} + +export type Plugin = BasePlugin | PluginWithSchema + +export function definePlugin ( + plugin: PluginWithSchema +): PluginWithSchema +export function definePlugin ( + plugin: BasePlugin +): BasePlugin +export function definePlugin (plugin: any): any { + return plugin +} + type PrimitiveArgument = { type: 'string' | 'number' | 'boolean'; description: string; @@ -68,25 +89,37 @@ export interface Explanation { export interface AthenaTool< Args extends Record = Record, - RetVals extends Argument | Record = Argument, + ReturnVals extends Argument | Record = Argument, > { name: string; description: string; args: Args; - retvals: RetVals; + returnVals: ReturnVals; fn: (args: { [K in keyof Args]: Args[K] extends Argument ? ArgumentInstance : never; - }) => Promise : { - [K in keyof RetVals]: RetVals[K] extends Argument - ? ArgumentInstance + }) => Promise : { + [K in keyof ReturnVals]: ReturnVals[K] extends Argument + ? ArgumentInstance : never; }>; - explainArgs?: (args: Record) => Explanation; + explainArgs?: (args: { + [K in keyof Args]: Args[K] extends Argument + ? ArgumentInstance + : never; + }) => Explanation; explainReturnVals?: ( - args: Record, - retvals: Record + args: { + [K in keyof Args]: Args[K] extends Argument + ? ArgumentInstance + : never; + }, + returnVals: ReturnVals extends Argument ? ArgumentInstance : { + [K in keyof ReturnVals]: ReturnVals[K] extends Argument + ? ArgumentInstance + : never; + } ) => Explanation; } @@ -94,15 +127,20 @@ export interface AthenaTool< * @internal */ export type PluginState = { - description: string - tools: Map + get name (): string + description: string | null + + get config (): Readonly>; + get tools (): Map - get context (): { + get athenaContext (): { + get stream (): WorkflowContext['stream']; handle: Workflow['handle']; sendEvent: WorkflowContext['sendEvent']; wait (handler: (stream: WorkflowContext['stream']) => Promise): Promise } + epoch: number cleanup?: () => void } @@ -164,7 +202,7 @@ export function useTool< export function sendEvent (event: WorkflowEventData) { const pluginState = usePluginState() - pluginState.context.sendEvent(event) + pluginState.athenaContext.sendEvent(event) } export function onEvent ( @@ -172,12 +210,26 @@ export function onEvent ( handler: (data: WorkflowEventData) => void | WorkflowEventData | Promise | Promise> ) { const pluginState = usePluginState() - const { handle } = pluginState.context + const { handle } = pluginState.athenaContext handle([event], handler) } export { - workflowEvent as defineEvent + eventSource, + WorkflowEvent, + WorkflowEventData, +} + +export function defineEvent ( + displayName?: string +) { + const pluginState = usePluginState() + const name = pluginState.name + const uniqueId = name + + (displayName ? `/${displayName}/${pluginState.epoch}` : pluginState.epoch++) + return workflowEvent({ + uniqueId + }) } export function useDescription ( @@ -186,3 +238,8 @@ export function useDescription ( const pluginState = usePluginState() pluginState.description = description } + +export function useStream (): WorkflowContext['stream'] { + const pluginState = usePluginState() + return pluginState.athenaContext.stream +} diff --git a/packages/core/test/basic.test.ts b/packages/core/test/basic.test.ts index f49e84d..3fb2337 100644 --- a/packages/core/test/basic.test.ts +++ b/packages/core/test/basic.test.ts @@ -1,7 +1,7 @@ import { expect, test, vi } from 'vitest' import { createAthena } from '../src/index.js' import { - Plugin, + definePlugin, useDescription } from '../src/plugin.js' @@ -11,10 +11,10 @@ test('should able to setup athena', async () => { useDescription('this plugin does nothing') return cleanupHandler }) - const noopPlugin: Plugin = { + const noopPlugin = definePlugin({ name: 'noop', setup: setupHandler - } + }) const athena = createAthena().add(noopPlugin).run() expect(setupHandler).toHaveBeenCalledOnce() await athena.stop() diff --git a/packages/core/test/tool.spec.tsx b/packages/core/test/tool.spec.tsx index a0908a2..7586036 100644 --- a/packages/core/test/tool.spec.tsx +++ b/packages/core/test/tool.spec.tsx @@ -2,16 +2,15 @@ import { expect, test } from 'vitest' import { useTool, onEvent, - Plugin, useDescription, sendEvent, - defineEvent + defineEvent, definePlugin } from '../src/plugin.js' import { createAthena } from '../src/index.js' test('should able to add tool to plugin', async () => { const messageSentEvent = defineEvent() - const examplePlugin: Plugin = { + const examplePlugin = definePlugin({ name: 'example', setup () { useDescription('this plugin does nothing') @@ -36,7 +35,7 @@ test('should able to add tool to plugin', async () => { expect(data).toBe('example result') }) } - } + }) const athena = createAthena().add(examplePlugin).run() await athena.stop() }) \ No newline at end of file diff --git a/packages/plugins/amadeus/package.json b/packages/plugins/amadeus/package.json new file mode 100644 index 0000000..7cadadb --- /dev/null +++ b/packages/plugins/amadeus/package.json @@ -0,0 +1,14 @@ +{ + "name": "amadeus", + "repository": { + "type": "git", + "url": "https://github.com/Athena-AI-Lab/athena-core.git" + }, + "private": true, + "dependencies": { + "@athena/core": "workspace:*", + "amadeus": "^11.0.0", + "openai": "^4.95.1", + "zod": "^3.25.67" + } +} diff --git a/packages/plugins/amadeus/src/index.ts b/packages/plugins/amadeus/src/index.ts new file mode 100644 index 0000000..15e46d0 --- /dev/null +++ b/packages/plugins/amadeus/src/index.ts @@ -0,0 +1,124 @@ +import Amadeus from 'amadeus' +import { + useTool, + definePlugin +} from '@athena/core/plugin' +import * as z from 'zod/v4' + +export default definePlugin({ + name: 'amadeus', + config: z.object({ + client_id: z.string().describe('Amadeus API Client ID'), + client_secret: z.string().describe('Amadeus API Client Secret') + }), + setup ({ client_id, client_secret }) { + const amadeus = new Amadeus({ + clientId: client_id, + clientSecret: client_secret + }) + useTool( + 'flight-offers-search', + 'Return list of Flight Offers based on searching criteria.', + { + args: { + originLocationCode: { + type: 'string', + description: 'city/airport IATA code from which the traveler will depart, e.g. BOS for Boston\nExample : SYD', + required: true + }, + destinationLocationCode: { + type: 'string', + description: 'city/airport IATA code to which the traveler is going, e.g. PAR for Paris\nExample : BKK', + required: true + }, + departureDate: { + type: 'string', + description: 'the date on which the traveler will depart from the origin to go to the destination. Dates are specified in the ISO 8601 YYYY-MM-DD format, e.g. 2017-12-25\nExample : 2023-05-02', + required: true + }, + returnDate: { + type: 'string', + description: 'the date on which the traveler will depart from the origin to go to the destination. Dates are specified in the ISO 8601 YYYY-MM-DD format, e.g. 2017-12-25\nExample : 2023-05-02', + required: false + }, + adults: { + type: 'number', + description: 'the number of adult travelers (age 12 or older on date of departure). The total number of seated travelers (adult and children) can not exceed 9.\nDefault value : 1', + required: true + }, + children: { + type: 'number', + description: 'the number of child travelers (older than age 2 and younger than age 12 on date of departure) who will each have their own separate seat. If specified, this number should be greater than or equal to 0\nThe total number of seated travelers (adult and children) can not exceed 9.', + required: false + }, + infants: { + type: 'number', + description: 'the number of infant travelers (whose age is less or equal to 2 on date of departure). Infants travel on the lap of an adult traveler, and thus the number of infants must not exceed the number of adults. If specified, this number should be greater than or equal to 0', + required: false + }, + travelClass: { + type: 'string', + description: 'most of the flight time should be spent in a cabin of this quality or higher. The accepted travel class is economy, premium economy, business or first class. If no travel class is specified, the search considers any travel class\nAvailable values : ECONOMY, PREMIUM_ECONOMY, BUSINESS, FIRST', + required: false + }, + includedAirlineCodes: { + type: 'string', + description: 'This option ensures that the system will only consider these airlines. This can not be cumulated with parameter excludedAirlineCodes.\nAirlines are specified as IATA airline codes and are comma-separated, e.g. 6X,7X,8X', + required: false + }, + excludedAirlineCodes: { + type: 'string', + description: 'This option ensures that the system will ignore these airlines. This can not be cumulated with parameter includedAirlineCodes.\nAirlines are specified as IATA airline codes and are comma-separated, e.g. 6X,7X,8X', + required: false + }, + nonStop: { + type: 'boolean', + description: 'if set to true, the search will find only flights going from the origin to the destination with no stop in between\nDefault value : false', + required: false + }, + currencyCode: { + type: 'string', + description: 'the preferred currency for the flight offers. Currency is specified in the ISO 4217 format, e.g. EUR for Euro', + required: false + }, + maxPrice: { + type: 'number', + description: 'maximum price per traveler. By default, no limit is applied. If specified, the value should be a positive number with no decimals', + required: false + }, + max: { + type: 'number', + description: 'maximum number of flight offers to return. If specified, the value should be greater than or equal to 1\nDefault value : 250', + required: false + } + }, + returnVals: { + description: 'The flight offers', + type: 'object', + required: true + } + }, + { + fn: async (args) => { + const response = await amadeus.shopping.flightOffersSearch.get({ + originLocationCode: args.originLocationCode, + destinationLocationCode: args.destinationLocationCode, + departureDate: args.departureDate, + returnDate: args.returnDate, + adults: args.adults, + children: args.children, + infants: args.infants, + travelClass: args.travelClass, + includedAirlineCodes: args.includedAirlineCodes, + excludedAirlineCodes: args.excludedAirlineCodes, + nonStop: args.nonStop, + currencyCode: args.currencyCode, + maxPrice: args.maxPrice, + max: args.max + }) + return response.data + } + } + ) + } +}) \ No newline at end of file diff --git a/packages/plugins/amadeus/src/type.d.ts b/packages/plugins/amadeus/src/type.d.ts new file mode 100644 index 0000000..3eecf6f --- /dev/null +++ b/packages/plugins/amadeus/src/type.d.ts @@ -0,0 +1 @@ +declare module "amadeus"; diff --git a/packages/plugins/amadeus/tsconfig.json b/packages/plugins/amadeus/tsconfig.json new file mode 100644 index 0000000..ea8a3a3 --- /dev/null +++ b/packages/plugins/amadeus/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "rootDir": ".", + "target": "esnext", + "module": "esnext", + "moduleResolution": "node16", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + }, + "include": [ + "./src", + ] +} diff --git a/packages/plugins/cerebrum/package.json b/packages/plugins/cerebrum/package.json new file mode 100644 index 0000000..8a21fd7 --- /dev/null +++ b/packages/plugins/cerebrum/package.json @@ -0,0 +1,12 @@ +{ + "name": "cerebrum", + "repository": { + "type": "git", + "url": "https://github.com/Athena-AI-Lab/athena-core.git" + }, + "private": true, + "dependencies": { + "@athena/core": "workspace:*", + "zod": "^3.25.67" + } +} diff --git a/packages/plugins/cerebrum/src/index.ts b/packages/plugins/cerebrum/src/index.ts new file mode 100644 index 0000000..119b20c --- /dev/null +++ b/packages/plugins/cerebrum/src/index.ts @@ -0,0 +1,104 @@ +import { + useTool, + definePlugin, + useStream, + eventSource, + WorkflowEventData +} from '@athena/core/plugin' +import * as z from 'zod/v4' +import OpenAI from 'openai' +import image2uri from 'image2uri' +import { ChatCompletionMessageParam } from 'openai/resources/chat/completions' + +const defaultHeaders = { + 'HTTP-Referer': 'https://athenalab.ai/', + 'X-Title': 'Athena' +} + +const eventDataToPrompt = (event: WorkflowEventData): string => { + const source = eventSource(event)! + const id = source.uniqueId + return ` +${id} +${event.data} +` +} + +function initialPrompt (): string { + return '' +} + +const delay = 500 // milliseconds + +export default definePlugin({ + name: 'cerebrum', + config: z.object({ + base_url: z.string().describe('Amadeus API Base URL').optional(), + api_key: z.string().describe('Amadeus API Key').optional(), + image_supported: z.boolean(). + default(false). + describe('Whether the plugin supports image input') + }), + setup ({ base_url, api_key, image_supported }) { + const imageUrls: string[] = [] + const eventQueue: WorkflowEventData[] = [] + const prompts: Array = [] + const openai = new OpenAI({ + baseURL: base_url, + apiKey: api_key, + defaultHeaders + }) + if (image_supported) { + useTool( + 'image-checkout', + 'Check out an image. Whenever you want to see an image, or the user asks you to see an image, use this tool.', + { + args: { + image: { + type: 'string', + description: 'The URL or local path of the image to check out.', + required: true + } + }, + returnVals: { + type: 'string', + description: 'The result of checking out the image.', + required: true + } + }, + { + fn: async (args) => { + let image = args.image + if (!image.startsWith('http')) { + image = await image2uri(image) + } + imageUrls.push(image) + return 'success' + }, + explainArgs: (args) => ({ + summary: 'Checking out the image...', + details: args.image + }) + } + ) + } + const athenaStream = useStream() + let timeoutSignal = AbortSignal.timeout(delay) + athenaStream.forEach((ev) => { + eventQueue.push(ev) + if (timeoutSignal.aborted) { + // process queue + const eventsPrompts = eventQueue.slice().map(eventDataToPrompt) + const promptSnapshot = prompts.slice() + + timeoutSignal = AbortSignal.timeout(delay) + } + }).catch() + // + // afterEventDefined((event) => { + // onEvent(event, async ({ data }) => { + // + // }) + // }) + } +}) \ No newline at end of file diff --git a/packages/plugins/cerebrum/src/type.d.ts b/packages/plugins/cerebrum/src/type.d.ts new file mode 100644 index 0000000..3eecf6f --- /dev/null +++ b/packages/plugins/cerebrum/src/type.d.ts @@ -0,0 +1 @@ +declare module "amadeus"; diff --git a/packages/plugins/cerebrum/tsconfig.json b/packages/plugins/cerebrum/tsconfig.json new file mode 100644 index 0000000..ea8a3a3 --- /dev/null +++ b/packages/plugins/cerebrum/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "rootDir": ".", + "target": "esnext", + "module": "esnext", + "moduleResolution": "node16", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + }, + "include": [ + "./src", + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 068d1dd..2dddbca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,7 +46,7 @@ importers: version: 0.63.0 openai: specifier: ^4.95.1 - version: 4.95.1(ws@8.18.1)(zod@3.24.2) + version: 4.95.1(ws@8.18.1)(zod@3.25.67) playwright: specifier: ^1.52.0 version: 1.52.0 @@ -114,16 +114,43 @@ importers: packages/core: dependencies: - '@athena/priompt': - specifier: workspace:* - version: link:../priompt '@llama-flow/core': specifier: ^0.4.4 - version: 0.4.4(zod@3.24.2) + version: 0.4.4(zod@3.25.67) devDependencies: + bunchee: + specifier: ^6.5.3 + version: 6.5.3(typescript@5.8.3) vitest: specifier: ^3.2.4 version: 3.2.4(@types/node@22.14.1)(jsdom@26.1.0)(tsx@4.19.3)(yaml@2.7.1) + zod: + specifier: ^3.25.67 + version: 3.25.67 + + packages/plugins/amadeus: + dependencies: + '@athena/core': + specifier: workspace:* + version: link:../../core + amadeus: + specifier: ^11.0.0 + version: 11.0.0 + openai: + specifier: ^4.95.1 + version: 4.95.1(ws@8.18.1)(zod@3.25.67) + zod: + specifier: ^3.25.67 + version: 3.25.67 + + packages/plugins/cerebrum: + dependencies: + '@athena/core': + specifier: workspace:* + version: link:../../core + zod: + specifier: ^3.25.67 + version: 3.25.67 packages/priompt: devDependencies: @@ -2978,8 +3005,8 @@ packages: yoga-layout@3.2.1: resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} - zod@3.24.2: - resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} + zod@3.25.67: + resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} snapshots: @@ -3169,9 +3196,9 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.0': {} - '@llama-flow/core@0.4.4(zod@3.24.2)': + '@llama-flow/core@0.4.4(zod@3.25.67)': optionalDependencies: - zod: 3.24.2 + zod: 3.25.67 '@napi-rs/nice-android-arm-eabi@1.0.1': optional: true @@ -4970,7 +4997,7 @@ snapshots: dependencies: mimic-function: 5.0.1 - openai@4.95.1(ws@8.18.1)(zod@3.24.2): + openai@4.95.1(ws@8.18.1)(zod@3.25.67): dependencies: '@types/node': 18.19.86 '@types/node-fetch': 2.6.12 @@ -4981,7 +5008,7 @@ snapshots: node-fetch: 2.7.0 optionalDependencies: ws: 8.18.1 - zod: 3.24.2 + zod: 3.25.67 transitivePeerDependencies: - encoding @@ -5922,5 +5949,4 @@ snapshots: yoga-layout@3.2.1: {} - zod@3.24.2: - optional: true + zod@3.25.67: {} From 97bc4535c3e26df35f225941214d455b102e3704 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Tue, 24 Jun 2025 17:17:06 +0800 Subject: [PATCH 6/8] fix: send event --- packages/core/src/index.ts | 64 ++++++++++++++++++-------- packages/core/src/plugin.ts | 13 +----- packages/plugins/cerebrum/src/index.ts | 3 ++ 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index b2c3e8d..8821e33 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,9 +1,7 @@ import { createWorkflow, Workflow, - WorkflowEvent, workflowEvent, - eventSource, WorkflowContext } from '@llama-flow/core' import { @@ -27,16 +25,32 @@ export type Athena = { const haltEvent = workflowEvent() +export const toolCallEvent = workflowEvent<{ + name: string; + args: Record; +}>() +export const toolResultEvent = workflowEvent<{ + name: string; + args: Record; + result: any; +}>() + +export interface AthenaContext { + handle: Workflow['handle']; + sendEvent: WorkflowContext['sendEvent']; + waitFor (handler: (stream: WorkflowContext['stream']) => Promise): Promise +} + export function createAthena (): AthenaConfig { const coreWorkflow = createWorkflow() - const toolsMap = new Map() + const toolsMap = new Map() const pluginSet = new Set() const pluginStateMap = new WeakMap() let sendEvent: WorkflowContext['sendEvent'] // one trick to keep the latest stream let latest: WorkflowContext['stream'] - async function waitFn (handler: (s: WorkflowContext['stream']) => Promise) { + async function waitFor (handler: (s: WorkflowContext['stream']) => Promise) { const [l, r] = latest.tee() await handler(l) latest = r @@ -65,6 +79,21 @@ export function createAthena (): AthenaConfig { return haltEvent.with() }) + coreWorkflow.handle([toolCallEvent], async ({ data }) => { + const tool = toolsMap.get(data.name) + if (!tool) { + throw new Error(`Tool "${data.name}" not found`) + } + const result: any = await tool.fn.call(null, data.args as any) + return toolResultEvent.with({ + name: data.name, + args: data.args, + result + }) + }) + + let context: AthenaContext | null = null + const config: AthenaConfig = { add: (plugin) => { pluginSet.add(plugin) @@ -82,20 +111,7 @@ export function createAthena (): AthenaConfig { return toolsMap }, get athenaContext () { - return { - get stream() { - const [l, r] = latest.tee() - latest = r - return l.filter( - ev => - eventSource(ev) !== pluginRegisterEvent && - eventSource(ev) !== pluginUnregisterEvent - ); - }, - sendEvent, - handle: coreWorkflow.handle, - wait: waitFn - } + return context! } } pluginStateMap.set(plugin, pluginState) @@ -103,8 +119,16 @@ export function createAthena (): AthenaConfig { }, run: () => { ({ sendEvent, stream: latest } = coreWorkflow.createContext()) + ;context = { + sendEvent, + handle: coreWorkflow.handle, + waitFor + } sendEvent(pluginRegisterEvent.with()) return { + get context(): AthenaContext { + return context! + }, get tools (): ReadonlyMap { return toolsMap }, @@ -112,9 +136,9 @@ export function createAthena (): AthenaConfig { return new Set(pluginSet) }, async stop (): Promise { - await waitFn(s => s.until(haltEvent).toArray()) + await context!.waitFor(s => s.until(haltEvent).toArray()) sendEvent(pluginUnregisterEvent.with()) - await waitFn(s => s.until(haltEvent).toArray()) + await context!.waitFor(s => s.until(haltEvent).toArray()) } } } diff --git a/packages/core/src/plugin.ts b/packages/core/src/plugin.ts index 470d25f..613dbfa 100644 --- a/packages/core/src/plugin.ts +++ b/packages/core/src/plugin.ts @@ -8,6 +8,7 @@ import { } from '@llama-flow/core' import { AsyncLocalStorage } from 'node:async_hooks' import * as z from 'zod/v4/core' +import { AthenaContext } from './index.js' type BasePlugin = { name: string @@ -133,12 +134,7 @@ export type PluginState = { get config (): Readonly>; get tools (): Map - get athenaContext (): { - get stream (): WorkflowContext['stream']; - handle: Workflow['handle']; - sendEvent: WorkflowContext['sendEvent']; - wait (handler: (stream: WorkflowContext['stream']) => Promise): Promise - } + get athenaContext (): AthenaContext epoch: number cleanup?: () => void @@ -238,8 +234,3 @@ export function useDescription ( const pluginState = usePluginState() pluginState.description = description } - -export function useStream (): WorkflowContext['stream'] { - const pluginState = usePluginState() - return pluginState.athenaContext.stream -} diff --git a/packages/plugins/cerebrum/src/index.ts b/packages/plugins/cerebrum/src/index.ts index 119b20c..26f58c0 100644 --- a/packages/plugins/cerebrum/src/index.ts +++ b/packages/plugins/cerebrum/src/index.ts @@ -22,6 +22,9 @@ const eventDataToPrompt = (event: WorkflowEventData): string => { ${id} ${event.data} ` +} +const toolCallResultTOPrompt = () => { + } function initialPrompt (): string { From 0f9f98504f91335832e5fc17e27c71bc136570bd Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Tue, 24 Jun 2025 17:26:58 +0800 Subject: [PATCH 7/8] fix: remove unused code --- packages/core/src/plugin.ts | 2 -- packages/core/tsconfig.json | 4 +-- packages/priompt/package.json | 29 ----------------- packages/priompt/src/index.ts | 2 -- packages/priompt/src/jsx-dev-runtime.ts | 5 --- packages/priompt/src/jsx-runtime.ts | 5 --- packages/priompt/src/lib.ts | 11 ------- packages/priompt/src/type.d.ts | 42 ------------------------- packages/priompt/tsconfig.json | 15 --------- 9 files changed, 1 insertion(+), 114 deletions(-) delete mode 100644 packages/priompt/package.json delete mode 100644 packages/priompt/src/index.ts delete mode 100644 packages/priompt/src/jsx-dev-runtime.ts delete mode 100644 packages/priompt/src/jsx-runtime.ts delete mode 100644 packages/priompt/src/lib.ts delete mode 100644 packages/priompt/src/type.d.ts delete mode 100644 packages/priompt/tsconfig.json diff --git a/packages/core/src/plugin.ts b/packages/core/src/plugin.ts index 613dbfa..ea93a98 100644 --- a/packages/core/src/plugin.ts +++ b/packages/core/src/plugin.ts @@ -1,7 +1,5 @@ import { eventSource, - Workflow, - WorkflowContext, workflowEvent, WorkflowEvent, WorkflowEventData diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 1be9ae9..c26dc40 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -7,9 +7,7 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true, - "jsx": "react-jsx", - "jsxImportSource": "@athena/priompt" + "skipLibCheck": true }, "include": [ "./src", diff --git a/packages/priompt/package.json b/packages/priompt/package.json deleted file mode 100644 index 4c58be4..0000000 --- a/packages/priompt/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "@athena/priompt", - "version": "0.0.1", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "./jsx-runtime": { - "types": "./dist/jsx-runtime.d.ts", - "default": "./dist/jsx-runtime.js" - }, - "./jsx-dev-runtime": { - "types": "./dist/jsx-dev-runtime.d.ts", - "default": "./dist/jsx-dev-runtime.js" - } - }, - "scripts": { - "build": "bunchee", - "dev": "bunchee --watch" - }, - "devDependencies": { - "bunchee": "^6.5.3" - }, - "repository": { - "type": "git", - "url": "https://github.com/Athena-AI-Lab/athena-core.git" - } -} diff --git a/packages/priompt/src/index.ts b/packages/priompt/src/index.ts deleted file mode 100644 index 94f031e..0000000 --- a/packages/priompt/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './lib.js' -export * from './type.d.js' diff --git a/packages/priompt/src/jsx-dev-runtime.ts b/packages/priompt/src/jsx-dev-runtime.ts deleted file mode 100644 index c20f56d..0000000 --- a/packages/priompt/src/jsx-dev-runtime.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './type.d.js' - -export function jsxDEV (): any { - // todo -} diff --git a/packages/priompt/src/jsx-runtime.ts b/packages/priompt/src/jsx-runtime.ts deleted file mode 100644 index 5ba71e2..0000000 --- a/packages/priompt/src/jsx-runtime.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './type.d.js' - -export function jsx () { - // todo -} diff --git a/packages/priompt/src/lib.ts b/packages/priompt/src/lib.ts deleted file mode 100644 index 13524e4..0000000 --- a/packages/priompt/src/lib.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ToolXMLElement } from './type.d.js' - -export function render ( - element: ToolXMLElement, - options?: { - tokenLimit?: number - } -): string { - // todo - return '' -} diff --git a/packages/priompt/src/type.d.ts b/packages/priompt/src/type.d.ts deleted file mode 100644 index a2417d0..0000000 --- a/packages/priompt/src/type.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -export type Node = - ArgProps - | ToolProps - | ExampleProps - | PrimitiveNode - -export type PrimitiveNode = string | number | boolean | null | undefined; - -export type ToolXMLElement = Node[] | Node; - -export type BaseProps = { - children?: ToolXMLElement[] | ToolXMLElement; -}; - -export type ExampleProps = { - children?: ToolXMLElement[] | ToolXMLElement -} - -export type ToolProps = { - name: string; - description?: string; - children?: ToolXMLElement[] | ToolXMLElement; -} - -export type ArgProps = { - name: string; - children?: ToolXMLElement[] | ToolXMLElement; -} - -export namespace JSX { - interface IntrinsicElements { - arg: ArgProps - tool: ToolProps - example: ExampleProps - } - - type Element = ToolXMLElement; - - interface ElementAttributesProperty { - props: BaseProps; - } -} diff --git a/packages/priompt/tsconfig.json b/packages/priompt/tsconfig.json deleted file mode 100644 index 681759c..0000000 --- a/packages/priompt/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "rootDir": ".", - "target": "esnext", - "module": "esnext", - "moduleResolution": "node16", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "skipLibCheck": true - }, - "include": [ - "./src" - ] -} From 787ea1b2ad66246ef38943e570a2fa5ba035062f Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Wed, 25 Jun 2025 09:35:53 -0700 Subject: [PATCH 8/8] feat: plugin --- packages/core/src/index.ts | 7 ++-- packages/core/src/plugin.ts | 5 +++ packages/plugins/cerebrum/src/index.ts | 48 +++++++++++++++++--------- 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 8821e33..4ae013a 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -26,10 +26,12 @@ export type Athena = { const haltEvent = workflowEvent() export const toolCallEvent = workflowEvent<{ + id: string; name: string; args: Record; }>() export const toolResultEvent = workflowEvent<{ + id: string; name: string; args: Record; result: any; @@ -86,6 +88,7 @@ export function createAthena (): AthenaConfig { } const result: any = await tool.fn.call(null, data.args as any) return toolResultEvent.with({ + id: data.id, name: data.name, args: data.args, result @@ -119,11 +122,11 @@ export function createAthena (): AthenaConfig { }, run: () => { ({ sendEvent, stream: latest } = coreWorkflow.createContext()) - ;context = { + context = Object.freeze({ sendEvent, handle: coreWorkflow.handle, waitFor - } + }) sendEvent(pluginRegisterEvent.with()) return { get context(): AthenaContext { diff --git a/packages/core/src/plugin.ts b/packages/core/src/plugin.ts index ea93a98..e1989b2 100644 --- a/packages/core/src/plugin.ts +++ b/packages/core/src/plugin.ts @@ -232,3 +232,8 @@ export function useDescription ( const pluginState = usePluginState() pluginState.description = description } + +export function useAthenaContext(): AthenaContext { + const pluginState = usePluginState() + return pluginState.athenaContext; +} diff --git a/packages/plugins/cerebrum/src/index.ts b/packages/plugins/cerebrum/src/index.ts index 26f58c0..e72b614 100644 --- a/packages/plugins/cerebrum/src/index.ts +++ b/packages/plugins/cerebrum/src/index.ts @@ -1,10 +1,12 @@ import { useTool, definePlugin, - useStream, eventSource, - WorkflowEventData + WorkflowEventData, + onEvent, + useAthenaContext } from '@athena/core/plugin' +import { toolResultEvent } from '@athena/core' import * as z from 'zod/v4' import OpenAI from 'openai' import image2uri from 'image2uri' @@ -17,9 +19,17 @@ const defaultHeaders = { const eventDataToPrompt = (event: WorkflowEventData): string => { const source = eventSource(event)! - const id = source.uniqueId + const name = source.uniqueId + if (toolResultEvent.include(event)) { + return ` +${name} +${event.data.id} +${event.data} + +` + } return ` -${id} +${name} ${event.data} ` } @@ -45,7 +55,7 @@ export default definePlugin({ setup ({ base_url, api_key, image_supported }) { const imageUrls: string[] = [] const eventQueue: WorkflowEventData[] = [] - const prompts: Array = [] + const messages: Array = [] const openai = new OpenAI({ baseURL: base_url, apiKey: api_key, @@ -85,18 +95,24 @@ export default definePlugin({ } ) } - const athenaStream = useStream() + const { waitFor } = useAthenaContext() + onEvent(toolResultEvent, toolResult => { + console.log('tool result', toolResult) + }) + function processQueue () { + const eventsPrompts = eventQueue.slice().map(eventDataToPrompt) + const messagePrompts = messages.slice() + } let timeoutSignal = AbortSignal.timeout(delay) - athenaStream.forEach((ev) => { - eventQueue.push(ev) - if (timeoutSignal.aborted) { - // process queue - const eventsPrompts = eventQueue.slice().map(eventDataToPrompt) - const promptSnapshot = prompts.slice() - - timeoutSignal = AbortSignal.timeout(delay) - } - }).catch() + waitFor(async stream => + stream.forEach((ev) => { + eventQueue.push(ev) + if (timeoutSignal.aborted) { + processQueue() + timeoutSignal = AbortSignal.timeout(delay) + } + }) + ).catch(console.error) // // afterEventDefined((event) => { // onEvent(event, async ({ data }) => {