8900 commited on
Commit
84d2859
·
verified ·
1 Parent(s): 78cfc1f

Update setup-hf-config.mjs

Browse files
Files changed (1) hide show
  1. setup-hf-config.mjs +235 -157
setup-hf-config.mjs CHANGED
@@ -5,47 +5,50 @@ import https from "node:https";
5
  var HOME = process.env.OPENCLAW_HOME || process.env.HOME || "/home/user";
6
  var STATE_DIR = path.join(HOME, ".openclaw");
7
  var CONFIG_PATH = path.join(STATE_DIR, "openclaw.json");
8
- var AUTH_PROFILES_PATH = path.join(STATE_DIR, "auth-profiles.json");
 
 
9
  var SPACE_HOST = (process.env.SPACE_HOST || "").trim();
10
 
11
  console.log("[setup] Starting… HOME=" + HOME);
 
12
 
13
- // – helpers –
14
  function parseList(val) {
15
- if (!val || !val.trim()) return [];
16
- return val.split(",").map(function(s){ return s.trim(); }).filter(Boolean);
17
  }
18
  function envStr(key) { return (process.env[key] || "").trim(); }
19
 
20
- // – auth –
21
  var gatewayToken = envStr("OPENCLAW_GATEWAY_TOKEN");
22
  var gatewayPassword = envStr("OPENCLAW_GATEWAY_PASSWORD");
23
  if (!gatewayToken && !gatewayPassword) {
24
- console.error("[setup] FATAL: set OPENCLAW_GATEWAY_TOKEN or OPENCLAW_GATEWAY_PASSWORD in Secrets");
25
- process.exit(0);
26
  }
27
 
28
- // – default model –
29
  var defaultModel = envStr("OPENCLAW_HF_DEFAULT_MODEL") || "google/gemini-2.0-flash";
30
 
31
- // – dynamic provider key detection –
32
  var EXCLUDE_PREFIXES = [
33
- "OPENCLAW_", "SPACE_", "SYSTEM_", "HF_",
34
- "NODE_", "PATH", "HOME", "USER", "PWD", "LANG", "LC_",
35
- "npm_", "HOSTNAME", "SHELL", "TERM", "SHLVL"
36
  ];
37
  var INCLUDE_SUFFIXES = [
38
- "_API_KEY", "_SECRET_KEY", "_ACCESS_TOKEN",
39
- "_BOT_TOKEN", "_AUTH_TOKEN", "_APP_KEY",
40
- "_SESSION_KEY", "_COOKIE", "_TOKEN"
41
  ];
42
  function isProviderKey(k){
43
- for (let i=0;i<EXCLUDE_PREFIXES.length;i++){ if(k.indexOf(EXCLUDE_PREFIXES[i])===0) return false; }
44
- for (let i=0;i<INCLUDE_SUFFIXES.length;i++){
45
- let s=INCLUDE_SUFFIXES[i];
46
- if(k.length>s.length && k.indexOf(s)===k.length-s.length) return true;
47
- }
48
- return false;
49
  }
50
 
51
  var allKeys = Object.keys(process.env);
@@ -54,163 +57,238 @@ providerKeys.sort();
54
  console.log("[setup] Detected provider keys ("+providerKeys.length+"):");
55
  providerKeys.forEach(k=>console.log(" + "+k));
56
 
57
- // – trusted proxies –
58
  var envProxies = parseList(envStr("OPENCLAW_GATEWAY_TRUSTED_PROXIES"));
59
  var trustedProxies = envProxies.length>0 ? envProxies : [
60
- "10.16.0.0/12","10.20.0.0/12",
61
- "10.16.4.123","10.16.7.92","10.16.18.232",
62
- "10.16.34.155","10.16.43.133","10.16.1.206",
63
- "10.16.37.110","10.16.43.246",
64
- "10.20.1.9","10.20.1.222",
65
- "10.20.26.157","10.20.31.87",
66
- "10.20.0.1","172.17.0.1"
67
  ];
68
 
69
- // – build config –
70
  var config = {
71
- gateway: {
72
- auth: gatewayToken ? { mode:"token", token:gatewayToken } : { mode:"password", password:gatewayPassword },
73
- controlUi: { allowInsecureAuth:true, allowedOrigins:["*"], dangerouslyDisableDeviceAuth:true, dangerouslyAllowHostHeaderOriginFallback:true },
74
- trustedProxies: trustedProxies
75
- },
76
- agents: { defaults:{ model:defaultModel } },
77
- env: { vars:{} }
78
  };
