@diegoaltoworks/chatter 0.57.0 → 0.58.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/dist/channels/index.js +18 -3
- package/dist/channels/index.mjs +18 -3
- package/dist/channels/pipeline.d.ts +8 -0
- package/dist/channels/pipeline.d.ts.map +1 -1
- package/dist/channels/telegram/channel.d.ts +7 -0
- package/dist/channels/telegram/channel.d.ts.map +1 -1
- package/dist/channels/telegram/index.js +18 -3
- package/dist/channels/telegram/index.mjs +18 -3
- package/dist/channels/whatsapp/inbound.d.ts +6 -0
- package/dist/channels/whatsapp/inbound.d.ts.map +1 -1
- package/dist/channels/whatsapp/index.js +18 -3
- package/dist/channels/whatsapp/index.mjs +18 -3
- package/dist/history/index.d.ts +1 -0
- package/dist/history/index.d.ts.map +1 -1
- package/dist/history/index.js +23 -2
- package/dist/history/index.mjs +23 -2
- package/dist/history/tursoStore.d.ts +13 -1
- package/dist/history/tursoStore.d.ts.map +1 -1
- package/dist/history/types.d.ts +2 -0
- package/dist/history/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/channels/index.js
CHANGED
|
@@ -274,6 +274,16 @@ async function resolvePersonaLayer(config, ctx) {
|
|
|
274
274
|
return void 0;
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
|
+
async function isHistoryEnabled(config, sender) {
|
|
278
|
+
const predicate = config.history?.historyEnabledFor;
|
|
279
|
+
if (!predicate) return true;
|
|
280
|
+
try {
|
|
281
|
+
return await predicate(sender);
|
|
282
|
+
} catch (error) {
|
|
283
|
+
config.logger?.error("historyEnabledFor threw; disabling history for this turn", error);
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
277
287
|
function createInboundPipeline(deps, config) {
|
|
278
288
|
const mutedChats = /* @__PURE__ */ new Set();
|
|
279
289
|
const now = config.now ?? Date.now;
|
|
@@ -313,12 +323,15 @@ function createInboundPipeline(deps, config) {
|
|
|
313
323
|
}
|
|
314
324
|
const personaLayer = await resolvePersonaLayer(config, { sender, text: msg.text });
|
|
315
325
|
const buckets = await resolveBuckets({ mode, sender, bucketsFor: config.bucketsFor });
|
|
316
|
-
const
|
|
326
|
+
const historyEnabled = config.history ? await isHistoryEnabled(config, sender) : false;
|
|
327
|
+
const priorTurns = config.history && historyEnabled ? await config.history.store.load(
|
|
317
328
|
conversationId,
|
|
318
329
|
config.history.limit ?? DEFAULT_HISTORY_LIMIT
|
|
319
330
|
) : [];
|
|
320
331
|
const messages = [...priorTurns, { role: "user", content: msg.text }];
|
|
321
|
-
|
|
332
|
+
if (historyEnabled) {
|
|
333
|
+
await config.history?.store.append(conversationId, { role: "user", content: msg.text });
|
|
334
|
+
}
|
|
322
335
|
const { system } = await prepareChat({
|
|
323
336
|
store: deps.store,
|
|
324
337
|
prompts: deps.prompts,
|
|
@@ -350,7 +363,9 @@ function createInboundPipeline(deps, config) {
|
|
|
350
363
|
if (!content) {
|
|
351
364
|
return { action: "ignore" };
|
|
352
365
|
}
|
|
353
|
-
|
|
366
|
+
if (historyEnabled) {
|
|
367
|
+
await config.history?.store.append(conversationId, { role: "assistant", content });
|
|
368
|
+
}
|
|
354
369
|
await turn.reply.sendAnswer(msg.chatId, content);
|
|
355
370
|
return { action: "reply", content };
|
|
356
371
|
};
|
package/dist/channels/index.mjs
CHANGED
|
@@ -241,6 +241,16 @@ async function resolvePersonaLayer(config, ctx) {
|
|
|
241
241
|
return void 0;
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
|
+
async function isHistoryEnabled(config, sender) {
|
|
245
|
+
const predicate = config.history?.historyEnabledFor;
|
|
246
|
+
if (!predicate) return true;
|
|
247
|
+
try {
|
|
248
|
+
return await predicate(sender);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
config.logger?.error("historyEnabledFor threw; disabling history for this turn", error);
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
244
254
|
function createInboundPipeline(deps, config) {
|
|
245
255
|
const mutedChats = /* @__PURE__ */ new Set();
|
|
246
256
|
const now = config.now ?? Date.now;
|
|
@@ -280,12 +290,15 @@ function createInboundPipeline(deps, config) {
|
|
|
280
290
|
}
|
|
281
291
|
const personaLayer = await resolvePersonaLayer(config, { sender, text: msg.text });
|
|
282
292
|
const buckets = await resolveBuckets({ mode, sender, bucketsFor: config.bucketsFor });
|
|
283
|
-
const
|
|
293
|
+
const historyEnabled = config.history ? await isHistoryEnabled(config, sender) : false;
|
|
294
|
+
const priorTurns = config.history && historyEnabled ? await config.history.store.load(
|
|
284
295
|
conversationId,
|
|
285
296
|
config.history.limit ?? DEFAULT_HISTORY_LIMIT
|
|
286
297
|
) : [];
|
|
287
298
|
const messages = [...priorTurns, { role: "user", content: msg.text }];
|
|
288
|
-
|
|
299
|
+
if (historyEnabled) {
|
|
300
|
+
await config.history?.store.append(conversationId, { role: "user", content: msg.text });
|
|
301
|
+
}
|
|
289
302
|
const { system } = await prepareChat({
|
|
290
303
|
store: deps.store,
|
|
291
304
|
prompts: deps.prompts,
|
|
@@ -317,7 +330,9 @@ function createInboundPipeline(deps, config) {
|
|
|
317
330
|
if (!content) {
|
|
318
331
|
return { action: "ignore" };
|
|
319
332
|
}
|
|
320
|
-
|
|
333
|
+
if (historyEnabled) {
|
|
334
|
+
await config.history?.store.append(conversationId, { role: "assistant", content });
|
|
335
|
+
}
|
|
321
336
|
await turn.reply.sendAnswer(msg.chatId, content);
|
|
322
337
|
return { action: "reply", content };
|
|
323
338
|
};
|
|
@@ -61,6 +61,14 @@ export interface InboundPipelineConfig {
|
|
|
61
61
|
store: HistoryStore;
|
|
62
62
|
/** Most recent turns to load per reply. @default 20 */
|
|
63
63
|
limit?: number;
|
|
64
|
+
/**
|
|
65
|
+
* Excludes a sender from history entirely — checked before both `load`
|
|
66
|
+
* and `append`, so an opted-out sender's turns are never read back and
|
|
67
|
+
* never written. A throw/rejection fails closed ("not enabled"): a
|
|
68
|
+
* broken predicate must never start recording a sender who may have
|
|
69
|
+
* opted out. @default every sender is enabled
|
|
70
|
+
*/
|
|
71
|
+
historyEnabledFor?: (sender: string) => boolean | Promise<boolean>;
|
|
64
72
|
};
|
|
65
73
|
/** Group chats eligible for a reply. Empty (default) = every group. Has no effect on DMs, which always reply. */
|
|
66
74
|
allowedChats?: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/channels/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EACL,KAAK,cAAc,EAIpB,MAAM,SAAS,CAAC;AAEjB,iNAAiN;AACjN,MAAM,WAAW,kBAAkB;IACjC,4CAA4C;IAC5C,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,kFAAkF;IAClF,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,0GAA0G;IAC1G,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,iHAAiH;IACjH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,kGAAkG;IAClG,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oGAAoG;IACpG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sGAAsG;IACtG,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KACd,KAAK,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACvD,gFAAgF;IAChF,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,YAAY,CAAC;QACpB,uDAAuD;QACvD,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/channels/pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -50,7 +50,14 @@ export interface TelegramChannelConfig {
|
|
|
50
50
|
/** Off by default — the channel stays single-turn until a store is configured. */
|
|
51
51
|
history?: {
|
|
52
52
|
store: HistoryStore;
|
|
53
|
+
/** Most recent turns to load per reply. @default 20 */
|
|
53
54
|
limit?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Excludes a sender from history entirely — see
|
|
57
|
+
* `InboundPipelineConfig.history.historyEnabledFor` in `./channels`.
|
|
58
|
+
* @default every sender is enabled
|
|
59
|
+
*/
|
|
60
|
+
historyEnabledFor?: (sender: string) => boolean | Promise<boolean>;
|
|
54
61
|
};
|
|
55
62
|
muteRegex?: RegExp;
|
|
56
63
|
unmuteRegex?: RegExp;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/channels/telegram/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAGxC,OAAO,EAAqB,KAAK,WAAW,EAAuB,MAAM,OAAO,CAAC;AAOjF,MAAM,WAAW,qBAAqB;IACpC,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;IACjB,8GAA8G;IAC9G,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iHAAiH;IACjH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,0IAA0I;IAC1I,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,iJAAiJ;IACjJ,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,kIAAkI;IAClI,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kIAAkI;IAClI,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4GAA4G;IAC5G,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KACd,KAAK,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACvD,kFAAkF;IAClF,OAAO,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/channels/telegram/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAGxC,OAAO,EAAqB,KAAK,WAAW,EAAuB,MAAM,OAAO,CAAC;AAOjF,MAAM,WAAW,qBAAqB;IACpC,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;IACjB,8GAA8G;IAC9G,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iHAAiH;IACjH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,0IAA0I;IAC1I,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,iJAAiJ;IACjJ,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,kIAAkI;IAClI,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kIAAkI;IAClI,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4GAA4G;IAC5G,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KACd,KAAK,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACvD,kFAAkF;IAClF,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,YAAY,CAAC;QACpB,uDAAuD;QACvD,KAAK,CAAC,EAAE,MAAM,CAAC;QACf;;;;WAIG;QACH,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KACpE,CAAC;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gHAAgH;IAChH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,cAAc,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,kBAAkB;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0GAA0G;IAC1G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iGAAiG;IACjG,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,mGAAmG;IACnG,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qJAAqJ;IACrJ,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,qEAAqE;IACrE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,uGAAuG;IACvG,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AASD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAoI5E"}
|
|
@@ -441,6 +441,16 @@ async function resolvePersonaLayer(config, ctx) {
|
|
|
441
441
|
return void 0;
|
|
442
442
|
}
|
|
443
443
|
}
|
|
444
|
+
async function isHistoryEnabled(config, sender) {
|
|
445
|
+
const predicate = config.history?.historyEnabledFor;
|
|
446
|
+
if (!predicate) return true;
|
|
447
|
+
try {
|
|
448
|
+
return await predicate(sender);
|
|
449
|
+
} catch (error) {
|
|
450
|
+
config.logger?.error("historyEnabledFor threw; disabling history for this turn", error);
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
444
454
|
function createInboundPipeline(deps, config) {
|
|
445
455
|
const mutedChats = /* @__PURE__ */ new Set();
|
|
446
456
|
const now = config.now ?? Date.now;
|
|
@@ -480,12 +490,15 @@ function createInboundPipeline(deps, config) {
|
|
|
480
490
|
}
|
|
481
491
|
const personaLayer = await resolvePersonaLayer(config, { sender, text: msg.text });
|
|
482
492
|
const buckets = await resolveBuckets({ mode, sender, bucketsFor: config.bucketsFor });
|
|
483
|
-
const
|
|
493
|
+
const historyEnabled = config.history ? await isHistoryEnabled(config, sender) : false;
|
|
494
|
+
const priorTurns = config.history && historyEnabled ? await config.history.store.load(
|
|
484
495
|
conversationId,
|
|
485
496
|
config.history.limit ?? DEFAULT_HISTORY_LIMIT
|
|
486
497
|
) : [];
|
|
487
498
|
const messages = [...priorTurns, { role: "user", content: msg.text }];
|
|
488
|
-
|
|
499
|
+
if (historyEnabled) {
|
|
500
|
+
await config.history?.store.append(conversationId, { role: "user", content: msg.text });
|
|
501
|
+
}
|
|
489
502
|
const { system } = await prepareChat({
|
|
490
503
|
store: deps.store,
|
|
491
504
|
prompts: deps.prompts,
|
|
@@ -517,7 +530,9 @@ function createInboundPipeline(deps, config) {
|
|
|
517
530
|
if (!content) {
|
|
518
531
|
return { action: "ignore" };
|
|
519
532
|
}
|
|
520
|
-
|
|
533
|
+
if (historyEnabled) {
|
|
534
|
+
await config.history?.store.append(conversationId, { role: "assistant", content });
|
|
535
|
+
}
|
|
521
536
|
await turn.reply.sendAnswer(msg.chatId, content);
|
|
522
537
|
return { action: "reply", content };
|
|
523
538
|
};
|
|
@@ -399,6 +399,16 @@ async function resolvePersonaLayer(config, ctx) {
|
|
|
399
399
|
return void 0;
|
|
400
400
|
}
|
|
401
401
|
}
|
|
402
|
+
async function isHistoryEnabled(config, sender) {
|
|
403
|
+
const predicate = config.history?.historyEnabledFor;
|
|
404
|
+
if (!predicate) return true;
|
|
405
|
+
try {
|
|
406
|
+
return await predicate(sender);
|
|
407
|
+
} catch (error) {
|
|
408
|
+
config.logger?.error("historyEnabledFor threw; disabling history for this turn", error);
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
402
412
|
function createInboundPipeline(deps, config) {
|
|
403
413
|
const mutedChats = /* @__PURE__ */ new Set();
|
|
404
414
|
const now = config.now ?? Date.now;
|
|
@@ -438,12 +448,15 @@ function createInboundPipeline(deps, config) {
|
|
|
438
448
|
}
|
|
439
449
|
const personaLayer = await resolvePersonaLayer(config, { sender, text: msg.text });
|
|
440
450
|
const buckets = await resolveBuckets({ mode, sender, bucketsFor: config.bucketsFor });
|
|
441
|
-
const
|
|
451
|
+
const historyEnabled = config.history ? await isHistoryEnabled(config, sender) : false;
|
|
452
|
+
const priorTurns = config.history && historyEnabled ? await config.history.store.load(
|
|
442
453
|
conversationId,
|
|
443
454
|
config.history.limit ?? DEFAULT_HISTORY_LIMIT
|
|
444
455
|
) : [];
|
|
445
456
|
const messages = [...priorTurns, { role: "user", content: msg.text }];
|
|
446
|
-
|
|
457
|
+
if (historyEnabled) {
|
|
458
|
+
await config.history?.store.append(conversationId, { role: "user", content: msg.text });
|
|
459
|
+
}
|
|
447
460
|
const { system } = await prepareChat({
|
|
448
461
|
store: deps.store,
|
|
449
462
|
prompts: deps.prompts,
|
|
@@ -475,7 +488,9 @@ function createInboundPipeline(deps, config) {
|
|
|
475
488
|
if (!content) {
|
|
476
489
|
return { action: "ignore" };
|
|
477
490
|
}
|
|
478
|
-
|
|
491
|
+
if (historyEnabled) {
|
|
492
|
+
await config.history?.store.append(conversationId, { role: "assistant", content });
|
|
493
|
+
}
|
|
479
494
|
await turn.reply.sendAnswer(msg.chatId, content);
|
|
480
495
|
return { action: "reply", content };
|
|
481
496
|
};
|
|
@@ -193,6 +193,12 @@ export interface WhatsAppInboundConfig {
|
|
|
193
193
|
store: HistoryStore;
|
|
194
194
|
/** Most recent turns to load per reply. @default 20 */
|
|
195
195
|
limit?: number;
|
|
196
|
+
/**
|
|
197
|
+
* Excludes a sender from history entirely — see
|
|
198
|
+
* `InboundPipelineConfig.history.historyEnabledFor` in `./channels`.
|
|
199
|
+
* @default every sender is enabled
|
|
200
|
+
*/
|
|
201
|
+
historyEnabledFor?: (sender: string) => boolean | Promise<boolean>;
|
|
196
202
|
};
|
|
197
203
|
now?: () => number;
|
|
198
204
|
/** Logger for gate/dispatch diagnostics. Default: a console logger writing to stderr. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/inbound.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/inbound.ts"],"names":[],"mappings":"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"}
|
|
@@ -852,6 +852,16 @@ async function resolvePersonaLayer(config, ctx) {
|
|
|
852
852
|
return void 0;
|
|
853
853
|
}
|
|
854
854
|
}
|
|
855
|
+
async function isHistoryEnabled(config, sender) {
|
|
856
|
+
const predicate = config.history?.historyEnabledFor;
|
|
857
|
+
if (!predicate) return true;
|
|
858
|
+
try {
|
|
859
|
+
return await predicate(sender);
|
|
860
|
+
} catch (error) {
|
|
861
|
+
config.logger?.error("historyEnabledFor threw; disabling history for this turn", error);
|
|
862
|
+
return false;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
855
865
|
function createInboundPipeline(deps, config) {
|
|
856
866
|
const mutedChats = /* @__PURE__ */ new Set();
|
|
857
867
|
const now = config.now ?? Date.now;
|
|
@@ -891,12 +901,15 @@ function createInboundPipeline(deps, config) {
|
|
|
891
901
|
}
|
|
892
902
|
const personaLayer = await resolvePersonaLayer(config, { sender, text: msg.text });
|
|
893
903
|
const buckets = await resolveBuckets({ mode, sender, bucketsFor: config.bucketsFor });
|
|
894
|
-
const
|
|
904
|
+
const historyEnabled = config.history ? await isHistoryEnabled(config, sender) : false;
|
|
905
|
+
const priorTurns = config.history && historyEnabled ? await config.history.store.load(
|
|
895
906
|
conversationId,
|
|
896
907
|
config.history.limit ?? DEFAULT_HISTORY_LIMIT
|
|
897
908
|
) : [];
|
|
898
909
|
const messages = [...priorTurns, { role: "user", content: msg.text }];
|
|
899
|
-
|
|
910
|
+
if (historyEnabled) {
|
|
911
|
+
await config.history?.store.append(conversationId, { role: "user", content: msg.text });
|
|
912
|
+
}
|
|
900
913
|
const { system } = await prepareChat({
|
|
901
914
|
store: deps.store,
|
|
902
915
|
prompts: deps.prompts,
|
|
@@ -928,7 +941,9 @@ function createInboundPipeline(deps, config) {
|
|
|
928
941
|
if (!content) {
|
|
929
942
|
return { action: "ignore" };
|
|
930
943
|
}
|
|
931
|
-
|
|
944
|
+
if (historyEnabled) {
|
|
945
|
+
await config.history?.store.append(conversationId, { role: "assistant", content });
|
|
946
|
+
}
|
|
932
947
|
await turn.reply.sendAnswer(msg.chatId, content);
|
|
933
948
|
return { action: "reply", content };
|
|
934
949
|
};
|
|
@@ -790,6 +790,16 @@ async function resolvePersonaLayer(config, ctx) {
|
|
|
790
790
|
return void 0;
|
|
791
791
|
}
|
|
792
792
|
}
|
|
793
|
+
async function isHistoryEnabled(config, sender) {
|
|
794
|
+
const predicate = config.history?.historyEnabledFor;
|
|
795
|
+
if (!predicate) return true;
|
|
796
|
+
try {
|
|
797
|
+
return await predicate(sender);
|
|
798
|
+
} catch (error) {
|
|
799
|
+
config.logger?.error("historyEnabledFor threw; disabling history for this turn", error);
|
|
800
|
+
return false;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
793
803
|
function createInboundPipeline(deps, config) {
|
|
794
804
|
const mutedChats = /* @__PURE__ */ new Set();
|
|
795
805
|
const now = config.now ?? Date.now;
|
|
@@ -829,12 +839,15 @@ function createInboundPipeline(deps, config) {
|
|
|
829
839
|
}
|
|
830
840
|
const personaLayer = await resolvePersonaLayer(config, { sender, text: msg.text });
|
|
831
841
|
const buckets = await resolveBuckets({ mode, sender, bucketsFor: config.bucketsFor });
|
|
832
|
-
const
|
|
842
|
+
const historyEnabled = config.history ? await isHistoryEnabled(config, sender) : false;
|
|
843
|
+
const priorTurns = config.history && historyEnabled ? await config.history.store.load(
|
|
833
844
|
conversationId,
|
|
834
845
|
config.history.limit ?? DEFAULT_HISTORY_LIMIT
|
|
835
846
|
) : [];
|
|
836
847
|
const messages = [...priorTurns, { role: "user", content: msg.text }];
|
|
837
|
-
|
|
848
|
+
if (historyEnabled) {
|
|
849
|
+
await config.history?.store.append(conversationId, { role: "user", content: msg.text });
|
|
850
|
+
}
|
|
838
851
|
const { system } = await prepareChat({
|
|
839
852
|
store: deps.store,
|
|
840
853
|
prompts: deps.prompts,
|
|
@@ -866,7 +879,9 @@ function createInboundPipeline(deps, config) {
|
|
|
866
879
|
if (!content) {
|
|
867
880
|
return { action: "ignore" };
|
|
868
881
|
}
|
|
869
|
-
|
|
882
|
+
if (historyEnabled) {
|
|
883
|
+
await config.history?.store.append(conversationId, { role: "assistant", content });
|
|
884
|
+
}
|
|
870
885
|
await turn.reply.sendAnswer(msg.chatId, content);
|
|
871
886
|
return { action: "reply", content };
|
|
872
887
|
};
|
package/dist/history/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @packageDocumentation
|
|
14
14
|
*/
|
|
15
|
+
export type { TursoHistoryStoreOptions } from "./tursoStore";
|
|
15
16
|
export { createTursoHistoryStore } from "./tursoStore";
|
|
16
17
|
export type { HistoryMessage, HistoryStore } from "./types";
|
|
17
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/history/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/history/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,YAAY,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/history/index.js
CHANGED
|
@@ -58,19 +58,32 @@ function ensureHistorySchema(client, tableName) {
|
|
|
58
58
|
var VALID_TABLE_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
59
59
|
var VALID_ROLES = /* @__PURE__ */ new Set(["user", "assistant"]);
|
|
60
60
|
var DEFAULT_MAX_PER_CONVERSATION = 200;
|
|
61
|
-
function createTursoHistoryStore(client, tableName = "chat_history", maxPerConversation = DEFAULT_MAX_PER_CONVERSATION) {
|
|
61
|
+
function createTursoHistoryStore(client, tableName = "chat_history", maxPerConversation = DEFAULT_MAX_PER_CONVERSATION, options) {
|
|
62
62
|
if (!VALID_TABLE_NAME.test(tableName)) {
|
|
63
63
|
throw new Error(`Invalid history store table name: ${tableName}`);
|
|
64
64
|
}
|
|
65
65
|
if (!Number.isInteger(maxPerConversation) || maxPerConversation < 1) {
|
|
66
66
|
throw new Error(`Invalid history store maxPerConversation: ${maxPerConversation}`);
|
|
67
67
|
}
|
|
68
|
+
if (options?.ttlMs !== void 0 && (!Number.isInteger(options.ttlMs) || options.ttlMs < 1)) {
|
|
69
|
+
throw new Error(`Invalid history store ttlMs: ${options.ttlMs}`);
|
|
70
|
+
}
|
|
71
|
+
const ttlMs = options?.ttlMs;
|
|
72
|
+
const now = options?.now ?? Date.now;
|
|
73
|
+
async function pruneExpired(conversationId) {
|
|
74
|
+
if (ttlMs === void 0) return;
|
|
75
|
+
await client.execute({
|
|
76
|
+
sql: `DELETE FROM ${tableName} WHERE conversation_id = ? AND created_at < ?`,
|
|
77
|
+
args: [conversationId, now() - ttlMs]
|
|
78
|
+
});
|
|
79
|
+
}
|
|
68
80
|
return {
|
|
69
81
|
async append(conversationId, message) {
|
|
70
82
|
await ensureHistorySchema(client, tableName);
|
|
83
|
+
await pruneExpired(conversationId);
|
|
71
84
|
await client.execute({
|
|
72
85
|
sql: `INSERT INTO ${tableName} (conversation_id, role, content, created_at) VALUES (?, ?, ?, ?)`,
|
|
73
|
-
args: [conversationId, message.role, message.content,
|
|
86
|
+
args: [conversationId, message.role, message.content, now()]
|
|
74
87
|
});
|
|
75
88
|
await client.execute({
|
|
76
89
|
sql: `DELETE FROM ${tableName} WHERE conversation_id = ? AND id NOT IN (
|
|
@@ -83,6 +96,7 @@ function createTursoHistoryStore(client, tableName = "chat_history", maxPerConve
|
|
|
83
96
|
const boundedLimit = Math.max(0, Math.trunc(limit));
|
|
84
97
|
if (boundedLimit === 0) return [];
|
|
85
98
|
await ensureHistorySchema(client, tableName);
|
|
99
|
+
await pruneExpired(conversationId);
|
|
86
100
|
const result = await client.execute({
|
|
87
101
|
sql: `SELECT role, content FROM ${tableName} WHERE conversation_id = ? ORDER BY id DESC LIMIT ?`,
|
|
88
102
|
args: [conversationId, boundedLimit]
|
|
@@ -91,6 +105,13 @@ function createTursoHistoryStore(client, tableName = "chat_history", maxPerConve
|
|
|
91
105
|
role: String(row.role),
|
|
92
106
|
content: String(row.content)
|
|
93
107
|
})).filter((row) => VALID_ROLES.has(row.role)).reverse();
|
|
108
|
+
},
|
|
109
|
+
async clear(conversationId) {
|
|
110
|
+
await ensureHistorySchema(client, tableName);
|
|
111
|
+
await client.execute({
|
|
112
|
+
sql: `DELETE FROM ${tableName} WHERE conversation_id = ?`,
|
|
113
|
+
args: [conversationId]
|
|
114
|
+
});
|
|
94
115
|
}
|
|
95
116
|
};
|
|
96
117
|
}
|
package/dist/history/index.mjs
CHANGED
|
@@ -32,19 +32,32 @@ function ensureHistorySchema(client, tableName) {
|
|
|
32
32
|
var VALID_TABLE_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
33
33
|
var VALID_ROLES = /* @__PURE__ */ new Set(["user", "assistant"]);
|
|
34
34
|
var DEFAULT_MAX_PER_CONVERSATION = 200;
|
|
35
|
-
function createTursoHistoryStore(client, tableName = "chat_history", maxPerConversation = DEFAULT_MAX_PER_CONVERSATION) {
|
|
35
|
+
function createTursoHistoryStore(client, tableName = "chat_history", maxPerConversation = DEFAULT_MAX_PER_CONVERSATION, options) {
|
|
36
36
|
if (!VALID_TABLE_NAME.test(tableName)) {
|
|
37
37
|
throw new Error(`Invalid history store table name: ${tableName}`);
|
|
38
38
|
}
|
|
39
39
|
if (!Number.isInteger(maxPerConversation) || maxPerConversation < 1) {
|
|
40
40
|
throw new Error(`Invalid history store maxPerConversation: ${maxPerConversation}`);
|
|
41
41
|
}
|
|
42
|
+
if (options?.ttlMs !== void 0 && (!Number.isInteger(options.ttlMs) || options.ttlMs < 1)) {
|
|
43
|
+
throw new Error(`Invalid history store ttlMs: ${options.ttlMs}`);
|
|
44
|
+
}
|
|
45
|
+
const ttlMs = options?.ttlMs;
|
|
46
|
+
const now = options?.now ?? Date.now;
|
|
47
|
+
async function pruneExpired(conversationId) {
|
|
48
|
+
if (ttlMs === void 0) return;
|
|
49
|
+
await client.execute({
|
|
50
|
+
sql: `DELETE FROM ${tableName} WHERE conversation_id = ? AND created_at < ?`,
|
|
51
|
+
args: [conversationId, now() - ttlMs]
|
|
52
|
+
});
|
|
53
|
+
}
|
|
42
54
|
return {
|
|
43
55
|
async append(conversationId, message) {
|
|
44
56
|
await ensureHistorySchema(client, tableName);
|
|
57
|
+
await pruneExpired(conversationId);
|
|
45
58
|
await client.execute({
|
|
46
59
|
sql: `INSERT INTO ${tableName} (conversation_id, role, content, created_at) VALUES (?, ?, ?, ?)`,
|
|
47
|
-
args: [conversationId, message.role, message.content,
|
|
60
|
+
args: [conversationId, message.role, message.content, now()]
|
|
48
61
|
});
|
|
49
62
|
await client.execute({
|
|
50
63
|
sql: `DELETE FROM ${tableName} WHERE conversation_id = ? AND id NOT IN (
|
|
@@ -57,6 +70,7 @@ function createTursoHistoryStore(client, tableName = "chat_history", maxPerConve
|
|
|
57
70
|
const boundedLimit = Math.max(0, Math.trunc(limit));
|
|
58
71
|
if (boundedLimit === 0) return [];
|
|
59
72
|
await ensureHistorySchema(client, tableName);
|
|
73
|
+
await pruneExpired(conversationId);
|
|
60
74
|
const result = await client.execute({
|
|
61
75
|
sql: `SELECT role, content FROM ${tableName} WHERE conversation_id = ? ORDER BY id DESC LIMIT ?`,
|
|
62
76
|
args: [conversationId, boundedLimit]
|
|
@@ -65,6 +79,13 @@ function createTursoHistoryStore(client, tableName = "chat_history", maxPerConve
|
|
|
65
79
|
role: String(row.role),
|
|
66
80
|
content: String(row.content)
|
|
67
81
|
})).filter((row) => VALID_ROLES.has(row.role)).reverse();
|
|
82
|
+
},
|
|
83
|
+
async clear(conversationId) {
|
|
84
|
+
await ensureHistorySchema(client, tableName);
|
|
85
|
+
await client.execute({
|
|
86
|
+
sql: `DELETE FROM ${tableName} WHERE conversation_id = ?`,
|
|
87
|
+
args: [conversationId]
|
|
88
|
+
});
|
|
68
89
|
}
|
|
69
90
|
};
|
|
70
91
|
}
|
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { Client } from "@libsql/client";
|
|
12
12
|
import type { HistoryStore } from "./types";
|
|
13
|
+
export interface TursoHistoryStoreOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Retention window: rows older than this are pruned whenever the
|
|
16
|
+
* conversation they belong to is accessed (`append` or `load`) — there is
|
|
17
|
+
* no background sweep. Unset: rows never expire on their own (only the
|
|
18
|
+
* `maxPerConversation` count cap and explicit `clear` remove them). Must be
|
|
19
|
+
* a positive integer, validated at construction like `maxPerConversation`.
|
|
20
|
+
*/
|
|
21
|
+
ttlMs?: number;
|
|
22
|
+
/** Injectable clock for tests. @default Date.now */
|
|
23
|
+
now?: () => number;
|
|
24
|
+
}
|
|
13
25
|
/**
|
|
14
26
|
* Creates a history store keyed by an arbitrary conversation id (a WhatsApp
|
|
15
27
|
* chat jid, a phone call sid, a web session id) on `tableName`.
|
|
@@ -22,5 +34,5 @@ import type { HistoryStore } from "./types";
|
|
|
22
34
|
* or disable pruning entirely (SQLite reads a negative `LIMIT` as
|
|
23
35
|
* unlimited), so it is validated at construction the same way `tableName` is.
|
|
24
36
|
*/
|
|
25
|
-
export declare function createTursoHistoryStore(client: Client, tableName?: string, maxPerConversation?: number): HistoryStore;
|
|
37
|
+
export declare function createTursoHistoryStore(client: Client, tableName?: string, maxPerConversation?: number, options?: TursoHistoryStoreOptions): HistoryStore;
|
|
26
38
|
//# sourceMappingURL=tursoStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tursoStore.d.ts","sourceRoot":"","sources":["../../src/history/tursoStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,SAAS,CAAC;AAkD5D;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,SAAS,SAAiB,EAC1B,kBAAkB,SAA+B,
|
|
1
|
+
{"version":3,"file":"tursoStore.d.ts","sourceRoot":"","sources":["../../src/history/tursoStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,SAAS,CAAC;AAkD5D,MAAM,WAAW,wBAAwB;IACvC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,SAAS,SAAiB,EAC1B,kBAAkB,SAA+B,EACjD,OAAO,CAAC,EAAE,wBAAwB,GACjC,YAAY,CAyEd"}
|
package/dist/history/types.d.ts
CHANGED
|
@@ -14,5 +14,7 @@ export interface HistoryStore {
|
|
|
14
14
|
append(conversationId: string, message: HistoryMessage): Promise<void>;
|
|
15
15
|
/** Load up to `limit` most recent turns for `conversationId`, oldest first. */
|
|
16
16
|
load(conversationId: string, limit: number): Promise<HistoryMessage[]>;
|
|
17
|
+
/** Reset primitive: erases all of `conversationId`'s history. Other conversations are untouched. */
|
|
18
|
+
clear(conversationId: string): Promise<void>;
|
|
17
19
|
}
|
|
18
20
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/history/types.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,+EAA+E;IAC/E,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/history/types.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,+EAA+E;IAC/E,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACvE,oGAAoG;IACpG,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C"}
|
package/package.json
CHANGED