@delt/claude-alarm 0.6.10 → 0.6.12

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.
@@ -1398,22 +1398,24 @@
1398
1398
  return toolName;
1399
1399
  }
1400
1400
 
1401
- // Returns { text, truncated } — truncated=true when input_preview was cut off
1401
+ // Returns { text } — dashboard shows full content, no truncation
1402
1402
  function formatPermPreview(toolName, raw) {
1403
- if (!raw) return { text: '', truncated: false };
1403
+ if (!raw) return { text: '' };
1404
1404
  let p = null;
1405
- let truncated = false;
1406
1405
  try { p = JSON.parse(raw); } catch {
1407
- truncated = true; // JSON parse failed = likely truncated by Claude Code
1408
- const cmdMatch = raw.match(/"command"\s*:\s*"((?:[^"\\]|\\.)*)"/);
1409
- const fileMatch = raw.match(/"file_path"\s*:\s*"((?:[^"\\]|\\.)*)"/);
1410
- const patternMatch = raw.match(/"pattern"\s*:\s*"((?:[^"\\]|\\.)*)"/);
1411
- const contentMatch = raw.match(/"content"\s*:\s*"((?:[^"\\]|\\.)*)"/);
1412
- if (cmdMatch) return { text: '$ ' + cmdMatch[1], truncated };
1413
- if (fileMatch) return { text: fileMatch[1], truncated };
1414
- if (patternMatch) return { text: patternMatch[1], truncated };
1415
- if (contentMatch) return { text: contentMatch[1].slice(0, 200), truncated };
1416
- return { text: raw.slice(0, 300), truncated };
1406
+ // Truncated JSON - extract known fields with regex (closing quote optional for truncated strings)
1407
+ const cmdMatch = raw.match(/"command"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1408
+ const fileMatch = raw.match(/"file_path"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1409
+ const patternMatch = raw.match(/"pattern"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1410
+ const contentMatch = raw.match(/"content"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1411
+ const titleMatch = raw.match(/"title"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1412
+ const msgMatch = raw.match(/"message"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1413
+ if (titleMatch && msgMatch) return { text: msgMatch[1] };
1414
+ if (cmdMatch) return { text: '$ ' + cmdMatch[1] };
1415
+ if (fileMatch) return { text: fileMatch[1] };
1416
+ if (patternMatch) return { text: patternMatch[1] };
1417
+ if (contentMatch) return { text: contentMatch[1] };
1418
+ return { text: raw };
1417
1419
  }
1418
1420
  let text;
1419
1421
  switch (toolName) {
@@ -1423,8 +1425,8 @@
1423
1425
  case 'Edit':
1424
1426
  if (p.file_path) {
1425
1427
  text = p.file_path;
1426
- if (p.new_string) { text += '\n+ ' + p.new_string.slice(0, 200); if (p.new_string.length > 200) truncated = true; }
1427
- else if (p.content) { text += '\n' + p.content.slice(0, 200); if (p.content.length > 200) truncated = true; }
1428
+ if (p.new_string) text += '\n+ ' + p.new_string;
1429
+ else if (p.content) text += '\n' + p.content;
1428
1430
  } else { text = raw; }
1429
1431
  break;
1430
1432
  case 'Read':
@@ -1435,18 +1437,16 @@
1435
1437
  text = (p.pattern || '') + (p.path ? ' in ' + p.path : ''); break;
1436
1438
  default:
1437
1439
  if (p.title && p.message) {
1438
- // Tools like notify: title is already shown in tool name, show message only
1439
1440
  text = p.message;
1440
1441
  } else if (p.content && typeof p.content === 'string') {
1441
- text = p.content.slice(0, 300);
1442
- if (p.content.length > 300) truncated = true;
1442
+ text = p.content;
1443
1443
  } else {
1444
1444
  const entries = Object.entries(p);
1445
- if (entries.length <= 3) text = entries.map(([k, v]) => k + ': ' + String(v).slice(0, 150)).join('\n');
1446
- else { text = JSON.stringify(p, null, 1).slice(0, 300); truncated = true; }
1445
+ if (entries.length <= 3) text = entries.map(([k, v]) => k + ': ' + String(v)).join('\n');
1446
+ else text = JSON.stringify(p, null, 1);
1447
1447
  }
1448
1448
  }
1449
- return { text: text || '', truncated };
1449
+ return { text: text || '' };
1450
1450
  }
1451
1451
 
1452
1452
  function sendPermissionVerdict(sessionId, requestId, behavior) {
@@ -1470,8 +1470,7 @@
1470
1470
  if (!reqs.length) { bar.classList.remove('active'); bar.innerHTML = ''; return; }
1471
1471
  bar.classList.add('active');
1472
1472
  bar.innerHTML = reqs.map(r => {
1473
- const { text: previewText, truncated } = formatPermPreview(r.toolName, r.inputPreview);
1474
- const truncLabel = truncated ? '<span style="color:var(--text-dim);font-size:10px;font-style:italic"> ...truncated</span>' : '';
1473
+ const { text: previewText } = formatPermPreview(r.toolName, r.inputPreview);
1475
1474
  const displayName = formatToolName(r.toolName, r.inputPreview);
1476
1475
  return `<div class="perm-item">
1477
1476
  <div class="perm-icon">&#9888;</div>
@@ -1479,7 +1478,7 @@
1479
1478
  <div class="perm-header">
1480
1479
  <span class="perm-tool">${esc(displayName)}</span>
1481
1480
  </div>
1482
- ${previewText ? `<div class="perm-preview">${esc(previewText)}${truncLabel}</div>` : ''}
1481
+ ${previewText ? `<div class="perm-preview">${esc(previewText)}</div>` : ''}
1483
1482
  </div>
1484
1483
  <div class="perm-actions">
1485
1484
  <button class="perm-allow" data-req-id="${esc(r.requestId)}" data-session-id="${esc(sid)}">Allow <span class="perm-kbd">(Enter)</span></button>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@delt/claude-alarm",
3
- "version": "0.6.10",
3
+ "version": "0.6.12",
4
4
  "description": "Monitor and get notifications from multiple Claude Code sessions via MCP Channels",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1398,22 +1398,24 @@
1398
1398
  return toolName;
1399
1399
  }
1400
1400
 
1401
- // Returns { text, truncated } — truncated=true when input_preview was cut off
1401
+ // Returns { text } — dashboard shows full content, no truncation
1402
1402
  function formatPermPreview(toolName, raw) {
1403
- if (!raw) return { text: '', truncated: false };
1403
+ if (!raw) return { text: '' };
1404
1404
  let p = null;
1405
- let truncated = false;
1406
1405
  try { p = JSON.parse(raw); } catch {
1407
- truncated = true; // JSON parse failed = likely truncated by Claude Code
1408
- const cmdMatch = raw.match(/"command"\s*:\s*"((?:[^"\\]|\\.)*)"/);
1409
- const fileMatch = raw.match(/"file_path"\s*:\s*"((?:[^"\\]|\\.)*)"/);
1410
- const patternMatch = raw.match(/"pattern"\s*:\s*"((?:[^"\\]|\\.)*)"/);
1411
- const contentMatch = raw.match(/"content"\s*:\s*"((?:[^"\\]|\\.)*)"/);
1412
- if (cmdMatch) return { text: '$ ' + cmdMatch[1], truncated };
1413
- if (fileMatch) return { text: fileMatch[1], truncated };
1414
- if (patternMatch) return { text: patternMatch[1], truncated };
1415
- if (contentMatch) return { text: contentMatch[1].slice(0, 200), truncated };
1416
- return { text: raw.slice(0, 300), truncated };
1406
+ // Truncated JSON - extract known fields with regex (closing quote optional for truncated strings)
1407
+ const cmdMatch = raw.match(/"command"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1408
+ const fileMatch = raw.match(/"file_path"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1409
+ const patternMatch = raw.match(/"pattern"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1410
+ const contentMatch = raw.match(/"content"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1411
+ const titleMatch = raw.match(/"title"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1412
+ const msgMatch = raw.match(/"message"\s*:\s*"((?:[^"\\]|\\.)*)"?/);
1413
+ if (titleMatch && msgMatch) return { text: msgMatch[1] };
1414
+ if (cmdMatch) return { text: '$ ' + cmdMatch[1] };
1415
+ if (fileMatch) return { text: fileMatch[1] };
1416
+ if (patternMatch) return { text: patternMatch[1] };
1417
+ if (contentMatch) return { text: contentMatch[1] };
1418
+ return { text: raw };
1417
1419
  }
1418
1420
  let text;
1419
1421
  switch (toolName) {
@@ -1423,8 +1425,8 @@
1423
1425
  case 'Edit':
1424
1426
  if (p.file_path) {
1425
1427
  text = p.file_path;
1426
- if (p.new_string) { text += '\n+ ' + p.new_string.slice(0, 200); if (p.new_string.length > 200) truncated = true; }
1427
- else if (p.content) { text += '\n' + p.content.slice(0, 200); if (p.content.length > 200) truncated = true; }
1428
+ if (p.new_string) text += '\n+ ' + p.new_string;
1429
+ else if (p.content) text += '\n' + p.content;
1428
1430
  } else { text = raw; }
1429
1431
  break;
1430
1432
  case 'Read':
@@ -1435,18 +1437,16 @@
1435
1437
  text = (p.pattern || '') + (p.path ? ' in ' + p.path : ''); break;
1436
1438
  default:
1437
1439
  if (p.title && p.message) {
1438
- // Tools like notify: title is already shown in tool name, show message only
1439
1440
  text = p.message;
1440
1441
  } else if (p.content && typeof p.content === 'string') {
1441
- text = p.content.slice(0, 300);
1442
- if (p.content.length > 300) truncated = true;
1442
+ text = p.content;
1443
1443
  } else {
1444
1444
  const entries = Object.entries(p);
1445
- if (entries.length <= 3) text = entries.map(([k, v]) => k + ': ' + String(v).slice(0, 150)).join('\n');
1446
- else { text = JSON.stringify(p, null, 1).slice(0, 300); truncated = true; }
1445
+ if (entries.length <= 3) text = entries.map(([k, v]) => k + ': ' + String(v)).join('\n');
1446
+ else text = JSON.stringify(p, null, 1);
1447
1447
  }
1448
1448
  }
1449
- return { text: text || '', truncated };
1449
+ return { text: text || '' };
1450
1450
  }
1451
1451
 
1452
1452
  function sendPermissionVerdict(sessionId, requestId, behavior) {
@@ -1470,8 +1470,7 @@
1470
1470
  if (!reqs.length) { bar.classList.remove('active'); bar.innerHTML = ''; return; }
1471
1471
  bar.classList.add('active');
1472
1472
  bar.innerHTML = reqs.map(r => {
1473
- const { text: previewText, truncated } = formatPermPreview(r.toolName, r.inputPreview);
1474
- const truncLabel = truncated ? '<span style="color:var(--text-dim);font-size:10px;font-style:italic"> ...truncated</span>' : '';
1473
+ const { text: previewText } = formatPermPreview(r.toolName, r.inputPreview);
1475
1474
  const displayName = formatToolName(r.toolName, r.inputPreview);
1476
1475
  return `<div class="perm-item">
1477
1476
  <div class="perm-icon">&#9888;</div>
@@ -1479,7 +1478,7 @@
1479
1478
  <div class="perm-header">
1480
1479
  <span class="perm-tool">${esc(displayName)}</span>
1481
1480
  </div>
1482
- ${previewText ? `<div class="perm-preview">${esc(previewText)}${truncLabel}</div>` : ''}
1481
+ ${previewText ? `<div class="perm-preview">${esc(previewText)}</div>` : ''}
1483
1482
  </div>
1484
1483
  <div class="perm-actions">
1485
1484
  <button class="perm-allow" data-req-id="${esc(r.requestId)}" data-session-id="${esc(sid)}">Allow <span class="perm-kbd">(Enter)</span></button>