79
 
80
  // 添加所有检测到的 provider keys 到环境变量
81
  providerKeys.forEach(pk=>{ config.env.vars[pk] = envStr(pk); });
82
 
83
- // – Telegram webhook setup –
84
  async function setupTelegram(){
85
- var token = envStr("TELEGRAM_BOT_TOKEN");
86
- if(!token){ console.log("[setup] Telegram: disabled (no TELEGRAM_BOT_TOKEN)"); return; }
87
-
88
- if(SPACE_HOST){
89
- var webhookUrl = "https://" + SPACE_HOST + "/tg-webhook";
90
- var r = await new Promise(resolve=>{
91
- var data = JSON.stringify({ url:webhookUrl, drop_pending_updates:true, max_connections:10 });
92
- var req = https.request({
93
- hostname: "api.telegram.org",
94
- path: "/bot"+token+"/setWebhook",
95
- method: "POST",
96
- headers: { "Content-Type":"application/json", "Content-Length": Buffer.byteLength(data) }
97
- }, res=>{
98
- let buf="";
99
- res.on("data",c=>buf+=c);
100
- res.on("end", ()=>{ try{ resolve(JSON.parse(buf)) } catch(e){ resolve(null) } });
101
- });
102
- req.on("error", ()=>resolve(null));
103
- req.setTimeout(8000, ()=>{ req.destroy(); resolve(null); });
104
- req.write(data);
105
- req.end();
106
- });
107
- if(r && r.ok) console.log("[setup] Telegram: webhook registered -> "+webhookUrl);
108
- else {
109
- console.log("[setup] Telegram: auto-registration failed (HF outbound blocked)");
110
- console.log("[setup] Telegram: open this URL in your browser once:");
111
- console.log(" https://api.telegram.org/bot"+token+"/setWebhook?url="+webhookUrl+"&drop_pending_updates=true");
112
- }
113
- } else {
114
- console.log("[setup] Telegram: set SPACE_HOST in Variables for auto webhook registration");
115
- }
116
 
117
- config.channels = { telegram:{ enabled:true, accounts:{ main:{ botToken:token, apiRoot:"https://api.telegram.org" } } } };
118
- console.log("[setup] Telegram: configured");
119
  }
120
 
