fix(monitor): inbox API returns {data:[...]} not {messages:[...]}
Some checks failed
CI / test (push) Failing after 3s
Some checks failed
CI / test (push) Failing after 3s
The MCP agent_inbox tool wraps the response as {messages:[...]},
but the raw API returns {data:[...]}. The monitor calls the raw
API directly, so it needs to parse {data:[...]}.
Verified with curl against live API. Removed debug channel events.
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
62b9ee7729
commit
b5dcdd1261
2 changed files with 25 additions and 7 deletions
|
|
@ -68,6 +68,12 @@ func New(opts ...Options) *Subsystem {
|
|||
if len(opts) > 0 && opts[0].Interval > 0 {
|
||||
interval = opts[0].Interval
|
||||
}
|
||||
// Override via env for debugging
|
||||
if envInterval := os.Getenv("MONITOR_INTERVAL"); envInterval != "" {
|
||||
if d, err := time.ParseDuration(envInterval); err == nil {
|
||||
interval = d
|
||||
}
|
||||
}
|
||||
return &Subsystem{
|
||||
interval: interval,
|
||||
poke: make(chan struct{}, 1),
|
||||
|
|
@ -75,6 +81,13 @@ func New(opts ...Options) *Subsystem {
|
|||
}
|
||||
}
|
||||
|
||||
// debugChannel sends a debug message via the notifier so it arrives as a channel event.
|
||||
func (m *Subsystem) debugChannel(msg string) {
|
||||
if m.notifier != nil {
|
||||
m.notifier.ChannelSend(context.Background(), "monitor.debug", map[string]any{"msg": msg})
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Subsystem) Name() string { return "monitor" }
|
||||
|
||||
func (m *Subsystem) RegisterTools(server *mcp.Server) {
|
||||
|
|
@ -95,6 +108,8 @@ func (m *Subsystem) Start(ctx context.Context) {
|
|||
monCtx, cancel := context.WithCancel(ctx)
|
||||
m.cancel = cancel
|
||||
|
||||
fmt.Fprintf(os.Stderr, "monitor: started (interval=%s, notifier=%v)\n", m.interval, m.notifier != nil)
|
||||
|
||||
m.wg.Add(1)
|
||||
go func() {
|
||||
defer m.wg.Done()
|
||||
|
|
@ -150,6 +165,7 @@ func (m *Subsystem) loop(ctx context.Context) {
|
|||
}
|
||||
|
||||
func (m *Subsystem) check(ctx context.Context) {
|
||||
fmt.Fprintf(os.Stderr, "monitor: check cycle running\n")
|
||||
var messages []string
|
||||
|
||||
// Check agent completions
|
||||
|
|
@ -270,6 +286,7 @@ func (m *Subsystem) checkInbox() string {
|
|||
keyFile := filepath.Join(home, ".claude", "brain.key")
|
||||
data, err := coreio.Local.Read(keyFile)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "monitor: checkInbox: no API key (env=%v, file err=%v)\n", apiKeyStr == "", err)
|
||||
return ""
|
||||
}
|
||||
apiKeyStr = data
|
||||
|
|
@ -298,11 +315,11 @@ func (m *Subsystem) checkInbox() string {
|
|||
}
|
||||
|
||||
var resp struct {
|
||||
Messages []struct {
|
||||
Data []struct {
|
||||
Read bool `json:"read"`
|
||||
From string `json:"from"`
|
||||
Subject string `json:"subject"`
|
||||
} `json:"messages"`
|
||||
} `json:"data"`
|
||||
}
|
||||
if json.NewDecoder(httpResp.Body).Decode(&resp) != nil {
|
||||
return ""
|
||||
|
|
@ -311,7 +328,7 @@ func (m *Subsystem) checkInbox() string {
|
|||
unread := 0
|
||||
senders := make(map[string]int)
|
||||
latestSubject := ""
|
||||
for _, msg := range resp.Messages {
|
||||
for _, msg := range resp.Data {
|
||||
if !msg.Read {
|
||||
unread++
|
||||
if msg.From != "" {
|
||||
|
|
@ -343,6 +360,7 @@ func (m *Subsystem) checkInbox() string {
|
|||
}
|
||||
// Push channel event for new messages
|
||||
if m.notifier != nil {
|
||||
fmt.Fprintf(os.Stderr, "monitor: pushing inbox.message channel event (new=%d)\n", unread-prevInbox)
|
||||
m.notifier.ChannelSend(context.Background(), "inbox.message", map[string]any{
|
||||
"new": unread - prevInbox,
|
||||
"total": unread,
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ func TestCheckInbox_Good_UnreadMessages(t *testing.T) {
|
|||
assert.NotEmpty(t, r.URL.Query().Get("agent"))
|
||||
|
||||
resp := map[string]any{
|
||||
"messages": []map[string]any{
|
||||
"data": []map[string]any{
|
||||
{"read": false, "from": "clotho", "subject": "task done"},
|
||||
{"read": false, "from": "gemini", "subject": "review ready"},
|
||||
{"read": true, "from": "clotho", "subject": "old msg"},
|
||||
|
|
@ -262,7 +262,7 @@ func TestCheckInbox_Good_UnreadMessages(t *testing.T) {
|
|||
func TestCheckInbox_Good_NoUnread(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
resp := map[string]any{
|
||||
"messages": []map[string]any{
|
||||
"data": []map[string]any{
|
||||
{"read": true, "from": "clotho", "subject": "old"},
|
||||
},
|
||||
}
|
||||
|
|
@ -281,7 +281,7 @@ func TestCheckInbox_Good_NoUnread(t *testing.T) {
|
|||
func TestCheckInbox_Good_SameCountNoRepeat(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
resp := map[string]any{
|
||||
"messages": []map[string]any{
|
||||
"data": []map[string]any{
|
||||
{"read": false, "from": "clotho", "subject": "msg"},
|
||||
},
|
||||
}
|
||||
|
|
@ -338,7 +338,7 @@ func TestCheckInbox_Bad_InvalidJSON(t *testing.T) {
|
|||
func TestCheckInbox_Good_MultipleSameSender(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
resp := map[string]any{
|
||||
"messages": []map[string]any{
|
||||
"data": []map[string]any{
|
||||
{"read": false, "from": "clotho", "subject": "msg1"},
|
||||
{"read": false, "from": "clotho", "subject": "msg2"},
|
||||
{"read": false, "from": "gemini", "subject": "msg3"},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue