From a9eec3057b409aec1998b4f7e61a1d2afef459f5 Mon Sep 17 00:00:00 2001 From: Adrian Belmans Date: Sat, 18 Oct 2025 11:55:12 +0200 Subject: [PATCH] added ollama support to humanifyjs --- package-lock.json | 16 +++++++++ package.json | 1 + src/commands/ollama.ts | 44 ++++++++++++++++++++++++ src/index.ts | 4 ++- src/plugins/ollama/ollama-rename.ts | 53 +++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/commands/ollama.ts create mode 100644 src/plugins/ollama/ollama-rename.ts diff --git a/package-lock.json b/package-lock.json index dc63823d..4a544507 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "dotenv": "^16.4.5", "ipull": "^3.9.0", "node-llama-cpp": "^3.0.0-beta.40", + "ollama": "^0.6.0", "openai": "^4.55.1", "tsx": "^4.16.2", "typescript": "^5.5.4", @@ -4814,6 +4815,15 @@ "node": ">= 18" } }, + "node_modules/ollama": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/ollama/-/ollama-0.6.0.tgz", + "integrity": "sha512-FHjdU2Ok5x2HZsxPui/MBJZ5J+HzmxoWYa/p9wk736eT+uAhS8nvIICar5YgwlG5MFNjDR6UA5F3RSKq+JseOA==", + "license": "MIT", + "dependencies": { + "whatwg-fetch": "^3.6.20" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -6489,6 +6499,12 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "license": "BSD-2-Clause" }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT" + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", diff --git a/package.json b/package.json index 77de63eb..2e644702 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "dotenv": "^16.4.5", "ipull": "^3.9.0", "node-llama-cpp": "^3.0.0-beta.40", + "ollama": "^0.6.0", "openai": "^4.55.1", "tsx": "^4.16.2", "typescript": "^5.5.4", diff --git a/src/commands/ollama.ts b/src/commands/ollama.ts new file mode 100644 index 00000000..fd762ff6 --- /dev/null +++ b/src/commands/ollama.ts @@ -0,0 +1,44 @@ +import { cli } from "../cli.js"; +import prettier from "../plugins/prettier.js"; +import { unminify } from "../unminify.js"; +import babel from "../plugins/babel/babel.js"; +import { ollamaRename } from "../plugins/ollama/ollama-rename.js"; +import { verbose } from "../verbose.js"; +import { env } from "../env.js"; +import { parseNumber } from "../number-utils.js"; +import { DEFAULT_CONTEXT_WINDOW_SIZE } from "./default-args.js"; + +export const ollama = cli() + .name("ollama") + .description("Use Ollama to unminify code") + .option("-m, --model ", "The model to use", "gpt-oss:20b") + .option("-o, --outputDir ", "The output directory", "output") + .option( + "--baseURL ", + "The Ollama base server URL.", + env("OLLAMA_BASE_URL") ?? "http://localhost:11434" + ) + .option("--verbose", "Show verbose output") + .option( + "--contextSize ", + "The context size to use for the LLM", + `${DEFAULT_CONTEXT_WINDOW_SIZE}` + ) + .argument("input", "The input minified Javascript file") + .action(async (filename, opts) => { + if (opts.verbose) { + verbose.enabled = true; + } + + const baseURL = opts.baseURL; + const contextWindowSize = parseNumber(opts.contextSize); + await unminify(filename, opts.outputDir, [ + babel, + ollamaRename({ + baseURL, + model: opts.model, + contextWindowSize + }), + prettier + ]); + }); diff --git a/src/index.ts b/src/index.ts index d14a0d5c..61ac78e6 100755 --- a/src/index.ts +++ b/src/index.ts @@ -3,15 +3,17 @@ import { version } from "../package.json"; import { download } from "./commands/download.js"; import { local } from "./commands/local.js"; import { openai } from "./commands/openai.js"; +import { ollama } from "./commands/ollama.js"; import { cli } from "./cli.js"; import { azure } from "./commands/gemini.js"; cli() .name("humanify") - .description("Unminify code using OpenAI's API or a local LLM") + .description("Unminify code using OpenAI's API, Ollama, or a local LLM") .version(version) .addCommand(local) .addCommand(openai) + .addCommand(ollama) .addCommand(azure) .addCommand(download()) .parse(process.argv); diff --git a/src/plugins/ollama/ollama-rename.ts b/src/plugins/ollama/ollama-rename.ts new file mode 100644 index 00000000..13846d3c --- /dev/null +++ b/src/plugins/ollama/ollama-rename.ts @@ -0,0 +1,53 @@ +import { Ollama } from "ollama"; +import { visitAllIdentifiers } from "../local-llm-rename/visit-all-identifiers.js"; +import { showPercentage } from "../../progress.js"; +import { verbose } from "../../verbose.js"; + +export function ollamaRename({ + baseURL, + model, + contextWindowSize +}: { + baseURL?: string; + model: string; + contextWindowSize: number; +}) { + const client = new Ollama({ host: baseURL }); + + return async (code: string): Promise => { + return await visitAllIdentifiers( + code, + async (name, surroundingCode) => { + verbose.log(`Renaming ${name}`); + verbose.log("Context: ", surroundingCode); + + const response = await client.chat({ + model, + messages: [ + { + role: "system", + content: `Rename Javascript variables/function \`${name}\` to have descriptive name based on their usage in the code. Respond only with valid JSON in the format: {"newName": "your_new_name_here"}` + }, + { + role: "user", + content: surroundingCode + } + ], + format: "json" + }); + + const result = response.message?.content; + if (!result) { + throw new Error("Failed to rename", { cause: response }); + } + const renamed = JSON.parse(result).newName; + + verbose.log(`Renamed to ${renamed}`); + + return renamed; + }, + contextWindowSize, + showPercentage + ); + }; +}