121
- // ⭐ 核心修复:创建 auth-profiles.json
122
  async function setupAuthProfiles(){
123
- var authProfiles = {};
124
-
125
- // OpenAI
126
- if (envStr("OPENAI_ACCESS_TOKEN")) {
127
- var openaiToken = envStr("OPENAI_ACCESS_TOKEN");
128
- authProfiles["openai"] = {
129
- name: "OpenAI",
130
- auth: { mode: "token", token: openaiToken },
131
- models: ["gpt-4o", "gpt-4-turbo", "gpt-4-mini", "gpt-3.5-turbo"]
132
- };
133
- authProfiles["openai-codex"] = {
134
- name: "OpenAI Codex",
135
- auth: { mode: "token", token: openaiToken },
136
- models: ["gpt-4o", "gpt-4-turbo", "gpt-4-mini", "gpt-3.5-turbo"]
137
- };
138
- console.log("[setup] ✓ OpenAI token bound to auth-profiles");
139
- }
140
 
141
- // Anthropic Claude
142
- if (envStr("ANTHROPIC_SESSION_KEY")) {
143
- var claudeToken = envStr("ANTHROPIC_SESSION_KEY");
144
- authProfiles["anthropic"] = {
145
- name: "Anthropic Claude",
146
- auth: { mode: "token", token: claudeToken },
147
- models: ["claude-3-opus", "claude-3-sonnet", "claude-3-haiku"]
148
- };
149
- console.log("[setup] ✓ Anthropic token bound to auth-profiles");
150
- }
 
 
 
 
 
151
 
152
- // Moonshot Kimi
153
- if (envStr("MOONSHOT_ACCESS_TOKEN")) {
154
- var kimiToken = envStr("MOONSHOT_ACCESS_TOKEN");
155
- authProfiles["moonshot"] = {
156
- name: "Moonshot Kimi",
157
- auth: { mode: "token", token: kimiToken },
158
- models: ["moonshot-v1-128k", "moonshot-v1-32k"]
159
- };
160
- console.log("[setup] ✓ Moonshot token bound to auth-profiles");
161
- }
162
 
163
- // Google Gemini (作为 API Key)
164
- if (envStr("GOOGLE_GEMINI_COOKIE")) {
165
- var geminiCookie = envStr("GOOGLE_GEMINI_COOKIE");
166
- // 尝试作为 API Key 存储(如果是通过 Cookie)
167
- authProfiles["google"] = {
168
- name: "Google Gemini",
169
- auth: { mode: "token", token: geminiCookie },
170
- models: ["gemini-2.0-flash", "gemini-1.5-pro", "gemini-1.5-flash"]
171
- };
172
- authProfiles["google-gemini-cli"] = {
173
- name: "Google Gemini CLI",
174
- auth: { mode: "token", token: geminiCookie },
175
- models: ["gemini-2.0-flash", "gemini-1.5-pro", "gemini-1.5-flash"]
176
- };
177
- console.log("[setup] ✓ Google Gemini cookie bound to auth-profiles");
178
- }
179
 
180
- // 通义千问
181
- if (envStr("QWEN_COOKIE")) {
182
- var qwenCookie = envStr("QWEN_COOKIE");
183
- authProfiles["qianwen"] = {
184
- name: "Alibaba Qwen",
185
- auth: { mode: "token", token: qwenCookie },
186
- models: ["qwen-max", "qwen-plus", "qwen-turbo"]
187
- };
188
- console.log("[setup] ✓ Qwen cookie bound to auth-profiles");
189
- }
 
 
 
 
 
190
 
191
- // 如果有认证信息,保存到 auth-profiles.json
192
- if (Object.keys(authProfiles).length > 0) {
193
- try {
194
- fs.writeFileSync(AUTH_PROFILES_PATH, JSON.stringify(authProfiles, null, 2), "utf-8");
195
- console.log("[setup] auth-profiles.json created with " + Object.keys(authProfiles).length + " profiles");
196
- } catch(e) {
197
- console.error("[setup] Failed to write auth-profiles.json: " + e.message);
198
- }
199
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  }
201
 
202
  (async function main(){
203
- await setupTelegram();
204
- await setupAuthProfiles();
205
-
206
- try{
207
- fs.mkdirSync(STATE_DIR,{recursive:true});
208
- if(fs.existsSync(CONFIG_PATH)) fs.copyFileSync(CONFIG_PATH, CONFIG_PATH+".bak");
209
- fs.writeFileSync(CONFIG_PATH, JSON.stringify(config,null,2),"utf-8");
210
- }catch(e){ console.error("[setup] Write failed: "+e.message); process.exit(0); }
211
-
212
- console.log("[setup] Done! All tokens configured.");
213
- console.log("[setup] auth = "+(gatewayToken?"token":"password"));
214
- console.log("[setup] default model= "+defaultModel);
215
- console.log("[setup] config = "+CONFIG_PATH);
216
  })().catch(e=>{ console.error("[setup] Fatal: "+e.message); process.exit(0); });
 
5
  var HOME = process.env.OPENCLAW_HOME || process.env.HOME || "/home/user";
6
  var STATE_DIR = path.join(HOME, ".openclaw");
7
  var CONFIG_PATH = path.join(STATE_DIR, "openclaw.json");
8
+ var AGENT_ID = "main";
9
+ var AGENT_DIR = path.join(STATE_DIR, "agents", AGENT_ID, "agent");
10
+ var AUTH_PROFILES_PATH = path.join(AGENT_DIR, "auth-profiles.json");
11
  var SPACE_HOST = (process.env.SPACE_HOST || "").trim();
12
 
13
  console.log("[setup] Starting… HOME=" + HOME);
14
+ console.log("[setup] AGENT_DIR=" + AGENT_DIR);
15
 
16
+ // helpers
17
  function parseList(val) {
18
+ if (!val || !val.trim()) return [];
19
+ return val.split(",").map(function(s){ return s.trim(); }).filter(Boolean);
20
  }
21
  function envStr(key) { return (process.env[key] || "").trim(); }
22
 
23
+ // auth
24
  var gatewayToken = envStr("OPENCLAW_GATEWAY_TOKEN");
25
  var gatewayPassword = envStr("OPENCLAW_GATEWAY_PASSWORD");
26
  if (!gatewayToken && !gatewayPassword) {
27
+ console.error("[setup] FATAL: set OPENCLAW_GATEWAY_TOKEN or OPENCLAW_GATEWAY_PASSWORD in Secrets");
28
+ process.exit(0);
29
  }
30
 
31
+ // default model
32
  var defaultModel = envStr("OPENCLAW_HF_DEFAULT_MODEL") || "google/gemini-2.0-flash";
33
 
34
+ // dynamic provider key detection
35
  var EXCLUDE_PREFIXES = [
36
+ "OPENCLAW_", "SPACE_", "SYSTEM_", "HF_",
37
+ "NODE_", "PATH", "HOME", "USER", "PWD", "LANG", "LC_",
38
+ "npm_", "HOSTNAME", "SHELL", "TERM", "SHLVL"
39
  ];
40
  var INCLUDE_SUFFIXES = [
41
+ "_API_KEY", "_SECRET_KEY", "_ACCESS_TOKEN",
42
+ "_BOT_TOKEN", "_AUTH_TOKEN", "_APP_KEY",
43
+ "_SESSION_KEY", "_COOKIE", "_TOKEN"
44
  ];
45
  function isProviderKey(k){
46
+ for (let i=0;i<EXCLUDE_PREFIXES.length;i++){ if(k.indexOf(EXCLUDE_PREFIXES[i])===0) return false; }
47
+ for (let i=0;i<INCLUDE_SUFFIXES.length;i++){
48
+ let s=INCLUDE_SUFFIXES[i];
49
+ if(k.length>s.length && k.indexOf(s)===k.length-s.length) return true;
50
+ }
51
+ return false;
52
  }
53
 
54
  var allKeys = Object.keys(process.env);
 
57
  console.log("[setup] Detected provider keys ("+providerKeys.length+"):");
58
  providerKeys.forEach(k=>console.log(" + "+k));
59
 
60
+ // trusted proxies
61
  var envProxies = parseList(envStr("OPENCLAW_GATEWAY_TRUSTED_PROXIES"));
62
  var trustedProxies = envProxies.length>0 ? envProxies : [
63
+ "10.16.0.0/12","10.20.0.0/12",
64
+ "10.16.4.123","10.16.7.92","10.16.18.232",
65
+ "10.16.34.155","10.16.43.133","10.16.1.206",
66
+ "10.16.37.110","10.16.43.246",
67
+ "10.20.1.9","10.20.1.222",
68
+ "10.20.26.157","10.20.31.87",
69
+ "10.20.0.1","172.17.0.1"
70
  ];
71
 
72
+ // build config
73
  var config = {
74
+ gateway: {
75
+ auth: gatewayToken ? { mode:"token", token:gatewayToken } : { mode:"password", password:gatewayPassword },
76
+ controlUi: { allowInsecureAuth:true, allowedOrigins:["*"], dangerouslyDisableDeviceAuth:true, dangerouslyAllowHostHeaderOriginFallback:true },
77
+ trustedProxies: trustedProxies
78
+ },
79
+ agents: { defaults:{ model:defaultModel } },
80
+ env: { vars:{} }
81
  };
82
 
83
  // 添加所有检测到的 provider keys 到环境变量
84
  providerKeys.forEach(pk=>{ config.env.vars[pk] = envStr(pk); });
85
 
86
+ // Telegram webhook setup
87
  async function setupTelegram(){
88
+ var token = envStr("TELEGRAM_BOT_TOKEN");
89
+ if(!token){ console.log("[setup] Telegram: disabled (no TELEGRAM_BOT_TOKEN)"); return; }
90
+
91
+ if(SPACE_HOST){
92
+ var webhookUrl = "https://" + SPACE_HOST + "/tg-webhook";
93
+ var r = await new Promise(resolve=>{
94
+ var data = JSON.stringify({ url:webhookUrl, drop_pending_updates:true, max_connections:10 });
95
+ var req = https.request({
96
+ hostname: "api.telegram.org",
97
+ path: "/bot"+token+"/setWebhook",
98
+ method: "POST",
99
+ headers: { "Content-Type":"application/json", "Content-Length": Buffer.byteLength(data) }
100
+ }, res=>{
101
+ let buf="";
102
+ res.on("data",c=>buf+=c);
103
+ res.on("end", ()=>{ try{ resolve(JSON.parse(buf)) } catch(e){ resolve(null) } });
104
+ });
105
+ req.on("error", ()=>resolve(null));
106
+ req.setTimeout(8000, ()=>{ req.destroy(); resolve(null); });
107
+ req.write(data);
108
+ req.end();
109
+ });
110
+ if(r && r.ok) console.log("[setup] Telegram: webhook registered -> "+webhookUrl);
111
+ else {
112
+ console.log("[setup] Telegram: auto-registration failed (HF outbound blocked)");
113
+ console.log("[setup] Telegram: open this URL in your browser once:");
114
+ console.log(" https://api.telegram.org/bot"+token+"/setWebhook?url="+webhookUrl+"&drop_pending_updates=true");
115
+ }
116
+ } else {
117
+ console.log("[setup] Telegram: set SPACE_HOST in Variables for auto webhook registration");
118
+ }
119
 
120
+ config.channels = { telegram:{ enabled:true, accounts:{ main:{ botToken:token, apiRoot:"https://api.telegram.org" } } } };
121
+ console.log("[setup] Telegram: configured");
122
  }
123
 
124
+ // 根据官方文档修复:auth-profiles.json 必须在 agent 目录中
125
  async function setupAuthProfiles(){
126
+ var authProfiles = { profiles: {} };
127
+ var profileCount = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
+ // OpenAI - 格式:type + provider + token
130
+ if (envStr("OPENAI_ACCESS_TOKEN")) {
131
+ authProfiles.profiles["openai:default"] = {
132
+ type: "token",
133
+ provider: "openai",
134
+ token: envStr("OPENAI_ACCESS_TOKEN")
135
+ };
136
+ authProfiles.profiles["openai-codex:default"] = {
137
+ type: "token",
138
+ provider: "openai-codex",
139
+ token: envStr("OPENAI_ACCESS_TOKEN")
140
+ };
141
+ profileCount += 2;
142
+ console.log("[setup] ✓ OpenAI token bound to auth-profiles (openai:default, openai-codex:default)");
143
+ }
144
 
145
+ // Anthropic Claude
146
+ if (envStr("ANTHROPIC_SESSION_KEY")) {
147
+ authProfiles.profiles["anthropic:default"] = {
148
+ type: "token",
149
+ provider: "anthropic",
150
+ token: envStr("ANTHROPIC_SESSION_KEY")
151
+ };
152
+ profileCount += 1;
153
+ console.log("[setup] ✓ Anthropic token bound to auth-profiles (anthropic:default)");
154
+ }
155
 
156
+ // Moonshot Kimi
157
+ if (envStr("MOONSHOT_ACCESS_TOKEN")) {
158
+ authProfiles.profiles["moonshot:default"] = {
159
+ type: "token",
160
+ provider: "moonshot",
161
+ token: envStr("MOONSHOT_ACCESS_TOKEN")
162
+ };
163
+ profileCount += 1;
164
+ console.log("[setup] ✓ Moonshot token bound to auth-profiles (moonshot:default)");
165
+ }
 
 
 
 
 
 
166
 
167
+ // Google Gemini
168
+ if (envStr("GOOGLE_GEMINI_COOKIE")) {
169
+ authProfiles.profiles["google:default"] = {
170
+ type: "token",
171
+ provider: "google",
172
+ token: envStr("GOOGLE_GEMINI_COOKIE")
173
+ };
174
+ authProfiles.profiles["google-gemini-cli:default"] = {
175
+ type: "token",
176
+ provider: "google-gemini-cli",
177
+ token: envStr("GOOGLE_GEMINI_COOKIE")
178
+ };
179
+ profileCount += 2;
180
+ console.log("[setup] ✓ Google Gemini cookie bound to auth-profiles (google:default, google-gemini-cli:default)");
181
+ }
182
 
183
+ // 通义千问
184
+ if (envStr("QWEN_COOKIE")) {
185
+ authProfiles.profiles["qianwen:default"] = {
186
+ type: "token",
187
+ provider: "qianwen",
188
+ token: envStr("QWEN_COOKIE")
189
+ };
190
+ profileCount += 1;
191
+ console.log("[setup] ✓ Qwen cookie bound to auth-profiles (qianwen:default)");
192
+ }
193
+
194
+ // 其他 API Key
195
+ if (envStr("DEEPSEEK_API_KEY")) {
196
+ authProfiles.profiles["deepseek:default"] = {
197
+ type: "token",
198
+ provider: "deepseek",
199
+ token: envStr("DEEPSEEK_API_KEY")
200
+ };
201
+ profileCount += 1;
202
+ console.log("[setup] ✓ DeepSeek API key bound to auth-profiles (deepseek:default)");
203
+ }
204
+
205
+ if (envStr("GROQ_API_KEY")) {
206
+ authProfiles.profiles["groq:default"] = {
207
+ type: "token",
208
+ provider: "groq",
209
+ token: envStr("GROQ_API_KEY")
210
+ };
211
+ profileCount += 1;
212
+ console.log("[setup] ✓ Groq API key bound to auth-profiles (groq:default)");
213
+ }
214
+
215
+ if (envStr("GEMINI_API_KEY")) {
216
+ authProfiles.profiles["gemini:default"] = {
217
+ type: "token",
218
+ provider: "gemini",
219
+ token: envStr("GEMINI_API_KEY")
220
+ };
221
+ profileCount += 1;
222
+ console.log("[setup] ✓ Gemini API key bound to auth-profiles (gemini:default)");
223
+ }
224
+
225
+ if (envStr("OPENROUTER_API_KEY")) {
226
+ authProfiles.profiles["openrouter:default"] = {
227
+ type: "token",
228
+ provider: "openrouter",
229
+ token: envStr("OPENROUTER_API_KEY")
230
+ };
231
+ profileCount += 1;
232
+ console.log("[setup] ✓ OpenRouter API key bound to auth-profiles (openrouter:default)");
233
+ }
234
+
235
+ if (envStr("ZAI_API_KEY")) {
236
+ authProfiles.profiles["zai:default"] = {
237
+ type: "token",
238
+ provider: "zai",
239
+ token: envStr("ZAI_API_KEY")
240
+ };
241
+ profileCount += 1;
242
+ console.log("[setup] ✓ Zai API key bound to auth-profiles (zai:default)");
243
+ }
244
+
245
+ if (envStr("SILICONFLOW_API_KEY")) {
246
+ authProfiles.profiles["siliconflow:default"] = {
247
+ type: "token",
248
+ provider: "siliconflow",
249
+ token: envStr("SILICONFLOW_API_KEY")
250
+ };
251
+ profileCount += 1;
252
+ console.log("[setup] ✓ SiliconFlow API key bound to auth-profiles (siliconflow:default)");
253
+ }
254
+
255
+ if (envStr("MINIMAX_API_KEY")) {
256
+ authProfiles.profiles["minimax:default"] = {
257
+ type: "token",
258
+ provider: "minimax",
259
+ token: envStr("MINIMAX_API_KEY")
260
+ };
261
+ profileCount += 1;
262
+ console.log("[setup] ✓ MiniMax API key bound to auth-profiles (minimax:default)");
263
+ }
264
+
265
+ // 如果有认证信息,保存到 auth-profiles.json
266
+ if (profileCount > 0) {
267
+ try {
268
+ // 创建 agent 目录
269
+ fs.mkdirSync(AGENT_DIR, {recursive:true});
270
+ // 写入 auth-profiles.json
271
+ fs.writeFileSync(AUTH_PROFILES_PATH, JSON.stringify(authProfiles, null, 2), "utf-8");
272
+ console.log("[setup] auth-profiles.json created at " + AUTH_PROFILES_PATH);
273
+ console.log("[setup] Total auth profiles: " + profileCount);
274
+ } catch(e) {
275
+ console.error("[setup] Failed to write auth-profiles.json: " + e.message);
276
+ }
277
+ }
278
  }
279
 
280
  (async function main(){
281
+ await setupTelegram();
282
+ await setupAuthProfiles();
283
+
284
+ try{
285
+ fs.mkdirSync(STATE_DIR,{recursive:true});
286
+ if(fs.existsSync(CONFIG_PATH)) fs.copyFileSync(CONFIG_PATH, CONFIG_PATH+".bak");
287
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config,null,2),"utf-8");
288
+ }catch(e){ console.error("[setup] Write failed: "+e.message); process.exit(0); }
289
+
290
+ console.log("[setup] Done! All tokens configured.");
291
+ console.log("[setup] auth = "+(gatewayToken?"token":"password"));
292
+ console.log("[setup] default model= "+defaultModel);
293
+ console.log("[setup] config = "+CONFIG_PATH);
294
  })().catch(e=>{ console.error("[setup] Fatal: "+e.message); process.exit(0); });