uv-suite 0.21.0 → 0.22.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uv-suite",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "Portable framework for AI-assisted software development. 10 agents, 9 skills, 5 hooks, 4 personas. Works with Claude Code, Cursor, and Codex.",
5
5
  "author": "Utsav Anand",
6
6
  "license": "MIT",
@@ -54,7 +54,16 @@
54
54
  {
55
55
  "matcher": "*",
56
56
  "hooks": [
57
- { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-start.sh", "timeout": 5 }
57
+ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-start.sh", "timeout": 5 },
58
+ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/watchtower-send.sh SessionStart", "timeout": 2, "async": true }
59
+ ]
60
+ }
61
+ ],
62
+ "UserPromptSubmit": [
63
+ {
64
+ "matcher": "*",
65
+ "hooks": [
66
+ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/watchtower-send.sh UserPromptSubmit", "timeout": 2, "async": true }
58
67
  ]
59
68
  }
60
69
  ],
@@ -56,6 +56,25 @@
56
56
  "type": "command",
57
57
  "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-start.sh",
58
58
  "timeout": 5
59
+ },
60
+ {
61
+ "type": "command",
62
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/watchtower-send.sh SessionStart",
63
+ "timeout": 2,
64
+ "async": true
65
+ }
66
+ ]
67
+ }
68
+ ],
69
+ "UserPromptSubmit": [
70
+ {
71
+ "matcher": "*",
72
+ "hooks": [
73
+ {
74
+ "type": "command",
75
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/watchtower-send.sh UserPromptSubmit",
76
+ "timeout": 2,
77
+ "async": true
59
78
  }
60
79
  ]
61
80
  }
@@ -40,7 +40,16 @@
40
40
  {
41
41
  "matcher": "*",
42
42
  "hooks": [
43
- { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-start.sh", "timeout": 5 }
43
+ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-start.sh", "timeout": 5 },
44
+ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/watchtower-send.sh SessionStart", "timeout": 2, "async": true }
45
+ ]
46
+ }
47
+ ],
48
+ "UserPromptSubmit": [
49
+ {
50
+ "matcher": "*",
51
+ "hooks": [
52
+ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/watchtower-send.sh UserPromptSubmit", "timeout": 2, "async": true }
44
53
  ]
45
54
  }
46
55
  ],
@@ -26,7 +26,16 @@
26
26
  {
27
27
  "matcher": "*",
28
28
  "hooks": [
29
- { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-start.sh", "timeout": 5 }
29
+ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-start.sh", "timeout": 5 },
30
+ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/watchtower-send.sh SessionStart", "timeout": 2, "async": true }
31
+ ]
32
+ }
33
+ ],
34
+ "UserPromptSubmit": [
35
+ {
36
+ "matcher": "*",
37
+ "hooks": [
38
+ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/watchtower-send.sh UserPromptSubmit", "timeout": 2, "async": true }
30
39
  ]
31
40
  }
32
41
  ],
@@ -118,12 +118,12 @@ let humanOnly = false;
118
118
  let selectedSession = '';
119
119
  let selectedType = '';
120
120
 
121
- // Session colors
121
+ // Session colors and naming
122
122
  const palette = ['#0a84ff','#30d158','#ff9f0a','#bf5af2','#ff375f','#64d2ff','#ffd60a','#ac8ee0','#ff6961','#5e5ce6'];
123
123
  let colorIdx = 0;
124
124
  function sessionColor(id) {
125
125
  if (!sessions[id]) {
126
- sessions[id] = { color: palette[colorIdx++ % palette.length], count: 0, lastEvent: null };
126
+ sessions[id] = { color: palette[colorIdx++ % palette.length], count: 0, lastEvent: null, label: null, app: null };
127
127
  updateSessionBar();
128
128
  updateFilterSession();
129
129
  }
@@ -132,14 +132,47 @@ function sessionColor(id) {
132
132
  return sessions[id].color;
133
133
  }
134
134
 
135
+ // Build a meaningful session label from the first user prompt or app name
136
+ function updateSessionLabel(sid, ev) {
137
+ if (!sessions[sid]) return;
138
+ // Capture source_app as fallback name
139
+ if (!sessions[sid].app && ev.source_app) {
140
+ sessions[sid].app = ev.source_app;
141
+ }
142
+ // Use first UserPromptSubmit content as the session label
143
+ if (!sessions[sid].label && ev.event_type === 'UserPromptSubmit') {
144
+ const prompt = ev.tool_input?.prompt || ev.tool_input?.content || ev.message || '';
145
+ if (prompt.length > 0) {
146
+ // Take first 40 chars, trim to last word boundary
147
+ let label = prompt.slice(0, 40).replace(/\s+\S*$/, '');
148
+ if (prompt.length > label.length) label += '...';
149
+ sessions[sid].label = label;
150
+ updateSessionBar();
151
+ updateFilterSession();
152
+ }
153
+ }
154
+ }
155
+
156
+ function sessionDisplayName(id) {
157
+ const s = sessions[id];
158
+ if (!s) return shortId(id);
159
+ if (s.label) return s.label;
160
+ if (s.app) return s.app;
161
+ return shortId(id);
162
+ }
163
+
164
+ function shortId(id) {
165
+ if (!id) return '—';
166
+ return id.length > 10 ? id.slice(0, 8) + '..' : id;
167
+ }
168
+
135
169
  function formatTime(ts) {
136
170
  const d = new Date(ts);
137
171
  return d.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });
138
172
  }
139
173
 
140
174
  function shortSession(id) {
141
- if (!id) return '—';
142
- return id.length > 12 ? id.slice(0, 8) + '...' : id;
175
+ return sessionDisplayName(id);
143
176
  }
144
177
 
145
178
  // Detect if event needs human intervention
@@ -245,6 +278,8 @@ function renderEvent(ev) {
245
278
  function addEvent(ev) {
246
279
  events.push(ev);
247
280
  if (emptyState.parentNode) emptyState.remove();
281
+ const sid = ev.session_id || ev.source_app || 'unknown';
282
+ updateSessionLabel(sid, ev);
248
283
  timeline.appendChild(renderEvent(ev));
249
284
  updateStats();
250
285
  updateFilterType(ev);