leedab 0.1.3 → 0.1.5
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 +43 -0
- package/dist/dashboard/routes.js +2 -3
- package/dist/gateway.js +6 -0
- package/dist/onboard/index.js +1 -1
- package/dist/team.d.ts +12 -8
- package/dist/team.js +66 -40
- package/package.json +1 -1
package/bin/leedab.js
CHANGED
|
@@ -91,6 +91,34 @@ program
|
|
|
91
91
|
}
|
|
92
92
|
});
|
|
93
93
|
|
|
94
|
+
program
|
|
95
|
+
.command("license")
|
|
96
|
+
.description("Show license details — tier, seats, status")
|
|
97
|
+
.action(async () => {
|
|
98
|
+
const { loadLicense, validateLicenseKey, saveLicense } = await import("../dist/license.js");
|
|
99
|
+
const cached = await loadLicense();
|
|
100
|
+
if (!cached?.key) {
|
|
101
|
+
console.log(chalk.red("\n No valid license found. Run `leedab onboard` to enter your key.\n"));
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
// Always fetch live
|
|
105
|
+
const license = await validateLicenseKey(cached.key);
|
|
106
|
+
await saveLicense(license);
|
|
107
|
+
if (!license) {
|
|
108
|
+
console.log(chalk.red("\n No valid license found. Run `leedab onboard` to enter your key.\n"));
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
console.log("");
|
|
112
|
+
console.log(chalk.bold(" License"));
|
|
113
|
+
console.log("");
|
|
114
|
+
console.log(` Key: ${license.key.slice(0, 16)}...`);
|
|
115
|
+
console.log(` Tier: ${license.tier}`);
|
|
116
|
+
console.log(` Status: ${license.valid ? chalk.green(license.status) : chalk.red(license.status)}`);
|
|
117
|
+
console.log(` Seats: ${license.seatsUsed} / ${license.maxSeats}`);
|
|
118
|
+
console.log(` Checked: ${new Date(license.validatedAt).toLocaleDateString()}`);
|
|
119
|
+
console.log("");
|
|
120
|
+
});
|
|
121
|
+
|
|
94
122
|
const configure = program
|
|
95
123
|
.command("configure")
|
|
96
124
|
.description("Reconfigure LeedAB settings");
|
|
@@ -268,6 +296,21 @@ pairing
|
|
|
268
296
|
return;
|
|
269
297
|
}
|
|
270
298
|
|
|
299
|
+
// Check seat limit
|
|
300
|
+
const { ensureLicense } = await import("../dist/license.js");
|
|
301
|
+
const license = await ensureLicense();
|
|
302
|
+
if (license && license.maxSeats > 0) {
|
|
303
|
+
// Count total unique users across all channel allowlists
|
|
304
|
+
const allUsers = new Set();
|
|
305
|
+
for (const ch of Object.values(config.channels || {})) {
|
|
306
|
+
for (const u of ch.allowFrom || []) allUsers.add(u);
|
|
307
|
+
}
|
|
308
|
+
if (allUsers.size >= license.maxSeats) {
|
|
309
|
+
console.error(chalk.red(`Seat limit reached (${allUsers.size}/${license.maxSeats}). Upgrade your plan to add more users.`));
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
271
314
|
config.channels[channel].allowFrom.push(userId);
|
|
272
315
|
config.channels[channel].dmPolicy = "allowlist";
|
|
273
316
|
await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
|
package/dist/dashboard/routes.js
CHANGED
|
@@ -429,9 +429,8 @@ export function createRoutes(config) {
|
|
|
429
429
|
}
|
|
430
430
|
const member = await addMember({
|
|
431
431
|
name: name.trim(),
|
|
432
|
-
email: email ||
|
|
433
|
-
role: role || "
|
|
434
|
-
channels: channels || [],
|
|
432
|
+
email: email || "",
|
|
433
|
+
role: role || "member",
|
|
435
434
|
});
|
|
436
435
|
json(res, member, 201);
|
|
437
436
|
},
|
package/dist/gateway.js
CHANGED
|
@@ -5,12 +5,18 @@ import { readFile, writeFile, readdir, copyFile, mkdir, access } from "node:fs/p
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
7
|
import { resolveOpenClawBin, openclawEnv } from "./openclaw.js";
|
|
8
|
+
import { ensureLicense } from "./license.js";
|
|
8
9
|
const execFileAsync = promisify(execFile);
|
|
9
10
|
let gatewayProcess = null;
|
|
10
11
|
/**
|
|
11
12
|
* Start the LeedAB agent gateway.
|
|
12
13
|
*/
|
|
13
14
|
export async function startGateway(config) {
|
|
15
|
+
// Verify license before starting
|
|
16
|
+
const license = await ensureLicense();
|
|
17
|
+
if (!license) {
|
|
18
|
+
throw new Error("No valid license found. Run `leedab onboard` to enter your license key.");
|
|
19
|
+
}
|
|
14
20
|
const bin = resolveOpenClawBin();
|
|
15
21
|
const stateDir = resolve(".leedab");
|
|
16
22
|
const env = openclawEnv(stateDir);
|
package/dist/onboard/index.js
CHANGED
|
@@ -24,7 +24,7 @@ export async function runOnboard() {
|
|
|
24
24
|
}
|
|
25
25
|
else {
|
|
26
26
|
console.log(chalk.bold(" License Key\n"));
|
|
27
|
-
console.log(chalk.dim("
|
|
27
|
+
console.log(chalk.dim(" Buy at ") + chalk.cyan("https://leedab.com") + chalk.dim(" — key is sent to your email.") + "\n");
|
|
28
28
|
let licensed = false;
|
|
29
29
|
while (!licensed) {
|
|
30
30
|
let licenseKey;
|
package/dist/team.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
export type Role = "admin" | "
|
|
1
|
+
export type Role = "admin" | "member" | "owner";
|
|
2
2
|
export interface TeamMember {
|
|
3
3
|
id: string;
|
|
4
|
-
|
|
5
|
-
email
|
|
4
|
+
user_id: number;
|
|
5
|
+
email: string;
|
|
6
|
+
username: string;
|
|
6
7
|
role: Role;
|
|
7
|
-
|
|
8
|
-
createdAt: string;
|
|
8
|
+
joined_at: string;
|
|
9
9
|
}
|
|
10
10
|
export declare function loadTeam(): Promise<TeamMember[]>;
|
|
11
|
-
export declare function addMember(member:
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
export declare function addMember(member: {
|
|
12
|
+
name: string;
|
|
13
|
+
email: string;
|
|
14
|
+
role: Role;
|
|
15
|
+
}): Promise<TeamMember>;
|
|
16
|
+
export declare function removeMember(memberId: string): Promise<boolean>;
|
|
17
|
+
export declare function updateRole(memberId: string, role: Role): Promise<boolean>;
|
package/dist/team.js
CHANGED
|
@@ -1,49 +1,75 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { loadLicense } from "./license.js";
|
|
2
|
+
const API_URL = "https://api.leedab.com/api/v1";
|
|
3
|
+
/**
|
|
4
|
+
* Get the license key for API auth.
|
|
5
|
+
*/
|
|
6
|
+
async function getAuthHeader() {
|
|
7
|
+
const license = await loadLicense();
|
|
8
|
+
if (!license?.key) {
|
|
9
|
+
throw new Error("No license key found. Run `leedab onboard` first.");
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
Authorization: `Bearer ${license.key}`,
|
|
13
|
+
"Content-Type": "application/json",
|
|
14
|
+
};
|
|
7
15
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Get the user's organization slug.
|
|
18
|
+
*/
|
|
19
|
+
async function getOrgSlug(headers) {
|
|
20
|
+
const res = await fetch(`${API_URL}/organizations`, { headers });
|
|
21
|
+
if (!res.ok) {
|
|
22
|
+
throw new Error("Failed to fetch organizations.");
|
|
12
23
|
}
|
|
13
|
-
|
|
14
|
-
|
|
24
|
+
const data = await res.json();
|
|
25
|
+
if (!data.length) {
|
|
26
|
+
throw new Error("No organization found. Create one in the dashboard first.");
|
|
15
27
|
}
|
|
28
|
+
return data[0].slug;
|
|
16
29
|
}
|
|
17
|
-
async function
|
|
18
|
-
await
|
|
19
|
-
|
|
30
|
+
export async function loadTeam() {
|
|
31
|
+
const headers = await getAuthHeader();
|
|
32
|
+
const slug = await getOrgSlug(headers);
|
|
33
|
+
const res = await fetch(`${API_URL}/organizations/${slug}/members/`, { headers });
|
|
34
|
+
if (!res.ok) {
|
|
35
|
+
throw new Error("Failed to fetch team members.");
|
|
36
|
+
}
|
|
37
|
+
const data = await res.json();
|
|
38
|
+
return data.members;
|
|
20
39
|
}
|
|
21
40
|
export async function addMember(member) {
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
41
|
+
const headers = await getAuthHeader();
|
|
42
|
+
const slug = await getOrgSlug(headers);
|
|
43
|
+
const res = await fetch(`${API_URL}/organizations/${slug}/invites/`, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers,
|
|
46
|
+
body: JSON.stringify({
|
|
47
|
+
email: member.email,
|
|
48
|
+
role: member.role,
|
|
49
|
+
}),
|
|
50
|
+
});
|
|
51
|
+
if (!res.ok) {
|
|
52
|
+
const err = await res.json().catch(() => ({}));
|
|
53
|
+
throw new Error(err.error || "Failed to add team member.");
|
|
54
|
+
}
|
|
55
|
+
return await res.json();
|
|
31
56
|
}
|
|
32
|
-
export async function removeMember(
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return
|
|
57
|
+
export async function removeMember(memberId) {
|
|
58
|
+
const headers = await getAuthHeader();
|
|
59
|
+
const slug = await getOrgSlug(headers);
|
|
60
|
+
const res = await fetch(`${API_URL}/organizations/${slug}/members/${memberId}/`, {
|
|
61
|
+
method: "DELETE",
|
|
62
|
+
headers,
|
|
63
|
+
});
|
|
64
|
+
return res.ok;
|
|
40
65
|
}
|
|
41
|
-
export async function updateRole(
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
66
|
+
export async function updateRole(memberId, role) {
|
|
67
|
+
const headers = await getAuthHeader();
|
|
68
|
+
const slug = await getOrgSlug(headers);
|
|
69
|
+
const res = await fetch(`${API_URL}/organizations/${slug}/members/${memberId}/`, {
|
|
70
|
+
method: "PUT",
|
|
71
|
+
headers,
|
|
72
|
+
body: JSON.stringify({ role }),
|
|
73
|
+
});
|
|
74
|
+
return res.ok;
|
|
49
75
|
}
|