@diegoaltoworks/chatter 0.56.0 → 0.57.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.
@@ -221,14 +221,35 @@ async function prepareChat({
221
221
  messages,
222
222
  personaLayer,
223
223
  channelHint,
224
- buckets
224
+ buckets,
225
+ sender,
226
+ rewriteQuery,
227
+ rerankContext,
228
+ logger
225
229
  }) {
226
230
  const lastUserMsg = lastUserMessage(messages);
227
231
  if (!lastUserMsg) {
228
232
  throw new Error("no user message found in conversation");
229
233
  }
230
234
  const { topK, label } = MODE_SETTINGS[mode];
231
- const ctx = await store.query(lastUserMsg.content, topK, buckets ?? defaultBuckets(mode));
235
+ let query = lastUserMsg.content;
236
+ if (rewriteQuery) {
237
+ try {
238
+ const rewritten = await rewriteQuery({ query, mode, sender });
239
+ if (typeof rewritten === "string" && rewritten.trim()) query = rewritten;
240
+ } catch (error) {
241
+ logger?.error("rewriteQuery threw; falling back to the original query", error);
242
+ }
243
+ }
244
+ let ctx = await store.query(query, topK, buckets ?? defaultBuckets(mode));
245
+ if (rerankContext) {
246
+ try {
247
+ const reranked = await rerankContext({ query, chunks: ctx });
248
+ if (Array.isArray(reranked) && reranked.every((c) => typeof c === "string")) ctx = reranked;
249
+ } catch (error) {
250
+ logger?.error("rerankContext threw; falling back to the original chunks", error);
251
+ }
252
+ }
232
253
  const persona = personaLayer?.trim() || (mode === "private" ? prompts.privatePersona : prompts.publicPersona);
233
254
  const hint = channelHint?.trim();
234
255
  const system = [
@@ -305,7 +326,11 @@ function createInboundPipeline(deps, config) {
305
326
  messages,
306
327
  personaLayer,
307
328
  channelHint: config.channelHint,
308
- buckets
329
+ buckets,
330
+ sender,
331
+ rewriteQuery: config.rewriteQuery,
332
+ rerankContext: config.rerankContext,
333
+ logger: config.logger
309
334
  });
310
335
  const { content: produced } = await answerOnce({
311
336
  answerFn: config.answerFn,
@@ -188,14 +188,35 @@ async function prepareChat({
188
188
  messages,
189
189
  personaLayer,
190
190
  channelHint,
191
- buckets
191
+ buckets,
192
+ sender,
193
+ rewriteQuery,
194
+ rerankContext,
195
+ logger
192
196
  }) {
193
197
  const lastUserMsg = lastUserMessage(messages);
194
198
  if (!lastUserMsg) {
195
199
  throw new Error("no user message found in conversation");
196
200
  }
197
201
  const { topK, label } = MODE_SETTINGS[mode];
198
- const ctx = await store.query(lastUserMsg.content, topK, buckets ?? defaultBuckets(mode));
202
+ let query = lastUserMsg.content;
203
+ if (rewriteQuery) {
204
+ try {
205
+ const rewritten = await rewriteQuery({ query, mode, sender });
206
+ if (typeof rewritten === "string" && rewritten.trim()) query = rewritten;
207
+ } catch (error) {
208
+ logger?.error("rewriteQuery threw; falling back to the original query", error);
209
+ }
210
+ }
211
+ let ctx = await store.query(query, topK, buckets ?? defaultBuckets(mode));
212
+ if (rerankContext) {
213
+ try {
214
+ const reranked = await rerankContext({ query, chunks: ctx });
215
+ if (Array.isArray(reranked) && reranked.every((c) => typeof c === "string")) ctx = reranked;
216
+ } catch (error) {
217
+ logger?.error("rerankContext threw; falling back to the original chunks", error);
218
+ }
219
+ }
199
220
  const persona = personaLayer?.trim() || (mode === "private" ? prompts.privatePersona : prompts.publicPersona);
200
221
  const hint = channelHint?.trim();
201
222
  const system = [
@@ -272,7 +293,11 @@ function createInboundPipeline(deps, config) {
272
293
  messages,
273
294
  personaLayer,
274
295
  channelHint: config.channelHint,
275
- buckets
296
+ buckets,
297
+ sender,
298
+ rewriteQuery: config.rewriteQuery,
299
+ rerankContext: config.rerankContext,
300
+ logger: config.logger
276
301
  });
277
302
  const { content: produced } = await answerOnce({
278
303
  answerFn: config.answerFn,
@@ -17,6 +17,7 @@ import type OpenAI from "openai";
17
17
  import type { AnswerFn, TransformReply } from "../core/answer";
18
18
  import type { BucketsFor } from "../core/buckets";
19
19
  import type { Logger } from "../core/logger";
20
+ import { type RerankContext, type RewriteQuery } from "../core/pipeline";
20
21
  import type { PromptLoader } from "../core/prompts";
21
22
  import type { VectorStore } from "../core/retrieval";
22
23
  import type { HistoryStore } from "../history/types";
@@ -41,6 +42,10 @@ export interface InboundPipelineConfig {
41
42
  channel?: string;
42
43
  answerFn?: AnswerFn;
43
44
  bucketsFor?: BucketsFor;
45
+ /** Rewrites the retrieval query before it reaches the vector store — see `ChatterConfig.rewriteQuery`. */
46
+ rewriteQuery?: RewriteQuery;
47
+ /** Post-processes retrieved chunks before they're folded into the prompt — see `ChatterConfig.rerankContext`. */
48
+ rerankContext?: RerankContext;
44
49
  /** Modifies or vetoes the produced reply before delivery — see `ChatterConfig.transformReply`. */
45
50
  transformReply?: TransformReply;
46
51
  model?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/channels/pipeline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/channels/pipeline.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,7 @@
20
20
  import type { AnswerFn, TransformReply } from "../../core/answer";
21
21
  import type { BucketsFor } from "../../core/buckets";
22
22
  import { type Logger } from "../../core/logger";
23
+ import type { RerankContext, RewriteQuery } from "../../core/pipeline";
23
24
  import type { HistoryStore } from "../../history/types";
24
25
  import type { Channel } from "../index";
25
26
  import { type TelegramApi } from "./api";
@@ -32,6 +33,10 @@ export interface TelegramChannelConfig {
32
33
  allowedChats?: string[];
33
34
  answerFn?: AnswerFn;
34
35
  bucketsFor?: BucketsFor;
36
+ /** Rewrites the retrieval query before it reaches the vector store — see `ChatterConfig.rewriteQuery`. Falls back to the server's own. */
37
+ rewriteQuery?: RewriteQuery;
38
+ /** Post-processes retrieved chunks before they're folded into the prompt — see `ChatterConfig.rerankContext`. Falls back to the server's own. */
39
+ rerankContext?: RerankContext;
35
40
  /** Modifies or vetoes the produced reply before delivery — see `ChatterConfig.transformReply`. Falls back to the server's own. */
36
41
  transformReply?: TransformReply;
37
42
  model?: string;
@@ -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,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,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;QAAE,KAAK,EAAE,YAAY,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,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,CAkI5E"}
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;QAAE,KAAK,EAAE,YAAY,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,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"}
@@ -388,14 +388,35 @@ async function prepareChat({
388
388
  messages,
389
389
  personaLayer,
390
390
  channelHint,
391
- buckets
391
+ buckets,
392
+ sender,
393
+ rewriteQuery,
394
+ rerankContext,
395
+ logger
392
396
  }) {
393
397
  const lastUserMsg = lastUserMessage(messages);
394
398
  if (!lastUserMsg) {
395
399
  throw new Error("no user message found in conversation");
396
400
  }
397
401
  const { topK, label } = MODE_SETTINGS[mode];
398
- const ctx = await store.query(lastUserMsg.content, topK, buckets ?? defaultBuckets(mode));
402
+ let query = lastUserMsg.content;
403
+ if (rewriteQuery) {
404
+ try {
405
+ const rewritten = await rewriteQuery({ query, mode, sender });
406
+ if (typeof rewritten === "string" && rewritten.trim()) query = rewritten;
407
+ } catch (error) {
408
+ logger?.error("rewriteQuery threw; falling back to the original query", error);
409
+ }
410
+ }
411
+ let ctx = await store.query(query, topK, buckets ?? defaultBuckets(mode));
412
+ if (rerankContext) {
413
+ try {
414
+ const reranked = await rerankContext({ query, chunks: ctx });
415
+ if (Array.isArray(reranked) && reranked.every((c) => typeof c === "string")) ctx = reranked;
416
+ } catch (error) {
417
+ logger?.error("rerankContext threw; falling back to the original chunks", error);
418
+ }
419
+ }
399
420
  const persona = personaLayer?.trim() || (mode === "private" ? prompts.privatePersona : prompts.publicPersona);
400
421
  const hint = channelHint?.trim();
401
422
  const system = [
@@ -472,7 +493,11 @@ function createInboundPipeline(deps, config) {
472
493
  messages,
473
494
  personaLayer,
474
495
  channelHint: config.channelHint,
475
- buckets
496
+ buckets,
497
+ sender,
498
+ rewriteQuery: config.rewriteQuery,
499
+ rerankContext: config.rerankContext,
500
+ logger: config.logger
476
501
  });
477
502
  const { content: produced } = await answerOnce({
478
503
  answerFn: config.answerFn,
@@ -625,6 +650,8 @@ function createTelegramChannel(config) {
625
650
  channel: channelName,
626
651
  answerFn: config.answerFn ?? deps.config.answerFn,
627
652
  bucketsFor: config.bucketsFor ?? deps.config.bucketsFor,
653
+ rewriteQuery: config.rewriteQuery ?? deps.config.rewriteQuery,
654
+ rerankContext: config.rerankContext ?? deps.config.rerankContext,
628
655
  transformReply: config.transformReply ?? deps.config.transformReply,
629
656
  model: config.model,
630
657
  channelHint: config.channelHint ?? "Channel: Telegram.",
@@ -346,14 +346,35 @@ async function prepareChat({
346
346
  messages,
347
347
  personaLayer,
348
348
  channelHint,
349
- buckets
349
+ buckets,
350
+ sender,
351
+ rewriteQuery,
352
+ rerankContext,
353
+ logger
350
354
  }) {
351
355
  const lastUserMsg = lastUserMessage(messages);
352
356
  if (!lastUserMsg) {
353
357
  throw new Error("no user message found in conversation");
354
358
  }
355
359
  const { topK, label } = MODE_SETTINGS[mode];
356
- const ctx = await store.query(lastUserMsg.content, topK, buckets ?? defaultBuckets(mode));
360
+ let query = lastUserMsg.content;
361
+ if (rewriteQuery) {
362
+ try {
363
+ const rewritten = await rewriteQuery({ query, mode, sender });
364
+ if (typeof rewritten === "string" && rewritten.trim()) query = rewritten;
365
+ } catch (error) {
366
+ logger?.error("rewriteQuery threw; falling back to the original query", error);
367
+ }
368
+ }
369
+ let ctx = await store.query(query, topK, buckets ?? defaultBuckets(mode));
370
+ if (rerankContext) {
371
+ try {
372
+ const reranked = await rerankContext({ query, chunks: ctx });
373
+ if (Array.isArray(reranked) && reranked.every((c) => typeof c === "string")) ctx = reranked;
374
+ } catch (error) {
375
+ logger?.error("rerankContext threw; falling back to the original chunks", error);
376
+ }
377
+ }
357
378
  const persona = personaLayer?.trim() || (mode === "private" ? prompts.privatePersona : prompts.publicPersona);
358
379
  const hint = channelHint?.trim();
359
380
  const system = [
@@ -430,7 +451,11 @@ function createInboundPipeline(deps, config) {
430
451
  messages,
431
452
  personaLayer,
432
453
  channelHint: config.channelHint,
433
- buckets
454
+ buckets,
455
+ sender,
456
+ rewriteQuery: config.rewriteQuery,
457
+ rerankContext: config.rerankContext,
458
+ logger: config.logger
434
459
  });
435
460
  const { content: produced } = await answerOnce({
436
461
  answerFn: config.answerFn,
@@ -583,6 +608,8 @@ function createTelegramChannel(config) {
583
608
  channel: channelName,
584
609
  answerFn: config.answerFn ?? deps.config.answerFn,
585
610
  bucketsFor: config.bucketsFor ?? deps.config.bucketsFor,
611
+ rewriteQuery: config.rewriteQuery ?? deps.config.rewriteQuery,
612
+ rerankContext: config.rerankContext ?? deps.config.rerankContext,
586
613
  transformReply: config.transformReply ?? deps.config.transformReply,
587
614
  model: config.model,
588
615
  channelHint: config.channelHint ?? "Channel: Telegram.",
@@ -36,6 +36,8 @@
36
36
  * prompts: deps.prompts,
37
37
  * answerFn: deps.config.answerFn,
38
38
  * bucketsFor: deps.config.bucketsFor,
39
+ * rewriteQuery: deps.config.rewriteQuery,
40
+ * rerankContext: deps.config.rerankContext,
39
41
  * transformReply: deps.config.transformReply,
40
42
  * registry: new Map(),
41
43
  * logger: deps.logger,
@@ -49,6 +51,7 @@ import type OpenAI from "openai";
49
51
  import type { AnswerFn, TransformReply } from "../../core/answer";
50
52
  import type { BucketsFor } from "../../core/buckets";
51
53
  import { type Logger } from "../../core/logger";
54
+ import type { RerankContext, RewriteQuery } from "../../core/pipeline";
52
55
  import type { PromptLoader } from "../../core/prompts";
53
56
  import type { VectorStore } from "../../core/retrieval";
54
57
  import type { HistoryStore } from "../../history/types";
@@ -129,6 +132,10 @@ export interface WhatsAppInboundConfig {
129
132
  prompts: PromptLoader;
130
133
  answerFn?: AnswerFn;
131
134
  bucketsFor?: BucketsFor;
135
+ /** Rewrites the retrieval query before it reaches the vector store — see `ChatterConfig.rewriteQuery`. */
136
+ rewriteQuery?: RewriteQuery;
137
+ /** Post-processes retrieved chunks before they're folded into the prompt — see `ChatterConfig.rerankContext`. */
138
+ rerankContext?: RerankContext;
132
139
  /** Modifies or vetoes the produced reply before delivery — see `ChatterConfig.transformReply`. */
133
140
  transformReply?: TransformReply;
134
141
  model?: string;
@@ -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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"}
@@ -799,14 +799,35 @@ async function prepareChat({
799
799
  messages,
800
800
  personaLayer,
801
801
  channelHint,
802
- buckets
802
+ buckets,
803
+ sender,
804
+ rewriteQuery,
805
+ rerankContext,
806
+ logger
803
807
  }) {
804
808
  const lastUserMsg = lastUserMessage(messages);
805
809
  if (!lastUserMsg) {
806
810
  throw new Error("no user message found in conversation");
807
811
  }
808
812
  const { topK, label } = MODE_SETTINGS[mode];
809
- const ctx = await store.query(lastUserMsg.content, topK, buckets ?? defaultBuckets(mode));
813
+ let query = lastUserMsg.content;
814
+ if (rewriteQuery) {
815
+ try {
816
+ const rewritten = await rewriteQuery({ query, mode, sender });
817
+ if (typeof rewritten === "string" && rewritten.trim()) query = rewritten;
818
+ } catch (error) {
819
+ logger?.error("rewriteQuery threw; falling back to the original query", error);
820
+ }
821
+ }
822
+ let ctx = await store.query(query, topK, buckets ?? defaultBuckets(mode));
823
+ if (rerankContext) {
824
+ try {
825
+ const reranked = await rerankContext({ query, chunks: ctx });
826
+ if (Array.isArray(reranked) && reranked.every((c) => typeof c === "string")) ctx = reranked;
827
+ } catch (error) {
828
+ logger?.error("rerankContext threw; falling back to the original chunks", error);
829
+ }
830
+ }
810
831
  const persona = personaLayer?.trim() || (mode === "private" ? prompts.privatePersona : prompts.publicPersona);
811
832
  const hint = channelHint?.trim();
812
833
  const system = [
@@ -883,7 +904,11 @@ function createInboundPipeline(deps, config) {
883
904
  messages,
884
905
  personaLayer,
885
906
  channelHint: config.channelHint,
886
- buckets
907
+ buckets,
908
+ sender,
909
+ rewriteQuery: config.rewriteQuery,
910
+ rerankContext: config.rerankContext,
911
+ logger: config.logger
887
912
  });
888
913
  const { content: produced } = await answerOnce({
889
914
  answerFn: config.answerFn,
@@ -1010,6 +1035,8 @@ function createWhatsAppInboundHandler(config) {
1010
1035
  channel: "whatsapp",
1011
1036
  answerFn: config.answerFn,
1012
1037
  bucketsFor: config.bucketsFor,
1038
+ rewriteQuery: config.rewriteQuery,
1039
+ rerankContext: config.rerankContext,
1013
1040
  transformReply: config.transformReply,
1014
1041
  model: config.model,
1015
1042
  channelHint: config.channelHint,
@@ -737,14 +737,35 @@ async function prepareChat({
737
737
  messages,
738
738
  personaLayer,
739
739
  channelHint,
740
- buckets
740
+ buckets,
741
+ sender,
742
+ rewriteQuery,
743
+ rerankContext,
744
+ logger
741
745
  }) {
742
746
  const lastUserMsg = lastUserMessage(messages);
743
747
  if (!lastUserMsg) {
744
748
  throw new Error("no user message found in conversation");
745
749
  }
746
750
  const { topK, label } = MODE_SETTINGS[mode];
747
- const ctx = await store.query(lastUserMsg.content, topK, buckets ?? defaultBuckets(mode));
751
+ let query = lastUserMsg.content;
752
+ if (rewriteQuery) {
753
+ try {
754
+ const rewritten = await rewriteQuery({ query, mode, sender });
755
+ if (typeof rewritten === "string" && rewritten.trim()) query = rewritten;
756
+ } catch (error) {
757
+ logger?.error("rewriteQuery threw; falling back to the original query", error);
758
+ }
759
+ }
760
+ let ctx = await store.query(query, topK, buckets ?? defaultBuckets(mode));
761
+ if (rerankContext) {
762
+ try {
763
+ const reranked = await rerankContext({ query, chunks: ctx });
764
+ if (Array.isArray(reranked) && reranked.every((c) => typeof c === "string")) ctx = reranked;
765
+ } catch (error) {
766
+ logger?.error("rerankContext threw; falling back to the original chunks", error);
767
+ }
768
+ }
748
769
  const persona = personaLayer?.trim() || (mode === "private" ? prompts.privatePersona : prompts.publicPersona);
749
770
  const hint = channelHint?.trim();
750
771
  const system = [
@@ -821,7 +842,11 @@ function createInboundPipeline(deps, config) {
821
842
  messages,
822
843
  personaLayer,
823
844
  channelHint: config.channelHint,
824
- buckets
845
+ buckets,
846
+ sender,
847
+ rewriteQuery: config.rewriteQuery,
848
+ rerankContext: config.rerankContext,
849
+ logger: config.logger
825
850
  });
826
851
  const { content: produced } = await answerOnce({
827
852
  answerFn: config.answerFn,
@@ -948,6 +973,8 @@ function createWhatsAppInboundHandler(config) {
948
973
  channel: "whatsapp",
949
974
  answerFn: config.answerFn,
950
975
  bucketsFor: config.bucketsFor,
976
+ rewriteQuery: config.rewriteQuery,
977
+ rerankContext: config.rerankContext,
951
978
  transformReply: config.transformReply,
952
979
  model: config.model,
953
980
  channelHint: config.channelHint,
@@ -8,6 +8,7 @@
8
8
  * then ask for the answer via `answerOnce`/`answerStream` (see ./answer.ts)
9
9
  * so a caller-supplied brain is honoured.
10
10
  */
11
+ import type { Logger } from "./logger";
11
12
  import type { PromptLoader } from "./prompts";
12
13
  import type { VectorStore } from "./retrieval";
13
14
  export type PipelineMode = "public" | "private";
@@ -23,6 +24,42 @@ export interface PreparedChat {
23
24
  /** Raw retrieved chunks, before being folded into `system` — for callers that log or display RAG context alongside the answer */
24
25
  context: string[];
25
26
  }
27
+ /** What `rewriteQuery` sees for a turn. */
28
+ export interface RewriteQueryArgs {
29
+ /** The latest user message's content — what retrieval would search on unmodified. */
30
+ query: string;
31
+ mode: PipelineMode;
32
+ /** Caller identity, where the surface has one. Absent on anonymous surfaces. */
33
+ sender?: string;
34
+ }
35
+ /**
36
+ * Rewrites the retrieval query before it reaches the vector store — e.g.
37
+ * expanding an ambiguous follow-up ("what about the second one?") into
38
+ * something embeddable on its own. Return the query unchanged to opt out for
39
+ * a given turn. A throw/rejection is caught by `prepareChat`, which falls
40
+ * back to the original query — a broken rewrite must never break retrieval.
41
+ */
42
+ export type RewriteQuery = (ctx: RewriteQueryArgs) => string | Promise<string>;
43
+ /** What `rerankContext` sees for a turn. */
44
+ export interface RerankContextArgs {
45
+ /** The query retrieval actually ran with — post-`rewriteQuery`, if configured. */
46
+ query: string;
47
+ /** Chunks `store.query` returned, in its own order. */
48
+ chunks: string[];
49
+ }
50
+ /**
51
+ * Reorders, filters, or otherwise post-processes the chunks retrieval
52
+ * returned before they're folded into the system prompt. A throw/rejection
53
+ * is caught by `prepareChat`, which falls back to the original chunks in
54
+ * their original order — a broken reranker must never break retrieval.
55
+ *
56
+ * This is NOT the seam for access control. Because a failure falls back to
57
+ * the unfiltered chunks, a hook that drops chunks a sender shouldn't see
58
+ * would silently un-drop them on its own error — the opposite of safe
59
+ * failure. Scope decisions belong in `bucketsFor` (see ./buckets), which
60
+ * fails closed by design; use this hook for relevance/ordering only.
61
+ */
62
+ export type RerankContext = (ctx: RerankContextArgs) => string[] | Promise<string[]>;
26
63
  /**
27
64
  * Run retrieval for the latest user message and assemble the system prompt.
28
65
  *
@@ -40,9 +77,15 @@ export interface PreparedChat {
40
77
  * `resolveBuckets` (see ./buckets) first, which is where the anonymous
41
78
  * ceiling is enforced.
42
79
  *
80
+ * `rewriteQuery` and `rerankContext` shape retrieval itself rather than the
81
+ * prompt around it: the former runs before `store.query`, the latter after.
82
+ * Both are optional and fail open — a throw, rejection, or malformed return
83
+ * value falls back to what retrieval would have done unmodified, so a buggy
84
+ * hook degrades relevance rather than breaking the chat path.
85
+ *
43
86
  * @throws if the conversation contains no user message
44
87
  */
45
- export declare function prepareChat({ store, prompts, mode, messages, personaLayer, channelHint, buckets, }: {
88
+ export declare function prepareChat({ store, prompts, mode, messages, personaLayer, channelHint, buckets, sender, rewriteQuery, rerankContext, logger, }: {
46
89
  store: VectorStore;
47
90
  prompts: PromptLoader;
48
91
  mode: PipelineMode;
@@ -56,5 +99,13 @@ export declare function prepareChat({ store, prompts, mode, messages, personaLay
56
99
  * `["base", mode]`. An empty array retrieves nothing.
57
100
  */
58
101
  buckets?: string[];
102
+ /** Caller identity, passed through to `rewriteQuery`. Absent on anonymous surfaces. */
103
+ sender?: string;
104
+ /** Rewrites the retrieval query before `store.query` runs — see {@link RewriteQuery}. */
105
+ rewriteQuery?: RewriteQuery;
106
+ /** Post-processes retrieved chunks before they're folded into the prompt — see {@link RerankContext}. */
107
+ rerankContext?: RerankContext;
108
+ /** Logs a `rewriteQuery`/`rerankContext` throw before falling back. Unset: the failure is silent. */
109
+ logger?: Pick<Logger, "error">;
59
110
  }): Promise<PreparedChat>;
60
111
  //# sourceMappingURL=pipeline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/core/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,iIAAiI;IACjI,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAOD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,WAAW,CAAC,EAChC,KAAK,EACL,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,OAAO,GACR,EAAE;IACD,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,GAAG,OAAO,CAAC,YAAY,CAAC,CAmBxB"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/core/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,iIAAiI;IACjI,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,2CAA2C;AAC3C,MAAM,WAAW,gBAAgB;IAC/B,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,gBAAgB,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAE/E,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,iBAAiB,KAAK,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAOrF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,WAAW,CAAC,EAChC,KAAK,EACL,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,OAAO,EACP,MAAM,EACN,YAAY,EACZ,aAAa,EACb,MAAM,GACP,EAAE;IACD,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,uFAAuF;IACvF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yFAAyF;IACzF,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,yGAAyG;IACzG,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,qGAAqG;IACrG,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,GAAG,OAAO,CAAC,YAAY,CAAC,CAuCxB"}
package/dist/index.d.ts CHANGED
@@ -25,7 +25,7 @@ export type { Logger, LogLevel } from "./core/logger";
25
25
  export { createConsoleLogger } from "./core/logger";
26
26
  export type { NormalizedChatBody } from "./core/messages";
27
27
  export { normalizeChatBody, normalizeMessages } from "./core/messages";
28
- export type { PipelineMessage, PipelineMode, PreparedChat } from "./core/pipeline";
28
+ export type { PipelineMessage, PipelineMode, PreparedChat, RerankContext, RerankContextArgs, RewriteQuery, RewriteQueryArgs, } from "./core/pipeline";
29
29
  export { prepareChat } from "./core/pipeline";
30
30
  export { PromptLoader } from "./core/prompts";
31
31
  export type { VectorStoreOptions } from "./core/retrieval";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}