From d6367853aef34b5c5627e18014f9f8d0bdedaaac Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 13 May 2026 03:26:25 +0200 Subject: [PATCH] Add TUI notifications and attention sounds (disabled by default) (#26980) --- bun.lock | 390 +------------- bunfig.toml | 1 + package.json | 9 +- packages/opencode/package.json | 1 + packages/opencode/specs/tui-plugins.md | 34 ++ packages/opencode/specs/v2/notifications.md | 13 + packages/opencode/src/audio.d.ts | 5 + packages/opencode/src/cli/cmd/tui/app.tsx | 12 +- .../opencode/src/cli/cmd/tui/attention.ts | 261 ++++++++++ .../src/cli/cmd/tui/config/tui-schema.ts | 45 ++ .../opencode/src/cli/cmd/tui/config/tui.ts | 33 +- .../tui/feature-plugins/home/tips-view.tsx | 230 +++++++-- .../cli/cmd/tui/feature-plugins/home/tips.tsx | 4 +- .../feature-plugins/system/notifications.ts | 94 ++++ .../opencode/src/cli/cmd/tui/plugin/api.tsx | 2 + .../src/cli/cmd/tui/plugin/internal.ts | 2 + .../src/cli/cmd/tui/plugin/runtime.ts | 55 +- .../opencode/src/cli/cmd/tui/util/audio.ts | 58 +++ packages/opencode/src/util/filesystem.ts | 9 +- .../test/cli/cmd/tui/attention.test.ts | 484 ++++++++++++++++++ .../test/cli/cmd/tui/notifications.test.ts | 267 ++++++++++ .../test/cli/run/runtime.boot.test.ts | 75 ++- .../test/cli/tui/plugin-loader.test.ts | 80 +++ packages/opencode/test/config/tui.test.ts | 54 ++ packages/opencode/test/fixture/tui-plugin.ts | 19 +- packages/opencode/test/fixture/tui-runtime.ts | 12 +- packages/plugin/package.json | 6 +- packages/plugin/src/tui.ts | 81 +++ packages/ui/src/assets/audio/alert-01.mp3 | Bin 0 -> 11436 bytes packages/ui/src/assets/audio/alert-02.mp3 | Bin 0 -> 8667 bytes packages/ui/src/assets/audio/alert-03.mp3 | Bin 0 -> 3197 bytes packages/ui/src/assets/audio/alert-04.mp3 | Bin 0 -> 7369 bytes packages/ui/src/assets/audio/alert-05.mp3 | Bin 0 -> 7603 bytes packages/ui/src/assets/audio/alert-06.mp3 | Bin 0 -> 7516 bytes packages/ui/src/assets/audio/alert-07.mp3 | Bin 0 -> 6741 bytes packages/ui/src/assets/audio/alert-08.mp3 | Bin 0 -> 6171 bytes packages/ui/src/assets/audio/alert-09.mp3 | Bin 0 -> 5752 bytes packages/ui/src/assets/audio/alert-10.mp3 | Bin 0 -> 10780 bytes packages/ui/src/assets/audio/bip-bop-01.mp3 | Bin 0 -> 4574 bytes packages/ui/src/assets/audio/bip-bop-02.mp3 | Bin 0 -> 5697 bytes packages/ui/src/assets/audio/bip-bop-03.mp3 | Bin 0 -> 4186 bytes packages/ui/src/assets/audio/bip-bop-04.mp3 | Bin 0 -> 5436 bytes packages/ui/src/assets/audio/bip-bop-05.mp3 | Bin 0 -> 3534 bytes packages/ui/src/assets/audio/bip-bop-06.mp3 | Bin 0 -> 5796 bytes packages/ui/src/assets/audio/bip-bop-07.mp3 | Bin 0 -> 3925 bytes packages/ui/src/assets/audio/bip-bop-08.mp3 | Bin 0 -> 4390 bytes packages/ui/src/assets/audio/bip-bop-09.mp3 | Bin 0 -> 8654 bytes packages/ui/src/assets/audio/bip-bop-10.mp3 | Bin 0 -> 6760 bytes packages/ui/src/assets/audio/nope-01.mp3 | Bin 0 -> 3195 bytes packages/ui/src/assets/audio/nope-02.mp3 | Bin 0 -> 5753 bytes packages/ui/src/assets/audio/nope-03.mp3 | Bin 0 -> 3820 bytes packages/ui/src/assets/audio/nope-04.mp3 | Bin 0 -> 3562 bytes packages/ui/src/assets/audio/nope-05.mp3 | Bin 0 -> 5858 bytes packages/ui/src/assets/audio/nope-06.mp3 | Bin 0 -> 6066 bytes packages/ui/src/assets/audio/nope-07.mp3 | Bin 0 -> 3459 bytes packages/ui/src/assets/audio/nope-08.mp3 | Bin 0 -> 7450 bytes packages/ui/src/assets/audio/nope-09.mp3 | Bin 0 -> 5960 bytes packages/ui/src/assets/audio/nope-10.mp3 | Bin 0 -> 3981 bytes packages/ui/src/assets/audio/nope-11.mp3 | Bin 0 -> 13681 bytes packages/ui/src/assets/audio/nope-12.mp3 | Bin 0 -> 11595 bytes .../ui/src/assets/audio/staplebops-01.mp3 | Bin 0 -> 3665 bytes .../ui/src/assets/audio/staplebops-02.mp3 | Bin 0 -> 3898 bytes .../ui/src/assets/audio/staplebops-03.mp3 | Bin 0 -> 5905 bytes .../ui/src/assets/audio/staplebops-04.mp3 | Bin 0 -> 4553 bytes .../ui/src/assets/audio/staplebops-05.mp3 | Bin 0 -> 3458 bytes .../ui/src/assets/audio/staplebops-06.mp3 | Bin 0 -> 4971 bytes .../ui/src/assets/audio/staplebops-07.mp3 | Bin 0 -> 10376 bytes packages/ui/src/assets/audio/yup-01.mp3 | Bin 0 -> 4418 bytes packages/ui/src/assets/audio/yup-02.mp3 | Bin 0 -> 6061 bytes packages/ui/src/assets/audio/yup-03.mp3 | Bin 0 -> 7575 bytes packages/ui/src/assets/audio/yup-04.mp3 | Bin 0 -> 8674 bytes packages/ui/src/assets/audio/yup-05.mp3 | Bin 0 -> 10339 bytes packages/ui/src/assets/audio/yup-06.mp3 | Bin 0 -> 5905 bytes 73 files changed, 1856 insertions(+), 480 deletions(-) create mode 100644 packages/opencode/specs/v2/notifications.md create mode 100644 packages/opencode/src/cli/cmd/tui/attention.ts create mode 100644 packages/opencode/src/cli/cmd/tui/feature-plugins/system/notifications.ts create mode 100644 packages/opencode/src/cli/cmd/tui/util/audio.ts create mode 100644 packages/opencode/test/cli/cmd/tui/attention.test.ts create mode 100644 packages/opencode/test/cli/cmd/tui/notifications.test.ts create mode 100644 packages/ui/src/assets/audio/alert-01.mp3 create mode 100644 packages/ui/src/assets/audio/alert-02.mp3 create mode 100644 packages/ui/src/assets/audio/alert-03.mp3 create mode 100644 packages/ui/src/assets/audio/alert-04.mp3 create mode 100644 packages/ui/src/assets/audio/alert-05.mp3 create mode 100644 packages/ui/src/assets/audio/alert-06.mp3 create mode 100644 packages/ui/src/assets/audio/alert-07.mp3 create mode 100644 packages/ui/src/assets/audio/alert-08.mp3 create mode 100644 packages/ui/src/assets/audio/alert-09.mp3 create mode 100644 packages/ui/src/assets/audio/alert-10.mp3 create mode 100644 packages/ui/src/assets/audio/bip-bop-01.mp3 create mode 100644 packages/ui/src/assets/audio/bip-bop-02.mp3 create mode 100644 packages/ui/src/assets/audio/bip-bop-03.mp3 create mode 100644 packages/ui/src/assets/audio/bip-bop-04.mp3 create mode 100644 packages/ui/src/assets/audio/bip-bop-05.mp3 create mode 100644 packages/ui/src/assets/audio/bip-bop-06.mp3 create mode 100644 packages/ui/src/assets/audio/bip-bop-07.mp3 create mode 100644 packages/ui/src/assets/audio/bip-bop-08.mp3 create mode 100644 packages/ui/src/assets/audio/bip-bop-09.mp3 create mode 100644 packages/ui/src/assets/audio/bip-bop-10.mp3 create mode 100644 packages/ui/src/assets/audio/nope-01.mp3 create mode 100644 packages/ui/src/assets/audio/nope-02.mp3 create mode 100644 packages/ui/src/assets/audio/nope-03.mp3 create mode 100644 packages/ui/src/assets/audio/nope-04.mp3 create mode 100644 packages/ui/src/assets/audio/nope-05.mp3 create mode 100644 packages/ui/src/assets/audio/nope-06.mp3 create mode 100644 packages/ui/src/assets/audio/nope-07.mp3 create mode 100644 packages/ui/src/assets/audio/nope-08.mp3 create mode 100644 packages/ui/src/assets/audio/nope-09.mp3 create mode 100644 packages/ui/src/assets/audio/nope-10.mp3 create mode 100644 packages/ui/src/assets/audio/nope-11.mp3 create mode 100644 packages/ui/src/assets/audio/nope-12.mp3 create mode 100644 packages/ui/src/assets/audio/staplebops-01.mp3 create mode 100644 packages/ui/src/assets/audio/staplebops-02.mp3 create mode 100644 packages/ui/src/assets/audio/staplebops-03.mp3 create mode 100644 packages/ui/src/assets/audio/staplebops-04.mp3 create mode 100644 packages/ui/src/assets/audio/staplebops-05.mp3 create mode 100644 packages/ui/src/assets/audio/staplebops-06.mp3 create mode 100644 packages/ui/src/assets/audio/staplebops-07.mp3 create mode 100644 packages/ui/src/assets/audio/yup-01.mp3 create mode 100644 packages/ui/src/assets/audio/yup-02.mp3 create mode 100644 packages/ui/src/assets/audio/yup-03.mp3 create mode 100644 packages/ui/src/assets/audio/yup-04.mp3 create mode 100644 packages/ui/src/assets/audio/yup-05.mp3 create mode 100644 packages/ui/src/assets/audio/yup-06.mp3 diff --git a/bun.lock b/bun.lock index 8e7a63a2ee..76602e8852 100644 --- a/bun.lock +++ b/bun.lock @@ -397,6 +397,7 @@ "@opencode-ai/plugin": "workspace:*", "@opencode-ai/script": "workspace:*", "@opencode-ai/sdk": "workspace:*", + "@opencode-ai/ui": "workspace:*", "@openrouter/ai-sdk-provider": "2.8.1", "@opentelemetry/api": "1.9.0", "@opentelemetry/context-async-hooks": "2.6.1", @@ -507,9 +508,9 @@ "typescript": "catalog:", }, "peerDependencies": { - "@opentui/core": ">=0.2.6", - "@opentui/keymap": ">=0.2.6", - "@opentui/solid": ">=0.2.6", + "@opentui/core": ">=0.2.8", + "@opentui/keymap": ">=0.2.8", + "@opentui/solid": ">=0.2.8", }, "optionalPeers": [ "@opentui/core", @@ -676,6 +677,9 @@ "@silvia-odwyer/photon-node@0.3.4": "patches/@silvia-odwyer%2Fphoton-node@0.3.4.patch", }, "overrides": { + "@opentui/core": "catalog:", + "@opentui/keymap": "catalog:", + "@opentui/solid": "catalog:", "@types/bun": "catalog:", "@types/node": "catalog:", }, @@ -689,9 +693,9 @@ "@npmcli/arborist": "9.4.0", "@octokit/rest": "22.0.0", "@openauthjs/openauth": "0.0.0-20250322224806", - "@opentui/core": "0.2.6", - "@opentui/keymap": "0.2.6", - "@opentui/solid": "0.2.6", + "@opentui/core": "0.2.8", + "@opentui/keymap": "0.2.8", + "@opentui/solid": "0.2.8", "@pierre/diffs": "1.1.0-beta.18", "@playwright/test": "1.59.1", "@sentry/solid": "10.36.0", @@ -1070,8 +1074,6 @@ "@develar/schema-utils": ["@develar/schema-utils@2.6.5", "", { "dependencies": { "ajv": "^6.12.0", "ajv-keywords": "^3.4.1" } }, "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig=="], - "@dimforge/rapier2d-simd-compat": ["@dimforge/rapier2d-simd-compat@0.17.3", "", {}, "sha512-bijvwWz6NHsNj5e5i1vtd3dU2pDhthSaTUZSh14DUGGKJfw8eMnlWZsxwHBxB/a3AXVNDjL9abuHw1k9FGR+jg=="], - "@dot/log": ["@dot/log@0.1.5", "", { "dependencies": { "chalk": "^4.1.2", "loglevelnext": "^6.0.0", "p-defer": "^3.0.0" } }, "sha512-ECraEVJWv2f2mWK93lYiefUkphStVlKD6yKDzisuoEmxuLKrxO9iGetHK2DoEAkj7sxjE886n0OUVVCUx0YPNg=="], "@drizzle-team/brocli": ["@drizzle-team/brocli@0.11.0", "", {}, "sha512-hD3pekGiPg0WPCCGAZmusBBJsDqGUR66Y452YgQsZOnkdQ7ViEPKuyP4huUGEZQefp8g34RRodXYmJ2TbCH+tg=="], @@ -1288,62 +1290,6 @@ "@isaacs/string-locale-compare": ["@isaacs/string-locale-compare@1.1.0", "", {}, "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ=="], - "@jimp/core": ["@jimp/core@1.6.0", "", { "dependencies": { "@jimp/file-ops": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "await-to-js": "^3.0.0", "exif-parser": "^0.1.12", "file-type": "^16.0.0", "mime": "3" } }, "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w=="], - - "@jimp/diff": ["@jimp/diff@1.6.0", "", { "dependencies": { "@jimp/plugin-resize": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "pixelmatch": "^5.3.0" } }, "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw=="], - - "@jimp/file-ops": ["@jimp/file-ops@1.6.0", "", {}, "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ=="], - - "@jimp/js-bmp": ["@jimp/js-bmp@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "bmp-ts": "^1.0.9" } }, "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw=="], - - "@jimp/js-gif": ["@jimp/js-gif@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "gifwrap": "^0.10.1", "omggif": "^1.0.10" } }, "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g=="], - - "@jimp/js-jpeg": ["@jimp/js-jpeg@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "jpeg-js": "^0.4.4" } }, "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA=="], - - "@jimp/js-png": ["@jimp/js-png@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "pngjs": "^7.0.0" } }, "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg=="], - - "@jimp/js-tiff": ["@jimp/js-tiff@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "utif2": "^4.1.0" } }, "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw=="], - - "@jimp/plugin-blit": ["@jimp/plugin-blit@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA=="], - - "@jimp/plugin-blur": ["@jimp/plugin-blur@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/utils": "1.6.0" } }, "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw=="], - - "@jimp/plugin-circle": ["@jimp/plugin-circle@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "zod": "^3.23.8" } }, "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw=="], - - "@jimp/plugin-color": ["@jimp/plugin-color@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "tinycolor2": "^1.6.0", "zod": "^3.23.8" } }, "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA=="], - - "@jimp/plugin-contain": ["@jimp/plugin-contain@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/plugin-blit": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ=="], - - "@jimp/plugin-cover": ["@jimp/plugin-cover@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/plugin-crop": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/types": "1.6.0", "zod": "^3.23.8" } }, "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA=="], - - "@jimp/plugin-crop": ["@jimp/plugin-crop@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang=="], - - "@jimp/plugin-displace": ["@jimp/plugin-displace@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q=="], - - "@jimp/plugin-dither": ["@jimp/plugin-dither@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0" } }, "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ=="], - - "@jimp/plugin-fisheye": ["@jimp/plugin-fisheye@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA=="], - - "@jimp/plugin-flip": ["@jimp/plugin-flip@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "zod": "^3.23.8" } }, "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg=="], - - "@jimp/plugin-hash": ["@jimp/plugin-hash@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/js-bmp": "1.6.0", "@jimp/js-jpeg": "1.6.0", "@jimp/js-png": "1.6.0", "@jimp/js-tiff": "1.6.0", "@jimp/plugin-color": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "any-base": "^1.1.0" } }, "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q=="], - - "@jimp/plugin-mask": ["@jimp/plugin-mask@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "zod": "^3.23.8" } }, "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA=="], - - "@jimp/plugin-print": ["@jimp/plugin-print@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/js-jpeg": "1.6.0", "@jimp/js-png": "1.6.0", "@jimp/plugin-blit": "1.6.0", "@jimp/types": "1.6.0", "parse-bmfont-ascii": "^1.0.6", "parse-bmfont-binary": "^1.0.6", "parse-bmfont-xml": "^1.1.6", "simple-xml-to-json": "^1.2.2", "zod": "^3.23.8" } }, "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A=="], - - "@jimp/plugin-quantize": ["@jimp/plugin-quantize@1.6.0", "", { "dependencies": { "image-q": "^4.0.0", "zod": "^3.23.8" } }, "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg=="], - - "@jimp/plugin-resize": ["@jimp/plugin-resize@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "zod": "^3.23.8" } }, "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA=="], - - "@jimp/plugin-rotate": ["@jimp/plugin-rotate@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/plugin-crop": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw=="], - - "@jimp/plugin-threshold": ["@jimp/plugin-threshold@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/plugin-color": "1.6.0", "@jimp/plugin-hash": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w=="], - - "@jimp/types": ["@jimp/types@1.6.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg=="], - - "@jimp/utils": ["@jimp/utils@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "tinycolor2": "^1.6.0" } }, "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA=="], - "@joshwooding/vite-plugin-react-docgen-typescript": ["@joshwooding/vite-plugin-react-docgen-typescript@0.7.0", "", { "dependencies": { "glob": "^13.0.1", "react-docgen-typescript": "^2.2.2" }, "peerDependencies": { "typescript": ">= 4.3.x", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["typescript"] }, "sha512-qvsTEwEFefhdirGOPnu9Wp6ChfIwy2dBCRuETU3uE+4cC+PFoxMSiiEhxk4lOluA34eARHA0OxqsEUYDqRMgeQ=="], "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], @@ -1616,23 +1562,23 @@ "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.40.0", "", {}, "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw=="], - "@opentui/core": ["@opentui/core@0.2.6", "", { "dependencies": { "bun-ffi-structs": "0.2.2", "diff": "9.0.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@opentui/core-darwin-arm64": "0.2.6", "@opentui/core-darwin-x64": "0.2.6", "@opentui/core-linux-arm64": "0.2.6", "@opentui/core-linux-x64": "0.2.6", "@opentui/core-win32-arm64": "0.2.6", "@opentui/core-win32-x64": "0.2.6" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-dBpMaWVM7wtW2/2TlGPrkPjg6gOL3MVU/5XXk+U1LDJB8L4q4NeYWVdzfAVNcEvgmuuCy/cVqdY2D4ei+e7MMg=="], + "@opentui/core": ["@opentui/core@0.2.8", "", { "dependencies": { "bun-ffi-structs": "0.2.2", "diff": "9.0.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@opentui/core-darwin-arm64": "0.2.8", "@opentui/core-darwin-x64": "0.2.8", "@opentui/core-linux-arm64": "0.2.8", "@opentui/core-linux-x64": "0.2.8", "@opentui/core-win32-arm64": "0.2.8", "@opentui/core-win32-x64": "0.2.8" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-bRRiCXuwjS8/6mN1oA5iVaf55z9APyalm7FnoxkLkEyIU1VDaQeTpYtElBbfo1rxtcO6Rj53XywH9oW8auNO9A=="], - "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.2.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-hR5nsxNj+059utzenTCF0kealUlibON6fLuebFUCGM/5kJnqa+shIh0XbUDFm0+F47vqVUgZufBdUuieQZIbvQ=="], + "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.2.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Qh6VCMQgW3hWh/7MR51y+XuQezh8NOLwKS8EQSoKzAr4VOc/W5P0/DvgMKgwaqXw2Mz0AIba/BvZ6by20yc4zA=="], - "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.2.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-pJ/bH4WC/mbBaakM1YdH6TVo67jhy0KPd61bCz97w0I/PJGr8fmNKvhmMt/AwyFgOQi3FYZiEKLMpGdvUcSsrQ=="], + "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.2.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-wQjJ38C3IiVx/gwwBYxnCarzgD75FdS7IyUErt3lhn57XriNiCbb7ScphWnRMwwtL8CI+bBGzClroDRA2lCfvg=="], - "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.2.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Pnd3kOxig8ii+/IqYheOPEgferylsQA0L6tKBnHQ9jRlCJOcu0Rv65Jepueh212vevdV9DzPURJnhejG06J6g=="], + "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.2.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-fx4ADeWSSSVU1O/MkMnklCRxtWRy6CLeAvktLlNdPb+BhmQIDg1kpZcdv7m/3cgD1/ksFEXIwO6VTvfKYE0umw=="], - "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.2.6", "", { "os": "linux", "cpu": "x64" }, "sha512-458Mx9tBzEPzfft8cSt5ZaIpEepoxBXBOL6AUVmDTKWaZ3uouraPcEKraGAyvOTDQp2XDI3R8c/2GdaR77FaUQ=="], + "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.2.8", "", { "os": "linux", "cpu": "x64" }, "sha512-4ekUyzopBj2ClsUbneLnUOrmZtvU67FCVFLgmBfKL4IvVl/P0YobGNg71gN1JNiYpY7hK77qOpidVLHcNMIE7w=="], - "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.2.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-BDUrdrT1RCcVnQoHJmUut4y811jDBAEtc6GJFB4Gs265Be8SrTjVCus6p2fSQ7j9sZQ1OcjO+5+4NkheSZICDQ=="], + "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.2.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-63K046wpzTzQOLOG9LTsp3+Ld0TNTxeQczexkg0pKSBxZFhws+/9YIGjTctZmJUfE1g1X4tI31dO+KNRpXRHQw=="], - "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.2.6", "", { "os": "win32", "cpu": "x64" }, "sha512-SUYAzRJ9TSoD2Qt8kn6FJz6dbTrFEPVig5mScB4zFGgGQO/Bbod2/Q31vLS/IQrX+FDb67WaErD+kuMCnMPPLA=="], + "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.2.8", "", { "os": "win32", "cpu": "x64" }, "sha512-+WDiTlTyDpgkis8rPAhW1fS7TwXJih+fk+RYXS2bC3tAKsRD+O3PRSkVABRbjkuXbtfJZf2cjOHZFGN4Vf5qDg=="], - "@opentui/keymap": ["@opentui/keymap@0.2.6", "", { "dependencies": { "@opentui/core": "0.2.6" }, "peerDependencies": { "@opentui/react": "0.2.6", "@opentui/solid": "0.2.6", "react": ">=19.2.0", "solid-js": "1.9.12" }, "optionalPeers": ["@opentui/react", "@opentui/solid", "react", "solid-js"] }, "sha512-+6OYuedrFCKVo4ryGFNwws++2VOmPcXU3PwpY0mP47gYQY2nvQ+etWIs2Y7r5eMIqUfxVCldkKsrzcEcA4tb/A=="], + "@opentui/keymap": ["@opentui/keymap@0.2.8", "", { "dependencies": { "@opentui/core": "0.2.8" }, "peerDependencies": { "@opentui/react": "0.2.8", "@opentui/solid": "0.2.8", "react": ">=19.2.0", "solid-js": "1.9.12" }, "optionalPeers": ["@opentui/react", "@opentui/solid", "react", "solid-js"] }, "sha512-/H9j8fP64cf3/nFDCvVP8+7cwU/oRh4sgfQH2NhcPp8illgBb/e9pG5x3vM0nK4RVyTqUvkPXsOeIX5u7vltlg=="], - "@opentui/solid": ["@opentui/solid@0.2.6", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.2.6", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-2y225WlOGi/fCaajkxBmLyVW8Cr+OmhowHdvrYcz5w2kBD15sKbJLIYu1G9DxceirT1uIyasGy2TGzRRcVkTDg=="], + "@opentui/solid": ["@opentui/solid@0.2.8", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.2.8", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-f2g0riBuzk4/ZmcJnp1k13odUmNZcfA3nF7RzdSlEfpkwNDfc4xqnRAwYbNNDwGNrJX0JDCTEZY5ZEhuL155MQ=="], "@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="], @@ -2284,8 +2230,6 @@ "@thisbeyond/solid-dnd": ["@thisbeyond/solid-dnd@0.7.5", "", { "peerDependencies": { "solid-js": "^1.5" } }, "sha512-DfI5ff+yYGpK9M21LhYwIPlbP2msKxN2ARwuu6GF8tT1GgNVDTI8VCQvH4TJFoVApP9d44izmAcTh/iTCH2UUw=="], - "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], - "@tsconfig/bun": ["@tsconfig/bun@1.0.9", "", {}, "sha512-4M0/Ivfwcpz325z6CwSifOBZYji3DFOEpY6zEUt0+Xi2qRhzwvmqQN9XAHJh3OVvRJuAqVTLU2abdCplvp6mwQ=="], "@tsconfig/node22": ["@tsconfig/node22@22.0.2", "", {}, "sha512-Kmwj4u8sDRDrMYRoN9FDEcXD8UpBSaPQQ24Gz+Gamqfm7xxn+GBR7ge/Z7pK8OXNGyUzbSwJj+TH6B+DS/epyA=="], @@ -2550,8 +2494,6 @@ "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="], - "any-base": ["any-base@1.1.0", "", {}, "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg=="], - "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], @@ -2620,8 +2562,6 @@ "avvio": ["avvio@9.2.0", "", { "dependencies": { "@fastify/error": "^4.0.0", "fastq": "^1.17.1" } }, "sha512-2t/sy01ArdHHE0vRH5Hsay+RtCZt3dLPji7W7/MMOCEgze5b7SNDC4j5H6FnVgPkI1MTNFGzHdHrVXDDl7QSSQ=="], - "await-to-js": ["await-to-js@3.0.0", "", {}, "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g=="], - "aws-sdk": ["aws-sdk@2.1692.0", "", { "dependencies": { "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", "jmespath": "0.16.0", "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", "util": "^0.12.4", "uuid": "8.0.0", "xml2js": "0.6.2" } }, "sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw=="], "aws-ssl-profiles": ["aws-ssl-profiles@1.1.2", "", {}, "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g=="], @@ -2686,8 +2626,6 @@ "blob-to-buffer": ["blob-to-buffer@1.2.9", "", {}, "sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA=="], - "bmp-ts": ["bmp-ts@1.0.9", "", {}, "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw=="], - "body-parser": ["body-parser@1.20.4", "", { "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "~1.2.0", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", "qs": "~6.14.0", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" } }, "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA=="], "bonjour-service": ["bonjour-service@1.3.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" } }, "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA=="], @@ -2730,16 +2668,6 @@ "bun-types": ["bun-types@1.3.12", "", { "dependencies": { "@types/node": "*" } }, "sha512-HqOLj5PoFajAQciOMRiIZGNoKxDJSr6qigAttOX40vJuSp6DN/CxWp9s3C1Xwm4oH7ybueITwiaOcWXoYVoRkA=="], - "bun-webgpu": ["bun-webgpu@0.1.5", "", { "dependencies": { "@webgpu/types": "^0.1.60" }, "optionalDependencies": { "bun-webgpu-darwin-arm64": "^0.1.5", "bun-webgpu-darwin-x64": "^0.1.5", "bun-webgpu-linux-x64": "^0.1.5", "bun-webgpu-win32-x64": "^0.1.5" } }, "sha512-91/K6S5whZKX7CWAm9AylhyKrLGRz6BUiiPiM/kXadSnD4rffljCD/q9cNFftm5YXhx4MvLqw33yEilxogJvwA=="], - - "bun-webgpu-darwin-arm64": ["bun-webgpu-darwin-arm64@0.1.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-lIsDkPzJzPl6yrB5CUOINJFPnTRv6fF/Q8J1mAr43ogSp86WZEg9XZKaT6f3EUJ+9ETogGoMnoj1q0AwHUTbAQ=="], - - "bun-webgpu-darwin-x64": ["bun-webgpu-darwin-x64@0.1.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-uEddf5U7GvKIkM/BV18rUKtYHL6d0KeqBjNHwfqDH9QgEo9KVSKvJXS5I/sMefk5V5pIYE+8tQhtrREevhocng=="], - - "bun-webgpu-linux-x64": ["bun-webgpu-linux-x64@0.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-Y/f15j9r8ba0xUz+3lATtS74OE+PPzQXO7Do/1eCluJcuOlfa77kMjvBK/ShWnem3Y9xqi59pebTPOGRB+CaJA=="], - - "bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.6", "", { "os": "win32", "cpu": "x64" }, "sha512-MHSFAKqizISb+C5NfDrFe3g0Al5Njnu0j/A+oO2Q+bIWX+fUYjBSowiYE1ZXJx65KuryuB+tiM7Qh6cQbVvkEg=="], - "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], @@ -3160,8 +3088,6 @@ "execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="], - "exif-parser": ["exif-parser@0.1.12", "", {}, "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw=="], - "exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="], "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], @@ -3224,8 +3150,6 @@ "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], - "file-type": ["file-type@16.5.4", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", "token-types": "^4.1.1" } }, "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw=="], - "filelist": ["filelist@1.0.6", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], @@ -3316,8 +3240,6 @@ "ghostty-web": ["ghostty-web@github:anomalyco/ghostty-web#20bd361", {}, "anomalyco-ghostty-web-20bd361", "sha512-dW0nwaiBBcun9y5WJSvm3HxDLe5o9V0xLCndQvWonRVubU8CS1PHxZpLffyPt1YujPWC13ez03aWxcuKBPYYGQ=="], - "gifwrap": ["gifwrap@0.10.1", "", { "dependencies": { "image-q": "^4.0.0", "omggif": "^1.0.10" } }, "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw=="], - "giget": ["giget@2.0.0", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.6.0", "pathe": "^2.0.3" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA=="], "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], @@ -3470,8 +3392,6 @@ "ignore-walk": ["ignore-walk@8.0.0", "", { "dependencies": { "minimatch": "^10.0.3" } }, "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A=="], - "image-q": ["image-q@4.0.0", "", { "dependencies": { "@types/node": "16.9.1" } }, "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw=="], - "immer": ["immer@11.1.4", "", {}, "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw=="], "import-local": ["import-local@3.2.0", "", { "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" }, "bin": { "import-local-fixture": "fixtures/cli.js" } }, "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA=="], @@ -3614,16 +3534,12 @@ "jake": ["jake@10.9.4", "", { "dependencies": { "async": "^3.2.6", "filelist": "^1.0.4", "picocolors": "^1.1.1" }, "bin": { "jake": "bin/cli.js" } }, "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA=="], - "jimp": ["jimp@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/diff": "1.6.0", "@jimp/js-bmp": "1.6.0", "@jimp/js-gif": "1.6.0", "@jimp/js-jpeg": "1.6.0", "@jimp/js-png": "1.6.0", "@jimp/js-tiff": "1.6.0", "@jimp/plugin-blit": "1.6.0", "@jimp/plugin-blur": "1.6.0", "@jimp/plugin-circle": "1.6.0", "@jimp/plugin-color": "1.6.0", "@jimp/plugin-contain": "1.6.0", "@jimp/plugin-cover": "1.6.0", "@jimp/plugin-crop": "1.6.0", "@jimp/plugin-displace": "1.6.0", "@jimp/plugin-dither": "1.6.0", "@jimp/plugin-fisheye": "1.6.0", "@jimp/plugin-flip": "1.6.0", "@jimp/plugin-hash": "1.6.0", "@jimp/plugin-mask": "1.6.0", "@jimp/plugin-print": "1.6.0", "@jimp/plugin-quantize": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/plugin-rotate": "1.6.0", "@jimp/plugin-threshold": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0" } }, "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg=="], - "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], "jmespath": ["jmespath@0.16.0", "", {}, "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw=="], "jose": ["jose@6.0.11", "", {}, "sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg=="], - "jpeg-js": ["jpeg-js@0.4.4", "", {}, "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="], - "js-base64": ["js-base64@3.7.7", "", {}, "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw=="], "js-beautify": ["js-beautify@1.15.4", "", { "dependencies": { "config-chain": "^1.1.13", "editorconfig": "^1.0.4", "glob": "^10.4.2", "js-cookie": "^3.0.5", "nopt": "^7.2.1" }, "bin": { "css-beautify": "js/bin/css-beautify.js", "html-beautify": "js/bin/html-beautify.js", "js-beautify": "js/bin/js-beautify.js" } }, "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA=="], @@ -4084,8 +4000,6 @@ "oidc-token-hash": ["oidc-token-hash@5.2.0", "", {}, "sha512-6gj2m8cJZ+iSW8bm0FXdGF0YhIQbKrfP4yWTNzxc31U6MOjfEmB1rHvlYvxI1B7t7BCi1F2vYTT6YhtQRG4hxw=="], - "omggif": ["omggif@1.0.10", "", {}, "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw=="], - "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="], "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], @@ -4160,12 +4074,6 @@ "param-case": ["param-case@3.0.4", "", { "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A=="], - "parse-bmfont-ascii": ["parse-bmfont-ascii@1.0.6", "", {}, "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA=="], - - "parse-bmfont-binary": ["parse-bmfont-binary@1.0.6", "", {}, "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA=="], - - "parse-bmfont-xml": ["parse-bmfont-xml@1.1.6", "", { "dependencies": { "xml-parse-from-string": "^1.0.0", "xml2js": "^0.5.0" } }, "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA=="], - "parse-conflict-json": ["parse-conflict-json@5.0.1", "", { "dependencies": { "json-parse-even-better-errors": "^5.0.0", "just-diff": "^6.0.0", "just-diff-apply": "^5.2.0" } }, "sha512-ZHEmNKMq1wyJXNwLxyHnluPfRAFSIliBvbK/UiOceROt4Xh9Pz0fq49NytIaeaCUf5VR86hwQ/34FCcNU5/LKQ=="], "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], @@ -4210,8 +4118,6 @@ "peberminta": ["peberminta@0.9.0", "", {}, "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ=="], - "peek-readable": ["peek-readable@4.1.0", "", {}, "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg=="], - "pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="], "perfect-debounce": ["perfect-debounce@2.1.0", "", {}, "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g=="], @@ -4232,8 +4138,6 @@ "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="], - "pixelmatch": ["pixelmatch@5.3.0", "", { "dependencies": { "pngjs": "^6.0.0" }, "bin": { "pixelmatch": "bin/pixelmatch" } }, "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q=="], - "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="], "pkg-dir": ["pkg-dir@4.2.0", "", { "dependencies": { "find-up": "^4.0.0" } }, "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ=="], @@ -4242,16 +4146,12 @@ "pkg-up": ["pkg-up@3.1.0", "", { "dependencies": { "find-up": "^3.0.0" } }, "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA=="], - "planck": ["planck@1.5.0", "", { "peerDependencies": { "stage-js": "^1.0.0-alpha.12" } }, "sha512-dlvqJE+FscZgrGUXJ5ybd0o5bvZ5XXyZNbm08xGsXp9WjXeAyWSFT6n9s/1PQcUBo4546fDXA5RMA4wbDyZw6g=="], - "playwright": ["playwright@1.59.1", "", { "dependencies": { "playwright-core": "1.59.1" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw=="], "playwright-core": ["playwright-core@1.59.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg=="], "plist": ["plist@3.1.0", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ=="], - "pngjs": ["pngjs@7.0.0", "", {}, "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow=="], - "poe-oauth": ["poe-oauth@0.0.6", "", {}, "sha512-dI8xrVl7RSFh0B+cb4GGuCjIfGtDT9VpbpVkP0UKcunpXF0eFw+6GencoJ7k+E02ZYqopBQApMVWGq70/GP69w=="], "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], @@ -4376,8 +4276,6 @@ "readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], - "readable-web-to-node-stream": ["readable-web-to-node-stream@3.0.4", "", { "dependencies": { "readable-stream": "^4.7.0" } }, "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw=="], - "readdir-glob": ["readdir-glob@1.1.3", "", { "dependencies": { "minimatch": "^5.1.0" } }, "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA=="], "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], @@ -4584,8 +4482,6 @@ "simple-update-notifier": ["simple-update-notifier@2.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w=="], - "simple-xml-to-json": ["simple-xml-to-json@1.2.7", "", {}, "sha512-mz9VXphOxQWX3eQ/uXCtm6upltoN0DLx8Zb5T4TFC4FHB7S9FDPGre8CfLWqPWQQH/GrQYd2AXhhVM5LDpYx6Q=="], - "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], "sitemap": ["sitemap@9.0.1", "", { "dependencies": { "@types/node": "^24.9.2", "@types/sax": "^1.2.1", "arg": "^5.0.0", "sax": "^1.4.1" }, "bin": { "sitemap": "dist/esm/cli.js" } }, "sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ=="], @@ -4672,8 +4568,6 @@ "stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="], - "stage-js": ["stage-js@1.0.2", "", {}, "sha512-EWTRBYlg7Qv9wGUao99/PfRe3KaiQqWmgSvTOXvaWnu1Jk/q/vV8yJVu6bi/3EqDZeMVnCPAjheba6OFc5k1GQ=="], - "standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="], "stat-mode": ["stat-mode@1.0.0", "", {}, "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg=="], @@ -4722,8 +4616,6 @@ "strnum": ["strnum@1.1.2", "", {}, "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA=="], - "strtok3": ["strtok3@6.3.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^4.1.0" } }, "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw=="], - "stubborn-fs": ["stubborn-fs@2.0.0", "", { "dependencies": { "stubborn-utils": "^1.0.1" } }, "sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA=="], "stubborn-utils": ["stubborn-utils@1.0.2", "", {}, "sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg=="], @@ -4776,8 +4668,6 @@ "thread-stream": ["thread-stream@4.0.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA=="], - "three": ["three@0.177.0", "", {}, "sha512-EiXv5/qWAaGI+Vz2A+JfavwYCMdGjxVsrn3oBwllUoqYeaBO75J63ZfyaQKoiLrqNHoTlUc6PFgMXnS0kI45zg=="], - "thunky": ["thunky@1.1.0", "", {}, "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="], "tiny-async-pool": ["tiny-async-pool@1.3.0", "", { "dependencies": { "semver": "^5.5.0" } }, "sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA=="], @@ -4790,8 +4680,6 @@ "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], - "tinycolor2": ["tinycolor2@1.6.0", "", {}, "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="], - "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], @@ -4812,8 +4700,6 @@ "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], - "token-types": ["token-types@4.2.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ=="], - "toml": ["toml@4.1.1", "", {}, "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw=="], "toolbeam-docs-theme": ["toolbeam-docs-theme@0.4.8", "", { "peerDependencies": { "@astrojs/starlight": "^0.34.3", "astro": "^5.7.13" } }, "sha512-b+5ynEFp4Woe5a22hzNQm42lD23t13ZMihVxHbzjA50zdcM9aOSJTIjdJ0PDSd4/50HbBXcpHiQsz6rM4N88ww=="], @@ -4966,8 +4852,6 @@ "utf8-byte-length": ["utf8-byte-length@1.0.5", "", {}, "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA=="], - "utif2": ["utif2@4.1.0", "", { "dependencies": { "pako": "^1.0.11" } }, "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w=="], - "util": ["util@0.12.5", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "which-typed-array": "^1.1.2" } }, "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA=="], "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], @@ -5096,8 +4980,6 @@ "xdg-basedir": ["xdg-basedir@5.1.0", "", {}, "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ=="], - "xml-parse-from-string": ["xml-parse-from-string@1.0.1", "", {}, "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g=="], - "xml2js": ["xml2js@0.6.2", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA=="], "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], @@ -5450,46 +5332,10 @@ "@gitlab/opencode-gitlab-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], - "@happy-dom/global-registrator/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "@hey-api/openapi-ts/open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="], "@hey-api/openapi-ts/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], - "@jimp/core/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], - - "@jimp/plugin-blit/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-circle/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-color/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-contain/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-cover/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-crop/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-displace/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-fisheye/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-flip/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-mask/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-print/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-quantize/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-resize/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-rotate/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/plugin-threshold/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@jimp/types/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "@jsx-email/cli/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "@jsx-email/cli/esbuild": ["esbuild@0.19.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.19.12", "@esbuild/android-arm": "0.19.12", "@esbuild/android-arm64": "0.19.12", "@esbuild/android-x64": "0.19.12", "@esbuild/darwin-arm64": "0.19.12", "@esbuild/darwin-x64": "0.19.12", "@esbuild/freebsd-arm64": "0.19.12", "@esbuild/freebsd-x64": "0.19.12", "@esbuild/linux-arm": "0.19.12", "@esbuild/linux-arm64": "0.19.12", "@esbuild/linux-ia32": "0.19.12", "@esbuild/linux-loong64": "0.19.12", "@esbuild/linux-mips64el": "0.19.12", "@esbuild/linux-ppc64": "0.19.12", "@esbuild/linux-riscv64": "0.19.12", "@esbuild/linux-s390x": "0.19.12", "@esbuild/linux-x64": "0.19.12", "@esbuild/netbsd-x64": "0.19.12", "@esbuild/openbsd-x64": "0.19.12", "@esbuild/sunos-x64": "0.19.12", "@esbuild/win32-arm64": "0.19.12", "@esbuild/win32-ia32": "0.19.12", "@esbuild/win32-x64": "0.19.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg=="], @@ -5628,24 +5474,16 @@ "@slack/bolt/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="], - "@slack/logger/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "@slack/oauth/@slack/logger": ["@slack/logger@3.0.0", "", { "dependencies": { "@types/node": ">=12.0.0" } }, "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA=="], - "@slack/oauth/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "@slack/socket-mode/@slack/logger": ["@slack/logger@3.0.0", "", { "dependencies": { "@types/node": ">=12.0.0" } }, "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA=="], - "@slack/socket-mode/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "@slack/socket-mode/@types/ws": ["@types/ws@7.4.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww=="], "@slack/socket-mode/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], "@slack/web-api/@slack/logger": ["@slack/logger@3.0.0", "", { "dependencies": { "@types/node": ">=12.0.0" } }, "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA=="], - "@slack/web-api/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "@slack/web-api/eventemitter3": ["eventemitter3@3.1.2", "", {}, "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="], "@slack/web-api/form-data": ["form-data@2.5.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" } }, "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A=="], @@ -5706,62 +5544,8 @@ "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="], - "@types/body-parser/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/cacache/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/cacheable-request/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/connect/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/cross-spawn/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/express-serve-static-core/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/fontkit/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/fs-extra/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/is-stream/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/jsonwebtoken/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/keyv/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/mssql/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/node-fetch/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/npm-registry-fetch/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/npmcli__arborist/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/npmlog/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/pacote/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/plist/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "@types/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], - "@types/readable-stream/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/responselike/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/sax/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/send/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/serve-static/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/ssri/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/tunnel/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/ws/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "@types/yauzl/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "@vitest/expect/@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="], "@vitest/expect/tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="], @@ -5838,18 +5622,12 @@ "builder-util-runtime/sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], - "bun-types/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - - "bun-webgpu/@webgpu/types": ["@webgpu/types@0.1.69", "", {}, "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ=="], - "c12/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], "c12/dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="], "clone-response/mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="], - "cloudflare/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "compress-commons/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], "condense-newlines/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], @@ -5884,8 +5662,6 @@ "effect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], - "electron/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "electron-builder/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "electron-builder/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], @@ -5940,8 +5716,6 @@ "gray-matter/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], - "happy-dom/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "happy-dom/ws": ["ws@8.20.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA=="], "html-minifier-terser/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], @@ -5954,8 +5728,6 @@ "iconv-corefoundation/node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="], - "image-q/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "js-beautify/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "js-beautify/nopt": ["nopt@7.2.1", "", { "dependencies": { "abbrev": "^2.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w=="], @@ -6028,9 +5800,9 @@ "openid-client/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], - "opentui-spinner/@opentui/core": ["@opentui/core@0.1.105", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.105", "@opentui/core-darwin-x64": "0.1.105", "@opentui/core-linux-arm64": "0.1.105", "@opentui/core-linux-x64": "0.1.105", "@opentui/core-win32-arm64": "0.1.105", "@opentui/core-win32-x64": "0.1.105", "bun-webgpu": "0.1.5", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-vllSOOCW6VIThV/96GRLJ1IxIBuR+ci6FDvnPIAG4s7SJ/FW6zAkqDn1xrtBwwk/lM3QWjLqy8BZc+zwWvveJA=="], + "opentui-spinner/@opentui/core": ["@opentui/core@0.2.7", "", { "dependencies": { "bun-ffi-structs": "0.2.2", "diff": "9.0.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@opentui/core-darwin-arm64": "0.2.7", "@opentui/core-darwin-x64": "0.2.7", "@opentui/core-linux-arm64": "0.2.7", "@opentui/core-linux-x64": "0.2.7", "@opentui/core-win32-arm64": "0.2.7", "@opentui/core-win32-x64": "0.2.7" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-cnN6JcaGC7SeQzobBy/CHzqUAQFtypazuw1CjQBo7WwoOiLMGubt9W5FXeF0zIrSxH2Ed6NLWhPYRg7SD4629Q=="], - "opentui-spinner/@opentui/solid": ["@opentui/solid@0.1.105", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.105", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.10", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.11" } }, "sha512-uxnaMP802sCI487pv/Hk9xdFdIj9mkg3eNliAqbqR0Shmd4phcjKEZvPRpijjmI99j4s9nul71jzF3h1oz31Nw=="], + "opentui-spinner/@opentui/solid": ["@opentui/solid@0.2.7", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.2.7", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-nlkx9HvuWaHtc5A8eUEAPNi+5+37LZS3ln73WRmtT5xin8LnQf+yhwopqGgPSnLq1ODLwhkKRdr/9JCDr2j7Bg=="], "ora/bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], @@ -6044,14 +5816,10 @@ "p-retry/retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], - "parse-bmfont-xml/xml2js": ["xml2js@0.5.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA=="], - "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], - "pixelmatch/pngjs": ["pngjs@6.0.0", "", {}, "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg=="], - "pkg-dir/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], "pkg-up/find-up": ["find-up@3.0.0", "", { "dependencies": { "locate-path": "^3.0.0" } }, "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg=="], @@ -6076,8 +5844,6 @@ "proper-lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - "protobufjs/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "raw-body/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], "readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], @@ -6108,8 +5874,6 @@ "shiki/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - "sitemap/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "sitemap/sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], @@ -6132,20 +5896,14 @@ "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "stripe/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], "tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], - "tedious/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], "tiny-async-pool/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - "token-types/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], - "tree-sitter-bash/node-addon-api": ["node-addon-api@8.7.0", "", {}, "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA=="], "tw-to-css/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], @@ -6162,8 +5920,6 @@ "uri-js/punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - "utif2/pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], - "venice-ai-sdk-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], "vite-plugin-icons-spritesheet/glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="], @@ -6478,8 +6234,6 @@ "@gitlab/opencode-gitlab-auth/open/wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], - "@happy-dom/global-registrator/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "@jsx-email/cli/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.19.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA=="], "@jsx-email/cli/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.19.12", "", { "os": "android", "cpu": "arm" }, "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w=="], @@ -6674,14 +6428,6 @@ "@sentry/cli/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - "@slack/logger/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@slack/oauth/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@slack/socket-mode/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@slack/web-api/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "@slack/web-api/form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "@slack/web-api/p-queue/eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], @@ -6708,60 +6454,6 @@ "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], - "@types/body-parser/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/cacache/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/cacheable-request/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/connect/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/cross-spawn/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/express-serve-static-core/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/fontkit/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/fs-extra/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/is-stream/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/jsonwebtoken/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/keyv/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/mssql/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/node-fetch/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/npm-registry-fetch/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/npmcli__arborist/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/npmlog/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/pacote/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/plist/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/readable-stream/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/responselike/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/sax/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/send/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/serve-static/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/ssri/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/tunnel/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/ws/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@types/yauzl/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "@vitest/expect/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], "accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], @@ -6810,12 +6502,8 @@ "body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "bun-types/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "c12/chokidar/readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], - "cloudflare/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "crc/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], @@ -6834,8 +6522,6 @@ "electron-winstaller/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], - "electron/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "esbuild-plugin-copy/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], @@ -6848,14 +6534,10 @@ "gray-matter/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], - "happy-dom/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "iconv-corefoundation/cli-truncate/slice-ansi": ["slice-ansi@3.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ=="], "iconv-corefoundation/cli-truncate/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "image-q/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "js-beautify/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], "js-beautify/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], @@ -6874,8 +6556,6 @@ "motion/framer-motion/motion-utils": ["motion-utils@12.36.0", "", {}, "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg=="], - "mssql/tedious/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "mssql/tedious/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], "opencode-gitlab-auth/open/wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], @@ -6894,24 +6574,22 @@ "opencontrol/@modelcontextprotocol/sdk/zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], - "opentui-spinner/@opentui/core/@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.105", "", { "os": "darwin", "cpu": "arm64" }, "sha512-1pIL7aer9amwj8EpYoMNtvavKetIe+nX8uBRmYsMQb+KvJoUAZUqENfRW+qHE5WrsOyxx8/QoyXTHw15GG5iLQ=="], + "opentui-spinner/@opentui/core/@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.2.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-CAy6cL3byz2Xf6gFiJHBpcnsp/2ADEWLLOUokVypOyPLcy8GY3sPzlA4pkAjVGQMYQhDj+Y3+SXz4uTLt4AETg=="], - "opentui-spinner/@opentui/core/@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.105", "", { "os": "darwin", "cpu": "x64" }, "sha512-hLIRSWlK3gY2NRXJGWiTBiMYSmRDjOYFZF6WtUVXhY2SL3sp08dhmr/6dmAVH+3pKCsCipLEsrrcQX6SAihCTA=="], + "opentui-spinner/@opentui/core/@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.2.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-K06h333rMkC9cyMJr/VvcRK3ik81Admd8ZsES5uf5YXWPdYhXGf75I1T8mKIThhUmoFLb8R5xqfuPmoocsjM7Q=="], - "opentui-spinner/@opentui/core/@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.105", "", { "os": "linux", "cpu": "arm64" }, "sha512-jlRKfPkozTZEkHEePuCWYcTIUtPm+ieInAwGVqGmjbvqjxdVv1/W/Dt6LEZ/9jpRiOPd+FjXAfLe6wa/XWHr+w=="], + "opentui-spinner/@opentui/core/@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.2.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-iYWGTztbdG9yYSB5Alxuo0dWAmkWQR0+/paNWUyPOocjigmKgMmACDtHgYqa7sxkIcWgmXljt/f8rgXDG4wdMg=="], - "opentui-spinner/@opentui/core/@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.105", "", { "os": "linux", "cpu": "x64" }, "sha512-kfWS1WMg6qHShmxZX9s1tZc/8JcXw6uyy2UtyTbJdRFExtXGH37oKHi8QK8iPL2ExCx4z7zqVnVJfO3X/Wh7lA=="], + "opentui-spinner/@opentui/core/@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.2.7", "", { "os": "linux", "cpu": "x64" }, "sha512-tymBCfYbsDRfHQNXsolkFfaTEIDhemD4+1ZovUztQd7i+0Ggnu9WbPN1SNCiRz6PjrlaNeQzZE3Wl8FfVdw/cw=="], - "opentui-spinner/@opentui/core/@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.105", "", { "os": "win32", "cpu": "arm64" }, "sha512-UFx6A8OpBVbGWK6OAw4GqAqKZgIITJfSOd35pG9yDVKQouHN2OGc2HeeXrH2A4h42p40Xl6IfcqqfllkpC13Dg=="], + "opentui-spinner/@opentui/core/@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.2.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-XLPJWdT8QOukrYDkpIng6+uNUlF66ByXcQlC3qA9JbrUTBetZhgXs8Q2jEjRfc+Ty3uh1iRSA6PgJGbbOK/f4Q=="], - "opentui-spinner/@opentui/core/@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.105", "", { "os": "win32", "cpu": "x64" }, "sha512-f9FqqUmxehwhF+cgyazm0YT0v0BYTTCPzd6eztqhl74N3x/kC+jOOz2rdJDC/tTBo1JVsF64KupOnhIs6/Cogg=="], + "opentui-spinner/@opentui/core/@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.2.7", "", { "os": "win32", "cpu": "x64" }, "sha512-CzVGEfqysVk8Hxcj0RDv/DtXIM6iZmbmr23kW7y8CJMPtmV1gmKI4D9abVjynWJnGbaSBnDi43mgZnGMgOdyEg=="], - "opentui-spinner/@opentui/core/bun-ffi-structs": ["bun-ffi-structs@0.1.2", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-Lh1oQAYHDcnesJauieA4UNkWGXY9hYck7OA5IaRwE3Bp6K2F2pJSNYqq+hIy7P3uOvo3km3oxS8304g5gDMl/w=="], + "opentui-spinner/@opentui/core/diff": ["diff@9.0.0", "", {}, "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw=="], "opentui-spinner/@opentui/solid/@babel/core": ["@babel/core@7.28.0", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", "@babel/helpers": "^7.27.6", "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.0", "@babel/types": "^7.28.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ=="], - "opentui-spinner/@opentui/solid/babel-preset-solid": ["babel-preset-solid@1.9.10", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.40.3" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^1.9.10" }, "optionalPeers": ["solid-js"] }, "sha512-HCelrgua/Y+kqO8RyL04JBWS/cVdrtUv/h45GntgQY+cJl4eBcKkCDV3TdMjtKx1nXwRaR9QXslM/Npm1dxdZQ=="], - "ora/bl/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], "ora/bl/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], @@ -6920,14 +6598,10 @@ "p-locate/p-limit/yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - "parse-bmfont-xml/xml2js/sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], - "pkg-dir/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], "pkg-up/find-up/locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], - "protobufjs/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "readable-stream/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "readdir-glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], @@ -6938,16 +6612,10 @@ "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "sitemap/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "storybook/open/wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "stripe/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "tedious/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "tw-to-css/tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], "tw-to-css/tailwindcss/glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], @@ -7250,8 +6918,6 @@ "js-beautify/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "mssql/tedious/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "opencontrol/@modelcontextprotocol/sdk/express/accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], "opencontrol/@modelcontextprotocol/sdk/express/body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="], diff --git a/bunfig.toml b/bunfig.toml index 363579bbf0..47c4ac5396 100644 --- a/bunfig.toml +++ b/bunfig.toml @@ -2,6 +2,7 @@ exact = true # Only install newly resolved package versions published at least 3 days ago. minimumReleaseAge = 259200 +minimumReleaseAgeExcludes = ["@opentui/core", "@opentui/core-darwin-arm64", "@opentui/core-darwin-x64", "@opentui/core-linux-arm64", "@opentui/core-linux-x64", "@opentui/core-win32-arm64", "@opentui/core-win32-x64", "@opentui/keymap", "@opentui/solid"] [test] root = "./do-not-run-tests-from-root" diff --git a/package.json b/package.json index 6d82864d6d..f1cc7da5c3 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,9 @@ "@types/cross-spawn": "6.0.6", "@octokit/rest": "22.0.0", "@hono/zod-validator": "0.4.2", - "@opentui/core": "0.2.6", - "@opentui/keymap": "0.2.6", - "@opentui/solid": "0.2.6", + "@opentui/core": "0.2.8", + "@opentui/keymap": "0.2.8", + "@opentui/solid": "0.2.8", "ulid": "3.0.1", "@kobalte/core": "0.13.11", "@types/luxon": "3.7.1", @@ -128,6 +128,9 @@ "electron" ], "overrides": { + "@opentui/core": "catalog:", + "@opentui/keymap": "catalog:", + "@opentui/solid": "catalog:", "@types/bun": "catalog:", "@types/node": "catalog:" }, diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 121b34c3a0..b0427f231b 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -108,6 +108,7 @@ "@opencode-ai/plugin": "workspace:*", "@opencode-ai/script": "workspace:*", "@opencode-ai/sdk": "workspace:*", + "@opencode-ai/ui": "workspace:*", "@openrouter/ai-sdk-provider": "2.8.1", "@opentelemetry/api": "1.9.0", "@opentelemetry/context-async-hooks": "2.6.1", diff --git a/packages/opencode/specs/tui-plugins.md b/packages/opencode/specs/tui-plugins.md index c1a9b271c1..e9ece6c0a2 100644 --- a/packages/opencode/specs/tui-plugins.md +++ b/packages/opencode/specs/tui-plugins.md @@ -29,6 +29,16 @@ Example: "plugin": ["@acme/opencode-plugin@1.2.3", ["./plugins/demo.tsx", { "label": "demo" }]], "plugin_enabled": { "acme.demo": false + }, + "attention": { + "enabled": true, + "notifications": true, + "sound": true, + "volume": 0.4, + "sound_pack": "opencode.default", + "sounds": { + "error": "/Users/me/sounds/error.mp3" + } } } ``` @@ -45,6 +55,11 @@ Example: - Internal plugins can declare `enabled: false` to be registered but inactive by default; `plugin_enabled` and runtime KV can still enable them by id. - `plugin_enabled` is merged across config layers. - Runtime enable/disable state is also stored in KV under `plugin_enabled`; that KV state overrides config on startup. +- `attention.enabled` defaults to `false`; when `false`, it disables all `api.attention.notify(...)` delivery. +- `attention.notifications` and `attention.sound` independently control terminal-mediated desktop notifications and built-in sounds. +- `attention.volume` sets the default built-in sound volume from `0` to `1`. +- `attention.sound_pack` selects the initial semantic sound pack. Persisted runtime selection in KV can override it. +- `attention.sounds` overrides individual semantic sound slots such as `error`, `done`, or `subagent_done`. - `leader_timeout` is a top-level TUI setting. - `keybinds` is a flat object keyed by command id; values are key binding values (`false`, `"none"`, a key string/object, a binding object, or an array of key strings/objects/binding objects). - `keybinds.leader` sets the key used by `` shortcuts. @@ -212,6 +227,7 @@ That is what makes local config-scoped plugins able to import `@opencode-ai/plug Top-level API groups exposed to `tui(api, options, meta)`: - `api.app.version` +- `api.attention.notify(input)` - `api.keys.formatSequence(parts)`, `formatBindings(bindings)` - `api.keymap` - `api.route.register(routes)` / `api.route.navigate(name, params?)` / `api.route.current` @@ -246,6 +262,24 @@ Top-level API groups exposed to `tui(api, options, meta)`: - `formatBindings(bindings)` formats binding lists and returns `undefined` when there is nothing to show. - For generic config-to-bindings helpers, import `createBindingLookup` from `@opencode-ai/plugin/tui`. +### Attention + +- `api.attention.notify({ title?, message, notification?, sound? })` requests user attention while keeping terminal focus, notifications, and audio owned by the host. +- `message` is required; `title` defaults to `"opencode"`; `notification` defaults to enabled with `when: "blurred"`; `sound` defaults to enabled with `when: "always"`. +- `when: "always"` requests delivery regardless of terminal focus state. +- `when: "focused"` only requests delivery after the terminal is known focused; `when: "blurred"` only requests delivery after the terminal is known blurred. +- Example: `notification: { when: "blurred" }, sound: { name: "question", when: "always" }` plays sound while focused but only triggers system notifications when blurred. +- Semantic sound names are `"default"`, `"question"`, `"permission"`, `"error"`, `"done"`, and `"subagent_done"`. +- `sound: true` plays the `"default"` sound; `sound: { name: "question" }` plays a named semantic sound. +- `sound: { volume }` overrides volume for that call; `sound: false` disables sound for that call; `notification: false` disables system notification for that call. +- `api.attention.soundboard.registerPack({ id, name?, sounds })` registers a sound pack and returns a disposer. Relative paths resolve from the plugin root and are cleaned up on plugin deactivation. +- `api.attention.soundboard.activate(id, { persist })` selects the active pack. `persist: true` writes the selected pack id to TUI KV state, not `tui.json`. +- `api.attention.soundboard.current()` and `list()` expose the active/registered packs for plugin UX. +- Config `attention.sounds` overrides active-pack sounds by slot. Failed loads fall back to the active pack and then `opencode.default`. +- The host strips ANSI/control characters and collapses newlines before sending text to the terminal notification API. +- Terminal and OS settings decide whether a requested notification is visibly displayed. +- Prefer privacy-safe messages such as `"A question needs your input"`; avoid full commands, paths, prompts, errors, secrets, or file contents unless the plugin intentionally exposes them. + ### Routes - Reserved route names: `home` and `session`. diff --git a/packages/opencode/specs/v2/notifications.md b/packages/opencode/specs/v2/notifications.md new file mode 100644 index 0000000000..96018f9944 --- /dev/null +++ b/packages/opencode/specs/v2/notifications.md @@ -0,0 +1,13 @@ +# TUI Notifications Default + +Problem: + +- v1 defaults `attention.enabled` to `false` +- users can opt in with `attention.enabled = true` +- v2 should make core TUI notifications a default behavior + +## v2 Target + +Flip `attention.enabled` to `true` by default in v2. + +Keep `attention.enabled = false` as the explicit opt-out. diff --git a/packages/opencode/src/audio.d.ts b/packages/opencode/src/audio.d.ts index c7c947450d..7b99d097a3 100644 --- a/packages/opencode/src/audio.d.ts +++ b/packages/opencode/src/audio.d.ts @@ -3,6 +3,11 @@ declare module "*.wav" { export default file } +declare module "*.mp3" { + const file: string + export default file +} + declare module "*.wasm" { const file: string export default file diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index d7f2cd14b0..29cca133bb 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -2,6 +2,7 @@ import { render, TimeToFirstDraw, useRenderer, useTerminalDimensions } from "@op import { createDefaultOpenTuiKeymap } from "@opentui/keymap/opentui" import * as Clipboard from "@tui/util/clipboard" import * as Selection from "@tui/util/selection" +import * as TuiAudio from "@tui/util/audio" import { createCliRenderer, MouseButton, type CliRendererConfig } from "@opentui/core" import { RouteProvider, useRoute } from "@tui/context/route" import { @@ -63,6 +64,7 @@ import { TuiConfig } from "@/cli/cmd/tui/config/tui" import { TuiPluginRuntime } from "@/cli/cmd/tui/plugin/runtime" import { createTuiApi } from "@/cli/cmd/tui/plugin/api" import type { RouteMap } from "@/cli/cmd/tui/plugin/api" +import { createTuiAttention } from "@/cli/cmd/tui/attention" import { FormatError, FormatUnknownError } from "@/cli/error" import { CommandPaletteProvider, useCommandPalette } from "./context/command-palette" import { OpencodeKeymapProvider, registerOpencodeKeymap, useBindings, useOpencodeKeymap } from "./keymap" @@ -176,10 +178,10 @@ export function tui(input: { unguard?.() resolve() } - const onBeforeExit = async () => { offKeymap() await TuiPluginRuntime.dispose() + TuiAudio.dispose() } const renderer = await createCliRenderer(rendererConfig(input.config)) @@ -283,6 +285,7 @@ function App(props: { onSnapshot?: () => Promise }) { routeRev() return routes.get(name)?.at(-1)?.render } + const attention = createTuiAttention({ renderer, config: tuiConfig, kv }) const api = createTuiApi({ tuiConfig, @@ -298,11 +301,13 @@ function App(props: { onSnapshot?: () => Promise }) { theme: themeState, toast, renderer, + attention, }) const [ready, setReady] = createSignal(false) TuiPluginRuntime.init({ api, config: tuiConfig, + dispose: () => attention.dispose(), }) .catch((error) => { console.error("Failed to load TUI plugins", error) @@ -320,7 +325,10 @@ function App(props: { onSnapshot?: () => Promise }) { }, { priority: 1 }, ) - onCleanup(offSelectionKeys) + onCleanup(() => { + offSelectionKeys() + attention.dispose() + }) // Wire up console copy-to-clipboard via opentui's onCopySelection callback renderer.console.onCopySelection = async (text: string) => { diff --git a/packages/opencode/src/cli/cmd/tui/attention.ts b/packages/opencode/src/cli/cmd/tui/attention.ts new file mode 100644 index 0000000000..60bd97b977 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/attention.ts @@ -0,0 +1,261 @@ +import type { + TuiAttention, + TuiAttentionNotifyInput, + TuiAttentionNotifyResult, + TuiAttentionNotifySkipReason, + TuiAttentionWhen, + TuiKV, + TuiAttentionSoundName, + TuiAttentionSoundPack, + TuiAttentionSoundPackInfo, +} from "@opencode-ai/plugin/tui" +import stripAnsi from "strip-ansi" +import type { TuiConfig } from "./config/tui" +import { isAttentionSoundName } from "./config/tui-schema" +import * as TuiAudio from "@tui/util/audio" +import defaultSoundPath from "@opencode-ai/ui/audio/bip-bop-01.mp3" with { type: "file" } +import questionSoundPath from "@opencode-ai/ui/audio/bip-bop-03.mp3" with { type: "file" } +import permissionSoundPath from "@opencode-ai/ui/audio/staplebops-06.mp3" with { type: "file" } +import errorSoundPath from "@opencode-ai/ui/audio/nope-03.mp3" with { type: "file" } +import doneSoundPath from "@opencode-ai/ui/audio/bip-bop-01.mp3" with { type: "file" } +import subagentDoneSoundPath from "@opencode-ai/ui/audio/yup-01.mp3" with { type: "file" } +import * as Log from "@opencode-ai/core/util/log" + +type FocusState = "unknown" | "focused" | "blurred" + +type AttentionRenderer = { + readonly isDestroyed: boolean + on(event: "focus" | "blur", listener: () => void): unknown + off(event: "focus" | "blur", listener: () => void): unknown + triggerNotification(message: string, title?: string): boolean +} + +type RegisteredSoundPack = TuiAttentionSoundPack & { + builtin: boolean +} + +type TuiAttentionHost = TuiAttention & { + dispose(): void +} + +const log = Log.create({ service: "tui.attention" }) + +const DEFAULT_TITLE = "opencode" +const DEFAULT_PACK_ID = "opencode.default" +const KV_SOUND_PACK = "attention_sound_pack" +const TITLE_LIMIT = 80 +const MESSAGE_LIMIT = 240 +const BUILTIN_PACK: RegisteredSoundPack = { + id: DEFAULT_PACK_ID, + name: "OpenCode Default", + builtin: true, + sounds: { + default: defaultSoundPath, + question: questionSoundPath, + permission: permissionSoundPath, + error: errorSoundPath, + done: doneSoundPath, + subagent_done: subagentDoneSoundPath, + }, +} + +function skipped(reason: TuiAttentionNotifySkipReason): TuiAttentionNotifyResult { + return { + ok: false, + notification: false, + sound: false, + skipped: reason, + } +} + +function normalizeText(input: string | undefined, fallback: string, limit: number) { + const text = stripAnsi(input ?? "") + .replace(/[ \t]*[\r\n]+[ \t]*/g, " ") + .replace(/[\u0000-\u0009\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, "") + .trim() + const normalized = text.length ? text : fallback + return Array.from(normalized).slice(0, limit).join("") +} + +function clampVolume(volume: number) { + if (!Number.isFinite(volume)) return 0 + return Math.min(1, Math.max(0, volume)) +} + +function soundVolume(input: TuiAttentionNotifyInput, config: Pick) { + if (!config.attention.sound) return + if (input.sound === false) return + if (input.sound === undefined) return clampVolume(config.attention.volume) + if (input.sound === true) return clampVolume(config.attention.volume) + return clampVolume(input.sound.volume ?? config.attention.volume) +} + +function normalizePack(pack: TuiAttentionSoundPack): RegisteredSoundPack | undefined { + const id = pack.id.trim() + if (!id) return + return { + id, + name: pack.name?.trim() || undefined, + builtin: false, + sounds: Object.fromEntries( + Object.entries(pack.sounds).filter( + (item): item is [TuiAttentionSoundName, string] => + isAttentionSoundName(item[0]) && typeof item[1] === "string" && item[1].trim().length > 0, + ), + ), + } +} + +function focusSkip(when: TuiAttentionWhen, focus: FocusState) { + if (when === "always") return + if (focus === "unknown") return "focus_unknown" + if (when === "blurred" && focus === "focused") return "focused" + if (when === "focused" && focus === "blurred") return "blurred" +} + +export function createTuiAttention(input: { + renderer: AttentionRenderer + config: Pick + kv?: TuiKV + audio?: Pick +}): TuiAttentionHost { + let focus: FocusState = "unknown" + let disposed = false + let activePackID: string | undefined + const packs = new Map([[BUILTIN_PACK.id, BUILTIN_PACK]]) + const audio = input.audio ?? TuiAudio + + const onFocus = () => { + focus = "focused" + } + const onBlur = () => { + focus = "blurred" + } + + input.renderer.on("focus", onFocus) + input.renderer.on("blur", onBlur) + + function configuredPackID() { + const stored = input.kv?.get(KV_SOUND_PACK, undefined) + return activePackID ?? stored ?? input.config.attention.sound_pack + } + + function currentPack() { + return packs.get(configuredPackID()) ?? BUILTIN_PACK + } + + function soundCandidates(name: TuiAttentionSoundName) { + return [input.config.attention.sounds[name], currentPack().sounds[name], BUILTIN_PACK.sounds[name]].filter( + (item, index, list): item is string => typeof item === "string" && list.indexOf(item) === index, + ) + } + + async function playSound(name: TuiAttentionSoundName, volume: number) { + try { + for (const file of soundCandidates(name)) { + const current = await audio.loadSoundFile(file).catch((error) => { + log.debug("failed to load attention sound", { file, error }) + return null + }) + if (disposed) return false + if (current == null) continue + if (audio.play(current, { volume }) != null) return true + } + return false + } catch (error) { + log.debug("failed to play attention sound", { error }) + return false + } + } + + return { + async notify(request) { + try { + if (!input.config.attention.enabled) return skipped("attention_disabled") + if (disposed || input.renderer.isDestroyed) return skipped("renderer_destroyed") + + const message = normalizeText(request.message, "", MESSAGE_LIMIT) + if (!message) return skipped("empty_message") + + const requestedNotification = typeof request.notification === "object" ? request.notification : undefined + const notificationSkip = focusSkip(requestedNotification?.when ?? "blurred", focus) + const notificationRequested = input.config.attention.notifications && request.notification !== false + const shouldNotify = notificationRequested && !notificationSkip + const notification = shouldNotify + ? (() => { + try { + return input.renderer.triggerNotification( + message, + normalizeText(request.title, DEFAULT_TITLE, TITLE_LIMIT), + ) + } catch (error) { + log.debug("failed to trigger attention notification", { error }) + return false + } + })() + : false + const volume = soundVolume(request, input.config) + const requestedSound = typeof request.sound === "object" ? request.sound : undefined + const soundSkip = volume === undefined ? undefined : focusSkip(requestedSound?.when ?? "always", focus) + const soundName = requestedSound?.name && isAttentionSoundName(requestedSound.name) ? requestedSound.name : "default" + const sound = volume === undefined || soundSkip ? false : await playSound(soundName, volume) + + if (!notification && !sound) { + if (notificationRequested && notificationSkip) return skipped(notificationSkip) + if (soundSkip) return skipped(soundSkip) + } + + return { + ok: notification || sound, + notification, + sound, + } + } catch (error) { + log.debug("failed to handle attention notification", { error }) + return { + ok: false, + notification: false, + sound: false, + } + } + }, + soundboard: { + registerPack(pack) { + const next = normalizePack(pack) + if (!next) return () => {} + packs.set(next.id, next) + let disposed = false + return () => { + if (disposed) return + disposed = true + if (packs.get(next.id) === next) packs.delete(next.id) + } + }, + activate(id, options) { + const pack = packs.get(id) + if (!pack) return false + activePackID = pack.id + if (options?.persist) input.kv?.set(KV_SOUND_PACK, pack.id) + return true + }, + current() { + return currentPack().id + }, + list(): TuiAttentionSoundPackInfo[] { + const current = currentPack().id + return Array.from(packs.values()).map((pack) => ({ + id: pack.id, + name: pack.name, + active: pack.id === current, + builtin: pack.builtin, + })) + }, + }, + dispose() { + if (disposed) return + disposed = true + input.renderer.off("focus", onFocus) + input.renderer.off("blur", onBlur) + }, + } +} diff --git a/packages/opencode/src/cli/cmd/tui/config/tui-schema.ts b/packages/opencode/src/cli/cmd/tui/config/tui-schema.ts index 80765da3c7..2c99f2a5ef 100644 --- a/packages/opencode/src/cli/cmd/tui/config/tui-schema.ts +++ b/packages/opencode/src/cli/cmd/tui/config/tui-schema.ts @@ -1,12 +1,47 @@ import { ConfigPlugin } from "@/config/plugin" import { TuiKeybind } from "./keybind" import { Schema } from "effect" +import { isRecord } from "@/util/record" +import { Filesystem } from "@/util/filesystem" +import { TuiAttentionSoundNames, type TuiAttentionSoundName } from "@opencode-ai/plugin/tui" + +export type TuiAttentionSoundPaths = Partial> + +export function isAttentionSoundName(value: string): value is TuiAttentionSoundName { + return TuiAttentionSoundNames.includes(value as TuiAttentionSoundName) +} + +export function resolveAttentionSoundPaths( + root: string, + sounds: unknown, + options?: { trim?: boolean }, +): TuiAttentionSoundPaths { + if (!isRecord(sounds)) return {} + return Object.fromEntries( + Object.entries(sounds).flatMap(([name, file]) => { + if (!isAttentionSoundName(name)) return [] + if (typeof file !== "string") return [] + const value = options?.trim ? file.trim() : file + if (!value) return [] + return [[name, Filesystem.resolveFilePath(root, value)]] + }), + ) +} export const KeymapLeaderTimeoutDefault = 2000 const KeymapLeaderTimeout = Schema.Int.check(Schema.isGreaterThan(0)).annotate({ description: "Leader key timeout in milliseconds", }) +const TuiAttentionSounds = Schema.Struct({ + default: Schema.optional(Schema.String), + question: Schema.optional(Schema.String), + permission: Schema.optional(Schema.String), + error: Schema.optional(Schema.String), + done: Schema.optional(Schema.String), + subagent_done: Schema.optional(Schema.String), +}) + export const ScrollSpeed = Schema.Number.check(Schema.isGreaterThanOrEqualTo(0.001)) export const ScrollAcceleration = Schema.Struct({ @@ -17,6 +52,15 @@ export const DiffStyle = Schema.Literals(["auto", "stacked"]).annotate({ description: "Control diff rendering style: 'auto' adapts to terminal width, 'stacked' always shows single column", }) +export const Attention = Schema.Struct({ + enabled: Schema.optional(Schema.Boolean), + notifications: Schema.optional(Schema.Boolean), + sound: Schema.optional(Schema.Boolean), + volume: Schema.optional(Schema.Number.check(Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(1))), + sound_pack: Schema.optional(Schema.String), + sounds: Schema.optional(TuiAttentionSounds), +}).annotate({ description: "Attention notification and sound settings" }) + export const TuiInfo = Schema.Struct({ $schema: Schema.optional(Schema.String), theme: Schema.optional(Schema.String), @@ -24,6 +68,7 @@ export const TuiInfo = Schema.Struct({ plugin: Schema.optional(Schema.Array(ConfigPlugin.Spec)), plugin_enabled: Schema.optional(Schema.Record(Schema.String, Schema.Boolean)), leader_timeout: Schema.optional(KeymapLeaderTimeout), + attention: Schema.optional(Attention), scroll_speed: Schema.optional(ScrollSpeed).annotate({ description: "TUI scroll speed", }), diff --git a/packages/opencode/src/cli/cmd/tui/config/tui.ts b/packages/opencode/src/cli/cmd/tui/config/tui.ts index e53e20d343..562b369db1 100644 --- a/packages/opencode/src/cli/cmd/tui/config/tui.ts +++ b/packages/opencode/src/cli/cmd/tui/config/tui.ts @@ -1,5 +1,6 @@ export * as TuiConfig from "./tui" +import path from "path" import { createBindingLookup } from "@opentui/keymap/extras" import { mergeDeep, unique } from "remeda" import { Context, Effect, Fiber, Layer, Schema } from "effect" @@ -7,7 +8,7 @@ import { ConfigParse } from "@/config/parse" import { InvalidError } from "@/config/error" import * as ConfigPaths from "@/config/paths" import { migrateTuiConfig } from "./tui-migrate" -import { KeymapLeaderTimeoutDefault, TuiInfo } from "./tui-schema" +import { KeymapLeaderTimeoutDefault, resolveAttentionSoundPaths, TuiInfo } from "./tui-schema" import { Flag } from "@opencode-ai/core/flag/flag" import { isRecord } from "@/util/record" import { Global } from "@opencode-ai/core/global" @@ -22,6 +23,7 @@ import * as Log from "@opencode-ai/core/util/log" import { ConfigVariable } from "@/config/variable" import { Npm } from "@opencode-ai/core/npm" import type { DeepMutable } from "@opencode-ai/core/schema" +import type { TuiAttentionSoundName } from "@opencode-ai/plugin/tui" const log = Log.create({ service: "tui.config" }) @@ -33,7 +35,15 @@ type Acc = { plugin_origins: ConfigPlugin.Origin[] } -export type Resolved = Omit & { +export type Resolved = Omit & { + attention: { + enabled: boolean + notifications: boolean + sound: boolean + volume: number + sound_pack: string + sounds: Partial> + } keybinds: TuiKeybind.BindingLookupView leader_timeout: number // Internal resolved plugin list used by runtime loading. @@ -101,7 +111,16 @@ const loadState = Effect.fn("TuiConfig.loadState")(function* (ctx: { directory: }) } } - const validated = ConfigParse.schema(Info, normalized, configFilepath) + const parsed = ConfigParse.schema(Info, normalized, configFilepath) + const validated = parsed.attention?.sounds + ? { + ...parsed, + attention: { + ...parsed.attention, + sounds: resolveAttentionSoundPaths(path.dirname(configFilepath), parsed.attention.sounds), + }, + } + : parsed return yield* resolvePlugins(validated, configFilepath) }).pipe( // catchCause (not tapErrorCause + orElseSucceed) because JSONC parsing and validation @@ -197,6 +216,14 @@ const loadState = Effect.fn("TuiConfig.loadState")(function* (ctx: { directory: const parsedKeybinds = TuiKeybind.parse(keybinds) const result: Resolved = { ...acc.result, + attention: { + enabled: acc.result.attention?.enabled ?? false, + notifications: acc.result.attention?.notifications ?? true, + sound: acc.result.attention?.sound ?? true, + volume: acc.result.attention?.volume ?? 0.4, + sound_pack: acc.result.attention?.sound_pack ?? "opencode.default", + sounds: acc.result.attention?.sounds ?? {}, + }, keybinds: createBindingLookup(TuiKeybind.toBindingConfig(parsedKeybinds), { commandMap: TuiKeybind.CommandMap, bindingDefaults: TuiKeybind.bindingDefaults(), diff --git a/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx b/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx index 07a2844e93..8c50914df3 100644 --- a/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx +++ b/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx @@ -1,11 +1,52 @@ -import { createMemo, For } from "solid-js" +import type { TuiPluginApi } from "@opencode-ai/plugin/tui" +import { createMemo, For, type Accessor } from "solid-js" import { DEFAULT_THEMES, useTheme } from "@tui/context/theme" import { Flag } from "@opencode-ai/core/flag/flag" +import { useCommandShortcut } from "../../keymap" const themeCount = Object.keys(DEFAULT_THEMES).length -const themeTip = `Use {highlight}/themes{/highlight} or {highlight}Ctrl+X T{/highlight} to switch between ${themeCount} built-in themes` type TipPart = { text: string; highlight: boolean } +type TipShortcut = Accessor +type Shortcuts = { + agentCycle: TipShortcut + childFirst: TipShortcut + childNext: TipShortcut + childPrevious: TipShortcut + commandList: TipShortcut + editorOpen: TipShortcut + helpShow: TipShortcut + inputClear: TipShortcut + inputNewline: TipShortcut + inputPaste: TipShortcut + inputUndo: TipShortcut + leader: TipShortcut + messagesCopy: TipShortcut + messagesFirst: TipShortcut + messagesLast: TipShortcut + messagesPageDown: TipShortcut + messagesPageUp: TipShortcut + messagesToggleConceal: TipShortcut + modelCycleRecent: TipShortcut + modelList: TipShortcut + sessionCycleRecent: TipShortcut + sessionCycleRecentReverse: TipShortcut + sessionExport: TipShortcut + sessionInterrupt: TipShortcut + sessionList: TipShortcut + sessionNew: TipShortcut + sessionParent: TipShortcut + sessionPinToggle: TipShortcut + sessionQuickSwitch1: TipShortcut + sessionQuickSwitch9: TipShortcut + sessionSidebarToggle: TipShortcut + sessionTimeline: TipShortcut + sessionToggleRecent: TipShortcut + statusView: TipShortcut + terminalSuspend: TipShortcut + themeList: TipShortcut +} +type Tip = string | ((shortcuts: Shortcuts) => string | undefined) function parse(tip: string): TipPart[] { const parts: TipPart[] = [] @@ -33,17 +74,86 @@ function parse(tip: string): TipPart[] { const NO_MODELS_TIP = "Run {highlight}/connect{/highlight} to add an AI provider and start coding" -export function Tips(props: { connected?: boolean }) { +function shortcutText(value: string) { + return `{highlight}${value}{/highlight}` +} + +function commandText(command: string, shortcut: string) { + if (!shortcut) return shortcutText(command) + return `${shortcutText(command)} or ${shortcutText(shortcut)}` +} + +function press(shortcut: string, text: string) { + if (!shortcut) return undefined + return `Press ${shortcutText(shortcut)} ${text}` +} + +function configShortcut(api: TuiPluginApi, command: string): TipShortcut { + return () => + api.tuiConfig.keybinds + .get(command) + .map((binding) => api.keys.formatSequence(Array.from(api.keymap.parseKeySequence(binding.key)))) + .filter(Boolean) + .join(", ") +} + +export function Tips(props: { api: TuiPluginApi; connected?: boolean }) { const theme = useTheme().theme - const randomTip = TIPS[Math.floor(Math.random() * TIPS.length)] - const parts = createMemo(() => parse(props.connected === false ? NO_MODELS_TIP : randomTip)) + const tipOffset = Math.random() + const shortcuts: Shortcuts = { + agentCycle: useCommandShortcut("agent.cycle"), + childFirst: configShortcut(props.api, "session.child.first"), + childNext: configShortcut(props.api, "session.child.next"), + childPrevious: configShortcut(props.api, "session.child.previous"), + commandList: useCommandShortcut("command.palette.show"), + editorOpen: useCommandShortcut("prompt.editor"), + helpShow: useCommandShortcut("help.show"), + inputClear: useCommandShortcut("prompt.clear"), + inputNewline: useCommandShortcut("input.newline"), + inputPaste: useCommandShortcut("prompt.paste"), + inputUndo: useCommandShortcut("input.undo"), + leader: configShortcut(props.api, "leader"), + messagesCopy: configShortcut(props.api, "messages.copy"), + messagesFirst: configShortcut(props.api, "session.first"), + messagesLast: configShortcut(props.api, "session.last"), + messagesPageDown: configShortcut(props.api, "session.page.down"), + messagesPageUp: configShortcut(props.api, "session.page.up"), + messagesToggleConceal: configShortcut(props.api, "session.toggle.conceal"), + modelCycleRecent: useCommandShortcut("model.cycle_recent"), + modelList: useCommandShortcut("model.list"), + sessionCycleRecent: useCommandShortcut("session.cycle_recent"), + sessionCycleRecentReverse: useCommandShortcut("session.cycle_recent_reverse"), + sessionExport: configShortcut(props.api, "session.export"), + sessionInterrupt: configShortcut(props.api, "session.interrupt"), + sessionList: useCommandShortcut("session.list"), + sessionNew: useCommandShortcut("session.new"), + sessionParent: configShortcut(props.api, "session.parent"), + sessionPinToggle: configShortcut(props.api, "session.pin.toggle"), + sessionQuickSwitch1: useCommandShortcut("session.quick_switch.1"), + sessionQuickSwitch9: useCommandShortcut("session.quick_switch.9"), + sessionSidebarToggle: configShortcut(props.api, "session.sidebar.toggle"), + sessionTimeline: configShortcut(props.api, "session.timeline"), + sessionToggleRecent: configShortcut(props.api, "session.toggle.recent"), + statusView: useCommandShortcut("opencode.status"), + terminalSuspend: useCommandShortcut("terminal.suspend"), + themeList: useCommandShortcut("theme.switch"), + } + const tip = createMemo(() => { + if (props.connected === false) return NO_MODELS_TIP + const tips = TIPS.flatMap((item) => { + const value = typeof item === "string" ? item : item(shortcuts) + return value ? [value] : [] + }) + return tips[Math.floor(tipOffset * tips.length)] ?? NO_MODELS_TIP + }) + const parts = createMemo(() => parse(tip())) return ( ● Tip{" "} - + {(part) => {part.text}} @@ -52,46 +162,66 @@ export function Tips(props: { connected?: boolean }) { ) } -const TIPS = [ +const TIPS: Tip[] = [ "Type {highlight}@{/highlight} followed by a filename to fuzzy search and attach files", "Start a message with {highlight}!{/highlight} to run shell commands directly (e.g., {highlight}!ls -la{/highlight})", - "Press {highlight}Tab{/highlight} to cycle between Build and Plan agents", + (shortcuts) => press(shortcuts.agentCycle(), "to cycle between Build and Plan agents"), "Use {highlight}/undo{/highlight} to revert the last message and file changes", "Use {highlight}/redo{/highlight} to restore previously undone messages and file changes", "Run {highlight}/share{/highlight} to create a public link to your conversation at opencode.ai", "Drag and drop images or PDFs into the terminal to add them as context", - "Press {highlight}Ctrl+V{/highlight} to paste images from your clipboard into the prompt", - "Press {highlight}Ctrl+X E{/highlight} or {highlight}/editor{/highlight} to compose messages in your external editor", + (shortcuts) => press(shortcuts.inputPaste(), "to paste images from your clipboard into the prompt"), + (shortcuts) => `Use ${commandText("/editor", shortcuts.editorOpen())} to compose messages in your external editor`, "Run {highlight}/init{/highlight} to auto-generate project rules based on your codebase", - "Run {highlight}/models{/highlight} or {highlight}Ctrl+X M{/highlight} to see and switch between available AI models", - themeTip, - "Press {highlight}Ctrl+X N{/highlight} or {highlight}/new{/highlight} to start a fresh conversation session", - "Use {highlight}/sessions{/highlight} or {highlight}Ctrl+X L{/highlight} to list and continue previous conversations", + (shortcuts) => `Use ${commandText("/models", shortcuts.modelList())} to see and switch between available AI models`, + (shortcuts) => `Use ${commandText("/themes", shortcuts.themeList())} to switch between ${themeCount} built-in themes`, + (shortcuts) => `Use ${commandText("/new", shortcuts.sessionNew())} to start a fresh conversation session`, + (shortcuts) => `Use ${commandText("/sessions", shortcuts.sessionList())} to list and continue previous conversations`, ...(Flag.OPENCODE_EXPERIMENTAL_SESSION_SWITCHING - ? [ - "Press {highlight}Ctrl+F{/highlight} in the session list to pin a session so it stays at the top", - "Pinned and recent sessions are bound to {highlight}Ctrl+X 1{/highlight} through {highlight}Ctrl+X 9{/highlight} for one-press switching", - "Press {highlight}Ctrl+X ]{/highlight} / {highlight}Ctrl+X [{/highlight} to cycle through recently visited sessions", - "Press {highlight}Ctrl+H{/highlight} in the session list to show or hide a session in the Recent group", - ] + ? ([ + (shortcuts) => + press(shortcuts.sessionPinToggle(), "in the session list to pin a session so it stays at the top"), + (shortcuts) => + shortcuts.sessionQuickSwitch1() && shortcuts.sessionQuickSwitch9() + ? `Pinned and recent sessions are bound to ${shortcutText(shortcuts.sessionQuickSwitch1())} through ${shortcutText(shortcuts.sessionQuickSwitch9())} for one-press switching` + : undefined, + (shortcuts) => + shortcuts.sessionCycleRecent() && shortcuts.sessionCycleRecentReverse() + ? `Press ${shortcutText(shortcuts.sessionCycleRecent())} / ${shortcutText(shortcuts.sessionCycleRecentReverse())} to cycle through recently visited sessions` + : undefined, + (shortcuts) => + press(shortcuts.sessionToggleRecent(), "in the session list to show or hide a session in the Recent group"), + ] satisfies Tip[]) : []), "Run {highlight}/compact{/highlight} to summarize long sessions near context limits", - "Press {highlight}Ctrl+X X{/highlight} or {highlight}/export{/highlight} to save the conversation as Markdown", - "Press {highlight}Ctrl+X Y{/highlight} to copy the assistant's last message to clipboard", - "Press {highlight}Ctrl+P{/highlight} to see all available actions and commands", + (shortcuts) => `Use ${commandText("/export", shortcuts.sessionExport())} to save the conversation as Markdown`, + (shortcuts) => press(shortcuts.messagesCopy(), "to copy the assistant's last message to clipboard"), + (shortcuts) => press(shortcuts.commandList(), "to see all available actions and commands"), "Run {highlight}/connect{/highlight} to add API keys for 75+ supported LLM providers", - "The leader key is {highlight}Ctrl+X{/highlight}; combine with other keys for quick actions", - "Press {highlight}F2{/highlight} to quickly switch between recently used models", - "Press {highlight}Ctrl+X B{/highlight} to show/hide the sidebar panel", - "Use {highlight}PageUp{/highlight}/{highlight}PageDown{/highlight} to navigate through conversation history", - "Press {highlight}Ctrl+G{/highlight} or {highlight}Home{/highlight} to jump to the beginning of the conversation", - "Press {highlight}Ctrl+Alt+G{/highlight} or {highlight}End{/highlight} to jump to the most recent message", - "Press {highlight}Shift+Enter{/highlight} or {highlight}Ctrl+J{/highlight} to add newlines in your prompt", - "Press {highlight}Ctrl+C{/highlight} when typing to clear the input field", - "Press {highlight}Escape{/highlight} to stop the AI mid-response", + (shortcuts) => `The leader key is ${shortcutText(shortcuts.leader())}; combine with other keys for quick actions`, + (shortcuts) => press(shortcuts.modelCycleRecent(), "to quickly switch between recently used models"), + (shortcuts) => press(shortcuts.sessionSidebarToggle(), "in a session to show or hide the sidebar panel"), + (shortcuts) => + shortcuts.messagesPageUp() && shortcuts.messagesPageDown() + ? `Use ${shortcutText(shortcuts.messagesPageUp())}/${shortcutText(shortcuts.messagesPageDown())} to navigate through conversation history` + : undefined, + (shortcuts) => press(shortcuts.messagesFirst(), "to jump to the beginning of the conversation"), + (shortcuts) => press(shortcuts.messagesLast(), "to jump to the most recent message"), + (shortcuts) => press(shortcuts.inputNewline(), "to add newlines in your prompt"), + (shortcuts) => press(shortcuts.inputClear(), "when typing to clear the input field"), + (shortcuts) => press(shortcuts.sessionInterrupt(), "to stop the AI mid-response"), "Switch to {highlight}Plan{/highlight} agent to get suggestions without making actual changes", "Use {highlight}@agent-name{/highlight} in prompts to invoke specialized subagents", - "Press {highlight}Ctrl+X Right/Left{/highlight} to cycle through parent and child sessions", + (shortcuts) => { + const items = [ + shortcuts.sessionParent(), + shortcuts.childFirst(), + shortcuts.childPrevious(), + shortcuts.childNext(), + ].filter(Boolean) + if (!items.length) return undefined + return `Use ${items.map(shortcutText).join(" / ")} to move between parent and child sessions` + }, "Create {highlight}opencode.json{/highlight} for server settings and {highlight}tui.json{/highlight} for TUI settings", "Place TUI settings in {highlight}~/.config/opencode/tui.json{/highlight} for global config", "Add {highlight}$schema{/highlight} to your config for autocomplete in your editor", @@ -99,22 +229,21 @@ const TIPS = [ "Override any keybind in {highlight}tui.json{/highlight} via the {highlight}keybinds{/highlight} section", "Set any keybind to {highlight}none{/highlight} to disable it completely", "Configure local or remote MCP servers in the {highlight}mcp{/highlight} config section", - "OpenCode auto-handles OAuth for remote MCP servers requiring auth", - "Add {highlight}.md{/highlight} files to {highlight}.opencode/command/{/highlight} to define reusable custom prompts", + "Add {highlight}.md{/highlight} files to {highlight}.opencode/commands/{/highlight} to define reusable custom prompts", "Use {highlight}$ARGUMENTS{/highlight}, {highlight}$1{/highlight}, {highlight}$2{/highlight} in custom commands for dynamic input", "Use backticks in commands to inject shell output (e.g., {highlight}`git status`{/highlight})", - "Add {highlight}.md{/highlight} files to {highlight}.opencode/agent/{/highlight} for specialized AI personas", + "Add {highlight}.md{/highlight} files to {highlight}.opencode/agents/{/highlight} for specialized AI personas", "Configure per-agent permissions for {highlight}edit{/highlight}, {highlight}bash{/highlight}, and {highlight}webfetch{/highlight} tools", 'Use patterns like {highlight}"git *": "allow"{/highlight} for granular bash permissions', 'Set {highlight}"rm -rf *": "deny"{/highlight} to block destructive commands', 'Configure {highlight}"git push": "ask"{/highlight} to require approval before pushing', - "OpenCode auto-formats files using prettier, gofmt, ruff, and more", - 'Set {highlight}"formatter": false{/highlight} in config to disable all auto-formatting', + 'Set {highlight}"formatter": true{/highlight} in config to enable built-in formatters like prettier, gofmt, and ruff', + 'Set {highlight}"formatter": false{/highlight} in config to disable formatters enabled by another config layer', "Define custom formatter commands with file extensions in config", - "OpenCode uses LSP servers for intelligent code analysis", + 'Set {highlight}"lsp": true{/highlight} in config to enable built-in LSP servers for code analysis', "Create {highlight}.ts{/highlight} files in {highlight}.opencode/tools/{/highlight} to define new LLM tools", "Tool definitions can invoke scripts written in Python, Go, etc", - "Add {highlight}.ts{/highlight} files to {highlight}.opencode/plugin/{/highlight} for event hooks", + "Add {highlight}.ts{/highlight} files to {highlight}.opencode/plugins/{/highlight} for event hooks", "Use plugins to send OS notifications when sessions complete", "Create a plugin to prevent OpenCode from reading sensitive files", "Use {highlight}opencode run{/highlight} for non-interactive scripting", @@ -133,7 +262,7 @@ const TIPS = [ 'Use {highlight}"theme": "system"{/highlight} to match your terminal\'s colors', "Create JSON theme files in {highlight}.opencode/themes/{/highlight} directory", "Themes support dark/light variants for both modes", - "Reference ANSI colors 0-255 in custom themes", + "Use numeric xterm color codes 0-255 in custom theme JSON", "Use {highlight}{env:VAR_NAME}{/highlight} syntax to reference environment variables in config", "Use {highlight}{file:path}{/highlight} to include file contents in config values", "Use {highlight}instructions{/highlight} in config to load additional rules files", @@ -149,18 +278,23 @@ const TIPS = [ "Permission {highlight}external_directory{/highlight} protects files outside project", "Run {highlight}opencode debug config{/highlight} to troubleshoot configuration", "Use {highlight}--print-logs{/highlight} flag to see detailed logs in stderr", - "Press {highlight}Ctrl+X G{/highlight} or {highlight}/timeline{/highlight} to jump to specific messages", - "Press {highlight}Ctrl+X H{/highlight} to toggle code block visibility in messages", - "Press {highlight}Ctrl+X S{/highlight} or {highlight}/status{/highlight} to see system status info", + (shortcuts) => `Use ${commandText("/timeline", shortcuts.sessionTimeline())} to jump to specific messages`, + (shortcuts) => press(shortcuts.messagesToggleConceal(), "to toggle code block visibility in messages"), + (shortcuts) => `Use ${commandText("/status", shortcuts.statusView())} to see system status info`, "Enable {highlight}scroll_acceleration{/highlight} in {highlight}tui.json{/highlight} for smooth macOS-style scrolling", - "Toggle username display in chat via command palette ({highlight}Ctrl+P{/highlight})", + (shortcuts) => + shortcuts.commandList() + ? `Toggle username display in chat via the command palette (${shortcutText(shortcuts.commandList())})` + : "Toggle username display in chat via the command palette", "Run {highlight}docker run -it --rm ghcr.io/anomalyco/opencode{/highlight} for containerized use", "Use {highlight}/connect{/highlight} with OpenCode Zen for curated, tested models", "Commit your project's {highlight}AGENTS.md{/highlight} file to Git for team sharing", "Use {highlight}/review{/highlight} to review uncommitted changes, branches, or PRs", - "Run {highlight}/help{/highlight} or {highlight}Ctrl+X H{/highlight} to show the help dialog", + (shortcuts) => `Use ${commandText("/help", shortcuts.helpShow())} to show the help dialog`, "Use {highlight}/rename{/highlight} to rename the current session", ...(process.platform === "win32" - ? ["Press {highlight}Ctrl+Z{/highlight} to undo changes in your prompt"] - : ["Press {highlight}Ctrl+Z{/highlight} to suspend the terminal and return to your shell"]), + ? ([(shortcuts) => press(shortcuts.inputUndo(), "to undo changes in your prompt")] satisfies Tip[]) + : ([ + (shortcuts) => press(shortcuts.terminalSuspend(), "to suspend the terminal and return to your shell"), + ] satisfies Tip[])), ] diff --git a/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips.tsx b/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips.tsx index 69071b1f7c..598366c08c 100644 --- a/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips.tsx +++ b/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips.tsx @@ -24,9 +24,9 @@ function View(props: { api: TuiPluginApi; hidden: boolean; show: boolean; connec })) return ( - + - + ) diff --git a/packages/opencode/src/cli/cmd/tui/feature-plugins/system/notifications.ts b/packages/opencode/src/cli/cmd/tui/feature-plugins/system/notifications.ts new file mode 100644 index 0000000000..cda815f5fc --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/feature-plugins/system/notifications.ts @@ -0,0 +1,94 @@ +import type { Event } from "@opencode-ai/sdk/v2" +import type { TuiAttentionSoundName, TuiPlugin, TuiPluginApi } from "@opencode-ai/plugin/tui" +import type { InternalTuiPlugin } from "../../plugin/internal" + +const id = "internal:notifications" + +type SessionError = Extract["properties"]["error"] + +function notify(api: TuiPluginApi, sessionID: string | undefined, message: string, sound: TuiAttentionSoundName) { + const session = sessionID ? api.state.session.get(sessionID) : undefined + const isSubagent = session?.parentID !== undefined + void api.attention.notify({ + title: session?.title, + message, + notification: isSubagent ? false : { when: "blurred" }, + sound: { name: sound, when: "always" }, + }) +} + +function sessionErrorMessage(error: SessionError) { + if (error?.name === "MessageAbortedError") return "Session aborted" + const data = error?.data + if (data && typeof data === "object" && "message" in data && data.message === "SSE read timed out") { + return "Model stopped responding" + } + return "Session error" +} + +const tui: TuiPlugin = async (api) => { + const active = new Set() + const errored = new Set() + const questions = new Set() + const permissions = new Set() + + api.event.on("question.asked", (event) => { + if (questions.has(event.properties.id)) return + questions.add(event.properties.id) + notify(api, event.properties.sessionID, "Question needs input", "question") + }) + + api.event.on("question.replied", (event) => { + questions.delete(event.properties.requestID) + }) + + api.event.on("question.rejected", (event) => { + questions.delete(event.properties.requestID) + }) + + api.event.on("permission.asked", (event) => { + if (permissions.has(event.properties.id)) return + permissions.add(event.properties.id) + notify(api, event.properties.sessionID, "Permission needs input", "permission") + }) + + api.event.on("permission.replied", (event) => { + permissions.delete(event.properties.requestID) + }) + + api.event.on("session.status", (event) => { + const sessionID = event.properties.sessionID + if (event.properties.status.type === "busy" || event.properties.status.type === "retry") { + active.add(sessionID) + errored.delete(sessionID) + return + } + + if (event.properties.status.type !== "idle") return + if (!active.has(sessionID)) return + active.delete(sessionID) + + if (errored.has(sessionID)) { + errored.delete(sessionID) + return + } + + const session = api.state.session.get(sessionID) + notify(api, sessionID, "Session done", session?.parentID ? "subagent_done" : "done") + }) + + api.event.on("session.error", (event) => { + const sessionID = event.properties.sessionID + if (!sessionID) return + if (!active.has(sessionID)) return + errored.add(sessionID) + notify(api, sessionID, sessionErrorMessage(event.properties.error), "error") + }) +} + +const plugin: InternalTuiPlugin = { + id, + tui, +} + +export default plugin diff --git a/packages/opencode/src/cli/cmd/tui/plugin/api.tsx b/packages/opencode/src/cli/cmd/tui/plugin/api.tsx index 8958a92853..05bfa31d14 100644 --- a/packages/opencode/src/cli/cmd/tui/plugin/api.tsx +++ b/packages/opencode/src/cli/cmd/tui/plugin/api.tsx @@ -40,6 +40,7 @@ type Input = { theme: ReturnType toast: ReturnType renderer: TuiPluginApi["renderer"] + attention: TuiPluginApi["attention"] } function routeRegister(routes: RouteMap, list: TuiRouteDefinition[], bump: () => void) { @@ -206,6 +207,7 @@ export function createTuiApi(input: Input): TuiPluginApi { } return { app: appApi(), + attention: input.attention, // Keep deprecated `api.command` working for v1 plugins; remove in v2. command: createCommandShim(input.keymap, input.dialog, input.tuiConfig.keybinds), keys: { diff --git a/packages/opencode/src/cli/cmd/tui/plugin/internal.ts b/packages/opencode/src/cli/cmd/tui/plugin/internal.ts index 664b5c1ac1..eaa9dfb320 100644 --- a/packages/opencode/src/cli/cmd/tui/plugin/internal.ts +++ b/packages/opencode/src/cli/cmd/tui/plugin/internal.ts @@ -7,6 +7,7 @@ import SidebarTodo from "../feature-plugins/sidebar/todo" import SidebarFiles from "../feature-plugins/sidebar/files" import SidebarFooter from "../feature-plugins/sidebar/footer" import PluginManager from "../feature-plugins/system/plugins" +import Notifications from "../feature-plugins/system/notifications" import SessionV2Debug from "../feature-plugins/system/session-v2" import WhichKey from "../feature-plugins/system/which-key" import type { TuiPlugin, TuiPluginModule } from "@opencode-ai/plugin/tui" @@ -27,6 +28,7 @@ export const INTERNAL_TUI_PLUGINS: InternalTuiPlugin[] = [ SidebarTodo, SidebarFiles, SidebarFooter, + Notifications, PluginManager, WhichKey, ...(Flag.OPENCODE_EXPERIMENTAL_EVENT_SYSTEM ? [SessionV2Debug] : []), diff --git a/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts b/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts index dad4595e7f..4af16d2b8e 100644 --- a/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts +++ b/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts @@ -17,6 +17,7 @@ import { TuiConfig } from "@/cli/cmd/tui/config/tui" import * as Log from "@opencode-ai/core/util/log" import { errorData, errorMessage } from "@/util/error" import { isRecord } from "@/util/record" +import { resolveAttentionSoundPaths } from "../config/tui-schema" import { readPackageThemes, readPluginId, @@ -51,7 +52,7 @@ type PluginLoad = { id: string module: TuiPluginModule origin: ConfigPlugin.Origin - theme_root: string + plugin_root: string theme_files: string[] } @@ -106,6 +107,7 @@ const ScopedKeymapMethods = new Set([ type RuntimeState = { directory: string api: Api + dispose?: () => void slots: HostSlots plugins: PluginEntry[] plugins_by_id: Map @@ -156,6 +158,37 @@ function createScopedKeymap(keymap: TuiPluginApi["keymap"], scope: PluginScope): }) } +function createScopedAttention( + attention: TuiPluginApi["attention"], + scope: PluginScope, + root: string, +): TuiPluginApi["attention"] { + return { + notify(input) { + return attention.notify(input) + }, + soundboard: { + registerPack(pack) { + return scope.track( + attention.soundboard.registerPack({ + ...pack, + sounds: resolveAttentionSoundPaths(root, pack.sounds, { trim: true }), + }), + ) + }, + activate(id, options) { + return attention.soundboard.activate(id, options) + }, + current() { + return attention.soundboard.current() + }, + list() { + return attention.soundboard.list() + }, + }, + } +} + type CleanupResult = { type: "ok" } | { type: "error"; error: unknown } | { type: "timeout" } function runCleanup(fn: () => unknown, ms: number): Promise { @@ -204,8 +237,7 @@ function createThemeInstaller( plugin: PluginEntry, ): TuiTheme["install"] { return async (file) => { - const raw = file.startsWith("file://") ? fileURLToPath(file) : file - const src = path.isAbsolute(raw) ? raw : path.resolve(root, raw) + const src = Filesystem.resolveFilePath(root, file) const name = path.basename(src, path.extname(src)) const source_dir = path.dirname(meta.source) const local_dir = @@ -330,7 +362,7 @@ function loadInternalPlugin(item: InternalTuiPlugin): PluginLoad { scope: "global", source: target, }, - theme_root: process.cwd(), + plugin_root: process.cwd(), theme_files: [], } } @@ -352,7 +384,7 @@ async function readThemeFiles(spec: string, pkg?: PluginPackage) { async function syncPluginThemes(plugin: PluginEntry) { if (!plugin.load.theme_files.length) return if (plugin.meta.state === "same") return - const install = createThemeInstaller(plugin.load.origin, plugin.load.theme_root, plugin.load.spec, plugin) + const install = createThemeInstaller(plugin.load.origin, plugin.load.plugin_root, plugin.load.spec, plugin) for (const file of plugin.load.theme_files) { await install(file).catch((error) => { warn("failed to sync tui plugin oc-themes", { path: plugin.load.spec, id: plugin.id, theme: file, error }) @@ -552,7 +584,7 @@ function pluginApi(runtime: RuntimeState, plugin: PluginEntry, scope: PluginScop } const theme: TuiPluginApi["theme"] = Object.assign(Object.create(api.theme), { - install: createThemeInstaller(load.origin, load.theme_root, load.spec, plugin), + install: createThemeInstaller(load.origin, load.plugin_root, load.spec, plugin), }) const event: TuiPluginApi["event"] = { @@ -576,6 +608,7 @@ function pluginApi(runtime: RuntimeState, plugin: PluginEntry, scope: PluginScop return { app: api.app, + attention: createScopedAttention(api.attention, scope, load.plugin_root), // Keep deprecated `api.command` working for v1 plugins; remove in v2. command: createCommandShim(keymap, api.ui.dialog, api.tuiConfig.keybinds), keys: api.keys, @@ -682,7 +715,7 @@ async function resolveExternalPlugins(list: ConfigPlugin.Origin[], wait: () => P id, module: mod, origin, - theme_root: loaded.pkg?.dir ?? resolveRoot(loaded.target), + plugin_root: loaded.pkg?.dir ?? resolveRoot(loaded.target), theme_files, } }, @@ -709,7 +742,7 @@ async function resolveExternalPlugins(list: ConfigPlugin.Origin[], wait: () => P id, module: EMPTY_TUI, origin, - theme_root: loaded.pkg?.dir ?? resolveRoot(loaded.target), + plugin_root: loaded.pkg?.dir ?? resolveRoot(loaded.target), theme_files, } }, @@ -967,7 +1000,7 @@ let loaded: Promise | undefined let runtime: RuntimeState | undefined export const Slot = View -export async function init(input: { api: HostPluginApi; config: TuiConfig.Resolved }) { +export async function init(input: { api: HostPluginApi; config: TuiConfig.Resolved; dispose?: () => void }) { const cwd = process.cwd() if (loaded) { if (dir !== cwd) { @@ -1014,15 +1047,17 @@ export async function dispose() { for (const plugin of queue) { await deactivatePluginEntry(state, plugin, false) } + state.dispose?.() } -async function load(input: { api: Api; config: TuiConfig.Resolved }) { +async function load(input: { api: Api; config: TuiConfig.Resolved; dispose?: () => void }) { const { api, config } = input const cwd = process.cwd() const slots = setupSlots(api) const next: RuntimeState = { directory: cwd, api, + dispose: input.dispose, slots, plugins: [], plugins_by_id: new Map(), diff --git a/packages/opencode/src/cli/cmd/tui/util/audio.ts b/packages/opencode/src/cli/cmd/tui/util/audio.ts new file mode 100644 index 0000000000..7d7c3d5a42 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/util/audio.ts @@ -0,0 +1,58 @@ +import { Audio, type AudioErrorContext, type AudioPlayOptions, type AudioSound, type AudioVoice } from "@opentui/core" +import * as Log from "@opencode-ai/core/util/log" + +const log = Log.create({ service: "tui.audio" }) + +let audio: Audio | null | undefined +const sounds = new Map>() + +function getAudio() { + if (audio !== undefined) return audio + try { + const next = Audio.create({ autoStart: false }) + next.on("error", (error: Error, context: AudioErrorContext) => { + log.debug("tui audio error", { error, context }) + }) + audio = next + return next + } catch (error) { + log.debug("failed to create tui audio", { error }) + audio = null + return null + } +} + +export function loadSoundFile(file: string) { + const current = getAudio() + if (!current) return Promise.resolve(null) + const cached = sounds.get(file) + if (cached) return cached + const task = Bun.file(file) + .bytes() + .then((bytes) => current.loadSound(bytes)) + .catch((error) => { + log.debug("failed to load tui sound", { file, error }) + return null + }) + sounds.set(file, task) + return task +} + +export function play(sound: AudioSound, options?: AudioPlayOptions) { + const current = getAudio() + if (!current) return null + if (!current.isStarted() && !current.start()) return null + return current.play(sound, options) +} + +export function stopVoice(voice: AudioVoice) { + return audio?.stopVoice(voice) ?? false +} + +export function dispose() { + audio?.dispose() + audio = undefined + sounds.clear() +} + +export * as TuiAudio from "./audio" diff --git a/packages/opencode/src/util/filesystem.ts b/packages/opencode/src/util/filesystem.ts index ded2b45178..696603adbb 100644 --- a/packages/opencode/src/util/filesystem.ts +++ b/packages/opencode/src/util/filesystem.ts @@ -1,10 +1,11 @@ import { chmod, mkdir, readFile, stat as statFile, writeFile } from "fs/promises" import { createWriteStream, existsSync, statSync } from "fs" import { realpathSync } from "fs" -import { dirname, join, relative, resolve as pathResolve, win32 } from "path" +import { dirname, isAbsolute, join, relative, resolve as pathResolve, win32 } from "path" import { Readable } from "stream" import { pipeline } from "stream/promises" import { Glob } from "@opencode-ai/core/util/glob" +import { fileURLToPath } from "url" // Fast sync version for metadata checks export async function exists(p: string): Promise { @@ -142,6 +143,12 @@ export function resolve(p: string): string { } } +export function resolveFilePath(root: string, file: string): string { + const raw = file.startsWith("file://") ? fileURLToPath(file) : file + if (isAbsolute(raw)) return raw + return pathResolve(root, raw) +} + export function windowsPath(p: string): string { if (process.platform !== "win32") return p return ( diff --git a/packages/opencode/test/cli/cmd/tui/attention.test.ts b/packages/opencode/test/cli/cmd/tui/attention.test.ts new file mode 100644 index 0000000000..071aabdd79 --- /dev/null +++ b/packages/opencode/test/cli/cmd/tui/attention.test.ts @@ -0,0 +1,484 @@ +import { describe, expect, test } from "bun:test" +import type { AudioPlayOptions, AudioSound } from "@opentui/core" +import { createTuiAttention } from "@/cli/cmd/tui/attention" +import type { TuiConfig } from "@/cli/cmd/tui/config/tui" + +type FocusEvent = "focus" | "blur" + +type AttentionConfig = Pick + +class FakeRenderer { + isDestroyed = false + notificationResult = true + notificationThrows = false + notifications: { message: string; title: string | undefined }[] = [] + listeners: Record void>> = { + focus: new Set(), + blur: new Set(), + } + + on(event: FocusEvent, listener: () => void) { + this.listeners[event].add(listener) + return this + } + + off(event: FocusEvent, listener: () => void) { + this.listeners[event].delete(listener) + return this + } + + emit(event: FocusEvent) { + for (const listener of this.listeners[event]) listener() + } + + listenerCount(event: FocusEvent) { + return this.listeners[event].size + } + + triggerNotification(message: string, title?: string) { + if (this.notificationThrows) throw new Error("notification failed") + this.notifications.push({ message, title }) + return this.notificationResult + } +} + +class FakeAudioEngine { + loadResult: AudioSound | null = 1 + playResult: number | null = 1 + loadCalls = 0 + playCalls = 0 + volumes: (number | undefined)[] = [] + loadPaths: string[] = [] + rejectLoad = false + rejectPaths = new Set() + + async loadSoundFile(path: string) { + this.loadCalls += 1 + this.loadPaths.push(path) + if (this.rejectLoad || this.rejectPaths.has(path)) throw new Error("decode failed") + return this.loadResult + } + + play(_sound: AudioSound, options?: AudioPlayOptions) { + this.playCalls += 1 + this.volumes.push(options?.volume) + return this.playResult + } +} + +class FakeKV { + store: Record = {} + + get ready() { + return true + } + + get(key: string, fallback?: Value) { + return (this.store[key] ?? fallback) as Value + } + + set(key: string, value: unknown) { + this.store[key] = value + } +} + +function config(attention: Partial = {}): AttentionConfig { + return { + attention: { + enabled: true, + notifications: true, + sound: true, + volume: 0.4, + sound_pack: "opencode.default", + sounds: {}, + ...attention, + }, + } +} + +describe("createTuiAttention", () => { + test("defaults to sound always and notification blurred", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + const attention = createTuiAttention({ renderer, config: config(), audio }) + + expect(await attention.notify({ message: "hello" })).toEqual({ + ok: true, + notification: false, + sound: true, + }) + expect(renderer.notifications).toHaveLength(0) + expect(audio.playCalls).toBe(1) + }) + + test("supports blurred-only requests", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + const attention = createTuiAttention({ renderer, config: config(), audio }) + + expect(await attention.notify({ message: "unknown", sound: { when: "blurred" } })).toEqual({ + ok: false, + notification: false, + sound: false, + skipped: "focus_unknown", + }) + renderer.emit("focus") + expect(await attention.notify({ message: "focused", sound: { when: "blurred" } })).toEqual({ + ok: false, + notification: false, + sound: false, + skipped: "focused", + }) + renderer.emit("blur") + expect(await attention.notify({ message: "blurred", sound: { when: "blurred" } })).toEqual({ + ok: true, + notification: true, + sound: true, + }) + expect(audio.playCalls).toBe(1) + }) + + test("supports focused-only requests", async () => { + const renderer = new FakeRenderer() + const attention = createTuiAttention({ renderer, config: config(), audio: new FakeAudioEngine() }) + + expect(await attention.notify({ message: "unknown", notification: { when: "focused" }, sound: false })).toEqual({ + ok: false, + notification: false, + sound: false, + skipped: "focus_unknown", + }) + renderer.emit("blur") + expect(await attention.notify({ message: "blurred", notification: { when: "focused" }, sound: false })).toEqual({ + ok: false, + notification: false, + sound: false, + skipped: "blurred", + }) + renderer.emit("focus") + expect(await attention.notify({ message: "focused", notification: { when: "focused" }, sound: false })).toEqual({ + ok: true, + notification: true, + sound: false, + }) + expect(renderer.notifications).toEqual([{ title: "opencode", message: "focused" }]) + }) + + test("notification can deliver while focused when requested", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + const attention = createTuiAttention({ renderer, config: config(), audio }) + renderer.emit("focus") + + expect(await attention.notify({ message: "hello", notification: { when: "always" } })).toEqual({ + ok: true, + notification: true, + sound: true, + }) + expect(audio.playCalls).toBe(1) + expect(renderer.notifications).toEqual([{ title: "opencode", message: "hello" }]) + }) + + test("notifies while blurred", async () => { + const renderer = new FakeRenderer() + const attention = createTuiAttention({ renderer, config: config(), audio: new FakeAudioEngine() }) + renderer.emit("blur") + + expect(await attention.notify({ title: "opencode", message: "hello", sound: false })).toEqual({ + ok: true, + notification: true, + sound: false, + }) + expect(renderer.notifications).toEqual([{ title: "opencode", message: "hello" }]) + }) + + test("when requested, blurred-only calls do not notify or play sound while focused", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + const attention = createTuiAttention({ renderer, config: config(), audio }) + renderer.emit("focus") + + expect(await attention.notify({ message: "hello", sound: { when: "blurred" } })).toEqual({ + ok: false, + notification: false, + sound: false, + skipped: "focused", + }) + expect(renderer.notifications).toHaveLength(0) + expect(audio.loadCalls).toBe(0) + }) + + test("can play sound always while notification is blurred-only", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + const attention = createTuiAttention({ renderer, config: config(), audio }) + renderer.emit("focus") + + expect( + await attention.notify({ + message: "hello", + sound: { name: "question" }, + }), + ).toEqual({ + ok: true, + notification: false, + sound: true, + }) + expect(renderer.notifications).toHaveLength(0) + expect(audio.playCalls).toBe(1) + + renderer.emit("blur") + expect( + await attention.notify({ + message: "hello again", + sound: { name: "question" }, + }), + ).toEqual({ + ok: true, + notification: true, + sound: true, + }) + expect(renderer.notifications).toEqual([{ title: "opencode", message: "hello again" }]) + }) + + test("can disable notification per call while still playing sound", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + const attention = createTuiAttention({ renderer, config: config(), audio }) + + expect(await attention.notify({ message: "hello", notification: false })).toEqual({ + ok: true, + notification: false, + sound: true, + }) + expect(renderer.notifications).toHaveLength(0) + expect(audio.playCalls).toBe(1) + }) + + test("skips empty messages and disabled attention", async () => { + const empty = new FakeRenderer() + empty.emit("blur") + const disabled = new FakeRenderer() + disabled.emit("blur") + + expect(await createTuiAttention({ renderer: empty, config: config() }).notify({ message: " \n " })).toEqual({ + ok: false, + notification: false, + sound: false, + skipped: "empty_message", + }) + expect( + await createTuiAttention({ renderer: disabled, config: config({ enabled: false }) }).notify({ message: "hello" }), + ).toEqual({ + ok: false, + notification: false, + sound: false, + skipped: "attention_disabled", + }) + }) + + test("respects notification and sound config independently", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + const attention = createTuiAttention({ renderer, config: config({ notifications: false }), audio }) + renderer.emit("blur") + + expect(await attention.notify({ message: "hello", sound: true })).toEqual({ + ok: true, + notification: false, + sound: true, + }) + expect(renderer.notifications).toHaveLength(0) + expect(audio.playCalls).toBe(1) + + const soundDisabledRenderer = new FakeRenderer() + const soundDisabledAudio = new FakeAudioEngine() + const soundDisabled = createTuiAttention({ + renderer: soundDisabledRenderer, + config: config({ sound: false }), + audio: soundDisabledAudio, + }) + soundDisabledRenderer.emit("blur") + + expect(await soundDisabled.notify({ message: "hello", sound: true })).toEqual({ + ok: true, + notification: true, + sound: false, + }) + expect(soundDisabledAudio.loadCalls).toBe(0) + }) + + test("loads audio lazily only for eligible sound requests", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + const attention = createTuiAttention({ renderer, config: config(), audio }) + + await attention.notify({ message: "unknown", sound: { when: "blurred" } }) + expect(audio.loadCalls).toBe(0) + + renderer.emit("blur") + expect(await attention.notify({ message: "blurred", sound: { volume: 2 } })).toEqual({ + ok: true, + notification: true, + sound: true, + }) + expect(audio.loadCalls).toBe(1) + expect(audio.volumes).toEqual([1]) + }) + + test("handles unavailable playback and delegates sound loading", async () => { + const unavailableRenderer = new FakeRenderer() + const unavailableAudio = new FakeAudioEngine() + unavailableAudio.playResult = null + const unavailable = createTuiAttention({ renderer: unavailableRenderer, config: config(), audio: unavailableAudio }) + unavailableRenderer.emit("blur") + + expect(await unavailable.notify({ message: "hello", sound: true })).toEqual({ + ok: true, + notification: true, + sound: false, + }) + expect(unavailableAudio.loadCalls).toBe(1) + expect(unavailableAudio.playCalls).toBe(1) + + const repeatedRenderer = new FakeRenderer() + const repeatedAudio = new FakeAudioEngine() + const repeated = createTuiAttention({ renderer: repeatedRenderer, config: config(), audio: repeatedAudio }) + repeatedRenderer.emit("blur") + + await repeated.notify({ message: "one", sound: true }) + await repeated.notify({ message: "two", sound: true }) + expect(repeatedAudio.loadCalls).toBe(2) + expect(repeatedAudio.playCalls).toBe(2) + }) + + test("plays named sounds from the active sound pack", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + const attention = createTuiAttention({ renderer, config: config(), audio }) + renderer.emit("blur") + + const dispose = attention.soundboard.registerPack({ + id: "acme.soft", + name: "Soft Alerts", + sounds: { + question: "/tmp/question.mp3", + }, + }) + + expect(attention.soundboard.activate("acme.soft")).toBe(true) + expect(attention.soundboard.current()).toBe("acme.soft") + expect(attention.soundboard.list()).toContainEqual({ + id: "acme.soft", + name: "Soft Alerts", + active: true, + builtin: false, + }) + + expect(await attention.notify({ message: "question", sound: { name: "question" } })).toEqual({ + ok: true, + notification: true, + sound: true, + }) + expect(audio.loadPaths).toEqual(["/tmp/question.mp3"]) + + dispose() + expect(attention.soundboard.current()).toBe("opencode.default") + }) + + test("uses config sound overrides before active pack sounds and falls back on load failure", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + audio.rejectPaths.add("/tmp/bad-question.mp3") + const attention = createTuiAttention({ + renderer, + config: config({ sounds: { question: "/tmp/bad-question.mp3" } }), + audio, + }) + renderer.emit("blur") + + attention.soundboard.registerPack({ + id: "acme.soft", + sounds: { + question: "/tmp/good-question.mp3", + }, + }) + attention.soundboard.activate("acme.soft") + + expect(await attention.notify({ message: "question", sound: { name: "question" } })).toEqual({ + ok: true, + notification: true, + sound: true, + }) + expect(audio.loadPaths).toEqual(["/tmp/bad-question.mp3", "/tmp/good-question.mp3"]) + }) + + test("persists activated sound pack in KV", () => { + const kv = new FakeKV() + const renderer = new FakeRenderer() + const attention = createTuiAttention({ renderer, config: config(), kv }) + + attention.soundboard.registerPack({ id: "acme.soft", sounds: { done: "/tmp/done.mp3" } }) + + expect(attention.soundboard.activate("missing", { persist: true })).toBe(false) + expect(kv.store.attention_sound_pack).toBeUndefined() + expect(attention.soundboard.activate("acme.soft", { persist: true })).toBe(true) + expect(kv.store.attention_sound_pack).toBe("acme.soft") + + const next = createTuiAttention({ renderer: new FakeRenderer(), config: config(), kv }) + next.soundboard.registerPack({ id: "acme.soft", sounds: { done: "/tmp/done.mp3" } }) + expect(next.soundboard.current()).toBe("acme.soft") + }) + + test("does not throw for notification or sound failures", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + renderer.notificationThrows = true + audio.rejectLoad = true + const attention = createTuiAttention({ renderer, config: config(), audio }) + renderer.emit("blur") + + expect(await attention.notify({ message: "hello", sound: true })).toEqual({ + ok: false, + notification: false, + sound: false, + }) + }) + + test("strips unsafe notification text", async () => { + const renderer = new FakeRenderer() + const attention = createTuiAttention({ renderer, config: config(), audio: new FakeAudioEngine() }) + renderer.emit("blur") + + await attention.notify({ + title: "\u001b[31m danger\n title\u0007", + message: "\u001b[32m hello\n world\u0000", + }) + + expect(renderer.notifications).toEqual([{ title: "danger title", message: "hello world" }]) + }) + + test("disposes renderer listeners", async () => { + const renderer = new FakeRenderer() + const audio = new FakeAudioEngine() + const attention = createTuiAttention({ renderer, config: config(), audio }) + renderer.emit("blur") + await attention.notify({ message: "hello", sound: true }) + + expect(renderer.listenerCount("focus")).toBe(1) + expect(renderer.listenerCount("blur")).toBe(1) + + attention.dispose() + renderer.isDestroyed = true + + expect(renderer.listenerCount("focus")).toBe(0) + expect(renderer.listenerCount("blur")).toBe(0) + expect(audio.loadCalls).toBe(1) + expect(await attention.notify({ message: "hello" })).toEqual({ + ok: false, + notification: false, + sound: false, + skipped: "renderer_destroyed", + }) + }) +}) diff --git a/packages/opencode/test/cli/cmd/tui/notifications.test.ts b/packages/opencode/test/cli/cmd/tui/notifications.test.ts new file mode 100644 index 0000000000..17ed54bafd --- /dev/null +++ b/packages/opencode/test/cli/cmd/tui/notifications.test.ts @@ -0,0 +1,267 @@ +import { describe, expect, test } from "bun:test" +import Notifications from "@/cli/cmd/tui/feature-plugins/system/notifications" +import type { Event, PermissionRequest, QuestionRequest, Session } from "@opencode-ai/sdk/v2" +import type { TuiAttentionNotifyInput } from "@opencode-ai/plugin/tui" +import { createTuiPluginApi } from "../../../fixture/tui-plugin" + +async function setup() { + const notifications: TuiAttentionNotifyInput[] = [] + const handlers = new Map void)[]>() + const session = (id: string, title: string, parentID?: string): Session => ({ + id, + title, + slug: id, + projectID: "project", + directory: "/workspace", + ...(parentID && { parentID }), + version: "0.0.0-test", + time: { created: 0, updated: 0 }, + }) + const sessions: Record = { + session: session("session", "Demo session"), + subagent: session("subagent", "Subagent session", "session"), + abort: session("abort", "Abort session"), + timeout: session("timeout", "Timeout session"), + } + + await Notifications.tui( + createTuiPluginApi({ + attention: { + async notify(input) { + notifications.push(input) + return { ok: true, notification: true, sound: true } + }, + }, + event: { + on: (type: Type, handler: (event: Extract) => void) => { + const list = handlers.get(type) ?? [] + const wrapped = handler as (event: Event) => void + list.push(wrapped) + handlers.set(type, list) + return () => { + handlers.set( + type, + (handlers.get(type) ?? []).filter((item) => item !== wrapped), + ) + } + }, + }, + state: { + session: { + get: (sessionID: string) => sessions[sessionID], + }, + }, + }), + undefined, + {} as never, + ) + + return { + notifications, + emit(event: Event) { + for (const handler of handlers.get(event.type) ?? []) handler(event) + }, + } +} + +function question(id: string, sessionID = "session"): QuestionRequest { + return { + id, + sessionID, + questions: [], + } +} + +function permission(id: string, sessionID = "session"): PermissionRequest { + return { + id, + sessionID, + permission: "edit", + patterns: [], + metadata: {}, + always: [], + } +} + +const questionNotification: TuiAttentionNotifyInput = { + title: "Demo session", + message: "Question needs input", + notification: { when: "blurred" }, + sound: { name: "question", when: "always" }, +} + +const permissionNotification: TuiAttentionNotifyInput = { + title: "Demo session", + message: "Permission needs input", + notification: { when: "blurred" }, + sound: { name: "permission", when: "always" }, +} + +describe("internal notifications TUI plugin", () => { + test("notifies for question and permission requests with blurred notifications and always-on sounds", async () => { + const harness = await setup() + + harness.emit({ id: "event-1", type: "question.asked", properties: question("question-1") }) + harness.emit({ id: "event-2", type: "permission.asked", properties: permission("permission-1") }) + + expect(harness.notifications).toEqual([questionNotification, permissionNotification]) + }) + + test("dedupes pending questions and permissions until they are resolved", async () => { + const harness = await setup() + + harness.emit({ id: "event-1", type: "question.asked", properties: question("question-1") }) + harness.emit({ id: "event-2", type: "question.asked", properties: question("question-1") }) + harness.emit({ + id: "event-3", + type: "question.replied", + properties: { sessionID: "session", requestID: "question-1", answers: [] }, + }) + harness.emit({ id: "event-4", type: "question.asked", properties: question("question-1") }) + + harness.emit({ id: "event-5", type: "permission.asked", properties: permission("permission-1") }) + harness.emit({ id: "event-6", type: "permission.asked", properties: permission("permission-1") }) + harness.emit({ + id: "event-7", + type: "permission.replied", + properties: { sessionID: "session", requestID: "permission-1", reply: "once" }, + }) + harness.emit({ id: "event-8", type: "permission.asked", properties: permission("permission-1") }) + + expect(harness.notifications).toEqual([ + questionNotification, + questionNotification, + permissionNotification, + permissionNotification, + ]) + }) + + test("notifies when an active session becomes idle and suppresses no-op idle", async () => { + const harness = await setup() + + harness.emit({ + id: "event-1", + type: "session.status", + properties: { sessionID: "session", status: { type: "idle" } }, + }) + harness.emit({ + id: "event-2", + type: "session.status", + properties: { sessionID: "session", status: { type: "busy" } }, + }) + harness.emit({ + id: "event-3", + type: "session.status", + properties: { sessionID: "session", status: { type: "idle" } }, + }) + + expect(harness.notifications).toEqual([ + { + title: "Demo session", + message: "Session done", + notification: { when: "blurred" }, + sound: { name: "done", when: "always" }, + }, + ]) + }) + + test("uses sound-only notifications and subagent_done sound for subagent sessions", async () => { + const harness = await setup() + + harness.emit({ id: "event-1", type: "question.asked", properties: question("question-1", "subagent") }) + harness.emit({ + id: "event-2", + type: "session.status", + properties: { sessionID: "subagent", status: { type: "busy" } }, + }) + harness.emit({ + id: "event-3", + type: "session.status", + properties: { sessionID: "subagent", status: { type: "idle" } }, + }) + + expect(harness.notifications).toEqual([ + { + title: "Subagent session", + message: "Question needs input", + notification: false, + sound: { name: "question", when: "always" }, + }, + { + title: "Subagent session", + message: "Session done", + notification: false, + sound: { name: "subagent_done", when: "always" }, + }, + ]) + }) + + test("notifies session errors once and suppresses the following idle done notification", async () => { + const harness = await setup() + + harness.emit({ + id: "event-1", + type: "session.status", + properties: { sessionID: "session", status: { type: "busy" } }, + }) + harness.emit({ + id: "event-2", + type: "session.error", + properties: { sessionID: "session", error: { name: "UnknownError", data: { message: "boom" } } }, + }) + harness.emit({ + id: "event-3", + type: "session.status", + properties: { sessionID: "session", status: { type: "idle" } }, + }) + + expect(harness.notifications).toEqual([ + { + title: "Demo session", + message: "Session error", + notification: { when: "blurred" }, + sound: { name: "error", when: "always" }, + }, + ]) + }) + + test("special-cases aborts and model response timeouts", async () => { + const harness = await setup() + + harness.emit({ + id: "event-1", + type: "session.status", + properties: { sessionID: "abort", status: { type: "busy" } }, + }) + harness.emit({ + id: "event-2", + type: "session.error", + properties: { sessionID: "abort", error: { name: "MessageAbortedError", data: { message: "Aborted" } } }, + }) + harness.emit({ + id: "event-3", + type: "session.status", + properties: { sessionID: "timeout", status: { type: "busy" } }, + }) + harness.emit({ + id: "event-4", + type: "session.error", + properties: { sessionID: "timeout", error: { name: "UnknownError", data: { message: "SSE read timed out" } } }, + }) + + expect(harness.notifications).toEqual([ + { + title: "Abort session", + message: "Session aborted", + notification: { when: "blurred" }, + sound: { name: "error", when: "always" }, + }, + { + title: "Timeout session", + message: "Model stopped responding", + notification: { when: "blurred" }, + sound: { name: "error", when: "always" }, + }, + ]) + }) +}) diff --git a/packages/opencode/test/cli/run/runtime.boot.test.ts b/packages/opencode/test/cli/run/runtime.boot.test.ts index e2569b0ac6..8dd9785532 100644 --- a/packages/opencode/test/cli/run/runtime.boot.test.ts +++ b/packages/opencode/test/cli/run/runtime.boot.test.ts @@ -1,14 +1,9 @@ import { afterEach, describe, expect, mock, spyOn, test } from "bun:test" -import type { KeyEvent, Renderable } from "@opentui/core" -import type { Binding } from "@opentui/keymap" -import { createBindingLookup } from "@opentui/keymap/extras" import { OpencodeClient, type Provider } from "@opencode-ai/sdk/v2" import { TuiConfig, type Resolved } from "@/cli/cmd/tui/config/tui" import { formatBindings } from "@/cli/cmd/run/keymap.shared" -import { TuiKeybind } from "@/cli/cmd/tui/config/keybind" import { resolveDiffStyle, resolveFooterKeybinds, resolveModelInfo } from "@/cli/cmd/run/runtime.boot" - -type RunBinding = Binding +import { createTuiResolvedConfig } from "../../fixture/tui-runtime" function model(id: string, providerID: string, context: number, variants?: Record>) { return { @@ -61,45 +56,37 @@ function model(id: string, providerID: string, context: number, variants?: Recor } } -function bindings(...keys: string[]) { - return keys.map((key) => ({ key })) -} - function config(input?: { leader?: string leaderTimeout?: number diff_style?: "auto" | "stacked" bindings?: Partial<{ - commandList: RunBinding[] - variantCycle: RunBinding[] - interrupt: RunBinding[] - historyPrevious: RunBinding[] - historyNext: RunBinding[] - inputClear: RunBinding[] - inputSubmit: RunBinding[] - inputNewline: RunBinding[] + commandList: string[] + variantCycle: string[] + interrupt: string[] + historyPrevious: string[] + historyNext: string[] + inputClear: string[] + inputSubmit: string[] + inputNewline: string[] }> }): Resolved { const bind = input?.bindings - const keybinds = TuiKeybind.Keybinds.parse({ - ...(input?.leader && { leader: input.leader }), - ...(bind?.commandList && { command_list: bind.commandList }), - ...(bind?.variantCycle && { variant_cycle: bind.variantCycle }), - ...(bind?.interrupt && { session_interrupt: bind.interrupt }), - ...(bind?.historyPrevious && { history_previous: bind.historyPrevious }), - ...(bind?.historyNext && { history_next: bind.historyNext }), - ...(bind?.inputClear && { input_clear: bind.inputClear }), - ...(bind?.inputSubmit && { input_submit: bind.inputSubmit }), - ...(bind?.inputNewline && { input_newline: bind.inputNewline }), - }) - return { + return createTuiResolvedConfig({ diff_style: input?.diff_style, - keybinds: createBindingLookup(TuiKeybind.toBindingConfig(keybinds), { - commandMap: TuiKeybind.CommandMap, - bindingDefaults: TuiKeybind.bindingDefaults(), - }), - leader_timeout: input?.leaderTimeout ?? 2000, - } + leader_timeout: input?.leaderTimeout, + keybinds: { + ...(input?.leader && { leader: input.leader }), + ...(bind?.commandList && { command_list: bind.commandList }), + ...(bind?.variantCycle && { variant_cycle: bind.variantCycle }), + ...(bind?.interrupt && { session_interrupt: bind.interrupt }), + ...(bind?.historyPrevious && { history_previous: bind.historyPrevious }), + ...(bind?.historyNext && { history_next: bind.historyNext }), + ...(bind?.inputClear && { input_clear: bind.inputClear }), + ...(bind?.inputSubmit && { input_submit: bind.inputSubmit }), + ...(bind?.inputNewline && { input_newline: bind.inputNewline }), + }, + }) } describe("run runtime boot", () => { @@ -112,14 +99,14 @@ describe("run runtime boot", () => { config({ leader: "ctrl+g", bindings: { - commandList: bindings("ctrl+p"), - variantCycle: bindings("ctrl+t", "alt+t"), - interrupt: bindings("ctrl+c"), - historyPrevious: bindings("k"), - historyNext: bindings("j"), - inputClear: bindings("ctrl+l"), - inputSubmit: bindings("ctrl+s"), - inputNewline: bindings("alt+return"), + commandList: ["ctrl+p"], + variantCycle: ["ctrl+t", "alt+t"], + interrupt: ["ctrl+c"], + historyPrevious: ["k"], + historyNext: ["j"], + inputClear: ["ctrl+l"], + inputSubmit: ["ctrl+s"], + inputNewline: ["alt+return"], }, }), ) diff --git a/packages/opencode/test/cli/tui/plugin-loader.test.ts b/packages/opencode/test/cli/tui/plugin-loader.test.ts index 493520fc00..ce62550e12 100644 --- a/packages/opencode/test/cli/tui/plugin-loader.test.ts +++ b/packages/opencode/test/cli/tui/plugin-loader.test.ts @@ -3,6 +3,7 @@ import fs from "fs/promises" import path from "path" import { pathToFileURL } from "url" import { createTestKeymap } from "@opentui/keymap/testing" +import type { TuiAttentionSoundPack } from "@opencode-ai/plugin/tui" import { tmpdir } from "../../fixture/fixture" import { createTuiPluginApi } from "../../fixture/tui-plugin" import { createTuiResolvedConfig, mockTuiRuntime } from "../../fixture/tui-runtime" @@ -854,6 +855,85 @@ test("plugin keymap proxy preserves real keymap receiver", async () => { } }) +test("auto-disposes plugin attention sound packs and resolves sound paths", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + const file = path.join(dir, "attention-soundpack-plugin.ts") + const spec = pathToFileURL(file).href + const absolute = path.join(dir, "sounds", "default.mp3") + const url = pathToFileURL(path.join(dir, "sounds", "error.mp3")).href + + await Bun.write( + file, + `export default { + id: "demo.attention.soundpack", + tui: async (api) => { + api.attention.soundboard.registerPack({ + id: "demo.pack", + sounds: { + default: ${JSON.stringify(absolute)}, + question: "sounds/question.mp3", + done: " sounds/done.mp3 ", + subagent_done: "sounds/subagent-done.mp3", + error: ${JSON.stringify(url)}, + nope: "sounds/nope.mp3", + permission: "", + }, + }) + }, +} +`, + ) + + return { spec } + }, + }) + + const packs: TuiAttentionSoundPack[] = [] + let dropped = 0 + const attention = { + soundboard: { + registerPack(pack: TuiAttentionSoundPack) { + packs.push(pack) + return () => { + dropped += 1 + } + }, + }, + } + const wait = spyOn(TuiConfig, "waitForDependencies").mockResolvedValue() + const cwd = spyOn(process, "cwd").mockImplementation(() => tmp.path) + + try { + await TuiPluginRuntime.init({ + api: createTuiPluginApi({ attention }), + config: createTuiResolvedConfig({ + plugin: [tmp.extra.spec], + plugin_origins: [{ spec: tmp.extra.spec, scope: "local", source: path.join(tmp.path, "tui.json") }], + }), + }) + + expect(packs).toEqual([ + { + id: "demo.pack", + sounds: { + default: path.join(tmp.path, "sounds", "default.mp3"), + question: path.join(tmp.path, "sounds", "question.mp3"), + done: path.join(tmp.path, "sounds", "done.mp3"), + subagent_done: path.join(tmp.path, "sounds", "subagent-done.mp3"), + error: path.join(tmp.path, "sounds", "error.mp3"), + }, + }, + ]) + expect(dropped).toBe(0) + } finally { + await TuiPluginRuntime.dispose() + expect(dropped).toBe(1) + cwd.mockRestore() + wait.mockRestore() + } +}) + test("auto-disposes plugin keymap transformers", async () => { await using tmp = await tmpdir({ init: async (dir) => { diff --git a/packages/opencode/test/config/tui.test.ts b/packages/opencode/test/config/tui.test.ts index db04568573..5c4f091851 100644 --- a/packages/opencode/test/config/tui.test.ts +++ b/packages/opencode/test/config/tui.test.ts @@ -1,6 +1,7 @@ import { afterEach, beforeEach, expect, test } from "bun:test" import path from "path" import fs from "fs/promises" +import { pathToFileURL } from "url" import { provideTestInstance, tmpdir } from "../fixture/fixture" import { InstanceRuntime } from "@/project/instance-runtime" import { TuiConfig } from "../../src/cli/cmd/tui/config/tui" @@ -142,6 +143,59 @@ test("loads tui config with the same precedence order as server config paths", a expect(config.diff_style).toBe("stacked") }) +test("resolves attention config defaults and overrides", async () => { + await using defaults = await tmpdir() + expect((await getTuiConfig(defaults.path)).attention).toEqual({ + enabled: false, + notifications: true, + sound: true, + volume: 0.4, + sound_pack: "opencode.default", + sounds: {}, + }) + + await using overridden = await tmpdir({ + init: async (dir) => { + await Bun.write( + path.join(dir, "tui.json"), + JSON.stringify( + { + attention: { + enabled: false, + notifications: false, + sound: false, + volume: 0.7, + sound_pack: "acme.soft", + sounds: { + default: path.join(dir, "default.mp3"), + question: pathToFileURL(path.join(dir, "question.mp3")).href, + error: "./error.mp3", + subagent_done: "./subagent-done.mp3", + }, + }, + }, + null, + 2, + ), + ) + }, + }) + + expect((await getTuiConfig(overridden.path)).attention).toEqual({ + enabled: false, + notifications: false, + sound: false, + volume: 0.7, + sound_pack: "acme.soft", + sounds: { + default: path.join(overridden.path, "default.mp3"), + question: path.join(overridden.path, "question.mp3"), + error: path.join(overridden.path, "error.mp3"), + subagent_done: path.join(overridden.path, "subagent-done.mp3"), + }, + }) +}) + test("migrates tui-specific keys from opencode.json when tui.json does not exist", async () => { await using tmp = await tmpdir({ init: async (dir) => { diff --git a/packages/opencode/test/fixture/tui-plugin.ts b/packages/opencode/test/fixture/tui-plugin.ts index 3d894bd0ae..f950254945 100644 --- a/packages/opencode/test/fixture/tui-plugin.ts +++ b/packages/opencode/test/fixture/tui-plugin.ts @@ -12,6 +12,10 @@ type Count = { command_drop: number } +type AttentionOpts = Partial> & { + soundboard?: Partial +} + function themeCurrent(): HostPluginApi["theme"]["current"] { const a = RGBA.fromInts(0, 120, 240) const b = RGBA.fromInts(120, 120, 120) @@ -83,6 +87,8 @@ function themeCurrent(): HostPluginApi["theme"]["current"] { type Opts = { client?: HostPluginApi["client"] | (() => HostPluginApi["client"]) renderer?: HostPluginApi["renderer"] + attention?: AttentionOpts + event?: HostPluginApi["event"] count?: Count keymap?: HostPluginApi["keymap"] tuiConfig?: Partial @@ -183,6 +189,17 @@ export function createTuiPluginApi(opts: Opts = {}): HostPluginApi { return opts.app?.version ?? "0.0.0-test" }, }, + attention: { + async notify(input) { + return opts.attention?.notify?.(input) ?? { ok: false, notification: false, sound: false } + }, + soundboard: { + registerPack: (pack) => opts.attention?.soundboard?.registerPack?.(pack) ?? (() => {}), + activate: (id, options) => opts.attention?.soundboard?.activate?.(id, options) ?? false, + current: () => opts.attention?.soundboard?.current?.() ?? "opencode.default", + list: () => opts.attention?.soundboard?.list?.() ?? [], + }, + }, keys: { formatSequence: () => "", formatBindings: () => undefined, @@ -190,7 +207,7 @@ export function createTuiPluginApi(opts: Opts = {}): HostPluginApi { get client() { return client() }, - event: { + event: opts.event ?? { on: () => { if (count) count.event_add += 1 return () => { diff --git a/packages/opencode/test/fixture/tui-runtime.ts b/packages/opencode/test/fixture/tui-runtime.ts index 64537b6c50..75fc2fdc44 100644 --- a/packages/opencode/test/fixture/tui-runtime.ts +++ b/packages/opencode/test/fixture/tui-runtime.ts @@ -5,7 +5,8 @@ import { TuiConfig } from "../../src/cli/cmd/tui/config/tui" import { TuiKeybind } from "../../src/cli/cmd/tui/config/keybind" type PluginSpec = string | [string, Record] -type ResolvedInput = Omit & { +type ResolvedInput = Omit & { + attention?: Partial keybinds?: Partial leader_timeout?: number } @@ -22,6 +23,15 @@ export function createTuiResolvedConfig(input: ResolvedInput = {}): TuiConfig.Re const keybinds = TuiKeybind.Keybinds.parse(input.keybinds ?? {}) return { ...input, + attention: { + enabled: false, + notifications: true, + sound: true, + volume: 0.4, + sound_pack: "opencode.default", + sounds: {}, + ...input.attention, + }, keybinds: createTuiResolvedKeybinds(keybinds), leader_timeout: input.leader_timeout ?? 2000, } diff --git a/packages/plugin/package.json b/packages/plugin/package.json index a3ce97368d..baff4cddba 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -22,9 +22,9 @@ "zod": "catalog:" }, "peerDependencies": { - "@opentui/core": ">=0.2.6", - "@opentui/keymap": ">=0.2.6", - "@opentui/solid": ">=0.2.6" + "@opentui/core": ">=0.2.8", + "@opentui/keymap": ">=0.2.8", + "@opentui/solid": ">=0.2.8" }, "peerDependenciesMeta": { "@opentui/core": { diff --git a/packages/plugin/src/tui.ts b/packages/plugin/src/tui.ts index d4c2261b28..354e44abcd 100644 --- a/packages/plugin/src/tui.ts +++ b/packages/plugin/src/tui.ts @@ -226,6 +226,76 @@ export type TuiToast = { duration?: number } +export type TuiAttentionWhen = "always" | "focused" | "blurred" + +export const TuiAttentionSoundNames = ["default", "question", "permission", "error", "done", "subagent_done"] as const +export type TuiAttentionSoundName = (typeof TuiAttentionSoundNames)[number] + +export type TuiAttentionSound = + | boolean + | { + name?: TuiAttentionSoundName + volume?: number + when?: TuiAttentionWhen + } + +export type TuiAttentionNotification = + | boolean + | { + when?: TuiAttentionWhen + } + +export type TuiAttentionSoundPack = { + id: string + name?: string + sounds: Partial> +} + +export type TuiAttentionSoundPackInfo = { + id: string + name?: string + active: boolean + builtin: boolean +} + +export type TuiAttentionSoundboardActivateOptions = { + persist?: boolean +} + +export type TuiAttentionSoundboard = { + registerPack(pack: TuiAttentionSoundPack): () => void + activate(id: string, options?: TuiAttentionSoundboardActivateOptions): boolean + current(): string + list(): ReadonlyArray +} + +export type TuiAttentionNotifyInput = { + title?: string + message: string + notification?: TuiAttentionNotification + sound?: TuiAttentionSound +} + +export type TuiAttentionNotifySkipReason = + | "attention_disabled" + | "empty_message" + | "blurred" + | "focused" + | "focus_unknown" + | "renderer_destroyed" + +export type TuiAttentionNotifyResult = { + ok: boolean + notification: boolean + sound: boolean + skipped?: TuiAttentionNotifySkipReason +} + +export type TuiAttention = { + notify(input: TuiAttentionNotifyInput): Promise + soundboard: TuiAttentionSoundboard +} + export type TuiThemeCurrent = { readonly primary: RGBA readonly secondary: RGBA @@ -333,9 +403,19 @@ type TuiBindingLookupView = { omit: (name: string, commands: readonly string[]) => Binding[] } +type TuiAttentionConfigView = { + enabled: boolean + notifications: boolean + sound: boolean + volume: number + sound_pack: string + sounds: Partial> +} + type TuiConfigView = Pick & NonNullable & { leader_timeout: number + attention: TuiAttentionConfigView plugin_enabled?: Record keybinds: TuiBindingLookupView } @@ -499,6 +579,7 @@ export type TuiWorkspace = { export type TuiPluginApi = { app: TuiApp + attention: TuiAttention /** * Legacy `api.command` API kept so v1 plugins can initialize. Remove in v2. * diff --git a/packages/ui/src/assets/audio/alert-01.mp3 b/packages/ui/src/assets/audio/alert-01.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..45c3f6afddf3389d845009c78cd29fdb49a7afd5 GIT binary patch literal 11436 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 KJ>!4s`}{Au`!56l literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/alert-02.mp3 b/packages/ui/src/assets/audio/alert-02.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..2aa5cda6acc966be98c16dbf6a88f1f731567b12 GIT binary patch literal 8667 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 literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/alert-04.mp3 b/packages/ui/src/assets/audio/alert-04.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..f4ed65209270bb1abf046093f8ac953def16d5f3 GIT binary patch literal 7369 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 literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/alert-06.mp3 b/packages/ui/src/assets/audio/alert-06.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..a0ced67c229ca7cc766b9ed3a3ba389b0ab5e295 GIT binary patch literal 7516 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 literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/alert-07.mp3 b/packages/ui/src/assets/audio/alert-07.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..312a419c5733ed39c7ace0d5e08798140e043209 GIT binary patch literal 6741 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 literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/bip-bop-01.mp3 b/packages/ui/src/assets/audio/bip-bop-01.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..f518059c54c1c9ca4f14ae0d4149fedc61d7d015 GIT binary patch literal 4574 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 literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/bip-bop-02.mp3 b/packages/ui/src/assets/audio/bip-bop-02.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..b25f80ada6f8f354be124386cd83e9562cc07871 GIT binary patch literal 5697 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 literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/bip-bop-03.mp3 b/packages/ui/src/assets/audio/bip-bop-03.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..adc68c91dc29e0023efbc142aa2f06dc33c6c6ff GIT binary patch literal 4186 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 NMmm2eTmQ#8{{enkOH}{> literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/bip-bop-08.mp3 b/packages/ui/src/assets/audio/bip-bop-08.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..24af5b0a23800318973d625867aa44933dff1736 GIT binary patch literal 4390 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 literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/bip-bop-10.mp3 b/packages/ui/src/assets/audio/bip-bop-10.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..056730a1f13f6c7334ee2f51dc3435886da74368 GIT binary patch literal 6760 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 literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/nope-02.mp3 b/packages/ui/src/assets/audio/nope-02.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..8cdf890a1825524298d9f0346fd9196919b55844 GIT binary patch literal 5753 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 literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/nope-03.mp3 b/packages/ui/src/assets/audio/nope-03.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..42442317c372845d0f0f3dd82f35c567ed0beff5 GIT binary patch literal 3820 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�Se`zAXIp#WBy8fHHNha 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�mj z@?mq%;gCh7l$+_fCr$L&`=VFSrhbRa-Hfu7)Ha-UODr6YWXUlp zmoK%3TRW(E=3;uyt#(fRnR8uP?nC(}LVR&heb#Ww&)Ty_!*8WoY_&qs8nt`1Cl5FV zzbcnrFK9&TNyzmD25EQ-)aR6z{6ds0-}bli`yku2((kshxvOb3b$Igei{&xD!^c1M ze{~!FLL9&j4qDl#sc%=5?oW@Jh}$ib!lRN|I+2}mhWCUyj+}v}pzbWzJqj>eCB>TIg&7 z>s#Nvi|(=Y#G(n$frMPa%sgD!l*~vCCkw;F^RS&zMqHeP+R1Ck9;;kEzjr*&Qd#Lb z3v6#*#QOXY9CVwe)9HQLz5^v?LV;-|BeJmrchhQ>wl1#*8gv-uMgSEpV2hvrK+;uqA5NDK?WD<$5{9F@;!e%Qd~j`&?JnEcGCQ?8GbXnDtP`m~5iEzpGUK|K{H?#NW05 zu_2k;l+M=xTOFhQrt0^V!x_$B#1ex49?iex|6`&5OHuv(;{Oxn&wa8<*xo+b?q01B i20)9kw;%WSJN^y+|L7F{rK3#y57GIj=IuX3=f42xL9Lnq literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/nope-06.mp3 b/packages/ui/src/assets/audio/nope-06.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..ed22c1cba2c66c97e76444cc66cd7b06f3bfd687 GIT binary patch literal 6066 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 literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/nope-07.mp3 b/packages/ui/src/assets/audio/nope-07.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..4b6dd462c80ca49e6c25015c28c0db2c74fc9e78 GIT binary patch literal 3459 zcmeH}dpuNI8^`yU8EIk+qLN!fZqYC^T|~LxO(x?qN{qXxjxKbOW?V8EMiU}b%gHOuT*G_x+sruXFk9{eJdd`&ny!)_R_`pY>aNJKEr2 zfEctpiDWB!A^`yE;vXHd5xX9@-q^_Kd*?y{&RX34x9WmP-m^bcWXXzd8PVkh;1_UT zBxaGc1+o@tT;$mTeTxh)@_K>EMWz=47Z7_E#TY1x(b!mA`4?I+iv?50>)GC=>fdc} zwxCsPK;}h-MyGT@NFoh@NQ@mv;kB7_7c_h#qhlHf;PTP6CqL{dVqroY&?|2@_o(E9 z`4`+yJQaJKnx%pxQ6W)BqoTuz^sxTNw99u_LRCw$ue~dR0~fjDl=sCf@9sEF70Jx$ zDL@$#86Hl+Z}8z@Bx!7jjh2G_wy>KHL25Xx_9lB0iI5?G;6$`Cbv`mC?a)|p4hH;b z*Da>BjBKGm76d;V+*;CA=m*Z{CLc{cmADBXj~uecOTyI{~i0^?CBeEP&xk74M&qQ5_DxD{P#8gMdiS=QUuU!8M>##?&z zttRPOFXMQ^1f2jK%rUh5qy6^!Hx=>@L_8TiQcN5*xp=z$x#!h)1D8@wd-w;lr*w21 zo%@2fI>JUT3*#m}==sc*xzq*(Hu+|~cz@s7!{jOB9SUZ z=iGigbz&f1Zuu)-GOa}Wz*OYveI46;p{h^===t-ZRB~9VSwV-TdMNxQxpTNcj*fsPL9F-j5GrpokXaB3 zcp>r=T|T6~{M4YJZiFV6wb}+Hv0?>$nZ#*zhYCCz-g(PB388sBsvdQ?(WJ{tR|6qY zPd)2ec%?#@)t7c(+wZy&T6pDv!LHmO+s{UT(T)_`SV6|2s?EVN!Lq)&EgN5`oGvzZ z-9BL=d#?$@bZ2+2iuE5q{?03TyuR+-bnlAwt#7y=qP(+vQ?*xLyI^d%Jjl5pJqB6s`a}}K`-n2jX1kO`O=%#e@#g;EwZ-Zw@B#)Bu?pK?oqyRwDM}S;Y zUlY>SO)S05%{(3y_DfXe9j6>H`0{532TiQQJO9zrsYHH8MKN0DRU;@-mWQOB!lSt55+gQ_|^-M8dRKD>Cax0b!L|J!&z zm>aSC@Vm~axfk!}UQLd>YFAFLuOkVGJE}&-QvF2J@71)NX{1RwmA|20zYY;vhSTZi zZLqp(kRTg2YjnooqK4mH^(#*xoi0mql@rr7-RFYB_r=)i@^5H<)qO5mRi=Z!zZ;`G zPPO_bc$gmB+{`TUazJfO_f3Bs5E)zbT#ZL=`YL2)FsS7tH+Zc?FcIXZN?WCXRKJ$n z>$^f%L3AF|4Yh{AkJ+hV>L9qEqfnA=T1g11t~!(B>Glwka!Gfzop)BU_VaCdn+HSXMluumSj*0$ z^KsAOjAX5)7&2zG?gXYTkvleOrb0oH5jw_JB*apu1iT$i__iG6Mh2&XJ2hA_kZx#j)iFUh~ffTNA@=DJ#g~Y*y z1`vEz9(73UnBLd+Ee?5muWxzl2d__ zMjgDb6z>VnqFTq|Eqx#e(U%MGga@D#DKHhzgTAWhKzEhB1xJ?4o?Yt}X_4=>bEYP* zOFjd(qbIbc=gueRnb1?-#*+C;vEkGB+CBC|(bYf2-tSo#5gQx&;_ckyeJ!`se47UX zo=3%hnV57J%MPSra@9>{I#`I9LS5?hNtja1S^3geitceGiIsA2tQAQbPxSEjEYqQW zRwZOv06Rn>VPaX+xsGj82#6)qP=BX#cY&l4E?6RB-^3H|IBy1$3rNMaoESqt<;+b? zboe#QT23IA90@6ZwxLW>KyKQr21vPYkv(|&fau!e(7Wl5}+ z2DZJrmi*hNp(=6GE~#e;Dej8Mq;vlvII-ydComWbKzzyj1|j|!bM-IdADdDvy9q#E zuLw7xQ4b+2qP6ZJDSv7i|5)gMU6f+k^+TJ@FbV+7N_2vn-vt2JpPK%U2aEmmLhmmA fm;wNv_BZ<}7D-mLp8xy#<9z&g>yP~W&F}4ZwM5#) literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/nope-08.mp3 b/packages/ui/src/assets/audio/nope-08.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..e54577e43576977e1db835f5d61fe6bedd804e7e GIT binary patch literal 7450 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 Kf7$tO>Go$N6t)8Z literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/nope-10.mp3 b/packages/ui/src/assets/audio/nope-10.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0720993519ca211892aa69fd91d550a01b27b936 GIT binary patch literal 3981 zcmeH~c{J4h9>;&i7{geH7)uztY0@yLL9&yOow3ANViFG%N_u3EA=%f;V6sffmZVgO zCp1J!NQ;bHkzLj@mxp`K?L2?n=REhGd(J)QzRvl5KcCO{_xpW5pYuN7?{7J3hy?@N zNZZ-k8f{q~0AMvIgq_q-RmLi-U@*U*+!>e~x-I_{?zm3GK;JEockAHZG6Z1%4##&1 z-X&#+;$0ec>DuAlE{t8Kc39YDZ5QSa+m*L^^xEoCMP)nq2eM$@9haAYy(_`-yU*O9 zv~N2sn_B}?RB(KWLUywB19I>#6c$HY8i>LC-jn4xgF}u>t^yRJA}eezRA!Ae*&~I! ztu+C@RkB}V?&)&n_u`f{HXViZsSwHZLsIg&3v22pL&L(dh@~WHnNx^#?pM`XoI@wr zzqPkPO)pKH9i%3T80!P};>q0m8-2JkJjoaLYQf**r+7bjd~lG=;IG!4?uud2BujZ! z%KCbIs-~&jkB(VHWnK*vP_R+_)Y-*|+27XBJY)RU=z*J9&S{@!+`Z1XttVh`U;EmmFZgBt)fF<&|d zPawn^qxH{5luHZ*uq7Do5yKc7=#nrM*ak;U?pQUb%0~}iEGs?$uvKE?-$3Q?d11r^xdEJG4= zY8V(tSSU`|iyzZQ7)MGOD<@BK;oEdQqg$k~?v~(kMNZ6IE!1yrBsotitq+-aMZIu# zJ)zNRK{ur%eJ`Yn}KR;TXi);R6bmrjvC8D2DEHooR&>)n}`jyi!q{@L#j2&gQ z*R|*Cz-t73%&8q>o&siIxaFW91Y05dJiv+}T#!iG$&U$Kf**3FJfhny+wv8hmB#XnBioE3!iql!7Y>JgTr*R)bj6uCAil z@#o(|cX#fV8QowqpZ{3domi;-rqmSZnX9#OpG7<>ina9}Z2$tBG$fE!M0)f1STa31 zOQe;c?!(TPj*h!o6$%-sWs8=v`b$qEyo3$w(a(+*K6AWOg0EWFq}f)sovZvzTfXsY zEysG!yvtJAn2U4-b5`PG|kalJY}u#b;VDZth!uKSSD_Q2M|(^??AEQRVvW6^!3*e*hWL3-0(VFNxxoMO6`t)FSq>mby7fS_l5f_Rx9PT(sV4z0#~6d zasUOG6(cj^F9?ha$Ba=mmcV}_E$lG?L zZ_7d#^e3{`?p`*sGWRpqIpsa*60cWsS%5uP+Qi$L5#bn+IgolPsgW6Z6|iJTqmg{y1^#x42Ut`itUZu$lc41u(y8^IrZaPoaMtS8*j|{GjzcKLv0l-VpaELbG zW_a({4Ox@YKucgfv&5%sFo|1VPz{cQfWQpxg|(-Az`i>gU` ze9-s8?-zzYJMJUXqr42SlqSh3IJX~)yJ{_5CnXeMNrDykf@r$2Rvth++O0sAa$cT{ z08&6+Qf#StZTv80ikH+7!-qX9<+1&~4nmnQx)#L;j*s^y+F;ngoo#UhYj1le&;07ofCe` z;gz^#Xi2HFGL9(<5)Ui%)qI~-Jbpd3UTEEhxe?U={b*^hf4&iL$QK|a1% zLRzA;bI^x3Rp~~93;Lu`d3v@-E8FUft?<6#yRgXVjhQf%WA(d7$=_ekOpi#DJ3Rn7 z#JDA)4bkFe1zR9}e(GE;M+mWZ<_$bOl5mW-Bk*28H#&e6O(l|BF;={Qg{VP3nh%ya zFkojBmoEA&jdq@PEPWE8L87CYFOGEGp%P7wIF;ABsLr`kn_gZ z<_ll z8W&@4VW2F>>c`AsF)8k&4kYCVz`>&t;Ci`j;g+KW*c9-msi7eIO8@Yz)Z*XLUiDR? zYtCLNw^NYFcFv1%3M>0`G@N$xT2u0Snc)VT2IVFTQRnr5LQ3V$lTItDlxZ!`ayzfP z*QW}ckLVfKTI_QV?Wxl_5nJf4^Evl|{0JJ9G=za z@Rb%mKj$PT6w85r!-Gj`dFg_HDs@U%>dJ|j#_4B6S~18@eK4mY*L`#ARGPb;zPBQc zpo}-LagZI&P(u3Iby(0hTJ|t3O6)>{OW`6E>Z5D=x#U|y2-JpOg@u7 zLM^$O4DFV8A37`Hkl3qbPYi9oxaRCLX1n!r2x^~?g7@cc33rC9tKeT(R|9ay85a-d z5aozJ@s#Aq+x2t@J+{Cv+K#)D0@$oxt@j5?_b%pe~14}mY+KKODVU7n**d( zimaP%MYRCHktb0A_@}gg2>w!?KVX*T@0vMh@3q#Pz4v_1+I!YHduyqQg8;vU%LIi| z|5eff0HnH(fv!?wBH|)Q1ma)Lf8Wkel<@zX`tPcRhmYH@+J#@2AOIk#4xpvIc#(@s zL_|bE;l>Sfb8~0sTet4tzaJlu#TFD4)YNo#j*N_qj=p;J`t|F{$?54gZ{Ez#&d)C{ zE-o!CFR!kyuCH%ye)#ZVYinm`cX#*8m%Y9H{r&IX4-b!zk55m}&d$$&_xx*&&cDWp zME+L(5;&>SzpIk!cLlF0|Eqp}QqcdqLUQ)&2CHEzDuFO-f;3=<7}-Z%TUCqU`A3xd zJ}RvTKF?5d=O`Hr#N=N0`7gmC`_Ip+Bc^Xktnm=y-646RG35^{mn*;QrM=*xgDf?! zg`BQvv@`Iu6td&l6;&*F;%?>h2~d&6mFRVE3!EhE^d-t#AH3V_>6rZ1*L?MLJN7}Y z#Wmr}7IhV+@Szvhp`4i1d{|5<{aX-B`qOQdsMXh8T%nN9=VEG{?y<`NprY??oE;3% z`+5t%0)BVCdO7#%$Mzqp((yws41up+U%6d-FsUdY-zCr|-xRuRR6^-3_P;TBCAKG1_7dR(-@HUSIDE41yJc`YZ@ zB@{AyD3!TL^u(i3rm(&lRsrIT3+}Wt#MP%+Id9uVgKc;~foy7wwJ!e052l{hcwUtn z+xT)C@Zee|{CQb!R&!f?I3C3eqilXSPn=X9^APE8mSw95o8Gz_o}lmaMIgS<+?*E) zHXYV%Tfk3SQ1`&<_=X%a`n<=eb%Et*a?TRH4=!Id<~dp~VKwIjd!UcIb|yzs>!Hl@ z)>(?RSSu1eKse)NYP1u*&DAh|Q-#rcuOF?6#`Wv~K{3Mp>moK<1**Qzx@JQ)?Si|b zZz;)IwOcuGhG&u|T3XJ(BVirG$h5&!R_E9My=(2PIfd+NP4Iqc*89pg!EaZxf|C!H zzJJnj&bZ&&m6&C9BmM4@+(JB8Y81Z5&=(*R?F{&eWhLjerJ$Upe~8ggWXi2m^SwPA zOJ0oUq>lj*!s&DFaJ46_#@}r3*JXpJIpga1L^K^?d}mHKqGv+fU=3wj%2(~hUS;0A z6~oQI$g?b=EQj`{I`aWv6P->vw7N+q2f>?wH7NM76TPJuXp(VhtRcDbNwn+`r0YfD zYj4}Q~|2Wa%Uo+*`WZ4Wo z2|f${aqa!@ne$7&bA1gy>@O-+yy^V7GB+G>@Sv2!DwLOhXRV zB*}HoOuxd!YyD+~ytKXxL=B{pxkv|;VgoGX+_#kGQSOK6al_||jzzJyHNCU*r0KA1 z-GPIWMwwQHS zrvugWpB;n9K+DL_Iq`&e&uBN9sCz?;;t%`c0SG>sF}K^-pY#+slZGdXfdMhJyB=~p zFlwN23f>n(=QU7>qtvXlO3{S1q2873zjx5ihR{)|O$MrM>&hCl^XoSCkT8d8Q<8s};>Th7bS(nj=YvMe=9ZmlU`ZU@?wQ_Vy;8`nj+TKL66Ah6*i zBnneIMO;ioQQFN0QXtycv`iOt)`}?JyVm_U5pw~kmTkFp>(4_L?x3s39w~n1!B)IEiD}pSU3$k->W&U zsqVI|IvMfR6Z#W=U3YAG{o(wFP>az4YR>PFs7iVVDiMpxy za97jSY~}{5A$#vdrrq36XvB2?y3_#s^*#whqTI8$G|BSQq(hbq_V>hdL)}ZKrk}<_ zbJhdkUeA9=+%`s_bldc36bi~wbv>6%At@=d@q6J9yAi@8csR8vADJrlxg|))daN|Y zG2giT(W#v$Id;2YLHf=Qf@uFkq?I6+bj3ye)p_jR`4YTM0gpbGtN$s4`y zr`2}3lwIch{l!Lq^`ovw&n4U5dQQnW+6{>8tYz5vpoi0_hMvQz?B%dcpI#{b0`~4y z`rRLHOJAC^eh9BsfBmDMgqCcEu5YxFY|V}&WyJ)$n3y&W*jA|JA$ADhuZK$1AnxEi z9*>A`C#?DhmKGrDmr#ZyM zkcBU{9|Hz4vTHjOti0qkF?J{+1-Sym97!RJl{P1q84520A6@X&eoDeDt*)S;RVR)JvK72qaT4^sQPSwcWv-zh$ zXH-2a%Ftp*vanjsR@BjNQpSQzGGQ^VO8EvuEjL|vLvF?%ZrJk#yC?abSg{@-YHV0b z0dAt=O4g(WlEhVGW%yz9eEw&Z^7-D$K9FKApgpJ)?pVC!S zv=3%`+>24XmHfW4J)|F`2WWKpu%bpyYQj@=8SF)QDc#-s`~=^>2oN*omOOfk0p0KP zQj|;sz^=!@S7dO+Tm}$)h@OkyM8_XpTQ~%?)wcUd!RyBEOc^rth@kVx-wU6q+)H)& zO{#K@s*q%0ZELTk-V{p2$}4jZ)ZB_r74Wo=7EooFy}_y~p&Ot-hI5>6@00Y|b7F5b zy}m>+>v-LRWGyac3(K7rfmTSAtwYa7ME&m04}>?iJn7+x&Jkz5>xBySFwy?W`*~rI zUC`K|g%`HPmB$dUteN+smJv8AEF#h3gBCc&Z7=0MC!Ovz%aiF^l$JYH-&>2`X!-$7 z8^G1mi3NvNHOwaYtnHP*nV8-w`-AH*j88quf$#RJ6)Z9qs+W3mHHXAV1MiSO@t z8Z}jW@3Q+x(8Eh;>k3JnL0yC8bS!3?ADyJ}l<7HWm!U+YYC~in%u^{vNt-JNLLNbm zA!jJvqNbC(P*h9Sq@OVGGgX+e$K+$+y!zDZsZ~0yB0=g&d*ic;d-zqU<_7auTD2J~d9LwClLsLN|Wpt{v>S^I2rW>5G}YSjEK4!gT7aHpy3T(0=ekUeD~CAf#^cz|YXLDTLkMWBM7JU}}6$ZZFc*Wjt*( zH<1!vii=lq_}~&v;Jt100%xb@LrLJE8lq$bHh`({34p7ccfzq^2wGWNQUQq(5^*Pd zDOelE-w5-2+G%TmUN(bMQWX>`L%AYwd=_x0*6Ulsw0e=rWNI-qz(~=Co8_Ju*ztGm zMIK2QiyLM+PNo{R?4BFGd)qAfU`H6{QQPkWZ_? z&C%W+T;6^$LlukVWUnzC?T5Mo+b2kKBNo@+U;kJLmM5n3W&M60YUebs(WWsY-|Jv;kX>h7T8|X`;F*Uj~spa z`8GFeS(7T+n)^xbA~`ErXW#q%8N>Y0jC0-?dKlAliBnGL&>>?Ktk2&0~&H zP7dRgV1O}kBQ|Kc6w>P_GXUvfo5)_fYDg)80Xo8l6)7=ELs)8432^#W|hwo5TVXAP1b??PbaTG(k>K7rV=rN;#%sC=(@E-2MAo^ zXt>z#UOBaMQLi{71$avmK`BZ5m=RjK3U#OeM>_#?pJH^KSdn<&ASjS5hEg?hlN?~! z|9JhXSf>9Q$87X)*7a9Jvy4+R9ztw14=_6gi&n;%@Upj&P{c)M&JhWp1)B5p6OErx zMD7sK;tq+5?x@YiArkr?U4^2u`eH$r2joB%wy-8O(HJf0H4-^-e7;sl|g zMk~k1OIP;AB}O5+Npy8TrY}j%+`$ep%4b~>S0oe>paBW^ejj=otOj+C(QDU5s#oLCMFTYqe5zg zDnfXr7-I=Z`q`aaB-dGy?nJ_QK5$rOF@npYW_SDTmc=MAyEarV^y zNVv$U+~=v_cj|=3NKEq`eY0s}Q&;jwi7U6O286SGYKR8{Sz*IfR>P)xjA6X??YhZG z<}hTu+Uj1X;X`C}qpw4Z2=B3?ujJ=HsE^D(dY?}Z=2hN3QgTqZLIVQt5Q%8@iLOia zA)n;f3DG8|q@+N0?AIA{5>j0l7_U?yUZ8vZbQ~rm<>34fr`RpN7NE=@L7G9Lo-Uhi zF-bvCv)$mwSn?-D5LAKL2+g{&_)n(poLPo(q+lt2WcDHfHggFYQ&>qcfPF5?nM4-N z2W1JObcTG4QkI!XQnMNv;EO4h!$yWX_C!^giIb9o;mp4m?GucU`g_@3k_4rUw5Nk?6Xnwtm0zas^5V8de~_%J z?M)VEQ&L*1`Bv%hj|g>J>JB*1YShehvgXtQDR7r4Zkx*+h^(L?1^5E!x4pGN4y1h}qQXtK4;S(ap4prV=Mi&@9ry&%L0$yBfwW|g4n7!iVw zU?uHQMt6ugyi8(SAxn2fuOP#V2f1NR^G3d=Q?frOkSfrFVjSgHdYs>_983o1NHDAR zK$?gKtbIno6xH=HIrZkiw2#4#nJm?V`MhxMyQ>E*`L^G&qw1}f^Xrk6t{ESh7K0CO z&8vD`xKa3_v+1XrbK2F=xB=`0dzNG@{k|KN+;>ZB8!heC^t_YlhE#0ZmDvaUu;h^} zIF$FoppZu&Usp8 z+M8#Eo0e+Udn{#s&>2{mz`CM!uZ732OL)b(&9PdxTJ{g9gO4@3=bjHW$h)(G5rmDm z(|V}>Nx7O99q9(k?LiU)cE??AV2Rd4fRbT*s(y5UJ&OdhqhUwr1q!0St$6q`B?y>E zN$tRmqM(LNq-ezPtcfe3B(Bkvu~^8|%|&9aCpCf)$nP!iGzojS>!SsOutjs*A%r2I zjvoN~K!0c6`V)i4h3%gd@?TkgN8D=wJm8)DQ8fTG-dxo!+k`Q`&%GtfQxR&k%1?^E z{J`PIDobp)@1h@KMogy8MaAvo(D1q+ix245++_Ls^;(5!Bbl0qTUwAhHd>+9pU>^S zeLcDYpI~*Vy+U|WDzR}*=(IkDKYliped9x)`E5&!i@*m?&DlO7Z}Y@Xmxsv8di=^( zuW@EAY`t;QDIGR-qxF=`n0jMs+Ah)lL4ARv`+#4_lyHu$UzFE!7UI6sG`=Azq$sZE zX=;Y+OtPsuUxKvRpNYi}wdRFnWm`Y|9@1nPousJ(VrTT+aUCvV2cy9-Oe!F_JSy9Z zKaM_2CKk}AmUPCxG&&<2PMM8W;&O#}v=`aAXdv*qFh2;ltC|&Os(xxkNe00MV}mJT zKnTs{NJl1sMp@eZkJaHXdX#d`X^eq<1B~o_fE$!Zr8G88oGK|Q6zWqOnfl>+T=`9lo{JSErRyv4@)YSmuGd5|d_M_Xr+FR^s1IC3e|_~k;R zknth^6e^hAsYc}27yn%y)+E(&eX%7ITwW(#^Whcgn*zUv7NWZSD@|afq5di}HB=2(NhqYxm5pZ&=~3Z#h2l&; zG-ik^-6N-WjAupBSq3-(e`K=9=jT7qxBr8+P^I0oCl+D+{K0V^ z9#Mf3Myg%kUZQO`K{PCUQl9BO72$(i-RGtlU z<_dTGlFfZyA@JM7jqiY%D@_E{@#VHzcdQ6;u#vt6D~d#dj)5vY2N9VtG2%8xf=>Vr2cw z2*cRakq{TFoDYu@))<}2EhWZ4F2qz6l+QzD;s?*Q9PFC5iLdY1l*r$qy^Rrmz%4pA z3IJ`(m32!O05%Z_yhGa??Mo5)<&C)dFQFU$`*w&G8Y{R$K@gv_Wr|L&U>{#Wrp^Y0 zrvt~%YRHF2(<1OM!>_o-1P!nQZ4ag`W|cmK2TWBrzVx-9T5|2dysgJe7VeEwrB><`oPb8m7&CVcap z{E@X@Znj%s9LhwEA*qR;htZgC&P0nj5mGWrrZ)k2n@nrb28rdQEdQAEdL<2zGe_l< zbyP^jth+3Iy?l{3*%83k6AfYy>LYg&p5Dr7-x?$$yp znOtfdjcAx{$V{osT!v@v3yTi#7k0$Od%M;@{K~q0)`)L-{3(4j*6?)2J*+XCZtdpO z-mUyquBMgV=d8{b(h02h+Yi0=G>f}Ia%qPTdCkP@4Hg1qodf?OXMMJ@c$e5P@)t^> zR^x$=OtF$a0e#6y*B0YW@%9FJ8=pqjM0E)!GO4XCLnlpTGNtGm{$D>28KIPTjCjdN zv`c(W|EHmD;%VE>mszYsrAm;Cr{IVkkq>D(A|I$8%Zwsl`LZ=y#dg-}YQ@OCYP2)i zrkj~7X+??dfX2#-3}%YQe%Quv&iZZaPTK?oitCUm8tO_ihuUv_3hi@9Dlz(r!!=jB zPkZg4=cUn2@EQ>zIRdxBj6_Fog_ZtjzGmdjnQen12p=)W>8Q}*1a(EAvn6#)y3&5tbClsJC;%NU{23D=;aKpExmfUa2zhC8kV3GD_teBT5oFE$HPH%zhaW;D{m9 zA`?k{X&f)Iejl91hw#(~);Chr3>cQ34qSFCoyPO_nQn@+$_p z0`1lHx42K9rKwj3U48)nBtJVUV=3dkD>{6?u;uc0TRJj8;;!iRx*f*j<~i_4!}`0D z`b$X*&n{(Es%vhUq3MdYi!=G;?Q8PI1+vUDG)m`d=v1LE-NYXV`Mt|})$YAZ5wABe z8-<$dOJ%G8OO_|@fR4Lcctp2PGTzMah_pHfzE`ADa~ilFT9&bL>&W2g?N?pDHgx|b zKj)`rnlq#ns;N5St=e{d=ONT$_WrphBYmd5|>r4Ur}@KqY7BGC9Uxb zNF0cJlaWY%OCukNr($Ae^%-x=c+hBs&9+EEt<&G)s}QuYyjVW0+;yM+7LC1YbH|sd zG#{2^y*|dAKB!ikaK~V&#F*eaJug9{OAU)+NrvCBX;=Nz)OL-vmUW~zxx}ufVh4)? zJ}wPWqb_eqwet7i%}VbRL%6{Rf-P?)lOA z>C9j1*2aPVGjoB%+Is;RS{Z@TO1B?_2O^AuvNe4tB2(H1Uy~<;6=<1F$XSTvk3h6~ zQ)6r@ASFXXM$E#vDsU&t0b0jTk;uuGT<20u;muOufSPuFUf`}MGS8Kf-Tis*wyd#~ zamQ;*UR2scnvuiP5+K#8c=D8I@|7}F$y7mEg5dso&|H-$8lk)WQ!-GL6mPJ0!QA&g z;+srrOULwVYO_sxoBc5g8$0Q;fsHQYJAqp)eY zA@_@RPw9d3$xn=BoLNEA*kl%ZS_jm+2#=ZTkkf>n+6xZ@Ise9s4gRU2Wi~IIluq>) z5{UX?e`w0un^n8rYeN(N=x2E%(}R{~&5jLUsrO!icaw+ehh2^0iBWl{IemqRfb4p$ zTZ!OmqjqzR*CN)ThnHQ%xu0AJjILft&ow%xUsdG<& z`7%%l!C8EnPBc6Q42WaqkZqg5Qa3i$y~^$7j|AN~(BICY&qa!Tkgu4DPBPWm)hISC zHkmG+D=gZ{oGr;K-MFjlXhL#8ew6}TLKfaF>8Sv*!)vOSy`)4 zNv6@T5Sp*vKRpBShxqx7%*G3|pJt~Ge+(y#M_pe)&Rh3layA*cY41**DUgNi3Sj%>ANh@6OGASCV*g>v2x zAy5zm%w1m?88XU63NWD>cA&H21*TNc@QYK6#Z$l>fRFTZ6^a_vrACLSVXQye`^5&4 z>MrWNx&kcP_9Dj1kt8-R!Q{GR+}Su15)g~M%S~avSOCncNdWlK-#W3z8pYV|JXCPa z5dv~&88o3!5p{h~k+8!q?qo8QKVd4s`(iXi0&@U(9BKTs+d-)S)^_v8<-m@^5~t~) z*Y{{u4M)=2?cMlmw9&0ALN8!A+G0Ze>h>uMDBubz=c6x!k4#01M{eu*r!9->)M2#Y z$nnl_;r0)1gGz`3bjE$zxb;!j1%+jqxMyH(ddf~Mo|}hg;=rB8!HjgV+5Ux}X5y@I z@)KJvVOzste-KkXcxsEaco(Ml*FU9QQ?|%^dR@X=vivinlLU$3YSy|ga~d+7%a%sD z-0kB{?6Dr7lVEh4yIYYfuEE8fz``4`G8l7xlTHKph?P<~BO&p3XwL#fzH=jwh$&>Z z)vlgP7f=Eoo5MC#5E{Ceaae%^gj5RD!)&r*s7W^zt17P2&n{GSUo_K{q;?!4E(aQB zLt<#~&*gFx&pH&En2H|5xG4ifv-#$&_+^G9sFg9{Sw3K27dj>(P-(P@T^}v0Jp%9PxgcsxcY$>szn?}zeJ$>(j(p2PQWqSA_B&-RY#y{K)X};0>d+?0) zTZyf_v{oRYa!sVQ?ch(IoL)E}Lj-x0^jfEHv-mfiXcievw(a-M-NV0SBR#qJV9lWa z8|FxsZt$Y&*YtLt)DiyWHcw#y0p~2alFOISiKNd@8Q}L=`?0J2UTDH-q{ie`@L3q~ z{BhsYKgjixysT=TSUP8|{V^P8nm>EcaTnKwVV|~4Xg!EGOQn`%qNO#w37A~XoW=7@iKp{*AObu+0eaW!Swx+(l`+( z4u5_@XY(qYzDvM1YhlW<<*vCPerDOVt(BDndK` zgVAjd&bc1PT*+)Y7+lu6)C_9XQln)GbV&3Yw9h=}2n+jz^XTYD_sRL@AMJcCu)<3Z zHNw;M#&fng`;AT@c4ycn!UbMO1uu#V_f=-O7!{m9o5V&=;emlr7IQ{sGo}LhQ?t=I zdNssD+!$E`Wk4 z2i^;Glu!~Vxn8UQTUkV@=?AXV532V(LHB&a04lstfGq=v0vO3D0e}iXVuDSGxB2z- z<{rtVv;mc+g`;d6ANm1gVp&9}u^U4`OiA!98lTo7%oU5kOq8+q@z@PCa@(}nFJ!;I zt&8|VJwNXKtc(pzQ%0>o7Yw#!>_zxG6tFRb!+;nUfTo09un=yYG|3~kBj@x*tLu7z z$k0jU6tn2vr~iHpXQkk;x68S|bWisUH)a>*HotHE^M1C?ngxbyh?V2$j$vJ8J@tPb zJ*@nn%K!b7|7}nIH2L46`5!y}6U*}xNdF8e{@1Zg_Fu;`0RRaM008YkFA9MUEq#q#a1_;i7FF64~u^RwDN&tb9N+>SXZ#{}slBhc;f4e8* zT4XA@tuLuK))Yk>O<)572nGViyA8x|lg%_tqdT!4CvnQ#5xme8L-#DPM#@NKmD_D= z!+q!!0Ba+w$BsWu=@-Iv*AY+`{kEe-V8@*X0D9eqQEM)Q6olwcaYCT0K$TBd5I$`CIv#>;S%-e|B9{X5K9PFV9>|0T3C45Jd7M^Ybrh;4(<=NhgaS0Oy>b*5R}n?Tw4P zE-!EUj%S=dMccuC@EV;gH`v?YQn+N*M-!zBY^TqvOJ3CpSplZ&bUAF#4?yVLZ-E z`OI_KPG}^59zK2`oYu!!X4#IY*P`087Aja;Y?i6Ytgz28-}YUO7!q=5S}H9Y!gt|c z;?EB`Hlmtq_p;u=7H@Y;{f-ZWn~)$3H{!h91Hax=D4cg^p*AJoLHuJ4RM?ckcli2* zOF+SRB((CW#PL& zc>PN0`_i>z<5FX{rmQr|19$=;XoM0O04PNmbiT##T?Sv0ublQ)g&)~E_pcF9u$aF} zD~^dICIE5Qe1d3CQED>+WJnq^6;eKlD%B|5btx$-Bi#1(0GVLJUZ4d58I$`co%0kx z2SdY$i?1N&V+Tfk(o~;TJNu5X$%rZGOu`Vt8WGGaw$mEKS%`$SF>ZYy-$2IlSs1mt zQ>=g{;TUWnz4?wZjF9+F@s)8+b6zS+M)l{!U(sqh&Rw44Nb7I8?v;0BC$~%|_`(kb z;+vw^qcm+#M%t?LFww5FNoaQ+PgtvBLG~z(TN0*%Xx*Ch{zjsQMZs0?O@lO!M^!g6 zWA9nKezu1{E$aVYD3|Um^kOgpi9s9kB=6e4nO9H=*U#)Qy z-J0|m`BNs&(fqL4tG*<;8r38Z~z#bJcSmcfWpgo#7V_zA+$M? zQE*%c*XrlT;xP~?gQlb_2M5w9JOD3Z1bf#p`5W)%Y>(0Gg_9Tg<9(>nu#ezeA{?WV(j+UFxfty^cw?w z71#swCGDHlUa0-L0B_;8oI8-@CbW^P4F(_*{J+0j+aX;F<_j z;{F7UA@P>xAfr?kp?ZytrRb-7*89mg&yJ@%HdTQ&%*LqlF+g8>B%}7dH&f`Cwjj)^ zeDMZ1PuAl~4x$16BBr)Ep({xJ`(tKK^barj6lgZcq)w%Gf64jYsf9oq`81P~i?Eg8 zPwV>M0z3=3Iw#Kn(3?IOUMh@?)PpVYr7DkiEA4VgO@3=yrM#=@ktZxoFl^)%0e8ia|V0_f@|PZI$uN*|M7) z!e6NVX%uZ7%L9A?TsFSJV>)R~{btJz8G&0X$8?~%%TM2&cm41D`pxd2hJr?xc$|i# z-kGptTmF-07LfskqL<2EnQ9y6^aA6Fpup;}oFs6HilcqxdY|J}Ub~?v-$y(g;u}Ov z6!2~ym@fRQWFA+e8d|YKlEGnfka5;BBFiOPThmXL4WKF-e}UUiw_H z-8x!m&GBF&yYz&(cBuKokl`#=7CV3NZGHfp&gv!}$3{13{jHz-DQvFP;AtmaZfU}Tzo(v2 zjTVN&CC{0JJwuE8bLYwQ%RydhZA~liOeSh(C0W%@A$g(iG$3$pbWX+-gTd^rJX`&d zud6R7nt-Bn@({>BDC1~1cFeQ-adYf~)u$?pt9$$3UiQ&k2u2@zI0_+y&A{548+1IK zlD+*BLXSEh=(fV#)9g{nG*T43pq!a#GJ=O-CSDg)3N}i1N&a{VtWuPm64!ldW&Tg# z6dA*|=qEcBxk|4I1?#soZL(|M9YsDBm?)F{Hb2F%DA``vGWgNNMzUI5SwK&JK;4-y z5iwU+B(D1FmxAuh&0VNHI#r@VXNUN_*g09m@8nO$y#oZIE@MxgrD(7ByLL(80G>Wj zO8~YV>3%Gof6#AN$FTo_2Ki>8=^XO)I!hq-^;-qn?0XHbRllBjl+H6@1T*?P3>`a# z0}FEEbG7_QvuxR`7^Ui11z1*$b_|zi2jcfzPgg#aLmlKeCB!4?Y?LD?5o6%fS%j2xe2XbHAssVB z0*KQiGi6|L>``Hn%d4hh%Zz9)CA5Rd-Q%~3pe`XhL5|b5YvgBRk;?-ZoRHzlvJ+j~ z(c2AqZ{v@fl4{DOa*%1Qu!3@bj)&2YEE8%^P@W{MGQBfYETKD_w5?@!G|`2@Ppf*U zP$}ho$Ns+>1gyD4vc`1=xtUJ<5zn^hf9M;PwAuydAy~8eB=+fC*bThzt3{rMu*c6A zMIXD>Q=4{*HoM6gK1zG2Z{T5P#P={(>sH@Xl11zBiE-9VeBnZ4R_l1cv8VBykIm0c zqx`;EJI?NoS6`qxzuNct{Jefl;eyn8{hKq7xlX$(ie##~H{`lgBaF^1c`rRR6ZNF{ z2()^_5|s7yQ$Xp|ZLC+pO)CQMn9#=)T;h7MgnF>PI3mdxwVIhyzVyAJ-C}l+wX@{U zYL9m#M1A{g+$VlU^i7r|sT_7Bq^_B`Tl4uVRKUjY;ZFtctZF*Gn>Mo~557UYo-d~( z`Xpm)BN3~$CXhSyC*$S--rCFdC)EJBN#)>ojZ+R~aYs;TtwE8j>XwhpprzThZ3$Mh z(MLt8V=}_2C_~?d%EOP+#UsArpEZv+Kl1E8D=rTjj=uTh36DODR=S30!>*Q_lYyBs zEVGv{IC~V4pee-n<@tB<5r;u94J*$#8(L#6o^P_IHEX=n#$QYZ>W|84_}{cX_a4>N z6935F&Ng|03qNh#9O-(LI($i|B8T!qc(SZWwUi8tlM?XDc8>OQKsO3*?=>y)Ua_I1 zr)FXRDY^1#hKLc9U5E6N!0oRT*757HnARtld4+9ib5SWzQ4q+!otaAF33q?Xr;;pL zQ@3q}o-vE?>vc;Z>VdfFT@9^A-SRH*>hO*CX7^_4R}k~6Sl@HnJ&x%<;Bs!OGaTTh zCAfmrS$rtDB@@_5W0|;d!`I5mPI&p|2r6s>>7kfqWWSQpS@QQe zWv(^Pn#;C$dC5M?xJziaBRFv78soXqqP*#S8I+dOl?x;|4x{wW~ z;q4g;qWKzfB07Th_}`Vjvn|eI*_Y^eDH_G2F_o@9NdJ_#E{ykOdiP3r%8-hB(4O>c zngrPj+)!N-3=2cF9CeP zJVqz^0Lc{E8ILRiRJe&FvieyexP?g2Hq^E>2Z)Ca*KNWC(Kd0=-dl1K^LZq>0D=EVdOHVK;)WR*-a;5UW?A;lEB zmsUYg&TqT@Pi(DkP6+|SMn(2cS z`m)%fRcquS+IvwdswtCi*ULU;FLqjFw~dn}cXV~DQ6%5vprWKXMq);2QTNG~CS~12 z%9XY&Dzl}*?gy>Tq+r1TcIS9UH^bU^QJlSq>SDIBe+ElN=as!f$I&fuqhTCdOnQ~y z)J3pP!J!%AssZfb3@eOt93tH9A%7`OBRT3mpbcl0t%TUaD4cX$?bRFupR}2kM0IqE zrkhpjO+DjRA&WwZ4Y*r3g@bBP4=ghbuu1i<88FhqikRhhRq1Qdm_O z4Yip<0xb!zx|4+8bodZjH&gc+>u7>>e9c>{RH>_Hl3CvdGEnYZg>Oy71?gmzNzp6* zX?TO@9+EEE-86|$8faqLrL2RjgItzUyHb`NiDElCBYS8RmQu+|B|X07ye)fDxO0bW zT&18C+4S_T#%bJ(HuX}rdW}gvr(q|v5pK-nQKZ3U$HV-2m17KQv_EECOmVE&}y_+priuVz`C8=u8c6DEgiTXqx%^u!+Np2+&LVdUKg52I# z?O7%HVngK*7$oW z9xtYsAmHg92SwAGgEduBx}yl0#J8rZ=^3L{%)@YYE<$dp%8AT62~UT?;1+jAZ)Zj_ zIOuG^=wSd?V?|hrs^o_9wqZ%$UJo2pVeR!NwI>1oOFSkg`8Z+#wfDQ267aVjpmX_< z@L+iIRqa>5Y;Q?vS1hT!>TN3;m4Z21lX^?Ot;(_Ybw?{z z%HMnFK{#gTYB_Vig5Bp+IbXMLN@o({7?a-SdoTvw zx4h2_|2qAp`R&P_r2UZ#is!XA5#~~vBff6If1jaF@g6t7ewoxdQj;$!{~**o?SPdZJM9i)nwH17Q;TiHRv+gNsJx4 zH*ZBH-oZ2D0+;Vv=AZ455pXp>c>4YeOS(k)rtF;2=qDFp`MHv>2O2*;UPHAi>n#!} zKFVsG7wX8hM2wa&z<=fbXgSvudN;M~k8owpHi{b&SxL0sEL#bjK9u~1YNGa)Kbux$ z=Exz@=T7hTcWxGpHSJ{?wG#Q^*KUAcOw`)l<@T)yW2LJ#$~T~jzXoglK5ThXGRiFr z?Y*fHD|;%MF`rjodGmr_g_M7@RPJ35C~iG(=5Jx`mSY*q>-U*;1o}LZ4wa_OMo9Z4 z7m?iRu(jNh2aKVDc8<2)yw_3GcXcqT_8fGyv2?OC(i9MWDh5G9r*}iF6mE{hdP6?~ zAsXb=j^>7F3U*U=5_XCiv!6xES+JxrLd!YxrlZ9AuP2VwgrgSPj8qnLYE+Z(?0Y#1 zp4EM}FBWdLXzz%|kguk;8Sozpy%<|5S9qP#O2#D7nnxJ~DRDj!9gTKcHhGAEpP=dt zr9YcR)%2S>{5dE5zzIrR#+=juRG@y>5JVjS8M6%dfOn(WIH7Mx$pqhY9Y2dnGI+qS z7^^+)__=@AO1(7t(hX*Rwk)swErTC!7zua2Ik%M>l=)0$9wwr!1d;LR^4<3pF5js7 zq&ApfYDn)|sryDciRP9y=DE*xGNsI&CwP$>l$lxwe`lpkd(F9FX8VmBT^Ev0^QMmK z77S~qYR$r;J;vDF$pV`lFfE6jG;vGeBJbsvSBF|j#TMo%N4^pbD(1dD2avFY4l-yw zwDSk@*7-U0SO{-IaApDqp+T=TGRyTLQWXC5+P$EVrT#DGnpxzgPDReFc8VgqaLb%a zq@D}YUuQ41HaC{vxoUODPA^BJn3iLI8%C^_UnxDZx+C|~QTM>YC)G3{-QPjSZ#VTd zQY<`Sa)Z$-Sd+Zd|4Y63z#X}nmS0S?V--5?o6hbBRD7_%fe1RE zOq=~N6GxS)_V_bJK?>S#Zug^UjpM_t!lom-5#DV{GmK@~M@Bp8%GH;m6YC2ph|JzHDy{L)+7==EI7XJ>+CQEq zIG!}%UY7%hvQj&-P!#8h(X$lQJb*omy%rUlvMtH9Ex=AnlUSA%J9w3bggE9pn0gx; zv#r6-50AH9z!6Va1G~}PENk3gLCJ_ZJ-J;}8HGDXEXJn$Rqqg330PZKDFfInSnX_S zps)BP+nS40!T|2;sF*l_l#+ptncCVY*xJaAOdFjc>zWWl2&0$w{!>i1aD0=$i)jr& z5|4K7LKcy!;Pje_*(Dp4GnrfgPQq|z6tf6fH9?Qrm=71QKZ?OU=LY0;1EjfINy(vl z{o_;AAUZ;DHB~BcI&ogbv6t;wWq9>j7(#O1^UW=z;q@@(rtZ+6mOC-U>MNkmgOx$E zky)#drj{4Q73Q@VIXmdOMiC&*& z&kFPTJD2-9`8(w;1)RG1WV+Bo2#FIlZOQ=%wVtqzN{?M#xv8LFKUvr#0Oxas8Q%Sv zg%siA#bsOM$F{lsya{wB zK`GB@%i@kC1e+z7PN}YEJB&3ldpV?w&j-D|Wp~BW4#gC;2x|WnCFD{hm{31j{Gj$= z^me9`x4!~wQoo?n<4M)F2}wCEa96V&LHBI=USB%~?J(!{X6%+p_M7$*DMgpkf*S7P z{A9D-hm0HExED zh9?V$7vSDcn7%O~$fm)Yx1i$56Z|VJbge8*3=0e|KiqLnK<%5o4}-1V5Z&q1v|%=5!-g;%HO&hPf7b^|ZR@oZ2om@Y*}d%N zns7^Ag5R@e%%i`>V0W9++}4{vQF!!EFGXYUd@mfYhom?3BFn5wf5kF} z=t!80yvHahV}LOCJ_CPX`0DL3^Q#bcR3n(vjKR=t)eqT}PV=rgmBa3wpNR>@0TbIOLTUh_ z;1V7`If0a6|Bqh~L8;Vba|61H7$Z&Q#L(q0t-jt_04L@hSUA?T#B% zb;cDe%DYjw`{uR=-o4vdYOjH`lNVhP1hX^J-7K+jk3bDeiH ztu29V&8!=hh?uR4O&upBlLm-T3%{f=0+7PF2SGAK069E8@q~cMYh0EH0%C`N*+D|p zvN7oHw2TxYYdDa#gQFkjz!kis~IwpPrnB~V~FWiC9xO1_v?CAdA^4E!&tFnNfP(Z zpTSf4sc@o-Th`6(plb>7ueg}D5azKx$q1v&Nv-wwe%VT3X|hD&%4Bux7GRh)Uv})4 z;%%4*@9HEnF-^E%o8$=Rc8OuS-MQUoGgh@b!VyxQLd~?37b_URQ$#ur^V@9DV&pzCWc`-## z;D4Flw`298G}HCZuNz{K$3d-w9Idps?b8Oopby5DTNV>zC1c$Nl5UruDVP~DLPG^N z8+NN@U{BSwRCVZEQFev06PNi*twPt^GC?YNYN8&D8{XuW=1A^jrz-(f*AGzjcW5cd zT&*s>eR3Y$yjob&hh%j6ICeXCSuS4@QOUBfl#!9eGc!NzRZ_Y<$LLkqDBKv}|K3ka z%^c$j&W~n8BIA+JzweHniH=u1^$|8rD9f{AyuyC#*PsmxG#nKs%U&cpn*Y2OQFOm-{oZ7}&qvn%TU`|&b7_KC1p=R05sutK3TFQZ zV$d23fT@US+*9 zM(H}f-~bvj@yLQD6FF-TeuR(>vaWyD5_AgOs&}x1H6!TjKDi4Da}_gL(xj`po_p79 zdN0)WF+7WsAZ-?Ha$7ySJL{>Dls?G$di<`hg~_#7e)rTcLvG8}{YFQ=$=?hb_4`h} zoAv1zQO#xssAR3X4V$J6^n?Tk7!6fS;>e|Ny&S>$D8;#i?nZW~VYgwRbgJQPWn6c0 zSOOHqsXbamjZng7u%U`o#=k2Yl}WUTna!C!!zq!NgRe5sYpS-?y)6QMKPweH2>PyB ztGSU>OzZP~A^3@}Wo9I<;5{LW%^_G+{aN&-BZf?{Uv{ z0CcoXwv7za2GKtm@ZEL4mXRXyW8bQN;ZJeD&k3|KCpVr);)JCe1pOOuApA@DJIs9W z{ZnP_4^E1(b`34jpWlUGPWX<2>dL5wuu}tBnPiNq2|6DAVb!xL?pbt(kc!loZ4%FdRt`g z<50wDKq2`JS}}&}5{ZJScvg5Hj0%oj6Z3)x#e$$ksWp5#da==D`Eaf$EIBc@t>T1_ z#y;@-FUEQl3&L&I`QgwWA&4%TB!7^a%-oQHodCW@PY;FzM<6y32|wY{&Gl}G)|hBQ zL!Q%o)8Ud{yi}&Ji3^vi>lKiu1(DM|i*)Pky5_XHc#d?*c~=nj^RO08*Ql#=CakPR zvcpRF?NQcCq&_tA#X0*5U-E;3ikFAWV|dErdihF93Xy6b7QWf{;_lX!DX zbfXrJ-w&BQ4te<3&*lSh@}K9v=eSEJkC7+UDIkeP$1bS`fQD2nF2n@;jR;U825{;| zfxa)T<5IeTDaqv$Ivams1Nlch`F1SmQi7;OD=0PtARyCA@flcR71Bx&1;+V^ni#Yx zxF;RUbCO70wTVYks?&xa^Tm(Xq)&=)f+%*#MJo?bbnhBQ7X3LVc_uN`gQ5N~5xI%i zhLa`B*UlAa(SynDFyh5Tqz7Hu{gtxk+=IgVT`Bim`7^QKQm)%!zI7&f<=zT(L=*-k zbWynuRy2h*)TQzhO1*hp3zr+AE9Vt#N*HG6&^*z z@R9j?Qc65n(FuhB03Cy%zpYlTB)_RCgh!gxRJr$ysCj`f4G!byG#O1soiQL2dS!=6Abq3a@c_mcn@?<@2^Z?KTa zZ#T~Nw3T&K|IwrLyPxR)WRL+Qrox*4w|4s{PyYYg5`PNse-8}fLKq7oaDZ9FBOB%% z$Uj~2zncC})A-ZqwLsL}Mnw0g0qdgC>t8wa@9X}H>woOb{b?vG`Q5Pe+m0mecSG5~ zzt_L|=6~$`D?0zZ?myiAdp7?{^B->iiq5~O`yZ?a|HXs<*!eFw{_Vy8D{lV_NN}oH literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/audio/staplebops-01.mp3 b/packages/ui/src/assets/audio/staplebops-01.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..b3b34a32fe8684b535ffb0d76255e62ef873da95 GIT binary patch literal 3665 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