@poncho-ai/messaging 0.7.6 → 0.7.8
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/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.js +37 -12
- package/package.json +1 -1
- package/src/adapters/telegram/index.ts +46 -16
- package/src/bridge.ts +8 -0
- package/src/types.ts +14 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @poncho-ai/messaging@0.7.
|
|
2
|
+
> @poncho-ai/messaging@0.7.8 build /home/runner/work/poncho-ai/poncho-ai/packages/messaging
|
|
3
3
|
> tsup src/index.ts --format esm --dts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
[34mCLI[39m tsup v8.5.1
|
|
8
8
|
[34mCLI[39m Target: es2022
|
|
9
9
|
[34mESM[39m Build start
|
|
10
|
-
[32mESM[39m [1mdist/index.js [22m[32m51.
|
|
11
|
-
[32mESM[39m ⚡️ Build success in
|
|
10
|
+
[32mESM[39m [1mdist/index.js [22m[32m51.91 KB[39m
|
|
11
|
+
[32mESM[39m ⚡️ Build success in 49ms
|
|
12
12
|
[34mDTS[39m Build start
|
|
13
|
-
[32mDTS[39m ⚡️ Build success in
|
|
14
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m11.
|
|
13
|
+
[32mDTS[39m ⚡️ Build success in 5402ms
|
|
14
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m11.66 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @poncho-ai/messaging
|
|
2
2
|
|
|
3
|
+
## 0.7.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`30026c5`](https://github.com/cesr/poncho-ai/commit/30026c5eba3f714bb80c2402c5e8f32c6fd38d87) Thanks [@cesr](https://github.com/cesr)! - Fix Telegram conversation instability on serverless: use stable platformThreadId instead of in-memory session counter.
|
|
8
|
+
|
|
9
|
+
## 0.7.7
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#61](https://github.com/cesr/poncho-ai/pull/61) [`0a51abe`](https://github.com/cesr/poncho-ai/commit/0a51abec12191397fd36ab1fd4feca7460489e33) Thanks [@cesr](https://github.com/cesr)! - Fix /new command on Telegram in serverless environments: persist conversation reset to the store so it survives cold starts.
|
|
14
|
+
|
|
3
15
|
## 0.7.6
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ interface IncomingMessage {
|
|
|
26
26
|
raw: unknown;
|
|
27
27
|
}
|
|
28
28
|
type IncomingMessageHandler = (message: IncomingMessage) => Promise<void>;
|
|
29
|
+
type ResetHandler = (platform: string, threadRef: ThreadRef) => Promise<void>;
|
|
29
30
|
type RouteHandler = (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;
|
|
30
31
|
type RouteRegistrar = (method: "GET" | "POST", path: string, handler: RouteHandler) => void;
|
|
31
32
|
interface MessagingAdapter {
|
|
@@ -43,6 +44,8 @@ interface MessagingAdapter {
|
|
|
43
44
|
initialize(): Promise<void>;
|
|
44
45
|
/** Set the handler that processes incoming messages. */
|
|
45
46
|
onMessage(handler: IncomingMessageHandler): void;
|
|
47
|
+
/** Set the handler called when a user resets the conversation (e.g. /new). */
|
|
48
|
+
onReset?(handler: ResetHandler): void;
|
|
46
49
|
/** Post a reply back to the originating thread. */
|
|
47
50
|
sendReply(threadRef: ThreadRef, content: string, options?: {
|
|
48
51
|
files?: FileAttachment[];
|
|
@@ -89,6 +92,11 @@ interface AgentRunner {
|
|
|
89
92
|
steps?: number;
|
|
90
93
|
maxSteps?: number;
|
|
91
94
|
}>;
|
|
95
|
+
/**
|
|
96
|
+
* Reset a conversation by clearing its messages, making the next
|
|
97
|
+
* interaction start fresh while keeping the same conversation ID.
|
|
98
|
+
*/
|
|
99
|
+
resetConversation?(conversationId: string): Promise<void>;
|
|
92
100
|
}
|
|
93
101
|
interface AgentBridgeOptions {
|
|
94
102
|
adapter: MessagingAdapter;
|
|
@@ -223,13 +231,14 @@ declare class TelegramAdapter implements MessagingAdapter {
|
|
|
223
231
|
private readonly webhookSecretEnv;
|
|
224
232
|
private readonly allowedUserIds;
|
|
225
233
|
private handler;
|
|
234
|
+
private resetHandler;
|
|
226
235
|
private approvalDecisionHandler;
|
|
227
|
-
private readonly sessionCounters;
|
|
228
236
|
private readonly approvalMessageIds;
|
|
229
237
|
private lastUpdateId;
|
|
230
238
|
constructor(options?: TelegramAdapterOptions);
|
|
231
239
|
initialize(): Promise<void>;
|
|
232
240
|
onMessage(handler: IncomingMessageHandler): void;
|
|
241
|
+
onReset(handler: ResetHandler): void;
|
|
233
242
|
registerRoutes(router: RouteRegistrar): void;
|
|
234
243
|
sendReply(threadRef: ThreadRef, content: string, options?: {
|
|
235
244
|
files?: FileAttachment[];
|
|
@@ -242,7 +251,6 @@ declare class TelegramAdapter implements MessagingAdapter {
|
|
|
242
251
|
updateApprovalMessage(approvalId: string, decision: "approved" | "denied", tool: string): Promise<void>;
|
|
243
252
|
private handleRequest;
|
|
244
253
|
private handleCallbackQuery;
|
|
245
|
-
private sessionKey;
|
|
246
254
|
private extractFiles;
|
|
247
255
|
}
|
|
248
256
|
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,12 @@ var AgentBridge = class {
|
|
|
30
30
|
this.waitUntil(processing);
|
|
31
31
|
return processing;
|
|
32
32
|
});
|
|
33
|
+
if (this.adapter.onReset && this.runner.resetConversation) {
|
|
34
|
+
this.adapter.onReset(async (platform, threadRef) => {
|
|
35
|
+
const conversationId = conversationIdFromThread(platform, threadRef);
|
|
36
|
+
await this.runner.resetConversation(conversationId);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
33
39
|
await this.adapter.initialize();
|
|
34
40
|
}
|
|
35
41
|
async handleMessage(message) {
|
|
@@ -1186,6 +1192,12 @@ var stripMention2 = (text, entities, botUsername, botId) => {
|
|
|
1186
1192
|
// src/adapters/telegram/index.ts
|
|
1187
1193
|
var TYPING_INTERVAL_MS = 4e3;
|
|
1188
1194
|
var NEW_COMMAND_RE = /^\/new(?:@(\S+))?$/i;
|
|
1195
|
+
var parseMessageThreadId = (platformThreadId, chatId) => {
|
|
1196
|
+
const parts = platformThreadId.split(":");
|
|
1197
|
+
if (parts.length !== 3 || parts[0] !== chatId) return void 0;
|
|
1198
|
+
const threadId = Number(parts[1]);
|
|
1199
|
+
return Number.isInteger(threadId) ? threadId : void 0;
|
|
1200
|
+
};
|
|
1189
1201
|
var collectBody3 = (req) => new Promise((resolve, reject) => {
|
|
1190
1202
|
const chunks = [];
|
|
1191
1203
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
@@ -1204,8 +1216,8 @@ var TelegramAdapter = class {
|
|
|
1204
1216
|
webhookSecretEnv;
|
|
1205
1217
|
allowedUserIds;
|
|
1206
1218
|
handler;
|
|
1219
|
+
resetHandler;
|
|
1207
1220
|
approvalDecisionHandler;
|
|
1208
|
-
sessionCounters = /* @__PURE__ */ new Map();
|
|
1209
1221
|
approvalMessageIds = /* @__PURE__ */ new Map();
|
|
1210
1222
|
lastUpdateId = 0;
|
|
1211
1223
|
constructor(options = {}) {
|
|
@@ -1231,6 +1243,9 @@ var TelegramAdapter = class {
|
|
|
1231
1243
|
onMessage(handler) {
|
|
1232
1244
|
this.handler = handler;
|
|
1233
1245
|
}
|
|
1246
|
+
onReset(handler) {
|
|
1247
|
+
this.resetHandler = handler;
|
|
1248
|
+
}
|
|
1234
1249
|
registerRoutes(router) {
|
|
1235
1250
|
router(
|
|
1236
1251
|
"POST",
|
|
@@ -1241,11 +1256,16 @@ var TelegramAdapter = class {
|
|
|
1241
1256
|
async sendReply(threadRef, content, options) {
|
|
1242
1257
|
const chatId = threadRef.channelId;
|
|
1243
1258
|
const replyTo = threadRef.messageId ? Number(threadRef.messageId) : void 0;
|
|
1259
|
+
const messageThreadId = parseMessageThreadId(
|
|
1260
|
+
threadRef.platformThreadId,
|
|
1261
|
+
chatId
|
|
1262
|
+
);
|
|
1244
1263
|
if (content) {
|
|
1245
1264
|
const chunks = splitMessage2(content);
|
|
1246
1265
|
for (const chunk of chunks) {
|
|
1247
1266
|
await sendMessage(this.botToken, chatId, chunk, {
|
|
1248
|
-
reply_to_message_id: replyTo
|
|
1267
|
+
reply_to_message_id: replyTo,
|
|
1268
|
+
message_thread_id: messageThreadId
|
|
1249
1269
|
});
|
|
1250
1270
|
}
|
|
1251
1271
|
}
|
|
@@ -1254,11 +1274,13 @@ var TelegramAdapter = class {
|
|
|
1254
1274
|
if (file.mediaType.startsWith("image/")) {
|
|
1255
1275
|
await sendPhoto(this.botToken, chatId, file.data, {
|
|
1256
1276
|
reply_to_message_id: replyTo,
|
|
1277
|
+
message_thread_id: messageThreadId,
|
|
1257
1278
|
filename: file.filename
|
|
1258
1279
|
});
|
|
1259
1280
|
} else {
|
|
1260
1281
|
await sendDocument(this.botToken, chatId, file.data, {
|
|
1261
1282
|
reply_to_message_id: replyTo,
|
|
1283
|
+
message_thread_id: messageThreadId,
|
|
1262
1284
|
filename: file.filename,
|
|
1263
1285
|
mediaType: file.mediaType
|
|
1264
1286
|
});
|
|
@@ -1413,11 +1435,20 @@ ${inputSummary}` : "(no input)"
|
|
|
1413
1435
|
res.end();
|
|
1414
1436
|
return;
|
|
1415
1437
|
}
|
|
1416
|
-
const key2 = this.sessionKey(message);
|
|
1417
|
-
const current = this.sessionCounters.get(key2) ?? 0;
|
|
1418
|
-
this.sessionCounters.set(key2, current + 1);
|
|
1419
1438
|
res.writeHead(200);
|
|
1420
1439
|
res.end();
|
|
1440
|
+
if (this.resetHandler) {
|
|
1441
|
+
const topicId2 = message.message_thread_id;
|
|
1442
|
+
const threadId = topicId2 ? `${chatId}:${topicId2}:0` : `${chatId}:0`;
|
|
1443
|
+
try {
|
|
1444
|
+
await this.resetHandler("telegram", {
|
|
1445
|
+
channelId: chatId,
|
|
1446
|
+
platformThreadId: threadId
|
|
1447
|
+
});
|
|
1448
|
+
} catch (err) {
|
|
1449
|
+
console.error("[telegram-adapter] reset handler error:", err instanceof Error ? err.message : err);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1421
1452
|
await sendMessage(
|
|
1422
1453
|
this.botToken,
|
|
1423
1454
|
chatId,
|
|
@@ -1446,10 +1477,8 @@ ${inputSummary}` : "(no input)"
|
|
|
1446
1477
|
res.end();
|
|
1447
1478
|
if (!this.handler) return;
|
|
1448
1479
|
const files = await this.extractFiles(message);
|
|
1449
|
-
const key = this.sessionKey(message);
|
|
1450
|
-
const session = this.sessionCounters.get(key) ?? 0;
|
|
1451
1480
|
const topicId = message.message_thread_id;
|
|
1452
|
-
const platformThreadId = topicId ? `${chatId}:${topicId}
|
|
1481
|
+
const platformThreadId = topicId ? `${chatId}:${topicId}:0` : `${chatId}:0`;
|
|
1453
1482
|
const userId = String(message.from?.id ?? "unknown");
|
|
1454
1483
|
const userName = [message.from?.first_name, message.from?.last_name].filter(Boolean).join(" ") || void 0;
|
|
1455
1484
|
const ponchoMessage = {
|
|
@@ -1505,10 +1534,6 @@ ${inputSummary}` : "(no input)"
|
|
|
1505
1534
|
// -----------------------------------------------------------------------
|
|
1506
1535
|
// Helpers
|
|
1507
1536
|
// -----------------------------------------------------------------------
|
|
1508
|
-
sessionKey(message) {
|
|
1509
|
-
const chatId = String(message.chat.id);
|
|
1510
|
-
return message.message_thread_id ? `${chatId}:${message.message_thread_id}` : chatId;
|
|
1511
|
-
}
|
|
1512
1537
|
async extractFiles(message) {
|
|
1513
1538
|
const files = [];
|
|
1514
1539
|
try {
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
IncomingMessage as PonchoIncomingMessage,
|
|
5
5
|
IncomingMessageHandler,
|
|
6
6
|
MessagingAdapter,
|
|
7
|
+
ResetHandler,
|
|
7
8
|
RouteRegistrar,
|
|
8
9
|
ThreadRef,
|
|
9
10
|
} from "../../types.js";
|
|
@@ -30,6 +31,19 @@ import {
|
|
|
30
31
|
const TYPING_INTERVAL_MS = 4_000;
|
|
31
32
|
const NEW_COMMAND_RE = /^\/new(?:@(\S+))?$/i;
|
|
32
33
|
|
|
34
|
+
const parseMessageThreadId = (
|
|
35
|
+
platformThreadId: string,
|
|
36
|
+
chatId: string,
|
|
37
|
+
): number | undefined => {
|
|
38
|
+
const parts = platformThreadId.split(":");
|
|
39
|
+
// Telegram thread format:
|
|
40
|
+
// - non-topic chats: `${chatId}:${session}`
|
|
41
|
+
// - forum topics: `${chatId}:${message_thread_id}:${session}`
|
|
42
|
+
if (parts.length !== 3 || parts[0] !== chatId) return undefined;
|
|
43
|
+
const threadId = Number(parts[1]);
|
|
44
|
+
return Number.isInteger(threadId) ? threadId : undefined;
|
|
45
|
+
};
|
|
46
|
+
|
|
33
47
|
export interface TelegramApprovalInfo {
|
|
34
48
|
approvalId: string;
|
|
35
49
|
tool: string;
|
|
@@ -69,8 +83,8 @@ export class TelegramAdapter implements MessagingAdapter {
|
|
|
69
83
|
private readonly webhookSecretEnv: string;
|
|
70
84
|
private readonly allowedUserIds: number[] | undefined;
|
|
71
85
|
private handler: IncomingMessageHandler | undefined;
|
|
86
|
+
private resetHandler: ResetHandler | undefined;
|
|
72
87
|
private approvalDecisionHandler: TelegramApprovalDecisionHandler | undefined;
|
|
73
|
-
private readonly sessionCounters = new Map<string, number>();
|
|
74
88
|
private readonly approvalMessageIds = new Map<string, { chatId: string; messageId: number }>();
|
|
75
89
|
private lastUpdateId = 0;
|
|
76
90
|
|
|
@@ -107,6 +121,10 @@ export class TelegramAdapter implements MessagingAdapter {
|
|
|
107
121
|
this.handler = handler;
|
|
108
122
|
}
|
|
109
123
|
|
|
124
|
+
onReset(handler: ResetHandler): void {
|
|
125
|
+
this.resetHandler = handler;
|
|
126
|
+
}
|
|
127
|
+
|
|
110
128
|
registerRoutes(router: RouteRegistrar): void {
|
|
111
129
|
router("POST", "/api/messaging/telegram", (req, res) =>
|
|
112
130
|
this.handleRequest(req, res),
|
|
@@ -122,12 +140,17 @@ export class TelegramAdapter implements MessagingAdapter {
|
|
|
122
140
|
const replyTo = threadRef.messageId
|
|
123
141
|
? Number(threadRef.messageId)
|
|
124
142
|
: undefined;
|
|
143
|
+
const messageThreadId = parseMessageThreadId(
|
|
144
|
+
threadRef.platformThreadId,
|
|
145
|
+
chatId,
|
|
146
|
+
);
|
|
125
147
|
|
|
126
148
|
if (content) {
|
|
127
149
|
const chunks = splitMessage(content);
|
|
128
150
|
for (const chunk of chunks) {
|
|
129
151
|
await sendMessage(this.botToken, chatId, chunk, {
|
|
130
152
|
reply_to_message_id: replyTo,
|
|
153
|
+
message_thread_id: messageThreadId,
|
|
131
154
|
});
|
|
132
155
|
}
|
|
133
156
|
}
|
|
@@ -137,11 +160,13 @@ export class TelegramAdapter implements MessagingAdapter {
|
|
|
137
160
|
if (file.mediaType.startsWith("image/")) {
|
|
138
161
|
await sendPhoto(this.botToken, chatId, file.data, {
|
|
139
162
|
reply_to_message_id: replyTo,
|
|
163
|
+
message_thread_id: messageThreadId,
|
|
140
164
|
filename: file.filename,
|
|
141
165
|
});
|
|
142
166
|
} else {
|
|
143
167
|
await sendDocument(this.botToken, chatId, file.data, {
|
|
144
168
|
reply_to_message_id: replyTo,
|
|
169
|
+
message_thread_id: messageThreadId,
|
|
145
170
|
filename: file.filename,
|
|
146
171
|
mediaType: file.mediaType,
|
|
147
172
|
});
|
|
@@ -348,13 +373,25 @@ export class TelegramAdapter implements MessagingAdapter {
|
|
|
348
373
|
return;
|
|
349
374
|
}
|
|
350
375
|
|
|
351
|
-
const key = this.sessionKey(message);
|
|
352
|
-
const current = this.sessionCounters.get(key) ?? 0;
|
|
353
|
-
this.sessionCounters.set(key, current + 1);
|
|
354
|
-
|
|
355
376
|
res.writeHead(200);
|
|
356
377
|
res.end();
|
|
357
378
|
|
|
379
|
+
// Clear conversation in the store so the next message starts fresh.
|
|
380
|
+
if (this.resetHandler) {
|
|
381
|
+
const topicId = message.message_thread_id;
|
|
382
|
+
const threadId = topicId
|
|
383
|
+
? `${chatId}:${topicId}:0`
|
|
384
|
+
: `${chatId}:0`;
|
|
385
|
+
try {
|
|
386
|
+
await this.resetHandler("telegram", {
|
|
387
|
+
channelId: chatId,
|
|
388
|
+
platformThreadId: threadId,
|
|
389
|
+
});
|
|
390
|
+
} catch (err) {
|
|
391
|
+
console.error("[telegram-adapter] reset handler error:", err instanceof Error ? err.message : err);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
358
395
|
await sendMessage(
|
|
359
396
|
this.botToken,
|
|
360
397
|
chatId,
|
|
@@ -396,12 +433,12 @@ export class TelegramAdapter implements MessagingAdapter {
|
|
|
396
433
|
const files = await this.extractFiles(message);
|
|
397
434
|
|
|
398
435
|
// -- Build thread ref -------------------------------------------------
|
|
399
|
-
|
|
400
|
-
|
|
436
|
+
// Always use a fixed session component so the conversationId is stable
|
|
437
|
+
// across serverless cold starts. /new resets via the store instead.
|
|
401
438
|
const topicId = message.message_thread_id;
|
|
402
439
|
const platformThreadId = topicId
|
|
403
|
-
? `${chatId}:${topicId}
|
|
404
|
-
: `${chatId}
|
|
440
|
+
? `${chatId}:${topicId}:0`
|
|
441
|
+
: `${chatId}:0`;
|
|
405
442
|
|
|
406
443
|
const userId = String(message.from?.id ?? "unknown");
|
|
407
444
|
const userName =
|
|
@@ -476,13 +513,6 @@ export class TelegramAdapter implements MessagingAdapter {
|
|
|
476
513
|
// Helpers
|
|
477
514
|
// -----------------------------------------------------------------------
|
|
478
515
|
|
|
479
|
-
private sessionKey(message: TelegramMessage): string {
|
|
480
|
-
const chatId = String(message.chat.id);
|
|
481
|
-
return message.message_thread_id
|
|
482
|
-
? `${chatId}:${message.message_thread_id}`
|
|
483
|
-
: chatId;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
516
|
private async extractFiles(
|
|
487
517
|
message: TelegramMessage,
|
|
488
518
|
): Promise<FileAttachment[]> {
|
package/src/bridge.ts
CHANGED
|
@@ -50,6 +50,14 @@ export class AgentBridge {
|
|
|
50
50
|
this.waitUntil(processing);
|
|
51
51
|
return processing;
|
|
52
52
|
});
|
|
53
|
+
|
|
54
|
+
if (this.adapter.onReset && this.runner.resetConversation) {
|
|
55
|
+
this.adapter.onReset(async (platform, threadRef) => {
|
|
56
|
+
const conversationId = conversationIdFromThread(platform, threadRef);
|
|
57
|
+
await this.runner.resetConversation!(conversationId);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
53
61
|
await this.adapter.initialize();
|
|
54
62
|
}
|
|
55
63
|
|
package/src/types.ts
CHANGED
|
@@ -33,6 +33,11 @@ export type IncomingMessageHandler = (
|
|
|
33
33
|
message: IncomingMessage,
|
|
34
34
|
) => Promise<void>;
|
|
35
35
|
|
|
36
|
+
export type ResetHandler = (
|
|
37
|
+
platform: string,
|
|
38
|
+
threadRef: ThreadRef,
|
|
39
|
+
) => Promise<void>;
|
|
40
|
+
|
|
36
41
|
// ---------------------------------------------------------------------------
|
|
37
42
|
// Route registration (adapter ↔ HTTP server contract)
|
|
38
43
|
// ---------------------------------------------------------------------------
|
|
@@ -73,6 +78,9 @@ export interface MessagingAdapter {
|
|
|
73
78
|
/** Set the handler that processes incoming messages. */
|
|
74
79
|
onMessage(handler: IncomingMessageHandler): void;
|
|
75
80
|
|
|
81
|
+
/** Set the handler called when a user resets the conversation (e.g. /new). */
|
|
82
|
+
onReset?(handler: ResetHandler): void;
|
|
83
|
+
|
|
76
84
|
/** Post a reply back to the originating thread. */
|
|
77
85
|
sendReply(
|
|
78
86
|
threadRef: ThreadRef,
|
|
@@ -133,6 +141,12 @@ export interface AgentRunner {
|
|
|
133
141
|
steps?: number;
|
|
134
142
|
maxSteps?: number;
|
|
135
143
|
}>;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Reset a conversation by clearing its messages, making the next
|
|
147
|
+
* interaction start fresh while keeping the same conversation ID.
|
|
148
|
+
*/
|
|
149
|
+
resetConversation?(conversationId: string): Promise<void>;
|
|
136
150
|
}
|
|
137
151
|
|
|
138
152
|
// ---------------------------------------------------------------------------
|