@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 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
@@ -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
+ }>;
@@ -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>;