@alfe.ai/gateway 0.0.1

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/README.md ADDED
@@ -0,0 +1,163 @@
1
+ # @alfe.ai/gateway
2
+
3
+ Local gateway daemon for Alfe — the always-on control plane for agent integrations.
4
+
5
+ ## Overview
6
+
7
+ The gateway daemon is a standalone Node.js process that:
8
+
9
+ - Maintains a persistent WebSocket connection to Alfe cloud (`@alfe/gateway-service` on Fly.io)
10
+ - Exposes a Unix socket at `~/.alfe/gateway.sock` for local plugin IPC
11
+ - Translates between the cloud protocol and local IPC protocol
12
+ - Survives OpenClaw restarts — it's the always-on bridge between cloud and agent
13
+ - Queues commands when plugins are offline (5min TTL)
14
+
15
+ ## Architecture
16
+
17
+ ```
18
+ Alfe Cloud ←—— control WS ——→ @alfe.ai/gateway (daemon, always running)
19
+ ↕ IPC (~/.alfe/gateway.sock)
20
+ @alfe.ai/openclaw (OpenClaw plugin, Phase 2)
21
+
22
+ OpenClaw process
23
+ ```
24
+
25
+ ## Prerequisites
26
+
27
+ 1. Run `alfe login` to configure your API key in `~/.alfe/config.toml`
28
+ 2. Node.js 22+
29
+ 3. pnpm
30
+
31
+ ## Usage
32
+
33
+ ### Via `alfe` CLI (recommended)
34
+
35
+ ```bash
36
+ # Start daemon (foreground)
37
+ alfe gateway start
38
+
39
+ # Check status
40
+ alfe gateway status
41
+
42
+ # Stop daemon
43
+ alfe gateway stop
44
+
45
+ # Install as system service (auto-start on boot)
46
+ alfe gateway install
47
+
48
+ # Remove system service
49
+ alfe gateway uninstall
50
+
51
+ # View logs
52
+ alfe gateway logs
53
+
54
+ # Full health check
55
+ alfe doctor
56
+ ```
57
+
58
+ ### Via standalone binary
59
+
60
+ ```bash
61
+ # Start daemon
62
+ alfe-gateway daemon
63
+
64
+ # Status
65
+ alfe-gateway status
66
+
67
+ # Stop
68
+ alfe-gateway stop
69
+ ```
70
+
71
+ ## IPC Protocol
72
+
73
+ Plugins connect to `~/.alfe/gateway.sock` and speak newline-delimited JSON:
74
+
75
+ ### Request (plugin → daemon)
76
+ ```json
77
+ { "type": "req", "id": "uuid", "method": "register", "params": { "name": "my-plugin", "version": "1.0.0", "protocolVersion": 1, "capabilities": ["integrations"] } }
78
+ ```
79
+
80
+ ### Response (daemon → plugin)
81
+ ```json
82
+ { "id": "uuid", "ok": true, "payload": { "status": "registered", "daemonVersion": "0.1.0", "protocolVersion": 1 } }
83
+ ```
84
+
85
+ ### Event (daemon → plugin)
86
+ ```json
87
+ { "type": "event", "event": "cloud.status", "payload": { "connected": true } }
88
+ ```
89
+
90
+ ### Phase 1 Methods
91
+
92
+ | Direction | Method | Description |
93
+ |-----------|--------|-------------|
94
+ | Daemon→Plugin | `integration.install` | Install an integration |
95
+ | Daemon→Plugin | `integration.remove` | Remove an integration |
96
+ | Daemon→Plugin | `integration.configure` | Update integration config |
97
+ | Daemon→Plugin | `integration.health` | Check integration health |
98
+ | Daemon→Plugin | `integration.activate` | Activate an installed integration |
99
+ | Daemon→Plugin | `integration.deactivate` | Deactivate a running integration |
100
+ | Daemon→Plugin | `integration.list` | List installed integrations |
101
+ | Plugin→Daemon | `register` | Register plugin with daemon |
102
+ | Plugin→Daemon | `status` | Get daemon health status |
103
+ | Plugin→Daemon | `integration.list` | List known integrations |
104
+ | Plugin→Daemon | `integration.report` | Report integration status |
105
+
106
+ ## File Locations
107
+
108
+ | File | Path |
109
+ |------|------|
110
+ | Config | `~/.alfe/config.toml` |
111
+ | Socket | `~/.alfe/gateway.sock` |
112
+ | PID file | `~/.alfe/gateway.pid` |
113
+ | Logs | `~/.alfe/logs/gateway.log` |
114
+ | launchd plist | `~/Library/LaunchAgents/ai.alfe.gateway.plist` |
115
+ | systemd unit | `~/.config/systemd/user/alfe-gateway.service` |
116
+
117
+ ## Security
118
+
119
+ - Socket file is `chmod 0600` (owner-only access)
120
+ - PID file prevents multiple daemon instances
121
+ - Secrets pass through in-memory only — never persisted to disk
122
+ - Auth via user's `api_key` from `~/.alfe/config.toml`
123
+
124
+ ## Development
125
+
126
+ ```bash
127
+ # From monorepo root
128
+ pnpm install
129
+ pnpm --filter @alfe.ai/gateway build
130
+ pnpm --filter @alfe.ai/gateway test
131
+
132
+ # Dev mode (auto-restart on changes)
133
+ pnpm --filter @alfe.ai/gateway dev
134
+ ```
135
+
136
+ ## Cloud Protocol
137
+
138
+ The daemon speaks the following message types with the cloud gateway service:
139
+
140
+ | Direction | Message | Description |
141
+ |-----------|---------|-------------|
142
+ | Outbound | `SERVICE_REGISTER` | Register daemon with cloud |
143
+ | Inbound | `SERVICE_ACK` | Cloud acknowledges registration |
144
+ | Inbound | `COMMAND` | Cloud sends a command to execute |
145
+ | Outbound | `COMMAND_ACK` | Daemon reports command result |
146
+ | Inbound | `DESIRED_STATE` | Cloud pushes desired integration state |
147
+ | Outbound | `RECONCILIATION_REPORT` | Daemon reports reconciliation results |
148
+ | Inbound | `PING` | Cloud heartbeat |
149
+ | Outbound | `PONG` | Daemon heartbeat response |
150
+
151
+ See `src/protocol.ts` for full type definitions.
152
+
153
+ ## Completed
154
+
155
+ - `@alfe.ai/openclaw` plugin connecting via IPC (`packages/openclaw/`)
156
+ - Integration manifest spec (`packages/integration-manifest/`)
157
+ - Integration registry — now DynamoDB-backed via `services/integrations/`
158
+ - Reconciliation engine (`src/reconciliation.ts`) — converges local state to cloud desired state
159
+
160
+ ## Roadmap
161
+
162
+ - Dashboard integration management (backend wired, UI in progress)
163
+ - Voice migration to integration model (`packages/openclaw-voice/` exists, not yet full integration)
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,125 @@
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";
3
+ import { spawn } from "node:child_process";
4
+ //#region bin/gateway.ts
5
+ /**
6
+ * Alfe Gateway CLI — manages the local daemon.
7
+ *
8
+ * Commands:
9
+ * daemon - Run the daemon in foreground (used by service managers)
10
+ * start - Start the daemon (background via service manager, or foreground fallback)
11
+ * stop - Stop a running daemon
12
+ * restart - Restart the daemon
13
+ * status - Show daemon status
14
+ * install - Install as a system service (launchd/systemd)
15
+ * uninstall - Remove the system service
16
+ * logs - Tail daemon logs
17
+ */
18
+ const command = process.argv[2];
19
+ async function main() {
20
+ switch (command) {
21
+ case "daemon":
22
+ await startDaemon();
23
+ break;
24
+ case "start": {
25
+ const existingPid = await checkExistingDaemon();
26
+ if (existingPid) {
27
+ console.log(`Daemon already running (PID ${String(existingPid)})`);
28
+ process.exit(0);
29
+ }
30
+ console.log("Starting Alfe Gateway Daemon...");
31
+ await startDaemon();
32
+ break;
33
+ }
34
+ case "stop":
35
+ if (await stopExistingDaemon()) console.log("Daemon stopped");
36
+ else console.log("Daemon is not running");
37
+ break;
38
+ case "restart":
39
+ if (await stopExistingDaemon()) {
40
+ console.log("Stopped existing daemon");
41
+ await new Promise((r) => setTimeout(r, 500));
42
+ }
43
+ console.log("Starting Alfe Gateway Daemon...");
44
+ await startDaemon();
45
+ break;
46
+ case "status":
47
+ try {
48
+ const health = await queryDaemonHealth(SOCKET_PATH);
49
+ console.log("\nAlfe Gateway Status\n");
50
+ console.log(formatHealthReport(health));
51
+ console.log();
52
+ } catch (err) {
53
+ const message = err instanceof Error ? err.message : String(err);
54
+ console.log(`\nAlfe Gateway Status\n`);
55
+ console.log(` Gateway daemon ✗ ${message}`);
56
+ console.log();
57
+ process.exit(1);
58
+ }
59
+ break;
60
+ case "install":
61
+ try {
62
+ const result = await installService();
63
+ console.log(result);
64
+ } catch (err) {
65
+ const message = err instanceof Error ? err.message : String(err);
66
+ console.error(`Install failed: ${message}`);
67
+ process.exit(1);
68
+ }
69
+ break;
70
+ case "uninstall":
71
+ try {
72
+ const result = await uninstallService();
73
+ console.log(result);
74
+ } catch (err) {
75
+ const message = err instanceof Error ? err.message : String(err);
76
+ console.error(`Uninstall failed: ${message}`);
77
+ process.exit(1);
78
+ }
79
+ break;
80
+ case "logs":
81
+ console.log(`Tailing ${LOG_FILE}\n`);
82
+ try {
83
+ spawn("tail", ["-f", LOG_FILE], { stdio: "inherit" }).on("error", () => {
84
+ console.error(`Cannot tail log file: ${LOG_FILE}`);
85
+ process.exit(1);
86
+ });
87
+ } catch {
88
+ console.error(`Log file not found: ${LOG_FILE}`);
89
+ process.exit(1);
90
+ }
91
+ break;
92
+ default:
93
+ console.log(`
94
+ Alfe Gateway Daemon
95
+
96
+ Usage: alfe-gateway <command>
97
+
98
+ Commands:
99
+ daemon Run daemon in foreground (for service managers)
100
+ start Start the daemon
101
+ stop Stop the daemon
102
+ restart Restart the daemon
103
+ status Show daemon and connection status
104
+ install Install as system service (launchd/systemd)
105
+ uninstall Remove system service
106
+ logs Tail daemon logs
107
+
108
+ Examples:
109
+ alfe-gateway start # Start daemon
110
+ alfe-gateway status # Check status
111
+ alfe-gateway install # Auto-start on boot
112
+ `);
113
+ if (command) {
114
+ console.error(`Unknown command: ${command}`);
115
+ process.exit(1);
116
+ }
117
+ }
118
+ }
119
+ main().catch((err) => {
120
+ const message = err instanceof Error ? err.message : String(err);
121
+ console.error("Fatal error:", message);
122
+ process.exit(1);
123
+ });
124
+ //#endregion
125
+ export {};