@kairyou/agent-tools 0.20.0 → 0.21.0
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/README.md +7 -5
- package/README.zh-CN.md +6 -5
- package/capabilities/usage/lib/format.mjs +25 -0
- package/capabilities/usage/lib/routes.mjs +25 -0
- package/dist/usage/core.mjs +36 -2
- package/docs/en/custom-gateway-routes.md +3 -0
- package/docs/zh-CN/custom-gateway-routes.md +2 -0
- package/package.json +1 -1
- package/skills/systems/at-zentao/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -116,8 +116,9 @@ compatibility and configuration.
|
|
|
116
116
|
### Provider usage
|
|
117
117
|
|
|
118
118
|
Shows API relay / gateway balance and quota inside the agent. Supports Sub2API,
|
|
119
|
-
One API (including OneHub and DoneHub), New API, Claude Code Hub, and
|
|
120
|
-
compatibility depends on the gateway version and enabled usage
|
|
119
|
+
One API (including OneHub and DoneHub), New API, Claude Code Hub, OpenRouter, and
|
|
120
|
+
Command Code; compatibility depends on the gateway version and enabled usage
|
|
121
|
+
endpoints.
|
|
121
122
|
|
|
122
123
|
```bash
|
|
123
124
|
npx -y @kairyou/agent-tools@latest usage -a claude codex opencode
|
|
@@ -139,8 +140,8 @@ configuration; official (non-relay) endpoints are skipped. If it reports
|
|
|
139
140
|
{
|
|
140
141
|
"providerUsage": {
|
|
141
142
|
// auto | sub2api | openai-compatible | one-api | one-hub |
|
|
142
|
-
// done-hub | new-api | claude-code-hub | openrouter | <custom-route-id>
|
|
143
|
-
"preset": "auto",
|
|
143
|
+
// done-hub | new-api | claude-code-hub | openrouter | commandcode | <custom-route-id>
|
|
144
|
+
"preset": "auto", // auto-detect, or select one protocol listed above
|
|
144
145
|
"days": 30, // how many recent days of spend to count
|
|
145
146
|
"debug": false // true: log probes to ~/.agent-tools/logs/usage-debug.log
|
|
146
147
|
}
|
|
@@ -149,7 +150,8 @@ configuration; official (non-relay) endpoints are skipped. If it reports
|
|
|
149
150
|
|
|
150
151
|
Keep `preset` set to `auto` for automatic detection. Select a specific protocol
|
|
151
152
|
only when you know which usage endpoint the gateway exposes; a configured custom
|
|
152
|
-
route id is also accepted.
|
|
153
|
+
route id is also accepted. Command Code usage relies on a version-sensitive
|
|
154
|
+
endpoint that is not part of its documented Provider API.
|
|
153
155
|
|
|
154
156
|
Output examples:
|
|
155
157
|
|
package/README.zh-CN.md
CHANGED
|
@@ -114,8 +114,8 @@ npx -y @kairyou/agent-tools@latest statusline -a claude
|
|
|
114
114
|
### Provider usage
|
|
115
115
|
|
|
116
116
|
在 agent 内查看 API 中转网关的余额和额度. 支持 Sub2API, One API (包括 OneHub
|
|
117
|
-
与 DoneHub), New API, Claude Code Hub 和
|
|
118
|
-
|
|
117
|
+
与 DoneHub), New API, Claude Code Hub, OpenRouter 和 Command Code. 具体兼容性
|
|
118
|
+
取决于网关版本及其是否开放相应接口.
|
|
119
119
|
|
|
120
120
|
```bash
|
|
121
121
|
npx -y @kairyou/agent-tools@latest usage -a claude codex opencode
|
|
@@ -136,8 +136,8 @@ npx -y @kairyou/agent-tools@latest usage -a claude codex opencode
|
|
|
136
136
|
{
|
|
137
137
|
"providerUsage": {
|
|
138
138
|
// auto | sub2api | openai-compatible | one-api | one-hub |
|
|
139
|
-
// done-hub | new-api | claude-code-hub | openrouter | <自定义 route id>
|
|
140
|
-
"preset": "auto",
|
|
139
|
+
// done-hub | new-api | claude-code-hub | openrouter | commandcode | <自定义 route id>
|
|
140
|
+
"preset": "auto", // 自动探测, 也可指定上面列出的协议
|
|
141
141
|
"days": 30, // 统计最近多少天的消耗
|
|
142
142
|
"debug": false // true: 探测过程写入 ~/.agent-tools/logs/usage-debug.log
|
|
143
143
|
}
|
|
@@ -145,7 +145,8 @@ npx -y @kairyou/agent-tools@latest usage -a claude codex opencode
|
|
|
145
145
|
```
|
|
146
146
|
|
|
147
147
|
保持 `preset: "auto"` 即可自动探测. 只有明确知道网关开放的是哪种用量协议时,
|
|
148
|
-
才指定相应的内置 preset 或已配置的自定义 route id.
|
|
148
|
+
才指定相应的内置 preset 或已配置的自定义 route id. Command Code 用量查询依赖
|
|
149
|
+
未包含在公开 Provider API 中的接口, 可能随版本变化.
|
|
149
150
|
|
|
150
151
|
显示效果示例:
|
|
151
152
|
|
|
@@ -226,6 +226,31 @@ export function formatOpenRouterLine(data) {
|
|
|
226
226
|
return parts.join(" | ");
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
function formatCredits(value) {
|
|
230
|
+
return typeof value === "number" && Number.isFinite(value)
|
|
231
|
+
? value.toLocaleString("en-US", { maximumFractionDigits: 1 })
|
|
232
|
+
: "";
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function formatCommandCodeWindow(label, window) {
|
|
236
|
+
if (!window || !Number.isFinite(window.used) || !Number.isFinite(window.cap)) return "";
|
|
237
|
+
const reset = window.resetAt ? compactDurationUntil(window.resetAt) : "";
|
|
238
|
+
return `${label} ${formatCredits(window.used)}/${formatCredits(window.cap)}${reset ? ` ⟳${reset}` : ""}`;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function formatCommandCodeLine(data) {
|
|
242
|
+
const credits = data?.credits || {};
|
|
243
|
+
const limits = data?.windowLimits || {};
|
|
244
|
+
const parts = [];
|
|
245
|
+
if (Number.isFinite(credits.monthlyCredits)) parts.push(`credits ${formatCredits(credits.monthlyCredits)}`);
|
|
246
|
+
const fiveHour = formatCommandCodeWindow("5h", limits.fiveHour);
|
|
247
|
+
const weekly = formatCommandCodeWindow("W", limits.weekly);
|
|
248
|
+
if (fiveHour) parts.push(fiveHour);
|
|
249
|
+
if (weekly) parts.push(weekly);
|
|
250
|
+
if (parts.length === 0) throw new Error("Command Code billing payload has no usage fields");
|
|
251
|
+
return parts.join(" | ");
|
|
252
|
+
}
|
|
253
|
+
|
|
229
254
|
export function formatOneApiBillingLine(limit, used) {
|
|
230
255
|
if (!hasSpendableOneApiLimit(limit)) return `used ${formatMoney(used)}`;
|
|
231
256
|
return `balance ${formatMoney(Math.max(0, limit - used))} | used ${formatMoney(used)}/${formatMoney(limit)}`;
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
hasSpendableOneApiLimit,
|
|
31
31
|
formatOpenRouterLine,
|
|
32
32
|
formatClaudeCodeHubLine,
|
|
33
|
+
formatCommandCodeLine,
|
|
33
34
|
} from "./format.mjs";
|
|
34
35
|
import { readRouteCache } from "./cache.mjs";
|
|
35
36
|
|
|
@@ -170,6 +171,22 @@ async function fetchOpenRouterUsage(context) {
|
|
|
170
171
|
throw lastError || new Error("OpenRouter usage unavailable");
|
|
171
172
|
}
|
|
172
173
|
|
|
174
|
+
// Command Code exposes subscription credits and rolling windows through the
|
|
175
|
+
// same internal endpoint used by its `/usage` overlay. This route is opt-in
|
|
176
|
+
// via the commandcode preset or the official host and is intentionally kept
|
|
177
|
+
// out of generic probing because the endpoint is not a documented Provider API.
|
|
178
|
+
async function fetchCommandCodeUsage(context) {
|
|
179
|
+
const base = cleanBaseUrl(context.baseUrl)
|
|
180
|
+
.replace(/\/provider\/v1$/i, "")
|
|
181
|
+
.replace(/\/provider$/i, "")
|
|
182
|
+
.replace(/\/v1$/i, "");
|
|
183
|
+
const json = await requestJson(joinUrl(base, "/alpha/billing/credits"), {
|
|
184
|
+
key: context.key,
|
|
185
|
+
name: "Command Code billing credits",
|
|
186
|
+
});
|
|
187
|
+
return usageResult(context, "commandcode-billing", formatCommandCodeLine(json), json);
|
|
188
|
+
}
|
|
189
|
+
|
|
173
190
|
const USAGE_ROUTES = {
|
|
174
191
|
"v1-usage": {
|
|
175
192
|
id: "v1-usage",
|
|
@@ -196,6 +213,11 @@ const USAGE_ROUTES = {
|
|
|
196
213
|
path: "/api/v1/me/quota",
|
|
197
214
|
run: fetchClaudeCodeHubUsage,
|
|
198
215
|
},
|
|
216
|
+
"commandcode": {
|
|
217
|
+
id: "commandcode",
|
|
218
|
+
path: "/alpha/billing/credits",
|
|
219
|
+
run: fetchCommandCodeUsage,
|
|
220
|
+
},
|
|
199
221
|
};
|
|
200
222
|
|
|
201
223
|
// User-authored gateway routes, declared in config.jsonc:
|
|
@@ -292,6 +314,7 @@ async function usageRouteIds(context) {
|
|
|
292
314
|
"done-hub": ["oneapi-billing"],
|
|
293
315
|
"openrouter": ["openrouter"],
|
|
294
316
|
"claude-code-hub": ["claude-code-hub"],
|
|
317
|
+
"commandcode": ["commandcode"],
|
|
295
318
|
};
|
|
296
319
|
if (routes[preset]) return routes[preset];
|
|
297
320
|
|
|
@@ -302,6 +325,8 @@ async function usageRouteIds(context) {
|
|
|
302
325
|
const customIds = (await customRoutes()).map((route) => route.id);
|
|
303
326
|
const builtinIds = hostIncludes(context.baseUrl, "openrouter.ai")
|
|
304
327
|
? ["openrouter"]
|
|
328
|
+
: hostIncludes(context.baseUrl, "commandcode.ai")
|
|
329
|
+
? ["commandcode"]
|
|
305
330
|
: ["v1-usage", "newapi-token", "oneapi-billing", "claude-code-hub"];
|
|
306
331
|
return [...new Set([...customIds, ...builtinIds])];
|
|
307
332
|
}
|
package/dist/usage/core.mjs
CHANGED
|
@@ -1490,6 +1490,26 @@ function formatOpenRouterLine(data) {
|
|
|
1490
1490
|
if (parts.length === 0) throw new Error("OpenRouter payload has no usage fields");
|
|
1491
1491
|
return parts.join(" | ");
|
|
1492
1492
|
}
|
|
1493
|
+
function formatCredits(value) {
|
|
1494
|
+
return typeof value === "number" && Number.isFinite(value) ? value.toLocaleString("en-US", { maximumFractionDigits: 1 }) : "";
|
|
1495
|
+
}
|
|
1496
|
+
function formatCommandCodeWindow(label, window) {
|
|
1497
|
+
if (!window || !Number.isFinite(window.used) || !Number.isFinite(window.cap)) return "";
|
|
1498
|
+
const reset = window.resetAt ? compactDurationUntil(window.resetAt) : "";
|
|
1499
|
+
return `${label} ${formatCredits(window.used)}/${formatCredits(window.cap)}${reset ? ` \u27F3${reset}` : ""}`;
|
|
1500
|
+
}
|
|
1501
|
+
function formatCommandCodeLine(data) {
|
|
1502
|
+
const credits = data?.credits || {};
|
|
1503
|
+
const limits = data?.windowLimits || {};
|
|
1504
|
+
const parts = [];
|
|
1505
|
+
if (Number.isFinite(credits.monthlyCredits)) parts.push(`credits ${formatCredits(credits.monthlyCredits)}`);
|
|
1506
|
+
const fiveHour = formatCommandCodeWindow("5h", limits.fiveHour);
|
|
1507
|
+
const weekly = formatCommandCodeWindow("W", limits.weekly);
|
|
1508
|
+
if (fiveHour) parts.push(fiveHour);
|
|
1509
|
+
if (weekly) parts.push(weekly);
|
|
1510
|
+
if (parts.length === 0) throw new Error("Command Code billing payload has no usage fields");
|
|
1511
|
+
return parts.join(" | ");
|
|
1512
|
+
}
|
|
1493
1513
|
function formatOneApiBillingLine(limit, used) {
|
|
1494
1514
|
if (!hasSpendableOneApiLimit(limit)) return `used ${formatMoney(used)}`;
|
|
1495
1515
|
return `balance ${formatMoney(Math.max(0, limit - used))} | used ${formatMoney(used)}/${formatMoney(limit)}`;
|
|
@@ -1706,6 +1726,14 @@ async function fetchOpenRouterUsage(context) {
|
|
|
1706
1726
|
}
|
|
1707
1727
|
throw lastError || new Error("OpenRouter usage unavailable");
|
|
1708
1728
|
}
|
|
1729
|
+
async function fetchCommandCodeUsage(context) {
|
|
1730
|
+
const base = cleanBaseUrl(context.baseUrl).replace(/\/provider\/v1$/i, "").replace(/\/provider$/i, "").replace(/\/v1$/i, "");
|
|
1731
|
+
const json = await requestJson(joinUrl(base, "/alpha/billing/credits"), {
|
|
1732
|
+
key: context.key,
|
|
1733
|
+
name: "Command Code billing credits"
|
|
1734
|
+
});
|
|
1735
|
+
return usageResult(context, "commandcode-billing", formatCommandCodeLine(json), json);
|
|
1736
|
+
}
|
|
1709
1737
|
var USAGE_ROUTES = {
|
|
1710
1738
|
"v1-usage": {
|
|
1711
1739
|
id: "v1-usage",
|
|
@@ -1731,6 +1759,11 @@ var USAGE_ROUTES = {
|
|
|
1731
1759
|
id: "claude-code-hub",
|
|
1732
1760
|
path: "/api/v1/me/quota",
|
|
1733
1761
|
run: fetchClaudeCodeHubUsage
|
|
1762
|
+
},
|
|
1763
|
+
"commandcode": {
|
|
1764
|
+
id: "commandcode",
|
|
1765
|
+
path: "/alpha/billing/credits",
|
|
1766
|
+
run: fetchCommandCodeUsage
|
|
1734
1767
|
}
|
|
1735
1768
|
};
|
|
1736
1769
|
var CUSTOM_ROUTE_HELPERS = { requestJson, agentConfig };
|
|
@@ -1806,12 +1839,13 @@ async function usageRouteIds(context) {
|
|
|
1806
1839
|
"one-hub": ["oneapi-billing"],
|
|
1807
1840
|
"done-hub": ["oneapi-billing"],
|
|
1808
1841
|
"openrouter": ["openrouter"],
|
|
1809
|
-
"claude-code-hub": ["claude-code-hub"]
|
|
1842
|
+
"claude-code-hub": ["claude-code-hub"],
|
|
1843
|
+
"commandcode": ["commandcode"]
|
|
1810
1844
|
};
|
|
1811
1845
|
if (routes[preset]) return routes[preset];
|
|
1812
1846
|
if (preset !== "auto") return (await routeRegistry())[preset] ? [preset] : [];
|
|
1813
1847
|
const customIds = (await customRoutes()).map((route) => route.id);
|
|
1814
|
-
const builtinIds = hostIncludes(context.baseUrl, "openrouter.ai") ? ["openrouter"] : ["v1-usage", "newapi-token", "oneapi-billing", "claude-code-hub"];
|
|
1848
|
+
const builtinIds = hostIncludes(context.baseUrl, "openrouter.ai") ? ["openrouter"] : hostIncludes(context.baseUrl, "commandcode.ai") ? ["commandcode"] : ["v1-usage", "newapi-token", "oneapi-billing", "claude-code-hub"];
|
|
1815
1849
|
return [.../* @__PURE__ */ new Set([...customIds, ...builtinIds])];
|
|
1816
1850
|
}
|
|
1817
1851
|
async function cachedUsageRoute(context, registry) {
|
|
@@ -4,6 +4,9 @@ Advanced guide for [provider usage](../../README.md#provider-usage): write your
|
|
|
4
4
|
usage probe for relays the built-in presets cannot reach (e.g. cookie-authenticated
|
|
5
5
|
gateways) without modifying package code.
|
|
6
6
|
|
|
7
|
+
Built-in presets, including `commandcode`, are documented in the main
|
|
8
|
+
[provider usage](../../README.md#provider-usage) section.
|
|
9
|
+
|
|
7
10
|
## Declare a route
|
|
8
11
|
|
|
9
12
|
Write a route module and list it in `providerUsage.routes` (paths resolve against
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: at-zentao
|
|
3
|
-
description: "
|
|
3
|
+
description: "Handle ZenTao (禅道) Bugs and Tasks end to end, including updating or writing back an item after code changes, managing Task status and hours, and reading linked Stories. Use for referenced ZenTao items, requirements, status changes, time entries, or post-implementation synchronization."
|
|
4
4
|
argument-hint: "bug <id> [request] | task <id> [request] | story <id> | bugs | tasks | export bug|task <id>"
|
|
5
5
|
---
|
|
6
6
|
|