fogact 1.1.10 → 1.2.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.
@@ -2,10 +2,9 @@
2
2
 
3
3
  const prompts = require("prompts");
4
4
  const { detectPlatforms, getPlatforms } = require("../platforms");
5
- const { loadUpstreamConfig } = require("../config/upstream");
6
5
  const { createActivationBackup } = require("./backup-service");
7
- const { inspectActivationCode, redeemActivationCode } = require("./fogact-api");
8
- const { maskKey, verifyNewApiKey } = require("./newapi");
6
+ const { getNodes, inspectActivationCode, testNode, verifyActivationCode } = require("./fogact-api");
7
+ const { maskKey } = require("./newapi");
9
8
 
10
9
  const SUPPORTED_SERVICES = ["codex", "claude"];
11
10
  const SERVICE_LABELS = {
@@ -149,6 +148,9 @@ function normalizeEntitlement(raw = {}, fallbackServices = []) {
149
148
  function extractApiKeyFromEntitlement(entitlement, fallback) {
150
149
  const raw = entitlement && entitlement.raw ? entitlement.raw : {};
151
150
  const credential = raw.credential || raw.credentials || {};
151
+ if (raw.proxy === true) {
152
+ return String(raw.apiKey || raw.key || raw.token || fallback || "").trim();
153
+ }
152
154
  return String(
153
155
  raw.apiKey ||
154
156
  raw.key ||
@@ -176,6 +178,16 @@ function extractBaseUrlFromEntitlement(entitlement) {
176
178
  ).trim().replace(/\/+$/, "");
177
179
  }
178
180
 
181
+ function extractProxyBaseUrlFromEntitlement(entitlement) {
182
+ const raw = entitlement && entitlement.raw ? entitlement.raw : {};
183
+ const service = raw.serviceKey || (entitlement.services && entitlement.services[0]);
184
+ return String(
185
+ raw.baseUrl ||
186
+ (raw.publicBaseUrl && service === "codex" ? `${String(raw.publicBaseUrl).replace(/\/+$/, "")}/v1` : raw.publicBaseUrl) ||
187
+ ""
188
+ ).trim().replace(/\/+$/, "");
189
+ }
190
+
179
191
  function isServiceAllowed(entitlement, service) {
180
192
  return !entitlement.services.length || entitlement.services.includes(service);
181
193
  }
@@ -219,21 +231,17 @@ async function promptService(defaultService, entitlement = normalizeEntitlement(
219
231
  if (!isServiceAllowed(entitlement, normalized)) {
220
232
  throw new Error(`当前激活码不支持 ${getServiceLabel(normalized)}`);
221
233
  }
222
- console.log(`能力范围: ${getServiceLabel(normalized)}`);
223
234
  return normalized;
224
235
  }
225
236
 
226
237
  const allowedServices = entitlement.services.length ? entitlement.services : [];
227
238
  if (allowedServices.length === 1) {
228
- console.log(`能力范围: ${getServiceLabel(allowedServices[0])}`);
229
239
  return allowedServices[0];
230
240
  }
231
241
 
232
242
  if (!allowPrompt) {
233
243
  if (allowedServices.length > 1) {
234
244
  const service = allowedServices[0];
235
- const labels = allowedServices.map(getServiceLabel).join(" / ");
236
- console.log(`能力范围: ${labels},本次自动激活 ${getServiceLabel(service)}`);
237
245
  return service;
238
246
  }
239
247
  console.log("✗ 激活码没有返回 Codex / Claude 能力,无法自动识别。请联系管理员重新生成激活码。");
@@ -253,75 +261,22 @@ async function promptService(defaultService, entitlement = normalizeEntitlement(
253
261
  return response.service || null;
254
262
  }
255
263
 
256
- async function promptApiKey(defaultApiKey) {
257
- if (defaultApiKey) {
258
- return defaultApiKey;
259
- }
260
-
261
- const response = await prompts({
262
- type: "password",
263
- name: "apiKey",
264
- message: "请输入 NewAPI API Key",
265
- validate: (value) => value && value.trim() ? true : "API Key 不能为空",
266
- }, { onCancel: () => false });
267
-
268
- return response.apiKey ? response.apiKey.trim() : null;
269
- }
270
-
271
- async function promptBaseUrl(defaultBaseUrl) {
272
- if (defaultBaseUrl) {
273
- return defaultBaseUrl;
274
- }
275
-
276
- const response = await prompts({
277
- type: "text",
278
- name: "baseUrl",
279
- message: "请输入 NewAPI Base URL",
280
- validate: (value) => value && value.trim() ? true : "Base URL 不能为空",
281
- }, { onCancel: () => false });
282
-
283
- return response.baseUrl ? response.baseUrl.trim().replace(/\/+$/, "") : null;
284
- }
285
-
286
264
  async function promptActivationCode(defaultCode) {
287
265
  if (defaultCode) {
288
266
  return defaultCode;
289
267
  }
290
268
 
291
269
  const response = await prompts({
292
- type: "text",
270
+ type: "password",
293
271
  name: "code",
294
- message: "请输入激活码 / 兑换码",
272
+ message: "请输入激活码:",
295
273
  validate: (value) => value && value.trim() ? true : "激活码不能为空",
296
274
  }, { onCancel: () => false });
297
275
 
298
276
  return response.code ? response.code.trim() : null;
299
277
  }
300
278
 
301
- async function promptCredentialType(options, upstream) {
302
- if (options.code) {
303
- return "code";
304
- }
305
- if (options.apiKey || upstream.apiKey) {
306
- return "api-key";
307
- }
308
-
309
- const response = await prompts({
310
- type: "select",
311
- name: "credentialType",
312
- message: "请选择激活方式",
313
- hint: "↑↓ 选择,回车确认",
314
- choices: [
315
- { title: "输入激活码 / 兑换码", value: "code" },
316
- { title: "输入 NewAPI API Key", value: "api-key" },
317
- ],
318
- initial: 0,
319
- }, { onCancel: () => false });
320
-
321
- return response.credentialType || null;
322
- }
323
-
324
- async function confirmActivation(yes) {
279
+ async function confirmActivation(yes, service) {
325
280
  if (yes) {
326
281
  return true;
327
282
  }
@@ -329,7 +284,7 @@ async function confirmActivation(yes) {
329
284
  const response = await prompts({
330
285
  type: "confirm",
331
286
  name: "confirmed",
332
- message: "确认开始激活?",
287
+ message: `确认激活 ${getServiceLabel(service)} 配置?`,
333
288
  initial: true,
334
289
  }, { onCancel: () => false });
335
290
 
@@ -353,6 +308,10 @@ function getBackupPaths(targets) {
353
308
  return targets.flatMap(({ detection }) => detection.paths || []);
354
309
  }
355
310
 
311
+ function divider(width = 37) {
312
+ return ` ${"─".repeat(width)}`;
313
+ }
314
+
356
315
  function printBanner() {
357
316
  console.log("");
358
317
  console.log("╭────────────────────────────────────────╮");
@@ -362,65 +321,109 @@ function printBanner() {
362
321
  console.log("");
363
322
  }
364
323
 
365
- function printDetection(service, detectedPlatforms, blockedPlatforms = []) {
366
- console.log("检测结果:");
367
- console.log(` 当前能力: ${getServiceLabel(service)}`);
368
- for (const { platform, detection } of detectedPlatforms) {
369
- const mark = canSelectPlatform(platform, detection) ? "✓" : "-";
370
- console.log(` ${mark} ${platform.name}:${getStatusLabel(platform, detection)}`);
371
- }
372
- for (const { platform } of blockedPlatforms) {
373
- console.log(` - ${platform.name}:当前激活码能力不包含`);
374
- }
324
+ function printCredentialProfile(service, upstream, apiKey, entitlement) {
375
325
  console.log("");
376
- }
377
-
378
- function printPlan(service, upstream, apiKey, targets, skipped = []) {
379
- console.log("激活计划:");
380
- console.log(` 能力: ${getServiceLabel(service)}`);
381
- console.log(` 上游: ${upstream.baseUrl}`);
382
- console.log(` 密钥: ${maskKey(apiKey)}`);
383
- console.log(" 平台:");
384
- for (const { platform, detection } of targets) {
385
- console.log(`${platform.name} (${getStatusLabel(platform, detection)})`);
386
- }
387
- for (const { platform } of skipped) {
388
- console.log(` - ${platform.name} (未选择)`);
326
+ console.log(" 账号信息");
327
+ console.log(divider());
328
+ console.log(` 服务类型: ${getServiceLabel(service)}`);
329
+ console.log(` 接入地址: ${upstream.baseUrl}`);
330
+ console.log(` 激活码: ${maskKey(apiKey)}`);
331
+ if (entitlement.planName) {
332
+ console.log(` 套餐名称: ${entitlement.planName}`);
333
+ }
334
+ if (entitlement.raw && entitlement.raw.expiresAt) {
335
+ console.log(` 到期时间: ${entitlement.raw.expiresAt}`);
336
+ }
337
+ const quota = entitlement.raw && entitlement.raw.quota;
338
+ if (quota && typeof quota === "object") {
339
+ const total = quota.total ?? quota.total_quota ?? quota.dailyLimit ?? quota.daily;
340
+ const used = quota.used ?? quota.used_quota ?? quota.dailyUsed;
341
+ if (total !== undefined) console.log(` 总配额: ${total}`);
342
+ if (used !== undefined) console.log(` 已使用: ${used}`);
389
343
  }
344
+ console.log("");
390
345
  }
391
346
 
392
- function printResultSummary(service, upstream, backupPath, results, redeemResult) {
347
+ function printResultSummary(service, backupPath, results, redeemResult) {
393
348
  const succeeded = results.filter(({ result }) => result.success);
394
349
  const skipped = results.filter(({ result }) => !result.success && result.skipped);
395
350
  const failed = results.filter(({ result }) => !result.success && !result.skipped);
351
+ const byId = new Map(results.map((entry) => [entry.platform.id, entry]));
396
352
 
397
353
  console.log("");
398
- console.log("激活结果:");
399
- for (const { platform, result } of results) {
400
- if (result.success) {
401
- console.log(` ✓ ${platform.name}`);
402
- for (const file of result.files || []) {
403
- console.log(` ${file}`);
354
+ if (backupPath) {
355
+ console.log(" 备份已创建");
356
+ }
357
+
358
+ const printConfigured = (entry, label) => {
359
+ if (!entry) return false;
360
+ if (entry.result.success) {
361
+ console.log(` ✓ ${label} 已激活`);
362
+ const files = entry.result.files || [];
363
+ if (files.length) console.log(` 配置: ${files.join(", ")}`);
364
+ return true;
365
+ }
366
+ if (!entry.result.skipped) {
367
+ console.log(` ✗ ${label} 激活失败: ${entry.result.error || entry.result.message || "未知错误"}`);
368
+ return true;
369
+ }
370
+ return false;
371
+ };
372
+
373
+ if (service === "codex") {
374
+ printConfigured(byId.get("codex-cli"), "Codex CLI");
375
+ } else {
376
+ printConfigured(byId.get("claude-code"), "Claude Code");
377
+ }
378
+
379
+ const opencode = byId.get("opencode");
380
+ if (!printConfigured(opencode, "OpenCode")) {
381
+ console.log("");
382
+ console.log(" ℹ 已跳过 OpenCode 配置(未检测到安装)");
383
+ console.log(" 如需使用,请先运行一次 opencode 初始化后重新激活");
384
+ }
385
+
386
+ const openclaw = byId.get("openclaw");
387
+ if (!printConfigured(openclaw, "OpenClaw")) {
388
+ console.log("");
389
+ console.log(" ℹ 已跳过 OpenClaw 配置(未检测到安装)");
390
+ console.log(" 如需使用,请先运行一次 openclaw 初始化后重新激活");
391
+ }
392
+
393
+ const extensionResults = [byId.get("vscode-codex-plugin"), byId.get("cursor-codex-plugin")]
394
+ .filter(Boolean)
395
+ .filter((entry) => entry.result.success || !entry.result.skipped);
396
+ if (extensionResults.length) {
397
+ for (const entry of extensionResults) {
398
+ if (entry.result.success) {
399
+ console.log("");
400
+ console.log(` ✓ ${entry.platform.name} 已激活`);
401
+ for (const file of entry.result.files || []) console.log(` 目录: ${file}`);
402
+ } else {
403
+ console.log("");
404
+ console.log(` ⚠ ${entry.platform.name}: ${entry.result.error || entry.result.message || "无法激活"}`);
404
405
  }
405
- } else if (result.skipped) {
406
- console.log(` - ${platform.name}: ${result.message || "已跳过"}`);
407
- } else {
408
- console.log(` ✗ ${platform.name}: ${result.error || result.message || "失败"}`);
409
406
  }
407
+ } else if (service === "codex") {
408
+ console.log("");
409
+ console.log(" ℹ 已跳过编辑器插件配置(未检测到 Codex 插件)");
410
410
  }
411
411
 
412
412
  console.log("");
413
- console.log("汇总:");
414
- console.log(` 能力: ${getServiceLabel(service)}`);
415
- console.log(` 上游: ${upstream.baseUrl}`);
416
- console.log(` 成功: ${succeeded.length}`);
417
- console.log(` 跳过: ${skipped.length}`);
418
- console.log(` 失败: ${failed.length}`);
419
- console.log(` 备份: ${backupPath || "无旧配置需要备份"}`);
420
- if (redeemResult) {
421
- console.log(` 兑换: ${redeemResult.valid ? "已完成" : `未完成(${redeemResult.error || "接口不可用"})`}`);
422
- }
423
- console.log(" 提示: 重启相关工具后生效");
413
+ if (failed.length) {
414
+ console.log(` 激活完成:${succeeded.length} 成功,${failed.length} 失败,${skipped.length} 跳过`);
415
+ }
416
+ if (service === "claude") {
417
+ const tools = ["Claude Code"];
418
+ if (byId.get("opencode")?.result.success) tools.push("OpenCode");
419
+ if (byId.get("openclaw")?.result.success) tools.push("OpenClaw");
420
+ console.log(` 请重启相关工具(${tools.join("/")})以应用新配置`);
421
+ } else {
422
+ const tools = ["Codex", "VSCode", "Cursor"];
423
+ if (byId.get("opencode")?.result.success) tools.push("OpenCode");
424
+ if (byId.get("openclaw")?.result.success) tools.push("OpenClaw");
425
+ console.log(` 请重启相关工具(${tools.join("/")})以应用新配置`);
426
+ }
424
427
  console.log("");
425
428
  }
426
429
 
@@ -431,6 +434,28 @@ async function selectPlatforms(detectedPlatforms, options = {}) {
431
434
  return getActivationTargets(detectedPlatforms, Boolean(options.all));
432
435
  }
433
436
 
437
+ async function verifyPrimaryNode() {
438
+ const nodes = await getNodes("codex");
439
+ const primary = nodes[0];
440
+ if (!primary) return null;
441
+
442
+ console.log("");
443
+ console.log(" 正在验证节点...");
444
+ const result = await testNode(primary.url);
445
+ if (result.available) {
446
+ console.log(` ✓ ${primary.name || "FogAct"} 已连接`);
447
+ console.log(` 延迟: ${result.latency}ms`);
448
+ console.log(` 地址: ${primary.url}`);
449
+ console.log("");
450
+ return { node: primary, latency: result.latency };
451
+ }
452
+
453
+ console.log(` ✗ ${primary.name || "FogAct"} 连接失败`);
454
+ console.log(` 地址: ${primary.url}`);
455
+ console.log("");
456
+ return null;
457
+ }
458
+
434
459
  async function resolveCodeCredential(options, upstream) {
435
460
  const code = await promptActivationCode(options.code);
436
461
  if (!code) {
@@ -438,7 +463,7 @@ async function resolveCodeCredential(options, upstream) {
438
463
  }
439
464
 
440
465
  console.log("");
441
- console.log("正在读取激活码能力...");
466
+ console.log("正在验证激活码...");
442
467
  const inspection = await inspectActivationCode(code);
443
468
  if (!inspection.valid) {
444
469
  console.log(`✗ 无法读取激活码能力: ${inspection.error || "接口未返回有效信息"}`);
@@ -447,199 +472,98 @@ async function resolveCodeCredential(options, upstream) {
447
472
 
448
473
  const entitlement = normalizeEntitlement(inspection, options.service ? [options.service] : []);
449
474
  const apiKey = extractApiKeyFromEntitlement(entitlement, code);
450
- const entitlementBaseUrl = extractBaseUrlFromEntitlement(entitlement);
475
+ const entitlementBaseUrl = extractProxyBaseUrlFromEntitlement(entitlement);
476
+ if (!apiKey || !entitlementBaseUrl || entitlement.raw.proxy !== true) {
477
+ console.log("✗ 激活接口没有返回 FogAct 中转配置,请联系管理员检查服务端代理设置。");
478
+ return { cancelled: true };
479
+ }
451
480
  return {
452
481
  activationCode: code,
453
482
  apiKey,
454
483
  entitlement,
455
- upstream: entitlementBaseUrl ? { ...upstream, baseUrl: entitlementBaseUrl } : upstream,
484
+ upstream: { services: {}, baseUrl: entitlementBaseUrl, proxy: true },
456
485
  inspection,
457
486
  };
458
487
  }
459
488
 
460
- async function resolveApiKeyCredential(options, upstream) {
461
- const apiKey = await promptApiKey(options.apiKey || upstream.apiKey);
462
- if (!apiKey) {
463
- return { cancelled: true };
464
- }
465
- return {
466
- apiKey,
467
- entitlement: normalizeEntitlement({}, options.service ? [options.service] : []),
468
- upstream,
469
- };
470
- }
471
-
472
489
  async function activateTargets({ service, upstream, apiKey, targets, activationCode, options = {} }) {
473
- console.log("");
474
- console.log("正在创建备份...");
475
490
  const backupPath = createActivationBackup(service, getBackupPaths(targets), {
476
491
  upstream: upstream.baseUrl,
477
492
  targets: targets.map(({ platform }) => platform.id),
478
493
  });
479
- if (backupPath) {
480
- console.log(`✓ 备份完成: ${backupPath}`);
481
- } else {
482
- console.log("ℹ 没有旧配置需要备份");
483
- }
484
494
 
485
- console.log("");
486
- console.log("正在激活平台...");
487
495
  const results = [];
488
496
  for (const { platform, detection } of targets) {
497
+ if (!canSelectPlatform(platform, detection)) {
498
+ results.push({ platform, result: { success: false, skipped: true, message: "未安装" } });
499
+ continue;
500
+ }
489
501
  try {
490
- const result = platform.activate({ service, upstream, apiKey, detection });
502
+ const result = platform.activate({ service, upstream, apiKey, options, detection });
491
503
  results.push({ platform, result });
492
- if (result.success) {
493
- console.log(`✓ ${platform.name}`);
494
- } else {
495
- console.log(`⚠ ${platform.name}: ${result.message || "已跳过"}`);
496
- }
497
504
  } catch (err) {
498
505
  results.push({ platform, result: { success: false, error: err.message } });
499
- console.log(`✗ ${platform.name}: ${err.message}`);
500
506
  }
501
507
  }
502
508
 
503
- let redeemResult = null;
509
+ let activationRecord = null;
504
510
  const failures = results.filter(({ result }) => !result.success && !result.skipped);
505
- if (activationCode && failures.length === 0 && !options.noRedeem) {
506
- console.log("");
507
- console.log("正在完成兑换记录...");
508
- redeemResult = await redeemActivationCode(activationCode, service);
509
- if (redeemResult.valid) {
510
- console.log("✓ 兑换记录已完成");
511
- } else {
512
- console.log(`⚠ 兑换记录未完成: ${redeemResult.error || "接口不可用"}`);
513
- }
511
+ if (activationCode && failures.length === 0) {
512
+ activationRecord = await verifyActivationCode(activationCode, service);
514
513
  }
515
514
 
516
- return { backupPath, results, redeemResult };
515
+ return { backupPath, results, redeemResult: null, activationRecord };
517
516
  }
518
517
 
519
- async function verifyCredential(upstream, apiKey, options = {}) {
520
- if (options.skipVerify) {
521
- console.log("跳过 NewAPI 连通性验证。");
522
- return { valid: true, skipped: true };
523
- }
524
-
525
- console.log("正在验证 NewAPI Key...");
526
- const verification = await verifyNewApiKey(upstream, apiKey);
527
- if (!verification.valid) {
528
- console.log(`✗ NewAPI 验证失败: ${verification.error}`);
529
- return verification;
530
- }
531
- console.log(`✓ NewAPI 验证通过(可见 ${verification.models.length} 个模型)`);
532
- return verification;
533
- }
534
-
535
- async function runNewApiActivation(options = {}) {
536
- const baseUpstream = loadUpstreamConfig({ configPath: options.upstreamConfig });
537
- const upstream = { ...baseUpstream };
538
- upstream.baseUrl = await promptBaseUrl(upstream.baseUrl);
539
- if (!upstream.baseUrl) {
540
- console.log("Activation cancelled.");
541
- return { success: false, cancelled: true };
542
- }
543
-
544
- const apiKey = await promptApiKey(options.apiKey || upstream.apiKey);
545
- if (!apiKey) {
546
- console.log("Activation cancelled.");
547
- return { success: false, cancelled: true };
548
- }
549
-
550
- const entitlement = normalizeEntitlement({}, options.service ? [options.service] : []);
551
- const service = await promptService(options.service, entitlement);
552
- if (!service) {
553
- console.log("Activation cancelled.");
554
- return { success: false, cancelled: true };
555
- }
556
-
557
- console.log("");
558
- const verification = await verifyCredential(upstream, apiKey, options);
559
- if (!verification.valid) {
560
- return { success: false, verification };
561
- }
562
-
563
- const detectedPlatforms = detectPlatforms(service);
564
- const selectedPlatformIds = options.platforms ? parsePlatformIds(options.platforms) : null;
565
- const targets = getActivationTargets(detectedPlatforms, Boolean(options.all), selectedPlatformIds);
566
- const skipped = detectedPlatforms.filter((entry) => !targets.includes(entry));
567
-
568
- console.log("");
569
- printPlan(service, upstream, apiKey, targets, skipped);
570
-
571
- if (!(await confirmActivation(Boolean(options.yes || options.auto)))) {
572
- console.log("Activation cancelled.");
573
- return { success: false, cancelled: true };
574
- }
575
-
576
- const activation = await activateTargets({ service, upstream, apiKey, targets, options });
577
- const failures = activation.results.filter(({ result }) => !result.success && !result.skipped);
578
- printResultSummary(service, upstream, activation.backupPath, activation.results, activation.redeemResult);
579
-
580
- return {
581
- success: failures.length === 0,
582
- backupPath: activation.backupPath,
583
- results: activation.results,
584
- };
585
- }
586
518
 
587
519
  async function runActivationWizard(options = {}) {
588
- printBanner();
589
- const baseUpstream = loadUpstreamConfig({ configPath: options.upstreamConfig });
590
- const credentialType = !options.code && options.apiKey ? "api-key" : "code";
520
+ if (!options.noNodeCheck) {
521
+ const node = await verifyPrimaryNode();
522
+ if (!node) {
523
+ return { success: false, cancelled: true };
524
+ }
525
+ }
591
526
 
592
- const credential = credentialType === "code"
593
- ? await resolveCodeCredential(options, baseUpstream)
594
- : await resolveApiKeyCredential(options, baseUpstream);
527
+ const credential = await resolveCodeCredential(options, {});
595
528
  if (credential.cancelled) {
596
529
  console.log("已取消。");
597
530
  return { success: false, cancelled: true };
598
531
  }
599
532
 
600
533
  const upstream = { ...credential.upstream };
601
- upstream.baseUrl = await promptBaseUrl(upstream.baseUrl);
602
534
  if (!upstream.baseUrl) {
603
535
  console.log("已取消。");
604
536
  return { success: false, cancelled: true };
605
537
  }
606
538
 
607
- const service = await promptService(options.service, credential.entitlement, { allowPrompt: credentialType === "api-key" });
539
+ const service = await promptService(options.service, credential.entitlement, { allowPrompt: false });
608
540
  if (!service) {
609
541
  console.log("已取消。");
610
542
  return { success: false, cancelled: true };
611
543
  }
612
544
 
613
- console.log("");
614
- if (credentialType === "api-key") {
615
- const verification = await verifyCredential(upstream, credential.apiKey, options);
616
- if (!verification.valid) {
617
- return { success: false, verification };
618
- }
619
- } else {
620
- console.log("✓ 已按激活码能力限制可选平台");
621
- }
622
545
 
623
546
  const allDetectedPlatforms = detectPlatforms(service);
624
547
  const allowedPlatforms = allDetectedPlatforms.filter((entry) => isPlatformAllowed(entry, credential.entitlement, service));
625
- const blockedPlatforms = allDetectedPlatforms.filter((entry) => !allowedPlatforms.includes(entry));
626
-
627
- console.log("");
628
- printDetection(service, allowedPlatforms, blockedPlatforms);
629
548
 
630
549
  const targets = await selectPlatforms(allowedPlatforms, options);
631
550
  if (targets.length === 0) {
632
- console.log("没有选择任何平台,已取消。");
551
+ console.log("");
552
+ console.log(" ✗ 当前环境没有可激活目标");
553
+ console.log("");
633
554
  return { success: false, cancelled: true };
634
555
  }
635
- const skipped = allowedPlatforms.filter((entry) => !targets.includes(entry)).concat(blockedPlatforms);
636
556
 
637
- printPlan(service, upstream, credential.apiKey, targets, skipped);
638
- if (!(await confirmActivation(Boolean(options.yes || options.auto)))) {
639
- console.log("已取消。");
557
+ printCredentialProfile(service, upstream, credential.apiKey, credential.entitlement);
558
+ if (!(await confirmActivation(Boolean(options.yes || options.auto), service))) {
559
+ console.log("");
560
+ console.log(" 已取消");
561
+ console.log("");
640
562
  return { success: false, cancelled: true };
641
563
  }
642
564
 
565
+ console.log("");
566
+ console.log(" 正在写入配置...");
643
567
  const activation = await activateTargets({
644
568
  service,
645
569
  upstream,
@@ -649,7 +573,8 @@ async function runActivationWizard(options = {}) {
649
573
  options,
650
574
  });
651
575
  const failures = activation.results.filter(({ result }) => !result.success && !result.skipped);
652
- printResultSummary(service, upstream, activation.backupPath, activation.results, activation.redeemResult);
576
+ console.log(" 配置完成");
577
+ printResultSummary(service, activation.backupPath, activation.results, activation.redeemResult);
653
578
 
654
579
  return {
655
580
  success: failures.length === 0,
@@ -667,5 +592,4 @@ module.exports = {
667
592
  normalizeServices,
668
593
  parsePlatformIds,
669
594
  runActivationWizard,
670
- runNewApiActivation,
671
595
  };