Something went wrong. Try again.
zig library for building requests to query inference providers usage limits
Something went wrong. Try again.
4.9 kB · 127 lines
Zig
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128//! OpenCode Go usage feed implementation.//!//! Mirrors prime-agent:packages/ai/src/utils/usage/providers/opencode-go.ts field for field.const std = @import("std");const usage = @import("../usage.zig");const iso8601 = @import("../iso8601.zig");
pub const OPENCODE_GO_USAGE_URL = "https://opencode.ai/zen/go/v1/usage";
const WindowDef = struct { key: []const u8, label: []const u8, windowLabel: []const u8, windowSeconds: i64,};
const OPENCODE_WINDOWS = [_]WindowDef{ .{ .key = "rolling", .label = "Session", .windowLabel = "5h window", .windowSeconds = 5 * 3600 }, .{ .key = "weekly", .label = "Weekly", .windowLabel = "7d window", .windowSeconds = 7 * 86_400 }, .{ .key = "monthly", .label = "Monthly", .windowLabel = "30d window", .windowSeconds = 30 * 86_400 },};
pub fn parseOpenCodeGoUsage(alloc: std.mem.Allocator, payload: ?std.json.Value) ![]const usage.UsageLimit { const root = usage.asObject(payload); const usage_obj = if (root) |r| usage.asObject(r.get("usage")) else null; if (usage_obj == null) return &[_]usage.UsageLimit{};
var limits = std.ArrayList(usage.UsageLimit).empty;
for (OPENCODE_WINDOWS) |win| { const raw_window = usage.asObject(usage_obj.?.get(win.key)) orelse continue;
const used_percent = usage.asNumber(raw_window.get("percent"));
const resets_at_str = usage.asString(raw_window.get("resetsAt")); const resets_at: ?i64 = if (resets_at_str) |s| iso8601.parseIso8601(s) else null;
const raw_status = usage.asString(raw_window.get("status")); const is_rate_limited = if (raw_status) |rs| blk: { const lower = try alloc.alloc(u8, rs.len); _ = std.ascii.lowerString(lower, rs); break :blk std.mem.eql(u8, lower, "rate-limited") or std.mem.eql(u8, lower, "exhausted"); } else false;
const status: []const u8 = if (is_rate_limited or (used_percent != null and used_percent.? >= 100.0)) "exhausted" else usage.statusFor(used_percent);
try limits.append(alloc, .{ .id = win.key, .label = win.label, .usedPercent = used_percent, .windowLabel = win.windowLabel, .windowSeconds = win.windowSeconds, .resetsAt = resets_at, .status = status, }); }
return limits.items;}
pub fn advance( alloc: std.mem.Allocator, credential_json: []const u8, responses_json: []const u8, _now_ms: i64,) !usage.Outcome { _ = _now_ms; const cred_parsed = std.json.parseFromSlice(std.json.Value, alloc, credential_json, .{}) catch { return .{ .report = .{ .error_message = "invalid credential JSON" } }; }; const cred_root = usage.asObject(cred_parsed.value) orelse { return .{ .report = .{ .error_message = "invalid credential JSON" } }; }; const kind = usage.asString(cred_root.get("kind")) orelse ""; if (!std.mem.eql(u8, kind, "apiKey")) { return .{ .report = .{ .error_message = "opencode-go needs an apiKey credential" } }; }
const api_key = usage.asString(cred_root.get("apiKey")) orelse ""; const cred_account_id = usage.asString(cred_root.get("accountId")); const cred_email = usage.asString(cred_root.get("email"));
const resp_parsed = std.json.parseFromSlice(std.json.Value, alloc, responses_json, .{}) catch { return .{ .report = .{ .error_message = "invalid responses JSON" } }; }; const resp_array = usage.asArray(resp_parsed.value) orelse { return .{ .report = .{ .error_message = "invalid responses JSON" } }; };
if (resp_array.items.len == 0) { var headers = std.ArrayList([2][]const u8).empty; const auth_hdr = try std.fmt.allocPrint(alloc, "Bearer {s}", .{api_key}); try headers.append(alloc, .{ "Authorization", auth_hdr }); try headers.append(alloc, .{ "Accept", "application/json" }); try headers.append(alloc, .{ "User-Agent", "OpenCode-Status-Plugin/1.0" });
const requests = try alloc.alloc(usage.UsageRequest, 1); requests[0] = .{ .method = "GET", .url = OPENCODE_GO_USAGE_URL, .headers = headers.items, }; return .{ .requests = requests }; }
const first = switch (try usage.parseFirstResponse(alloc, resp_array, "usage body is not JSON")) { .ok => |f| f, .err => |msg| return .{ .report = .{ .error_message = msg } }, }; const body_parsed = first.parsed;
const limits = try parseOpenCodeGoUsage(alloc, body_parsed.value);
return .{ .report = .{ .planType = "Go", .accountId = cred_account_id, .email = cred_email, .limits = limits, .notes = &[_][]const u8{"OpenCode Go unified models"}, .error_message = null, }, };}