fogact 1.2.0 → 1.2.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/bin/web-server.js +829 -230
- package/frontend/admin/admin-panel-v2.js +8 -5
- package/frontend/user/assets/AnnouncementDetail-Dvxmwz0A-fogact-live.js +12 -0
- package/frontend/user/assets/Announcements-CS1tF2mx-fogact-live.js +11 -0
- package/frontend/user/assets/CardBind-CsCxihhP-fogact-live.js +21 -0
- package/frontend/user/assets/CardContent.vue_vue_type_script_setup_true_lang-D2L-uqSl-fogact-live.js +1 -0
- package/frontend/user/assets/CardDescription.vue_vue_type_script_setup_true_lang-D-v5Pl7F-fogact-live.js +1 -0
- package/frontend/user/assets/CardTitle.vue_vue_type_script_setup_true_lang-a0CCN6D5-fogact-live.js +1 -0
- package/frontend/user/assets/Dashboard-rPsmltm5-fogact-live.js +51 -0
- package/frontend/user/assets/Dashboard-rPsmltm5.js +1 -1
- package/frontend/user/assets/DashboardLayout-DDkxHYFj-fogact-live.js +80 -0
- package/frontend/user/assets/DashboardLayout-DDkxHYFj.js +2 -2
- package/frontend/user/assets/Input.vue_vue_type_script_setup_true_lang-B0SyPmYb-fogact-live.js +6 -0
- package/frontend/user/assets/Label.vue_vue_type_script_setup_true_lang-CxYORSgN-fogact-live.js +1 -0
- package/frontend/user/assets/Progress.vue_vue_type_script_setup_true_lang-2_QbPsEQ-fogact-live.js +1 -0
- package/frontend/user/assets/QuotaPack-B_tJ7Psm-fogact-live.js +6 -0
- package/frontend/user/assets/Renewal-BSDhDmwv-fogact-live.js +6 -0
- package/frontend/user/assets/ScrollArea.vue_vue_type_script_setup_true_lang-DMYwcfpz-fogact-live.js +1 -0
- package/frontend/user/assets/Separator.vue_vue_type_script_setup_true_lang-Ckg8EXj_-fogact-live.js +1 -0
- package/frontend/user/assets/Settings-CBdAa3lw-fogact-live.js +11 -0
- package/frontend/user/assets/TooltipTrigger.vue_vue_type_script_setup_true_lang-DtSBjzGo-fogact-live.js +16 -0
- package/frontend/user/assets/Welcome-Dtfp6oER-fogact-live.js +1 -0
- package/frontend/user/assets/Welcome-Dtfp6oER.js +1 -1
- package/frontend/user/assets/_plugin-vue_export-helper-5cjT4u0R-fogact-live.js +16 -0
- package/frontend/user/assets/activity-wYWtyqTJ-fogact-live.js +6 -0
- package/frontend/user/assets/announcement-35mOnjRL-fogact-live.js +16 -0
- package/frontend/user/assets/announcement-35mOnjRL.js +1 -1
- package/frontend/user/assets/calendar-BFNuCata-fogact-live.js +6 -0
- package/frontend/user/assets/chevron-down-kDbuU1Py-fogact-live.js +6 -0
- package/frontend/user/assets/chevron-right-BayASIm0-fogact-live.js +6 -0
- package/frontend/user/assets/eye-CY62vip0-fogact-live.js +6 -0
- package/frontend/user/assets/gauge-C5NQ-mV8-fogact-live.js +6 -0
- package/frontend/user/assets/index-Da98HOxL.js +3 -3
- package/frontend/user/assets/index-fogact-live.js +91 -0
- package/frontend/user/assets/link-2-DT5R5nGO-fogact-live.js +6 -0
- package/frontend/user/assets/package-rUbExUEn-fogact-live.js +6 -0
- package/frontend/user/assets/plus-CQc6C8wG-fogact-live.js +11 -0
- package/frontend/user/assets/refresh-cw-Y9hCloPL-fogact-live.js +6 -0
- package/frontend/user/assets/useUserPageRefresh-BYZvpNR9-fogact-live.js +1 -0
- package/frontend/user/assets/zap-l5zbZqrM-fogact-live.js +11 -0
- package/frontend/user/index.html +5 -5
- package/lib/commands/activate.js +1 -8
- package/lib/config/claude.js +1 -0
- package/lib/config/codex.js +1 -1
- package/lib/config/upstream.js +3 -0
- package/lib/index.js +109 -29
- package/lib/platforms/opencode.js +1 -1
- package/lib/services/activation-orchestrator.js +30 -166
- package/lib/services/database.js +47 -0
- package/lib/services/fogact-api.js +12 -9
- package/package.json +1 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{c as e}from"./index-fogact-live.js";/**
|
|
2
|
+
* @license lucide-vue-next v0.468.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const n=e("Link2Icon",[["path",{d:"M9 17H7A5 5 0 0 1 7 7h2",key:"8i5ue5"}],["path",{d:"M15 7h2a5 5 0 1 1 0 10h-2",key:"1b9ql8"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12",key:"1jonct"}]]);export{n as L};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{c as a}from"./index-fogact-live.js";/**
|
|
2
|
+
* @license lucide-vue-next v0.468.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const c=a("PackageIcon",[["path",{d:"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z",key:"1a0edw"}],["path",{d:"M12 22V12",key:"d0xqtd"}],["path",{d:"m3.3 7 7.703 4.734a2 2 0 0 0 1.994 0L20.7 7",key:"yx3hmr"}],["path",{d:"m7.5 4.27 9 5.15",key:"1c824w"}]]);export{c as P};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import{c as a}from"./index-fogact-live.js";/**
|
|
2
|
+
* @license lucide-vue-next v0.468.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const s=a("LayersIcon",[["path",{d:"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",key:"zw3jo"}],["path",{d:"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",key:"1wduqc"}],["path",{d:"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",key:"kqbvx6"}]]);/**
|
|
7
|
+
* @license lucide-vue-next v0.468.0 - ISC
|
|
8
|
+
*
|
|
9
|
+
* This source code is licensed under the ISC license.
|
|
10
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
+
*/const t=a("PlusIcon",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]]);export{s as L,t as P};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{c as e}from"./index-fogact-live.js";/**
|
|
2
|
+
* @license lucide-vue-next v0.468.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const t=e("RefreshCwIcon",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);export{t as R};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{u as c}from"./index-fogact-live.js";import{w as i,L as d,f as h}from"./chart-vendor-CULJE59K.js";const o=Symbol("user-page-refresh");function v(l,e={}){const n=c(),f=h(o,null);let t=0;async function a(r="custom"){var u;const s=++t;(u=e.resetBeforeLoad)==null||u.call(e,r),await l({reason:r,runId:s,isLatest:()=>s===t})}return e.reloadOnKeyChange!==!1&&i(()=>n.activeKeyId,(r,s)=>{r!==s&&a("active-key-change")}),e.reloadOnManualRefresh!==!1&&f&&i(()=>f.refreshTick.value,()=>{a("manual-refresh")}),e.immediate!==!1&&d(()=>{a("initial")}),{reload:a}}export{v as a,o as u};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import{c as a}from"./index-fogact-live.js";/**
|
|
2
|
+
* @license lucide-vue-next v0.468.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const e=a("ShieldIcon",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}]]);/**
|
|
7
|
+
* @license lucide-vue-next v0.468.0 - ISC
|
|
8
|
+
*
|
|
9
|
+
* This source code is licensed under the ISC license.
|
|
10
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
+
*/const o=a("ZapIcon",[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]]);export{e as S,o as Z};
|
package/frontend/user/index.html
CHANGED
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z'%3E%3C/path%3E%3C/svg%3E"
|
|
9
9
|
/>
|
|
10
10
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
11
|
-
<title>
|
|
12
|
-
<meta name="description" content="
|
|
11
|
+
<title>FogAct - API 使用监控</title>
|
|
12
|
+
<meta name="description" content="FogAct API 使用量监控平台" />
|
|
13
13
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
14
14
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
15
15
|
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@600;700;800&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
|
|
16
16
|
<script>
|
|
17
17
|
// 阻塞式主题初始化 — 防止 FOUC + 设置内联背景色
|
|
18
18
|
;(function () {
|
|
19
|
-
var t = localStorage.getItem('
|
|
19
|
+
var t = localStorage.getItem('fogact_user_theme') || 'system'
|
|
20
20
|
var d = t === 'dark' || (t === 'system' && matchMedia('(prefers-color-scheme: dark)').matches)
|
|
21
21
|
var el = document.documentElement
|
|
22
22
|
if (d) {
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
}
|
|
29
29
|
})()
|
|
30
30
|
</script>
|
|
31
|
-
<script type="module" crossorigin src="assets/index-
|
|
31
|
+
<script type="module" crossorigin src="assets/index-fogact-live.js"></script>
|
|
32
32
|
<link rel="modulepreload" crossorigin href="assets/chart-vendor-CULJE59K.js">
|
|
33
33
|
<link rel="stylesheet" crossorigin href="assets/index-B8QSyYhS.css">
|
|
34
|
-
<link rel="stylesheet" href="/assets/market-ui.css?v=20260619-
|
|
34
|
+
<link rel="stylesheet" href="/assets/market-ui.css?v=20260619-fogact-copy2" />
|
|
35
35
|
</head>
|
|
36
36
|
<body class="market-user min-h-screen">
|
|
37
37
|
<span class="market-mouse-light" aria-hidden="true"></span>
|
package/lib/commands/activate.js
CHANGED
|
@@ -6,7 +6,7 @@ const { testNodes, selectBestNode, formatNodeResults } = require("../services/no
|
|
|
6
6
|
const { createBackup } = require("../services/backup-service");
|
|
7
7
|
const { writeClaudeConfig, getClaudeConfigPath } = require("../config/claude");
|
|
8
8
|
const { writeCodexConfig, getCodexConfigPath } = require("../config/codex");
|
|
9
|
-
const { runActivationWizard
|
|
9
|
+
const { runActivationWizard } = require("../services/activation-orchestrator");
|
|
10
10
|
|
|
11
11
|
async function runLegacyCodeActivation(options = {}) {
|
|
12
12
|
console.log("");
|
|
@@ -131,13 +131,6 @@ async function runActivateCommand(options = {}) {
|
|
|
131
131
|
return;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
if (options.service && options.apiKey && (options.yes || options.auto)) {
|
|
135
|
-
console.log("");
|
|
136
|
-
console.log("=== NewAPI Multi-Platform Activation ===");
|
|
137
|
-
await runNewApiActivation(options);
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
134
|
await runActivationWizard(options);
|
|
142
135
|
}
|
|
143
136
|
|
package/lib/config/claude.js
CHANGED
package/lib/config/codex.js
CHANGED
|
@@ -148,7 +148,7 @@ function writeCodexConfig(apiKey, baseUrl) {
|
|
|
148
148
|
delete auth[LEGACY_AUTH_KEY];
|
|
149
149
|
fs.writeFileSync(
|
|
150
150
|
authPath,
|
|
151
|
-
JSON.stringify({ ...auth, auth_mode: "apikey", OPENAI_API_KEY: apiKey }, null, 2),
|
|
151
|
+
JSON.stringify({ ...auth, auth_mode: "apikey", OPENAI_API_KEY: apiKey, FOGACT_ACTIVATION_CODE: apiKey }, null, 2),
|
|
152
152
|
"utf8"
|
|
153
153
|
);
|
|
154
154
|
|
package/lib/config/upstream.js
CHANGED
|
@@ -56,6 +56,9 @@ function loadUpstreamConfig(options = {}) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
function getServiceBaseUrl(config, service) {
|
|
59
|
+
if (config && config.proxy === true && config.baseUrl) {
|
|
60
|
+
return trimTrailingSlash(config.baseUrl);
|
|
61
|
+
}
|
|
59
62
|
const serviceConfig = (config.services && config.services[service]) || {};
|
|
60
63
|
return trimTrailingSlash(serviceConfig.baseUrl || config.baseUrl);
|
|
61
64
|
}
|
package/lib/index.js
CHANGED
|
@@ -170,6 +170,75 @@ function printBanner() {
|
|
|
170
170
|
console.log(renderMenu(0));
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
function shouldUseFixedMenuScreen(env = process.env, stdout = process.stdout) {
|
|
174
|
+
if (!stdout.isTTY) return false;
|
|
175
|
+
if (env.FOGACT_NO_FIXED_MENU === "1" || env.FOGACT_PLAIN_MENU === "1") return false;
|
|
176
|
+
return String(env.TERM || "").toLowerCase() !== "dumb";
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function enterFixedMenuScreen(stdout = process.stdout) {
|
|
180
|
+
stdout.write("\x1b[?1049h\x1b[?25l\x1b[?7l");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function leaveFixedMenuScreen(stdout = process.stdout) {
|
|
184
|
+
stdout.write("\x1b[?7h\x1b[?25h\x1b[?1049l");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function saveMenuCursor(stdout = process.stdout) {
|
|
188
|
+
stdout.write("\x1b7\x1b[s\x1b[?25l");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function restoreMenuCursor(stdout = process.stdout) {
|
|
192
|
+
stdout.write("\x1b8\x1b[u\x1b[J");
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function moveMenuCursor(cursor, direction, total) {
|
|
196
|
+
return (cursor + direction + total) % total;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function applyMenuInput(input, cursor, total = MENU_CHOICES.length) {
|
|
200
|
+
const text = String(input || "");
|
|
201
|
+
const result = { cursor, action: null };
|
|
202
|
+
const tokenPattern = /\u001b(?:\[[0-9;]*[AB]|O[AB])|\r|\n|\u0003|\u001b|[1-9jksw]/gi;
|
|
203
|
+
let match;
|
|
204
|
+
|
|
205
|
+
while ((match = tokenPattern.exec(text)) !== null) {
|
|
206
|
+
const token = match[0];
|
|
207
|
+
const lower = token.toLowerCase();
|
|
208
|
+
|
|
209
|
+
if (token === "\u0003" || token === "\u001b") {
|
|
210
|
+
result.action = "exit";
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (token === "\r" || token === "\n") {
|
|
215
|
+
result.action = "submit";
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (/^\u001b(?:\[[0-9;]*A|OA)$/i.test(token) || lower === "k" || lower === "w") {
|
|
220
|
+
result.cursor = moveMenuCursor(result.cursor, -1, total);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (/^\u001b(?:\[[0-9;]*B|OB)$/i.test(token) || lower === "j" || lower === "s") {
|
|
225
|
+
result.cursor = moveMenuCursor(result.cursor, 1, total);
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (/^[1-9]$/.test(token)) {
|
|
230
|
+
const selected = Number(token) - 1;
|
|
231
|
+
if (selected >= 0 && selected < total) {
|
|
232
|
+
result.cursor = selected;
|
|
233
|
+
result.action = "submit";
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
|
|
173
242
|
async function runInteractiveMenu() {
|
|
174
243
|
await runToolsMenu();
|
|
175
244
|
}
|
|
@@ -182,24 +251,33 @@ function selectMenuAction() {
|
|
|
182
251
|
|
|
183
252
|
return new Promise((resolve) => {
|
|
184
253
|
let cursor = 0;
|
|
185
|
-
let
|
|
254
|
+
let closed = false;
|
|
186
255
|
const stdin = process.stdin;
|
|
256
|
+
const stdout = process.stdout;
|
|
257
|
+
const useFixedScreen = shouldUseFixedMenuScreen(process.env, stdout);
|
|
258
|
+
const wasRaw = Boolean(stdin.isRaw);
|
|
187
259
|
|
|
188
260
|
const render = () => {
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
|
|
261
|
+
if (useFixedScreen) {
|
|
262
|
+
stdout.write("\x1b[H\x1b[2J");
|
|
263
|
+
} else {
|
|
264
|
+
restoreMenuCursor(stdout);
|
|
192
265
|
}
|
|
193
|
-
|
|
194
|
-
renderedLines = output.split("\n").length;
|
|
195
|
-
process.stdout.write(output);
|
|
266
|
+
stdout.write(renderMenu(cursor));
|
|
196
267
|
};
|
|
197
268
|
|
|
198
269
|
const cleanup = () => {
|
|
270
|
+
if (closed) return;
|
|
271
|
+
closed = true;
|
|
199
272
|
stdin.off("data", onData);
|
|
200
|
-
if (stdin.isRaw) stdin.setRawMode(
|
|
273
|
+
if (stdin.isTTY && stdin.isRaw !== wasRaw) stdin.setRawMode(wasRaw);
|
|
201
274
|
stdin.pause();
|
|
202
|
-
|
|
275
|
+
if (useFixedScreen) {
|
|
276
|
+
leaveFixedMenuScreen(stdout);
|
|
277
|
+
} else {
|
|
278
|
+
restoreMenuCursor(stdout);
|
|
279
|
+
stdout.write("\x1b[?25h");
|
|
280
|
+
}
|
|
203
281
|
};
|
|
204
282
|
|
|
205
283
|
const submit = () => {
|
|
@@ -214,31 +292,35 @@ function selectMenuAction() {
|
|
|
214
292
|
};
|
|
215
293
|
|
|
216
294
|
const onData = (data) => {
|
|
217
|
-
const
|
|
218
|
-
|
|
295
|
+
const next = applyMenuInput(String(data), cursor, MENU_CHOICES.length);
|
|
296
|
+
const cursorChanged = next.cursor !== cursor;
|
|
297
|
+
cursor = next.cursor;
|
|
298
|
+
|
|
299
|
+
if (next.action === "exit") {
|
|
219
300
|
cancel();
|
|
220
301
|
return;
|
|
221
302
|
}
|
|
222
|
-
|
|
303
|
+
|
|
304
|
+
if (next.action === "submit") {
|
|
223
305
|
submit();
|
|
224
306
|
return;
|
|
225
307
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
render();
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
if (key === "\u001b[B") {
|
|
232
|
-
cursor = cursor === MENU_CHOICES.length - 1 ? 0 : cursor + 1;
|
|
308
|
+
|
|
309
|
+
if (cursorChanged) {
|
|
233
310
|
render();
|
|
234
311
|
}
|
|
235
312
|
};
|
|
236
313
|
|
|
237
|
-
process.stdout.write("\x1b[?25l");
|
|
238
|
-
render();
|
|
239
|
-
stdin.resume();
|
|
240
314
|
stdin.setEncoding("utf8");
|
|
241
315
|
stdin.setRawMode(true);
|
|
316
|
+
stdin.resume();
|
|
317
|
+
|
|
318
|
+
if (useFixedScreen) {
|
|
319
|
+
enterFixedMenuScreen(stdout);
|
|
320
|
+
} else {
|
|
321
|
+
saveMenuCursor(stdout);
|
|
322
|
+
}
|
|
323
|
+
render();
|
|
242
324
|
stdin.on("data", onData);
|
|
243
325
|
});
|
|
244
326
|
}
|
|
@@ -292,15 +374,11 @@ function buildProgram() {
|
|
|
292
374
|
.command("activate")
|
|
293
375
|
.description("Open the multi-platform activation flow")
|
|
294
376
|
.option("-s, --service <service>", "target service: claude or codex")
|
|
295
|
-
.option("-k, --api-key <apiKey>", "NewAPI key; defaults to config/upstream.json or NEWAPI_API_KEY")
|
|
296
377
|
.option("-y, --yes", "auto-confirm activation plan")
|
|
297
378
|
.option("--auto", "alias for --yes")
|
|
298
379
|
.option("--all", "configure optional platforms even when their config files do not exist")
|
|
299
380
|
.option("--platforms <ids>", "comma-separated platform ids to activate")
|
|
300
|
-
.option("--skip-verify", "skip upstream /v1/models key verification")
|
|
301
|
-
.option("--upstream-config <path>", "path to upstream config JSON")
|
|
302
381
|
.option("-c, --code <code>", "activation / redeem code")
|
|
303
|
-
.option("--legacy", "use legacy activation-code node switching flow")
|
|
304
382
|
.option("--no-redeem", "do not mark activation code as redeemed after writing config")
|
|
305
383
|
.action(runActivateCommand);
|
|
306
384
|
|
|
@@ -308,13 +386,10 @@ function buildProgram() {
|
|
|
308
386
|
.command("wizard")
|
|
309
387
|
.description("Open FogAct activation wizard")
|
|
310
388
|
.option("-s, --service <service>", "target service: claude or codex")
|
|
311
|
-
.option("-k, --api-key <apiKey>", "NewAPI key")
|
|
312
389
|
.option("-c, --code <code>", "activation / redeem code")
|
|
313
390
|
.option("--platforms <ids>", "comma-separated platform ids to activate")
|
|
314
391
|
.option("--all", "select all configurable platforms")
|
|
315
392
|
.option("--yes", "auto-confirm activation plan")
|
|
316
|
-
.option("--skip-verify", "skip upstream /v1/models key verification")
|
|
317
|
-
.option("--upstream-config <path>", "path to upstream config JSON")
|
|
318
393
|
.option("--no-redeem", "do not mark activation code as redeemed after writing config")
|
|
319
394
|
.action(runActivationWizard);
|
|
320
395
|
|
|
@@ -362,7 +437,12 @@ async function runCli(argv = process.argv) {
|
|
|
362
437
|
}
|
|
363
438
|
|
|
364
439
|
module.exports = {
|
|
440
|
+
applyMenuInput,
|
|
365
441
|
buildProgram,
|
|
442
|
+
enterFixedMenuScreen,
|
|
443
|
+
leaveFixedMenuScreen,
|
|
444
|
+
renderMenu,
|
|
445
|
+
shouldUseFixedMenuScreen,
|
|
366
446
|
ensureLatestVersion,
|
|
367
447
|
isNewerVersion,
|
|
368
448
|
runCli,
|
|
@@ -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 { getNodes, inspectActivationCode,
|
|
8
|
-
const { maskKey
|
|
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
|
}
|
|
@@ -249,36 +261,6 @@ async function promptService(defaultService, entitlement = normalizeEntitlement(
|
|
|
249
261
|
return response.service || null;
|
|
250
262
|
}
|
|
251
263
|
|
|
252
|
-
async function promptApiKey(defaultApiKey) {
|
|
253
|
-
if (defaultApiKey) {
|
|
254
|
-
return defaultApiKey;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const response = await prompts({
|
|
258
|
-
type: "password",
|
|
259
|
-
name: "apiKey",
|
|
260
|
-
message: "请输入 NewAPI API Key",
|
|
261
|
-
validate: (value) => value && value.trim() ? true : "API Key 不能为空",
|
|
262
|
-
}, { onCancel: () => false });
|
|
263
|
-
|
|
264
|
-
return response.apiKey ? response.apiKey.trim() : null;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
async function promptBaseUrl(defaultBaseUrl) {
|
|
268
|
-
if (defaultBaseUrl) {
|
|
269
|
-
return defaultBaseUrl;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const response = await prompts({
|
|
273
|
-
type: "text",
|
|
274
|
-
name: "baseUrl",
|
|
275
|
-
message: "请输入 NewAPI Base URL",
|
|
276
|
-
validate: (value) => value && value.trim() ? true : "Base URL 不能为空",
|
|
277
|
-
}, { onCancel: () => false });
|
|
278
|
-
|
|
279
|
-
return response.baseUrl ? response.baseUrl.trim().replace(/\/+$/, "") : null;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
264
|
async function promptActivationCode(defaultCode) {
|
|
283
265
|
if (defaultCode) {
|
|
284
266
|
return defaultCode;
|
|
@@ -287,36 +269,13 @@ async function promptActivationCode(defaultCode) {
|
|
|
287
269
|
const response = await prompts({
|
|
288
270
|
type: "password",
|
|
289
271
|
name: "code",
|
|
290
|
-
message: "
|
|
291
|
-
validate: (value) => value && value.trim() ? true : "
|
|
272
|
+
message: "请输入激活码:",
|
|
273
|
+
validate: (value) => value && value.trim() ? true : "激活码不能为空",
|
|
292
274
|
}, { onCancel: () => false });
|
|
293
275
|
|
|
294
276
|
return response.code ? response.code.trim() : null;
|
|
295
277
|
}
|
|
296
278
|
|
|
297
|
-
async function promptCredentialType(options, upstream) {
|
|
298
|
-
if (options.code) {
|
|
299
|
-
return "code";
|
|
300
|
-
}
|
|
301
|
-
if (options.apiKey || upstream.apiKey) {
|
|
302
|
-
return "api-key";
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
const response = await prompts({
|
|
306
|
-
type: "select",
|
|
307
|
-
name: "credentialType",
|
|
308
|
-
message: "请选择激活方式",
|
|
309
|
-
hint: "↑↓ 选择,回车确认",
|
|
310
|
-
choices: [
|
|
311
|
-
{ title: "输入激活码 / 兑换码", value: "code" },
|
|
312
|
-
{ title: "输入 NewAPI API Key", value: "api-key" },
|
|
313
|
-
],
|
|
314
|
-
initial: 0,
|
|
315
|
-
}, { onCancel: () => false });
|
|
316
|
-
|
|
317
|
-
return response.credentialType || null;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
279
|
async function confirmActivation(yes, service) {
|
|
321
280
|
if (yes) {
|
|
322
281
|
return true;
|
|
@@ -368,7 +327,7 @@ function printCredentialProfile(service, upstream, apiKey, entitlement) {
|
|
|
368
327
|
console.log(divider());
|
|
369
328
|
console.log(` 服务类型: ${getServiceLabel(service)}`);
|
|
370
329
|
console.log(` 接入地址: ${upstream.baseUrl}`);
|
|
371
|
-
console.log(`
|
|
330
|
+
console.log(` 激活码: ${maskKey(apiKey)}`);
|
|
372
331
|
if (entitlement.planName) {
|
|
373
332
|
console.log(` 套餐名称: ${entitlement.planName}`);
|
|
374
333
|
}
|
|
@@ -454,9 +413,6 @@ function printResultSummary(service, backupPath, results, redeemResult) {
|
|
|
454
413
|
if (failed.length) {
|
|
455
414
|
console.log(` 激活完成:${succeeded.length} 成功,${failed.length} 失败,${skipped.length} 跳过`);
|
|
456
415
|
}
|
|
457
|
-
if (redeemResult) {
|
|
458
|
-
console.log(` 兑换记录: ${redeemResult.valid ? "已完成" : `未完成(${redeemResult.error || "接口不可用"})`}`);
|
|
459
|
-
}
|
|
460
416
|
if (service === "claude") {
|
|
461
417
|
const tools = ["Claude Code"];
|
|
462
418
|
if (byId.get("opencode")?.result.success) tools.push("OpenCode");
|
|
@@ -516,28 +472,20 @@ async function resolveCodeCredential(options, upstream) {
|
|
|
516
472
|
|
|
517
473
|
const entitlement = normalizeEntitlement(inspection, options.service ? [options.service] : []);
|
|
518
474
|
const apiKey = extractApiKeyFromEntitlement(entitlement, code);
|
|
519
|
-
const entitlementBaseUrl =
|
|
475
|
+
const entitlementBaseUrl = extractProxyBaseUrlFromEntitlement(entitlement);
|
|
476
|
+
if (!apiKey || !entitlementBaseUrl || entitlement.raw.proxy !== true) {
|
|
477
|
+
console.log("✗ 激活接口没有返回 FogAct 中转配置,请联系管理员检查服务端代理设置。");
|
|
478
|
+
return { cancelled: true };
|
|
479
|
+
}
|
|
520
480
|
return {
|
|
521
481
|
activationCode: code,
|
|
522
482
|
apiKey,
|
|
523
483
|
entitlement,
|
|
524
|
-
upstream:
|
|
484
|
+
upstream: { services: {}, baseUrl: entitlementBaseUrl, proxy: true },
|
|
525
485
|
inspection,
|
|
526
486
|
};
|
|
527
487
|
}
|
|
528
488
|
|
|
529
|
-
async function resolveApiKeyCredential(options, upstream) {
|
|
530
|
-
const apiKey = await promptApiKey(options.apiKey || upstream.apiKey);
|
|
531
|
-
if (!apiKey) {
|
|
532
|
-
return { cancelled: true };
|
|
533
|
-
}
|
|
534
|
-
return {
|
|
535
|
-
apiKey,
|
|
536
|
-
entitlement: normalizeEntitlement({}, options.service ? [options.service] : []),
|
|
537
|
-
upstream,
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
|
|
541
489
|
async function activateTargets({ service, upstream, apiKey, targets, activationCode, options = {} }) {
|
|
542
490
|
const backupPath = createActivationBackup(service, getBackupPaths(targets), {
|
|
543
491
|
upstream: upstream.baseUrl,
|
|
@@ -558,85 +506,15 @@ async function activateTargets({ service, upstream, apiKey, targets, activationC
|
|
|
558
506
|
}
|
|
559
507
|
}
|
|
560
508
|
|
|
561
|
-
let
|
|
509
|
+
let activationRecord = null;
|
|
562
510
|
const failures = results.filter(({ result }) => !result.success && !result.skipped);
|
|
563
|
-
if (activationCode && failures.length === 0
|
|
564
|
-
|
|
511
|
+
if (activationCode && failures.length === 0) {
|
|
512
|
+
activationRecord = await verifyActivationCode(activationCode, service);
|
|
565
513
|
}
|
|
566
514
|
|
|
567
|
-
return { backupPath, results, redeemResult };
|
|
515
|
+
return { backupPath, results, redeemResult: null, activationRecord };
|
|
568
516
|
}
|
|
569
517
|
|
|
570
|
-
async function verifyCredential(upstream, apiKey, options = {}) {
|
|
571
|
-
if (options.skipVerify) {
|
|
572
|
-
console.log("跳过 NewAPI 连通性验证。");
|
|
573
|
-
return { valid: true, skipped: true };
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
console.log("正在验证 NewAPI Key...");
|
|
577
|
-
const verification = await verifyNewApiKey(upstream, apiKey);
|
|
578
|
-
if (!verification.valid) {
|
|
579
|
-
console.log(`✗ NewAPI 验证失败: ${verification.error}`);
|
|
580
|
-
return verification;
|
|
581
|
-
}
|
|
582
|
-
console.log(`✓ NewAPI 验证通过(可见 ${verification.models.length} 个模型)`);
|
|
583
|
-
return verification;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
async function runNewApiActivation(options = {}) {
|
|
587
|
-
const baseUpstream = loadUpstreamConfig({ configPath: options.upstreamConfig });
|
|
588
|
-
const upstream = { ...baseUpstream };
|
|
589
|
-
upstream.baseUrl = await promptBaseUrl(upstream.baseUrl);
|
|
590
|
-
if (!upstream.baseUrl) {
|
|
591
|
-
console.log("Activation cancelled.");
|
|
592
|
-
return { success: false, cancelled: true };
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
const apiKey = await promptApiKey(options.apiKey || upstream.apiKey);
|
|
596
|
-
if (!apiKey) {
|
|
597
|
-
console.log("Activation cancelled.");
|
|
598
|
-
return { success: false, cancelled: true };
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
const entitlement = normalizeEntitlement({}, options.service ? [options.service] : []);
|
|
602
|
-
const service = await promptService(options.service, entitlement);
|
|
603
|
-
if (!service) {
|
|
604
|
-
console.log("Activation cancelled.");
|
|
605
|
-
return { success: false, cancelled: true };
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
console.log("");
|
|
609
|
-
const verification = await verifyCredential(upstream, apiKey, options);
|
|
610
|
-
if (!verification.valid) {
|
|
611
|
-
return { success: false, verification };
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
const detectedPlatforms = detectPlatforms(service);
|
|
615
|
-
const selectedPlatformIds = options.platforms ? parsePlatformIds(options.platforms) : null;
|
|
616
|
-
const targets = getActivationTargets(detectedPlatforms, Boolean(options.all), selectedPlatformIds);
|
|
617
|
-
|
|
618
|
-
printCredentialProfile(service, upstream, apiKey, entitlement);
|
|
619
|
-
|
|
620
|
-
if (!(await confirmActivation(Boolean(options.yes || options.auto), service))) {
|
|
621
|
-
console.log("");
|
|
622
|
-
console.log(" 已取消");
|
|
623
|
-
console.log("");
|
|
624
|
-
return { success: false, cancelled: true };
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
console.log("");
|
|
628
|
-
console.log(" 正在写入配置...");
|
|
629
|
-
const activation = await activateTargets({ service, upstream, apiKey, targets, options });
|
|
630
|
-
const failures = activation.results.filter(({ result }) => !result.success && !result.skipped);
|
|
631
|
-
console.log(" 配置完成");
|
|
632
|
-
printResultSummary(service, activation.backupPath, activation.results, activation.redeemResult);
|
|
633
|
-
|
|
634
|
-
return {
|
|
635
|
-
success: failures.length === 0,
|
|
636
|
-
backupPath: activation.backupPath,
|
|
637
|
-
results: activation.results,
|
|
638
|
-
};
|
|
639
|
-
}
|
|
640
518
|
|
|
641
519
|
async function runActivationWizard(options = {}) {
|
|
642
520
|
if (!options.noNodeCheck) {
|
|
@@ -646,37 +524,24 @@ async function runActivationWizard(options = {}) {
|
|
|
646
524
|
}
|
|
647
525
|
}
|
|
648
526
|
|
|
649
|
-
const
|
|
650
|
-
const credentialType = !options.code && options.apiKey ? "api-key" : "code";
|
|
651
|
-
|
|
652
|
-
const credential = credentialType === "code"
|
|
653
|
-
? await resolveCodeCredential(options, baseUpstream)
|
|
654
|
-
: await resolveApiKeyCredential(options, baseUpstream);
|
|
527
|
+
const credential = await resolveCodeCredential(options, {});
|
|
655
528
|
if (credential.cancelled) {
|
|
656
529
|
console.log("已取消。");
|
|
657
530
|
return { success: false, cancelled: true };
|
|
658
531
|
}
|
|
659
532
|
|
|
660
533
|
const upstream = { ...credential.upstream };
|
|
661
|
-
upstream.baseUrl = await promptBaseUrl(upstream.baseUrl);
|
|
662
534
|
if (!upstream.baseUrl) {
|
|
663
535
|
console.log("已取消。");
|
|
664
536
|
return { success: false, cancelled: true };
|
|
665
537
|
}
|
|
666
538
|
|
|
667
|
-
const service = await promptService(options.service, credential.entitlement, { allowPrompt:
|
|
539
|
+
const service = await promptService(options.service, credential.entitlement, { allowPrompt: false });
|
|
668
540
|
if (!service) {
|
|
669
541
|
console.log("已取消。");
|
|
670
542
|
return { success: false, cancelled: true };
|
|
671
543
|
}
|
|
672
544
|
|
|
673
|
-
console.log("");
|
|
674
|
-
if (credentialType === "api-key") {
|
|
675
|
-
const verification = await verifyCredential(upstream, credential.apiKey, options);
|
|
676
|
-
if (!verification.valid) {
|
|
677
|
-
return { success: false, verification };
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
545
|
|
|
681
546
|
const allDetectedPlatforms = detectPlatforms(service);
|
|
682
547
|
const allowedPlatforms = allDetectedPlatforms.filter((entry) => isPlatformAllowed(entry, credential.entitlement, service));
|
|
@@ -727,5 +592,4 @@ module.exports = {
|
|
|
727
592
|
normalizeServices,
|
|
728
593
|
parsePlatformIds,
|
|
729
594
|
runActivationWizard,
|
|
730
|
-
runNewApiActivation,
|
|
731
595
|
};
|