@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.
@@ -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
- payload: GitHubCopilotUsagePayload,
6
- capturedAt: number,
5
+ payload: GitHubCopilotUsagePayload,
6
+ capturedAt: number,
7
7
  ): UsageReport {
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;
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
- 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
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
- if (premium.unlimited === true) {
23
- bucket = { id, label, unit: "count" };
24
- } else {
25
- const entitlement = asNonnegativeNumber(premium.entitlement);
26
- const rawRemaining =
27
- asFiniteNumber(premium.remaining) ?? asFiniteNumber(premium.quota_remaining);
28
- if (entitlement === undefined || rawRemaining === undefined) {
29
- throw new Error(`GitHub Copilot ${label.toLowerCase()} quota was incomplete.`);
30
- }
31
- const overageUsed = Math.max(
32
- asNonnegativeNumber(premium.overage_count) ?? 0,
33
- Math.max(0, -rawRemaining),
34
- );
35
- if (overageUsed > 0) {
36
- metrics.push({
37
- id: "overage-used",
38
- label: "Additional usage",
39
- value: overageUsed,
40
- unit: "count",
41
- });
42
- }
43
- bucket = {
44
- id,
45
- label,
46
- used: asNonnegativeNumber(premium.credits_used) ?? Math.max(0, entitlement - rawRemaining),
47
- remaining: Math.max(0, rawRemaining),
48
- limit: entitlement,
49
- unit: "count",
50
- period: "monthly",
51
- ...resetTimestamp(payload),
52
- };
53
- }
54
- } else {
55
- const limited = asObject(payload.limited_user_quotas);
56
- const monthly = asObject(payload.monthly_quotas);
57
- const remaining = asNonnegativeNumber(limited?.chat);
58
- const entitlement = asNonnegativeNumber(monthly?.chat);
59
- if (remaining === undefined || entitlement === undefined) {
60
- throw new Error("GitHub Copilot usage response contained no supported quota.");
61
- }
62
- semanticsLabel = "GitHub Copilot Free chat quota";
63
- bucket = {
64
- id: "chat-requests",
65
- label: "Chat requests",
66
- used: Math.max(0, entitlement - remaining),
67
- remaining,
68
- limit: entitlement,
69
- unit: "count",
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
- const notes: string[] = [];
76
- const plan = asString(payload.copilot_plan) ?? asString(payload.access_type_sku);
77
- if (plan) notes.push(`Plan: ${plan}`);
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
- return {
80
- providerId: "github-copilot",
81
- providerName: "GitHub Copilot",
82
- capturedAt,
83
- source: "github-copilot-user",
84
- semantics: { kind: "consumer-subscription", label: semanticsLabel },
85
- accountLabel: asString(payload.login),
86
- buckets: [bucket],
87
- metrics,
88
- ...(notes.length > 0 ? { notes } : {}),
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
- const raw =
94
- asString(payload.quota_reset_date_utc) ??
95
- asString(payload.quota_reset_date) ??
96
- asString(payload.limited_user_reset_date);
97
- if (!raw) return {};
98
- const milliseconds = Date.parse(raw);
99
- return Number.isNaN(milliseconds) ? {} : { resetsAt: Math.floor(milliseconds / 1000) };
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
- if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
104
- return value as Record<string, unknown>;
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
- if (typeof value !== "string") return undefined;
109
- return sanitizeDisplayText(value, 80) || undefined;
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
- if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
114
- return value;
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
- const number = asFiniteNumber(value);
119
- return number === undefined || number < 0 ? undefined : number;
112
+ const number = asFiniteNumber(value);
113
+ return number === undefined || number < 0 ? undefined : number;
120
114
  }