fogact 1.2.2 → 1.2.4

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.
Files changed (39) hide show
  1. package/bin/web-server.js +557 -141
  2. package/config/upstream.example.json +1 -1
  3. package/frontend/user/assets/AnnouncementDetail-Dvxmwz0A-fogact-live.js +12 -0
  4. package/frontend/user/assets/Announcements-CS1tF2mx-fogact-live.js +11 -0
  5. package/frontend/user/assets/CardBind-CsCxihhP-fogact-live.js +21 -0
  6. package/frontend/user/assets/CardContent.vue_vue_type_script_setup_true_lang-D2L-uqSl-fogact-live.js +1 -0
  7. package/frontend/user/assets/CardDescription.vue_vue_type_script_setup_true_lang-D-v5Pl7F-fogact-live.js +1 -0
  8. package/frontend/user/assets/CardTitle.vue_vue_type_script_setup_true_lang-a0CCN6D5-fogact-live.js +1 -0
  9. package/frontend/user/assets/Dashboard-rPsmltm5-fogact-live.js +51 -0
  10. package/frontend/user/assets/DashboardLayout-DDkxHYFj-fogact-live.js +80 -0
  11. package/frontend/user/assets/Input.vue_vue_type_script_setup_true_lang-B0SyPmYb-fogact-live.js +6 -0
  12. package/frontend/user/assets/Label.vue_vue_type_script_setup_true_lang-CxYORSgN-fogact-live.js +1 -0
  13. package/frontend/user/assets/Progress.vue_vue_type_script_setup_true_lang-2_QbPsEQ-fogact-live.js +1 -0
  14. package/frontend/user/assets/QuotaPack-B_tJ7Psm-fogact-live.js +6 -0
  15. package/frontend/user/assets/Renewal-BSDhDmwv-fogact-live.js +6 -0
  16. package/frontend/user/assets/ScrollArea.vue_vue_type_script_setup_true_lang-DMYwcfpz-fogact-live.js +1 -0
  17. package/frontend/user/assets/Separator.vue_vue_type_script_setup_true_lang-Ckg8EXj_-fogact-live.js +1 -0
  18. package/frontend/user/assets/Settings-CBdAa3lw-fogact-live.js +11 -0
  19. package/frontend/user/assets/TooltipTrigger.vue_vue_type_script_setup_true_lang-DtSBjzGo-fogact-live.js +16 -0
  20. package/frontend/user/assets/Welcome-Dtfp6oER-fogact-live.js +1 -0
  21. package/frontend/user/assets/_plugin-vue_export-helper-5cjT4u0R-fogact-live.js +16 -0
  22. package/frontend/user/assets/activity-wYWtyqTJ-fogact-live.js +6 -0
  23. package/frontend/user/assets/announcement-35mOnjRL-fogact-live.js +16 -0
  24. package/frontend/user/assets/calendar-BFNuCata-fogact-live.js +6 -0
  25. package/frontend/user/assets/chevron-down-kDbuU1Py-fogact-live.js +6 -0
  26. package/frontend/user/assets/chevron-right-BayASIm0-fogact-live.js +6 -0
  27. package/frontend/user/assets/eye-CY62vip0-fogact-live.js +6 -0
  28. package/frontend/user/assets/gauge-C5NQ-mV8-fogact-live.js +6 -0
  29. package/frontend/user/assets/index-fogact-live.js +91 -0
  30. package/frontend/user/assets/link-2-DT5R5nGO-fogact-live.js +6 -0
  31. package/frontend/user/assets/package-rUbExUEn-fogact-live.js +6 -0
  32. package/frontend/user/assets/plus-CQc6C8wG-fogact-live.js +11 -0
  33. package/frontend/user/assets/refresh-cw-Y9hCloPL-fogact-live.js +6 -0
  34. package/frontend/user/assets/useUserPageRefresh-BYZvpNR9-fogact-live.js +1 -0
  35. package/frontend/user/assets/zap-l5zbZqrM-fogact-live.js +11 -0
  36. package/frontend/user/index.html +1 -1
  37. package/lib/index.js +91 -13
  38. package/lib/services/database.js +47 -0
  39. 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};
@@ -28,7 +28,7 @@
28
28
  }
29
29
  })()
30
30
  </script>
