english-optimizer-cli 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 +487 -0
- package/config.yaml +38 -0
- package/dist/ai/api-provider.js +138 -0
- package/dist/ai/ollama.js +103 -0
- package/dist/ai/provider.js +26 -0
- package/dist/config/config.js +223 -0
- package/dist/core/batch.js +45 -0
- package/dist/core/editor.js +175 -0
- package/dist/core/instant-editor.js +149 -0
- package/dist/core/optimizer.js +74 -0
- package/dist/history/logger.js +57 -0
- package/dist/index.js +279 -0
- package/dist/prompts/custom.js +75 -0
- package/dist/prompts/templates.js +59 -0
- package/dist/prompts/translation-prompt.js +57 -0
- package/dist/prompts/yaml-prompt.js +101 -0
- package/dist/types/index.js +11 -0
- package/dist/utils/display.js +80 -0
- package/docker-compose.yml +22 -0
- package/package.json +54 -0
- package/prompt.yaml +48 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.OllamaProvider = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const templates_1 = require("../prompts/templates");
|
|
9
|
+
class OllamaProvider {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
}
|
|
13
|
+
async optimize(text, mode) {
|
|
14
|
+
const prompt = (0, templates_1.getPromptTemplate)(mode, text);
|
|
15
|
+
try {
|
|
16
|
+
const response = await axios_1.default.post(`${this.config.baseUrl}/api/generate`, {
|
|
17
|
+
model: this.config.model,
|
|
18
|
+
prompt: prompt,
|
|
19
|
+
stream: false,
|
|
20
|
+
options: {
|
|
21
|
+
temperature: 0.7,
|
|
22
|
+
top_p: 0.9,
|
|
23
|
+
},
|
|
24
|
+
}, {
|
|
25
|
+
timeout: 60000, // 60 seconds timeout
|
|
26
|
+
});
|
|
27
|
+
if (response.data && response.data.response) {
|
|
28
|
+
// Extract the optimized text from the response
|
|
29
|
+
let result = response.data.response.trim();
|
|
30
|
+
// Remove quotes if the model wrapped the response in them
|
|
31
|
+
if (result.startsWith('"') && result.endsWith('"')) {
|
|
32
|
+
result = result.slice(1, -1);
|
|
33
|
+
}
|
|
34
|
+
// Remove common prefixes if present
|
|
35
|
+
const prefixesToRemove = ['Rewritten text:', 'Corrected text:', 'Optimized text:'];
|
|
36
|
+
for (const prefix of prefixesToRemove) {
|
|
37
|
+
if (result.startsWith(prefix)) {
|
|
38
|
+
result = result.slice(prefix.length).trim();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
throw new Error('Invalid response from Ollama');
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
47
|
+
const axiosError = error;
|
|
48
|
+
if (axiosError.code === 'ECONNREFUSED') {
|
|
49
|
+
throw new Error(`Cannot connect to Ollama at ${this.config.baseUrl}. Make sure Ollama is running.`);
|
|
50
|
+
}
|
|
51
|
+
throw new Error(`Ollama API error: ${axiosError.message}`);
|
|
52
|
+
}
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async generateWithPrompt(prompt) {
|
|
57
|
+
try {
|
|
58
|
+
const response = await axios_1.default.post(`${this.config.baseUrl}/api/generate`, {
|
|
59
|
+
model: this.config.model,
|
|
60
|
+
prompt: prompt,
|
|
61
|
+
stream: false,
|
|
62
|
+
options: {
|
|
63
|
+
temperature: 0.7,
|
|
64
|
+
top_p: 0.9,
|
|
65
|
+
},
|
|
66
|
+
}, {
|
|
67
|
+
timeout: 60000,
|
|
68
|
+
});
|
|
69
|
+
if (response.data && response.data.response) {
|
|
70
|
+
let result = response.data.response.trim();
|
|
71
|
+
// Remove quotes if the model wrapped the response in them
|
|
72
|
+
if (result.startsWith('"') && result.endsWith('"')) {
|
|
73
|
+
result = result.slice(1, -1);
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
throw new Error('Invalid response from Ollama');
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
81
|
+
const axiosError = error;
|
|
82
|
+
if (axiosError.code === 'ECONNREFUSED') {
|
|
83
|
+
throw new Error(`Cannot connect to Ollama at ${this.config.baseUrl}. Make sure Ollama is running.`);
|
|
84
|
+
}
|
|
85
|
+
throw new Error(`Ollama API error: ${axiosError.message}`);
|
|
86
|
+
}
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async isAvailable() {
|
|
91
|
+
try {
|
|
92
|
+
const response = await axios_1.default.get(`${this.config.baseUrl}/api/tags`, {
|
|
93
|
+
timeout: 5000,
|
|
94
|
+
});
|
|
95
|
+
return response.status === 200;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.OllamaProvider = OllamaProvider;
|
|
103
|
+
//# sourceMappingURL=ollama.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiProvider = exports.OllamaProvider = void 0;
|
|
4
|
+
exports.createProvider = createProvider;
|
|
5
|
+
const ollama_1 = require("./ollama");
|
|
6
|
+
const api_provider_1 = require("./api-provider");
|
|
7
|
+
function createProvider(config) {
|
|
8
|
+
if (config.ai.provider === 'ollama') {
|
|
9
|
+
if (!config.ai.ollama) {
|
|
10
|
+
throw new Error('Ollama configuration is missing');
|
|
11
|
+
}
|
|
12
|
+
return new ollama_1.OllamaProvider(config.ai.ollama);
|
|
13
|
+
}
|
|
14
|
+
else if (config.ai.provider === 'api') {
|
|
15
|
+
if (!config.ai.api) {
|
|
16
|
+
throw new Error('API configuration is missing');
|
|
17
|
+
}
|
|
18
|
+
return new api_provider_1.ApiProvider(config.ai.api);
|
|
19
|
+
}
|
|
20
|
+
throw new Error(`Unknown provider: ${config.ai.provider}`);
|
|
21
|
+
}
|
|
22
|
+
var ollama_2 = require("./ollama");
|
|
23
|
+
Object.defineProperty(exports, "OllamaProvider", { enumerable: true, get: function () { return ollama_2.OllamaProvider; } });
|
|
24
|
+
var api_provider_2 = require("./api-provider");
|
|
25
|
+
Object.defineProperty(exports, "ApiProvider", { enumerable: true, get: function () { return api_provider_2.ApiProvider; } });
|
|
26
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.configManager = exports.ConfigManager = void 0;
|
|
40
|
+
const zod_1 = require("zod");
|
|
41
|
+
const fs_1 = require("fs");
|
|
42
|
+
const path_1 = require("path");
|
|
43
|
+
const os_1 = require("os");
|
|
44
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
45
|
+
const yaml = __importStar(require("js-yaml"));
|
|
46
|
+
// Load environment variables
|
|
47
|
+
dotenv_1.default.config();
|
|
48
|
+
// Zod schema for validation
|
|
49
|
+
const ConfigSchema = zod_1.z.object({
|
|
50
|
+
ai: zod_1.z.object({
|
|
51
|
+
provider: zod_1.z.enum(['ollama', 'api']),
|
|
52
|
+
ollama: zod_1.z
|
|
53
|
+
.object({
|
|
54
|
+
baseUrl: zod_1.z.string().url(),
|
|
55
|
+
model: zod_1.z.string(),
|
|
56
|
+
})
|
|
57
|
+
.optional(),
|
|
58
|
+
api: zod_1.z
|
|
59
|
+
.object({
|
|
60
|
+
provider: zod_1.z.enum(['openai', 'glm', 'custom']),
|
|
61
|
+
apiKey: zod_1.z.string(),
|
|
62
|
+
baseUrl: zod_1.z.string().url(),
|
|
63
|
+
model: zod_1.z.string(),
|
|
64
|
+
})
|
|
65
|
+
.optional(),
|
|
66
|
+
}),
|
|
67
|
+
hotkeys: zod_1.z.record(zod_1.z.string()),
|
|
68
|
+
features: zod_1.z.object({
|
|
69
|
+
enableHistory: zod_1.z.boolean(),
|
|
70
|
+
historyPath: zod_1.z.string(),
|
|
71
|
+
enableCustomPrompts: zod_1.z.boolean(),
|
|
72
|
+
customPromptsPath: zod_1.z.string(),
|
|
73
|
+
}),
|
|
74
|
+
});
|
|
75
|
+
const DEFAULT_CONFIG = {
|
|
76
|
+
ai: {
|
|
77
|
+
provider: 'ollama',
|
|
78
|
+
ollama: {
|
|
79
|
+
baseUrl: 'http://localhost:11434',
|
|
80
|
+
model: 'llama3.2:3b',
|
|
81
|
+
},
|
|
82
|
+
api: {
|
|
83
|
+
provider: 'openai',
|
|
84
|
+
apiKey: '',
|
|
85
|
+
baseUrl: 'https://api.openai.com/v1',
|
|
86
|
+
model: 'gpt-3.5-turbo',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
hotkeys: {
|
|
90
|
+
professional: 'p',
|
|
91
|
+
concise: 'c',
|
|
92
|
+
grammar: 'g',
|
|
93
|
+
senior_developer: 'd',
|
|
94
|
+
reset: 'r',
|
|
95
|
+
history: 'h',
|
|
96
|
+
quit: 'q',
|
|
97
|
+
},
|
|
98
|
+
features: {
|
|
99
|
+
enableHistory: true,
|
|
100
|
+
historyPath: (0, path_1.join)((0, os_1.homedir)(), '.english-optimizer', 'history.json'),
|
|
101
|
+
enableCustomPrompts: true,
|
|
102
|
+
customPromptsPath: (0, path_1.join)((0, os_1.homedir)(), '.english-optimizer', 'prompts.json'),
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
const CONFIG_DIR = (0, path_1.join)((0, os_1.homedir)(), '.english-optimizer');
|
|
106
|
+
const CONFIG_FILE_YAML = (0, path_1.join)(CONFIG_DIR, 'config.yaml');
|
|
107
|
+
const CONFIG_FILE_JSON = (0, path_1.join)(CONFIG_DIR, 'config.json');
|
|
108
|
+
class ConfigManager {
|
|
109
|
+
constructor() {
|
|
110
|
+
this.config = this.loadConfig();
|
|
111
|
+
}
|
|
112
|
+
loadConfig() {
|
|
113
|
+
// Try to load from YAML config file first, then JSON
|
|
114
|
+
let configFilePath = null;
|
|
115
|
+
let fileContent = '';
|
|
116
|
+
if ((0, fs_1.existsSync)(CONFIG_FILE_YAML)) {
|
|
117
|
+
configFilePath = CONFIG_FILE_YAML;
|
|
118
|
+
try {
|
|
119
|
+
fileContent = (0, fs_1.readFileSync)(CONFIG_FILE_YAML, 'utf-8');
|
|
120
|
+
const fileConfig = yaml.load(fileContent);
|
|
121
|
+
const mergedConfig = this.mergeWithDefaults(fileConfig);
|
|
122
|
+
const validated = ConfigSchema.parse(mergedConfig);
|
|
123
|
+
return validated;
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.warn('Failed to load YAML config file, trying JSON:', error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if ((0, fs_1.existsSync)(CONFIG_FILE_JSON)) {
|
|
130
|
+
configFilePath = CONFIG_FILE_JSON;
|
|
131
|
+
try {
|
|
132
|
+
fileContent = (0, fs_1.readFileSync)(CONFIG_FILE_JSON, 'utf-8');
|
|
133
|
+
const fileConfig = JSON.parse(fileContent);
|
|
134
|
+
const mergedConfig = this.mergeWithDefaults(fileConfig);
|
|
135
|
+
const validated = ConfigSchema.parse(mergedConfig);
|
|
136
|
+
return validated;
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
console.warn('Failed to load JSON config file, using defaults:', error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Load from environment variables
|
|
143
|
+
const envConfig = this.loadFromEnv();
|
|
144
|
+
const mergedConfig = this.mergeWithDefaults(envConfig);
|
|
145
|
+
return ConfigSchema.parse(mergedConfig);
|
|
146
|
+
}
|
|
147
|
+
loadFromEnv() {
|
|
148
|
+
const env = {};
|
|
149
|
+
if (process.env.AI_PROVIDER) {
|
|
150
|
+
env.ai = {
|
|
151
|
+
provider: process.env.AI_PROVIDER,
|
|
152
|
+
};
|
|
153
|
+
if (process.env.AI_PROVIDER === 'ollama') {
|
|
154
|
+
env.ai.ollama = {
|
|
155
|
+
baseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
|
|
156
|
+
model: process.env.OLLAMA_MODEL || 'llama3.2:3b',
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
else if (process.env.AI_PROVIDER === 'api') {
|
|
160
|
+
env.ai.api = {
|
|
161
|
+
provider: process.env.API_PROVIDER || 'openai',
|
|
162
|
+
apiKey: process.env.API_KEY || '',
|
|
163
|
+
baseUrl: process.env.API_BASE_URL || 'https://api.openai.com/v1',
|
|
164
|
+
model: process.env.API_MODEL || 'gpt-3.5-turbo',
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (process.env.ENABLE_HISTORY !== undefined) {
|
|
169
|
+
env.features = {
|
|
170
|
+
enableHistory: process.env.ENABLE_HISTORY === 'true',
|
|
171
|
+
enableCustomPrompts: process.env.ENABLE_CUSTOM_PROMPTS !== undefined
|
|
172
|
+
? process.env.ENABLE_CUSTOM_PROMPTS === 'true'
|
|
173
|
+
: true,
|
|
174
|
+
historyPath: (0, path_1.join)((0, os_1.homedir)(), '.english-optimizer', 'history.json'),
|
|
175
|
+
customPromptsPath: (0, path_1.join)((0, os_1.homedir)(), '.english-optimizer', 'prompts.json'),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return env;
|
|
179
|
+
}
|
|
180
|
+
mergeWithDefaults(partial) {
|
|
181
|
+
return {
|
|
182
|
+
ai: {
|
|
183
|
+
...DEFAULT_CONFIG.ai,
|
|
184
|
+
...partial.ai,
|
|
185
|
+
ollama: partial.ai?.ollama
|
|
186
|
+
? { ...DEFAULT_CONFIG.ai.ollama, ...partial.ai.ollama }
|
|
187
|
+
: DEFAULT_CONFIG.ai.ollama,
|
|
188
|
+
api: partial.ai?.api
|
|
189
|
+
? { ...DEFAULT_CONFIG.ai.api, ...partial.ai.api }
|
|
190
|
+
: DEFAULT_CONFIG.ai.api,
|
|
191
|
+
},
|
|
192
|
+
hotkeys: { ...DEFAULT_CONFIG.hotkeys, ...partial.hotkeys },
|
|
193
|
+
features: { ...DEFAULT_CONFIG.features, ...partial.features },
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
getConfig() {
|
|
197
|
+
return this.config;
|
|
198
|
+
}
|
|
199
|
+
saveConfig(config) {
|
|
200
|
+
const validated = ConfigSchema.parse(config);
|
|
201
|
+
// Ensure config directory exists
|
|
202
|
+
if (!(0, fs_1.existsSync)(CONFIG_DIR)) {
|
|
203
|
+
(0, fs_1.mkdirSync)(CONFIG_DIR, { recursive: true });
|
|
204
|
+
}
|
|
205
|
+
// Save to YAML if it exists or by default, otherwise use JSON
|
|
206
|
+
const configFilePath = (0, fs_1.existsSync)(CONFIG_FILE_YAML) ? CONFIG_FILE_YAML : CONFIG_FILE_JSON;
|
|
207
|
+
if (configFilePath.endsWith('.yaml')) {
|
|
208
|
+
(0, fs_1.writeFileSync)(configFilePath, yaml.dump(validated, { indent: 2 }), 'utf-8');
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
(0, fs_1.writeFileSync)(configFilePath, JSON.stringify(validated, null, 2), 'utf-8');
|
|
212
|
+
}
|
|
213
|
+
this.config = validated;
|
|
214
|
+
}
|
|
215
|
+
static ensureConfigDir() {
|
|
216
|
+
if (!(0, fs_1.existsSync)(CONFIG_DIR)) {
|
|
217
|
+
(0, fs_1.mkdirSync)(CONFIG_DIR, { recursive: true });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
exports.ConfigManager = ConfigManager;
|
|
222
|
+
exports.configManager = new ConfigManager();
|
|
223
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BatchProcessor = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const display_1 = require("../utils/display");
|
|
6
|
+
class BatchProcessor {
|
|
7
|
+
constructor(optimizer) {
|
|
8
|
+
this.optimizer = optimizer;
|
|
9
|
+
}
|
|
10
|
+
async processBatch(options) {
|
|
11
|
+
(0, display_1.displayInfo)(`Processing ${options.files.length} file(s)...`);
|
|
12
|
+
for (const file of options.files) {
|
|
13
|
+
await this.processFile(file, options);
|
|
14
|
+
}
|
|
15
|
+
(0, display_1.displayInfo)(`Batch processing complete!`);
|
|
16
|
+
}
|
|
17
|
+
async processFile(filePath, options) {
|
|
18
|
+
try {
|
|
19
|
+
// Read file
|
|
20
|
+
const content = (0, fs_1.readFileSync)(filePath, 'utf-8');
|
|
21
|
+
(0, display_1.displayModeInfo)(options.mode);
|
|
22
|
+
console.log(`\nProcessing: ${filePath}`);
|
|
23
|
+
// Optimize content
|
|
24
|
+
const result = await this.optimizer.optimize(content, options.mode);
|
|
25
|
+
(0, display_1.displayOptimization)(result.original, result.optimized);
|
|
26
|
+
// Write output
|
|
27
|
+
if (options.inPlace) {
|
|
28
|
+
(0, fs_1.writeFileSync)(filePath, result.optimized, 'utf-8');
|
|
29
|
+
console.log(`ā
Updated: ${filePath}`);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
const outputPath = options.outputSuffix
|
|
33
|
+
? filePath.replace(/(\.[^.]+)$/, `${options.outputSuffix}$1`)
|
|
34
|
+
: `${filePath}.optimized`;
|
|
35
|
+
(0, fs_1.writeFileSync)(outputPath, result.optimized, 'utf-8');
|
|
36
|
+
console.log(`ā
Created: ${outputPath}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.error(`ā Error processing ${filePath}:`, error);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.BatchProcessor = BatchProcessor;
|
|
45
|
+
//# sourceMappingURL=batch.js.map
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.InteractiveEditor = void 0;
|
|
7
|
+
const readline_1 = __importDefault(require("readline"));
|
|
8
|
+
const process_1 = require("process");
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const types_1 = require("../types");
|
|
11
|
+
const display_1 = require("../utils/display");
|
|
12
|
+
const config_1 = require("../config/config");
|
|
13
|
+
class InteractiveEditor {
|
|
14
|
+
constructor(optimizer, historyLogger, customPromptLoader) {
|
|
15
|
+
this.currentText = '';
|
|
16
|
+
this.optimizer = optimizer;
|
|
17
|
+
this.historyLogger = historyLogger;
|
|
18
|
+
this.customPromptLoader = customPromptLoader;
|
|
19
|
+
this.rl = readline_1.default.createInterface({
|
|
20
|
+
input: process_1.stdin,
|
|
21
|
+
output: process_1.stdout,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
async start() {
|
|
25
|
+
(0, display_1.displayWelcome)();
|
|
26
|
+
(0, display_1.displayHelp)();
|
|
27
|
+
console.log('\nEnter your text (press Enter twice to finish):\n');
|
|
28
|
+
// Read multi-line input
|
|
29
|
+
const lines = [];
|
|
30
|
+
let emptyLineCount = 0;
|
|
31
|
+
while (true) {
|
|
32
|
+
const line = await this.question('');
|
|
33
|
+
lines.push(line);
|
|
34
|
+
if (line.trim() === '') {
|
|
35
|
+
emptyLineCount++;
|
|
36
|
+
if (emptyLineCount >= 1) {
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
emptyLineCount = 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
this.currentText = lines.join('\n').trim();
|
|
45
|
+
if (!this.currentText) {
|
|
46
|
+
(0, display_1.displayInfo)('No text provided. Exiting...');
|
|
47
|
+
this.rl.close();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
await this.runOptimizationLoop();
|
|
51
|
+
}
|
|
52
|
+
async runOptimizationLoop() {
|
|
53
|
+
const config = config_1.configManager.getConfig();
|
|
54
|
+
while (true) {
|
|
55
|
+
console.log('\n' + 'ā'.repeat(60));
|
|
56
|
+
console.log(chalk_1.default.cyan('Current text:'));
|
|
57
|
+
console.log(chalk_1.default.gray(this.currentText));
|
|
58
|
+
console.log('ā'.repeat(60));
|
|
59
|
+
console.log(chalk_1.default.yellow('\nPress a hotkey (or Ctrl+Q to quit):'));
|
|
60
|
+
// Use raw mode to capture single keypress
|
|
61
|
+
const key = await this.captureKeypress();
|
|
62
|
+
if (key === '\u0003' || key === 'q') {
|
|
63
|
+
// Ctrl+C or q
|
|
64
|
+
console.log('\n\nGoodbye! š\n');
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
else if (key === 'r') {
|
|
68
|
+
// Reset
|
|
69
|
+
console.log(chalk_1.default.yellow('\nāŗ Reset to original'));
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
else if (key === 'h') {
|
|
73
|
+
// History
|
|
74
|
+
await this.showHistory();
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
else if (key === 'p') {
|
|
78
|
+
// Professional
|
|
79
|
+
await this.performOptimization(types_1.OptimizationMode.PROFESSIONAL);
|
|
80
|
+
}
|
|
81
|
+
else if (key === 'c') {
|
|
82
|
+
// Concise
|
|
83
|
+
await this.performOptimization(types_1.OptimizationMode.CONCISE);
|
|
84
|
+
}
|
|
85
|
+
else if (key === 'g') {
|
|
86
|
+
// Grammar
|
|
87
|
+
await this.performOptimization(types_1.OptimizationMode.GRAMMAR);
|
|
88
|
+
}
|
|
89
|
+
else if (key === 'd') {
|
|
90
|
+
// Senior Developer
|
|
91
|
+
await this.performOptimization(types_1.OptimizationMode.SENIOR_DEVELOPER);
|
|
92
|
+
}
|
|
93
|
+
else if (this.customPromptLoader && config.features.enableCustomPrompts) {
|
|
94
|
+
// Check for custom prompt hotkeys
|
|
95
|
+
const customPrompt = this.customPromptLoader.getPromptByHotkey(key);
|
|
96
|
+
if (customPrompt) {
|
|
97
|
+
await this.performCustomOptimization(customPrompt);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
this.rl.close();
|
|
103
|
+
}
|
|
104
|
+
async performOptimization(mode) {
|
|
105
|
+
try {
|
|
106
|
+
(0, display_1.displayModeInfo)(mode);
|
|
107
|
+
console.log(chalk_1.default.gray('Optimizing...'));
|
|
108
|
+
const result = await this.optimizer.optimize(this.currentText, mode);
|
|
109
|
+
(0, display_1.displayOptimization)(result.original, result.optimized);
|
|
110
|
+
// Ask if user wants to use the optimized version
|
|
111
|
+
const accept = await this.question('\nUse this version? (y/n): ');
|
|
112
|
+
if (accept.toLowerCase() === 'y') {
|
|
113
|
+
this.currentText = result.optimized;
|
|
114
|
+
(0, display_1.displaySuccess)('Text updated!');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
(0, display_1.displayError)(error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async performCustomOptimization(customPrompt) {
|
|
122
|
+
try {
|
|
123
|
+
console.log(chalk_1.default.yellow(`\n[${customPrompt.name}]`));
|
|
124
|
+
console.log(chalk_1.default.gray(customPrompt.description));
|
|
125
|
+
console.log(chalk_1.default.gray('Optimizing...'));
|
|
126
|
+
// For custom prompts, we'd need to extend the provider
|
|
127
|
+
// For now, this is a placeholder
|
|
128
|
+
(0, display_1.displayInfo)('Custom prompts will be implemented soon!');
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
(0, display_1.displayError)(error);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async showHistory() {
|
|
135
|
+
if (!this.historyLogger) {
|
|
136
|
+
(0, display_1.displayInfo)('History is disabled.');
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const history = this.historyLogger.getRecentEntries(5);
|
|
140
|
+
if (history.length === 0) {
|
|
141
|
+
(0, display_1.displayInfo)('No history yet.');
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
console.log(chalk_1.default.cyan('\nš Recent Optimizations:\n'));
|
|
145
|
+
for (const entry of history) {
|
|
146
|
+
(0, display_1.displayHistoryEntry)(entry);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
question(query) {
|
|
150
|
+
return new Promise((resolve) => {
|
|
151
|
+
this.rl.question(query, (answer) => {
|
|
152
|
+
resolve(answer);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
captureKeypress() {
|
|
157
|
+
return new Promise((resolve) => {
|
|
158
|
+
const originalRawMode = process_1.stdin.isRaw;
|
|
159
|
+
process_1.stdin.setRawMode(true);
|
|
160
|
+
process_1.stdin.resume();
|
|
161
|
+
process_1.stdin.once('data', (key) => {
|
|
162
|
+
process_1.stdin.setRawMode(originalRawMode);
|
|
163
|
+
process_1.stdin.pause();
|
|
164
|
+
process_1.stdin.removeAllListeners('data');
|
|
165
|
+
const str = key.toString('utf8');
|
|
166
|
+
resolve(str);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
close() {
|
|
171
|
+
this.rl.close();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exports.InteractiveEditor = InteractiveEditor;
|
|
175
|
+
//# sourceMappingURL=editor.js.map
|