leedab 0.1.5 → 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 +24 -15
- 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 +2 -0
- package/dist/paths.js +4 -0
- 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
|
}
|
|
@@ -114,7 +112,19 @@ program
|
|
|
114
112
|
console.log(` Key: ${license.key.slice(0, 16)}...`);
|
|
115
113
|
console.log(` Tier: ${license.tier}`);
|
|
116
114
|
console.log(` Status: ${license.valid ? chalk.green(license.status) : chalk.red(license.status)}`);
|
|
117
|
-
|
|
115
|
+
// Count local allowlist users as seats
|
|
116
|
+
let localSeats = 0;
|
|
117
|
+
try {
|
|
118
|
+
const { readFile } = await import("node:fs/promises");
|
|
119
|
+
const { resolve } = await import("node:path");
|
|
120
|
+
const ocConfig = JSON.parse(await readFile(resolve(STATE_DIR, "openclaw.json"), "utf-8"));
|
|
121
|
+
const allUsers = new Set();
|
|
122
|
+
for (const ch of Object.values(ocConfig.channels || {})) {
|
|
123
|
+
for (const u of ch.allowFrom || []) allUsers.add(u);
|
|
124
|
+
}
|
|
125
|
+
localSeats = allUsers.size;
|
|
126
|
+
} catch {}
|
|
127
|
+
console.log(` Seats: ${localSeats} / ${license.maxSeats}`);
|
|
118
128
|
console.log(` Checked: ${new Date(license.validatedAt).toLocaleDateString()}`);
|
|
119
129
|
console.log("");
|
|
120
130
|
});
|
|
@@ -131,7 +141,7 @@ configure
|
|
|
131
141
|
const result = await onboardProvider();
|
|
132
142
|
if (result) {
|
|
133
143
|
const { readFile, writeFile } = await import("node:fs/promises");
|
|
134
|
-
const configPath = resolve("
|
|
144
|
+
const configPath = resolve(resolve(STATE_DIR, "config.json"));
|
|
135
145
|
try {
|
|
136
146
|
const raw = JSON.parse(await readFile(configPath, "utf-8"));
|
|
137
147
|
raw.agent.model = result.model;
|
|
@@ -161,7 +171,7 @@ program
|
|
|
161
171
|
program
|
|
162
172
|
.command("start")
|
|
163
173
|
.description("Start the LeedAB agent and dashboard")
|
|
164
|
-
.option("-c, --config <path>", "Path to config file", "
|
|
174
|
+
.option("-c, --config <path>", "Path to config file", resolve(STATE_DIR, "config.json"))
|
|
165
175
|
.option("-p, --dashboard-port <port>", "Dashboard port", "3000")
|
|
166
176
|
.action(async (opts) => {
|
|
167
177
|
const spinner = ora("Starting LeedAB agent...").start();
|
|
@@ -196,7 +206,7 @@ program
|
|
|
196
206
|
program
|
|
197
207
|
.command("dashboard")
|
|
198
208
|
.description("Open the setup dashboard (without starting the agent)")
|
|
199
|
-
.option("-c, --config <path>", "Path to config file", "
|
|
209
|
+
.option("-c, --config <path>", "Path to config file", resolve(STATE_DIR, "config.json"))
|
|
200
210
|
.option("-p, --port <port>", "Dashboard port", "3000")
|
|
201
211
|
.action(async (opts) => {
|
|
202
212
|
try {
|
|
@@ -374,7 +384,7 @@ pairing
|
|
|
374
384
|
program
|
|
375
385
|
.command("channels")
|
|
376
386
|
.description("List configured channels and their status")
|
|
377
|
-
.option("-c, --config <path>", "Path to config file", "
|
|
387
|
+
.option("-c, --config <path>", "Path to config file", resolve(STATE_DIR, "config.json"))
|
|
378
388
|
.action(async (opts) => {
|
|
379
389
|
const config = await loadConfig(opts.config);
|
|
380
390
|
await setupChannels(config);
|
|
@@ -618,8 +628,7 @@ team
|
|
|
618
628
|
|
|
619
629
|
// Default action: show status if in a project, nudge to onboard if not
|
|
620
630
|
if (process.argv.length <= 2) {
|
|
621
|
-
|
|
622
|
-
if (!hasProject) {
|
|
631
|
+
if (!existsSync(STATE_DIR)) {
|
|
623
632
|
console.log(chalk.bold("\n LeedAB") + chalk.dim(" — Your enterprise AI agent\n"));
|
|
624
633
|
console.log(chalk.dim(" Get started:\n"));
|
|
625
634
|
console.log(` ${chalk.cyan("leedab onboard")} Interactive setup wizard`);
|
|
@@ -630,7 +639,7 @@ if (process.argv.length <= 2) {
|
|
|
630
639
|
// Show project status
|
|
631
640
|
(async () => {
|
|
632
641
|
try {
|
|
633
|
-
const config = await loadConfig("
|
|
642
|
+
const config = await loadConfig(resolve(STATE_DIR, "config.json"));
|
|
634
643
|
const channels = Object.entries(config.channels)
|
|
635
644
|
.filter(([_, v]) => v?.enabled)
|
|
636
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
ADDED
package/dist/paths.js
ADDED
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() {
|