31
- <script type="module" crossorigin src="assets/index-Da98HOxL.js?v=20260619-fogact-loading-fix"></script>
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
34
  <link rel="stylesheet" href="/assets/market-ui.css?v=20260619-fogact-copy2" />
package/lib/index.js CHANGED
@@ -170,6 +170,28 @@ 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
+
173
195
  function moveMenuCursor(cursor, direction, total) {
174
196
  return (cursor + direction + total) % total;
175
197
  }
@@ -221,6 +243,41 @@ async function runInteractiveMenu() {
221
243
  await runToolsMenu();
222
244
  }
223
245
 
246
+ function waitForMenuReturn(message = "按回车返回菜单...") {
247
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
248
+ return Promise.resolve();
249
+ }
250
+
251
+ return new Promise((resolve) => {
252
+ const stdin = process.stdin;
253
+ const wasRaw = Boolean(stdin.isRaw);
254
+ let closed = false;
255
+
256
+ const cleanup = () => {
257
+ if (closed) return;
258
+ closed = true;
259
+ stdin.off("data", onData);
260
+ if (stdin.isTTY && stdin.isRaw !== wasRaw) stdin.setRawMode(wasRaw);
261
+ stdin.pause();
262
+ process.stdout.write("\n");
263
+ resolve();
264
+ };
265
+
266
+ const onData = (data) => {
267
+ const value = String(data);
268
+ if (value.includes("\u0003") || value.includes("\u001b") || value.includes("\r") || value.includes("\n")) {
269
+ cleanup();
270
+ }
271
+ };
272
+
273
+ process.stdout.write(` ${message}`);
274
+ stdin.setEncoding("utf8");
275
+ stdin.setRawMode(true);
276
+ stdin.resume();
277
+ stdin.on("data", onData);
278
+ });
279
+ }
280
+
224
281
  function selectMenuAction() {
225
282
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
226
283
  printBanner();
@@ -229,24 +286,33 @@ function selectMenuAction() {
229
286
 
230
287
  return new Promise((resolve) => {
231
288
  let cursor = 0;
232
- let renderedLines = 0;
289
+ let closed = false;
233
290
  const stdin = process.stdin;
291
+ const stdout = process.stdout;
292
+ const useFixedScreen = shouldUseFixedMenuScreen(process.env, stdout);
293
+ const wasRaw = Boolean(stdin.isRaw);
234
294
 
235
295
  const render = () => {
236
- if (renderedLines > 0) {
237
- process.stdout.write(`\x1b[${renderedLines}A`);
238
- process.stdout.write("\x1b[J");
296
+ if (useFixedScreen) {
297
+ stdout.write("\x1b[H\x1b[2J");
298
+ } else {
299
+ restoreMenuCursor(stdout);
239
300
  }
240
- const output = renderMenu(cursor);
241
- renderedLines = output.split("\n").length;
242
- process.stdout.write(output);
301
+ stdout.write(renderMenu(cursor));
243
302
  };
244
303
 
245
304
  const cleanup = () => {
305
+ if (closed) return;
306
+ closed = true;
246
307
  stdin.off("data", onData);
247
- if (stdin.isRaw) stdin.setRawMode(false);
308
+ if (stdin.isTTY && stdin.isRaw !== wasRaw) stdin.setRawMode(wasRaw);
248
309
  stdin.pause();
249
- process.stdout.write("\x1b[?25h\n");
310
+ if (useFixedScreen) {
311
+ leaveFixedMenuScreen(stdout);
312
+ } else {
313
+ restoreMenuCursor(stdout);
314
+ stdout.write("\x1b[?25h");
315
+ }
250
316
  };
251
317
 
252
318
  const submit = () => {
@@ -261,7 +327,7 @@ function selectMenuAction() {
261
327
  };
262
328
 
263
329
  const onData = (data) => {
264
- const next = applyMenuInput(data.toString("utf8"), cursor, MENU_CHOICES.length);
330
+ const next = applyMenuInput(String(data), cursor, MENU_CHOICES.length);
265
331
  const cursorChanged = next.cursor !== cursor;
266
332
  cursor = next.cursor;
267
333
 
@@ -280,11 +346,16 @@ function selectMenuAction() {
280
346
  }
281
347
  };
282
348
 
283
- process.stdout.write("\x1b[?25l");
284
- render();
285
- stdin.resume();
286
349
  stdin.setEncoding("utf8");
287
350
  stdin.setRawMode(true);
351
+ stdin.resume();
352
+
353
+ if (useFixedScreen) {
354
+ enterFixedMenuScreen(stdout);
355
+ } else {
356
+ saveMenuCursor(stdout);
357
+ }
358
+ render();
288
359
  stdin.on("data", onData);
289
360
  });
290
361
  }
@@ -299,9 +370,11 @@ async function runToolsMenu() {
299
370
  break;
300
371
  case "test":
301
372
  await runTestCommand();
373
+ await waitForMenuReturn();
302
374
  break;
303
375
  case "restore":
304
376
  await runRestoreCommand();
377
+ await waitForMenuReturn();
305
378
  break;
306
379
  default:
307
380
  console.log("");
@@ -403,10 +476,15 @@ async function runCli(argv = process.argv) {
403
476
  module.exports = {
404
477
  applyMenuInput,
405
478
  buildProgram,
479
+ enterFixedMenuScreen,
480
+ leaveFixedMenuScreen,
481
+ renderMenu,
482
+ shouldUseFixedMenuScreen,
406
483
  ensureLatestVersion,
407
484
  isNewerVersion,
408
485
  runCli,
409
486
  runInteractiveMenu,
410
487
  runToolsMenu,
411
488
  runWebServer,
489
+ waitForMenuReturn,
412
490
  };
@@ -6,6 +6,7 @@ const path = require("path");
6
6
  const DATA_DIR = path.join(__dirname, "..", "..", "data");
7
7
  const USERS_FILE = path.join(DATA_DIR, "users.json");
8
8
  const CODES_FILE = path.join(DATA_DIR, "codes.json");
9
+ const USAGE_FILE = path.join(DATA_DIR, "usage.json");
9
10
 
10
11
  // 确保数据目录存在
11
12
  function ensureDataDir() {
@@ -257,6 +258,51 @@ const codeDb = {
257
258
  },
258
259
  };
259
260
 
261
+ // 用量日志数据库操作
262
+ const usageDb = {
263
+ getAll() {
264
+ return readJsonFile(USAGE_FILE, []);
265
+ },
266
+
267
+ create(usageData) {
268
+ const items = this.getAll();
269
+ const now = new Date().toISOString();
270
+ const newItem = {
271
+ id: usageData.id || `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
272
+ codeId: usageData.codeId || null,
273
+ code: usageData.code || null,
274
+ service: usageData.service || "claude",
275
+ model: usageData.model || "unknown",
276
+ inputTokens: Number(usageData.inputTokens || 0),
277
+ outputTokens: Number(usageData.outputTokens || 0),
278
+ totalTokens: Number(usageData.totalTokens || 0),
279
+ requests: Number(usageData.requests || 1),
280
+ statusCode: usageData.statusCode || null,
281
+ success: usageData.success !== false,
282
+ cost: Number(usageData.cost || 0),
283
+ path: usageData.path || null,
284
+ createdAt: usageData.createdAt || now,
285
+ };
286
+ items.push(newItem);
287
+ writeJsonFile(USAGE_FILE, items);
288
+ return newItem;
289
+ },
290
+
291
+ getByCode(code) {
292
+ const value = String(code || "").trim();
293
+ if (!value) return [];
294
+ return this.getAll().filter((item) => item.code === value);
295
+ },
296
+
297
+ getSince(code, since) {
298
+ const sinceTime = since ? new Date(since).getTime() : 0;
299
+ return this.getByCode(code).filter((item) => {
300
+ const createdAt = new Date(item.createdAt || 0).getTime();
301
+ return Number.isFinite(createdAt) && createdAt >= sinceTime;
302
+ });
303
+ },
304
+ };
305
+
260
306
  // 初始化示例数据
261
307
  function initializeSampleData() {
262
308
  ensureDataDir();
@@ -457,5 +503,6 @@ function initializeSampleData() {
457
503
  module.exports = {
458
504
  userDb,
459
505
  codeDb,
506
+ usageDb,
460
507
  initializeSampleData,
461
508
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fogact",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "FogAct activation helper for Claude Code and Codex",
5
5
  "keywords": [
6
6
  "fogact",