leedab 0.1.0
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/LICENSE +6 -0
- package/README.md +85 -0
- package/bin/leedab.js +626 -0
- package/dist/analytics.d.ts +20 -0
- package/dist/analytics.js +57 -0
- package/dist/audit.d.ts +15 -0
- package/dist/audit.js +46 -0
- package/dist/brand.d.ts +9 -0
- package/dist/brand.js +57 -0
- package/dist/channels/index.d.ts +5 -0
- package/dist/channels/index.js +47 -0
- package/dist/config/index.d.ts +10 -0
- package/dist/config/index.js +49 -0
- package/dist/config/schema.d.ts +58 -0
- package/dist/config/schema.js +21 -0
- package/dist/dashboard/routes.d.ts +5 -0
- package/dist/dashboard/routes.js +410 -0
- package/dist/dashboard/server.d.ts +2 -0
- package/dist/dashboard/server.js +80 -0
- package/dist/dashboard/static/app.js +351 -0
- package/dist/dashboard/static/console.html +252 -0
- package/dist/dashboard/static/favicon.png +0 -0
- package/dist/dashboard/static/index.html +815 -0
- package/dist/dashboard/static/logo-dark.png +0 -0
- package/dist/dashboard/static/logo-light.png +0 -0
- package/dist/dashboard/static/sessions.html +182 -0
- package/dist/dashboard/static/settings.html +274 -0
- package/dist/dashboard/static/style.css +493 -0
- package/dist/dashboard/static/team.html +215 -0
- package/dist/gateway.d.ts +8 -0
- package/dist/gateway.js +213 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/license.d.ts +27 -0
- package/dist/license.js +92 -0
- package/dist/memory/index.d.ts +9 -0
- package/dist/memory/index.js +41 -0
- package/dist/onboard/index.d.ts +4 -0
- package/dist/onboard/index.js +263 -0
- package/dist/onboard/oauth-server.d.ts +13 -0
- package/dist/onboard/oauth-server.js +73 -0
- package/dist/onboard/steps/google.d.ts +12 -0
- package/dist/onboard/steps/google.js +178 -0
- package/dist/onboard/steps/provider.d.ts +10 -0
- package/dist/onboard/steps/provider.js +292 -0
- package/dist/onboard/steps/teams.d.ts +5 -0
- package/dist/onboard/steps/teams.js +51 -0
- package/dist/onboard/steps/telegram.d.ts +6 -0
- package/dist/onboard/steps/telegram.js +88 -0
- package/dist/onboard/steps/welcome.d.ts +1 -0
- package/dist/onboard/steps/welcome.js +10 -0
- package/dist/onboard/steps/whatsapp.d.ts +2 -0
- package/dist/onboard/steps/whatsapp.js +76 -0
- package/dist/openclaw.d.ts +9 -0
- package/dist/openclaw.js +20 -0
- package/dist/team.d.ts +13 -0
- package/dist/team.js +49 -0
- package/dist/templates/verticals/supply-chain/HEARTBEAT.md +12 -0
- package/dist/templates/verticals/supply-chain/SOUL.md +49 -0
- package/dist/templates/verticals/supply-chain/WORKFLOWS.md +148 -0
- package/dist/templates/verticals/supply-chain/vault-template.json +18 -0
- package/dist/templates/workspace/AGENTS.md +181 -0
- package/dist/templates/workspace/BOOTSTRAP.md +32 -0
- package/dist/templates/workspace/HEARTBEAT.md +9 -0
- package/dist/templates/workspace/IDENTITY.md +14 -0
- package/dist/templates/workspace/SOUL.md +32 -0
- package/dist/templates/workspace/TOOLS.md +40 -0
- package/dist/templates/workspace/USER.md +26 -0
- package/dist/vault.d.ts +24 -0
- package/dist/vault.js +123 -0
- package/package.json +58 -0
package/dist/audit.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface AuditEntry {
|
|
2
|
+
timestamp: string;
|
|
3
|
+
user: string;
|
|
4
|
+
channel: string;
|
|
5
|
+
action: string;
|
|
6
|
+
query?: string;
|
|
7
|
+
responseSummary?: string;
|
|
8
|
+
durationMs?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function logAudit(entry: AuditEntry): Promise<void>;
|
|
11
|
+
export declare function readAuditLog(options?: {
|
|
12
|
+
since?: Date;
|
|
13
|
+
channel?: string;
|
|
14
|
+
limit?: number;
|
|
15
|
+
}): Promise<AuditEntry[]>;
|
package/dist/audit.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { appendFile, readFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { resolve, dirname } from "node:path";
|
|
3
|
+
const AUDIT_PATH = resolve(".leedab", "logs", "audit.jsonl");
|
|
4
|
+
export async function logAudit(entry) {
|
|
5
|
+
await mkdir(dirname(AUDIT_PATH), { recursive: true });
|
|
6
|
+
const line = JSON.stringify({
|
|
7
|
+
...entry,
|
|
8
|
+
timestamp: entry.timestamp || new Date().toISOString(),
|
|
9
|
+
});
|
|
10
|
+
await appendFile(AUDIT_PATH, line + "\n", "utf-8");
|
|
11
|
+
}
|
|
12
|
+
export async function readAuditLog(options) {
|
|
13
|
+
let raw;
|
|
14
|
+
try {
|
|
15
|
+
raw = await readFile(AUDIT_PATH, "utf-8");
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
let entries = raw
|
|
21
|
+
.trim()
|
|
22
|
+
.split("\n")
|
|
23
|
+
.filter(Boolean)
|
|
24
|
+
.map((line) => {
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(line);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
.filter(Boolean);
|
|
33
|
+
if (options?.since) {
|
|
34
|
+
const since = options.since.toISOString();
|
|
35
|
+
entries = entries.filter((e) => e.timestamp >= since);
|
|
36
|
+
}
|
|
37
|
+
if (options?.channel) {
|
|
38
|
+
entries = entries.filter((e) => e.channel === options.channel);
|
|
39
|
+
}
|
|
40
|
+
// Most recent first
|
|
41
|
+
entries.reverse();
|
|
42
|
+
if (options?.limit) {
|
|
43
|
+
entries = entries.slice(0, options.limit);
|
|
44
|
+
}
|
|
45
|
+
return entries;
|
|
46
|
+
}
|
package/dist/brand.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ChildProcess, type SpawnOptions } from "node:child_process";
|
|
2
|
+
/**
|
|
3
|
+
* Spawn a gateway command with LeedAB branding applied to all output.
|
|
4
|
+
*/
|
|
5
|
+
export declare function spawnBranded(bin: string, args: string[], options?: SpawnOptions): ChildProcess;
|
|
6
|
+
/**
|
|
7
|
+
* Run a gateway command with branded output and wait for exit.
|
|
8
|
+
*/
|
|
9
|
+
export declare function execBranded(bin: string, args: string[], options?: SpawnOptions): Promise<number>;
|
package/dist/brand.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { Transform } from "node:stream";
|
|
3
|
+
const REPLACEMENTS = [
|
|
4
|
+
[/🦞 OpenClaw \d{4}\.\d+\.\d+ \([a-f0-9]+\)/g, "LeedAB"],
|
|
5
|
+
[/🦞 OpenClaw/g, "LeedAB"],
|
|
6
|
+
[/OpenClaw/g, "LeedAB"],
|
|
7
|
+
[/openclaw/g, "leedab"],
|
|
8
|
+
[/leedab tui/g, "leedab terminal"],
|
|
9
|
+
[/🦞/g, ""],
|
|
10
|
+
];
|
|
11
|
+
// Motd quips — strip the " — <quip>" after the version line
|
|
12
|
+
const MOTD_PATTERN = /LeedAB\s*\n\s{3}.+\n/g;
|
|
13
|
+
function createBrandTransform() {
|
|
14
|
+
return new Transform({
|
|
15
|
+
transform(chunk, _encoding, callback) {
|
|
16
|
+
let text = chunk.toString();
|
|
17
|
+
// Strip the full banner block: "🦞 OpenClaw 2026.x.x (hash) — quip\n\n"
|
|
18
|
+
text = text.replace(/🦞 OpenClaw \d{4}\.\d+\.\d+ \([a-f0-9]+\)[^\n]*\n\s*[^\n]*\n\n?/g, "");
|
|
19
|
+
// Catch any remaining OpenClaw references
|
|
20
|
+
for (const [pattern, replacement] of REPLACEMENTS) {
|
|
21
|
+
text = text.replace(pattern, replacement);
|
|
22
|
+
}
|
|
23
|
+
// Collapse 3+ consecutive newlines into 2
|
|
24
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
25
|
+
// Strip leading blank lines
|
|
26
|
+
if (text.match(/^\n+$/))
|
|
27
|
+
text = "";
|
|
28
|
+
callback(null, text);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Spawn a gateway command with LeedAB branding applied to all output.
|
|
34
|
+
*/
|
|
35
|
+
export function spawnBranded(bin, args, options = {}) {
|
|
36
|
+
const child = spawn(bin, args, {
|
|
37
|
+
...options,
|
|
38
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
39
|
+
});
|
|
40
|
+
if (child.stdout) {
|
|
41
|
+
child.stdout.pipe(createBrandTransform()).pipe(process.stdout);
|
|
42
|
+
}
|
|
43
|
+
if (child.stderr) {
|
|
44
|
+
child.stderr.pipe(createBrandTransform()).pipe(process.stderr);
|
|
45
|
+
}
|
|
46
|
+
return child;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Run a gateway command with branded output and wait for exit.
|
|
50
|
+
*/
|
|
51
|
+
export function execBranded(bin, args, options = {}) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const child = spawnBranded(bin, args, options);
|
|
54
|
+
child.on("close", (code) => resolve(code ?? 1));
|
|
55
|
+
child.on("error", reject);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
/**
|
|
3
|
+
* List channel status and print a summary table.
|
|
4
|
+
*/
|
|
5
|
+
export async function setupChannels(config) {
|
|
6
|
+
const channels = [
|
|
7
|
+
{
|
|
8
|
+
name: "Telegram",
|
|
9
|
+
enabled: config.channels.telegram?.enabled ?? false,
|
|
10
|
+
status: config.channels.telegram?.enabled ? "connected" : "unconfigured",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: "WhatsApp",
|
|
14
|
+
enabled: config.channels.whatsapp?.enabled ?? false,
|
|
15
|
+
status: config.channels.whatsapp?.enabled
|
|
16
|
+
? config.channels.whatsapp?.phone
|
|
17
|
+
? "connected"
|
|
18
|
+
: "disconnected"
|
|
19
|
+
: "unconfigured",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: "Teams",
|
|
23
|
+
enabled: config.channels.teams?.enabled ?? false,
|
|
24
|
+
status: config.channels.teams?.enabled
|
|
25
|
+
? config.channels.teams?.appId
|
|
26
|
+
? "connected"
|
|
27
|
+
: "disconnected"
|
|
28
|
+
: "unconfigured",
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
console.log(chalk.bold("\nChannels:"));
|
|
32
|
+
for (const ch of channels) {
|
|
33
|
+
const icon = statusIcon(ch.status);
|
|
34
|
+
console.log(` ${icon} ${ch.name}: ${ch.status}`);
|
|
35
|
+
}
|
|
36
|
+
console.log();
|
|
37
|
+
}
|
|
38
|
+
function statusIcon(status) {
|
|
39
|
+
switch (status) {
|
|
40
|
+
case "connected":
|
|
41
|
+
return chalk.green("●");
|
|
42
|
+
case "disconnected":
|
|
43
|
+
return chalk.yellow("○");
|
|
44
|
+
default:
|
|
45
|
+
return chalk.dim("○");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type LeedABConfig } from "./schema.js";
|
|
2
|
+
export { type LeedABConfig } from "./schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* Load and validate a LeedAB config file, merging with defaults.
|
|
5
|
+
*/
|
|
6
|
+
export declare function loadConfig(configPath?: string): Promise<LeedABConfig>;
|
|
7
|
+
/**
|
|
8
|
+
* Write default config to leedab.config.json.
|
|
9
|
+
*/
|
|
10
|
+
export declare function initConfig(): Promise<void>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { readFile, writeFile, access } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { DEFAULT_CONFIG } from "./schema.js";
|
|
4
|
+
/**
|
|
5
|
+
* Load and validate a LeedAB config file, merging with defaults.
|
|
6
|
+
*/
|
|
7
|
+
export async function loadConfig(configPath = "leedab.config.json") {
|
|
8
|
+
const fullPath = resolve(configPath);
|
|
9
|
+
let userConfig = {};
|
|
10
|
+
try {
|
|
11
|
+
const raw = await readFile(fullPath, "utf-8");
|
|
12
|
+
userConfig = JSON.parse(raw);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
console.warn(`No config at ${fullPath}, using defaults.`);
|
|
16
|
+
}
|
|
17
|
+
return deepMerge(DEFAULT_CONFIG, userConfig);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Write default config to leedab.config.json.
|
|
21
|
+
*/
|
|
22
|
+
export async function initConfig() {
|
|
23
|
+
const configPath = resolve("leedab.config.json");
|
|
24
|
+
try {
|
|
25
|
+
await access(configPath);
|
|
26
|
+
throw new Error("leedab.config.json already exists");
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (err.code !== "ENOENT")
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
await writeFile(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2) + "\n");
|
|
33
|
+
}
|
|
34
|
+
function deepMerge(target, source) {
|
|
35
|
+
const result = { ...target };
|
|
36
|
+
for (const key of Object.keys(source)) {
|
|
37
|
+
if (source[key] &&
|
|
38
|
+
typeof source[key] === "object" &&
|
|
39
|
+
!Array.isArray(source[key]) &&
|
|
40
|
+
target[key] &&
|
|
41
|
+
typeof target[key] === "object") {
|
|
42
|
+
result[key] = deepMerge(target[key], source[key]);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
result[key] = source[key];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export interface WhatsAppChannelConfig {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
/** Phone number to register with Baileys */
|
|
4
|
+
phone?: string;
|
|
5
|
+
/** Groups to listen in (empty = DMs only) */
|
|
6
|
+
groups?: string[];
|
|
7
|
+
/** DM policy: "open" | "pairing" | "closed" */
|
|
8
|
+
dmPolicy?: "open" | "pairing" | "closed";
|
|
9
|
+
}
|
|
10
|
+
export interface TelegramChannelConfig {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
/** Bot token from @BotFather */
|
|
13
|
+
token?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface TeamsChannelConfig {
|
|
16
|
+
enabled: boolean;
|
|
17
|
+
/** Azure AD app ID */
|
|
18
|
+
appId?: string;
|
|
19
|
+
/** Tenant ID */
|
|
20
|
+
tenantId?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface GatewayConfig {
|
|
23
|
+
port: number;
|
|
24
|
+
host: string;
|
|
25
|
+
auth?: {
|
|
26
|
+
mode: "none" | "token" | "tailscale";
|
|
27
|
+
token?: string;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface MemoryConfig {
|
|
31
|
+
/** Path to memory directory (default: .leedab/memory) */
|
|
32
|
+
dir: string;
|
|
33
|
+
/** Enable vector search if embedding provider is set */
|
|
34
|
+
vectorSearch: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface AgentConfig {
|
|
37
|
+
/** Agent display name */
|
|
38
|
+
name: string;
|
|
39
|
+
/** Default model to use */
|
|
40
|
+
model: string;
|
|
41
|
+
/** Path to SOUL.md personality file */
|
|
42
|
+
soulPath: string;
|
|
43
|
+
/** Thinking level: "none" | "low" | "medium" | "high" */
|
|
44
|
+
thinkingLevel: "none" | "low" | "medium" | "high";
|
|
45
|
+
/** Industry vertical for pre-configured templates */
|
|
46
|
+
vertical?: "general" | "supply-chain";
|
|
47
|
+
}
|
|
48
|
+
export interface LeedABConfig {
|
|
49
|
+
agent: AgentConfig;
|
|
50
|
+
gateway: GatewayConfig;
|
|
51
|
+
memory: MemoryConfig;
|
|
52
|
+
channels: {
|
|
53
|
+
whatsapp?: WhatsAppChannelConfig;
|
|
54
|
+
telegram?: TelegramChannelConfig;
|
|
55
|
+
teams?: TeamsChannelConfig;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export declare const DEFAULT_CONFIG: LeedABConfig;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const DEFAULT_CONFIG = {
|
|
2
|
+
agent: {
|
|
3
|
+
name: "LeedAB",
|
|
4
|
+
model: "claude-sonnet-4-6",
|
|
5
|
+
soulPath: "./SOUL.md",
|
|
6
|
+
thinkingLevel: "medium",
|
|
7
|
+
},
|
|
8
|
+
gateway: {
|
|
9
|
+
port: 18789,
|
|
10
|
+
host: "127.0.0.1",
|
|
11
|
+
},
|
|
12
|
+
memory: {
|
|
13
|
+
dir: ".leedab/memory",
|
|
14
|
+
vectorSearch: false,
|
|
15
|
+
},
|
|
16
|
+
channels: {
|
|
17
|
+
whatsapp: { enabled: false },
|
|
18
|
+
telegram: { enabled: false },
|
|
19
|
+
teams: { enabled: false },
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type IncomingMessage, type ServerResponse } from "node:http";
|
|
2
|
+
import type { LeedABConfig } from "../config/schema.js";
|
|
3
|
+
type RouteHandler = (req: IncomingMessage, res: ServerResponse, url: URL) => Promise<void>;
|
|
4
|
+
export declare function createRoutes(config: LeedABConfig): Record<string, RouteHandler>;
|
|
5
|
+
export {};
|