@alfe.ai/gateway 0.0.1 → 0.0.2

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/health.js CHANGED
@@ -5,6 +5,7 @@ import { homedir } from "node:os";
5
5
  import pino from "pino";
6
6
  import { chmodSync, existsSync, mkdirSync, unlinkSync } from "node:fs";
7
7
  import { getEndpointFromToken, readConfig } from "@alfe.ai/config";
8
+ import { AlfeApiClient, AuthService } from "@alfe/api-client";
8
9
  import { parse } from "smol-toml";
9
10
  import WebSocket from "ws";
10
11
  import { createConnection, createServer } from "node:net";
@@ -71,22 +72,32 @@ const PID_PATH = join(ALFE_DIR, "gateway.pid");
71
72
  * Returns agentId (derived from tokenId) and orgId (tenantId).
72
73
  */
73
74
  async function resolveAgentIdentity(apiKey, apiEndpoint) {
74
- const validateUrl = `${apiEndpoint}/auth/validate`;
75
- const response = await fetch(validateUrl, {
76
- method: "POST",
77
- headers: { "Content-Type": "application/json" },
78
- body: JSON.stringify({ token: apiKey })
79
- });
80
- if (!response.ok) throw new Error(`Token validation failed (HTTP ${String(response.status)}). Is your API key valid? Run \`alfe login\` to reconfigure.`);
81
- const result = await response.json();
82
- if (!result.success || !result.data?.valid) throw new Error(`API key invalid: ${result.data?.error ?? "validation failed"}. Run \`alfe login\` to reconfigure.`);
83
- const orgId = result.data.tenantId;
84
- if (!orgId) throw new Error("Token validation returned no tenantId — cannot determine org.");
85
- return {
86
- agentId: result.data.tokenId ?? deriveAgentId(apiKey),
87
- orgId,
88
- runtime: result.data.runtime ?? "openclaw"
89
- };
75
+ const auth = new AuthService(new AlfeApiClient({
76
+ apiBaseUrl: apiEndpoint,
77
+ getToken: () => Promise.resolve(apiKey)
78
+ }));
79
+ const maxAttempts = 3;
80
+ const delayMs = 3e3;
81
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
82
+ const result = await auth.validate(apiKey);
83
+ if (!result.ok) {
84
+ if (result.status === 401 || result.status === 403) throw new Error(`Token validation failed: ${result.error}. Is your API key valid? Run \`alfe login\` to reconfigure.`);
85
+ if (attempt < maxAttempts) {
86
+ await new Promise((r) => setTimeout(r, delayMs));
87
+ continue;
88
+ }
89
+ throw new Error(`Token validation failed after ${String(maxAttempts)} attempts: ${result.error}. Is your API key valid? Run \`alfe login\` to reconfigure.`);
90
+ }
91
+ if (!result.data.valid) throw new Error("API key invalid: validation failed. Run `alfe login` to reconfigure.");
92
+ const orgId = result.data.tenantId;
93
+ if (!orgId) throw new Error("Token validation returned no tenantId — cannot determine org.");
94
+ return {
95
+ agentId: result.data.tokenId ?? deriveAgentId(apiKey),
96
+ orgId,
97
+ runtime: result.data.runtime ?? "openclaw"
98
+ };
99
+ }
100
+ throw new Error("Token validation failed: exhausted retries.");
90
101
  }
91
102
  /**
92
103
  * Derive a stable agent ID from an API key (fallback when tokenId not available).
@@ -192,10 +203,10 @@ async function loadDaemonConfig() {
192
203
  /**
193
204
  * Fetch agent workspace config from the API.
194
205
  *
195
- * 1. GET /agents/me/workspace → { personalityKey }
196
- * 2. If personalityKey set, GET /personalities/:key/files → persona file contents
206
+ * 1. GET /agents/me/workspace → { templateKey }
207
+ * 2. If templateKey set, GET /templates/:key/files → persona file contents
197
208
  *
198
- * Returns null if the agent has no personality assigned or the fetch fails.
209
+ * Returns null if the agent has no template assigned or the fetch fails.
199
210
  */
