Add local JSON daemon and route TUI/CLI through it.
A per-DataDir background process owns ticket JSON, history, and sync so multiple TUI instances stay consistent; MCP token APIs are ready for phase 2. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"task/internal/daemon/api"
|
||||
)
|
||||
|
||||
// SubscribeEvents streams SSE change events until ctx is cancelled.
|
||||
func (c *Client) SubscribeEvents(ctx context.Context, emit func(api.Event)) error {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://daemon/v1/events", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set(api.HeaderClient, c.kind)
|
||||
if c.kind == api.ClientMCP {
|
||||
if c.token != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+c.token)
|
||||
}
|
||||
if c.project != "" {
|
||||
req.Header.Set("X-TM-Project", c.project)
|
||||
}
|
||||
}
|
||||
// No overall timeout for long-lived SSE.
|
||||
httpClient := *c.http
|
||||
httpClient.Timeout = 0
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode >= 400 {
|
||||
return fmt.Errorf("events: %s", resp.Status)
|
||||
}
|
||||
sc := bufio.NewScanner(resp.Body)
|
||||
for sc.Scan() {
|
||||
line := sc.Text()
|
||||
if !strings.HasPrefix(line, "data: ") {
|
||||
continue
|
||||
}
|
||||
var ev api.Event
|
||||
if err := json.Unmarshal([]byte(strings.TrimPrefix(line, "data: ")), &ev); err != nil {
|
||||
continue
|
||||
}
|
||||
emit(ev)
|
||||
}
|
||||
return sc.Err()
|
||||
}
|
||||
Reference in New Issue
Block a user