From c51cecb4adbeede6f061a048ddbdc5c3531c2f5d Mon Sep 17 00:00:00 2001 From: polvallverdu Date: Fri, 28 Mar 2025 09:34:14 +0100 Subject: [PATCH 1/6] chore: bumped node-llama-cpp --- apps/cli/package.json | 2 +- pnpm-lock.yaml | 198 ++++++++++++++++++++---------------------- 2 files changed, 93 insertions(+), 107 deletions(-) diff --git a/apps/cli/package.json b/apps/cli/package.json index cf174fc..65c8c3e 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -38,7 +38,7 @@ "@trpc/client": "catalog:", "clipboardy": "^4.0.0", "commander": "^13.1.0", - "node-llama-cpp": "^3.6.0", + "node-llama-cpp": "^3.7.0", "superjson": "catalog:", "yaml": "^2.7.0", "zod": "catalog:" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ce9c178..7c6af89 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -453,8 +453,8 @@ importers: specifier: ^13.1.0 version: 13.1.0 node-llama-cpp: - specifier: ^3.6.0 - version: 3.6.0(typescript@5.7.3) + specifier: ^3.7.0 + version: 3.7.0(typescript@5.7.3) superjson: specifier: 'catalog:' version: 2.2.1 @@ -488,7 +488,7 @@ importers: version: link:../../packages/validators '@types/bun': specifier: latest - version: 1.2.5 + version: 1.2.8 eslint: specifier: 'catalog:' version: 9.19.0(jiti@1.21.7) @@ -564,7 +564,7 @@ importers: version: 0.15.5(@sveltejs/kit@2.17.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)))(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0))) '@sentry/sveltekit': specifier: ^8.50.0 - version: 8.54.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0)(@sveltejs/kit@2.17.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)))(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)))(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)) + version: 8.54.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0)(@sveltejs/kit@2.17.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)))(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)))(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)) '@tailwindcss/typography': specifier: ^0.5.15 version: 0.5.16(tailwindcss@3.4.17(ts-node@10.9.2(@swc/core@1.10.14(@swc/helpers@0.5.15))(@types/node@22.13.1)(typescript@5.7.3))) @@ -703,7 +703,7 @@ importers: version: 1.4.1 '@sentry/bun': specifier: ^8.50.0 - version: 8.54.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0) + version: 8.54.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0) '@t3-oss/env-core': specifier: 'catalog:' version: 0.11.1(typescript@5.7.3)(zod@3.24.1) @@ -734,7 +734,7 @@ importers: version: link:../../tooling/typescript '@types/bun': specifier: latest - version: 1.2.5 + version: 1.2.8 dotenv-cli: specifier: 7.4.2 version: 7.4.2 @@ -1007,7 +1007,7 @@ importers: version: 0.11.1(typescript@5.7.3)(zod@3.24.1) drizzle-orm: specifier: 0.39.3 - version: 0.39.3(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(bun-types@1.2.5)(postgres@3.4.5) + version: 0.39.3(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(bun-types@1.2.7)(postgres@3.4.5) nanoid: specifier: 5.0.9 version: 5.0.9 @@ -1419,7 +1419,7 @@ importers: version: 1.13.4(eslint@9.19.0(jiti@1.21.7)) eslint-plugin-import: specifier: ^2.29.1 - version: 2.31.0(eslint@9.19.0(jiti@1.21.7)) + version: 2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7)) eslint-plugin-jsx-a11y: specifier: ^6.8.0 version: 6.10.2(eslint@9.19.0(jiti@1.21.7)) @@ -3990,69 +3990,69 @@ packages: resolution: {integrity: sha512-KZ7/T4UOY3BqJBdweJPeebKW34YzIH+a2y4o7yqTIowoi6dw3sMj140o1Q8FvpPbH5J6lr2TWVCWdgSTYvHNgw==} engines: {node: '>= 10'} - '@node-llama-cpp/linux-arm64@3.6.0': - resolution: {integrity: sha512-hE/hqxtr5DQyY1DohwOcY742NQZtEFag8H/FQP2Y7fnlNQYhiOe45PcAJDiqmEUMmlCGVvHZaCWbaNVoTMYdWg==} - engines: {node: '>=18.0.0'} + '@node-llama-cpp/linux-arm64@3.7.0': + resolution: {integrity: sha512-bcgEyTNURICSsPz1hvahhrdiezzGB8VweUGQw+AVLurH/j2eomUFIa2DXZ22SFSUkbV4L7EBei17HjKpe6sKxg==} + engines: {node: '>=20.0.0'} cpu: [arm64, x64] os: [linux] - '@node-llama-cpp/linux-armv7l@3.6.0': - resolution: {integrity: sha512-aRyDVf8szfJJWHnNWG56Ir3LtfXxj9vwLXbXy4XwfHlMTuBHWhmrRXyB8f3A/aJ8h6u48wMVxqxdmwnXigSKWg==} - engines: {node: '>=18.0.0'} + '@node-llama-cpp/linux-armv7l@3.7.0': + resolution: {integrity: sha512-0CBUJG4Z7JKvYFlqcVRqpvN7nD21JWr8B7T5P6aiU/WydnwiaYrhUBY0Qn3VmmMmjncA2APonGZsjt2lcPs32A==} + engines: {node: '>=20.0.0'} cpu: [arm, x64] os: [linux] - '@node-llama-cpp/linux-x64-cuda@3.6.0': - resolution: {integrity: sha512-lS9F+aX2cGV1I/pAuCNeQm9bGELNmnvKqbF4k4ZjNk64ZT2sE74o2S/uN6GvMJETG+rgQiKRuKb1l/yIm0LOfA==} - engines: {node: '>=18.0.0'} + '@node-llama-cpp/linux-x64-cuda@3.7.0': + resolution: {integrity: sha512-QjAjvJiAqkzX1CXfJN8UMVw866pArkYyExajJnFfcULYsk+Hs5E01m9GxXYdsADOTU91M0N9A6hsgDR/3oAwyg==} + engines: {node: '>=20.0.0'} cpu: [x64] os: [linux] - '@node-llama-cpp/linux-x64-vulkan@3.6.0': - resolution: {integrity: sha512-1Wc6e1YJRpjllD6MRfwYPxE7z8qvmaYrEFyVPzTe9sghKXUswpBmmb0mM/yOzwT/mUBygSwOEBvTkp3nG+pWhg==} - engines: {node: '>=18.0.0'} + '@node-llama-cpp/linux-x64-vulkan@3.7.0': + resolution: {integrity: sha512-tCFg7P7DbgLM7ZPIAENzZHlURWBJrAgawatPQb50SySilvgo3epWMtxJVw4/ZCde8F6mFxGuIy0q66Gqwa1vMw==} + engines: {node: '>=20.0.0'} cpu: [x64] os: [linux] - '@node-llama-cpp/linux-x64@3.6.0': - resolution: {integrity: sha512-lUzTTY7AwRz5j/f6rss6fPc2u3YNOmo4k8Zap38kzy9H6rL+U2nlanN+4STs5j/7gcx5f/VHRnPrYDl5OPcmTw==} - engines: {node: '>=18.0.0'} + '@node-llama-cpp/linux-x64@3.7.0': + resolution: {integrity: sha512-IC8YtwvIM3sTwf2VKcOxkTmrTJLvE0QqB4dweFqlwFJMh0JDNqRMzoAl5JcN6Q7swyStB9PzsUSklcVrw+xPBw==} + engines: {node: '>=20.0.0'} cpu: [x64] os: [linux] - '@node-llama-cpp/mac-arm64-metal@3.6.0': - resolution: {integrity: sha512-bOtZkJ6dCWHnZ1SP8EJ+LOdIFKo/7clb0ck+IwD/Bn/2ePzObVBsq30IxpRnUXx8pZ54+CzmTQuS2NOMHXS0PQ==} - engines: {node: '>=18.0.0'} + '@node-llama-cpp/mac-arm64-metal@3.7.0': + resolution: {integrity: sha512-RkcO+tEuaxRMDT/sVhAJiMZ/CLY3a8WpbNtL01J0QP3jJo8xQeWgsaRIucnZc/U7OdvSvuAUIk0QAAdWbca2Hw==} + engines: {node: '>=20.0.0'} cpu: [arm64, x64] os: [darwin] - '@node-llama-cpp/mac-x64@3.6.0': - resolution: {integrity: sha512-xjyEAsOXQ6i3VuXoQYB5llYuNz0sP9YnrDzAJ8sqovXXYkSyXPRyTCF5/PaAFc6QMkpsFIw3fSbavJeSzR5IGw==} - engines: {node: '>=18.0.0'} + '@node-llama-cpp/mac-x64@3.7.0': + resolution: {integrity: sha512-bzpUAwdRxK/ESIyt4aALkMYvDF8oQGAK8TuqjN2N7lNCuDwmshHpia45QvUyQl1v+6LplXXYmwGV9az0tU8LqQ==} + engines: {node: '>=20.0.0'} cpu: [x64] os: [darwin] - '@node-llama-cpp/win-arm64@3.6.0': - resolution: {integrity: sha512-o4gEUBVMZ1R3Oy1f642UA1vJtnVLAJq2W+diPUxJVqXs9KYDOf7+JuxVcTEzSj6+wBsN3ZRtt36Xst41Jwp6FQ==} - engines: {node: '>=18.0.0'} + '@node-llama-cpp/win-arm64@3.7.0': + resolution: {integrity: sha512-FsLpoTUGAsHceXStPhT1P3dFntovvoRCj5wi9orCqjO7nBMBrp/+aQ8C+erK5DqCvvZfNM7rHbiEQv8pF8eCwA==} + engines: {node: '>=20.0.0'} cpu: [arm64, x64] os: [win32] - '@node-llama-cpp/win-x64-cuda@3.6.0': - resolution: {integrity: sha512-vxNrz4BwMNgmfbRxALdTnb7RlJnO6p5uXlZP8fxpaD0zyBllenURTTzEo3Wobpa98af5DWEY1AueH9RFixvscA==} - engines: {node: '>=18.0.0'} + '@node-llama-cpp/win-x64-cuda@3.7.0': + resolution: {integrity: sha512-gUfqR+3jVjOy5ONPC+eJLkAsjZd31kS/LryicY+2gLg4vtJPw7TygLJJueKWd+gACh+AnENVNH1wd6oqSvKWPQ==} + engines: {node: '>=20.0.0'} cpu: [x64] os: [win32] - '@node-llama-cpp/win-x64-vulkan@3.6.0': - resolution: {integrity: sha512-2XhzVQaRw5QxMqtg+517W+tn0fgDqvo12I0/wVpaBctwIaX+yOcj+njGlVUbMBFzhR9VM9wo5N2bjfRYI6y+PA==} - engines: {node: '>=18.0.0'} + '@node-llama-cpp/win-x64-vulkan@3.7.0': + resolution: {integrity: sha512-Vb0c9bt/dy8YVAJ56anlOWlNXeysDTatdHssMVesTG9MogvWYReScReqT7VzQIBLzLjKQV/D7rAVpQj7Vzf6zw==} + engines: {node: '>=20.0.0'} cpu: [x64] os: [win32] - '@node-llama-cpp/win-x64@3.6.0': - resolution: {integrity: sha512-JDJoDeBkJhvFlINwi7tyTuOjSTJoBF6yyf7o89iMZ2xniyo6BzhI2d/79PGLkXht/1+sGNoCyzbuz3cBgP06Fg==} - engines: {node: '>=18.0.0'} + '@node-llama-cpp/win-x64@3.7.0': + resolution: {integrity: sha512-Ha/a5fi5etaJrmhmDSzsC/5Ceq74NqElazVbBij0hJjgu7SV/vghg/FyB9q6itAiDxn74+kwZZAcrZhVMAWHrA==} + engines: {node: '>=20.0.0'} cpu: [x64] os: [win32] @@ -5652,8 +5652,8 @@ packages: '@types/btoa-lite@1.0.2': resolution: {integrity: sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg==} - '@types/bun@1.2.5': - resolution: {integrity: sha512-w2OZTzrZTVtbnJew1pdFmgV99H0/L+Pvw+z1P67HaR18MHOzYnTYOi6qzErhK8HyT+DB782ADVPPE92Xu2/Opg==} + '@types/bun@1.2.8': + resolution: {integrity: sha512-t8L1RvJVUghW5V+M/fL3Thbxcs0HwNsXsnTEBEfEVqGteiJToOlZ/fyOEaR1kZsNqnu+3XA4RI/qmnX4w6+S+w==} '@types/bunyan@1.8.11': resolution: {integrity: sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ==} @@ -6472,8 +6472,8 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - bun-types@1.2.5: - resolution: {integrity: sha512-3oO6LVGGRRKI4kHINx5PIdIgnLRb7l/SprhzqXapmoYkFl5m4j6EvALvbDVuuBFaamB46Ap6HCUxIXNLCGy+tg==} + bun-types@1.2.7: + resolution: {integrity: sha512-P4hHhk7kjF99acXqKvltyuMQ2kf/rzIw3ylEDpCxDS9Xa0X0Yp/gJu/vDCucmWpiur5qJ0lwB2bWzOXa2GlHqA==} bun@1.2.4: resolution: {integrity: sha512-ZY0EZ/UKqheaLeAtMsfJA6jWoWvV9HAtfFaOJSmS3LrNpFKs1Sg5fZLSsczN1h3a+Dtheo4O3p3ZYWrf40kRGw==} @@ -9755,6 +9755,11 @@ packages: engines: {node: ^18 || >=20} hasBin: true + nanoid@5.1.5: + resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} + engines: {node: ^18 || >=20} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -9849,9 +9854,9 @@ packages: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} - node-llama-cpp@3.6.0: - resolution: {integrity: sha512-SzjsZLuG2pQPPkgMniTgK4sCcslA6ion5L55L8qeGnIb0cAhzVDbJ0Lxl5NhuTMm8KkxVZXF2yTihyulPMSLhw==} - engines: {node: '>=18.0.0'} + node-llama-cpp@3.7.0: + resolution: {integrity: sha512-f4qGXbmWSGGjklVZ0ISaRL/ysNxb5I8DGt5Nd1fkul3jbgO9MBvFILG+wDDxqowiSB94yskKwKgFOn2+F1CL6A==} + engines: {node: '>=20.0.0'} hasBin: true peerDependencies: typescript: '>=5.0.0' @@ -16195,37 +16200,37 @@ snapshots: '@ngrok/ngrok-win32-ia32-msvc': 1.4.1 '@ngrok/ngrok-win32-x64-msvc': 1.4.1 - '@node-llama-cpp/linux-arm64@3.6.0': + '@node-llama-cpp/linux-arm64@3.7.0': optional: true - '@node-llama-cpp/linux-armv7l@3.6.0': + '@node-llama-cpp/linux-armv7l@3.7.0': optional: true - '@node-llama-cpp/linux-x64-cuda@3.6.0': + '@node-llama-cpp/linux-x64-cuda@3.7.0': optional: true - '@node-llama-cpp/linux-x64-vulkan@3.6.0': + '@node-llama-cpp/linux-x64-vulkan@3.7.0': optional: true - '@node-llama-cpp/linux-x64@3.6.0': + '@node-llama-cpp/linux-x64@3.7.0': optional: true - '@node-llama-cpp/mac-arm64-metal@3.6.0': + '@node-llama-cpp/mac-arm64-metal@3.7.0': optional: true - '@node-llama-cpp/mac-x64@3.6.0': + '@node-llama-cpp/mac-x64@3.7.0': optional: true - '@node-llama-cpp/win-arm64@3.6.0': + '@node-llama-cpp/win-arm64@3.7.0': optional: true - '@node-llama-cpp/win-x64-cuda@3.6.0': + '@node-llama-cpp/win-x64-cuda@3.7.0': optional: true - '@node-llama-cpp/win-x64-vulkan@3.6.0': + '@node-llama-cpp/win-x64-vulkan@3.7.0': optional: true - '@node-llama-cpp/win-x64@3.6.0': + '@node-llama-cpp/win-x64@3.7.0': optional: true '@nodelib/fs.scandir@2.1.5': @@ -17661,11 +17666,11 @@ snapshots: '@sentry-internal/replay-canvas': 8.54.0 '@sentry/core': 8.54.0 - '@sentry/bun@8.54.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0)': + '@sentry/bun@8.54.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0)': dependencies: '@sentry/core': 8.54.0 '@sentry/node': 8.54.0 - '@sentry/opentelemetry': 8.54.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0) + '@sentry/opentelemetry': 8.54.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0) transitivePeerDependencies: - '@opentelemetry/api' - '@opentelemetry/context-async-hooks' @@ -17798,30 +17803,6 @@ snapshots: magic-string: 0.30.7 svelte: 5.19.7 - '@sentry/sveltekit@8.54.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0)(@sveltejs/kit@2.17.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)))(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)))(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0))': - dependencies: - '@sentry/core': 8.54.0 - '@sentry/node': 8.54.0 - '@sentry/opentelemetry': 8.54.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0) - '@sentry/svelte': 8.54.0(svelte@5.19.7) - '@sentry/vite-plugin': 2.22.6 - '@sveltejs/kit': 2.17.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)))(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)) - magic-string: 0.30.7 - magicast: 0.2.8 - sorcery: 1.0.0 - optionalDependencies: - vite: 6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0) - transitivePeerDependencies: - - '@opentelemetry/api' - - '@opentelemetry/context-async-hooks' - - '@opentelemetry/core' - - '@opentelemetry/instrumentation' - - '@opentelemetry/sdk-trace-base' - - '@opentelemetry/semantic-conventions' - - encoding - - supports-color - - svelte - '@sentry/sveltekit@8.54.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0)(@sveltejs/kit@2.17.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)))(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0)))(svelte@5.19.7)(vite@6.0.6(@types/node@22.13.1)(jiti@1.21.7)(sass-embedded@1.83.4)(terser@5.37.0)(yaml@2.7.0))': dependencies: '@sentry/core': 8.54.0 @@ -18222,9 +18203,9 @@ snapshots: '@types/btoa-lite@1.0.2': {} - '@types/bun@1.2.5': + '@types/bun@1.2.8': dependencies: - bun-types: 1.2.5 + bun-types: 1.2.7 '@types/bunyan@1.8.11': dependencies: @@ -19205,7 +19186,7 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - bun-types@1.2.5: + bun-types@1.2.7: dependencies: '@types/node': 22.13.1 '@types/ws': 8.5.14 @@ -20079,11 +20060,11 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.39.3(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(bun-types@1.2.5)(postgres@3.4.5): + drizzle-orm@0.39.3(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(bun-types@1.2.7)(postgres@3.4.5): optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/pg': 8.6.1 - bun-types: 1.2.5 + bun-types: 1.2.7 postgres: 3.4.5 dunder-proto@1.0.1: @@ -20477,16 +20458,17 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(eslint-import-resolver-node@0.3.9)(eslint@9.19.0(jiti@1.21.7)): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.23.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.19.0(jiti@1.21.7)): dependencies: debug: 3.2.7 optionalDependencies: + '@typescript-eslint/parser': 8.23.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3) eslint: 9.19.0(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(eslint@9.19.0(jiti@1.21.7)): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.19.0(jiti@1.21.7)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -20497,7 +20479,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.19.0(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(eslint-import-resolver-node@0.3.9)(eslint@9.19.0(jiti@1.21.7)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.23.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.19.0(jiti@1.21.7)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -20508,6 +20490,8 @@ snapshots: semver: 6.3.1 string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.23.0(eslint@9.19.0(jiti@1.21.7))(typescript@5.7.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -23146,6 +23130,8 @@ snapshots: nanoid@5.0.9: {} + nanoid@5.1.5: {} + natural-compare@1.4.0: {} negotiator@0.6.3: {} @@ -23239,7 +23225,7 @@ snapshots: node-forge@1.3.1: {} - node-llama-cpp@3.6.0(typescript@5.7.3): + node-llama-cpp@3.7.0(typescript@5.7.3): dependencies: '@huggingface/jinja': 0.3.3 async-retry: 1.3.3 @@ -23257,7 +23243,7 @@ snapshots: is-unicode-supported: 2.1.0 lifecycle-utils: 2.0.0 log-symbols: 7.0.0 - nanoid: 5.0.9 + nanoid: 5.1.5 node-addon-api: 8.3.1 octokit: 4.1.2 ora: 8.2.0 @@ -23272,17 +23258,17 @@ snapshots: which: 5.0.0 yargs: 17.7.2 optionalDependencies: - '@node-llama-cpp/linux-arm64': 3.6.0 - '@node-llama-cpp/linux-armv7l': 3.6.0 - '@node-llama-cpp/linux-x64': 3.6.0 - '@node-llama-cpp/linux-x64-cuda': 3.6.0 - '@node-llama-cpp/linux-x64-vulkan': 3.6.0 - '@node-llama-cpp/mac-arm64-metal': 3.6.0 - '@node-llama-cpp/mac-x64': 3.6.0 - '@node-llama-cpp/win-arm64': 3.6.0 - '@node-llama-cpp/win-x64': 3.6.0 - '@node-llama-cpp/win-x64-cuda': 3.6.0 - '@node-llama-cpp/win-x64-vulkan': 3.6.0 + '@node-llama-cpp/linux-arm64': 3.7.0 + '@node-llama-cpp/linux-armv7l': 3.7.0 + '@node-llama-cpp/linux-x64': 3.7.0 + '@node-llama-cpp/linux-x64-cuda': 3.7.0 + '@node-llama-cpp/linux-x64-vulkan': 3.7.0 + '@node-llama-cpp/mac-arm64-metal': 3.7.0 + '@node-llama-cpp/mac-x64': 3.7.0 + '@node-llama-cpp/win-arm64': 3.7.0 + '@node-llama-cpp/win-x64': 3.7.0 + '@node-llama-cpp/win-x64-cuda': 3.7.0 + '@node-llama-cpp/win-x64-vulkan': 3.7.0 typescript: 5.7.3 transitivePeerDependencies: - supports-color From e488f81159ca04dcd2712b7c5d9c38ea605b37fd Mon Sep 17 00:00:00 2001 From: polvallverdu Date: Sat, 29 Mar 2025 12:42:11 +0100 Subject: [PATCH 2/6] feat: added gemma3, and better ask command --- apps/cli/src/commands/ask.ts | 211 +++++++++++++++++++++++--------- apps/cli/src/llms/localllm.ts | 44 ++++++- apps/cli/src/llms/parser.ts | 26 +++- apps/cli/src/utils/models.ts | 74 ++++++----- packages/agent/src/index.ts | 19 ++- packages/api/src/router/chat.ts | 61 ++++----- packages/redis/package.json | 1 + packages/redis/src/index.ts | 4 +- pnpm-lock.yaml | 3 + 9 files changed, 295 insertions(+), 148 deletions(-) diff --git a/apps/cli/src/commands/ask.ts b/apps/cli/src/commands/ask.ts index 089ce08..b7744c6 100644 --- a/apps/cli/src/commands/ask.ts +++ b/apps/cli/src/commands/ask.ts @@ -4,8 +4,9 @@ import chalk from "chalk"; import clipboardy from "clipboardy"; import { Command } from "commander"; -import type { LLMResponse } from "@bashbuddy/validators"; -import { processPrompt } from "@bashbuddy/agent"; +import type { LLMMessage } from "@bashbuddy/agent"; +import type { LLMContext, LLMResponse } from "@bashbuddy/validators"; +import { processPrompt, yamlPrompt } from "@bashbuddy/agent"; import { SITE_URLS } from "@bashbuddy/consts"; import { LocalLLM } from "../llms/localllm"; @@ -32,6 +33,15 @@ export function createAskCommand(): Command { return askCommand; } +interface ConversationState { + messages: LLMMessage[]; + context: LLMContext; + chatId: string; + llm?: LocalLLM; + isCloudMode: boolean; + revisionCount: number; +} + async function execute(question: string) { p.intro("BashBuddy"); @@ -42,6 +52,7 @@ async function execute(question: string) { ]); let commandToRun: string | undefined; + let conversationState: ConversationState; switch (mode) { case LOCAL_MODE: { @@ -61,15 +72,26 @@ async function execute(question: string) { await llm.init(); modelSpinner.stop("Model loaded!"); - const createNewOutputStream = (newUserInput: string) => - Promise.resolve(processPrompt(llm, context, newUserInput, true)); - - commandToRun = await cliInfer( - await createNewOutputStream(question), - createNewOutputStream, - 1, - false, - ); + conversationState = { + messages: [ + { + role: "system", + content: yamlPrompt(context), + }, + { + role: "user", + content: question, + }, + ], + context, + chatId: "local", + llm, + isCloudMode: false, + revisionCount: 1, + }; + + const stream = processPrompt(llm, conversationState.messages); + commandToRun = await handleInference(stream, conversationState); await llm.dispose(); @@ -79,20 +101,27 @@ async function execute(question: string) { try { const chatId = await trpc.chat.createChat.mutate(); - const createNewOutputStream = (newUserInput: string) => - trpc.chat.ask.mutate({ - input: newUserInput, - context, - chatId, - useYaml: true, - }); - - commandToRun = await cliInfer( - await createNewOutputStream(question), - createNewOutputStream, - 1, - true, - ); + conversationState = { + messages: [ + { + role: "user", + content: question, + }, + ], + context, + chatId, + isCloudMode: true, + revisionCount: 1, + }; + + const stream = await trpc.chat.ask.mutate({ + input: question, + context, + chatId, + useYaml: true, + }); + + commandToRun = await handleInference(stream, conversationState); } catch (err) { if (err instanceof TRPCClientError) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access @@ -140,24 +169,32 @@ async function execute(question: string) { } } -async function cliInfer( +/** + * Process LLM inference and return the parsed response + */ +async function processInference( outputStream: AsyncIterable, - createNewOutputStream: ( - newUserInput: string, - ) => Promise>, - revisionCount = 1, - isCloudMode = false, -): Promise { + state: ConversationState, +): Promise { const llmSpinner = p.spinner(); llmSpinner.start("Processing..."); let finalResponse: LLMResponse; try { - finalResponse = await parseYamlResponse(outputStream, (response) => { - if (response.command) { - llmSpinner.message(response.command); - } + const { parsed, raw } = await parseYamlResponse( + outputStream, + (response) => { + if (response.command) { + llmSpinner.message(response.command); + } + }, + ); + + finalResponse = parsed; + state.messages.push({ + role: "model", + content: raw, }); } catch (err) { if (err instanceof ResponseParseError) { @@ -171,25 +208,70 @@ async function cliInfer( } llmSpinner.stop(finalResponse.command); + return finalResponse; +} - if (finalResponse.wrong) { +/** + * Display command information to the user + */ +function displayCommandInfo(response: LLMResponse): void { + if (response.wrong) { p.log.message(chalk.red("Please, limit yourself to ask for commands. ")); - return; } - if (finalResponse.explanation) { - p.log.message(chalk.dim(`Explanation: ${finalResponse.explanation}`)); + if (response.explanation) { + p.log.message(chalk.dim(`Explanation: ${response.explanation}`)); } - if (finalResponse.dangerous) { + if (response.dangerous) { p.log.message( chalk.red( `⚠️ Be careful, buddy has marked this command as dangerous. Make sure to know what it does.`, ), ); } +} + +/** + * Generate a new inference stream based on user suggestion + */ +async function generateNewStream( + suggestion: string, + state: ConversationState, +): Promise> { + // Add the suggestion to the messages + state.messages.push({ + role: "user", + content: suggestion, + }); + + // Increment revision count + state.revisionCount += 1; + // Generate a new stream based on mode + if (state.isCloudMode) { + return trpc.chat.ask.mutate({ + input: suggestion, + context: state.context, + chatId: state.chatId, + useYaml: true, + }); + } else { + if (!state.llm) { + throw new Error("LLM not initialized"); + } + return processPrompt(state.llm, state.messages); + } +} + +/** + * Handle user action on the command + */ +async function handleUserAction( + response: LLMResponse, + state: ConversationState, +): Promise { // Options for the select component const options = [ { value: "copyAndRun", label: "Copy & Run" }, @@ -198,9 +280,9 @@ async function cliInfer( ]; // Only add the suggest option if we haven't reached the revision limit in cloud mode - if (!isCloudMode || revisionCount < 5) { + if (!state.isCloudMode || state.revisionCount < 5) { options.push({ value: "suggest", label: "Suggest changes" }); - } else if (revisionCount >= 5) { + } else if (state.revisionCount >= 5) { p.log.message( chalk.yellow("You've reached the maximum of 5 revisions in cloud mode."), ); @@ -221,11 +303,11 @@ async function cliInfer( switch (action) { case "run": - return finalResponse.command; + return response.command; case "copy": { // Copy the command to clipboard try { - await clipboardy.write(finalResponse.command); + await clipboardy.write(response.command); p.log.success("Command copied to clipboard"); } catch { p.log.error("Failed to copy command to clipboard"); @@ -233,7 +315,7 @@ async function cliInfer( p.log.message( chalk.dim( - `Feel free to paste the command into your terminal: ${finalResponse.command}`, + `Feel free to paste the command into your terminal: ${response.command}`, ), ); @@ -242,18 +324,18 @@ async function cliInfer( case "copyAndRun": { // Copy the command to clipboard and run it try { - await clipboardy.write(finalResponse.command); + await clipboardy.write(response.command); p.log.success("Command copied to clipboard"); } catch { p.log.error( - `Failed to copy command to clipboard, but will still run. Feel free to copy it: ${finalResponse.command}`, + `Failed to copy command to clipboard, but will still run. Feel free to copy it: ${response.command}`, ); } - return finalResponse.command; + return response.command; } case "suggest": { - // Allow user to suggest changes (original behavior when typing) + // Allow user to suggest changes const suggestion = await p.text({ message: "What changes would you like to suggest?", placeholder: "Type your suggestion here", @@ -265,12 +347,8 @@ async function cliInfer( } if (suggestion) { - return cliInfer( - await createNewOutputStream(suggestion), - createNewOutputStream, - revisionCount + 1, - isCloudMode, - ); + const newStream = await generateNewStream(suggestion, state); + return handleInference(newStream, state); } return undefined; } @@ -278,3 +356,24 @@ async function cliInfer( return undefined; } } + +/** + * Handle the entire inference process + */ +async function handleInference( + outputStream: AsyncIterable, + state: ConversationState, +): Promise { + // Process the inference + const finalResponse = await processInference(outputStream, state); + + if (!finalResponse) { + return undefined; + } + + // Display command information + displayCommandInfo(finalResponse); + + // Handle user action + return handleUserAction(finalResponse, state); +} diff --git a/apps/cli/src/llms/localllm.ts b/apps/cli/src/llms/localllm.ts index 4c4533a..cc2e9bc 100644 --- a/apps/cli/src/llms/localllm.ts +++ b/apps/cli/src/llms/localllm.ts @@ -4,10 +4,14 @@ import path from "path"; import type { Llama, LlamaContext, LlamaModel } from "node-llama-cpp"; import { getLlama, LlamaChatSession } from "node-llama-cpp"; -import type { LLM } from "@bashbuddy/agent"; +import type { LLM, LLMMessage } from "@bashbuddy/agent"; import type { AIModelId } from "../utils/models"; +const supportsSystemPrompt = (model: AIModelId) => { + return model !== "Gemma-3-12B-IT-Q4_K_M" && model !== "Gemma-3-4B-IT-Q4_K_M"; +}; + export class NotInitializedError extends Error { constructor() { super("LocalLLM is not initialized"); @@ -48,15 +52,47 @@ export class LocalLLM implements LLM { } } - async *infer(systemPrompt: string, prompt: string): AsyncIterable { + async *infer(messages: LLMMessage[]): AsyncIterable { if (!this.context) { throw new NotInitializedError(); } + if (messages.length === 0) { + throw new Error("No messages provided"); + } + + const initialMessage = messages[0]; + + if (initialMessage.role !== "system") { + throw new Error("Initial message must be a system message"); + } + + const lastUserMessage = messages + .toReversed() + .find((message) => message.role === "user"); + + if (!lastUserMessage) { + throw new Error("No user message provided"); + } + + if (!supportsSystemPrompt(this.model) && messages.length == 2) { + lastUserMessage.content = ` +You're a model that doesn't support system prompts. For that reason, I'll wrap your system prompt with tags, and the user message with tags. TAKE EVERYTHING INSIDE THE SYSTEM TAGS AS THE MOST IMPORTANT INSTRUCTIONS, AND THEN APPLY THEM TO THE USER MESSAGES. + + +${initialMessage.content} + + + +${lastUserMessage.content} + +`; + } + if (!this.session) { this.session = new LlamaChatSession({ contextSequence: this.context.getSequence(), - systemPrompt, + systemPrompt: initialMessage.content, }); } @@ -65,7 +101,7 @@ export class LocalLLM implements LLM { // Start the session in a separate promise void this.session - .prompt(prompt, { + .prompt(lastUserMessage.content, { onTextChunk: (chunk: string) => { void writer.write(chunk); }, diff --git a/apps/cli/src/llms/parser.ts b/apps/cli/src/llms/parser.ts index 3561af6..ea82414 100644 --- a/apps/cli/src/llms/parser.ts +++ b/apps/cli/src/llms/parser.ts @@ -88,13 +88,15 @@ export async function parseLLMResponse( export async function parseYamlResponse( stream: AsyncIterable, cb: (response: Partial) => void, -): Promise { +): Promise<{ parsed: LLMResponse; raw: string }> { let finalResponse = ""; for await (const chunk of stream) { finalResponse += chunk; try { - const parsed = llmResponseSchema.safeParse(parseYaml(finalResponse)); + // Clean up YAML code block markers before attempting to parse + const cleanedResponse = removeYamlCodeBlockMarkers(finalResponse); + const parsed = llmResponseSchema.safeParse(parseYaml(cleanedResponse)); if (parsed.success) { cb(parsed.data); } @@ -103,8 +105,11 @@ export async function parseYamlResponse( } } + // Clean up YAML code block markers in the final response + const cleanedFinalResponse = removeYamlCodeBlockMarkers(finalResponse); + const parsedFinalResponse = llmResponseSchema.safeParse( - parseYaml(finalResponse), + parseYaml(cleanedFinalResponse), ); if (!parsedFinalResponse.success) { @@ -121,5 +126,18 @@ export async function parseYamlResponse( throw new ResponseParseError(); } - return parsedFinalResponse.data; + return { parsed: parsedFinalResponse.data, raw: cleanedFinalResponse }; +} + +/** + * Removes YAML code block markers from a string + */ +function removeYamlCodeBlockMarkers(text: string): string { + // Remove ```yaml at the beginning + let cleaned = text.replace(/^\s*```yaml\s*/i, ""); + + // Remove ``` at the end + cleaned = cleaned.replace(/\s*```\s*$/, ""); + + return cleaned; } diff --git a/apps/cli/src/utils/models.ts b/apps/cli/src/utils/models.ts index 4ffc9c3..507cf56 100644 --- a/apps/cli/src/utils/models.ts +++ b/apps/cli/src/utils/models.ts @@ -19,7 +19,24 @@ export interface AIModel { } // Available models -export const availableModels: AIModel[] = [ +export const availableModels = [ + { + id: "Qwen-2.5-7B-Instruct-Q6_K", + name: "Qwen 2.5 7B Q6", + downloadUrl: + "https://huggingface.co/bartowski/Qwen2.5-7B-Instruct-GGUF/resolve/main/Qwen2.5-7B-Instruct-Q6_K.gguf", + size: "6.65 GB", + requiredRAM: 10, + }, + { + id: "Qwen-2.5-7B-Instruct-Q4_K_M", + name: "Qwen 2.5 7B Q4", + downloadUrl: + "https://huggingface.co/bartowski/Qwen2.5-7B-Instruct-GGUF/resolve/main/Qwen2.5-7B-Instruct-Q4_K_M.gguf", + size: "4.58 GB", + requiredRAM: 8, + recommended: true, + }, { id: "Meta-Llama-3.1-8B-Instruct-Q4_K_M", name: "Llama 3.1 8B Q4", @@ -38,25 +55,23 @@ export const availableModels: AIModel[] = [ requiredRAM: 12, }, - // TODO: Waiting on update from node-llama-cpp (https://github.com/withcatai/node-llama-cpp/issues/440) - // { - // id: "Gemma-3-4B-IT-Q4_K_M", - // name: "Gemma 3 4B Q4", - // description: "Less weight, faster, but less accurate", - // downloadUrl: - // "https://huggingface.co/unsloth/gemma-3-4b-it-GGUF/resolve/main/gemma-3-4b-it-Q4_K_M.gguf", - // size: "2.4 GB", - // requiredRAM: 6, - // }, - // { - // id: "Gemma-3-12B-IT-Q4_K_M", - // name: "Gemma 3 12B Q4", - // description: "Heavier, slower, but more accurate", - // downloadUrl: - // "https://huggingface.co/unsloth/gemma-3-12b-it-GGUF/resolve/main/gemma-3-12b-it-Q4_K_M.gguf", - // size: "7.3 GB", - // requiredRAM: 12, - // }, + { + id: "Gemma-3-4B-IT-Q4_K_M", + name: "Gemma 3 4B Q4", + downloadUrl: + "https://huggingface.co/unsloth/gemma-3-4b-it-GGUF/resolve/main/gemma-3-4b-it-Q4_K_M.gguf", + size: "2.4 GB", + requiredRAM: 4, + }, + { + id: "Gemma-3-12B-IT-Q4_K_M", + name: "Gemma 3 12B Q4", + downloadUrl: + "https://huggingface.co/unsloth/gemma-3-12b-it-GGUF/resolve/main/gemma-3-12b-it-Q4_K_M.gguf", + size: "7.3 GB", + requiredRAM: 12, + }, + // It's fucking stupid // { // id: "Llama-3.2-3B-Instruct-Q4_K_M", @@ -78,24 +93,7 @@ export const availableModels: AIModel[] = [ // size: "9.05 GB", // requiredRAM: 16, // }, - { - id: "Qwen-2.5-7B-Instruct-Q6_K", - name: "Qwen 2.5 7B Q6", - downloadUrl: - "https://huggingface.co/bartowski/Qwen2.5-7B-Instruct-GGUF/resolve/main/Qwen2.5-7B-Instruct-Q6_K.gguf", - size: "6.65 GB", - requiredRAM: 10, - }, - { - id: "Qwen-2.5-7B-Instruct-Q4_K_M", - name: "Qwen 2.5 7B Q4", - downloadUrl: - "https://huggingface.co/bartowski/Qwen2.5-7B-Instruct-GGUF/resolve/main/Qwen2.5-7B-Instruct-Q4_K_M.gguf", - size: "4.58 GB", - requiredRAM: 8, - recommended: true, - }, -]; +] as const; export type AIModelId = (typeof availableModels)[number]["id"]; diff --git a/packages/agent/src/index.ts b/packages/agent/src/index.ts index 2323ed2..417468f 100644 --- a/packages/agent/src/index.ts +++ b/packages/agent/src/index.ts @@ -1,17 +1,16 @@ -import type { LLMContext } from "@bashbuddy/validators"; +export interface LLMMessage { + role: "user" | "model" | "system"; + content: string; +} -import { prompt as jsonPrompt } from "./prompts/json"; -import { prompt as yamlPrompt } from "./prompts/yaml"; +export { prompt as yamlPrompt } from "./prompts/yaml"; +export { prompt as jsonPrompt } from "./prompts/json"; export async function* processPrompt( llm: LLM, - context: LLMContext, - userPrompt: string, - useYaml = false, + messages: LLMMessage[], ): AsyncIterable { - const prompt = useYaml ? yamlPrompt(context) : jsonPrompt(context); - - const stream = llm.infer(prompt, userPrompt); + const stream = llm.infer(messages); for await (const chunk of stream) { yield chunk; @@ -25,5 +24,5 @@ export interface LLM { * @param prompt The input prompt to process * @returns A stream of string responses */ - infer(systemPrompt: string, prompt: string): AsyncIterable; + infer(messages: LLMMessage[]): AsyncIterable; } diff --git a/packages/api/src/router/chat.ts b/packages/api/src/router/chat.ts index eb81dcf..406bbb3 100644 --- a/packages/api/src/router/chat.ts +++ b/packages/api/src/router/chat.ts @@ -4,8 +4,8 @@ import { Groq } from "groq-sdk"; import { Langfuse } from "langfuse"; import { z } from "zod"; -import type { LLM } from "@bashbuddy/agent"; -import { processPrompt } from "@bashbuddy/agent"; +import type { LLM, LLMMessage } from "@bashbuddy/agent"; +import { jsonPrompt, processPrompt, yamlPrompt } from "@bashbuddy/agent"; import { eq, increment } from "@bashbuddy/db"; import { db } from "@bashbuddy/db/client"; import { userTable } from "@bashbuddy/db/schema"; @@ -36,39 +36,27 @@ const langfuse = class GroqLLM implements LLM { private groq: Groq; - private messages: Groq.Chat.Completions.ChatCompletionMessageParam[]; private chatId: string; private userId: string; - constructor( - messages: Groq.Chat.Completions.ChatCompletionMessageParam[], - chatId: string, - userId: string, - ) { + constructor(chatId: string, userId: string) { this.groq = new Groq(); - this.messages = messages; this.chatId = chatId; this.userId = userId; } - async *infer(systemPrompt: string, prompt: string): AsyncIterable { + async *infer(messages: LLMMessage[]): AsyncIterable { const trace = langfuse?.trace({ name: "chat.ask", id: this.chatId, userId: this.userId, }); - const messages: Groq.Chat.Completions.ChatCompletionMessageParam[] = [ - { - role: "system", - content: systemPrompt, - }, - ...this.messages, - { - role: "user", - content: prompt, - }, - ]; + const groqMessages: Groq.Chat.Completions.ChatCompletionMessageParam[] = + messages.map((message) => ({ + role: message.role === "model" ? "assistant" : message.role, + content: message.content, + })); const temperature = 0.7; const maxCompletionTokens = 1024; @@ -86,7 +74,7 @@ class GroqLLM implements LLM { }); const chatCompletion = await this.groq.chat.completions.create({ - messages, + messages: groqMessages, model: "llama-3.1-8b-instant", temperature, max_completion_tokens: maxCompletionTokens, @@ -203,18 +191,23 @@ export const chatRouter = { .where(eq(userTable.id, ctx.user.id)) .execute(); - const groqLLM = new GroqLLM( - chatSession.messages, - input.chatId, - ctx.user.id, - ); + const messages: LLMMessage[] = [ + { + role: "system", + content: input.useYaml + ? yamlPrompt(input.context) + : jsonPrompt(input.context), + }, + ...chatSession.messages, + { + role: "user", + content: input.input, + }, + ]; + + const groqLLM = new GroqLLM(input.chatId, ctx.user.id); - const stream = processPrompt( - groqLLM, - input.context, - input.input, - input.useYaml, - ); + const stream = processPrompt(groqLLM, messages); await addMessageToChatSession(input.chatId, { role: "user", @@ -229,7 +222,7 @@ export const chatRouter = { } await addMessageToChatSession(input.chatId, { - role: "assistant", + role: "model", content, }); diff --git a/packages/redis/package.json b/packages/redis/package.json index 911191d..4fdab65 100755 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -30,6 +30,7 @@ "@t3-oss/env-core": "catalog:" }, "devDependencies": { + "@types/bun": "latest", "@bashbuddy/eslint-config": "workspace:*", "@bashbuddy/prettier-config": "workspace:*", "@bashbuddy/tsconfig": "workspace:*", diff --git a/packages/redis/src/index.ts b/packages/redis/src/index.ts index 056d5e2..c57e2f4 100755 --- a/packages/redis/src/index.ts +++ b/packages/redis/src/index.ts @@ -7,7 +7,7 @@ import { env } from "../env"; export { Ratelimit }; const chatMessageSchema = z.object({ - role: z.enum(["user", "assistant", "system"]), + role: z.enum(["user", "model", "system"]), content: z.string(), }); @@ -26,7 +26,7 @@ const redis = new Redis({ }); export async function createChatSession(userId: string) { - const id = crypto.randomUUID(); + const id = Bun.randomUUIDv7(); await redis.hset(id, { userId, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c6af89..1d0c2af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1255,6 +1255,9 @@ importers: '@bashbuddy/tsconfig': specifier: workspace:* version: link:../../tooling/typescript + '@types/bun': + specifier: latest + version: 1.2.8 dotenv-cli: specifier: 'catalog:' version: 7.4.2 From 82d9425441549f5068b9b69f32c0bc82bb60d5e9 Mon Sep 17 00:00:00 2001 From: polvallverdu Date: Sat, 29 Mar 2025 12:44:30 +0100 Subject: [PATCH 3/6] feat: added ability to type directly on the command --- apps/cli/src/commands/ask.ts | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/apps/cli/src/commands/ask.ts b/apps/cli/src/commands/ask.ts index b7744c6..9f01cb8 100644 --- a/apps/cli/src/commands/ask.ts +++ b/apps/cli/src/commands/ask.ts @@ -23,8 +23,14 @@ import { runCommandWithStream } from "../utils/runner"; export function createAskCommand(): Command { const askCommand = new Command("ask") .description("Ask a question to the AI") - .argument("", "The question to ask the AI") - .action((questionParts: string[]) => { + .argument("[question...]", "The question to ask the AI") + .action((questionParts: string[] = []) => { + // If no question parts, prompt the user + if (questionParts.length === 0) { + promptForQuestion().catch(console.error); + return; + } + // Join all parts of the question with spaces const question = questionParts.join(" "); execute(question).catch(console.error); @@ -33,6 +39,25 @@ export function createAskCommand(): Command { return askCommand; } +/** + * Prompt the user for a question if none was provided + */ +async function promptForQuestion() { + p.intro("BashBuddy"); + + const question = await p.text({ + message: "What would you like to ask?", + placeholder: "Ask for a command", + }); + + if (p.isCancel(question) || !question) { + p.cancel("Operation cancelled"); + return; + } + + await execute(question); +} + interface ConversationState { messages: LLMMessage[]; context: LLMContext; From 06d3f9d6855230c1a0cec7c2d241488b4672de9c Mon Sep 17 00:00:00 2001 From: polvallverdu Date: Sat, 29 Mar 2025 12:44:59 +0100 Subject: [PATCH 4/6] chore: changeset --- .changeset/stale-buckets-roll.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/stale-buckets-roll.md diff --git a/.changeset/stale-buckets-roll.md b/.changeset/stale-buckets-roll.md new file mode 100644 index 0000000..42405b8 --- /dev/null +++ b/.changeset/stale-buckets-roll.md @@ -0,0 +1,5 @@ +--- +"@bashbuddy/cli": patch +--- + +Added gemma 3, and better command structure From 7f1a5aaa3a96b12bd780435ed0e0bba8bd05f838 Mon Sep 17 00:00:00 2001 From: polvallverdu Date: Sat, 29 Mar 2025 12:54:48 +0100 Subject: [PATCH 5/6] feat: added blog post --- apps/landing/src/components/Header.svelte | 10 ++++---- .../posts/gemma-3-arrives-to-bashbuddy.svx | 23 ++++++++++++++++++ .../src/routes/blog/[slug]/+page.svelte | 2 +- .../gemma-3-arrives-to-bashbuddy.png | Bin 0 -> 261016 bytes 4 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 apps/landing/src/lib/posts/gemma-3-arrives-to-bashbuddy.svx create mode 100644 apps/landing/static/images/posts/gemma-3-arrives-to-bashbuddy/gemma-3-arrives-to-bashbuddy.png diff --git a/apps/landing/src/components/Header.svelte b/apps/landing/src/components/Header.svelte index c6d7004..150938c 100644 --- a/apps/landing/src/components/Header.svelte +++ b/apps/landing/src/components/Header.svelte @@ -9,7 +9,8 @@ import { SITE_URLS } from "@bashbuddy/consts"; - const BANNER_STORAGE_KEY = "bashbuddy-qwen-banner-closed"; + // const BANNER_STORAGE_KEY = "bashbuddy-qwen-banner-closed"; + const BANNER_STORAGE_KEY = "bashbuddy-gemma-3-banner-closed"; let isMenuOpen = $state(false); let isBannerVisible = $state(false); @@ -104,12 +105,11 @@ >

- We've added Qwen 2.5 models to BashBuddy Local! + We've added Gemma 3 models to BashBuddy Local! - Read more ➡️Read more ➡️