200
211
  async function fetchAgentConfig(apiKey, apiEndpoint) {
201
212
  try {
@@ -204,18 +215,18 @@ async function fetchAgentConfig(apiKey, apiEndpoint) {
204
215
  headers: { "Authorization": `Bearer ${apiKey}` }
205
216
  });
206
217
  if (!wsResponse.ok) return null;
207
- const personalityKey = (await wsResponse.json()).data?.personalityKey;
208
- if (!personalityKey) return null;
209
- const filesResponse = await fetch(`${apiEndpoint}/personalities/${encodeURIComponent(personalityKey)}/files`, {
218
+ const templateKey = (await wsResponse.json()).data?.templateKey;
219
+ if (!templateKey) return null;
220
+ const filesResponse = await fetch(`${apiEndpoint}/templates/${encodeURIComponent(templateKey)}/files`, {
210
221
  method: "GET",
211
222
  headers: { "Authorization": `Bearer ${apiKey}` }
212
223
  });
213
224
  if (!filesResponse.ok) return {
214
- personalityKey,
225
+ templateKey,
215
226
  files: {}
216
227
  };
217
228
  return {
218
- personalityKey,
229
+ templateKey,
219
230
  files: (await filesResponse.json()).data?.files ?? {}
220
231
  };
221
232
  } catch {
@@ -232,6 +243,7 @@ const ID_PREFIXES = {
232
243
  token: "tok",
233
244
  transaction: "txn",
234
245
  subscription: "sub",
246
+ conversation: "conv",
235
247
  request: "req",
236
248
  connection: "conn",
237
249
  correlation: "cor",
@@ -1635,6 +1647,35 @@ async function startDaemon() {
1635
1647
  }, "Alfe Gateway Daemon started ✅");
1636
1648
  }
1637
1649
  async function handleCloudCommand(command) {
1650
+ if (command.command === "support.diagnostic") try {
1651
+ const { runDiagnostic } = await import("@alfe.ai/doctor");
1652
+ const payload = command.payload;
1653
+ const workspacePath = Object.values(config.runtimes)[0]?.workspace ?? "~/.openclaw";
1654
+ const report = await runDiagnostic({
1655
+ task: payload.task,
1656
+ workspacePath,
1657
+ apiKey: payload.apiKey,
1658
+ timeoutSeconds: 60
1659
+ });
1660
+ return {
1661
+ type: "COMMAND_ACK",
1662
+ commandId: command.commandId,
1663
+ status: report.success ? "ok" : "error",
1664
+ result: report
1665
+ };
1666
+ } catch (err) {
1667
+ const message = err instanceof Error ? err.message : String(err);
1668
+ logger.error({ err: message }, "Diagnostic failed");
1669
+ return {
1670
+ type: "COMMAND_ACK",
1671
+ commandId: command.commandId,
1672
+ status: "error",
1673
+ result: {
1674
+ code: "DIAGNOSTIC_FAILED",
1675
+ message
1676
+ }
1677
+ };
1678
+ }
1638
1679
  const ipcRequest = cloudCommandToIPCRequest(command);
1639
1680
  if (!ipcRequest) {
1640
1681
  logger.warn({ command: command.command }, "Unrecognized cloud command");
@@ -38,7 +38,7 @@ declare function startDaemon(): Promise<void>;
38
38
  * 4. Use tokenId as agent identity for cloud registration
39
39
  */
40
40
  interface AgentWorkspaceConfig {
41
- personalityKey?: string;
41
+ templateKey?: string;
42
42
  files: Record<string, string>;
43
43
  }
44
44
  declare const ALFE_DIR: string;
@@ -86,10 +86,10 @@ declare function loadDaemonConfig(): Promise<DaemonConfig>;
86
86
  /**
87
87
  * Fetch agent workspace config from the API.
88
88
  *
89
- * 1. GET /agents/me/workspace → { personalityKey }
90
- * 2. If personalityKey set, GET /personalities/:key/files → persona file contents
89
+ * 1. GET /agents/me/workspace → { templateKey }
90
+ * 2. If templateKey set, GET /templates/:key/files → persona file contents
91
91
  *
92
- * Returns null if the agent has no personality assigned or the fetch fails.
92
+ * Returns null if the agent has no template assigned or the fetch fails.
93
93
  */
94
94
  declare function fetchAgentConfig(apiKey: string, apiEndpoint: string): Promise<AgentWorkspaceConfig | null>;
95
95
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfe.ai/gateway",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Alfe local gateway daemon — persistent control plane for agent integrations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,8 +22,10 @@
22
22
  "smol-toml": "^1.3.0",
23
23
  "pino-roll": "^1.2.0",
24
24
  "ws": "^8.18.0",
25
- "@alfe.ai/config": "^0.0.1",
26
- "@alfe.ai/integrations": "^0.0.1"
25
+ "@alfe/api-client": "0.1.0",
26
+ "@alfe.ai/config": "^0.0.2",
27
+ "@alfe.ai/doctor": "^0.1.0",
28
+ "@alfe.ai/integrations": "^0.0.2"
27
29
  },
28
30
  "devDependencies": {
29
31
  "@types/ws": "^8.5.13",