agentgui 1.0.39 → 1.0.40
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/CLAUDE.md +0 -0
- package/acp-launcher.js +14 -51
- package/package.json +1 -1
- package/01-initial-load.png +0 -0
- package/AUTOMATIC_IMPORT.md +0 -284
- package/CONVERSATION_DISPLAY_FIX.md +0 -125
- package/DEBUG_GUIDE.md +0 -136
- package/DIAGNOSTICS.md +0 -61
- package/FINAL_SUMMARY.md +0 -312
- package/IMPLEMENTATION_CHECKLIST.md +0 -287
- package/IMPLEMENTATION_STATUS.md +0 -189
- package/README.md +0 -213
- package/RECENT_UPDATES.md +0 -209
- package/REMOTE_DEBUG_GUIDE.md +0 -225
- package/RESPONSE_ISSUES.md +0 -157
- package/SIDEBAR_FIX_SUMMARY.md +0 -111
- package/STATE_CONSISTENCY_GUARANTEE.md +0 -183
- package/STATE_CONSISTENCY_TEST_INDEX.md +0 -268
- package/STATE_CONSISTENCY_TEST_REPORT.md +0 -256
- package/STATE_MACHINE_SUMMARY.md +0 -172
- package/TEST_README.md +0 -205
- package/TEST_SUMMARY.md +0 -159
- package/test-artifacts/01-window-a-initial.png +0 -0
- package/test-artifacts/01-window-b-initial.png +0 -0
- package/test-artifacts/02-window-a-after-send.png +0 -0
- package/test-artifacts/02-window-b-after-send.png +0 -0
- package/test-artifacts/snapshot-a-1.txt +0 -1
- package/test-artifacts/snapshot-b-1.txt +0 -1
- package/test-state-consistency.cjs +0 -239
- package/test-state-manager.js +0 -55
package/REMOTE_DEBUG_GUIDE.md
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
# Remote Server Debugging Guide
|
|
2
|
-
|
|
3
|
-
## Issue
|
|
4
|
-
Conversations are not displaying in AgentGUI on remote server (https://buildesk.acc.l-inc.co.za/gm/), even though:
|
|
5
|
-
- ✅ The application loads
|
|
6
|
-
- ✅ The layout works
|
|
7
|
-
- ✅ The sidebar is visible
|
|
8
|
-
|
|
9
|
-
## Root Cause Analysis
|
|
10
|
-
|
|
11
|
-
### On Local Server ✅
|
|
12
|
-
- 83 conversations stored in `~/.gmgui/data.db`
|
|
13
|
-
- 68 Claude Code conversations discovered in `~/.claude/projects/`
|
|
14
|
-
- All 68 imported successfully
|
|
15
|
-
- API returns conversations correctly
|
|
16
|
-
- Frontend fetches and displays them
|
|
17
|
-
|
|
18
|
-
### On Remote Server ❓
|
|
19
|
-
- Unknown database state
|
|
20
|
-
- Unknown Claude Code availability
|
|
21
|
-
- Conversations showing as empty
|
|
22
|
-
|
|
23
|
-
## Diagnostic Checklist
|
|
24
|
-
|
|
25
|
-
### 1. Check if API is returning conversations
|
|
26
|
-
|
|
27
|
-
In browser console:
|
|
28
|
-
```javascript
|
|
29
|
-
fetch('/gm/api/conversations')
|
|
30
|
-
.then(r => r.json())
|
|
31
|
-
.then(d => console.log('Conversations from API:', d.conversations?.length || 0))
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
If this returns 0: **Database is empty or API is failing**
|
|
35
|
-
If this returns > 0: **API is working, issue is in frontend**
|
|
36
|
-
|
|
37
|
-
### 2. Check frontend state
|
|
38
|
-
|
|
39
|
-
In browser console:
|
|
40
|
-
```javascript
|
|
41
|
-
// Check if app was initialized
|
|
42
|
-
console.log('app.conversations.size:', app.conversations.size);
|
|
43
|
-
|
|
44
|
-
// If size is 0, check if fetchConversations was called
|
|
45
|
-
console.log('API returned data:', app.conversations);
|
|
46
|
-
|
|
47
|
-
// Force a refetch
|
|
48
|
-
await app.fetchConversations();
|
|
49
|
-
console.log('After refetch:', app.conversations.size);
|
|
50
|
-
|
|
51
|
-
// If still 0, render to see debug info
|
|
52
|
-
app.renderChatHistory();
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### 3. Manually trigger import
|
|
56
|
-
|
|
57
|
-
In browser console:
|
|
58
|
-
```javascript
|
|
59
|
-
// Try to import Claude Code conversations
|
|
60
|
-
await fetch('/gm/api/import/claude-code')
|
|
61
|
-
.then(r => r.json())
|
|
62
|
-
.then(d => console.log('Import result:', d));
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Then refetch:
|
|
66
|
-
```javascript
|
|
67
|
-
await app.fetchConversations();
|
|
68
|
-
app.renderChatHistory();
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### 4. Check Claude Code projects
|
|
72
|
-
|
|
73
|
-
In terminal on remote server:
|
|
74
|
-
```bash
|
|
75
|
-
# Check if Claude Code directory exists
|
|
76
|
-
ls -la ~/.claude/projects/
|
|
77
|
-
|
|
78
|
-
# List all projects
|
|
79
|
-
find ~/.claude/projects -name "sessions-index.json" 2>/dev/null | wc -l
|
|
80
|
-
|
|
81
|
-
# Check first project
|
|
82
|
-
ls -la ~/.claude/projects/ | head
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
If directory doesn't exist or is empty: **Claude Code hasn't been used on this server**
|
|
86
|
-
|
|
87
|
-
### 5. Check database directly
|
|
88
|
-
|
|
89
|
-
In terminal on remote server:
|
|
90
|
-
```bash
|
|
91
|
-
# Check database location (should be ~/.gmgui/data.db)
|
|
92
|
-
ls -lh ~/.gmgui/data.db
|
|
93
|
-
|
|
94
|
-
# Get conversation count (if Node/better-sqlite3 available)
|
|
95
|
-
node -e "
|
|
96
|
-
const DB = require('better-sqlite3');
|
|
97
|
-
const db = new DB(process.env.HOME + '/.gmgui/data.db');
|
|
98
|
-
const count = db.prepare('SELECT COUNT(*) as c FROM conversations').get();
|
|
99
|
-
console.log('DB Conversations:', count.c);
|
|
100
|
-
db.close();
|
|
101
|
-
"
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
If file doesn't exist: **Database not initialized**
|
|
105
|
-
If count is 0: **No conversations in database**
|
|
106
|
-
|
|
107
|
-
## Solutions by Scenario
|
|
108
|
-
|
|
109
|
-
### Scenario A: API returns 0, Database is empty
|
|
110
|
-
**Problem:** No conversations to display (first time setup)
|
|
111
|
-
**Solution:**
|
|
112
|
-
1. Import Claude Code conversations (if available)
|
|
113
|
-
2. Or create new conversations
|
|
114
|
-
3. Or import from JSON
|
|
115
|
-
|
|
116
|
-
### Scenario B: API returns conversations, Frontend shows 0
|
|
117
|
-
**Problem:** Frontend not fetching/displaying properly
|
|
118
|
-
**Solution:**
|
|
119
|
-
1. Check browser console for errors
|
|
120
|
-
2. Check [DEBUG] logs
|
|
121
|
-
3. Try `_debug.forceRefetch()` in console
|
|
122
|
-
4. Check if BASE_URL is set correctly
|
|
123
|
-
|
|
124
|
-
### Scenario C: Claude Code projects exist but no conversations
|
|
125
|
-
**Problem:** Discovered conversations but not imported
|
|
126
|
-
**Solution:**
|
|
127
|
-
1. Open browser console
|
|
128
|
-
2. Call import endpoint
|
|
129
|
-
3. Call `app.fetchConversations()`
|
|
130
|
-
4. Call `app.renderChatHistory()`
|
|
131
|
-
|
|
132
|
-
### Scenario D: Conversations exist but frontend won't display
|
|
133
|
-
**Problem:** Rendering issue
|
|
134
|
-
**Solution:**
|
|
135
|
-
1. Check HTML element `#chatList` exists
|
|
136
|
-
2. Check CSS isn't hiding it
|
|
137
|
-
3. Check for JavaScript errors
|
|
138
|
-
4. Test `_debug.forceRefetch()`
|
|
139
|
-
|
|
140
|
-
## What to Look For in Console
|
|
141
|
-
|
|
142
|
-
When page loads, should see these logs:
|
|
143
|
-
```
|
|
144
|
-
[DEBUG] Init: Starting initialization
|
|
145
|
-
[DEBUG] Init: BASE_URL = /gm
|
|
146
|
-
[DEBUG] Init: Window width: XXXX
|
|
147
|
-
[DEBUG] Init: Fetched agents, count: X
|
|
148
|
-
[DEBUG] Init: Auto-imported Claude Code conversations
|
|
149
|
-
[DEBUG] fetchConversations: Starting fetch from /gm/api/conversations
|
|
150
|
-
[DEBUG] fetchConversations response count: X
|
|
151
|
-
[DEBUG] Init: Fetched conversations, count: X
|
|
152
|
-
[DEBUG] renderChatHistory - conversations.size: X
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
If you see `conversations.size: 0` anywhere, that's the issue.
|
|
156
|
-
|
|
157
|
-
## Commands to Run in Browser Console
|
|
158
|
-
|
|
159
|
-
```javascript
|
|
160
|
-
// 1. Comprehensive status check
|
|
161
|
-
{
|
|
162
|
-
api: await fetch('/gm/api/conversations').then(r => r.json()).then(d => d.conversations?.length),
|
|
163
|
-
app: app.conversations.size,
|
|
164
|
-
baseUrl: BASE_URL,
|
|
165
|
-
windowWidth: window.innerWidth,
|
|
166
|
-
chatList: !!document.getElementById('chatList'),
|
|
167
|
-
agents: app.agents.size
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// 2. Force refetch and render
|
|
171
|
-
await app.fetchConversations();
|
|
172
|
-
app.renderChatHistory();
|
|
173
|
-
window.app.conversations.size
|
|
174
|
-
|
|
175
|
-
// 3. Check Claude Code availability
|
|
176
|
-
await fetch('/gm/api/discover/claude-code').then(r => r.json()).then(d => console.log('Claude Code available:', d.discovered?.length))
|
|
177
|
-
|
|
178
|
-
// 4. Manual import
|
|
179
|
-
await fetch('/gm/api/import/claude-code').then(r => r.json()).then(d => console.log('Import:', d))
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
## Expected Behavior
|
|
183
|
-
|
|
184
|
-
**After Fix:**
|
|
185
|
-
1. Page loads
|
|
186
|
-
2. Console shows [DEBUG] logs
|
|
187
|
-
3. Page title shows "GMGUI (XX chats)"
|
|
188
|
-
4. Sidebar shows conversation list
|
|
189
|
-
5. Can click conversation to view it
|
|
190
|
-
6. Can create new conversations
|
|
191
|
-
7. Can import Claude Code conversations
|
|
192
|
-
|
|
193
|
-
## If Still Stuck
|
|
194
|
-
|
|
195
|
-
1. **Collect information:**
|
|
196
|
-
- Output of all console commands above
|
|
197
|
-
- Screenshot of browser console showing all [DEBUG] logs
|
|
198
|
-
- Output of `echo $HOME` on remote server
|
|
199
|
-
- Output of `ls -la ~/.claude/projects/` on remote server
|
|
200
|
-
- Output of `ls -la ~/.gmgui/` on remote server
|
|
201
|
-
|
|
202
|
-
2. **Share these logs** for remote debugging
|
|
203
|
-
|
|
204
|
-
3. **Try manual steps:**
|
|
205
|
-
- In console: `await _debug.forceRefetch()`
|
|
206
|
-
- Then: `app.renderChatHistory()`
|
|
207
|
-
- Screenshot result
|
|
208
|
-
|
|
209
|
-
## Important Notes
|
|
210
|
-
|
|
211
|
-
- `~/.gmgui/data.db` - AgentGUI database (stores conversations)
|
|
212
|
-
- `~/.claude/projects/` - Claude Code storage (where conversations come from)
|
|
213
|
-
- `/gm/api/conversations` - Endpoint to get all conversations
|
|
214
|
-
- `/gm/api/discover/claude-code` - Find available Claude Code conversations
|
|
215
|
-
- `/gm/api/import/claude-code` - Import Claude Code conversations to AgentGUI
|
|
216
|
-
|
|
217
|
-
## Performance Tip
|
|
218
|
-
|
|
219
|
-
If you have lots of conversations (100+), they might load slowly. You can paginate by checking:
|
|
220
|
-
```javascript
|
|
221
|
-
// Check how many are in the list element
|
|
222
|
-
document.getElementById('chatList').children.length
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
If this is less than the API count, pagination is needed (future enhancement).
|
package/RESPONSE_ISSUES.md
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
# Response Display Issues & Analysis
|
|
2
|
-
|
|
3
|
-
## Issue 1: Combined Responses Without Separation
|
|
4
|
-
|
|
5
|
-
Example from user feedback:
|
|
6
|
-
```
|
|
7
|
-
"Let me start by reading the PRD file to understand what tasks need to be completed.This is a large PRD with many unchecked items across 6 phases. Let me explore the codebase to understand the current state before planning implementation."
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
**Problem**: Two separate thoughts/steps are combined into one paragraph without proper separation:
|
|
11
|
-
- "Let me start by reading..." (statement of intent)
|
|
12
|
-
- "This is a large PRD..." (observation/analysis)
|
|
13
|
-
|
|
14
|
-
### Root Cause Analysis
|
|
15
|
-
|
|
16
|
-
The ResponseFormatter is parsing continuous text as a single segment if it doesn't have explicit markdown formatting. When Claude sends thinking or analysis steps, they may be:
|
|
17
|
-
1. Separated by newlines in the actual response
|
|
18
|
-
2. Separated by periods/punctuation but no blank lines
|
|
19
|
-
3. Represented as separate agent messages but concatenated
|
|
20
|
-
|
|
21
|
-
### Current Handling
|
|
22
|
-
|
|
23
|
-
In `response-formatter.js`, the `parseResponse()` function treats consecutive text lines as one segment unless they have markdown markers (# ## etc).
|
|
24
|
-
|
|
25
|
-
### Fix Needed
|
|
26
|
-
|
|
27
|
-
1. **Detect step boundaries**: Recognize patterns like:
|
|
28
|
-
- "Let me..." → New action/step
|
|
29
|
-
- "I'll..." → New intent
|
|
30
|
-
- "Now..." → Transition
|
|
31
|
-
- "Here's..." → Result presentation
|
|
32
|
-
- "First..." / "Next..." → Sequential steps
|
|
33
|
-
|
|
34
|
-
2. **Segment by semantic meaning**: Break text into logical paragraphs that represent:
|
|
35
|
-
- Planning/Analysis
|
|
36
|
-
- Investigation
|
|
37
|
-
- Results
|
|
38
|
-
- Explanations
|
|
39
|
-
|
|
40
|
-
3. **Add visual separators**: Use cards or dividers between segments
|
|
41
|
-
|
|
42
|
-
## Issue 2: Tags/JSON Not Rendering
|
|
43
|
-
|
|
44
|
-
Types of content that should render specially:
|
|
45
|
-
- `<thinking>` tags (Claude's reasoning)
|
|
46
|
-
- `<tool_use>` tags (Tool call indicators)
|
|
47
|
-
- `<result>` tags (Tool results)
|
|
48
|
-
- Metadata blocks
|
|
49
|
-
- Tool output
|
|
50
|
-
|
|
51
|
-
Example that should render:
|
|
52
|
-
```
|
|
53
|
-
<thinking>
|
|
54
|
-
This problem requires analysis
|
|
55
|
-
</thinking>
|
|
56
|
-
|
|
57
|
-
<tool_use>
|
|
58
|
-
name: fs_access
|
|
59
|
-
</tool_use>
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
## Issue 3: Metadata-Rich Content
|
|
63
|
-
|
|
64
|
-
Elements that need special rendering:
|
|
65
|
-
- Tool names (should be in code styling)
|
|
66
|
-
- Function signatures (should be formatted as code)
|
|
67
|
-
- API responses (should be formatted as JSON blocks)
|
|
68
|
-
- Task lists (should be checkboxes or special formatting)
|
|
69
|
-
- Subagent notifications (should have special styling)
|
|
70
|
-
|
|
71
|
-
## Solution Architecture
|
|
72
|
-
|
|
73
|
-
### Enhanced ResponseFormatter
|
|
74
|
-
|
|
75
|
-
1. **XML Tag Detection**
|
|
76
|
-
```javascript
|
|
77
|
-
detectXMLTags(text) // Find <thinking>, <tool_use>, <result>, etc.
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
2. **Smart Segmentation**
|
|
81
|
-
```javascript
|
|
82
|
-
segmentByIntent(text) // Break on "Let me", "I'll", "Now", etc.
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
3. **Special Element Handling**
|
|
86
|
-
```javascript
|
|
87
|
-
renderToolCall(toolData)
|
|
88
|
-
renderThinking(thoughtText)
|
|
89
|
-
renderResult(resultData)
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Frontend Enhancement
|
|
93
|
-
|
|
94
|
-
1. **New Segment Types**
|
|
95
|
-
- `thinking` → Collapsible gray box
|
|
96
|
-
- `tool_call` → Highlighted with tool name
|
|
97
|
-
- `tool_result` → Code/result styling
|
|
98
|
-
- `analysis` → Regular text with better spacing
|
|
99
|
-
- `action` → Action statement styling
|
|
100
|
-
|
|
101
|
-
2. **CSS Classes for Each**
|
|
102
|
-
```css
|
|
103
|
-
.segment-thinking { background: #f9f9f9; border-left: 4px solid #999; }
|
|
104
|
-
.segment-tool_call { background: #f0f8ff; border-left: 4px solid #007acc; }
|
|
105
|
-
.segment-tool_result { background: #fff9e6; border-left: 4px solid #ffb300; }
|
|
106
|
-
.segment-action { font-weight: 500; color: #333; margin-top: 1.5rem; }
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Implementation Priority
|
|
110
|
-
|
|
111
|
-
1. **High Priority** (Breaking issues)
|
|
112
|
-
- Fix response combining (split on semantic boundaries)
|
|
113
|
-
- Render `<thinking>` blocks separately
|
|
114
|
-
- Proper code block formatting
|
|
115
|
-
|
|
116
|
-
2. **Medium Priority** (Display quality)
|
|
117
|
-
- Tool call highlighting
|
|
118
|
-
- Tool result formatting
|
|
119
|
-
- Better metadata display
|
|
120
|
-
|
|
121
|
-
3. **Low Priority** (Enhancement)
|
|
122
|
-
- Animated reveals for collapsible sections
|
|
123
|
-
- Copy-to-clipboard for code blocks
|
|
124
|
-
- Export formatting
|
|
125
|
-
|
|
126
|
-
## Files to Modify
|
|
127
|
-
|
|
128
|
-
1. `response-formatter.js`
|
|
129
|
-
- Add XML tag detection
|
|
130
|
-
- Add intent-based segmentation
|
|
131
|
-
- Add special element parsing
|
|
132
|
-
|
|
133
|
-
2. `static/app.js`
|
|
134
|
-
- Add `renderThinkingSegment()`
|
|
135
|
-
- Add `renderToolCallSegment()`
|
|
136
|
-
- Add `renderActionSegment()`
|
|
137
|
-
|
|
138
|
-
3. `static/styles.css`
|
|
139
|
-
- Add styling for new segment types
|
|
140
|
-
- Add visual hierarchy
|
|
141
|
-
|
|
142
|
-
## Testing Strategy
|
|
143
|
-
|
|
144
|
-
Create test cases with responses like:
|
|
145
|
-
```
|
|
146
|
-
Let me analyze this requirement.
|
|
147
|
-
|
|
148
|
-
Looking at the code structure, I see...
|
|
149
|
-
|
|
150
|
-
Now I'll implement the solution.
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
Should produce:
|
|
154
|
-
- Segment 1: "Let me analyze..." (action/planning)
|
|
155
|
-
- Segment 2: "Looking at..." (analysis)
|
|
156
|
-
- Segment 3: "Now I'll..." (implementation step)
|
|
157
|
-
|
package/SIDEBAR_FIX_SUMMARY.md
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# Conversation Display Fix - Root Cause and Solution
|
|
2
|
-
|
|
3
|
-
## Problem
|
|
4
|
-
Conversations were not visible in the AgentGUI on the remote server, even though:
|
|
5
|
-
- ✅ API was returning 83 conversations correctly
|
|
6
|
-
- ✅ Database had conversations stored
|
|
7
|
-
- ✅ App.js initialization logic was sound
|
|
8
|
-
|
|
9
|
-
## Root Cause
|
|
10
|
-
**The sidebar was hidden on narrow/mobile screens due to CSS responsive design.**
|
|
11
|
-
|
|
12
|
-
### CSS Behavior
|
|
13
|
-
The responsive CSS (at `styles.css` line 1181) applies at screens < 768px:
|
|
14
|
-
```css
|
|
15
|
-
@media (max-width: 768px) {
|
|
16
|
-
.sidebar {
|
|
17
|
-
transform: translateX(-100%); /* Hidden by default */
|
|
18
|
-
position: absolute;
|
|
19
|
-
}
|
|
20
|
-
.sidebar.open {
|
|
21
|
-
transform: translateX(0); /* Only visible with .open class */
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### What Was Happening
|
|
27
|
-
1. Page loads on narrow screen (or browser window narrower than 768px)
|
|
28
|
-
2. Conversations ARE fetched and loaded into the app ✅
|
|
29
|
-
3. renderChatHistory() IS called and renders conversation items ✅
|
|
30
|
-
4. BUT: The sidebar is hidden with `transform: translateX(-100%)` by default
|
|
31
|
-
5. Users can't see the conversation list because sidebar is off-screen
|
|
32
|
-
|
|
33
|
-
## Solution Implemented
|
|
34
|
-
Modified `init()` method in `static/app.js` to:
|
|
35
|
-
|
|
36
|
-
1. **Detect screen width** on page load
|
|
37
|
-
2. **On mobile/narrow screens (< 768px)**:
|
|
38
|
-
- Add the `open` class to sidebar
|
|
39
|
-
- This applies `transform: translateX(0)` which makes sidebar visible
|
|
40
|
-
3. **On desktop screens (≥ 768px)**:
|
|
41
|
-
- Ensure sidebar doesn't have `open` class
|
|
42
|
-
- Desktop CSS keeps sidebar visible without the class
|
|
43
|
-
|
|
44
|
-
```javascript
|
|
45
|
-
const sidebar = document.getElementById('sidebar');
|
|
46
|
-
if (window.innerWidth >= 768 && sidebar) {
|
|
47
|
-
sidebar.classList.remove('open'); // Desktop: always visible
|
|
48
|
-
} else if (sidebar) {
|
|
49
|
-
sidebar.classList.add('open'); // Mobile: toggle visibility on
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Additional Improvements Made
|
|
54
|
-
|
|
55
|
-
### 1. Robust DOM Ready Check
|
|
56
|
-
Wrapped app instantiation in `initializeApp()` function that:
|
|
57
|
-
- Waits for `#chatList` element to be present
|
|
58
|
-
- Retries every 100ms if element not found
|
|
59
|
-
- Prevents errors if app loads before DOM
|
|
60
|
-
|
|
61
|
-
### 2. Enhanced Error Logging
|
|
62
|
-
Added detailed error checking in `fetchConversations()`:
|
|
63
|
-
- Check HTTP response status
|
|
64
|
-
- Log full error details and stack traces
|
|
65
|
-
- Warn if conversations size becomes 0
|
|
66
|
-
- Log response data for debugging
|
|
67
|
-
|
|
68
|
-
### 3. Window Width Logging
|
|
69
|
-
Added `[DEBUG] Init: Window width:` log to help diagnose screen size issues
|
|
70
|
-
|
|
71
|
-
## Testing Checklist
|
|
72
|
-
|
|
73
|
-
After deploying, verify:
|
|
74
|
-
|
|
75
|
-
- [ ] Open on desktop (> 768px width) - sidebar should be visible with conversations
|
|
76
|
-
- [ ] Open on mobile/narrow window (< 768px) - sidebar should be hidden but clickable via hamburger icon
|
|
77
|
-
- [ ] Check browser console - should see `[DEBUG]` logs showing:
|
|
78
|
-
- Window width
|
|
79
|
-
- Conversation count loaded
|
|
80
|
-
- chatList innerHTML length
|
|
81
|
-
- [ ] Page title should show "GMGUI (83 chats)" or similar
|
|
82
|
-
- [ ] Clicking conversation item should load it
|
|
83
|
-
- [ ] New conversations should appear immediately
|
|
84
|
-
|
|
85
|
-
## Files Modified
|
|
86
|
-
- `static/app.js` - Added sidebar visibility logic and improved initialization
|
|
87
|
-
|
|
88
|
-
## Commit
|
|
89
|
-
```
|
|
90
|
-
fix: Ensure sidebar is visible and conversations display on all screen sizes
|
|
91
|
-
|
|
92
|
-
- Made DOM ready check more robust with polling
|
|
93
|
-
- Moved app instantiation to safe initialization function
|
|
94
|
-
- Added window width logging to detect screen size issues
|
|
95
|
-
- Auto-open sidebar on mobile/narrow screens (< 768px)
|
|
96
|
-
- Ensure sidebar doesn't have 'open' class on desktop to prevent transform
|
|
97
|
-
- Enhanced fetchConversations error logging and checks
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Browser Compatibility
|
|
101
|
-
- Works on all screen sizes
|
|
102
|
-
- Responsive design preserved
|
|
103
|
-
- Mobile users can click hamburger icon to toggle sidebar
|
|
104
|
-
- Desktop users see full sidebar
|
|
105
|
-
|
|
106
|
-
## Next Steps if Issue Persists
|
|
107
|
-
1. Check browser console for `[DEBUG]` logs
|
|
108
|
-
2. Verify page title shows conversation count
|
|
109
|
-
3. Check window width log to confirm screen size detection
|
|
110
|
-
4. Verify `#chatList` element exists in DOM (F12 → Elements tab)
|
|
111
|
-
5. Check if any JavaScript errors prevent initialization
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
# State Consistency Guarantee
|
|
2
|
-
|
|
3
|
-
## Principle
|
|
4
|
-
**Server is the single source of truth. Client state ALWAYS matches server state.**
|
|
5
|
-
|
|
6
|
-
## Architecture
|
|
7
|
-
|
|
8
|
-
### Single Source of Truth
|
|
9
|
-
- Server database (`~/.gmgui/data.db`) is the authoritative state
|
|
10
|
-
- Client state is derived from server, never modifies independently
|
|
11
|
-
- Every UI update is triggered by verified server data
|
|
12
|
-
|
|
13
|
-
### State Flow
|
|
14
|
-
```
|
|
15
|
-
User Action (create/update message)
|
|
16
|
-
↓
|
|
17
|
-
Sent to Server via API
|
|
18
|
-
↓
|
|
19
|
-
Server updates database
|
|
20
|
-
↓
|
|
21
|
-
Server broadcasts sync event
|
|
22
|
-
↓
|
|
23
|
-
Client receives event
|
|
24
|
-
↓
|
|
25
|
-
Client calls fetchConversations() [CRITICAL]
|
|
26
|
-
↓
|
|
27
|
-
Client updates local state from fresh server data
|
|
28
|
-
↓
|
|
29
|
-
Client renders UI
|
|
30
|
-
↓
|
|
31
|
-
ALL TABS see identical data
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Consistency Guarantees
|
|
35
|
-
|
|
36
|
-
### ✅ No Eventual Consistency Issues
|
|
37
|
-
- No "eventually consistent" data
|
|
38
|
-
- All windows/tabs show identical data **immediately**
|
|
39
|
-
- No delayed updates or race conditions
|
|
40
|
-
|
|
41
|
-
### ✅ Impossible States Prevented
|
|
42
|
-
- Can't have a conversation in one tab but not another
|
|
43
|
-
- Can't have different message counts across tabs
|
|
44
|
-
- Can't have stale timestamps anywhere
|
|
45
|
-
|
|
46
|
-
### ✅ Multi-Tab Synchronization
|
|
47
|
-
- When message is sent in Tab A
|
|
48
|
-
- Server processes it (broadcasts event)
|
|
49
|
-
- Tab A fetches fresh state
|
|
50
|
-
- Tab B receives broadcast (WebSocket or BroadcastChannel)
|
|
51
|
-
- Tab B fetches fresh state
|
|
52
|
-
- **Both tabs show identical data < 100ms apart**
|
|
53
|
-
|
|
54
|
-
### ✅ Connection Loss Handling
|
|
55
|
-
- If WebSocket disconnects > 2 seconds: force full refresh
|
|
56
|
-
- When reconnecting: fetch full state immediately
|
|
57
|
-
- No partial/stale data shown to user
|
|
58
|
-
|
|
59
|
-
### ✅ Timestamp Consistency
|
|
60
|
-
- Conversation `updated_at` always matches server
|
|
61
|
-
- All views see same ordering of conversations
|
|
62
|
-
- New conversations appear in all tabs simultaneously
|
|
63
|
-
|
|
64
|
-
## Implementation Details
|
|
65
|
-
|
|
66
|
-
### Every Sync Event Triggers Full Fetch
|
|
67
|
-
```javascript
|
|
68
|
-
case 'conversation_created':
|
|
69
|
-
console.log('[STATE SYNC] Conversation created, fetching full state');
|
|
70
|
-
// Never trust just the event data
|
|
71
|
-
this.fetchConversations().then(() => this.renderChatHistory());
|
|
72
|
-
break;
|
|
73
|
-
|
|
74
|
-
case 'session_updated':
|
|
75
|
-
console.log('[STATE SYNC] Session updated, fetching full state');
|
|
76
|
-
// Always get fresh authoritative state from server
|
|
77
|
-
this.fetchConversations().then(() => {
|
|
78
|
-
this.renderChatHistory();
|
|
79
|
-
if (this.currentConversation === event.conversationId) {
|
|
80
|
-
this.displayConversation(event.conversationId);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
break;
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### No Local-Only Mutations
|
|
87
|
-
- Client never mutates `this.conversations` without server verification
|
|
88
|
-
- Every mutation is preceded by `fetchConversations()`
|
|
89
|
-
- No optimistic updates that might be wrong
|
|
90
|
-
|
|
91
|
-
### Three-Pronged Sync Strategy
|
|
92
|
-
1. **WebSocket**: Real-time sync events from server
|
|
93
|
-
2. **BroadcastChannel**: Cross-tab sync (same browser)
|
|
94
|
-
3. **Consistency Monitor**: Verify state every 3 seconds
|
|
95
|
-
|
|
96
|
-
## Performance Implications
|
|
97
|
-
|
|
98
|
-
### Acceptable Trade-offs
|
|
99
|
-
- More API calls: Yes (necessary for consistency)
|
|
100
|
-
- Slight latency for renders: <100ms (imperceptible)
|
|
101
|
-
- Guaranteed consistency: YES (priceless)
|
|
102
|
-
|
|
103
|
-
### Optimization
|
|
104
|
-
- Debouncing: Rapid updates batched together
|
|
105
|
-
- Caching: Avoid unnecessary re-renders
|
|
106
|
-
- WebSocket: Primary sync method (low bandwidth)
|
|
107
|
-
|
|
108
|
-
## Testing Consistency
|
|
109
|
-
|
|
110
|
-
### Multi-Tab Test
|
|
111
|
-
1. Open Tab A: http://localhost:9897/gm/
|
|
112
|
-
2. Open Tab B: http://localhost:9897/gm/
|
|
113
|
-
3. Send message in Tab A
|
|
114
|
-
4. Observe: Message appears in Tab B < 100ms
|
|
115
|
-
5. Conversation order updates in both tabs simultaneously
|
|
116
|
-
6. Message count matches in both tabs
|
|
117
|
-
|
|
118
|
-
### Network Disconnect Test
|
|
119
|
-
1. Open DevTools
|
|
120
|
-
2. Throttle network (DevTools > Network tab)
|
|
121
|
-
3. Send message
|
|
122
|
-
4. Close network/disconnect WebSocket
|
|
123
|
-
5. Wait 2+ seconds
|
|
124
|
-
6. Restore network
|
|
125
|
-
7. Observe: Data is re-fetched and consistent
|
|
126
|
-
|
|
127
|
-
### Timestamp Test
|
|
128
|
-
1. Send message in conversation A
|
|
129
|
-
2. Switch to conversation B in Tab 1
|
|
130
|
-
3. Tab 2 still shows A
|
|
131
|
-
4. Observe: Both tabs show updated timestamp for A
|
|
132
|
-
5. Both tabs show same list order
|
|
133
|
-
|
|
134
|
-
## What NEVER Happens
|
|
135
|
-
- ❌ Conversation list differs between tabs
|
|
136
|
-
- ❌ Message appears in one tab but not another
|
|
137
|
-
- ❌ Stale conversation timestamps shown
|
|
138
|
-
- ❌ Out-of-order messages displayed
|
|
139
|
-
- ❌ Inconsistent conversation counts
|
|
140
|
-
- ❌ Missing recent messages
|
|
141
|
-
|
|
142
|
-
## Code Review Checklist
|
|
143
|
-
|
|
144
|
-
When modifying state-related code:
|
|
145
|
-
- ✅ Does all paths to state change call `fetchConversations()`?
|
|
146
|
-
- ✅ Are event handlers fetching fresh data?
|
|
147
|
-
- ✅ Is server the source of truth or local state?
|
|
148
|
-
- ✅ Could multiple tabs get inconsistent data?
|
|
149
|
-
- ✅ Are timestamps always from server?
|
|
150
|
-
|
|
151
|
-
## Future Enhancements
|
|
152
|
-
|
|
153
|
-
### Already Implemented
|
|
154
|
-
- ✅ Server-as-truth architecture
|
|
155
|
-
- ✅ All sync events trigger fetch
|
|
156
|
-
- ✅ WebSocket real-time sync
|
|
157
|
-
- ✅ BroadcastChannel cross-tab sync
|
|
158
|
-
- ✅ Consistency monitor (3s checks)
|
|
159
|
-
- ✅ Automatic reconnect with full refresh
|
|
160
|
-
|
|
161
|
-
### Possible Improvements (maintain consistency)
|
|
162
|
-
- [ ] Delta sync (only changed items) - while maintaining consistency
|
|
163
|
-
- [ ] Compression for large datasets
|
|
164
|
-
- [ ] Pagination for 1000+ conversations
|
|
165
|
-
- [ ] Caching with validation
|
|
166
|
-
|
|
167
|
-
## References
|
|
168
|
-
|
|
169
|
-
- `server.js` - Authoritative database and broadcast
|
|
170
|
-
- `app.js` - Client state synchronization
|
|
171
|
-
- `database.js` - Data persistence layer
|
|
172
|
-
- Sync events: `conversation_created`, `conversation_updated`, `conversation_deleted`, `message_created`, `session_updated`, `conversations_updated`
|
|
173
|
-
|
|
174
|
-
## Related Issues Fixed
|
|
175
|
-
|
|
176
|
-
- **Issue**: Different tabs showing different conversation lists
|
|
177
|
-
- **Root Cause**: Local mutations without server verification
|
|
178
|
-
- **Fix**: All mutations now preceded by `fetchConversations()`
|
|
179
|
-
- **Status**: ✅ FIXED
|
|
180
|
-
|
|
181
|
-
---
|
|
182
|
-
|
|
183
|
-
**Philosophy**: Better to have extra API calls and guaranteed consistency than fast but unreliable state. Consistency is non-negotiable.
|