diff --git a/WelsonJS.Augmented/WelsonJS.Launcher/Program.cs b/WelsonJS.Augmented/WelsonJS.Launcher/Program.cs index 1ab087b..71167c0 100644 --- a/WelsonJS.Augmented/WelsonJS.Launcher/Program.cs +++ b/WelsonJS.Augmented/WelsonJS.Launcher/Program.cs @@ -201,57 +201,137 @@ namespace WelsonJS.Launcher private static void HandleTargetFilePath(string filePath) { - string fileExtension = Path.GetExtension(filePath); + if (string.IsNullOrWhiteSpace(filePath)) + throw new ArgumentException("filePath is null or empty.", nameof(filePath)); - if (String.IsNullOrEmpty(fileExtension)) - { - throw new ArgumentException("The file extension is null or empty"); - } + if (!File.Exists(filePath)) + throw new FileNotFoundException("Target file not found.", filePath); - if (fileExtension.Equals(".zip", StringComparison.OrdinalIgnoreCase)) - { + string ext = Path.GetExtension(filePath); + if (string.IsNullOrEmpty(ext)) + throw new ArgumentException("The file extension is null or empty.", nameof(filePath)); + + if (ext.Equals(".zip", StringComparison.OrdinalIgnoreCase)) throw new NotImplementedException("Not implemented yet."); - } - if (fileExtension.Equals(".js", StringComparison.OrdinalIgnoreCase)) + if (!ext.Equals(".js", StringComparison.OrdinalIgnoreCase)) + throw new NotSupportedException($"Unsupported file type: {ext}"); + + string instanceId = Guid.NewGuid().ToString(); + string workingDirectory = CreateInstanceDirectory(instanceId); + + string appRoot = GetAppRootDirectory(); + if (string.IsNullOrWhiteSpace(appRoot) || !Directory.Exists(appRoot)) + throw new DirectoryNotFoundException($"Application root not found: {appRoot}"); + + DeployBaseFiles(appRoot, workingDirectory); + DeployOptionalDataFiles(appRoot, workingDirectory); + DeployEntrypoint(filePath, workingDirectory); + + RecordFirstDeployTime(workingDirectory, instanceId); + + RunCommandPrompt( + workingDirectory: workingDirectory, + entryFileName: "app.js", + scriptName: "bootstrap", + isConsoleApplication: true, + isInteractiveServiceApplication: false + ); + } + + private static void DeployBaseFiles(string appRoot, string workingDirectory) + { + CopyFile( + Path.Combine(appRoot, "app.js"), + Path.Combine(workingDirectory, "app.js"), + isRequired: true + ); + + CopyDirectoryRecursive( + Path.Combine(appRoot, "app", "assets", "js"), + Path.Combine(workingDirectory, "app", "assets", "js"), + isRequired: true + ); + + CopyDirectoryRecursive( + Path.Combine(appRoot, "lib"), + Path.Combine(workingDirectory, "lib"), + isRequired: true + ); + } + + private static void DeployOptionalDataFiles(string appRoot, string workingDirectory) + { + CopyFile( + Path.Combine(appRoot, "data", "apikey.json"), + Path.Combine(workingDirectory, "data", "apikey.json"), + isRequired: false + ); + + CopyFile( + Path.Combine(appRoot, "data", "available_proxies.json"), + Path.Combine(workingDirectory, "data", "available_proxies.json"), + isRequired: false + ); + + CopyFile( + Path.Combine(appRoot, "data", "filetypes.json"), + Path.Combine(workingDirectory, "data", "filetypes.json"), + isRequired: false + ); + } + + private static void DeployEntrypoint(string sourceJsPath, string workingDirectory) + { + CopyFile( + sourceJsPath, + Path.Combine(workingDirectory, "bootstrap.js"), + isRequired: true + ); + } + + private static void CopyDirectoryRecursive( + string sourceDir, + string destinationDir, + bool isRequired = false + ) + { + if (!Directory.Exists(sourceDir)) { - string instanceId = Guid.NewGuid().ToString(); - string workingDirectory = CreateInstanceDirectory(instanceId); - - string appRoot = GetAppRootDirectory(); - string appBaseSource = Path.Combine(appRoot, "app.js"); - if (!File.Exists(appBaseSource)) - { - throw new FileNotFoundException("app.js not found in application root.", appBaseSource); - } - - string appBaseDestination = Path.Combine(workingDirectory, "app.js"); - File.Copy(appBaseSource, appBaseDestination, overwrite: true); - - string assetsSource = Path.Combine(appRoot, "app", "assets", "js"); - string assetsDestination = Path.Combine(workingDirectory, "app", "assets", "js"); - CopyDirectoryRecursive(assetsSource, assetsDestination); - - string libSource = Path.Combine(appRoot, "lib"); - string libDestination = Path.Combine(workingDirectory, "lib"); - CopyDirectoryRecursive(libSource, libDestination); - - string entrypointDestination = Path.Combine(workingDirectory, "bootstrap.js"); - File.Copy(filePath, entrypointDestination, overwrite: true); - - RecordFirstDeployTime(workingDirectory, instanceId); - - RunCommandPrompt( - workingDirectory: workingDirectory, - entryFileName: "app.js", - scriptName: "bootstrap", - isConsoleApplication: true, - isInteractiveServiceApplication: false - ); + if (isRequired) + throw new DirectoryNotFoundException($"Required directory not found: {sourceDir}"); return; } - throw new NotSupportedException($"Unsupported file type: {fileExtension}"); + Directory.CreateDirectory(destinationDir); + + foreach (string file in Directory.GetFiles(sourceDir)) + { + string destFile = Path.Combine(destinationDir, Path.GetFileName(file)); + File.Copy(file, destFile, overwrite: true); + } + + foreach (string subDir in Directory.GetDirectories(sourceDir)) + { + string destSubDir = Path.Combine(destinationDir, Path.GetFileName(subDir)); + CopyDirectoryRecursive(subDir, destSubDir, isRequired); + } + } + + private static void CopyFile(string sourcePath, string destinationPath, bool isRequired) + { + if (!File.Exists(sourcePath)) + { + if (isRequired) + throw new FileNotFoundException("Required file not found.", sourcePath); + return; + } + + string parent = Path.GetDirectoryName(destinationPath); + if (!string.IsNullOrEmpty(parent)) + Directory.CreateDirectory(parent); + + File.Copy(sourcePath, destinationPath, overwrite: true); } private static string GetAppRootDirectory() @@ -299,33 +379,6 @@ namespace WelsonJS.Launcher return workingDirectory; } - private static void CopyDirectoryRecursive(string sourceDir, string destDir) - { - if (!Directory.Exists(sourceDir)) - { - throw new DirectoryNotFoundException("Source directory not found: " + sourceDir); - } - - Directory.CreateDirectory(destDir); - - foreach (var file in Directory.GetFiles(sourceDir, "*", SearchOption.AllDirectories)) - { - string normalizedSource = sourceDir.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); - string relativePath = file.Substring(normalizedSource.Length + 1).TrimStart( - Path.DirectorySeparatorChar, - Path.AltDirectorySeparatorChar - ); - string targetPath = Path.Combine(destDir, relativePath); - string targetDir = Path.GetDirectoryName(targetPath); - if (!Directory.Exists(targetDir)) - { - Directory.CreateDirectory(targetDir); - } - - File.Copy(file, targetPath, overwrite: true); - } - } - public static void RunCommandPrompt(string workingDirectory, string entryFileName, string scriptName, bool isConsoleApplication = false, bool isInteractiveServiceApplication = false) { if (!isConsoleApplication) diff --git a/data/apikey.json b/data/apikey.json index ba5b59a..1c4a751 100644 --- a/data/apikey.json +++ b/data/apikey.json @@ -8,6 +8,7 @@ "deepseek": "file:data/deepseek_apikey.txt", "moonshot": "file:data/moonshot_apikey.txt", "clovastudio": "file:data/clovastudio_apikey.txt", + "friendiai": "file:data/friendiai_apikey.txt", "catswords-ai": "file:data/catswords_ai_apikey.txt", "scrapeops": "file:data/scrapeops_apikey.txt", "serpapi": "file:data/serpapi_apikey.txt", diff --git a/lib/language-inference-engine.js b/lib/language-inference-engine.js index 5ab9bad..c15a75c 100644 --- a/lib/language-inference-engine.js +++ b/lib/language-inference-engine.js @@ -17,6 +17,7 @@ // - Moonshot: https://kimi.moonshot.cn/user/agreement/userPrivacy // - AlibabaCloud: https://www.alibabacloud.com/help/en/legal/latest/alibaba-cloud-international-website-privacy-policy // - ClovaStudio: https://clova-x.naver.com/ai_policies +// - FriendIAI: https://friendli.ai/privacypolicy // - Catswords AI: https://policy.catswords.social/site_terms.html // var HTTP = require("lib/http"); @@ -428,6 +429,65 @@ var ENGINE_PROFILES = { } } }, + "friendiai": { + "type": "llm", + "availableModels": [ + "LGAI-EXAONE/K-EXAONE-236B-A23B", + "MiniMaxAI/MiniMax-M2.1", + "zai-org/GLM-4.6", + "meta-llama-3.1-8b-instruct", + "mistralai/Magistral-Small-2506", + "skt/A.X-3.1", + "Qwen/Qwen3-235B-A22B-Thinking-2507", + "Qwen/Qwen3-235B-A22B-Instruct-2507", + "meta-llama-3.3-70b-instruct", + "mistralai/Devstral-Small-2505", + "google/gemma-3-27b-it", + "Qwen/Qwen3-32B", + "meta-llama/Llama-4-Scout-17B-16E-Instruct", + "Qwen/Qwen3-30B-A3B", + "meta-llama/Llama-4-Maverick-17B-128E-Instruct", + "mistralai/Mistral-Small-3.1-24B-Instruct-2503", + "deepseek-ai/DeepSeek-V3.1", + "skt/A.X-4.0", + "naver-hyperclovax/HyperCLOVAX-SEED-Think-14B", + "LGAI-EXAONE/EXAONE-4.0.1-32B" + ], + "headers": { + "Content-Type": "application/json", + "Authorization": "Bearer {apikey}" + }, + "url": "https://api.friendli.ai/serverless/v1", + "wrap": function(model, message, temperature) { + return { + "model": model, + "messages": [{ + "role": "system", + "content": BIAS_MESSAGE + }, { + "role": "user", + "content": message + }], + "temperature": temperature, + "stream": false, + "parse_reasoning": true, + "chat_template_kwargs": { + "enable_thinking": true + } + }; + }, + "callback": function(response) { + if ("error" in response) { + return ["Error: " + response.error.message]; + } else { + return response.choices.reduce(function(a, x) { + a.push(x.message.content); + + return a; + }, []); + } + } + }, "catswords-ai": { "type": "llm", "availableModels": [ @@ -553,7 +613,7 @@ exports.create = function() { return new LanguageInferenceEngine(); }; -exports.VERSIONINFO = "Language Inference Engine integration version 0.1.11"; +exports.VERSIONINFO = "Language Inference Engine integration version 0.1.12"; exports.AUTHOR = "gnh1201@catswords.re.kr"; exports.global = global; exports.require = global.require;