parseToolsInvocation accepts the JSON envelope {cmd, args} or the argv form ("describe @diagram" / "list").
(args []string)
| 141 | // parseToolsInvocation accepts the JSON envelope {cmd, args} or the argv form |
| 142 | // ("describe @diagram" / "list"). |
| 143 | func parseToolsInvocation(args []string) (string, string, error) { |
| 144 | payload := strings.TrimSpace(strings.Join(args, " ")) |
| 145 | |
| 146 | if strings.HasPrefix(payload, "{") { |
| 147 | var raw map[string]json.RawMessage |
| 148 | if err := json.Unmarshal([]byte(payload), &raw); err != nil { |
| 149 | return "", "", fmt.Errorf(`parse envelope: %w. Expected {"cmd":"describe","args":{"name":"@x"}}`, err) |
| 150 | } |
| 151 | var cmdStr string |
| 152 | if rc, ok := raw["cmd"]; ok { |
| 153 | _ = json.Unmarshal(rc, &cmdStr) |
| 154 | } |
| 155 | canon := canonicalToolsCmd(cmdStr) |
| 156 | if canon == "" { |
| 157 | return "", "", fmt.Errorf("missing or unknown cmd %q (valid: describe|list)", cmdStr) |
| 158 | } |
| 159 | var inner string |
| 160 | if rargs, ok := raw["args"]; ok && len(rargs) > 0 { |
| 161 | inner = string(rargs) |
| 162 | } else { |
| 163 | delete(raw, "cmd") |
| 164 | b, _ := json.Marshal(raw) |
| 165 | inner = string(b) |
| 166 | } |
| 167 | return canon, inner, nil |
| 168 | } |
| 169 | |
| 170 | canon := canonicalToolsCmd(args[0]) |
| 171 | if canon == "" { |
| 172 | return "", "", fmt.Errorf("unknown cmd %q (valid: describe|list)", args[0]) |
| 173 | } |
| 174 | // The agent flattener delivers the {cmd,args} envelope as "--flag value" |
| 175 | // argv, so both flag and positional spellings must resolve here. |
| 176 | in := map[string]interface{}{} |
| 177 | rest := args[1:] |
| 178 | for i := 0; i < len(rest); i++ { |
| 179 | a := strings.TrimSpace(rest[i]) |
| 180 | if a == "" { |
| 181 | continue |
| 182 | } |
| 183 | if strings.HasPrefix(a, "-") { |
| 184 | key := strings.TrimLeft(a, "-") |
| 185 | if eq := strings.IndexByte(key, '='); eq >= 0 { |
| 186 | in[key[:eq]] = trimQuotes(strings.TrimSpace(key[eq+1:])) |
| 187 | continue |
| 188 | } |
| 189 | if i+1 < len(rest) { |
| 190 | i++ |
| 191 | in[key] = trimQuotes(strings.TrimSpace(rest[i])) |
| 192 | } |
| 193 | continue |
| 194 | } |
| 195 | if _, ok := in["name"]; !ok { |
| 196 | in["name"] = a |
| 197 | } |
| 198 | } |
| 199 | b, _ := json.Marshal(in) |
| 200 | return canon, string(b), nil |
no test coverage detected