aicq-chat-plugin 3.3.1 → 3.4.1
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 +14 -9
- package/SKILL.md +17 -13
- package/{cli.js → cli.cjs} +19 -34
- package/index.js +191 -257
- package/lib/package.json +3 -0
- package/openclaw.plugin.json +2 -2
- package/package.json +17 -12
- package/{postinstall.js → postinstall.cjs} +5 -4
- package/setup-entry.js +8 -55
- package/src/channel.js +218 -136
- package/src/ui-routes.js +545 -420
- package/index.mjs +0 -70
- package/setup-entry.mjs +0 -9
- package/src/channel.mjs +0 -254
- package/src/gateway-handlers.mjs +0 -178
package/index.mjs
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AICQ Chat Plugin — Channel Plugin Entry Point (ESM)
|
|
3
|
-
*
|
|
4
|
-
* Uses OpenClaw Channel Plugin SDK:
|
|
5
|
-
* - defineChannelPluginEntry from openclaw/plugin-sdk/channel-core
|
|
6
|
-
* - createChatChannelPlugin from openclaw/plugin-sdk/channel-core
|
|
7
|
-
*
|
|
8
|
-
* Architecture: In-process Channel (no sidecar, no independent port)
|
|
9
|
-
*/
|
|
10
|
-
import { defineChannelPluginEntry } from 'openclaw/plugin-sdk/channel-core';
|
|
11
|
-
import { aicqChatPlugin } from './src/channel.mjs';
|
|
12
|
-
|
|
13
|
-
export default defineChannelPluginEntry({
|
|
14
|
-
id: 'aicq-chat',
|
|
15
|
-
name: 'AICQ Encrypted Chat',
|
|
16
|
-
description: 'End-to-end encrypted chat channel via AICQ protocol — in-process Channel plugin',
|
|
17
|
-
plugin: aicqChatPlugin,
|
|
18
|
-
|
|
19
|
-
registerCliMetadata(api) {
|
|
20
|
-
api.registerCli(
|
|
21
|
-
({ program }) => {
|
|
22
|
-
program
|
|
23
|
-
.command('aicq-chat')
|
|
24
|
-
.description('AICQ Encrypted Chat management');
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
descriptors: [
|
|
28
|
-
{
|
|
29
|
-
name: 'aicq-chat',
|
|
30
|
-
description: 'AICQ Encrypted Chat management',
|
|
31
|
-
hasSubcommands: false,
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
},
|
|
35
|
-
);
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
registerFull(api) {
|
|
39
|
-
// Register gateway HTTP routes for the SPA UI
|
|
40
|
-
const gatewayMethods = [
|
|
41
|
-
'aicq.status',
|
|
42
|
-
'aicq.friends.list',
|
|
43
|
-
'aicq.friends.add',
|
|
44
|
-
'aicq.friends.remove',
|
|
45
|
-
'aicq.friends.requests',
|
|
46
|
-
'aicq.friends.acceptRequest',
|
|
47
|
-
'aicq.friends.rejectRequest',
|
|
48
|
-
'aicq.identity.info',
|
|
49
|
-
'aicq.agent.create',
|
|
50
|
-
'aicq.agent.delete',
|
|
51
|
-
'aicq.chat.send',
|
|
52
|
-
'aicq.chat.history',
|
|
53
|
-
'aicq.chat.streamChunk',
|
|
54
|
-
'aicq.chat.streamEnd',
|
|
55
|
-
'aicq.groups.list',
|
|
56
|
-
'aicq.groups.create',
|
|
57
|
-
'aicq.groups.join',
|
|
58
|
-
'aicq.groups.messages',
|
|
59
|
-
'aicq.groups.silent',
|
|
60
|
-
'aicq.sessions.list',
|
|
61
|
-
];
|
|
62
|
-
|
|
63
|
-
for (const method of gatewayMethods) {
|
|
64
|
-
api.registerGatewayMethod(method, async (kwargs, ctx) => {
|
|
65
|
-
const { handleGateway } = await import('./src/gateway-handlers.mjs');
|
|
66
|
-
return handleGateway(method, kwargs, ctx);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
});
|
package/setup-entry.mjs
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AICQ Setup Entry — Setup Wizard for first-time configuration
|
|
3
|
-
*
|
|
4
|
-
* Uses defineSetupPluginEntry from the OpenClaw Channel SDK
|
|
5
|
-
*/
|
|
6
|
-
import { defineSetupPluginEntry } from 'openclaw/plugin-sdk/channel-core';
|
|
7
|
-
import { aicqChatPlugin } from './src/channel.mjs';
|
|
8
|
-
|
|
9
|
-
export default defineSetupPluginEntry(aicqChatPlugin);
|
package/src/channel.mjs
DELETED
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AICQ Channel Plugin — Core Channel Logic (ESM)
|
|
3
|
-
*
|
|
4
|
-
* Uses OpenClaw Channel Plugin SDK:
|
|
5
|
-
* - createChatChannelPlugin from openclaw/plugin-sdk/channel-core
|
|
6
|
-
* - createChannelPluginBase from openclaw/plugin-sdk/channel-core
|
|
7
|
-
*
|
|
8
|
-
* Wraps existing lib/ modules (identity, server-client, handshake, chat, database)
|
|
9
|
-
* into the proper OpenClaw Channel plugin interface.
|
|
10
|
-
*/
|
|
11
|
-
import { createChatChannelPlugin, createChannelPluginBase } from 'openclaw/plugin-sdk/channel-core';
|
|
12
|
-
import { createRequire } from 'module';
|
|
13
|
-
import path from 'path';
|
|
14
|
-
import fs from 'fs';
|
|
15
|
-
import os from 'os';
|
|
16
|
-
|
|
17
|
-
const require = createRequire(import.meta.url);
|
|
18
|
-
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
19
|
-
|
|
20
|
-
// ── Configuration ──────────────────────────────────────────────────
|
|
21
|
-
const DATA_DIR = process.env.AICQ_DATA_DIR || path.join(os.homedir(), '.aicq-plugin');
|
|
22
|
-
const SERVER_URL = process.env.AICQ_SERVER_URL || 'https://aicq.online';
|
|
23
|
-
|
|
24
|
-
fs.mkdirSync(DATA_DIR, { recursive: true });
|
|
25
|
-
|
|
26
|
-
// ── Lazy-loaded CommonJS modules ───────────────────────────────────
|
|
27
|
-
let _db = null;
|
|
28
|
-
let _identity = null;
|
|
29
|
-
let _serverClient = null;
|
|
30
|
-
let _handshake = null;
|
|
31
|
-
let _chat = null;
|
|
32
|
-
let _initialized = false;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Initialize all plugin components (async, called once)
|
|
36
|
-
*/
|
|
37
|
-
async function ensureInitialized() {
|
|
38
|
-
if (_initialized) return;
|
|
39
|
-
|
|
40
|
-
const PluginDatabase = require('../lib/database');
|
|
41
|
-
const IdentityManager = require('../lib/identity');
|
|
42
|
-
const ServerClient = require('../lib/server-client');
|
|
43
|
-
const HandshakeManager = require('../lib/handshake');
|
|
44
|
-
const ChatManager = require('../lib/chat');
|
|
45
|
-
|
|
46
|
-
// Initialize database
|
|
47
|
-
_db = new PluginDatabase(DATA_DIR);
|
|
48
|
-
await _db.init();
|
|
49
|
-
console.log('[AICQ Channel] Database initialized');
|
|
50
|
-
|
|
51
|
-
// Initialize managers
|
|
52
|
-
_identity = new IdentityManager(_db);
|
|
53
|
-
_serverClient = new ServerClient(_identity, _db, SERVER_URL);
|
|
54
|
-
_handshake = new HandshakeManager(_identity, _serverClient, _db);
|
|
55
|
-
_chat = new ChatManager(_identity, _serverClient, _db, path.join(DATA_DIR, 'uploads'));
|
|
56
|
-
|
|
57
|
-
// Periodic cleanup
|
|
58
|
-
setInterval(() => _db.cleanup(), 3600000);
|
|
59
|
-
|
|
60
|
-
_initialized = true;
|
|
61
|
-
console.log('[AICQ Channel] Plugin components initialized');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Resolve account from OpenClaw config
|
|
66
|
-
* Reads channels.<channel-id> section and returns a resolved account object
|
|
67
|
-
*/
|
|
68
|
-
function resolveAccount(cfg, accountId) {
|
|
69
|
-
const section = (cfg.channels || {})[ 'aicq-chat' ];
|
|
70
|
-
const token = section?.accountId || accountId || null;
|
|
71
|
-
return {
|
|
72
|
-
accountId: token,
|
|
73
|
-
serverUrl: section?.serverUrl || SERVER_URL,
|
|
74
|
-
autoAcceptFriends: section?.autoAcceptFriends ?? true,
|
|
75
|
-
dmPolicy: section?.dmPolicy || 'allowlist',
|
|
76
|
-
enabled: section?.enabled ?? true,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Inspect account without materializing secrets
|
|
82
|
-
*/
|
|
83
|
-
function inspectAccount(cfg, accountId) {
|
|
84
|
-
const section = (cfg.channels || {})[ 'aicq-chat' ];
|
|
85
|
-
return {
|
|
86
|
-
enabled: section?.enabled ?? true,
|
|
87
|
-
configured: Boolean(section?.accountId || accountId),
|
|
88
|
-
hasAccountId: Boolean(section?.accountId || accountId),
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// ── Build the Channel Plugin using SDK ──────────────────────────────
|
|
93
|
-
export const aicqChatPlugin = createChatChannelPlugin({
|
|
94
|
-
base: createChannelPluginBase({
|
|
95
|
-
id: 'aicq-chat',
|
|
96
|
-
setup: {
|
|
97
|
-
resolveAccount,
|
|
98
|
-
inspectAccount,
|
|
99
|
-
},
|
|
100
|
-
}),
|
|
101
|
-
|
|
102
|
-
// DM security: who can message the bot
|
|
103
|
-
security: {
|
|
104
|
-
dm: {
|
|
105
|
-
channelKey: 'aicq-chat',
|
|
106
|
-
resolvePolicy: (account) => account.dmPolicy || 'allowlist',
|
|
107
|
-
resolveAllowFrom: async (account) => {
|
|
108
|
-
// Only friends in the contact list can send DMs
|
|
109
|
-
await ensureInitialized();
|
|
110
|
-
if (!_identity || !account.accountId) return [];
|
|
111
|
-
const friends = _db.listFriends(account.accountId);
|
|
112
|
-
return friends.map(f => f.id || f.friend_id);
|
|
113
|
-
},
|
|
114
|
-
defaultPolicy: 'allowlist',
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
|
|
118
|
-
// Pairing: DM approval flow for new contacts
|
|
119
|
-
pairing: {
|
|
120
|
-
text: {
|
|
121
|
-
idLabel: 'AICQ Account ID',
|
|
122
|
-
message: 'Share this pairing code with the other party to verify your identity:',
|
|
123
|
-
generate: async ({ target, code }) => {
|
|
124
|
-
await ensureInitialized();
|
|
125
|
-
if (_handshake && target) {
|
|
126
|
-
try {
|
|
127
|
-
await _serverClient.ensureAuth(target);
|
|
128
|
-
const result = await _handshake.generateFriendCode(target);
|
|
129
|
-
return { code: result.number, instructions: `Share this pairing code: ${result.number}` };
|
|
130
|
-
} catch (e) {
|
|
131
|
-
// Fallback to the generated code
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
return { code, instructions: `Share this pairing code: ${code}` };
|
|
135
|
-
},
|
|
136
|
-
verify: async ({ accountId, peerCode }) => {
|
|
137
|
-
await ensureInitialized();
|
|
138
|
-
try {
|
|
139
|
-
const result = await _handshake.addFriendByCode(accountId, peerCode);
|
|
140
|
-
return { success: true, peerId: result.peer_id || result.friend_id || peerCode };
|
|
141
|
-
} catch (e) {
|
|
142
|
-
return { success: false, error: e.message };
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
|
|
148
|
-
// Threading: how replies are delivered
|
|
149
|
-
threading: {
|
|
150
|
-
topLevelReplyToMode: 'reply',
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
// Outbound: send messages to the platform
|
|
154
|
-
outbound: {
|
|
155
|
-
attachedResults: {
|
|
156
|
-
sendText: async (params) => {
|
|
157
|
-
await ensureInitialized();
|
|
158
|
-
const result = await _chat.sendMessage(
|
|
159
|
-
params.fromAccountId || params.accountId,
|
|
160
|
-
params.to,
|
|
161
|
-
params.text,
|
|
162
|
-
{ isGroup: false }
|
|
163
|
-
);
|
|
164
|
-
return { messageId: result?.message_id || result?.id || `msg_${Date.now()}` };
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
base: {
|
|
168
|
-
sendMedia: async (params) => {
|
|
169
|
-
await ensureInitialized();
|
|
170
|
-
const result = await _chat.sendMessage(
|
|
171
|
-
params.fromAccountId || params.accountId,
|
|
172
|
-
params.to,
|
|
173
|
-
params.mediaUrl || params.filePath,
|
|
174
|
-
{ type: params.mediaType || 'file', isGroup: false }
|
|
175
|
-
);
|
|
176
|
-
return { messageId: result?.message_id || result?.id || `msg_${Date.now()}` };
|
|
177
|
-
},
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
|
|
181
|
-
// Lifecycle: account management
|
|
182
|
-
lifecycle: {
|
|
183
|
-
onAccountCreate: async (accountId) => {
|
|
184
|
-
await ensureInitialized();
|
|
185
|
-
let agentIdentity = _identity.loadAgent(accountId);
|
|
186
|
-
if (!agentIdentity) {
|
|
187
|
-
agentIdentity = _identity.createAgent(accountId, `agent-${accountId.slice(0, 8)}`);
|
|
188
|
-
}
|
|
189
|
-
try {
|
|
190
|
-
await _serverClient.start(accountId);
|
|
191
|
-
} catch (e) {
|
|
192
|
-
console.error('[AICQ Channel] Server connection failed for account:', accountId, e.message);
|
|
193
|
-
}
|
|
194
|
-
},
|
|
195
|
-
onAccountDelete: async (accountId) => {
|
|
196
|
-
try {
|
|
197
|
-
_serverClient.disconnect();
|
|
198
|
-
} catch (e) {}
|
|
199
|
-
_identity.deleteAgent(accountId);
|
|
200
|
-
},
|
|
201
|
-
onShutdown: async () => {
|
|
202
|
-
try {
|
|
203
|
-
_serverClient.stop();
|
|
204
|
-
} catch (e) {}
|
|
205
|
-
console.log('[AICQ Channel] Shutdown complete');
|
|
206
|
-
},
|
|
207
|
-
},
|
|
208
|
-
|
|
209
|
-
// Inbound: process incoming messages (used when AICQ server pushes messages)
|
|
210
|
-
inbound: {
|
|
211
|
-
onText: async (message) => {
|
|
212
|
-
const { toAccountId, fromPeerId, encryptedContent } = message;
|
|
213
|
-
await ensureInitialized();
|
|
214
|
-
|
|
215
|
-
let content = encryptedContent || message.content || message.payload || '';
|
|
216
|
-
const session = _db.loadSession(toAccountId, fromPeerId);
|
|
217
|
-
if (session && session.session_key && typeof content === 'string') {
|
|
218
|
-
try {
|
|
219
|
-
const { decryptMessage } = require('../lib/crypto');
|
|
220
|
-
content = decryptMessage(content, session.session_key);
|
|
221
|
-
} catch (e) {
|
|
222
|
-
// Might be plaintext, keep as is
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
return {
|
|
227
|
-
text: typeof content === 'string' ? content : JSON.stringify(content),
|
|
228
|
-
metadata: {
|
|
229
|
-
fromPeerId,
|
|
230
|
-
timestamp: message.timestamp,
|
|
231
|
-
},
|
|
232
|
-
};
|
|
233
|
-
},
|
|
234
|
-
onMedia: async (message) => {
|
|
235
|
-
await ensureInitialized();
|
|
236
|
-
let content = message.encryptedContent || message.content || '';
|
|
237
|
-
const session = _db.loadSession(message.toAccountId, message.fromPeerId);
|
|
238
|
-
if (session && session.session_key && typeof content === 'string') {
|
|
239
|
-
try {
|
|
240
|
-
const { decryptMessage } = require('../lib/crypto');
|
|
241
|
-
content = decryptMessage(content, session.session_key);
|
|
242
|
-
} catch (e) {}
|
|
243
|
-
}
|
|
244
|
-
return {
|
|
245
|
-
mediaUrl: content,
|
|
246
|
-
mediaType: message.mediaType || 'file',
|
|
247
|
-
metadata: { fromPeerId: message.fromPeerId },
|
|
248
|
-
};
|
|
249
|
-
},
|
|
250
|
-
},
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
// Export for gateway handlers to access managers
|
|
254
|
-
export { ensureInitialized, _db, _identity, _serverClient, _handshake, _chat };
|
package/src/gateway-handlers.mjs
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AICQ Gateway Handlers — Gateway method implementations
|
|
3
|
-
*
|
|
4
|
-
* Handles all aicq.* gateway methods for the SPA UI.
|
|
5
|
-
* Lazy-initializes the plugin components on first call.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
let _handlersInitialized = false;
|
|
9
|
-
let _db = null;
|
|
10
|
-
let _identity = null;
|
|
11
|
-
let _serverClient = null;
|
|
12
|
-
let _handshake = null;
|
|
13
|
-
let _chat = null;
|
|
14
|
-
|
|
15
|
-
async function ensureHandlersInitialized() {
|
|
16
|
-
if (_handlersInitialized) return;
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
const channelModule = await import('./channel.mjs');
|
|
20
|
-
await channelModule.ensureInitialized();
|
|
21
|
-
// Access the lazy-loaded managers through the module's exports
|
|
22
|
-
_db = channelModule._db;
|
|
23
|
-
_identity = channelModule._identity;
|
|
24
|
-
_serverClient = channelModule._serverClient;
|
|
25
|
-
_handshake = channelModule._handshake;
|
|
26
|
-
_chat = channelModule._chat;
|
|
27
|
-
_handlersInitialized = true;
|
|
28
|
-
} catch (e) {
|
|
29
|
-
console.error('[AICQ Gateway] Failed to initialize handlers:', e.message);
|
|
30
|
-
throw e;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function getCurrentAgentId() {
|
|
35
|
-
if (!_identity) return null;
|
|
36
|
-
const agents = _identity.listAgents();
|
|
37
|
-
return agents.length > 0 ? agents[0].agent_id : null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Main gateway method dispatcher
|
|
42
|
-
*/
|
|
43
|
-
export async function handleGateway(method, kwargs = {}, ctx = {}) {
|
|
44
|
-
await ensureHandlersInitialized();
|
|
45
|
-
const currentAgentId = getCurrentAgentId();
|
|
46
|
-
|
|
47
|
-
switch (method) {
|
|
48
|
-
case 'aicq.status':
|
|
49
|
-
return {
|
|
50
|
-
state: _serverClient?.connected ? 'connected' : 'disconnected',
|
|
51
|
-
agent_id: currentAgentId,
|
|
52
|
-
version: '3.3.0',
|
|
53
|
-
architecture: 'channel',
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
case 'aicq.friends.list':
|
|
57
|
-
return { friends: _db?.listFriends(currentAgentId) || [] };
|
|
58
|
-
|
|
59
|
-
case 'aicq.friends.add':
|
|
60
|
-
return await _handshake?.addFriendByCode(currentAgentId, kwargs.temp_number);
|
|
61
|
-
|
|
62
|
-
case 'aicq.friends.remove':
|
|
63
|
-
_db?.removeFriend(currentAgentId, kwargs.friend_id);
|
|
64
|
-
return { success: true };
|
|
65
|
-
|
|
66
|
-
case 'aicq.friends.requests':
|
|
67
|
-
return { requests: _db?.getPendingRequests(currentAgentId) || [] };
|
|
68
|
-
|
|
69
|
-
case 'aicq.friends.acceptRequest':
|
|
70
|
-
return await _handshake?.acceptRequest(currentAgentId, kwargs.request_id);
|
|
71
|
-
|
|
72
|
-
case 'aicq.friends.rejectRequest':
|
|
73
|
-
return await _handshake?.rejectRequest(currentAgentId, kwargs.request_id);
|
|
74
|
-
|
|
75
|
-
case 'aicq.identity.info':
|
|
76
|
-
return _identity?.getInfo(currentAgentId) || {};
|
|
77
|
-
|
|
78
|
-
case 'aicq.agent.create':
|
|
79
|
-
_identity?.createAgent(kwargs.agent_id, kwargs.nickname);
|
|
80
|
-
return { success: true };
|
|
81
|
-
|
|
82
|
-
case 'aicq.agent.delete':
|
|
83
|
-
_identity?.deleteAgent(kwargs.agent_id);
|
|
84
|
-
return { success: true };
|
|
85
|
-
|
|
86
|
-
case 'aicq.chat.send':
|
|
87
|
-
return await _chat?.sendMessage(currentAgentId, kwargs.targetId, kwargs.content, { isGroup: kwargs.isGroup });
|
|
88
|
-
|
|
89
|
-
case 'aicq.chat.history':
|
|
90
|
-
return { messages: _db?.getChatHistory(currentAgentId, kwargs.targetId, { limit: kwargs.limit || 50 }) || [] };
|
|
91
|
-
|
|
92
|
-
case 'aicq.chat.streamChunk': {
|
|
93
|
-
if (!kwargs.friend_id && !kwargs.targetId) return { error: 'friend_id or targetId is required' };
|
|
94
|
-
if (!kwargs.data) return { error: 'data is required' };
|
|
95
|
-
const chunkType = kwargs.chunk_type || kwargs.chunkType || 'text';
|
|
96
|
-
const ALLOWED_CHUNK_TYPES = ['text', 'reasoning', 'thinking', 'clear_text', 'tool_call', 'tool_result'];
|
|
97
|
-
if (!ALLOWED_CHUNK_TYPES.includes(chunkType)) return { error: `Invalid chunk_type: ${chunkType}. Allowed: ${ALLOWED_CHUNK_TYPES.join(', ')}` };
|
|
98
|
-
const streamTarget = kwargs.friend_id || kwargs.targetId;
|
|
99
|
-
const sent = _serverClient?.sendWS({
|
|
100
|
-
type: 'stream_chunk',
|
|
101
|
-
to: streamTarget,
|
|
102
|
-
chunkType: chunkType,
|
|
103
|
-
data: kwargs.data,
|
|
104
|
-
});
|
|
105
|
-
if (!sent) return { error: 'Not connected to server', success: false };
|
|
106
|
-
return { success: true };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
case 'aicq.chat.streamEnd': {
|
|
110
|
-
if (!kwargs.friend_id && !kwargs.targetId) return { error: 'friend_id or targetId is required' };
|
|
111
|
-
const endTarget = kwargs.friend_id || kwargs.targetId;
|
|
112
|
-
const msgId = kwargs.message_id || kwargs.messageId || ('msg_' + Date.now() + '_' + Math.random().toString(36).substr(2, 6));
|
|
113
|
-
const endSent = _serverClient?.sendWS({
|
|
114
|
-
type: 'stream_end',
|
|
115
|
-
to: endTarget,
|
|
116
|
-
messageId: msgId,
|
|
117
|
-
});
|
|
118
|
-
if (!endSent) return { error: 'Not connected to server', success: false };
|
|
119
|
-
return { success: true, messageId: msgId };
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
case 'aicq.groups.list':
|
|
123
|
-
return { groups: _db?.listGroups(currentAgentId) || [] };
|
|
124
|
-
|
|
125
|
-
case 'aicq.groups.create': {
|
|
126
|
-
await _serverClient?.ensureAuth(currentAgentId);
|
|
127
|
-
const result = await _serverClient?.createGroup(kwargs.name, kwargs.description);
|
|
128
|
-
if (result?.id) {
|
|
129
|
-
_db?.addGroup({
|
|
130
|
-
agent_id: currentAgentId,
|
|
131
|
-
id: result.id,
|
|
132
|
-
name: kwargs.name,
|
|
133
|
-
owner_id: currentAgentId,
|
|
134
|
-
members_json: result.members || '[]',
|
|
135
|
-
description: kwargs.description || '',
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
return { success: true, group: result };
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
case 'aicq.groups.join':
|
|
142
|
-
await _serverClient?.ensureAuth(currentAgentId);
|
|
143
|
-
return await _serverClient?.inviteGroupMember(kwargs.group_id, currentAgentId);
|
|
144
|
-
|
|
145
|
-
case 'aicq.groups.messages': {
|
|
146
|
-
await _serverClient?.ensureAuth(currentAgentId);
|
|
147
|
-
return await _serverClient?.getGroupMessages(kwargs.group_id, kwargs.limit || 50);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
case 'aicq.groups.silent':
|
|
151
|
-
_db?.setGroupSilentMode(currentAgentId, kwargs.group_id, !!kwargs.silent);
|
|
152
|
-
return { success: true, silent: !!kwargs.silent };
|
|
153
|
-
|
|
154
|
-
default:
|
|
155
|
-
return { error: `Unknown method: ${method}` };
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Individual method exports (for direct registration)
|
|
160
|
-
export async function getStatus(kwargs, ctx) { return handleGateway('aicq.status', kwargs, ctx); }
|
|
161
|
-
export async function listFriends(kwargs, ctx) { return handleGateway('aicq.friends.list', kwargs, ctx); }
|
|
162
|
-
export async function addFriend(kwargs, ctx) { return handleGateway('aicq.friends.add', kwargs, ctx); }
|
|
163
|
-
export async function removeFriend(kwargs, ctx) { return handleGateway('aicq.friends.remove', kwargs, ctx); }
|
|
164
|
-
export async function listFriendRequests(kwargs, ctx) { return handleGateway('aicq.friends.requests', kwargs, ctx); }
|
|
165
|
-
export async function acceptFriendRequest(kwargs, ctx) { return handleGateway('aicq.friends.acceptRequest', kwargs, ctx); }
|
|
166
|
-
export async function rejectFriendRequest(kwargs, ctx) { return handleGateway('aicq.friends.rejectRequest', kwargs, ctx); }
|
|
167
|
-
export async function getIdentityInfo(kwargs, ctx) { return handleGateway('aicq.identity.info', kwargs, ctx); }
|
|
168
|
-
export async function createAgent(kwargs, ctx) { return handleGateway('aicq.agent.create', kwargs, ctx); }
|
|
169
|
-
export async function deleteAgent(kwargs, ctx) { return handleGateway('aicq.agent.delete', kwargs, ctx); }
|
|
170
|
-
export async function chatSend(kwargs, ctx) { return handleGateway('aicq.chat.send', kwargs, ctx); }
|
|
171
|
-
export async function chatHistory(kwargs, ctx) { return handleGateway('aicq.chat.history', kwargs, ctx); }
|
|
172
|
-
export async function chatStreamChunk(kwargs, ctx) { return handleGateway('aicq.chat.streamChunk', kwargs, ctx); }
|
|
173
|
-
export async function chatStreamEnd(kwargs, ctx) { return handleGateway('aicq.chat.streamEnd', kwargs, ctx); }
|
|
174
|
-
export async function listGroups(kwargs, ctx) { return handleGateway('aicq.groups.list', kwargs, ctx); }
|
|
175
|
-
export async function createGroup(kwargs, ctx) { return handleGateway('aicq.groups.create', kwargs, ctx); }
|
|
176
|
-
export async function joinGroup(kwargs, ctx) { return handleGateway('aicq.groups.join', kwargs, ctx); }
|
|
177
|
-
export async function getGroupMessages(kwargs, ctx) { return handleGateway('aicq.groups.messages', kwargs, ctx); }
|
|
178
|
-
export async function setGroupSilent(kwargs, ctx) { return handleGateway('aicq.groups.silent', kwargs, ctx); }
|