termux-dev 1.4.12 → 1.4.13

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 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.12</tspan>
28
+ THE TERMINAL-NATIVE AI CODING AGENT <tspan fill="#00f2fe" font-weight="bold">v1.4.13</tspan>
29
29
  </text>
30
30
 
31
31
  <!-- Top Accent Line -->
@@ -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.12'
21
+ 'User-Agent': 'devx-doctor/1.4.13'
22
22
  }
23
23
  }, (res) => {
24
24
  res.resume(); // consume response data to free up memory and release socket
@@ -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.12 (headless) | ${planMode ? 'PLAN' : 'AGENT'} | ${config.model}`)));
38
+ console.log(pc.bold(pc.cyan(`⚡ devx v1.4.13 (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.12'),
487
+ ' ' + theme.boldFn('v1.4.13'),
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.12'),
502
+ indent + theme.boldFn('v1.4.13'),
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.12 • theme: ${currentTh.name})`)}`,
648
+ message: `${pc.bold('⚙️ Settings')} ${pc.dim(`(devx v1.4.13 • 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.12 by ApvCode)')}`,
689
+ name: `${currentTh.colorFn('✨ About devx')} ${pc.dim('(v1.4.13 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.12 — Terminal-Native AI Coding Agent\n` +
705
+ p.note(`⚡ devx v1.4.13 — 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.12')
774
+ .version('1.4.13')
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')
@@ -79,7 +79,7 @@ export function askPrompt(opts = {}) {
79
79
  return spans;
80
80
  }
81
81
  function formatInputWithBadges(str) {
82
- return str.replace(/(\[(?:Pasted text #\d+ \+\d+ lines|\d+\.png \d+kb)\])/g, (match) => theme.badgeFn(` ${match.slice(1, -1)} `));
82
+ return str.replace(/(\[(?:Pasted text #\d+ \+\d+ lines|\d+\.png \d+kb)\])/g, (match) => theme.badgeFn(` ${match.slice(1, -1)} `) + '\x1b[0m');
83
83
  }
84
84
  function expandPastes(text) {
85
85
  let expanded = text;
@@ -95,13 +95,11 @@ export function askPrompt(opts = {}) {
95
95
  const trimmed = text.trim();
96
96
  const lines = trimmed.split(/\r\n|\r|\n/);
97
97
  if (lines.length <= 1 && text.length < 80) {
98
- // Short paste: insert normally
99
98
  input = input.slice(0, cursorPos) + text + input.slice(cursorPos);
100
99
  cursorPos += text.length;
101
100
  render();
102
101
  return;
103
102
  }
104
- // Check if pasted text is an image path
105
103
  if (trimmed.match(/\.(png|jpe?g|webp|gif|bmp)$/i)) {
106
104
  processPastedFilePath(trimmed, usedImageNames)
107
105
  .then((imgRes) => {
@@ -130,7 +128,6 @@ export function askPrompt(opts = {}) {
130
128
  render();
131
129
  }
132
130
  function getDropdownItems() {
133
- // 1. Slash commands dropdown (when input starts with /)
134
131
  if (input.startsWith('/')) {
135
132
  const q = input.trim().toLowerCase();
136
133
  const baseList = [
@@ -146,7 +143,6 @@ export function askPrompt(opts = {}) {
146
143
  replaceLen: input.length
147
144
  }));
148
145
  }
149
- // 2. @ file mention autocomplete
150
146
  const beforeCursor = input.slice(0, cursorPos);
151
147
  const atMatch = beforeCursor.match(/@([a-zA-Z0-9_\-./]*)$/);
152
148
  if (atMatch && availableFiles.length > 0) {
@@ -179,7 +175,7 @@ export function askPrompt(opts = {}) {
179
175
  if (selectedIndex < 0)
180
176
  selectedIndex = 0;
181
177
  const pageSize = Math.min(4, Math.max(2, Math.floor(rows / 4)));
182
- const innerBoxWidth = Math.max(14, Math.min(cols - 6, 50));
178
+ const innerBoxWidth = Math.max(10, Math.min(cols - 8, 48));
183
179
  const total = items.length;
184
180
  let startIndex = 0;
185
181
  if (total > pageSize) {
@@ -200,47 +196,42 @@ export function askPrompt(opts = {}) {
200
196
  const mid = Math.max(0, Math.floor(innerBoxWidth / 2) - 2);
201
197
  botBorderStr = '─'.repeat(mid) + ' ▼ ' + '─'.repeat(Math.max(0, innerBoxWidth - mid - 3));
202
198
  }
203
- dropdownLines.push(pc.dim('│') + ' ' + pc.dim('╭' + topBorderStr + '╮'));
199
+ dropdownLines.push(pc.dim('│') + ' ' + pc.dim('╭' + topBorderStr + '╮') + '\x1b[0m');
204
200
  for (let i = startIndex; i < endIndex; i++) {
205
201
  const item = items[i];
206
202
  const isSelected = i === selectedIndex;
207
203
  const pointer = isSelected ? '› ' : ' ';
208
- const availWidth = innerBoxWidth - 2;
204
+ const availWidth = innerBoxWidth;
209
205
  let row = '';
210
- if (availWidth < 22) {
211
- const labelStr = item.label.length > availWidth
212
- ? item.label.slice(0, availWidth - 1) + '…'
213
- : item.label.padEnd(availWidth);
214
- const plain = pointer + labelStr;
215
- row = isSelected ? theme.badgeFn(plain) : pointer + theme.boldFn(labelStr);
206
+ if (availWidth < 20) {
207
+ const labelStr = item.label.length > availWidth - 2
208
+ ? item.label.slice(0, availWidth - 3) + '…'
209
+ : item.label.padEnd(availWidth - 2, ' ');
210
+ const plain = (pointer + labelStr).padEnd(availWidth, ' ').slice(0, availWidth);
211
+ row = isSelected
212
+ ? theme.badgeFn(plain) + '\x1b[0m'
213
+ : pointer + theme.boldFn(labelStr) + '\x1b[0m';
216
214
  }
217
215
  else {
218
- const labelMax = Math.min(14, Math.floor(availWidth * 0.42));
216
+ const labelMax = Math.min(13, Math.max(6, Math.floor(availWidth * 0.35)));
219
217
  const labelStr = item.label.length > labelMax
220
218
  ? item.label.slice(0, labelMax - 1) + '…'
221
- : item.label.padEnd(labelMax);
222
- const descMax = availWidth - labelMax - 1;
219
+ : item.label.padEnd(labelMax, ' ');
220
+ const descMax = Math.max(4, availWidth - labelMax - pointer.length - 1);
223
221
  const descStr = item.desc.length > descMax
224
222
  ? item.desc.slice(0, descMax - 1) + '…'
225
- : item.desc.padEnd(descMax);
226
- const plain = `${pointer}${labelStr} ${descStr}`;
223
+ : item.desc.padEnd(descMax, ' ');
224
+ const plain = (pointer + labelStr + ' ' + descStr).padEnd(availWidth, ' ').slice(0, availWidth);
227
225
  if (isSelected) {
228
- row = theme.badgeFn(plain);
226
+ row = theme.badgeFn(plain) + '\x1b[0m';
229
227
  }
230
228
  else {
231
- row = `${pointer}${theme.boldFn(labelStr)} ${pc.gray(descStr)}`;
229
+ row = `${pointer}${theme.boldFn(labelStr)} ${pc.gray(descStr)}\x1b[0m`;
232
230
  }
233
231
  }
234
- const currentLen = stripAnsi(row).length;
235
- if (currentLen < innerBoxWidth) {
236
- row += ' '.repeat(innerBoxWidth - currentLen);
237
- }
238
- else if (currentLen > innerBoxWidth) {
239
- row = row.slice(0, innerBoxWidth);
240
- }
241
- dropdownLines.push(pc.dim('│') + ' ' + pc.dim('│') + row + pc.dim('│'));
232
+ dropdownLines.push(pc.dim('│') + ' ' + pc.dim('│') + row + pc.dim('│') + '\x1b[0m');
242
233
  }
243
- dropdownLines.push(pc.dim('│') + ' ' + pc.dim('╰' + botBorderStr + '╯'));
234
+ dropdownLines.push(pc.dim('│') + ' ' + pc.dim('╰' + botBorderStr + '╯') + '\x1b[0m');
244
235
  }
245
236
  // 1. Format and write the Prompt line safely (guaranteed <= cols - 1 chars)
246
237
  let inputDisplay = pc.dim('│') + ' ';
@@ -248,13 +239,13 @@ export function askPrompt(opts = {}) {
248
239
  if (input.length === 0) {
249
240
  const maxPlace = Math.max(10, cols - 6);
250
241
  const displayPlace = placeholder.length > maxPlace ? placeholder.slice(0, maxPlace - 1) + '…' : placeholder;
251
- inputDisplay += pc.dim(displayPlace);
242
+ inputDisplay += pc.dim(displayPlace) + '\x1b[0m';
252
243
  renderCursorCol = 3;
253
244
  }
254
245
  else {
255
246
  const maxInputLen = Math.max(10, cols - 6);
256
247
  if (input.length <= maxInputLen) {
257
- inputDisplay += formatInputWithBadges(input);
248
+ inputDisplay += formatInputWithBadges(input) + '\x1b[0m';
258
249
  renderCursorCol = 3 + cursorPos;
259
250
  }
260
251
  else {
@@ -263,24 +254,24 @@ export function askPrompt(opts = {}) {
263
254
  const visibleChunk = input.slice(start, start + maxInputLen);
264
255
  const prefix = start > 0 ? '…' : '';
265
256
  const suffix = start + maxInputLen < input.length ? '…' : '';
266
- inputDisplay += pc.dim(prefix) + formatInputWithBadges(visibleChunk) + pc.dim(suffix);
257
+ inputDisplay += pc.dim(prefix) + formatInputWithBadges(visibleChunk) + pc.dim(suffix) + '\x1b[0m';
267
258
  renderCursorCol = 3 + (prefix ? 1 : 0) + (cursorPos - start);
268
259
  }
269
260
  }
270
- process.stdout.write(`\r\x1b[2K${inputDisplay}`);
261
+ process.stdout.write(`\x1b[0m\r\x1b[2K${inputDisplay}\x1b[0m`);
271
262
  // 2. Draw dropdown lines below, and clear extra lines from previous render
272
263
  const maxDropdowns = Math.max(dropdownLines.length, lastRenderedDropdownLines);
273
264
  if (maxDropdowns > 0) {
274
265
  for (let i = 0; i < maxDropdowns; i++) {
275
266
  if (i < dropdownLines.length) {
276
- process.stdout.write(`\n\x1b[2K${dropdownLines[i]}`);
267
+ process.stdout.write(`\n\x1b[0m\x1b[2K${dropdownLines[i]}\x1b[0m`);
277
268
  }
278
269
  else {
279
- process.stdout.write(`\n\x1b[2K`);
270
+ process.stdout.write(`\n\x1b[0m\x1b[2K`);
280
271
  }
281
272
  }
282
273
  // Move cursor back up to input line (line 0)
283
- process.stdout.write(`\x1b[${maxDropdowns}A`);
274
+ process.stdout.write(`\x1b[0m\x1b[${maxDropdowns}A`);
284
275
  }
285
276
  // 3. Place cursor precisely
286
277
  process.stdout.write(`\r\x1b[${renderCursorCol}C`);
@@ -301,9 +292,9 @@ export function askPrompt(opts = {}) {
301
292
  function clearBoxAndExit(finalInput) {
302
293
  if (lastRenderedDropdownLines > 0) {
303
294
  for (let i = 0; i < lastRenderedDropdownLines; i++) {
304
- process.stdout.write(`\n\x1b[2K`);
295
+ process.stdout.write(`\n\x1b[0m\x1b[2K`);
305
296
  }
306
- process.stdout.write(`\x1b[${lastRenderedDropdownLines}A`);
297
+ process.stdout.write(`\x1b[0m\x1b[${lastRenderedDropdownLines}A`);
307
298
  lastRenderedDropdownLines = 0;
308
299
  }
309
300
  const fullText = expandPastes(finalInput);
@@ -313,7 +304,7 @@ export function askPrompt(opts = {}) {
313
304
  GLOBAL_PROMPT_HISTORY.push(fullText.trim());
314
305
  }
315
306
  }
316
- process.stdout.write(`\r\x1b[2K${pc.dim('│')} ${formatInputWithBadges(finalInput)}\n\n`);
307
+ process.stdout.write(`\x1b[0m\r\x1b[2K${pc.dim('│')} ${formatInputWithBadges(finalInput)}\x1b[0m\n\n`);
317
308
  cleanup();
318
309
  resolve(fullText);
319
310
  }
@@ -359,12 +350,12 @@ export function askPrompt(opts = {}) {
359
350
  if (str === '\x03') {
360
351
  if (lastRenderedDropdownLines > 0) {
361
352
  for (let i = 0; i < lastRenderedDropdownLines; i++) {
362
- process.stdout.write(`\n\x1b[2K`);
353
+ process.stdout.write(`\n\x1b[0m\x1b[2K`);
363
354
  }
364
- process.stdout.write(`\x1b[${lastRenderedDropdownLines}A`);
355
+ process.stdout.write(`\x1b[0m\x1b[${lastRenderedDropdownLines}A`);
365
356
  lastRenderedDropdownLines = 0;
366
357
  }
367
- process.stdout.write(`\r\x1b[2K\n`);
358
+ process.stdout.write(`\x1b[0m\r\x1b[2K\n`);
368
359
  cleanup();
369
360
  resolve('__CANCEL__');
370
361
  return;
@@ -396,7 +387,7 @@ export function askPrompt(opts = {}) {
396
387
  render();
397
388
  }
398
389
  else {
399
- process.stdout.write(`\r\x1b[2K${pc.yellow('⚠️ No image in clipboard. Take a screenshot first (Win+Shift+S)\n')}`);
390
+ process.stdout.write(`\x1b[0m\r\x1b[2K${pc.yellow('⚠️ No image in clipboard. Take a screenshot first (Win+Shift+S)\n')}`);
400
391
  input = '';
401
392
  cursorPos = 0;
402
393
  render();
@@ -440,12 +431,12 @@ export function askPrompt(opts = {}) {
440
431
  else {
441
432
  if (lastRenderedDropdownLines > 0) {
442
433
  for (let i = 0; i < lastRenderedDropdownLines; i++) {
443
- process.stdout.write(`\n\x1b[2K`);
434
+ process.stdout.write(`\n\x1b[0m\x1b[2K`);
444
435
  }
445
- process.stdout.write(`\x1b[${lastRenderedDropdownLines}A`);
436
+ process.stdout.write(`\x1b[0m\x1b[${lastRenderedDropdownLines}A`);
446
437
  lastRenderedDropdownLines = 0;
447
438
  }
448
- process.stdout.write(`\r\x1b[2K`);
439
+ process.stdout.write(`\x1b[0m\r\x1b[2K`);
449
440
  cleanup();
450
441
  resolve(`__TOGGLE_MODE__:${input}`);
451
442
  }
@@ -551,7 +542,7 @@ export function askPrompt(opts = {}) {
551
542
  }
552
543
  return;
553
544
  }
554
- // Backspace / DEL handling (including Android IME chunks)
545
+ // Backspace / DEL handling
555
546
  if (str.includes('\x08') || str.includes('\x7f')) {
556
547
  for (let i = 0; i < str.length; i++) {
557
548
  const ch = str[i];
@@ -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.12 &bull; Terminal-Native AI Assistant</div>
142
+ <div class="footer">devx v1.4.13 &bull; Terminal-Native AI Assistant</div>
143
143
  </div>
144
144
  </body>
145
145
  </html>`;
package/dist/cli/theme.js CHANGED
@@ -8,7 +8,7 @@ export const THEMES = {
8
8
  colorFn: (s) => pc.cyan(s),
9
9
  boldFn: (s) => pc.bold(pc.cyan(s)),
10
10
  accentFn: (s) => pc.blue(s),
11
- badgeFn: (s) => pc.bgCyan(pc.black(` ${s} `)),
11
+ badgeFn: (s) => pc.bgCyan(pc.black(s)),
12
12
  diffAddBg: (s) => pc.bgCyan(pc.black(s)),
13
13
  diffRemoveBg: (s) => pc.bgBlue(pc.white(s)),
14
14
  hex: '#00f2fe'
@@ -21,7 +21,7 @@ export const THEMES = {
21
21
  colorFn: (s) => pc.magenta(s),
22
22
  boldFn: (s) => pc.bold(pc.magenta(s)),
23
23
  accentFn: (s) => pc.blue(s),
24
- badgeFn: (s) => pc.bgMagenta(pc.black(` ${s} `)),
24
+ badgeFn: (s) => pc.bgMagenta(pc.black(s)),
25
25
  diffAddBg: (s) => pc.bgMagenta(pc.black(s)),
26
26
  diffRemoveBg: (s) => pc.bgBlue(pc.white(s)),
27
27
  hex: '#d946ef'
@@ -34,7 +34,7 @@ export const THEMES = {
34
34
  colorFn: (s) => pc.green(s),
35
35
  boldFn: (s) => pc.bold(pc.green(s)),
36
36
  accentFn: (s) => pc.cyan(s),
37
- badgeFn: (s) => pc.bgGreen(pc.black(` ${s} `)),
37
+ badgeFn: (s) => pc.bgGreen(pc.black(s)),
38
38
  diffAddBg: (s) => pc.bgGreen(pc.black(s)),
39
39
  diffRemoveBg: (s) => pc.bgRed(pc.white(s)),
40
40
  hex: '#22c55e'
@@ -47,7 +47,7 @@ export const THEMES = {
47
47
  colorFn: (s) => pc.yellow(s),
48
48
  boldFn: (s) => pc.bold(pc.yellow(s)),
49
49
  accentFn: (s) => pc.red(s),
50
- badgeFn: (s) => pc.bgYellow(pc.black(` ${s} `)),
50
+ badgeFn: (s) => pc.bgYellow(pc.black(s)),
51
51
  diffAddBg: (s) => pc.bgYellow(pc.black(s)),
52
52
  diffRemoveBg: (s) => pc.bgRed(pc.white(s)),
53
53
  hex: '#f59e0b'
@@ -60,7 +60,7 @@ export const THEMES = {
60
60
  colorFn: (s) => pc.red(s),
61
61
  boldFn: (s) => pc.bold(pc.red(s)),
62
62
  accentFn: (s) => pc.magenta(s),
63
- badgeFn: (s) => pc.bgRed(pc.white(` ${s} `)),
63
+ badgeFn: (s) => pc.bgRed(pc.white(s)),
64
64
  diffAddBg: (s) => pc.bgRed(pc.white(s)),
65
65
  diffRemoveBg: (s) => pc.bgMagenta(pc.white(s)),
66
66
  hex: '#ef4444'
@@ -73,7 +73,7 @@ export const THEMES = {
73
73
  colorFn: (s) => pc.white(s),
74
74
  boldFn: (s) => pc.bold(pc.white(s)),
75
75
  accentFn: (s) => pc.dim(s),
76
- badgeFn: (s) => pc.bgWhite(pc.black(` ${s} `)),
76
+ badgeFn: (s) => pc.bgWhite(pc.black(s)),
77
77
  diffAddBg: (s) => pc.bgWhite(pc.black(s)),
78
78
  diffRemoveBg: (s) => pc.bgBlack(pc.white(s)),
79
79
  hex: '#ffffff'
@@ -63,7 +63,7 @@ export class MCPClient {
63
63
  capabilities: {},
64
64
  clientInfo: {
65
65
  name: 'devx',
66
- version: '1.4.12'
66
+ version: '1.4.13'
67
67
  }
68
68
  });
69
69
  if (!initResult) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termux-dev",
3
- "version": "1.4.12",
3
+ "version": "1.4.13",
4
4
  "description": "Ultra-fast, terminal-native AI coding assistant and agent built for Android Termux, Windows, macOS, and Linux.",
5
5
  "main": "dist/cli/index.js",
6
6
  "type": "module",