mirror of
https://github.com/gnh1201/welsonjs.git
synced 2025-05-07 12:16:04 +00:00
commit
426a9d7721
|
@ -62,7 +62,7 @@ WelsonJS is tailored for developers who need a reliable, lightweight JavaScript
|
||||||
## Specifications
|
## Specifications
|
||||||
- Built-in transpilers: [TypeScript](https://www.typescriptlang.org/), [Rescript](https://rescript-lang.org/), [CoffeeScript 2](https://coffeescript.org/), [LiveScript](https://livescript.net/)
|
- Built-in transpilers: [TypeScript](https://www.typescriptlang.org/), [Rescript](https://rescript-lang.org/), [CoffeeScript 2](https://coffeescript.org/), [LiveScript](https://livescript.net/)
|
||||||
- **Ready to use on Windows machine immediately. No require additional software installation.**
|
- **Ready to use on Windows machine immediately. No require additional software installation.**
|
||||||
- **WelsonJS Launcher**: Manage an instances (Like a container), User-defined variable editor, [Microsoft Monaco Editor](https://github.com/microsoft/monaco-editor) (Pre-embedded rich code editor), [Microsoft Copilot](https://copilot.microsoft.com) on the code editor.
|
- **WelsonJS Launcher**: Manage instances (Like a container), User-defined variable editor, [Microsoft Monaco Editor](https://github.com/microsoft/monaco-editor) (Pre-embedded rich code editor), [Microsoft Copilot](https://copilot.microsoft.com) on the code editor.
|
||||||
- ES5(ECMAScript 5), XML, JSON, YAML compatibility: [core-js](https://github.com/zloirock/core-js), [JSON2.js](https://github.com/douglascrockford/JSON-js), [js-yaml](https://github.com/nodeca/js-yaml)
|
- ES5(ECMAScript 5), XML, JSON, YAML compatibility: [core-js](https://github.com/zloirock/core-js), [JSON2.js](https://github.com/douglascrockford/JSON-js), [js-yaml](https://github.com/nodeca/js-yaml)
|
||||||
- HTML5, CSS3 compatibility: [html5shiv](https://github.com/aFarkas/html5shiv), [jquery-html5-placeholder-shim](https://github.com/parndt/jquery-html5-placeholder-shim), [Respond](https://github.com/scottjehl/Respond), [selectivizr](https://github.com/keithclark/selectivizr), [ExplorerCanvas](https://github.com/arv/ExplorerCanvas), [Modernizr](https://github.com/Modernizr/Modernizr)
|
- HTML5, CSS3 compatibility: [html5shiv](https://github.com/aFarkas/html5shiv), [jquery-html5-placeholder-shim](https://github.com/parndt/jquery-html5-placeholder-shim), [Respond](https://github.com/scottjehl/Respond), [selectivizr](https://github.com/keithclark/selectivizr), [ExplorerCanvas](https://github.com/arv/ExplorerCanvas), [Modernizr](https://github.com/Modernizr/Modernizr)
|
||||||
- Classical CSS Frameworks: [cascadeframework](https://github.com/jslegers/cascadeframework), [golden-layout](https://github.com/golden-layout/golden-layout)
|
- Classical CSS Frameworks: [cascadeframework](https://github.com/jslegers/cascadeframework), [golden-layout](https://github.com/golden-layout/golden-layout)
|
||||||
|
|
|
@ -242,10 +242,7 @@ namespace WelsonJS.Launcher
|
||||||
|
|
||||||
private void startCodeEditorToolStripMenuItem_Click(object sender, EventArgs e)
|
private void startCodeEditorToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (Program.resourceServer == null)
|
Program.StartResourceServer();
|
||||||
{
|
|
||||||
Program.resourceServer = new ResourceServer(Program.GetAppConfig("ResourceServerPrefix"), "editor.html");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Program.resourceServer.IsRunning())
|
if (!Program.resourceServer.IsRunning())
|
||||||
{
|
{
|
||||||
|
|
|
@ -138,13 +138,24 @@ namespace WelsonJS.Launcher
|
||||||
return workingDirectory;
|
return workingDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void StartResourceServer()
|
||||||
|
{
|
||||||
|
lock(typeof(Program))
|
||||||
|
{
|
||||||
|
if (resourceServer == null)
|
||||||
|
{
|
||||||
|
resourceServer = new ResourceServer(GetAppConfig("ResourceServerPrefix"), "editor.html");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
public static void OpenWebBrowser(string url)
|
public static void OpenWebBrowser(string url)
|
||||||
{
|
{
|
||||||
string userDataDir = Path.Combine(GetAppDataPath(), "EdgeUserProfile");
|
string userDataDir = Path.Combine(GetAppDataPath(), "EdgeUserProfile");
|
||||||
string remoteAllowOrigins = "http://localhost:3000";
|
string remoteAllowOrigins = GetAppConfig("ResourceServerPrefix");
|
||||||
|
int remoteDebuggingPort = new Uri(GetAppConfig("DevToolsPrefix")).Port;
|
||||||
string[] arguments = {
|
string[] arguments = {
|
||||||
$"\"{url}\"",
|
$"\"{url}\"",
|
||||||
"--remote-debugging-port=9222",
|
$"--remote-debugging-port={remoteDebuggingPort}",
|
||||||
$"--remote-allow-origins={remoteAllowOrigins}", // for security reason
|
$"--remote-allow-origins={remoteAllowOrigins}", // for security reason
|
||||||
$"--user-data-dir=\"{userDataDir}\""
|
$"--user-data-dir=\"{userDataDir}\""
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
139
WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs
Normal file
139
WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WelsonJS.Launcher.ResourceTools
|
||||||
|
{
|
||||||
|
public class AzureAi : IResourceTool
|
||||||
|
{
|
||||||
|
private ResourceServer Server;
|
||||||
|
private const string Prefix = "azure-ai/";
|
||||||
|
private const int ChunkSize = 4096;
|
||||||
|
private readonly string AzureAiServiceUrl;
|
||||||
|
private readonly string AzureAiServiceApiKey;
|
||||||
|
|
||||||
|
public AzureAi(ResourceServer server)
|
||||||
|
{
|
||||||
|
Server = server;
|
||||||
|
|
||||||
|
AzureAiServiceUrl = Program.GetAppConfig("AzureAiServiceUrl");
|
||||||
|
AzureAiServiceApiKey = Program.GetAppConfig("AzureAiServiceApiKey");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanHandle(string path)
|
||||||
|
{
|
||||||
|
return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleAsync(HttpListenerContext context, string path)
|
||||||
|
{
|
||||||
|
string apiKey = AzureAiServiceApiKey;
|
||||||
|
if (string.IsNullOrEmpty(apiKey))
|
||||||
|
{
|
||||||
|
WriteError(context, "Missing the API key.", HttpStatusCode.BadRequest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string requestBody = ReadRequestBody(context);
|
||||||
|
bool isStreaming = ContainsSequentialKeywords(requestBody, new[] { "\"stream\"", "true" }, 30);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var response = await SendAzureRequestAsync(apiKey, requestBody, isStreaming))
|
||||||
|
{
|
||||||
|
await ForwardResponseAsync(context, response, isStreaming);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
WriteError(context, "Request error: " + ex.Message, HttpStatusCode.BadGateway);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ReadRequestBody(HttpListenerContext context)
|
||||||
|
{
|
||||||
|
using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
|
||||||
|
{
|
||||||
|
return reader.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<HttpResponseMessage> SendAzureRequestAsync(string apiKey, string requestBody, bool isStreaming)
|
||||||
|
{
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
var requestMessage = new HttpRequestMessage(HttpMethod.Post, AzureAiServiceUrl);
|
||||||
|
requestMessage.Headers.Add("api-key", apiKey);
|
||||||
|
requestMessage.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
var completionOption = isStreaming
|
||||||
|
? HttpCompletionOption.ResponseHeadersRead
|
||||||
|
: HttpCompletionOption.ResponseContentRead;
|
||||||
|
|
||||||
|
return await client.SendAsync(requestMessage, completionOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ForwardResponseAsync(HttpListenerContext context, HttpResponseMessage response, bool isStreaming)
|
||||||
|
{
|
||||||
|
context.Response.StatusCode = (int)response.StatusCode;
|
||||||
|
context.Response.ContentType = response.Content.Headers.ContentType?.ToString() ?? "application/json";
|
||||||
|
|
||||||
|
using (var responseStream = await response.Content.ReadAsStreamAsync())
|
||||||
|
{
|
||||||
|
if (isStreaming)
|
||||||
|
{
|
||||||
|
context.Response.SendChunked = true;
|
||||||
|
context.Response.Headers.Add("Transfer-Encoding", "chunked");
|
||||||
|
context.Response.Headers.Add("Cache-Control", "no-cache");
|
||||||
|
|
||||||
|
byte[] buffer = new byte[ChunkSize];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
||||||
|
{
|
||||||
|
await context.Response.OutputStream.WriteAsync(buffer, 0, bytesRead);
|
||||||
|
context.Response.OutputStream.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await responseStream.CopyToAsync(context.Response.OutputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteError(HttpListenerContext context, string message, HttpStatusCode statusCode)
|
||||||
|
{
|
||||||
|
context.Response.StatusCode = (int)statusCode;
|
||||||
|
using (var writer = new StreamWriter(context.Response.OutputStream, Encoding.UTF8))
|
||||||
|
{
|
||||||
|
writer.Write(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ContainsSequentialKeywords(string input, string[] keywords, int maxDistance)
|
||||||
|
{
|
||||||
|
if (input == null || keywords == null || keywords.Length < 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int position = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < keywords.Length; i++)
|
||||||
|
{
|
||||||
|
int index = input.IndexOf(keywords[i], position, StringComparison.OrdinalIgnoreCase);
|
||||||
|
if (index < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (i > 0 && (index - position) > maxDistance)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
position = index + keywords[i].Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,6 +74,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="IResourceTool.cs" />
|
<Compile Include="IResourceTool.cs" />
|
||||||
|
<Compile Include="ResourceTools\AzureAi.cs" />
|
||||||
<Compile Include="ResourceTools\Config.cs" />
|
<Compile Include="ResourceTools\Config.cs" />
|
||||||
<Compile Include="ResourceTools\Completion.cs" />
|
<Compile Include="ResourceTools\Completion.cs" />
|
||||||
<Compile Include="ResourceTools\DevTools.cs" />
|
<Compile Include="ResourceTools\DevTools.cs" />
|
||||||
|
@ -165,6 +166,5 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="editor.html" />
|
<EmbeddedResource Include="editor.html" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -50,16 +50,14 @@
|
||||||
<span class="icon mif-floppy-disks"></span>
|
<span class="icon mif-floppy-disks"></span>
|
||||||
<span class="caption">Save File</span>
|
<span class="caption">Save File</span>
|
||||||
</button>
|
</button>
|
||||||
<button id="btnGenerate" class="ribbon-button">
|
<span class="title">File</span>
|
||||||
|
</div>
|
||||||
|
<div class="group">
|
||||||
|
<button id="btnCopilot" class="ribbon-button">
|
||||||
<span class="icon mif-rocket"></span>
|
<span class="icon mif-rocket"></span>
|
||||||
<span class="caption">Generate</span>
|
<span class="caption">Copilot</span>
|
||||||
</button>
|
</button>
|
||||||
<button id="btnSponsor" class="ribbon-button">
|
<span class="title">Generative</span>
|
||||||
<span class="icon mif-heart"></span>
|
|
||||||
<span class="caption">Sponsor</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<span class="title">Common</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="group">
|
<div class="group">
|
||||||
<button id="btnWhois" class="ribbon-button">
|
<button id="btnWhois" class="ribbon-button">
|
||||||
|
@ -70,8 +68,7 @@
|
||||||
<span class="icon mif-earth"></span>
|
<span class="icon mif-earth"></span>
|
||||||
<span class="caption">DNS</span>
|
<span class="caption">DNS</span>
|
||||||
</button>
|
</button>
|
||||||
|
<span class="title">Network</span>
|
||||||
<span class="title">Network tools</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -240,18 +237,14 @@
|
||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
};
|
};
|
||||||
|
|
||||||
document.getElementById("btnSponsor").onclick = function () {
|
document.getElementById("btnCopilot").onclick = function () {
|
||||||
navigate('https://github.com/sponsors/gnh1201');
|
|
||||||
};
|
|
||||||
|
|
||||||
document.getElementById("btnGenerate").onclick = function () {
|
|
||||||
const promptMessage = prompt("Enter a prompt message:", '');
|
const promptMessage = prompt("Enter a prompt message:", '');
|
||||||
if (!promptMessage || promptMessage.trim() == '') {
|
if (!promptMessage || promptMessage.trim() == '') {
|
||||||
alert("A prompt message is required.");
|
alert("A prompt message is required.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
appendTextToEditor(`\n//${promptMessage}... Thinking with Generative AI...`);
|
appendTextToEditor(`\n//${promptMessage}... Generating text with Copilot...`);
|
||||||
|
|
||||||
(async function () {
|
(async function () {
|
||||||
const targetWsUrl = await getTargetByUrl('copilot.microsoft.com');
|
const targetWsUrl = await getTargetByUrl('copilot.microsoft.com');
|
||||||
|
|
Loading…
Reference in New Issue
Block a user