@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.
- package/dist/bin/gateway.js +1 -1
- package/dist/health.js +252 -55
- package/dist/src/index.d.ts +10 -1
- package/dist/src/index.js +2 -2
- package/package.json +2 -2
package/dist/bin/gateway.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as installService,
|
|
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.
|
|
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
|
-
|
|
3318
|
-
|
|
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 =
|
|
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
|
|
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=${
|
|
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
|
|
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
|
|
4562
|
-
|
|
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({
|
|
4669
|
+
logger$1.info({
|
|
4670
|
+
path: unitPath,
|
|
4671
|
+
root
|
|
4672
|
+
}, "Wrote systemd unit");
|
|
4565
4673
|
try {
|
|
4566
|
-
execSync(
|
|
4567
|
-
execSync(
|
|
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
|
|
4680
|
+
const root = isRootUser();
|
|
4681
|
+
const unitPath = root ? getSystemdSystemServicePath() : getSystemdServicePath();
|
|
4682
|
+
const ctl = root ? "systemctl" : "systemctl --user";
|
|
4573
4683
|
try {
|
|
4574
|
-
execSync(
|
|
4575
|
-
execSync(
|
|
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(
|
|
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:
|
|
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(
|
|
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:
|
|
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 (
|
|
20046
|
-
logger$1.debug({ runtime: config.runtime }, "Starting agent runtime
|
|
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")
|
|
20141
|
-
const { runDiagnostic } = await import("@alfe.ai/doctor");
|
|
20272
|
+
if (command.command === "support.diagnostic") {
|
|
20142
20273
|
const payload = command.payload;
|
|
20143
|
-
|
|
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: "
|
|
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,
|
|
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 };
|
package/dist/src/index.d.ts
CHANGED
|
@@ -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
|
|
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.
|
|
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",
|