package handlers import ( "os/exec" "github.com/gin-gonic/gin" ) const claudeModeScript = "/data/director/scripts/claude-mode.sh" // GetClaudeMode returns the current Claude provider mode (api or proxy) // by parsing the openclaw.json directly via the toggle script. func (h *Handler) GetClaudeMode(c *gin.Context) { out, err := exec.Command(claudeModeScript, "status").CombinedOutput() if err != nil { c.JSON(500, gin.H{"error": err.Error(), "output": string(out)}) return } mode := "unknown" for _, line := range splitLines(string(out)) { if hasPrefix(line, "Current Claude mode: ") { mode = trim(line[len("Current Claude mode: "):]) break } } c.JSON(200, gin.H{ "mode": mode, "output": string(out), }) } // SetClaudeMode flips between api and proxy modes. func (h *Handler) SetClaudeMode(c *gin.Context) { var input struct { Mode string `json:"mode" binding:"required"` } if err := c.ShouldBindJSON(&input); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } if input.Mode != "api" && input.Mode != "proxy" { c.JSON(400, gin.H{"error": "mode must be 'api' or 'proxy'"}) return } out, err := exec.Command(claudeModeScript, input.Mode).CombinedOutput() if err != nil { c.JSON(500, gin.H{"error": err.Error(), "output": string(out)}) return } h.broadcast(c, "system:claude-mode", gin.H{"mode": input.Mode}) c.JSON(200, gin.H{"mode": input.Mode, "output": string(out)}) } // tiny string helpers — avoid importing strings just for these func splitLines(s string) []string { var out []string start := 0 for i := 0; i < len(s); i++ { if s[i] == '\n' { out = append(out, s[start:i]) start = i + 1 } } if start < len(s) { out = append(out, s[start:]) } return out } func hasPrefix(s, p string) bool { return len(s) >= len(p) && s[:len(p)] == p } func trim(s string) string { start, end := 0, len(s) for start < end && (s[start] == ' ' || s[start] == '\t' || s[start] == '\r') { start++ } for end > start && (s[end-1] == ' ' || s[end-1] == '\t' || s[end-1] == '\r') { end-- } return s[start:end] }