diff --git a/open-sse/config/credentialLoader.ts b/open-sse/config/credentialLoader.ts index cc740a48ae..2350abce21 100644 --- a/open-sse/config/credentialLoader.ts +++ b/open-sse/config/credentialLoader.ts @@ -16,7 +16,6 @@ import { readFileSync, existsSync } from "fs"; import { join } from "path"; -import { resolveDataDir } from "../../src/lib/dataPaths"; // Fields that can be overridden per provider const CREDENTIAL_FIELDS = [ @@ -41,27 +40,23 @@ function credGlobals(): CredGlobals { return globalThis as CredGlobals; } -/** - * Resolves the path to provider-credentials.json using the application's - * data directory. Delegates to resolveDataDir() which handles DATA_DIR env, - * platform-specific defaults, and fallback logic. - * - * previous: Priority: DATA_DIR env → ./data (project root) - */ function resolveCredentialsPath(): string { + let resolveDataDir: (options?: { isCloud?: boolean }) => string; + + try { + resolveDataDir = require("@/lib/dataPaths").resolveDataDir; + } catch (err) { + const fallbackDataDir = process.env.DATA_DIR || join(process.cwd(), "data"); + console.warn( + `[CREDENTIALS] Could not load dataPaths module, using fallback: ${fallbackDataDir}` + ); + return join(fallbackDataDir, "provider-credentials.json"); + } + return join(resolveDataDir(), "provider-credentials.json"); } -/** - * Load and merge external credentials into the PROVIDERS object. - * Uses TTL-based caching (60s) so credential file changes are picked up - * without requiring a server restart. - * - * @param {object} providers - The PROVIDERS object from constants.js - * @returns {object} The same PROVIDERS object (mutated in place) - */ export function loadProviderCredentials>(providers: T): T { - // Return cached result if within TTL if (cachedProviders && Date.now() - lastLoadTime < CONFIG_TTL_MS) { return cachedProviders as T; } diff --git a/open-sse/config/providerRegistry.ts b/open-sse/config/providerRegistry.ts index a3bce6d173..38f5c4323d 100644 --- a/open-sse/config/providerRegistry.ts +++ b/open-sse/config/providerRegistry.ts @@ -1209,9 +1209,9 @@ export const REGISTRY: Record = { authType: "apikey", authHeader: "bearer", models: [ - { id: "gpt-oss-120b", name: "GPT OSS 120B", toolCalling: false }, - { id: "openai/gpt-oss-120b", name: "GPT OSS 120B (OpenAI Prefix)", toolCalling: false }, - { id: "openai/gpt-oss-20b", name: "GPT OSS 20B", toolCalling: false }, + { id: "gpt-oss-120b", name: "GPT OSS 120B" }, + { id: "openai/gpt-oss-120b", name: "GPT OSS 120B (OpenAI Prefix)" }, + { id: "openai/gpt-oss-20b", name: "GPT OSS 20B" }, { id: "meta/llama-3.3-70b-instruct", name: "Llama 3.3 70B" }, { id: "nvidia/llama-3.3-70b-instruct", name: "Llama 3.3 70B (NVIDIA Prefix)" }, { id: "meta/llama-4-maverick-17b-128e-instruct", name: "Llama 4 Maverick" }, diff --git a/open-sse/services/autoCombo/persistence.ts b/open-sse/services/autoCombo/persistence.ts index 7dae3521a9..e445ed5766 100644 --- a/open-sse/services/autoCombo/persistence.ts +++ b/open-sse/services/autoCombo/persistence.ts @@ -7,7 +7,7 @@ import fs from "fs"; import path from "path"; -import { resolveDataDir } from "../../../src/lib/dataPaths"; +import { resolveDataDir } from "@/lib/dataPaths"; export interface AdaptationState { comboId: string; diff --git a/package-lock.json b/package-lock.json index 5da6f07344..a05f478aa7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,7 @@ "selfsigned": "^5.5.0", "tsx": "^4.21.0", "undici": "^8.1.0", - "uuid": "^13.0.0", + "uuid": "^14.0.0", "wreq-js": "^2.0.1", "xxhash-wasm": "^1.1.0", "yazl": "^3.3.1", @@ -70,7 +70,7 @@ "concurrently": "^9.2.1", "cross-env": "^10.1.0", "eslint": "^9.39.2", - "eslint-config-next": "16.2.3", + "eslint-config-next": "16.2.4", "husky": "^9.1.7", "jsdom": "^29.0.1", "lint-staged": "^16.2.7", @@ -2635,6 +2635,20 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/@lobehub/ui/node_modules/uuid": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "peer": true, + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, "node_modules/@mdx-js/mdx": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", @@ -2778,15 +2792,15 @@ } }, "node_modules/@next/env": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.3.tgz", - "integrity": "sha512-ZWXyj4uNu4GCWQw9cjRxWlbD+33mcDszIo9iQxFnBX3Wmgq9ulaSJcl6VhuWx5pCWqqD+9W6Wfz7N0lM5lYPMA==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.4.tgz", + "integrity": "sha512-dKkkOzOSwFYe5RX6y26fZgkSpVAlIOJKQHIiydQcrWH6y/97+RceSOAdjZ14Qa3zLduVUy0TXcn+EiM6t4rPgw==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.2.3.tgz", - "integrity": "sha512-nE/b9mht28XJxjTwKs/yk7w4XTaU3t40UHVAky6cjiijdP/SEy3hGsnQMPxmXPTpC7W4/97okm6fngKnvCqVaA==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.2.4.tgz", + "integrity": "sha512-tOX826JJ96gYK/go18sPUgMq9FK1tqxBFfUCEufJb5XIkWFFmpgU7mahJANKGkHs7F41ir3tReJ3Lv5La0RvhA==", "dev": true, "license": "MIT", "dependencies": { @@ -2794,9 +2808,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.3.tgz", - "integrity": "sha512-u37KDKTKQ+OQLvY+z7SNXixwo4Q2/IAJFDzU1fYe66IbCE51aDSAzkNDkWmLN0yjTUh4BKBd+hb69jYn6qqqSg==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.4.tgz", + "integrity": "sha512-OXTFFox5EKN1Ym08vfrz+OXxmCcEjT4SFMbNRsWZE99dMqt2Kcusl5MqPXcW232RYkMLQTy0hqgAMEsfEd/l2A==", "cpu": [ "arm64" ], @@ -2810,9 +2824,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.3.tgz", - "integrity": "sha512-gHjL/qy6Q6CG3176FWbAKyKh9IfntKZTB3RY/YOJdDFpHGsUDXVH38U4mMNpHVGXmeYW4wj22dMp1lTfmu/bTQ==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.4.tgz", + "integrity": "sha512-XhpVnUfmYWvD3YrXu55XdcAkQtOnvaI6wtQa8fuF5fGoKoxIUZ0kWPtcOfqJEWngFF/lOS9l3+O9CcownhiQxQ==", "cpu": [ "x64" ], @@ -2826,9 +2840,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.3.tgz", - "integrity": "sha512-U6vtblPtU/P14Y/b/n9ZY0GOxbbIhTFuaFR7F4/uMBidCi2nSdaOFhA0Go81L61Zd6527+yvuX44T4ksnf8T+Q==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.4.tgz", + "integrity": "sha512-Mx/tjlNA3G8kg14QvuGAJ4xBwPk1tUHq56JxZ8CXnZwz1Etz714soCEzGQQzVMz4bEnGPowzkV6Xrp6wAkEWOQ==", "cpu": [ "arm64" ], @@ -2842,9 +2856,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.3.tgz", - "integrity": "sha512-/YV0LgjHUmfhQpn9bVoGc4x4nan64pkhWR5wyEV8yCOfwwrH630KpvRg86olQHTwHIn1z59uh6JwKvHq1h4QEw==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.4.tgz", + "integrity": "sha512-iVMMp14514u7Nup2umQS03nT/bN9HurK8ufylC3FZNykrwjtx7V1A7+4kvhbDSCeonTVqV3Txnv0Lu+m2oDXNg==", "cpu": [ "arm64" ], @@ -2858,9 +2872,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.3.tgz", - "integrity": "sha512-/HiWEcp+WMZ7VajuiMEFGZ6cg0+aYZPqCJD3YJEfpVWQsKYSjXQG06vJP6F1rdA03COD9Fef4aODs3YxKx+RDQ==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.4.tgz", + "integrity": "sha512-EZOvm1aQWgnI/N/xcWOlnS3RQBk0VtVav5Zo7n4p0A7UKyTDx047k8opDbXgBpHl4CulRqRfbw3QrX2w5UOXMQ==", "cpu": [ "x64" ], @@ -2874,9 +2888,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.3.tgz", - "integrity": "sha512-Kt44hGJfZSefebhk/7nIdivoDr3Ugp5+oNz9VvF3GUtfxutucUIHfIO0ZYO8QlOPDQloUVQn4NVC/9JvHRk9hw==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.4.tgz", + "integrity": "sha512-h9FxsngCm9cTBf71AR4fGznDEDx1hS7+kSEiIRjq5kO1oXWm07DxVGZjCvk0SGx7TSjlUqhI8oOyz7NfwAdPoA==", "cpu": [ "x64" ], @@ -2890,9 +2904,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.3.tgz", - "integrity": "sha512-O2NZ9ie3Tq6xj5Z5CSwBT3+aWAMW2PIZ4egUi9MaWLkwaehgtB7YZjPm+UpcNpKOme0IQuqDcor7BsW6QBiQBw==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.4.tgz", + "integrity": "sha512-3NdJV5OXMSOeJYijX+bjaLge3mJBlh4ybydbT4GFoB/2hAojWHtMhl3CYlYoMrjPuodp0nzFVi4Tj2+WaMg+Ow==", "cpu": [ "arm64" ], @@ -2906,9 +2920,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.3.tgz", - "integrity": "sha512-Ibm29/GgB/ab5n7XKqlStkm54qqZE8v2FnijUPBgrd67FWrac45o/RsNlaOWjme/B5UqeWt/8KM4aWBwA1D2Kw==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.4.tgz", + "integrity": "sha512-kMVGgsqhO5YTYODD9IPGGhA6iprWidQckK3LmPeW08PIFENRmgfb4MjXHO+p//d+ts2rpjvK5gXWzXSMrPl9cw==", "cpu": [ "x64" ], @@ -6537,17 +6551,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.2.tgz", - "integrity": "sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.0.tgz", + "integrity": "sha512-HyAZtpdkgZwpq8Sz3FSUvCR4c+ScbuWa9AksK2Jweub7w4M3yTz4O11AqVJzLYjy/B9ZWPyc81I+mOdJU/bDQw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.58.2", - "@typescript-eslint/type-utils": "8.58.2", - "@typescript-eslint/utils": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2", + "@typescript-eslint/scope-manager": "8.59.0", + "@typescript-eslint/type-utils": "8.59.0", + "@typescript-eslint/utils": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -6560,7 +6574,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.58.2", + "@typescript-eslint/parser": "^8.59.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -6576,16 +6590,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.2.tgz", - "integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.0.tgz", + "integrity": "sha512-TI1XGwKbDpo9tRW8UDIXCOeLk55qe9ZFGs8MTKU6/M08HWTw52DD/IYhfQtOEhEdPhLMT26Ka/x7p70nd3dzDg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.58.2", - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2", + "@typescript-eslint/scope-manager": "8.59.0", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0", "debug": "^4.4.3" }, "engines": { @@ -6601,14 +6615,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.2.tgz", - "integrity": "sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.0.tgz", + "integrity": "sha512-Lw5ITrR5s5TbC19YSvlr63ZfLaJoU6vtKTHyB0GQOpX0W7d5/Ir6vUahWi/8Sps/nOukZQ0IB3SmlxZnjaKVnw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.58.2", - "@typescript-eslint/types": "^8.58.2", + "@typescript-eslint/tsconfig-utils": "^8.59.0", + "@typescript-eslint/types": "^8.59.0", "debug": "^4.4.3" }, "engines": { @@ -6623,14 +6637,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.2.tgz", - "integrity": "sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.0.tgz", + "integrity": "sha512-UzR16Ut8IpA3Mc4DbgAShlPPkVm8xXMWafXxB0BocaVRHs8ZGakAxGRskF7FId3sdk9lgGD73GSFaWmWFDE4dg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2" + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6641,9 +6655,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.2.tgz", - "integrity": "sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.0.tgz", + "integrity": "sha512-91Sbl3s4Kb3SybliIY6muFBmHVv+pYXfybC4Oolp3dvk8BvIE3wOPc+403CWIT7mJNkfQRGtdqghzs2+Z91Tqg==", "dev": true, "license": "MIT", "engines": { @@ -6658,15 +6672,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.2.tgz", - "integrity": "sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.0.tgz", + "integrity": "sha512-3TRiZaQSltGqGeNrJzzr1+8YcEobKH9rHnqIp/1psfKFmhRQDNMGP5hBufanYTGznwShzVLs3Mz+gDN7HkWfXg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2", - "@typescript-eslint/utils": "8.58.2", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0", + "@typescript-eslint/utils": "8.59.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -6683,9 +6697,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.2.tgz", - "integrity": "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.0.tgz", + "integrity": "sha512-nLzdsT1gdOgFxxxwrlNVUBzSNBEEHJ86bblmk4QAS6stfig7rcJzWKqCyxFy3YRRHXDWEkb2NralA1nOYkkm/A==", "dev": true, "license": "MIT", "engines": { @@ -6697,16 +6711,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.2.tgz", - "integrity": "sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.0.tgz", + "integrity": "sha512-O9Re9P1BmBLFJyikRbQpLku/QA3/AueZNO9WePLBwQrvkixTmDe8u76B6CYUAITRl/rHawggEqUGn5QIkVRLMw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.58.2", - "@typescript-eslint/tsconfig-utils": "8.58.2", - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2", + "@typescript-eslint/project-service": "8.59.0", + "@typescript-eslint/tsconfig-utils": "8.59.0", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -6777,16 +6791,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.2.tgz", - "integrity": "sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.0.tgz", + "integrity": "sha512-I1R/K7V07XsMJ12Oaxg/O9GfrysGTmCRhvZJBv0RE0NcULMzjqVpR5kRRQjHsz3J/bElU7HwCO7zkqL+MSUz+g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.58.2", - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2" + "@typescript-eslint/scope-manager": "8.59.0", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6801,13 +6815,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.2.tgz", - "integrity": "sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.0.tgz", + "integrity": "sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.2", + "@typescript-eslint/types": "8.59.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -7799,9 +7813,9 @@ } }, "node_modules/axios": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz", - "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.1.tgz", + "integrity": "sha512-WOG+Jj8ZOvR0a3rAn+Tuf1UQJRxw5venr6DgdbJzngJE3qG7X0kL83CZGpdHMxEm+ZK3seAbvFsw4FfOfP9vxg==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.11", @@ -10140,13 +10154,13 @@ } }, "node_modules/eslint-config-next": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.2.3.tgz", - "integrity": "sha512-Dnkrylzjof/Az7iNoIQJqD18zTxQZcngir19KJaiRsMnnjpQSVoa6aEg/1Q4hQC+cW90uTlgQYadwL1CYNwFWA==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.2.4.tgz", + "integrity": "sha512-A6ekXYFj/YQxBPMl45g3e+U8zJo+X2+ZQwcz34pPKjpc/3S4roBA2Rd9xWB4FKuSxhofo1/95WjzmUY+wHrOhg==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "16.2.3", + "@next/eslint-plugin-next": "16.2.4", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", @@ -11187,6 +11201,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -15519,12 +15534,12 @@ } }, "node_modules/next": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/next/-/next-16.2.3.tgz", - "integrity": "sha512-9V3zV4oZFza3PVev5/poB9g0dEafVcgNyQ8eTRop8GvxZjV2G15FC5ARuG1eFD42QgeYkzJBJzHghNP8Ad9xtA==", + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/next/-/next-16.2.4.tgz", + "integrity": "sha512-kPvz56wF5frc+FxlHI5qnklCzbq53HTwORaWBGdT0vNoKh1Aya9XC8aPauH4NJxqtzbWsS5mAbctm4cr+EkQ2Q==", "license": "MIT", "dependencies": { - "@next/env": "16.2.3", + "@next/env": "16.2.4", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", @@ -15538,14 +15553,14 @@ "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "16.2.3", - "@next/swc-darwin-x64": "16.2.3", - "@next/swc-linux-arm64-gnu": "16.2.3", - "@next/swc-linux-arm64-musl": "16.2.3", - "@next/swc-linux-x64-gnu": "16.2.3", - "@next/swc-linux-x64-musl": "16.2.3", - "@next/swc-win32-arm64-msvc": "16.2.3", - "@next/swc-win32-x64-msvc": "16.2.3", + "@next/swc-darwin-arm64": "16.2.4", + "@next/swc-darwin-x64": "16.2.4", + "@next/swc-linux-arm64-gnu": "16.2.4", + "@next/swc-linux-arm64-musl": "16.2.4", + "@next/swc-linux-x64-gnu": "16.2.4", + "@next/swc-linux-x64-musl": "16.2.4", + "@next/swc-win32-arm64-msvc": "16.2.4", + "@next/swc-win32-x64-msvc": "16.2.4", "sharp": "^0.34.5" }, "peerDependencies": { @@ -16517,9 +16532,9 @@ } }, "node_modules/prettier": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.2.tgz", - "integrity": "sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", "bin": { @@ -19671,9 +19686,9 @@ } }, "node_modules/typescript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz", - "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -19685,16 +19700,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.58.2.tgz", - "integrity": "sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.0.tgz", + "integrity": "sha512-BU3ONW9X+v90EcCH9ZS6LMackcVtxRLlI3XrYyqZIwVSHIk7Qf7bFw1z0M9Q0IUxhTMZCf8piY9hTYaNEIASrw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.58.2", - "@typescript-eslint/parser": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2", - "@typescript-eslint/utils": "8.58.2" + "@typescript-eslint/eslint-plugin": "8.59.0", + "@typescript-eslint/parser": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0", + "@typescript-eslint/utils": "8.59.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -20027,9 +20042,9 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", - "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz", + "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -20679,9 +20694,9 @@ "license": "ISC" }, "node_modules/wreq-js": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/wreq-js/-/wreq-js-2.2.2.tgz", - "integrity": "sha512-iNcPyvVg14nWtHMzN595GDH1ELB1CDfVUV4s+AfSrP2go01/LYVBCkx4AdyMNAup4myQEiNBBmRI2Co2MKsFPQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/wreq-js/-/wreq-js-2.3.0.tgz", + "integrity": "sha512-jROBpTUhVH40qG+cAvBhdduKPGDSx55jK1dIDmVuu29sux9i8KY0u0wb5tHkMzXKDy9hrfHP+bpvaSq25rGwEA==", "cpu": [ "x64", "arm64" @@ -20691,10 +20706,7 @@ "darwin", "linux", "win32" - ], - "engines": { - "node": ">=20.0.0" - } + ] }, "node_modules/wsl-utils": { "version": "0.3.1", diff --git a/package.json b/package.json index fcc76e04a9..36ab8342b5 100644 --- a/package.json +++ b/package.json @@ -135,7 +135,7 @@ "selfsigned": "^5.5.0", "tsx": "^4.21.0", "undici": "^8.1.0", - "uuid": "^13.0.0", + "uuid": "^14.0.0", "wreq-js": "^2.0.1", "xxhash-wasm": "^1.1.0", "yazl": "^3.3.1", @@ -161,7 +161,7 @@ "concurrently": "^9.2.1", "cross-env": "^10.1.0", "eslint": "^9.39.2", - "eslint-config-next": "16.2.3", + "eslint-config-next": "16.2.4", "husky": "^9.1.7", "jsdom": "^29.0.1", "lint-staged": "^16.2.7", diff --git a/src/app/api/skills/marketplace/route.ts b/src/app/api/skills/marketplace/route.ts index 4c623e3a45..e0ae1fa146 100644 --- a/src/app/api/skills/marketplace/route.ts +++ b/src/app/api/skills/marketplace/route.ts @@ -1,6 +1,12 @@ import { NextResponse } from "next/server"; import { getSettings } from "@/lib/db/settings"; import { isAuthenticated } from "@/shared/utils/apiAuth"; +import { getSkillsProviderSetting } from "@/lib/skills/providerSettings"; + +const POPULAR_BY_PROVIDER = { + skillsmp: ["web-search", "file-reader", "sql-assistant", "devops-helper", "docs-assistant"], + skillssh: ["git", "terminal", "postgres", "kubernetes", "playwright"], +} as const; export async function GET(request: Request) { if (!(await isAuthenticated(request))) { @@ -8,7 +14,21 @@ export async function GET(request: Request) { } try { const { searchParams } = new URL(request.url); - const q = searchParams.get("q") || ""; + const q = searchParams.get("q")?.trim() || ""; + const provider = await getSkillsProviderSetting(); + + // Return popular skills when query is empty + if (!q) { + const popularList = POPULAR_BY_PROVIDER[provider]; + const skills = popularList.map((name) => ({ + name, + description: `Popular skill: ${name}`, + installCount: 0, + })); + return NextResponse.json({ skills }); + } + + // Search SkillsMP for non-empty queries const settings = await getSettings(); const apiKey = (settings as Record).skillsmpApiKey; diff --git a/src/lib/db/encryption.ts b/src/lib/db/encryption.ts index 07ab9db803..80a27aba7b 100644 --- a/src/lib/db/encryption.ts +++ b/src/lib/db/encryption.ts @@ -135,14 +135,16 @@ export function decrypt(ciphertext: string | null | undefined): string | null | console.warn( "[Encryption] Found encrypted data but STORAGE_ENCRYPTION_KEY is not set. Cannot decrypt." ); - return ciphertext; + // Return null instead of encrypted ciphertext to prevent sending encrypted tokens to providers + return null; } const body = ciphertext.slice(PREFIX.length); const parts = body.split(":"); if (parts.length !== 3) { console.error("[Encryption] Malformed encrypted value"); - return ciphertext; + // Return null instead of encrypted ciphertext to prevent sending malformed encrypted tokens to providers + return null; } const [ivHex, encryptedHex, authTagHex] = parts; @@ -154,7 +156,17 @@ export function decrypt(ciphertext: string | null | undefined): string | null | decipher.setAuthTag(authTag); let decrypted = decipher.update(encryptedHex, "hex", "utf8"); - decrypted += decipher.final("utf8"); + try { + decrypted += decipher.final("utf8"); + } catch (finalErr: unknown) { + const finalMessage = finalErr instanceof Error ? finalErr.message : String(finalErr); + console.error( + `[Encryption] Decryption final() failed: ${finalMessage}. ` + + `Ciphertext prefix: ${ciphertext.slice(0, 30)}... ` + + `Auth tag validation likely failed.` + ); + return ciphertext; + } return decrypted; } catch (err: unknown) { const legacyKey = getLegacyKey(); @@ -174,7 +186,8 @@ export function decrypt(ciphertext: string | null | undefined): string | null | } const message = err instanceof Error ? err.message : String(err); console.error("[Encryption] Decryption failed:", message); - return ciphertext; + // Return null instead of encrypted ciphertext to prevent sending encrypted tokens to providers + return null; } } diff --git a/src/lib/modelCapabilities.ts b/src/lib/modelCapabilities.ts index 7ee0354550..45f1aa7c3d 100644 --- a/src/lib/modelCapabilities.ts +++ b/src/lib/modelCapabilities.ts @@ -6,7 +6,7 @@ import { parseModel, resolveCanonicalProviderModel } from "@omniroute/open-sse/s import { MODEL_SPECS, getModelSpec, type ModelSpec } from "@/shared/constants/modelSpecs"; import { getSyncedCapability } from "@/lib/modelsDevSync"; -const TOOL_CALLING_UNSUPPORTED_PATTERNS = ["gpt-oss-120b", "deepseek-reasoner"]; +const TOOL_CALLING_UNSUPPORTED_PATTERNS: string[] = []; const REASONING_UNSUPPORTED_PATTERNS = [ "antigravity/claude-sonnet-4-6", "antigravity/claude-sonnet-4-5", diff --git a/tests/unit/db-encryption.test.ts b/tests/unit/db-encryption.test.ts index 97b290f241..092743358f 100644 --- a/tests/unit/db-encryption.test.ts +++ b/tests/unit/db-encryption.test.ts @@ -66,7 +66,7 @@ test("connection field helpers encrypt and decrypt all supported credential fiel assert.deepEqual(decrypted, connection); }); -test("decrypt returns the original ciphertext when the value is malformed or the key is wrong", async () => { +test("decrypt returns null when the value is malformed or the key is wrong", async () => { process.env.STORAGE_ENCRYPTION_KEY = "task-304-secret-c"; const firstModule = await importFresh("src/lib/db/encryption.ts"); const encrypted = firstModule.encrypt("top-secret"); @@ -74,6 +74,8 @@ test("decrypt returns the original ciphertext when the value is malformed or the process.env.STORAGE_ENCRYPTION_KEY = "task-304-secret-d"; const secondModule = await importFresh("src/lib/db/encryption.ts"); - assert.equal(secondModule.decrypt(encrypted), encrypted); - assert.equal(secondModule.decrypt("enc:v1:not-valid"), "enc:v1:not-valid"); + // When decryption fails with wrong key, return null (not encrypted ciphertext) + // This prevents sending encrypted tokens to APIs + assert.equal(secondModule.decrypt(encrypted), null); + assert.equal(secondModule.decrypt("enc:v1:not-valid"), null); }); diff --git a/tests/unit/db/encryption-error-handling.test.mjs b/tests/unit/db/encryption-error-handling.test.mjs new file mode 100644 index 0000000000..e40e531ed7 --- /dev/null +++ b/tests/unit/db/encryption-error-handling.test.mjs @@ -0,0 +1,34 @@ +import { test } from "node:test"; +import assert from "node:assert"; +import { decrypt } from "../../../src/lib/db/encryption.ts"; + +test("decrypt() with invalid auth tag should not crash and return ciphertext", () => { + const invalidCiphertext = "enc:v1:0000:0000:0000"; + const result = decrypt(invalidCiphertext); + + assert.strictEqual(result, invalidCiphertext, "Should return ciphertext unchanged on error"); + assert.strictEqual(typeof result, "string", "Result should be a string"); +}); + +test("decrypt() with malformed ciphertext should not crash", () => { + const malformed = "enc:v1:invalid"; + const result = decrypt(malformed); + + assert.strictEqual(result, malformed, "Should return malformed ciphertext unchanged"); +}); + +test("decrypt() with null should return null", () => { + const result = decrypt(null); + assert.strictEqual(result, null, "Should return null for null input"); +}); + +test("decrypt() with undefined should return undefined", () => { + const result = decrypt(undefined); + assert.strictEqual(result, undefined, "Should return undefined for undefined input"); +}); + +test("decrypt() with non-encrypted string should return as-is", () => { + const plaintext = "this-is-not-encrypted"; + const result = decrypt(plaintext); + assert.strictEqual(result, plaintext, "Should return plaintext unchanged"); +}); diff --git a/tests/unit/model-capabilities-registry.test.ts b/tests/unit/model-capabilities-registry.test.ts index d862cc54bc..1dbc1bd240 100644 --- a/tests/unit/model-capabilities-registry.test.ts +++ b/tests/unit/model-capabilities-registry.test.ts @@ -103,3 +103,20 @@ test("canonical model capability resolver merges models.dev data and keeps stati 32768 ); }); + +test("GPT OSS and DeepSeek Reasoner models support tool calling", () => { + // GPT OSS models should not be blocked by the heuristic + assert.equal(modelCapabilities.supportsToolCalling("nvidia/gpt-oss-120b"), true); + assert.equal(modelCapabilities.supportsToolCalling("gpt-oss-120b"), true); + assert.equal(modelCapabilities.supportsToolCalling("openai/gpt-oss-20b"), true); + + // DeepSeek Reasoner supports tool calling + assert.equal(modelCapabilities.supportsToolCalling("deepseek-reasoner"), true); + assert.equal(modelCapabilities.supportsToolCalling("deepseek/deepseek-r1"), true); + + // Full capability resolution + const gptOss = modelCapabilities.getResolvedModelCapabilities("nvidia/gpt-oss-120b"); + assert.equal(gptOss.toolCalling, true); + const deepseek = modelCapabilities.getResolvedModelCapabilities("deepseek/deepseek-reasoner"); + assert.equal(deepseek.toolCalling, true); +}); diff --git a/tests/unit/services-branch-hardening.test.ts b/tests/unit/services-branch-hardening.test.ts index 16467867d4..6adef33e1f 100644 --- a/tests/unit/services-branch-hardening.test.ts +++ b/tests/unit/services-branch-hardening.test.ts @@ -79,8 +79,8 @@ test("model capability helpers cover denylist, empty input and default-safe path assert.equal(modelCapabilities.supportsReasoning("missing-provider/tool"), true); assert.equal(modelCapabilities.supportsToolCalling(""), false); - assert.equal(modelCapabilities.supportsToolCalling("openai/gpt-oss-120b"), false); - assert.equal(modelCapabilities.supportsToolCalling("deepseek-reasoner"), false); + assert.equal(modelCapabilities.supportsToolCalling("openai/gpt-oss-120b"), true); + assert.equal(modelCapabilities.supportsToolCalling("deepseek-reasoner"), true); assert.equal( modelCapabilities.supportsToolCalling("openai/nonexistent-default-safe-model"), true