leedab 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/leedab.js +11 -14
- package/dist/audit.js +2 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +7 -6
- package/dist/config/schema.d.ts +1 -1
- package/dist/dashboard/routes.js +2 -1
- package/dist/gateway.js +4 -3
- package/dist/license.js +3 -2
- package/dist/onboard/index.js +8 -6
- package/dist/onboard/steps/provider.js +2 -1
- package/dist/openclaw.js +2 -1
- package/dist/paths.d.ts +1 -1
- package/dist/paths.js +1 -1
- package/dist/vault.js +2 -1
- package/package.json +1 -1
package/bin/leedab.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import { resolve } from "node:path";
|
|
6
|
+
import { homedir } from "node:os";
|
|
6
7
|
import { program } from "commander";
|
|
7
8
|
import chalk from "chalk";
|
|
8
9
|
import ora from "ora";
|
|
@@ -19,7 +20,7 @@ import { ensureLicense } from "../dist/license.js";
|
|
|
19
20
|
|
|
20
21
|
const pkg = createRequire(import.meta.url)("../package.json");
|
|
21
22
|
const OPENCLAW_BIN = resolveOpenClawBin();
|
|
22
|
-
const STATE_DIR = resolve(".leedab");
|
|
23
|
+
const STATE_DIR = resolve(homedir(), ".leedab");
|
|
23
24
|
const ocEnv = openclawEnv(STATE_DIR);
|
|
24
25
|
|
|
25
26
|
/** Commands that don't require an existing project directory or license. */
|
|
@@ -37,12 +38,9 @@ function requireProject(command) {
|
|
|
37
38
|
const parentName = command.parent?.name();
|
|
38
39
|
if (NO_PROJECT_REQUIRED.has(name) || NO_PROJECT_REQUIRED.has(parentName)) return;
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
console.error(chalk.red("\n Not a LeedAB project directory.\n"));
|
|
44
|
-
console.error(chalk.dim(" Run ") + chalk.cyan("leedab onboard") + chalk.dim(" to set up a new project here,"));
|
|
45
|
-
console.error(chalk.dim(" or cd into an existing project directory.\n"));
|
|
41
|
+
if (!existsSync(STATE_DIR)) {
|
|
42
|
+
console.error(chalk.red("\n LeedAB is not set up yet.\n"));
|
|
43
|
+
console.error(chalk.dim(" Run ") + chalk.cyan("leedab onboard") + chalk.dim(" to get started.\n"));
|
|
46
44
|
process.exit(1);
|
|
47
45
|
}
|
|
48
46
|
}
|
|
@@ -143,7 +141,7 @@ configure
|
|
|
143
141
|
const result = await onboardProvider();
|
|
144
142
|
if (result) {
|
|
145
143
|
const { readFile, writeFile } = await import("node:fs/promises");
|
|
146
|
-
const configPath = resolve("
|
|
144
|
+
const configPath = resolve(resolve(STATE_DIR, "config.json"));
|
|
147
145
|
try {
|
|
148
146
|
const raw = JSON.parse(await readFile(configPath, "utf-8"));
|
|
149
147
|
raw.agent.model = result.model;
|
|
@@ -173,7 +171,7 @@ program
|
|
|
173
171
|
program
|
|
174
172
|
.command("start")
|
|
175
173
|
.description("Start the LeedAB agent and dashboard")
|
|
176
|
-
.option("-c, --config <path>", "Path to config file", "
|
|
174
|
+
.option("-c, --config <path>", "Path to config file", resolve(STATE_DIR, "config.json"))
|
|
177
175
|
.option("-p, --dashboard-port <port>", "Dashboard port", "3000")
|
|
178
176
|
.action(async (opts) => {
|
|
179
177
|
const spinner = ora("Starting LeedAB agent...").start();
|
|
@@ -208,7 +206,7 @@ program
|
|
|
208
206
|
program
|
|
209
207
|
.command("dashboard")
|
|
210
208
|
.description("Open the setup dashboard (without starting the agent)")
|
|
211
|
-
.option("-c, --config <path>", "Path to config file", "
|
|
209
|
+
.option("-c, --config <path>", "Path to config file", resolve(STATE_DIR, "config.json"))
|
|
212
210
|
.option("-p, --port <port>", "Dashboard port", "3000")
|
|
213
211
|
.action(async (opts) => {
|
|
214
212
|
try {
|
|
@@ -386,7 +384,7 @@ pairing
|
|
|
386
384
|
program
|
|
387
385
|
.command("channels")
|
|
388
386
|
.description("List configured channels and their status")
|
|
389
|
-
.option("-c, --config <path>", "Path to config file", "
|
|
387
|
+
.option("-c, --config <path>", "Path to config file", resolve(STATE_DIR, "config.json"))
|
|
390
388
|
.action(async (opts) => {
|
|
391
389
|
const config = await loadConfig(opts.config);
|
|
392
390
|
await setupChannels(config);
|
|
@@ -630,8 +628,7 @@ team
|
|
|
630
628
|
|
|
631
629
|
// Default action: show status if in a project, nudge to onboard if not
|
|
632
630
|
if (process.argv.length <= 2) {
|
|
633
|
-
|
|
634
|
-
if (!hasProject) {
|
|
631
|
+
if (!existsSync(STATE_DIR)) {
|
|
635
632
|
console.log(chalk.bold("\n LeedAB") + chalk.dim(" — Your enterprise AI agent\n"));
|
|
636
633
|
console.log(chalk.dim(" Get started:\n"));
|
|
637
634
|
console.log(` ${chalk.cyan("leedab onboard")} Interactive setup wizard`);
|
|
@@ -642,7 +639,7 @@ if (process.argv.length <= 2) {
|
|
|
642
639
|
// Show project status
|
|
643
640
|
(async () => {
|
|
644
641
|
try {
|
|
645
|
-
const config = await loadConfig("
|
|
642
|
+
const config = await loadConfig(resolve(STATE_DIR, "config.json"));
|
|
646
643
|
const channels = Object.entries(config.channels)
|
|
647
644
|
.filter(([_, v]) => v?.enabled)
|
|
648
645
|
.map(([k]) => k);
|
package/dist/audit.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { appendFile, readFile, mkdir } from "node:fs/promises";
|
|
2
2
|
import { resolve, dirname } from "node:path";
|
|
3
|
-
|
|
3
|
+
import { STATE_DIR } from "./paths.js";
|
|
4
|
+
const AUDIT_PATH = resolve(STATE_DIR, "logs", "audit.jsonl");
|
|
4
5
|
export async function logAudit(entry) {
|
|
5
6
|
await mkdir(dirname(AUDIT_PATH), { recursive: true });
|
|
6
7
|
const line = JSON.stringify({
|
package/dist/config/index.d.ts
CHANGED
|
@@ -5,6 +5,6 @@ export { type LeedABConfig } from "./schema.js";
|
|
|
5
5
|
*/
|
|
6
6
|
export declare function loadConfig(configPath?: string): Promise<LeedABConfig>;
|
|
7
7
|
/**
|
|
8
|
-
* Write default config to leedab
|
|
8
|
+
* Write default config to ~/.leedab/config.json.
|
|
9
9
|
*/
|
|
10
10
|
export declare function initConfig(): Promise<void>;
|
package/dist/config/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { readFile, writeFile, access } from "node:fs/promises";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
+
import { STATE_DIR } from "../paths.js";
|
|
3
4
|
import { DEFAULT_CONFIG } from "./schema.js";
|
|
5
|
+
const DEFAULT_CONFIG_PATH = resolve(STATE_DIR, "config.json");
|
|
4
6
|
/**
|
|
5
7
|
* Load and validate a LeedAB config file, merging with defaults.
|
|
6
8
|
*/
|
|
7
|
-
export async function loadConfig(configPath =
|
|
9
|
+
export async function loadConfig(configPath = DEFAULT_CONFIG_PATH) {
|
|
8
10
|
const fullPath = resolve(configPath);
|
|
9
11
|
let userConfig = {};
|
|
10
12
|
try {
|
|
@@ -17,19 +19,18 @@ export async function loadConfig(configPath = "leedab.config.json") {
|
|
|
17
19
|
return deepMerge(DEFAULT_CONFIG, userConfig);
|
|
18
20
|
}
|
|
19
21
|
/**
|
|
20
|
-
* Write default config to leedab
|
|
22
|
+
* Write default config to ~/.leedab/config.json.
|
|
21
23
|
*/
|
|
22
24
|
export async function initConfig() {
|
|
23
|
-
const configPath = resolve("leedab.config.json");
|
|
24
25
|
try {
|
|
25
|
-
await access(
|
|
26
|
-
throw new Error("
|
|
26
|
+
await access(DEFAULT_CONFIG_PATH);
|
|
27
|
+
throw new Error("config.json already exists");
|
|
27
28
|
}
|
|
28
29
|
catch (err) {
|
|
29
30
|
if (err.code !== "ENOENT")
|
|
30
31
|
throw err;
|
|
31
32
|
}
|
|
32
|
-
await writeFile(
|
|
33
|
+
await writeFile(DEFAULT_CONFIG_PATH, JSON.stringify(DEFAULT_CONFIG, null, 2) + "\n");
|
|
33
34
|
}
|
|
34
35
|
function deepMerge(target, source) {
|
|
35
36
|
const result = { ...target };
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export interface GatewayConfig {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
export interface MemoryConfig {
|
|
31
|
-
/** Path to memory directory (default:
|
|
31
|
+
/** Path to memory directory (default: ~/.leedab/memory) */
|
|
32
32
|
dir: string;
|
|
33
33
|
/** Enable vector search if embedding provider is set */
|
|
34
34
|
vectorSearch: boolean;
|
package/dist/dashboard/routes.js
CHANGED
|
@@ -8,6 +8,7 @@ import { addEntry, removeEntry, listEntries } from "../vault.js";
|
|
|
8
8
|
import { readAuditLog } from "../audit.js";
|
|
9
9
|
import { getAnalytics } from "../analytics.js";
|
|
10
10
|
import { loadTeam, addMember, removeMember, updateRole } from "../team.js";
|
|
11
|
+
import { STATE_DIR } from "../paths.js";
|
|
11
12
|
const execFileAsync = promisify(execFile);
|
|
12
13
|
async function restartGatewayQuietly(stateDir) {
|
|
13
14
|
try {
|
|
@@ -22,7 +23,7 @@ async function restartGatewayQuietly(stateDir) {
|
|
|
22
23
|
}
|
|
23
24
|
export function createRoutes(config) {
|
|
24
25
|
const bin = resolveOpenClawBin();
|
|
25
|
-
const stateDir =
|
|
26
|
+
const stateDir = STATE_DIR;
|
|
26
27
|
return {
|
|
27
28
|
/**
|
|
28
29
|
* POST /api/chat — send a message to the agent, get a response
|
package/dist/gateway.js
CHANGED
|
@@ -6,6 +6,7 @@ import { fileURLToPath } from "node:url";
|
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
7
|
import { resolveOpenClawBin, openclawEnv } from "./openclaw.js";
|
|
8
8
|
import { ensureLicense } from "./license.js";
|
|
9
|
+
import { STATE_DIR } from "./paths.js";
|
|
9
10
|
const execFileAsync = promisify(execFile);
|
|
10
11
|
let gatewayProcess = null;
|
|
11
12
|
/**
|
|
@@ -18,7 +19,7 @@ export async function startGateway(config) {
|
|
|
18
19
|
throw new Error("No valid license found. Run `leedab onboard` to enter your license key.");
|
|
19
20
|
}
|
|
20
21
|
const bin = resolveOpenClawBin();
|
|
21
|
-
const stateDir =
|
|
22
|
+
const stateDir = STATE_DIR;
|
|
22
23
|
const env = openclawEnv(stateDir);
|
|
23
24
|
// Seed workspace templates (skip files that already exist)
|
|
24
25
|
await seedWorkspace();
|
|
@@ -64,7 +65,7 @@ export async function startGateway(config) {
|
|
|
64
65
|
}
|
|
65
66
|
export async function stopGateway() {
|
|
66
67
|
const bin = resolveOpenClawBin();
|
|
67
|
-
const stateDir =
|
|
68
|
+
const stateDir = STATE_DIR;
|
|
68
69
|
try {
|
|
69
70
|
await execFileAsync(bin, ["gateway", "stop"], {
|
|
70
71
|
env: openclawEnv(stateDir),
|
|
@@ -199,7 +200,7 @@ async function seedWorkspace() {
|
|
|
199
200
|
}
|
|
200
201
|
async function waitForGateway(port, timeoutMs = 20000) {
|
|
201
202
|
const bin = resolveOpenClawBin();
|
|
202
|
-
const stateDir =
|
|
203
|
+
const stateDir = STATE_DIR;
|
|
203
204
|
const start = Date.now();
|
|
204
205
|
while (Date.now() - start < timeoutMs) {
|
|
205
206
|
try {
|
package/dist/license.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
|
|
3
|
+
import { STATE_DIR } from "./paths.js";
|
|
4
|
+
const LICENSE_PATH = resolve(STATE_DIR, "license.json");
|
|
4
5
|
const VERIFY_URL = "https://api.leedab.com/api/v1/licensing/verify";
|
|
5
6
|
const REVALIDATE_DAYS = 7;
|
|
6
7
|
/**
|
|
@@ -40,7 +41,7 @@ export async function validateLicenseKey(key) {
|
|
|
40
41
|
* Save license info to disk.
|
|
41
42
|
*/
|
|
42
43
|
export async function saveLicense(license) {
|
|
43
|
-
await mkdir(
|
|
44
|
+
await mkdir(STATE_DIR, { recursive: true });
|
|
44
45
|
await writeFile(LICENSE_PATH, JSON.stringify(license, null, 2) + "\n");
|
|
45
46
|
}
|
|
46
47
|
/**
|
package/dist/onboard/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import { DEFAULT_CONFIG } from "../config/schema.js";
|
|
|
12
12
|
import { initMemory } from "../memory/index.js";
|
|
13
13
|
import { addEntry, listEntries } from "../vault.js";
|
|
14
14
|
import { validateLicenseKey, saveLicense, loadLicense } from "../license.js";
|
|
15
|
+
import { STATE_DIR } from "../paths.js";
|
|
15
16
|
/**
|
|
16
17
|
* Run the full onboarding wizard. Writes leedab.config.json and .leedab/ secrets.
|
|
17
18
|
*/
|
|
@@ -198,15 +199,16 @@ export async function runOnboard() {
|
|
|
198
199
|
chalk.cyan("leedab vault add <service>"));
|
|
199
200
|
}
|
|
200
201
|
// --- Write everything ---
|
|
201
|
-
const configDir =
|
|
202
|
+
const configDir = STATE_DIR;
|
|
202
203
|
await mkdir(configDir, { recursive: true });
|
|
203
204
|
// Write config (no secrets)
|
|
204
|
-
await writeFile(resolve("
|
|
205
|
+
await writeFile(resolve(STATE_DIR, "config.json"), JSON.stringify(config, null, 2) + "\n");
|
|
205
206
|
// Write secrets separately
|
|
206
207
|
if (Object.keys(secrets).length > 0) {
|
|
207
208
|
await writeFile(resolve(configDir, "secrets.json"), JSON.stringify(secrets, null, 2) + "\n");
|
|
208
209
|
}
|
|
209
210
|
// Init memory directory
|
|
211
|
+
config.memory.dir = resolve(STATE_DIR, "memory");
|
|
210
212
|
await initMemory(config.memory.dir);
|
|
211
213
|
// Summary
|
|
212
214
|
console.log(chalk.bold("\n Setup complete!\n"));
|
|
@@ -229,10 +231,10 @@ export async function runOnboard() {
|
|
|
229
231
|
if (vaultEntries.length > 0) {
|
|
230
232
|
console.log(chalk.green(` Vault: ${vaultEntries.length} service(s) stored`));
|
|
231
233
|
}
|
|
232
|
-
console.log(chalk.dim(`\n Config:
|
|
233
|
-
console.log(chalk.dim(` Secrets:
|
|
234
|
-
console.log(chalk.dim(` Vault:
|
|
235
|
-
console.log(chalk.dim(` Memory:
|
|
234
|
+
console.log(chalk.dim(`\n Config: ~/.leedab/config.json`));
|
|
235
|
+
console.log(chalk.dim(` Secrets: ~/.leedab/secrets.json`));
|
|
236
|
+
console.log(chalk.dim(` Vault: ~/.leedab/vault.json`));
|
|
237
|
+
console.log(chalk.dim(` Memory: ~/.leedab/memory/`));
|
|
236
238
|
console.log(chalk.bold(`\n Start your agent: ${chalk.cyan("leedab start")}\n`));
|
|
237
239
|
}
|
|
238
240
|
/**
|
|
@@ -5,6 +5,7 @@ import { promisify } from "node:util";
|
|
|
5
5
|
import inquirer from "inquirer";
|
|
6
6
|
import chalk from "chalk";
|
|
7
7
|
import { resolveOpenClawBin, openclawEnv } from "../../openclaw.js";
|
|
8
|
+
import { STATE_DIR } from "../../paths.js";
|
|
8
9
|
const execFileAsync = promisify(execFile);
|
|
9
10
|
const PROVIDERS = [
|
|
10
11
|
{
|
|
@@ -164,7 +165,7 @@ async function passKeyToOpenClaw(flag, apiKey) {
|
|
|
164
165
|
* Write the chosen model into .leedab/openclaw.json so the gateway actually uses it.
|
|
165
166
|
*/
|
|
166
167
|
export async function updateOpenClawModel(openclawModel) {
|
|
167
|
-
const configPath = resolve(
|
|
168
|
+
const configPath = resolve(STATE_DIR, "openclaw.json");
|
|
168
169
|
try {
|
|
169
170
|
const raw = JSON.parse(await readFile(configPath, "utf-8"));
|
|
170
171
|
if (!raw.agents)
|
package/dist/openclaw.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { STATE_DIR } from "./paths.js";
|
|
3
4
|
const require = createRequire(import.meta.url);
|
|
4
5
|
/**
|
|
5
6
|
* Resolve the OpenClaw binary path relative to the leedab package,
|
|
@@ -15,6 +16,6 @@ export function resolveOpenClawBin() {
|
|
|
15
16
|
export function openclawEnv(stateDir) {
|
|
16
17
|
return {
|
|
17
18
|
...process.env,
|
|
18
|
-
OPENCLAW_STATE_DIR: stateDir ??
|
|
19
|
+
OPENCLAW_STATE_DIR: stateDir ?? STATE_DIR,
|
|
19
20
|
};
|
|
20
21
|
}
|
package/dist/paths.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/** Global LeedAB state directory - always ~/.
|
|
1
|
+
/** Global LeedAB state directory - always ~/.leedab */
|
|
2
2
|
export declare const STATE_DIR: string;
|
package/dist/paths.js
CHANGED
package/dist/vault.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
2
2
|
import { resolve, dirname } from "node:path";
|
|
3
3
|
import { randomBytes, scryptSync, createCipheriv, createDecipheriv } from "node:crypto";
|
|
4
|
-
|
|
4
|
+
import { STATE_DIR } from "./paths.js";
|
|
5
|
+
const VAULT_PATH = resolve(STATE_DIR, "vault.json");
|
|
5
6
|
const MAGIC = "LEEDAB_VAULT_V1";
|
|
6
7
|
const ALGORITHM = "aes-256-gcm";
|
|
7
8
|
async function ensureDir() {
|