repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
nushell/modules/kimi.nu
Raw# Kimi Code / Moonshot AI integration.
# Set KIMI_API_KEY in secrets.nuon.
# Override base URL with KIMI_API_BASE (default: https://api.kimi.com/coding/v1).
export def main [] {
print "Kimi Code / Moonshot AI integration"
print " kimi usage — check subscription quota"
print " kimi chat <message> — send a chat completion"
print " kimi models — list available models"
print ""
print "Run a subcommand with --help for details."
}
# ── Usage ─────────────────────────────────────────────────────────────────────
# `kimi usage` — check Kimi Code subscription quota and usage.
export def usage [] {
let token = get-token
let base = get-base
let hs = {
Authorization: $'Bearer ($token)'
Accept: "application/json"
}
let res = try {
http get --headers $hs $"($base)/usages"
} catch { |e|
error make {
msg: "Failed to fetch usage"
label: { text: "Check KIMI_API_KEY and network connection" }
}
}
let c = (ansi c)
let g = (ansi g)
let y = (ansi y)
let r = (ansi r)
let d = (ansi d)
let e = (ansi rst)
print $"($c)KIMI CODE USAGE($e)"
print ""
# ── weekly / main usage ──
let usage = $res | get --optional usage | default {}
let limit = $usage | get --optional limit | default "0"
let used = $usage | get --optional used | default "0"
let remain = $usage | get --optional remaining | default "0"
let reset = $usage | get --optional resetTime | default ""
if ($limit | into int) > 0 {
let pct = ($remain | into int) * 100 // ($limit | into int)
let bar = bar $pct
let color = if $pct <= 10 { $r } else if $pct <= 30 { $y } else { $g }
let reset_hint = if $reset != "" { $" ($d)resets ($reset)($e)" } else { "" }
print $" ($c)Weekly Quota($e)"
print $" ($bar) ($color)($remain)/($limit) ($pct)% left($e)($reset_hint)"
print ""
}
# ── total quota ──
let total_quota = $res | get --optional totalQuota | default {}
let tq_limit = $total_quota | get --optional limit | default "0"
let tq_remain = $total_quota | get --optional remaining | default "0"
if ($tq_limit | into int) > 0 {
print $" ($c)Total Quota($e) ($tq_remain)/($tq_limit) remaining"
print ""
}
# ── windowed limits ──
let limits = $res | get --optional limits | default []
if ($limits | length) > 0 {
print $" ($c)Rate Limits($e)"
for item in $limits {
let window = $item | get --optional window | default {}
let detail = $item | get --optional detail | default {}
let w_dur = $window | get --optional duration | default 0
let w_unit = $window | get --optional timeUnit | default ""
let d_limit = $detail | get --optional limit | default "0"
let d_used = $detail | get --optional used | default "0"
let d_remain = $detail | get --optional remaining | default "0"
let label = if ($w_unit | str contains "MINUTE") and $w_dur >= 60 and ($w_dur mod 60) == 0 {
$"($w_dur / 60)h limit"
} else if ($w_unit | str contains "MINUTE") {
$"($w_dur)m limit"
} else if ($w_unit | str contains "HOUR") {
$"($w_dur)h limit"
} else if ($w_unit | str contains "DAY") {
$"($w_dur)d limit"
} else {
"Rate limit"
}
let pct = if ($d_limit | into int) > 0 {
($d_remain | into int) * 100 // ($d_limit | into int)
} else { 0 }
let bar = bar $pct
print $" ($label) ($bar) ($d_remain)/($d_limit)"
}
print ""
}
# ── parallel / concurrency ──
let parallel = $res | get --optional parallel | default {}
let p_limit = $parallel | get --optional limit | default "0"
if ($p_limit | into int) > 0 {
print $" ($c)Concurrency($e) max ($p_limit) parallel requests"
print ""
}
}
def bar [pct: int] {
let n = ($pct / 10 | math round | into int)
let n = if $n > 10 { 10 } else if $n < 0 { 0 } else { $n }
let g = (ansi g)
let d = (ansi d)
let y = (ansi y)
let r = (ansi r)
let e = (ansi rst)
let color = if $pct < 50 { $g } else if $pct < 80 { $y } else { $r }
let filled = 1..$n | each { $"($g)▓" } | str join
let empty = 1..(10 - $n) | each { $"($d)░" } | str join
$"($filled)($empty)($e)"
}
# ── Private helpers ───────────────────────────────────────────────────────────
def get-token [] {
let token = $env | get --optional KIMI_API_KEY
if ($token | is-empty) {
error make {
msg: "KIMI_API_KEY is not set"
label: { text: "Set KIMI_API_KEY in secrets.nuon" }
}
}
$token
}
def get-base [] {
$env | get --optional KIMI_API_BASE | default "https://api.kimi.com/coding/v1"
}
def headers [] {
{
Authorization: $'Bearer (get-token)'
Content-Type: "application/json"
Accept: "application/json"
}
}
# ── Chat ──────────────────────────────────────────────────────────────────────
# `kimi chat` — send a chat completion to kimi-for-coding.
#
# # Parameters
# `message` # The user message (required)
# `--system` # Optional system prompt
export def chat [
message: string
--system (-s): string = ""
] {
if ($message | str trim | is-empty) {
error make {
msg: "Message cannot be empty"
label: { text: "Provide a non-empty message" }
}
}
let base = get-base
let hs = headers
mut messages = []
if ($system | str trim | is-not-empty) {
$messages = $messages | append { role: "system", content: $system }
}
$messages = $messages | append { role: "user", content: $message }
let payload = {
model: "kimi-for-coding"
messages: $messages
}
let resp = try {
http post --headers $hs $"($base)/chat/completions" ($payload | to json)
} catch { |e|
let raw = $e.raw | default ""
if ($raw | str contains "401") {
error make {
msg: "Authentication failed (401)"
label: { text: "Check KIMI_API_KEY is correct and active" }
}
} else if ($raw | str contains "403") {
error make {
msg: "Access forbidden (403)"
label: { text: "Kimi Code API key may be restricted. Ensure subscription includes API access and key is active at https://www.kimi.com/code/console" }
}
} else if ($raw | str contains "429") {
error make {
msg: "Rate limited (429)"
label: { text: "Too many requests — wait and retry" }
}
}
error make {
msg: "Chat request failed"
label: { text: ($e.msg | default "Check network and API base URL") }
}
}
let choice = $resp | get --optional choices | default [] | get 0 | default {}
let content = $choice | get --optional message.content | default ""
let finish = $choice | get --optional finish_reason | default ""
print $content
if $finish != "stop" and ($finish | is-not-empty) {
print $"(ansi d)[finish_reason: ($finish)](ansi rst)"
}
}
# ── Models ────────────────────────────────────────────────────────────────────
# `kimi models` — list models available on the current endpoint.
export def models [] {
let base = get-base
let hs = headers
let res = try {
http get --headers $hs $"($base)/models"
} catch { |e|
error make {
msg: "Failed to list models"
label: { text: "Check KIMI_API_KEY and KIMI_API_BASE" }
}
}
$res.data | each { |m|
{
id: $m.id
display_name: ($m | get --optional display_name | default "")
context: ($m | get --optional context_length | default 0)
}
} | table -e
}