termux-dev 1.4.4 → 1.4.6
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/assets/banner.svg +1 -1
- package/assets/preview_work1.png +0 -0
- package/dist/cli/doctor.js +1 -1
- package/dist/cli/headless.js +1 -1
- package/dist/cli/index.js +6 -6
- package/dist/cli/prompt.js +62 -78
- package/dist/cli/server.js +1 -1
- package/dist/mcp/client.js +1 -1
- package/package.json +1 -1
package/assets/banner.svg
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
<!-- Tagline & Badge -->
|
|
27
27
|
<text x="425" y="142" font-family="system-ui, -apple-system, sans-serif" font-size="14" font-weight="600" fill="#8b949e" text-anchor="middle" letter-spacing="3">
|
|
28
|
-
THE TERMINAL-NATIVE AI CODING AGENT <tspan fill="#00f2fe" font-weight="bold">v1.4.
|
|
28
|
+
THE TERMINAL-NATIVE AI CODING AGENT <tspan fill="#00f2fe" font-weight="bold">v1.4.6</tspan>
|
|
29
29
|
</text>
|
|
30
30
|
|
|
31
31
|
<!-- Top Accent Line -->
|
|
Binary file
|
package/dist/cli/doctor.js
CHANGED
|
@@ -18,7 +18,7 @@ async function pingUrl(url) {
|
|
|
18
18
|
const req = https.get(url, {
|
|
19
19
|
timeout: 3000,
|
|
20
20
|
headers: {
|
|
21
|
-
'User-Agent': 'devx-doctor/1.4.
|
|
21
|
+
'User-Agent': 'devx-doctor/1.4.6'
|
|
22
22
|
}
|
|
23
23
|
}, (res) => {
|
|
24
24
|
res.resume(); // consume response data to free up memory and release socket
|
package/dist/cli/headless.js
CHANGED
|
@@ -35,7 +35,7 @@ export async function runHeadlessMode(userPrompt, config, options = {}) {
|
|
|
35
35
|
});
|
|
36
36
|
try {
|
|
37
37
|
if (!isQuiet && !isJson) {
|
|
38
|
-
console.log(pc.bold(pc.cyan(`⚡ devx v1.4.
|
|
38
|
+
console.log(pc.bold(pc.cyan(`⚡ devx v1.4.6 (headless) | ${planMode ? 'PLAN' : 'AGENT'} | ${config.model}`)));
|
|
39
39
|
console.log(pc.dim(`Task: ${userPrompt}\n`));
|
|
40
40
|
}
|
|
41
41
|
for await (const event of agent.run(abortController.signal)) {
|
package/dist/cli/index.js
CHANGED
|
@@ -484,7 +484,7 @@ function drawLogo() {
|
|
|
484
484
|
theme.colorFn(' █▀▀▄ █▀▀▀ █ █ █ █'),
|
|
485
485
|
theme.colorFn(' █ █ █▀▀▀ ▀▄▀ ▀▄▀ '),
|
|
486
486
|
theme.colorFn(' █▄▄▀ █▄▄▄ ▀ ▀ ▀ '),
|
|
487
|
-
' ' + theme.boldFn('v1.4.
|
|
487
|
+
' ' + theme.boldFn('v1.4.6'),
|
|
488
488
|
''
|
|
489
489
|
];
|
|
490
490
|
for (const line of logo) {
|
|
@@ -499,7 +499,7 @@ function drawLogo() {
|
|
|
499
499
|
indent + theme.colorFn('▀▀▀█▀▀▀ █▀▀▀ █▀▀█ █▄ ▄█ █ █ ▀▄ ▄▀ █▀▀▄ █▀▀▀ █ █'),
|
|
500
500
|
indent + theme.colorFn(' █ █▀▀▀ █▄▄▀ █ █ █ █ █ █ ▀▀ █ █ █▀▀▀ █ █'),
|
|
501
501
|
indent + theme.colorFn(' █ █▄▄▄ █ ▀▄ █ █ ▀▄▄▀ ▄▀ ▀▄ █▄▄▀ █▄▄▄ ▀▄▀ '),
|
|
502
|
-
indent + theme.boldFn('v1.4.
|
|
502
|
+
indent + theme.boldFn('v1.4.6'),
|
|
503
503
|
''
|
|
504
504
|
];
|
|
505
505
|
for (const line of logo) {
|
|
@@ -645,7 +645,7 @@ async function handleSettings(config) {
|
|
|
645
645
|
const maxIterLabel = maxIter >= 9999 ? 'Unlimited' : `${maxIter} steps`;
|
|
646
646
|
const currentTh = getCurrentTheme();
|
|
647
647
|
const choice = await select({
|
|
648
|
-
message: `${pc.bold('⚙️ Settings')} ${pc.dim(`(devx v1.4.
|
|
648
|
+
message: `${pc.bold('⚙️ Settings')} ${pc.dim(`(devx v1.4.6 • theme: ${currentTh.name})`)}`,
|
|
649
649
|
choices: [
|
|
650
650
|
{
|
|
651
651
|
name: `🎨 Color Theme: ${currentTh.emoji} ${currentTh.name}`,
|
|
@@ -686,7 +686,7 @@ async function handleSettings(config) {
|
|
|
686
686
|
description: 'Limit how many tool steps (file edits, terminal commands) agent can do per request'
|
|
687
687
|
},
|
|
688
688
|
{
|
|
689
|
-
name: `${currentTh.colorFn('✨ About devx')} ${pc.dim('(v1.4.
|
|
689
|
+
name: `${currentTh.colorFn('✨ About devx')} ${pc.dim('(v1.4.6 by ApvCode)')}`,
|
|
690
690
|
value: 'about',
|
|
691
691
|
description: 'Terminal-Native AI Coding Agent created by ApvCode (https://github.com/apvcode/Termux-Dev)'
|
|
692
692
|
},
|
|
@@ -702,7 +702,7 @@ async function handleSettings(config) {
|
|
|
702
702
|
continue;
|
|
703
703
|
}
|
|
704
704
|
if (choice === 'about') {
|
|
705
|
-
p.note(`⚡ devx v1.4.
|
|
705
|
+
p.note(`⚡ devx v1.4.6 — Terminal-Native AI Coding Agent\n` +
|
|
706
706
|
`🎨 Theme: ${currentTh.emoji} ${currentTh.name}\n` +
|
|
707
707
|
`👤 Author: ApvCode (https://github.com/apvcode)\n` +
|
|
708
708
|
`🌟 Repository: https://github.com/apvcode/Termux-Dev\n` +
|
|
@@ -771,7 +771,7 @@ export async function main() {
|
|
|
771
771
|
program
|
|
772
772
|
.name('devx')
|
|
773
773
|
.description('Terminal-native AI coding assistant and vibe-coding agent')
|
|
774
|
-
.version('1.4.
|
|
774
|
+
.version('1.4.6')
|
|
775
775
|
.option('-p, --prompt <task>', 'Run one-shot task non-interactively (headless mode)')
|
|
776
776
|
.option('-y, --yolo', 'Automatically approve all tool executions without confirmation')
|
|
777
777
|
.option('-m, --model <model>', 'Specify AI model to use for this execution')
|
package/dist/cli/prompt.js
CHANGED
|
@@ -42,8 +42,7 @@ export function askPrompt(opts = {}) {
|
|
|
42
42
|
let input = opts.initialValue || '';
|
|
43
43
|
let cursorPos = input.length;
|
|
44
44
|
let selectedIndex = 0;
|
|
45
|
-
let
|
|
46
|
-
let lastCursorLine = 0;
|
|
45
|
+
let lastTotalLines = 0;
|
|
47
46
|
let disposed = false;
|
|
48
47
|
let historyIndex = GLOBAL_PROMPT_HISTORY.length;
|
|
49
48
|
let tempDraft = '';
|
|
@@ -156,19 +155,49 @@ export function askPrompt(opts = {}) {
|
|
|
156
155
|
function stripAnsi(str) {
|
|
157
156
|
return str.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
|
|
158
157
|
}
|
|
158
|
+
// Helper: clear all previously rendered lines and move cursor to line 0
|
|
159
|
+
function clearPreviousRender() {
|
|
160
|
+
if (lastTotalLines > 1) {
|
|
161
|
+
process.stdout.write(`\x1b[${lastTotalLines - 1}A`);
|
|
162
|
+
}
|
|
163
|
+
for (let i = 0; i < lastTotalLines; i++) {
|
|
164
|
+
process.stdout.write(`\r\x1b[2K`);
|
|
165
|
+
if (i < lastTotalLines - 1)
|
|
166
|
+
process.stdout.write('\n');
|
|
167
|
+
}
|
|
168
|
+
if (lastTotalLines > 1) {
|
|
169
|
+
process.stdout.write(`\x1b[${lastTotalLines - 1}A`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
159
172
|
function render() {
|
|
160
173
|
if (disposed)
|
|
161
174
|
return;
|
|
162
175
|
const items = getDropdownItems();
|
|
163
|
-
const dropdownLines = [];
|
|
164
176
|
const cols = Math.max(28, process.stdout.columns || 80);
|
|
165
177
|
const rows = Math.max(8, process.stdout.rows || 24);
|
|
178
|
+
const prefixLen = 3;
|
|
179
|
+
const maxPerLine = Math.max(10, cols - prefixLen - 1);
|
|
180
|
+
const allLines = [];
|
|
181
|
+
let inputLineCount = 0;
|
|
182
|
+
if (input.length === 0) {
|
|
183
|
+
const displayPlace = placeholder.length > maxPerLine ? placeholder.slice(0, maxPerLine - 1) + '…' : placeholder;
|
|
184
|
+
allLines.push(pc.dim('│') + ' ' + pc.dim(displayPlace));
|
|
185
|
+
inputLineCount = 1;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
let pos = 0;
|
|
189
|
+
while (pos < input.length) {
|
|
190
|
+
const chunk = input.slice(pos, pos + maxPerLine);
|
|
191
|
+
allLines.push(pc.dim('│') + ' ' + formatInputWithBadges(chunk));
|
|
192
|
+
pos += maxPerLine;
|
|
193
|
+
}
|
|
194
|
+
inputLineCount = allLines.length;
|
|
195
|
+
}
|
|
166
196
|
if (items.length > 0) {
|
|
167
197
|
if (selectedIndex >= items.length)
|
|
168
198
|
selectedIndex = 0;
|
|
169
199
|
if (selectedIndex < 0)
|
|
170
200
|
selectedIndex = items.length - 1;
|
|
171
|
-
// Ensure inner box width strictly fits: innerBoxWidth + 5 <= cols - 2
|
|
172
201
|
const innerBoxWidth = Math.max(16, Math.min(cols - 8, 54));
|
|
173
202
|
const isNarrowOrShort = rows <= 16 || cols < 50;
|
|
174
203
|
const pageSize = isNarrowOrShort
|
|
@@ -194,7 +223,7 @@ export function askPrompt(opts = {}) {
|
|
|
194
223
|
const mid = Math.max(0, Math.floor(innerBoxWidth / 2) - 2);
|
|
195
224
|
botBorderStr = '─'.repeat(mid) + ' ▼ ' + '─'.repeat(Math.max(0, innerBoxWidth - mid - 3));
|
|
196
225
|
}
|
|
197
|
-
|
|
226
|
+
allLines.push(pc.dim('│') + ' ' + pc.dim('╭' + topBorderStr + '╮'));
|
|
198
227
|
for (let i = startIndex; i < endIndex; i++) {
|
|
199
228
|
const item = items[i];
|
|
200
229
|
const isSelected = i === selectedIndex;
|
|
@@ -202,13 +231,11 @@ export function askPrompt(opts = {}) {
|
|
|
202
231
|
const availWidth = innerBoxWidth - 2;
|
|
203
232
|
let row = '';
|
|
204
233
|
if (availWidth < 20) {
|
|
205
|
-
// Very narrow mobile screen: show command name only
|
|
206
234
|
const labelStr = item.label.length > availWidth ? item.label.slice(0, availWidth - 1) + '…' : item.label.padEnd(availWidth);
|
|
207
235
|
const plain = pointer + labelStr;
|
|
208
236
|
row = isSelected ? theme.badgeFn(plain) : (pointer + theme.boldFn(labelStr));
|
|
209
237
|
}
|
|
210
238
|
else {
|
|
211
|
-
// Show command name and truncated description
|
|
212
239
|
const labelMax = Math.min(15, Math.floor(availWidth * 0.45));
|
|
213
240
|
const labelStr = item.label.length > labelMax ? item.label.slice(0, labelMax - 1) + '…' : item.label.padEnd(labelMax);
|
|
214
241
|
const descMax = availWidth - labelMax - 1;
|
|
@@ -221,74 +248,37 @@ export function askPrompt(opts = {}) {
|
|
|
221
248
|
row = `${pointer}${theme.boldFn(labelStr)} ${pc.gray(descStr)}`;
|
|
222
249
|
}
|
|
223
250
|
}
|
|
224
|
-
// Safety guarantee: exact visible width must match innerBoxWidth
|
|
225
251
|
const currentLen = stripAnsi(row).length;
|
|
226
252
|
if (currentLen < innerBoxWidth) {
|
|
227
253
|
row += ' '.repeat(innerBoxWidth - currentLen);
|
|
228
254
|
}
|
|
229
|
-
|
|
255
|
+
allLines.push(pc.dim('│') + ' ' + pc.dim('│') + row + pc.dim('│'));
|
|
230
256
|
}
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const plainBefore = stripAnsi(pc.dim('│') + ' ' + formatInputWithBadges(input.slice(0, cursorPos)));
|
|
243
|
-
const linesBefore = plainBefore.split('\n');
|
|
244
|
-
let curLine = 0;
|
|
245
|
-
for (let i = 0; i < linesBefore.length - 1; i++) {
|
|
246
|
-
const l = linesBefore[i];
|
|
247
|
-
curLine += l.length === 0 ? 1 : Math.max(1, Math.floor((l.length - 1) / cols) + 1);
|
|
248
|
-
}
|
|
249
|
-
const lastLineSegment = linesBefore[linesBefore.length - 1];
|
|
250
|
-
const wrapOffsetInLastLine = Math.floor(lastLineSegment.length / cols);
|
|
251
|
-
curLine += wrapOffsetInLastLine;
|
|
252
|
-
const curCol = lastLineSegment.length % cols;
|
|
253
|
-
// 1. Single-line fast path (flicker-free atomic render)
|
|
254
|
-
let inputDisplay = pc.dim('│') + ' ';
|
|
255
|
-
if (input.length === 0) {
|
|
256
|
-
const maxPlace = Math.max(12, cols - 8);
|
|
257
|
-
const displayPlace = placeholder.length > maxPlace ? placeholder.slice(0, maxPlace - 1) + '…' : placeholder;
|
|
258
|
-
inputDisplay += pc.dim(displayPlace);
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
inputDisplay += formatInputWithBadges(input);
|
|
262
|
-
}
|
|
263
|
-
if (totalInputLines === 1 && dropdownLines.length === 0 && lastCursorLine === 0 && lastDropdownLines === 0) {
|
|
264
|
-
process.stdout.write(`\r\x1b[2K${inputDisplay}`);
|
|
265
|
-
process.stdout.write(`\r\x1b[${curCol}C`);
|
|
266
|
-
lastCursorLine = 0;
|
|
267
|
-
lastDropdownLines = 0;
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
// 2. Multi-line / dropdown path: move to Line 0 and erase down
|
|
271
|
-
if (lastCursorLine > 0) {
|
|
272
|
-
process.stdout.write(`\x1b[${lastCursorLine}A`);
|
|
273
|
-
}
|
|
274
|
-
process.stdout.write('\r\x1b[J');
|
|
275
|
-
process.stdout.write(inputDisplay);
|
|
276
|
-
if (dropdownLines.length > 0) {
|
|
277
|
-
for (const dl of dropdownLines) {
|
|
278
|
-
process.stdout.write(`\n${dl}`);
|
|
257
|
+
allLines.push(pc.dim('│') + ' ' + pc.dim('╰' + botBorderStr + '╯'));
|
|
258
|
+
}
|
|
259
|
+
clearPreviousRender();
|
|
260
|
+
const maxLinesToWrite = Math.max(allLines.length, lastTotalLines);
|
|
261
|
+
for (let i = 0; i < maxLinesToWrite; i++) {
|
|
262
|
+
process.stdout.write('\r\x1b[2K');
|
|
263
|
+
if (i < allLines.length) {
|
|
264
|
+
process.stdout.write(allLines[i]);
|
|
265
|
+
}
|
|
266
|
+
if (i < maxLinesToWrite - 1) {
|
|
267
|
+
process.stdout.write('\n');
|
|
279
268
|
}
|
|
280
269
|
}
|
|
281
|
-
const
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
270
|
+
const cursorInputLine = input.length === 0 ? 0 : Math.min(Math.floor(cursorPos / maxPerLine), inputLineCount - 1);
|
|
271
|
+
const cursorCol = input.length === 0 ? prefixLen : prefixLen + (cursorPos % maxPerLine);
|
|
272
|
+
const currentLine = maxLinesToWrite - 1;
|
|
273
|
+
const moveUp = currentLine - cursorInputLine;
|
|
274
|
+
if (moveUp > 0) {
|
|
275
|
+
process.stdout.write(`\x1b[${moveUp}A`);
|
|
285
276
|
}
|
|
286
277
|
process.stdout.write('\r');
|
|
287
|
-
if (
|
|
288
|
-
process.stdout.write(`\x1b[${
|
|
278
|
+
if (cursorCol > 0) {
|
|
279
|
+
process.stdout.write(`\x1b[${cursorCol}C`);
|
|
289
280
|
}
|
|
290
|
-
|
|
291
|
-
lastDropdownLines = dropdownLines.length;
|
|
281
|
+
lastTotalLines = allLines.length;
|
|
292
282
|
}
|
|
293
283
|
render();
|
|
294
284
|
function cleanup() {
|
|
@@ -303,10 +293,8 @@ export function askPrompt(opts = {}) {
|
|
|
303
293
|
process.stdin.pause();
|
|
304
294
|
}
|
|
305
295
|
function clearBoxAndExit(finalInput) {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
process.stdout.write('\r\x1b[J');
|
|
296
|
+
clearPreviousRender();
|
|
297
|
+
process.stdout.write('\r\x1b[2K');
|
|
310
298
|
const fullText = expandPastes(finalInput);
|
|
311
299
|
if (fullText.trim()) {
|
|
312
300
|
if (GLOBAL_PROMPT_HISTORY.length === 0 || GLOBAL_PROMPT_HISTORY[GLOBAL_PROMPT_HISTORY.length - 1] !== fullText.trim()) {
|
|
@@ -314,7 +302,7 @@ export function askPrompt(opts = {}) {
|
|
|
314
302
|
}
|
|
315
303
|
}
|
|
316
304
|
const lines = fullText.split('\n');
|
|
317
|
-
process.stdout.write(
|
|
305
|
+
process.stdout.write(`${pc.dim('│')} ${formatInputWithBadges(lines[0])}\n`);
|
|
318
306
|
for (let i = 1; i < lines.length; i++) {
|
|
319
307
|
process.stdout.write(pc.dim('│') + ' ' + lines[i] + '\n');
|
|
320
308
|
}
|
|
@@ -440,10 +428,8 @@ export function askPrompt(opts = {}) {
|
|
|
440
428
|
}
|
|
441
429
|
// Ctrl+C
|
|
442
430
|
if (str === '\x03' || (str.length === 1 && str.charCodeAt(0) === 3)) {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
}
|
|
446
|
-
process.stdout.write('\r\x1b[J\n');
|
|
431
|
+
clearPreviousRender();
|
|
432
|
+
process.stdout.write('\r\x1b[2K\n');
|
|
447
433
|
cleanup();
|
|
448
434
|
resolve('__CANCEL__');
|
|
449
435
|
return;
|
|
@@ -503,10 +489,8 @@ export function askPrompt(opts = {}) {
|
|
|
503
489
|
render();
|
|
504
490
|
}
|
|
505
491
|
else {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}
|
|
509
|
-
process.stdout.write('\r\x1b[J');
|
|
492
|
+
clearPreviousRender();
|
|
493
|
+
process.stdout.write('\r\x1b[2K');
|
|
510
494
|
cleanup();
|
|
511
495
|
resolve(`__TOGGLE_MODE__:${input}`);
|
|
512
496
|
}
|
package/dist/cli/server.js
CHANGED
|
@@ -139,7 +139,7 @@ function renderDirectoryHtml(dirPath, relPath, files, port) {
|
|
|
139
139
|
${parentLink}
|
|
140
140
|
${items || '<li style="padding: 20px; text-align: center; color: #6e7681;">No visible files in this directory</li>'}
|
|
141
141
|
</ul>
|
|
142
|
-
<div class="footer">devx v1.4.
|
|
142
|
+
<div class="footer">devx v1.4.6 • Terminal-Native AI Assistant</div>
|
|
143
143
|
</div>
|
|
144
144
|
</body>
|
|
145
145
|
</html>`;
|
package/dist/mcp/client.js
CHANGED
package/package.json
CHANGED