diff --git a/.gitignore b/.gitignore index 154cd292..3f5bb546 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,10 @@ cortex.log api.log prism.log api.json -openai-python/* \ No newline at end of file +openai-python/* +build +cortex-js/cortex.exe +cortex-js/package-lock.json +.vscode +cortex-js/command +cortex-js/src/infrastructure/commanders/test/test_data diff --git a/cortex-js/cpuinfo/bin/cpuinfo b/cortex-js/cpuinfo/bin/cpuinfo deleted file mode 100644 index a4e172c3..00000000 Binary files a/cortex-js/cpuinfo/bin/cpuinfo and /dev/null differ diff --git a/cortex-js/cpuinfo/bin/cpuinfo.exe b/cortex-js/cpuinfo/bin/cpuinfo.exe deleted file mode 100644 index c96c8192..00000000 Binary files a/cortex-js/cpuinfo/bin/cpuinfo.exe and /dev/null differ diff --git a/cortex-js/cpuinfo/binding.gyp b/cortex-js/cpuinfo/binding.gyp new file mode 100644 index 00000000..988f8d0e --- /dev/null +++ b/cortex-js/cpuinfo/binding.gyp @@ -0,0 +1,9 @@ +{ + "targets": [ + { + "target_name": "cpuinfo", + "sources": ["src/cpuinfo.cpp"], + "includes": ["common.gypi"], + } + ] +} \ No newline at end of file diff --git a/cortex-js/cpuinfo/common.gypi b/cortex-js/cpuinfo/common.gypi new file mode 100644 index 00000000..7a8632f0 --- /dev/null +++ b/cortex-js/cpuinfo/common.gypi @@ -0,0 +1,8 @@ +{ + 'defines': [ 'V8_DEPRECATION_WARNINGS=1' ], + 'conditions': [ + [ 'OS in "linux freebsd openbsd solaris android aix os400 cloudabi"', { + 'cflags': ['-Wno-cast-function-type'], + }], + ], +} \ No newline at end of file diff --git a/cortex-js/cpuinfo/index.ts b/cortex-js/cpuinfo/index.ts new file mode 100644 index 00000000..a8b798e8 --- /dev/null +++ b/cortex-js/cpuinfo/index.ts @@ -0,0 +1,4 @@ +export type InstructionSet = 'AVX' | 'AVX2' | 'AVX512'; // Add more as needed later +export const cpuInfo = require('bindings')('cpuinfo') as { + cpuInfo: () => InstructionSet[]; +}; diff --git a/cortex-js/cpuinfo/package.json b/cortex-js/cpuinfo/package.json new file mode 100644 index 00000000..447324e5 --- /dev/null +++ b/cortex-js/cpuinfo/package.json @@ -0,0 +1,33 @@ +{ + "name": "cpuinfo", + "version": "1.0.0", + "description": "Get CPU instructions", + "main": "dist/index.js", + "scripts": { + "build": "tsc", + "test": "ts-node index.ts", + "install": "prebuild-install -r napi || node-gyp rebuild" + }, + "author": "", + "license": "ISC", + "gypfile": true, + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1" + }, + "devDependencies": { + "@types/node": "^20.14.9", + "typescript": "^5.5.3" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "files": [ + "binding.gyp", + "deps/", + "*.js", + "*.d.ts", + "src/" + ] +} diff --git a/cortex-js/cpuinfo/src/cpuinfo.cpp b/cortex-js/cpuinfo/src/cpuinfo.cpp index 9ba181ca..adbf6f05 100644 --- a/cortex-js/cpuinfo/src/cpuinfo.cpp +++ b/cortex-js/cpuinfo/src/cpuinfo.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -5,190 +7,269 @@ #ifdef _WIN32 #include #include -typedef unsigned __int32 uint32_t; +typedef unsigned __int32 uint32_t; #else #include #endif -using namespace std; +namespace +{ + + using v8::Array; + using v8::Context; + using v8::FunctionCallbackInfo; + using v8::Isolate; + using v8::Local; + using v8::Object; + using v8::String; + using v8::Value; + using namespace std; + using namespace v8; +#if defined(_WIN32) || defined(LINUX) #define MAX_INTEL_TOP_LVL 4 -class CPUID { - uint32_t regs[4]; + class CPUID + { + uint32_t regs[4]; public: - explicit CPUID(unsigned funcId, unsigned subFuncId) { + explicit CPUID(unsigned funcId, unsigned subFuncId) + { #ifdef _WIN32 - __cpuidex((int *)regs, (int)funcId, (int)subFuncId); + __cpuidex((int *)regs, (int)funcId, (int)subFuncId); #else - asm volatile - ("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) - : "a" (funcId), "c" (subFuncId)); - // ECX is set to zero for CPUID function 4 + asm volatile("cpuid" : "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) + : "a"(funcId), "c"(subFuncId)); + // ECX is set to zero for CPUID function 4 #endif - } + } - const uint32_t &EAX() const {return regs[0];} - const uint32_t &EBX() const {return regs[1];} - const uint32_t &ECX() const {return regs[2];} - const uint32_t &EDX() const {return regs[3];} -}; + const uint32_t &EAX() const { return regs[0]; } + const uint32_t &EBX() const { return regs[1]; } + const uint32_t &ECX() const { return regs[2]; } + const uint32_t &EDX() const { return regs[3]; } + }; -class CPUInfo { + class CPUInfo + { public: CPUInfo(); - string vendor() const { return mVendorId; } - string model() const { return mModelName; } - int cores() const { return mNumCores; } - float cpuSpeedInMHz() const { return mCPUMHz; } - bool isSSE() const { return mIsSSE; } - bool isSSE2() const { return mIsSSE2; } - bool isSSE3() const { return mIsSSE3; } - bool isSSE41() const { return mIsSSE41; } - bool isSSE42() const { return mIsSSE42; } - bool isAVX() const { return mIsAVX; } - bool isAVX2() const { return mIsAVX2; } - bool isAVX512() const { return mIsAVX512; } - bool isHyperThreaded() const { return mIsHTT; } - int logicalCpus() const { return mNumLogCpus; } + string vendor() const { return mVendorId; } + string model() const { return mModelName; } + int cores() const { return mNumCores; } + float cpuSpeedInMHz() const { return mCPUMHz; } + bool isSSE() const { return mIsSSE; } + bool isSSE2() const { return mIsSSE2; } + bool isSSE3() const { return mIsSSE3; } + bool isSSE41() const { return mIsSSE41; } + bool isSSE42() const { return mIsSSE42; } + bool isAVX() const { return mIsAVX; } + bool isAVX2() const { return mIsAVX2; } + bool isAVX512() const { return mIsAVX512; } + bool isHyperThreaded() const { return mIsHTT; } + int logicalCpus() const { return mNumLogCpus; } private: // Bit positions for data extractions - static const uint32_t SSE_POS = 0x02000000; - static const uint32_t SSE2_POS = 0x04000000; - static const uint32_t SSE3_POS = 0x00000001; + static const uint32_t SSE_POS = 0x02000000; + static const uint32_t SSE2_POS = 0x04000000; + static const uint32_t SSE3_POS = 0x00000001; static const uint32_t SSE41_POS = 0x00080000; static const uint32_t SSE42_POS = 0x00100000; - static const uint32_t AVX_POS = 0x10000000; - static const uint32_t AVX2_POS = 0x00000020; + static const uint32_t AVX_POS = 0x10000000; + static const uint32_t AVX2_POS = 0x00000020; static const uint32_t AVX512_POS = 0x00010000; // AVX-512F bit in EBX from CPUID function 7 - static const uint32_t LVL_NUM = 0x000000FF; - static const uint32_t LVL_TYPE = 0x0000FF00; + static const uint32_t LVL_NUM = 0x000000FF; + static const uint32_t LVL_TYPE = 0x0000FF00; static const uint32_t LVL_CORES = 0x0000FFFF; // Attributes string mVendorId; string mModelName; - int mNumSMT; - int mNumCores; - int mNumLogCpus; - float mCPUMHz; - bool mIsHTT; - bool mIsSSE; - bool mIsSSE2; - bool mIsSSE3; - bool mIsSSE41; - bool mIsSSE42; - bool mIsAVX; - bool mIsAVX2; - bool mIsAVX512; -}; - -CPUInfo::CPUInfo() -{ - // Get vendor name EAX=0 - CPUID cpuID0(0, 0); - uint32_t HFS = cpuID0.EAX(); - mVendorId += string((const char *)&cpuID0.EBX(), 4); - mVendorId += string((const char *)&cpuID0.EDX(), 4); - mVendorId += string((const char *)&cpuID0.ECX(), 4); - // Get SSE instructions availability - CPUID cpuID1(1, 0); - mIsHTT = cpuID1.EDX() & AVX_POS; - mIsSSE = cpuID1.EDX() & SSE_POS; - mIsSSE2 = cpuID1.EDX() & SSE2_POS; - mIsSSE3 = cpuID1.ECX() & SSE3_POS; - mIsSSE41 = cpuID1.ECX() & SSE41_POS; - mIsSSE42 = cpuID1.ECX() & SSE41_POS; - mIsAVX = cpuID1.ECX() & AVX_POS; - // Get AVX2 and AVX512 instructions availability - CPUID cpuID7(7, 0); - mIsAVX2 = cpuID7.EBX() & AVX2_POS; - mIsAVX512 = cpuID7.EBX() & AVX512_POS; - - string upVId = mVendorId; - for_each(upVId.begin(), upVId.end(), [](char& in) { in = ::toupper(in); }); - // Get num of cores - if (upVId.find("INTEL") != std::string::npos) { - if(HFS >= 11) { - for (int lvl=0; lvl= 11) + { + for (int lvl = 0; lvl < MAX_INTEL_TOP_LVL; ++lvl) + { CPUID cpuID4(0x0B, lvl); - uint32_t currLevel = (LVL_TYPE & cpuID4.ECX())>>8; - switch(currLevel) { - case 0x01: mNumSMT = LVL_CORES & cpuID4.EBX(); break; - case 0x02: mNumLogCpus = LVL_CORES & cpuID4.EBX(); break; - default: break; + uint32_t currLevel = (LVL_TYPE & cpuID4.ECX()) >> 8; + switch (currLevel) + { + case 0x01: + mNumSMT = LVL_CORES & cpuID4.EBX(); + break; + case 0x02: + mNumLogCpus = LVL_CORES & cpuID4.EBX(); + break; + default: + break; } + } + mNumCores = mNumLogCpus / mNumSMT; } - mNumCores = mNumLogCpus/mNumSMT; - } else { - if (HFS>=1) { + else + { + if (HFS >= 1) + { + mNumLogCpus = (cpuID1.EBX() >> 16) & 0xFF; + if (HFS >= 4) + { + mNumCores = 1 + (CPUID(4, 0).EAX() >> 26) & 0x3F; + } + } + if (mIsHTT) + { + if (!(mNumCores > 1)) + { + mNumCores = 1; + mNumLogCpus = (mNumLogCpus >= 2 ? mNumLogCpus : 2); + } + } + else + { + mNumCores = mNumLogCpus = 1; + } + } + } + else if (upVId.find("AMD") != std::string::npos) + { + if (HFS >= 1) + { mNumLogCpus = (cpuID1.EBX() >> 16) & 0xFF; - if (HFS>=4) { - mNumCores = 1 + (CPUID(4, 0).EAX() >> 26) & 0x3F; + if (CPUID(0x80000000, 0).EAX() >= 8) + { + mNumCores = 1 + (CPUID(0x80000008, 0).ECX() & 0xFF); } } - if (mIsHTT) { - if (!(mNumCores>1)) { + if (mIsHTT) + { + if (!(mNumCores > 1)) + { mNumCores = 1; mNumLogCpus = (mNumLogCpus >= 2 ? mNumLogCpus : 2); } - } else { + } + else + { mNumCores = mNumLogCpus = 1; } } - } else if (upVId.find("AMD") != std::string::npos) { - if (HFS>=1) { - mNumLogCpus = (cpuID1.EBX() >> 16) & 0xFF; - if (CPUID(0x80000000, 0).EAX() >=8) { - mNumCores = 1 + (CPUID(0x80000008, 0).ECX() & 0xFF); - } + else + { + cout << "Unexpected vendor id" << endl; } - if (mIsHTT) { - if (!(mNumCores>1)) { - mNumCores = 1; - mNumLogCpus = (mNumLogCpus >= 2 ? mNumLogCpus : 2); - } - } else { - mNumCores = mNumLogCpus = 1; + // Get processor brand string + // This seems to be working for both Intel & AMD vendors + for (int i = 0x80000002; i < 0x80000005; ++i) + { + CPUID cpuID(i, 0); + mModelName += string((const char *)&cpuID.EAX(), 4); + mModelName += string((const char *)&cpuID.EBX(), 4); + mModelName += string((const char *)&cpuID.ECX(), 4); + mModelName += string((const char *)&cpuID.EDX(), 4); + } + } +#endif + // int main(int argc, char *argv[]) + // { + // CPUInfo cinfo; + + // cout << "{\n"; + // cout << " \"vendor\": \"" << cinfo.vendor() << "\",\n"; + // cout << " \"brand\": \"" << cinfo.model() << "\",\n"; + // cout << " \"cores\": " << cinfo.cores() << ",\n"; + // cout << " \"threads\": " << cinfo.logicalCpus() << ",\n"; + // cout << " \"is_hyperthreading\": " << (cinfo.isHyperThreaded() ? "true" : "false") << ",\n"; + // cout << " \"instructions\": {\n"; + // cout << " \"SSE\": " << (cinfo.isSSE() ? "true" : "false") << ",\n"; + // cout << " \"SSE2\": " << (cinfo.isSSE2() ? "true" : "false") << ",\n"; + // cout << " \"SSE3\": " << (cinfo.isSSE3() ? "true" : "false") << ",\n"; + // cout << " \"SSE41\": " << (cinfo.isSSE41() ? "true" : "false") << ",\n"; + // cout << " \"SSE42\": " << (cinfo.isSSE42() ? "true" : "false") << ",\n"; + // cout << " \"AVX\": " << (cinfo.isAVX() ? "true" : "false") << ",\n"; + // cout << " \"AVX2\": " << (cinfo.isAVX2() ? "true" : "false") << ",\n"; + // cout << " \"AVX512\": " << (cinfo.isAVX512() ? "true" : "false") << "\n"; + // cout << " }\n"; + // cout << "}\n"; + + // return 0; + // } + + static void Method(const v8::FunctionCallbackInfo &args) + { + v8::Isolate *isolate = args.GetIsolate(); + std::vector> arr = {}; +#if defined(_WIN32) || defined(LINUX) + CPUInfo cinfo; + if (cinfo.isAVX512()) + { + arr.push_back(String::NewFromUtf8(isolate, "AVX512").ToLocalChecked()); + } + if (cinfo.isAVX2()) + { + arr.push_back(String::NewFromUtf8(isolate, "AVX2").ToLocalChecked()); } - } else { - cout<< "Unexpected vendor id" < exports, + v8::Local module, + v8::Local context) + { + NODE_SET_METHOD(exports, "cpuInfo", Method); } -} -int main(int argc, char *argv[]) -{ - CPUInfo cinfo; - - cout << "{\n"; - cout << " \"vendor\": \"" << cinfo.vendor() << "\",\n"; - cout << " \"brand\": \"" << cinfo.model() << "\",\n"; - cout << " \"cores\": " << cinfo.cores() << ",\n"; - cout << " \"threads\": " << cinfo.logicalCpus() << ",\n"; - cout << " \"is_hyperthreading\": " << (cinfo.isHyperThreaded() ? "true" : "false") << ",\n"; - cout << " \"instructions\": {\n"; - cout << " \"SSE\": " << (cinfo.isSSE() ? "true" : "false") << ",\n"; - cout << " \"SSE2\": " << (cinfo.isSSE2() ? "true" : "false") << ",\n"; - cout << " \"SSE3\": " << (cinfo.isSSE3() ? "true" : "false") << ",\n"; - cout << " \"SSE41\": " << (cinfo.isSSE41() ? "true" : "false") << ",\n"; - cout << " \"SSE42\": " << (cinfo.isSSE42() ? "true" : "false") << ",\n"; - cout << " \"AVX\": " << (cinfo.isAVX() ? "true" : "false") << ",\n"; - cout << " \"AVX2\": " << (cinfo.isAVX2() ? "true" : "false") << ",\n"; - cout << " \"AVX512\": " << (cinfo.isAVX512() ? "true" : "false") << "\n"; - cout << " }\n"; - cout << "}\n"; - - return 0; } + +NODE_MODULE(NODE_GYP_MODULE_NAME, InitModule) \ No newline at end of file diff --git a/cortex-js/cpuinfo/tsconfig.json b/cortex-js/cpuinfo/tsconfig.json new file mode 100644 index 00000000..d8d1f719 --- /dev/null +++ b/cortex-js/cpuinfo/tsconfig.json @@ -0,0 +1,108 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": false, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/cortex-js/package.json b/cortex-js/package.json index 87b95cc6..79c35e60 100644 --- a/cortex-js/package.json +++ b/cortex-js/package.json @@ -10,11 +10,11 @@ }, "scripts": { "dev": "nest dev", - "build": "nest build && cpx \"cpuinfo/bin/**\" dist/bin", - "build:binary": "npx -q patch-package && run-script-os && cpx \"cpuinfo/bin/**\" dist/bin", - "build:binary:windows": "bun build --compile ./src/command.ts --outfile cortex.exe --external @nestjs/microservices --external @nestjs/websockets/socket-module --external class-transformer/storage", - "build:binary:linux": "bun build --compile ./src/command.ts --outfile cortex --external @nestjs/microservices --external @nestjs/websockets/socket-module --external class-transformer/storage", - "build:binary:macos": "bun build --compile ./src/command.ts --outfile cortex --external @nestjs/microservices --external @nestjs/websockets/socket-module --external class-transformer/storage", + "preinstall": "npx node-gyp rebuild -C ./cpuinfo && cd cpuinfo && yarn && yarn build", + "compile": "npx ncc build ./dist/src/command.js -o command", + "build": "nest build", + "build:cpuInfo": "npx node-gyp rebuild -C ./cpuinfo", + "build:binary": "yarn build:cpuInfo && yarn compile && npx -q patch-package && npx pkg .", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "build:extensions": "run-script-os", "build:extensions:windows": "powershell -command \"$jobs = Get-ChildItem -Path './src/extensions' -Directory | ForEach-Object { Start-Job -Name ($_.Name) -ScriptBlock { param($_dir); try { Set-Location $_dir; yarn; yarn build; Write-Output 'Build successful in ' + $_dir } catch { Write-Error 'Error in ' + $_dir; throw } } -ArgumentList $_.FullName }; $jobs | Wait-Job; $jobs | ForEach-Object { Receive-Job -Job $_ -Keep } | ForEach-Object { Write-Host $_ }; $failed = $jobs | Where-Object { $_.State -ne 'Completed' -or $_.ChildJobs[0].JobStateInfo.State -ne 'Completed' }; if ($failed) { Exit 1 }\"", @@ -31,7 +31,10 @@ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:e2e": "jest --config ./test/jest-e2e.json", "typeorm": "typeorm-ts-node-esm", - "build:dev": "npx nest build && chmod +x ./dist/src/command.js && npm link" + "build:dev": "npx nest build && run-script-os && npm link", + "build:dev:windows": "echo 'Windows build complete'", + "build:dev:macos": "chmod +x ./dist/src/command.js", + "build:dev:linux": "chmod +x ./dist/src/command.js" }, "dependencies": { "@huggingface/gguf": "^0.1.5", @@ -62,7 +65,8 @@ "typeorm": "^0.3.20", "ulid": "^2.3.0", "uuid": "^9.0.1", - "yaml": "^2.4.2" + "yaml": "^2.4.2", + "cpuinfo": "link: ../cpuinfo" }, "devDependencies": { "@nestjs/cli": "^10.0.0", @@ -89,6 +93,7 @@ "is-primitive": "^3.0.1", "jest": "^29.5.0", "nest-commander-testing": "^3.3.0", + "node-gyp": "^10.1.0", "prettier": "^3.0.0", "run-script-os": "^1.1.6", "source-map-support": "^0.5.21", @@ -125,5 +130,10 @@ "@/(.*)$": "/$1", "@commanders/(.*)$": "/../src/infrastructure/commanders/$1" } + }, + "pkg": { + "scripts": "command/**/*.js", + "assets": ["command/*.node", "**/package.json", "node_modules/axios/**/*", "cpuinfo/**/*"], + "outputPath": "dist" } } diff --git a/cortex-js/src/infrastructure/commanders/init.command.ts b/cortex-js/src/infrastructure/commanders/init.command.ts index 38cde473..30a80143 100644 --- a/cortex-js/src/infrastructure/commanders/init.command.ts +++ b/cortex-js/src/infrastructure/commanders/init.command.ts @@ -38,7 +38,7 @@ export class InitCommand extends CommandRunner { if (options?.silent) { const installationOptions = await this.initUsecases.defaultInstallationOptions(); - return this.initUsecases.installEngine(installationOptions); + await this.initUsecases.installEngine(installationOptions); } else { options = await this.inquirerService.ask( 'init-run-mode-questions', @@ -57,6 +57,7 @@ export class InitCommand extends CommandRunner { TelemetrySource.CLI, ); } + console.log('Cortex engines installed successfully!'); } @Option({ diff --git a/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts b/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts index 101776d1..4b6cb1e1 100644 --- a/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts +++ b/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts @@ -1,5 +1,5 @@ import { cpSync, createWriteStream, existsSync, readdirSync, rmSync } from 'fs'; -import { delimiter, join } from 'path'; +import { join } from 'path'; import { HttpService } from '@nestjs/axios'; import { Presets, SingleBar } from 'cli-progress'; import decompress from 'decompress'; @@ -9,8 +9,6 @@ import { Injectable } from '@nestjs/common'; import { firstValueFrom } from 'rxjs'; import { FileManagerService } from '@/infrastructure/services/file-manager/file-manager.service'; import { rm } from 'fs/promises'; -import { exec } from 'child_process'; -import { appPath } from '@/utils/app-path'; import { CORTEX_ENGINE_RELEASES_URL, CORTEX_RELEASES_URL, @@ -18,7 +16,8 @@ import { } from '@/infrastructure/constants/cortex'; import { checkNvidiaGPUExist, cudaVersion } from '@/utils/cuda'; import { Engines } from '../types/engine.interface'; -import { checkModelCompatibility } from '@/utils/model-check'; + +import { cpuInfo } from 'cpuinfo'; @Injectable() export class InitCliUsecases { @@ -271,35 +270,9 @@ export class InitCliUsecases { private detectInstructions = (): Promise< 'AVX' | 'AVX2' | 'AVX512' | undefined > => { - return new Promise<'AVX' | 'AVX2' | 'AVX512' | undefined>((res) => { - // Execute the cpuinfo command - - exec( - join( - appPath, - `bin/cpuinfo${process.platform !== 'linux' ? '.exe' : ''}`, - ), - (error, stdout) => { - if (error) { - // If there's an error, it means lscpu is not installed - console.log('CPUInfo is not installed.'); - res('AVX'); - } else { - // If the command executes successfully, parse the output to detect CPU instructions - if (stdout.includes('"AVX512": "true"')) { - console.log('AVX-512 instructions detected.'); - res('AVX512'); - } else if ('"AVX2": "true"') { - console.log('AVX2 instructions detected.'); - res('AVX2'); - } else { - console.log('AVXs instructions detected.'); - res('AVX'); - } - } - }, - ); - }); + const cpuInstruction = cpuInfo.cpuInfo()[0]?? 'AVX' + console.log(cpuInstruction, 'CPU instructions detected'); + return Promise.resolve(cpuInstruction); }; /** diff --git a/cortex-js/src/usecases/models/models.usecases.ts b/cortex-js/src/usecases/models/models.usecases.ts index 036a6d8b..5de6b8ae 100644 --- a/cortex-js/src/usecases/models/models.usecases.ts +++ b/cortex-js/src/usecases/models/models.usecases.ts @@ -348,7 +348,8 @@ export class ModelsUsecases { const toDownloads: Record = files .filter((e) => this.validFileDownload(e)) .reduce((acc: Record, file) => { - acc[file.downloadUrl] = join(modelFolder, file.rfilename); + if (file.downloadUrl) + acc[file.downloadUrl] = join(modelFolder, file.rfilename); return acc; }, {});