From 9c302f8c5427488892ec5249a77eef58a68d8a33 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Fri, 6 Feb 2026 03:41:01 -0800 Subject: [PATCH 1/8] Add agent.pause() / agent.resume() for mid-execution control Allows pausing the agent's action loop at clean boundaries (between actions and between batches) for human-in-the-loop review or conditional execution, then resuming without losing state. stop() while paused unblocks the loop to prevent deadlocks. --- packages/magnitude-core/src/agent/index.ts | 39 ++- .../magnitude-core/src/agent/pause.test.ts | 250 ++++++++++++++++++ packages/magnitude-core/src/common/events.ts | 3 + 3 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 packages/magnitude-core/src/agent/pause.test.ts diff --git a/packages/magnitude-core/src/agent/index.ts b/packages/magnitude-core/src/agent/index.ts index af67082d..49c2f697 100644 --- a/packages/magnitude-core/src/agent/index.ts +++ b/packages/magnitude-core/src/agent/index.ts @@ -71,6 +71,8 @@ export class Agent { //public readonly memory: AgentMemory; private doneActing: boolean; + private _paused: boolean = false; + private _pauseResolve: (() => void) | null = null; protected latestTaskMemory: AgentMemory;// | null = null; @@ -116,6 +118,8 @@ export class Agent { this.models = new MultiModelHarness(llms); this.models.events.on('tokensUsed', (usage) => this.events.emit('tokensUsed', usage), this); this.doneActing = false; + this._paused = false; + this._pauseResolve = null; this.memoryOptions = { // TODO: maybe do if Gemini or other prompt caching supported providers as well @@ -387,6 +391,8 @@ export class Agent { // Execute partial recipe for (const action of actions) { + await this._waitIfPaused(); + if (this.doneActing) break; await this.exec(action, memory); // const postActionScreenshot = await this.screenshot(); @@ -399,6 +405,7 @@ export class Agent { // if (finished) { // break; // } + await this._waitIfPaused(); if (this.doneActing) { break; } @@ -420,12 +427,42 @@ export class Agent { this.doneActing = true; } + private async _waitIfPaused(): Promise { + if (!this._paused) return; + this.events.emit('pause'); + logger.info("Agent: Paused"); + await new Promise((resolve) => { + this._pauseResolve = resolve; + }); + } + + pause(): void { + this._paused = true; + } + + resume(): void { + this._paused = false; + if (this._pauseResolve) { + this._pauseResolve(); + this._pauseResolve = null; + } + this.events.emit('resume'); + logger.info("Agent: Resumed"); + } + + get paused(): boolean { + return this._paused; + } + async stop() { /** * Stop the agent and close the browser context. * May be called asynchronously and interrupt an agent in the middle of a action sequence. */ - // set signal to cancelled? + this.doneActing = true; + if (this._paused) { + this.resume(); // unblock so loop can see doneActing and exit + } logger.info("Agent: Stopping connectors..."); for (const connector of this.connectors) { try { diff --git a/packages/magnitude-core/src/agent/pause.test.ts b/packages/magnitude-core/src/agent/pause.test.ts new file mode 100644 index 00000000..c4f4e136 --- /dev/null +++ b/packages/magnitude-core/src/agent/pause.test.ts @@ -0,0 +1,250 @@ +import { describe, expect, test } from 'bun:test'; +import EventEmitter from 'eventemitter3'; +import { AgentEvents } from '@/common/events'; + +// Minimal Agent-like class that isolates pause/resume logic for testing +// without requiring LLM clients, connectors, or BAML dependencies +class PauseableLoop { + public readonly events: EventEmitter = new EventEmitter(); + private doneActing: boolean = false; + private _paused: boolean = false; + private _pauseResolve: (() => void) | null = null; + + private async _waitIfPaused(): Promise { + if (!this._paused) return; + this.events.emit('pause'); + await new Promise((resolve) => { + this._pauseResolve = resolve; + }); + } + + pause(): void { + this._paused = true; + } + + resume(): void { + this._paused = false; + if (this._pauseResolve) { + this._pauseResolve(); + this._pauseResolve = null; + } + this.events.emit('resume'); + } + + get paused(): boolean { + return this._paused; + } + + queueDone(): void { + this.doneActing = true; + } + + stop(): void { + this.doneActing = true; + if (this._paused) { + this.resume(); + } + } + + /** + * Simulates the Agent._act() loop structure. + * Each "batch" is an array of action labels. The loop processes batches + * until doneActing is set, mirroring the real while(true) loop. + */ + async runLoop(batches: string[][], onAction: (label: string) => void): Promise { + this.doneActing = false; + let batchIndex = 0; + + while (true) { + const actions = batches[batchIndex % batches.length]; + batchIndex++; + + for (const action of actions) { + await this._waitIfPaused(); + if (this.doneActing) return; + onAction(action); + } + + await this._waitIfPaused(); + if (this.doneActing) return; + } + } +} + +describe('Agent pause/resume', () => { + test('pause() sets paused flag', () => { + const loop = new PauseableLoop(); + expect(loop.paused).toBe(false); + loop.pause(); + expect(loop.paused).toBe(true); + }); + + test('resume() clears paused flag', () => { + const loop = new PauseableLoop(); + loop.pause(); + loop.resume(); + expect(loop.paused).toBe(false); + }); + + test('resume() when not paused is a no-op (no error)', () => { + const loop = new PauseableLoop(); + expect(() => loop.resume()).not.toThrow(); + expect(loop.paused).toBe(false); + }); + + test('loop pauses before action and resumes on resume()', async () => { + const loop = new PauseableLoop(); + const executed: string[] = []; + + // Pause immediately so first action blocks + loop.pause(); + + const loopPromise = loop.runLoop( + [['a', 'b']], + (label) => { + executed.push(label); + // After executing both actions, stop + if (executed.length === 2) loop.queueDone(); + } + ); + + // Give microtasks a chance to settle — loop should be blocked + await new Promise(r => setTimeout(r, 20)); + expect(executed).toEqual([]); + + // Resume — loop should execute actions then stop + loop.resume(); + await loopPromise; + expect(executed).toEqual(['a', 'b']); + }); + + test('pause mid-batch stops before next action', async () => { + const loop = new PauseableLoop(); + const executed: string[] = []; + + const loopPromise = loop.runLoop( + [['a', 'b', 'c']], + (label) => { + executed.push(label); + if (label === 'a') loop.pause(); // pause after first action + } + ); + + // Wait for loop to pause after 'a' + await new Promise(r => setTimeout(r, 20)); + expect(executed).toEqual(['a']); + + // Resume and let it finish + loop.resume(); + await new Promise(r => setTimeout(r, 20)); + // 'b' should now execute, pause again since flag was cleared by resume + // Actually after resume, _paused is false, so b and c run + expect(executed).toContain('b'); + expect(executed).toContain('c'); + + // Stop the loop + loop.stop(); + await loopPromise; + }); + + test('pause emits pause event, resume emits resume event', async () => { + const loop = new PauseableLoop(); + const events: string[] = []; + + loop.events.on('pause', () => events.push('pause')); + loop.events.on('resume', () => events.push('resume')); + + loop.pause(); + + const loopPromise = loop.runLoop( + [['a']], + () => loop.queueDone() + ); + + // Wait for loop to hit _waitIfPaused and emit 'pause' + await new Promise(r => setTimeout(r, 20)); + expect(events).toEqual(['pause']); + + loop.resume(); + await loopPromise; + expect(events).toEqual(['pause', 'resume']); + }); + + test('stop() while paused unblocks the loop', async () => { + const loop = new PauseableLoop(); + const executed: string[] = []; + + loop.pause(); + + const loopPromise = loop.runLoop( + [['a', 'b']], + (label) => executed.push(label) + ); + + await new Promise(r => setTimeout(r, 20)); + expect(executed).toEqual([]); + + // stop() should set doneActing and resume so loop exits + loop.stop(); + await loopPromise; + + // No actions should have executed — loop exits immediately after unblocking + expect(executed).toEqual([]); + }); + + test('pause between batches blocks next iteration', async () => { + const loop = new PauseableLoop(); + const executed: string[] = []; + let batchCount = 0; + + const loopPromise = loop.runLoop( + [['a'], ['b']], + (label) => { + executed.push(label); + batchCount++; + // After first batch completes, pause before second batch + if (batchCount === 1) loop.pause(); + if (batchCount === 2) loop.queueDone(); + } + ); + + // Let first batch run, then loop should pause at between-batch check + await new Promise(r => setTimeout(r, 20)); + expect(executed).toEqual(['a']); + + loop.resume(); + await loopPromise; + expect(executed).toEqual(['a', 'b']); + }); + + test('multiple pause/resume cycles work correctly', async () => { + const loop = new PauseableLoop(); + const executed: string[] = []; + let actionCount = 0; + + const loopPromise = loop.runLoop( + [['x']], + (label) => { + actionCount++; + executed.push(`${label}${actionCount}`); + if (actionCount < 3) { + loop.pause(); // pause after each action + } else { + loop.queueDone(); // done after 3rd + } + } + ); + + // First action runs, then pauses + await new Promise(r => setTimeout(r, 20)); + expect(executed).toEqual(['x1']); + + loop.resume(); + await new Promise(r => setTimeout(r, 20)); + expect(executed).toEqual(['x1', 'x2']); + + loop.resume(); + await loopPromise; + expect(executed).toEqual(['x1', 'x2', 'x3']); + }); +}); diff --git a/packages/magnitude-core/src/common/events.ts b/packages/magnitude-core/src/common/events.ts index b3854348..956f5ebe 100644 --- a/packages/magnitude-core/src/common/events.ts +++ b/packages/magnitude-core/src/common/events.ts @@ -19,5 +19,8 @@ export interface AgentEvents { 'actionStarted': (action: Action) => void; 'actionDone': (action: Action) => void; + 'pause': () => void; + 'resume': () => void; + 'tokensUsed': (usage: ModelUsage) => void; } \ No newline at end of file From 41ddd6e44891a1a4ea7134032450d7246400d8e7 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Sun, 8 Feb 2026 17:51:47 -0800 Subject: [PATCH 2/8] Replace log-update terminal UI with Ink (React) components Migrate the test runner rendering layer from manual ANSI string building with log-update to Ink components. State bridge pattern handles the async mount race condition. No changes to TestRenderer interface or TestStateTracker. Closes #94 --- package-lock.json | 3991 +++++++++++------ packages/magnitude-test/package.json | 11 +- .../term-app/components/FailureDisplay.tsx | 13 + .../src/term-app/components/InkApp.tsx | 113 + .../src/term-app/components/Summary.tsx | 73 + .../src/term-app/components/TestDisplay.tsx | 107 + .../term-app/components/TestGroupDisplay.tsx | 18 + .../src/term-app/components/TitleBar.tsx | 17 + .../magnitude-test/src/term-app/constants.ts | 21 - .../src/term-app/drawingUtils.ts | 104 - packages/magnitude-test/src/term-app/index.ts | 15 - .../magnitude-test/src/term-app/indicators.ts | 36 + .../src/term-app/termAppRenderer.ts | 211 +- .../magnitude-test/src/term-app/uiRenderer.ts | 395 -- .../magnitude-test/src/term-app/uiState.ts | 135 - 15 files changed, 3028 insertions(+), 2232 deletions(-) create mode 100644 packages/magnitude-test/src/term-app/components/FailureDisplay.tsx create mode 100644 packages/magnitude-test/src/term-app/components/InkApp.tsx create mode 100644 packages/magnitude-test/src/term-app/components/Summary.tsx create mode 100644 packages/magnitude-test/src/term-app/components/TestDisplay.tsx create mode 100644 packages/magnitude-test/src/term-app/components/TestGroupDisplay.tsx create mode 100644 packages/magnitude-test/src/term-app/components/TitleBar.tsx delete mode 100644 packages/magnitude-test/src/term-app/drawingUtils.ts create mode 100644 packages/magnitude-test/src/term-app/indicators.ts delete mode 100644 packages/magnitude-test/src/term-app/uiRenderer.ts delete mode 100644 packages/magnitude-test/src/term-app/uiState.ts diff --git a/package-lock.json b/package-lock.json index 9cca531c..f84dde87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,31 @@ "node": ">=18" } }, + "node_modules/@alcalzone/ansi-tokenize": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@alcalzone/ansi-tokenize/-/ansi-tokenize-0.2.4.tgz", + "integrity": "sha512-HTgrrTgZ9Jgeo6Z3oqbQ7lifOVvRR14vaDuBGPPUxk9Thm+vObaO4QfYYYWw4Zo5CWQDBEfsinFA6Gre+AqwNQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@alcalzone/ansi-tokenize/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/@babel/runtime": { "version": "7.27.6", "dev": true, @@ -552,1180 +577,1849 @@ "commander": "~14.0.0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.5", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.26.0.tgz", + "integrity": "sha512-hj0sKNCQOOo2fgyII3clmJXP28VhgDfU5iy3GNHlWO76KG6N7x4D9ezH5lJtQTG+1J6MFDAJXC1qsI+W+LvZoA==", "cpu": [ - "arm64" + "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "darwin" + "aix" ], "engines": { "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", + "node_modules/@esbuild/android-arm": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.26.0.tgz", + "integrity": "sha512-C0hkDsYNHZkBtPxxDx177JN90/1MiCpvBNjz1f5yWJo1+5+c5zr8apjastpEG+wtPjo9FFtGG7owSsAxyKiHxA==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", + "node_modules/@esbuild/android-arm64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.26.0.tgz", + "integrity": "sha512-DDnoJ5eoa13L8zPh87PUlRd/IyFaIKOlRbxiwcSbeumcJ7UZKdtuMCHa1Q27LWQggug6W4m28i4/O2qiQQ5NZQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", + "node_modules/@esbuild/android-x64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.26.0.tgz", + "integrity": "sha512-bKDkGXGZnj0T70cRpgmv549x38Vr2O3UWLbjT2qmIkdIWcmlg8yebcFWoT9Dku7b5OV3UqPEuNKRzlNhjwUJ9A==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "dev": true, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.5", + "cpu": [ + "arm64" + ], "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", + "node_modules/@esbuild/darwin-x64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.26.0.tgz", + "integrity": "sha512-OPnYj0zpYW0tHusMefyaMvNYQX5pNQuSsHFTHUBNp3vVXupwqpxofcjVsUx11CQhGVkGeXjC3WLjh91hgBG2xw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10.10.0" + "node": ">=18" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.26.0.tgz", + "integrity": "sha512-jix2fa6GQeZhO1sCKNaNMjfj5hbOvoL2F5t+w6gEPxALumkpOV/wq7oUBMHBn2hY2dOm+mEV/K+xfZy3mrsxNQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=18" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.26.0.tgz", + "integrity": "sha512-tccJaH5xHJD/239LjbVvJwf6T4kSzbk6wPFerF0uwWlkw/u7HL+wnAzAH5GB2irGhYemDgiNTp8wJzhAHQ64oA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-3-Clause" + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", + "node_modules/@esbuild/linux-arm": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.26.0.tgz", + "integrity": "sha512-JY8NyU31SyRmRpuc5W8PQarAx4TvuYbyxbPIpHAZdr/0g4iBr8KwQBS4kiiamGl2f42BBecHusYCsyxi7Kn8UQ==", "cpu": [ - "arm64" + "arm" ], - "license": "Apache-2.0", + "dev": true, + "license": "MIT", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" + "node": ">=18" } }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", + "node_modules/@esbuild/linux-arm64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.26.0.tgz", + "integrity": "sha512-IMJYN7FSkLttYyTbsbme0Ra14cBO5z47kpamo16IwggzzATFY2lcZAwkbcNkWiAduKrTgFJP7fW5cBI7FzcuNQ==", "cpu": [ "arm64" ], - "license": "LGPL-3.0-or-later", + "dev": true, + "license": "MIT", "optional": true, "os": [ - "darwin" + "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@isaacs/balanced-match": { - "version": "4.0.1", + "node_modules/@esbuild/linux-ia32": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.26.0.tgz", + "integrity": "sha512-XITaGqGVLgk8WOHw8We9Z1L0lbLFip8LyQzKYFKO4zFo1PFaaSKsbNjvkb7O8kEXytmSGRkYpE8LLVpPJpsSlw==", + "cpu": [ + "ia32" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "20 || >=22" + "node": ">=18" } }, - "node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", + "node_modules/@esbuild/linux-loong64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.26.0.tgz", + "integrity": "sha512-MkggfbDIczStUJwq9wU7gQ7kO33d8j9lWuOCDifN9t47+PeI+9m2QVh51EI/zZQ1spZtFMC1nzBJ+qNGCjJnsg==", + "cpu": [ + "loong64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@isaacs/balanced-match": "^4.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "20 || >=22" + "node": ">=18" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.26.0.tgz", + "integrity": "sha512-fUYup12HZWAeccNLhQ5HwNBPr4zXCPgUWzEq2Rfw7UwqwfQrFZ0SR/JljaURR8xIh9t+o1lNUFTECUTmaP7yKA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.26.0.tgz", + "integrity": "sha512-MzRKhM0Ip+//VYwC8tialCiwUQ4G65WfALtJEFyU0GKJzfTYoPBw5XNWf0SLbCUYQbxTKamlVwPmcw4DgZzFxg==", + "cpu": [ + "ppc64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/@isaacs/cliui/node_modules/string-width/node_modules/emoji-regex": { - "version": "9.2.2", - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.26.0.tgz", + "integrity": "sha512-QhCc32CwI1I4Jrg1enCv292sm3YJprW8WHHlyxJhae/dVs+KRWkbvz2Nynl5HmZDW/m9ZxrXayHzjzVNvQMGQA==", + "cpu": [ + "riscv64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=18" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "6.1.0", + "node_modules/@esbuild/linux-s390x": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.26.0.tgz", + "integrity": "sha512-1D6vi6lfI18aNT1aTf2HV+RIlm6fxtlAp8eOJ4mmnbYmZ4boz8zYDar86sIYNh0wmiLJEbW/EocaKAX6Yso2fw==", + "cpu": [ + "s390x" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=18" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", + "node_modules/@esbuild/linux-x64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.26.0.tgz", + "integrity": "sha512-rnDcepj7LjrKFvZkx+WrBv6wECeYACcFjdNPvVPojCPJD8nHpb3pv3AuR9CXgdnjH1O23btICj0rsp0L9wAnHA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=18" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.11", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.26.0.tgz", + "integrity": "sha512-FSWmgGp0mDNjEXXFcsf12BmVrb+sZBBBlyh3LwB/B9ac3Kkc8x5D2WimYW9N7SUkolui8JzVnVlWh7ZmjCpnxw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.26.0.tgz", + "integrity": "sha512-0QfciUDFryD39QoSPUDshj4uNEjQhp73+3pbSAaxjV2qGOEDsM67P7KbJq7LzHoVl46oqhIhJ1S+skKGR7lMXA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.28", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.26.0.tgz", + "integrity": "sha512-vmAK+nHhIZWImwJ3RNw9hX3fU4UGN/OqbSE0imqljNbUQC3GvVJ1jpwYoTfD6mmXmQaxdJY6Hn4jQbLGJKg5Yw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@manypkg/find-root": { - "version": "1.1.0", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.26.0.tgz", + "integrity": "sha512-GPXF7RMkJ7o9bTyUsnyNtrFMqgM3X+uM/LWw4CeHIjqc32fm0Ir6jKDnWHpj8xHFstgWDUYseSABK9KCkHGnpg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.5.5", - "@types/node": "^12.7.1", - "find-up": "^4.1.0", - "fs-extra": "^8.1.0" + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@manypkg/find-root/node_modules/@types/node": { - "version": "12.20.55", - "dev": true, - "license": "MIT" - }, - "node_modules/@manypkg/find-root/node_modules/find-up": { - "version": "4.1.0", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.26.0.tgz", + "integrity": "sha512-nUHZ5jEYqbBthbiBksbmHTlbb5eElyVfs/s1iHQ8rLBq1eWsd5maOnDpCocw1OM8kFK747d1Xms8dXJHtduxSw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@manypkg/find-root/node_modules/find-up/node_modules/locate-path": { - "version": "5.0.0", + "node_modules/@esbuild/sunos-x64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.26.0.tgz", + "integrity": "sha512-TMg3KCTCYYaVO+R6P5mSORhcNDDlemUVnUbb8QkboUtOhb5JWKAzd5uMIMECJQOxHZ/R+N8HHtDF5ylzLfMiLw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@manypkg/find-root/node_modules/find-up/node_modules/locate-path/node_modules/p-locate": { - "version": "4.1.0", + "node_modules/@esbuild/win32-arm64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.26.0.tgz", + "integrity": "sha512-apqYgoAUd6ZCb9Phcs8zN32q6l0ZQzQBdVXOofa6WvHDlSOhwCWgSfVQabGViThS40Y1NA4SCvQickgZMFZRlA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@manypkg/find-root/node_modules/fs-extra": { - "version": "8.1.0", + "node_modules/@esbuild/win32-ia32": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.26.0.tgz", + "integrity": "sha512-FGJAcImbJNZzLWu7U6WB0iKHl4RuY4TsXEwxJPl9UZLS47agIZuILZEX3Pagfw7I4J3ddflomt9f0apfaJSbaw==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6 <7 || >=8" + "node": ">=18" } }, - "node_modules/@manypkg/find-root/node_modules/fs-extra/node_modules/jsonfile": { - "version": "4.0.0", + "node_modules/@esbuild/win32-x64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.26.0.tgz", + "integrity": "sha512-WAckBKaVnmFqbEhbymrPK7M086DQMpL1XoRbpmN0iW8k5JSXjDRQBhcZNa0VweItknLq9eAeCL34jK7/CDcw7A==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@manypkg/find-root/node_modules/fs-extra/node_modules/universalify": { - "version": "0.1.2", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", "dev": true, "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": ">= 4.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@manypkg/get-packages": { - "version": "1.1.3", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", "dev": true, "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.5.5", - "@changesets/types": "^4.0.1", - "@manypkg/find-root": "^1.1.0", - "fs-extra": "^8.1.0", - "globby": "^11.0.0", - "read-yaml-file": "^1.1.0" + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@manypkg/get-packages/node_modules/@changesets/types": { - "version": "4.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@manypkg/get-packages/node_modules/fs-extra": { - "version": "8.1.0", + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@manypkg/get-packages/node_modules/fs-extra/node_modules/jsonfile": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@manypkg/get-packages/node_modules/fs-extra/node_modules/universalify": { - "version": "0.1.2", + "node_modules/@eslint/js": { + "version": "8.57.1", "dev": true, "license": "MIT", "engines": { - "node": ">= 4.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.18.1", - "license": "MIT", + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "ajv": "^6.12.6", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "eventsource-parser": "^3.0.0", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.23.8", - "zod-to-json-schema": "^3.24.1" + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=18" + "node": ">=10.10.0" } }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "license": "MIT", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": "^14.21.3 || >=16" + "node": ">=12.22" }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } + "license": "BSD-3-Clause" }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@paralleldrive/cuid2": { - "version": "2.2.2", - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.1.5" + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "dev": true, - "license": "MIT", + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", "optional": true, - "engines": { - "node": ">=14" + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@rollup/plugin-alias": { - "version": "5.1.1", - "dev": true, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", "license": "MIT", "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "node": "20 || >=22" } }, - "node_modules/@rollup/plugin-commonjs": { - "version": "28.0.6", - "dev": true, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "fdir": "^6.2.0", - "is-reference": "1.2.1", - "magic-string": "^0.30.3", - "picomatch": "^4.0.2" + "@isaacs/balanced-match": "^4.0.1" }, "engines": { - "node": ">=16.0.0 || 14 >= 14.17" - }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "node": "20 || >=22" } }, - "node_modules/@rollup/plugin-dynamic-import-vars": { - "version": "2.1.5", - "dev": true, - "license": "MIT", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "license": "ISC", "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "astring": "^1.8.5", - "estree-walker": "^2.0.2", - "fast-glob": "^3.2.12", - "magic-string": "^0.30.3" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "node": ">=12" } }, - "node_modules/@rollup/plugin-inject": { - "version": "5.0.5", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.3" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@rollup/plugin-json": { - "version": "6.1.0", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/string-width/node_modules/emoji-regex": { + "version": "9.2.2", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^5.1.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "16.0.1", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.1.0", "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@rollup/pluginutils": { - "version": "5.2.0", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.44.1", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@scarf/scarf": { - "version": "1.4.0", - "hasInstallScript": true, - "license": "Apache-2.0" - }, - "node_modules/@sec-ant/readable-stream": { - "version": "0.4.1", - "license": "MIT" - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", + "node_modules/@isaacs/cliui/node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", "license": "MIT", "engines": { - "node": ">=18" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@types/bun": { - "version": "1.2.17", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.11", "dev": true, "license": "MIT", "dependencies": { - "bun-types": "1.2.17" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@types/cheerio": { - "version": "1.0.0", - "deprecated": "This is a stub types definition. cheerio provides its own type definitions, so you do not need this installed.", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", "dev": true, "license": "MIT", - "dependencies": { - "cheerio": "*" - } + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/@types/estree": { - "version": "1.0.8", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, - "node_modules/@types/fs-extra": { - "version": "11.0.4", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.28", + "dev": true, "license": "MIT", "dependencies": { - "@types/jsonfile": "*", - "@types/node": "*" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", + "node_modules/@manypkg/find-root": { + "version": "1.1.0", "dev": true, - "license": "MIT" - }, - "node_modules/@types/jsonfile": { - "version": "6.1.4", "license": "MIT", "dependencies": { - "@types/node": "*" + "@babel/runtime": "^7.5.5", + "@types/node": "^12.7.1", + "find-up": "^4.1.0", + "fs-extra": "^8.1.0" } }, - "node_modules/@types/nextgen-events": { - "version": "1.1.4", + "node_modules/@manypkg/find-root/node_modules/@types/node": { + "version": "12.20.55", + "dev": true, "license": "MIT" }, - "node_modules/@types/node": { - "version": "22.15.34", + "node_modules/@manypkg/find-root/node_modules/find-up": { + "version": "4.1.0", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/object-hash": { - "version": "3.0.6", - "license": "MIT" + "node_modules/@manypkg/find-root/node_modules/find-up/node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/@types/prop-types": { - "version": "15.7.15", + "node_modules/@manypkg/find-root/node_modules/find-up/node_modules/locate-path/node_modules/p-locate": { + "version": "4.1.0", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/@types/react": { - "version": "18.3.23", + "node_modules/@manypkg/find-root/node_modules/fs-extra": { + "version": "8.1.0", "dev": true, "license": "MIT", "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" } }, - "node_modules/@types/resolve": { - "version": "1.20.2", + "node_modules/@manypkg/find-root/node_modules/fs-extra/node_modules/jsonfile": { + "version": "4.0.0", "dev": true, - "license": "MIT" + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } }, - "node_modules/@types/semver": { - "version": "7.7.0", + "node_modules/@manypkg/find-root/node_modules/fs-extra/node_modules/universalify": { + "version": "0.1.2", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } }, - "node_modules/@types/terminal-kit": { - "version": "2.5.7", + "node_modules/@manypkg/get-packages": { + "version": "1.1.3", + "dev": true, "license": "MIT", "dependencies": { - "@types/nextgen-events": "*" + "@babel/runtime": "^7.5.5", + "@changesets/types": "^4.0.1", + "@manypkg/find-root": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "^11.0.0", + "read-yaml-file": "^1.1.0" } }, - "node_modules/@types/uuid": { - "version": "9.0.8", + "node_modules/@manypkg/get-packages/node_modules/@changesets/types": { + "version": "4.1.0", "dev": true, "license": "MIT" }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", + "node_modules/@manypkg/get-packages/node_modules/fs-extra": { + "version": "8.1.0", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=6 <7 || >=8" } }, - "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", + "node_modules/@manypkg/get-packages/node_modules/fs-extra/node_modules/jsonfile": { + "version": "4.0.0", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", + "node_modules/@manypkg/get-packages/node_modules/fs-extra/node_modules/universalify": { + "version": "0.1.2", "dev": true, "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.18.1", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "ajv": "^6.12.6", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": ">=18" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/@typescript-eslint/types": { - "version": "6.21.0", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", "dev": true, "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">= 8" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.3", - "dev": true, - "license": "ISC", + "node_modules/@paralleldrive/cuid2": { + "version": "2.2.2", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@noble/hashes": "^1.1.5" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch/node_modules/brace-expansion": { - "version": "2.0.2", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" + "optional": true, + "engines": { + "node": ">=14" } }, - "node_modules/@typescript-eslint/utils": { - "version": "6.21.0", + "node_modules/@rollup/plugin-alias": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-6.0.0.tgz", + "integrity": "sha512-tPCzJOtS7uuVZd+xPhoy5W4vThe6KWXNmsFCNktaAh5RTqcLiSfT4huPQIXkgJ6YCOjJHvecOAzQxLFhPxKr+g==", "dev": true, "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" - }, "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=20.19.0" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "rollup": ">=4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", + "node_modules/@rollup/plugin-commonjs": { + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-29.0.0.tgz", + "integrity": "sha512-U2YHaxR2cU/yAiwKJtJRhnyLk7cifnQw0zUpISsocBDoHDJn+HTV74ABqnwr5bEgWUwFZC9oFL6wLe21lHu5eQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "fdir": "^6.2.0", + "is-reference": "1.2.1", + "magic-string": "^0.30.3", + "picomatch": "^4.0.2" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": ">=16.0.0 || 14 >= 14.17" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", + "node_modules/@rollup/plugin-dynamic-import-vars": { + "version": "2.1.5", "dev": true, - "license": "ISC" - }, - "node_modules/accepts": { - "version": "2.0.0", "license": "MIT", "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" + "@rollup/pluginutils": "^5.0.1", + "astring": "^1.8.5", + "estree-walker": "^2.0.2", + "fast-glob": "^3.2.12", + "magic-string": "^0.30.3" }, "engines": { - "node": ">= 0.6" + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/acorn": { - "version": "8.15.0", + "node_modules/@rollup/plugin-json": { + "version": "6.1.0", "dev": true, "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "@rollup/pluginutils": "^5.1.0" }, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "dev": true, - "license": "MIT", + "node": ">=14.0.0" + }, "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/ansi-colors": { - "version": "4.1.3", + "node_modules/@rollup/plugin-node-resolve": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.3.tgz", + "integrity": "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "7.0.0", - "license": "MIT", "dependencies": { - "environment": "^1.0.0" + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" }, "engines": { - "node": ">=18" + "node": ">=14.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=8" + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/@rollup/pluginutils": { + "version": "5.2.0", + "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/ansis": { - "version": "4.1.0", - "license": "ISC", - "engines": { - "node": ">=14" - } + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] }, - "node_modules/any-promise": { - "version": "1.3.0", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "android" + ] }, - "node_modules/argparse": { - "version": "2.0.1", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Python-2.0" + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/array-union": { - "version": "2.1.0", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "engines": { - "node": ">=8" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/astring": { - "version": "1.9.0", + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "bin": { - "astring": "bin/astring" - } + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/asynckit": { - "version": "0.4.0", + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "license": "MIT" + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/bun": { + "version": "1.2.17", + "dev": true, + "license": "MIT", + "dependencies": { + "bun-types": "1.2.17" + } + }, + "node_modules/@types/cheerio": { + "version": "1.0.0", + "deprecated": "This is a stub types definition. cheerio provides its own type definitions, so you do not need this installed.", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "license": "MIT", + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.15.34", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/object-hash": { + "version": "3.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.13", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.13.tgz", + "integrity": "sha512-KkiJeU6VbYbUOp5ITMIc7kBfqlYkKA5KhEHVrGMmUUMt7NeaZg65ojdPk+FtNrBAOXNVM5QM72jnADjM+XVRAQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.7.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "dev": true, "license": "MIT" }, - "node_modules/atomic-sleep": { - "version": "1.0.0", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch/node_modules/brace-expansion": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "dev": true, + "license": "ISC" + }, + "node_modules/accepts": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "dev": true, "license": "MIT", "engines": { - "node": ">=8.0.0" + "node": ">=6" } }, - "node_modules/axios": { - "version": "1.10.0", + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/b4a": { - "version": "1.6.7", - "license": "Apache-2.0" + "node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/balanced-match": { - "version": "1.0.2", + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "4.1.0", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", "dev": true, "license": "MIT" }, - "node_modules/bare-events": { - "version": "2.5.4", - "license": "Apache-2.0", - "optional": true + "node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" }, - "node_modules/bare-fs": { - "version": "4.1.5", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-events": "^2.5.4", - "bare-path": "^3.0.0", - "bare-stream": "^2.6.4" - }, + "node_modules/array-union": { + "version": "2.1.0", + "dev": true, + "license": "MIT", "engines": { - "bare": ">=1.16.0" - }, - "peerDependencies": { - "bare-buffer": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - } + "node": ">=8" } }, - "node_modules/bare-os": { - "version": "3.6.1", - "license": "Apache-2.0", - "optional": true, + "node_modules/astring": { + "version": "1.9.0", + "dev": true, + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "license": "MIT", "engines": { - "bare": ">=1.14.0" + "node": ">=8.0.0" } }, - "node_modules/bare-path": { - "version": "3.0.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-os": "^3.0.1" + "node_modules/auto-bind": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-5.0.1.tgz", + "integrity": "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bare-stream": { - "version": "2.6.5", - "license": "Apache-2.0", - "optional": true, + "node_modules/axios": { + "version": "1.10.0", + "license": "MIT", "dependencies": { - "streamx": "^2.21.0" - }, - "peerDependencies": { - "bare-buffer": "*", - "bare-events": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - }, - "bare-events": { - "optional": true - } + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "node_modules/base64-js": { - "version": "1.5.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, "license": "MIT" }, "node_modules/better-path-resolve": { @@ -1739,15 +2433,6 @@ "node": ">=4" } }, - "node_modules/bl": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, "node_modules/body-parser": { "version": "2.2.0", "license": "MIT", @@ -1800,28 +2485,6 @@ "node": ">=8" } }, - "node_modules/buffer": { - "version": "5.7.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, "node_modules/bun-types": { "version": "1.2.17", "dev": true, @@ -1893,7 +2556,9 @@ } }, "node_modules/chalk": { - "version": "5.4.1", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -1959,10 +2624,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/chownr": { - "version": "1.1.4", - "license": "ISC" - }, "node_modules/ci-info": { "version": "3.9.0", "dev": true, @@ -1977,19 +2638,108 @@ "node": ">=8" } }, - "node_modules/cli-cursor": { - "version": "5.0.0", + "node_modules/cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.1.tgz", + "integrity": "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==", "license": "MIT", "dependencies": { - "restore-cursor": "^5.0.0" + "slice-ansi": "^7.1.0", + "string-width": "^8.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.1.tgz", + "integrity": "sha512-KpqHIdDL9KwYk22wEOg/VIqYbrnLeSApsKT/bSj6Ez7pn3CftUiLAv2Lccpq1ALcpLV9UX1Ppn92npZWu2w/aw==", + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/code-excerpt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", + "license": "MIT", + "dependencies": { + "convert-to-spaces": "^2.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/color": { "version": "4.2.3", "license": "MIT", @@ -2046,6 +2796,8 @@ }, "node_modules/commondir": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true, "license": "MIT" }, @@ -2084,6 +2836,15 @@ "node": ">= 0.6" } }, + "node_modules/convert-to-spaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/cookie": { "version": "0.7.2", "license": "MIT", @@ -2150,8 +2911,10 @@ } }, "node_modules/csstype": { - "version": "3.1.3", - "dev": true, + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, "license": "MIT" }, "node_modules/dataloader": { @@ -2178,27 +2941,7 @@ "peerDependenciesMeta": { "supports-color": { "optional": true - } - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "license": "MIT", - "engines": { - "node": ">=4.0.0" + } } }, "node_modules/deep-is": { @@ -2208,6 +2951,8 @@ }, "node_modules/deepmerge": { "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "license": "MIT", "engines": { @@ -2312,180 +3057,574 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/dotenv": { - "version": "16.6.1", - "license": "BSD-2-Clause", + "node_modules/dotenv": { + "version": "16.6.1", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "10.4.0", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/encoding-sniffer/node_modules/iconv-lite": { + "version": "0.6.3", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-toolkit": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.44.0.tgz", + "integrity": "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/esbuild": { + "version": "0.25.5", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" + } + }, + "node_modules/esbuild/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild/node_modules/@esbuild/darwin-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">=18" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", + "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "license": "MIT" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "license": "MIT" + "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/emoji-regex": { - "version": "10.4.0", - "license": "MIT" + "node_modules/esbuild/node_modules/@esbuild/linux-loong64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/encodeurl": { - "version": "2.0.0", + "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "cpu": [ + "mips64el" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.8" + "node": ">=18" } }, - "node_modules/encoding-sniffer": { - "version": "0.2.1", + "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "cpu": [ + "ppc64" + ], "license": "MIT", - "dependencies": { - "iconv-lite": "^0.6.3", - "whatwg-encoding": "^3.1.1" - }, - "funding": { - "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/encoding-sniffer/node_modules/iconv-lite": { - "version": "0.6.3", + "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "cpu": [ + "riscv64" + ], "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/end-of-stream": { - "version": "1.4.5", + "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "cpu": [ + "s390x" + ], "license": "MIT", - "dependencies": { - "once": "^1.4.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/enquirer": { - "version": "2.4.1", - "dev": true, + "node_modules/esbuild/node_modules/@esbuild/linux-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8.6" + "node": ">=18" } }, - "node_modules/entities": { - "version": "4.5.0", - "license": "BSD-2-Clause", + "node_modules/esbuild/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": ">=18" } }, - "node_modules/environment": { - "version": "1.1.0", + "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "cpu": [ + "x64" + ], "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-define-property": { - "version": "1.0.1", + "node_modules/esbuild/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/es-errors": { - "version": "1.3.0", + "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "cpu": [ + "x64" + ], "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/es-object-atoms": { - "version": "1.1.1", + "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", + "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/esbuild": { + "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { "version": "0.25.5", - "hasInstallScript": true, + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "cpu": [ + "ia32" + ], "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild/node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.5", - "@esbuild/android-arm": "0.25.5", - "@esbuild/android-arm64": "0.25.5", - "@esbuild/android-x64": "0.25.5", - "@esbuild/darwin-arm64": "0.25.5", - "@esbuild/darwin-x64": "0.25.5", - "@esbuild/freebsd-arm64": "0.25.5", - "@esbuild/freebsd-x64": "0.25.5", - "@esbuild/linux-arm": "0.25.5", - "@esbuild/linux-arm64": "0.25.5", - "@esbuild/linux-ia32": "0.25.5", - "@esbuild/linux-loong64": "0.25.5", - "@esbuild/linux-mips64el": "0.25.5", - "@esbuild/linux-ppc64": "0.25.5", - "@esbuild/linux-riscv64": "0.25.5", - "@esbuild/linux-s390x": "0.25.5", - "@esbuild/linux-x64": "0.25.5", - "@esbuild/netbsd-arm64": "0.25.5", - "@esbuild/netbsd-x64": "0.25.5", - "@esbuild/openbsd-arm64": "0.25.5", - "@esbuild/openbsd-x64": "0.25.5", - "@esbuild/sunos-x64": "0.25.5", - "@esbuild/win32-arm64": "0.25.5", - "@esbuild/win32-ia32": "0.25.5", - "@esbuild/win32-x64": "0.25.5" } }, "node_modules/escape-html": { @@ -2740,13 +3879,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/expand-template": { - "version": "2.0.3", - "license": "(MIT OR WTFPL)", - "engines": { - "node": ">=6" - } - }, "node_modules/express": { "version": "5.1.0", "license": "MIT", @@ -2826,10 +3958,6 @@ "version": "3.1.3", "license": "MIT" }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "license": "MIT" - }, "node_modules/fast-glob": { "version": "3.3.3", "dev": true, @@ -3067,10 +4195,6 @@ "node": ">= 0.8" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "license": "MIT" - }, "node_modules/fs-extra": { "version": "11.3.0", "license": "MIT", @@ -3163,10 +4287,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "license": "MIT" - }, "node_modules/glob": { "version": "11.0.3", "license": "ISC", @@ -3375,24 +4495,6 @@ "node": ">=0.10.0" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/ignore": { "version": "5.3.2", "dev": true, @@ -3432,6 +4534,18 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/inflight": { "version": "1.0.6", "dev": true, @@ -3445,10 +4559,188 @@ "version": "2.0.4", "license": "ISC" }, - "node_modules/ini": { - "version": "1.3.8", + "node_modules/ink": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/ink/-/ink-6.6.0.tgz", + "integrity": "sha512-QDt6FgJxgmSxAelcOvOHUvFxbIUjVpCH5bx+Slvc5m7IEcpGt3dYwbz/L+oRnqEGeRvwy1tineKK4ect3nW1vQ==", + "license": "MIT", + "dependencies": { + "@alcalzone/ansi-tokenize": "^0.2.1", + "ansi-escapes": "^7.2.0", + "ansi-styles": "^6.2.1", + "auto-bind": "^5.0.1", + "chalk": "^5.6.0", + "cli-boxes": "^3.0.0", + "cli-cursor": "^4.0.0", + "cli-truncate": "^5.1.1", + "code-excerpt": "^4.0.0", + "es-toolkit": "^1.39.10", + "indent-string": "^5.0.0", + "is-in-ci": "^2.0.0", + "patch-console": "^2.0.0", + "react-reconciler": "^0.33.0", + "signal-exit": "^3.0.7", + "slice-ansi": "^7.1.0", + "stack-utils": "^2.0.6", + "string-width": "^8.1.0", + "type-fest": "^4.27.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0", + "ws": "^8.18.0", + "yoga-layout": "~3.2.1" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@types/react": ">=19.0.0", + "react": ">=19.0.0", + "react-devtools-core": "^6.1.2" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react-devtools-core": { + "optional": true + } + } + }, + "node_modules/ink-spinner": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ink-spinner/-/ink-spinner-5.0.0.tgz", + "integrity": "sha512-EYEasbEjkqLGyPOUc8hBJZNuC5GvXGMLu0w5gdTNskPc7Izc5vO3tdQEYnzvshucyGCBXc86ig0ujXPMWaQCdA==", + "license": "MIT", + "dependencies": { + "cli-spinners": "^2.7.0" + }, + "engines": { + "node": ">=14.16" + }, + "peerDependencies": { + "ink": ">=4.0.0", + "react": ">=18.0.0" + } + }, + "node_modules/ink/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ink/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ink/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, + "node_modules/ink/node_modules/string-width": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.1.tgz", + "integrity": "sha512-KpqHIdDL9KwYk22wEOg/VIqYbrnLeSApsKT/bSj6Ez7pn3CftUiLAv2Lccpq1ALcpLV9UX1Ppn92npZWu2w/aw==", + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/ink/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "license": "MIT", @@ -3462,6 +4754,8 @@ }, "node_modules/is-core-module": { "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "license": "MIT", "dependencies": { @@ -3506,8 +4800,25 @@ "node": ">=0.10.0" } }, + "node_modules/is-in-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-in-ci/-/is-in-ci-2.0.0.tgz", + "integrity": "sha512-cFeerHriAnhrQSbpAxL37W1wcJKUUX07HyLWZCW1URJT/ra3GyUTzBgUnh24TMVfNTV2Hij2HLxkPHFZfOZy5w==", + "license": "MIT", + "bin": { + "is-in-ci": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-module": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", "dev": true, "license": "MIT" }, @@ -3543,6 +4854,8 @@ }, "node_modules/is-reference": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3727,46 +5040,6 @@ "dev": true, "license": "MIT" }, - "node_modules/log-update": { - "version": "6.1.0", - "license": "MIT", - "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.1.0", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/lru-cache": { "version": "11.1.0", "license": "ISC", @@ -3775,11 +5048,13 @@ } }, "node_modules/magic-string": { - "version": "0.30.17", + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/magnitude-core": { @@ -3870,24 +5145,13 @@ "node": ">= 0.6" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-response": { - "version": "3.1.0", + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/minimatch": { @@ -3915,10 +5179,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "license": "MIT" - }, "node_modules/mlly": { "version": "1.7.4", "dev": true, @@ -3930,37 +5190,6 @@ "ufo": "^1.5.4" } }, - "node_modules/moondream": { - "version": "0.1.1", - "license": "MIT", - "dependencies": { - "sharp": "^0.32.1" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/moondream/node_modules/sharp": { - "version": "0.32.6", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.2", - "node-addon-api": "^6.1.0", - "prebuild-install": "^7.1.1", - "semver": "^7.5.4", - "simple-get": "^4.0.1", - "tar-fs": "^3.0.4", - "tunnel-agent": "^0.6.0" - }, - "engines": { - "node": ">=14.15.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/mri": { "version": "1.2.0", "dev": true, @@ -3983,10 +5212,6 @@ "thenify-all": "^1.0.0" } }, - "node_modules/napi-build-utils": { - "version": "2.0.0", - "license": "MIT" - }, "node_modules/natural-compare": { "version": "1.4.0", "dev": true, @@ -3999,20 +5224,6 @@ "node": ">= 0.6" } }, - "node_modules/node-abi": { - "version": "3.75.0", - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-addon-api": { - "version": "6.1.0", - "license": "MIT" - }, "node_modules/node-fetch": { "version": "2.7.0", "dev": true, @@ -4129,21 +5340,8 @@ "node_modules/once": { "version": "1.4.0", "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "7.0.0", - "license": "MIT", - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "wrappy": "1" } }, "node_modules/optionator": { @@ -4325,6 +5523,15 @@ "node": ">= 0.8" } }, + "node_modules/patch-console": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/patch-console/-/patch-console-2.0.0.tgz", + "integrity": "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/patchright": { "version": "1.52.5", "license": "Apache-2.0", @@ -4376,6 +5583,8 @@ }, "node_modules/path-parse": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true, "license": "MIT" }, @@ -4515,21 +5724,24 @@ } }, "node_modules/pkgroll": { - "version": "2.13.1", + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/pkgroll/-/pkgroll-2.23.0.tgz", + "integrity": "sha512-n3DACf3DZCbfTzr/LnZ+KDT272zzqzduvQxMS7j96wYA94YUA4MgoCCcmV6XZ1r5ypdBzDs44C6FwSXuDpxKVw==", "dev": true, "license": "MIT", "dependencies": { - "@rollup/plugin-alias": "^5.1.1", - "@rollup/plugin-commonjs": "^28.0.5", + "@rollup/plugin-alias": "^6.0.0", + "@rollup/plugin-commonjs": "^29.0.0", "@rollup/plugin-dynamic-import-vars": "^2.1.5", - "@rollup/plugin-inject": "^5.0.5", "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^16.0.1", - "@rollup/pluginutils": "^5.1.4", - "esbuild": "^0.25.5", - "magic-string": "^0.30.17", - "rollup": "^4.43.0", - "rollup-pluginutils": "^2.8.2" + "@rollup/plugin-node-resolve": "^16.0.3", + "cjs-module-lexer": "^2.1.1", + "esbuild": "^0.26.0", + "magic-string": "^0.30.21", + "rollup": "^4.53.1", + "rollup-plugin-import-trace": "^1.0.0", + "rollup-pluginutils": "^2.8.2", + "yaml": "^2.8.1" }, "bin": { "pkgroll": "dist/cli.mjs" @@ -4549,6 +5761,65 @@ } } }, + "node_modules/pkgroll/node_modules/@esbuild/darwin-arm64": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.26.0.tgz", + "integrity": "sha512-6Z3naJgOuAIB0RLlJkYc81An3rTlQ/IeRdrU3dOea8h/PvZSgitZV+thNuIccw0MuK1GmIAnAmd5TrMZad8FTQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/pkgroll/node_modules/esbuild": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.26.0.tgz", + "integrity": "sha512-3Hq7jri+tRrVWha+ZeIVhl4qJRha/XjRNSopvTsOaCvfPHrflTYTcUFcEjMKdxofsXXsdc4zjg5NOTnL4Gl57Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.26.0", + "@esbuild/android-arm": "0.26.0", + "@esbuild/android-arm64": "0.26.0", + "@esbuild/android-x64": "0.26.0", + "@esbuild/darwin-arm64": "0.26.0", + "@esbuild/darwin-x64": "0.26.0", + "@esbuild/freebsd-arm64": "0.26.0", + "@esbuild/freebsd-x64": "0.26.0", + "@esbuild/linux-arm": "0.26.0", + "@esbuild/linux-arm64": "0.26.0", + "@esbuild/linux-ia32": "0.26.0", + "@esbuild/linux-loong64": "0.26.0", + "@esbuild/linux-mips64el": "0.26.0", + "@esbuild/linux-ppc64": "0.26.0", + "@esbuild/linux-riscv64": "0.26.0", + "@esbuild/linux-s390x": "0.26.0", + "@esbuild/linux-x64": "0.26.0", + "@esbuild/netbsd-arm64": "0.26.0", + "@esbuild/netbsd-x64": "0.26.0", + "@esbuild/openbsd-arm64": "0.26.0", + "@esbuild/openbsd-x64": "0.26.0", + "@esbuild/openharmony-arm64": "0.26.0", + "@esbuild/sunos-x64": "0.26.0", + "@esbuild/win32-arm64": "0.26.0", + "@esbuild/win32-ia32": "0.26.0", + "@esbuild/win32-x64": "0.26.0" + } + }, "node_modules/playwright": { "name": "patchright", "version": "1.52.5", @@ -4626,54 +5897,6 @@ "node": ">=20" } }, - "node_modules/prebuild-install": { - "version": "7.1.3", - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^2.0.0", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/prebuild-install/node_modules/tar-fs": { - "version": "2.1.3", - "license": "MIT", - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/prebuild-install/node_modules/tar-fs/node_modules/tar-stream": { - "version": "2.2.0", - "license": "MIT", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "dev": true, @@ -4834,24 +6057,28 @@ "node": ">=0.10.0" } }, - "node_modules/rc": { - "version": "1.2.8", - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", + "node_modules/react-reconciler": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.33.0.tgz", + "integrity": "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA==", "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, "engines": { "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^19.2.0" } }, "node_modules/read-yaml-file": { @@ -4888,18 +6115,6 @@ "sprintf-js": "~1.0.2" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/readdirp": { "version": "4.1.2", "dev": true, @@ -4920,11 +6135,13 @@ } }, "node_modules/resolve": { - "version": "1.22.10", + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -4946,20 +6163,6 @@ "node": ">=8" } }, - "node_modules/restore-cursor": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/reusify": { "version": "1.1.0", "dev": true, @@ -5003,7 +6206,9 @@ } }, "node_modules/rollup": { - "version": "4.44.1", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", "dev": true, "license": "MIT", "dependencies": { @@ -5017,29 +6222,59 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.44.1", - "@rollup/rollup-android-arm64": "4.44.1", - "@rollup/rollup-darwin-arm64": "4.44.1", - "@rollup/rollup-darwin-x64": "4.44.1", - "@rollup/rollup-freebsd-arm64": "4.44.1", - "@rollup/rollup-freebsd-x64": "4.44.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.44.1", - "@rollup/rollup-linux-arm-musleabihf": "4.44.1", - "@rollup/rollup-linux-arm64-gnu": "4.44.1", - "@rollup/rollup-linux-arm64-musl": "4.44.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.44.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1", - "@rollup/rollup-linux-riscv64-gnu": "4.44.1", - "@rollup/rollup-linux-riscv64-musl": "4.44.1", - "@rollup/rollup-linux-s390x-gnu": "4.44.1", - "@rollup/rollup-linux-x64-gnu": "4.44.1", - "@rollup/rollup-linux-x64-musl": "4.44.1", - "@rollup/rollup-win32-arm64-msvc": "4.44.1", - "@rollup/rollup-win32-ia32-msvc": "4.44.1", - "@rollup/rollup-win32-x64-msvc": "4.44.1", + "@rollup/rollup-android-arm-eabi": "4.57.1", + "@rollup/rollup-android-arm64": "4.57.1", + "@rollup/rollup-darwin-arm64": "4.57.1", + "@rollup/rollup-darwin-x64": "4.57.1", + "@rollup/rollup-freebsd-arm64": "4.57.1", + "@rollup/rollup-freebsd-x64": "4.57.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", + "@rollup/rollup-linux-arm-musleabihf": "4.57.1", + "@rollup/rollup-linux-arm64-gnu": "4.57.1", + "@rollup/rollup-linux-arm64-musl": "4.57.1", + "@rollup/rollup-linux-loong64-gnu": "4.57.1", + "@rollup/rollup-linux-loong64-musl": "4.57.1", + "@rollup/rollup-linux-ppc64-gnu": "4.57.1", + "@rollup/rollup-linux-ppc64-musl": "4.57.1", + "@rollup/rollup-linux-riscv64-gnu": "4.57.1", + "@rollup/rollup-linux-riscv64-musl": "4.57.1", + "@rollup/rollup-linux-s390x-gnu": "4.57.1", + "@rollup/rollup-linux-x64-gnu": "4.57.1", + "@rollup/rollup-linux-x64-musl": "4.57.1", + "@rollup/rollup-openbsd-x64": "4.57.1", + "@rollup/rollup-openharmony-arm64": "4.57.1", + "@rollup/rollup-win32-arm64-msvc": "4.57.1", + "@rollup/rollup-win32-ia32-msvc": "4.57.1", + "@rollup/rollup-win32-x64-gnu": "4.57.1", + "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-import-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-import-trace/-/rollup-plugin-import-trace-1.0.0.tgz", + "integrity": "sha512-byUjwhEc42qnbcTOZ7E0cDDNidkKkN4VwoW5dknA/61F0c60v2l2ktPraUH4+ehhZ/L/yS/Exry/q8gz0hEZOQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.20.0" + }, + "funding": { + "url": "https://github.com/privatenumber/rollup-plugin-import-trace?sponsor=1" + }, + "peerDependencies": { + "rollup": "^3.0.0 || ^4.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, "node_modules/rollup-pluginutils": { "version": "2.8.2", "dev": true, @@ -5118,6 +6353,12 @@ "version": "2.1.2", "license": "MIT" }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, "node_modules/secure-json-parse": { "version": "2.7.0", "license": "BSD-3-Clause" @@ -5297,47 +6538,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/simple-concat": { - "version": "1.0.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/simple-get": { - "version": "4.0.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "node_modules/simple-swizzle": { "version": "0.2.2", "license": "MIT", @@ -5420,6 +6620,27 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/statuses": { "version": "2.0.2", "license": "MIT", @@ -5431,24 +6652,6 @@ "version": "3.9.0", "license": "MIT" }, - "node_modules/streamx": { - "version": "2.22.1", - "license": "MIT", - "dependencies": { - "fast-fifo": "^1.3.2", - "text-decoder": "^1.1.0" - }, - "optionalDependencies": { - "bare-events": "^2.2.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/string-width": { "version": "7.2.0", "license": "MIT", @@ -5666,6 +6869,8 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "license": "MIT", "engines": { @@ -5675,27 +6880,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tar-fs": { - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - }, - "optionalDependencies": { - "bare-fs": "^4.0.1", - "bare-path": "^3.0.0" - } - }, - "node_modules/tar-stream": { - "version": "3.1.7", - "license": "MIT", - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, "node_modules/term-size": { "version": "2.2.1", "dev": true, @@ -5707,13 +6891,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/text-decoder": { - "version": "1.2.3", - "license": "Apache-2.0", - "dependencies": { - "b4a": "^1.6.4" - } - }, "node_modules/text-table": { "version": "0.2.0", "dev": true, @@ -5877,16 +7054,6 @@ } } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/turbo": { "version": "2.5.4", "dev": true, @@ -6008,10 +7175,6 @@ "punycode": "^2.1.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "license": "MIT" - }, "node_modules/uuid": { "version": "9.0.1", "funding": [ @@ -6085,6 +7248,21 @@ "node": ">= 8" } }, + "node_modules/widest-line": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", + "license": "MIT", + "dependencies": { + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "dev": true, @@ -6184,6 +7362,43 @@ "version": "1.0.2", "license": "ISC" }, + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "dev": true, @@ -6205,6 +7420,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoga-layout": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz", + "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==", + "license": "MIT" + }, "node_modules/zod": { "version": "3.25.67", "license": "MIT", @@ -6219,16 +7440,8 @@ "zod": "^3.24.1" } }, - "node_modules/zod-to-json-schema/node_modules/zod": { - "version": "3.25.67", - "license": "MIT", - "peer": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "packages/create-magnitude-app": { - "version": "0.0.7", + "version": "0.0.8", "license": "Apache-2.0", "dependencies": { "@clack/prompts": "^0.11.0", @@ -6261,17 +7474,15 @@ } }, "packages/magnitude-core": { - "version": "0.2.31", + "version": "0.3.1", "license": "Apache-2.0", "dependencies": { "@boundaryml/baml": "^0.202.0", "@paralleldrive/cuid2": "^2.2.2", - "@types/object-hash": "^3.0.6", "ansis": "^4.1.0", "commander": "^13.1.0", "eventemitter3": "^5.0.1", "magnitude-extract": "0.0.2", - "moondream": "^0.1.0", "object-hash": "^3.0.0", "pino": "^9.6.0", "pino-pretty": "^13.0.0", @@ -6286,6 +7497,7 @@ }, "devDependencies": { "@types/node": "^22.13.4", + "@types/object-hash": "^3.0.6", "pkgroll": "^2.10.0", "typescript": "~5.7.2" } @@ -6345,10 +7557,12 @@ } }, "packages/magnitude-mcp": { - "version": "0.1.0", + "version": "0.1.3", + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { "@modelcontextprotocol/sdk": "^1.18.0", - "magnitude-core": "^0.2.31", + "magnitude-core": "^0.3.1", "patchright": "^1.49.0", "zod": "^3.24.2", "zod-to-json-schema": "^3.24.5" @@ -6358,7 +7572,7 @@ }, "devDependencies": { "@types/node": "^20.17.30", - "tsup": "^8.0.0", + "pkgroll": "^2.15.4", "typescript": "^5.8.3" } }, @@ -6382,32 +7596,26 @@ "node": ">=14.17" } }, - "packages/magnitude-mcp/node_modules/zod": { - "version": "3.25.67", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "packages/magnitude-test": { - "version": "0.3.10", + "version": "0.3.13", "license": "Apache-2.0", "dependencies": { "@commander-js/extra-typings": "^14.0.0", "@paralleldrive/cuid2": "^2.2.2", - "@types/terminal-kit": "^2.5.7", "chalk": "^5.4.1", "commander": "^14.0.0", "dotenv": "^16.5.0", "esbuild": "^0.25.1", "glob": "^11.0.1", + "ink": "^6.0.0", + "ink-spinner": "^5.0.0", "jiti": "^2.4.2", - "log-update": "^6.1.0", - "magnitude-core": "0.2.31", + "magnitude-core": "0.3.1", "pino": "^9.6.0", "pino-pretty": "^13.0.0", "playwright": "^1.51.0", "posthog-node": "^4.18.0", + "react": "^19.1.0", "std-env": "^3.9.0", "zod": "^3.24.2" }, @@ -6416,7 +7624,7 @@ }, "devDependencies": { "@types/node": "^22.13.4", - "@types/react": "^18.2.0", + "@types/react": "^19.0.0", "pkgroll": "^2.10.0", "playwright": "npm:rebrowser-playwright@^1.52.0", "typescript": "~5.7.2" @@ -6468,13 +7676,6 @@ "engines": { "node": ">=14.17" } - }, - "packages/magnitude-test/node_modules/zod": { - "version": "3.25.67", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } diff --git a/packages/magnitude-test/package.json b/packages/magnitude-test/package.json index 0a4c424b..01730b58 100644 --- a/packages/magnitude-test/package.json +++ b/packages/magnitude-test/package.json @@ -18,8 +18,8 @@ "default": "./dist/index.cjs" }, "import": { - "types": "./dist/index.d.mts", - "default": "./dist/index.mjs" + "types": "./dist/index.d.ts", + "default": "./dist/index.js" } }, "repository": { @@ -59,7 +59,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/node": "^22.13.4", - "@types/react": "^18.2.0", + "@types/react": "^19.0.0", "pkgroll": "^2.10.0", "typescript": "~5.7.2", "playwright": "npm:rebrowser-playwright@^1.52.0" @@ -67,19 +67,20 @@ "dependencies": { "@commander-js/extra-typings": "^14.0.0", "@paralleldrive/cuid2": "^2.2.2", - "@types/terminal-kit": "^2.5.7", "chalk": "^5.4.1", "commander": "^14.0.0", "dotenv": "^16.5.0", "esbuild": "^0.25.1", "glob": "^11.0.1", + "ink": "^6.0.0", + "ink-spinner": "^5.0.0", "jiti": "^2.4.2", - "log-update": "^6.1.0", "magnitude-core": "0.3.1", "pino": "^9.6.0", "pino-pretty": "^13.0.0", "playwright": "^1.51.0", "posthog-node": "^4.18.0", + "react": "^19.1.0", "std-env": "^3.9.0", "zod": "^3.24.2" } diff --git a/packages/magnitude-test/src/term-app/components/FailureDisplay.tsx b/packages/magnitude-test/src/term-app/components/FailureDisplay.tsx new file mode 100644 index 00000000..109ef909 --- /dev/null +++ b/packages/magnitude-test/src/term-app/components/FailureDisplay.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { Text } from 'ink'; +import { TestFailure } from '@/runner/state'; + +interface FailureDisplayProps { + failure: TestFailure; +} + +export function FailureDisplay({ failure }: FailureDisplayProps) { + return ( + {'↳ '}{failure.message ?? 'Unknown error details'} + ); +} diff --git a/packages/magnitude-test/src/term-app/components/InkApp.tsx b/packages/magnitude-test/src/term-app/components/InkApp.tsx new file mode 100644 index 00000000..4af84e56 --- /dev/null +++ b/packages/magnitude-test/src/term-app/components/InkApp.tsx @@ -0,0 +1,113 @@ +import React, { useState, useEffect } from 'react'; +import { Box, Text, useApp, useInput, useStdout } from 'ink'; +import { RegisteredTest, MagnitudeConfig } from '@/discovery/types'; +import { AllTestStates } from '../types'; +import { MAX_APP_WIDTH } from '../constants'; +import { TitleBar } from './TitleBar'; +import { TestDisplay } from './TestDisplay'; +import { TestGroupDisplay } from './TestGroupDisplay'; +import { Summary } from './Summary'; + +export interface StateBridge { + update: (states: AllTestStates) => void; + setModel: (model: string) => void; +} + +interface InkAppProps { + tests: RegisteredTest[]; + config: MagnitudeConfig; + initialStates: AllTestStates; + onReady: (bridge: StateBridge) => void; +} + +function groupRegisteredTestsForDisplay(tests: RegisteredTest[]): + Record }> { + const files: Record }> = {}; + for (const test of tests) { + if (!files[test.filepath]) { + files[test.filepath] = { ungrouped: [], groups: {} }; + } + if (test.group) { + if (!files[test.filepath].groups[test.group]) { + files[test.filepath].groups[test.group] = []; + } + files[test.filepath].groups[test.group].push(test); + } else { + files[test.filepath].ungrouped.push(test); + } + } + return files; +} + +export function InkApp({ tests, config, initialStates, onReady }: InkAppProps) { + const [testStates, setTestStates] = useState(initialStates); + const [model, setModel] = useState(''); + const { exit } = useApp(); + const { stdout } = useStdout(); + + const showActions = config.display?.showActions ?? true; + const showThoughts = config.display?.showThoughts ?? false; + + useEffect(() => { + onReady({ update: setTestStates, setModel }); + }, []); + + useInput((_input, key) => { + if (key.ctrl && _input === 'c') { + exit(); + } + }); + + const width = Math.min(stdout?.columns ?? MAX_APP_WIDTH, MAX_APP_WIDTH); + const grouped = groupRegisteredTestsForDisplay(tests); + + return ( + + + + {Object.entries(grouped).map(([filepath, { ungrouped, groups }]) => ( + + {'☰ '}{filepath} + + {ungrouped.map(test => { + const state = testStates[test.id]; + if (!state) return null; + return ( + + + + ); + })} + + {Object.entries(groups).map(([groupName, groupTests]) => ( + + {groupTests.map(test => { + const state = testStates[test.id]; + if (!state) return null; + return ( + + ); + })} + + ))} + + ))} + + + + + + + ); +} diff --git a/packages/magnitude-test/src/term-app/components/Summary.tsx b/packages/magnitude-test/src/term-app/components/Summary.tsx new file mode 100644 index 00000000..5667b022 --- /dev/null +++ b/packages/magnitude-test/src/term-app/components/Summary.tsx @@ -0,0 +1,73 @@ +import React from 'react'; +import { Box, Text } from 'ink'; +import { RegisteredTest } from '@/discovery/types'; +import { TestFailure } from '@/runner/state'; +import { AllTestStates } from '../types'; +import { calculateCost } from '@/util'; +import { FailureDisplay } from './FailureDisplay'; + +interface SummaryProps { + testStates: AllTestStates; + registeredTests: RegisteredTest[]; + model: string; +} + +export function Summary({ testStates, registeredTests, model }: SummaryProps) { + let totalInputTokens = 0; + let totalOutputTokens = 0; + const statusCounts = { pending: 0, running: 0, passed: 0, failed: 0, cancelled: 0 }; + const failuresWithContext: Array<{ filepath: string; groupName?: string; testTitle: string; failure: TestFailure }> = []; + + const testContextMap = new Map(); + for (const test of registeredTests) { + testContextMap.set(test.id, { filepath: test.filepath, groupName: test.group, testTitle: test.title }); + } + + for (const [testId, state] of Object.entries(testStates)) { + statusCounts[state.status]++; + if (state.modelUsage.length > 0) { + totalInputTokens += state.modelUsage[0].inputTokens; + totalOutputTokens += state.modelUsage[0].outputTokens; + } + if (state.failure) { + const context = testContextMap.get(testId); + failuresWithContext.push({ + filepath: context?.filepath ?? 'Unknown File', + groupName: context?.groupName, + testTitle: context?.testTitle ?? 'Unknown Test', + failure: state.failure, + }); + } + } + + let costDescription = ''; + const cost = calculateCost(model, totalInputTokens, totalOutputTokens); + if (cost !== undefined) { + costDescription = ` ($${cost.toFixed(2)})`; + } + + return ( + + + {statusCounts.passed > 0 && {'✓ '}{statusCounts.passed} passed} + {statusCounts.failed > 0 && {'✗ '}{statusCounts.failed} failed} + {statusCounts.running > 0 && {'▷ '}{statusCounts.running} running} + {statusCounts.pending > 0 && {'◌ '}{statusCounts.pending} pending} + {statusCounts.cancelled > 0 && {'⊘ '}{statusCounts.cancelled} cancelled} + tokens: {totalInputTokens} in, {totalOutputTokens} out{costDescription} + + + {failuresWithContext.length > 0 && ( + + Failures: + {failuresWithContext.map((f, i) => ( + + {f.filepath}{f.groupName ? ` > ${f.groupName}` : ''} {'> '}{f.testTitle} + + + ))} + + )} + + ); +} diff --git a/packages/magnitude-test/src/term-app/components/TestDisplay.tsx b/packages/magnitude-test/src/term-app/components/TestDisplay.tsx new file mode 100644 index 00000000..7411b628 --- /dev/null +++ b/packages/magnitude-test/src/term-app/components/TestDisplay.tsx @@ -0,0 +1,107 @@ +import React, { useState, useEffect } from 'react'; +import { Box, Text } from 'ink'; +import Spinner from 'ink-spinner'; +import { TestState, StepDescriptor, CheckDescriptor } from '@/runner/state'; +import { testStatus, stepStatus, checkStatus } from '../indicators'; +import { FailureDisplay } from './FailureDisplay'; +import { formatDuration } from '../util'; + +interface TestDisplayProps { + title: string; + state: TestState; + showActions: boolean; + showThoughts: boolean; +} + +export function TestDisplay({ title, state, showActions, showThoughts }: TestDisplayProps) { + const [elapsed, setElapsed] = useState(0); + + useEffect(() => { + if (state.status !== 'running' || !state.startedAt) { + if (state.startedAt && state.doneAt) { + setElapsed(state.doneAt - state.startedAt); + } + return; + } + setElapsed(Date.now() - state.startedAt); + const interval = setInterval(() => { + setElapsed(Date.now() - state.startedAt!); + }, 100); + return () => clearInterval(interval); + }, [state.status, state.startedAt, state.doneAt]); + + const ts = testStatus(state.status); + const timerText = state.status !== 'pending' ? ` [${formatDuration(elapsed)}]` : ''; + + return ( + + + {state.status === 'running' ? ( + + ) : ( + {ts.char} + )} + {title} + {timerText} + + + {state.stepsAndChecks.map((item, i) => ( + + ))} + + {state.failure && ( + + + + )} + + ); +} + +interface StepOrCheckDisplayProps { + item: StepDescriptor | CheckDescriptor; + showActions: boolean; + showThoughts: boolean; +} + +function StepOrCheckDisplay({ item, showActions, showThoughts }: StepOrCheckDisplayProps) { + const s = item.variant === 'step' ? stepStatus(item.status) : checkStatus(item.status); + + const merged: Array<{ kind: 'action' | 'thought'; text: string; t: number }> = []; + if (item.variant === 'step') { + if (showActions) { + for (const a of item.actions) { + merged.push({ kind: 'action', text: a.pretty, t: a.time }); + } + } + if (showThoughts) { + for (const th of item.thoughts) { + merged.push({ kind: 'thought', text: th.text, t: th.time }); + } + } + merged.sort((a, b) => a.t === b.t ? (a.kind === 'thought' ? -1 : 1) : a.t - b.t); + } + + return ( + + + {s.char} + {item.description} + + {merged.map((m, i) => ( + + {m.kind === 'thought' ? ( + {'💭 '}{m.text} + ) : ( + {m.text} + )} + + ))} + + ); +} diff --git a/packages/magnitude-test/src/term-app/components/TestGroupDisplay.tsx b/packages/magnitude-test/src/term-app/components/TestGroupDisplay.tsx new file mode 100644 index 00000000..8be9ae7e --- /dev/null +++ b/packages/magnitude-test/src/term-app/components/TestGroupDisplay.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { Box, Text } from 'ink'; + +interface TestGroupDisplayProps { + groupName: string; + children: React.ReactNode; +} + +export function TestGroupDisplay({ groupName, children }: TestGroupDisplayProps) { + return ( + + {'↳ '}{groupName} + + {children} + + + ); +} diff --git a/packages/magnitude-test/src/term-app/components/TitleBar.tsx b/packages/magnitude-test/src/term-app/components/TitleBar.tsx new file mode 100644 index 00000000..797b55aa --- /dev/null +++ b/packages/magnitude-test/src/term-app/components/TitleBar.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { Box, Text, Spacer } from 'ink'; +import { VERSION } from '@/version'; + +interface TitleBarProps { + model: string; +} + +export function TitleBar({ model }: TitleBarProps) { + return ( + + Magnitude v{VERSION} + + {model} + + ); +} diff --git a/packages/magnitude-test/src/term-app/constants.ts b/packages/magnitude-test/src/term-app/constants.ts index 0627c2dd..37118b2a 100644 --- a/packages/magnitude-test/src/term-app/constants.ts +++ b/packages/magnitude-test/src/term-app/constants.ts @@ -1,22 +1 @@ -// --- ANSI Escape Codes --- -export const ANSI_RESET = '\x1b[0m'; -export const ANSI_GREEN = '\x1b[32m'; -//export const ANSI_GREEN = '\x1b[32m'; -export const ANSI_BRIGHT_BLUE = '\x1b[94m'; -export const ANSI_GRAY = '\x1b[90m'; -export const ANSI_RED = '\x1b[31m'; -export const ANSI_BOLD = '\x1b[1m'; -export const ANSI_DIM = '\x1b[2m'; - -// --- Box Drawing Characters --- -// export const BOX_CHARS_ROUNDED = { -// topLeft: '╭', topRight: '╮', bottomLeft: '╰', bottomRight: '╯', -// horizontal: '─', vertical: '│' -// }; - -// --- Configuration --- export const MAX_APP_WIDTH = 100; -// export const PADDING = 2; - -// --- Spinner Characters --- -export const spinnerChars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; diff --git a/packages/magnitude-test/src/term-app/drawingUtils.ts b/packages/magnitude-test/src/term-app/drawingUtils.ts deleted file mode 100644 index 0218b8cf..00000000 --- a/packages/magnitude-test/src/term-app/drawingUtils.ts +++ /dev/null @@ -1,104 +0,0 @@ -//import { ActionDescriptor, FailureDescriptor } from 'magnitude-core'; -import { ANSI_RESET, ANSI_GREEN, ANSI_BRIGHT_BLUE, ANSI_GRAY, ANSI_RED } from './constants'; -import { TestState } from '@/runner/state'; - -/** - * Calculate the visible length of a string, accounting for ANSI escape codes. - * @param s The string to calculate the length for - * @returns The visible length of the string - */ -export const str = (s: string): number => { - // Basic ANSI escape code removal for length calculation - // This is a simplified version and might not cover all ANSI sequences. - const ansiRegex = /\x1b\[[0-9;]*[mGKH]/g; - return s.replace(ansiRegex, '').length; -}; - -// Box drawing functions removed as per user request to remove borders. -// createBoxAnsi was here -// insertLineIntoBoxAnsi was here - - -/** - * Get the status indicator character for a test. - * @param status Test status - * @returns Plain character symbol - */ -export function getTestStatusIndicatorChar(status: TestState['status']): string { - // Returns plain char - switch (status) { - case 'passed': return '✓'; - case 'failed': return '✕'; - case 'cancelled': return '⊘'; - case 'pending': - default: return '◌'; - } -} - -/** - * Get the status indicator character for a step. - * @param status Step status - * @returns Plain character symbol - */ -export function getStepStatusIndicatorChar(status: TestState['status']): string { - // Returns plain char - switch (status) { - case 'running': return '>'; case 'passed': return '⚑'; - case 'failed': return '✕'; case 'cancelled': return '⊘'; - case 'pending': default: return '•'; - } -} - -/** - * Get the status indicator character for a check. - * @param status Check status - * @returns Plain character symbol - */ -export function getCheckStatusIndicatorChar(status: TestState['status']): string { - // Returns plain char - switch (status) { - case 'running': return '?'; case 'passed': return '✓'; - case 'failed': return '✕'; case 'cancelled': return '⊘'; - case 'pending': default: return '•'; - } -} - -/** - * Apply styling to text based on status and type. - * @param status The status to style for - * @param text The text to style - * @param type The type of element being styled - * @returns String with ANSI codes - */ -export function styleAnsi(status: TestState['status'], text: string, type: 'test' | 'step' | 'check'): string { - // Returns string with ANSI codes - let colorCode = ANSI_GRAY; // Default gray - switch (type) { - case 'test': - switch (status) { - case 'running': colorCode = ANSI_BRIGHT_BLUE; break; - case 'passed': colorCode = ANSI_GREEN; break; - case 'failed': colorCode = ANSI_RED; break; - case 'cancelled': colorCode = ANSI_GRAY; break; - } - break; - case 'step': - switch (status) { - case 'running': colorCode = ANSI_GRAY; break; - case 'passed': colorCode = ANSI_BRIGHT_BLUE; break; - case 'failed': colorCode = ANSI_RED; break; - case 'cancelled': colorCode = ANSI_GRAY; break; - } - break; - case 'check': - switch (status) { - case 'running': colorCode = ANSI_GRAY; break; - case 'passed': colorCode = ANSI_BRIGHT_BLUE; break; - case 'failed': colorCode = ANSI_RED; break; - case 'cancelled': colorCode = ANSI_GRAY; break; - } - break; - } - // Important: Ensure reset code is appended - return `${colorCode}${text}${ANSI_RESET}`; -} diff --git a/packages/magnitude-test/src/term-app/index.ts b/packages/magnitude-test/src/term-app/index.ts index 122f4668..d9c2e836 100644 --- a/packages/magnitude-test/src/term-app/index.ts +++ b/packages/magnitude-test/src/term-app/index.ts @@ -1,16 +1 @@ -// This file is the entry point for the terminal application. -// Most of the core UI logic has been moved to TermAppRenderer.ts - -// Re-export specific components if needed by other parts of the application, -// otherwise, this file can remain minimal. - -// For example, if constants or specific utility functions from this directory -// are used broadly: -// export * from './constants'; -// export * from './util'; // Be careful with this, ensure no circular dependencies - -// The TermAppRenderer class is now the primary export for managing the terminal UI. export { TermAppRenderer } from './termAppRenderer'; - -// The uiState and uiRenderer modules export their own functions and variables -// and can be imported directly where needed. diff --git a/packages/magnitude-test/src/term-app/indicators.ts b/packages/magnitude-test/src/term-app/indicators.ts new file mode 100644 index 00000000..e0f2328d --- /dev/null +++ b/packages/magnitude-test/src/term-app/indicators.ts @@ -0,0 +1,36 @@ +import { TestStatus } from '@/runner/state'; + +export interface StatusStyle { + char: string; + color: string; // Ink color prop value +} + +export function testStatus(status: TestStatus): StatusStyle { + switch (status) { + case 'passed': return { char: '✓', color: 'green' }; + case 'failed': return { char: '✕', color: 'red' }; + case 'cancelled': return { char: '⊘', color: 'gray' }; + case 'running': return { char: '', color: 'blueBright' }; // spinner handled by component + case 'pending': return { char: '◌', color: 'gray' }; + } +} + +export function stepStatus(status: TestStatus): StatusStyle { + switch (status) { + case 'running': return { char: '>', color: 'gray' }; + case 'passed': return { char: '⚑', color: 'blueBright' }; + case 'failed': return { char: '✕', color: 'red' }; + case 'cancelled': return { char: '⊘', color: 'gray' }; + case 'pending': return { char: '•', color: 'gray' }; + } +} + +export function checkStatus(status: TestStatus): StatusStyle { + switch (status) { + case 'running': return { char: '?', color: 'gray' }; + case 'passed': return { char: '✓', color: 'blueBright' }; + case 'failed': return { char: '✕', color: 'red' }; + case 'cancelled': return { char: '⊘', color: 'gray' }; + case 'pending': return { char: '•', color: 'gray' }; + } +} diff --git a/packages/magnitude-test/src/term-app/termAppRenderer.ts b/packages/magnitude-test/src/term-app/termAppRenderer.ts index 1126be1f..55e7fa0c 100644 --- a/packages/magnitude-test/src/term-app/termAppRenderer.ts +++ b/packages/magnitude-test/src/term-app/termAppRenderer.ts @@ -1,196 +1,83 @@ -import { TestRenderer } from "@/renderer"; -import { RegisteredTest, MagnitudeConfig } from "@/discovery/types"; -import { TestState } from "@/runner/state"; -import { AllTestStates } from "./types"; // Import AllTestStates directly -import * as uiState from './uiState'; -import { scheduleRedraw, redraw } from './uiRenderer'; -import { describeModel } from '@/util'; // Import describeModel -// Import other necessary types and functions from term-app/index, term-app/util etc. as needed -// For now, let's assume logUpdate might be used directly or indirectly -import logUpdate from 'log-update'; -// import { MAX_APP_WIDTH } from "./constants"; // No longer used - -// Functions that might be moved or adapted from term-app/index.ts -// For now, keep them here or ensure they are imported if they remain in index.ts -// and are exported. -// We'll need to handle SIGINT and resize eventually. +import React from 'react'; +import { render } from 'ink'; +import { TestRenderer } from '@/renderer'; +import { RegisteredTest, MagnitudeConfig } from '@/discovery/types'; +import { TestState } from '@/runner/state'; +import { AllTestStates } from './types'; +import { InkApp, StateBridge } from './components/InkApp'; +import { describeModel } from '@/util'; export class TermAppRenderer implements TestRenderer { private magnitudeConfig: MagnitudeConfig; private initialTests: RegisteredTest[]; - private firstModelReportedInUI = false; // New flag - - // To manage SIGINT listener - private sigintListener: (() => void) | null = null; + private firstModelReportedInUI = false; - private applyDisplaySettings(): void { - const newSettings = { ...uiState.renderSettings }; - if (this.magnitudeConfig.display?.showActions !== undefined) { - newSettings.showActions = this.magnitudeConfig.display.showActions; - } - if (this.magnitudeConfig.display?.showThoughts !== undefined) { - newSettings.showThoughts = this.magnitudeConfig.display.showThoughts; - } - uiState.setRenderSettings(newSettings); - } + private bridge: StateBridge | null = null; + private testStates: AllTestStates = {}; + private inkInstance: ReturnType | null = null; constructor(config: MagnitudeConfig, initialTests: RegisteredTest[]) { this.magnitudeConfig = config; - this.initialTests = [...initialTests]; // Store a copy - - // Initial setup based on config, if needed immediately - this.applyDisplaySettings(); - uiState.setCurrentModel(""); // Set to blank - // uiState.setAllRegisteredTests will be called in start() after resetState() + this.initialTests = [...initialTests]; } public start(): void { - process.stdout.write('\n'); // Ensure output starts on a new line - uiState.resetState(); // Reset all UI state + process.stdout.write('\n'); - // Re-apply initial settings after reset - this.applyDisplaySettings(); - // uiState.setCurrentModel(""); // No longer needed here, resetState handles it. - this.firstModelReportedInUI = false; // Reset flag on start - uiState.setAllRegisteredTests(this.initialTests); // Set the tests - - // Initialize currentTestStates for all tests to 'pending' - const initialTestStates: AllTestStates = {}; // Use direct import + // Initialize all tests as pending for (const test of this.initialTests) { - initialTestStates[test.id] = { - status: 'pending', // Add initial status + this.testStates[test.id] = { + status: 'pending', stepsAndChecks: [], modelUsage: [], - // macroUsage: { provider: '', model: '', inputTokens: 0, outputTokens: 0, numCalls: 0 }, - // microUsage: { provider: '', numCalls: 0 }, }; } - uiState.setCurrentTestStates(initialTestStates); - uiState.setElapsedTimes({}); // Clear elapsed times - - // process.stdout.write('\n'); // Removed unnecessary newline - // logUpdate.clear(); // Removed screen clearing - // process.stdout.write('\x1b[2J\x1b[H'); // Removed screen clearing - - // Setup event listeners - this.sigintListener = this.handleExitKeyPress.bind(this); - - process.on('SIGINT', this.sigintListener); - - // Start the timer interval (adapted from original initializeUI) - if (!uiState.timerInterval) { - const interval = setInterval(() => { - if (uiState.isFinished) { - clearInterval(uiState.timerInterval!); - uiState.setTimerInterval(null); - return; - } - let runningTestsExist = false; - uiState.setSpinnerFrame((uiState.spinnerFrame + 1) % uiState.spinnerChars.length); - - Object.entries(uiState.currentTestStates).forEach(([testId, state]) => { - // Assuming TestState from runner will have a 'status' field - // For now, we need to check if the state itself implies running - // This part will be more robust once TestState includes status directly - // Now we can use the explicit status - const liveState = state as TestState; // Cast to full TestState from runner/state - if (liveState.status === 'running') { - runningTestsExist = true; - // Ensure startedAt is set if running, though TestStateTracker should handle this - if (liveState.startedAt) { - uiState.updateElapsedTime(testId, Date.now() - liveState.startedAt); - } else { - // This case should ideally not happen if TestState is correctly managed - // uiState.updateElapsedTime(testId, 0); - } - } - }); - if (runningTestsExist && !uiState.redrawScheduled) { // Only schedule if not already scheduled - scheduleRedraw(); // Direct call - } - }, 100); - uiState.setTimerInterval(interval); - } - - scheduleRedraw(); // Initial draw - Direct call - } - - public stop(): void { - if (uiState.isFinished) return; // Prevent double cleanup - uiState.setIsFinished(true); - - if (uiState.timerInterval) { - clearInterval(uiState.timerInterval); - uiState.setTimerInterval(null); - } - // Remove event listeners - if (this.sigintListener) { - process.removeListener('SIGINT', this.sigintListener); - this.sigintListener = null; - } - - redraw(); // Last draw to reflect final state - // logUpdate.done(); // Responsibility moved to redraw() when isFinished is true - // process.stderr.write('\n'); // Also moved to redraw() - // DO NOT call process.exit() here + this.firstModelReportedInUI = false; + + this.inkInstance = render( + React.createElement(InkApp, { + tests: this.initialTests, + config: this.magnitudeConfig, + initialStates: { ...this.testStates }, + onReady: (bridge: StateBridge) => { + this.bridge = bridge; + // Flush any updates that arrived before mount + bridge.update({ ...this.testStates }); + }, + }), + { exitOnCtrlC: false } + ); } public onTestStateUpdated(test: RegisteredTest, newState: TestState): void { - const currentStates = { ...uiState.currentTestStates }; - const testId = test.id; - - // Merge new state into existing state for the test - // Ensure startedAt is preserved if already set and newState doesn't have it - const existingState = currentStates[testId] || {}; - const updatedTestState = { - ...existingState, + const existing = this.testStates[test.id] || {}; + this.testStates[test.id] = { + ...existing, ...newState, - startedAt: newState.startedAt || existingState.startedAt, - }; - currentStates[testId] = updatedTestState; - - uiState.setCurrentTestStates(currentStates); + startedAt: newState.startedAt || existing.startedAt, + }; - // New logic to detect and set the first model for the UI + // Detect first model for the UI title bar if (!this.firstModelReportedInUI && newState.modelUsage && newState.modelUsage.length > 0) { - const firstModelEntry = newState.modelUsage[0]; - let modelNameToReport: string | undefined = undefined; - - if (firstModelEntry && firstModelEntry.llm) { - modelNameToReport = describeModel(firstModelEntry.llm); - } - - if (modelNameToReport) { - uiState.setCurrentModel(modelNameToReport); - this.firstModelReportedInUI = true; + if (firstModelEntry?.llm) { + const modelName = describeModel(firstModelEntry.llm); + if (modelName) { + this.bridge?.setModel(modelName); + this.firstModelReportedInUI = true; + } } } - // Handle startedAt and elapsedTimes - if (updatedTestState.startedAt && !updatedTestState.doneAt) { // Test is running or just started - if (!uiState.elapsedTimes[testId] || uiState.elapsedTimes[testId] === 0) { - // If it just started, set elapsed time to 0 or based on current time - uiState.updateElapsedTime(testId, Date.now() - updatedTestState.startedAt); - } - } else if (updatedTestState.startedAt && updatedTestState.doneAt) { // Test finished - uiState.updateElapsedTime(testId, updatedTestState.doneAt - updatedTestState.startedAt); - } - - scheduleRedraw(); // Direct call + // If bridge not ready yet, testStates is still buffered — flushed on mount + this.bridge?.update({ ...this.testStates }); } - // onResize method removed as per user request. - - // Adapted from term-app/index.ts - private handleExitKeyPress(): void { - // No longer distinguish between isFinished, just trigger stop - this.stop(); - // The TestSuiteRunner or CLI will handle actual process exit if needed after stop() completes. - // Forcing an exit here might preempt cleanup or final reporting. - // A second SIGINT will terminate if stop() doesn't lead to exit. + public stop(): void { + this.inkInstance?.unmount(); + process.stderr.write('\n'); } } diff --git a/packages/magnitude-test/src/term-app/uiRenderer.ts b/packages/magnitude-test/src/term-app/uiRenderer.ts deleted file mode 100644 index 6ade2f52..00000000 --- a/packages/magnitude-test/src/term-app/uiRenderer.ts +++ /dev/null @@ -1,395 +0,0 @@ -import { setImmediate } from "node:timers"; -import logUpdate from 'log-update'; -import { RegisteredTest } from '@/discovery/types'; -import { TestFailure, TestState as RunnerTestState, StepDescriptor as RunnerStepDescriptor, CheckDescriptor as RunnerCheckDescriptor } from '@/runner/state'; -import { AllTestStates } from './types'; -import { VERSION } from '@/version'; -import { formatDuration } from './util'; // wrapText removed -import { - ANSI_RESET, ANSI_GREEN, ANSI_BRIGHT_BLUE, - ANSI_GRAY, ANSI_RED, ANSI_BOLD, ANSI_DIM -} from './constants'; // PADDING, BOX_CHARS_ROUNDED removed -import { - str, styleAnsi, - getTestStatusIndicatorChar, - getStepStatusIndicatorChar, getCheckStatusIndicatorChar -} from './drawingUtils'; // createBoxAnsi, insertLineIntoBoxAnsi removed -import { - // currentWidth, // Will be unused if all wrapping is gone (now removed from uiState) - redrawScheduled, currentTestStates, allRegisteredTests, - currentModel, elapsedTimes, isFinished, spinnerFrame, - lastOutputLineCount, isFirstDraw, /* isResizing, */ renderSettings, // isResizing removed from uiState - setRedrawScheduled, setLastOutputLineCount, setIsFirstDraw, spinnerChars -} from './uiState'; -import { calculateCost } from '@/util'; - -const UI_LEFT_PADDING = ' '; - -/** - * Generate the title bar portion of the UI - * @returns Array of strings with ANSI codes representing the title bar - */ -export function generateTitleBarString(): string[] { - const titleText = `${ANSI_BRIGHT_BLUE}${ANSI_BOLD}Magnitude v${VERSION}${ANSI_RESET}`; - const modelText = `${ANSI_GRAY}${currentModel}${ANSI_RESET}`; - // Simple single line for title bar, no complex padding or width calculations - return [`${UI_LEFT_PADDING}${titleText} ${modelText}`]; -} - -/** - * Generate a string representation of a failure - */ -export function generateFailureString(failure: TestFailure, indent: number): string[] { - const output: string[] = []; - const prefix = '↳ '; - const prefixAnsi = `${ANSI_RED}${prefix}${ANSI_RESET}`; - - const addLine = (text: string, styleCode = ANSI_RED, bold = false) => { - const fullStyleCode = `${styleCode}${bold ? ANSI_BOLD : ''}`; - // No wrapping, text is a single line - output.push(UI_LEFT_PADDING + ' '.repeat(indent) + prefixAnsi + `${fullStyleCode}${text}${ANSI_RESET}`); - }; - - if (failure && failure.message) { - addLine(failure.message); - } else { - addLine("Unknown error details"); - } - return output; -} - -/** - * Generate a string representation of a test - */ -export function generateTestString(test: RegisteredTest, state: RunnerTestState, indent: number): string[] { - const output: string[] = []; - const testId = test.id; - const stepIndent = indent + 2; - const actionIndent = stepIndent + 2; - - const currentStatus = state.status; - const statusCharPlain = currentStatus === 'running' ? spinnerChars[spinnerFrame] : getTestStatusIndicatorChar(currentStatus); - const statusStyled = styleAnsi(currentStatus, statusCharPlain, 'test'); - const timerText = currentStatus !== 'pending' ? `${ANSI_GRAY} [${formatDuration(elapsedTimes[testId] ?? 0)}]${ANSI_RESET}` : ''; - - // No wrapping for title - output.push(UI_LEFT_PADDING + ' '.repeat(indent) + `${statusStyled} ${test.title}${timerText}`); - - if (state.stepsAndChecks && state.stepsAndChecks.length > 0) { - state.stepsAndChecks.forEach((item: RunnerStepDescriptor | RunnerCheckDescriptor) => { - let itemCharPlain = ''; - let itemDesc = ''; - let itemStyleType: 'step' | 'check' = 'step'; - - if (item.variant === 'step') { - itemCharPlain = getStepStatusIndicatorChar(item.status); - itemDesc = item.description; - itemStyleType = 'step'; - } else { // Check - itemCharPlain = getCheckStatusIndicatorChar(item.status); - itemDesc = item.description; - itemStyleType = 'check'; - } - - const styledChar = styleAnsi(item.status, itemCharPlain, itemStyleType); - // No wrapping for description - output.push(UI_LEFT_PADDING + ' '.repeat(stepIndent) + `${styledChar} ${itemDesc}`); - - if (item.variant === 'step') { - const actions = item.actions?.map(a => ({ - kind: 'action' as const, - text: a.pretty, - t: a.time - })) ?? []; - - const thoughts = item.thoughts?.map(th => ({ - kind: 'thought' as const, - text: th.text, - t: th.time - })) ?? []; - - const merged = [...thoughts, ...actions].sort((a, b) => - a.t === b.t ? (a.kind === 'thought' ? -1 : 1) : a.t - b.t - ); - - for (const mergedItem of merged) { - if (mergedItem.kind === 'thought' && renderSettings.showThoughts) { - output.push(UI_LEFT_PADDING + ' '.repeat(actionIndent) + `${ANSI_DIM}💭 ${mergedItem.text}${ANSI_RESET}`); - } else if (mergedItem.kind === 'action' && renderSettings.showActions) { - output.push(UI_LEFT_PADDING + ' '.repeat(actionIndent) + `${ANSI_GRAY}${mergedItem.text}${ANSI_RESET}`); - } - } - } - }); - } - - if (state.failure) { - const failureLines = generateFailureString(state.failure, stepIndent); - output.push(...failureLines); - } - return output; -} - -// Helper function to group tests for display -function groupRegisteredTestsForDisplay(tests: RegisteredTest[]): - Record }> { - const files: Record }> = {}; - for (const test of tests) { - if (!files[test.filepath]) { - files[test.filepath] = { ungrouped: [], groups: {} }; - } - if (test.group) { - if (!files[test.filepath].groups[test.group]) { - files[test.filepath].groups[test.group] = []; - } - files[test.filepath].groups[test.group].push(test); - } else { - files[test.filepath].ungrouped.push(test); - } - } - return files; -} - - -/** - * Generate the test list portion of the UI - */ -export function generateTestListString(): string[] { - const output: string[] = []; - const fileIndent = 0; - const groupIndent = fileIndent + 2; - const testBaseIndent = groupIndent; - - const groupedDisplayTests = groupRegisteredTestsForDisplay(allRegisteredTests); - - for (const [filepath, { ungrouped, groups }] of Object.entries(groupedDisplayTests)) { - const fileHeader = `${ANSI_BRIGHT_BLUE}${ANSI_BOLD}☰ ${filepath}${ANSI_RESET}`; - output.push(UI_LEFT_PADDING + ' '.repeat(fileIndent) + fileHeader); - - if (ungrouped.length > 0) { - for (const test of ungrouped) { - const state = currentTestStates[test.id]; - if (state) { - const testLines = generateTestString(test, state, testBaseIndent); - output.push(...testLines); - } - } - } - - if (Object.entries(groups).length > 0) { - for (const [groupName, groupTests] of Object.entries(groups)) { - const groupHeader = `${ANSI_BRIGHT_BLUE}${ANSI_BOLD}↳ ${groupName}${ANSI_RESET}`; - output.push(UI_LEFT_PADDING + ' '.repeat(groupIndent) + groupHeader); - - for (const test of groupTests) { - const state = currentTestStates[test.id]; - if (state) { - const testLines = generateTestString(test, state, testBaseIndent + 2); - output.push(...testLines); - } - } - } - } - output.push(UI_LEFT_PADDING); // Blank line between files/main groups - } - return output; -} - -/** - * Generate the summary portion of the UI - */ -export function generateSummaryString(): string[] { - const output: string[] = []; - let totalInputTokens = 0; - let totalOutputTokens = 0; - const statusCounts = { pending: 0, running: 0, passed: 0, failed: 0, cancelled: 0, total: 0 }; - const failuresWithContext: { filepath: string; groupName?: string; testTitle: string; failure: TestFailure }[] = []; - - const testContextMap = new Map(); - allRegisteredTests.forEach(test => { - testContextMap.set(test.id, { filepath: test.filepath, groupName: test.group, testTitle: test.title }); - }); - - Object.entries(currentTestStates).forEach(([testId, state]) => { - statusCounts.total++; - statusCounts[state.status]++; - if (state.modelUsage.length > 0) { - totalInputTokens += state.modelUsage[0].inputTokens; - totalOutputTokens += state.modelUsage[0].outputTokens; - } - if (state.failure) { - const context = testContextMap.get(testId); - failuresWithContext.push({ - filepath: context?.filepath ?? 'Unknown File', groupName: context?.groupName, - testTitle: context?.testTitle ?? 'Unknown Test', failure: state.failure - }); - } - }); - - const hasFailures = failuresWithContext.length > 0; - - let statusLine = ''; - if (statusCounts.passed > 0) statusLine += `${ANSI_GREEN}✓ ${statusCounts.passed} passed${ANSI_RESET} `; - if (statusCounts.failed > 0) statusLine += `${ANSI_RED}✗ ${statusCounts.failed} failed${ANSI_RESET} `; - if (statusCounts.running > 0) statusLine += `${ANSI_BRIGHT_BLUE}▷ ${statusCounts.running} running${ANSI_RESET} `; - if (statusCounts.pending > 0) statusLine += `${ANSI_GRAY}◌ ${statusCounts.pending} pending${ANSI_RESET} `; - if (statusCounts.cancelled > 0) statusLine += `${ANSI_GRAY}⊘ ${statusCounts.cancelled} cancelled${ANSI_RESET} `; - - let costDescription = ''; - const cost = calculateCost(currentModel, totalInputTokens, totalOutputTokens); - if (cost !== undefined) { - costDescription = ` (\$${cost.toFixed(2)})`; - } - let tokenText = `${ANSI_GRAY}tokens: ${totalInputTokens} in, ${totalOutputTokens} out${costDescription}${ANSI_RESET}`; - - output.push(UI_LEFT_PADDING + statusLine.trimEnd() + (statusLine && tokenText ? ' ' : '') + tokenText.trimStart()); - - if (hasFailures) { - output.push(UI_LEFT_PADDING + `${ANSI_DIM}Failures:${ANSI_RESET}`); - for (const { filepath, groupName, testTitle, failure } of failuresWithContext) { - const contextString = `${ANSI_DIM}${filepath}${groupName ? ` > ${groupName}` : ''} > ${testTitle}${ANSI_RESET}`; - output.push(UI_LEFT_PADDING + UI_LEFT_PADDING + contextString); // Indent context further with prepended spaces - const failureLines = generateFailureString(failure, 4); // generateFailureString already adds padding - output.push(...failureLines); - output.push(UI_LEFT_PADDING); // Blank line after each failure with prepended spaces - } - } - return output; -} - -/** - * Calculate the height needed for the test list (now just line count) - */ -export function calculateTestListHeight(tests: RegisteredTest[], testStates: AllTestStates): number { - let height = 0; - const groupedDisplayTests = groupRegisteredTestsForDisplay(tests); - - const addStepsAndChecksHeight = (state: RunnerTestState) => { - if (state.stepsAndChecks) { - state.stepsAndChecks.forEach((item: RunnerStepDescriptor | RunnerCheckDescriptor) => { - height++; // Item description line - if (item.variant === 'step') { - if (renderSettings.showActions) { - height += item.actions?.length ?? 0; - } - if (renderSettings.showThoughts) { - height += item.thoughts?.length ?? 0; - } - } - }); - } - }; - - for (const [filepath, { ungrouped, groups }] of Object.entries(groupedDisplayTests)) { - height++; // File header line - - if (ungrouped.length > 0) { - for (const test of ungrouped) { - const state = testStates[test.id]; - if (state) { - height++; // Test title line - addStepsAndChecksHeight(state); - if (state.failure) { - height++; // generateFailureString returns 1 line - } - } - } - } - - if (Object.entries(groups).length > 0) { - for (const [groupName, groupTests] of Object.entries(groups)) { - height++; // Group header line - for (const test of groupTests) { - const state = testStates[test.id]; - if (state) { - height++; // Test title line - addStepsAndChecksHeight(state); - if (state.failure) { - height++; // generateFailureString returns 1 line - } - } - } - } - } - height++; // Blank line between files - } - return height; -} - -/** - * Calculate the height needed for the summary (now just line count) - */ -export function calculateSummaryHeight(testStates: AllTestStates): number { - let height = 0; - height++; // Status counts line - - const failuresExist = Object.values(testStates).some(state => !!state.failure); - if (failuresExist) { - height++; // "Failures:" title - Object.values(testStates).forEach((state) => { - if (state.failure) { - height++; // Context line - height++; // Failure message line (generateFailureString returns 1 line) - height++; // Blank line after failure - } - }); - } - return height; -} - -/** - * Main function to redraw the UI - */ -export function redraw() { - setRedrawScheduled(false); - - let testListLineCount = calculateTestListHeight(allRegisteredTests, currentTestStates); - let summaryLineCount = calculateSummaryHeight(currentTestStates); - if (Object.values(currentTestStates).length === 0) { // No tests, no summary - summaryLineCount = 0; - testListLineCount = 0; - } - - const outputLines: string[] = []; - // outputLines.push(''); // Initial blank line for spacing from prompt - REMOVED - - outputLines.push(...generateTitleBarString()); // generateTitleBarString now adds padding - outputLines.push(UI_LEFT_PADDING); // Blank line after title bar with padding - - if (testListLineCount > 0) { - outputLines.push(...generateTestListString()); // generateTestListString now adds padding - // generateTestListString already adds a blank line (now with padding) at the end of each file section - } - - if (summaryLineCount > 0) { - if (testListLineCount > 0) outputLines.push(UI_LEFT_PADDING); // Blank line before summary if test list was also shown, with padding - outputLines.push(...generateSummaryString()); // generateSummaryString now adds padding - } - - const frameContent = outputLines.join('\n'); - - logUpdate.clear(); // Clear previous output before drawing new frame - logUpdate(frameContent); - - setLastOutputLineCount(outputLines.length); // Still useful for potential future optimizations - if (isFirstDraw) { // Still useful to track if it's the very first render pass - setIsFirstDraw(false); - } - - // If the rendering process has finished (stop() was called), - // then this redraw is the final one, so call logUpdate.done(). - if (isFinished) { - logUpdate.done(); - process.stderr.write('\n'); // Ensure prompt is on a new line after final output - } -} - -/** - * Schedule a UI redraw if one is not already scheduled - */ -export function scheduleRedraw() { - if (!redrawScheduled) { - setRedrawScheduled(true); - setImmediate(redraw); - } -} diff --git a/packages/magnitude-test/src/term-app/uiState.ts b/packages/magnitude-test/src/term-app/uiState.ts deleted file mode 100644 index a121cde8..00000000 --- a/packages/magnitude-test/src/term-app/uiState.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { RegisteredTest } from '@/discovery/types'; // Changed import -import { AllTestStates } from './types'; -import { MAX_APP_WIDTH, spinnerChars as localSpinnerChars } from './constants'; // Import and alias - -// --- UI State --- -// Export spinnerChars so TermAppRenderer can access it via uiState.spinnerChars -export const spinnerChars = localSpinnerChars; - -export interface RenderSettings { - showActions: boolean; - showThoughts: boolean; -} - -// currentWidth removed as it's no longer used for layout -export let redrawScheduled = false; -export let renderSettings: RenderSettings = { showActions: true, showThoughts: false }; -export let timerInterval: NodeJS.Timeout | null = null; -export let currentTestStates: AllTestStates = {}; -export let allRegisteredTests: RegisteredTest[] = []; // Changed from currentTests -export let currentModel = ''; -export let elapsedTimes: { [testId: string]: number } = {}; -export let isFinished = false; -export let spinnerFrame = 0; -export let lastOutputLineCount = 0; // Track lines for stability -export let isFirstDraw = true; // Flag to handle the first redraw specially -// resizeTimeout removed -// isResizing removed - -/** - * Resets all UI state to initial values - */ -export function resetState() { - // currentWidth reset removed - redrawScheduled = false; - renderSettings = { showActions: true, showThoughts: false }; // Reset render settings - timerInterval = null; - currentTestStates = {}; - allRegisteredTests = []; // Changed from currentTests - currentModel = ''; - elapsedTimes = {}; - isFinished = false; - spinnerFrame = 0; - lastOutputLineCount = 0; - isFirstDraw = true; - // resizeTimeout reset removed - // isResizing reset removed -} - -/** - * Sets the redrawScheduled flag - */ -export function setRedrawScheduled(value: boolean) { - redrawScheduled = value; -} - -/** - * Sets the lastOutputLineCount - */ -export function setLastOutputLineCount(count: number) { - lastOutputLineCount = count; -} - -/** - * Sets the isFirstDraw flag - */ -export function setIsFirstDraw(value: boolean) { - isFirstDraw = value; -} - -// setCurrentWidth removed -// setIsResizing removed -// setResizeTimeout removed - -/** - * Sets the currentModel - */ -export function setCurrentModel(model: string) { - currentModel = model; -} - -/** - * Sets the allRegisteredTests - */ -export function setAllRegisteredTests(tests: RegisteredTest[]) { // Changed signature - allRegisteredTests = tests; -} - -/** - * Sets the currentTestStates - */ -export function setCurrentTestStates(states: AllTestStates) { - currentTestStates = states; -} - -/** - * Sets the timerInterval - */ -export function setTimerInterval(interval: NodeJS.Timeout | null) { - timerInterval = interval; -} - -/** - * Sets the spinnerFrame - */ -export function setSpinnerFrame(frame: number) { - spinnerFrame = frame; -} - -/** - * Sets the elapsedTimes - */ -export function setElapsedTimes(times: { [testId: string]: number }) { - elapsedTimes = times; -} - -/** - * Updates a specific entry in the elapsedTimes map - */ -export function updateElapsedTime(testId: string, time: number) { - elapsedTimes[testId] = time; -} - -/** - * Sets the isFinished flag - */ -export function setIsFinished(value: boolean) { - isFinished = value; -} - -/** - * Sets the renderSettings - */ -export function setRenderSettings(settings: RenderSettings) { - renderSettings = settings; -} From 7da0fe35895683ffa0ca35ac4e32b6c4ff8ac4eb Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Wed, 4 Mar 2026 12:47:18 -0800 Subject: [PATCH 3/8] Add mouse:hover action to magnitude-core Allow the LLM planner to hover over elements to reveal dropdown menus, tooltips, and other hover-triggered content. Co-Authored-By: Claude Opus 4.6 --- packages/magnitude-core/src/actions/types.ts | 7 ++++++- packages/magnitude-core/src/actions/webActions.ts | 15 +++++++++++++++ packages/magnitude-core/src/web/harness.ts | 13 ++++++++++++- packages/magnitude-core/src/web/types.ts | 8 +++++++- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/packages/magnitude-core/src/actions/types.ts b/packages/magnitude-core/src/actions/types.ts index f4ecfe02..2f7f0815 100644 --- a/packages/magnitude-core/src/actions/types.ts +++ b/packages/magnitude-core/src/actions/types.ts @@ -10,7 +10,7 @@ export interface Action { [key: string]: any } -export type ActionIntent = ClickIntent | TypeIntent | ScrollIntent | SwitchTabIntent; // really we want switch tab to be an option only if >1 tab +export type ActionIntent = ClickIntent | HoverIntent | TypeIntent | ScrollIntent | SwitchTabIntent; // really we want switch tab to be an option only if >1 tab export type Intent = ActionIntent | CheckIntent; //export type Recipe = Ingredient[]; @@ -19,6 +19,11 @@ export interface ClickIntent { target: string; } +export interface HoverIntent { + variant: 'hover'; + target: string; +} + export interface TypeIntent { variant: 'type'; target: string; diff --git a/packages/magnitude-core/src/actions/webActions.ts b/packages/magnitude-core/src/actions/webActions.ts index 3a9bd101..048b5369 100644 --- a/packages/magnitude-core/src/actions/webActions.ts +++ b/packages/magnitude-core/src/actions/webActions.ts @@ -34,6 +34,20 @@ export const mouseDoubleClickAction = createAction({ render: ({ x, y }) => `⊙ double click (${x}, ${y})` }); +export const mouseHoverAction = createAction({ + name: 'mouse:hover', + description: "Hover over an element to reveal tooltips, dropdown menus, or hidden content", + schema: z.object({ + x: z.number().int(), + y: z.number().int(), + }), + resolver: async ({ input: { x, y }, agent }) => { + const web = agent.require(BrowserConnector); + await web.getHarness().hover({ x, y }); + }, + render: ({ x, y }) => `◎ hover (${x}, ${y})` +}); + export const mouseRightClickAction = createAction({ name: 'mouse:right_click', schema: z.object({ @@ -197,6 +211,7 @@ export const webActions = [ clickCoordAction, mouseDoubleClickAction, mouseRightClickAction, + mouseHoverAction, scrollCoordAction, mouseDragAction, newTabAction, diff --git a/packages/magnitude-core/src/web/harness.ts b/packages/magnitude-core/src/web/harness.ts index 28a610b0..f19d2185 100644 --- a/packages/magnitude-core/src/web/harness.ts +++ b/packages/magnitude-core/src/web/harness.ts @@ -1,5 +1,5 @@ import { Page, Browser, BrowserContext, PageScreenshotOptions } from "playwright"; -import { ClickWebAction, ScrollWebAction, SwitchTabWebAction, TypeWebAction, WebAction } from '@/web/types'; +import { ClickWebAction, HoverWebAction, ScrollWebAction, SwitchTabWebAction, TypeWebAction, WebAction } from '@/web/types'; import { PageStabilityAnalyzer } from "./stability"; import { parseTypeContent } from "./util"; import { ActionVisualizer, ActionVisualizerOptions } from "./visualizer"; @@ -288,6 +288,15 @@ export class WebHarness { // implements StateComponent await this.visualizer.showAll(); } + async hover({ x, y }: { x: number, y: number }, options?: { transform: boolean }) { + if (options?.transform ?? true) ({ x, y } = await this.transformCoordinates({ x, y })); + await Promise.all([ + this.visualizer.moveVirtualCursor(x, y), + this.page.mouse.move(x, y, { steps: 20 }) + ]); + await this.waitForStability(); + } + async rightClick({ x, y }: { x: number, y: number }, options?: { transform: boolean }) { if (options?.transform ?? true) ({ x, y } = await this.transformCoordinates({ x, y })); await this._click(x, y, { button: "right" }); @@ -391,6 +400,8 @@ export class WebHarness { // implements StateComponent async executeAction(action: WebAction) { if (action.variant === 'click') { await this.click(action); + } else if (action.variant === 'hover') { + await this.hover(action); } else if (action.variant === 'type') { await this.clickAndType(action); } else if (action.variant === 'scroll') { diff --git a/packages/magnitude-core/src/web/types.ts b/packages/magnitude-core/src/web/types.ts index 993ea39b..57bed800 100644 --- a/packages/magnitude-core/src/web/types.ts +++ b/packages/magnitude-core/src/web/types.ts @@ -14,7 +14,7 @@ export type Base64Image = `data:image/${'jpeg'|'png'|'gif'};base64,${string}`; // variant: ActionVariant // } -export type WebAction = NavigateWebAction | ClickWebAction | TypeWebAction | ScrollWebAction | SwitchTabWebAction; +export type WebAction = NavigateWebAction | ClickWebAction | HoverWebAction | TypeWebAction | ScrollWebAction | SwitchTabWebAction; // Currently only emitted synthetically export interface NavigateWebAction { @@ -28,6 +28,12 @@ export interface ClickWebAction { y: number } +export interface HoverWebAction { + variant: 'hover' + x: number + y: number +} + export interface TypeWebAction { variant: 'type' x: number From 7cdcbf507526fb279d4fd2d46fac7322c7870091 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Mon, 16 Mar 2026 21:43:37 -0700 Subject: [PATCH 4/8] Add BrowserProvider.reset() to close all browsers and clear singleton Idempotent static method that closes all active browsers, clears the activeBrowsers record, and removes the singleton from globalThis. Safe to call when no browsers exist or when browsers are already closed. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/web/browserProvider.test.ts | 57 +++++++++++++++++++ .../magnitude-core/src/web/browserProvider.ts | 17 ++++++ 2 files changed, 74 insertions(+) create mode 100644 packages/magnitude-core/src/web/browserProvider.test.ts diff --git a/packages/magnitude-core/src/web/browserProvider.test.ts b/packages/magnitude-core/src/web/browserProvider.test.ts new file mode 100644 index 00000000..1ef8e299 --- /dev/null +++ b/packages/magnitude-core/src/web/browserProvider.test.ts @@ -0,0 +1,57 @@ +import { describe, expect, test, beforeEach } from 'bun:test'; +import { BrowserProvider } from '@/web/browserProvider'; + +beforeEach(async () => { + // Ensure clean state before each test + await BrowserProvider.reset(); +}); + +describe('BrowserProvider.reset()', () => { + test('is idempotent when no instance exists', async () => { + expect((globalThis as any).__magnitude__?.browserProvider).toBeUndefined(); + // Should not throw + await BrowserProvider.reset(); + expect((globalThis as any).__magnitude__?.browserProvider).toBeUndefined(); + }); + + test('is idempotent when instance exists but has no browsers', async () => { + // Force creation of singleton with no active browsers + BrowserProvider.getInstance(); + expect((globalThis as any).__magnitude__.browserProvider).toBeDefined(); + + await BrowserProvider.reset(); + expect((globalThis as any).__magnitude__.browserProvider).toBeUndefined(); + }); + + test('closes active browsers and clears singleton', async () => { + const instance = BrowserProvider.getInstance(); + + // Create a context which launches a real browser + const context = await instance.newContext({ launchOptions: { headless: true } }); + + // Verify a browser is tracked + expect(Object.keys((instance as any).activeBrowsers).length).toBeGreaterThan(0); + + await BrowserProvider.reset(); + + // Singleton should be cleared + expect((globalThis as any).__magnitude__.browserProvider).toBeUndefined(); + + // activeBrowsers on the old instance should be empty + expect(Object.keys((instance as any).activeBrowsers).length).toBe(0); + }); + + test('does not throw if browser is already closed', async () => { + const instance = BrowserProvider.getInstance(); + const context = await instance.newContext({ launchOptions: { headless: true } }); + + // Close the browser before reset + const activeBrowser = Object.values((instance as any).activeBrowsers)[0] as any; + const browser = await activeBrowser.browserPromise; + await browser.close(); + + // reset() should still succeed + await BrowserProvider.reset(); + expect((globalThis as any).__magnitude__.browserProvider).toBeUndefined(); + }); +}); diff --git a/packages/magnitude-core/src/web/browserProvider.ts b/packages/magnitude-core/src/web/browserProvider.ts index 35266ad9..c77e5659 100644 --- a/packages/magnitude-core/src/web/browserProvider.ts +++ b/packages/magnitude-core/src/web/browserProvider.ts @@ -44,6 +44,23 @@ export class BrowserProvider { return (globalThis as any).__magnitude__.browserProvider; } + public static async reset(): Promise { + const instance: BrowserProvider | undefined = (globalThis as any).__magnitude__?.browserProvider; + if (!instance) return; + + for (const [key, activeBrowser] of Object.entries(instance.activeBrowsers)) { + try { + const browser = await activeBrowser.browserPromise; + await browser.close(); + } catch { + // Ignore errors (browser may already be closed) + } + delete instance.activeBrowsers[key]; + } + + (globalThis as any).__magnitude__.browserProvider = undefined; + } + private async _launchOrReuseBrowser(options: LaunchOptions): Promise { // hash options const hash = objectHash({ From f149c49a354501569daf5e7507aa4f4b4a36c520 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Mon, 16 Mar 2026 21:45:53 -0700 Subject: [PATCH 5/8] Simplify BrowserProvider.reset(): parallelize closes, remove unused vars Use Promise.allSettled for concurrent browser closing instead of sequential awaits. Replace per-key deletes with single object reset. Remove unused context variables in tests. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../magnitude-core/src/web/browserProvider.test.ts | 4 ++-- packages/magnitude-core/src/web/browserProvider.ts | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/magnitude-core/src/web/browserProvider.test.ts b/packages/magnitude-core/src/web/browserProvider.test.ts index 1ef8e299..2cca8fdb 100644 --- a/packages/magnitude-core/src/web/browserProvider.test.ts +++ b/packages/magnitude-core/src/web/browserProvider.test.ts @@ -27,7 +27,7 @@ describe('BrowserProvider.reset()', () => { const instance = BrowserProvider.getInstance(); // Create a context which launches a real browser - const context = await instance.newContext({ launchOptions: { headless: true } }); + await instance.newContext({ launchOptions: { headless: true } }); // Verify a browser is tracked expect(Object.keys((instance as any).activeBrowsers).length).toBeGreaterThan(0); @@ -43,7 +43,7 @@ describe('BrowserProvider.reset()', () => { test('does not throw if browser is already closed', async () => { const instance = BrowserProvider.getInstance(); - const context = await instance.newContext({ launchOptions: { headless: true } }); + await instance.newContext({ launchOptions: { headless: true } }); // Close the browser before reset const activeBrowser = Object.values((instance as any).activeBrowsers)[0] as any; diff --git a/packages/magnitude-core/src/web/browserProvider.ts b/packages/magnitude-core/src/web/browserProvider.ts index c77e5659..aa3ad880 100644 --- a/packages/magnitude-core/src/web/browserProvider.ts +++ b/packages/magnitude-core/src/web/browserProvider.ts @@ -48,16 +48,14 @@ export class BrowserProvider { const instance: BrowserProvider | undefined = (globalThis as any).__magnitude__?.browserProvider; if (!instance) return; - for (const [key, activeBrowser] of Object.entries(instance.activeBrowsers)) { - try { + await Promise.allSettled( + Object.values(instance.activeBrowsers).map(async (activeBrowser) => { const browser = await activeBrowser.browserPromise; await browser.close(); - } catch { - // Ignore errors (browser may already be closed) - } - delete instance.activeBrowsers[key]; - } + }) + ); + instance.activeBrowsers = {}; (globalThis as any).__magnitude__.browserProvider = undefined; } From 5b72ddf3be82f5c5f3a0d22e6bbb1fa360bf7196 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Mon, 16 Mar 2026 21:55:45 -0700 Subject: [PATCH 6/8] Re-export z from zod in magnitude-core public API Lets consumers write `import { z } from 'magnitude-core'` instead of reaching into node_modules, avoiding version mismatch and breakage on internal restructuring. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/magnitude-core/src/index.ts | 1 + .../magnitude-core/src/web/zodReexport.test.ts | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 packages/magnitude-core/src/web/zodReexport.test.ts diff --git a/packages/magnitude-core/src/index.ts b/packages/magnitude-core/src/index.ts index c502694e..be5d3ee5 100644 --- a/packages/magnitude-core/src/index.ts +++ b/packages/magnitude-core/src/index.ts @@ -23,6 +23,7 @@ export * from '@/common'; export * from "@/telemetry"; export { buildDefaultBrowserAgentOptions } from "@/ai/util"; export { logger } from './logger'; +export { z } from 'zod'; //export { ModelUsage } from '@/ai/modelHarness'; setLogLevel('OFF'); \ No newline at end of file diff --git a/packages/magnitude-core/src/web/zodReexport.test.ts b/packages/magnitude-core/src/web/zodReexport.test.ts new file mode 100644 index 00000000..31940823 --- /dev/null +++ b/packages/magnitude-core/src/web/zodReexport.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, test } from 'bun:test'; + +describe('z re-export', () => { + test('z.object() returns a valid schema via entry point', async () => { + const { z } = await import('@/index'); + const schema = z.object({ name: z.string() }); + const result = schema.safeParse({ name: 'test' }); + expect(result.success).toBe(true); + }); + + test('re-exported z is the same zod instance', async () => { + const { z: reexported } = await import('@/index'); + const { z: direct } = await import('zod'); + expect(reexported).toBe(direct); + }); +}); From e625e245d31515c18586e1a498dd592caad43fef Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Mon, 16 Mar 2026 22:03:43 -0700 Subject: [PATCH 7/8] Fix Summary token undercount and memoize stable computations Summary only read modelUsage[0], missing tokens from additional models. Also memoize groupRegisteredTestsForDisplay and testContextMap since their inputs are stable across re-renders. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/term-app/components/InkApp.tsx | 4 ++-- .../src/term-app/components/Summary.tsx | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/magnitude-test/src/term-app/components/InkApp.tsx b/packages/magnitude-test/src/term-app/components/InkApp.tsx index 4af84e56..8ce632fb 100644 --- a/packages/magnitude-test/src/term-app/components/InkApp.tsx +++ b/packages/magnitude-test/src/term-app/components/InkApp.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useMemo } from 'react'; import { Box, Text, useApp, useInput, useStdout } from 'ink'; import { RegisteredTest, MagnitudeConfig } from '@/discovery/types'; import { AllTestStates } from '../types'; @@ -59,7 +59,7 @@ export function InkApp({ tests, config, initialStates, onReady }: InkAppProps) { }); const width = Math.min(stdout?.columns ?? MAX_APP_WIDTH, MAX_APP_WIDTH); - const grouped = groupRegisteredTestsForDisplay(tests); + const grouped = useMemo(() => groupRegisteredTestsForDisplay(tests), [tests]); return ( diff --git a/packages/magnitude-test/src/term-app/components/Summary.tsx b/packages/magnitude-test/src/term-app/components/Summary.tsx index 5667b022..82e99289 100644 --- a/packages/magnitude-test/src/term-app/components/Summary.tsx +++ b/packages/magnitude-test/src/term-app/components/Summary.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { Box, Text } from 'ink'; import { RegisteredTest } from '@/discovery/types'; import { TestFailure } from '@/runner/state'; @@ -18,16 +18,19 @@ export function Summary({ testStates, registeredTests, model }: SummaryProps) { const statusCounts = { pending: 0, running: 0, passed: 0, failed: 0, cancelled: 0 }; const failuresWithContext: Array<{ filepath: string; groupName?: string; testTitle: string; failure: TestFailure }> = []; - const testContextMap = new Map(); - for (const test of registeredTests) { - testContextMap.set(test.id, { filepath: test.filepath, groupName: test.group, testTitle: test.title }); - } + const testContextMap = useMemo(() => { + const map = new Map(); + for (const test of registeredTests) { + map.set(test.id, { filepath: test.filepath, groupName: test.group, testTitle: test.title }); + } + return map; + }, [registeredTests]); for (const [testId, state] of Object.entries(testStates)) { statusCounts[state.status]++; - if (state.modelUsage.length > 0) { - totalInputTokens += state.modelUsage[0].inputTokens; - totalOutputTokens += state.modelUsage[0].outputTokens; + for (const usage of state.modelUsage) { + totalInputTokens += usage.inputTokens; + totalOutputTokens += usage.outputTokens; } if (state.failure) { const context = testContextMap.get(testId); From 792cfb7f9d101ce8798859826aa9a22ec0f08278 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Mon, 16 Mar 2026 22:18:43 -0700 Subject: [PATCH 8/8] Add publish script and scope magnitude-core to @ddwang Rename package to @ddwang/magnitude-core with prerelease version 0.3.1-ddwang.1 to avoid colliding with upstream. Add scripts/publish.sh for manual npm publishing with dry-run confirmation. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/magnitude-core/package.json | 4 ++-- scripts/publish.sh | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100755 scripts/publish.sh diff --git a/packages/magnitude-core/package.json b/packages/magnitude-core/package.json index ef5897e3..5379efbe 100644 --- a/packages/magnitude-core/package.json +++ b/packages/magnitude-core/package.json @@ -1,6 +1,6 @@ { - "name": "magnitude-core", - "version": "0.3.1", + "name": "@ddwang/magnitude-core", + "version": "0.3.1-ddwang.1", "description": "Magnitude e2e testing agent", "publishConfig": { "access": "public" diff --git a/scripts/publish.sh b/scripts/publish.sh new file mode 100755 index 00000000..5032bbca --- /dev/null +++ b/scripts/publish.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "$0")/../packages/magnitude-core" + +VERSION=$(node -p "require('./package.json').version") + +echo "=== Dry run: contents of @ddwang/magnitude-core@$VERSION ===" +npm pack --dry-run +echo "" + +echo "Publishing @ddwang/magnitude-core@$VERSION. Press enter to continue, Ctrl+C to abort." +read + +npm publish --access public