@nalvietnam/avatar-cli 1.12.0 → 1.12.2
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.js +60 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -223,21 +223,27 @@ function spinnerWithElapsed(prefix) {
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
// src/lib/check-claude-code-subscription-and-quota.ts
|
|
226
|
-
var QUOTA_VERIFY_TIMEOUT_MS =
|
|
226
|
+
var QUOTA_VERIFY_TIMEOUT_MS = 6e4;
|
|
227
227
|
var QUOTA_VERIFY_PROMPT = "ok";
|
|
228
|
-
function
|
|
228
|
+
function readClaudeCodeAuthInfo() {
|
|
229
229
|
const result = spawnSync("claude", ["auth", "status"], { encoding: "utf8" });
|
|
230
|
-
if (result.error || result.status !== 0) return "not-authenticated";
|
|
230
|
+
if (result.error || result.status !== 0) return { state: "not-authenticated" };
|
|
231
231
|
const stdout = (result.stdout || "").trim();
|
|
232
|
-
if (stdout.startsWith("{")) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
232
|
+
if (!stdout.startsWith("{")) {
|
|
233
|
+
return { state: "authenticated" };
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
const parsed = JSON.parse(stdout);
|
|
237
|
+
if (parsed.loggedIn !== true) return { state: "not-authenticated" };
|
|
238
|
+
return {
|
|
239
|
+
state: "authenticated",
|
|
240
|
+
email: parsed.email,
|
|
241
|
+
subscriptionType: parsed.subscriptionType,
|
|
242
|
+
apiProvider: parsed.apiProvider
|
|
243
|
+
};
|
|
244
|
+
} catch {
|
|
245
|
+
return { state: "authenticated" };
|
|
239
246
|
}
|
|
240
|
-
return "authenticated";
|
|
241
247
|
}
|
|
242
248
|
function triggerClaudeCodeAuthLogin() {
|
|
243
249
|
log.info("Kh\u1EDFi \u0111\u1ED9ng \u0111\u0103ng nh\u1EADp Claude Code (browser s\u1EBD m\u1EDF)...");
|
|
@@ -283,7 +289,7 @@ function getQuotaErrorHint(reason) {
|
|
|
283
289
|
case "rate_limit":
|
|
284
290
|
return "B\u1ECB rate limit t\u1EA1m th\u1EDDi. Ch\u1EDD v\xE0i ph\xFAt r\u1ED3i ch\u1EA1y `avatar ai setup`.";
|
|
285
291
|
case "timeout":
|
|
286
|
-
return "
|
|
292
|
+
return "Timeout 60s: (1) m\u1EA1ng VN ch\u1EADm \u2014 th\u1EED VPN, (2) Anthropic API spike \u2014 retry v\xE0i ph\xFAt, (3) token v\u1EABn auth nh\u01B0ng quota h\u1EBFt \xE2m th\u1EA7m \u2014 check t\u1EA1i claude.ai/settings/usage.";
|
|
287
293
|
default:
|
|
288
294
|
return "L\u1ED7i ch\u01B0a bi\u1EBFt. Xem stderr \u1EDF tr\xEAn + ch\u1EA1y `claude --print ok` tay \u0111\u1EC3 debug.";
|
|
289
295
|
}
|
|
@@ -294,8 +300,13 @@ function verifyClaudeCodeQuota() {
|
|
|
294
300
|
timeout: QUOTA_VERIFY_TIMEOUT_MS,
|
|
295
301
|
stdio: ["ignore", "pipe", "pipe"]
|
|
296
302
|
});
|
|
297
|
-
|
|
298
|
-
|
|
303
|
+
const isTimeout = result.signal === "SIGTERM" || result.status === 143 || result.error?.code === "ETIMEDOUT";
|
|
304
|
+
if (isTimeout) {
|
|
305
|
+
return {
|
|
306
|
+
ok: false,
|
|
307
|
+
reason: "timeout",
|
|
308
|
+
detail: `claude --print > ${QUOTA_VERIFY_TIMEOUT_MS / 1e3}s (m\u1EA1ng ch\u1EADm / API rate limit / token revoked kh\xF4ng return error)`
|
|
309
|
+
};
|
|
299
310
|
}
|
|
300
311
|
const stderr = result.stderr || "";
|
|
301
312
|
const stdout = result.stdout || "";
|
|
@@ -802,15 +813,48 @@ async function runAiSetupPhase(args) {
|
|
|
802
813
|
const choice = await promptAiProviderChoice(globalInfo);
|
|
803
814
|
switch (choice) {
|
|
804
815
|
case "subscription": {
|
|
805
|
-
|
|
816
|
+
let authInfo = readClaudeCodeAuthInfo();
|
|
817
|
+
if (authInfo.state !== "authenticated") {
|
|
806
818
|
triggerClaudeCodeAuthLogin();
|
|
819
|
+
authInfo = readClaudeCodeAuthInfo();
|
|
807
820
|
}
|
|
821
|
+
if (authInfo.state === "authenticated" && authInfo.subscriptionType) {
|
|
822
|
+
await writeClaudeSettings(args.workspacePath, {
|
|
823
|
+
provider: "subscription",
|
|
824
|
+
model: SUBSCRIPTION_DEFAULT_MODEL
|
|
825
|
+
});
|
|
826
|
+
await appendAuditEntry(
|
|
827
|
+
"ai_setup",
|
|
828
|
+
`provider=subscription,result=ok,plan=${authInfo.subscriptionType},probe=skipped`
|
|
829
|
+
);
|
|
830
|
+
log.success(
|
|
831
|
+
`AI ready \xB7 Subscription (${authInfo.subscriptionType}) \xB7 model=${SUBSCRIPTION_DEFAULT_MODEL}`
|
|
832
|
+
);
|
|
833
|
+
return { ok: true, provider: "subscription", model: SUBSCRIPTION_DEFAULT_MODEL };
|
|
834
|
+
}
|
|
835
|
+
log.dim("Auth status kh\xF4ng tr\u1EA3 subscriptionType \u2014 verify quota (30-60s)...");
|
|
808
836
|
let quota = verifyClaudeCodeQuota();
|
|
809
837
|
if (!quota.ok && quota.reason === "auth-expired") {
|
|
810
838
|
log.warn("Token Claude Code \u0111\xE3 h\u1EBFt h\u1EA1n. T\u1EF1 \u0111\u1ED9ng re-login...");
|
|
811
839
|
triggerClaudeCodeAuthLogin();
|
|
812
840
|
quota = verifyClaudeCodeQuota();
|
|
813
841
|
}
|
|
842
|
+
if (!quota.ok && (quota.reason === "timeout" || quota.reason === "unknown")) {
|
|
843
|
+
log.warn(`Probe verify ${quota.reason} \u2014 accept trust auth status. Ti\u1EBFp t\u1EE5c.`);
|
|
844
|
+
if (quota.detail?.trim()) log.warn(` Chi ti\u1EBFt: ${quota.detail.slice(0, 200)}`);
|
|
845
|
+
await writeClaudeSettings(args.workspacePath, {
|
|
846
|
+
provider: "subscription",
|
|
847
|
+
model: SUBSCRIPTION_DEFAULT_MODEL
|
|
848
|
+
});
|
|
849
|
+
await appendAuditEntry(
|
|
850
|
+
"ai_setup",
|
|
851
|
+
`provider=subscription,result=ok,probe=${quota.reason}-soft-pass`
|
|
852
|
+
);
|
|
853
|
+
log.success(
|
|
854
|
+
`AI ready \xB7 Subscription (probe ${quota.reason}, soft-pass) \xB7 model=${SUBSCRIPTION_DEFAULT_MODEL}`
|
|
855
|
+
);
|
|
856
|
+
return { ok: true, provider: "subscription", model: SUBSCRIPTION_DEFAULT_MODEL };
|
|
857
|
+
}
|
|
814
858
|
if (!quota.ok) {
|
|
815
859
|
const reason = quota.reason ?? "unknown";
|
|
816
860
|
await appendAuditEntry(
|
|
@@ -818,9 +862,7 @@ async function runAiSetupPhase(args) {
|
|
|
818
862
|
`provider=subscription,result=no-quota,reason=${reason}`
|
|
819
863
|
);
|
|
820
864
|
log.warn(`Subscription verify th\u1EA5t b\u1EA1i (${reason}).`);
|
|
821
|
-
if (quota.detail?.trim()) {
|
|
822
|
-
log.warn(` Chi ti\u1EBFt: ${quota.detail.slice(0, 200)}`);
|
|
823
|
-
}
|
|
865
|
+
if (quota.detail?.trim()) log.warn(` Chi ti\u1EBFt: ${quota.detail.slice(0, 200)}`);
|
|
824
866
|
log.warn(` \u2192 ${getQuotaErrorHint(reason)}`);
|
|
825
867
|
return { ok: false, reason: `subscription-${reason}`, phase: "quota" };
|
|
826
868
|
}
|