wormclaude 1.0.137 → 1.0.139

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/ansi.js CHANGED
@@ -193,6 +193,16 @@ export function itemAnsi(it, cols) {
193
193
  const extra = lines.length > 1 ? paint(` (+${lines.length - 1} ${word})`, theme.greyDim) : '';
194
194
  return '\n' + head + '\n' + paint(' ⎿ ', theme.greyDim) + paint(first, theme.grey) + extra;
195
195
  }
196
+ if (it.kind === 'fileprev') {
197
+ // Yazmadan ÖNCE dosya içeriği önizlemesi (Claude "Create file" bloğu gibi).
198
+ const word = t('tui.linesWord') || 'satır';
199
+ const lines = it.lines || [];
200
+ const head = paint(' ┌ ', theme.greyDim) + paint((t('tui.createFile') || 'Oluşturulacak dosya') + ': ', theme.redBright, true) + paint(`${it.file} (${lines.length} ${word})`, theme.white);
201
+ const PREV = 14;
202
+ const body = lines.slice(0, PREV).map((ln, i) => paint(` │ ${String(i + 1).padStart(3, ' ')} `, theme.greyDim) + paint(ln.replace(/\t/g, ' ').slice(0, Math.max(8, W - 10)), theme.grey));
203
+ const more = lines.length > PREV ? '\n' + paint(` │ … +${lines.length - PREV} ${word}`, theme.greyDim) : '';
204
+ return '\n' + head + (body.length ? '\n' + body.join('\n') : '') + more;
205
+ }
196
206
  if (it.kind === 'note')
197
207
  return '\n' + wrap(it.text || '', W).map((ln) => paint(ln, theme.greyDim)).join('\n');
198
208
  return '';
