shitton
This commit is contained in:
@@ -28,13 +28,8 @@
|
|||||||
"@types/fluent-ffmpeg": "^2.1.28",
|
"@types/fluent-ffmpeg": "^2.1.28",
|
||||||
"@types/node": "^25.6.1",
|
"@types/node": "^25.6.1",
|
||||||
"@types/qrcode": "^1.5.6",
|
"@types/qrcode": "^1.5.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.59.2",
|
"@typescript/native-preview": "^7.0.0-beta",
|
||||||
"@typescript-eslint/parser": "^8.59.2",
|
|
||||||
"drizzle-kit": "^0.31.10",
|
"drizzle-kit": "^0.31.10",
|
||||||
"eslint": "^10.3.0",
|
|
||||||
"tsx": "^4.21.0",
|
|
||||||
"typescript": "^6.0.3",
|
|
||||||
"typescript-eslint": "^8.59.2",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -99,30 +94,8 @@
|
|||||||
|
|
||||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
|
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
|
||||||
|
|
||||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
|
|
||||||
|
|
||||||
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
|
|
||||||
|
|
||||||
"@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="],
|
|
||||||
|
|
||||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.5.5", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w=="],
|
|
||||||
|
|
||||||
"@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="],
|
|
||||||
|
|
||||||
"@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="],
|
|
||||||
|
|
||||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.1", "", { "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" } }, "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ=="],
|
|
||||||
|
|
||||||
"@google/genai": ["@google/genai@2.0.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-6XpO+YbGutXkm5QgR7NZktISxSz0dw3pSs9NtCUQwvhJc1eyA3KhdKhE/0Uaxp3a6eul3LC0SKau1bXymjOKUg=="],
|
"@google/genai": ["@google/genai@2.0.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-6XpO+YbGutXkm5QgR7NZktISxSz0dw3pSs9NtCUQwvhJc1eyA3KhdKhE/0Uaxp3a6eul3LC0SKau1bXymjOKUg=="],
|
||||||
|
|
||||||
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
|
||||||
|
|
||||||
"@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="],
|
|
||||||
|
|
||||||
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
|
|
||||||
|
|
||||||
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
|
||||||
|
|
||||||
"@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="],
|
"@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="],
|
||||||
|
|
||||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
|
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
|
||||||
@@ -253,14 +226,8 @@
|
|||||||
|
|
||||||
"@types/bun": ["@types/bun@1.3.13", "", { "dependencies": { "bun-types": "1.3.13" } }, "sha512-9fqXWk5YIHGGnUau9TEi+qdlTYDAnOj+xLCmSTwXfAIqXr2x4tytJb43E9uCvt09zJURKXwAtkoH4nLQfzeTXw=="],
|
"@types/bun": ["@types/bun@1.3.13", "", { "dependencies": { "bun-types": "1.3.13" } }, "sha512-9fqXWk5YIHGGnUau9TEi+qdlTYDAnOj+xLCmSTwXfAIqXr2x4tytJb43E9uCvt09zJURKXwAtkoH4nLQfzeTXw=="],
|
||||||
|
|
||||||
"@types/esrecurse": ["@types/esrecurse@4.3.1", "", {}, "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw=="],
|
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
|
||||||
|
|
||||||
"@types/fluent-ffmpeg": ["@types/fluent-ffmpeg@2.1.28", "", { "dependencies": { "@types/node": "*" } }, "sha512-5ovxsDwBcPfJ+eYs1I/ZpcYCnkce7pvH9AHSvrZllAp1ZPpTRDZAFjF3TRFbukxSgIYTTNYePbS0rKUmaxVbXw=="],
|
"@types/fluent-ffmpeg": ["@types/fluent-ffmpeg@2.1.28", "", { "dependencies": { "@types/node": "*" } }, "sha512-5ovxsDwBcPfJ+eYs1I/ZpcYCnkce7pvH9AHSvrZllAp1ZPpTRDZAFjF3TRFbukxSgIYTTNYePbS0rKUmaxVbXw=="],
|
||||||
|
|
||||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
|
||||||
|
|
||||||
"@types/node": ["@types/node@25.6.1", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-coJCN8O1q4AGyyqCAUSP06P+SrMTu18BkEj3NVAK07q6QUneD2wzj3CLv9+yP+BMeZQlMvneXqqvDe3w+xcq7g=="],
|
"@types/node": ["@types/node@25.6.1", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-coJCN8O1q4AGyyqCAUSP06P+SrMTu18BkEj3NVAK07q6QUneD2wzj3CLv9+yP+BMeZQlMvneXqqvDe3w+xcq7g=="],
|
||||||
|
|
||||||
"@types/qrcode": ["@types/qrcode@1.5.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw=="],
|
"@types/qrcode": ["@types/qrcode@1.5.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw=="],
|
||||||
@@ -269,34 +236,24 @@
|
|||||||
|
|
||||||
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
|
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.59.2", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.59.2", "@typescript-eslint/type-utils": "8.59.2", "@typescript-eslint/utils": "8.59.2", "@typescript-eslint/visitor-keys": "8.59.2", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.59.2", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-j/bwmkBvHUtPNxzuWe5z6BEk3q54YRyGlBXkSsmfoih7zNrBvl5A9A98anlp/7JbyZcWIJ8KXo/3Tq/DjFLtuQ=="],
|
"@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260421.2", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260421.2", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260421.2", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260421.2", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260421.2", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260421.2", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260421.2", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260421.2" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-CmajHI25HpVWE9R1XFoxr+cphJPxoYD3eFioQtAvXYkMFKnLdICMS9pXre9Pybizb75ejRxjKD5/CVG055rEIg=="],
|
||||||
|
|
||||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.59.2", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.59.2", "@typescript-eslint/types": "8.59.2", "@typescript-eslint/typescript-estree": "8.59.2", "@typescript-eslint/visitor-keys": "8.59.2", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-plR3pp6D+SSUn1HM7xvSkx12/DhoHInI2YF35KAcVFNZvlC0gtrWqx7Qq1oH2Ssgi0vlFRCTbP+DZc7B9+TtsQ=="],
|
"@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260421.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-fHv1r3ZmVo6zxuAIFmuX3w9QxbcauoG0SsWhmDwm6VmRubLlOJIcmTtlmV3JAb9oOnq8LuzZljzT7Q39fSMQDw=="],
|
||||||
|
|
||||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.59.2", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.59.2", "@typescript-eslint/types": "^8.59.2", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-+2hqvEkeyf/0FBor67duF0Ll7Ot8jyKzDQOSrxazF/danillRq2DwR9dLptsXpoZQqxE1UisSmoZewrlPas9Vw=="],
|
"@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260421.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-KWTR6xbW9t+JS7D5DQIzo75pqVXVWUxF9PMv/+S6xsnOjCVd6g0ixHcFpFMJMKSUQpGPr8Z5f7b8ks6LHW01jg=="],
|
||||||
|
|
||||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.59.2", "", { "dependencies": { "@typescript-eslint/types": "8.59.2", "@typescript-eslint/visitor-keys": "8.59.2" } }, "sha512-JzfyEpEtOU89CcFSwyNS3mu4MLvLSXqnmX05+aKBDM+TdR5jzcGOEBwxwGNxrEQ7p/z6kK2WyioCGBf2zZBnvg=="],
|
"@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260421.2", "", { "os": "linux", "cpu": "arm" }, "sha512-BWLQO3nemLDSV5PoE5GPHe1dU9Dth77Kv8/cle9Ujcp4LhPo0KincdPqFH/qKeU/xvW25mgFueflZ1nc4rKuww=="],
|
||||||
|
|
||||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.59.2", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-BKK4alN7oi4C/zv4VqHQ+uRU+lTa6JGIZ7s1juw7b3RHo9OfKB+bKX3u0iVZetdsUCBBkSbdWbarJbmN0fTeSw=="],
|
"@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260421.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-VLMEuml3BhUb+jaL0TXQ4xvVODxJF+RhkI+tBWvlynsJI4khTXEiwWh+wPOJrsfBRYFRMXEu28Odl/HXkYze8w=="],
|
||||||
|
|
||||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.59.2", "", { "dependencies": { "@typescript-eslint/types": "8.59.2", "@typescript-eslint/typescript-estree": "8.59.2", "@typescript-eslint/utils": "8.59.2", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-nhqaj1nmTdVVl/BP5omXNRGO38jn5iosis2vbdmupF2txCf8ylWT8lx+JlvMYYVqzGVKtjojUFoQ3JRWK+mfzQ=="],
|
"@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260421.2", "", { "os": "linux", "cpu": "x64" }, "sha512-qUrJWTB5/wv4wnRG0TRXElAxc2kykNiRNyEIEqBbLmzDlrcvAW7RRy8MXoY1ZyTiKGMu14itZ3x9oW6+blFpRw=="],
|
||||||
|
|
||||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.59.2", "", {}, "sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q=="],
|
"@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260421.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Rc6NsWlZmCs5YUKVzKgwoBOoRUGsPzct4BDMRX0csD1devLBBc4AbUXWKsJRbpwIAnqMO1ld4sNHEb+wXgfNHQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.59.2", "", { "dependencies": { "@typescript-eslint/project-service": "8.59.2", "@typescript-eslint/tsconfig-utils": "8.59.2", "@typescript-eslint/types": "8.59.2", "@typescript-eslint/visitor-keys": "8.59.2", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg=="],
|
"@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260421.2", "", { "os": "win32", "cpu": "x64" }, "sha512-GQv1+dya1t6EqF2Cpsb+xoozovdX10JUSf6Kl/8xNkTapzmlHd+uMr+8ku3jIASTxoRGn0Mklgjj3MDKrOTuLg=="],
|
||||||
|
|
||||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.59.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.59.2", "@typescript-eslint/types": "8.59.2", "@typescript-eslint/typescript-estree": "8.59.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-Juw3EinkXqjaffxz6roowvV7GZT/kET5vSKKZT6upl5TXdWkLkYmNPXwDDL2Vkt2DPn0nODIS4egC/0AGxKo/Q=="],
|
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.59.2", "", { "dependencies": { "@typescript-eslint/types": "8.59.2", "eslint-visitor-keys": "^5.0.0" } }, "sha512-NwjLUnGy8/Zfx23fl50tRC8rYaYnM52xNRYFAXvmiil9yh1+K6aRVQMnzW6gQB/1DLgWt977lYQn7C+wtgXZiA=="],
|
|
||||||
|
|
||||||
"acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
|
|
||||||
|
|
||||||
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
|
|
||||||
|
|
||||||
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
||||||
|
|
||||||
"ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
|
|
||||||
|
|
||||||
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||||
|
|
||||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||||
@@ -307,13 +264,13 @@
|
|||||||
|
|
||||||
"axios": ["axios@1.16.0", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" } }, "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w=="],
|
"axios": ["axios@1.16.0", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" } }, "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w=="],
|
||||||
|
|
||||||
"balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||||
|
|
||||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||||
|
|
||||||
"bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
|
"bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
|
||||||
|
|
||||||
"brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
|
"brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
"buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
|
"buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
|
||||||
|
|
||||||
@@ -341,8 +298,6 @@
|
|||||||
|
|
||||||
"decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="],
|
"decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="],
|
||||||
|
|
||||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
|
||||||
|
|
||||||
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="],
|
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="],
|
||||||
|
|
||||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||||
@@ -373,43 +328,11 @@
|
|||||||
|
|
||||||
"esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
|
"esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
|
||||||
|
|
||||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
|
||||||
|
|
||||||
"eslint": ["eslint@10.3.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.5.5", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-XbEXaRva5cF0ZQB8w6MluHA0kZZfV2DuCMJ3ozyEOHLwDpZX2Lmm/7Pp0xdJmI0GL1W05VH5VwIFHEm1Vcw2gw=="],
|
|
||||||
|
|
||||||
"eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="],
|
|
||||||
|
|
||||||
"eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
|
|
||||||
|
|
||||||
"espree": ["espree@11.2.0", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw=="],
|
|
||||||
|
|
||||||
"esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
|
|
||||||
|
|
||||||
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
|
|
||||||
|
|
||||||
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
|
|
||||||
|
|
||||||
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
|
||||||
|
|
||||||
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
|
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
|
||||||
|
|
||||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
|
||||||
|
|
||||||
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
|
|
||||||
|
|
||||||
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
|
|
||||||
|
|
||||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
|
||||||
|
|
||||||
"fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
|
"fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
|
||||||
|
|
||||||
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
|
"find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
|
||||||
|
|
||||||
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
|
|
||||||
|
|
||||||
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
|
|
||||||
|
|
||||||
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
|
|
||||||
|
|
||||||
"fluent-ffmpeg": ["fluent-ffmpeg@2.1.3", "", { "dependencies": { "async": "^0.2.9", "which": "^1.1.1" } }, "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q=="],
|
"fluent-ffmpeg": ["fluent-ffmpeg@2.1.3", "", { "dependencies": { "async": "^0.2.9", "which": "^1.1.1" } }, "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q=="],
|
||||||
|
|
||||||
@@ -437,12 +360,10 @@
|
|||||||
|
|
||||||
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||||
|
|
||||||
"get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="],
|
"get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="],
|
||||||
|
|
||||||
"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=="],
|
"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=="],
|
||||||
|
|
||||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
|
||||||
|
|
||||||
"google-auth-library": ["google-auth-library@10.5.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.0.0", "gcp-metadata": "^8.0.0", "google-logging-utils": "^1.0.0", "gtoken": "^8.0.0", "jws": "^4.0.0" } }, "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w=="],
|
"google-auth-library": ["google-auth-library@10.5.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.0.0", "gcp-metadata": "^8.0.0", "google-logging-utils": "^1.0.0", "gtoken": "^8.0.0", "jws": "^4.0.0" } }, "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w=="],
|
||||||
|
|
||||||
"google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="],
|
"google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="],
|
||||||
@@ -461,16 +382,8 @@
|
|||||||
|
|
||||||
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
|
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
|
||||||
|
|
||||||
"ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
|
||||||
|
|
||||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
|
||||||
|
|
||||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
|
||||||
|
|
||||||
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||||
|
|
||||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
|
||||||
|
|
||||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||||
|
|
||||||
"jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
"jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||||
@@ -479,25 +392,15 @@
|
|||||||
|
|
||||||
"json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],
|
"json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],
|
||||||
|
|
||||||
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
|
|
||||||
|
|
||||||
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
|
||||||
|
|
||||||
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
|
|
||||||
|
|
||||||
"jsonfile": ["jsonfile@5.0.0", "", { "dependencies": { "universalify": "^0.1.2" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w=="],
|
"jsonfile": ["jsonfile@5.0.0", "", { "dependencies": { "universalify": "^0.1.2" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w=="],
|
||||||
|
|
||||||
"jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="],
|
"jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="],
|
||||||
|
|
||||||
"jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
|
"jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
|
||||||
|
|
||||||
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
|
|
||||||
|
|
||||||
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
|
||||||
|
|
||||||
"libsql": ["libsql@0.5.29", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.5.29", "@libsql/darwin-x64": "0.5.29", "@libsql/linux-arm-gnueabihf": "0.5.29", "@libsql/linux-arm-musleabihf": "0.5.29", "@libsql/linux-arm64-gnu": "0.5.29", "@libsql/linux-arm64-musl": "0.5.29", "@libsql/linux-x64-gnu": "0.5.29", "@libsql/linux-x64-musl": "0.5.29", "@libsql/win32-x64-msvc": "0.5.29" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "arm", "x64", "arm64", ] }, "sha512-8lMP8iMgiBzzoNbAPQ59qdVcj6UaE/Vnm+fiwX4doX4Narook0a4GPKWBEv+CR8a1OwbfkgL18uBfBjWdF0Fzg=="],
|
"libsql": ["libsql@0.5.29", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.5.29", "@libsql/darwin-x64": "0.5.29", "@libsql/linux-arm-gnueabihf": "0.5.29", "@libsql/linux-arm-musleabihf": "0.5.29", "@libsql/linux-arm64-gnu": "0.5.29", "@libsql/linux-arm64-musl": "0.5.29", "@libsql/linux-x64-gnu": "0.5.29", "@libsql/linux-x64-musl": "0.5.29", "@libsql/win32-x64-msvc": "0.5.29" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "arm", "x64", "arm64", ] }, "sha512-8lMP8iMgiBzzoNbAPQ59qdVcj6UaE/Vnm+fiwX4doX4Narook0a4GPKWBEv+CR8a1OwbfkgL18uBfBjWdF0Fzg=="],
|
||||||
|
|
||||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
"locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
|
||||||
|
|
||||||
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
||||||
|
|
||||||
@@ -509,14 +412,12 @@
|
|||||||
|
|
||||||
"mime-types": ["mime-types@2.1.29", "", { "dependencies": { "mime-db": "1.46.0" } }, "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ=="],
|
"mime-types": ["mime-types@2.1.29", "", { "dependencies": { "mime-db": "1.46.0" } }, "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ=="],
|
||||||
|
|
||||||
"minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
|
"minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
||||||
|
|
||||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
|
||||||
|
|
||||||
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
|
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
|
||||||
|
|
||||||
"node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
|
"node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
|
||||||
@@ -525,11 +426,9 @@
|
|||||||
|
|
||||||
"openai": ["openai@6.37.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-0H5dEGFmmLv6KSd0W1w2nyL8WsLkX6yoLeQpU+dZAOuGcany5qkYQMmj35ZrKgb6yiyYqpUzFOpR8mZQkgqeEQ=="],
|
"openai": ["openai@6.37.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-0H5dEGFmmLv6KSd0W1w2nyL8WsLkX6yoLeQpU+dZAOuGcany5qkYQMmj35ZrKgb6yiyYqpUzFOpR8mZQkgqeEQ=="],
|
||||||
|
|
||||||
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
|
"p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
||||||
|
|
||||||
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
"p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
||||||
|
|
||||||
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
|
|
||||||
|
|
||||||
"p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="],
|
"p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="],
|
||||||
|
|
||||||
@@ -543,20 +442,14 @@
|
|||||||
|
|
||||||
"path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
"path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||||
|
|
||||||
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
|
||||||
|
|
||||||
"pngjs": ["pngjs@5.0.0", "", {}, "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="],
|
"pngjs": ["pngjs@5.0.0", "", {}, "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="],
|
||||||
|
|
||||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
|
||||||
|
|
||||||
"promise-limit": ["promise-limit@2.7.0", "", {}, "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="],
|
"promise-limit": ["promise-limit@2.7.0", "", {}, "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="],
|
||||||
|
|
||||||
"protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
|
"protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
|
||||||
|
|
||||||
"proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="],
|
"proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="],
|
||||||
|
|
||||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
|
||||||
|
|
||||||
"qrcode": ["qrcode@1.5.4", "", { "dependencies": { "dijkstrajs": "^1.0.1", "pngjs": "^5.0.0", "yargs": "^15.3.1" }, "bin": { "qrcode": "bin/qrcode" } }, "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg=="],
|
"qrcode": ["qrcode@1.5.4", "", { "dependencies": { "dijkstrajs": "^1.0.1", "pngjs": "^5.0.0", "yargs": "^15.3.1" }, "bin": { "qrcode": "bin/qrcode" } }, "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg=="],
|
||||||
|
|
||||||
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
|
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
|
||||||
@@ -597,10 +490,6 @@
|
|||||||
|
|
||||||
"systeminformation": ["systeminformation@5.31.6", "", { "os": "!aix", "bin": { "systeminformation": "lib/cli.js" } }, "sha512-Uv2b2uGGM6ns+26czgW2cYRabYdnswM0ddSOOlryHOaelzsmDSet1iM/NT7VOYxW8x/BW+HkY+b1Ve2pLTSGSA=="],
|
"systeminformation": ["systeminformation@5.31.6", "", { "os": "!aix", "bin": { "systeminformation": "lib/cli.js" } }, "sha512-Uv2b2uGGM6ns+26czgW2cYRabYdnswM0ddSOOlryHOaelzsmDSet1iM/NT7VOYxW8x/BW+HkY+b1Ve2pLTSGSA=="],
|
||||||
|
|
||||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
|
||||||
|
|
||||||
"ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="],
|
|
||||||
|
|
||||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="],
|
"tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="],
|
||||||
@@ -609,20 +498,12 @@
|
|||||||
|
|
||||||
"twemoji-parser": ["twemoji-parser@14.0.0", "", {}, "sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA=="],
|
"twemoji-parser": ["twemoji-parser@14.0.0", "", {}, "sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA=="],
|
||||||
|
|
||||||
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
|
|
||||||
|
|
||||||
"typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],
|
|
||||||
|
|
||||||
"typescript-eslint": ["typescript-eslint@8.59.2", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.59.2", "@typescript-eslint/parser": "8.59.2", "@typescript-eslint/typescript-estree": "8.59.2", "@typescript-eslint/utils": "8.59.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-pJw051uomb3ZeCzGTpRb8RbEqB5Y4WWet8gl/GcTlU35BSx0PVdZ86/bqkQCyKKuraVQEK7r6kBHQXF+fBhkoQ=="],
|
|
||||||
|
|
||||||
"typescript-telegram-bot-api": ["typescript-telegram-bot-api@0.16.0", "", { "dependencies": { "axios": "^1.7.7", "form-data": "^4.0.1" } }, "sha512-NaAjXucQiZ87U8La/IMaWDOghbMlJzfMbU4rG8ppFpgPOvEwat/zfN5BM+J2QDvKVGN87qJ+1nELnkm3ctSLnQ=="],
|
"typescript-telegram-bot-api": ["typescript-telegram-bot-api@0.16.0", "", { "dependencies": { "axios": "^1.7.7", "form-data": "^4.0.1" } }, "sha512-NaAjXucQiZ87U8La/IMaWDOghbMlJzfMbU4rG8ppFpgPOvEwat/zfN5BM+J2QDvKVGN87qJ+1nELnkm3ctSLnQ=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
"undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||||
|
|
||||||
"universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="],
|
"universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="],
|
||||||
|
|
||||||
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
|
||||||
|
|
||||||
"web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
|
"web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
|
||||||
|
|
||||||
"whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="],
|
"whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="],
|
||||||
@@ -631,8 +512,6 @@
|
|||||||
|
|
||||||
"which-module": ["which-module@2.0.1", "", {}, "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="],
|
"which-module": ["which-module@2.0.1", "", {}, "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="],
|
||||||
|
|
||||||
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
|
||||||
|
|
||||||
"wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
|
"wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
|
||||||
|
|
||||||
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||||
@@ -645,18 +524,12 @@
|
|||||||
|
|
||||||
"yargs-parser": ["yargs-parser@18.1.3", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ=="],
|
"yargs-parser": ["yargs-parser@18.1.3", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ=="],
|
||||||
|
|
||||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
|
||||||
|
|
||||||
"zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
"zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
||||||
|
|
||||||
"zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
|
"zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
|
||||||
|
|
||||||
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
|
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
|
||||||
|
|
||||||
"@esbuild-kit/esm-loader/get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="],
|
|
||||||
|
|
||||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
|
||||||
|
|
||||||
"@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
"@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||||
|
|
||||||
"@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
|
"@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
|
||||||
@@ -673,18 +546,12 @@
|
|||||||
|
|
||||||
"@types/ws/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
"@types/ws/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
|
||||||
|
|
||||||
"bun-types/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="],
|
"bun-types/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="],
|
||||||
|
|
||||||
"cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
"cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
"eslint/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
|
||||||
|
|
||||||
"fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
|
"fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
|
||||||
|
|
||||||
"glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
|
||||||
|
|
||||||
"libsql/detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="],
|
"libsql/detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="],
|
||||||
|
|
||||||
"protobufjs/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="],
|
"protobufjs/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="],
|
||||||
@@ -695,7 +562,7 @@
|
|||||||
|
|
||||||
"tsx/esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="],
|
"tsx/esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="],
|
||||||
|
|
||||||
"yargs/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
|
"tsx/get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="],
|
||||||
|
|
||||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
|
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
|
||||||
|
|
||||||
@@ -753,8 +620,6 @@
|
|||||||
|
|
||||||
"@types/ws/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
"@types/ws/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||||
|
|
||||||
"glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
|
||||||
|
|
||||||
"protobufjs/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
"protobufjs/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||||
|
|
||||||
"tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="],
|
"tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="],
|
||||||
@@ -808,13 +673,5 @@
|
|||||||
"tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="],
|
"tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="],
|
||||||
|
|
||||||
"tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="],
|
"tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="],
|
||||||
|
|
||||||
"yargs/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
|
|
||||||
|
|
||||||
"glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
|
||||||
|
|
||||||
"yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
|
||||||
|
|
||||||
"yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+326
-1342
File diff suppressed because it is too large
Load Diff
+4
-11
@@ -2,20 +2,18 @@
|
|||||||
"name": "tg-chat-bot",
|
"name": "tg-chat-bot",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc -p tsconfig.build.json",
|
"build": "tsgo -p tsconfig.json",
|
||||||
"lint": "eslint .",
|
|
||||||
"start": "node dist/index.js",
|
"start": "node dist/index.js",
|
||||||
"bun:start": "bun run dist/index.js"
|
"bun:start": "bun run src/index.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@google/genai": "^2.0.0",
|
"@google/genai": "^2.0.0",
|
||||||
"@mistralai/mistralai": "^2.2.1",
|
"@mistralai/mistralai": "^2.2.1",
|
||||||
"openai": "^6.37.0",
|
"openai": "^6.37.0",
|
||||||
"ollama": "^0.6.3",
|
"ollama": "^0.6.3",
|
||||||
|
|
||||||
"typescript-telegram-bot-api": "^0.16.0",
|
"typescript-telegram-bot-api": "^0.16.0",
|
||||||
|
|
||||||
"@libsql/client": "^0.17.3",
|
"@libsql/client": "^0.17.3",
|
||||||
"@napi-rs/canvas": "^1.0.0",
|
"@napi-rs/canvas": "^1.0.0",
|
||||||
"axios": "^1.16.0",
|
"axios": "^1.16.0",
|
||||||
@@ -34,12 +32,7 @@
|
|||||||
"@types/fluent-ffmpeg": "^2.1.28",
|
"@types/fluent-ffmpeg": "^2.1.28",
|
||||||
"@types/node": "^25.6.1",
|
"@types/node": "^25.6.1",
|
||||||
"@types/qrcode": "^1.5.6",
|
"@types/qrcode": "^1.5.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.59.2",
|
|
||||||
"@typescript-eslint/parser": "^8.59.2",
|
|
||||||
"drizzle-kit": "^0.31.10",
|
"drizzle-kit": "^0.31.10",
|
||||||
"eslint": "^10.3.0",
|
"@typescript/native-preview": "^7.0.0-beta"
|
||||||
"tsx": "^4.21.0",
|
|
||||||
"typescript": "^6.0.3",
|
|
||||||
"typescript-eslint": "^8.59.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,283 @@
|
|||||||
|
import {Message} from "typescript-telegram-bot-api";
|
||||||
|
|
||||||
|
export type AiRunnerLogLevel = "trace" | "debug" | "info" | "success" | "warn" | "error";
|
||||||
|
|
||||||
|
export type AiRunnerLogDetails = Record<string, unknown>;
|
||||||
|
|
||||||
|
export type AiLogToolCallLike = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
argumentsText: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AI_RUNNER_LOG_PREFIX = "unified-ai-runner";
|
||||||
|
const AI_RUNNER_LOG_MAX_STRING = 600;
|
||||||
|
const AI_RUNNER_LOG_MAX_ARRAY = 8;
|
||||||
|
|
||||||
|
const LOG_LEVEL_WEIGHT: Record<AiRunnerLogLevel, number> = {
|
||||||
|
trace: 10,
|
||||||
|
debug: 20,
|
||||||
|
info: 30,
|
||||||
|
success: 30,
|
||||||
|
warn: 40,
|
||||||
|
error: 50,
|
||||||
|
};
|
||||||
|
|
||||||
|
const AI_RUNNER_LOG_COLORS: Record<AiRunnerLogLevel | "reset" | "bold" | "dim" | "label" | "key" | "value", string> = {
|
||||||
|
reset: "\x1b[0m",
|
||||||
|
bold: "\x1b[1m",
|
||||||
|
dim: "\x1b[2m",
|
||||||
|
trace: "\x1b[90m",
|
||||||
|
debug: "\x1b[90m",
|
||||||
|
info: "\x1b[36m",
|
||||||
|
success: "\x1b[32m",
|
||||||
|
warn: "\x1b[33m",
|
||||||
|
error: "\x1b[31m",
|
||||||
|
label: "\x1b[35m",
|
||||||
|
key: "\x1b[94m",
|
||||||
|
value: "\x1b[97m",
|
||||||
|
};
|
||||||
|
|
||||||
|
function envBool(name: string, defaultValue: boolean): boolean {
|
||||||
|
const value = process.env[name];
|
||||||
|
if (value === undefined) return defaultValue;
|
||||||
|
return !["0", "false", "no", "off"].includes(value.trim().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
function aiRunnerLogsEnabled(): boolean {
|
||||||
|
return envBool("AI_RUNNER_LOGS", true) && envBool("AI_LOG_ENABLED", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function aiRunnerColorsEnabled(): boolean {
|
||||||
|
return envBool("AI_RUNNER_LOG_COLORS", true) && !process.env.NO_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configuredMinLevel(): AiRunnerLogLevel {
|
||||||
|
const raw = process.env.AI_LOG_LEVEL?.trim().toLowerCase();
|
||||||
|
if (raw && raw in LOG_LEVEL_WEIGHT) return raw as AiRunnerLogLevel;
|
||||||
|
return "debug";
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldWriteLevel(level: AiRunnerLogLevel): boolean {
|
||||||
|
return LOG_LEVEL_WEIGHT[level] >= LOG_LEVEL_WEIGHT[configuredMinLevel()];
|
||||||
|
}
|
||||||
|
|
||||||
|
function paintAiLog(value: string, color: keyof typeof AI_RUNNER_LOG_COLORS): string {
|
||||||
|
if (!aiRunnerColorsEnabled()) return value;
|
||||||
|
return `${AI_RUNNER_LOG_COLORS[color]}${value}${AI_RUNNER_LOG_COLORS.reset}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function truncateAiLogString(value: string, max = AI_RUNNER_LOG_MAX_STRING): string {
|
||||||
|
if (value.length <= max) return value;
|
||||||
|
return `${value.slice(0, max)}… (+${value.length - max} chars)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeJsonParseObject(value?: string): Record<string, unknown> {
|
||||||
|
if (!value?.trim()) return {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed: unknown = JSON.parse(value);
|
||||||
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
||||||
|
? parsed as Record<string, unknown>
|
||||||
|
: {};
|
||||||
|
} catch {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSecretKey(keyPath: string): boolean {
|
||||||
|
const normalized = keyPath.toLowerCase();
|
||||||
|
return normalized.includes("token")
|
||||||
|
|| normalized.includes("secret")
|
||||||
|
|| normalized.includes("apikey")
|
||||||
|
|| normalized.includes("api_key")
|
||||||
|
|| normalized.includes("authorization")
|
||||||
|
|| normalized.endsWith(".key")
|
||||||
|
|| normalized === "key";
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPromptKey(keyPath: string): boolean {
|
||||||
|
const normalized = keyPath.toLowerCase();
|
||||||
|
return normalized.includes("prompt") || normalized.includes("systemprompt");
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTextPreviewKey(keyPath: string): boolean {
|
||||||
|
const normalized = keyPath.toLowerCase();
|
||||||
|
return normalized.includes("content")
|
||||||
|
|| normalized.includes("message")
|
||||||
|
|| normalized.includes("text")
|
||||||
|
|| normalized.includes("preview")
|
||||||
|
|| normalized.includes("input")
|
||||||
|
|| normalized.includes("output");
|
||||||
|
}
|
||||||
|
|
||||||
|
function isToolArgsKey(keyPath: string): boolean {
|
||||||
|
const normalized = keyPath.toLowerCase();
|
||||||
|
return normalized.endsWith("args")
|
||||||
|
|| normalized.endsWith("arguments")
|
||||||
|
|| normalized.includes("toolargs")
|
||||||
|
|| normalized.includes("tool_args");
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDaoKey(keyPath: string): boolean {
|
||||||
|
const normalized = keyPath.toLowerCase();
|
||||||
|
return normalized.includes("dao")
|
||||||
|
|| normalized.includes("database")
|
||||||
|
|| normalized.includes("db.")
|
||||||
|
|| normalized.includes("sql")
|
||||||
|
|| normalized.includes("chunk");
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldRedactKey(keyPath: string): boolean {
|
||||||
|
if (isSecretKey(keyPath)) return true;
|
||||||
|
if (isPromptKey(keyPath) && !envBool("AI_LOG_PROMPTS", false)) return true;
|
||||||
|
if (isToolArgsKey(keyPath) && !envBool("AI_LOG_TOOL_ARGS", false)) return true;
|
||||||
|
if (isDaoKey(keyPath) && !envBool("AI_LOG_DAO", false)) return true;
|
||||||
|
if (isTextPreviewKey(keyPath) && !envBool("AI_LOG_TEXT_PREVIEW", false)) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function primitiveToLogValue(value: unknown): unknown {
|
||||||
|
if (value instanceof Error) {
|
||||||
|
return {
|
||||||
|
name: value.name,
|
||||||
|
message: value.message,
|
||||||
|
stack: value.stack?.split("\n").slice(0, 6).join("\n"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === "string") return truncateAiLogString(value);
|
||||||
|
if (typeof value === "number" || typeof value === "boolean" || value === null || value === undefined) return value;
|
||||||
|
if (typeof value === "bigint") return value.toString();
|
||||||
|
if (typeof value === "function") return `[Function ${value.name || "anonymous"}]`;
|
||||||
|
if (Buffer.isBuffer(value)) return `<Buffer ${(value as {length: number}).length} bytes>`;
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function flattenAiLogDetails(
|
||||||
|
value: unknown,
|
||||||
|
keyPath = "",
|
||||||
|
depth = 0,
|
||||||
|
seen = new WeakSet<object>(),
|
||||||
|
): Record<string, unknown> {
|
||||||
|
if (keyPath && shouldRedactKey(keyPath)) {
|
||||||
|
return {[keyPath]: "<redacted>"};
|
||||||
|
}
|
||||||
|
|
||||||
|
const primitive = primitiveToLogValue(value);
|
||||||
|
if (primitive !== undefined || value === undefined) {
|
||||||
|
return keyPath ? {[keyPath]: primitive} : {value: primitive};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value !== "object" || value === null) {
|
||||||
|
return keyPath ? {[keyPath]: String(value)} : {value: String(value)};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seen.has(value)) {
|
||||||
|
return keyPath ? {[keyPath]: "[Circular]"} : {value: "[Circular]"};
|
||||||
|
}
|
||||||
|
seen.add(value);
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
if (depth >= 2) {
|
||||||
|
return keyPath ? {[keyPath]: `[Array ${value.length}]`} : {value: `[Array ${value.length}]`};
|
||||||
|
}
|
||||||
|
|
||||||
|
const entries: Record<string, unknown> = {};
|
||||||
|
value.slice(0, AI_RUNNER_LOG_MAX_ARRAY).forEach((item, index) => {
|
||||||
|
Object.assign(entries, flattenAiLogDetails(item, keyPath ? `${keyPath}.${index}` : String(index), depth + 1, seen));
|
||||||
|
});
|
||||||
|
if (value.length > AI_RUNNER_LOG_MAX_ARRAY) {
|
||||||
|
entries[keyPath ? `${keyPath}.__more` : "__more"] = value.length - AI_RUNNER_LOG_MAX_ARRAY;
|
||||||
|
}
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth >= 3) {
|
||||||
|
return keyPath ? {[keyPath]: "[Object]"} : {value: "[Object]"};
|
||||||
|
}
|
||||||
|
|
||||||
|
const entries: Record<string, unknown> = {};
|
||||||
|
for (const [key, raw] of Object.entries(value as Record<string, unknown>)) {
|
||||||
|
const childPath = keyPath ? `${keyPath}.${key}` : key;
|
||||||
|
|
||||||
|
if ((key.toLowerCase() === "data" || key.toLowerCase() === "image_url" || key.toLowerCase().endsWith("b64")) && typeof raw === "string") {
|
||||||
|
entries[childPath] = `<${raw.length} chars>`;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(entries, flattenAiLogDetails(raw, childPath, depth + 1, seen));
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function redactLogValue(value: unknown): Record<string, unknown> {
|
||||||
|
return flattenAiLogDetails(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatAiLogDetails(details?: AiRunnerLogDetails): string {
|
||||||
|
if (!details || !Object.keys(details).length) return "";
|
||||||
|
|
||||||
|
const flattened = flattenAiLogDetails(details);
|
||||||
|
const chunks = Object.entries(flattened).map(([key, value]) => {
|
||||||
|
const safeValue = typeof value === "string" ? value : JSON.stringify(value);
|
||||||
|
return `${paintAiLog(key, "key")}=${paintAiLog(safeValue ?? "undefined", "value")}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return ` ${chunks.join(" ")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function aiLog(level: AiRunnerLogLevel, event: string, details?: AiRunnerLogDetails): void {
|
||||||
|
if (!aiRunnerLogsEnabled() || !shouldWriteLevel(level)) return;
|
||||||
|
|
||||||
|
const timestamp = paintAiLog(new Date().toISOString(), "dim");
|
||||||
|
const prefix = paintAiLog(AI_RUNNER_LOG_PREFIX, "bold");
|
||||||
|
const levelText = paintAiLog(level.toUpperCase().padEnd(7), level);
|
||||||
|
const eventText = paintAiLog(event, "label");
|
||||||
|
const line = `${timestamp} ${prefix} ${levelText} ${eventText}${formatAiLogDetails(details)}`;
|
||||||
|
|
||||||
|
if (level === "error") {
|
||||||
|
console.error(line);
|
||||||
|
} else if (level === "warn") {
|
||||||
|
console.warn(line);
|
||||||
|
} else {
|
||||||
|
console.log(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function aiLogDuration(startedAt: number): string {
|
||||||
|
const ms = Date.now() - startedAt;
|
||||||
|
if (ms < 1000) return `${ms}ms`;
|
||||||
|
return `${(ms / 1000).toFixed(2)}s`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function aiLogToolCall(toolCall: AiLogToolCallLike): Record<string, unknown> {
|
||||||
|
return {
|
||||||
|
id: toolCall.id,
|
||||||
|
name: toolCall.name,
|
||||||
|
arguments: safeJsonParseObject(toolCall.argumentsText),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function aiLogMessageIdentity(msg: Message | undefined): Record<string, unknown> | undefined {
|
||||||
|
if (!msg) return undefined;
|
||||||
|
return {
|
||||||
|
chatId: msg.chat?.id,
|
||||||
|
chatType: msg.chat?.type,
|
||||||
|
messageId: msg.message_id,
|
||||||
|
fromId: msg.from?.id,
|
||||||
|
username: msg.from?.username,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function aiLogProviderTarget(target: {provider: string; purpose?: string; model?: string; baseUrl?: string; apiKey?: string} | undefined): Record<string, unknown> | undefined {
|
||||||
|
if (!target) return undefined;
|
||||||
|
return {
|
||||||
|
provider: target.provider,
|
||||||
|
purpose: target.purpose,
|
||||||
|
model: target.model,
|
||||||
|
baseUrl: target.baseUrl,
|
||||||
|
apiKey: target.apiKey,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -207,7 +207,7 @@ export function createMistralClient(target: AiRuntimeTarget): Mistral {
|
|||||||
|
|
||||||
export function createOllamaClient(target: AiRuntimeTarget): Ollama {
|
export function createOllamaClient(target: AiRuntimeTarget): Ollama {
|
||||||
return new Ollama({
|
return new Ollama({
|
||||||
host: target.baseUrl?.endsWith(":11434") ? target.baseUrl : target.baseUrl + ":11434",
|
host: target.baseUrl,
|
||||||
headers: target.apiKey ? {"Authorization": `Bearer ${target.apiKey}`} : undefined,
|
headers: target.apiKey ? {"Authorization": `Bearer ${target.apiKey}`} : undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,26 +65,5 @@ export function asMistralChatMessage(message: ChatMessage): MistralChatMessage {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/*
|
|
||||||
const messages: any[] = ordered.map(part => {
|
|
||||||
const content: any[] = [{
|
|
||||||
type: "input_text",
|
|
||||||
text: (Environment.USE_NAMES_IN_PROMPT && !part.bot ? `MESSAGE FROM USER \"${part.name}\":\n` : "") + part.content,
|
|
||||||
}];
|
|
||||||
|
|
||||||
if (!part.bot) {
|
|
||||||
for (const image of part.images ?? []) {
|
|
||||||
content.push({type: "input_image", image_url: `data:image/jpeg;base64,${image}`, detail: "auto"});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {role: part.bot ? "assistant" : "user", content};
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Environment.SYSTEM_PROMPT && Environment.USE_SYSTEM_PROMPT) {
|
|
||||||
messages.unshift({role: "system", content: Environment.SYSTEM_PROMPT});
|
|
||||||
}
|
|
||||||
return {parts: messages, imageCount};
|
|
||||||
*/
|
|
||||||
|
|
||||||
export type AiChatMessage = | OpenAIChatMessage | OllamaChatMessage | MistralChatMessage | GeminiMessage;
|
export type AiChatMessage = | OpenAIChatMessage | OllamaChatMessage | MistralChatMessage | GeminiMessage;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export type MistralContentChunk =
|
|||||||
|
|
||||||
export type MistralFunctionCall = {
|
export type MistralFunctionCall = {
|
||||||
name: string;
|
name: string;
|
||||||
arguments: { [k: string]: any } | string;
|
arguments: Record<string, unknown> | string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MistralToolCall = {
|
export type MistralToolCall = {
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
import {ResponseInputItem} from "openai/resources/responses/responses";
|
import type {ResponseInputMessageContentList} from "openai/resources/responses/responses";
|
||||||
|
|
||||||
export type OpenAIChatMessage = ResponseInputItem
|
export type OpenAIChatMessage = {
|
||||||
|
type: "message";
|
||||||
|
role: "system" | "user" | "assistant";
|
||||||
|
content: string | ResponseInputMessageContentList;
|
||||||
|
};
|
||||||
|
|||||||
@@ -295,26 +295,38 @@ export async function formatRuntimeModelInfo(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type NamedModel = {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
model?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ModelListResponse = {
|
||||||
|
models?: NamedModel[];
|
||||||
|
data?: NamedModel[];
|
||||||
|
};
|
||||||
|
|
||||||
export async function listProviderModels(provider: AiProvider): Promise<string[]> {
|
export async function listProviderModels(provider: AiProvider): Promise<string[]> {
|
||||||
const target = resolveAiRuntimeTarget(provider, "chat", getRuntimeModel(provider));
|
const target = resolveAiRuntimeTarget(provider, "chat", getRuntimeModel(provider));
|
||||||
|
|
||||||
switch (provider) {
|
switch (provider) {
|
||||||
case AiProvider.OLLAMA: {
|
case AiProvider.OLLAMA: {
|
||||||
const ollama = createOllamaClient(target);
|
const ollama = createOllamaClient(target);
|
||||||
const result: any = await ollama.list();
|
const result = await ollama.list() as ModelListResponse;
|
||||||
return (result.models ?? []).map((m: any) => m.model || m.name).filter(Boolean);
|
return (result.models ?? []).map(m => m.model || m.name).filter((name): name is string => !!name);
|
||||||
}
|
}
|
||||||
case AiProvider.GEMINI: {
|
case AiProvider.GEMINI: {
|
||||||
const models: string[] = [];
|
const models: string[] = [];
|
||||||
if (getGeminiApiMode(target) === "openai") {
|
if (getGeminiApiMode(target) === "openai") {
|
||||||
const geminiAi = createGeminiOpenAiClient(target);
|
const geminiAi = createGeminiOpenAiClient(target);
|
||||||
const iterable: any = await geminiAi.models.list();
|
const iterable = await geminiAi.models.list() as AsyncIterable<NamedModel>;
|
||||||
for await (const model of iterable) models.push(model.name || model.id || String(model));
|
for await (const model of iterable) models.push(model.name || model.id || String(model));
|
||||||
return models;
|
return models;
|
||||||
}
|
}
|
||||||
|
|
||||||
const geminiAi = createGoogleGenAiClient(target);
|
const geminiAi = createGoogleGenAiClient(target);
|
||||||
const iterable: any = await geminiAi.models.list();
|
const iterable = await geminiAi.models.list() as AsyncIterable<NamedModel>;
|
||||||
for await (const model of iterable) {
|
for await (const model of iterable) {
|
||||||
const name = model.name || model.id || String(model);
|
const name = model.name || model.id || String(model);
|
||||||
models.push(String(name).replace(/^models\//, ""));
|
models.push(String(name).replace(/^models\//, ""));
|
||||||
@@ -323,13 +335,14 @@ export async function listProviderModels(provider: AiProvider): Promise<string[]
|
|||||||
}
|
}
|
||||||
case AiProvider.MISTRAL: {
|
case AiProvider.MISTRAL: {
|
||||||
const mistralAi = createMistralClient(target);
|
const mistralAi = createMistralClient(target);
|
||||||
const result: any = await mistralAi.models.list();
|
const result = await mistralAi.models.list() as ModelListResponse | NamedModel[];
|
||||||
return (result.data ?? result.models ?? result ?? []).map((m: any) => m.id || m.name || String(m)).filter(Boolean);
|
const items = Array.isArray(result) ? result : result.data ?? result.models ?? [];
|
||||||
|
return items.map(m => m.id || m.name || String(m)).filter((name): name is string => !!name);
|
||||||
}
|
}
|
||||||
case AiProvider.OPENAI: {
|
case AiProvider.OPENAI: {
|
||||||
const openAi = createOpenAiClient(target);
|
const openAi = createOpenAiClient(target);
|
||||||
const result: any = await openAi.models.list();
|
const result = await openAi.models.list() as ModelListResponse;
|
||||||
return (result.data ?? []).map((m: any) => m.id).filter(Boolean);
|
return (result.data ?? []).map(m => m.id).filter((id): id is string => !!id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ export type AiRequestQueueTarget = {
|
|||||||
baseUrl?: string;
|
baseUrl?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type QueueEntry<T> = {
|
type QueueEntry = {
|
||||||
target: AiRequestQueueTarget;
|
target: AiRequestQueueTarget;
|
||||||
queueKey: string;
|
queueKey: string;
|
||||||
run: () => Promise<T>;
|
run: () => Promise<unknown>;
|
||||||
resolve: (value: T | PromiseLike<T>) => void;
|
resolve: (value: unknown) => void;
|
||||||
reject: (reason?: unknown) => void;
|
reject: (reason?: unknown) => void;
|
||||||
onPositionChange: (requestsBefore: number) => Promise<void> | void;
|
onPositionChange: (requestsBefore: number) => Promise<void> | void;
|
||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
@@ -26,7 +26,7 @@ type EnqueueOptions<T> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class AiProviderRequestQueue {
|
class AiProviderRequestQueue {
|
||||||
private readonly waiting = new Map<string, Array<QueueEntry<any>>>();
|
private readonly waiting = new Map<string, QueueEntry[]>();
|
||||||
private readonly active = new Map<string, number>();
|
private readonly active = new Map<string, number>();
|
||||||
|
|
||||||
enqueue<T>(target: AiRequestQueueTarget, options: EnqueueOptions<T>): Promise<T> {
|
enqueue<T>(target: AiRequestQueueTarget, options: EnqueueOptions<T>): Promise<T> {
|
||||||
@@ -36,11 +36,11 @@ class AiProviderRequestQueue {
|
|||||||
|
|
||||||
return new Promise<T>((resolve, reject) => {
|
return new Promise<T>((resolve, reject) => {
|
||||||
const queueKey = this.queueKey(target);
|
const queueKey = this.queueKey(target);
|
||||||
const entry: QueueEntry<T> = {
|
const entry: QueueEntry = {
|
||||||
target,
|
target,
|
||||||
queueKey,
|
queueKey,
|
||||||
run: options.run,
|
run: options.run,
|
||||||
resolve,
|
resolve: value => resolve(value as T),
|
||||||
reject,
|
reject,
|
||||||
onPositionChange: options.onPositionChange,
|
onPositionChange: options.onPositionChange,
|
||||||
signal: options.signal,
|
signal: options.signal,
|
||||||
@@ -63,11 +63,11 @@ class AiProviderRequestQueue {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private getQueue(queueKey: string): Array<QueueEntry<any>> | undefined {
|
private getQueue(queueKey: string): QueueEntry[] | undefined {
|
||||||
return this.waiting.get(queueKey);
|
return this.waiting.get(queueKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getOrCreateQueue(queueKey: string): Array<QueueEntry<any>> {
|
private getOrCreateQueue(queueKey: string): QueueEntry[] {
|
||||||
let queue = this.waiting.get(queueKey);
|
let queue = this.waiting.get(queueKey);
|
||||||
if (!queue) {
|
if (!queue) {
|
||||||
queue = [];
|
queue = [];
|
||||||
@@ -104,7 +104,7 @@ class AiProviderRequestQueue {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeWaitingEntry(entry: QueueEntry<any>): boolean {
|
private removeWaitingEntry(entry: QueueEntry): boolean {
|
||||||
const queue = this.getQueue(entry.queueKey);
|
const queue = this.getQueue(entry.queueKey);
|
||||||
if (!queue) return false;
|
if (!queue) return false;
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ class AiProviderRequestQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async runEntry(entry: QueueEntry<any>): Promise<void> {
|
private async runEntry(entry: QueueEntry): Promise<void> {
|
||||||
try {
|
try {
|
||||||
entry.resolve(await entry.run());
|
entry.resolve(await entry.run());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -174,7 +174,7 @@ class AiProviderRequestQueue {
|
|||||||
}).catch(console.error);
|
}).catch(console.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
private deleteQueueIfIdle(queueKey: string, queue: Array<QueueEntry<any>>): void {
|
private deleteQueueIfIdle(queueKey: string, queue: QueueEntry[]): void {
|
||||||
if (!queue.length && this.activeCount(queueKey) <= 0) {
|
if (!queue.length && this.activeCount(queueKey) <= 0) {
|
||||||
this.waiting.delete(queueKey);
|
this.waiting.delete(queueKey);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-10
@@ -198,7 +198,7 @@ async function transcribeGeminiSpeech(audio: AiDownloadedFile, signal?: AbortSig
|
|||||||
temperature: 0,
|
temperature: 0,
|
||||||
abortSignal: signal,
|
abortSignal: signal,
|
||||||
},
|
},
|
||||||
});
|
}) as unknown as GeminiSpeechResponse;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
provider: AiProvider.GEMINI,
|
provider: AiProvider.GEMINI,
|
||||||
@@ -240,17 +240,19 @@ async function transcribeOllamaSpeech(audio: AiDownloadedFile, signal?: AbortSig
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function collectGeminiText(response: any): string {
|
type GeminiSpeechResponse = {
|
||||||
if (typeof response?.text === "string") return response.text;
|
text?: string;
|
||||||
|
candidates?: Array<{content?: {parts?: Array<{text?: string}>}}> ;
|
||||||
|
};
|
||||||
|
|
||||||
const candidates = response?.candidates ?? [];
|
function collectGeminiText(response: GeminiSpeechResponse): string {
|
||||||
const candidateText = candidates
|
if (typeof response.text === "string") return response.text;
|
||||||
.flatMap((candidate: any) => candidate?.content?.parts ?? [])
|
|
||||||
.map((part: any) => part?.text ?? "")
|
const candidateText = (response.candidates ?? [])
|
||||||
|
.flatMap(candidate => candidate.content?.parts ?? [])
|
||||||
|
.map(part => part.text ?? "")
|
||||||
.join("");
|
.join("");
|
||||||
if (candidateText.trim()) return candidateText;
|
if (candidateText.trim()) return candidateText;
|
||||||
|
|
||||||
return (response?.candidates ?? [])
|
return "";
|
||||||
.map((output: any) => typeof output === "string" ? output : output?.content?.parts?.[0]?.text ?? "")
|
|
||||||
.join("");
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ export class TelegramStreamMessage {
|
|||||||
}
|
}
|
||||||
if (shouldRemoveKeyboard) await this.removeKeyboard();
|
if (shouldRemoveKeyboard) await this.removeKeyboard();
|
||||||
this.lastSent = next;
|
this.lastSent = next;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
if (shouldRemoveKeyboard && this.isMessageNotModified(e)) {
|
if (shouldRemoveKeyboard && this.isMessageNotModified(e)) {
|
||||||
await this.removeKeyboard();
|
await this.removeKeyboard();
|
||||||
this.lastSent = next;
|
this.lastSent = next;
|
||||||
@@ -369,8 +369,9 @@ export class TelegramStreamMessage {
|
|||||||
if (result && result !== true) this.waitMessage = result;
|
if (result && result !== true) this.waitMessage = result;
|
||||||
this.mediaMode = true;
|
this.mediaMode = true;
|
||||||
this.lastSent = next;
|
this.lastSent = next;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
if (!String(e?.message ?? e).includes("message is not modified")) logError(e);
|
const message = e instanceof Error ? e.message : String(e);
|
||||||
|
if (!message.includes("message is not modified")) logError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ async function synthesizeMistralSpeech(text: string, voice?: string): Promise<Sy
|
|||||||
if (target.model) request.model = target.model;
|
if (target.model) request.model = target.model;
|
||||||
if (voice || Environment.MISTRAL_TTS_VOICE_ID) request.voiceId = voice || Environment.MISTRAL_TTS_VOICE_ID;
|
if (voice || Environment.MISTRAL_TTS_VOICE_ID) request.voiceId = voice || Environment.MISTRAL_TTS_VOICE_ID;
|
||||||
|
|
||||||
const response: any = await mistralAi.audio.speech.complete(request);
|
const response = await mistralAi.audio.speech.complete(request) as unknown as {audioData?: string; audio_data?: string};
|
||||||
const audioData = response?.audioData ?? response?.audio_data;
|
const audioData = response?.audioData ?? response?.audio_data;
|
||||||
if (typeof audioData !== "string" || !audioData.trim()) {
|
if (typeof audioData !== "string" || !audioData.trim()) {
|
||||||
throw new Error(Environment.mistralTtsNoAudioDataText);
|
throw new Error(Environment.mistralTtsNoAudioDataText);
|
||||||
@@ -192,7 +192,7 @@ async function synthesizeMistralSpeech(text: string, voice?: string): Promise<Sy
|
|||||||
async function synthesizeGeminiSpeech(text: string, voice?: string): Promise<SynthesizedSpeech> {
|
async function synthesizeGeminiSpeech(text: string, voice?: string): Promise<SynthesizedSpeech> {
|
||||||
const target = resolveAiRuntimeTarget(AiProvider.GEMINI, "textToSpeech");
|
const target = resolveAiRuntimeTarget(AiProvider.GEMINI, "textToSpeech");
|
||||||
const geminiAi = createGoogleGenAiClient(target);
|
const geminiAi = createGoogleGenAiClient(target);
|
||||||
const response: any = await geminiAi.models.generateContent({
|
const response = await geminiAi.models.generateContent({
|
||||||
model: target.model,
|
model: target.model,
|
||||||
contents: text,
|
contents: text,
|
||||||
config: {
|
config: {
|
||||||
|
|||||||
@@ -15,7 +15,15 @@ export function getOpenAITools(): AiTool[] {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOpenAIResponsesTools(): any[] {
|
export type OpenAiResponseTool = {
|
||||||
|
type: "function";
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
parameters?: unknown;
|
||||||
|
strict: false;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getOpenAIResponsesTools(): OpenAiResponseTool[] {
|
||||||
return getTools().map(tool => ({
|
return getTools().map(tool => ({
|
||||||
type: "function",
|
type: "function",
|
||||||
name: tool.function.name,
|
name: tool.function.name,
|
||||||
|
|||||||
+2
-25
@@ -1,28 +1,5 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
interface Tool {
|
|
||||||
type: string;
|
|
||||||
function: {
|
|
||||||
name?: string;
|
|
||||||
description?: string;
|
|
||||||
type?: string;
|
|
||||||
parameters?: {
|
|
||||||
type?: string;
|
|
||||||
$defs?: any;
|
|
||||||
items?: any;
|
|
||||||
required?: string[];
|
|
||||||
properties?: {
|
|
||||||
[key: string]: {
|
|
||||||
type?: string | string[];
|
|
||||||
items?: any;
|
|
||||||
description?: string;
|
|
||||||
enum?: any[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
export type AiToolParameters = {
|
export type AiToolParameters = {
|
||||||
type: "object";
|
type: "object";
|
||||||
@@ -45,7 +22,7 @@ export type AiToolCall = {
|
|||||||
function: {
|
function: {
|
||||||
name: string;
|
name: string;
|
||||||
arguments: {
|
arguments: {
|
||||||
[key: string]: any;
|
[key: string]: unknown;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -356,11 +356,12 @@ export async function webSearch(args?: Record<string, unknown>) {
|
|||||||
|
|
||||||
note: "Use returned URLs as sources. Do not invent facts that are not present in the snippets/results.",
|
note: "Use returned URLs as sources. Do not invent facts that are not present in the snippets/results.",
|
||||||
};
|
};
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
logError(e);
|
logError(e);
|
||||||
|
|
||||||
const status = e?.response?.status;
|
const axiosLike = e as {response?: {status?: unknown; data?: unknown}};
|
||||||
const data = e?.response?.data;
|
const status = axiosLike.response?.status;
|
||||||
|
const data = axiosLike.response?.data;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ok: false,
|
ok: false,
|
||||||
|
|||||||
@@ -327,8 +327,8 @@ async function assertNoSymlinkInPath(
|
|||||||
if (stat.isSymbolicLink()) {
|
if (stat.isSymbolicLink()) {
|
||||||
throw new Error("Symlinks are not allowed in file tool paths.");
|
throw new Error("Symlinks are not allowed in file tool paths.");
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
if (e?.code === "ENOENT" && options?.allowMissingTail) {
|
if ((e as NodeJS.ErrnoException).code === "ENOENT" && options?.allowMissingTail) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,8 +341,8 @@ async function pathExists(absolutePath: string): Promise<boolean> {
|
|||||||
try {
|
try {
|
||||||
await fs.promises.lstat(absolutePath);
|
await fs.promises.lstat(absolutePath);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
if (e?.code === "ENOENT") return false;
|
if ((e as NodeJS.ErrnoException).code === "ENOENT") return false;
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ export const marketRatesToolPrompt = [
|
|||||||
"- When the user asks for all rates, group fiat currencies separately from crypto and gold.",
|
"- When the user asks for all rates, group fiat currencies separately from crypto and gold.",
|
||||||
].join("\n");
|
].join("\n");
|
||||||
|
|
||||||
export async function getMarketRates(): Promise<any | undefined> {
|
export async function getMarketRates(): Promise<unknown | undefined> {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get("https://apid.r00t.top/api/v2/currency/rates");
|
const response = await axios.get("https://apid.r00t.top/api/v2/currency/rates");
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
console.error("GET_MARKET_RATES", e);
|
console.error("GET_MARKET_RATES", e);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -692,7 +692,7 @@ function parsePythonInterpreterArgs(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
code,
|
code,
|
||||||
stdin,
|
stdin: typeof stdin === "string" ? stdin : undefined,
|
||||||
timeoutMs: timeoutMs === undefined ? undefined : Number(timeoutMs),
|
timeoutMs: timeoutMs === undefined ? undefined : Number(timeoutMs),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export async function loadOllamaModel(model: string, ollama: Ollama, contextLeng
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
console.error("Error loading Ollama model:", model);
|
console.error("Error loading Ollama model:", model);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export const weatherToolPrompt = [
|
|||||||
"If the city is missing or unclear, ask the user to specify it.",
|
"If the city is missing or unclear, ask the user to specify it.",
|
||||||
].join("\n");
|
].join("\n");
|
||||||
|
|
||||||
export async function getWeather(args?: Record<string, unknown>): Promise<any | null> {
|
export async function getWeather(args?: Record<string, unknown>): Promise<Record<string, unknown> | null> {
|
||||||
console.log("getWeather()");
|
console.log("getWeather()");
|
||||||
try {
|
try {
|
||||||
const city = asNonEmptyString(args?.city);
|
const city = asNonEmptyString(args?.city);
|
||||||
@@ -137,7 +137,7 @@ export async function getWeather(args?: Record<string, unknown>): Promise<any |
|
|||||||
windSpeed: wind.speed,
|
windSpeed: wind.speed,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
logError(e);
|
logError(e);
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
// Gemini provider runner extracted from unified-ai-runner.ts.
|
||||||
|
import {getGeminiTools} from "./tool-mappers";
|
||||||
|
import {TelegramStreamMessage} from "./telegram-stream-message";
|
||||||
|
import {ToolRuntimeContext} from "./tools/runtime";
|
||||||
|
import {GeminiMessage} from "./gemini-chat-message";
|
||||||
|
import {createGoogleGenAiClient} from "./ai-runtime-target";
|
||||||
|
import {aiLog, aiLogDuration, aiLogProviderTarget, aiLogToolCall} from "./ai-logger";
|
||||||
|
|
||||||
|
import {AsyncIterableStream, GeminiFunctionCallLike, GeminiResponseLike, MAX_TOOL_ROUNDS, RuntimeConfigSnapshot, ToolCallData, ToolExecutionMemory, executeToolBatch, roundStatus, safeJsonParseObject, GeminiGenerationRequest} from "./unified-ai-runner.shared";
|
||||||
|
|
||||||
|
function collectGeminiResponseText(response: GeminiResponseLike & { text?: string }): string {
|
||||||
|
if (typeof response.text === "string") return response.text;
|
||||||
|
|
||||||
|
return (response.candidates ?? [])
|
||||||
|
.flatMap(candidate => candidate.content?.parts ?? [])
|
||||||
|
.map(part => part.text ?? "")
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function collectGeminiFunctionCalls(response: GeminiResponseLike): ToolCallData[] {
|
||||||
|
const calls = response.functionCalls
|
||||||
|
?? (response.candidates ?? []).flatMap(candidate => {
|
||||||
|
return (candidate.content?.parts ?? [])
|
||||||
|
.map(part => part.functionCall)
|
||||||
|
.filter((call): call is GeminiFunctionCallLike => !!call);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (calls ?? []).map((call, index) => ({
|
||||||
|
id: call.id ?? `gemini_${index}_${call.name ?? "call"}`,
|
||||||
|
name: call.name ?? "",
|
||||||
|
argumentsText: JSON.stringify(call.args ?? {}),
|
||||||
|
})).filter((call: ToolCallData) => call.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeGeminiFunctionCalls(existing: ToolCallData[], next: ToolCallData[]): ToolCallData[] {
|
||||||
|
const merged = [...existing];
|
||||||
|
for (const call of next) {
|
||||||
|
const index = merged.findIndex(item => item.id === call.id);
|
||||||
|
if (index === -1) {
|
||||||
|
merged.push(call);
|
||||||
|
} else {
|
||||||
|
merged[index] = call;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return merged;
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendGeminiToolRound(messages: GeminiMessage[], calls: ToolCallData[], results: string[]): void {
|
||||||
|
messages.push({
|
||||||
|
role: "model",
|
||||||
|
parts: calls.map(call => ({
|
||||||
|
functionCall: {
|
||||||
|
id: call.id,
|
||||||
|
name: call.name,
|
||||||
|
args: safeJsonParseObject(call.argumentsText),
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
messages.push({
|
||||||
|
role: "user",
|
||||||
|
parts: calls.map((call, index) => ({
|
||||||
|
functionResponse: {
|
||||||
|
id: call.id,
|
||||||
|
name: call.name,
|
||||||
|
response: {result: results[index] ?? ""},
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function runGemini(
|
||||||
|
messages: GeminiMessage[],
|
||||||
|
streamMessage: TelegramStreamMessage,
|
||||||
|
signal: AbortSignal,
|
||||||
|
stream: boolean,
|
||||||
|
firstRoundStatus: string,
|
||||||
|
config: RuntimeConfigSnapshot,
|
||||||
|
toolContext: ToolRuntimeContext,
|
||||||
|
): Promise<void> {
|
||||||
|
const runnerStartedAt = Date.now();
|
||||||
|
const geminiAi = createGoogleGenAiClient(config.geminiChatTarget);
|
||||||
|
|
||||||
|
aiLog("info", "gemini.run.start", {
|
||||||
|
stream,
|
||||||
|
target: aiLogProviderTarget(config.geminiChatTarget),
|
||||||
|
inputMessages: messages.length,
|
||||||
|
hasToolInputFiles: !!toolContext.pythonInputFiles?.length,
|
||||||
|
});
|
||||||
|
|
||||||
|
const toolMemory: ToolExecutionMemory = new Map();
|
||||||
|
|
||||||
|
for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
|
||||||
|
const roundStartedAt = Date.now();
|
||||||
|
aiLog("debug", "gemini.round.start", {round, messages: messages.length, stream});
|
||||||
|
if (signal.aborted) throw new Error("Aborted");
|
||||||
|
|
||||||
|
streamMessage.setStatus(roundStatus(round, firstRoundStatus) ?? "");
|
||||||
|
await streamMessage.flush();
|
||||||
|
|
||||||
|
const request: GeminiGenerationRequest = {
|
||||||
|
model: config.geminiChatTarget.model,
|
||||||
|
contents: messages,
|
||||||
|
config: {
|
||||||
|
tools: getGeminiTools(),
|
||||||
|
temperature: messages.length <= 2 ? 0 : 0.6,
|
||||||
|
abortSignal: signal,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
const response = await geminiAi.models.generateContent(request) as unknown as GeminiResponseLike & {
|
||||||
|
text?: string
|
||||||
|
};
|
||||||
|
const text = collectGeminiResponseText(response);
|
||||||
|
streamMessage.append(text);
|
||||||
|
const calls = collectGeminiFunctionCalls(response);
|
||||||
|
aiLog(calls.length ? "info" : "success", calls.length ? "gemini.tool_calls" : "gemini.run.done", {
|
||||||
|
round,
|
||||||
|
duration: calls.length ? aiLogDuration(roundStartedAt) : aiLogDuration(runnerStartedAt),
|
||||||
|
textChars: text.length,
|
||||||
|
calls: calls.map(aiLogToolCall),
|
||||||
|
});
|
||||||
|
if (!calls.length) return;
|
||||||
|
|
||||||
|
appendGeminiToolRound(messages, calls, await executeToolBatch(calls, streamMessage, toolContext, toolMemory));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await geminiAi.models.generateContentStream(request) as unknown as AsyncIterableStream<GeminiResponseLike & {
|
||||||
|
text?: string
|
||||||
|
}>;
|
||||||
|
aiLog("debug", "gemini.stream.open", {round});
|
||||||
|
let calls: ToolCallData[] = [];
|
||||||
|
const roundTextStart = streamMessage.getText().length;
|
||||||
|
for await (const chunk of response) {
|
||||||
|
if (signal.aborted) throw new Error("Aborted");
|
||||||
|
streamMessage.append(collectGeminiResponseText(chunk));
|
||||||
|
calls = mergeGeminiFunctionCalls(calls, collectGeminiFunctionCalls(chunk));
|
||||||
|
}
|
||||||
|
|
||||||
|
aiLog(calls.length ? "info" : "success", calls.length ? "gemini.tool_calls" : "gemini.run.done", {
|
||||||
|
round,
|
||||||
|
duration: calls.length ? aiLogDuration(roundStartedAt) : aiLogDuration(runnerStartedAt),
|
||||||
|
textChars: streamMessage.getText().slice(roundTextStart).length,
|
||||||
|
calls: calls.map(aiLogToolCall),
|
||||||
|
});
|
||||||
|
if (!calls.length) return;
|
||||||
|
appendGeminiToolRound(messages, calls, await executeToolBatch(calls, streamMessage, toolContext, toolMemory));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class GeminiProviderRunner {
|
||||||
|
static run = runGemini;
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
// Mistral provider runner extracted from unified-ai-runner.ts.
|
||||||
|
import {Environment} from "../common/environment";
|
||||||
|
import {getMistralTools} from "./tool-mappers";
|
||||||
|
import {TelegramStreamMessage} from "./telegram-stream-message";
|
||||||
|
import {ToolRuntimeContext} from "./tools/runtime";
|
||||||
|
import {MistralChatMessage} from "./mistral-chat-message";
|
||||||
|
import {createMistralClient} from "./ai-runtime-target";
|
||||||
|
import {aiLog, aiLogDuration, aiLogProviderTarget, aiLogToolCall} from "./ai-logger";
|
||||||
|
|
||||||
|
import {MAX_TOOL_ROUNDS, MistralDeltaLike, MistralDocumentReference, RuntimeConfigSnapshot, StreamingToolCallAccumulator, ToolCallData, ToolExecutionMemory, contentFromMistralDelta, executeToolBatch, mistralToolCalls, normalizeMistralToolCalls, roundStatus} from "./unified-ai-runner.shared";
|
||||||
|
|
||||||
|
export async function runMistral(
|
||||||
|
messages: MistralChatMessage[],
|
||||||
|
documents: MistralDocumentReference[],
|
||||||
|
streamMessage: TelegramStreamMessage,
|
||||||
|
signal: AbortSignal,
|
||||||
|
stream: boolean,
|
||||||
|
firstRoundStatus: string,
|
||||||
|
config: RuntimeConfigSnapshot,
|
||||||
|
toolContext: ToolRuntimeContext,
|
||||||
|
): Promise<void> {
|
||||||
|
const runnerStartedAt = Date.now();
|
||||||
|
const mistralAi = createMistralClient(config.mistralChatTarget);
|
||||||
|
aiLog("info", "mistral.run.start", {
|
||||||
|
stream,
|
||||||
|
target: aiLogProviderTarget(config.mistralChatTarget),
|
||||||
|
inputMessages: messages.length,
|
||||||
|
documents: documents.length,
|
||||||
|
hasToolInputFiles: !!toolContext.pythonInputFiles?.length,
|
||||||
|
});
|
||||||
|
|
||||||
|
const toolMemory: ToolExecutionMemory = new Map();
|
||||||
|
|
||||||
|
for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
|
||||||
|
const roundStartedAt = Date.now();
|
||||||
|
aiLog("debug", "mistral.round.start", {round, messages: messages.length, stream});
|
||||||
|
if (signal.aborted) throw new Error("Aborted");
|
||||||
|
|
||||||
|
streamMessage.setStatus(roundStatus(round, firstRoundStatus) ?? "");
|
||||||
|
await streamMessage.flush();
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
const request = {
|
||||||
|
model: config.mistralChatTarget.model,
|
||||||
|
messages,
|
||||||
|
tools: getMistralTools(),
|
||||||
|
documents: documents
|
||||||
|
} as unknown as Parameters<typeof mistralAi.chat.complete>[0];
|
||||||
|
const response = await mistralAi.chat.complete(request, {signal});
|
||||||
|
const msg = response.choices?.[0]?.message;
|
||||||
|
const text = typeof msg?.content === "string" ? msg.content : JSON.stringify(msg?.content ?? "");
|
||||||
|
streamMessage.append(text);
|
||||||
|
const calls = normalizeMistralToolCalls(mistralToolCalls(msg));
|
||||||
|
aiLog(calls.length ? "info" : "success", calls.length ? "mistral.tool_calls" : "mistral.run.done", {
|
||||||
|
round,
|
||||||
|
duration: calls.length ? aiLogDuration(roundStartedAt) : aiLogDuration(runnerStartedAt),
|
||||||
|
textChars: text.length,
|
||||||
|
calls: calls.map(aiLogToolCall),
|
||||||
|
});
|
||||||
|
if (!calls.length) return;
|
||||||
|
messages.push({
|
||||||
|
role: "assistant",
|
||||||
|
content: text,
|
||||||
|
toolCalls: calls.map(call => ({
|
||||||
|
id: call.id,
|
||||||
|
function: {name: call.name, arguments: call.argumentsText},
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
const toolResults = await executeToolBatch(calls, streamMessage, toolContext, toolMemory);
|
||||||
|
for (const [index, call] of calls.entries()) {
|
||||||
|
messages.push({
|
||||||
|
role: "tool",
|
||||||
|
name: call.name,
|
||||||
|
toolCallId: call.id,
|
||||||
|
content: toolResults[index] ?? "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const request = {
|
||||||
|
model: config.mistralChatTarget.model,
|
||||||
|
messages,
|
||||||
|
tools: getMistralTools(),
|
||||||
|
documents: documents
|
||||||
|
} as unknown as Parameters<typeof mistralAi.chat.stream>[0];
|
||||||
|
const streamResponse = await mistralAi.chat.stream(request, {signal});
|
||||||
|
aiLog("debug", "mistral.stream.open", {round});
|
||||||
|
let calls: ToolCallData[] = [];
|
||||||
|
const roundTextStart = streamMessage.getText().length;
|
||||||
|
const toolCallAccumulator = new StreamingToolCallAccumulator("mistral_stream", round);
|
||||||
|
|
||||||
|
for await (const event of streamResponse) {
|
||||||
|
if (signal.aborted) throw new Error("Aborted");
|
||||||
|
|
||||||
|
const choice = event.data?.choices?.[0];
|
||||||
|
const delta = choice?.delta;
|
||||||
|
const mistralDelta = delta as MistralDeltaLike;
|
||||||
|
|
||||||
|
streamMessage.append(contentFromMistralDelta(mistralDelta));
|
||||||
|
|
||||||
|
const rawDeltaCalls = mistralToolCalls(mistralDelta);
|
||||||
|
if (rawDeltaCalls.length) {
|
||||||
|
calls = toolCallAccumulator.add(rawDeltaCalls);
|
||||||
|
streamMessage.setStatus(Environment.getUseToolText(calls));
|
||||||
|
await streamMessage.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aiLog(calls.length ? "info" : "success", calls.length ? "mistral.tool_calls" : "mistral.run.done", {
|
||||||
|
round,
|
||||||
|
duration: calls.length ? aiLogDuration(roundStartedAt) : aiLogDuration(runnerStartedAt),
|
||||||
|
textChars: streamMessage.getText().slice(roundTextStart).length,
|
||||||
|
calls: calls.map(aiLogToolCall),
|
||||||
|
});
|
||||||
|
if (!calls.length) return;
|
||||||
|
const roundText = streamMessage.getText().slice(roundTextStart);
|
||||||
|
messages.push({
|
||||||
|
role: "assistant",
|
||||||
|
content: roundText,
|
||||||
|
toolCalls: calls.map(c => ({id: c.id, function: {name: c.name, arguments: c.argumentsText}}))
|
||||||
|
});
|
||||||
|
const toolResults = await executeToolBatch(calls, streamMessage, toolContext, toolMemory);
|
||||||
|
for (const [index, call] of calls.entries()) {
|
||||||
|
messages.push({
|
||||||
|
role: "tool",
|
||||||
|
name: call.name,
|
||||||
|
toolCallId: call.id,
|
||||||
|
content: toolResults[index] ?? "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class MistralProviderRunner {
|
||||||
|
static run = runMistral;
|
||||||
|
}
|
||||||
@@ -0,0 +1,404 @@
|
|||||||
|
// Ollama provider runner extracted from unified-ai-runner.ts.
|
||||||
|
import {Message} from "typescript-telegram-bot-api";
|
||||||
|
import * as fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import {AiProvider} from "../model/ai-provider";
|
||||||
|
import {Environment} from "../common/environment";
|
||||||
|
import {bot, notesDir} from "../index";
|
||||||
|
import {clamp, logError} from "../util/utils";
|
||||||
|
import {getOllamaTools} from "./tool-mappers";
|
||||||
|
import {TelegramStreamMessage} from "./telegram-stream-message";
|
||||||
|
import {getModelCapabilities} from "./provider-model-runtime";
|
||||||
|
import {ChatMessage} from "./chat-messages-types";
|
||||||
|
import {ChatRequest, Tool} from "ollama";
|
||||||
|
import {ToolRuntimeContext} from "./tools/runtime";
|
||||||
|
import {enqueueTelegramApiCall} from "../util/telegram-api-queue";
|
||||||
|
import {getCurrentDateTimeTool} from "./tools/datetime";
|
||||||
|
import {getMarketRatesTool} from "./tools/market-rates";
|
||||||
|
import {getWeatherTool} from "./tools/weather";
|
||||||
|
import {loadOllamaModel, unloadAllOllamaModels} from "./tools/utils";
|
||||||
|
import {createOllamaClient} from "./ai-runtime-target";
|
||||||
|
import {GetNoteFileResult, GetNoteFileResultSchema} from "./tools/send-note-file";
|
||||||
|
import {aiLog, aiLogDuration, aiLogMessageIdentity, aiLogProviderTarget, aiLogToolCall} from "./ai-logger";
|
||||||
|
|
||||||
|
import {DEFAULT_OLLAMA_CONTEXT_SIZE, MAX_OLLAMA_CONTEXT_SIZE, MAX_TOOL_ROUNDS, MIN_OLLAMA_CONTEXT_SIZE, RuntimeConfigSnapshot, Think, ToolCallData, ToolExecutionMemory, allToolSchemaNames, appendOllamaToolResults, dedupeToolCalls, executeToolBatch, normalizeOllamaToolCalls, roundStatus, safeJsonParseObject, isRecord, isOllamaModelActive, OllamaToolCallLike} from "./unified-ai-runner.shared";
|
||||||
|
import {latestUserTextFromOllamaMessages, looksLikeToolRankerJson, OllamaToolRanker} from "./unified-ai-runner.tool-ranker";
|
||||||
|
|
||||||
|
export async function runOllama(
|
||||||
|
msg: Message,
|
||||||
|
messages: ChatMessage[],
|
||||||
|
streamMessage: TelegramStreamMessage,
|
||||||
|
signal: AbortSignal,
|
||||||
|
stream: boolean,
|
||||||
|
think: Think,
|
||||||
|
firstRoundStatus: string,
|
||||||
|
config: RuntimeConfigSnapshot,
|
||||||
|
toolContext: ToolRuntimeContext,
|
||||||
|
contextSize?: number,
|
||||||
|
): Promise<void> {
|
||||||
|
const fromId = msg.from?.id;
|
||||||
|
const runnerStartedAt = Date.now();
|
||||||
|
|
||||||
|
const audioCount = messages.reduce((sum, m) => sum + (m.audioParts?.length || m.audios?.length || 0), 0);
|
||||||
|
const videoNoteCount = messages.reduce((sum, m) => sum + (m.videoNotes?.length ?? 0), 0);
|
||||||
|
const imageCount = messages.reduce((sum, m) => sum + (m.imageParts?.length || m.images?.length || 0), 0);
|
||||||
|
|
||||||
|
const target = (audioCount || videoNoteCount) ? config.ollamaAudioTarget :
|
||||||
|
imageCount ? config.ollamaVisionTarget :
|
||||||
|
think ? config.ollamaThinkingTarget : config.ollamaChatTarget;
|
||||||
|
const model = target.model;
|
||||||
|
aiLog("info", "ollama.run.start", {
|
||||||
|
stream,
|
||||||
|
think,
|
||||||
|
target: aiLogProviderTarget(target),
|
||||||
|
requestedContextSize: contextSize,
|
||||||
|
message: aiLogMessageIdentity(msg),
|
||||||
|
counts: {messages: messages.length, images: imageCount, audio: audioCount, videoNotes: videoNoteCount},
|
||||||
|
hasToolInputFiles: !!toolContext.pythonInputFiles?.length,
|
||||||
|
});
|
||||||
|
|
||||||
|
const ollama = createOllamaClient(target);
|
||||||
|
const modelInfo = await ollama.show({model});
|
||||||
|
const modelInfoMap = isRecord(modelInfo.model_info) ? modelInfo.model_info : {};
|
||||||
|
const contextKey = Object.keys(modelInfoMap).find(k => k.endsWith(".context_length"));
|
||||||
|
// @ts-ignore
|
||||||
|
const rawMaxContextLength = contextKey ? modelInfoMap[contextKey] : undefined;
|
||||||
|
const parsedMaxContextLength =
|
||||||
|
typeof rawMaxContextLength === "number"
|
||||||
|
? rawMaxContextLength
|
||||||
|
: typeof rawMaxContextLength === "string"
|
||||||
|
? Number(rawMaxContextLength)
|
||||||
|
: DEFAULT_OLLAMA_CONTEXT_SIZE;
|
||||||
|
|
||||||
|
const maxContextLength = Number.isFinite(parsedMaxContextLength)
|
||||||
|
? parsedMaxContextLength
|
||||||
|
: DEFAULT_OLLAMA_CONTEXT_SIZE;
|
||||||
|
|
||||||
|
const context = clamp(
|
||||||
|
contextSize === -1 ? MAX_OLLAMA_CONTEXT_SIZE : contextSize ?? DEFAULT_OLLAMA_CONTEXT_SIZE,
|
||||||
|
MIN_OLLAMA_CONTEXT_SIZE,
|
||||||
|
maxContextLength ?? DEFAULT_OLLAMA_CONTEXT_SIZE
|
||||||
|
);
|
||||||
|
aiLog("debug", "ollama.context.resolved", {model, contextKey, maxContextLength, context});
|
||||||
|
|
||||||
|
const modelsToLoad = [model];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const activeModels = (await ollama.ps()).models.map(m => m.model);
|
||||||
|
const oldSet = new Set(activeModels);
|
||||||
|
const newSet = new Set(modelsToLoad);
|
||||||
|
|
||||||
|
const added = modelsToLoad.filter(m => !oldSet.has(m));
|
||||||
|
const removed = activeModels.filter(m => !newSet.has(m));
|
||||||
|
const diff = [...added, ...removed];
|
||||||
|
aiLog("debug", "ollama.models.active", {activeModels, requiredModels: modelsToLoad, added, removed});
|
||||||
|
if (diff.length) {
|
||||||
|
aiLog("info", "ollama.models.unload_extra", {keep: modelsToLoad, diff});
|
||||||
|
await unloadAllOllamaModels(ollama, modelsToLoad);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
logError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await isOllamaModelActive(ollama, target))) {
|
||||||
|
const loadStartedAt = Date.now();
|
||||||
|
aiLog("info", "ollama.model.load.start", {model, context});
|
||||||
|
const currentStatus = streamMessage.getStatus();
|
||||||
|
streamMessage.setStatus(Environment.getLoadingModelText(model));
|
||||||
|
await streamMessage.flush();
|
||||||
|
if (await loadOllamaModel(model, ollama, context)) {
|
||||||
|
aiLog("success", "ollama.model.load.done", {model, duration: aiLogDuration(loadStartedAt)});
|
||||||
|
streamMessage.setStatus(currentStatus ?? Environment.waitThinkText);
|
||||||
|
await streamMessage.flush();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
aiLog("debug", "ollama.model.already_loaded", {model});
|
||||||
|
}
|
||||||
|
|
||||||
|
let interval: ReturnType<typeof setInterval> | null = null;
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
let typingInFlight = false;
|
||||||
|
const applyTyping = async () => {
|
||||||
|
if (typingInFlight) return;
|
||||||
|
typingInFlight = true;
|
||||||
|
try {
|
||||||
|
await enqueueTelegramApiCall(
|
||||||
|
() => bot.sendChatAction({chat_id: msg.chat.id, action: "typing"}),
|
||||||
|
{method: "sendChatAction", chatId: msg.chat.id, chatType: msg.chat.type}
|
||||||
|
).catch(logError);
|
||||||
|
} finally {
|
||||||
|
typingInFlight = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await applyTyping();
|
||||||
|
interval = setInterval(() => {
|
||||||
|
applyTyping().catch(logError);
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
const toolMemory: ToolExecutionMemory = new Map();
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
|
||||||
|
const roundStartedAt = Date.now();
|
||||||
|
aiLog("debug", "ollama.round.start", {
|
||||||
|
round,
|
||||||
|
context,
|
||||||
|
messages: messages.length,
|
||||||
|
stream,
|
||||||
|
think: audioCount ? false : think,
|
||||||
|
});
|
||||||
|
|
||||||
|
const request: ChatRequest = {
|
||||||
|
model: model,
|
||||||
|
messages: messages,
|
||||||
|
think: audioCount ? false : think,
|
||||||
|
options: {
|
||||||
|
temperature: 0.6,
|
||||||
|
num_ctx: context,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let activeToolNames: string[] = [];
|
||||||
|
if ((await getModelCapabilities(AiProvider.OLLAMA, model, "tools"))?.tools?.supported) {
|
||||||
|
const availableOllamaTools: Tool[] = fromId !== Environment.CREATOR_ID
|
||||||
|
? [getCurrentDateTimeTool, getMarketRatesTool, getWeatherTool]
|
||||||
|
: getOllamaTools() as Tool[];
|
||||||
|
|
||||||
|
aiLog("debug", "ollama.tools.available", {
|
||||||
|
round,
|
||||||
|
tools: allToolSchemaNames(availableOllamaTools),
|
||||||
|
rankerEnabled: !!config.ollamaToolRankerTarget,
|
||||||
|
});
|
||||||
|
|
||||||
|
const rankerSelection = await new OllamaToolRanker(config).selectTools({
|
||||||
|
userQuery: latestUserTextFromOllamaMessages(messages),
|
||||||
|
availableTools: availableOllamaTools,
|
||||||
|
round,
|
||||||
|
signal,
|
||||||
|
});
|
||||||
|
|
||||||
|
activeToolNames = rankerSelection.selectedNames;
|
||||||
|
if (rankerSelection.tools.length > 0) {
|
||||||
|
request.tools = rankerSelection.tools;
|
||||||
|
} else {
|
||||||
|
delete request.tools;
|
||||||
|
}
|
||||||
|
|
||||||
|
aiLog("debug", "ollama.tools.selected", {
|
||||||
|
round,
|
||||||
|
tools: activeToolNames,
|
||||||
|
count: activeToolNames.length,
|
||||||
|
usedRanker: rankerSelection.usedRanker,
|
||||||
|
missing: rankerSelection.missing,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
const response = await ollama.chat({
|
||||||
|
...request,
|
||||||
|
stream: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const message = response.message;
|
||||||
|
const rawContent = message?.content ?? "";
|
||||||
|
|
||||||
|
const nativeCalls = dedupeToolCalls(
|
||||||
|
normalizeOllamaToolCalls(
|
||||||
|
message?.tool_calls as readonly OllamaToolCallLike[] | undefined,
|
||||||
|
round,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const responseText = rawContent;
|
||||||
|
|
||||||
|
if (looksLikeToolRankerJson(responseText)) {
|
||||||
|
aiLog("error", "ollama.response.looks_like_tool_ranker_json", {
|
||||||
|
round,
|
||||||
|
preview: responseText.slice(0, 800),
|
||||||
|
target: aiLogProviderTarget(target),
|
||||||
|
});
|
||||||
|
throw new Error("Ollama chat model returned tool-ranker JSON. Check that OLLAMA chat target and OLLAMA tools/ranker target are not mixed up.");
|
||||||
|
}
|
||||||
|
|
||||||
|
streamMessage.append(responseText);
|
||||||
|
|
||||||
|
aiLog("debug", "ollama.response.received", {
|
||||||
|
round,
|
||||||
|
duration: aiLogDuration(roundStartedAt),
|
||||||
|
textChars: responseText.length,
|
||||||
|
nativeToolCallCount: nativeCalls.length,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!nativeCalls.length) {
|
||||||
|
aiLog("success", "ollama.run.done", {round, duration: aiLogDuration(runnerStartedAt)});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const calls = nativeCalls;
|
||||||
|
|
||||||
|
aiLog("info", "ollama.tool_calls", {
|
||||||
|
round,
|
||||||
|
calls: calls.map(aiLogToolCall),
|
||||||
|
});
|
||||||
|
|
||||||
|
messages.push({
|
||||||
|
role: "assistant",
|
||||||
|
content: responseText,
|
||||||
|
tool_calls: calls.map(c => ({
|
||||||
|
function: {
|
||||||
|
name: c.name,
|
||||||
|
arguments: safeJsonParseObject(c.argumentsText),
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
appendOllamaToolResults(
|
||||||
|
messages,
|
||||||
|
calls,
|
||||||
|
await executeToolBatch(calls, streamMessage, toolContext, toolMemory),
|
||||||
|
);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await ollama.chat({
|
||||||
|
...request,
|
||||||
|
stream: true
|
||||||
|
});
|
||||||
|
|
||||||
|
aiLog("debug", "ollama.stream.open", {round});
|
||||||
|
const calls: ToolCallData[] = [];
|
||||||
|
const roundTextStart = streamMessage.getText().length;
|
||||||
|
const abortOllamaResponse = () => response.abort?.();
|
||||||
|
signal.addEventListener("abort", abortOllamaResponse, {once: true});
|
||||||
|
if (signal.aborted) abortOllamaResponse();
|
||||||
|
try {
|
||||||
|
for await (const chunk of response) {
|
||||||
|
const localToolCalls: ToolCallData[] = [];
|
||||||
|
|
||||||
|
localToolCalls.push(...normalizeOllamaToolCalls(
|
||||||
|
chunk.message.tool_calls as readonly OllamaToolCallLike[] | undefined,
|
||||||
|
round,
|
||||||
|
));
|
||||||
|
|
||||||
|
const newStatus = roundStatus(round, firstRoundStatus, chunk.message.content, localToolCalls, !!chunk.message.thinking);
|
||||||
|
const previousStatus = streamMessage.getStatus();
|
||||||
|
if (newStatus && newStatus !== Environment.waitThinkText) {
|
||||||
|
streamMessage.setStatus(newStatus);
|
||||||
|
} else {
|
||||||
|
streamMessage.clearStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streamMessage.getStatus() !== previousStatus && previousStatus && newStatus !== Environment.waitThinkText) {
|
||||||
|
await streamMessage.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signal.aborted) {
|
||||||
|
response.abort?.();
|
||||||
|
throw new Error("Aborted");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(chunk.message?.thinking && streamMessage.getStatus() !== Environment.reasoningText)) {
|
||||||
|
streamMessage.append(chunk.message?.content ?? "");
|
||||||
|
}
|
||||||
|
|
||||||
|
calls.push(...normalizeOllamaToolCalls(
|
||||||
|
chunk.message?.tool_calls as readonly OllamaToolCallLike[] | undefined,
|
||||||
|
round,
|
||||||
|
));
|
||||||
|
|
||||||
|
if (chunk.done) {
|
||||||
|
aiLog("debug", "ollama.stream.done", {
|
||||||
|
round,
|
||||||
|
duration: aiLogDuration(roundStartedAt),
|
||||||
|
textChars: streamMessage.getText().slice(roundTextStart).length,
|
||||||
|
toolCallCount: calls.length,
|
||||||
|
});
|
||||||
|
await streamMessage.flush(streamMessage.regenerateKeyboard(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
signal.removeEventListener("abort", abortOllamaResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
const streamedRoundText = streamMessage.getText().slice(roundTextStart);
|
||||||
|
if (!calls.length && looksLikeToolRankerJson(streamedRoundText)) {
|
||||||
|
streamMessage.replaceText(streamMessage.getText().slice(0, roundTextStart));
|
||||||
|
aiLog("error", "ollama.response.looks_like_tool_ranker_json", {
|
||||||
|
round,
|
||||||
|
preview: streamedRoundText.slice(0, 800),
|
||||||
|
target: aiLogProviderTarget(target),
|
||||||
|
});
|
||||||
|
throw new Error("Ollama chat model returned tool-ranker JSON. Check that OLLAMA chat target and OLLAMA tools/ranker target are not mixed up.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!calls.length) {
|
||||||
|
aiLog("success", "ollama.run.done", {
|
||||||
|
round,
|
||||||
|
duration: aiLogDuration(runnerStartedAt),
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
calls.splice(0, calls.length, ...dedupeToolCalls(calls));
|
||||||
|
|
||||||
|
aiLog("info", "ollama.tool_calls", {
|
||||||
|
round,
|
||||||
|
calls: calls.map(aiLogToolCall),
|
||||||
|
});
|
||||||
|
|
||||||
|
const roundText = streamMessage.getText().slice(roundTextStart);
|
||||||
|
|
||||||
|
messages.push({
|
||||||
|
role: "assistant",
|
||||||
|
content: roundText,
|
||||||
|
tool_calls: calls.map(c => ({
|
||||||
|
function: {
|
||||||
|
name: c.name,
|
||||||
|
arguments: safeJsonParseObject(c.argumentsText),
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
const toolResults = await executeToolBatch(calls, streamMessage, toolContext, toolMemory);
|
||||||
|
|
||||||
|
let successGetNoteFileResult: GetNoteFileResult | undefined = undefined;
|
||||||
|
|
||||||
|
for (const toolResult of toolResults) {
|
||||||
|
try {
|
||||||
|
const raw = JSON.parse(toolResult);
|
||||||
|
const res = GetNoteFileResultSchema.safeParse(raw);
|
||||||
|
|
||||||
|
if (res.success && res.data.success) {
|
||||||
|
successGetNoteFileResult = res.data;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Not every tool result is JSON.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (successGetNoteFileResult && "attachment" in successGetNoteFileResult) {
|
||||||
|
await bot.sendDocument({
|
||||||
|
chat_id: msg.chat.id,
|
||||||
|
reply_parameters: {
|
||||||
|
message_id: msg.message_id,
|
||||||
|
},
|
||||||
|
document: fs.createReadStream(path.join(notesDir, successGetNoteFileResult.attachment.relativePath)),
|
||||||
|
}).catch(logError);
|
||||||
|
}
|
||||||
|
|
||||||
|
appendOllamaToolResults(messages, calls, toolResults);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (interval) clearInterval(interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class OllamaProviderRunner {
|
||||||
|
static run = runOllama;
|
||||||
|
}
|
||||||
@@ -0,0 +1,426 @@
|
|||||||
|
// OpenAI and OpenAI-compatible provider runners extracted from unified-ai-runner.ts.
|
||||||
|
import {Message} from "typescript-telegram-bot-api";
|
||||||
|
import {Environment} from "../common/environment";
|
||||||
|
import {getOpenAITools} from "./tool-mappers";
|
||||||
|
import {TelegramStreamMessage} from "./telegram-stream-message";
|
||||||
|
import {ToolRuntimeContext} from "./tools/runtime";
|
||||||
|
import {OpenAIChatMessage} from "./openai-chat-message";
|
||||||
|
import type {ResponseCreateParamsNonStreaming, ResponseCreateParamsStreaming, ResponseInputItem, ResponseStreamEvent} from "openai/resources/responses/responses";
|
||||||
|
import type {ChatCompletionCreateParamsNonStreaming, ChatCompletionCreateParamsStreaming} from "openai/resources/chat/completions";
|
||||||
|
import {createGeminiOpenAiClient, createOpenAiClient} from "./ai-runtime-target";
|
||||||
|
import {aiLog, aiLogDuration, aiLogMessageIdentity, aiLogProviderTarget, aiLogToolCall} from "./ai-logger";
|
||||||
|
|
||||||
|
import {AsyncIterableStream, MAX_TOOL_ROUNDS, OPENAI_IMAGE_PARTIALS, OpenAiChatCompletionResponseLike, OpenAiChatToolCallLike, OpenAiCompatibleChatMessage, OpenAiCompatibleContentPart, OpenAiResponseLike, OpenAiResponseOutputItem, RuntimeConfigSnapshot, ToolCallData, StreamingToolCallAccumulator, collectOpenAiResponseFunctionCalls, collectOpenAiResponseImages, collectOpenAiResponseText, executeToolBatch, getOpenAIResponsesToolsWithImage, openAiResponseItemCallId, safeJsonParseObject, showOpenAiGeneratedImage, ToolExecutionMemory, isRecord, roundStatus, OpenAiChatCompletionStreamChunkLike} from "./unified-ai-runner.shared";
|
||||||
|
|
||||||
|
export async function runOpenAi(
|
||||||
|
messages: OpenAIChatMessage[],
|
||||||
|
streamMessage: TelegramStreamMessage,
|
||||||
|
signal: AbortSignal,
|
||||||
|
stream: boolean,
|
||||||
|
firstRoundStatus: string,
|
||||||
|
sourceMessage: Message,
|
||||||
|
config: RuntimeConfigSnapshot,
|
||||||
|
toolContext: ToolRuntimeContext,
|
||||||
|
): Promise<void> {
|
||||||
|
// TODO: 13.05.2026: remove
|
||||||
|
firstRoundStatus;
|
||||||
|
const runnerStartedAt = Date.now();
|
||||||
|
let responseInput: unknown[] = [...messages];
|
||||||
|
const openAi = createOpenAiClient(config.openAiChatTarget);
|
||||||
|
|
||||||
|
aiLog("info", "openai.run.start", {
|
||||||
|
stream,
|
||||||
|
target: aiLogProviderTarget(config.openAiChatTarget),
|
||||||
|
imageTarget: aiLogProviderTarget(config.openAiImageTarget),
|
||||||
|
inputMessages: messages.length,
|
||||||
|
sourceMessage: aiLogMessageIdentity(sourceMessage),
|
||||||
|
hasToolInputFiles: !!toolContext.pythonInputFiles?.length,
|
||||||
|
});
|
||||||
|
|
||||||
|
const toolMemory: ToolExecutionMemory = new Map();
|
||||||
|
|
||||||
|
for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
|
||||||
|
const roundStartedAt = Date.now();
|
||||||
|
aiLog("debug", "openai.round.start", {round, inputItems: responseInput.length, stream});
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
const request: ResponseCreateParamsNonStreaming = {
|
||||||
|
model: config.openAiChatTarget.model,
|
||||||
|
input: responseInput as ResponseInputItem[],
|
||||||
|
// TODO: 13.05.2026, Danil Nikolaev: fix
|
||||||
|
tools: getOpenAIResponsesToolsWithImage(config) as any,
|
||||||
|
instructions: config.systemPrompt,
|
||||||
|
};
|
||||||
|
const response = await openAi.responses.create(request, {signal}) as unknown as OpenAiResponseLike;
|
||||||
|
|
||||||
|
const responseText = collectOpenAiResponseText(response);
|
||||||
|
streamMessage.append(responseText);
|
||||||
|
aiLog("debug", "openai.response.received", {
|
||||||
|
round,
|
||||||
|
duration: aiLogDuration(roundStartedAt),
|
||||||
|
textChars: responseText.length,
|
||||||
|
outputItems: response?.output?.length ?? 0,
|
||||||
|
});
|
||||||
|
const images = collectOpenAiResponseImages(response);
|
||||||
|
if (images.length) {
|
||||||
|
await showOpenAiGeneratedImage(
|
||||||
|
streamMessage,
|
||||||
|
sourceMessage,
|
||||||
|
images[images.length - 1],
|
||||||
|
`final_${round}`,
|
||||||
|
Environment.getImageGenDoneText(config.openAiImageTarget.model),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const calls = collectOpenAiResponseFunctionCalls(response);
|
||||||
|
aiLog(calls.length ? "info" : "success", calls.length ? "openai.tool_calls" : "openai.run.done", {
|
||||||
|
round,
|
||||||
|
duration: calls.length ? aiLogDuration(roundStartedAt) : aiLogDuration(runnerStartedAt),
|
||||||
|
calls: calls.map(call => ({
|
||||||
|
id: call.callId,
|
||||||
|
name: call.name,
|
||||||
|
arguments: safeJsonParseObject(call.argumentsText)
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
if (!calls.length) return;
|
||||||
|
|
||||||
|
const toolCalls = calls.map(call => ({
|
||||||
|
id: call.callId,
|
||||||
|
name: call.name,
|
||||||
|
argumentsText: call.argumentsText,
|
||||||
|
}));
|
||||||
|
const toolResults = await executeToolBatch(toolCalls, streamMessage, toolContext, toolMemory);
|
||||||
|
const toolOutputs = calls.map((call, index) => ({
|
||||||
|
type: "function_call_output" as const,
|
||||||
|
call_id: call.callId,
|
||||||
|
output: toolResults[index] ?? "",
|
||||||
|
}));
|
||||||
|
responseInput = [...responseInput, ...(response.output ?? []), ...toolOutputs];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let completedResponse: OpenAiResponseLike | null = null;
|
||||||
|
const request: ResponseCreateParamsStreaming = {
|
||||||
|
model: config.openAiChatTarget.model,
|
||||||
|
input: responseInput as ResponseInputItem[],
|
||||||
|
stream: true,
|
||||||
|
// TODO: 13.05.2026, Danil Nikolaev: fix
|
||||||
|
tools: getOpenAIResponsesToolsWithImage(config) as any,
|
||||||
|
};
|
||||||
|
const response = await openAi.responses.create(request, {signal}) as unknown as AsyncIterableStream<ResponseStreamEvent>;
|
||||||
|
|
||||||
|
aiLog("debug", "openai.stream.open", {round});
|
||||||
|
|
||||||
|
let localToolCalls: ToolCallData[] = [];
|
||||||
|
for await (const event of response) {
|
||||||
|
if (signal.aborted) throw new Error("Aborted");
|
||||||
|
|
||||||
|
switch (event.type) {
|
||||||
|
case "response.output_text.delta":
|
||||||
|
streamMessage.append(event.delta ?? "");
|
||||||
|
break;
|
||||||
|
case "response.image_generation_call.in_progress":
|
||||||
|
streamMessage.setStatus(Environment.startingImageGenText);
|
||||||
|
await streamMessage.flush();
|
||||||
|
break;
|
||||||
|
case "response.image_generation_call.generating":
|
||||||
|
streamMessage.setStatus(Environment.imageGenText);
|
||||||
|
await streamMessage.flush();
|
||||||
|
break;
|
||||||
|
case "response.image_generation_call.partial_image": {
|
||||||
|
const iteration = (event.partial_image_index ?? 0) + 1;
|
||||||
|
await showOpenAiGeneratedImage(
|
||||||
|
streamMessage,
|
||||||
|
sourceMessage,
|
||||||
|
event.partial_image_b64,
|
||||||
|
`partial_${round}_${iteration}`,
|
||||||
|
Environment.getPartialImageGenText(iteration, OPENAI_IMAGE_PARTIALS),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "response.image_generation_call.completed":
|
||||||
|
streamMessage.setStatus(Environment.finalizingImageGenText);
|
||||||
|
await streamMessage.flush();
|
||||||
|
break;
|
||||||
|
case "response.output_item.added":
|
||||||
|
if (event.item.type === "function_call" && event.item.name) {
|
||||||
|
const item = event.item as OpenAiResponseOutputItem & { id?: string };
|
||||||
|
localToolCalls.push({
|
||||||
|
id: openAiResponseItemCallId(item),
|
||||||
|
name: item.name ?? "",
|
||||||
|
argumentsText: item.arguments ?? "{}",
|
||||||
|
});
|
||||||
|
|
||||||
|
aiLog("info", "openai.stream.tool_call.added", {
|
||||||
|
round,
|
||||||
|
toolCalls: localToolCalls.map(aiLogToolCall)
|
||||||
|
});
|
||||||
|
streamMessage.setStatus(Environment.getUseToolText(localToolCalls));
|
||||||
|
await streamMessage.flush();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "response.output_item.done":
|
||||||
|
if (event.item.type === "function_call" && event.item.name) {
|
||||||
|
const item = event.item as OpenAiResponseOutputItem & { id?: string };
|
||||||
|
const itemId = openAiResponseItemCallId(item);
|
||||||
|
const index = localToolCalls.findIndex(c => c.id === itemId);
|
||||||
|
if (index !== -1) {
|
||||||
|
localToolCalls.splice(index, 1);
|
||||||
|
if (localToolCalls.length === 0) {
|
||||||
|
streamMessage.clearStatus();
|
||||||
|
} else {
|
||||||
|
streamMessage.setStatus(Environment.getUseToolText(localToolCalls));
|
||||||
|
}
|
||||||
|
await streamMessage.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "response.function_call_arguments.delta":
|
||||||
|
break;
|
||||||
|
case "response.function_call_arguments.done":
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "response.completed":
|
||||||
|
completedResponse = event.response as unknown as OpenAiResponseLike;
|
||||||
|
break;
|
||||||
|
case "response.failed":
|
||||||
|
throw new Error(event.response?.error?.message ?? "OpenAI response failed");
|
||||||
|
case "error":
|
||||||
|
throw new Error(event.message ?? event?.message ?? "OpenAI stream error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!completedResponse) throw new Error("OpenAI did not return the final response.completed event.");
|
||||||
|
|
||||||
|
aiLog("debug", "openai.stream.completed", {
|
||||||
|
round,
|
||||||
|
duration: aiLogDuration(roundStartedAt),
|
||||||
|
outputItems: completedResponse?.output?.length ?? 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const images = collectOpenAiResponseImages(completedResponse);
|
||||||
|
if (images.length) {
|
||||||
|
await showOpenAiGeneratedImage(
|
||||||
|
streamMessage,
|
||||||
|
sourceMessage,
|
||||||
|
images[images.length - 1],
|
||||||
|
`final_${round}`,
|
||||||
|
Environment.getImageGenDoneText(config.openAiImageTarget.model),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const calls = collectOpenAiResponseFunctionCalls(completedResponse);
|
||||||
|
aiLog(calls.length ? "info" : "success", calls.length ? "openai.tool_calls" : "openai.run.done", {
|
||||||
|
round,
|
||||||
|
duration: calls.length ? aiLogDuration(roundStartedAt) : aiLogDuration(runnerStartedAt),
|
||||||
|
calls: calls.map(call => ({
|
||||||
|
id: call.callId,
|
||||||
|
name: call.name,
|
||||||
|
arguments: safeJsonParseObject(call.argumentsText)
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
if (!calls.length) return;
|
||||||
|
|
||||||
|
const toolCalls = calls.map(call => ({
|
||||||
|
id: call.callId,
|
||||||
|
name: call.name,
|
||||||
|
argumentsText: call.argumentsText,
|
||||||
|
}));
|
||||||
|
const toolResults = await executeToolBatch(toolCalls, streamMessage, toolContext, toolMemory);
|
||||||
|
const toolOutputs = calls.map((call, index) => ({
|
||||||
|
type: "function_call_output",
|
||||||
|
call_id: call.callId,
|
||||||
|
output: toolResults[index] ?? "",
|
||||||
|
}));
|
||||||
|
responseInput = [...responseInput, ...(completedResponse.output ?? []), ...toolOutputs];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function openAiResponseContentToText(content: unknown): string {
|
||||||
|
if (typeof content === "string") return content;
|
||||||
|
if (!Array.isArray(content)) return "";
|
||||||
|
return content.map(part => isRecord(part) ? part.text ?? part.content ?? part.refusal ?? "" : "").join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function openAiResponseMessagesToChatCompletions(messages: OpenAIChatMessage[]): OpenAiCompatibleChatMessage[] {
|
||||||
|
return messages.map((message): OpenAiCompatibleChatMessage => {
|
||||||
|
if (message.role === "system" || message.role === "assistant") {
|
||||||
|
return {
|
||||||
|
role: message.role,
|
||||||
|
content: openAiResponseContentToText(message.content),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = Array.isArray(message.content)
|
||||||
|
? message.content.map((part): OpenAiCompatibleContentPart => {
|
||||||
|
if (isRecord(part) && part.type === "input_image") {
|
||||||
|
return {
|
||||||
|
type: "image_url",
|
||||||
|
image_url: {url: String(part.image_url ?? "")},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "text",
|
||||||
|
text: isRecord(part) && typeof part.text === "string" ? part.text : "",
|
||||||
|
};
|
||||||
|
})
|
||||||
|
: message.content;
|
||||||
|
|
||||||
|
return {role: "user", content};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeOpenAiChatToolCalls(toolCalls: OpenAiChatToolCallLike[] = []): ToolCallData[] {
|
||||||
|
return toolCalls.map((call, i) => ({
|
||||||
|
id: call.id || `openai_chat_${Date.now()}_${i}`,
|
||||||
|
name: call.function?.name || call.name || "",
|
||||||
|
argumentsText: typeof call.function?.arguments === "string"
|
||||||
|
? call.function.arguments
|
||||||
|
: JSON.stringify(call.function?.arguments ?? call.arguments ?? {}),
|
||||||
|
})).filter(call => call.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function appendOpenAiChatToolResults(
|
||||||
|
messages: OpenAiCompatibleChatMessage[],
|
||||||
|
calls: ToolCallData[],
|
||||||
|
results: string[],
|
||||||
|
): Promise<void> {
|
||||||
|
for (const [index, call] of calls.entries()) {
|
||||||
|
messages.push({
|
||||||
|
role: "tool",
|
||||||
|
tool_call_id: call.id,
|
||||||
|
content: results[index] ?? "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function runOpenAiCompatibleChat(
|
||||||
|
messages: OpenAIChatMessage[],
|
||||||
|
streamMessage: TelegramStreamMessage,
|
||||||
|
signal: AbortSignal,
|
||||||
|
stream: boolean,
|
||||||
|
firstRoundStatus: string,
|
||||||
|
config: RuntimeConfigSnapshot,
|
||||||
|
toolContext: ToolRuntimeContext,
|
||||||
|
): Promise<void> {
|
||||||
|
const runnerStartedAt = Date.now();
|
||||||
|
const geminiOpenAi = createGeminiOpenAiClient(config.geminiChatTarget);
|
||||||
|
const chatMessages = openAiResponseMessagesToChatCompletions(messages);
|
||||||
|
const toolMemory: ToolExecutionMemory = new Map();
|
||||||
|
|
||||||
|
aiLog("info", "openai_compatible.run.start", {
|
||||||
|
stream,
|
||||||
|
target: aiLogProviderTarget(config.geminiChatTarget),
|
||||||
|
inputMessages: messages.length,
|
||||||
|
chatMessages: chatMessages.length,
|
||||||
|
hasToolInputFiles: !!toolContext.pythonInputFiles?.length,
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
|
||||||
|
const roundStartedAt = Date.now();
|
||||||
|
aiLog("debug", "openai_compatible.round.start", {round, messages: chatMessages.length, stream});
|
||||||
|
streamMessage.setStatus(roundStatus(round, firstRoundStatus) ?? "");
|
||||||
|
await streamMessage.flush();
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
const request: ChatCompletionCreateParamsNonStreaming = {
|
||||||
|
model: config.geminiChatTarget.model,
|
||||||
|
messages: chatMessages,
|
||||||
|
tools: getOpenAITools(),
|
||||||
|
temperature: 0.6,
|
||||||
|
};
|
||||||
|
const response = await geminiOpenAi.chat.completions.create(request, {signal}) as unknown as OpenAiChatCompletionResponseLike;
|
||||||
|
const message = response.choices?.[0]?.message;
|
||||||
|
streamMessage.append(message?.content ?? "");
|
||||||
|
const calls = normalizeOpenAiChatToolCalls(message?.tool_calls ?? []);
|
||||||
|
aiLog(calls.length ? "info" : "success", calls.length ? "openai_compatible.tool_calls" : "openai_compatible.run.done", {
|
||||||
|
round,
|
||||||
|
duration: calls.length ? aiLogDuration(roundStartedAt) : aiLogDuration(runnerStartedAt),
|
||||||
|
textChars: message?.content?.length ?? 0,
|
||||||
|
calls: calls.map(aiLogToolCall),
|
||||||
|
});
|
||||||
|
if (!calls.length) return;
|
||||||
|
|
||||||
|
chatMessages.push({
|
||||||
|
role: "assistant",
|
||||||
|
content: message?.content ?? "",
|
||||||
|
tool_calls: calls.map(call => ({
|
||||||
|
id: call.id,
|
||||||
|
type: "function" as const,
|
||||||
|
function: {
|
||||||
|
name: call.name,
|
||||||
|
arguments: call.argumentsText,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
await appendOpenAiChatToolResults(chatMessages, calls, await executeToolBatch(calls, streamMessage, toolContext, toolMemory));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const request: ChatCompletionCreateParamsStreaming = {
|
||||||
|
model: config.geminiChatTarget.model,
|
||||||
|
messages: chatMessages,
|
||||||
|
tools: getOpenAITools(),
|
||||||
|
temperature: 0.6,
|
||||||
|
stream: true,
|
||||||
|
};
|
||||||
|
const response = await geminiOpenAi.chat.completions.create(request, {signal}) as unknown as AsyncIterableStream<OpenAiChatCompletionStreamChunkLike>;
|
||||||
|
|
||||||
|
aiLog("debug", "openai_compatible.stream.open", {round});
|
||||||
|
// const streamToolCalls: OpenAiChatToolCallLike[] = [];
|
||||||
|
const roundTextStart = streamMessage.getText().length;
|
||||||
|
const toolCallAccumulator = new StreamingToolCallAccumulator("openai_chat_stream", round);
|
||||||
|
let calls: ToolCallData[] = [];
|
||||||
|
|
||||||
|
for await (const chunk of response) {
|
||||||
|
if (signal.aborted) throw new Error("Aborted");
|
||||||
|
|
||||||
|
const delta = chunk.choices?.[0]?.delta;
|
||||||
|
streamMessage.append(delta?.content ?? "");
|
||||||
|
|
||||||
|
if (delta?.tool_calls?.length) {
|
||||||
|
calls = toolCallAccumulator.add(delta.tool_calls);
|
||||||
|
streamMessage.setStatus(Environment.getUseToolText(calls));
|
||||||
|
await streamMessage.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// const calls = collectOpenAiChatStreamToolCalls(streamToolCalls);
|
||||||
|
aiLog(calls.length ? "info" : "success", calls.length ? "openai_compatible.tool_calls" : "openai_compatible.run.done", {
|
||||||
|
round,
|
||||||
|
duration: calls.length ? aiLogDuration(roundStartedAt) : aiLogDuration(runnerStartedAt),
|
||||||
|
textChars: streamMessage.getText().slice(roundTextStart).length,
|
||||||
|
calls: calls.map(aiLogToolCall),
|
||||||
|
});
|
||||||
|
if (!calls.length) return;
|
||||||
|
|
||||||
|
const roundText = streamMessage.getText().slice(roundTextStart);
|
||||||
|
chatMessages.push({
|
||||||
|
role: "assistant",
|
||||||
|
content: roundText,
|
||||||
|
tool_calls: calls.map(call => ({
|
||||||
|
id: call.id,
|
||||||
|
type: "function",
|
||||||
|
function: {
|
||||||
|
name: call.name,
|
||||||
|
arguments: call.argumentsText,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
await appendOpenAiChatToolResults(chatMessages, calls, await executeToolBatch(calls, streamMessage, toolContext, toolMemory));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class OpenAiProviderRunner {
|
||||||
|
static run = runOpenAi;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class OpenAiCompatibleProviderRunner {
|
||||||
|
static run = runOpenAiCompatibleChat;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,225 @@
|
|||||||
|
import {Tool} from "ollama";
|
||||||
|
import {AiRuntimeTarget, createOllamaClient} from "./ai-runtime-target";
|
||||||
|
import {aiLog, aiLogDuration, aiLogProviderTarget} from "./ai-logger";
|
||||||
|
import {allToolSchemaNames, isRecord, JsonObject, RuntimeConfigSnapshot, safeJsonParseObject, toolSchemaNames} from "./unified-ai-runner.shared";
|
||||||
|
|
||||||
|
type RankedToolStep = {
|
||||||
|
t: string | string[];
|
||||||
|
h?: string;
|
||||||
|
from?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type RankedToolPlan = {
|
||||||
|
s?: RankedToolStep[];
|
||||||
|
m?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ToolRankerSelection = {
|
||||||
|
tools: Tool[];
|
||||||
|
selectedNames: string[];
|
||||||
|
missing: string;
|
||||||
|
raw: string;
|
||||||
|
usedRanker: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class OllamaToolRanker {
|
||||||
|
constructor(private readonly config: RuntimeConfigSnapshot) {}
|
||||||
|
|
||||||
|
async selectTools(args: {
|
||||||
|
userQuery: string;
|
||||||
|
availableTools: Tool[];
|
||||||
|
round: number;
|
||||||
|
signal: AbortSignal;
|
||||||
|
}): Promise<ToolRankerSelection> {
|
||||||
|
const {availableTools, round, signal, userQuery} = args;
|
||||||
|
const target = this.config.ollamaToolRankerTarget;
|
||||||
|
|
||||||
|
if (!availableTools.length) {
|
||||||
|
return {tools: [], selectedNames: [], missing: "", raw: "", usedRanker: false};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ranker disabled/unconfigured: keep old behavior and expose all allowed tools.
|
||||||
|
if (!target?.model) {
|
||||||
|
return {
|
||||||
|
tools: availableTools,
|
||||||
|
selectedNames: allToolSchemaNames(availableTools),
|
||||||
|
missing: "",
|
||||||
|
raw: "",
|
||||||
|
usedRanker: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const startedAt = Date.now();
|
||||||
|
const availableNames = new Set(allToolSchemaNames(availableTools));
|
||||||
|
const prompt = this.config.rankerToolPrompt?.trim() || DEFAULT_TOOL_RANKER_PROMPT;
|
||||||
|
const toolsForPrompt = availableTools.map(tool => ({
|
||||||
|
names: toolSchemaNames(tool),
|
||||||
|
schema: tool,
|
||||||
|
}));
|
||||||
|
|
||||||
|
aiLog("debug", "ollama.tool_ranker.start", {
|
||||||
|
round,
|
||||||
|
target: aiLogProviderTarget(target),
|
||||||
|
queryChars: userQuery.length,
|
||||||
|
availableTools: [...availableNames],
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const ollama = createOllamaClient(target as AiRuntimeTarget);
|
||||||
|
const response = await ollama.chat({
|
||||||
|
model: target.model,
|
||||||
|
messages: [
|
||||||
|
{role: "system", content: prompt},
|
||||||
|
{
|
||||||
|
role: "user",
|
||||||
|
content: JSON.stringify({
|
||||||
|
q: userQuery,
|
||||||
|
tools: toolsForPrompt,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stream: false,
|
||||||
|
options: {
|
||||||
|
temperature: 0,
|
||||||
|
num_ctx: 8192,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (signal.aborted) throw new Error("Aborted");
|
||||||
|
|
||||||
|
const raw = response.message?.content?.trim() ?? "";
|
||||||
|
const plan = parseToolRankerPlan(raw);
|
||||||
|
const selectedNames = normalizeToolRankerNames(plan, availableNames);
|
||||||
|
const selectedNameSet = new Set(selectedNames);
|
||||||
|
const tools = availableTools.filter(tool => toolSchemaNames(tool).some(name => selectedNameSet.has(name)));
|
||||||
|
const missing = typeof plan?.m === "string" ? plan.m.trim() : "";
|
||||||
|
|
||||||
|
aiLog("debug", "ollama.tool_ranker.done", {
|
||||||
|
round,
|
||||||
|
duration: aiLogDuration(startedAt),
|
||||||
|
selectedNames,
|
||||||
|
selectedCount: tools.length,
|
||||||
|
missing,
|
||||||
|
rawPreview: raw.slice(0, 800),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Important: if the plan is valid and empty, use NO tools. Do not fall back to all tools.
|
||||||
|
return {tools, selectedNames, missing, raw, usedRanker: true};
|
||||||
|
} catch (error) {
|
||||||
|
if (String(error).includes("Aborted")) throw error;
|
||||||
|
|
||||||
|
aiLog("warn", "ollama.tool_ranker.failed.fallback_all_allowed", {
|
||||||
|
round,
|
||||||
|
target: aiLogProviderTarget(target),
|
||||||
|
duration: aiLogDuration(startedAt),
|
||||||
|
error,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ranker transport/model failure is different from "ranker returned empty plan".
|
||||||
|
// In that case, preserve availability rather than silently disabling tools.
|
||||||
|
return {
|
||||||
|
tools: availableTools,
|
||||||
|
selectedNames: allToolSchemaNames(availableTools),
|
||||||
|
missing: "",
|
||||||
|
raw: "",
|
||||||
|
usedRanker: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function latestUserTextFromOllamaMessages(messages: readonly { role?: string; content?: unknown }[]): string {
|
||||||
|
for (let i = messages.length - 1; i >= 0; i--) {
|
||||||
|
const message = messages[i];
|
||||||
|
if (message?.role !== "user") continue;
|
||||||
|
if (typeof message.content === "string") return message.content;
|
||||||
|
if (Array.isArray(message.content)) {
|
||||||
|
return message.content
|
||||||
|
.map(part => isRecord(part) && typeof part.text === "string" ? part.text : "")
|
||||||
|
.filter(Boolean)
|
||||||
|
.join("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function looksLikeToolRankerJson(text: string): boolean {
|
||||||
|
const parsed = safeJsonParseObject(extractJsonObjectText(text) ?? text);
|
||||||
|
return Array.isArray(parsed.s) && typeof parsed.m === "string";
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseToolRankerPlan(raw: string): RankedToolPlan | undefined {
|
||||||
|
const jsonText = extractJsonObjectText(raw);
|
||||||
|
if (!jsonText) return undefined;
|
||||||
|
|
||||||
|
const parsed = safeJsonParseObject(jsonText) as JsonObject;
|
||||||
|
if (!Array.isArray(parsed.s)) return undefined;
|
||||||
|
|
||||||
|
return parsed as RankedToolPlan;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeToolRankerNames(plan: RankedToolPlan | undefined, availableNames: Set<string>): string[] {
|
||||||
|
if (!plan?.s?.length) return [];
|
||||||
|
|
||||||
|
const result: string[] = [];
|
||||||
|
for (const step of plan.s) {
|
||||||
|
const rawNames = Array.isArray(step.t) ? step.t : [step.t];
|
||||||
|
for (const rawName of rawNames) {
|
||||||
|
if (typeof rawName !== "string") continue;
|
||||||
|
const name = rawName.trim();
|
||||||
|
if (availableNames.has(name) && !result.includes(name)) {
|
||||||
|
result.push(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractJsonObjectText(raw: string): string | undefined {
|
||||||
|
const text = raw.trim()
|
||||||
|
.replace(/^```(?:json)?\s*/i, "")
|
||||||
|
.replace(/\s*```$/i, "")
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
const start = text.indexOf("{");
|
||||||
|
if (start === -1) return undefined;
|
||||||
|
|
||||||
|
let depth = 0;
|
||||||
|
let inString = false;
|
||||||
|
let escaped = false;
|
||||||
|
|
||||||
|
for (let i = start; i < text.length; i++) {
|
||||||
|
const ch = text[i];
|
||||||
|
|
||||||
|
if (escaped) {
|
||||||
|
escaped = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === "\\") {
|
||||||
|
escaped = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === '"') {
|
||||||
|
inString = !inString;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inString) continue;
|
||||||
|
|
||||||
|
if (ch === "{") depth++;
|
||||||
|
if (ch === "}") depth--;
|
||||||
|
|
||||||
|
if (depth === 0) {
|
||||||
|
return text.slice(start, i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_TOOL_RANKER_PROMPT = `You are a tool router. Return strict compact JSON only.
|
||||||
|
Schema: {"s":[{"t":"tool_name","h":"short input hint","from":"previous_tool.output_or_empty"}],"m":""}
|
||||||
|
Use tools only when they are needed. If no tool is needed, return {"s":[],"m":""}.
|
||||||
|
Never answer the user. Never explain. Never use markdown.`;
|
||||||
+128
-2067
File diff suppressed because it is too large
Load Diff
@@ -96,8 +96,8 @@ export class AiCancel extends CallbackCommand {
|
|||||||
{method: "editMessageText", chatId: message.chat.id, chatType: message.chat.type}
|
{method: "editMessageText", chatId: message.chat.id, chatType: message.chat.type}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result && result !== true) {
|
if (result) {
|
||||||
await MessageStore.put({...result, text: cancelledText} as Message);
|
await MessageStore.put({...(result as object), text: cancelledText} as Message);
|
||||||
} else {
|
} else {
|
||||||
await MessageStore.put({
|
await MessageStore.put({
|
||||||
chatId: message.chat.id,
|
chatId: message.chat.id,
|
||||||
|
|||||||
+8
-6
@@ -21,8 +21,9 @@ export class Ae extends Command {
|
|||||||
try {
|
try {
|
||||||
let result = this.executeEvaluation(match);
|
let result = this.executeEvaluation(match);
|
||||||
await oldSendMessage(msg, result).catch(async () => await errorPlaceholder(msg));
|
await oldSendMessage(msg, result).catch(async () => await errorPlaceholder(msg));
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
const text = e.message.toString();
|
const error = e instanceof Error ? e : new Error(String(e));
|
||||||
|
const text = error.message.toString();
|
||||||
|
|
||||||
if (text.includes("is not defined")) {
|
if (text.includes("is not defined")) {
|
||||||
await oldSendMessage(msg, Environment.variableNotDefinedText).catch(logError);
|
await oldSendMessage(msg, Environment.variableNotDefinedText).catch(logError);
|
||||||
@@ -30,7 +31,7 @@ export class Ae extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logError(`${text}
|
logError(`${text}
|
||||||
* Stacktrace: ${e.stack}`);
|
* Stacktrace: ${error.stack}`);
|
||||||
|
|
||||||
await oldSendMessage(msg, text).catch(logError);
|
await oldSendMessage(msg, text).catch(logError);
|
||||||
}
|
}
|
||||||
@@ -43,15 +44,16 @@ export class Ae extends Command {
|
|||||||
e = ((typeof e == "string") ? e : JSON.stringify(e));
|
e = ((typeof e == "string") ? e : JSON.stringify(e));
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
const text = e.message.toString();
|
const error = e instanceof Error ? e : new Error(String(e));
|
||||||
|
const text = error.message.toString();
|
||||||
|
|
||||||
if (text.includes("is not defined")) {
|
if (text.includes("is not defined")) {
|
||||||
return Environment.evaluationVariableNotDefinedText;
|
return Environment.evaluationVariableNotDefinedText;
|
||||||
}
|
}
|
||||||
|
|
||||||
logError(`${text}
|
logError(`${text}
|
||||||
* Stacktrace: ${e.stack}`);
|
* Stacktrace: ${error.stack}`);
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export class Distort extends Command {
|
|||||||
}),
|
}),
|
||||||
{method: "sendPhoto", chatId, chatType: msg.chat.type}
|
{method: "sendPhoto", chatId, chatType: msg.chat.type}
|
||||||
);
|
);
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
await oldReplyToMessage(
|
await oldReplyToMessage(
|
||||||
msg, Environment.getDistortFailedText(e)
|
msg, Environment.getDistortFailedText(e)
|
||||||
).catch(logError);
|
).catch(logError);
|
||||||
|
|||||||
+1
-1
@@ -69,7 +69,7 @@ export class Qr extends Command {
|
|||||||
}),
|
}),
|
||||||
{method: "sendPhoto", chatId, chatType: msg.chat.type}
|
{method: "sendPhoto", chatId, chatType: msg.chat.type}
|
||||||
);
|
);
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
await replyToMessage({
|
await replyToMessage({
|
||||||
message: msg,
|
message: msg,
|
||||||
text: Environment.getQrCodeFailedText(e)
|
text: Environment.getQrCodeFailedText(e)
|
||||||
|
|||||||
@@ -1636,8 +1636,8 @@ export class Environment {
|
|||||||
private static getFileMtimeMs(filePath: string): number | undefined {
|
private static getFileMtimeMs(filePath: string): number | undefined {
|
||||||
try {
|
try {
|
||||||
return fs.statSync(filePath).mtimeMs;
|
return fs.statSync(filePath).mtimeMs;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
if (e?.code === "ENOENT") {
|
if ((e as NodeJS.ErrnoException).code === "ENOENT") {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ function normalizeLanguageCode(value: string | undefined | null): string | undef
|
|||||||
function readMtimeMs(filePath: string): number | undefined {
|
function readMtimeMs(filePath: string): number | undefined {
|
||||||
try {
|
try {
|
||||||
return fs.statSync(filePath).mtimeMs;
|
return fs.statSync(filePath).mtimeMs;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
if (e?.code === "ENOENT") return undefined;
|
if ((e as NodeJS.ErrnoException).code === "ENOENT") return undefined;
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
export type OllamaRequest = {
|
export type OllamaRequest = {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
stream: unknown;
|
||||||
stream: any;
|
|
||||||
done: boolean;
|
done: boolean;
|
||||||
fromId: number;
|
fromId: number;
|
||||||
chatId: number;
|
chatId: number;
|
||||||
|
|||||||
@@ -68,11 +68,12 @@ export class ShellCommandRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {stdout, stderr};
|
return {stdout, stderr};
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error("Error code:", error.code);
|
const err = error as Partial<Error & {code: unknown; stdout: string; stderr: string}>;
|
||||||
console.error("Stderr:", error.stderr);
|
console.error("Error code:", err.code);
|
||||||
|
console.error("Stderr:", err.stderr);
|
||||||
|
|
||||||
return {stdout: error.stdout ?? null, stderr: error.stderr ?? error.message};
|
return {stdout: err.stdout ?? null, stderr: err.stderr ?? err.message ?? String(error)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-11
@@ -1,4 +1,5 @@
|
|||||||
import * as si from "systeminformation";
|
import * as si from "systeminformation";
|
||||||
|
import {redactLogValue} from "../ai/ai-logger";
|
||||||
import {Command} from "../base/command";
|
import {Command} from "../base/command";
|
||||||
import {CallbackCommand} from "../base/callback-command";
|
import {CallbackCommand} from "../base/callback-command";
|
||||||
import {
|
import {
|
||||||
@@ -65,7 +66,7 @@ export const ignoreIfMarkupFailed = (e: Error | TelegramError) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const logError = (e: Error | TelegramError | string | unknown) => {
|
export const logError = (e: Error | TelegramError | string | unknown) => {
|
||||||
console.error(e);
|
console.error(redactLogValue(e));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const errorPlaceholder = async (msg: Message) => {
|
export const errorPlaceholder = async (msg: Message) => {
|
||||||
@@ -307,13 +308,13 @@ export async function editMessageText(options: EditOptions, retries = 1) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
return Promise.resolve(message);
|
return Promise.resolve(message);
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
logError(e);
|
logError(e);
|
||||||
|
|
||||||
if (isMarkupFailed(e)) {
|
if (isMarkupFailed(e as Error | TelegramError)) {
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
} else if (isTooManyRequests(e) && retries > 0) {
|
} else if (isTooManyRequests(e as Error | TelegramError) && retries > 0) {
|
||||||
const retryAfter = Number(e.message.split("retry after ")[1]) || 30;
|
const retryAfter = Number((e instanceof Error ? e.message : String(e)).split("retry after ")[1]) || 30;
|
||||||
await delay(retryAfter * 1000);
|
await delay(retryAfter * 1000);
|
||||||
return editMessageText(options, retries - 1);
|
return editMessageText(options, retries - 1);
|
||||||
} else {
|
} else {
|
||||||
@@ -1836,9 +1837,10 @@ export function startIntervalEditor(params: {
|
|||||||
try {
|
try {
|
||||||
await params.editFn(next);
|
await params.editFn(next);
|
||||||
lastSent = next;
|
lastSent = next;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
if ((e?.description ?? e?.message ?? "").includes("message is not modified")) return;
|
const description = e instanceof Error ? e.message : String(e);
|
||||||
logError("edit failed: " + e);
|
if (description.includes("message is not modified")) return;
|
||||||
|
logError("edit failed: " + description);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1896,7 +1898,6 @@ type RuntimeInfo =
|
|||||||
| { runtime: "unknown"; version: string };
|
| { runtime: "unknown"; version: string };
|
||||||
|
|
||||||
export function getRuntimeInfo(): RuntimeInfo {
|
export function getRuntimeInfo(): RuntimeInfo {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const v = process.versions ?? {};
|
const v = process.versions ?? {};
|
||||||
|
|
||||||
if (typeof v.bun === "string") {
|
if (typeof v.bun === "string") {
|
||||||
@@ -1906,7 +1907,6 @@ export function getRuntimeInfo(): RuntimeInfo {
|
|||||||
return {runtime: "node", version: v.node};
|
return {runtime: "node", version: v.node};
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
return {runtime: "unknown", version: String(process.version ?? "")};
|
return {runtime: "unknown", version: String(process.version ?? "")};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1957,7 +1957,6 @@ export async function imageToBase64(filePath: string, withMimeType: boolean = fa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
export function ifTrue(exp?: string | number | boolean): boolean {
|
export function ifTrue(exp?: string | number | boolean): boolean {
|
||||||
if (!exp) return false;
|
if (!exp) return false;
|
||||||
|
|
||||||
|
|||||||
+16
-8
@@ -1,24 +1,32 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"module": "NodeNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "NodeNext", // Modern resolution
|
"moduleResolution": "Bundler",
|
||||||
"rootDir": "src", // Limits scope
|
"rootDir": "src",
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"incremental": true, // HUGE performance boost
|
"incremental": true,
|
||||||
"isolatedModules": true, // Ensures compatibility with fast runners
|
"isolatedModules": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"types": [
|
||||||
|
"node",
|
||||||
|
"bun"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts"],
|
"include": [
|
||||||
"exclude": ["node_modules", "dist"] // Explicitly exclude build artifacts
|
"src/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"dist"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user