Commit b6f0b05
authored
feat: add terminal UI with Bubble Tea v2 (#12)
* feat: add terminal UI with Bubble Tea v2
Implement `yantra tui` — a polished terminal chat UI that connects to
the gateway server via WebSocket. The TUI starts the gateway in-process
(goroutine), then renders streaming responses, tool progress, and
session management in an alternate-screen Bubble Tea app.
New files in internal/tui/:
- app.go: root Model composing header, chat viewport, input, status bar
- chat.go: message rendering with streaming cursor, tool spinners, glamour markdown
- client.go: WebSocket client with reconnect and exponential backoff
- commands.go: slash command parser (/new, /sessions, /switch, /cancel, /clear, /help, /quit)
- input.go: textarea wrapper with Enter-to-send and dynamic height
- markdown.go: glamour wrapper for completed assistant messages
- messages.go: tea.Msg types bridging server frames into Bubble Tea
- styles.go: adaptive dark/light lipgloss styles with purple branding
Dependencies: bubbletea v2, bubbles v2, lipgloss v2, glamour.
* fix: address PR review — nil program, conn race, reconnect, health timeout, DB leak
1. nil Program: Connect() no longer takes a program arg; AttachProgram()
wires it before Run(). readLoop now receives frames correctly.
2. conn race: readLoop takes the conn as a local argument so it never
races with Close/Reconnect mutating c.conn. sessionID reads also
protected by mutex.
3. Reconnect never triggered: DisconnectedMsg handler now returns
a.client.Reconnect() cmd for automatic exponential-backoff reconnect.
4. Health poll timeout: waitForHealth uses http.Client{Timeout: 1s} so a
stalled request can't block past the overall deadline.
5. DB leak: startGatewayInProcess returns a cleanup func that closes all
opened SQLite databases; runTUI defers it.
* fix: Gemini array items bug + TUI visual redesign
- Fix Gemini provider: jsonPropToGeminiSchema now parses the 'items'
field for array-type parameters, fixing 400 errors with tools like
memory_save that have array properties (tags).
- Redesign TUI visuals for a cleaner, modern look:
- Replace heavy purple header bar with subtle bordered title line
- Use ❯/◆ indicators for user/assistant messages instead of labels
- Indented message bodies with 4-space padding
- Softer color palette (Monokai-inspired: soft purple, cyan, yellow)
- Streaming shows 'thinking...' placeholder then text with ▍ cursor
- Tool progress: spinner + yellow name + dimmed status
- Errors: ✗ prefix with pink-red text
- Remove mouse capture so text selection/copy works natively
- Minimal status bar with accent-colored session ID
* fix: detect dark mode before tea.Program to prevent ANSI escape leak
Move lipgloss.HasDarkBackground() call to runTUI before creating the
Bubble Tea program. The terminal query response was arriving after
Bubble Tea took over stdin, leaking raw escape sequences into the
textarea input.1 parent 86a2245 commit b6f0b05
12 files changed
Lines changed: 1623 additions & 12 deletions
File tree
- cmd/yantra
- internal
- provider
- tui
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| 12 | + | |
11 | 13 | | |
| 14 | + | |
12 | 15 | | |
13 | 16 | | |
14 | 17 | | |
15 | 18 | | |
16 | 19 | | |
| 20 | + | |
17 | 21 | | |
18 | 22 | | |
19 | 23 | | |
| |||
302 | 306 | | |
303 | 307 | | |
304 | 308 | | |
305 | | - | |
306 | | - | |
307 | | - | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
308 | 463 | | |
309 | 464 | | |
310 | 465 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
6 | 9 | | |
| 10 | + | |
7 | 11 | | |
8 | 12 | | |
9 | 13 | | |
| |||
20 | 24 | | |
21 | 25 | | |
22 | 26 | | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
23 | 43 | | |
24 | 44 | | |
25 | 45 | | |
| |||
29 | 49 | | |
30 | 50 | | |
31 | 51 | | |
| 52 | + | |
32 | 53 | | |
33 | 54 | | |
| 55 | + | |
34 | 56 | | |
| 57 | + | |
| 58 | + | |
35 | 59 | | |
36 | 60 | | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
37 | 64 | | |
38 | 65 | | |
39 | 66 | | |
| 67 | + | |
40 | 68 | | |
41 | 69 | | |
42 | 70 | | |
43 | 71 | | |
44 | 72 | | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
45 | 76 | | |
46 | 77 | | |
47 | 78 | | |
48 | 79 | | |
49 | | - | |
50 | | - | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
51 | 83 | | |
52 | 84 | | |
53 | 85 | | |
| |||
0 commit comments