@alfe.ai/gateway 0.0.5 → 0.0.7

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as installService, d as SOCKET_PATH, h as LOG_FILE, i as checkExistingDaemon, n as queryDaemonHealth, o as stopExistingDaemon, r as startDaemon, s as uninstallService, t as formatHealthReport } from "../health.js";
2
+ import { a as installService, c as uninstallService, f as SOCKET_PATH, g as LOG_FILE, i as checkExistingDaemon, n as queryDaemonHealth, r as startDaemon, s as stopExistingDaemon, t as formatHealthReport } from "../health.js";
3
3
  import { spawn } from "node:child_process";
4
4
  //#region bin/gateway.ts
5
5
  /**
package/dist/health.js CHANGED
@@ -104,6 +104,15 @@ const ID_PREFIXES = {
104
104
  transaction: "txn",
105
105
  subscription: "sub",
106
106
  conversation: "conv",
107
+ referral: "ref",
108
+ promoCode: "prc",
109
+ promoRedemption: "prr",
110
+ pendingPromo: "pdp",
111
+ webhook: "whk",
112
+ webhookDelivery: "wdl",
113
+ onboardingSession: "obs",
114
+ inviteToken: "inv",
115
+ claimToken: "clm",
107
116
  run: "run",
108
117
  request: "req",
109
118
  connection: "conn",
@@ -381,6 +390,21 @@ var AuthService = class {
381
390
  deleteToken(tokenId) {
382
391
  return this.client.request(`${this.prefix}/tokens/${tokenId}`, { method: "DELETE" });
383
392
  }
393
+ getReferralCode() {
394
+ return this.client.request(`${this.prefix}/referral/code`);
395
+ }
396
+ redeemCode(code) {
397
+ return this.client.request(`${this.prefix}/referral/redeem`, {
398
+ method: "POST",
399
+ body: JSON.stringify({ code })
400
+ });
401
+ }
402
+ getReferralStatus() {
403
+ return this.client.request(`${this.prefix}/referral/status`);
404
+ }
405
+ getReferralHistory() {
406
+ return this.client.request(`${this.prefix}/referral/history`);
407
+ }
384
408
  };
385
409
  //#endregion
386
410
  //#region ../../packages-internal/types/dist/lib/enum-values.js
@@ -3069,7 +3093,8 @@ enumValues({
3069
3093
  });
3070
3094
  enumValues({
3071
3095
  Anthropic: "anthropic",
3072
- OpenAI: "openai"
3096
+ OpenAI: "openai",
3097
+ ElevenLabs: "elevenlabs"
3073
3098
  });
3074
3099
  enumValues({
3075
3100
  Month: "month",
@@ -3095,6 +3120,7 @@ enumValues({
3095
3120
  Provisioning: "provisioning",
3096
3121
  Running: "running",
3097
3122
  Stopped: "stopped",
3123
+ Failing: "failing",
3098
3124
  Failed: "failed",
3099
3125
  BillingSuspended: "billing_suspended"
3100
3126
  });
@@ -3121,6 +3147,8 @@ enumValues({
3121
3147
  SubscriptionCredit: "subscription_credit",
3122
3148
  AutoRecharge: "auto_recharge",
3123
3149
  AdminGift: "admin_gift",
3150
+ ReferralCredit: "referral_credit",
3151
+ PromoCredit: "promo_credit",
3124
3152
  Refund: "refund"
3125
3153
  });
3126
3154
  enumValues({
@@ -3134,6 +3162,36 @@ enumValues({
3134
3162
  Week: "week",
3135
3163
  Month: "month"
3136
3164
  });
3165
+ enumValues({
3166
+ Active: "active",
3167
+ Paused: "paused",
3168
+ Revoked: "revoked"
3169
+ });
3170
+ enumValues({
3171
+ Pending: "pending",
3172
+ Completed: "completed",
3173
+ Failed: "failed"
3174
+ });
3175
+ enumValues({
3176
+ BalanceCredit: "balance_credit",
3177
+ SubscriptionDiscount: "subscription_discount",
3178
+ FreeTrial: "free_trial"
3179
+ });
3180
+ enumValues({
3181
+ Active: "active",
3182
+ Paused: "paused",
3183
+ Revoked: "revoked"
3184
+ });
3185
+ enumValues({
3186
+ Pending: "pending",
3187
+ Completed: "completed",
3188
+ Failed: "failed"
3189
+ });
3190
+ enumValues({
3191
+ Pending: "pending",
3192
+ Consumed: "consumed",
3193
+ Expired: "expired"
3194
+ });
3137
3195
  enumValues({
3138
3196
  Synced: "synced",
3139
3197
  Stale: "stale",
@@ -3183,6 +3241,31 @@ _enum(OPENAI_MODELS);
3183
3241
  _enum([...ANTHROPIC_MODELS, ...OPENAI_MODELS]);
3184
3242
  AnthropicModel.Opus, AnthropicModel.Sonnet, AnthropicModel.Haiku, OpenAIModel.GPT4o, OpenAIModel.GPT4oMini, OpenAIModel.O3;
3185
3243
  AnthropicModel.Opus, AnthropicModel.Sonnet, AnthropicModel.Haiku, OpenAIModel.GPT4o, OpenAIModel.GPT4oMini, OpenAIModel.O3;
3244
+ enumValues({
3245
+ PendingChallenge: "pending_challenge",
3246
+ Creating: "creating",
3247
+ Complete: "complete",
3248
+ Failed: "failed",
3249
+ Expired: "expired"
3250
+ });
3251
+ enumValues({
3252
+ Active: "active",
3253
+ Used: "used",
3254
+ Expired: "expired",
3255
+ Revoked: "revoked"
3256
+ });
3257
+ enumValues({
3258
+ Pending: "pending",
3259
+ Claimed: "claimed",
3260
+ Expired: "expired"
3261
+ });
3262
+ enumValues({
3263
+ Mcp: "mcp",
3264
+ Api: "api",
3265
+ Cli: "cli",
3266
+ Dashboard: "dashboard",
3267
+ Agent: "agent"
3268
+ });
3186
3269
  //#endregion
3187
3270
  //#region src/config.ts
3188
3271
  /**
@@ -3243,7 +3326,7 @@ async function resolveAgentIdentity(apiKey, apiEndpoint) {
3243
3326
  if (!result.data.valid) throw new Error("API key invalid: validation failed. Run `alfe login` to reconfigure.");
3244
3327
  const orgId = result.data.tenantId;
3245
3328
  if (!orgId) throw new Error("Token validation returned no tenantId — cannot determine org.");
3246
- const agentId = result.data.tokenId ?? deriveAgentId(apiKey);
3329
+ const agentId = result.data.agentId ?? deriveAgentId(apiKey);
3247
3330
  const runtime = result.data.runtime ?? "openclaw";
3248
3331
  logger$1.debug({
3249
3332
  agentId,
@@ -3314,14 +3397,11 @@ function isManagedMode() {
3314
3397
  async function loadManagedConfig() {
3315
3398
  logger$1.debug("Loading managed config from environment...");
3316
3399
  const apiKey = process.env.ALFE_API_KEY;
3317
- const apiEndpoint = process.env.ALFE_API_ENDPOINT;
3318
- if (!apiKey || !apiEndpoint) throw new Error(`ALFE_API_KEY and ALFE_API_ENDPOINT required in managed mode (apiKey=${apiKey ? "set" : "missing"}, apiEndpoint=${apiEndpoint ? "set" : "missing"})`);
3319
- logger$1.debug({
3320
- apiEndpoint,
3321
- gatewayWsUrlEnv: process.env.ALFE_GATEWAY_WS_URL ?? "(not set)"
3322
- }, "Environment loaded, resolving identity...");
3400
+ if (!apiKey) throw new Error("ALFE_API_KEY required in managed mode");
3401
+ const apiEndpoint = process.env.ALFE_API_ENDPOINT ?? getEndpointFromToken(apiKey);
3402
+ logger$1.debug({ apiEndpoint }, "Environment loaded, resolving identity...");
3323
3403
  const identity = await resolveAgentIdentity(apiKey, apiEndpoint);
3324
- const gatewayWsUrl = process.env.ALFE_GATEWAY_WS_URL ?? deriveGatewayWsUrl(apiEndpoint);
3404
+ const gatewayWsUrl = deriveGatewayWsUrl(apiEndpoint);
3325
3405
  logger$1.debug({
3326
3406
  agentId: identity.agentId,
3327
3407
  orgId: identity.orgId,
@@ -3337,7 +3417,8 @@ async function loadManagedConfig() {
3337
3417
  agentId: identity.agentId,
3338
3418
  orgId: identity.orgId,
3339
3419
  runtime: identity.runtime,
3340
- runtimes: identity.runtime === "openclaw" ? { openclaw: { workspace: join(homedir(), ".openclaw") } } : {}
3420
+ runtimes: identity.runtime === "openclaw" ? { openclaw: { workspace: join(homedir(), ".openclaw") } } : {},
3421
+ autoStartRuntime: true
3341
3422
  };
3342
3423
  }
3343
3424
  /**
@@ -3368,7 +3449,8 @@ async function loadDaemonConfig() {
3368
3449
  agentId: identity.agentId,
3369
3450
  orgId: identity.orgId,
3370
3451
  runtime: identity.runtime,
3371
- runtimes
3452
+ runtimes,
3453
+ autoStartRuntime: alfeConfig.auto_start_runtime ?? false
3372
3454
  };
3373
3455
  }
3374
3456
  /**
@@ -4441,6 +4523,12 @@ var CommandQueue = class {
4441
4523
  */
