claude-code-templates 1.5.8 → 1.5.9

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/analytics.js +154 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-templates",
3
- "version": "1.5.8",
3
+ "version": "1.5.9",
4
4
  "description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/analytics.js CHANGED
@@ -138,7 +138,8 @@ class ClaudeAnalytics {
138
138
  tokens: this.estimateTokens(content),
139
139
  project: projectFromPath || this.extractProjectFromConversation(parsedMessages),
140
140
  status: this.determineConversationStatus(parsedMessages, stats.mtime),
141
- conversationState: this.determineConversationState(parsedMessages, stats.mtime)
141
+ conversationState: this.determineConversationState(parsedMessages, stats.mtime),
142
+ statusSquares: this.generateStatusSquares(parsedMessages)
142
143
  };
143
144
 
144
145
  conversations.push(conversation);
@@ -303,6 +304,78 @@ class ClaudeAnalytics {
303
304
  return 'Inactive';
304
305
  }
305
306
 
307
+ generateStatusSquares(messages) {
308
+ if (!messages || messages.length === 0) {
309
+ return [];
310
+ }
311
+
312
+ // Sort messages by timestamp and take last 10 for status squares
313
+ const sortedMessages = messages.sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));
314
+ const recentMessages = sortedMessages.slice(-10);
315
+
316
+ return recentMessages.map((message, index) => {
317
+ const messageNum = sortedMessages.length - recentMessages.length + index + 1;
318
+
319
+ // Determine status based on message content and role
320
+ if (message.role === 'user') {
321
+ return {
322
+ type: 'pending',
323
+ tooltip: `Message #${messageNum}: User input`
324
+ };
325
+ } else if (message.role === 'assistant') {
326
+ // Check if the message contains tool usage or errors
327
+ const content = message.content || '';
328
+
329
+ if (typeof content === 'string') {
330
+ if (content.includes('[Tool:') || content.includes('tool_use')) {
331
+ return {
332
+ type: 'tool',
333
+ tooltip: `Message #${messageNum}: Tool execution`
334
+ };
335
+ } else if (content.includes('error') || content.includes('Error') || content.includes('failed')) {
336
+ return {
337
+ type: 'error',
338
+ tooltip: `Message #${messageNum}: Error in response`
339
+ };
340
+ } else {
341
+ return {
342
+ type: 'success',
343
+ tooltip: `Message #${messageNum}: Successful response`
344
+ };
345
+ }
346
+ } else if (Array.isArray(content)) {
347
+ // Check for tool_use blocks in array content
348
+ const hasToolUse = content.some(block => block.type === 'tool_use');
349
+ const hasError = content.some(block =>
350
+ block.type === 'text' && (block.text?.includes('error') || block.text?.includes('Error'))
351
+ );
352
+
353
+ if (hasError) {
354
+ return {
355
+ type: 'error',
356
+ tooltip: `Message #${messageNum}: Error in response`
357
+ };
358
+ } else if (hasToolUse) {
359
+ return {
360
+ type: 'tool',
361
+ tooltip: `Message #${messageNum}: Tool execution`
362
+ };
363
+ } else {
364
+ return {
365
+ type: 'success',
366
+ tooltip: `Message #${messageNum}: Successful response`
367
+ };
368
+ }
369
+ }
370
+ }
371
+
372
+ return {
373
+ type: 'pending',
374
+ tooltip: `Message #${messageNum}: Unknown status`
375
+ };
376
+ });
377
+ }
378
+
306
379
  determineProjectStatus(lastActivity) {
307
380
  const now = new Date();
308
381
  const timeDiff = now - lastActivity;
@@ -731,6 +804,10 @@ async function createWebDashboard() {
731
804
  .session-id {
732
805
  color: #d57455;
733
806
  font-family: monospace;
807
+ display: flex;
808
+ align-items: center;
809
+ flex-wrap: wrap;
810
+ gap: 4px;
734
811
  }
735
812
 
736
813
  .session-project {
@@ -787,6 +864,66 @@ async function createWebDashboard() {
787
864
  50% { opacity: 0.6; }
788
865
  }
789
866
 
867
+ .status-squares {
868
+ display: flex;
869
+ gap: 2px;
870
+ align-items: center;
871
+ margin-left: 4px;
872
+ flex-wrap: wrap;
873
+ }
874
+
875
+ .status-square {
876
+ width: 8px;
877
+ height: 8px;
878
+ border-radius: 1px;
879
+ cursor: help;
880
+ position: relative;
881
+ }
882
+
883
+ .status-square.success {
884
+ background: #d57455;
885
+ }
886
+
887
+ .status-square.tool {
888
+ background: #f97316;
889
+ }
890
+
891
+ .status-square.error {
892
+ background: #dc2626;
893
+ }
894
+
895
+ .status-square.pending {
896
+ background: #6b7280;
897
+ }
898
+
899
+ .status-square:hover::after {
900
+ content: attr(data-tooltip);
901
+ position: absolute;
902
+ bottom: 100%;
903
+ left: 50%;
904
+ transform: translateX(-50%);
905
+ background: #1c1c1c;
906
+ color: #fff;
907
+ padding: 4px 8px;
908
+ border-radius: 4px;
909
+ font-size: 0.75rem;
910
+ white-space: nowrap;
911
+ z-index: 1000;
912
+ margin-bottom: 4px;
913
+ border: 1px solid #30363d;
914
+ }
915
+
916
+ .status-square:hover::before {
917
+ content: '';
918
+ position: absolute;
919
+ bottom: 100%;
920
+ left: 50%;
921
+ transform: translateX(-50%);
922
+ border: 4px solid transparent;
923
+ border-top-color: #30363d;
924
+ z-index: 1000;
925
+ }
926
+
790
927
  .loading, .error {
791
928
  text-align: center;
792
929
  padding: 40px;
@@ -1138,7 +1275,12 @@ async function createWebDashboard() {
1138
1275
 
1139
1276
  tableBody.innerHTML = filteredConversations.map(conv => \`
1140
1277
  <tr onclick="showSessionDetail('\${conv.id}')" style="cursor: pointer;">
1141
- <td class="session-id">\${conv.id.substring(0, 8)}...</td>
1278
+ <td class="session-id">
1279
+ \${conv.id.substring(0, 8)}...
1280
+ <div class="status-squares">
1281
+ \${generateStatusSquaresHTML(conv.statusSquares || [])}
1282
+ </div>
1283
+ </td>
1142
1284
  <td class="session-project">\${conv.project}</td>
1143
1285
  <td class="session-messages">\${conv.messageCount}</td>
1144
1286
  <td class="session-tokens">\${conv.tokens.toLocaleString()}</td>
@@ -1182,6 +1324,16 @@ async function createWebDashboard() {
1182
1324
  return '';
1183
1325
  }
1184
1326
 
1327
+ function generateStatusSquaresHTML(statusSquares) {
1328
+ if (!statusSquares || statusSquares.length === 0) {
1329
+ return '';
1330
+ }
1331
+
1332
+ return statusSquares.map(square =>
1333
+ \`<div class="status-square \${square.type}" data-tooltip="\${square.tooltip}"></div>\`
1334
+ ).join('');
1335
+ }
1336
+
1185
1337
  // Filter button handlers
1186
1338
  document.addEventListener('DOMContentLoaded', function() {
1187
1339
  const filterButtons = document.querySelectorAll('.filter-btn');