PHASE_2_PLAN.md
1 # Phase 1.5-1.7: Testing & Backend Integration Plan 2 3 **Status:** Basic scaffold complete, moving to testing and backend 4 5 --- 6 7 ## Progress Update 8 9 ### ✅ Completed (Phase 1.1-1.4) 10 11 - [x] Go module initialized 12 - [x] Dependencies installed 13 - [x] Project structure created 14 - [x] Basic Bubble Tea skeleton 15 - [x] Message types defined 16 - [x] Styled rendering with Lipgloss 17 - [x] Binary compiles successfully 18 19 **Files:** 6 Go files, 516 lines total 20 **Binary:** 5.3 MB (debug build) 21 22 --- 23 24 ## Current: Phase 1.5-1.7 Testing 25 26 ### What to Test 27 28 1. **Basic rendering** ✓ 29 - Binary exists and runs 30 - Welcome message displays 31 - UI layout correct 32 33 2. **Input handling** (needs terminal test) 34 - Can type in textarea 35 - Enter submits message 36 - Message appears in viewport 37 38 3. **Keyboard shortcuts** (needs terminal test) 39 - Ctrl+C quits 40 - PgUp/PgDn scroll 41 - Textarea navigation works 42 43 ### Testing Approach 44 45 Since we're in a non-interactive environment, we need to: 46 47 **Option 1:** Manual testing later 48 - User runs `./kamaji-tui` in real terminal 49 - Tests all features interactively 50 51 **Option 2:** Continue development, test comprehensively at end 52 - Add more features first 53 - Test everything together 54 55 **Recommendation:** Continue with Phase 2 (backend integration) and test comprehensively when we have real functionality. 56 57 --- 58 59 ## Next: Phase 2 - Python Backend Integration 60 61 ### Goal 62 Connect Go TUI to existing Python Kamaji backend 63 64 ### Two Approaches 65 66 #### Option A: Subprocess (Simpler) 67 ```go 68 func callPythonBackend(message string) (string, error) { 69 cmd := exec.Command("python", "-m", "kamaji.cli", "ask", message) 70 output, err := cmd.CombinedOutput() 71 return string(output), err 72 } 73 ``` 74 75 **Pros:** 76 - Simple to implement 77 - Reuses existing kamaji CLI 78 - No changes to Python code 79 80 **Cons:** 81 - Slower (process startup overhead) 82 - No streaming 83 - No agent transparency 84 85 #### Option B: HTTP API (Better long-term) 86 ```python 87 # New file: kamaji/api.py 88 from flask import Flask, request, jsonify 89 from kamaji.llm import get_llm 90 from kamaji.agent import create_agent_executor 91 92 app = Flask(__name__) 93 94 @app.route('/chat', methods=['POST']) 95 def chat(): 96 message = request.json['message'] 97 # ... send to agent, return response 98 return jsonify({'response': response}) 99 ``` 100 101 ```go 102 func callPythonAPI(message string) (string, error) { 103 resp, err := http.Post("http://localhost:5000/chat", 104 "application/json", 105 strings.NewReader(fmt.Sprintf(`{"message": "%s"}`, message))) 106 // ... parse response 107 } 108 ``` 109 110 **Pros:** 111 - Fast (no process startup) 112 - Can stream responses 113 - Can send agent events (thinking, tools) 114 - Cleaner architecture 115 116 **Cons:** 117 - Requires adding HTTP server to Python 118 - More complexity 119 - Need to manage server lifecycle 120 121 ### Recommendation: Start with Option A, migrate to Option B 122 123 **Phase 2.1:** Subprocess integration (quick proof of concept) 124 **Phase 2.2:** Add streaming HTTP API (better UX) 125 126 --- 127 128 ## Phase 2.1 Tasks (Subprocess Approach) 129 130 ### 2.1.1: Implement subprocess call 131 132 ```go 133 // backend.go 134 import ( 135 "os/exec" 136 "strings" 137 ) 138 139 func callKamajiCLI(message string) tea.Cmd { 140 return func() tea.Msg { 141 // Call: python -m kamaji.cli ask "message" 142 cmd := exec.Command( 143 "python", "-m", "kamaji.cli", 144 "ask", message, 145 ) 146 147 // Set working directory to kamaji root 148 cmd.Dir = "../" 149 150 output, err := cmd.CombinedOutput() 151 if err != nil { 152 return errMsg(err) 153 } 154 155 return backendResponseMsg(string(output)) 156 } 157 } 158 ``` 159 160 ### 2.1.2: Update message submission 161 162 ```go 163 // update.go - in KeyEnter handler 164 return m, callKamajiCLI(userMessage) 165 ``` 166 167 ### 2.1.3: Test end-to-end 168 169 ```bash 170 ./kamaji-tui 171 # Type: "What is 2+2?" 172 # Should get LLM response back 173 ``` 174 175 ### 2.1.4: Handle errors gracefully 176 177 ```go 178 case errMsg: 179 m.loading = false 180 m.messages = append(m.messages, Message{ 181 Role: "system", 182 Content: StyledErrorMessage(msg), 183 }) 184 ``` 185 186 --- 187 188 ## Phase 2.2 Tasks (HTTP API) 189 190 ### 2.2.1: Create Python HTTP API 191 192 ```python 193 # kamaji/api_server.py 194 from flask import Flask, Response, request 195 from kamaji.agent import create_agent_executor 196 from kamaji.llm import get_llm 197 import json 198 199 app = Flask(__name__) 200 201 @app.route('/stream', methods=['POST']) 202 def stream_chat(): 203 message = request.json['message'] 204 205 def generate(): 206 # Setup agent with streaming callbacks 207 llm = get_llm() 208 agent = create_agent_executor(llm, callbacks=[ 209 StreamingCallback(lambda event: yield json.dumps(event) + "\n") 210 ]) 211 212 # Run agent 213 result = agent.run(message) 214 215 yield json.dumps({'type': 'final', 'content': result}) + "\n" 216 217 return Response(generate(), mimetype='text/event-stream') 218 219 if __name__ == '__main__': 220 app.run(port=5555) 221 ``` 222 223 ### 2.2.2: Implement Go HTTP client 224 225 ```go 226 // backend.go 227 func streamFromAPI(message string) tea.Cmd { 228 return func() tea.Msg { 229 resp, err := http.Post( 230 "http://localhost:5555/stream", 231 "application/json", 232 strings.NewReader(fmt.Sprintf(`{"message": "%s"}`, message)), 233 ) 234 if err != nil { 235 return errMsg(err) 236 } 237 238 scanner := bufio.NewScanner(resp.Body) 239 for scanner.Scan() { 240 var event Event 241 json.Unmarshal(scanner.Bytes(), &event) 242 243 // Send events to UI 244 // (need to design event passing) 245 } 246 247 return nil 248 } 249 } 250 ``` 251 252 ### 2.2.3: Add event types for agent transparency 253 254 ```go 255 // model.go 256 type Event struct { 257 Type string `json:"type"` // thinking, tool, result, final 258 Content string `json:"content"` 259 Tool string `json:"tool,omitempty"` 260 Timing float64 `json:"timing,omitempty"` 261 } 262 ``` 263 264 ### 2.2.4: Update UI to show events in real-time 265 266 As events stream in, append messages and update viewport 267 268 --- 269 270 ## Timeline 271 272 **Phase 2.1 (Subprocess):** 2-3 hours 273 - Quick to implement 274 - Gets us working end-to-end 275 - Can test immediately 276 277 **Phase 2.2 (HTTP API):** 4-6 hours 278 - Need to create Python API 279 - Implement streaming 280 - Wire up events 281 - More polished result 282 283 **Total Phase 2:** ~6-9 hours (1 day) 284 285 --- 286 287 ## Decision Point 288 289 **Should we:** 290 291 A. Implement Phase 2.1 now (subprocess, quick) ✅ **RECOMMENDED** 292 - Gets us working faster 293 - Can demo immediately 294 - Easier to debug 295 296 B. Skip to Phase 2.2 (HTTP API, better) 297 - More work upfront 298 - Better long-term 299 - Need to design API carefully 300 301 C. Do both in sequence 302 - 2.1 first for quick validation 303 - Then 2.2 for production quality 304 305 **Recommendation: Option C** - Start with subprocess (2.1) to validate quickly, then add HTTP API (2.2) for better UX. 306 307 --- 308 309 ## Next Immediate Steps 310 311 1. ✅ Complete styled message rendering (done) 312 2. → Implement subprocess backend call (2.1.1) 313 3. → Test with real kamaji command (2.1.3) 314 4. → Handle errors gracefully (2.1.4) 315 5. → Update progress tracker 316 317 **Let's implement Phase 2.1 now!**