wormclaude 1.0.97 → 1.0.98

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/dist/theme.js CHANGED
@@ -16,4 +16,4 @@ export const theme = {
16
16
  synType: '#a78bfa', // tip/sınıf adları, sabitler
17
17
  synProp: '#e0e0e0', // özellik/anahtar adları
18
18
  };
19
- export const VERSION = '1.0.97';
19
+ export const VERSION = '1.0.98';
package/dist/tui.js CHANGED
@@ -64,7 +64,7 @@ export async function runTui() {
64
64
  ...(_memCtx ? [{ role: 'system', content: _memCtx }] : []),
65
65
  ];
66
66
  const displayItems = [{ kind: 'banner' }];
67
- let inputBuf = '', busy = false, streamChars = 0, spin = 0;
67
+ let inputBuf = '', inputCur = 0, busy = false, streamChars = 0, spin = 0;
68
68
  // Canlı akış artık FOOTER'da DEĞİL — içerik akışına (mesajın altından aşağı) satır-satır basılır.
69
69
  const SPIN = ['·', '✢', '✳', '✶', '✻', '✽', '✶', '✳', '✢'];
70
70
  // Canlı bağlam ölçer: son isteğin prompt_tokens'ı = o anki kullanılan bağlam (footer'da gösterilir).
@@ -76,25 +76,36 @@ export async function runTui() {
76
76
  const MAX_INPUT_LINES = 6;
77
77
  const inputBoxLines = (W) => {
78
78
  const inner = Math.max(4, W - 2); // "✶ " önek payı
79
+ const REV = '\x1b[7m', UNREV = '\x1b[27m'; // ters-video blok imleç
80
+ // Karakterleri hücreye çevir; imleçteki karakter ters-video (sondaysa boşluk bloğu).
81
+ const cells = [];
82
+ const chs = [...inputBuf];
83
+ for (let i = 0; i < chs.length; i++) {
84
+ cells.push({ s: i === inputCur ? REV + chs[i] + UNREV : chs[i], w: stringWidth(chs[i]) || 1 });
85
+ }
86
+ if (inputCur >= chs.length)
87
+ cells.push({ s: REV + ' ' + UNREV, w: 1 });
88
+ // Genişliğe göre sar.
79
89
  const wrapped = [];
80
- let cur = '';
81
- for (const ch of inputBuf) {
82
- if (vis(cur + ch) > inner) {
90
+ let cur = '', w = 0;
91
+ for (const c of cells) {
92
+ if (w + c.w > inner) {
83
93
  wrapped.push(cur);
84
- cur = ch;
94
+ cur = '';
95
+ w = 0;
85
96
  }
86
- else
87
- cur += ch;
97
+ cur += c.s;
98
+ w += c.w;
88
99
  }
89
100
  wrapped.push(cur);
90
101
  if (wrapped.length <= MAX_INPUT_LINES) {
91
- return wrapped.map((ln, i) => (i === 0 ? paint('✶ ', theme.redBright, true) : ' ') + paint(ln, theme.white) + (i === wrapped.length - 1 ? paint('▌', theme.greyDim) : ''));
102
+ return wrapped.map((ln, i) => (i === 0 ? paint('✶ ', theme.redBright, true) : ' ') + paint(ln, theme.white));
92
103
  }
93
104
  // Çok uzun (büyük yapıştırma): son birkaç satır + üstte özet — footer'ı doldurmaz.
94
105
  const extra = wrapped.length - (MAX_INPUT_LINES - 1);
95
106
  const tail = wrapped.slice(-(MAX_INPUT_LINES - 1));
96
107
  const head = paint('✶ ' + t('tui.pasteSummary', extra, inputBuf.length), theme.greyDim);
97
- return [head, ...tail.map((ln, i) => ' ' + paint(ln, theme.white) + (i === tail.length - 1 ? paint('▌', theme.greyDim) : ''))];
108
+ return [head, ...tail.map((ln) => ' ' + paint(ln, theme.white))];
98
109
  };
99
110
  // Footer yüksekliği DİNAMİK: izin=4; değilse (durum/menü) + çizgi + giriş-satırları + çizgi.
100
111
  // SABİT rezerve footer alanı (scroll region bir kez ayarlanır → churn/duplicate yok). Footer bu
@@ -464,6 +475,7 @@ export async function runTui() {
464
475
  if (key && key.ctrl && key.name === 'c') {
465
476
  if (inputBuf) {
466
477
  inputBuf = '';
478
+ inputCur = 0;
467
479
  refresh();
468
480
  return;
469
481
  }
@@ -489,6 +501,7 @@ export async function runTui() {
489
501
  if (inputHistory.length) {
490
502
  histIdx = histIdx < 0 ? inputHistory.length - 1 : Math.max(0, histIdx - 1);
491
503
  inputBuf = inputHistory[histIdx];
504
+ inputCur = inputBuf.length;
492
505
  refresh();
493
506
  }
494
507
  return;
@@ -508,15 +521,38 @@ export async function runTui() {
508
521
  }
509
522
  else
510
523
  inputBuf = inputHistory[histIdx];
524
+ inputCur = inputBuf.length;
511
525
  refresh();
512
526
  }
513
527
  return;
514
528
  }
529
+ // ← → imleç hareketi + Home/End (Ctrl+A/Ctrl+E)
530
+ if (key && key.name === 'left') {
531
+ inputCur = Math.max(0, inputCur - 1);
532
+ refresh();
533
+ return;
534
+ }
535
+ if (key && key.name === 'right') {
536
+ inputCur = Math.min(inputBuf.length, inputCur + 1);
537
+ refresh();
538
+ return;
539
+ }
540
+ if (key && (key.name === 'home' || (key.ctrl && key.name === 'a'))) {
541
+ inputCur = 0;
542
+ refresh();
543
+ return;
544
+ }
545
+ if (key && (key.name === 'end' || (key.ctrl && key.name === 'e'))) {
546
+ inputCur = inputBuf.length;
547
+ refresh();
548
+ return;
549
+ }
515
550
  // Tab — seçili slash komutunu tamamla
516
551
  if (key && key.name === 'tab') {
517
552
  const m = cmdMatches();
518
553
  if (m.length) {
519
554
  inputBuf = m[Math.min(cmdSel, m.length - 1)].name + ' ';
555
+ inputCur = inputBuf.length;
520
556
  cmdSel = 0;
521
557
  refresh();
522
558
  }
@@ -527,6 +563,7 @@ export async function runTui() {
527
563
  return; // tur sürerken Enter beklemede; yazılan metin durur (type-ahead)
528
564
  let v = inputBuf.trim();
529
565
  inputBuf = '';
566
+ inputCur = 0;
530
567
  histIdx = -1;
531
568
  if (!v) {
532
569
  refresh();
@@ -601,19 +638,31 @@ export async function runTui() {
601
638
  return;
602
639
  }
603
640
  if (key && key.name === 'backspace') {
604
- inputBuf = inputBuf.slice(0, -1);
641
+ if (inputCur > 0) {
642
+ inputBuf = inputBuf.slice(0, inputCur - 1) + inputBuf.slice(inputCur);
643
+ inputCur--;
644
+ }
645
+ cmdSel = 0;
646
+ scheduleFooter();
647
+ return;
648
+ }
649
+ if (key && key.name === 'delete') {
650
+ if (inputCur < inputBuf.length)
651
+ inputBuf = inputBuf.slice(0, inputCur) + inputBuf.slice(inputCur + 1);
605
652
  cmdSel = 0;
606
653
  scheduleFooter();
607
654
  return;
608
655
  }
609
656
  if (key && key.name === 'escape') {
610
657
  inputBuf = '';
658
+ inputCur = 0;
611
659
  refresh();
612
660
  return;
613
661
  }
614
- // sadece gerçek yazdırılabilir karakter (her zaman → cevap üretilirken bile type-ahead)
662
+ // sadece gerçek yazdırılabilir karakter — imleç KONUMUNA ekle (her zaman → type-ahead)
615
663
  if (str && !key?.ctrl && !key?.meta && !str.startsWith('\x1b') && !/[\x00-\x1f]/.test(str)) {
616
- inputBuf += str;
664
+ inputBuf = inputBuf.slice(0, inputCur) + str + inputBuf.slice(inputCur);
665
+ inputCur += str.length;
617
666
  cmdSel = 0;
618
667
  scheduleFooter();
619
668
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wormclaude",
3
- "version": "1.0.97",
3
+ "version": "1.0.98",
4
4
  "description": "WormClaude CLI - uncensored security+code assistant (ink TUI, Claude-style)",
5
5
  "type": "module",
6
6
  "bin": {