4442
4524
  const LAUNCHD_LABEL = "ai.alfe.gateway";
4443
4525
  const SYSTEMD_SERVICE = "alfe-gateway";
4526
+ function isRootUser() {
4527
+ return process.getuid?.() === 0;
4528
+ }
4529
+ function getSystemdSystemServicePath() {
4530
+ return `/etc/systemd/system/${SYSTEMD_SERVICE}.service`;
4531
+ }
4444
4532
  function getLaunchdPlistPath() {
4445
4533
  return join(homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
4446
4534
  }
@@ -4455,6 +4543,10 @@ function getGatewayBinPath() {
4455
4543
  if (globalBin) return globalBin;
4456
4544
  const builtBin = join(import.meta.dirname, "..", "bin", "gateway.js");
4457
4545
  if (existsSync(builtBin)) return builtBin;
4546
+ try {
4547
+ const resolved = execSync("node -e \"console.log(require.resolve('@alfe.ai/gateway/bin/gateway.js'))\"", { encoding: "utf-8" }).trim();
4548
+ if (existsSync(resolved)) return resolved;
4549
+ } catch {}
4458
4550
  return "alfe-gateway";
4459
4551
  }
4460
4552
  function getNodePath() {
@@ -4501,9 +4593,18 @@ function generateLaunchdPlist() {
4501
4593
  </plist>`;
4502
4594
  }
4503
4595
  /**
4504
- * Generate a systemd user unit for Linux.
4596
+ * Generate a systemd unit for Linux.
4597
+ * Root users get a system-level unit; non-root get a user-level unit.
4505
4598
  */
4506
4599
  function generateSystemdUnit() {
4600
+ const nodePath = getNodePath();
4601
+ const gatewayBin = getGatewayBinPath();
4602
+ const root = isRootUser();
4603
+ const envLines = [
4604
+ "ALFE_MANAGED",
4605
+ "ALFE_API_KEY",
4606
+ "LOG_LEVEL"
4607
+ ].filter((key) => process.env[key]).map((key) => `Environment=${key}=${process.env[key] ?? ""}`).join("\n");
4507
4608
  return `[Unit]
4508
4609
  Description=Alfe Gateway Daemon
4509
4610
  After=network-online.target
@@ -4511,13 +4612,14 @@ Wants=network-online.target
4511
4612
 
4512
4613
  [Service]
4513
4614
  Type=simple
4514
- ExecStart=${getNodePath()} ${getGatewayBinPath()} daemon
4615
+ ExecStart=${nodePath} ${gatewayBin} daemon
4515
4616
  Restart=always
4516
4617
  RestartSec=10
4517
- Environment=NODE_ENV=production
4618
+ Environment=NODE_ENV=production${root ? "\nEnvironment=HOME=/root\nWorkingDirectory=/root" : ""}
4619
+ ${envLines}
4518
4620
 
4519
4621
  [Install]
4520
- WantedBy=default.target`;
4622
+ WantedBy=${root ? "multi-user.target" : "default.target"}`;
4521
4623
  }
4522
4624
  /**
4523
4625
  * Install the service unit for the current platform.
@@ -4558,31 +4660,57 @@ async function uninstallLaunchd() {
4558
4660
  return `Uninstalled: ${plistPath}`;
4559
4661
  }
4560
4662
  async function installSystemd() {
4561
- const unitPath = getSystemdServicePath();
4562
- await mkdir(join(homedir(), ".config", "systemd", "user"), { recursive: true });
4663
+ const root = isRootUser();
4664
+ const unitPath = root ? getSystemdSystemServicePath() : getSystemdServicePath();
4665
+ const dir = root ? "/etc/systemd/system" : join(homedir(), ".config", "systemd", "user");
4666
+ const ctl = root ? "systemctl" : "systemctl --user";
4667
+ if (!root) await mkdir(dir, { recursive: true });
4563
4668
  await writeFile(unitPath, generateSystemdUnit(), "utf-8");
4564
- logger$1.info({ path: unitPath }, "Wrote systemd unit");
4669
+ logger$1.info({
4670
+ path: unitPath,
4671
+ root
4672
+ }, "Wrote systemd unit");
4565
4673
  try {
4566
- execSync("systemctl --user daemon-reload", { stdio: "pipe" });
4567
- execSync(`systemctl --user enable ${SYSTEMD_SERVICE}`, { stdio: "pipe" });
4674
+ execSync(`${ctl} daemon-reload`, { stdio: "pipe" });
4675
+ execSync(`${ctl} enable ${SYSTEMD_SERVICE}`, { stdio: "pipe" });
4568
4676
  } catch {}
4569
- return `Installed: ${unitPath}\nService enabled for user session.`;
4677
+ return `Installed: ${unitPath}\nService enabled${root ? " (system-level)" : " for user session"}.`;
4570
4678
  }
4571
4679
  async function uninstallSystemd() {
4572
- const unitPath = getSystemdServicePath();
4680
+ const root = isRootUser();
4681
+ const unitPath = root ? getSystemdSystemServicePath() : getSystemdServicePath();
4682
+ const ctl = root ? "systemctl" : "systemctl --user";
4573
4683
  try {
4574
- execSync(`systemctl --user disable ${SYSTEMD_SERVICE}`, { stdio: "pipe" });
4575
- execSync(`systemctl --user stop ${SYSTEMD_SERVICE}`, { stdio: "pipe" });
4684
+ execSync(`${ctl} disable ${SYSTEMD_SERVICE}`, { stdio: "pipe" });
4685
+ execSync(`${ctl} stop ${SYSTEMD_SERVICE}`, { stdio: "pipe" });
4576
4686
  } catch {}
4577
4687
  try {
4578
4688
  await unlink(unitPath);
4579
4689
  } catch {}
4580
4690
  try {
4581
- execSync("systemctl --user daemon-reload", { stdio: "pipe" });
4691
+ execSync(`${ctl} daemon-reload`, { stdio: "pipe" });
4582
4692
  } catch {}
4583
4693
  return `Uninstalled: ${unitPath}`;
4584
4694
  }
4585
4695
  /**
4696
+ * Start the installed service via systemctl/launchctl.
4697
+ */
4698
+ function startService() {
4699
+ const platform = process.platform;
4700
+ if (platform === "darwin") {
4701
+ const plistPath = getLaunchdPlistPath();
4702
+ execSync(`launchctl start ${LAUNCHD_LABEL}`, { stdio: "pipe" });
4703
+ logger$1.info({ path: plistPath }, "Started launchd service");
4704
+ return;
4705
+ }
4706
+ if (platform === "linux") {
4707
+ execSync(`${isRootUser() ? "systemctl" : "systemctl --user"} start ${SYSTEMD_SERVICE}`, { stdio: "pipe" });
4708
+ logger$1.info("Started systemd service");
4709
+ return;
4710
+ }
4711
+ throw new Error(`Unsupported platform: ${platform}`);
4712
+ }
4713
+ /**
4586
4714
  * Write the current process PID to the PID file.
4587
4715
  */
4588
4716
  async function writePidFile() {
@@ -19918,6 +20046,8 @@ let integrationManager;
19918
20046
  let aiProxyServer = null;
19919
20047
  let runtimeProcess = null;
19920
20048
  let localRelay = null;
20049
+ let aiProxyUrl = null;
20050
+ let aiProxyRunning = false;
19921
20051
  let cloudConnected = false;
19922
20052
  let shuttingDown = false;
19923
20053
  /**
@@ -19968,20 +20098,21 @@ async function startDaemon() {
19968
20098
  commandQueue.startGC();
19969
20099
  logger$1.debug("Starting AI proxy...");
19970
20100
  try {
19971
- const { createProxyServer } = await import("@alfe.ai/ai-proxy-local");
20101
+ const { createProxyServer, DEFAULT_AI_PROXY_PORT } = await import("@alfe.ai/ai-proxy-local");
19972
20102
  const { getAiServiceUrlFromToken } = await import("@alfe.ai/config");
19973
20103
  const proxyUrl = getAiServiceUrlFromToken(config.apiKey);
19974
- const AI_PROXY_PORT = 18193;
19975
20104
  aiProxyServer = createProxyServer({
19976
- port: AI_PROXY_PORT,
20105
+ port: DEFAULT_AI_PROXY_PORT,
19977
20106
  apiKey: config.apiKey,
19978
20107
  proxyUrl
19979
20108
  });
19980
20109
  const server = aiProxyServer;
19981
20110
  await new Promise((resolve, reject) => {
19982
- server.listen(AI_PROXY_PORT, "127.0.0.1", () => {
20111
+ server.listen(DEFAULT_AI_PROXY_PORT, "127.0.0.1", () => {
20112
+ aiProxyRunning = true;
20113
+ aiProxyUrl = `http://127.0.0.1:${String(DEFAULT_AI_PROXY_PORT)}`;
19983
20114
  logger$1.info({
19984
- port: AI_PROXY_PORT,
20115
+ port: DEFAULT_AI_PROXY_PORT,
19985
20116
  upstream: proxyUrl
19986
20117
  }, "AI proxy started");
19987
20118
  resolve();
@@ -20042,8 +20173,8 @@ async function startDaemon() {
20042
20173
  cloudClient.setIntegrationManager(integrationAdapter);
20043
20174
  cloudClient.start();
20044
20175
  logger$1.debug("Cloud client started");
20045
- if (managed && config.runtime) {
20046
- logger$1.debug({ runtime: config.runtime }, "Starting agent runtime (managed mode)...");
20176
+ if (config.autoStartRuntime && config.runtime) {
20177
+ logger$1.debug({ runtime: config.runtime }, "Starting agent runtime...");
20047
20178
  const runtimeCfg = config.runtimes[config.runtime];
20048
20179
  if (runtimeCfg) {
20049
20180
  const runtimeToken = randomUUID();
@@ -20059,8 +20190,8 @@ async function startDaemon() {
20059
20190
  ALFE_API_KEY: config.apiKey,
20060
20191
  ALFE_API_URL: config.apiEndpoint,
20061
20192
  ALFE_AGENT_ID: config.agentId,
20062
- ANTHROPIC_BASE_URL: "http://127.0.0.1:18193",
20063
- OPENAI_BASE_URL: "http://127.0.0.1:18193",
20193
+ ANTHROPIC_BASE_URL: aiProxyUrl ?? "http://127.0.0.1:18193",
20194
+ OPENAI_BASE_URL: aiProxyUrl ?? "http://127.0.0.1:18193",
20064
20195
  OPENCLAW_GATEWAY_TOKEN: runtimeToken
20065
20196
  }
20066
20197
  });
@@ -20113,6 +20244,7 @@ async function startDaemon() {
20113
20244
  resolve();
20114
20245
  });
20115
20246
  });
20247
+ aiProxyRunning = false;
20116
20248
  logger$1.debug("AI proxy stopped");
20117
20249
  }
20118
20250
  logger$1.debug("Stopping cloud client...");
@@ -20137,33 +20269,94 @@ async function startDaemon() {
20137
20269
  }, "Alfe Gateway Daemon started ✅");
20138
20270
  }
20139
20271
  async function handleCloudCommand(command) {
20140
- if (command.command === "support.diagnostic") try {
20141
- const { runDiagnostic } = await import("@alfe.ai/doctor");
20272
+ if (command.command === "support.diagnostic") {
20142
20273
  const payload = command.payload;
20143
- const workspacePath = Object.values(config.runtimes)[0]?.workspace ?? "~/.openclaw";
20144
- const report = await runDiagnostic({
20145
- task: payload.task,
20146
- workspacePath,
20147
- timeoutSeconds: 300
20148
- });
20149
- return {
20150
- type: "COMMAND_ACK",
20151
- commandId: command.commandId,
20152
- status: report.success ? "ok" : "error",
20153
- result: report
20154
- };
20155
- } catch (err) {
20156
- const message = err instanceof Error ? err.message : String(err);
20157
- logger$1.error({ err: message }, "Diagnostic failed");
20158
- return {
20274
+ if (!payload.apiKey && !aiProxyRunning) return {
20159
20275
  type: "COMMAND_ACK",
20160
20276
  commandId: command.commandId,
20161
20277
  status: "error",
20162
20278
  result: {
20163
- code: "DIAGNOSTIC_FAILED",
20164
- message
20279
+ code: "PROXY_NOT_RUNNING",
20280
+ message: "AI proxy is not running — diagnostic requires LLM access"
20165
20281
  }
20166
20282
  };
20283
+ let proxyUrl;
20284
+ if (aiProxyRunning) proxyUrl = aiProxyUrl ?? void 0;
20285
+ else {
20286
+ const { getAiServiceUrlFromToken } = await import("@alfe.ai/config");
20287
+ proxyUrl = getAiServiceUrlFromToken(config.apiKey);
20288
+ }
20289
+ try {
20290
+ const { runDiagnostic } = await import("@alfe.ai/doctor");
20291
+ const workspacePath = Object.values(config.runtimes)[0]?.workspace ?? "~/.openclaw";
20292
+ const report = await runDiagnostic({
20293
+ task: payload.task,
20294
+ workspacePath,
20295
+ timeoutSeconds: 300,
20296
+ proxyUrl,
20297
+ apiKey: payload.apiKey
20298
+ });
20299
+ return {
20300
+ type: "COMMAND_ACK",
20301
+ commandId: command.commandId,
20302
+ status: report.success ? "ok" : "error",
20303
+ result: report
20304
+ };
20305
+ } catch (err) {
20306
+ const message = err instanceof Error ? err.message : String(err);
20307
+ logger$1.error({ err: message }, "Diagnostic failed");
20308
+ return {
20309
+ type: "COMMAND_ACK",
20310
+ commandId: command.commandId,
20311
+ status: "error",
20312
+ result: {
20313
+ code: "DIAGNOSTIC_FAILED",
20314
+ message
20315
+ }
20316
+ };
20317
+ }
20318
+ }
20319
+ if (command.command === "integration.status") {
20320
+ const payload = command.payload;
20321
+ try {
20322
+ if (payload?.integrationId) {
20323
+ const info = integrationManager.get(payload.integrationId);
20324
+ if (!info) return {
20325
+ type: "COMMAND_ACK",
20326
+ commandId: command.commandId,
20327
+ status: "error",
20328
+ result: {
20329
+ code: "NOT_FOUND",
20330
+ message: `Integration "${payload.integrationId}" not found`
20331
+ }
20332
+ };
20333
+ return {
20334
+ type: "COMMAND_ACK",
20335
+ commandId: command.commandId,
20336
+ status: "ok",
20337
+ result: { integrations: [info] }
20338
+ };
20339
+ }
20340
+ const integrations = integrationManager.list();
20341
+ return {
20342
+ type: "COMMAND_ACK",
20343
+ commandId: command.commandId,
20344
+ status: "ok",
20345
+ result: { integrations }
20346
+ };
20347
+ } catch (err) {
20348
+ const message = err instanceof Error ? err.message : String(err);
20349
+ logger$1.error({ err: message }, "Integration status failed");
20350
+ return {
20351
+ type: "COMMAND_ACK",
20352
+ commandId: command.commandId,
20353
+ status: "error",
20354
+ result: {
20355
+ code: "STATUS_FAILED",
20356
+ message
20357
+ }
20358
+ };
20359
+ }
20167
20360
  }
20168
20361
  const ipcRequest = cloudCommandToIPCRequest(command);
20169
20362
  if (!ipcRequest) {
@@ -20249,6 +20442,7 @@ function handleStatus() {
20249
20442
  status: cloudConnected ? "connected" : "disconnected",
20250
20443
  latencyMs: cloudClient.getLatencyMs()
20251
20444
  },
20445
+ aiProxy: { status: aiProxyRunning ? "running" : "stopped" },
20252
20446
  plugins: (ipcServer?.getRegisteredPlugins() ?? []).map(([, info]) => ({
20253
20447
  name: info.name,
20254
20448
  version: info.version,
@@ -20336,6 +20530,7 @@ async function queryDaemonHealth(socketPath, timeoutMs = 5e3) {
20336
20530
  if (err.code === "ECONNREFUSED" || err.code === "ENOENT") resolve({
20337
20531
  daemon: { status: "stopped" },
20338
20532
  cloud: { status: "unknown" },
20533
+ aiProxy: { status: "stopped" },
20339
20534
  plugins: [],
20340
20535
  commandQueue: { totalPending: 0 }
20341
20536
  });
@@ -20352,6 +20547,8 @@ function formatHealthReport(health) {
20352
20547
  lines.push(` Gateway daemon ${daemonIcon} ${health.daemon.status}` + (health.daemon.uptime ? ` (uptime: ${formatUptime(health.daemon.uptime)})` : "") + (health.daemon.version ? ` v${health.daemon.version}` : ""));
20353
20548
  const cloudIcon = health.cloud.status === "connected" ? "✓" : "✗";
20354
20549
  lines.push(` Cloud connection ${cloudIcon} ${health.cloud.status}` + (health.cloud.latencyMs !== void 0 ? ` (latency: ${String(health.cloud.latencyMs)}ms)` : ""));
20550
+ const proxyIcon = health.aiProxy.status === "running" ? "✓" : "✗";
20551
+ lines.push(` AI proxy ${proxyIcon} ${health.aiProxy.status}`);
20355
20552
  if (health.plugins.length === 0) lines.push(" Plugins – none connected");
20356
20553
  else for (const plugin of health.plugins) {
20357
20554
  const lastSeenAgo = Date.now() - plugin.lastSeen;
@@ -20373,4 +20570,4 @@ function formatDuration(ms) {
20373
20570
  return `${String(Math.round(seconds / 3600))}h`;
20374
20571
  }
20375
20572
  //#endregion
20376
- export { installService as a, PROTOCOL_VERSION as c, SOCKET_PATH as d, fetchAgentConfig as f, logger$1 as g, LOG_FILE as h, checkExistingDaemon as i, ALFE_DIR as l, resolveAgentIdentity as m, queryDaemonHealth as n, stopExistingDaemon as o, loadDaemonConfig as p, startDaemon as r, uninstallService as s, formatHealthReport as t, PID_PATH as u };
20573
+ export { logger$1 as _, installService as a, uninstallService as c, PID_PATH as d, SOCKET_PATH as f, LOG_FILE as g, resolveAgentIdentity as h, checkExistingDaemon as i, PROTOCOL_VERSION as l, loadDaemonConfig as m, queryDaemonHealth as n, startService as o, fetchAgentConfig as p, startDaemon as r, stopExistingDaemon as s, formatHealthReport as t, ALFE_DIR as u };
@@ -60,6 +60,8 @@ interface DaemonConfig {
60
60
  runtime: string;
61
61
  /** Runtime configurations keyed by runtime name (e.g. 'openclaw') */
62
62
  runtimes: Record<string, RuntimeConfig>;
63
+ /** Whether to auto-start the agent runtime process (e.g. openclaw) */
64
+ autoStartRuntime: boolean;
63
65
  }
64
66
  interface AgentIdentity {
65
67
  agentId: string;
@@ -113,6 +115,9 @@ interface DaemonHealth {
113
115
  status: 'connected' | 'disconnected' | 'unknown';
114
116
  latencyMs?: number;
115
117
  };
118
+ aiProxy: {
119
+ status: 'running' | 'stopped';
120
+ };
116
121
  plugins: {
117
122
  name: string;
118
123
  version: string;
@@ -152,6 +157,10 @@ declare function installService(): Promise<string>;
152
157
  * Uninstall the service unit for the current platform.
153
158
  */
154
159
  declare function uninstallService(): Promise<string>;
160
+ /**
161
+ * Start the installed service via systemctl/launchctl.
162
+ */
163
+ declare function startService(): void;
155
164
  /**
156
165
  * Write the current process PID to the PID file.
157
166
  */
@@ -166,4 +175,4 @@ declare function checkExistingDaemon(): Promise<number | null>;
166
175
  */
167
176
  declare function stopExistingDaemon(): Promise<boolean>;
168
177
  //#endregion
169
- export { ALFE_DIR, type AgentIdentity, type AgentWorkspaceConfig, type DaemonConfig, type DaemonHealth, type IPCEvent, type IPCRequest, type IPCResponse, PID_PATH, PROTOCOL_VERSION, SOCKET_PATH, checkExistingDaemon, fetchAgentConfig, formatHealthReport, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, startDaemon, stopExistingDaemon, uninstallService };
178
+ export { ALFE_DIR, type AgentIdentity, type AgentWorkspaceConfig, type DaemonConfig, type DaemonHealth, type IPCEvent, type IPCRequest, type IPCResponse, PID_PATH, PROTOCOL_VERSION, SOCKET_PATH, checkExistingDaemon, fetchAgentConfig, formatHealthReport, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, startDaemon, startService, stopExistingDaemon, uninstallService };
package/dist/src/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as installService, c as PROTOCOL_VERSION, d as SOCKET_PATH, f as fetchAgentConfig, g as logger, i as checkExistingDaemon, l as ALFE_DIR, m as resolveAgentIdentity, n as queryDaemonHealth, o as stopExistingDaemon, p as loadDaemonConfig, r as startDaemon, s as uninstallService, t as formatHealthReport, u as PID_PATH } from "../health.js";
2
- export { ALFE_DIR, PID_PATH, PROTOCOL_VERSION, SOCKET_PATH, checkExistingDaemon, fetchAgentConfig, formatHealthReport, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, startDaemon, stopExistingDaemon, uninstallService };
1
+ import { _ as logger, a as installService, c as uninstallService, d as PID_PATH, f as SOCKET_PATH, h as resolveAgentIdentity, i as checkExistingDaemon, l as PROTOCOL_VERSION, m as loadDaemonConfig, n as queryDaemonHealth, o as startService, p as fetchAgentConfig, r as startDaemon, s as stopExistingDaemon, t as formatHealthReport, u as ALFE_DIR } from "../health.js";
2
+ export { ALFE_DIR, PID_PATH, PROTOCOL_VERSION, SOCKET_PATH, checkExistingDaemon, fetchAgentConfig, formatHealthReport, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, startDaemon, startService, stopExistingDaemon, uninstallService };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfe.ai/gateway",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "Alfe local gateway daemon — persistent control plane for agent integrations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,8 +19,8 @@
19
19
  ],
20
20
  "dependencies": {
21
21
  "pino": "^9.6.0",
22
- "smol-toml": "^1.3.0",
23
22
  "pino-roll": "^1.2.0",
23
+ "smol-toml": ">=1.6.1",
24
24
  "ws": "^8.18.0",
25
25
  "@alfe.ai/ai-proxy-local": "^0.0.2",
26
26
  "@alfe.ai/config": "^0.0.2",