@aigne/afs-messaging 1.11.0-beta.12
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.md +26 -0
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +10 -0
- package/dist/base.cjs +598 -0
- package/dist/base.d.cts +174 -0
- package/dist/base.d.cts.map +1 -0
- package/dist/base.d.mts +174 -0
- package/dist/base.d.mts.map +1 -0
- package/dist/base.mjs +599 -0
- package/dist/base.mjs.map +1 -0
- package/dist/index.cjs +5 -0
- package/dist/index.d.cts +3 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +4 -0
- package/dist/types.cjs +12 -0
- package/dist/types.d.cts +89 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +89 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +12 -0
- package/dist/types.mjs.map +1 -0
- package/package.json +54 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2025 ArcBlock, Inc. All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
This software and associated documentation files (the "Software") are proprietary
|
|
6
|
+
and confidential. Unauthorized copying, modification, distribution, or use of
|
|
7
|
+
this Software, via any medium, is strictly prohibited.
|
|
8
|
+
|
|
9
|
+
The Software is provided for internal use only within ArcBlock, Inc. and its
|
|
10
|
+
authorized affiliates.
|
|
11
|
+
|
|
12
|
+
## No License Granted
|
|
13
|
+
|
|
14
|
+
No license, express or implied, is granted to any party for any purpose.
|
|
15
|
+
All rights are reserved by ArcBlock, Inc.
|
|
16
|
+
|
|
17
|
+
## Public Artifact Distribution
|
|
18
|
+
|
|
19
|
+
Portions of this Software may be released publicly under separate open-source
|
|
20
|
+
licenses (such as MIT License) through designated public repositories. Such
|
|
21
|
+
public releases are governed by their respective licenses and do not affect
|
|
22
|
+
the proprietary nature of this repository.
|
|
23
|
+
|
|
24
|
+
## Contact
|
|
25
|
+
|
|
26
|
+
For licensing inquiries, contact: legal@arcblock.io
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
//#region \0@oxc-project+runtime@0.108.0/helpers/decorate.js
|
|
3
|
+
function __decorate(decorators, target, key, desc) {
|
|
4
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
5
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
6
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
7
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
exports.__decorate = __decorate;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region \0@oxc-project+runtime@0.108.0/helpers/decorate.js
|
|
2
|
+
function __decorate(decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
export { __decorate };
|
package/dist/base.cjs
ADDED
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
const require_types = require('./types.cjs');
|
|
2
|
+
const require_decorate = require('./_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs');
|
|
3
|
+
let _aigne_afs = require("@aigne/afs");
|
|
4
|
+
let _aigne_afs_provider = require("@aigne/afs/provider");
|
|
5
|
+
|
|
6
|
+
//#region src/base.ts
|
|
7
|
+
const DEFAULT_BUFFER_SIZE = 100;
|
|
8
|
+
/**
|
|
9
|
+
* Abstract base class for messaging platform providers.
|
|
10
|
+
*
|
|
11
|
+
* Subclass must implement:
|
|
12
|
+
* - providerName: string (e.g., "telegram")
|
|
13
|
+
* - eventPrefix: string (e.g., "telegram")
|
|
14
|
+
* - getMessageCapabilities(): MessageCapabilities
|
|
15
|
+
* - createBotClient(config: BotConfig): unknown
|
|
16
|
+
* - sendMessage(client, convId, text, opts?): Promise<{ messageId: string }>
|
|
17
|
+
* - normalizeMessage(raw): BufferedMessage
|
|
18
|
+
* - normalizeSender(raw): MessageSender
|
|
19
|
+
*/
|
|
20
|
+
var BaseMessageProvider = class extends _aigne_afs_provider.AFSBaseProvider {
|
|
21
|
+
get name() {
|
|
22
|
+
return this.providerName;
|
|
23
|
+
}
|
|
24
|
+
accessMode = "readwrite";
|
|
25
|
+
_bufferSize;
|
|
26
|
+
/** botName → platform client */
|
|
27
|
+
_botClients = /* @__PURE__ */ new Map();
|
|
28
|
+
/** botName → BotConfig */
|
|
29
|
+
_botConfigs = /* @__PURE__ */ new Map();
|
|
30
|
+
/** botName → Set<conversationId> */
|
|
31
|
+
_botConversations = /* @__PURE__ */ new Map();
|
|
32
|
+
/** botName → (conversationId → BufferedMessage[]) */
|
|
33
|
+
_botBuffers = /* @__PURE__ */ new Map();
|
|
34
|
+
/** Ordered list of bot names (for consistent listing) */
|
|
35
|
+
_botOrder = [];
|
|
36
|
+
/** Pending bot configs — created in constructor, clients instantiated lazily */
|
|
37
|
+
_pendingBots = null;
|
|
38
|
+
constructor(options) {
|
|
39
|
+
super();
|
|
40
|
+
this._bufferSize = options.bufferSize ?? DEFAULT_BUFFER_SIZE;
|
|
41
|
+
this._pendingBots = options.bots;
|
|
42
|
+
for (const botConfig of options.bots) this._addBotConfig(botConfig);
|
|
43
|
+
}
|
|
44
|
+
/** Ensure all pending bot clients are created. Called lazily on first access. */
|
|
45
|
+
_ensureClients() {
|
|
46
|
+
if (!this._pendingBots) return;
|
|
47
|
+
const pending = this._pendingBots;
|
|
48
|
+
this._pendingBots = null;
|
|
49
|
+
for (const config of pending) if (!this._botClients.has(config.name)) {
|
|
50
|
+
const client = this.createBotClient(config);
|
|
51
|
+
this._botClients.set(config.name, client);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Get a bot client, creating lazily if needed. */
|
|
55
|
+
_getClient(botName) {
|
|
56
|
+
this._ensureClients();
|
|
57
|
+
return this._botClients.get(botName);
|
|
58
|
+
}
|
|
59
|
+
/** Register bot config and conversations without creating the client. */
|
|
60
|
+
_addBotConfig(config) {
|
|
61
|
+
const name = config.name;
|
|
62
|
+
if (this._botConfigs.has(name)) return;
|
|
63
|
+
this._botConfigs.set(name, config);
|
|
64
|
+
const conversations = /* @__PURE__ */ new Set();
|
|
65
|
+
if (Array.isArray(config.conversations)) for (const c of config.conversations) conversations.add(String(c));
|
|
66
|
+
this._botConversations.set(name, conversations);
|
|
67
|
+
const buffers = /* @__PURE__ */ new Map();
|
|
68
|
+
for (const convId of conversations) buffers.set(convId, []);
|
|
69
|
+
this._botBuffers.set(name, buffers);
|
|
70
|
+
this._botOrder.push(name);
|
|
71
|
+
}
|
|
72
|
+
_removeBot(name) {
|
|
73
|
+
if (!this._botConfigs.has(name)) return false;
|
|
74
|
+
this._botClients.delete(name);
|
|
75
|
+
this._botConfigs.delete(name);
|
|
76
|
+
this._botConversations.delete(name);
|
|
77
|
+
this._botBuffers.delete(name);
|
|
78
|
+
const idx = this._botOrder.indexOf(name);
|
|
79
|
+
if (idx >= 0) this._botOrder.splice(idx, 1);
|
|
80
|
+
this.onBotRemoved(name);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
/** Hook for subclasses to initialize platform-specific state (e.g. polling, gateway) when a bot is added at runtime. */
|
|
84
|
+
onBotAdded(_name) {}
|
|
85
|
+
/** Hook for subclasses to clean up platform-specific state when a bot is removed. */
|
|
86
|
+
onBotRemoved(_name) {}
|
|
87
|
+
/**
|
|
88
|
+
* Buffer a received message and emit the appropriate event.
|
|
89
|
+
* Called by subclass when a new message arrives from the platform.
|
|
90
|
+
*
|
|
91
|
+
* - Buffers the message in the ring buffer
|
|
92
|
+
* - Auto-adds conversation if not yet tracked
|
|
93
|
+
* - Detects /commands → emits messaging:command
|
|
94
|
+
* - Otherwise → emits messaging:message
|
|
95
|
+
*/
|
|
96
|
+
emitMessageReceived(botName, msg) {
|
|
97
|
+
const convId = msg.conversationId;
|
|
98
|
+
const conversations = this._botConversations.get(botName);
|
|
99
|
+
if (conversations && !conversations.has(convId)) {
|
|
100
|
+
conversations.add(convId);
|
|
101
|
+
const buffers = this._botBuffers.get(botName);
|
|
102
|
+
if (buffers && !buffers.has(convId)) buffers.set(convId, []);
|
|
103
|
+
}
|
|
104
|
+
this._pushToRingBuffer(botName, convId, msg);
|
|
105
|
+
const path = `/${botName}/conversations/${convId}/messages/${msg.id}`;
|
|
106
|
+
const text = msg.text.trim();
|
|
107
|
+
if (text.startsWith("/")) {
|
|
108
|
+
const spaceIdx = text.indexOf(" ");
|
|
109
|
+
const command = spaceIdx > 0 ? text.slice(1, spaceIdx) : text.slice(1);
|
|
110
|
+
const args = spaceIdx > 0 ? text.slice(spaceIdx + 1).trim() : "";
|
|
111
|
+
this.emit({
|
|
112
|
+
type: require_types.MESSAGING_EVENTS.COMMAND,
|
|
113
|
+
path,
|
|
114
|
+
data: {
|
|
115
|
+
botName,
|
|
116
|
+
conversationId: convId,
|
|
117
|
+
messageId: msg.id,
|
|
118
|
+
command,
|
|
119
|
+
args,
|
|
120
|
+
text,
|
|
121
|
+
from: msg.from
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
} else this.emit({
|
|
125
|
+
type: require_types.MESSAGING_EVENTS.MESSAGE,
|
|
126
|
+
path,
|
|
127
|
+
data: {
|
|
128
|
+
botName,
|
|
129
|
+
conversationId: convId,
|
|
130
|
+
messageId: msg.id,
|
|
131
|
+
text,
|
|
132
|
+
from: msg.from
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
_pushToRingBuffer(botName, convId, msg) {
|
|
137
|
+
let botBuffers = this._botBuffers.get(botName);
|
|
138
|
+
if (!botBuffers) {
|
|
139
|
+
botBuffers = /* @__PURE__ */ new Map();
|
|
140
|
+
this._botBuffers.set(botName, botBuffers);
|
|
141
|
+
}
|
|
142
|
+
let buffer = botBuffers.get(convId);
|
|
143
|
+
if (!buffer) {
|
|
144
|
+
buffer = [];
|
|
145
|
+
botBuffers.set(convId, buffer);
|
|
146
|
+
}
|
|
147
|
+
buffer.push(msg);
|
|
148
|
+
while (buffer.length > this._bufferSize) buffer.shift();
|
|
149
|
+
}
|
|
150
|
+
async listRoot(_ctx) {
|
|
151
|
+
return { data: this._botOrder.map((name) => {
|
|
152
|
+
return this.buildEntry(`/${name}`, {
|
|
153
|
+
id: name,
|
|
154
|
+
meta: {
|
|
155
|
+
type: "directory",
|
|
156
|
+
childrenCount: 2
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}) };
|
|
160
|
+
}
|
|
161
|
+
async listBot(ctx) {
|
|
162
|
+
const { botName } = ctx.params;
|
|
163
|
+
if (!this._botConfigs.has(botName)) throw new _aigne_afs.AFSNotFoundError(`/${botName}`);
|
|
164
|
+
const convs = this._botConversations.get(botName);
|
|
165
|
+
return { data: [this.buildEntry(`/${botName}/ctl`, { meta: { description: "Bot control file" } }), this.buildEntry(`/${botName}/conversations`, { meta: {
|
|
166
|
+
type: "directory",
|
|
167
|
+
childrenCount: convs.size
|
|
168
|
+
} })] };
|
|
169
|
+
}
|
|
170
|
+
async listConversations(ctx) {
|
|
171
|
+
const { botName } = ctx.params;
|
|
172
|
+
const convs = this._botConversations.get(botName);
|
|
173
|
+
if (!convs) throw new _aigne_afs.AFSNotFoundError(`/${botName}/conversations`);
|
|
174
|
+
return { data: [...convs].map((convId) => {
|
|
175
|
+
const buffer = this._botBuffers.get(botName)?.get(convId) ?? [];
|
|
176
|
+
return this.buildEntry(`/${botName}/conversations/${convId}`, {
|
|
177
|
+
id: convId,
|
|
178
|
+
meta: {
|
|
179
|
+
conversationId: convId,
|
|
180
|
+
childrenCount: buffer.length
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}) };
|
|
184
|
+
}
|
|
185
|
+
async listConversationChildren(ctx) {
|
|
186
|
+
const { botName, convId } = ctx.params;
|
|
187
|
+
const buffer = this._botBuffers.get(botName)?.get(convId) ?? [];
|
|
188
|
+
return { data: [this.buildEntry(`/${botName}/conversations/${convId}/messages`, { meta: {
|
|
189
|
+
type: "directory",
|
|
190
|
+
childrenCount: buffer.length
|
|
191
|
+
} })] };
|
|
192
|
+
}
|
|
193
|
+
async listMessages(ctx) {
|
|
194
|
+
const { botName, convId } = ctx.params;
|
|
195
|
+
return { data: (this._botBuffers.get(botName)?.get(convId) ?? []).map((msg) => this.buildEntry(`/${botName}/conversations/${convId}/messages/${msg.id}`, {
|
|
196
|
+
id: msg.id,
|
|
197
|
+
content: msg.text,
|
|
198
|
+
meta: {
|
|
199
|
+
kind: "messaging:message",
|
|
200
|
+
from: msg.from,
|
|
201
|
+
timestamp: msg.timestamp,
|
|
202
|
+
format: "text",
|
|
203
|
+
conversationId: convId,
|
|
204
|
+
...msg.replyTo ? { replyTo: msg.replyTo } : {},
|
|
205
|
+
...msg.platform ? { platform: msg.platform } : {}
|
|
206
|
+
}
|
|
207
|
+
})) };
|
|
208
|
+
}
|
|
209
|
+
async listMessageChildren(_ctx) {
|
|
210
|
+
return { data: [] };
|
|
211
|
+
}
|
|
212
|
+
async readRoot(_ctx) {
|
|
213
|
+
return this.buildEntry("/", {
|
|
214
|
+
content: JSON.stringify({
|
|
215
|
+
provider: this.providerName,
|
|
216
|
+
bots: this._botOrder,
|
|
217
|
+
bufferSize: this._bufferSize
|
|
218
|
+
}),
|
|
219
|
+
meta: { childrenCount: this._botOrder.length }
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
async readBot(ctx) {
|
|
223
|
+
const { botName } = ctx.params;
|
|
224
|
+
if (!this._botConfigs.get(botName)) throw new _aigne_afs.AFSNotFoundError(`/${botName}`);
|
|
225
|
+
const conversations = [...this._botConversations.get(botName) ?? []];
|
|
226
|
+
return this.buildEntry(`/${botName}`, {
|
|
227
|
+
id: botName,
|
|
228
|
+
content: JSON.stringify({
|
|
229
|
+
name: botName,
|
|
230
|
+
platform: this.providerName,
|
|
231
|
+
conversations
|
|
232
|
+
}),
|
|
233
|
+
meta: {
|
|
234
|
+
type: "directory",
|
|
235
|
+
childrenCount: 2
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
async readCtl(ctx) {
|
|
240
|
+
const { botName } = ctx.params;
|
|
241
|
+
if (!this._botConfigs.get(botName)) throw new _aigne_afs.AFSNotFoundError(`/${botName}/ctl`);
|
|
242
|
+
const conversations = [...this._botConversations.get(botName) ?? []];
|
|
243
|
+
return this.buildEntry(`/${botName}/ctl`, { content: JSON.stringify({
|
|
244
|
+
name: botName,
|
|
245
|
+
platform: this.providerName,
|
|
246
|
+
conversations
|
|
247
|
+
}) });
|
|
248
|
+
}
|
|
249
|
+
async readConversationsDir(ctx) {
|
|
250
|
+
const { botName } = ctx.params;
|
|
251
|
+
const convs = this._botConversations.get(botName);
|
|
252
|
+
if (!convs) throw new _aigne_afs.AFSNotFoundError(`/${botName}/conversations`);
|
|
253
|
+
return this.buildEntry(`/${botName}/conversations`, {
|
|
254
|
+
content: JSON.stringify({
|
|
255
|
+
type: "directory",
|
|
256
|
+
count: convs.size
|
|
257
|
+
}),
|
|
258
|
+
meta: {
|
|
259
|
+
type: "directory",
|
|
260
|
+
childrenCount: convs.size
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
async readConversation(ctx) {
|
|
265
|
+
const { botName, convId } = ctx.params;
|
|
266
|
+
const convs = this._botConversations.get(botName);
|
|
267
|
+
if (!convs || !convs.has(convId)) throw new _aigne_afs.AFSNotFoundError(`/${botName}/conversations/${convId}`);
|
|
268
|
+
const buffer = this._botBuffers.get(botName)?.get(convId) ?? [];
|
|
269
|
+
return this.buildEntry(`/${botName}/conversations/${convId}`, {
|
|
270
|
+
id: convId,
|
|
271
|
+
content: JSON.stringify({
|
|
272
|
+
conversationId: convId,
|
|
273
|
+
messageCount: buffer.length
|
|
274
|
+
}),
|
|
275
|
+
meta: { childrenCount: 1 }
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
async readMessagesDir(ctx) {
|
|
279
|
+
const { botName, convId } = ctx.params;
|
|
280
|
+
const buffer = this._botBuffers.get(botName)?.get(convId) ?? [];
|
|
281
|
+
return this.buildEntry(`/${botName}/conversations/${convId}/messages`, {
|
|
282
|
+
content: JSON.stringify({
|
|
283
|
+
type: "directory",
|
|
284
|
+
count: buffer.length
|
|
285
|
+
}),
|
|
286
|
+
meta: {
|
|
287
|
+
type: "directory",
|
|
288
|
+
childrenCount: buffer.length
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
async readMessage(ctx) {
|
|
293
|
+
const { botName, convId, msgId } = ctx.params;
|
|
294
|
+
const msg = (this._botBuffers.get(botName)?.get(convId) ?? []).find((m) => m.id === msgId);
|
|
295
|
+
if (!msg) throw new _aigne_afs.AFSNotFoundError(`/${botName}/conversations/${convId}/messages/${msgId}`);
|
|
296
|
+
return this.buildEntry(`/${botName}/conversations/${convId}/messages/${msgId}`, {
|
|
297
|
+
id: msgId,
|
|
298
|
+
content: msg.text,
|
|
299
|
+
meta: {
|
|
300
|
+
kind: "messaging:message",
|
|
301
|
+
from: msg.from,
|
|
302
|
+
timestamp: msg.timestamp,
|
|
303
|
+
format: "text",
|
|
304
|
+
conversationId: convId,
|
|
305
|
+
...msg.replyTo ? { replyTo: msg.replyTo } : {},
|
|
306
|
+
...msg.platform ? { platform: msg.platform } : {}
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
async readRootMeta(_ctx) {
|
|
311
|
+
const m = { childrenCount: this._botOrder.length };
|
|
312
|
+
return this.buildEntry("/.meta", {
|
|
313
|
+
content: m,
|
|
314
|
+
meta: m
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
async readCapabilities(_ctx) {
|
|
318
|
+
const messaging = this.getMessageCapabilities();
|
|
319
|
+
const manifest = {
|
|
320
|
+
schemaVersion: 1,
|
|
321
|
+
provider: this.providerName,
|
|
322
|
+
description: `${this.providerName} messaging provider`,
|
|
323
|
+
tools: [],
|
|
324
|
+
actions: [{
|
|
325
|
+
description: "Root-level bot management actions",
|
|
326
|
+
catalog: [{
|
|
327
|
+
name: "add-bot",
|
|
328
|
+
description: "Add a bot instance at runtime",
|
|
329
|
+
inputSchema: {
|
|
330
|
+
type: "object",
|
|
331
|
+
properties: { name: {
|
|
332
|
+
type: "string",
|
|
333
|
+
description: "Bot instance name"
|
|
334
|
+
} },
|
|
335
|
+
required: ["name"]
|
|
336
|
+
}
|
|
337
|
+
}, {
|
|
338
|
+
name: "remove-bot",
|
|
339
|
+
description: "Remove a bot instance",
|
|
340
|
+
inputSchema: {
|
|
341
|
+
type: "object",
|
|
342
|
+
properties: { name: {
|
|
343
|
+
type: "string",
|
|
344
|
+
description: "Bot instance name to remove"
|
|
345
|
+
} },
|
|
346
|
+
required: ["name"]
|
|
347
|
+
}
|
|
348
|
+
}],
|
|
349
|
+
discovery: { pathTemplate: "/.actions" }
|
|
350
|
+
}, {
|
|
351
|
+
kind: "messaging:conversation",
|
|
352
|
+
description: "Conversation-level messaging actions",
|
|
353
|
+
catalog: [{
|
|
354
|
+
name: "send",
|
|
355
|
+
description: "Send a text message to this conversation",
|
|
356
|
+
inputSchema: {
|
|
357
|
+
type: "object",
|
|
358
|
+
properties: { text: {
|
|
359
|
+
type: "string",
|
|
360
|
+
description: "Message text to send"
|
|
361
|
+
} },
|
|
362
|
+
required: ["text"]
|
|
363
|
+
}
|
|
364
|
+
}, {
|
|
365
|
+
name: "typing",
|
|
366
|
+
description: "Show typing indicator in this conversation",
|
|
367
|
+
inputSchema: {
|
|
368
|
+
type: "object",
|
|
369
|
+
properties: {},
|
|
370
|
+
required: []
|
|
371
|
+
}
|
|
372
|
+
}],
|
|
373
|
+
discovery: {
|
|
374
|
+
pathTemplate: "/:botName/conversations/:convId/.actions",
|
|
375
|
+
note: "Replace :botName and :convId with actual values"
|
|
376
|
+
}
|
|
377
|
+
}],
|
|
378
|
+
operations: this.getOperationsDeclaration()
|
|
379
|
+
};
|
|
380
|
+
return this.buildEntry("/.meta/.capabilities", {
|
|
381
|
+
content: {
|
|
382
|
+
...manifest,
|
|
383
|
+
messaging
|
|
384
|
+
},
|
|
385
|
+
meta: { kind: "afs:capabilities" }
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
async readBotMeta(ctx) {
|
|
389
|
+
const { botName } = ctx.params;
|
|
390
|
+
if (!this._botConfigs.has(botName)) throw new _aigne_afs.AFSNotFoundError(`/${botName}/.meta`);
|
|
391
|
+
const m = {
|
|
392
|
+
botName,
|
|
393
|
+
childrenCount: 2
|
|
394
|
+
};
|
|
395
|
+
return this.buildEntry(`/${botName}/.meta`, {
|
|
396
|
+
content: m,
|
|
397
|
+
meta: m
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
async readConversationsMeta(ctx) {
|
|
401
|
+
const { botName } = ctx.params;
|
|
402
|
+
const convs = this._botConversations.get(botName);
|
|
403
|
+
if (!convs) throw new _aigne_afs.AFSNotFoundError(`/${botName}/conversations/.meta`);
|
|
404
|
+
const m = {
|
|
405
|
+
type: "directory",
|
|
406
|
+
childrenCount: convs.size
|
|
407
|
+
};
|
|
408
|
+
return this.buildEntry(`/${botName}/conversations/.meta`, {
|
|
409
|
+
content: m,
|
|
410
|
+
meta: m
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
async readConversationMeta(ctx) {
|
|
414
|
+
const { botName, convId } = ctx.params;
|
|
415
|
+
const m = {
|
|
416
|
+
conversationId: convId,
|
|
417
|
+
childrenCount: (this._botBuffers.get(botName)?.get(convId) ?? []).length
|
|
418
|
+
};
|
|
419
|
+
return this.buildEntry(`/${botName}/conversations/${convId}/.meta`, {
|
|
420
|
+
content: m,
|
|
421
|
+
meta: m
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
async readMessagesMeta(ctx) {
|
|
425
|
+
const { botName, convId } = ctx.params;
|
|
426
|
+
const m = {
|
|
427
|
+
type: "directory",
|
|
428
|
+
childrenCount: (this._botBuffers.get(botName)?.get(convId) ?? []).length
|
|
429
|
+
};
|
|
430
|
+
return this.buildEntry(`/${botName}/conversations/${convId}/messages/.meta`, {
|
|
431
|
+
content: m,
|
|
432
|
+
meta: m
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
async readMsgMeta(ctx) {
|
|
436
|
+
const { botName, convId, msgId } = ctx.params;
|
|
437
|
+
const msg = (this._botBuffers.get(botName)?.get(convId) ?? []).find((m$1) => m$1.id === msgId);
|
|
438
|
+
if (!msg) throw new _aigne_afs.AFSNotFoundError(`/${botName}/conversations/${convId}/messages/${msgId}/.meta`);
|
|
439
|
+
const m = {
|
|
440
|
+
from: msg.from,
|
|
441
|
+
timestamp: msg.timestamp
|
|
442
|
+
};
|
|
443
|
+
return this.buildEntry(`/${botName}/conversations/${convId}/messages/${msgId}/.meta`, {
|
|
444
|
+
content: m,
|
|
445
|
+
meta: m
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
async explainRoot(_ctx) {
|
|
449
|
+
return {
|
|
450
|
+
content: `${this.providerName} messaging provider. Lists bots and their conversations. Messages are files you read().`,
|
|
451
|
+
format: "markdown"
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
async explainBot(_ctx) {
|
|
455
|
+
return {
|
|
456
|
+
content: `A ${this.providerName} bot instance. Read \`ctl\` for status. List \`conversations/\` for active conversations.`,
|
|
457
|
+
format: "markdown"
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
async explainConversation(_ctx) {
|
|
461
|
+
return {
|
|
462
|
+
content: "A conversation. List `messages/` for buffered messages. Use `.actions/send` to send a message.",
|
|
463
|
+
format: "markdown"
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
async explainMessage(_ctx) {
|
|
467
|
+
return {
|
|
468
|
+
content: "A single buffered message.",
|
|
469
|
+
format: "markdown"
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
async listRootActions(_ctx) {
|
|
473
|
+
return { data: [this.buildEntry("/.actions/add-bot", { meta: {
|
|
474
|
+
description: "Add a bot instance at runtime",
|
|
475
|
+
inputSchema: {
|
|
476
|
+
type: "object",
|
|
477
|
+
properties: { name: {
|
|
478
|
+
type: "string",
|
|
479
|
+
description: "Bot instance name"
|
|
480
|
+
} },
|
|
481
|
+
required: ["name"]
|
|
482
|
+
}
|
|
483
|
+
} }), this.buildEntry("/.actions/remove-bot", { meta: {
|
|
484
|
+
description: "Remove a bot instance",
|
|
485
|
+
inputSchema: {
|
|
486
|
+
type: "object",
|
|
487
|
+
properties: { name: {
|
|
488
|
+
type: "string",
|
|
489
|
+
description: "Bot instance name to remove"
|
|
490
|
+
} },
|
|
491
|
+
required: ["name"]
|
|
492
|
+
}
|
|
493
|
+
} })] };
|
|
494
|
+
}
|
|
495
|
+
async execAddBot(_ctx, args) {
|
|
496
|
+
const name = String(args.name ?? "");
|
|
497
|
+
if (!name) throw new Error("add-bot requires a name");
|
|
498
|
+
const config = {
|
|
499
|
+
name,
|
|
500
|
+
...args
|
|
501
|
+
};
|
|
502
|
+
this._addBotConfig(config);
|
|
503
|
+
this._botClients.set(name, this.createBotClient(config));
|
|
504
|
+
this.onBotAdded(name);
|
|
505
|
+
return {
|
|
506
|
+
success: true,
|
|
507
|
+
data: {
|
|
508
|
+
ok: true,
|
|
509
|
+
botName: name
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
async execRemoveBot(_ctx, args) {
|
|
514
|
+
const name = String(args.name ?? "");
|
|
515
|
+
return {
|
|
516
|
+
success: true,
|
|
517
|
+
data: {
|
|
518
|
+
ok: this._removeBot(name),
|
|
519
|
+
botName: name
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
async listConversationActions(ctx) {
|
|
524
|
+
const { botName, convId } = ctx.params;
|
|
525
|
+
return { data: [this.buildEntry(`/${botName}/conversations/${convId}/.actions/send`, { meta: {
|
|
526
|
+
description: "Send a text message to this conversation",
|
|
527
|
+
inputSchema: {
|
|
528
|
+
type: "object",
|
|
529
|
+
properties: { text: {
|
|
530
|
+
type: "string",
|
|
531
|
+
description: "Message text to send"
|
|
532
|
+
} },
|
|
533
|
+
required: ["text"]
|
|
534
|
+
}
|
|
535
|
+
} }), this.buildEntry(`/${botName}/conversations/${convId}/.actions/typing`, { meta: {
|
|
536
|
+
description: "Show typing indicator in this conversation",
|
|
537
|
+
inputSchema: {
|
|
538
|
+
type: "object",
|
|
539
|
+
properties: {},
|
|
540
|
+
required: []
|
|
541
|
+
}
|
|
542
|
+
} })] };
|
|
543
|
+
}
|
|
544
|
+
async execSend(ctx, args) {
|
|
545
|
+
const { botName, convId } = ctx.params;
|
|
546
|
+
const client = this._getClient(botName);
|
|
547
|
+
if (!client) throw new Error(`Bot "${botName}" not found`);
|
|
548
|
+
const text = String(args.text ?? "");
|
|
549
|
+
const { text: _t, ...sendOpts } = args;
|
|
550
|
+
return {
|
|
551
|
+
success: true,
|
|
552
|
+
data: await this.sendMessage(client, convId, text, sendOpts)
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
async execTyping(ctx) {
|
|
556
|
+
const { botName, convId } = ctx.params;
|
|
557
|
+
const client = this._getClient(botName);
|
|
558
|
+
if (!client) throw new Error(`Bot "${botName}" not found`);
|
|
559
|
+
await this.sendTypingIndicator(client, convId);
|
|
560
|
+
return {
|
|
561
|
+
success: true,
|
|
562
|
+
data: { ok: true }
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/")], BaseMessageProvider.prototype, "listRoot", null);
|
|
567
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/:botName")], BaseMessageProvider.prototype, "listBot", null);
|
|
568
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/:botName/conversations")], BaseMessageProvider.prototype, "listConversations", null);
|
|
569
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/:botName/conversations/:convId")], BaseMessageProvider.prototype, "listConversationChildren", null);
|
|
570
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/:botName/conversations/:convId/messages")], BaseMessageProvider.prototype, "listMessages", null);
|
|
571
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/:botName/conversations/:convId/messages/:msgId")], BaseMessageProvider.prototype, "listMessageChildren", null);
|
|
572
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/")], BaseMessageProvider.prototype, "readRoot", null);
|
|
573
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:botName")], BaseMessageProvider.prototype, "readBot", null);
|
|
574
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:botName/ctl")], BaseMessageProvider.prototype, "readCtl", null);
|
|
575
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:botName/conversations")], BaseMessageProvider.prototype, "readConversationsDir", null);
|
|
576
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:botName/conversations/:convId")], BaseMessageProvider.prototype, "readConversation", null);
|
|
577
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:botName/conversations/:convId/messages")], BaseMessageProvider.prototype, "readMessagesDir", null);
|
|
578
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:botName/conversations/:convId/messages/:msgId")], BaseMessageProvider.prototype, "readMessage", null);
|
|
579
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/.meta")], BaseMessageProvider.prototype, "readRootMeta", null);
|
|
580
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/.meta/.capabilities")], BaseMessageProvider.prototype, "readCapabilities", null);
|
|
581
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:botName/.meta")], BaseMessageProvider.prototype, "readBotMeta", null);
|
|
582
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:botName/conversations/.meta")], BaseMessageProvider.prototype, "readConversationsMeta", null);
|
|
583
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:botName/conversations/:convId/.meta")], BaseMessageProvider.prototype, "readConversationMeta", null);
|
|
584
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:botName/conversations/:convId/messages/.meta")], BaseMessageProvider.prototype, "readMessagesMeta", null);
|
|
585
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:botName/conversations/:convId/messages/:msgId/.meta")], BaseMessageProvider.prototype, "readMsgMeta", null);
|
|
586
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/")], BaseMessageProvider.prototype, "explainRoot", null);
|
|
587
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/:botName")], BaseMessageProvider.prototype, "explainBot", null);
|
|
588
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/:botName/conversations/:convId")], BaseMessageProvider.prototype, "explainConversation", null);
|
|
589
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/:botName/conversations/:convId/messages/:msgId")], BaseMessageProvider.prototype, "explainMessage", null);
|
|
590
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Actions)("/")], BaseMessageProvider.prototype, "listRootActions", null);
|
|
591
|
+
require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/", "add-bot")], BaseMessageProvider.prototype, "execAddBot", null);
|
|
592
|
+
require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/", "remove-bot")], BaseMessageProvider.prototype, "execRemoveBot", null);
|
|
593
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Actions)("/:botName/conversations/:convId")], BaseMessageProvider.prototype, "listConversationActions", null);
|
|
594
|
+
require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/:botName/conversations/:convId", "send")], BaseMessageProvider.prototype, "execSend", null);
|
|
595
|
+
require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/:botName/conversations/:convId", "typing")], BaseMessageProvider.prototype, "execTyping", null);
|
|
596
|
+
|
|
597
|
+
//#endregion
|
|
598
|
+
exports.BaseMessageProvider = BaseMessageProvider;
|