secrets-import: add "grok" entry + import-from-grok! (add-grok phase 5)
ober
9a51e93c07d5f9fbcb6669ed4190d5025b67f159
--- a/src/jcode/core/secrets-import.ss +++ b/src/jcode/core/secrets-import.ss @@ -20,12 +20,14 @@ import-from-claude-code! import-from-aider! import-from-env! + import-from-grok! import-prompt-missing!) (import :std/text/json :std/misc/string :std/os/path :jcode/core/secrets + :jcode/core/grok-auth :jcode/core/log :jerboa/core :jerboa/runtime) @@ -40,6 +42,10 @@ ("openrouter" . "OPENROUTER_API_KEY") ("deepseek" . "DEEPSEEK_API_KEY") ("xai" . "XAI_API_KEY") + ;; "grok" is the Grok CLI session-token provider. Its preferred env var is + ;; GROK_CODE_XAI_API_KEY so import-from-env! does not collide with xai's + ;; XAI_API_KEY; runtime lookup in config.ss accepts both. + ("grok" . "GROK_CODE_XAI_API_KEY") ("groq" . "GROQ_API_KEY") ("mistral" . "MISTRAL_API_KEY") ("together" . "TOGETHER_API_KEY") @@ -168,6 +174,37 @@ (log-info logger "aider-import" `((count . ,added) (path . ,path))) added))))) +;;; ---- ~/.grok session token ---- + +(def (import-from-grok!) + ;; Best-effort import of the Grok CLI bearer token from ~/.grok/auth.json + ;; into the encrypted store under "grok". Only the current `key` is + ;; written — refresh_token / email / user_id / principal_id stay in + ;; ~/.grok and are never logged. Returns the count imported (0 or 1). + ;; + ;; Surface a clear "session token" disclaimer so the user knows this is + ;; NOT a durable API key: Grok tokens expire (default ~6h) and the CLI + ;; hot-reloads auth.json on `grok login`. Runtime ~/.grok lookup remains + ;; the primary path (config-get-provider-key); explicit `keys import grok` + ;; is for users who prefer a single source of truth. + (let ((tok (grok-auth-token))) + (cond + ((not tok) + (display " No usable token in ~/.grok/auth.json (run `grok login`)." + (current-error-port)) + (newline (current-error-port)) + 0) + (else + (secret-store-set! "grok" tok) + (display " Imported Grok CLI session token into the encrypted store." + (current-error-port)) + (newline (current-error-port)) + (display " Note: Grok tokens expire — re-run `grok login` and `jcode keys import grok` when 401s appear." + (current-error-port)) + (newline (current-error-port)) + (log-info logger "grok-import" '((count . 1))) + 1)))) + ;;; ---- env vars ---- (def (import-from-env!) --- a/test/run.ss +++ b/test/run.ss @@ -6,6 +6,7 @@ (jcode core message) (jcode core grok-auth) (jcode core config) + (jcode core secrets-import) (jcode provider provider) (jcode tool registry) (jcode tool file) @@ -1767,6 +1768,21 @@ (grok-list-models (make-provider "grok" "" "grok-build" "https://x/v1")) (lambda (ms) (assoc "grok-build" ms))) +;; ── secrets-import: grok known-providers entry ──────────────────── +;; *known-providers* (secrets-import) is the single-env-var-per-provider +;; mapping used by import-from-env! / aider import / interactive prompts. +;; For "grok" we pick GROK_CODE_XAI_API_KEY so it does not duplicate xai's +;; XAI_API_KEY entry; runtime config-get-provider-key accepts BOTH names. + +(section "=== secrets-import: grok ===") + +(check! "*known-providers* maps grok → GROK_CODE_XAI_API_KEY" + (cdr (assoc "grok" *known-providers*)) "GROK_CODE_XAI_API_KEY") +(check! "*known-providers* still maps xai → XAI_API_KEY" + (cdr (assoc "xai" *known-providers*)) "XAI_API_KEY") +(check-pred! "*known-providers* still contains anthropic" + *known-providers* (lambda (l) (assoc "anthropic" l))) + ;; ── Results ─────────────────────────────────────────────────────── (printf "~n~a passed, ~a failed~n" pass-count fail-count)