@chrysb/alphaclaw 0.9.16 → 0.9.18

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 (42) hide show
  1. package/README.md +25 -0
  2. package/lib/public/css/tailwind.generated.css +1 -1
  3. package/lib/public/dist/app.bundle.js +1858 -1758
  4. package/lib/public/js/components/agents-tab/agent-overview/model-card.js +59 -7
  5. package/lib/public/js/components/agents-tab/agent-overview/use-model-card.js +124 -0
  6. package/lib/public/js/components/api-feature-panel.js +76 -0
  7. package/lib/public/js/components/envars.js +1 -1
  8. package/lib/public/js/components/general/index.js +6 -0
  9. package/lib/public/js/components/general/use-general-tab.js +69 -0
  10. package/lib/public/js/components/row-accessory-select.js +52 -0
  11. package/lib/public/js/lib/api.js +26 -0
  12. package/lib/public/js/lib/model-catalog.js +6 -0
  13. package/lib/public/js/lib/model-config.js +12 -7
  14. package/lib/public/js/lib/storage-keys.js +4 -0
  15. package/lib/public/js/lib/thinking-levels.js +37 -0
  16. package/lib/server/agents/agents.js +33 -7
  17. package/lib/server/agents/channels.js +4 -2
  18. package/lib/server/alphaclaw-config.js +99 -0
  19. package/lib/server/chat-ws.js +4 -1
  20. package/lib/server/constants.js +73 -0
  21. package/lib/server/cost-utils.js +2 -0
  22. package/lib/server/db/auth/index.js +147 -0
  23. package/lib/server/db/auth/schema.js +17 -0
  24. package/lib/server/gateway.js +321 -20
  25. package/lib/server/helpers.js +1 -3
  26. package/lib/server/init/register-server-routes.js +45 -18
  27. package/lib/server/init/runtime-init.js +4 -0
  28. package/lib/server/init/server-lifecycle.js +1 -24
  29. package/lib/server/login-throttle.js +261 -60
  30. package/lib/server/model-catalog-bootstrap.json +5 -0
  31. package/lib/server/onboarding/index.js +2 -2
  32. package/lib/server/onboarding/openclaw.js +27 -3
  33. package/lib/server/openclaw-thinking.js +103 -0
  34. package/lib/server/openclaw-version.js +1 -1
  35. package/lib/server/routes/agents.js +10 -3
  36. package/lib/server/routes/models.js +35 -1
  37. package/lib/server/routes/onboarding.js +2 -2
  38. package/lib/server/routes/proxy.js +219 -1
  39. package/lib/server/routes/system.js +63 -2
  40. package/lib/server/usage-tracker-config.js +52 -1
  41. package/lib/server.js +60 -22
  42. package/package.json +2 -2
@@ -12,12 +12,17 @@ const {
12
12
  kRootDir,
13
13
  } = require("./constants");
14
14
  const { withOpenclawStartupEnv } = require("./openclaw-runtime-env");
15
+ const { isOpenAiCompatApiEnabled } = require("./alphaclaw-config");
15
16
 
16
17
  let gatewayChild = null;
17
18
  let gatewayExitHandler = null;
18
19
  let gatewayLaunchHandler = null;
19
20
  const kGatewayStderrTailLines = 50;
20
21
  const kPluginRuntimeDepsPreflightTimeoutMs = 120 * 1000;
22
+ const kGatewayShortCmdTimeoutMs = 15 * 1000;
23
+ const kGatewayLifecycleCmdTimeoutMs = 90 * 1000;
24
+ const kGatewayRestartReadyTimeoutMs = 120 * 1000;
25
+ const kGatewayRestartReadyPollMs = 500;
21
26
  let gatewayStderrTail = [];
22
27
  const expectedExitPids = new Set();
23
28
 
@@ -225,27 +230,122 @@ const isGatewayRunning = () =>
225
230
  });
226
231
  });
227
232
 
