htmlgraph 0.24.1__py3-none-any.whl → 0.25.0__py3-none-any.whl
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.
- htmlgraph/__init__.py +20 -1
- htmlgraph/agent_detection.py +26 -10
- htmlgraph/analytics/cross_session.py +4 -3
- htmlgraph/analytics/work_type.py +52 -16
- htmlgraph/analytics_index.py +51 -19
- htmlgraph/api/__init__.py +3 -0
- htmlgraph/api/main.py +2115 -0
- htmlgraph/api/static/htmx.min.js +1 -0
- htmlgraph/api/static/style-redesign.css +1344 -0
- htmlgraph/api/static/style.css +1079 -0
- htmlgraph/api/templates/dashboard-redesign.html +812 -0
- htmlgraph/api/templates/dashboard.html +783 -0
- htmlgraph/api/templates/partials/activity-feed-hierarchical.html +326 -0
- htmlgraph/api/templates/partials/activity-feed.html +570 -0
- htmlgraph/api/templates/partials/agents-redesign.html +317 -0
- htmlgraph/api/templates/partials/agents.html +317 -0
- htmlgraph/api/templates/partials/event-traces.html +373 -0
- htmlgraph/api/templates/partials/features-kanban-redesign.html +509 -0
- htmlgraph/api/templates/partials/features.html +509 -0
- htmlgraph/api/templates/partials/metrics-redesign.html +346 -0
- htmlgraph/api/templates/partials/metrics.html +346 -0
- htmlgraph/api/templates/partials/orchestration-redesign.html +443 -0
- htmlgraph/api/templates/partials/orchestration.html +163 -0
- htmlgraph/api/templates/partials/spawners.html +375 -0
- htmlgraph/atomic_ops.py +560 -0
- htmlgraph/builders/base.py +55 -1
- htmlgraph/builders/bug.py +17 -2
- htmlgraph/builders/chore.py +17 -2
- htmlgraph/builders/epic.py +17 -2
- htmlgraph/builders/feature.py +25 -2
- htmlgraph/builders/phase.py +17 -2
- htmlgraph/builders/spike.py +27 -2
- htmlgraph/builders/track.py +14 -0
- htmlgraph/cigs/__init__.py +4 -0
- htmlgraph/cigs/reporter.py +818 -0
- htmlgraph/cli.py +1427 -401
- htmlgraph/cli_commands/__init__.py +1 -0
- htmlgraph/cli_commands/feature.py +195 -0
- htmlgraph/cli_framework.py +115 -0
- htmlgraph/collections/__init__.py +2 -0
- htmlgraph/collections/base.py +21 -0
- htmlgraph/collections/session.py +189 -0
- htmlgraph/collections/spike.py +7 -1
- htmlgraph/collections/task_delegation.py +236 -0
- htmlgraph/collections/traces.py +482 -0
- htmlgraph/config.py +113 -0
- htmlgraph/converter.py +41 -0
- htmlgraph/cost_analysis/__init__.py +5 -0
- htmlgraph/cost_analysis/analyzer.py +438 -0
- htmlgraph/dashboard.html +3315 -492
- htmlgraph-0.24.1.data/data/htmlgraph/dashboard.html → htmlgraph/dashboard.html.backup +2246 -248
- htmlgraph/dashboard.html.bak +7181 -0
- htmlgraph/dashboard.html.bak2 +7231 -0
- htmlgraph/dashboard.html.bak3 +7232 -0
- htmlgraph/db/__init__.py +38 -0
- htmlgraph/db/queries.py +790 -0
- htmlgraph/db/schema.py +1334 -0
- htmlgraph/deploy.py +26 -27
- htmlgraph/docs/API_REFERENCE.md +841 -0
- htmlgraph/docs/HTTP_API.md +750 -0
- htmlgraph/docs/INTEGRATION_GUIDE.md +752 -0
- htmlgraph/docs/ORCHESTRATION_PATTERNS.md +710 -0
- htmlgraph/docs/README.md +533 -0
- htmlgraph/docs/version_check.py +3 -1
- htmlgraph/error_handler.py +544 -0
- htmlgraph/event_log.py +2 -0
- htmlgraph/hooks/__init__.py +8 -0
- htmlgraph/hooks/bootstrap.py +169 -0
- htmlgraph/hooks/context.py +271 -0
- htmlgraph/hooks/drift_handler.py +521 -0
- htmlgraph/hooks/event_tracker.py +405 -15
- htmlgraph/hooks/post_tool_use_handler.py +257 -0
- htmlgraph/hooks/pretooluse.py +476 -6
- htmlgraph/hooks/prompt_analyzer.py +648 -0
- htmlgraph/hooks/session_handler.py +583 -0
- htmlgraph/hooks/state_manager.py +501 -0
- htmlgraph/hooks/subagent_stop.py +309 -0
- htmlgraph/hooks/task_enforcer.py +39 -0
- htmlgraph/models.py +111 -15
- htmlgraph/operations/fastapi_server.py +230 -0
- htmlgraph/orchestration/headless_spawner.py +22 -14
- htmlgraph/pydantic_models.py +476 -0
- htmlgraph/quality_gates.py +350 -0
- htmlgraph/repo_hash.py +511 -0
- htmlgraph/sdk.py +348 -10
- htmlgraph/server.py +194 -0
- htmlgraph/session_hooks.py +300 -0
- htmlgraph/session_manager.py +131 -1
- htmlgraph/session_registry.py +587 -0
- htmlgraph/session_state.py +436 -0
- htmlgraph/system_prompts.py +449 -0
- htmlgraph/templates/orchestration-view.html +350 -0
- htmlgraph/track_builder.py +19 -0
- htmlgraph/validation.py +115 -0
- htmlgraph-0.25.0.data/data/htmlgraph/dashboard.html +7417 -0
- {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/METADATA +91 -64
- {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/RECORD +103 -42
- {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/styles.css +0 -0
- {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
- {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
- {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
- {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/WHEEL +0 -0
- {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
<!-- Grouped Activity Feed - Display events organized by conversation turn (user prompt) -->
|
|
2
|
+
<div class="view-container activity-feed-view">
|
|
3
|
+
<div class="view-header">
|
|
4
|
+
<h2>Agent Activity Feed</h2>
|
|
5
|
+
<div class="view-info">
|
|
6
|
+
<small>Events grouped by conversation turn. Click to expand/collapse child events.</small>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="view-filters">
|
|
9
|
+
<div class="trace-controls">
|
|
10
|
+
<button type="button" class="btn-small" onclick="expandAllConversationTurns()" title="Expand all conversation turns">Expand All</button>
|
|
11
|
+
<button type="button" class="btn-small" onclick="collapseAllConversationTurns()" title="Collapse all conversation turns">Collapse All</button>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<!-- Spawner Activity Filter -->
|
|
17
|
+
<div class="spawner-filter">
|
|
18
|
+
<label for="agent-type-filter">Filter:</label>
|
|
19
|
+
<select id="agent-type-filter" onchange="filterByAgentType(this.value)">
|
|
20
|
+
<option value="all">All Activity</option>
|
|
21
|
+
<option value="direct">Direct Actions Only</option>
|
|
22
|
+
<option value="spawner">Spawner Delegations Only</option>
|
|
23
|
+
<optgroup label="Specific Spawners">
|
|
24
|
+
<option value="gemini">Gemini (FREE)</option>
|
|
25
|
+
<option value="codex">Codex (Paid)</option>
|
|
26
|
+
<option value="copilot">Copilot (GitHub)</option>
|
|
27
|
+
</optgroup>
|
|
28
|
+
</select>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="conversation-feed">
|
|
32
|
+
{% if conversation_turns %}
|
|
33
|
+
<div class="conversation-turns-list">
|
|
34
|
+
{% for turn in conversation_turns %}
|
|
35
|
+
<!-- Conversation Turn Container -->
|
|
36
|
+
<div class="conversation-turn"
|
|
37
|
+
data-turn-id="{{ turn.userQuery.event_id }}"
|
|
38
|
+
data-spawner-type="{% if turn.has_spawner %}spawner{% else %}direct{% endif %}"
|
|
39
|
+
data-agent="{{ turn.userQuery.agent_id }}">
|
|
40
|
+
<!-- User Query Parent Row (Clickable) -->
|
|
41
|
+
<div class="userquery-parent"
|
|
42
|
+
onclick="toggleConversationTurn('{{ turn.userQuery.event_id }}')"
|
|
43
|
+
data-turn-id="{{ turn.userQuery.event_id }}">
|
|
44
|
+
|
|
45
|
+
<!-- Expand/Collapse Toggle -->
|
|
46
|
+
<span class="expand-toggle-turn" id="toggle-{{ turn.userQuery.event_id }}">▶</span>
|
|
47
|
+
|
|
48
|
+
<!-- User Prompt Text -->
|
|
49
|
+
<div class="prompt-section">
|
|
50
|
+
<span class="prompt-text" title="{{ turn.userQuery.prompt }}">
|
|
51
|
+
{{ turn.userQuery.prompt[:100] }}{% if turn.userQuery.prompt|length > 100 %}...{% endif %}
|
|
52
|
+
</span>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<!-- Stats Badges -->
|
|
56
|
+
<div class="turn-stats">
|
|
57
|
+
{% if turn.stats.tool_count > 0 %}
|
|
58
|
+
<span class="stat-badge tool-count" title="Tool calls">
|
|
59
|
+
{{ turn.stats.tool_count }}
|
|
60
|
+
</span>
|
|
61
|
+
{% endif %}
|
|
62
|
+
|
|
63
|
+
<span class="stat-badge duration" title="Total duration">
|
|
64
|
+
{{ "%.2f"|format(turn.stats.total_duration) }}s
|
|
65
|
+
</span>
|
|
66
|
+
|
|
67
|
+
{% if turn.stats.success_count > 0 %}
|
|
68
|
+
<span class="stat-badge success" title="Successful operations">
|
|
69
|
+
✓ {{ turn.stats.success_count }}
|
|
70
|
+
</span>
|
|
71
|
+
{% endif %}
|
|
72
|
+
|
|
73
|
+
{% if turn.stats.error_count > 0 %}
|
|
74
|
+
<span class="stat-badge error" title="Errors">
|
|
75
|
+
✗ {{ turn.stats.error_count }}
|
|
76
|
+
</span>
|
|
77
|
+
{% endif %}
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<!-- Timestamp -->
|
|
81
|
+
<div class="turn-timestamp">
|
|
82
|
+
{{ turn.userQuery.timestamp }}
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<!-- Child Events Container (Hidden by default) -->
|
|
87
|
+
<div class="turn-children collapsed" id="children-{{ turn.userQuery.event_id }}">
|
|
88
|
+
{% if turn.children %}
|
|
89
|
+
{% for child in turn.children %}
|
|
90
|
+
<!-- Child Event Row -->
|
|
91
|
+
<div class="child-event-row" data-event-id="{{ child.event_id }}">
|
|
92
|
+
<!-- Tree Connector -->
|
|
93
|
+
<span class="tree-connector">
|
|
94
|
+
{% if loop.last %}└─{% else %}├─{% endif %}
|
|
95
|
+
</span>
|
|
96
|
+
|
|
97
|
+
<!-- Tool Name -->
|
|
98
|
+
<span class="child-tool-name">{{ child.tool_name }}</span>
|
|
99
|
+
|
|
100
|
+
<!-- Summary/Input -->
|
|
101
|
+
<span class="child-summary" title="{{ child.summary }}">
|
|
102
|
+
{{ child.summary[:80] }}{% if child.summary|length > 80 %}...{% endif %}
|
|
103
|
+
</span>
|
|
104
|
+
|
|
105
|
+
<!-- Agent Badge with Spawner Support -->
|
|
106
|
+
{% if child.spawner_type %}
|
|
107
|
+
<!-- Spawner delegation: show orchestrator → spawned AI -->
|
|
108
|
+
<span class="child-agent-badge agent-{{ child.agent|lower|replace(' ', '-') }}">
|
|
109
|
+
{{ child.agent }}
|
|
110
|
+
</span>
|
|
111
|
+
<span class="delegation-arrow">→</span>
|
|
112
|
+
<span class="spawner-badge spawner-{{ child.spawner_type|lower }}">
|
|
113
|
+
{{ child.spawned_agent or child.subagent_type or child.spawner_type }}
|
|
114
|
+
{% if child.cost_usd %}
|
|
115
|
+
<span class="cost-badge">${{ "%.2f"|format(child.cost_usd) }}</span>
|
|
116
|
+
{% endif %}
|
|
117
|
+
</span>
|
|
118
|
+
{% else %}
|
|
119
|
+
<!-- Regular agent: just show agent name -->
|
|
120
|
+
<span class="child-agent-badge agent-{{ child.agent|lower|replace(' ', '-') }}">
|
|
121
|
+
{{ child.agent }}
|
|
122
|
+
</span>
|
|
123
|
+
{% endif %}
|
|
124
|
+
|
|
125
|
+
<!-- Duration -->
|
|
126
|
+
<span class="child-duration">
|
|
127
|
+
{{ "%.2f"|format(child.duration_seconds) }}s
|
|
128
|
+
</span>
|
|
129
|
+
|
|
130
|
+
<!-- Timestamp -->
|
|
131
|
+
<span class="child-timestamp">
|
|
132
|
+
{{ child.timestamp }}
|
|
133
|
+
</span>
|
|
134
|
+
</div>
|
|
135
|
+
{% endfor %}
|
|
136
|
+
{% else %}
|
|
137
|
+
<div class="no-children-message">
|
|
138
|
+
<span class="tree-connector">└─</span>
|
|
139
|
+
<span class="text-muted">No child events</span>
|
|
140
|
+
</div>
|
|
141
|
+
{% endif %}
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
{% endfor %}
|
|
145
|
+
</div>
|
|
146
|
+
{% else %}
|
|
147
|
+
<div class="empty-state">
|
|
148
|
+
<p>No conversation turns found</p>
|
|
149
|
+
<small>Agent activity will appear here as tasks are executed</small>
|
|
150
|
+
</div>
|
|
151
|
+
{% endif %}
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<!-- Auto-refresh indicator -->
|
|
155
|
+
<div class="auto-refresh-indicator">
|
|
156
|
+
<span class="refresh-dot"></span>
|
|
157
|
+
Live updates enabled (via WebSocket)
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
|
|
161
|
+
<style>
|
|
162
|
+
/* ============================================
|
|
163
|
+
Grouped Activity Feed - Conversation Turns
|
|
164
|
+
============================================ */
|
|
165
|
+
|
|
166
|
+
.conversation-feed {
|
|
167
|
+
display: flex;
|
|
168
|
+
flex-direction: column;
|
|
169
|
+
font-family: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;
|
|
170
|
+
font-size: 0.8rem;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/* Conversation Turns List Container */
|
|
174
|
+
.conversation-turns-list {
|
|
175
|
+
display: flex;
|
|
176
|
+
flex-direction: column;
|
|
177
|
+
gap: 0.5rem;
|
|
178
|
+
padding: 0.5rem;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* Individual Conversation Turn */
|
|
182
|
+
.conversation-turn {
|
|
183
|
+
border-radius: 4px;
|
|
184
|
+
overflow: hidden;
|
|
185
|
+
background: var(--bg-base);
|
|
186
|
+
border: 1px solid var(--border-subtle);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* User Query Parent Row - Clickable Header */
|
|
190
|
+
.userquery-parent {
|
|
191
|
+
display: flex;
|
|
192
|
+
align-items: center;
|
|
193
|
+
gap: 0.75rem;
|
|
194
|
+
padding: 1rem;
|
|
195
|
+
background: rgba(200, 255, 0, 0.08);
|
|
196
|
+
border-left: 3px solid var(--accent, #c8ff00);
|
|
197
|
+
cursor: pointer;
|
|
198
|
+
transition: all 0.15s ease;
|
|
199
|
+
user-select: none;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.userquery-parent:hover {
|
|
203
|
+
background: rgba(200, 255, 0, 0.12);
|
|
204
|
+
border-left-color: #a3e635;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* Expand/Collapse Toggle */
|
|
208
|
+
.expand-toggle-turn {
|
|
209
|
+
display: inline-flex;
|
|
210
|
+
align-items: center;
|
|
211
|
+
justify-content: center;
|
|
212
|
+
width: 24px;
|
|
213
|
+
height: 24px;
|
|
214
|
+
font-size: 0.8rem;
|
|
215
|
+
color: var(--accent-lime, #a3e635);
|
|
216
|
+
transition: transform 0.2s ease;
|
|
217
|
+
flex-shrink: 0;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.expand-toggle-turn.expanded {
|
|
221
|
+
transform: rotate(90deg);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* Prompt Section */
|
|
225
|
+
.prompt-section {
|
|
226
|
+
display: flex;
|
|
227
|
+
align-items: center;
|
|
228
|
+
gap: 0.5rem;
|
|
229
|
+
flex: 1;
|
|
230
|
+
min-width: 0;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.prompt-icon {
|
|
234
|
+
font-size: 1.1rem;
|
|
235
|
+
flex-shrink: 0;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.prompt-text {
|
|
239
|
+
color: var(--text-primary);
|
|
240
|
+
font-weight: 500;
|
|
241
|
+
overflow: hidden;
|
|
242
|
+
text-overflow: ellipsis;
|
|
243
|
+
white-space: nowrap;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* Turn Stats Container */
|
|
247
|
+
.turn-stats {
|
|
248
|
+
display: flex;
|
|
249
|
+
align-items: center;
|
|
250
|
+
gap: 0.4rem;
|
|
251
|
+
flex-shrink: 0;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* Stat Badges */
|
|
255
|
+
.stat-badge {
|
|
256
|
+
display: inline-block;
|
|
257
|
+
padding: 0.25rem 0.5rem;
|
|
258
|
+
font-size: 0.65rem;
|
|
259
|
+
font-weight: 600;
|
|
260
|
+
text-transform: uppercase;
|
|
261
|
+
letter-spacing: 0.05em;
|
|
262
|
+
border-radius: 3px;
|
|
263
|
+
background: rgba(255, 255, 255, 0.1);
|
|
264
|
+
color: var(--text-secondary);
|
|
265
|
+
white-space: nowrap;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.stat-badge.tool-count {
|
|
269
|
+
background: rgba(163, 230, 53, 0.2);
|
|
270
|
+
color: #a3e635;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.stat-badge.duration {
|
|
274
|
+
background: rgba(100, 200, 255, 0.2);
|
|
275
|
+
color: #64c8ff;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.stat-badge.success {
|
|
279
|
+
background: rgba(34, 197, 94, 0.2);
|
|
280
|
+
color: #22c55e;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.stat-badge.error {
|
|
284
|
+
background: rgba(239, 68, 68, 0.2);
|
|
285
|
+
color: #ef4444;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* Turn Timestamp */
|
|
289
|
+
.turn-timestamp {
|
|
290
|
+
font-size: 0.65rem;
|
|
291
|
+
color: var(--text-muted);
|
|
292
|
+
flex-shrink: 0;
|
|
293
|
+
min-width: 140px;
|
|
294
|
+
text-align: right;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/* Child Events Container */
|
|
298
|
+
.turn-children {
|
|
299
|
+
display: flex;
|
|
300
|
+
flex-direction: column;
|
|
301
|
+
background: rgba(163, 230, 53, 0.02);
|
|
302
|
+
border-top: 1px solid var(--border-subtle);
|
|
303
|
+
padding: 0.5rem 0rem;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.turn-children.collapsed {
|
|
307
|
+
display: none;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/* Child Event Row */
|
|
311
|
+
.child-event-row {
|
|
312
|
+
display: flex;
|
|
313
|
+
align-items: center;
|
|
314
|
+
gap: 0.2rem;
|
|
315
|
+
padding: 0.5rem 0;
|
|
316
|
+
border-bottom: 1px solid rgba(163, 230, 53, 0.1);
|
|
317
|
+
font-size: 0.75rem;
|
|
318
|
+
margin-left: 0;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.child-event-row:last-child {
|
|
322
|
+
border-bottom: none;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/* Tree Connector */
|
|
326
|
+
.tree-connector {
|
|
327
|
+
color: var(--accent-lime, #a3e635);
|
|
328
|
+
font-size: 0.9rem;
|
|
329
|
+
font-weight: bold;
|
|
330
|
+
font-family: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;
|
|
331
|
+
white-space: pre;
|
|
332
|
+
flex-shrink: 0;
|
|
333
|
+
min-width: 16px;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/* Child Tool Name */
|
|
337
|
+
.child-tool-name {
|
|
338
|
+
display: inline-block;
|
|
339
|
+
padding: 0.1rem 0.3rem;
|
|
340
|
+
background: rgba(255, 255, 255, 0.05);
|
|
341
|
+
color: var(--text-primary);
|
|
342
|
+
border-radius: 2px;
|
|
343
|
+
font-weight: 500;
|
|
344
|
+
flex-shrink: 0;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/* Child Summary */
|
|
348
|
+
.child-summary {
|
|
349
|
+
color: var(--text-secondary);
|
|
350
|
+
flex: 1;
|
|
351
|
+
min-width: 0;
|
|
352
|
+
overflow: hidden;
|
|
353
|
+
text-overflow: ellipsis;
|
|
354
|
+
white-space: nowrap;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/* Child Agent Badge */
|
|
358
|
+
.child-agent-badge {
|
|
359
|
+
display: inline-block;
|
|
360
|
+
padding: 0.1rem 0.35rem;
|
|
361
|
+
font-size: 0.6rem;
|
|
362
|
+
font-weight: 600;
|
|
363
|
+
text-transform: uppercase;
|
|
364
|
+
letter-spacing: 0.05em;
|
|
365
|
+
border-radius: 2px;
|
|
366
|
+
background: rgba(255, 255, 255, 0.08);
|
|
367
|
+
color: var(--text-secondary);
|
|
368
|
+
flex-shrink: 0;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.child-agent-badge.agent-claude-code,
|
|
372
|
+
.child-agent-badge.agent-claude {
|
|
373
|
+
background: rgba(200, 255, 0, 0.15);
|
|
374
|
+
color: #c8ff00;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.child-agent-badge.agent-gemini,
|
|
378
|
+
.child-agent-badge.agent-gemini-2-0-flash-exp {
|
|
379
|
+
background: rgba(74, 222, 128, 0.15);
|
|
380
|
+
color: #4ade80;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/* Child Duration */
|
|
384
|
+
.child-duration {
|
|
385
|
+
display: inline-block;
|
|
386
|
+
padding: 0.1rem 0.3rem;
|
|
387
|
+
background: rgba(100, 200, 255, 0.1);
|
|
388
|
+
color: #64c8ff;
|
|
389
|
+
border-radius: 2px;
|
|
390
|
+
font-size: 0.65rem;
|
|
391
|
+
flex-shrink: 0;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/* Child Timestamp */
|
|
395
|
+
.child-timestamp {
|
|
396
|
+
color: var(--text-muted);
|
|
397
|
+
font-size: 0.65rem;
|
|
398
|
+
flex-shrink: 0;
|
|
399
|
+
min-width: 140px;
|
|
400
|
+
text-align: right;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/* No Children Message */
|
|
404
|
+
.no-children-message {
|
|
405
|
+
display: flex;
|
|
406
|
+
align-items: center;
|
|
407
|
+
gap: 0.5rem;
|
|
408
|
+
padding: 0.6rem 0;
|
|
409
|
+
color: var(--text-muted);
|
|
410
|
+
font-size: 0.75rem;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/* ============================================
|
|
414
|
+
Control Buttons
|
|
415
|
+
============================================ */
|
|
416
|
+
|
|
417
|
+
.trace-controls {
|
|
418
|
+
display: flex;
|
|
419
|
+
gap: 0.5rem;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
.btn-small {
|
|
423
|
+
padding: 0.3rem 0.6rem;
|
|
424
|
+
font-size: 0.65rem;
|
|
425
|
+
background: var(--bg-darker);
|
|
426
|
+
border: 1px solid var(--border-subtle);
|
|
427
|
+
color: var(--text-secondary);
|
|
428
|
+
cursor: pointer;
|
|
429
|
+
border-radius: 2px;
|
|
430
|
+
transition: all 0.15s ease;
|
|
431
|
+
text-transform: uppercase;
|
|
432
|
+
letter-spacing: 0.05em;
|
|
433
|
+
font-family: inherit;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.btn-small:hover {
|
|
437
|
+
background: rgba(163, 230, 53, 0.1);
|
|
438
|
+
border-color: var(--accent-lime, #a3e635);
|
|
439
|
+
color: var(--accent-lime, #a3e635);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/* ============================================
|
|
443
|
+
Empty State
|
|
444
|
+
============================================ */
|
|
445
|
+
|
|
446
|
+
.empty-state {
|
|
447
|
+
padding: 3rem;
|
|
448
|
+
text-align: center;
|
|
449
|
+
color: var(--text-muted);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.empty-state p {
|
|
453
|
+
font-size: 1rem;
|
|
454
|
+
margin-bottom: 0.5rem;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/* ============================================
|
|
458
|
+
Auto-refresh Indicator
|
|
459
|
+
============================================ */
|
|
460
|
+
|
|
461
|
+
.auto-refresh-indicator {
|
|
462
|
+
display: flex;
|
|
463
|
+
align-items: center;
|
|
464
|
+
gap: 0.5rem;
|
|
465
|
+
padding: 0.5rem 1rem;
|
|
466
|
+
font-size: 0.65rem;
|
|
467
|
+
color: var(--text-muted);
|
|
468
|
+
background: var(--bg-darker);
|
|
469
|
+
border-top: 1px solid var(--border-subtle);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.refresh-dot {
|
|
473
|
+
width: 6px;
|
|
474
|
+
height: 6px;
|
|
475
|
+
background: var(--accent-lime, #a3e635);
|
|
476
|
+
border-radius: 50%;
|
|
477
|
+
animation: pulse 2s ease-in-out infinite;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
@keyframes pulse {
|
|
481
|
+
0%, 100% { opacity: 1; }
|
|
482
|
+
50% { opacity: 0.4; }
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/* ============================================
|
|
486
|
+
Responsive Adjustments
|
|
487
|
+
============================================ */
|
|
488
|
+
|
|
489
|
+
@media (max-width: 1200px) {
|
|
490
|
+
.turn-timestamp,
|
|
491
|
+
.child-timestamp {
|
|
492
|
+
display: none;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
@media (max-width: 900px) {
|
|
497
|
+
.turn-stats {
|
|
498
|
+
flex-wrap: wrap;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
.child-summary {
|
|
502
|
+
max-width: 150px;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
@media (max-width: 700px) {
|
|
507
|
+
.userquery-parent {
|
|
508
|
+
flex-wrap: wrap;
|
|
509
|
+
gap: 0.5rem;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.prompt-section {
|
|
513
|
+
width: 100%;
|
|
514
|
+
order: 2;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
.turn-stats {
|
|
518
|
+
order: 3;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
.child-event-row {
|
|
522
|
+
flex-wrap: wrap;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
.child-summary {
|
|
526
|
+
width: 100%;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
</style>
|
|
530
|
+
|
|
531
|
+
<script>
|
|
532
|
+
// JavaScript functions for expand/collapse functionality
|
|
533
|
+
// Called from onclick handlers in the template
|
|
534
|
+
|
|
535
|
+
function toggleConversationTurn(turnId) {
|
|
536
|
+
const childrenContainer = document.getElementById(`children-${turnId}`);
|
|
537
|
+
const toggleButton = document.getElementById(`toggle-${turnId}`);
|
|
538
|
+
|
|
539
|
+
if (childrenContainer) {
|
|
540
|
+
childrenContainer.classList.toggle('collapsed');
|
|
541
|
+
if (toggleButton) {
|
|
542
|
+
toggleButton.classList.toggle('expanded');
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
function expandAllConversationTurns() {
|
|
548
|
+
// Get all child containers and remove the 'collapsed' class
|
|
549
|
+
document.querySelectorAll('.turn-children').forEach(container => {
|
|
550
|
+
container.classList.remove('collapsed');
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
// Rotate all toggle buttons
|
|
554
|
+
document.querySelectorAll('.expand-toggle-turn').forEach(toggle => {
|
|
555
|
+
toggle.classList.add('expanded');
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
function collapseAllConversationTurns() {
|
|
560
|
+
// Get all child containers and add the 'collapsed' class
|
|
561
|
+
document.querySelectorAll('.turn-children').forEach(container => {
|
|
562
|
+
container.classList.add('collapsed');
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// Rotate all toggle buttons back
|
|
566
|
+
document.querySelectorAll('.expand-toggle-turn').forEach(toggle => {
|
|
567
|
+
toggle.classList.remove('expanded');
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
</script>
|