fogact 1.1.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/LICENSE +21 -0
- package/README.md +244 -0
- package/README.zh-CN.md +244 -0
- package/bin/cli.js +9 -0
- package/bin/web-server.js +1434 -0
- package/config/upstream.example.json +14 -0
- package/frontend/activate.html +249 -0
- package/frontend/admin/admin-panel-v2.js +1899 -0
- package/frontend/admin/index.html +705 -0
- package/frontend/assets/market-ui.css +1876 -0
- package/frontend/color-test.html +136 -0
- package/frontend/index.html +191 -0
- package/frontend/user/assets/AnnouncementDetail-Dvxmwz0A.js +12 -0
- package/frontend/user/assets/Announcements-CS1tF2mx.js +11 -0
- package/frontend/user/assets/CardBind-CsCxihhP.js +21 -0
- package/frontend/user/assets/CardContent.vue_vue_type_script_setup_true_lang-D2L-uqSl.js +1 -0
- package/frontend/user/assets/CardDescription.vue_vue_type_script_setup_true_lang-D-v5Pl7F.js +1 -0
- package/frontend/user/assets/CardTitle.vue_vue_type_script_setup_true_lang-a0CCN6D5.js +1 -0
- package/frontend/user/assets/Dashboard-rPsmltm5.js +51 -0
- package/frontend/user/assets/DashboardLayout-BUCWGlXC.css +1 -0
- package/frontend/user/assets/DashboardLayout-DDkxHYFj.js +80 -0
- package/frontend/user/assets/Input.vue_vue_type_script_setup_true_lang-B0SyPmYb.js +6 -0
- package/frontend/user/assets/Label.vue_vue_type_script_setup_true_lang-CxYORSgN.js +1 -0
- package/frontend/user/assets/Progress.vue_vue_type_script_setup_true_lang-2_QbPsEQ.js +1 -0
- package/frontend/user/assets/QuotaPack-B_tJ7Psm.js +6 -0
- package/frontend/user/assets/Renewal-BSDhDmwv.js +6 -0
- package/frontend/user/assets/ScrollArea.vue_vue_type_script_setup_true_lang-DMYwcfpz.js +1 -0
- package/frontend/user/assets/Separator.vue_vue_type_script_setup_true_lang-Ckg8EXj_.js +1 -0
- package/frontend/user/assets/Settings-CBdAa3lw.js +11 -0
- package/frontend/user/assets/TooltipTrigger.vue_vue_type_script_setup_true_lang-DtSBjzGo.js +16 -0
- package/frontend/user/assets/Welcome-7IfzEli4.css +1 -0
- package/frontend/user/assets/Welcome-Dtfp6oER.js +1 -0
- package/frontend/user/assets/_plugin-vue_export-helper-5cjT4u0R.js +16 -0
- package/frontend/user/assets/activity-wYWtyqTJ.js +6 -0
- package/frontend/user/assets/announcement-35mOnjRL.js +16 -0
- package/frontend/user/assets/calendar-BFNuCata.js +6 -0
- package/frontend/user/assets/chart-vendor-CULJE59K.js +37 -0
- package/frontend/user/assets/chevron-down-kDbuU1Py.js +6 -0
- package/frontend/user/assets/chevron-right-BayASIm0.js +6 -0
- package/frontend/user/assets/eye-CY62vip0.js +6 -0
- package/frontend/user/assets/gauge-C5NQ-mV8.js +6 -0
- package/frontend/user/assets/index-B8QSyYhS.css +1 -0
- package/frontend/user/assets/index-Da98HOxL.js +91 -0
- package/frontend/user/assets/link-2-DT5R5nGO.js +6 -0
- package/frontend/user/assets/package-rUbExUEn.js +6 -0
- package/frontend/user/assets/plus-CQc6C8wG.js +11 -0
- package/frontend/user/assets/refresh-cw-Y9hCloPL.js +6 -0
- package/frontend/user/assets/useUserPageRefresh-BYZvpNR9.js +1 -0
- package/frontend/user/assets/zap-l5zbZqrM.js +11 -0
- package/frontend/user/index.html +67 -0
- package/install.sh +402 -0
- package/lib/commands/activate.js +144 -0
- package/lib/commands/restore.js +102 -0
- package/lib/commands/test.js +40 -0
- package/lib/config/claude.js +81 -0
- package/lib/config/codex.js +164 -0
- package/lib/config/upstream.js +79 -0
- package/lib/index.js +164 -0
- package/lib/platforms/claude-code.js +35 -0
- package/lib/platforms/codex-cli.js +35 -0
- package/lib/platforms/editor-codex.js +138 -0
- package/lib/platforms/index.js +32 -0
- package/lib/platforms/openclaw.js +118 -0
- package/lib/platforms/opencode.js +89 -0
- package/lib/services/activation-orchestrator.js +666 -0
- package/lib/services/backup-service.js +162 -0
- package/lib/services/cliproxy-api.js +174 -0
- package/lib/services/database.js +461 -0
- package/lib/services/newapi.js +97 -0
- package/lib/services/node-service.js +49 -0
- package/lib/utils/json-file.js +33 -0
- package/package.json +53 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{c as e}from"./index-Da98HOxL.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-Da98HOxL.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-Da98HOxL.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-Da98HOxL.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-Da98HOxL.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-Da98HOxL.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};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN" data-theme="silk">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link
|
|
6
|
+
rel="icon"
|
|
7
|
+
type="image/svg+xml"
|
|
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
|
+
/>
|
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
11
|
+
<title>CLIProxy - API 使用监控</title>
|
|
12
|
+
<meta name="description" content="CLIProxy API 使用量监控平台" />
|
|
13
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
14
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
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
|
+
<script>
|
|
17
|
+
// 阻塞式主题初始化 — 防止 FOUC + 设置内联背景色
|
|
18
|
+
;(function () {
|
|
19
|
+
var t = localStorage.getItem('yunyi_user_theme') || 'system'
|
|
20
|
+
var d = t === 'dark' || (t === 'system' && matchMedia('(prefers-color-scheme: dark)').matches)
|
|
21
|
+
var el = document.documentElement
|
|
22
|
+
if (d) {
|
|
23
|
+
el.classList.add('dark')
|
|
24
|
+
el.style.colorScheme = 'dark'
|
|
25
|
+
el.style.backgroundColor = 'hsl(240, 10%, 3.9%)'
|
|
26
|
+
} else {
|
|
27
|
+
el.style.backgroundColor = 'hsl(210, 40%, 98%)'
|
|
28
|
+
}
|
|
29
|
+
})()
|
|
30
|
+
</script>
|
|
31
|
+
<script type="module" crossorigin src="assets/index-Da98HOxL.js"></script>
|
|
32
|
+
<link rel="modulepreload" crossorigin href="assets/chart-vendor-CULJE59K.js">
|
|
33
|
+
<link rel="stylesheet" crossorigin href="assets/index-B8QSyYhS.css">
|
|
34
|
+
<link rel="stylesheet" href="/assets/market-ui.css?v=20260616-upstream2" />
|
|
35
|
+
</head>
|
|
36
|
+
<body class="market-user min-h-screen">
|
|
37
|
+
<span class="market-mouse-light" aria-hidden="true"></span>
|
|
38
|
+
<div id="app">
|
|
39
|
+
<!-- 纯 CSS 加载占位,Vue 挂载后自动替换 -->
|
|
40
|
+
<div style="display:flex;align-items:center;justify-content:center;height:100vh;opacity:0.4">
|
|
41
|
+
<svg width="24" height="24" viewBox="0 0 24 24" style="animation:_s .8s linear infinite">
|
|
42
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"
|
|
43
|
+
stroke-dasharray="31.4 31.4" stroke-linecap="round"/>
|
|
44
|
+
</svg>
|
|
45
|
+
</div>
|
|
46
|
+
<style>@keyframes _s{to{transform:rotate(360deg)}}</style>
|
|
47
|
+
</div>
|
|
48
|
+
<script>
|
|
49
|
+
let marketPointerRaf = 0
|
|
50
|
+
window.addEventListener('load', function () {
|
|
51
|
+
requestAnimationFrame(function () {
|
|
52
|
+
document.body.classList.add('motion-ready')
|
|
53
|
+
})
|
|
54
|
+
}, { once: true })
|
|
55
|
+
|
|
56
|
+
window.addEventListener('pointermove', function (event) {
|
|
57
|
+
if (marketPointerRaf) return
|
|
58
|
+
marketPointerRaf = requestAnimationFrame(function () {
|
|
59
|
+
document.body.classList.add('is-pointer-active')
|
|
60
|
+
document.body.style.setProperty('--cursor-x', event.clientX + 'px')
|
|
61
|
+
document.body.style.setProperty('--cursor-y', event.clientY + 'px')
|
|
62
|
+
marketPointerRaf = 0
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
</script>
|
|
66
|
+
</body>
|
|
67
|
+
</html>
|
package/install.sh
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
|
|
4
|
+
PACKAGE_NAME="${FOGIDC_PACKAGE:-fogact}"
|
|
5
|
+
GITHUB_REPO="${FOGIDC_GITHUB_REPO:-FogMaly/cliproxy-activator}"
|
|
6
|
+
GIT_REF="${FOGIDC_GIT_REF:-main}"
|
|
7
|
+
INSTALL_METHOD="${FOGIDC_INSTALL_METHOD:-npm}"
|
|
8
|
+
INSTALL_DIR="${FOGIDC_INSTALL_DIR:-}"
|
|
9
|
+
SERVICE="${FOGIDC_SERVICE:-}"
|
|
10
|
+
CODE="${FOGIDC_CODE:-}"
|
|
11
|
+
API_KEY="${NEWAPI_API_KEY:-${FOGIDC_API_KEY:-}}"
|
|
12
|
+
BASE_URL="${NEWAPI_BASE_URL:-${FOGIDC_BASE_URL:-}}"
|
|
13
|
+
CLIPROXY_BASE="${CLIPROXY_API_BASE:-}"
|
|
14
|
+
PLATFORMS="${FOGIDC_PLATFORMS:-}"
|
|
15
|
+
RUN_WEB="${FOGIDC_RUN_WEB:-0}"
|
|
16
|
+
WEB_PORT="${PORT:-${FOGIDC_WEB_PORT:-34020}}"
|
|
17
|
+
ADMIN_PASSWORD_VALUE="${ADMIN_PASSWORD:-${FOGIDC_ADMIN_PASSWORD:-}}"
|
|
18
|
+
SKIP_VERIFY="${FOGIDC_SKIP_VERIFY:-0}"
|
|
19
|
+
ALL_PLATFORMS="${FOGIDC_ALL:-0}"
|
|
20
|
+
NO_ACTIVATE="${FOGIDC_NO_ACTIVATE:-0}"
|
|
21
|
+
NO_REDEEM="${FOGIDC_NO_REDEEM:-0}"
|
|
22
|
+
CREATE_SYSTEMD="${FOGIDC_SYSTEMD:-0}"
|
|
23
|
+
|
|
24
|
+
log() { printf '%s\n' "==> $*"; }
|
|
25
|
+
warn() { printf '%s\n' "WARN: $*" >&2; }
|
|
26
|
+
fail() { printf '%s\n' "ERROR: $*" >&2; exit 1; }
|
|
27
|
+
has() { command -v "$1" >/dev/null 2>&1; }
|
|
28
|
+
is_root() { [ "$(id -u 2>/dev/null || echo 1)" = "0" ]; }
|
|
29
|
+
|
|
30
|
+
usage() {
|
|
31
|
+
cat <<'EOF'
|
|
32
|
+
FogAct bootstrap installer
|
|
33
|
+
|
|
34
|
+
Usage:
|
|
35
|
+
curl -fsSL https://raw.githubusercontent.com/FogMaly/cliproxy-activator/main/install.sh | sh
|
|
36
|
+
curl -fsSL https://raw.githubusercontent.com/FogMaly/cliproxy-activator/main/install.sh | sh -s -- --service codex --code YOUR_CODE
|
|
37
|
+
|
|
38
|
+
Options:
|
|
39
|
+
--service <codex|claude> Activate a specific service after install
|
|
40
|
+
--code <code> Activation / redeem code
|
|
41
|
+
--api-key <key> NewAPI key for direct activation
|
|
42
|
+
--base-url <url> NewAPI base URL for direct activation
|
|
43
|
+
--cliproxy-api-base <url> Activation backend URL for code mode
|
|
44
|
+
--platforms <ids> Comma-separated target platform ids
|
|
45
|
+
--all Configure all creatable optional platforms
|
|
46
|
+
--skip-verify Skip NewAPI /v1/models verification
|
|
47
|
+
--no-redeem Do not mark activation code as redeemed
|
|
48
|
+
--no-activate Install only
|
|
49
|
+
--web Start local Web UI after install
|
|
50
|
+
--systemd Create and start a systemd Web UI service
|
|
51
|
+
--method <npm|github> Install from npm package or GitHub source
|
|
52
|
+
--install-dir <path> GitHub source install directory
|
|
53
|
+
-h, --help Show help
|
|
54
|
+
|
|
55
|
+
Environment variables mirror the options:
|
|
56
|
+
FOGIDC_PACKAGE=fogact, FOGIDC_SERVICE, FOGIDC_CODE, NEWAPI_BASE_URL, NEWAPI_API_KEY,
|
|
57
|
+
CLIPROXY_API_BASE, FOGIDC_PLATFORMS, FOGIDC_ALL=1,
|
|
58
|
+
FOGIDC_SKIP_VERIFY=1, FOGIDC_RUN_WEB=1, FOGIDC_SYSTEMD=1
|
|
59
|
+
EOF
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
while [ "$#" -gt 0 ]; do
|
|
63
|
+
case "$1" in
|
|
64
|
+
--service) SERVICE="${2:-}"; shift 2 ;;
|
|
65
|
+
--code) CODE="${2:-}"; shift 2 ;;
|
|
66
|
+
--api-key) API_KEY="${2:-}"; shift 2 ;;
|
|
67
|
+
--base-url) BASE_URL="${2:-}"; shift 2 ;;
|
|
68
|
+
--cliproxy-api-base) CLIPROXY_BASE="${2:-}"; shift 2 ;;
|
|
69
|
+
--platforms) PLATFORMS="${2:-}"; shift 2 ;;
|
|
70
|
+
--all) ALL_PLATFORMS=1; shift ;;
|
|
71
|
+
--skip-verify) SKIP_VERIFY=1; shift ;;
|
|
72
|
+
--no-redeem) NO_REDEEM=1; shift ;;
|
|
73
|
+
--no-activate) NO_ACTIVATE=1; shift ;;
|
|
74
|
+
--web) RUN_WEB=1; shift ;;
|
|
75
|
+
--systemd) CREATE_SYSTEMD=1; RUN_WEB=1; shift ;;
|
|
76
|
+
--method) INSTALL_METHOD="${2:-}"; shift 2 ;;
|
|
77
|
+
--install-dir) INSTALL_DIR="${2:-}"; shift 2 ;;
|
|
78
|
+
-h|--help) usage; exit 0 ;;
|
|
79
|
+
*) fail "Unknown option: $1" ;;
|
|
80
|
+
esac
|
|
81
|
+
done
|
|
82
|
+
|
|
83
|
+
run_sudo() {
|
|
84
|
+
if is_root; then
|
|
85
|
+
"$@"
|
|
86
|
+
elif has sudo; then
|
|
87
|
+
sudo "$@"
|
|
88
|
+
else
|
|
89
|
+
fail "Need root or sudo to install missing system packages. Install Node.js 16+ manually, then rerun."
|
|
90
|
+
fi
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
node_major() {
|
|
94
|
+
node -p "Number(process.versions.node.split('.')[0])" 2>/dev/null || echo 0
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
node_ok() {
|
|
98
|
+
has node && has npm && [ "$(node_major)" -ge 16 ]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
install_node_system() {
|
|
102
|
+
log "Node.js 16+ not found; installing Node.js"
|
|
103
|
+
|
|
104
|
+
if has apt-get; then
|
|
105
|
+
run_sudo apt-get update
|
|
106
|
+
run_sudo apt-get install -y ca-certificates curl gnupg
|
|
107
|
+
if has curl; then
|
|
108
|
+
if curl -fsSL https://deb.nodesource.com/setup_20.x | run_sudo bash -; then
|
|
109
|
+
run_sudo apt-get install -y nodejs
|
|
110
|
+
else
|
|
111
|
+
warn "NodeSource setup failed; falling back to distro nodejs/npm"
|
|
112
|
+
run_sudo apt-get install -y nodejs npm
|
|
113
|
+
fi
|
|
114
|
+
else
|
|
115
|
+
run_sudo apt-get install -y nodejs npm
|
|
116
|
+
fi
|
|
117
|
+
return
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
if has dnf; then
|
|
121
|
+
run_sudo dnf install -y ca-certificates curl
|
|
122
|
+
if has curl && curl -fsSL https://rpm.nodesource.com/setup_20.x | run_sudo bash -; then
|
|
123
|
+
run_sudo dnf install -y nodejs
|
|
124
|
+
else
|
|
125
|
+
warn "NodeSource setup failed; falling back to distro nodejs/npm"
|
|
126
|
+
run_sudo dnf install -y nodejs npm
|
|
127
|
+
fi
|
|
128
|
+
return
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
if has yum; then
|
|
132
|
+
run_sudo yum install -y ca-certificates curl
|
|
133
|
+
if has curl && curl -fsSL https://rpm.nodesource.com/setup_20.x | run_sudo bash -; then
|
|
134
|
+
run_sudo yum install -y nodejs
|
|
135
|
+
else
|
|
136
|
+
warn "NodeSource setup failed; falling back to distro nodejs/npm"
|
|
137
|
+
run_sudo yum install -y nodejs npm
|
|
138
|
+
fi
|
|
139
|
+
return
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
if has apk; then
|
|
143
|
+
run_sudo apk add --no-cache nodejs npm
|
|
144
|
+
return
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
if has pacman; then
|
|
148
|
+
run_sudo pacman -Sy --noconfirm nodejs npm
|
|
149
|
+
return
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
if has zypper; then
|
|
153
|
+
run_sudo zypper --non-interactive install nodejs20 npm20 || run_sudo zypper --non-interactive install nodejs npm
|
|
154
|
+
return
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
if has brew; then
|
|
158
|
+
brew install node
|
|
159
|
+
return
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
fail "Unsupported OS package manager. Install Node.js 16+ and npm, then rerun."
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
ensure_node() {
|
|
166
|
+
if node_ok; then
|
|
167
|
+
log "Node.js $(node -v) and npm $(npm -v) detected"
|
|
168
|
+
return
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
install_node_system
|
|
172
|
+
|
|
173
|
+
if ! node_ok; then
|
|
174
|
+
fail "Node.js 16+ and npm are still unavailable after installation."
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
log "Node.js $(node -v) and npm $(npm -v) ready"
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
ensure_global_npm_prefix() {
|
|
181
|
+
prefix="$(npm config get prefix 2>/dev/null || echo /usr/local)"
|
|
182
|
+
bindir="$prefix/bin"
|
|
183
|
+
|
|
184
|
+
if is_root || [ -w "$prefix" ] || [ -w "$bindir" ]; then
|
|
185
|
+
return
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
user_prefix="${HOME:-$PWD}/.local"
|
|
189
|
+
log "Global npm prefix is not writable; using $user_prefix"
|
|
190
|
+
mkdir -p "$user_prefix/bin"
|
|
191
|
+
npm config set prefix "$user_prefix" >/dev/null
|
|
192
|
+
PATH="$user_prefix/bin:$PATH"
|
|
193
|
+
export PATH
|
|
194
|
+
|
|
195
|
+
case ":$PATH:" in
|
|
196
|
+
*":$user_prefix/bin:"*) : ;;
|
|
197
|
+
*) PATH="$user_prefix/bin:$PATH"; export PATH ;;
|
|
198
|
+
esac
|
|
199
|
+
|
|
200
|
+
shell_rc="${HOME:-}/.profile"
|
|
201
|
+
if [ -n "${HOME:-}" ] && [ -f "$shell_rc" ] && ! grep -q 'export PATH="$HOME/.local/bin:$PATH"' "$shell_rc" 2>/dev/null; then
|
|
202
|
+
printf '\n# FogAct npm global binaries\nexport PATH="$HOME/.local/bin:$PATH"\n' >> "$shell_rc" || true
|
|
203
|
+
fi
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
ensure_git() {
|
|
207
|
+
if has git; then
|
|
208
|
+
return
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
log "git not found; installing git"
|
|
212
|
+
if has apt-get; then run_sudo apt-get update && run_sudo apt-get install -y git; return; fi
|
|
213
|
+
if has dnf; then run_sudo dnf install -y git; return; fi
|
|
214
|
+
if has yum; then run_sudo yum install -y git; return; fi
|
|
215
|
+
if has apk; then run_sudo apk add --no-cache git; return; fi
|
|
216
|
+
if has pacman; then run_sudo pacman -Sy --noconfirm git; return; fi
|
|
217
|
+
if has zypper; then run_sudo zypper --non-interactive install git; return; fi
|
|
218
|
+
if has brew; then brew install git; return; fi
|
|
219
|
+
fail "git is required for --method github. Install git, then rerun."
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
install_from_npm() {
|
|
223
|
+
ensure_global_npm_prefix
|
|
224
|
+
log "Installing $PACKAGE_NAME from npm"
|
|
225
|
+
npm install -g "$PACKAGE_NAME@latest"
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
install_from_github() {
|
|
229
|
+
ensure_git
|
|
230
|
+
if [ -z "$INSTALL_DIR" ]; then
|
|
231
|
+
if is_root; then
|
|
232
|
+
INSTALL_DIR="/opt/fogact"
|
|
233
|
+
else
|
|
234
|
+
INSTALL_DIR="${HOME:-$PWD}/.local/share/fogact"
|
|
235
|
+
fi
|
|
236
|
+
fi
|
|
237
|
+
|
|
238
|
+
log "Installing from GitHub: $GITHUB_REPO#$GIT_REF"
|
|
239
|
+
if [ -d "$INSTALL_DIR/.git" ]; then
|
|
240
|
+
git -C "$INSTALL_DIR" fetch --depth 1 origin "$GIT_REF"
|
|
241
|
+
git -C "$INSTALL_DIR" checkout -q FETCH_HEAD
|
|
242
|
+
else
|
|
243
|
+
mkdir -p "$(dirname "$INSTALL_DIR")"
|
|
244
|
+
rm -rf "$INSTALL_DIR"
|
|
245
|
+
git clone --depth 1 --branch "$GIT_REF" "https://github.com/$GITHUB_REPO.git" "$INSTALL_DIR"
|
|
246
|
+
fi
|
|
247
|
+
|
|
248
|
+
(cd "$INSTALL_DIR" && npm install)
|
|
249
|
+
|
|
250
|
+
fogact_cli() {
|
|
251
|
+
node "$INSTALL_DIR/bin/cli.js" "$@"
|
|
252
|
+
}
|
|
253
|
+
fogact_web() {
|
|
254
|
+
node "$INSTALL_DIR/bin/web-server.js" "$@"
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
find_public_ip() {
|
|
259
|
+
if has curl; then
|
|
260
|
+
curl -fsS --max-time 3 https://api.ipify.org 2>/dev/null || true
|
|
261
|
+
elif has wget; then
|
|
262
|
+
wget -qO- --timeout=3 https://api.ipify.org 2>/dev/null || true
|
|
263
|
+
fi
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
start_web_background() {
|
|
267
|
+
log "Starting FogAct Web UI on port $WEB_PORT"
|
|
268
|
+
log_dir="${HOME:-$PWD}/.fogact/logs"
|
|
269
|
+
mkdir -p "$log_dir"
|
|
270
|
+
|
|
271
|
+
if has fogact-web; then
|
|
272
|
+
PORT="$WEB_PORT" ADMIN_PASSWORD="$ADMIN_PASSWORD_VALUE" nohup fogact-web > "$log_dir/web.log" 2>&1 &
|
|
273
|
+
else
|
|
274
|
+
PORT="$WEB_PORT" ADMIN_PASSWORD="$ADMIN_PASSWORD_VALUE" nohup sh -c 'node "$1"' sh "$INSTALL_DIR/bin/web-server.js" > "$log_dir/web.log" 2>&1 &
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
sleep 2
|
|
278
|
+
log "Web UI log: $log_dir/web.log"
|
|
279
|
+
log "Local: http://127.0.0.1:$WEB_PORT/"
|
|
280
|
+
public_ip="$(find_public_ip)"
|
|
281
|
+
if [ -n "$public_ip" ]; then
|
|
282
|
+
log "Public: http://$public_ip:$WEB_PORT/"
|
|
283
|
+
fi
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
create_systemd_service() {
|
|
287
|
+
if ! has systemctl; then
|
|
288
|
+
warn "systemd not found; falling back to background start"
|
|
289
|
+
start_web_background
|
|
290
|
+
return
|
|
291
|
+
fi
|
|
292
|
+
|
|
293
|
+
if ! is_root; then
|
|
294
|
+
warn "systemd service creation needs root; falling back to background start"
|
|
295
|
+
start_web_background
|
|
296
|
+
return
|
|
297
|
+
fi
|
|
298
|
+
|
|
299
|
+
web_bin="$(command -v fogact-web 2>/dev/null || true)"
|
|
300
|
+
if [ -z "$web_bin" ] && [ -n "$INSTALL_DIR" ]; then
|
|
301
|
+
web_bin="/usr/bin/node $INSTALL_DIR/bin/web-server.js"
|
|
302
|
+
fi
|
|
303
|
+
[ -n "$web_bin" ] || fail "Cannot locate fogact-web binary for systemd service."
|
|
304
|
+
|
|
305
|
+
cat > /etc/systemd/system/fogact-web.service <<EOF
|
|
306
|
+
[Unit]
|
|
307
|
+
Description=FogAct Web UI
|
|
308
|
+
After=network.target
|
|
309
|
+
|
|
310
|
+
[Service]
|
|
311
|
+
Type=simple
|
|
312
|
+
Environment=PORT=$WEB_PORT
|
|
313
|
+
Environment=ADMIN_PASSWORD=$ADMIN_PASSWORD_VALUE
|
|
314
|
+
ExecStart=$web_bin
|
|
315
|
+
Restart=on-failure
|
|
316
|
+
RestartSec=3
|
|
317
|
+
|
|
318
|
+
[Install]
|
|
319
|
+
WantedBy=multi-user.target
|
|
320
|
+
EOF
|
|
321
|
+
|
|
322
|
+
systemctl daemon-reload
|
|
323
|
+
systemctl enable --now fogact-web.service
|
|
324
|
+
log "systemd service started: fogact-web.service"
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
run_activation() {
|
|
328
|
+
if [ "$NO_ACTIVATE" = "1" ]; then
|
|
329
|
+
return
|
|
330
|
+
fi
|
|
331
|
+
|
|
332
|
+
if [ -z "$SERVICE" ] && [ -z "$CODE" ] && [ -z "$API_KEY" ]; then
|
|
333
|
+
log "Install complete. No activation options supplied."
|
|
334
|
+
print_next_steps
|
|
335
|
+
return
|
|
336
|
+
fi
|
|
337
|
+
|
|
338
|
+
if [ -n "$BASE_URL" ]; then export NEWAPI_BASE_URL="$BASE_URL"; fi
|
|
339
|
+
if [ -n "$API_KEY" ]; then export NEWAPI_API_KEY="$API_KEY"; fi
|
|
340
|
+
if [ -n "$CLIPROXY_BASE" ]; then export CLIPROXY_API_BASE="$CLIPROXY_BASE"; fi
|
|
341
|
+
|
|
342
|
+
set -- wizard --yes
|
|
343
|
+
if [ -n "$SERVICE" ]; then set -- "$@" --service "$SERVICE"; fi
|
|
344
|
+
if [ -n "$CODE" ]; then set -- "$@" --code "$CODE"; fi
|
|
345
|
+
if [ -n "$API_KEY" ]; then set -- "$@" --api-key "$API_KEY"; fi
|
|
346
|
+
if [ -n "$PLATFORMS" ]; then set -- "$@" --platforms "$PLATFORMS"; fi
|
|
347
|
+
if [ "$ALL_PLATFORMS" = "1" ]; then set -- "$@" --all; fi
|
|
348
|
+
if [ "$SKIP_VERIFY" = "1" ]; then set -- "$@" --skip-verify; fi
|
|
349
|
+
if [ "$NO_REDEEM" = "1" ]; then set -- "$@" --no-redeem; fi
|
|
350
|
+
|
|
351
|
+
log "Running activation"
|
|
352
|
+
if [ "$INSTALL_METHOD" = "github" ]; then
|
|
353
|
+
node "$INSTALL_DIR/bin/cli.js" "$@"
|
|
354
|
+
else
|
|
355
|
+
fogact "$@"
|
|
356
|
+
fi
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
print_next_steps() {
|
|
360
|
+
cat <<EOF
|
|
361
|
+
|
|
362
|
+
Next commands:
|
|
363
|
+
fogact --help
|
|
364
|
+
fogact wizard --code YOUR_CODE --yes
|
|
365
|
+
fogact activate --service codex --yes
|
|
366
|
+
fogact-web
|
|
367
|
+
|
|
368
|
+
For code mode with a remote activation backend:
|
|
369
|
+
export CLIPROXY_API_BASE="https://your-activator.example.com"
|
|
370
|
+
fogact wizard --code YOUR_CODE --yes
|
|
371
|
+
|
|
372
|
+
For direct NewAPI mode:
|
|
373
|
+
export NEWAPI_BASE_URL="https://newapi.example.com"
|
|
374
|
+
export NEWAPI_API_KEY="sk-your-key"
|
|
375
|
+
fogact activate --service codex --yes
|
|
376
|
+
EOF
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
main() {
|
|
380
|
+
log "FogAct bootstrap"
|
|
381
|
+
ensure_node
|
|
382
|
+
|
|
383
|
+
case "$INSTALL_METHOD" in
|
|
384
|
+
npm) install_from_npm ;;
|
|
385
|
+
github) install_from_github ;;
|
|
386
|
+
*) fail "Unsupported install method: $INSTALL_METHOD" ;;
|
|
387
|
+
esac
|
|
388
|
+
|
|
389
|
+
run_activation
|
|
390
|
+
|
|
391
|
+
if [ "$RUN_WEB" = "1" ]; then
|
|
392
|
+
if [ "$CREATE_SYSTEMD" = "1" ]; then
|
|
393
|
+
create_systemd_service
|
|
394
|
+
else
|
|
395
|
+
start_web_background
|
|
396
|
+
fi
|
|
397
|
+
fi
|
|
398
|
+
|
|
399
|
+
log "Done"
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
main
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const prompts = require("prompts");
|
|
4
|
+
const { verifyActivationCode, getNodes } = require("../services/cliproxy-api");
|
|
5
|
+
const { testNodes, selectBestNode, formatNodeResults } = require("../services/node-service");
|
|
6
|
+
const { createBackup } = require("../services/backup-service");
|
|
7
|
+
const { writeClaudeConfig, getClaudeConfigPath } = require("../config/claude");
|
|
8
|
+
const { writeCodexConfig, getCodexConfigPath } = require("../config/codex");
|
|
9
|
+
const { runActivationWizard, runNewApiActivation } = require("../services/activation-orchestrator");
|
|
10
|
+
|
|
11
|
+
async function runLegacyCodeActivation(options = {}) {
|
|
12
|
+
console.log("");
|
|
13
|
+
console.log("=== CLIProxy Activation (Legacy Code Mode) ===");
|
|
14
|
+
console.log("");
|
|
15
|
+
|
|
16
|
+
let service = options.service;
|
|
17
|
+
if (!service) {
|
|
18
|
+
const response = await prompts({
|
|
19
|
+
type: "select",
|
|
20
|
+
name: "service",
|
|
21
|
+
message: "Select service to activate",
|
|
22
|
+
choices: [
|
|
23
|
+
{ title: "Claude Code", value: "claude" },
|
|
24
|
+
{ title: "Codex", value: "codex" },
|
|
25
|
+
],
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (!response.service) {
|
|
29
|
+
console.log("Activation cancelled.");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
service = response.service;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let code = options.code;
|
|
37
|
+
if (!code) {
|
|
38
|
+
const response = await prompts({
|
|
39
|
+
type: "text",
|
|
40
|
+
name: "code",
|
|
41
|
+
message: "Enter activation code",
|
|
42
|
+
validate: (value) => value.length > 0 || "Activation code is required",
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (!response.code) {
|
|
46
|
+
console.log("Activation cancelled.");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
code = response.code;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log("");
|
|
54
|
+
console.log("Verifying activation code...");
|
|
55
|
+
|
|
56
|
+
const verification = await verifyActivationCode(code, service);
|
|
57
|
+
|
|
58
|
+
if (!verification.valid) {
|
|
59
|
+
console.log("");
|
|
60
|
+
console.log("✗ Activation failed:", verification.error);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log("✓ Activation code verified");
|
|
65
|
+
console.log("");
|
|
66
|
+
console.log("Testing available nodes...");
|
|
67
|
+
|
|
68
|
+
let nodes = verification.nodes;
|
|
69
|
+
if (!nodes || nodes.length === 0) {
|
|
70
|
+
nodes = await getNodes(service);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (nodes.length === 0) {
|
|
74
|
+
console.log("✗ No nodes available");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const testResults = await testNodes(nodes);
|
|
79
|
+
console.log("");
|
|
80
|
+
console.log(formatNodeResults(testResults));
|
|
81
|
+
|
|
82
|
+
const bestNode = selectBestNode(testResults);
|
|
83
|
+
|
|
84
|
+
if (!bestNode) {
|
|
85
|
+
console.log("");
|
|
86
|
+
console.log("✗ No available nodes found");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log("");
|
|
91
|
+
console.log(`✓ Selected node: ${bestNode.name || bestNode.url} (${bestNode.latency}ms)`);
|
|
92
|
+
|
|
93
|
+
const configPath = service === "claude" ? getClaudeConfigPath() : getCodexConfigPath();
|
|
94
|
+
|
|
95
|
+
console.log("");
|
|
96
|
+
console.log("Creating backup...");
|
|
97
|
+
|
|
98
|
+
const backupPath = createBackup(service, configPath);
|
|
99
|
+
|
|
100
|
+
if (backupPath) {
|
|
101
|
+
console.log(`✓ Backup created: ${backupPath}`);
|
|
102
|
+
} else {
|
|
103
|
+
console.log("ℹ No existing config to backup");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
console.log("");
|
|
107
|
+
console.log("Writing configuration...");
|
|
108
|
+
|
|
109
|
+
let writtenPath;
|
|
110
|
+
if (service === "claude") {
|
|
111
|
+
writtenPath = writeClaudeConfig(code, bestNode.url);
|
|
112
|
+
} else {
|
|
113
|
+
writtenPath = writeCodexConfig(code, bestNode.url);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
console.log(`✓ Configuration written: ${writtenPath}`);
|
|
117
|
+
console.log("");
|
|
118
|
+
console.log("=== Activation Complete ===");
|
|
119
|
+
console.log("");
|
|
120
|
+
console.log(`Service: ${service === "claude" ? "Claude Code" : "Codex"}`);
|
|
121
|
+
console.log(`Node: ${bestNode.url}`);
|
|
122
|
+
console.log(`Config: ${writtenPath}`);
|
|
123
|
+
console.log("");
|
|
124
|
+
console.log("Please restart your application to apply changes.");
|
|
125
|
+
console.log("");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function runActivateCommand(options = {}) {
|
|
129
|
+
if (options.legacy && options.code) {
|
|
130
|
+
await runLegacyCodeActivation(options);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
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
|
+
await runActivationWizard(options);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
module.exports = { runActivateCommand, runLegacyCodeActivation };
|