Skip to content

Commit a366c7c

Browse files
Brandon Salzbergclaude
andcommitted
Complete MIND chat with Claude tool execution loop
- Send tool definitions on session start, wait for processing - Handle tool_use responses: parse tool calls, execute locally, send results back - Pass active profile to tool execution so commands use correct credentials - Full loop: user question → Claude requests tools → CLI executes → Claude answers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9def4b1 commit a366c7c

1 file changed

Lines changed: 49 additions & 4 deletions

File tree

cmd/chat.go

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,21 @@ func init() {
4444

4545
func runChat(cmd *cobra.Command, args []string) error {
4646
cfg := config.LoadFromCmd(cmd)
47+
chatProfile = cfg.Profile
4748

4849
fmt.Println("Rhombus MIND Chat (powered by Claude)")
4950
fmt.Println("Ask questions about your cameras, events, and devices. Type 'exit' to quit.")
5051
fmt.Println()
5152

5253
contextID := fmt.Sprintf("cli-%d", time.Now().UnixMilli())
5354

54-
// Send tool definitions as the first message
55+
// Send tool definitions as the first message and wait for it to be processed
56+
fmt.Print("\033[2mInitializing tools...\033[0m")
5557
if err := sendToolDefinitions(cfg, contextID); err != nil {
58+
fmt.Printf("\r\033[K")
5659
fmt.Fprintf(os.Stderr, "Warning: failed to register tools: %v\n", err)
60+
} else {
61+
fmt.Printf("\r\033[K")
5762
}
5863

5964
scanner := bufio.NewScanner(os.Stdin)
@@ -92,16 +97,51 @@ func sendToolDefinitions(cfg config.Config, contextID string) error {
9297

9398
query := "[TOOLS]" + string(toolsJSON)
9499

95-
_, err = client.APICall(cfg, "/api/chatbot/submitChat", map[string]any{
100+
resp, err := client.APICall(cfg, "/api/chatbot/submitChat", map[string]any{
96101
"contextId": contextID,
97102
"query": query,
98103
})
99104
if err != nil {
100105
return err
101106
}
102107

103-
// Wait briefly for it to be processed
104-
time.Sleep(500 * time.Millisecond)
108+
recordUuid, _ := resp["chatRecordUuid"].(string)
109+
if recordUuid == "" {
110+
return nil
111+
}
112+
113+
// Wait for the tools message to be fully processed before continuing
114+
for i := 0; i < 30; i++ {
115+
time.Sleep(500 * time.Millisecond)
116+
117+
pollResp, err := client.APICall(cfg, "/api/chatbot/getChatRecord", map[string]any{
118+
"recordUuid": recordUuid,
119+
})
120+
if err != nil {
121+
continue
122+
}
123+
124+
chat, ok := pollResp["chat"].(map[string]any)
125+
if !ok {
126+
continue
127+
}
128+
129+
// Any response means it's been processed
130+
if _, hasResponse := chat["response"]; hasResponse {
131+
return nil
132+
}
133+
134+
timeline, _ := chat["timeline"].([]any)
135+
if len(timeline) > 0 {
136+
lastEvent, _ := timeline[len(timeline)-1].(map[string]any)
137+
status, _ := lastEvent["status"].(string)
138+
// If it reached any final status, it's done
139+
if status == "ANSWERED" || status == "NO_RESPONSE" || status == "PARTIALLY_ANSWERED" {
140+
return nil
141+
}
142+
}
143+
}
144+
105145
return nil
106146
}
107147

@@ -264,6 +304,8 @@ func pollForResponse(cfg config.Config, recordUuid string) (string, error) {
264304
return "", fmt.Errorf("timed out waiting for response")
265305
}
266306

307+
var chatProfile string
308+
267309
func executeRhombusCommand(command string) string {
268310
args := strings.Fields(command)
269311

@@ -273,6 +315,9 @@ func executeRhombusCommand(command string) string {
273315
}
274316

275317
args = append(args, "--output", "json")
318+
if chatProfile != "" {
319+
args = append(args, "--profile", chatProfile)
320+
}
276321

277322
cmd := exec.Command(executable, args...)
278323
output, err := cmd.CombinedOutput()

0 commit comments

Comments
 (0)