@eclaw/openclaw-channel 1.0.18 → 1.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/README.md +58 -155
- package/dist/channel.d.ts +0 -19
- package/dist/channel.js +2 -4
- package/dist/client.d.ts +5 -10
- package/dist/client.js +14 -57
- package/dist/config.js +4 -16
- package/dist/gateway.d.ts +6 -5
- package/dist/gateway.js +165 -89
- package/dist/index.d.ts +21 -0
- package/dist/index.js +6 -35
- package/dist/outbound.d.ts +0 -2
- package/dist/outbound.js +0 -18
- package/dist/types.d.ts +2 -19
- package/dist/webhook-handler.d.ts +3 -14
- package/dist/webhook-handler.js +29 -111
- package/openclaw.plugin.json +27 -27
- package/package.json +60 -60
- package/dist/onboarding.d.ts +0 -19
- package/dist/onboarding.js +0 -77
- package/dist/webhook-registry.d.ts +0 -19
- package/dist/webhook-registry.js +0 -39
package/openclaw.plugin.json
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "
|
|
3
|
-
"name": "E-Claw",
|
|
4
|
-
"version": "1.0.0",
|
|
5
|
-
"description": "E-Claw AI
|
|
6
|
-
"channels": ["eclaw"],
|
|
7
|
-
"configSchema": {
|
|
8
|
-
"type": "object",
|
|
9
|
-
"properties": {
|
|
10
|
-
"accounts": {
|
|
11
|
-
"type": "object",
|
|
12
|
-
"additionalProperties": {
|
|
13
|
-
"type": "object",
|
|
14
|
-
"properties": {
|
|
15
|
-
"enabled": { "type": "boolean", "default": true },
|
|
16
|
-
"apiKey": { "type": "string", "description": "Channel API Key (eck_...)" },
|
|
17
|
-
"apiSecret": { "type": "string", "description": "Channel API Secret (ecs_...)" },
|
|
18
|
-
"apiBase": { "type": "string", "default": "https://eclawbot.com" },
|
|
19
|
-
"entityId": { "type": "number", "
|
|
20
|
-
"botName": { "type": "string", "maxLength": 20 }
|
|
21
|
-
},
|
|
22
|
-
"required": ["apiKey", "apiSecret"]
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "eclaw",
|
|
3
|
+
"name": "E-Claw",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "E-Claw AI Agent collaboration channel for OpenClaw",
|
|
6
|
+
"channels": ["eclaw"],
|
|
7
|
+
"configSchema": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"properties": {
|
|
10
|
+
"accounts": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"additionalProperties": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"properties": {
|
|
15
|
+
"enabled": { "type": "boolean", "default": true },
|
|
16
|
+
"apiKey": { "type": "string", "description": "Channel API Key (eck_...)" },
|
|
17
|
+
"apiSecret": { "type": "string", "description": "Channel API Secret (ecs_...)" },
|
|
18
|
+
"apiBase": { "type": "string", "default": "https://eclawbot.com" },
|
|
19
|
+
"entityId": { "type": "number", "default": 0, "minimum": 0, "maximum": 7 },
|
|
20
|
+
"botName": { "type": "string", "maxLength": 20 }
|
|
21
|
+
},
|
|
22
|
+
"required": ["apiKey", "apiSecret"]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
package/package.json
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@eclaw/openclaw-channel",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "E-Claw channel plugin for OpenClaw — AI
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"import": "./dist/index.js",
|
|
11
|
-
"types": "./dist/index.d.ts"
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
"files": [
|
|
15
|
-
"dist/",
|
|
16
|
-
"openclaw.plugin.json",
|
|
17
|
-
"README.md"
|
|
18
|
-
],
|
|
19
|
-
"scripts": {
|
|
20
|
-
"build": "tsc",
|
|
21
|
-
"dev": "tsc --watch",
|
|
22
|
-
"test": "vitest run",
|
|
23
|
-
"lint": "tsc --noEmit",
|
|
24
|
-
"prepublishOnly": "npm run build"
|
|
25
|
-
},
|
|
26
|
-
"openclaw": {
|
|
27
|
-
"extensions": [
|
|
28
|
-
"./dist/index.js"
|
|
29
|
-
],
|
|
30
|
-
"channel": {
|
|
31
|
-
"id": "eclaw",
|
|
32
|
-
"label": "E-Claw",
|
|
33
|
-
"selectionLabel": "E-Claw (AI
|
|
34
|
-
"docsPath": "https://github.com/HankHuang0516/openclaw-channel-eclaw#readme",
|
|
35
|
-
"description": "Connect OpenClaw to E-Claw —
|
|
36
|
-
},
|
|
37
|
-
"install": {
|
|
38
|
-
"npmSpec": "@eclaw/openclaw-channel"
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
"keywords": [
|
|
42
|
-
"openclaw",
|
|
43
|
-
"openclaw-channel",
|
|
44
|
-
"channel",
|
|
45
|
-
"eclaw",
|
|
46
|
-
"ai-agent",
|
|
47
|
-
"live-wallpaper"
|
|
48
|
-
],
|
|
49
|
-
"author": "HankHuang",
|
|
50
|
-
"license": "MIT",
|
|
51
|
-
"repository": {
|
|
52
|
-
"type": "git",
|
|
53
|
-
"url": "https://github.com/HankHuang0516/openclaw-channel-eclaw"
|
|
54
|
-
},
|
|
55
|
-
"devDependencies": {
|
|
56
|
-
"typescript": "^5.4",
|
|
57
|
-
"vitest": "^2.0",
|
|
58
|
-
"@types/node": "^20"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@eclaw/openclaw-channel",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "E-Claw channel plugin for OpenClaw — AI Agent collaboration and A2A communication platform",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/",
|
|
16
|
+
"openclaw.plugin.json",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"dev": "tsc --watch",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"lint": "tsc --noEmit",
|
|
24
|
+
"prepublishOnly": "npm run build"
|
|
25
|
+
},
|
|
26
|
+
"openclaw": {
|
|
27
|
+
"extensions": [
|
|
28
|
+
"./dist/index.js"
|
|
29
|
+
],
|
|
30
|
+
"channel": {
|
|
31
|
+
"id": "eclaw",
|
|
32
|
+
"label": "E-Claw",
|
|
33
|
+
"selectionLabel": "E-Claw (AI Agent Collaboration)",
|
|
34
|
+
"docsPath": "https://github.com/HankHuang0516/openclaw-channel-eclaw#readme",
|
|
35
|
+
"description": "Connect OpenClaw to E-Claw — the AI Agent collaboration and A2A communication platform for Android."
|
|
36
|
+
},
|
|
37
|
+
"install": {
|
|
38
|
+
"npmSpec": "@eclaw/openclaw-channel"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"openclaw",
|
|
43
|
+
"openclaw-channel",
|
|
44
|
+
"channel",
|
|
45
|
+
"eclaw",
|
|
46
|
+
"ai-agent",
|
|
47
|
+
"live-wallpaper"
|
|
48
|
+
],
|
|
49
|
+
"author": "HankHuang",
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "git+https://github.com/HankHuang0516/openclaw-channel-eclaw.git"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"typescript": "^5.4",
|
|
57
|
+
"vitest": "^2.0",
|
|
58
|
+
"@types/node": "^20"
|
|
59
|
+
}
|
|
60
|
+
}
|
package/dist/onboarding.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export declare const eclawOnboardingAdapter: {
|
|
2
|
-
channel: string;
|
|
3
|
-
getStatus: ({ cfg }: {
|
|
4
|
-
cfg: any;
|
|
5
|
-
}) => Promise<{
|
|
6
|
-
channel: string;
|
|
7
|
-
configured: boolean;
|
|
8
|
-
statusLines: string[];
|
|
9
|
-
selectionHint: string;
|
|
10
|
-
quickstartScore: number;
|
|
11
|
-
}>;
|
|
12
|
-
configure: ({ cfg, prompter }: {
|
|
13
|
-
cfg: any;
|
|
14
|
-
prompter: any;
|
|
15
|
-
}) => Promise<{
|
|
16
|
-
cfg: any;
|
|
17
|
-
accountId: string;
|
|
18
|
-
}>;
|
|
19
|
-
};
|
package/dist/onboarding.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { listAccountIds, resolveAccount } from './config.js';
|
|
2
|
-
const DEFAULT_ACCOUNT_ID = 'default';
|
|
3
|
-
export const eclawOnboardingAdapter = {
|
|
4
|
-
channel: 'eclaw',
|
|
5
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
|
-
getStatus: async ({ cfg }) => {
|
|
7
|
-
const ids = listAccountIds(cfg);
|
|
8
|
-
const configured = ids.some((id) => {
|
|
9
|
-
const acc = resolveAccount(cfg, id);
|
|
10
|
-
return Boolean(acc.apiKey);
|
|
11
|
-
});
|
|
12
|
-
return {
|
|
13
|
-
channel: 'eclaw',
|
|
14
|
-
configured,
|
|
15
|
-
statusLines: [`E-Claw: ${configured ? 'configured' : 'not configured'}`],
|
|
16
|
-
selectionHint: configured ? 'configured' : 'E-Claw (AI Live Wallpaper Chat)',
|
|
17
|
-
quickstartScore: configured ? 1 : 3,
|
|
18
|
-
};
|
|
19
|
-
},
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
-
configure: async ({ cfg, prompter }) => {
|
|
22
|
-
const accountId = DEFAULT_ACCOUNT_ID;
|
|
23
|
-
const resolved = resolveAccount(cfg, accountId);
|
|
24
|
-
await prompter.note([
|
|
25
|
-
'1. Log in to https://eclawbot.com',
|
|
26
|
-
'2. Go to Portal → Settings → Channel API',
|
|
27
|
-
'3. Create an API Key',
|
|
28
|
-
'4. Enter the credentials below',
|
|
29
|
-
].join('\n'), 'E-Claw Setup');
|
|
30
|
-
const apiKey = await prompter.text({
|
|
31
|
-
message: 'Channel API Key',
|
|
32
|
-
placeholder: 'eck_...',
|
|
33
|
-
initialValue: resolved.apiKey || '',
|
|
34
|
-
validate: (v) => (String(v ?? '').trim() ? undefined : 'Required'),
|
|
35
|
-
});
|
|
36
|
-
const entityIdStr = await prompter.text({
|
|
37
|
-
message: 'Entity ID (0–3)',
|
|
38
|
-
placeholder: '0',
|
|
39
|
-
initialValue: String(resolved.entityId ?? 0),
|
|
40
|
-
validate: (v) => {
|
|
41
|
-
const n = Number(v);
|
|
42
|
-
return Number.isInteger(n) && n >= 0 && n <= 3 ? undefined : 'Must be 0–3';
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
const botName = await prompter.text({
|
|
46
|
-
message: 'Bot display name (optional)',
|
|
47
|
-
placeholder: 'My Bot',
|
|
48
|
-
initialValue: resolved.botName ?? '',
|
|
49
|
-
});
|
|
50
|
-
const webhookUrl = await prompter.text({
|
|
51
|
-
message: 'Webhook URL (your OpenClaw public URL, e.g. https://openclaw.example.com)',
|
|
52
|
-
placeholder: 'https://your-openclaw-domain.com',
|
|
53
|
-
initialValue: resolved.webhookUrl ?? '',
|
|
54
|
-
});
|
|
55
|
-
const nextCfg = {
|
|
56
|
-
...cfg,
|
|
57
|
-
channels: {
|
|
58
|
-
...(cfg.channels ?? {}),
|
|
59
|
-
eclaw: {
|
|
60
|
-
...(cfg.channels?.eclaw ?? {}),
|
|
61
|
-
accounts: {
|
|
62
|
-
...(cfg.channels?.eclaw?.accounts ?? {}), // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
63
|
-
[accountId]: {
|
|
64
|
-
apiKey: String(apiKey).trim(),
|
|
65
|
-
apiBase: resolved.apiBase || 'https://eclawbot.com',
|
|
66
|
-
entityId: Number(entityIdStr),
|
|
67
|
-
botName: String(botName).trim() || undefined,
|
|
68
|
-
webhookUrl: String(webhookUrl).trim() || undefined,
|
|
69
|
-
enabled: true,
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
return { cfg: nextCfg, accountId };
|
|
76
|
-
},
|
|
77
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-session webhook token registry.
|
|
3
|
-
*
|
|
4
|
-
* Each account generates a random callbackToken when it starts.
|
|
5
|
-
* The token is sent to E-Claw as part of the callback URL registration,
|
|
6
|
-
* and E-Claw echoes it back as `Authorization: Bearer <token>` on every push.
|
|
7
|
-
*
|
|
8
|
-
* The main route handler (registered on the gateway HTTP server) looks up
|
|
9
|
-
* the correct per-account handler by matching the Bearer token.
|
|
10
|
-
*/
|
|
11
|
-
type WebhookHandler = (req: any, res: any) => Promise<void>;
|
|
12
|
-
export declare function registerWebhookToken(callbackToken: string, accountId: string, handler: WebhookHandler): void;
|
|
13
|
-
export declare function unregisterWebhookToken(callbackToken: string): void;
|
|
14
|
-
/**
|
|
15
|
-
* Dispatch an incoming webhook request to the correct account handler.
|
|
16
|
-
* Verifies the Bearer token and routes to the matching handler.
|
|
17
|
-
*/
|
|
18
|
-
export declare function dispatchWebhook(req: any, res: any): Promise<void>;
|
|
19
|
-
export {};
|
package/dist/webhook-registry.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-session webhook token registry.
|
|
3
|
-
*
|
|
4
|
-
* Each account generates a random callbackToken when it starts.
|
|
5
|
-
* The token is sent to E-Claw as part of the callback URL registration,
|
|
6
|
-
* and E-Claw echoes it back as `Authorization: Bearer <token>` on every push.
|
|
7
|
-
*
|
|
8
|
-
* The main route handler (registered on the gateway HTTP server) looks up
|
|
9
|
-
* the correct per-account handler by matching the Bearer token.
|
|
10
|
-
*/
|
|
11
|
-
const registry = new Map();
|
|
12
|
-
export function registerWebhookToken(callbackToken, accountId, handler) {
|
|
13
|
-
registry.set(callbackToken, { accountId, handler });
|
|
14
|
-
}
|
|
15
|
-
export function unregisterWebhookToken(callbackToken) {
|
|
16
|
-
registry.delete(callbackToken);
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Dispatch an incoming webhook request to the correct account handler.
|
|
20
|
-
* Verifies the Bearer token and routes to the matching handler.
|
|
21
|
-
*/
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
-
export async function dispatchWebhook(req, res) {
|
|
24
|
-
const authHeader = req.headers?.authorization;
|
|
25
|
-
if (!authHeader?.startsWith('Bearer ')) {
|
|
26
|
-
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
27
|
-
res.end(JSON.stringify({ error: 'Unauthorized' }));
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const token = authHeader.slice(7);
|
|
31
|
-
const entry = registry.get(token);
|
|
32
|
-
if (!entry) {
|
|
33
|
-
// Unknown token — likely a stale push after a server restart
|
|
34
|
-
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
35
|
-
res.end(JSON.stringify({ error: 'Unknown token' }));
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
await entry.handler(req, res);
|
|
39
|
-
}
|