Add key subcommand to all 31 implementations

- Validate API keys via portal endpoint
- Show key status, tier, expiration with color-coded output
- Add --extend flag to open browser for key renewal
- Update .gitignore for compiled binaries
- Update README with key command documentation
This commit is contained in:
Russell Ballestrini 2025-12-27 11:50:34 -05:00
parent eb5d4ca8bf
commit 5380af54cb
32 changed files with 3140 additions and 70 deletions

96
un.ml Normal file → Executable file
View file

@ -62,6 +62,9 @@ let green = "\x1b[32m"
let yellow = "\x1b[33m"
let reset = "\x1b[0m"
(* Portal base URL *)
let portal_base = "https://unsandbox.com"
(* Extension to language mapping *)
let ext_to_lang ext =
match ext with
@ -118,6 +121,23 @@ let curl_post api_key endpoint json =
let _ = Unix.close_process_in ic in
output
let portal_curl_post api_key endpoint json =
let tmp_file = Printf.sprintf "/tmp/un_ocaml_%d.json" (Random.int 999999) in
let oc = open_out tmp_file in
output_string oc json;
close_out oc;
let cmd = Printf.sprintf "curl -s -X POST %s%s -H 'Content-Type: application/json' -H 'Authorization: Bearer %s' -d @%s"
portal_base endpoint api_key tmp_file in
let ic = Unix.open_process_in cmd in
let rec read_all acc =
try let line = input_line ic in read_all (acc ^ line ^ "\n")
with End_of_file -> acc
in
let output = read_all "" in
let _ = Unix.close_process_in ic in
Sys.remove tmp_file;
output
let curl_get api_key endpoint =
let cmd = Printf.sprintf "curl -s https://api.unsandbox.com%s -H 'Authorization: Bearer %s'"
endpoint api_key in
@ -147,6 +167,31 @@ let curl_delete api_key endpoint =
let _ = Unix.close_process_in ic in
output
(* Extract JSON value - simple regex-based parser *)
let extract_json_value json_str key =
let pattern = "\"" ^ key ^ "\"\\s*:\\s*\"\\([^\"]*\\)\"" in
let regex = Str.regexp pattern in
try
let _ = Str.search_forward regex json_str 0 in
Some (Str.matched_group 1 json_str)
with Not_found -> None
(* Open browser *)
let open_browser url =
Printf.printf "%sOpening browser: %s%s\n" blue url reset;
let _ = match Sys.os_type with
| "Unix" | "Cygwin" ->
(* Try xdg-open for Linux *)
(try Sys.command (Printf.sprintf "xdg-open '%s' 2>/dev/null" url)
with _ ->
(* Fallback to open for macOS *)
try Sys.command (Printf.sprintf "open '%s' 2>/dev/null" url)
with _ -> 1)
| "Win32" ->
Sys.command (Printf.sprintf "start '%s'" url)
| _ -> 1
in ()
(* Parse JSON response for stdout/stderr/exit_code *)
let extract_field field json =
try
@ -226,6 +271,53 @@ let execute_command file env_vars artifacts out_dir network vcpu =
in
exit exit_code
(* Display key info *)
let display_key_info response extend =
let status = extract_json_value response "status" in
let public_key = extract_json_value response "public_key" in
let tier = extract_json_value response "tier" in
let expires_at = extract_json_value response "expires_at" in
match status with
| Some "valid" ->
Printf.printf "%sValid%s\n" green reset;
(match public_key with Some pk -> Printf.printf "Public Key: %s\n" pk | None -> ());
(match tier with Some t -> Printf.printf "Tier: %s\n" t | None -> ());
(match expires_at with Some exp -> Printf.printf "Expires: %s\n" exp | None -> ());
if extend then
(match public_key with
| Some pk -> open_browser (Printf.sprintf "%s/keys/extend?pk=%s" portal_base pk)
| None -> ())
| Some "expired" ->
Printf.printf "%sExpired%s\n" red reset;
(match public_key with Some pk -> Printf.printf "Public Key: %s\n" pk | None -> ());
(match tier with Some t -> Printf.printf "Tier: %s\n" t | None -> ());
(match expires_at with Some exp -> Printf.printf "Expired: %s\n" exp | None -> ());
Printf.printf "%sTo renew: Visit %s/keys/extend%s\n" yellow portal_base reset;
if extend then
(match public_key with
| Some pk -> open_browser (Printf.sprintf "%s/keys/extend?pk=%s" portal_base pk)
| None -> ())
| Some "invalid" ->
Printf.printf "%sInvalid%s\n" red reset
| Some s ->
Printf.printf "%sUnknown status: %s%s\n" red s reset;
Printf.printf "%s\n" response
| None ->
Printf.printf "%sError: Could not parse response%s\n" red reset;
Printf.printf "%s\n" response
(* Validate key command *)
let validate_key api_key extend =
let json = "{}" in
let response = portal_curl_post api_key "/keys/validate" json in
display_key_info response extend
(* Key command *)
let key_command extend =
let api_key = get_api_key () in
validate_key api_key extend
(* Session command *)
let session_command action shell network vcpu =
let api_key = get_api_key () in
@ -364,7 +456,11 @@ let () =
Printf.printf "Usage: un.ml [options] <source_file>\n";
Printf.printf " un.ml session [options]\n";
Printf.printf " un.ml service [options]\n";
Printf.printf " un.ml key [--extend]\n";
exit 1
| "key" :: rest ->
let extend = List.mem "--extend" rest in
key_command extend
| "session" :: rest ->
let rec parse_session action shell network vcpu = function
| [] -> session_command action shell network vcpu