@howaboua/opencode-usage-plugin 0.0.1 → 0.0.3
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/hooks/proxy.d.ts +2 -2
- package/dist/hooks/proxy.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -7
- package/dist/providers/proxy/config.d.ts.map +1 -1
- package/dist/providers/proxy/config.js +4 -1
- package/dist/providers/proxy/format.d.ts.map +1 -1
- package/dist/providers/proxy/format.js +30 -11
- package/dist/providers/proxy/index.d.ts.map +1 -1
- package/dist/providers/proxy/index.js +66 -23
- package/dist/providers/proxy/types.d.ts +96 -77
- package/dist/providers/proxy/types.d.ts.map +1 -1
- package/dist/ui/status.d.ts.map +1 -1
- package/dist/ui/status.js +33 -13
- package/package.json +1 -1
- package/dist/tools/index.d.ts +0 -3
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js +0 -2
- package/dist/tools/proxy-limits.d.ts +0 -16
- package/dist/tools/proxy-limits.d.ts.map +0 -1
- package/dist/tools/proxy-limits.js +0 -33
- package/dist/tools/usage.d.ts +0 -10
- package/dist/tools/usage.d.ts.map +0 -1
- package/dist/tools/usage.js +0 -12
package/dist/hooks/proxy.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Hooks for
|
|
3
|
-
* Manages silent responses after
|
|
2
|
+
* Hooks for usage status display.
|
|
3
|
+
* Manages silent responses after command execution if needed.
|
|
4
4
|
*/
|
|
5
5
|
export declare function markSilent(sessionID: string, messageID: string): void;
|
|
6
6
|
export declare function proxyHooks(): {
|
package/dist/hooks/proxy.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Hooks for
|
|
3
|
-
* Manages silent responses after
|
|
2
|
+
* Hooks for usage status display.
|
|
3
|
+
* Manages silent responses after command execution if needed.
|
|
4
4
|
*/
|
|
5
5
|
const silence = new Map();
|
|
6
6
|
export function markSilent(sessionID, messageID) {
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAMjD,eAAO,MAAM,WAAW,EAAE,MA2CzB,CAAA;AAED,eAAe,WAAW,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Plugin entry point for Usage Tracking.
|
|
3
|
-
* Wires hooks
|
|
3
|
+
* Wires hooks for live usage snapshots.
|
|
4
4
|
*/
|
|
5
|
-
import { commandHooks, sessionHooks, proxyHooks
|
|
5
|
+
import { commandHooks, sessionHooks, proxyHooks } from "./hooks";
|
|
6
6
|
import { createUsageState } from "./state";
|
|
7
|
-
import { usageTool, createProxyLimitsTool } from "./tools";
|
|
8
7
|
import { loadAuths } from "./usage/fetch";
|
|
9
8
|
import { loadProxyConfig } from "./providers/proxy/config";
|
|
10
9
|
export const UsagePlugin = async ({ client }) => {
|
|
@@ -44,10 +43,6 @@ export const UsagePlugin = async ({ client }) => {
|
|
|
44
43
|
"command.execute.before": commandHookHandlers["command.execute.before"],
|
|
45
44
|
...sessionHooks(state),
|
|
46
45
|
...proxyHookHandlers,
|
|
47
|
-
tool: {
|
|
48
|
-
"usage.get": usageTool(),
|
|
49
|
-
"proxy-limits": createProxyLimitsTool(sendStatusMessage, markSilent),
|
|
50
|
-
},
|
|
51
46
|
};
|
|
52
47
|
};
|
|
53
48
|
export default UsagePlugin;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAI1C,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAI1C,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC,CAwD5D"}
|
|
@@ -38,7 +38,10 @@ export async function loadProxyConfig() {
|
|
|
38
38
|
}
|
|
39
39
|
try {
|
|
40
40
|
const content = await file.text();
|
|
41
|
-
|
|
41
|
+
// Remove comments first (both // and /* */)
|
|
42
|
+
const withoutComments = content.replace(/(\".*?\"|\'.*?\')|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g1) => g1 ?? "");
|
|
43
|
+
// Remove trailing commas before closing brackets/braces
|
|
44
|
+
const cleanJson = withoutComments.replace(/,(\s*[}\]])/g, "$1");
|
|
42
45
|
const config = JSON.parse(cleanJson);
|
|
43
46
|
if (!config.endpoint) {
|
|
44
47
|
throw new Error('Config must contain "endpoint" field');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/format.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/format.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAA8B,MAAM,SAAS,CAAA;AAsGxE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAkC7D"}
|
|
@@ -48,26 +48,44 @@ function aggregateCredentialsByTier(credentials) {
|
|
|
48
48
|
};
|
|
49
49
|
for (const cred of credentials) {
|
|
50
50
|
const tier = normalizeTier(cred.tier);
|
|
51
|
-
const
|
|
52
|
-
for (const [name,
|
|
51
|
+
const groupUsage = cred.group_usage ?? {};
|
|
52
|
+
for (const [name, groupData] of Object.entries(groupUsage)) {
|
|
53
53
|
if (!(name in GROUP_MAPPING))
|
|
54
54
|
continue;
|
|
55
55
|
const mappedName = GROUP_MAPPING[name];
|
|
56
|
+
// Find the best window from group_usage
|
|
57
|
+
const windows = groupData.windows || {};
|
|
58
|
+
let bestWindow = null;
|
|
59
|
+
// Priority order for windows
|
|
60
|
+
const windowPriority = ["daily", "5h", "1h", "15m"];
|
|
61
|
+
for (const windowName of windowPriority) {
|
|
62
|
+
if (windows[windowName]) {
|
|
63
|
+
bestWindow = windows[windowName];
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Fallback to any available window
|
|
68
|
+
if (!bestWindow && Object.keys(windows).length > 0) {
|
|
69
|
+
bestWindow = Object.values(windows)[0];
|
|
70
|
+
}
|
|
71
|
+
if (!bestWindow)
|
|
72
|
+
continue;
|
|
56
73
|
const existing = result[tier].get(mappedName);
|
|
57
74
|
if (existing) {
|
|
58
|
-
existing.remaining +=
|
|
59
|
-
existing.max +=
|
|
60
|
-
if (
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
existing.remaining += bestWindow.remaining;
|
|
76
|
+
existing.max += bestWindow.limit || 0;
|
|
77
|
+
if (bestWindow.reset_at) {
|
|
78
|
+
const newResetTime = new Date(bestWindow.reset_at * 1000).toISOString();
|
|
79
|
+
if (!existing.resetTime || new Date(newResetTime) > new Date(existing.resetTime)) {
|
|
80
|
+
existing.resetTime = newResetTime;
|
|
63
81
|
}
|
|
64
82
|
}
|
|
65
83
|
}
|
|
66
84
|
else {
|
|
67
85
|
result[tier].set(mappedName, {
|
|
68
|
-
remaining:
|
|
69
|
-
max:
|
|
70
|
-
resetTime:
|
|
86
|
+
remaining: bestWindow.remaining,
|
|
87
|
+
max: bestWindow.limit || bestWindow.remaining,
|
|
88
|
+
resetTime: bestWindow.reset_at ? new Date(bestWindow.reset_at * 1000).toISOString() : null,
|
|
71
89
|
});
|
|
72
90
|
}
|
|
73
91
|
}
|
|
@@ -84,7 +102,8 @@ export function formatProxyLimits(data) {
|
|
|
84
102
|
}
|
|
85
103
|
for (const [providerName, provider] of Object.entries(data.providers)) {
|
|
86
104
|
lines.push(`${providerName}:`);
|
|
87
|
-
const
|
|
105
|
+
const credentialsArray = Object.values(provider.credentials ?? {});
|
|
106
|
+
const tierData = aggregateCredentialsByTier(credentialsArray);
|
|
88
107
|
for (const [tierName, quotas] of Object.entries(tierData)) {
|
|
89
108
|
if (quotas.size === 0)
|
|
90
109
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAM5C,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAM5C,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AA+I5C,eAAO,MAAM,aAAa,EAAE,aAwB3B,CAAA"}
|
|
@@ -11,31 +11,70 @@ const GROUP_MAPPING = {
|
|
|
11
11
|
"claude": "claude",
|
|
12
12
|
"g3-pro": "g3-pro",
|
|
13
13
|
"g3-flash": "g3-fla",
|
|
14
|
+
"g25-flash": "25-flash",
|
|
15
|
+
"g25-lite": "25-lite",
|
|
14
16
|
"pro": "g3-pro",
|
|
15
|
-
"3-flash": "g3-fla"
|
|
17
|
+
"3-flash": "g3-fla",
|
|
18
|
+
"25-flash": "25-flash",
|
|
19
|
+
"25-lite": "25-lite"
|
|
16
20
|
};
|
|
17
21
|
function normalizeTier(tier) {
|
|
18
22
|
if (!tier)
|
|
19
23
|
return "free";
|
|
20
24
|
return tier.includes("free") ? "free" : "paid";
|
|
21
25
|
}
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Extract quota groups from group_usage data
|
|
28
|
+
* New API structure: group_usage[groupName].windows[windowName]
|
|
29
|
+
*/
|
|
30
|
+
function parseQuotaGroupsFromCredential(groupUsage) {
|
|
31
|
+
if (!groupUsage)
|
|
24
32
|
return [];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
const result = new Map();
|
|
34
|
+
for (const [groupName, groupData] of Object.entries(groupUsage)) {
|
|
35
|
+
const mappedName = GROUP_MAPPING[groupName];
|
|
36
|
+
if (!mappedName)
|
|
37
|
+
continue;
|
|
38
|
+
// Find the window with the best data (prefer daily, then 5h, then any)
|
|
39
|
+
const windows = groupData.windows || {};
|
|
40
|
+
let bestWindow = null;
|
|
41
|
+
// Priority order for windows
|
|
42
|
+
const windowPriority = ["daily", "5h", "1h", "15m"];
|
|
43
|
+
for (const windowName of windowPriority) {
|
|
44
|
+
if (windows[windowName]) {
|
|
45
|
+
bestWindow = windows[windowName];
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Fallback to any available window
|
|
50
|
+
if (!bestWindow && Object.keys(windows).length > 0) {
|
|
51
|
+
bestWindow = Object.values(windows)[0];
|
|
52
|
+
}
|
|
53
|
+
if (!bestWindow)
|
|
54
|
+
continue;
|
|
55
|
+
const existing = result.get(mappedName);
|
|
56
|
+
if (existing) {
|
|
57
|
+
existing.remaining += bestWindow.remaining;
|
|
58
|
+
existing.max += bestWindow.limit || 0;
|
|
59
|
+
// Use the latest reset time
|
|
60
|
+
if (bestWindow.reset_at) {
|
|
61
|
+
const newResetTime = new Date(bestWindow.reset_at * 1000).toISOString();
|
|
62
|
+
if (!existing.resetTime || new Date(newResetTime) > new Date(existing.resetTime)) {
|
|
63
|
+
existing.resetTime = newResetTime;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
result.set(mappedName, {
|
|
69
|
+
name: mappedName,
|
|
70
|
+
remaining: bestWindow.remaining,
|
|
71
|
+
max: bestWindow.limit || bestWindow.remaining,
|
|
72
|
+
remainingPct: bestWindow.limit ? Math.round((bestWindow.remaining / bestWindow.limit) * 100) : 0,
|
|
73
|
+
resetTime: bestWindow.reset_at ? new Date(bestWindow.reset_at * 1000).toISOString() : null,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return Array.from(result.values());
|
|
39
78
|
}
|
|
40
79
|
function aggregateByTier(credentials) {
|
|
41
80
|
const tiers = {
|
|
@@ -44,7 +83,7 @@ function aggregateByTier(credentials) {
|
|
|
44
83
|
};
|
|
45
84
|
for (const cred of credentials) {
|
|
46
85
|
const tier = normalizeTier(cred.tier);
|
|
47
|
-
const groups = parseQuotaGroupsFromCredential(cred.
|
|
86
|
+
const groups = parseQuotaGroupsFromCredential(cred.group_usage);
|
|
48
87
|
for (const group of groups) {
|
|
49
88
|
const existing = tiers[tier].get(group.name);
|
|
50
89
|
if (existing) {
|
|
@@ -76,13 +115,17 @@ function aggregateByTier(credentials) {
|
|
|
76
115
|
function parseProviders(data) {
|
|
77
116
|
if (!data.providers)
|
|
78
117
|
return [];
|
|
79
|
-
return Object.entries(data.providers).map(([name, provider]) =>
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
118
|
+
return Object.entries(data.providers).map(([name, provider]) => {
|
|
119
|
+
// Convert credentials object to array
|
|
120
|
+
const credentialsArray = Object.values(provider.credentials || {});
|
|
121
|
+
return {
|
|
122
|
+
name,
|
|
123
|
+
tiers: aggregateByTier(credentialsArray),
|
|
124
|
+
};
|
|
125
|
+
});
|
|
83
126
|
}
|
|
84
127
|
function parseProxyQuota(data) {
|
|
85
|
-
const summary = data.
|
|
128
|
+
const summary = data.summary;
|
|
86
129
|
return {
|
|
87
130
|
providers: parseProviders(data),
|
|
88
131
|
totalCredentials: summary?.total_credentials ?? 0,
|
|
@@ -13,96 +13,116 @@ export type ProxyConfig = {
|
|
|
13
13
|
};
|
|
14
14
|
/** Token statistics from the proxy */
|
|
15
15
|
export type TokenStats = {
|
|
16
|
-
input_cached
|
|
17
|
-
input_uncached
|
|
18
|
-
input_cache_pct
|
|
19
|
-
output
|
|
16
|
+
input_cached?: number;
|
|
17
|
+
input_uncached?: number;
|
|
18
|
+
input_cache_pct?: number;
|
|
19
|
+
output?: number;
|
|
20
|
+
prompt_tokens?: number;
|
|
21
|
+
completion_tokens?: number;
|
|
22
|
+
thinking_tokens?: number;
|
|
23
|
+
output_tokens?: number;
|
|
24
|
+
prompt_tokens_cache_read?: number;
|
|
25
|
+
prompt_tokens_cache_write?: number;
|
|
26
|
+
total_tokens?: number;
|
|
27
|
+
request_count?: number;
|
|
28
|
+
success_count?: number;
|
|
29
|
+
failure_count?: number;
|
|
30
|
+
approx_cost?: number;
|
|
20
31
|
};
|
|
21
|
-
/**
|
|
22
|
-
export type
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
/** Window-based quota information */
|
|
33
|
+
export type WindowQuota = {
|
|
34
|
+
limit?: number;
|
|
35
|
+
remaining: number;
|
|
36
|
+
reset_at?: number | null;
|
|
37
|
+
request_count?: number;
|
|
38
|
+
success_count?: number;
|
|
39
|
+
failure_count?: number;
|
|
40
|
+
total_used?: number;
|
|
41
|
+
total_remaining?: number;
|
|
42
|
+
total_max?: number;
|
|
43
|
+
remaining_pct?: number;
|
|
44
|
+
};
|
|
45
|
+
/** Model group usage information */
|
|
46
|
+
export type GroupUsageWindow = {
|
|
47
|
+
[windowName: string]: WindowQuota;
|
|
48
|
+
};
|
|
49
|
+
export type GroupUsage = {
|
|
50
|
+
windows: GroupUsageWindow;
|
|
51
|
+
totals: TokenStats;
|
|
52
|
+
fair_cycle_exhausted?: boolean;
|
|
53
|
+
fair_cycle_reason?: string | null;
|
|
54
|
+
cooldown_remaining?: number | null;
|
|
55
|
+
cooldown_source?: string | null;
|
|
56
|
+
custom_cap?: number | null;
|
|
57
|
+
};
|
|
58
|
+
/** Model usage information */
|
|
59
|
+
export type ModelUsage = {
|
|
60
|
+
windows: GroupUsageWindow;
|
|
61
|
+
totals: TokenStats;
|
|
62
|
+
};
|
|
63
|
+
/** Tier availability info */
|
|
64
|
+
export type TierAvailability = {
|
|
65
|
+
total: number;
|
|
66
|
+
available: number;
|
|
67
|
+
};
|
|
68
|
+
/** Tier window info */
|
|
69
|
+
export type TierWindow = {
|
|
70
|
+
total_used: number;
|
|
71
|
+
total_remaining: number;
|
|
72
|
+
total_max: number;
|
|
73
|
+
remaining_pct: number;
|
|
74
|
+
tier_availability: Record<string, TierAvailability>;
|
|
75
|
+
};
|
|
76
|
+
/** Model group tiers */
|
|
77
|
+
export type GroupTiers = {
|
|
78
|
+
[tierName: string]: {
|
|
29
79
|
priority: number;
|
|
30
80
|
total: number;
|
|
31
|
-
}
|
|
32
|
-
total_remaining_pct: number;
|
|
33
|
-
total_requests_max: number;
|
|
34
|
-
total_requests_remaining: number;
|
|
35
|
-
total_requests_used: number;
|
|
81
|
+
};
|
|
36
82
|
};
|
|
37
|
-
/**
|
|
38
|
-
export type
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
success_count: number;
|
|
42
|
-
failure_count: number;
|
|
43
|
-
prompt_tokens: number;
|
|
44
|
-
prompt_tokens_cached: number;
|
|
45
|
-
completion_tokens: number;
|
|
46
|
-
approx_cost: number;
|
|
47
|
-
window_start_ts: number | null;
|
|
48
|
-
quota_reset_ts: number | null;
|
|
49
|
-
baseline_remaining_fraction: number | null;
|
|
50
|
-
baseline_fetched_at: number | null;
|
|
51
|
-
quota_max_requests: number;
|
|
52
|
-
quota_display: string;
|
|
83
|
+
/** Fair cycle summary */
|
|
84
|
+
export type FairCycleSummary = {
|
|
85
|
+
exhausted_count: number;
|
|
86
|
+
total_count: number;
|
|
53
87
|
};
|
|
54
|
-
/** Model group
|
|
55
|
-
export type
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
requests_max: number;
|
|
62
|
-
requests_remaining: number;
|
|
63
|
-
requests_used: number;
|
|
64
|
-
reset_time_iso: string | null;
|
|
88
|
+
/** Model group aggregation */
|
|
89
|
+
export type ModelGroupAggregation = {
|
|
90
|
+
tiers: GroupTiers;
|
|
91
|
+
windows: {
|
|
92
|
+
[windowName: string]: TierWindow;
|
|
93
|
+
};
|
|
94
|
+
fair_cycle_summary: FairCycleSummary;
|
|
65
95
|
};
|
|
66
|
-
/** Credential information */
|
|
67
|
-
export type
|
|
68
|
-
|
|
96
|
+
/** Credential information from new API */
|
|
97
|
+
export type CredentialData = {
|
|
98
|
+
stable_id: string;
|
|
99
|
+
accessor_masked?: string;
|
|
69
100
|
full_path: string;
|
|
70
|
-
|
|
71
|
-
|
|
101
|
+
identifier: string;
|
|
102
|
+
email?: string | null;
|
|
72
103
|
tier?: string;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
models: Record<string, ModelQuota>;
|
|
82
|
-
model_groups?: Record<string, ModelGroup>;
|
|
104
|
+
priority?: number;
|
|
105
|
+
active_requests?: number;
|
|
106
|
+
status: string;
|
|
107
|
+
totals: TokenStats;
|
|
108
|
+
model_usage?: Record<string, ModelUsage>;
|
|
109
|
+
group_usage?: Record<string, GroupUsage>;
|
|
110
|
+
last_used_at?: number;
|
|
111
|
+
first_used_at?: number;
|
|
83
112
|
};
|
|
84
|
-
/** Provider information */
|
|
113
|
+
/** Provider information from new API */
|
|
85
114
|
export type Provider = {
|
|
115
|
+
provider: string;
|
|
86
116
|
credential_count: number;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
total_requests: number;
|
|
91
|
-
tokens: TokenStats;
|
|
92
|
-
approx_cost: number | null;
|
|
93
|
-
credentials: Credential[];
|
|
94
|
-
quota_groups?: Record<string, QuotaGroup>;
|
|
95
|
-
global?: {
|
|
96
|
-
approx_cost: number | null;
|
|
97
|
-
tokens: TokenStats;
|
|
98
|
-
total_requests: number;
|
|
99
|
-
};
|
|
117
|
+
rotation_mode?: string;
|
|
118
|
+
credentials: Record<string, CredentialData>;
|
|
119
|
+
quota_groups?: Record<string, ModelGroupAggregation>;
|
|
100
120
|
};
|
|
101
|
-
/** Summary statistics */
|
|
121
|
+
/** Summary statistics from new API */
|
|
102
122
|
export type Summary = {
|
|
103
|
-
total_providers
|
|
123
|
+
total_providers?: number;
|
|
104
124
|
total_credentials: number;
|
|
105
|
-
active_credentials
|
|
125
|
+
active_credentials: number;
|
|
106
126
|
exhausted_credentials?: number;
|
|
107
127
|
total_requests: number;
|
|
108
128
|
tokens: TokenStats;
|
|
@@ -112,7 +132,6 @@ export type Summary = {
|
|
|
112
132
|
export type ProxyResponse = {
|
|
113
133
|
providers: Record<string, Provider>;
|
|
114
134
|
summary: Summary;
|
|
115
|
-
global_summary?: Summary;
|
|
116
135
|
data_source: string;
|
|
117
136
|
timestamp: number;
|
|
118
137
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oEAAoE;AACpE,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE;QACV,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,KAAK,CAAC,EAAE,OAAO,CAAA;KAChB,CAAA;CACF,CAAA;AAED,sCAAsC;AACtC,MAAM,MAAM,UAAU,GAAG;IACvB,YAAY,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/types.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/status.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/ui/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C,KAAK,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;AAExC,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,UAAU,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/ui/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C,KAAK,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;AAExC,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,UAAU,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,OAAO,CAAC,IAAI,CAAC,CAwChB;AA0GD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,UAAU,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,aAAa,EAAE,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BhB"}
|
package/dist/ui/status.js
CHANGED
|
@@ -2,25 +2,45 @@
|
|
|
2
2
|
* Renders usage snapshots into readable status text.
|
|
3
3
|
*/
|
|
4
4
|
export async function sendStatusMessage(options) {
|
|
5
|
-
|
|
5
|
+
// 1. Send to Companion via Bus
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
const bus = options.client.bus;
|
|
8
|
+
if (bus) {
|
|
9
|
+
try {
|
|
10
|
+
await bus.publish({
|
|
11
|
+
topic: "companion.projection",
|
|
12
|
+
body: {
|
|
13
|
+
key: "usage",
|
|
14
|
+
kind: "markdown",
|
|
15
|
+
content: options.text,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
catch { }
|
|
20
|
+
}
|
|
21
|
+
// 2. Send plain message to TUI
|
|
22
|
+
await options.client.session
|
|
6
23
|
.prompt({
|
|
7
24
|
path: { id: options.sessionID },
|
|
8
25
|
body: {
|
|
9
26
|
noReply: true,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
27
|
+
parts: [
|
|
28
|
+
{
|
|
29
|
+
type: "text",
|
|
30
|
+
text: options.text,
|
|
31
|
+
ignored: true,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
13
34
|
},
|
|
14
35
|
})
|
|
15
|
-
.
|
|
16
|
-
.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
})
|
|
23
|
-
.catch(() => { });
|
|
36
|
+
.catch(async () => {
|
|
37
|
+
// 3. Fallback: Toast
|
|
38
|
+
await options.client.tui
|
|
39
|
+
.showToast({
|
|
40
|
+
body: { title: "Usage Status", message: options.text, variant: "info" },
|
|
41
|
+
})
|
|
42
|
+
.catch(() => { });
|
|
43
|
+
});
|
|
24
44
|
}
|
|
25
45
|
function formatBar(remainingPercent) {
|
|
26
46
|
const clamped = Math.max(0, Math.min(100, remainingPercent));
|
package/package.json
CHANGED
package/dist/tools/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACnC,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA"}
|
package/dist/tools/index.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Proxy limits tool for checking quota stats.
|
|
3
|
-
*/
|
|
4
|
-
type SendStatusFn = (sessionID: string, text: string) => Promise<void>;
|
|
5
|
-
type MarkSilentFn = (sessionID: string, messageID: string) => void;
|
|
6
|
-
export declare function createProxyLimitsTool(sendStatus: SendStatusFn, markSilent: MarkSilentFn): {
|
|
7
|
-
description: string;
|
|
8
|
-
args: {
|
|
9
|
-
refresh: import("zod").ZodDefault<import("zod").ZodOptional<import("zod").ZodBoolean>>;
|
|
10
|
-
};
|
|
11
|
-
execute(args: {
|
|
12
|
-
refresh: boolean;
|
|
13
|
-
}, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
14
|
-
};
|
|
15
|
-
export {};
|
|
16
|
-
//# sourceMappingURL=proxy-limits.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"proxy-limits.d.ts","sourceRoot":"","sources":["../../src/tools/proxy-limits.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,KAAK,YAAY,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AACtE,KAAK,YAAY,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;AAElE,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY;;;;;;;;EA+BvF"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Proxy limits tool for checking quota stats.
|
|
3
|
-
*/
|
|
4
|
-
import { tool } from "@opencode-ai/plugin";
|
|
5
|
-
import { loadProxyConfig, fetchProxyLimits, formatProxyLimits } from "../providers/proxy";
|
|
6
|
-
export function createProxyLimitsTool(sendStatus, markSilent) {
|
|
7
|
-
return tool({
|
|
8
|
-
description: "Check current usage limits from the antigravity proxy server. Displays results as an inline status message.",
|
|
9
|
-
args: {
|
|
10
|
-
refresh: tool.schema
|
|
11
|
-
.boolean()
|
|
12
|
-
.optional()
|
|
13
|
-
.default(false)
|
|
14
|
-
.describe("Force refresh the limits data (default: false)"),
|
|
15
|
-
},
|
|
16
|
-
async execute(_args, context) {
|
|
17
|
-
markSilent(context.sessionID, context.messageID);
|
|
18
|
-
try {
|
|
19
|
-
const config = await loadProxyConfig();
|
|
20
|
-
const data = await fetchProxyLimits(config);
|
|
21
|
-
const message = formatProxyLimits(data);
|
|
22
|
-
await sendStatus(context.sessionID, message);
|
|
23
|
-
return "";
|
|
24
|
-
}
|
|
25
|
-
catch (error) {
|
|
26
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
27
|
-
const errorMessage = `Proxy Limits Error\n\n${message}`;
|
|
28
|
-
await sendStatus(context.sessionID, errorMessage);
|
|
29
|
-
return "";
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
}
|
package/dist/tools/usage.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provides a simple tool wrapper for usage info.
|
|
3
|
-
* Keeps tool definitions separate from hooks and rendering.
|
|
4
|
-
*/
|
|
5
|
-
export declare const usageTool: () => {
|
|
6
|
-
description: string;
|
|
7
|
-
args: {};
|
|
8
|
-
execute(args: Record<string, never>, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
9
|
-
};
|
|
10
|
-
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/tools/usage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,eAAO,MAAM,SAAS;;;;CAOlB,CAAA"}
|
package/dist/tools/usage.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provides a simple tool wrapper for usage info.
|
|
3
|
-
* Keeps tool definitions separate from hooks and rendering.
|
|
4
|
-
*/
|
|
5
|
-
import { tool } from "@opencode-ai/plugin";
|
|
6
|
-
export const usageTool = () => tool({
|
|
7
|
-
description: "Get current rate limit snapshots for all providers",
|
|
8
|
-
args: {},
|
|
9
|
-
async execute() {
|
|
10
|
-
return "Run /usage in the chat to see current limits.";
|
|
11
|
-
},
|
|
12
|
-
});
|