ia_rewrite_ntapp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/configure.js +65 -0
- package/index.js +115 -0
- package/package.json +18 -0
- package/setup.js +37 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# ia_rewrite_ntapp
|
package/configure.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const os = require("os");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { execFileSync } = require("child_process");
|
|
5
|
+
|
|
6
|
+
const CONFIG_FILE = path.join(process.env.USERPROFILE || os.homedir(), ".ia-rewrite-config.json");
|
|
7
|
+
|
|
8
|
+
const SYSTEM_PROMPT =
|
|
9
|
+
"Você é um editor linguístico especialista e poliglota. Sua missão é aprimorar o texto seguindo estas regras: 1. Detecte o idioma e estilo. 2. Mantenha a intenção original. 3. Corrija gramática e coesão. 4. Faça o MÍNIMO de alterações possíveis. 5. Retorne APENAS o texto corrigido.";
|
|
10
|
+
|
|
11
|
+
function runVbsInputBox(prompt, title, defaultValue) {
|
|
12
|
+
const vbs = [
|
|
13
|
+
"Dim result",
|
|
14
|
+
`result = InputBox(\"${prompt}\", \"${title}\", \"${defaultValue}\")`,
|
|
15
|
+
"WScript.Echo result",
|
|
16
|
+
].join("\r\n");
|
|
17
|
+
|
|
18
|
+
const tmpPath = path.join(os.tmpdir(), `ia_rewrite_input_${Date.now()}_${Math.random()}.vbs`);
|
|
19
|
+
fs.writeFileSync(tmpPath, vbs, "utf8");
|
|
20
|
+
try {
|
|
21
|
+
const output = execFileSync("cscript.exe", ["//Nologo", tmpPath], { encoding: "utf8" });
|
|
22
|
+
return String(output).trim();
|
|
23
|
+
} finally {
|
|
24
|
+
try { fs.unlinkSync(tmpPath); } catch (_) {}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function ensureConfig() {
|
|
29
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
30
|
+
const existing = fs.readFileSync(CONFIG_FILE, "utf8").trim();
|
|
31
|
+
if (existing) return JSON.parse(existing);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const baseUrl = runVbsInputBox(
|
|
35
|
+
"URL Base da API:",
|
|
36
|
+
"Configuração ia_rewrite_ntapp",
|
|
37
|
+
"http://127.0.0.1:1234/v1"
|
|
38
|
+
);
|
|
39
|
+
const model = runVbsInputBox(
|
|
40
|
+
"Nome do Modelo:",
|
|
41
|
+
"Configuração ia_rewrite_ntapp",
|
|
42
|
+
"openai/gpt-oss-20b"
|
|
43
|
+
);
|
|
44
|
+
const apiKey = runVbsInputBox(
|
|
45
|
+
"API Key:",
|
|
46
|
+
"Configuração ia_rewrite_ntapp",
|
|
47
|
+
"local"
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const config = {
|
|
51
|
+
OPENAI_API_BASEURL: baseUrl || "http://127.0.0.1:1234/v1",
|
|
52
|
+
OPENAI_API_MODEL: model || "openai/gpt-oss-20b",
|
|
53
|
+
OPENAI_API_KEY: apiKey || "local",
|
|
54
|
+
SYSTEM_PROMPT,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), "utf8");
|
|
58
|
+
return config;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = { ensureConfig, CONFIG_FILE };
|
|
62
|
+
|
|
63
|
+
if (require.main === module) {
|
|
64
|
+
ensureConfig();
|
|
65
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const os = require("os");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const axios = require("axios");
|
|
5
|
+
const clipboardy = require("clipboardy");
|
|
6
|
+
const notifier = require("node-notifier");
|
|
7
|
+
const { execFileSync, execSync } = require("child_process");
|
|
8
|
+
const { ensureConfig, CONFIG_FILE } = require("./configure");
|
|
9
|
+
|
|
10
|
+
function notify(title, message) {
|
|
11
|
+
try {
|
|
12
|
+
notifier.notify({ title, message });
|
|
13
|
+
} catch (_) {}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function runVbsSendKeys(keys) {
|
|
17
|
+
const vbs = [
|
|
18
|
+
"Set WshShell = CreateObject(\"WScript.Shell\")",
|
|
19
|
+
"WScript.Sleep 100",
|
|
20
|
+
`WshShell.SendKeys \"${keys}\"`,
|
|
21
|
+
].join("\r\n");
|
|
22
|
+
|
|
23
|
+
const tmpPath = path.join(os.tmpdir(), `ia_rewrite_sendkeys_${Date.now()}_${Math.random()}.vbs`);
|
|
24
|
+
fs.writeFileSync(tmpPath, vbs, "utf8");
|
|
25
|
+
try {
|
|
26
|
+
execFileSync("cscript.exe", ["//Nologo", tmpPath], { encoding: "utf8" });
|
|
27
|
+
} finally {
|
|
28
|
+
try { fs.unlinkSync(tmpPath); } catch (_) {}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function readClipboardFallback() {
|
|
33
|
+
const output = execSync("powershell -NoProfile -Command Get-Clipboard", { encoding: "utf8" });
|
|
34
|
+
return String(output);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function readClipboard() {
|
|
38
|
+
try {
|
|
39
|
+
return await clipboardy.read();
|
|
40
|
+
} catch (_) {
|
|
41
|
+
return readClipboardFallback();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function writeClipboardFallback(text) {
|
|
46
|
+
const escaped = String(text).replace(/`/g, "``").replace(/\$/g, "`$");
|
|
47
|
+
execSync(`powershell -NoProfile -Command Set-Clipboard -Value @'\n${escaped}\n'@`, { encoding: "utf8" });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function writeClipboard(text) {
|
|
51
|
+
try {
|
|
52
|
+
await clipboardy.write(text);
|
|
53
|
+
} catch (_) {
|
|
54
|
+
writeClipboardFallback(text);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function loadConfig() {
|
|
59
|
+
if (!fs.existsSync(CONFIG_FILE)) return null;
|
|
60
|
+
const raw = fs.readFileSync(CONFIG_FILE, "utf8").trim();
|
|
61
|
+
if (!raw) return null;
|
|
62
|
+
return JSON.parse(raw);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function callModel(config, text) {
|
|
66
|
+
const baseUrl = config.OPENAI_API_BASEURL.replace(/\/$/, "");
|
|
67
|
+
const model = config.OPENAI_API_MODEL;
|
|
68
|
+
const apiKey = config.OPENAI_API_KEY;
|
|
69
|
+
const systemPrompt = config.SYSTEM_PROMPT;
|
|
70
|
+
|
|
71
|
+
const payload = {
|
|
72
|
+
model,
|
|
73
|
+
messages: [
|
|
74
|
+
{ role: "system", content: systemPrompt },
|
|
75
|
+
{ role: "user", content: text },
|
|
76
|
+
],
|
|
77
|
+
temperature: 0.2,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const headers = {
|
|
81
|
+
"Content-Type": "application/json",
|
|
82
|
+
};
|
|
83
|
+
if (apiKey) headers.Authorization = `Bearer ${apiKey}`;
|
|
84
|
+
|
|
85
|
+
const url = `${baseUrl}/chat/completions`;
|
|
86
|
+
const response = await axios.post(url, payload, { headers, timeout: 30000 });
|
|
87
|
+
const content = response?.data?.choices?.[0]?.message?.content;
|
|
88
|
+
if (!content) throw new Error("Resposta vazia da API");
|
|
89
|
+
return String(content).trim();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function main() {
|
|
93
|
+
let config = loadConfig();
|
|
94
|
+
if (!config) config = ensureConfig();
|
|
95
|
+
|
|
96
|
+
runVbsSendKeys("^c");
|
|
97
|
+
await new Promise((r) => setTimeout(r, 150));
|
|
98
|
+
|
|
99
|
+
const original = (await readClipboard()).trim();
|
|
100
|
+
if (!original) {
|
|
101
|
+
notify("ia_rewrite_ntapp", "Clipboard vazio. Selecione um texto e tente novamente.");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
const rewritten = await callModel(config, original);
|
|
107
|
+
await writeClipboard(rewritten);
|
|
108
|
+
runVbsSendKeys("^v");
|
|
109
|
+
notify("ia_rewrite_ntapp", "Texto reescrito e colado com sucesso.");
|
|
110
|
+
} catch (err) {
|
|
111
|
+
notify("ia_rewrite_ntapp", `Erro: ${err.message || err}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ia_rewrite_ntapp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI para reescrever texto selecionado via IA",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"postinstall": "node setup.js",
|
|
9
|
+
"start": "node index.js",
|
|
10
|
+
"publish-npm": "powershell -File ./publish-npm.ps1"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"axios": "^1.6.8",
|
|
14
|
+
"clipboardy": "^3.0.0",
|
|
15
|
+
"dotenv": "^16.4.5",
|
|
16
|
+
"node-notifier": "^10.0.1"
|
|
17
|
+
}
|
|
18
|
+
}
|
package/setup.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const os = require("os");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const { execSync } = require("child_process");
|
|
5
|
+
const { ensureConfig, CONFIG_FILE } = require("./configure");
|
|
6
|
+
|
|
7
|
+
function createShortcut() {
|
|
8
|
+
const desktop = path.join(process.env.USERPROFILE || os.homedir(), "Desktop");
|
|
9
|
+
const target = process.execPath;
|
|
10
|
+
const script = path.join(__dirname, "index.js");
|
|
11
|
+
const lnkPath = path.join(desktop, "ia_rewrite_ntapp.lnk");
|
|
12
|
+
|
|
13
|
+
const ps = [
|
|
14
|
+
"$WshShell = New-Object -ComObject WScript.Shell",
|
|
15
|
+
`$Shortcut = $WshShell.CreateShortcut(\"${lnkPath}\")`,
|
|
16
|
+
`$Shortcut.TargetPath = \"${target}\"`,
|
|
17
|
+
`$Shortcut.Arguments = \"${script}\"`,
|
|
18
|
+
`$Shortcut.WorkingDirectory = \"${__dirname}\"`,
|
|
19
|
+
"$Shortcut.WindowStyle = 7",
|
|
20
|
+
"$Shortcut.Hotkey = 'Ctrl+Alt+R'",
|
|
21
|
+
"$Shortcut.Save()",
|
|
22
|
+
].join("; ");
|
|
23
|
+
|
|
24
|
+
execSync(`powershell -NoProfile -Command "${ps}"`, { encoding: "utf8" });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function postInstall() {
|
|
28
|
+
try {
|
|
29
|
+
createShortcut();
|
|
30
|
+
} catch (_) {}
|
|
31
|
+
|
|
32
|
+
if (!fs.existsSync(CONFIG_FILE) || !fs.readFileSync(CONFIG_FILE, "utf8").trim()) {
|
|
33
|
+
ensureConfig();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
postInstall();
|