@narumitw/pi-usage 0.60.6 → 0.60.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.ts +104 -363
- package/dist/index.ts.map +2 -2
- package/docs/providers.md +2 -1
- package/package.json +73 -74
- package/src/codex-fast-runtime.ts +148 -184
- package/src/codex-fast.ts +74 -83
- package/src/codex-resets.ts +249 -278
- package/src/core.ts +204 -206
- package/src/format.ts +519 -574
- package/src/index.ts +77 -77
- package/src/oauth-credential-source.ts +57 -65
- package/src/providers/baseten.ts +32 -36
- package/src/providers/codex.ts +109 -120
- package/src/providers/deepseek.ts +59 -64
- package/src/providers/fireworks.ts +219 -238
- package/src/providers/github-copilot.ts +89 -95
- package/src/providers/kimi-coding.ts +202 -213
- package/src/providers/minimax.ts +214 -219
- package/src/providers/moonshot.ts +41 -46
- package/src/providers/opencode-zen.ts +56 -59
- package/src/providers/openrouter.ts +50 -53
- package/src/providers/vercel-ai-gateway.ts +33 -33
- package/src/providers/xai.ts +141 -148
- package/src/providers/zai-errors.ts +75 -75
- package/src/providers/zai.ts +173 -189
- package/src/query.ts +887 -967
- package/src/settings.ts +275 -304
- package/src/types.ts +145 -145
- package/src/usage-helpers.ts +18 -18
- package/src/usage-settings-ui.ts +118 -145
- package/src/usage-targets.ts +98 -114
- package/src/usage.ts +1264 -1426
|
@@ -2,119 +2,113 @@ import { sanitizeDisplayText } from "../core.js";
|
|
|
2
2
|
import type { GitHubCopilotUsagePayload, UsageBucket, UsageReport } from "../types.js";
|
|
3
3
|
|
|
4
4
|
export function normalizeGitHubCopilotUsagePayload(
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
payload: GitHubCopilotUsagePayload,
|
|
6
|
+
capturedAt: number,
|
|
7
7
|
): UsageReport {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
const snapshots = asObject(payload.quota_snapshots);
|
|
9
|
+
const premium = asObject(snapshots?.premium_interactions);
|
|
10
|
+
const metrics: UsageReport["metrics"] = [];
|
|
11
|
+
let semanticsLabel: string;
|
|
12
|
+
let bucket: UsageBucket;
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
? "GitHub Copilot AI Credits allowance"
|
|
20
|
-
: "GitHub Copilot premium request quota";
|
|
14
|
+
if (premium) {
|
|
15
|
+
const tokenBasedBilling = premium.token_based_billing === true;
|
|
16
|
+
const id = tokenBasedBilling ? "ai-credits" : "premium-requests";
|
|
17
|
+
const label = tokenBasedBilling ? "AI credits" : "Premium requests";
|
|
18
|
+
semanticsLabel = tokenBasedBilling ? "GitHub Copilot AI Credits allowance" : "GitHub Copilot premium request quota";
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
period: "monthly",
|
|
71
|
-
...resetTimestamp(payload),
|
|
72
|
-
};
|
|
73
|
-
}
|
|
20
|
+
if (premium.unlimited === true) {
|
|
21
|
+
bucket = { id, label, unit: "count" };
|
|
22
|
+
} else {
|
|
23
|
+
const entitlement = asNonnegativeNumber(premium.entitlement);
|
|
24
|
+
const rawRemaining = asFiniteNumber(premium.remaining) ?? asFiniteNumber(premium.quota_remaining);
|
|
25
|
+
if (entitlement === undefined || rawRemaining === undefined) {
|
|
26
|
+
throw new Error(`GitHub Copilot ${label.toLowerCase()} quota was incomplete.`);
|
|
27
|
+
}
|
|
28
|
+
const overageUsed = Math.max(asNonnegativeNumber(premium.overage_count) ?? 0, Math.max(0, -rawRemaining));
|
|
29
|
+
if (overageUsed > 0) {
|
|
30
|
+
metrics.push({
|
|
31
|
+
id: "overage-used",
|
|
32
|
+
label: "Additional usage",
|
|
33
|
+
value: overageUsed,
|
|
34
|
+
unit: "count",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
bucket = {
|
|
38
|
+
id,
|
|
39
|
+
label,
|
|
40
|
+
used: asNonnegativeNumber(premium.credits_used) ?? Math.max(0, entitlement - rawRemaining),
|
|
41
|
+
remaining: Math.max(0, rawRemaining),
|
|
42
|
+
limit: entitlement,
|
|
43
|
+
unit: "count",
|
|
44
|
+
period: "monthly",
|
|
45
|
+
...resetTimestamp(payload),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
const limited = asObject(payload.limited_user_quotas);
|
|
50
|
+
const monthly = asObject(payload.monthly_quotas);
|
|
51
|
+
const remaining = asNonnegativeNumber(limited?.chat);
|
|
52
|
+
const entitlement = asNonnegativeNumber(monthly?.chat);
|
|
53
|
+
if (remaining === undefined || entitlement === undefined) {
|
|
54
|
+
throw new Error("GitHub Copilot usage response contained no supported quota.");
|
|
55
|
+
}
|
|
56
|
+
semanticsLabel = "GitHub Copilot Free chat quota";
|
|
57
|
+
bucket = {
|
|
58
|
+
id: "chat-requests",
|
|
59
|
+
label: "Chat requests",
|
|
60
|
+
used: Math.max(0, entitlement - remaining),
|
|
61
|
+
remaining,
|
|
62
|
+
limit: entitlement,
|
|
63
|
+
unit: "count",
|
|
64
|
+
period: "monthly",
|
|
65
|
+
...resetTimestamp(payload),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
74
68
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
const notes: string[] = [];
|
|
70
|
+
const plan = asString(payload.copilot_plan) ?? asString(payload.access_type_sku);
|
|
71
|
+
if (plan) notes.push(`Plan: ${plan}`);
|
|
78
72
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
73
|
+
return {
|
|
74
|
+
providerId: "github-copilot",
|
|
75
|
+
providerName: "GitHub Copilot",
|
|
76
|
+
capturedAt,
|
|
77
|
+
source: "github-copilot-user",
|
|
78
|
+
semantics: { kind: "consumer-subscription", label: semanticsLabel },
|
|
79
|
+
accountLabel: asString(payload.login),
|
|
80
|
+
buckets: [bucket],
|
|
81
|
+
metrics,
|
|
82
|
+
...(notes.length > 0 ? { notes } : {}),
|
|
83
|
+
};
|
|
90
84
|
}
|
|
91
85
|
|
|
92
86
|
function resetTimestamp(payload: GitHubCopilotUsagePayload): { resetsAt?: number } {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
87
|
+
const raw =
|
|
88
|
+
asString(payload.quota_reset_date_utc) ??
|
|
89
|
+
asString(payload.quota_reset_date) ??
|
|
90
|
+
asString(payload.limited_user_reset_date);
|
|
91
|
+
if (!raw) return {};
|
|
92
|
+
const milliseconds = Date.parse(raw);
|
|
93
|
+
return Number.isNaN(milliseconds) ? {} : { resetsAt: Math.floor(milliseconds / 1000) };
|
|
100
94
|
}
|
|
101
95
|
|
|
102
96
|
function asObject(value: unknown): Record<string, unknown> | undefined {
|
|
103
|
-
|
|
104
|
-
|
|
97
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
|
|
98
|
+
return value as Record<string, unknown>;
|
|
105
99
|
}
|
|
106
100
|
|
|
107
101
|
function asString(value: unknown): string | undefined {
|
|
108
|
-
|
|
109
|
-
|
|
102
|
+
if (typeof value !== "string") return undefined;
|
|
103
|
+
return sanitizeDisplayText(value, 80) || undefined;
|
|
110
104
|
}
|
|
111
105
|
|
|
112
106
|
function asFiniteNumber(value: unknown): number | undefined {
|
|
113
|
-
|
|
114
|
-
|
|
107
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
|
|
108
|
+
return value;
|
|
115
109
|
}
|
|
116
110
|
|
|
117
111
|
function asNonnegativeNumber(value: unknown): number | undefined {
|
|
118
|
-
|
|
119
|
-
|
|
112
|
+
const number = asFiniteNumber(value);
|
|
113
|
+
return number === undefined || number < 0 ? undefined : number;
|
|
120
114
|
}
|