@alfe.ai/cli 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 +53 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1021 -0
- package/dist/index.js.map +1 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @alfe.ai/cli
|
|
2
|
+
|
|
3
|
+
CLI for setting up and managing Alfe AI agents.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm install
|
|
9
|
+
pnpm build
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Authenticate with the Alfe API
|
|
16
|
+
alfe login
|
|
17
|
+
|
|
18
|
+
# Run the setup wizard
|
|
19
|
+
alfe setup
|
|
20
|
+
|
|
21
|
+
# Diagnose environment and connectivity issues
|
|
22
|
+
alfe doctor
|
|
23
|
+
|
|
24
|
+
# Manage the local gateway daemon
|
|
25
|
+
alfe gateway start|stop|restart|status|install|uninstall|logs
|
|
26
|
+
|
|
27
|
+
# Manage integrations
|
|
28
|
+
alfe integration list|install|remove|configure|status|search
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Configuration
|
|
32
|
+
|
|
33
|
+
Config is stored at `~/.alfe/config.toml`:
|
|
34
|
+
|
|
35
|
+
```toml
|
|
36
|
+
api_key = "your-api-key-here"
|
|
37
|
+
gateway = "https://api.alfe.ai" # optional, derived from token prefix
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The API endpoint is derived automatically from your token prefix (`alfe_dev_`, `alfe_test_`, `alfe_live_`). The `gateway` field overrides this.
|
|
41
|
+
|
|
42
|
+
## Development
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Run in dev mode
|
|
46
|
+
pnpm dev
|
|
47
|
+
|
|
48
|
+
# Type check
|
|
49
|
+
pnpm typecheck
|
|
50
|
+
|
|
51
|
+
# Build
|
|
52
|
+
pnpm build
|
|
53
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,1021 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import ora from "ora";
|
|
6
|
+
import { confirm, input } from "@inquirer/prompts";
|
|
7
|
+
import { configExists, getEndpointFromToken, readConfig, writeConfig, writeRuntimeConfig } from "@alfe.ai/config";
|
|
8
|
+
import { fetchAgentConfig, installService, resolveAgentIdentity, startDaemon } from "@alfe.ai/gateway";
|
|
9
|
+
import { execFile, spawn } from "node:child_process";
|
|
10
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import { promisify } from "node:util";
|
|
14
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
15
|
+
//#region \0rolldown/runtime.js
|
|
16
|
+
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
17
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region ../../packages-internal/ids/dist/prefixes.js
|
|
20
|
+
const ID_PREFIXES = {
|
|
21
|
+
agent: "agt",
|
|
22
|
+
organization: "org",
|
|
23
|
+
person: "per",
|
|
24
|
+
auditEvent: "evt",
|
|
25
|
+
token: "tok",
|
|
26
|
+
transaction: "txn",
|
|
27
|
+
subscription: "sub",
|
|
28
|
+
request: "req",
|
|
29
|
+
connection: "conn",
|
|
30
|
+
correlation: "cor",
|
|
31
|
+
command: "cmd",
|
|
32
|
+
message: "msg",
|
|
33
|
+
ipcRequest: "ipc",
|
|
34
|
+
pluginConnection: "plg"
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region ../../packages-internal/ids/dist/create.js
|
|
38
|
+
var import_index_umd = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
39
|
+
(function(global, factory) {
|
|
40
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.ULID = {}));
|
|
41
|
+
})(exports, (function(exports$1) {
|
|
42
|
+
"use strict";
|
|
43
|
+
function createError(message) {
|
|
44
|
+
const err = new Error(message);
|
|
45
|
+
err.source = "ulid";
|
|
46
|
+
return err;
|
|
47
|
+
}
|
|
48
|
+
const ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
49
|
+
const ENCODING_LEN = 32;
|
|
50
|
+
const TIME_MAX = Math.pow(2, 48) - 1;
|
|
51
|
+
const TIME_LEN = 10;
|
|
52
|
+
const RANDOM_LEN = 16;
|
|
53
|
+
function replaceCharAt(str, index, char) {
|
|
54
|
+
if (index > str.length - 1) return str;
|
|
55
|
+
return str.substr(0, index) + char + str.substr(index + 1);
|
|
56
|
+
}
|
|
57
|
+
function incrementBase32(str) {
|
|
58
|
+
let done = void 0;
|
|
59
|
+
let index = str.length;
|
|
60
|
+
let char;
|
|
61
|
+
let charIndex;
|
|
62
|
+
const maxCharIndex = ENCODING_LEN - 1;
|
|
63
|
+
while (!done && index-- >= 0) {
|
|
64
|
+
char = str[index];
|
|
65
|
+
charIndex = ENCODING.indexOf(char);
|
|
66
|
+
if (charIndex === -1) throw createError("incorrectly encoded string");
|
|
67
|
+
if (charIndex === maxCharIndex) {
|
|
68
|
+
str = replaceCharAt(str, index, ENCODING[0]);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
done = replaceCharAt(str, index, ENCODING[charIndex + 1]);
|
|
72
|
+
}
|
|
73
|
+
if (typeof done === "string") return done;
|
|
74
|
+
throw createError("cannot increment this string");
|
|
75
|
+
}
|
|
76
|
+
function randomChar(prng) {
|
|
77
|
+
let rand = Math.floor(prng() * ENCODING_LEN);
|
|
78
|
+
if (rand === ENCODING_LEN) rand = ENCODING_LEN - 1;
|
|
79
|
+
return ENCODING.charAt(rand);
|
|
80
|
+
}
|
|
81
|
+
function encodeTime(now, len) {
|
|
82
|
+
if (isNaN(now)) throw new Error(now + " must be a number");
|
|
83
|
+
if (now > TIME_MAX) throw createError("cannot encode time greater than " + TIME_MAX);
|
|
84
|
+
if (now < 0) throw createError("time must be positive");
|
|
85
|
+
if (Number.isInteger(Number(now)) === false) throw createError("time must be an integer");
|
|
86
|
+
let mod;
|
|
87
|
+
let str = "";
|
|
88
|
+
for (; len > 0; len--) {
|
|
89
|
+
mod = now % ENCODING_LEN;
|
|
90
|
+
str = ENCODING.charAt(mod) + str;
|
|
91
|
+
now = (now - mod) / ENCODING_LEN;
|
|
92
|
+
}
|
|
93
|
+
return str;
|
|
94
|
+
}
|
|
95
|
+
function encodeRandom(len, prng) {
|
|
96
|
+
let str = "";
|
|
97
|
+
for (; len > 0; len--) str = randomChar(prng) + str;
|
|
98
|
+
return str;
|
|
99
|
+
}
|
|
100
|
+
function decodeTime(id) {
|
|
101
|
+
if (id.length !== TIME_LEN + RANDOM_LEN) throw createError("malformed ulid");
|
|
102
|
+
var time = id.substr(0, TIME_LEN).split("").reverse().reduce((carry, char, index) => {
|
|
103
|
+
const encodingIndex = ENCODING.indexOf(char);
|
|
104
|
+
if (encodingIndex === -1) throw createError("invalid character found: " + char);
|
|
105
|
+
return carry += encodingIndex * Math.pow(ENCODING_LEN, index);
|
|
106
|
+
}, 0);
|
|
107
|
+
if (time > TIME_MAX) throw createError("malformed ulid, timestamp too large");
|
|
108
|
+
return time;
|
|
109
|
+
}
|
|
110
|
+
function detectPrng(allowInsecure = false, root) {
|
|
111
|
+
if (!root) root = typeof window !== "undefined" ? window : null;
|
|
112
|
+
const browserCrypto = root && (root.crypto || root.msCrypto);
|
|
113
|
+
if (browserCrypto) return () => {
|
|
114
|
+
const buffer = new Uint8Array(1);
|
|
115
|
+
browserCrypto.getRandomValues(buffer);
|
|
116
|
+
return buffer[0] / 255;
|
|
117
|
+
};
|
|
118
|
+
else try {
|
|
119
|
+
const nodeCrypto = __require("crypto");
|
|
120
|
+
return () => nodeCrypto.randomBytes(1).readUInt8() / 255;
|
|
121
|
+
} catch (e) {}
|
|
122
|
+
if (allowInsecure) {
|
|
123
|
+
try {
|
|
124
|
+
console.error("secure crypto unusable, falling back to insecure Math.random()!");
|
|
125
|
+
} catch (e) {}
|
|
126
|
+
return () => Math.random();
|
|
127
|
+
}
|
|
128
|
+
throw createError("secure crypto unusable, insecure Math.random not allowed");
|
|
129
|
+
}
|
|
130
|
+
function factory(currPrng) {
|
|
131
|
+
if (!currPrng) currPrng = detectPrng();
|
|
132
|
+
return function ulid(seedTime) {
|
|
133
|
+
if (isNaN(seedTime)) seedTime = Date.now();
|
|
134
|
+
return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN, currPrng);
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function monotonicFactory(currPrng) {
|
|
138
|
+
if (!currPrng) currPrng = detectPrng();
|
|
139
|
+
let lastTime = 0;
|
|
140
|
+
let lastRandom;
|
|
141
|
+
return function ulid(seedTime) {
|
|
142
|
+
if (isNaN(seedTime)) seedTime = Date.now();
|
|
143
|
+
if (seedTime <= lastTime) {
|
|
144
|
+
const incrementedRandom = lastRandom = incrementBase32(lastRandom);
|
|
145
|
+
return encodeTime(lastTime, TIME_LEN) + incrementedRandom;
|
|
146
|
+
}
|
|
147
|
+
lastTime = seedTime;
|
|
148
|
+
const newRandom = lastRandom = encodeRandom(RANDOM_LEN, currPrng);
|
|
149
|
+
return encodeTime(seedTime, TIME_LEN) + newRandom;
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
const ulid = factory();
|
|
153
|
+
exports$1.decodeTime = decodeTime;
|
|
154
|
+
exports$1.detectPrng = detectPrng;
|
|
155
|
+
exports$1.encodeRandom = encodeRandom;
|
|
156
|
+
exports$1.encodeTime = encodeTime;
|
|
157
|
+
exports$1.factory = factory;
|
|
158
|
+
exports$1.incrementBase32 = incrementBase32;
|
|
159
|
+
exports$1.monotonicFactory = monotonicFactory;
|
|
160
|
+
exports$1.randomChar = randomChar;
|
|
161
|
+
exports$1.replaceCharAt = replaceCharAt;
|
|
162
|
+
exports$1.ulid = ulid;
|
|
163
|
+
}));
|
|
164
|
+
})))();
|
|
165
|
+
function createId(prefix) {
|
|
166
|
+
return `${prefix}_${(0, import_index_umd.ulid)()}`;
|
|
167
|
+
}
|
|
168
|
+
function correlationId() {
|
|
169
|
+
return createId(ID_PREFIXES.correlation);
|
|
170
|
+
}
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region ../../packages-internal/api-client/dist/client.js
|
|
173
|
+
/**
|
|
174
|
+
* @alfe/api-client — Typed HTTP client for Alfe services.
|
|
175
|
+
*
|
|
176
|
+
* Platform-agnostic: works in React Native and browser environments.
|
|
177
|
+
* Uses standard fetch() API — no Node.js dependencies.
|
|
178
|
+
*/
|
|
179
|
+
var AlfeApiClient = class {
|
|
180
|
+
apiBaseUrl;
|
|
181
|
+
getToken;
|
|
182
|
+
onAuthFailure;
|
|
183
|
+
constructor(options) {
|
|
184
|
+
this.apiBaseUrl = options.apiBaseUrl;
|
|
185
|
+
this.getToken = options.getToken;
|
|
186
|
+
this.onAuthFailure = options.onAuthFailure;
|
|
187
|
+
}
|
|
188
|
+
/** Shared fetch logic — handles auth, 401, and network errors. */
|
|
189
|
+
async _fetch(path, options) {
|
|
190
|
+
try {
|
|
191
|
+
const token = await this.getToken();
|
|
192
|
+
if (!token) {
|
|
193
|
+
this.onAuthFailure?.();
|
|
194
|
+
return {
|
|
195
|
+
ok: false,
|
|
196
|
+
result: {
|
|
197
|
+
ok: false,
|
|
198
|
+
error: "No auth token available",
|
|
199
|
+
status: 401
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
const url = `${this.apiBaseUrl}${path}`;
|
|
204
|
+
const headers = new Headers(options?.headers);
|
|
205
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
206
|
+
headers.set("Content-Type", "application/json");
|
|
207
|
+
headers.set("x-correlation-id", correlationId());
|
|
208
|
+
const res = await fetch(url, {
|
|
209
|
+
...options,
|
|
210
|
+
headers
|
|
211
|
+
});
|
|
212
|
+
if (res.status === 401) {
|
|
213
|
+
this.onAuthFailure?.();
|
|
214
|
+
return {
|
|
215
|
+
ok: false,
|
|
216
|
+
result: {
|
|
217
|
+
ok: false,
|
|
218
|
+
error: "Session expired",
|
|
219
|
+
status: 401
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
const body = await res.json();
|
|
224
|
+
if (!res.ok) return {
|
|
225
|
+
ok: false,
|
|
226
|
+
result: {
|
|
227
|
+
ok: false,
|
|
228
|
+
error: body.message || `API error: ${String(res.status)}`,
|
|
229
|
+
status: res.status
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
return {
|
|
233
|
+
ok: true,
|
|
234
|
+
res,
|
|
235
|
+
body
|
|
236
|
+
};
|
|
237
|
+
} catch (err) {
|
|
238
|
+
return {
|
|
239
|
+
ok: false,
|
|
240
|
+
result: {
|
|
241
|
+
ok: false,
|
|
242
|
+
error: err instanceof Error ? err.message : "Network error"
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Make an authenticated request to an Alfe API endpoint.
|
|
249
|
+
* Unwraps the @auriclabs/api-core `{ data, timestamp, requestId }` envelope.
|
|
250
|
+
*/
|
|
251
|
+
async request(path, options) {
|
|
252
|
+
const result = await this._fetch(path, options);
|
|
253
|
+
if (!result.ok) return result.result;
|
|
254
|
+
return {
|
|
255
|
+
ok: true,
|
|
256
|
+
data: result.body.data
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Make an authenticated request that returns the body directly (no envelope unwrap).
|
|
261
|
+
* Use for APIs that don't use the @auriclabs/api-core response format (e.g. gateway).
|
|
262
|
+
*/
|
|
263
|
+
async rawRequest(path, options) {
|
|
264
|
+
const result = await this._fetch(path, options);
|
|
265
|
+
if (!result.ok) return result.result;
|
|
266
|
+
return {
|
|
267
|
+
ok: true,
|
|
268
|
+
data: result.body
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
getApiBaseUrl() {
|
|
272
|
+
return this.apiBaseUrl;
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region ../../packages-internal/api-client/dist/services/auth.js
|
|
277
|
+
var AuthService = class {
|
|
278
|
+
client;
|
|
279
|
+
constructor(client) {
|
|
280
|
+
this.client = client;
|
|
281
|
+
}
|
|
282
|
+
prefix = "/auth";
|
|
283
|
+
validate() {
|
|
284
|
+
return this.client.request(`${this.prefix}/validate`);
|
|
285
|
+
}
|
|
286
|
+
listTokens() {
|
|
287
|
+
return this.client.request(`${this.prefix}/tokens`);
|
|
288
|
+
}
|
|
289
|
+
createToken(data) {
|
|
290
|
+
return this.client.request(`${this.prefix}/tokens`, {
|
|
291
|
+
method: "POST",
|
|
292
|
+
body: JSON.stringify(data)
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
deleteToken(tokenId) {
|
|
296
|
+
return this.client.request(`${this.prefix}/tokens/${tokenId}`, { method: "DELETE" });
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region src/commands/login.ts
|
|
301
|
+
/**
|
|
302
|
+
* alfe login — authenticate with the Alfe API.
|
|
303
|
+
*/
|
|
304
|
+
function createAuthService$1(apiKey, gateway) {
|
|
305
|
+
return new AuthService(new AlfeApiClient({
|
|
306
|
+
apiBaseUrl: (gateway ?? getEndpointFromToken(apiKey)).replace(/\/+$/, ""),
|
|
307
|
+
getToken: () => Promise.resolve(apiKey)
|
|
308
|
+
}));
|
|
309
|
+
}
|
|
310
|
+
const loginCommand = new Command("login").description("Authenticate with the Alfe API").action(async () => {
|
|
311
|
+
if (configExists()) {
|
|
312
|
+
const spinner = ora("Checking existing credentials…").start();
|
|
313
|
+
try {
|
|
314
|
+
const existing = await readConfig();
|
|
315
|
+
const result = await createAuthService$1(existing.api_key, existing.gateway).validate();
|
|
316
|
+
if (result.ok && result.data.valid) {
|
|
317
|
+
spinner.succeed(chalk.green("Already logged in. Your API key is valid."));
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
spinner.warn("Existing API key is invalid. Let's set up a new one.");
|
|
321
|
+
} catch {
|
|
322
|
+
spinner.warn("Couldn't read existing config. Let's set up a new one.");
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
const apiKey = await input({
|
|
326
|
+
message: "Paste your Alfe API key:",
|
|
327
|
+
transformer: (value) => "*".repeat(value.length),
|
|
328
|
+
validate: (value) => value.trim().length > 0 ? true : "API key cannot be empty"
|
|
329
|
+
});
|
|
330
|
+
const spinner = ora("Validating API key…").start();
|
|
331
|
+
const result = await createAuthService$1(apiKey.trim()).validate();
|
|
332
|
+
if (!result.ok || !result.data.valid) {
|
|
333
|
+
spinner.fail(chalk.red("Invalid API key. Please check your key and try again."));
|
|
334
|
+
process.exit(1);
|
|
335
|
+
}
|
|
336
|
+
await writeConfig({ api_key: apiKey.trim() });
|
|
337
|
+
spinner.succeed(chalk.green("Logged in successfully! Config saved to ~/.alfe/config.toml"));
|
|
338
|
+
});
|
|
339
|
+
//#endregion
|
|
340
|
+
//#region src/lib/runtime.ts
|
|
341
|
+
/**
|
|
342
|
+
* Runtime detection, installation, and workspace setup utilities.
|
|
343
|
+
*
|
|
344
|
+
* Handles detecting whether a runtime (e.g. openclaw) is installed,
|
|
345
|
+
* installing it if needed, initializing the workspace directory,
|
|
346
|
+
* and writing cloud-provided persona files.
|
|
347
|
+
*/
|
|
348
|
+
const execFileAsync = promisify(execFile);
|
|
349
|
+
/**
|
|
350
|
+
* Get the default workspace path for a runtime.
|
|
351
|
+
*/
|
|
352
|
+
function getDefaultWorkspace(runtime) {
|
|
353
|
+
if (runtime === "openclaw") return join(homedir(), ".openclaw");
|
|
354
|
+
return join(homedir(), `.${runtime}`);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Detect whether a runtime is installed and get its version.
|
|
358
|
+
*/
|
|
359
|
+
async function detectRuntime(name) {
|
|
360
|
+
if (name === "openclaw") try {
|
|
361
|
+
const { stdout } = await execFileAsync("openclaw", ["--version"]);
|
|
362
|
+
return {
|
|
363
|
+
installed: true,
|
|
364
|
+
version: stdout.trim()
|
|
365
|
+
};
|
|
366
|
+
} catch {
|
|
367
|
+
return { installed: false };
|
|
368
|
+
}
|
|
369
|
+
return { installed: false };
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Install a runtime globally via npm.
|
|
373
|
+
*/
|
|
374
|
+
async function installRuntime(name) {
|
|
375
|
+
if (name === "openclaw") {
|
|
376
|
+
await execFileAsync("npm", [
|
|
377
|
+
"install",
|
|
378
|
+
"-g",
|
|
379
|
+
"openclaw"
|
|
380
|
+
]);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
throw new Error(`Unknown runtime: ${name}`);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Initialize the runtime workspace directory.
|
|
387
|
+
* For openclaw, runs `openclaw onboard` in non-interactive mode.
|
|
388
|
+
*/
|
|
389
|
+
async function initWorkspace(name, workspace) {
|
|
390
|
+
if (name === "openclaw") {
|
|
391
|
+
await mkdir(workspace, { recursive: true });
|
|
392
|
+
try {
|
|
393
|
+
await execFileAsync("openclaw", [
|
|
394
|
+
"onboard",
|
|
395
|
+
"--non-interactive",
|
|
396
|
+
"--workspace",
|
|
397
|
+
workspace,
|
|
398
|
+
"--skip-health"
|
|
399
|
+
]);
|
|
400
|
+
} catch {
|
|
401
|
+
await mkdir(join(workspace, "config"), { recursive: true });
|
|
402
|
+
}
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
throw new Error(`Unknown runtime: ${name}`);
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Write cloud-provided persona files into the workspace.
|
|
409
|
+
* Files come from the personality registry (S3) as a filename→content map.
|
|
410
|
+
* Only writes files that have non-empty content.
|
|
411
|
+
*/
|
|
412
|
+
async function writeWorkspaceFiles(workspace, config) {
|
|
413
|
+
for (const [filename, content] of Object.entries(config.files)) if (content) await writeFile(join(workspace, filename), content, "utf-8");
|
|
414
|
+
}
|
|
415
|
+
//#endregion
|
|
416
|
+
//#region src/commands/setup.ts
|
|
417
|
+
/**
|
|
418
|
+
* alfe setup — interactive first-time setup.
|
|
419
|
+
*
|
|
420
|
+
* Walks the user through:
|
|
421
|
+
* 1. Authenticating with the Alfe API (login)
|
|
422
|
+
* 2. Detecting and installing the agent runtime (e.g. OpenClaw)
|
|
423
|
+
* 3. Initializing the runtime workspace with agent persona files
|
|
424
|
+
* 4. Installing the gateway daemon as a system service
|
|
425
|
+
*
|
|
426
|
+
* In managed mode (ALFE_MANAGED=true), skips interactive prompts
|
|
427
|
+
* and directly starts the gateway daemon.
|
|
428
|
+
*/
|
|
429
|
+
function createAuthService(apiKey, gateway) {
|
|
430
|
+
return new AuthService(new AlfeApiClient({
|
|
431
|
+
apiBaseUrl: (gateway ?? getEndpointFromToken(apiKey)).replace(/\/+$/, ""),
|
|
432
|
+
getToken: () => Promise.resolve(apiKey)
|
|
433
|
+
}));
|
|
434
|
+
}
|
|
435
|
+
async function runManagedSetup() {
|
|
436
|
+
console.log(chalk.bold("\nAlfe Managed Agent\n"));
|
|
437
|
+
const apiKey = process.env.ALFE_API_KEY;
|
|
438
|
+
if (!apiKey) {
|
|
439
|
+
console.error(chalk.red("ALFE_API_KEY environment variable is required"));
|
|
440
|
+
process.exit(1);
|
|
441
|
+
}
|
|
442
|
+
const apiEndpoint = process.env.ALFE_API_ENDPOINT;
|
|
443
|
+
if (!apiEndpoint) {
|
|
444
|
+
console.error(chalk.red("ALFE_API_ENDPOINT environment variable is required"));
|
|
445
|
+
process.exit(1);
|
|
446
|
+
}
|
|
447
|
+
const identity = await resolveAgentIdentity(apiKey, apiEndpoint);
|
|
448
|
+
const workspace = getDefaultWorkspace(identity.runtime);
|
|
449
|
+
const wsSpinner = ora("Initializing workspace…").start();
|
|
450
|
+
try {
|
|
451
|
+
await initWorkspace(identity.runtime, workspace);
|
|
452
|
+
wsSpinner.succeed(chalk.green("Workspace initialized."));
|
|
453
|
+
} catch (err) {
|
|
454
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
455
|
+
wsSpinner.fail(chalk.red(`Workspace init failed: ${message}`));
|
|
456
|
+
process.exit(1);
|
|
457
|
+
}
|
|
458
|
+
const configSpinner = ora("Fetching agent config…").start();
|
|
459
|
+
const agentConfig = await fetchAgentConfig(apiKey, apiEndpoint);
|
|
460
|
+
if (agentConfig) {
|
|
461
|
+
await writeWorkspaceFiles(workspace, agentConfig);
|
|
462
|
+
configSpinner.succeed(chalk.green("Agent persona applied."));
|
|
463
|
+
} else configSpinner.info("No workspace config found — using defaults.");
|
|
464
|
+
console.log(chalk.blue("Starting gateway daemon...\n"));
|
|
465
|
+
await startDaemon();
|
|
466
|
+
}
|
|
467
|
+
const setupCommand = new Command("setup").description("Set up Alfe — authenticate and install the gateway daemon").action(async () => {
|
|
468
|
+
if (process.env.ALFE_MANAGED === "true") return runManagedSetup();
|
|
469
|
+
console.log(chalk.bold("\nAlfe Setup\n"));
|
|
470
|
+
console.log(chalk.blue("Step 1:"), "Authenticate with Alfe Cloud\n");
|
|
471
|
+
let needsLogin = true;
|
|
472
|
+
let apiKey = "";
|
|
473
|
+
let gateway;
|
|
474
|
+
if (configExists()) {
|
|
475
|
+
const spinner = ora("Checking existing credentials…").start();
|
|
476
|
+
try {
|
|
477
|
+
const existing = await readConfig();
|
|
478
|
+
const result = await createAuthService(existing.api_key, existing.gateway).validate();
|
|
479
|
+
if (result.ok && result.data.valid) {
|
|
480
|
+
spinner.succeed(chalk.green("Already authenticated."));
|
|
481
|
+
needsLogin = false;
|
|
482
|
+
apiKey = existing.api_key;
|
|
483
|
+
gateway = existing.gateway;
|
|
484
|
+
} else spinner.warn("Existing API key is invalid.");
|
|
485
|
+
} catch {
|
|
486
|
+
spinner.warn("Couldn't verify existing config.");
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
if (needsLogin) {
|
|
490
|
+
apiKey = await input({
|
|
491
|
+
message: "Paste your Alfe API key:",
|
|
492
|
+
transformer: (value) => "*".repeat(value.length),
|
|
493
|
+
validate: (value) => value.trim().length > 0 ? true : "API key cannot be empty"
|
|
494
|
+
});
|
|
495
|
+
apiKey = apiKey.trim();
|
|
496
|
+
const spinner = ora("Validating API key…").start();
|
|
497
|
+
const result = await createAuthService(apiKey).validate();
|
|
498
|
+
if (!result.ok || !result.data.valid) {
|
|
499
|
+
spinner.fail(chalk.red("Invalid API key. Run alfe setup again with a valid key."));
|
|
500
|
+
process.exit(1);
|
|
501
|
+
}
|
|
502
|
+
await writeConfig({ api_key: apiKey });
|
|
503
|
+
spinner.succeed(chalk.green("Authenticated."));
|
|
504
|
+
}
|
|
505
|
+
console.log(chalk.blue("\nStep 2:"), "Configure agent runtime\n");
|
|
506
|
+
const apiEndpoint = gateway ?? getEndpointFromToken(apiKey);
|
|
507
|
+
const identitySpinner = ora("Resolving agent identity…").start();
|
|
508
|
+
let runtime;
|
|
509
|
+
try {
|
|
510
|
+
runtime = (await resolveAgentIdentity(apiKey, apiEndpoint)).runtime;
|
|
511
|
+
identitySpinner.succeed(chalk.green(`Agent runtime: ${runtime}`));
|
|
512
|
+
} catch (err) {
|
|
513
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
514
|
+
identitySpinner.fail(chalk.red(`Identity resolution failed: ${message}`));
|
|
515
|
+
process.exit(1);
|
|
516
|
+
}
|
|
517
|
+
const detection = await detectRuntime(runtime);
|
|
518
|
+
if (!detection.installed) if (await confirm({
|
|
519
|
+
message: `${runtime} is not installed. Install it now?`,
|
|
520
|
+
default: true
|
|
521
|
+
})) {
|
|
522
|
+
const installSpinner = ora(`Installing ${runtime}…`).start();
|
|
523
|
+
try {
|
|
524
|
+
await installRuntime(runtime);
|
|
525
|
+
installSpinner.succeed(chalk.green(`${runtime} installed.`));
|
|
526
|
+
} catch (err) {
|
|
527
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
528
|
+
installSpinner.fail(chalk.red(`Failed to install ${runtime}: ${message}`));
|
|
529
|
+
process.exit(1);
|
|
530
|
+
}
|
|
531
|
+
} else console.log(chalk.yellow(`Skipping ${runtime} install. You'll need to install it manually.`));
|
|
532
|
+
else console.log(chalk.green(` ${runtime} already installed (${detection.version ?? "unknown version"}).`));
|
|
533
|
+
const workspace = getDefaultWorkspace(runtime);
|
|
534
|
+
const wsSpinner = ora("Initializing workspace…").start();
|
|
535
|
+
try {
|
|
536
|
+
await initWorkspace(runtime, workspace);
|
|
537
|
+
wsSpinner.succeed(chalk.green("Workspace initialized."));
|
|
538
|
+
} catch (err) {
|
|
539
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
540
|
+
wsSpinner.fail(chalk.red(`Workspace init failed: ${message}`));
|
|
541
|
+
process.exit(1);
|
|
542
|
+
}
|
|
543
|
+
const configSpinner = ora("Fetching agent config…").start();
|
|
544
|
+
const agentConfig = await fetchAgentConfig(apiKey, apiEndpoint);
|
|
545
|
+
if (agentConfig) {
|
|
546
|
+
await writeWorkspaceFiles(workspace, agentConfig);
|
|
547
|
+
configSpinner.succeed(chalk.green("Agent persona applied."));
|
|
548
|
+
} else configSpinner.info("No workspace config found — using defaults.");
|
|
549
|
+
await writeRuntimeConfig(runtime, { workspace });
|
|
550
|
+
console.log(chalk.blue("\nStep 3:"), "Install the gateway daemon\n");
|
|
551
|
+
const gwSpinner = ora("Installing gateway service…").start();
|
|
552
|
+
try {
|
|
553
|
+
const result = await installService();
|
|
554
|
+
gwSpinner.succeed(chalk.green(result));
|
|
555
|
+
} catch (err) {
|
|
556
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
557
|
+
gwSpinner.fail(chalk.red(`Gateway install failed: ${message}`));
|
|
558
|
+
process.exit(1);
|
|
559
|
+
}
|
|
560
|
+
console.log(chalk.green("\n✓ Alfe is ready to use.\n"));
|
|
561
|
+
});
|
|
562
|
+
//#endregion
|
|
563
|
+
//#region src/commands/doctor.ts
|
|
564
|
+
/**
|
|
565
|
+
* alfe doctor — diagnose environment and connectivity issues.
|
|
566
|
+
*
|
|
567
|
+
* Checks:
|
|
568
|
+
* 1. Config exists and API key is valid
|
|
569
|
+
* 2. Gateway daemon status + cloud connection
|
|
570
|
+
* 3. Registered plugins and their health
|
|
571
|
+
*/
|
|
572
|
+
const SOCKET_PATH$1 = join(homedir(), ".alfe", "gateway.sock");
|
|
573
|
+
const doctorCommand = new Command("doctor").description("Diagnose environment and configuration issues").action(async () => {
|
|
574
|
+
console.log(chalk.bold("\n🩺 Alfe Doctor\n"));
|
|
575
|
+
console.log(chalk.dim("Checking configuration..."));
|
|
576
|
+
if (!configExists()) {
|
|
577
|
+
console.log(` Config ${chalk.red("✗")} ~/.alfe/config.toml not found`);
|
|
578
|
+
console.log(chalk.yellow("\n Run `alfe login` to set up your API key.\n"));
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
let apiKey;
|
|
582
|
+
let apiEndpoint;
|
|
583
|
+
try {
|
|
584
|
+
const config = await readConfig();
|
|
585
|
+
apiKey = config.api_key;
|
|
586
|
+
apiEndpoint = config.gateway ?? getEndpointFromToken(config.api_key);
|
|
587
|
+
console.log(` Config ${chalk.green("✓")} loaded (endpoint: ${apiEndpoint})`);
|
|
588
|
+
} catch (err) {
|
|
589
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
590
|
+
console.log(` Config ${chalk.red("✗")} ${message}`);
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
console.log(chalk.dim("Validating API key..."));
|
|
594
|
+
try {
|
|
595
|
+
const response = await fetch(`${apiEndpoint}/auth/validate`, {
|
|
596
|
+
method: "POST",
|
|
597
|
+
headers: { "Content-Type": "application/json" },
|
|
598
|
+
body: JSON.stringify({ token: apiKey })
|
|
599
|
+
});
|
|
600
|
+
if (response.ok) {
|
|
601
|
+
const result = await response.json();
|
|
602
|
+
if (result.success && result.data?.valid) console.log(` API key ${chalk.green("✓")} valid (org: ${result.data.tenantId ?? "unknown"})`);
|
|
603
|
+
else console.log(` API key ${chalk.red("✗")} invalid — run \`alfe login\``);
|
|
604
|
+
} else console.log(` API key ${chalk.red("✗")} validation failed (HTTP ${String(response.status)})`);
|
|
605
|
+
} catch (err) {
|
|
606
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
607
|
+
console.log(` API key ${chalk.yellow("?")} cannot reach API (${message})`);
|
|
608
|
+
}
|
|
609
|
+
console.log(chalk.dim("Checking gateway daemon..."));
|
|
610
|
+
try {
|
|
611
|
+
const { queryDaemonHealth, formatHealthReport } = await import("@alfe.ai/gateway");
|
|
612
|
+
const health = await queryDaemonHealth(SOCKET_PATH$1);
|
|
613
|
+
console.log(formatHealthReport(health));
|
|
614
|
+
} catch (err) {
|
|
615
|
+
if (err.code === "ERR_MODULE_NOT_FOUND") console.log(` Gateway daemon ${chalk.yellow("–")} @alfe.ai/gateway not installed`);
|
|
616
|
+
else {
|
|
617
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
618
|
+
console.log(` Gateway daemon ${chalk.red("✗")} unreachable (${message})`);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
console.log();
|
|
622
|
+
});
|
|
623
|
+
//#endregion
|
|
624
|
+
//#region src/commands/gateway.ts
|
|
625
|
+
/**
|
|
626
|
+
* alfe gateway — manage the local gateway daemon.
|
|
627
|
+
*
|
|
628
|
+
* Subcommands:
|
|
629
|
+
* start - Start the daemon
|
|
630
|
+
* stop - Stop the daemon
|
|
631
|
+
* restart - Restart the daemon
|
|
632
|
+
* status - Show daemon status
|
|
633
|
+
* install - Install as system service
|
|
634
|
+
* uninstall - Remove system service
|
|
635
|
+
* logs - Tail daemon logs
|
|
636
|
+
*/
|
|
637
|
+
const SOCKET_PATH = join(homedir(), ".alfe", "gateway.sock");
|
|
638
|
+
const PID_PATH = join(homedir(), ".alfe", "gateway.pid");
|
|
639
|
+
const LOG_FILE = join(homedir(), ".alfe", "logs", "gateway.log");
|
|
640
|
+
const gatewayCommand = new Command("gateway").description("Manage the Alfe gateway daemon").action(() => {
|
|
641
|
+
gatewayCommand.help();
|
|
642
|
+
});
|
|
643
|
+
gatewayCommand.command("start").description("Start the gateway daemon").action(async () => {
|
|
644
|
+
const pid = getRunningPid();
|
|
645
|
+
if (pid) {
|
|
646
|
+
console.log(chalk.yellow(`Daemon already running (PID ${String(pid)})`));
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
console.log(chalk.blue("Starting Alfe Gateway Daemon..."));
|
|
650
|
+
try {
|
|
651
|
+
const { startDaemon } = await import("@alfe.ai/gateway");
|
|
652
|
+
await startDaemon();
|
|
653
|
+
} catch (err) {
|
|
654
|
+
if (err.code === "ERR_MODULE_NOT_FOUND") console.error(chalk.red("Gateway package not found. Install with: pnpm add @alfe.ai/gateway"));
|
|
655
|
+
else {
|
|
656
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
657
|
+
console.error(chalk.red(`Failed to start daemon: ${message}`));
|
|
658
|
+
}
|
|
659
|
+
process.exit(1);
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
gatewayCommand.command("stop").description("Stop the gateway daemon").action(async () => {
|
|
663
|
+
const pid = getRunningPid();
|
|
664
|
+
if (!pid) {
|
|
665
|
+
console.log(chalk.yellow("Daemon is not running"));
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
try {
|
|
669
|
+
process.kill(pid, "SIGTERM");
|
|
670
|
+
console.log(chalk.green(`Sent SIGTERM to daemon (PID ${String(pid)})`));
|
|
671
|
+
for (let i = 0; i < 50; i++) {
|
|
672
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
673
|
+
try {
|
|
674
|
+
process.kill(pid, 0);
|
|
675
|
+
} catch {
|
|
676
|
+
console.log(chalk.green("Daemon stopped"));
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
console.log(chalk.yellow("Daemon did not stop — sending SIGKILL"));
|
|
681
|
+
process.kill(pid, "SIGKILL");
|
|
682
|
+
} catch {
|
|
683
|
+
console.log(chalk.yellow("Daemon is not running (stale PID file)"));
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
gatewayCommand.command("restart").description("Restart the gateway daemon").action(async () => {
|
|
687
|
+
const pid = getRunningPid();
|
|
688
|
+
if (pid) try {
|
|
689
|
+
process.kill(pid, "SIGTERM");
|
|
690
|
+
console.log(chalk.blue("Stopping daemon..."));
|
|
691
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
692
|
+
} catch {}
|
|
693
|
+
console.log(chalk.blue("Starting Alfe Gateway Daemon..."));
|
|
694
|
+
try {
|
|
695
|
+
const { startDaemon } = await import("@alfe.ai/gateway");
|
|
696
|
+
await startDaemon();
|
|
697
|
+
} catch (err) {
|
|
698
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
699
|
+
console.error(chalk.red(`Failed to start daemon: ${message}`));
|
|
700
|
+
process.exit(1);
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
gatewayCommand.command("status").description("Show gateway daemon status").action(async () => {
|
|
704
|
+
try {
|
|
705
|
+
const { queryDaemonHealth, formatHealthReport } = await import("@alfe.ai/gateway");
|
|
706
|
+
const health = await queryDaemonHealth(SOCKET_PATH);
|
|
707
|
+
console.log(chalk.bold("\nAlfe Gateway Status\n"));
|
|
708
|
+
console.log(formatHealthReport(health));
|
|
709
|
+
console.log();
|
|
710
|
+
} catch {
|
|
711
|
+
const pid = getRunningPid();
|
|
712
|
+
console.log(chalk.bold("\nAlfe Gateway Status\n"));
|
|
713
|
+
if (pid) console.log(` Gateway daemon ${chalk.yellow("?")} running (PID ${String(pid)}) but IPC unreachable`);
|
|
714
|
+
else console.log(` Gateway daemon ${chalk.red("✗")} stopped`);
|
|
715
|
+
console.log();
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
gatewayCommand.command("install").description("Install as system service (auto-start on boot)").action(async () => {
|
|
719
|
+
try {
|
|
720
|
+
const { installService } = await import("@alfe.ai/gateway");
|
|
721
|
+
const result = await installService();
|
|
722
|
+
console.log(chalk.green(result));
|
|
723
|
+
} catch (err) {
|
|
724
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
725
|
+
console.error(chalk.red(`Install failed: ${message}`));
|
|
726
|
+
process.exit(1);
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
gatewayCommand.command("uninstall").description("Remove system service").action(async () => {
|
|
730
|
+
try {
|
|
731
|
+
const { uninstallService } = await import("@alfe.ai/gateway");
|
|
732
|
+
const result = await uninstallService();
|
|
733
|
+
console.log(chalk.green(result));
|
|
734
|
+
} catch (err) {
|
|
735
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
736
|
+
console.error(chalk.red(`Uninstall failed: ${message}`));
|
|
737
|
+
process.exit(1);
|
|
738
|
+
}
|
|
739
|
+
});
|
|
740
|
+
gatewayCommand.command("logs").description("Tail daemon logs").action(() => {
|
|
741
|
+
if (!existsSync(LOG_FILE)) {
|
|
742
|
+
console.log(chalk.yellow(`No log file found at ${LOG_FILE}`));
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
console.log(chalk.dim(`Tailing ${LOG_FILE}\n`));
|
|
746
|
+
spawn("tail", ["-f", LOG_FILE], { stdio: "inherit" }).on("error", () => {
|
|
747
|
+
console.error(chalk.red("Failed to tail log file"));
|
|
748
|
+
});
|
|
749
|
+
});
|
|
750
|
+
function getRunningPid() {
|
|
751
|
+
if (!existsSync(PID_PATH)) return null;
|
|
752
|
+
try {
|
|
753
|
+
const pidStr = readFileSync(PID_PATH, "utf-8").trim();
|
|
754
|
+
const pid = parseInt(pidStr, 10);
|
|
755
|
+
if (isNaN(pid)) return null;
|
|
756
|
+
process.kill(pid, 0);
|
|
757
|
+
return pid;
|
|
758
|
+
} catch {
|
|
759
|
+
return null;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
//#endregion
|
|
763
|
+
//#region src/commands/integration.ts
|
|
764
|
+
/**
|
|
765
|
+
* alfe integration — manage Alfe integrations.
|
|
766
|
+
*
|
|
767
|
+
* Subcommands:
|
|
768
|
+
* list - List installed integrations
|
|
769
|
+
* install - Install an integration from the registry
|
|
770
|
+
* remove - Uninstall an integration
|
|
771
|
+
* configure - Interactive configuration wizard
|
|
772
|
+
* status - Health check for integrations
|
|
773
|
+
* search - Search the registry index
|
|
774
|
+
*/
|
|
775
|
+
const integrationCommand = new Command("integration").alias("int").description("Manage Alfe integrations").action(() => {
|
|
776
|
+
integrationCommand.help();
|
|
777
|
+
});
|
|
778
|
+
integrationCommand.command("list").description("List installed integrations").action(async () => {
|
|
779
|
+
try {
|
|
780
|
+
const { StateManager } = await import("@alfe.ai/integrations");
|
|
781
|
+
const integrations = new StateManager().list();
|
|
782
|
+
if (integrations.length === 0) {
|
|
783
|
+
console.log(chalk.dim("No integrations installed."));
|
|
784
|
+
console.log(chalk.dim(" Run: alfe integration search <query>"));
|
|
785
|
+
console.log(chalk.dim(" Run: alfe integration install <name>"));
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
console.log(chalk.bold("\nInstalled Integrations\n"));
|
|
789
|
+
for (const integration of integrations) {
|
|
790
|
+
const statusColor = getStatusColor(integration.status);
|
|
791
|
+
const statusIcon = getStatusIcon(integration.status);
|
|
792
|
+
console.log(` ${statusIcon} ${chalk.bold(integration.id)} ${chalk.dim(`v${integration.version}`)} ${statusColor(integration.status)}`);
|
|
793
|
+
if (integration.error) console.log(` ${chalk.red(`Error: ${integration.error}`)}`);
|
|
794
|
+
}
|
|
795
|
+
console.log();
|
|
796
|
+
} catch (err) {
|
|
797
|
+
handleModuleError(err);
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
integrationCommand.command("install <name> [version]").description("Install an integration from the registry").action(async (name, version) => {
|
|
801
|
+
try {
|
|
802
|
+
const { IntegrationManager } = await import("@alfe.ai/integrations");
|
|
803
|
+
const manager = new IntegrationManager();
|
|
804
|
+
console.log(chalk.blue(`Installing ${name}${version ? `@${version}` : ""}...`));
|
|
805
|
+
console.log();
|
|
806
|
+
const result = await manager.install({
|
|
807
|
+
name,
|
|
808
|
+
version
|
|
809
|
+
});
|
|
810
|
+
if (result.ok) {
|
|
811
|
+
const payload = result.payload;
|
|
812
|
+
console.log(chalk.green(`✅ Integration "${payload.name ?? payload.id ?? "unknown"}" installed successfully`));
|
|
813
|
+
console.log(chalk.dim(` Version: ${payload.version ?? "unknown"}`));
|
|
814
|
+
if (payload.capabilities && payload.capabilities.length > 0) console.log(chalk.dim(` Capabilities: ${payload.capabilities.join(", ")}`));
|
|
815
|
+
console.log();
|
|
816
|
+
console.log(chalk.dim("Next steps:"));
|
|
817
|
+
console.log(chalk.dim(` alfe integration configure ${name}`));
|
|
818
|
+
console.log(chalk.dim(` alfe integration status ${name}`));
|
|
819
|
+
} else {
|
|
820
|
+
console.error(chalk.red(`❌ Installation failed: ${result.error?.message ?? "unknown error"}`));
|
|
821
|
+
process.exit(1);
|
|
822
|
+
}
|
|
823
|
+
} catch (err) {
|
|
824
|
+
handleModuleError(err);
|
|
825
|
+
}
|
|
826
|
+
});
|
|
827
|
+
integrationCommand.command("remove <name>").description("Uninstall an integration").action(async (name) => {
|
|
828
|
+
try {
|
|
829
|
+
const { IntegrationManager } = await import("@alfe.ai/integrations");
|
|
830
|
+
const manager = new IntegrationManager();
|
|
831
|
+
console.log(chalk.blue(`Removing ${name}...`));
|
|
832
|
+
const result = await manager.uninstall({ name });
|
|
833
|
+
if (result.ok) console.log(chalk.green(`✅ Integration "${name}" removed successfully`));
|
|
834
|
+
else {
|
|
835
|
+
console.error(chalk.red(`❌ Removal failed: ${result.error?.message ?? "unknown error"}`));
|
|
836
|
+
process.exit(1);
|
|
837
|
+
}
|
|
838
|
+
} catch (err) {
|
|
839
|
+
handleModuleError(err);
|
|
840
|
+
}
|
|
841
|
+
});
|
|
842
|
+
integrationCommand.command("configure <name>").description("Interactive configuration wizard for an integration").action(async (name) => {
|
|
843
|
+
try {
|
|
844
|
+
const { IntegrationManager } = await import("@alfe.ai/integrations");
|
|
845
|
+
const { Installer } = await import("@alfe.ai/integrations");
|
|
846
|
+
const { parseManifestFile } = await import("@alfe.ai/integration-manifest");
|
|
847
|
+
const inquirer = await import("@inquirer/prompts");
|
|
848
|
+
const nodePath = await import("node:path");
|
|
849
|
+
const nodeFs = await import("node:fs");
|
|
850
|
+
const installPath = new Installer().getInstallPath(name);
|
|
851
|
+
const manifestPath = nodePath.join(installPath, "alfe-integration.yaml");
|
|
852
|
+
if (!nodeFs.existsSync(manifestPath)) {
|
|
853
|
+
console.error(chalk.red(`Integration "${name}" is not installed or manifest is missing.`));
|
|
854
|
+
process.exit(1);
|
|
855
|
+
}
|
|
856
|
+
const manifest = parseManifestFile(manifestPath);
|
|
857
|
+
if (manifest.config_schema.length === 0) {
|
|
858
|
+
console.log(chalk.yellow(`Integration "${name}" has no configuration fields.`));
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
console.log(chalk.bold(`\nConfigure: ${manifest.name}\n`));
|
|
862
|
+
console.log(chalk.dim(manifest.description));
|
|
863
|
+
console.log();
|
|
864
|
+
const config = {};
|
|
865
|
+
for (const field of manifest.config_schema) {
|
|
866
|
+
const requiredMark = field.required ? chalk.red(" *") : "";
|
|
867
|
+
const hint = field.description ? chalk.dim(` (${field.description})`) : "";
|
|
868
|
+
let value;
|
|
869
|
+
switch (field.type) {
|
|
870
|
+
case "secret":
|
|
871
|
+
value = await inquirer.password({ message: `${field.label}${requiredMark}${hint}:` });
|
|
872
|
+
break;
|
|
873
|
+
case "boolean":
|
|
874
|
+
value = await inquirer.confirm({
|
|
875
|
+
message: `${field.label}${requiredMark}${hint}:`,
|
|
876
|
+
default: field.default ?? false
|
|
877
|
+
});
|
|
878
|
+
break;
|
|
879
|
+
case "enum":
|
|
880
|
+
value = await inquirer.select({
|
|
881
|
+
message: `${field.label}${requiredMark}${hint}:`,
|
|
882
|
+
choices: (field.options ?? []).map((o) => ({
|
|
883
|
+
name: o,
|
|
884
|
+
value: o
|
|
885
|
+
}))
|
|
886
|
+
});
|
|
887
|
+
break;
|
|
888
|
+
case "number": {
|
|
889
|
+
const numStr = await inquirer.input({
|
|
890
|
+
message: `${field.label}${requiredMark}${hint}:`,
|
|
891
|
+
default: field.default?.toString()
|
|
892
|
+
});
|
|
893
|
+
value = numStr ? Number(numStr) : void 0;
|
|
894
|
+
break;
|
|
895
|
+
}
|
|
896
|
+
default:
|
|
897
|
+
value = await inquirer.input({
|
|
898
|
+
message: `${field.label}${requiredMark}${hint}:`,
|
|
899
|
+
default: field.default
|
|
900
|
+
});
|
|
901
|
+
break;
|
|
902
|
+
}
|
|
903
|
+
if (value !== void 0 && value !== "") config[field.key] = value;
|
|
904
|
+
}
|
|
905
|
+
const result = new IntegrationManager().configure({
|
|
906
|
+
name,
|
|
907
|
+
config
|
|
908
|
+
});
|
|
909
|
+
if (result.ok) {
|
|
910
|
+
console.log(chalk.green(`\n✅ Integration "${name}" configured successfully`));
|
|
911
|
+
const payload = result.payload;
|
|
912
|
+
if (payload.secretCount && payload.secretCount > 0) console.log(chalk.dim(` ${String(payload.secretCount)} secret(s) stored in memory only`));
|
|
913
|
+
} else {
|
|
914
|
+
console.error(chalk.red(`\n❌ Configuration failed: ${result.error?.message ?? "unknown error"}`));
|
|
915
|
+
process.exit(1);
|
|
916
|
+
}
|
|
917
|
+
} catch (err) {
|
|
918
|
+
handleModuleError(err);
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
integrationCommand.command("status [name]").description("Health check for one or all integrations").action(async (name) => {
|
|
922
|
+
try {
|
|
923
|
+
const { IntegrationManager } = await import("@alfe.ai/integrations");
|
|
924
|
+
const result = await new IntegrationManager().health({ name });
|
|
925
|
+
if (!result.ok) {
|
|
926
|
+
console.error(chalk.red(`Health check failed: ${result.error?.message ?? "unknown error"}`));
|
|
927
|
+
process.exit(1);
|
|
928
|
+
}
|
|
929
|
+
const payload = result.payload;
|
|
930
|
+
if (name) {
|
|
931
|
+
const statusIcon = payload.healthy ? chalk.green("✓") : chalk.red("✗");
|
|
932
|
+
console.log(`\n ${statusIcon} ${chalk.bold(payload.name ?? "unknown")} ${chalk.dim(`v${payload.version ?? "unknown"}`)} ${payload.message ?? ""}`);
|
|
933
|
+
} else {
|
|
934
|
+
const report = payload;
|
|
935
|
+
const overallIcon = report.overall ? chalk.green("✓") : chalk.red("✗");
|
|
936
|
+
console.log(chalk.bold(`\nIntegration Health Report ${overallIcon}\n`));
|
|
937
|
+
for (const check of report.results ?? []) {
|
|
938
|
+
const icon = check.healthy ? chalk.green("✓") : chalk.red("✗");
|
|
939
|
+
const statusColor = getStatusColor(check.status);
|
|
940
|
+
console.log(` ${icon} ${chalk.bold(check.name)} ${chalk.dim(`v${check.version ?? "?"}`)} ${statusColor(check.status)} ${chalk.dim(check.message ?? "")}`);
|
|
941
|
+
}
|
|
942
|
+
if ((report.results ?? []).length === 0) console.log(chalk.dim(" No integrations installed."));
|
|
943
|
+
}
|
|
944
|
+
console.log();
|
|
945
|
+
} catch (err) {
|
|
946
|
+
handleModuleError(err);
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
integrationCommand.command("search [query]").description("Search the integration registry").action(async (query) => {
|
|
950
|
+
try {
|
|
951
|
+
const { Registry } = await import("@alfe.ai/integrations");
|
|
952
|
+
const registry = new Registry();
|
|
953
|
+
const results = query ? await registry.search(query) : await registry.list();
|
|
954
|
+
if (results.length === 0) {
|
|
955
|
+
console.log(chalk.dim(query ? `No integrations matching "${query}".` : "Registry is empty."));
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
console.log(chalk.bold(`\nAvailable Integrations${query ? ` matching "${query}"` : ""}\n`));
|
|
959
|
+
for (const entry of results) {
|
|
960
|
+
console.log(` ${chalk.bold(entry.name)} ${chalk.dim(`v${entry.latest}`)} ${entry.description}`);
|
|
961
|
+
console.log(chalk.dim(` Versions: ${entry.versions.join(", ")} | ${entry.repo}`));
|
|
962
|
+
}
|
|
963
|
+
console.log();
|
|
964
|
+
console.log(chalk.dim(" Install with: alfe integration install <name>"));
|
|
965
|
+
console.log();
|
|
966
|
+
} catch (err) {
|
|
967
|
+
handleModuleError(err);
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
function getStatusColor(status) {
|
|
971
|
+
switch (status) {
|
|
972
|
+
case "active": return chalk.green;
|
|
973
|
+
case "configured": return chalk.blue;
|
|
974
|
+
case "installed": return chalk.cyan;
|
|
975
|
+
case "installing": return chalk.yellow;
|
|
976
|
+
case "error": return chalk.red;
|
|
977
|
+
default: return chalk.dim;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
function getStatusIcon(status) {
|
|
981
|
+
switch (status) {
|
|
982
|
+
case "active": return chalk.green("●");
|
|
983
|
+
case "configured": return chalk.blue("●");
|
|
984
|
+
case "installed": return chalk.cyan("●");
|
|
985
|
+
case "installing": return chalk.yellow("◌");
|
|
986
|
+
case "error": return chalk.red("●");
|
|
987
|
+
default: return chalk.dim("○");
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
function handleModuleError(err) {
|
|
991
|
+
if (err.code === "ERR_MODULE_NOT_FOUND") console.error(chalk.red("Integration packages not found. Make sure @alfe.ai/integrations and related packages are installed."));
|
|
992
|
+
else {
|
|
993
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
994
|
+
console.error(chalk.red(`Error: ${message}`));
|
|
995
|
+
}
|
|
996
|
+
process.exit(1);
|
|
997
|
+
}
|
|
998
|
+
//#endregion
|
|
999
|
+
//#region src/index.ts
|
|
1000
|
+
/**
|
|
1001
|
+
* Alfe CLI — set up and manage Alfe AI agents.
|
|
1002
|
+
*
|
|
1003
|
+
* Commands:
|
|
1004
|
+
* login - Authenticate with the Alfe API
|
|
1005
|
+
* setup - Interactive setup wizard
|
|
1006
|
+
* doctor - Diagnose environment issues
|
|
1007
|
+
* gateway - Manage the local gateway daemon
|
|
1008
|
+
* integration - Manage Alfe integrations
|
|
1009
|
+
*/
|
|
1010
|
+
const program = new Command();
|
|
1011
|
+
program.name("alfe").description("CLI for setting up and managing Alfe AI agents").version("0.1.0");
|
|
1012
|
+
program.addCommand(loginCommand);
|
|
1013
|
+
program.addCommand(setupCommand);
|
|
1014
|
+
program.addCommand(doctorCommand);
|
|
1015
|
+
program.addCommand(gatewayCommand);
|
|
1016
|
+
program.addCommand(integrationCommand);
|
|
1017
|
+
program.parse();
|
|
1018
|
+
//#endregion
|
|
1019
|
+
export {};
|
|
1020
|
+
|
|
1021
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["createAuthService","SOCKET_PATH"],"sources":["../../../packages-internal/ids/dist/prefixes.js","../../../node_modules/.pnpm/ulid@2.4.0/node_modules/ulid/dist/index.umd.js","../../../packages-internal/ids/dist/create.js","../../../packages-internal/api-client/dist/client.js","../../../packages-internal/api-client/dist/services/auth.js","../src/commands/login.ts","../src/lib/runtime.ts","../src/commands/setup.ts","../src/commands/doctor.ts","../src/commands/gateway.ts","../src/commands/integration.ts","../src/index.ts"],"sourcesContent":["export const ID_PREFIXES = {\n // Persisted entities\n agent: 'agt',\n organization: 'org',\n person: 'per',\n auditEvent: 'evt',\n token: 'tok',\n transaction: 'txn',\n subscription: 'sub',\n // Ephemeral IDs\n request: 'req',\n connection: 'conn',\n correlation: 'cor',\n command: 'cmd',\n message: 'msg',\n ipcRequest: 'ipc',\n pluginConnection: 'plg',\n};\n//# sourceMappingURL=prefixes.js.map","(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n typeof define === 'function' && define.amd ? define(['exports'], factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ULID = {}));\n})(this, (function (exports) { 'use strict';\n\n function createError(message) {\n const err = new Error(message);\n err.source = \"ulid\";\n return err;\n }\n // These values should NEVER change. If\n // they do, we're no longer making ulids!\n const ENCODING = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\"; // Crockford's Base32\n const ENCODING_LEN = ENCODING.length;\n const TIME_MAX = Math.pow(2, 48) - 1;\n const TIME_LEN = 10;\n const RANDOM_LEN = 16;\n function replaceCharAt(str, index, char) {\n if (index > str.length - 1) {\n return str;\n }\n return str.substr(0, index) + char + str.substr(index + 1);\n }\n function incrementBase32(str) {\n let done = undefined;\n let index = str.length;\n let char;\n let charIndex;\n const maxCharIndex = ENCODING_LEN - 1;\n while (!done && index-- >= 0) {\n char = str[index];\n charIndex = ENCODING.indexOf(char);\n if (charIndex === -1) {\n throw createError(\"incorrectly encoded string\");\n }\n if (charIndex === maxCharIndex) {\n str = replaceCharAt(str, index, ENCODING[0]);\n continue;\n }\n done = replaceCharAt(str, index, ENCODING[charIndex + 1]);\n }\n if (typeof done === \"string\") {\n return done;\n }\n throw createError(\"cannot increment this string\");\n }\n function randomChar(prng) {\n let rand = Math.floor(prng() * ENCODING_LEN);\n if (rand === ENCODING_LEN) {\n rand = ENCODING_LEN - 1;\n }\n return ENCODING.charAt(rand);\n }\n function encodeTime(now, len) {\n if (isNaN(now)) {\n throw new Error(now + \" must be a number\");\n }\n if (now > TIME_MAX) {\n throw createError(\"cannot encode time greater than \" + TIME_MAX);\n }\n if (now < 0) {\n throw createError(\"time must be positive\");\n }\n if (Number.isInteger(Number(now)) === false) {\n throw createError(\"time must be an integer\");\n }\n let mod;\n let str = \"\";\n for (; len > 0; len--) {\n mod = now % ENCODING_LEN;\n str = ENCODING.charAt(mod) + str;\n now = (now - mod) / ENCODING_LEN;\n }\n return str;\n }\n function encodeRandom(len, prng) {\n let str = \"\";\n for (; len > 0; len--) {\n str = randomChar(prng) + str;\n }\n return str;\n }\n function decodeTime(id) {\n if (id.length !== TIME_LEN + RANDOM_LEN) {\n throw createError(\"malformed ulid\");\n }\n var time = id\n .substr(0, TIME_LEN)\n .split(\"\")\n .reverse()\n .reduce((carry, char, index) => {\n const encodingIndex = ENCODING.indexOf(char);\n if (encodingIndex === -1) {\n throw createError(\"invalid character found: \" + char);\n }\n return (carry += encodingIndex * Math.pow(ENCODING_LEN, index));\n }, 0);\n if (time > TIME_MAX) {\n throw createError(\"malformed ulid, timestamp too large\");\n }\n return time;\n }\n function detectPrng(allowInsecure = false, root) {\n if (!root) {\n root = typeof window !== \"undefined\" ? window : null;\n }\n const browserCrypto = root && (root.crypto || root.msCrypto);\n if (browserCrypto) {\n return () => {\n const buffer = new Uint8Array(1);\n browserCrypto.getRandomValues(buffer);\n return buffer[0] / 0xff;\n };\n }\n else {\n try {\n const nodeCrypto = require(\"crypto\");\n return () => nodeCrypto.randomBytes(1).readUInt8() / 0xff;\n }\n catch (e) { }\n }\n if (allowInsecure) {\n try {\n console.error(\"secure crypto unusable, falling back to insecure Math.random()!\");\n }\n catch (e) { }\n return () => Math.random();\n }\n throw createError(\"secure crypto unusable, insecure Math.random not allowed\");\n }\n function factory(currPrng) {\n if (!currPrng) {\n currPrng = detectPrng();\n }\n return function ulid(seedTime) {\n if (isNaN(seedTime)) {\n seedTime = Date.now();\n }\n return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN, currPrng);\n };\n }\n function monotonicFactory(currPrng) {\n if (!currPrng) {\n currPrng = detectPrng();\n }\n let lastTime = 0;\n let lastRandom;\n return function ulid(seedTime) {\n if (isNaN(seedTime)) {\n seedTime = Date.now();\n }\n if (seedTime <= lastTime) {\n const incrementedRandom = (lastRandom = incrementBase32(lastRandom));\n return encodeTime(lastTime, TIME_LEN) + incrementedRandom;\n }\n lastTime = seedTime;\n const newRandom = (lastRandom = encodeRandom(RANDOM_LEN, currPrng));\n return encodeTime(seedTime, TIME_LEN) + newRandom;\n };\n }\n const ulid = factory();\n\n exports.decodeTime = decodeTime;\n exports.detectPrng = detectPrng;\n exports.encodeRandom = encodeRandom;\n exports.encodeTime = encodeTime;\n exports.factory = factory;\n exports.incrementBase32 = incrementBase32;\n exports.monotonicFactory = monotonicFactory;\n exports.randomChar = randomChar;\n exports.replaceCharAt = replaceCharAt;\n exports.ulid = ulid;\n\n}));\n","import { ulid } from 'ulid';\nimport { ID_PREFIXES } from './prefixes.js';\nexport function createId(prefix) {\n return `${prefix}_${ulid()}`;\n}\n// Typed factories (persisted entities)\nexport function agentId() { return createId(ID_PREFIXES.agent); }\nexport function orgId() { return createId(ID_PREFIXES.organization); }\nexport function personId() { return createId(ID_PREFIXES.person); }\nexport function auditEventId() { return createId(ID_PREFIXES.auditEvent); }\nexport function tokenId() { return createId(ID_PREFIXES.token); }\nexport function transactionId() { return createId(ID_PREFIXES.transaction); }\nexport function subscriptionId() { return createId(ID_PREFIXES.subscription); }\n// Typed factories (ephemeral)\nexport function requestId() { return createId(ID_PREFIXES.request); }\nexport function connectionId() { return createId(ID_PREFIXES.connection); }\nexport function correlationId() { return createId(ID_PREFIXES.correlation); }\nexport function commandId() { return createId(ID_PREFIXES.command); }\nexport function messageId() { return createId(ID_PREFIXES.message); }\nexport function ipcRequestId() { return createId(ID_PREFIXES.ipcRequest); }\nexport function pluginConnectionId() { return createId(ID_PREFIXES.pluginConnection); }\n//# sourceMappingURL=create.js.map","/**\n * @alfe/api-client — Typed HTTP client for Alfe services.\n *\n * Platform-agnostic: works in React Native and browser environments.\n * Uses standard fetch() API — no Node.js dependencies.\n */\nimport { correlationId } from \"@alfe/ids\";\nexport class AlfeApiClient {\n apiBaseUrl;\n getToken;\n onAuthFailure;\n constructor(options) {\n this.apiBaseUrl = options.apiBaseUrl;\n this.getToken = options.getToken;\n this.onAuthFailure = options.onAuthFailure;\n }\n /** Shared fetch logic — handles auth, 401, and network errors. */\n async _fetch(path, options) {\n try {\n const token = await this.getToken();\n if (!token) {\n this.onAuthFailure?.();\n return { ok: false, result: { ok: false, error: \"No auth token available\", status: 401 } };\n }\n const url = `${this.apiBaseUrl}${path}`;\n const headers = new Headers(options?.headers);\n headers.set(\"Authorization\", `Bearer ${token}`);\n headers.set(\"Content-Type\", \"application/json\");\n headers.set(\"x-correlation-id\", correlationId());\n const res = await fetch(url, { ...options, headers });\n if (res.status === 401) {\n this.onAuthFailure?.();\n return { ok: false, result: { ok: false, error: \"Session expired\", status: 401 } };\n }\n const body = await res.json();\n if (!res.ok) {\n const errBody = body;\n return {\n ok: false,\n result: {\n ok: false,\n error: errBody.message || `API error: ${String(res.status)}`,\n status: res.status,\n },\n };\n }\n return { ok: true, res, body };\n }\n catch (err) {\n const message = err instanceof Error ? err.message : \"Network error\";\n return { ok: false, result: { ok: false, error: message } };\n }\n }\n /**\n * Make an authenticated request to an Alfe API endpoint.\n * Unwraps the @auriclabs/api-core `{ data, timestamp, requestId }` envelope.\n */\n async request(path, options) {\n const result = await this._fetch(path, options);\n if (!result.ok)\n return result.result;\n return { ok: true, data: result.body.data };\n }\n /**\n * Make an authenticated request that returns the body directly (no envelope unwrap).\n * Use for APIs that don't use the @auriclabs/api-core response format (e.g. gateway).\n */\n async rawRequest(path, options) {\n const result = await this._fetch(path, options);\n if (!result.ok)\n return result.result;\n return { ok: true, data: result.body };\n }\n getApiBaseUrl() {\n return this.apiBaseUrl;\n }\n}\n//# sourceMappingURL=client.js.map","// ── Service ──────────────────────────────────────────────────────────\nexport class AuthService {\n client;\n constructor(client) {\n this.client = client;\n }\n prefix = \"/auth\";\n validate() {\n return this.client.request(`${this.prefix}/validate`);\n }\n listTokens() {\n return this.client.request(`${this.prefix}/tokens`);\n }\n createToken(data) {\n return this.client.request(`${this.prefix}/tokens`, {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n }\n deleteToken(tokenId) {\n return this.client.request(`${this.prefix}/tokens/${tokenId}`, {\n method: \"DELETE\",\n });\n }\n}\n//# sourceMappingURL=auth.js.map","/**\n * alfe login — authenticate with the Alfe API.\n */\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { input } from \"@inquirer/prompts\";\nimport { configExists, readConfig, writeConfig, getEndpointFromToken } from \"@alfe.ai/config\";\nimport { AlfeApiClient, AuthService } from \"@alfe/api-client\";\n\nfunction createAuthService(apiKey: string, gateway?: string): AuthService {\n const apiBaseUrl = (gateway ?? getEndpointFromToken(apiKey)).replace(/\\/+$/, \"\");\n const client = new AlfeApiClient({\n apiBaseUrl,\n getToken: () => Promise.resolve(apiKey),\n });\n return new AuthService(client);\n}\n\nexport const loginCommand = new Command(\"login\")\n .description(\"Authenticate with the Alfe API\")\n .action(async () => {\n // Check if already logged in with a valid key\n if (configExists()) {\n const spinner = ora(\"Checking existing credentials…\").start();\n try {\n const existing = await readConfig();\n const auth = createAuthService(existing.api_key, existing.gateway);\n const result = await auth.validate();\n\n if (result.ok && result.data.valid) {\n spinner.succeed(\n chalk.green(\"Already logged in. Your API key is valid.\"),\n );\n return;\n }\n\n spinner.warn(\"Existing API key is invalid. Let's set up a new one.\");\n } catch {\n spinner.warn(\"Couldn't read existing config. Let's set up a new one.\");\n }\n }\n\n // Prompt for API key\n const apiKey = await input({\n message: \"Paste your Alfe API key:\",\n transformer: (value: string) => \"*\".repeat(value.length),\n validate: (value: string) =>\n value.trim().length > 0 ? true : \"API key cannot be empty\",\n });\n\n // Validate the key\n const spinner = ora(\"Validating API key…\").start();\n const auth = createAuthService(apiKey.trim());\n const result = await auth.validate();\n\n if (!result.ok || !result.data.valid) {\n spinner.fail(\n chalk.red(\"Invalid API key. Please check your key and try again.\"),\n );\n process.exit(1);\n }\n\n // Write config\n await writeConfig({ api_key: apiKey.trim() });\n spinner.succeed(\n chalk.green(\"Logged in successfully! Config saved to ~/.alfe/config.toml\"),\n );\n });\n","/**\n * Runtime detection, installation, and workspace setup utilities.\n *\n * Handles detecting whether a runtime (e.g. openclaw) is installed,\n * installing it if needed, initializing the workspace directory,\n * and writing cloud-provided persona files.\n */\n\nimport { execFile } from \"node:child_process\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { promisify } from \"node:util\";\nimport type { AgentWorkspaceConfig } from \"@alfe.ai/gateway\";\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Get the default workspace path for a runtime.\n */\nexport function getDefaultWorkspace(runtime: string): string {\n if (runtime === \"openclaw\") return join(homedir(), \".openclaw\");\n return join(homedir(), `.${runtime}`);\n}\n\n/**\n * Detect whether a runtime is installed and get its version.\n */\nexport async function detectRuntime(\n name: string,\n): Promise<{ installed: boolean; version?: string }> {\n if (name === \"openclaw\") {\n try {\n const { stdout } = await execFileAsync(\"openclaw\", [\"--version\"]);\n const version = stdout.trim();\n return { installed: true, version };\n } catch {\n return { installed: false };\n }\n }\n\n return { installed: false };\n}\n\n/**\n * Install a runtime globally via npm.\n */\nexport async function installRuntime(name: string): Promise<void> {\n if (name === \"openclaw\") {\n await execFileAsync(\"npm\", [\"install\", \"-g\", \"openclaw\"]);\n return;\n }\n\n throw new Error(`Unknown runtime: ${name}`);\n}\n\n/**\n * Initialize the runtime workspace directory.\n * For openclaw, runs `openclaw onboard` in non-interactive mode.\n */\nexport async function initWorkspace(\n name: string,\n workspace: string,\n): Promise<void> {\n if (name === \"openclaw\") {\n await mkdir(workspace, { recursive: true });\n\n try {\n await execFileAsync(\"openclaw\", [\n \"onboard\",\n \"--non-interactive\",\n \"--workspace\",\n workspace,\n \"--skip-health\",\n ]);\n } catch {\n // If openclaw onboard isn't available or fails, create minimal workspace structure\n await mkdir(join(workspace, \"config\"), { recursive: true });\n }\n return;\n }\n\n throw new Error(`Unknown runtime: ${name}`);\n}\n\n/**\n * Write cloud-provided persona files into the workspace.\n * Files come from the personality registry (S3) as a filename→content map.\n * Only writes files that have non-empty content.\n */\nexport async function writeWorkspaceFiles(\n workspace: string,\n config: AgentWorkspaceConfig,\n): Promise<void> {\n for (const [filename, content] of Object.entries(config.files)) {\n if (content) {\n await writeFile(join(workspace, filename), content, \"utf-8\");\n }\n }\n}\n","/**\n * alfe setup — interactive first-time setup.\n *\n * Walks the user through:\n * 1. Authenticating with the Alfe API (login)\n * 2. Detecting and installing the agent runtime (e.g. OpenClaw)\n * 3. Initializing the runtime workspace with agent persona files\n * 4. Installing the gateway daemon as a system service\n *\n * In managed mode (ALFE_MANAGED=true), skips interactive prompts\n * and directly starts the gateway daemon.\n */\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { confirm, input } from \"@inquirer/prompts\";\nimport {\n configExists,\n readConfig,\n writeConfig,\n writeRuntimeConfig,\n getEndpointFromToken,\n} from \"@alfe.ai/config\";\nimport { AlfeApiClient, AuthService } from \"@alfe/api-client\";\nimport {\n installService,\n startDaemon,\n resolveAgentIdentity,\n fetchAgentConfig,\n} from \"@alfe.ai/gateway\";\nimport {\n detectRuntime,\n installRuntime,\n initWorkspace,\n writeWorkspaceFiles,\n getDefaultWorkspace,\n} from \"../lib/runtime.js\";\n\nfunction createAuthService(apiKey: string, gateway?: string): AuthService {\n const apiBaseUrl = (gateway ?? getEndpointFromToken(apiKey)).replace(\n /\\/+$/,\n \"\",\n );\n const client = new AlfeApiClient({\n apiBaseUrl,\n getToken: () => Promise.resolve(apiKey),\n });\n return new AuthService(client);\n}\n\nasync function runManagedSetup(): Promise<void> {\n console.log(chalk.bold(\"\\nAlfe Managed Agent\\n\"));\n\n const apiKey = process.env.ALFE_API_KEY;\n if (!apiKey) {\n console.error(chalk.red(\"ALFE_API_KEY environment variable is required\"));\n process.exit(1);\n }\n\n const apiEndpoint = process.env.ALFE_API_ENDPOINT;\n if (!apiEndpoint) {\n console.error(\n chalk.red(\"ALFE_API_ENDPOINT environment variable is required\"),\n );\n process.exit(1);\n }\n\n // Resolve identity to discover runtime\n const identity = await resolveAgentIdentity(apiKey, apiEndpoint);\n\n // Initialize workspace (runtime is pre-installed in Docker image)\n const workspace = getDefaultWorkspace(identity.runtime);\n const wsSpinner = ora(\"Initializing workspace…\").start();\n try {\n await initWorkspace(identity.runtime, workspace);\n wsSpinner.succeed(chalk.green(\"Workspace initialized.\"));\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n wsSpinner.fail(chalk.red(`Workspace init failed: ${message}`));\n process.exit(1);\n }\n\n // Fetch and apply agent persona from cloud\n const configSpinner = ora(\"Fetching agent config…\").start();\n const agentConfig = await fetchAgentConfig(apiKey, apiEndpoint);\n if (agentConfig) {\n await writeWorkspaceFiles(workspace, agentConfig);\n configSpinner.succeed(chalk.green(\"Agent persona applied.\"));\n } else {\n configSpinner.info(\"No workspace config found — using defaults.\");\n }\n\n console.log(chalk.blue(\"Starting gateway daemon...\\n\"));\n await startDaemon();\n}\n\nexport const setupCommand = new Command(\"setup\")\n .description(\"Set up Alfe — authenticate and install the gateway daemon\")\n .action(async () => {\n if (process.env.ALFE_MANAGED === \"true\") {\n return runManagedSetup();\n }\n\n console.log(chalk.bold(\"\\nAlfe Setup\\n\"));\n\n // ── Step 1: Login ────────────────────────────────────────\n console.log(chalk.blue(\"Step 1:\"), \"Authenticate with Alfe Cloud\\n\");\n\n let needsLogin = true;\n let apiKey = \"\";\n let gateway: string | undefined;\n\n if (configExists()) {\n const spinner = ora(\"Checking existing credentials…\").start();\n try {\n const existing = await readConfig();\n const auth = createAuthService(existing.api_key, existing.gateway);\n const result = await auth.validate();\n\n if (result.ok && result.data.valid) {\n spinner.succeed(chalk.green(\"Already authenticated.\"));\n needsLogin = false;\n apiKey = existing.api_key;\n gateway = existing.gateway;\n } else {\n spinner.warn(\"Existing API key is invalid.\");\n }\n } catch {\n spinner.warn(\"Couldn't verify existing config.\");\n }\n }\n\n if (needsLogin) {\n apiKey = await input({\n message: \"Paste your Alfe API key:\",\n transformer: (value: string) => \"*\".repeat(value.length),\n validate: (value: string) =>\n value.trim().length > 0 ? true : \"API key cannot be empty\",\n });\n apiKey = apiKey.trim();\n\n const spinner = ora(\"Validating API key…\").start();\n const auth = createAuthService(apiKey);\n const result = await auth.validate();\n\n if (!result.ok || !result.data.valid) {\n spinner.fail(\n chalk.red(\"Invalid API key. Run alfe setup again with a valid key.\"),\n );\n process.exit(1);\n }\n\n await writeConfig({ api_key: apiKey });\n spinner.succeed(chalk.green(\"Authenticated.\"));\n }\n\n // ── Step 2: Runtime ──────────────────────────────────────\n console.log(chalk.blue(\"\\nStep 2:\"), \"Configure agent runtime\\n\");\n\n const apiEndpoint = gateway ?? getEndpointFromToken(apiKey);\n const identitySpinner = ora(\"Resolving agent identity…\").start();\n let runtime: string;\n try {\n const identity = await resolveAgentIdentity(apiKey, apiEndpoint);\n runtime = identity.runtime;\n identitySpinner.succeed(\n chalk.green(`Agent runtime: ${runtime}`),\n );\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n identitySpinner.fail(chalk.red(`Identity resolution failed: ${message}`));\n process.exit(1);\n }\n\n // Detect if runtime is installed\n const detection = await detectRuntime(runtime);\n\n if (!detection.installed) {\n const shouldInstall = await confirm({\n message: `${runtime} is not installed. Install it now?`,\n default: true,\n });\n\n if (shouldInstall) {\n const installSpinner = ora(`Installing ${runtime}…`).start();\n try {\n await installRuntime(runtime);\n installSpinner.succeed(chalk.green(`${runtime} installed.`));\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n installSpinner.fail(\n chalk.red(`Failed to install ${runtime}: ${message}`),\n );\n process.exit(1);\n }\n } else {\n console.log(\n chalk.yellow(\n `Skipping ${runtime} install. You'll need to install it manually.`,\n ),\n );\n }\n } else {\n console.log(\n chalk.green(` ${runtime} already installed (${detection.version ?? \"unknown version\"}).`),\n );\n }\n\n // Initialize workspace\n const workspace = getDefaultWorkspace(runtime);\n const wsSpinner = ora(\"Initializing workspace…\").start();\n try {\n await initWorkspace(runtime, workspace);\n wsSpinner.succeed(chalk.green(\"Workspace initialized.\"));\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n wsSpinner.fail(chalk.red(`Workspace init failed: ${message}`));\n process.exit(1);\n }\n\n // Fetch and apply agent persona from cloud\n const configSpinner = ora(\"Fetching agent config…\").start();\n const agentConfig = await fetchAgentConfig(apiKey, apiEndpoint);\n if (agentConfig) {\n await writeWorkspaceFiles(workspace, agentConfig);\n configSpinner.succeed(chalk.green(\"Agent persona applied.\"));\n } else {\n configSpinner.info(\"No workspace config found — using defaults.\");\n }\n\n // Write runtime config to config.toml\n await writeRuntimeConfig(runtime, { workspace });\n\n // ── Step 3: Install gateway ──────────────────────────────\n console.log(chalk.blue(\"\\nStep 3:\"), \"Install the gateway daemon\\n\");\n\n const gwSpinner = ora(\"Installing gateway service…\").start();\n try {\n const result = await installService();\n gwSpinner.succeed(chalk.green(result));\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n gwSpinner.fail(chalk.red(`Gateway install failed: ${message}`));\n process.exit(1);\n }\n\n // ── Done ─────────────────────────────────────────────────\n console.log(chalk.green(\"\\n✓ Alfe is ready to use.\\n\"));\n });\n","/**\n * alfe doctor — diagnose environment and connectivity issues.\n *\n * Checks:\n * 1. Config exists and API key is valid\n * 2. Gateway daemon status + cloud connection\n * 3. Registered plugins and their health\n */\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { configExists, readConfig, getEndpointFromToken } from \"@alfe.ai/config\";\n\nconst SOCKET_PATH = join(homedir(), \".alfe\", \"gateway.sock\");\n\nexport const doctorCommand = new Command(\"doctor\")\n .description(\"Diagnose environment and configuration issues\")\n .action(async () => {\n console.log(chalk.bold(\"\\n🩺 Alfe Doctor\\n\"));\n\n // 1. Check config\n console.log(chalk.dim(\"Checking configuration...\"));\n if (!configExists()) {\n console.log(\n ` Config ${chalk.red(\"✗\")} ~/.alfe/config.toml not found`,\n );\n console.log(\n chalk.yellow(\"\\n Run `alfe login` to set up your API key.\\n\"),\n );\n return;\n }\n\n let apiKey: string;\n let apiEndpoint: string;\n try {\n const config = await readConfig();\n apiKey = config.api_key;\n apiEndpoint = config.gateway ?? getEndpointFromToken(config.api_key);\n console.log(\n ` Config ${chalk.green(\"✓\")} loaded (endpoint: ${apiEndpoint})`,\n );\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.log(\n ` Config ${chalk.red(\"✗\")} ${message}`,\n );\n return;\n }\n\n // 2. Validate API key\n console.log(chalk.dim(\"Validating API key...\"));\n try {\n const response = await fetch(`${apiEndpoint}/auth/validate`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token: apiKey }),\n });\n\n if (response.ok) {\n const result = (await response.json()) as {\n success: boolean;\n data?: { valid: boolean; tenantId?: string };\n };\n if (result.success && result.data?.valid) {\n console.log(\n ` API key ${chalk.green(\"✓\")} valid (org: ${result.data.tenantId ?? \"unknown\"})`,\n );\n } else {\n console.log(\n ` API key ${chalk.red(\"✗\")} invalid — run \\`alfe login\\``,\n );\n }\n } else {\n console.log(\n ` API key ${chalk.red(\"✗\")} validation failed (HTTP ${String(response.status)})`,\n );\n }\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.log(\n ` API key ${chalk.yellow(\"?\")} cannot reach API (${message})`,\n );\n }\n\n // 3. Gateway daemon\n console.log(chalk.dim(\"Checking gateway daemon...\"));\n try {\n const { queryDaemonHealth, formatHealthReport } = await import(\n \"@alfe.ai/gateway\"\n );\n const health = await queryDaemonHealth(SOCKET_PATH);\n console.log(formatHealthReport(health));\n } catch (err: unknown) {\n const errObj = err as { code?: string; message?: string };\n if (errObj.code === \"ERR_MODULE_NOT_FOUND\") {\n console.log(\n ` Gateway daemon ${chalk.yellow(\"–\")} @alfe.ai/gateway not installed`,\n );\n } else {\n const message = err instanceof Error ? err.message : String(err);\n console.log(\n ` Gateway daemon ${chalk.red(\"✗\")} unreachable (${message})`,\n );\n }\n }\n\n console.log();\n });\n","/**\n * alfe gateway — manage the local gateway daemon.\n *\n * Subcommands:\n * start - Start the daemon\n * stop - Stop the daemon\n * restart - Restart the daemon\n * status - Show daemon status\n * install - Install as system service\n * uninstall - Remove system service\n * logs - Tail daemon logs\n */\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { spawn } from \"node:child_process\";\n\nconst SOCKET_PATH = join(homedir(), \".alfe\", \"gateway.sock\");\nconst PID_PATH = join(homedir(), \".alfe\", \"gateway.pid\");\nconst LOG_FILE = join(homedir(), \".alfe\", \"logs\", \"gateway.log\");\n\nexport const gatewayCommand = new Command(\"gateway\")\n .description(\"Manage the Alfe gateway daemon\")\n .action(() => {\n // Show help if no subcommand\n gatewayCommand.help();\n });\n\ngatewayCommand\n .command(\"start\")\n .description(\"Start the gateway daemon\")\n .action(async () => {\n const pid = getRunningPid();\n if (pid) {\n console.log(chalk.yellow(`Daemon already running (PID ${String(pid)})`));\n return;\n }\n\n console.log(chalk.blue(\"Starting Alfe Gateway Daemon...\"));\n\n // Import and run the daemon\n try {\n const { startDaemon } = await import(\"@alfe.ai/gateway\");\n await startDaemon();\n } catch (err: unknown) {\n const errObj = err as { code?: string };\n if (errObj.code === \"ERR_MODULE_NOT_FOUND\") {\n console.error(\n chalk.red(\n \"Gateway package not found. Install with: pnpm add @alfe.ai/gateway\",\n ),\n );\n } else {\n const message = err instanceof Error ? err.message : String(err);\n console.error(chalk.red(`Failed to start daemon: ${message}`));\n }\n process.exit(1);\n }\n });\n\ngatewayCommand\n .command(\"stop\")\n .description(\"Stop the gateway daemon\")\n .action(async () => {\n const pid = getRunningPid();\n if (!pid) {\n console.log(chalk.yellow(\"Daemon is not running\"));\n return;\n }\n\n try {\n process.kill(pid, \"SIGTERM\");\n console.log(chalk.green(`Sent SIGTERM to daemon (PID ${String(pid)})`));\n\n // Wait for exit\n for (let i = 0; i < 50; i++) {\n await new Promise((r) => setTimeout(r, 100));\n try {\n process.kill(pid, 0);\n } catch {\n console.log(chalk.green(\"Daemon stopped\"));\n return;\n }\n }\n\n console.log(chalk.yellow(\"Daemon did not stop — sending SIGKILL\"));\n process.kill(pid, \"SIGKILL\");\n } catch {\n console.log(chalk.yellow(\"Daemon is not running (stale PID file)\"));\n }\n });\n\ngatewayCommand\n .command(\"restart\")\n .description(\"Restart the gateway daemon\")\n .action(async () => {\n const pid = getRunningPid();\n if (pid) {\n try {\n process.kill(pid, \"SIGTERM\");\n console.log(chalk.blue(\"Stopping daemon...\"));\n await new Promise((r) => setTimeout(r, 1000));\n } catch {\n // Already dead\n }\n }\n\n console.log(chalk.blue(\"Starting Alfe Gateway Daemon...\"));\n try {\n const { startDaemon } = await import(\"@alfe.ai/gateway\");\n await startDaemon();\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(chalk.red(`Failed to start daemon: ${message}`));\n process.exit(1);\n }\n });\n\ngatewayCommand\n .command(\"status\")\n .description(\"Show gateway daemon status\")\n .action(async () => {\n try {\n const { queryDaemonHealth, formatHealthReport } = await import(\n \"@alfe.ai/gateway\"\n );\n const health = await queryDaemonHealth(SOCKET_PATH);\n console.log(chalk.bold(\"\\nAlfe Gateway Status\\n\"));\n console.log(formatHealthReport(health));\n console.log();\n } catch {\n // Fallback: check PID file\n const pid = getRunningPid();\n console.log(chalk.bold(\"\\nAlfe Gateway Status\\n\"));\n if (pid) {\n console.log(\n ` Gateway daemon ${chalk.yellow(\"?\")} running (PID ${String(pid)}) but IPC unreachable`,\n );\n } else {\n console.log(\n ` Gateway daemon ${chalk.red(\"✗\")} stopped`,\n );\n }\n console.log();\n }\n });\n\ngatewayCommand\n .command(\"install\")\n .description(\"Install as system service (auto-start on boot)\")\n .action(async () => {\n try {\n const { installService } = await import(\"@alfe.ai/gateway\");\n const result = await installService();\n console.log(chalk.green(result));\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(chalk.red(`Install failed: ${message}`));\n process.exit(1);\n }\n });\n\ngatewayCommand\n .command(\"uninstall\")\n .description(\"Remove system service\")\n .action(async () => {\n try {\n const { uninstallService } = await import(\"@alfe.ai/gateway\");\n const result = await uninstallService();\n console.log(chalk.green(result));\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(chalk.red(`Uninstall failed: ${message}`));\n process.exit(1);\n }\n });\n\ngatewayCommand\n .command(\"logs\")\n .description(\"Tail daemon logs\")\n .action(() => {\n if (!existsSync(LOG_FILE)) {\n console.log(chalk.yellow(`No log file found at ${LOG_FILE}`));\n return;\n }\n\n console.log(chalk.dim(`Tailing ${LOG_FILE}\\n`));\n // spawn imported at top of file (ESM)\n const tail = spawn(\"tail\", [\"-f\", LOG_FILE], { stdio: \"inherit\" });\n tail.on(\"error\", () => {\n console.error(chalk.red(\"Failed to tail log file\"));\n });\n });\n\n// ── Helpers ─────────────────────────────────────────────────\n\nfunction getRunningPid(): number | null {\n if (!existsSync(PID_PATH)) return null;\n\n try {\n const pidStr = readFileSync(PID_PATH, \"utf-8\").trim();\n const pid = parseInt(pidStr, 10);\n if (isNaN(pid)) return null;\n\n // Check if process is alive\n process.kill(pid, 0);\n return pid;\n } catch {\n return null;\n }\n}\n","/**\n * alfe integration — manage Alfe integrations.\n *\n * Subcommands:\n * list - List installed integrations\n * install - Install an integration from the registry\n * remove - Uninstall an integration\n * configure - Interactive configuration wizard\n * status - Health check for integrations\n * search - Search the registry index\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\n\nexport const integrationCommand = new Command('integration')\n .alias('int')\n .description('Manage Alfe integrations')\n .action(() => {\n integrationCommand.help();\n });\n\n// ── List ────────────────────────────────────────────────────\n\nintegrationCommand\n .command('list')\n .description('List installed integrations')\n .action(async () => {\n try {\n const { StateManager } = await import('@alfe.ai/integrations');\n const state = new StateManager();\n const integrations = state.list();\n\n if (integrations.length === 0) {\n console.log(chalk.dim('No integrations installed.'));\n console.log(chalk.dim(' Run: alfe integration search <query>'));\n console.log(chalk.dim(' Run: alfe integration install <name>'));\n return;\n }\n\n console.log(chalk.bold('\\nInstalled Integrations\\n'));\n\n for (const integration of integrations) {\n const statusColor = getStatusColor(integration.status);\n const statusIcon = getStatusIcon(integration.status);\n\n console.log(\n ` ${statusIcon} ${chalk.bold(integration.id)} ${chalk.dim(`v${integration.version}`)} ${statusColor(integration.status)}`,\n );\n\n if (integration.error) {\n console.log(` ${chalk.red(`Error: ${integration.error}`)}`);\n }\n }\n\n console.log();\n } catch (err: unknown) {\n handleModuleError(err);\n }\n });\n\n// ── Install ─────────────────────────────────────────────────\n\nintegrationCommand\n .command('install <name> [version]')\n .description('Install an integration from the registry')\n .action(async (name: string, version?: string) => {\n try {\n const { IntegrationManager } = await import('@alfe.ai/integrations');\n const manager = new IntegrationManager();\n\n console.log(chalk.blue(`Installing ${name}${version ? `@${version}` : ''}...`));\n console.log();\n\n const result = await manager.install({ name, version });\n\n if (result.ok) {\n const payload = result.payload as { name?: string; id?: string; version?: string; capabilities?: string[] };\n console.log(chalk.green(`✅ Integration \"${payload.name ?? payload.id ?? 'unknown'}\" installed successfully`));\n console.log(chalk.dim(` Version: ${payload.version ?? 'unknown'}`));\n if (payload.capabilities && payload.capabilities.length > 0) {\n console.log(chalk.dim(` Capabilities: ${payload.capabilities.join(', ')}`));\n }\n console.log();\n console.log(chalk.dim('Next steps:'));\n console.log(chalk.dim(` alfe integration configure ${name}`));\n console.log(chalk.dim(` alfe integration status ${name}`));\n } else {\n console.error(chalk.red(`❌ Installation failed: ${result.error?.message ?? 'unknown error'}`));\n process.exit(1);\n }\n } catch (err: unknown) {\n handleModuleError(err);\n }\n });\n\n// ── Remove ──────────────────────────────────────────────────\n\nintegrationCommand\n .command('remove <name>')\n .description('Uninstall an integration')\n .action(async (name: string) => {\n try {\n const { IntegrationManager } = await import('@alfe.ai/integrations');\n const manager = new IntegrationManager();\n\n console.log(chalk.blue(`Removing ${name}...`));\n\n const result = await manager.uninstall({ name });\n\n if (result.ok) {\n console.log(chalk.green(`✅ Integration \"${name}\" removed successfully`));\n } else {\n console.error(chalk.red(`❌ Removal failed: ${result.error?.message ?? 'unknown error'}`));\n process.exit(1);\n }\n } catch (err: unknown) {\n handleModuleError(err);\n }\n });\n\n// ── Configure ───────────────────────────────────────────────\n\nintegrationCommand\n .command('configure <name>')\n .description('Interactive configuration wizard for an integration')\n .action(async (name: string) => {\n try {\n const { IntegrationManager } = await import('@alfe.ai/integrations');\n const { Installer } = await import('@alfe.ai/integrations');\n const { parseManifestFile } = await import('@alfe.ai/integration-manifest');\n const inquirer = await import('@inquirer/prompts');\n const nodePath = await import('node:path');\n const nodeFs = await import('node:fs');\n\n const installer = new Installer();\n const installPath = installer.getInstallPath(name);\n const manifestPath = nodePath.join(installPath, 'alfe-integration.yaml');\n\n if (!nodeFs.existsSync(manifestPath)) {\n console.error(chalk.red(`Integration \"${name}\" is not installed or manifest is missing.`));\n process.exit(1);\n }\n\n const manifest = parseManifestFile(manifestPath);\n\n if (manifest.config_schema.length === 0) {\n console.log(chalk.yellow(`Integration \"${name}\" has no configuration fields.`));\n return;\n }\n\n console.log(chalk.bold(`\\nConfigure: ${manifest.name}\\n`));\n console.log(chalk.dim(manifest.description));\n console.log();\n\n const config: Record<string, unknown> = {};\n\n for (const field of manifest.config_schema) {\n const requiredMark = field.required ? chalk.red(' *') : '';\n const hint = field.description ? chalk.dim(` (${field.description})`) : '';\n\n let value: unknown;\n\n switch (field.type) {\n case 'secret':\n value = await inquirer.password({\n message: `${field.label}${requiredMark}${hint}:`,\n });\n break;\n\n case 'boolean':\n value = await inquirer.confirm({\n message: `${field.label}${requiredMark}${hint}:`,\n default: (field.default as boolean | undefined) ?? false,\n });\n break;\n\n case 'enum':\n value = await inquirer.select({\n message: `${field.label}${requiredMark}${hint}:`,\n choices: (field.options ?? []).map((o) => ({ name: o, value: o })),\n });\n break;\n\n case 'number': {\n const numStr = await inquirer.input({\n message: `${field.label}${requiredMark}${hint}:`,\n default: field.default?.toString(),\n });\n value = numStr ? Number(numStr) : undefined;\n break;\n }\n\n default: // string\n value = await inquirer.input({\n message: `${field.label}${requiredMark}${hint}:`,\n default: field.default as string,\n });\n break;\n }\n\n if (value !== undefined && value !== '') {\n config[field.key] = value;\n }\n }\n\n const manager = new IntegrationManager();\n const result = manager.configure({ name, config });\n\n if (result.ok) {\n console.log(chalk.green(`\\n✅ Integration \"${name}\" configured successfully`));\n const payload = result.payload as { secretCount?: number };\n if (payload.secretCount && payload.secretCount > 0) {\n console.log(chalk.dim(` ${String(payload.secretCount)} secret(s) stored in memory only`));\n }\n } else {\n console.error(chalk.red(`\\n❌ Configuration failed: ${result.error?.message ?? 'unknown error'}`));\n process.exit(1);\n }\n } catch (err: unknown) {\n handleModuleError(err);\n }\n });\n\n// ── Status ──────────────────────────────────────────────────\n\nintegrationCommand\n .command('status [name]')\n .description('Health check for one or all integrations')\n .action(async (name?: string) => {\n try {\n const { IntegrationManager } = await import('@alfe.ai/integrations');\n const manager = new IntegrationManager();\n\n const result = await manager.health({ name });\n\n if (!result.ok) {\n console.error(chalk.red(`Health check failed: ${result.error?.message ?? 'unknown error'}`));\n process.exit(1);\n }\n\n interface HealthCheck {\n healthy: boolean;\n name: string;\n version?: string;\n status: string;\n message?: string;\n }\n interface HealthPayload {\n healthy?: boolean;\n name?: string;\n version?: string;\n message?: string;\n overall?: boolean;\n results?: HealthCheck[];\n }\n const payload = result.payload as HealthPayload;\n\n if (name) {\n // Single integration health\n const statusIcon = payload.healthy ? chalk.green('✓') : chalk.red('✗');\n console.log(\n `\\n ${statusIcon} ${chalk.bold(payload.name ?? 'unknown')} ${chalk.dim(`v${payload.version ?? 'unknown'}`)} ${payload.message ?? ''}`,\n );\n } else {\n // All integrations health\n const report = payload;\n const overallIcon = report.overall ? chalk.green('✓') : chalk.red('✗');\n console.log(chalk.bold(`\\nIntegration Health Report ${overallIcon}\\n`));\n\n for (const check of report.results ?? []) {\n const icon = check.healthy ? chalk.green('✓') : chalk.red('✗');\n const statusColor = getStatusColor(check.status);\n console.log(\n ` ${icon} ${chalk.bold(check.name)} ${chalk.dim(`v${check.version ?? '?'}`)} ${statusColor(check.status)} ${chalk.dim(check.message ?? '')}`,\n );\n }\n\n if ((report.results ?? []).length === 0) {\n console.log(chalk.dim(' No integrations installed.'));\n }\n }\n\n console.log();\n } catch (err: unknown) {\n handleModuleError(err);\n }\n });\n\n// ── Search ──────────────────────────────────────────────────\n\nintegrationCommand\n .command('search [query]')\n .description('Search the integration registry')\n .action(async (query?: string) => {\n try {\n const { Registry } = await import('@alfe.ai/integrations');\n const registry = new Registry();\n\n const results = query ? await registry.search(query) : await registry.list();\n\n if (results.length === 0) {\n console.log(chalk.dim(query ? `No integrations matching \"${query}\".` : 'Registry is empty.'));\n return;\n }\n\n console.log(chalk.bold(`\\nAvailable Integrations${query ? ` matching \"${query}\"` : ''}\\n`));\n\n for (const entry of results) {\n console.log(\n ` ${chalk.bold(entry.name)} ${chalk.dim(`v${entry.latest}`)} ${entry.description}`,\n );\n console.log(\n chalk.dim(` Versions: ${entry.versions.join(', ')} | ${entry.repo}`),\n );\n }\n\n console.log();\n console.log(chalk.dim(' Install with: alfe integration install <name>'));\n console.log();\n } catch (err: unknown) {\n handleModuleError(err);\n }\n });\n\n// ── Helpers ─────────────────────────────────────────────────\n\nfunction getStatusColor(status: string): (s: string) => string {\n switch (status) {\n case 'active':\n return chalk.green;\n case 'configured':\n return chalk.blue;\n case 'installed':\n return chalk.cyan;\n case 'installing':\n return chalk.yellow;\n case 'error':\n return chalk.red;\n default:\n return chalk.dim;\n }\n}\n\nfunction getStatusIcon(status: string): string {\n switch (status) {\n case 'active':\n return chalk.green('●');\n case 'configured':\n return chalk.blue('●');\n case 'installed':\n return chalk.cyan('●');\n case 'installing':\n return chalk.yellow('◌');\n case 'error':\n return chalk.red('●');\n default:\n return chalk.dim('○');\n }\n}\n\nfunction handleModuleError(err: unknown): void {\n const errObj = err as { code?: string };\n if (errObj.code === 'ERR_MODULE_NOT_FOUND') {\n console.error(\n chalk.red(\n 'Integration packages not found. Make sure @alfe.ai/integrations and related packages are installed.',\n ),\n );\n } else {\n const message = err instanceof Error ? err.message : String(err);\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n}\n","#!/usr/bin/env node\n\n/**\n * Alfe CLI — set up and manage Alfe AI agents.\n *\n * Commands:\n * login - Authenticate with the Alfe API\n * setup - Interactive setup wizard\n * doctor - Diagnose environment issues\n * gateway - Manage the local gateway daemon\n * integration - Manage Alfe integrations\n */\n\nimport { Command } from \"commander\";\nimport { loginCommand } from \"./commands/login.js\";\nimport { setupCommand } from \"./commands/setup.js\";\nimport { doctorCommand } from \"./commands/doctor.js\";\nimport { gatewayCommand } from \"./commands/gateway.js\";\nimport { integrationCommand } from \"./commands/integration.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"alfe\")\n .description(\"CLI for setting up and managing Alfe AI agents\")\n .version(\"0.1.0\");\n\nprogram.addCommand(loginCommand);\nprogram.addCommand(setupCommand);\nprogram.addCommand(doctorCommand);\nprogram.addCommand(gatewayCommand);\nprogram.addCommand(integrationCommand);\n\nprogram.parse();\n"],"x_google_ignoreList":[1],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alfe.ai/cli",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "CLI for setting up and managing Alfe AI agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"alfe": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@inquirer/prompts": "^7.0.0",
|
|
22
|
+
"chalk": "^5.4.1",
|
|
23
|
+
"commander": "^13.0.0",
|
|
24
|
+
"ora": "^8.1.1",
|
|
25
|
+
"@alfe.ai/config": "^0.0.1",
|
|
26
|
+
"@alfe.ai/gateway": "^0.0.1",
|
|
27
|
+
"@alfe.ai/integration-manifest": "^0.0.1",
|
|
28
|
+
"@alfe.ai/integrations": "^0.0.1"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"tsx": "^4.19.0",
|
|
32
|
+
"@alfe/api-client": "0.1.0"
|
|
33
|
+
},
|
|
34
|
+
"license": "UNLICENSED",
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsdown",
|
|
37
|
+
"dev": "tsdown --watch",
|
|
38
|
+
"typecheck": "tsc --noEmit",
|
|
39
|
+
"lint": "eslint ."
|
|
40
|
+
}
|
|
41
|
+
}
|