ccus-cli 0.1.24 → 0.1.25
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/cli.js +14 -3
- package/dist/lib/api-mode.js +37 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -982,7 +982,7 @@ async function handleApiConfig(options) {
|
|
|
982
982
|
` provider: ${next.provider}`,
|
|
983
983
|
` token 环境变量: ${next.tokenEnv}`,
|
|
984
984
|
` token 兜底: ${maskSecret(next.token)}`,
|
|
985
|
-
` 当前生效 token: ${maskSecret((0, api_mode_1.
|
|
985
|
+
` 当前生效 token: ${maskSecret((0, api_mode_1.resolveApiTokenWithSettings)(next))}`,
|
|
986
986
|
` 缓存 TTL: ${formatDurationMs(next.cacheTtlMs)}`,
|
|
987
987
|
` 请求超时: ${formatDurationMs(next.timeoutMs)}`,
|
|
988
988
|
` User-Agent: ${next.userAgent}`,
|
|
@@ -1011,8 +1011,19 @@ async function handleApiTest(options) {
|
|
|
1011
1011
|
return;
|
|
1012
1012
|
}
|
|
1013
1013
|
process.stdout.write(`正在用 provider=${config.provider} 拉取额度(超时 ${formatDurationMs(config.timeoutMs)})...\n`);
|
|
1014
|
+
// 环境变量和 config.token 都拿不到 token 时,回退到 ~/.claude/settings.json 的 env 字段。
|
|
1015
|
+
// 手动跑 api test 时不在 Claude Code 进程树下,环境变量里通常没有 ANTHROPIC_AUTH_TOKEN,
|
|
1016
|
+
// 而 settings.json 的 env 是 Claude Code 持久化这些变量的地方,正好作为来源。
|
|
1017
|
+
let env = process.env;
|
|
1018
|
+
if (!(0, api_mode_1.resolveApiToken)(config, env)) {
|
|
1019
|
+
const settingsToken = (0, api_mode_1.readClaudeSettingsEnvTokenSync)(config.tokenEnv);
|
|
1020
|
+
if (settingsToken) {
|
|
1021
|
+
env = { ...process.env, [config.tokenEnv]: settingsToken };
|
|
1022
|
+
(0, debug_1.debugLog)("api-mode", `token from settings.json env.${config.tokenEnv}`);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1014
1025
|
try {
|
|
1015
|
-
const quota = await (0, api_mode_1.fetchQuota)(config,
|
|
1026
|
+
const quota = await (0, api_mode_1.fetchQuota)(config, env);
|
|
1016
1027
|
const fiveHour = quota.fiveHour !== null ? `${quota.fiveHour.toFixed(1)}%` : "--";
|
|
1017
1028
|
const sevenDay = quota.sevenDay !== null ? `${quota.sevenDay.toFixed(1)}%` : "--";
|
|
1018
1029
|
process.stdout.write(`✅ 5h ${fiveHour} | 7d ${sevenDay}${quota.level ? ` | level ${quota.level}` : ""}\n`);
|
|
@@ -1042,7 +1053,7 @@ async function handleApiStatus(options) {
|
|
|
1042
1053
|
const lines = [
|
|
1043
1054
|
` 启用: ${config.enabled ? "是" : "否"}`,
|
|
1044
1055
|
` provider: ${config.provider}`,
|
|
1045
|
-
` 当前生效 token: ${maskSecret((0, api_mode_1.
|
|
1056
|
+
` 当前生效 token: ${maskSecret((0, api_mode_1.resolveApiTokenWithSettings)(config))}`,
|
|
1046
1057
|
` 缓存 TTL: ${formatDurationMs(config.cacheTtlMs)}`,
|
|
1047
1058
|
` 缓存状态: ${ageLabel}`,
|
|
1048
1059
|
];
|
package/dist/lib/api-mode.js
CHANGED
|
@@ -8,6 +8,8 @@ exports.defaultApiConfig = defaultApiConfig;
|
|
|
8
8
|
exports.readApiConfig = readApiConfig;
|
|
9
9
|
exports.writeApiConfig = writeApiConfig;
|
|
10
10
|
exports.resolveApiToken = resolveApiToken;
|
|
11
|
+
exports.readClaudeSettingsEnvTokenSync = readClaudeSettingsEnvTokenSync;
|
|
12
|
+
exports.resolveApiTokenWithSettings = resolveApiTokenWithSettings;
|
|
11
13
|
exports.extractCustomQuota = extractCustomQuota;
|
|
12
14
|
exports.runExtractor = runExtractor;
|
|
13
15
|
exports.normalizeExtractorResult = normalizeExtractorResult;
|
|
@@ -117,6 +119,41 @@ function resolveApiToken(config, env = process.env) {
|
|
|
117
119
|
}
|
|
118
120
|
return typeof config.token === "string" && config.token.trim() !== "" ? config.token : null;
|
|
119
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* 从 ~/.claude/settings.json 的 env 字段读 tokenEnv 指定的那个键。
|
|
124
|
+
*
|
|
125
|
+
* Claude Code 启动子进程时会把 settings.json 的 env 注入环境变量,但用户在终端手动跑
|
|
126
|
+
* `ccus api test` 时不在 Claude Code 进程树下,环境变量里通常没有 ANTHROPIC_AUTH_TOKEN ——
|
|
127
|
+
* 这时回退到 settings.json(env 是 Claude Code 持久化这些变量的地方)读取。
|
|
128
|
+
* 只读 env 字段(apiKeyHelper 需要 spawn 子进程、有副作用,不在此支持)。任何缺失/异常返回 null。
|
|
129
|
+
*/
|
|
130
|
+
function readClaudeSettingsEnvTokenSync(tokenEnv, settingsPath = (0, paths_1.getClaudeSettingsPath)()) {
|
|
131
|
+
try {
|
|
132
|
+
const raw = node_fs_1.default.readFileSync(settingsPath, "utf8");
|
|
133
|
+
const parsed = JSON.parse(raw);
|
|
134
|
+
if (!isRecord(parsed)) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
const envField = parsed.env;
|
|
138
|
+
if (!isRecord(envField)) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
const value = envField[tokenEnv];
|
|
142
|
+
return typeof value === "string" && value.trim() !== "" ? value : null;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* 三层回退解析 token:环境变量 → config.token → ~/.claude/settings.json 的 env 字段。
|
|
150
|
+
*
|
|
151
|
+
* 仅供 `api test` / `api status` / `api config` 这类手动命令显示与判断用;statusline 高频路径
|
|
152
|
+
* 仍走纯 `resolveApiToken`(不读文件),行为不变。
|
|
153
|
+
*/
|
|
154
|
+
function resolveApiTokenWithSettings(config, env = process.env) {
|
|
155
|
+
return resolveApiToken(config, env) ?? readClaudeSettingsEnvTokenSync(config.tokenEnv);
|
|
156
|
+
}
|
|
120
157
|
/** 把 header 值里的 {{token}} / {{apikey}} 占位符替换成实际 token;token 为空则替换为空串。 */
|
|
121
158
|
function renderHeader(value, token) {
|
|
122
159
|
return value.replaceAll(/{{\s*(token|apikey)\s*}}/gi, token ?? "");
|