228
- const runGatewayCmd = (cmd) => {
229
- console.log(`[alphaclaw] Running: openclaw gateway ${cmd}`);
233
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
234
+
235
+ const waitForGatewayReady = async ({
236
+ timeoutMs = kGatewayRestartReadyTimeoutMs,
237
+ } = {}) => {
238
+ const startedAt = Date.now();
239
+ while (Date.now() - startedAt < timeoutMs) {
240
+ if (await isGatewayRunning()) return true;
241
+ await sleep(kGatewayRestartReadyPollMs);
242
+ }
243
+ return false;
244
+ };
245
+
246
+ const logGatewayCmdOutput = (cmd, e) => {
247
+ if (e?.stdout?.trim()) {
248
+ console.log(`[alphaclaw] gateway ${cmd} stdout: ${e.stdout.trim()}`);
249
+ }
250
+ if (e?.stderr?.trim()) {
251
+ console.log(`[alphaclaw] gateway ${cmd} stderr: ${e.stderr.trim()}`);
252
+ }
253
+ if (!e?.stdout?.trim() && !e?.stderr?.trim()) {
254
+ console.log(`[alphaclaw] gateway ${cmd} error: ${e.message}`);
255
+ }
256
+ if (e?.status !== undefined && e?.status !== null) {
257
+ console.log(`[alphaclaw] gateway ${cmd} exit code: ${e.status}`);
258
+ }
259
+ };
260
+
261
+ const runGatewayShortCmd = (cmd) => {
230
262
  try {
231
- if (cmd === "--force" || cmd === "restart") {
232
- prepareOpenclawChannelPlugins();
233
- }
234
263
  const out = execSync(`openclaw gateway ${cmd}`, {
235
264
  env: gatewayEnv(),
236
- timeout: 15000,
265
+ timeout: kGatewayShortCmdTimeoutMs,
237
266
  encoding: "utf8",
238
267
  });
239
268
  if (out.trim()) console.log(`[alphaclaw] ${out.trim()}`);
240
269
  } catch (e) {
241
- if (e.stdout?.trim())
242
- console.log(`[alphaclaw] gateway ${cmd} stdout: ${e.stdout.trim()}`);
243
- if (e.stderr?.trim())
244
- console.log(`[alphaclaw] gateway ${cmd} stderr: ${e.stderr.trim()}`);
245
- if (!e.stdout?.trim() && !e.stderr?.trim())
246
- console.log(`[alphaclaw] gateway ${cmd} error: ${e.message}`);
247
- console.log(`[alphaclaw] gateway ${cmd} exit code: ${e.status}`);
270
+ logGatewayCmdOutput(cmd, e);
271
+ }
272
+ };
273
+
274
+ const runGatewayLifecycleRestart = () => {
275
+ console.log("[alphaclaw] Running: openclaw gateway restart");
276
+ try {
277
+ const out = execSync("openclaw gateway restart", {
278
+ env: gatewayEnv(),
279
+ timeout: kGatewayLifecycleCmdTimeoutMs,
280
+ encoding: "utf8",
281
+ });
282
+ if (out.trim()) console.log(`[alphaclaw] ${out.trim()}`);
283
+ return true;
284
+ } catch (e) {
285
+ logGatewayCmdOutput("restart", e);
286
+ return false;
287
+ }
288
+ };
289
+
290
+ const hasActiveManagedGatewayChild = () =>
291
+ !!(
292
+ gatewayChild &&
293
+ gatewayChild.exitCode === null &&
294
+ !gatewayChild.killed
295
+ );
296
+
297
+ const runGatewayRestartCmd = async (cmd) => {
298
+ prepareOpenclawChannelPlugins();
299
+ const startedAt = Date.now();
300
+ const child = spawn("openclaw", ["gateway", cmd], {
301
+ env: gatewayEnv(),
302
+ stdio: ["ignore", "pipe", "pipe"],
303
+ });
304
+ child.stdout.on("data", (d) => process.stdout.write(`[gateway] ${d}`));
305
+ child.stderr.on("data", (d) => {
306
+ appendStderrTail(d);
307
+ process.stderr.write(`[gateway] ${d}`);
308
+ });
309
+ child.on("exit", (code, signal) => {
310
+ console.log(
311
+ `[alphaclaw] gateway ${cmd} supervisor exited: code=${code ?? "null"}${signal ? ` signal=${signal}` : ""}`,
312
+ );
313
+ });
314
+
315
+ const ready = await waitForGatewayReady();
316
+ if (ready) {
317
+ console.log(
318
+ `[alphaclaw] Gateway ${cmd} ready (${Date.now() - startedAt}ms); leaving supervisor running`,
319
+ );
320
+ gatewayChild = null;
321
+ await notifyGatewayLaunch();
322
+ return;
323
+ }
324
+
325
+ console.warn(
326
+ `[alphaclaw] Gateway ${cmd} did not become ready within ${kGatewayRestartReadyTimeoutMs}ms; stopping`,
327
+ );
328
+ try {
329
+ child.kill("SIGTERM");
330
+ } catch {
331
+ // ignore
248
332
  }
333
+ runGatewayShortCmd("stop");
334
+ };
335
+
336
+ const runGatewayColdStart = async () => {
337
+ stopManagedGatewayChild();
338
+ runGatewayShortCmd("stop");
339
+ await runGatewayRestartCmd("--force");
340
+ };
341
+
342
+ const runGatewayCmd = async (cmd) => {
343
+ console.log(`[alphaclaw] Running: openclaw gateway ${cmd}`);
344
+ if (cmd === "--force") {
345
+ await runGatewayRestartCmd("--force");
346
+ return;
347
+ }
348
+ runGatewayShortCmd(cmd);
249
349
  };
250
350
 
251
351
  const launchGatewayProcess = () => {
@@ -322,6 +422,23 @@ const markManagedGatewayExitExpected = () => {
322
422
  return true;
323
423
  };
324
424
 
425
+ const notifyGatewayLaunch = async () => {
426
+ if (!gatewayLaunchHandler) return;
427
+ if (!(await isGatewayRunning())) return;
428
+ const pid =
429
+ gatewayChild &&
430
+ gatewayChild.exitCode === null &&
431
+ !gatewayChild.killed &&
432
+ gatewayChild.pid
433
+ ? gatewayChild.pid
434
+ : null;
435
+ try {
436
+ gatewayLaunchHandler({ startedAt: Date.now(), pid });
437
+ } catch (err) {
438
+ console.error(`[alphaclaw] Gateway launch handler error: ${err.message}`);
439
+ }
440
+ };
441
+
325
442
  const startGateway = async () => {
326
443
  if (!isOnboarded()) {
327
444
  console.log("[alphaclaw] Not onboarded yet — skipping gateway start");
@@ -329,22 +446,45 @@ const startGateway = async () => {
329
446
  }
330
447
  if (await isGatewayRunning()) {
331
448
  console.log("[alphaclaw] Gateway already running — skipping start");
449
+ await notifyGatewayLaunch();
332
450
  return;
333
451
  }
334
452
  console.log("[alphaclaw] Starting openclaw gateway...");
335
453
  launchGatewayProcess();
336
454
  };
337
455
 
338
- const restartGateway = (reloadEnv) => {
339
- reloadEnv();
456
+ const stopManagedGatewayChild = () => {
340
457
  markManagedGatewayExitExpected();
341
- runGatewayCmd("--force");
458
+ if (!gatewayChild || gatewayChild.exitCode !== null || gatewayChild.killed) {
459
+ return;
460
+ }
461
+ try {
462
+ gatewayChild.kill("SIGTERM");
463
+ } catch {
464
+ // ignore
465
+ }
466
+ gatewayChild = null;
342
467
  };
343
468
 
344
- const restartGatewayLight = (reloadEnv) => {
469
+ const restartGateway = async (reloadEnv) => {
345
470
  reloadEnv();
346
- markManagedGatewayExitExpected();
347
- runGatewayCmd("restart");
471
+ await runGatewayColdStart();
472
+ };
473
+
474
+ const restartGatewayLight = async (reloadEnv) => {
475
+ reloadEnv();
476
+ if (await isGatewayRunning()) {
477
+ if (runGatewayLifecycleRestart()) {
478
+ console.log("[alphaclaw] Gateway light restart complete");
479
+ return;
480
+ }
481
+ console.warn("[alphaclaw] Gateway light restart failed");
482
+ return;
483
+ }
484
+ if (!hasActiveManagedGatewayChild()) {
485
+ console.log("[alphaclaw] Gateway not running — starting managed process");
486
+ launchGatewayProcess();
487
+ }
348
488
  };
349
489
 
350
490
  const attachGatewaySignalHandlers = () => {
@@ -366,6 +506,31 @@ const ensureGatewayProxyConfig = (origin) => {
366
506
  if (!cfg.gateway) cfg.gateway = {};
367
507
  let changed = false;
368
508
 
509
+ if (isOpenAiCompatApiEnabled({ fsModule: fs, openclawDir: OPENCLAW_DIR })) {
510
+ if (!cfg.gateway.http) cfg.gateway.http = {};
511
+ if (!cfg.gateway.http.endpoints) cfg.gateway.http.endpoints = {};
512
+
513
+ const chatCompletions = cfg.gateway.http.endpoints.chatCompletions || {};
514
+ if (chatCompletions.enabled !== true) {
515
+ cfg.gateway.http.endpoints.chatCompletions = {
516
+ ...chatCompletions,
517
+ enabled: true,
518
+ };
519
+ console.log("[alphaclaw] Enabled gateway OpenAI chat completions endpoint");
520
+ changed = true;
521
+ }
522
+
523
+ const responses = cfg.gateway.http.endpoints.responses || {};
524
+ if (responses.enabled !== true) {
525
+ cfg.gateway.http.endpoints.responses = {
526
+ ...responses,
527
+ enabled: true,
528
+ };
529
+ console.log("[alphaclaw] Enabled gateway OpenResponses endpoint");
530
+ changed = true;
531
+ }
532
+ }
533
+
369
534
  if (!Array.isArray(cfg.gateway.trustedProxies)) {
370
535
  cfg.gateway.trustedProxies = [];
371
536
  }
@@ -387,8 +552,144 @@ const ensureGatewayProxyConfig = (origin) => {
387
552
  }
388
553
  }
389
554
 
555
+ // Managed remote MCP server entry. Env-driven so any AlphaClaw operator
556
+ // (Render, Fly, fly.io-style PaaS, plain VPS) can wire OpenClaw to a
557
+ // remote MCP server without hand-editing /data/.openclaw/openclaw.json.
558
+ //
559
+ // REMOTE_MCP_URL upstream MCP endpoint (streamable-http).
560
+ // REMOTE_MCP_API_TOKEN Bearer token the remote MCP expects. Persisted
561
+ // as the ${REMOTE_MCP_API_TOKEN} reference, not
562
+ // raw, so the openclaw.json that gets
563
+ // git-committed never holds the plaintext.
564
+ // REMOTE_MCP_NAME Key under mcp.servers.<name>. Default "remote".
565
+ // REMOTE_MCP_PROXY_URL When set, OpenClaw connects here instead of
566
+ // REMOTE_MCP_URL. Intended for a same-host
567
+ // scanning proxy (e.g. `pipelock mcp proxy
568
+ // --listen ... --upstream <REMOTE_MCP_URL>`),
569
+ // but the implementation is proxy-agnostic.
570
+ // The supervisor that starts that proxy is
571
+ // responsible for unsetting this env var when
572
+ // the proxy is not running, so AlphaClaw never
573
+ // points OpenClaw at a dead listener.
574
+ const remoteMcpUrl = String(process.env.REMOTE_MCP_URL || "").trim();
575
+ const remoteMcpToken = String(
576
+ process.env.REMOTE_MCP_API_TOKEN || "",
577
+ ).trim();
578
+ const remoteMcpProxyUrl = String(
579
+ process.env.REMOTE_MCP_PROXY_URL || "",
580
+ ).trim();
581
+ const remoteMcpNameRaw = String(process.env.REMOTE_MCP_NAME || "").trim();
582
+ // Constrain the managed key. OpenClaw sanitizes names later for tool
583
+ // prefixes, but the config-key itself must be safe to use as an object
584
+ // key and to read back in `openclaw mcp` CLI commands. Reject names
585
+ // with prototype-pollution shapes, spaces, or path-like names; fall
586
+ // back to "remote" with a warning so a typo doesn't silently misroute.
587
+ const kRemoteMcpNamePattern = /^[A-Za-z0-9_-]{1,64}$/;
588
+ const kReservedRemoteMcpNames = new Set([
589
+ "__proto__",
590
+ "constructor",
591
+ "prototype",
592
+ ]);
593
+ let remoteMcpName = "remote";
594
+ if (remoteMcpNameRaw) {
595
+ if (
596
+ kRemoteMcpNamePattern.test(remoteMcpNameRaw) &&
597
+ !kReservedRemoteMcpNames.has(remoteMcpNameRaw)
598
+ ) {
599
+ remoteMcpName = remoteMcpNameRaw;
600
+ } else {
601
+ console.warn(
602
+ `[alphaclaw] REMOTE_MCP_NAME=${JSON.stringify(remoteMcpNameRaw)} is invalid (must match ${kRemoteMcpNamePattern} and not be a reserved key); falling back to "remote"`,
603
+ );
604
+ }
605
+ }
606
+ const placeholderAuth = "Bearer ${REMOTE_MCP_API_TOKEN}";
607
+ const desiredAuth = `Bearer ${remoteMcpToken}`;
608
+ const kManagedMarker = "_alphaclawManaged";
609
+ let mcpChanged = false;
610
+
611
+ // Clean up any managed entries left over from a prior REMOTE_MCP_NAME
612
+ // value. Without this, renaming REMOTE_MCP_NAME from "sure" to "notion"
613
+ // would leave the old "sure" entry behind, duplicating MCP tools or
614
+ // routing callbacks to a stale target. The marker scopes the cleanup so
615
+ // user-managed entries (no marker) are never touched.
616
+ if (cfg.mcp?.servers) {
617
+ for (const [key, entry] of Object.entries(cfg.mcp.servers)) {
618
+ if (
619
+ entry &&
620
+ typeof entry === "object" &&
621
+ entry[kManagedMarker] === true &&
622
+ key !== remoteMcpName
623
+ ) {
624
+ delete cfg.mcp.servers[key];
625
+ mcpChanged = true;
626
+ console.log(
627
+ `[alphaclaw] Removed stale managed MCP server "${key}" (REMOTE_MCP_NAME is now "${remoteMcpName}")`,
628
+ );
629
+ }
630
+ }
631
+ }
632
+
633
+ if (remoteMcpUrl && remoteMcpToken) {
634
+ if (!cfg.mcp) cfg.mcp = {};
635
+ if (!cfg.mcp.servers) cfg.mcp.servers = {};
636
+ const existing = cfg.mcp.servers[remoteMcpName] || {};
637
+ const effectiveUrl = remoteMcpProxyUrl || remoteMcpUrl;
638
+ const existingHeaders = existing.headers || {};
639
+ const existingAuth = existingHeaders.Authorization;
640
+ // Only the placeholder counts as "already sanitized". A plaintext
641
+ // Bearer (even one that matches the current desiredAuth) must trigger a
642
+ // rewrite so the substitution loop below scrubs it back to the
643
+ // ${REMOTE_MCP_API_TOKEN} reference.
644
+ const authIsPlaceholder = existingAuth === placeholderAuth;
645
+ const hasManagedMarker = existing[kManagedMarker] === true;
646
+ if (
647
+ existing.url !== effectiveUrl ||
648
+ existing.transport !== "streamable-http" ||
649
+ !authIsPlaceholder ||
650
+ !hasManagedMarker
651
+ ) {
652
+ cfg.mcp.servers[remoteMcpName] = {
653
+ ...existing,
654
+ url: effectiveUrl,
655
+ transport: "streamable-http",
656
+ headers: {
657
+ ...existingHeaders,
658
+ Authorization: desiredAuth,
659
+ },
660
+ [kManagedMarker]: true,
661
+ };
662
+ mcpChanged = true;
663
+ console.log(
664
+ `[alphaclaw] Configured remote MCP server "${remoteMcpName}" (url=${effectiveUrl}, via_proxy=${Boolean(remoteMcpProxyUrl)})`,
665
+ );
666
+ }
667
+ } else if (
668
+ cfg.mcp?.servers?.[remoteMcpName] &&
669
+ cfg.mcp.servers[remoteMcpName][kManagedMarker] === true
670
+ ) {
671
+ delete cfg.mcp.servers[remoteMcpName];
672
+ mcpChanged = true;
673
+ console.log(
674
+ `[alphaclaw] Removed remote MCP server "${remoteMcpName}" entry (REMOTE_MCP_URL / REMOTE_MCP_API_TOKEN unset)`,
675
+ );
676
+ }
677
+ if (cfg.mcp?.servers && Object.keys(cfg.mcp.servers).length === 0) {
678
+ delete cfg.mcp.servers;
679
+ }
680
+ if (cfg.mcp && Object.keys(cfg.mcp).length === 0) {
681
+ delete cfg.mcp;
682
+ }
683
+ if (mcpChanged) changed = true;
684
+
390
685
  if (changed) {
391
- fs.writeFileSync(configPath, JSON.stringify(cfg, null, 2));
686
+ let content = JSON.stringify(cfg, null, 2);
687
+ if (remoteMcpToken) {
688
+ const jsonValue = JSON.stringify(desiredAuth);
689
+ const jsonPlaceholder = JSON.stringify(placeholderAuth);
690
+ content = content.split(jsonValue).join(jsonPlaceholder);
691
+ }
692
+ fs.writeFileSync(configPath, content);
392
693
  }
393
694
  return changed;
394
695
  } catch (e) {
@@ -60,9 +60,7 @@ const isDebugEnabled = () =>
60
60
  isTruthyEnvFlag(process.env.DEBUG);
61
61
 
62
62
  const getClientKey = (req) =>
63
- normalizeIp(
64
- req.ip || req.headers["x-forwarded-for"] || req.socket?.remoteAddress || "",
65
- ) || "unknown";
63
+ normalizeIp(req.ip || req.socket?.remoteAddress || "") || "unknown";
66
64
 
67
65
  const resolveGithubRepoUrl = (repoInput) => {
68
66
  const cleaned = String(repoInput || "")
@@ -1,3 +1,4 @@
1
+ const { runOnboardedBootSequence } = require("../startup");
1
2
  const { registerAuthRoutes } = require("../routes/auth");
2
3
  const { registerPageRoutes } = require("../routes/pages");
3
4
  const { registerModelRoutes } = require("../routes/models");
@@ -41,8 +42,13 @@ const registerServerRoutes = ({
41
42
  resolveGithubRepoUrl,
42
43
  resolveModelProvider,
43
44
  ensureGatewayProxyConfig,
45
+ isOpenAiCompatApiEnabled,
46
+ openAiCompatApiThrottle,
44
47
  getBaseUrl,
45
48
  startGateway,
49
+ ensureManagedExecDefaults,
50
+ ensureUsageTrackerPluginConfig,
51
+ resolveSetupUrl,
46
52
  syncChannelConfig,
47
53
  getChannelStatus,
48
54
  openclawVersionService,
@@ -105,24 +111,6 @@ const registerServerRoutes = ({
105
111
  writeEnvFile,
106
112
  reloadEnv,
107
113
  });
108
- registerOnboardingRoutes({
109
- app,
110
- fs,
111
- constants,
112
- shellCmd,
113
- gatewayEnv,
114
- readEnvFile,
115
- writeEnvFile,
116
- reloadEnv,
117
- isOnboarded,
118
- resolveGithubRepoUrl,
119
- resolveModelProvider,
120
- hasCodexOauthProfile: authProfiles.hasCodexOauthProfile,
121
- authProfiles,
122
- ensureGatewayProxyConfig,
123
- getBaseUrl,
124
- startGateway,
125
- });
126
114
  registerSystemRoutes({
127
115
  app,
128
116
  fs,
@@ -147,6 +135,8 @@ const registerServerRoutes = ({
147
135
  authProfiles,
148
136
  watchdog,
149
137
  doctorService,
138
+ ensureGatewayProxyConfig,
139
+ getBaseUrl,
150
140
  });
151
141
  registerBrowseRoutes({
152
142
  app,
@@ -183,6 +173,38 @@ const registerServerRoutes = ({
183
173
  reloadEnv,
184
174
  restartRequiredState,
185
175
  });
176
+ const runOnboardedBoot = () =>
177
+ runOnboardedBootSequence({
178
+ ensureManagedExecDefaults,
179
+ ensureUsageTrackerPluginConfig,
180
+ doSyncPromptFiles,
181
+ reloadEnv,
182
+ syncChannelConfig,
183
+ readEnvFile,
184
+ ensureGatewayProxyConfig,
185
+ resolveSetupUrl,
186
+ startGateway,
187
+ watchdog,
188
+ gmailWatchService,
189
+ });
190
+ registerOnboardingRoutes({
191
+ app,
192
+ fs,
193
+ constants,
194
+ shellCmd,
195
+ gatewayEnv,
196
+ readEnvFile,
197
+ writeEnvFile,
198
+ reloadEnv,
199
+ isOnboarded,
200
+ resolveGithubRepoUrl,
201
+ resolveModelProvider,
202
+ hasCodexOauthProfile: authProfiles.hasCodexOauthProfile,
203
+ authProfiles,
204
+ ensureGatewayProxyConfig,
205
+ getBaseUrl,
206
+ runOnboardedBootSequence: runOnboardedBoot,
207
+ });
186
208
  registerTelegramRoutes({
187
209
  app,
188
210
  telegramApi,
@@ -256,6 +278,10 @@ const registerServerRoutes = ({
256
278
  app,
257
279
  proxy,
258
280
  getGatewayUrl,
281
+ getGatewayToken: () =>
282
+ process.env.OPENCLAW_GATEWAY_TOKEN || constants.GATEWAY_TOKEN || "",
283
+ isOpenAiCompatApiEnabled,
284
+ openAiCompatApiThrottle,
259
285
  SETUP_API_PREFIXES,
260
286
  requireAuth,
261
287
  oauthCallbackMiddleware,
@@ -266,6 +292,7 @@ const registerServerRoutes = ({
266
292
  requireAuth,
267
293
  isAuthorizedRequest,
268
294
  gmailWatchService,
295
+ runOnboardedBootSequence: runOnboardedBoot,
269
296
  };
270
297
  };
271
298
 
@@ -19,11 +19,15 @@ const initializeServerRuntime = ({
19
19
 
20
20
  const initializeServerDatabases = ({
21
21
  constants,
22
+ initAuthDb,
22
23
  initWebhooksDb,
23
24
  initWatchdogDb,
24
25
  initUsageDb,
25
26
  initDoctorDb,
26
27
  }) => {
28
+ initAuthDb({
29
+ rootDir: constants.kRootDir,
30
+ });
27
31
  initWebhooksDb({
28
32
  rootDir: constants.kRootDir,
29
33
  pruneDays: constants.kWebhookPruneDays,
@@ -3,34 +3,11 @@ const startServerLifecycle = ({
3
3
  PORT,
4
4
  isOnboarded,
5
5
  runOnboardedBootSequence,
6
- ensureManagedExecDefaults,
7
- ensureUsageTrackerPluginConfig,
8
- doSyncPromptFiles,
9
- reloadEnv,
10
- syncChannelConfig,
11
- readEnvFile,
12
- ensureGatewayProxyConfig,
13
- resolveSetupUrl,
14
- startGateway,
15
- watchdog,
16
- gmailWatchService,
17
6
  }) => {
18
7
  server.listen(PORT, "0.0.0.0", () => {
19
8
  console.log(`[alphaclaw] Express listening on :${PORT}`);
20
9
  if (isOnboarded()) {
21
- runOnboardedBootSequence({
22
- ensureManagedExecDefaults,
23
- ensureUsageTrackerPluginConfig,
24
- doSyncPromptFiles,
25
- reloadEnv,
26
- syncChannelConfig,
27
- readEnvFile,
28
- ensureGatewayProxyConfig,
29
- resolveSetupUrl,
30
- startGateway,
31
- watchdog,
32
- gmailWatchService,
33
- });
10
+ runOnboardedBootSequence();
34
11
  } else {
35
12
  console.log("[alphaclaw] Awaiting onboarding via Setup UI");
36
13
  }