@ozaiya/openclaw-channel 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 +21 -0
- package/README.md +29 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/src/api.d.ts +101 -0
- package/dist/src/api.js +247 -0
- package/dist/src/api.js.map +1 -0
- package/dist/src/botActions.d.ts +25 -0
- package/dist/src/botActions.js +51 -0
- package/dist/src/botActions.js.map +1 -0
- package/dist/src/channel.d.ts +10 -0
- package/dist/src/channel.js +643 -0
- package/dist/src/channel.js.map +1 -0
- package/dist/src/crypto.d.ts +45 -0
- package/dist/src/crypto.js +132 -0
- package/dist/src/crypto.js.map +1 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.js +10 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/runtime.d.ts +6 -0
- package/dist/src/runtime.js +11 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/types.d.ts +87 -0
- package/dist/src/types.js +5 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/webhook.d.ts +14 -0
- package/dist/src/webhook.js +138 -0
- package/dist/src/webhook.js.map +1 -0
- package/package.json +73 -0
- package/types/openclaw-plugin-sdk.d.ts +109 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ozaiya
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @ozaiya/openclaw-channel
|
|
2
|
+
|
|
3
|
+
[OpenClaw](https://openclaw.ai) channel plugin for [Ozaiya](https://ozai.dev) E2E encrypted group chat.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Enables OpenClaw AI agents to participate in Ozaiya chat groups — receiving messages, processing them through the agent pipeline, and sending encrypted responses back.
|
|
8
|
+
|
|
9
|
+
All messages are end-to-end encrypted using libsodium.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Install via OpenClaw plugin manager
|
|
15
|
+
openclaw plugins install @ozaiya/openclaw-channel
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Configuration
|
|
19
|
+
|
|
20
|
+
Add the Ozaiya channel in your OpenClaw config. No additional configuration is required — the channel authenticates using your Ozaiya account credentials managed by OpenClaw.
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
- [OpenClaw](https://openclaw.ai) >= 2026.0.0
|
|
25
|
+
- An [Ozaiya](https://ozai.dev) account
|
|
26
|
+
|
|
27
|
+
## License
|
|
28
|
+
|
|
29
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw plugin entry point for the Ozaiya E2E encrypted chat channel.
|
|
3
|
+
*
|
|
4
|
+
* Registers the Ozaiya channel plugin so OpenClaw agents can participate
|
|
5
|
+
* in Ozaiya chat groups — receiving messages, processing them through the
|
|
6
|
+
* agent pipeline, and sending encrypted responses back.
|
|
7
|
+
*/
|
|
8
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
9
|
+
declare const plugin: {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
configSchema: unknown;
|
|
14
|
+
register(api: OpenClawPluginApi): void;
|
|
15
|
+
};
|
|
16
|
+
export default plugin;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
|
|
2
|
+
import { ozaiyaPlugin } from "./src/channel.js";
|
|
3
|
+
import { setOzaiyaRuntime } from "./src/runtime.js";
|
|
4
|
+
const plugin = {
|
|
5
|
+
id: "ozaiya",
|
|
6
|
+
name: "Ozaiya",
|
|
7
|
+
description: "Ozaiya E2E encrypted chat channel plugin",
|
|
8
|
+
configSchema: emptyPluginConfigSchema(),
|
|
9
|
+
register(api) {
|
|
10
|
+
setOzaiyaRuntime(api.runtime);
|
|
11
|
+
api.registerChannel({ plugin: ozaiyaPlugin });
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
export default plugin;
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,MAAM,GAAG;IACb,EAAE,EAAE,QAAQ;IACZ,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,0CAA0C;IACvD,YAAY,EAAE,uBAAuB,EAAE;IACvC,QAAQ,CAAC,GAAsB;QAC7B,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9B,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;IAChD,CAAC;CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ozaiya API client for sending messages and probing connectivity.
|
|
3
|
+
*/
|
|
4
|
+
import type { OzaiyaSendMessageResult, OzaiyaChatFileUploadResponse } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Send an encrypted message to an Ozaiya chat group.
|
|
7
|
+
*
|
|
8
|
+
* POST /v1/chat/groups/:groupId/messages
|
|
9
|
+
* Auth: Bearer <botToken>
|
|
10
|
+
*/
|
|
11
|
+
export declare function sendMessage(apiBaseUrl: string, botToken: string, groupId: string, contentBase64: string, replyToId?: string): Promise<OzaiyaSendMessageResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Fetch all groups the bot belongs to, including wrappedGroupKey.
|
|
14
|
+
*
|
|
15
|
+
* GET /v1/chat/groups → { groups: [{ id, wrappedGroupKey, ... }] }
|
|
16
|
+
*/
|
|
17
|
+
export declare function fetchGroups(apiBaseUrl: string, botToken: string): Promise<Array<{
|
|
18
|
+
id: string;
|
|
19
|
+
wrappedGroupKey: string;
|
|
20
|
+
name?: string;
|
|
21
|
+
}>>;
|
|
22
|
+
/**
|
|
23
|
+
* Create a new chat group. The caller becomes owner.
|
|
24
|
+
*
|
|
25
|
+
* POST /v1/chat/groups
|
|
26
|
+
* Auth: Bearer <botToken>
|
|
27
|
+
*/
|
|
28
|
+
export declare function createGroup(apiBaseUrl: string, botToken: string, name: string, wrappedGroupKey: string): Promise<{
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
groupCode: string;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Add a member to a group (caller must be owner/admin).
|
|
35
|
+
*
|
|
36
|
+
* POST /v1/chat/groups/:groupId/members
|
|
37
|
+
* Auth: Bearer <botToken>
|
|
38
|
+
*/
|
|
39
|
+
export declare function addMember(apiBaseUrl: string, botToken: string, groupId: string, userId: string, wrappedGroupKey: string): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Batch fetch user Curve25519 public keys (hex-encoded).
|
|
42
|
+
*
|
|
43
|
+
* POST /v1/chat/users/public-keys
|
|
44
|
+
* Auth: Bearer <botToken>
|
|
45
|
+
*/
|
|
46
|
+
export declare function getUserPublicKeys(apiBaseUrl: string, botToken: string, userIds: string[]): Promise<Array<{
|
|
47
|
+
id: string;
|
|
48
|
+
publicKey: string;
|
|
49
|
+
}>>;
|
|
50
|
+
/**
|
|
51
|
+
* Toggle an emoji reaction on a message.
|
|
52
|
+
*
|
|
53
|
+
* POST /v1/chat/messages/:messageId/reactions
|
|
54
|
+
* Auth: Bearer <botToken>
|
|
55
|
+
*/
|
|
56
|
+
export declare function toggleReaction(apiBaseUrl: string, botToken: string, messageId: string, emoji: string): Promise<{
|
|
57
|
+
added: boolean;
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Edit an encrypted message's content.
|
|
61
|
+
*
|
|
62
|
+
* PATCH /v1/chat/messages/:messageId
|
|
63
|
+
* Auth: Bearer <botToken>
|
|
64
|
+
*/
|
|
65
|
+
export declare function editMessage(apiBaseUrl: string, botToken: string, messageId: string, contentBase64: string): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Delete a message (soft-delete).
|
|
68
|
+
*
|
|
69
|
+
* DELETE /v1/chat/messages/:messageId
|
|
70
|
+
* Auth: Bearer <botToken>
|
|
71
|
+
*/
|
|
72
|
+
export declare function deleteMessage(apiBaseUrl: string, botToken: string, messageId: string): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Pin a message in a group.
|
|
75
|
+
*
|
|
76
|
+
* POST /v1/chat/messages/:messageId/pin
|
|
77
|
+
* Auth: Bearer <botToken>
|
|
78
|
+
*/
|
|
79
|
+
export declare function pinMessage(apiBaseUrl: string, botToken: string, messageId: string): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Unpin a message in a group.
|
|
82
|
+
*
|
|
83
|
+
* DELETE /v1/chat/messages/:messageId/pin
|
|
84
|
+
* Auth: Bearer <botToken>
|
|
85
|
+
*/
|
|
86
|
+
export declare function unpinMessage(apiBaseUrl: string, botToken: string, messageId: string): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Upload a file to an Ozaiya chat group (multipart).
|
|
89
|
+
*
|
|
90
|
+
* POST /v1/chat/groups/:groupId/upload
|
|
91
|
+
* Auth: Bearer <botToken>
|
|
92
|
+
*/
|
|
93
|
+
export declare function uploadFile(apiBaseUrl: string, botToken: string, groupId: string, filename: string, mime: string, buffer: Buffer): Promise<OzaiyaChatFileUploadResponse>;
|
|
94
|
+
/**
|
|
95
|
+
* Probe Ozaiya API connectivity by listing bot accounts.
|
|
96
|
+
* Returns true if the API is reachable and the token is valid.
|
|
97
|
+
*/
|
|
98
|
+
export declare function probeApi(apiBaseUrl: string, botToken: string, timeoutMs?: number): Promise<{
|
|
99
|
+
ok: boolean;
|
|
100
|
+
error?: string;
|
|
101
|
+
}>;
|
package/dist/src/api.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Send an encrypted message to an Ozaiya chat group.
|
|
3
|
+
*
|
|
4
|
+
* POST /v1/chat/groups/:groupId/messages
|
|
5
|
+
* Auth: Bearer <botToken>
|
|
6
|
+
*/
|
|
7
|
+
export async function sendMessage(apiBaseUrl, botToken, groupId, contentBase64, replyToId) {
|
|
8
|
+
const body = { content: contentBase64 };
|
|
9
|
+
if (replyToId) {
|
|
10
|
+
body.replyToId = replyToId;
|
|
11
|
+
}
|
|
12
|
+
const res = await fetch(`${apiBaseUrl}/v1/chat/groups/${groupId}/messages`, {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
Authorization: `Bearer ${botToken}`,
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify(body),
|
|
19
|
+
signal: AbortSignal.timeout(15_000),
|
|
20
|
+
});
|
|
21
|
+
if (!res.ok) {
|
|
22
|
+
const text = await res.text().catch(() => "");
|
|
23
|
+
throw new Error(`Ozaiya API error ${res.status}: ${text}`);
|
|
24
|
+
}
|
|
25
|
+
return (await res.json());
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Fetch all groups the bot belongs to, including wrappedGroupKey.
|
|
29
|
+
*
|
|
30
|
+
* GET /v1/chat/groups → { groups: [{ id, wrappedGroupKey, ... }] }
|
|
31
|
+
*/
|
|
32
|
+
export async function fetchGroups(apiBaseUrl, botToken) {
|
|
33
|
+
const res = await fetch(`${apiBaseUrl}/v1/chat/groups`, {
|
|
34
|
+
method: "GET",
|
|
35
|
+
headers: { Authorization: `Bearer ${botToken}` },
|
|
36
|
+
signal: AbortSignal.timeout(15_000),
|
|
37
|
+
});
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
const text = await res.text().catch(() => "");
|
|
40
|
+
throw new Error(`Ozaiya API error ${res.status}: ${text}`);
|
|
41
|
+
}
|
|
42
|
+
const data = (await res.json());
|
|
43
|
+
return data.groups;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create a new chat group. The caller becomes owner.
|
|
47
|
+
*
|
|
48
|
+
* POST /v1/chat/groups
|
|
49
|
+
* Auth: Bearer <botToken>
|
|
50
|
+
*/
|
|
51
|
+
export async function createGroup(apiBaseUrl, botToken, name, wrappedGroupKey) {
|
|
52
|
+
const res = await fetch(`${apiBaseUrl}/v1/chat/groups`, {
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: {
|
|
55
|
+
"Content-Type": "application/json",
|
|
56
|
+
Authorization: `Bearer ${botToken}`,
|
|
57
|
+
},
|
|
58
|
+
body: JSON.stringify({ name, wrappedGroupKey }),
|
|
59
|
+
signal: AbortSignal.timeout(15_000),
|
|
60
|
+
});
|
|
61
|
+
if (!res.ok) {
|
|
62
|
+
const text = await res.text().catch(() => "");
|
|
63
|
+
throw new Error(`Ozaiya API error ${res.status}: ${text}`);
|
|
64
|
+
}
|
|
65
|
+
const data = (await res.json());
|
|
66
|
+
return data.group;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Add a member to a group (caller must be owner/admin).
|
|
70
|
+
*
|
|
71
|
+
* POST /v1/chat/groups/:groupId/members
|
|
72
|
+
* Auth: Bearer <botToken>
|
|
73
|
+
*/
|
|
74
|
+
export async function addMember(apiBaseUrl, botToken, groupId, userId, wrappedGroupKey) {
|
|
75
|
+
const res = await fetch(`${apiBaseUrl}/v1/chat/groups/${groupId}/members`, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers: {
|
|
78
|
+
"Content-Type": "application/json",
|
|
79
|
+
Authorization: `Bearer ${botToken}`,
|
|
80
|
+
},
|
|
81
|
+
body: JSON.stringify({ userId, wrappedGroupKey }),
|
|
82
|
+
signal: AbortSignal.timeout(15_000),
|
|
83
|
+
});
|
|
84
|
+
if (!res.ok) {
|
|
85
|
+
const text = await res.text().catch(() => "");
|
|
86
|
+
throw new Error(`Ozaiya API error ${res.status}: ${text}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Batch fetch user Curve25519 public keys (hex-encoded).
|
|
91
|
+
*
|
|
92
|
+
* POST /v1/chat/users/public-keys
|
|
93
|
+
* Auth: Bearer <botToken>
|
|
94
|
+
*/
|
|
95
|
+
export async function getUserPublicKeys(apiBaseUrl, botToken, userIds) {
|
|
96
|
+
const res = await fetch(`${apiBaseUrl}/v1/chat/users/public-keys`, {
|
|
97
|
+
method: "POST",
|
|
98
|
+
headers: {
|
|
99
|
+
"Content-Type": "application/json",
|
|
100
|
+
Authorization: `Bearer ${botToken}`,
|
|
101
|
+
},
|
|
102
|
+
body: JSON.stringify({ userIds }),
|
|
103
|
+
signal: AbortSignal.timeout(15_000),
|
|
104
|
+
});
|
|
105
|
+
if (!res.ok) {
|
|
106
|
+
const text = await res.text().catch(() => "");
|
|
107
|
+
throw new Error(`Ozaiya API error ${res.status}: ${text}`);
|
|
108
|
+
}
|
|
109
|
+
const data = (await res.json());
|
|
110
|
+
return data.users;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Toggle an emoji reaction on a message.
|
|
114
|
+
*
|
|
115
|
+
* POST /v1/chat/messages/:messageId/reactions
|
|
116
|
+
* Auth: Bearer <botToken>
|
|
117
|
+
*/
|
|
118
|
+
export async function toggleReaction(apiBaseUrl, botToken, messageId, emoji) {
|
|
119
|
+
const res = await fetch(`${apiBaseUrl}/v1/chat/messages/${messageId}/reactions`, {
|
|
120
|
+
method: "POST",
|
|
121
|
+
headers: {
|
|
122
|
+
"Content-Type": "application/json",
|
|
123
|
+
Authorization: `Bearer ${botToken}`,
|
|
124
|
+
},
|
|
125
|
+
body: JSON.stringify({ emoji }),
|
|
126
|
+
signal: AbortSignal.timeout(15_000),
|
|
127
|
+
});
|
|
128
|
+
if (!res.ok) {
|
|
129
|
+
const text = await res.text().catch(() => "");
|
|
130
|
+
throw new Error(`Ozaiya API error ${res.status}: ${text}`);
|
|
131
|
+
}
|
|
132
|
+
return (await res.json());
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Edit an encrypted message's content.
|
|
136
|
+
*
|
|
137
|
+
* PATCH /v1/chat/messages/:messageId
|
|
138
|
+
* Auth: Bearer <botToken>
|
|
139
|
+
*/
|
|
140
|
+
export async function editMessage(apiBaseUrl, botToken, messageId, contentBase64) {
|
|
141
|
+
const res = await fetch(`${apiBaseUrl}/v1/chat/messages/${messageId}`, {
|
|
142
|
+
method: "PATCH",
|
|
143
|
+
headers: {
|
|
144
|
+
"Content-Type": "application/json",
|
|
145
|
+
Authorization: `Bearer ${botToken}`,
|
|
146
|
+
},
|
|
147
|
+
body: JSON.stringify({ content: contentBase64 }),
|
|
148
|
+
signal: AbortSignal.timeout(15_000),
|
|
149
|
+
});
|
|
150
|
+
if (!res.ok) {
|
|
151
|
+
const text = await res.text().catch(() => "");
|
|
152
|
+
throw new Error(`Ozaiya API error ${res.status}: ${text}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Delete a message (soft-delete).
|
|
157
|
+
*
|
|
158
|
+
* DELETE /v1/chat/messages/:messageId
|
|
159
|
+
* Auth: Bearer <botToken>
|
|
160
|
+
*/
|
|
161
|
+
export async function deleteMessage(apiBaseUrl, botToken, messageId) {
|
|
162
|
+
const res = await fetch(`${apiBaseUrl}/v1/chat/messages/${messageId}`, {
|
|
163
|
+
method: "DELETE",
|
|
164
|
+
headers: { Authorization: `Bearer ${botToken}` },
|
|
165
|
+
signal: AbortSignal.timeout(15_000),
|
|
166
|
+
});
|
|
167
|
+
if (!res.ok) {
|
|
168
|
+
const text = await res.text().catch(() => "");
|
|
169
|
+
throw new Error(`Ozaiya API error ${res.status}: ${text}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Pin a message in a group.
|
|
174
|
+
*
|
|
175
|
+
* POST /v1/chat/messages/:messageId/pin
|
|
176
|
+
* Auth: Bearer <botToken>
|
|
177
|
+
*/
|
|
178
|
+
export async function pinMessage(apiBaseUrl, botToken, messageId) {
|
|
179
|
+
const res = await fetch(`${apiBaseUrl}/v1/chat/messages/${messageId}/pin`, {
|
|
180
|
+
method: "POST",
|
|
181
|
+
headers: { Authorization: `Bearer ${botToken}` },
|
|
182
|
+
signal: AbortSignal.timeout(15_000),
|
|
183
|
+
});
|
|
184
|
+
if (!res.ok) {
|
|
185
|
+
const text = await res.text().catch(() => "");
|
|
186
|
+
throw new Error(`Ozaiya API error ${res.status}: ${text}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Unpin a message in a group.
|
|
191
|
+
*
|
|
192
|
+
* DELETE /v1/chat/messages/:messageId/pin
|
|
193
|
+
* Auth: Bearer <botToken>
|
|
194
|
+
*/
|
|
195
|
+
export async function unpinMessage(apiBaseUrl, botToken, messageId) {
|
|
196
|
+
const res = await fetch(`${apiBaseUrl}/v1/chat/messages/${messageId}/pin`, {
|
|
197
|
+
method: "DELETE",
|
|
198
|
+
headers: { Authorization: `Bearer ${botToken}` },
|
|
199
|
+
signal: AbortSignal.timeout(15_000),
|
|
200
|
+
});
|
|
201
|
+
if (!res.ok) {
|
|
202
|
+
const text = await res.text().catch(() => "");
|
|
203
|
+
throw new Error(`Ozaiya API error ${res.status}: ${text}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Upload a file to an Ozaiya chat group (multipart).
|
|
208
|
+
*
|
|
209
|
+
* POST /v1/chat/groups/:groupId/upload
|
|
210
|
+
* Auth: Bearer <botToken>
|
|
211
|
+
*/
|
|
212
|
+
export async function uploadFile(apiBaseUrl, botToken, groupId, filename, mime, buffer) {
|
|
213
|
+
const formData = new FormData();
|
|
214
|
+
formData.append("file", new Blob([new Uint8Array(buffer)], { type: mime }), filename);
|
|
215
|
+
const res = await fetch(`${apiBaseUrl}/v1/chat/groups/${groupId}/upload`, {
|
|
216
|
+
method: "POST",
|
|
217
|
+
headers: { Authorization: `Bearer ${botToken}` },
|
|
218
|
+
body: formData,
|
|
219
|
+
signal: AbortSignal.timeout(60_000),
|
|
220
|
+
});
|
|
221
|
+
if (!res.ok) {
|
|
222
|
+
const text = await res.text().catch(() => "");
|
|
223
|
+
throw new Error(`Ozaiya API error ${res.status}: ${text}`);
|
|
224
|
+
}
|
|
225
|
+
return (await res.json());
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Probe Ozaiya API connectivity by listing bot accounts.
|
|
229
|
+
* Returns true if the API is reachable and the token is valid.
|
|
230
|
+
*/
|
|
231
|
+
export async function probeApi(apiBaseUrl, botToken, timeoutMs = 5000) {
|
|
232
|
+
try {
|
|
233
|
+
const res = await fetch(`${apiBaseUrl}/v1/bots`, {
|
|
234
|
+
method: "GET",
|
|
235
|
+
headers: { Authorization: `Bearer ${botToken}` },
|
|
236
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
237
|
+
});
|
|
238
|
+
if (res.ok) {
|
|
239
|
+
return { ok: true };
|
|
240
|
+
}
|
|
241
|
+
return { ok: false, error: `HTTP ${res.status}` };
|
|
242
|
+
}
|
|
243
|
+
catch (err) {
|
|
244
|
+
return { ok: false, error: String(err) };
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
interface BotConfig {
|
|
2
|
+
apiBaseUrl: string;
|
|
3
|
+
botToken: string;
|
|
4
|
+
botPrivateKey: string;
|
|
5
|
+
}
|
|
6
|
+
interface BotCreateGroupResult {
|
|
7
|
+
groupId: string;
|
|
8
|
+
groupCode: string;
|
|
9
|
+
groupKey: Uint8Array;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create a group and optionally invite members.
|
|
13
|
+
* Handles all crypto (key generation, wrapping) internally.
|
|
14
|
+
*
|
|
15
|
+
* Flow:
|
|
16
|
+
* 1. Generate a random 32-byte AES group key
|
|
17
|
+
* 2. Derive bot's Curve25519 public key from seed
|
|
18
|
+
* 3. Wrap the group key for the bot (creator/owner)
|
|
19
|
+
* 4. Call createGroup API
|
|
20
|
+
* 5. If memberUserIds provided: fetch their public keys, wrap for each, and add them
|
|
21
|
+
*
|
|
22
|
+
* @returns The created group info and the raw group key (for message encryption)
|
|
23
|
+
*/
|
|
24
|
+
export declare function botCreateGroup(config: BotConfig, name: string, memberUserIds?: string[]): Promise<BotCreateGroupResult>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level convenience functions for bot operations.
|
|
3
|
+
*
|
|
4
|
+
* Combines crypto and API calls so consumers can create groups
|
|
5
|
+
* and invite members with a single function call.
|
|
6
|
+
*/
|
|
7
|
+
import _sodium from "libsodium-wrappers";
|
|
8
|
+
import { generateGroupKey, wrapGroupKey } from "./crypto.js";
|
|
9
|
+
import { createGroup, addMember, getUserPublicKeys } from "./api.js";
|
|
10
|
+
/**
|
|
11
|
+
* Create a group and optionally invite members.
|
|
12
|
+
* Handles all crypto (key generation, wrapping) internally.
|
|
13
|
+
*
|
|
14
|
+
* Flow:
|
|
15
|
+
* 1. Generate a random 32-byte AES group key
|
|
16
|
+
* 2. Derive bot's Curve25519 public key from seed
|
|
17
|
+
* 3. Wrap the group key for the bot (creator/owner)
|
|
18
|
+
* 4. Call createGroup API
|
|
19
|
+
* 5. If memberUserIds provided: fetch their public keys, wrap for each, and add them
|
|
20
|
+
*
|
|
21
|
+
* @returns The created group info and the raw group key (for message encryption)
|
|
22
|
+
*/
|
|
23
|
+
export async function botCreateGroup(config, name, memberUserIds) {
|
|
24
|
+
await _sodium.ready;
|
|
25
|
+
const sodium = _sodium;
|
|
26
|
+
// 1. Generate group key
|
|
27
|
+
const groupKey = await generateGroupKey();
|
|
28
|
+
// 2. Derive bot public key from seed
|
|
29
|
+
const seed = sodium.from_base64(config.botPrivateKey, sodium.base64_variants.ORIGINAL);
|
|
30
|
+
const botKeypair = sodium.crypto_box_seed_keypair(seed);
|
|
31
|
+
const botPublicKeyHex = sodium.to_hex(botKeypair.publicKey);
|
|
32
|
+
// 3. Wrap for bot (creator)
|
|
33
|
+
const botWrappedKey = await wrapGroupKey(groupKey, botPublicKeyHex);
|
|
34
|
+
// 4. Create group
|
|
35
|
+
const group = await createGroup(config.apiBaseUrl, config.botToken, name, botWrappedKey);
|
|
36
|
+
// 5. Invite members (wrap sequentially for crypto, then add in parallel)
|
|
37
|
+
if (memberUserIds && memberUserIds.length > 0) {
|
|
38
|
+
const users = await getUserPublicKeys(config.apiBaseUrl, config.botToken, memberUserIds);
|
|
39
|
+
const wrapped = await Promise.all(users.map(async (user) => ({
|
|
40
|
+
userId: user.id,
|
|
41
|
+
wrappedKey: await wrapGroupKey(groupKey, user.publicKey),
|
|
42
|
+
})));
|
|
43
|
+
await Promise.all(wrapped.map((w) => addMember(config.apiBaseUrl, config.botToken, group.id, w.userId, w.wrappedKey)));
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
groupId: group.id,
|
|
47
|
+
groupCode: group.groupCode,
|
|
48
|
+
groupKey,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=botActions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"botActions.js","sourceRoot":"","sources":["../../src/botActions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,OAAO,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAcrE;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAiB,EACjB,IAAY,EACZ,aAAwB;IAExB,MAAM,OAAO,CAAC,KAAK,CAAC;IACpB,MAAM,MAAM,GAAG,OAAO,CAAC;IAEvB,wBAAwB;IACxB,MAAM,QAAQ,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAE1C,qCAAqC;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvF,MAAM,UAAU,GAAG,MAAM,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAE5D,4BAA4B;IAC5B,MAAM,aAAa,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IAEpE,kBAAkB;IAClB,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;IAEzF,yEAAyE;IACzE,IAAI,aAAa,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACzF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;YACzB,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,UAAU,EAAE,MAAM,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC;SACzD,CAAC,CAAC,CACJ,CAAC;QACF,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAChB,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAChF,CACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,EAAE;QACjB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,QAAQ;KACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ozaiya ChannelPlugin implementation for OpenClaw.
|
|
3
|
+
*
|
|
4
|
+
* Enables OpenClaw AI agents to participate in Ozaiya E2E encrypted chat groups.
|
|
5
|
+
* Messages arrive via webhook, are decrypted, processed by the agent, and responses
|
|
6
|
+
* are encrypted and sent back via the Ozaiya API.
|
|
7
|
+
*/
|
|
8
|
+
import type { ChannelPlugin } from "openclaw/plugin-sdk";
|
|
9
|
+
import type { ResolvedOzaiyaAccount } from "./types.js";
|
|
10
|
+
export declare const ozaiyaPlugin: ChannelPlugin<ResolvedOzaiyaAccount>;
|