package/dist/i18n.js CHANGED
@@ -80,6 +80,8 @@ const STR = {
80
80
  'tui.wrote': 'Yazıldı:',
81
81
  'tui.edited': 'Düzenlendi:',
82
82
  'tui.toolDone': 'tamam',
83
+ 'tui.createFile': 'Oluşturulacak dosya',
84
+ 'tui.permCreate': 'oluşturulsun mu?',
83
85
  'tui.pasteSummary': '…(+{0} satır · {1} karakter, Enter ile gönder)',
84
86
  'tui.permLabel': 'İZİN',
85
87
  'tui.permRun': 'çalıştırılsın mı?',
@@ -144,6 +146,8 @@ const STR = {
144
146
  'tui.wrote': 'Wrote',
145
147
  'tui.edited': 'Edited',
146
148
  'tui.toolDone': 'done',
149
+ 'tui.createFile': 'Create file',
150
+ 'tui.permCreate': '— create it?',
147
151
  'tui.pasteSummary': '…(+{0} lines · {1} chars, Enter to send)',
148
152
  'tui.permLabel': 'PERMISSION',
149
153
  'tui.permRun': 'run it?',
@@ -9,7 +9,8 @@ import { safeJsonParse } from './safejson.js';
9
9
  const ARG_KEYS = ['arguments', 'parameters', 'input', 'args', 'params'];
10
10
  // Model araç adını JSON DIŞINA koyabiliyor: `Bash {"command":...}` / `Write {"file_path":...}`.
11
11
  const _TOOLS = 'Bash|PowerShell|Read|Write|Edit|Glob|Grep|WebFetch|WebSearch|Sleep|TaskOutput';
12
- const TOOL_PREFIX_RE = new RegExp('(?:^|[\\n>*`\\s])(' + _TOOLS + ')\\s*\\{');
12
+ // name ile `{` arasında opsiyonel `,`/`:` olabilir: `Write {`, `Write,{`, `Write, {`, `Write: {`.
13
+ const TOOL_PREFIX_RE = new RegExp('(?:^|[\\n>*`\\s])(' + _TOOLS + ')\\s*[,:]?\\s*\\{');
13
14
  // Fonksiyon-çağrı pseudo-syntax'i: `Write(file_path="...", content="""...""")`.
14
15
  const TOOL_PAREN_RE = new RegExp('(' + _TOOLS + ')\\s*\\(');
15
16
  // `key="val"` / `key='val'` / `key="""val"""` argümanlarını çözer (content çok-satırlı olabilir).
@@ -236,10 +237,11 @@ export function recoverInlineToolCalls(text) {
236
237
  // 5) "ToolName { ...args... }" — model araç adını JSON DIŞINA koyuyor (Bash {"command":...}).
237
238
  // Args doğrudan obje (arguments sarmalı yok) → {name: ToolName, arguments: {...}}.
238
239
  if (!out.length) {
239
- const re = new RegExp('(' + _TOOLS + ')\\s*(\\{)', 'g');
240
+ const re = new RegExp('(' + _TOOLS + ')\\s*[,:]?\\s*(\\{)', 'g');
240
241
  let mm;
241
242
  while ((mm = re.exec(t)) !== null) {
242
- const objs = extractTopLevelJsonObjects(t.slice(mm.index + mm[1].length));
243
+ // mm[2] = '{' konumu; name'den { 'a kadar olan kısmı (virgül/boşluk) atla.
244
+ const objs = extractTopLevelJsonObjects(t.slice(mm.index + mm[0].length - 1));
243
245
  if (objs.length) {
244
246
  const args = safeJsonParse(objs[0], null);
245
247
  if (args && typeof args === 'object' && !Array.isArray(args))
@@ -293,7 +295,7 @@ export function stripInlineToolCalls(text) {
293
295
  s = s.replace(/AskUserQuestion[\s\S]*?\[[^\]]*\]\s*/gi, '');
294
296
  // ToolName {…} biçimi (Bash {"command":...}) — adı + ardından gelen dengeli {…} bloğunu sil.
295
297
  {
296
- const re = new RegExp('(' + _TOOLS + ')\\s*\\{', 'g');
298
+ const re = new RegExp('(' + _TOOLS + ')\\s*[,:]?\\s*\\{', 'g');
297
299
  let mm;
298
300
  const spans = [];
299
301
  while ((mm = re.exec(s)) !== null) {
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.137';
19
+ export const VERSION = '1.0.139';
package/dist/tui.js CHANGED
@@ -234,7 +234,8 @@ export async function runTui() {
234
234
  let body;
235
235
  if (perm) {
236
236
  // İzin dialogu: araç adı + Evet/Tümü/Hayır
237
- const q = paint(' ' + t('tui.permLabel') + ' ', theme.redBright, true) + paint(perm.label, theme.white) + paint(' ' + t('tui.permRun'), theme.grey);
237
+ const _permQ = (perm.name === 'Write' || perm.name === 'Edit') ? t('tui.permCreate') : t('tui.permRun');
238
+ const q = paint(' ' + t('tui.permLabel') + ' ', theme.redBright, true) + paint(perm.label, theme.white) + paint(' ' + _permQ, theme.grey);
238
239
  const opts = paint(' ' + t('tui.permYes'), theme.redBright, true) + paint(' · ', theme.greyDim)
239
240
  + paint(t('tui.permAll'), theme.grey) + paint(' · ', theme.greyDim) + paint(t('tui.permNo'), theme.grey);
240
241
  body = [line, q, opts, line];
@@ -394,8 +395,13 @@ export async function runTui() {
394
395
  if (toolCalls.length)
395
396
  am.tool_calls = toolCalls.map((t) => ({ id: t.id, type: 'function', function: { name: t.name, arguments: t.args || '{}' } }));
396
397
  history.push(am);
397
- if (answer)
398
- lastAnswer = answer; // gösterim akışta yapıldı; tekrar printItem YOK (duplikasyon olmaz)
398
+ if (answer) {
399
+ lastAnswer = answer;
400
+ // RESIZE FIX: gösterim akışta stdout'a yapıldı ama displayItems'a da KAYDET ki resize/redraw
401
+ // sonrası cevap kaybolmasın. printItem YOK (stdout'a tekrar yazmaz → akışta duplikasyon olmaz),
402
+ // sadece diziye ekle → redrawAll() onu geri çizebilir.
403
+ displayItems.push({ kind: 'assistant', text: answer });
404
+ }
399
405
  if (!toolCalls.length)
400
406
  break;
401
407
  // takılma koruması: aynı araç-çağrısı 3 kez üst üste → dur
@@ -414,6 +420,11 @@ export async function runTui() {
414
420
  confirm: (c, args) => new Promise((resolve) => {
415
421
  if (allowAll.has(c.name))
416
422
  return resolve('allow');
423
+ // Claude tarzı: Write/Edit'te YAZMADAN ÖNCE dosya içeriğini göster, sonra onay iste.
424
+ if ((c.name === 'Write' && args?.content != null) || (c.name === 'Edit' && args?.new_string != null)) {
425
+ const _content = String(c.name === 'Write' ? args.content : args.new_string);
426
+ printItem({ kind: 'fileprev', file: relWs(args.file_path), lines: _content.split('\n') });
427
+ }
417
428
  perm = { label: toolLabel(c.name, args), name: c.name, resolve };
418
429
  refresh();
419
430
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wormclaude",
3
- "version": "1.0.137",
3
+ "version": "1.0.139",
4
4
  "description": "WormClaude CLI - uncensored security+code assistant (ink TUI, Claude-style)",
5
5
  "type": "module",
6
6
  "bin": {