@diegoaltoworks/chatter 0.55.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.
- package/dist/channels/index.js +46 -4
- package/dist/channels/index.mjs +46 -4
- package/dist/channels/pipeline.d.ts +16 -1
- package/dist/channels/pipeline.d.ts.map +1 -1
- package/dist/channels/telegram/channel.d.ts +8 -1
- package/dist/channels/telegram/channel.d.ts.map +1 -1
- package/dist/channels/telegram/index.js +52 -5
- package/dist/channels/telegram/index.mjs +52 -5
- package/dist/channels/whatsapp/inbound.d.ts +11 -1
- package/dist/channels/whatsapp/inbound.d.ts.map +1 -1
- package/dist/channels/whatsapp/index.js +52 -5
- package/dist/channels/whatsapp/index.mjs +52 -5
- package/dist/core/answer.d.ts +31 -0
- package/dist/core/answer.d.ts.map +1 -1
- package/dist/core/pipeline.d.ts +52 -1
- package/dist/core/pipeline.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +128 -19
- package/dist/index.mjs +127 -19
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +57 -8
- package/dist/mcp-server.mjs +57 -8
- package/dist/routes/demo.d.ts.map +1 -1
- package/dist/routes/openai.d.ts.map +1 -1
- package/dist/routes/private.d.ts.map +1 -1
- package/dist/routes/public.d.ts.map +1 -1
- package/dist/server.js +104 -13
- package/dist/server.mjs +104 -13
- package/dist/types.d.ts +42 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -249,6 +249,18 @@ async function answerOnce({
|
|
|
249
249
|
}
|
|
250
250
|
return completeOnce({ client, system, messages, temperature, model });
|
|
251
251
|
}
|
|
252
|
+
async function applyTransformReply(transformReply, input, logger) {
|
|
253
|
+
if (!transformReply) return input.text;
|
|
254
|
+
try {
|
|
255
|
+
return await transformReply(input);
|
|
256
|
+
} catch (error) {
|
|
257
|
+
logger?.error(
|
|
258
|
+
`transformReply threw for channel "${input.channel}"; sending the original reply`,
|
|
259
|
+
error
|
|
260
|
+
);
|
|
261
|
+
return input.text;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
252
264
|
async function* answerStream({
|
|
253
265
|
answerFn,
|
|
254
266
|
client,
|
|
@@ -366,14 +378,35 @@ async function prepareChat({
|
|
|
366
378
|
messages,
|
|
367
379
|
personaLayer,
|
|
368
380
|
channelHint,
|
|
369
|
-
buckets
|
|
381
|
+
buckets,
|
|
382
|
+
sender,
|
|
383
|
+
rewriteQuery,
|
|
384
|
+
rerankContext,
|
|
385
|
+
logger
|
|
370
386
|
}) {
|
|
371
387
|
const lastUserMsg = lastUserMessage(messages);
|
|
372
388
|
if (!lastUserMsg) {
|
|
373
389
|
throw new Error("no user message found in conversation");
|
|
374
390
|
}
|
|
375
391
|
const { topK, label } = MODE_SETTINGS[mode];
|
|
376
|
-
|
|
392
|
+
let query = lastUserMsg.content;
|
|
393
|
+
if (rewriteQuery) {
|
|
394
|
+
try {
|
|
395
|
+
const rewritten = await rewriteQuery({ query, mode, sender });
|
|
396
|
+
if (typeof rewritten === "string" && rewritten.trim()) query = rewritten;
|
|
397
|
+
} catch (error) {
|
|
398
|
+
logger?.error("rewriteQuery threw; falling back to the original query", error);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
let ctx = await store.query(query, topK, buckets ?? defaultBuckets(mode));
|
|
402
|
+
if (rerankContext) {
|
|
403
|
+
try {
|
|
404
|
+
const reranked = await rerankContext({ query, chunks: ctx });
|
|
405
|
+
if (Array.isArray(reranked) && reranked.every((c) => typeof c === "string")) ctx = reranked;
|
|
406
|
+
} catch (error) {
|
|
407
|
+
logger?.error("rerankContext threw; falling back to the original chunks", error);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
377
410
|
const persona = personaLayer?.trim() || (mode === "private" ? prompts.privatePersona : prompts.publicPersona);
|
|
378
411
|
const hint = channelHint?.trim();
|
|
379
412
|
const system = [
|
|
@@ -1051,7 +1084,16 @@ function demoRoutes(deps) {
|
|
|
1051
1084
|
return c.json({ error: "no user message found in conversation" }, 400);
|
|
1052
1085
|
}
|
|
1053
1086
|
const buckets = await resolveBuckets({ mode: "public", bucketsFor: config.bucketsFor });
|
|
1054
|
-
const { system } = await prepareChat({
|
|
1087
|
+
const { system } = await prepareChat({
|
|
1088
|
+
store,
|
|
1089
|
+
prompts,
|
|
1090
|
+
mode: "public",
|
|
1091
|
+
messages,
|
|
1092
|
+
buckets,
|
|
1093
|
+
rewriteQuery: config.rewriteQuery,
|
|
1094
|
+
rerankContext: config.rerankContext,
|
|
1095
|
+
logger
|
|
1096
|
+
});
|
|
1055
1097
|
const model = config.openai.model || DEFAULT_MODEL;
|
|
1056
1098
|
const url = new URL(c.req.url);
|
|
1057
1099
|
const wantsStream3 = url.searchParams.get("stream") === "1";
|
|
@@ -1080,7 +1122,12 @@ function demoRoutes(deps) {
|
|
|
1080
1122
|
mode: "public",
|
|
1081
1123
|
model
|
|
1082
1124
|
});
|
|
1083
|
-
|
|
1125
|
+
const reply = await applyTransformReply(
|
|
1126
|
+
config.transformReply,
|
|
1127
|
+
{ channel: "widget-demo", text: out.content },
|
|
1128
|
+
logger
|
|
1129
|
+
);
|
|
1130
|
+
return c.json({ reply: reply ?? "" });
|
|
1084
1131
|
} catch (error) {
|
|
1085
1132
|
const err = error;
|
|
1086
1133
|
logger.error("Demo chat error:", err);
|
|
@@ -1204,7 +1251,7 @@ function oversizedBodyError(message) {
|
|
|
1204
1251
|
return { error: { message, type: "invalid_request_error" } };
|
|
1205
1252
|
}
|
|
1206
1253
|
function openaiRoutes(deps) {
|
|
1207
|
-
const { client, store, config, prompts, apiKeyManager } = deps;
|
|
1254
|
+
const { client, store, config, prompts, apiKeyManager, logger } = deps;
|
|
1208
1255
|
const app = new import_hono2.Hono();
|
|
1209
1256
|
const { limitPublic, limitPrivate } = createRateLimiter(config);
|
|
1210
1257
|
const requirePrivateJWT = createJWTMiddleware(config);
|
|
@@ -1246,13 +1293,23 @@ function openaiRoutes(deps) {
|
|
|
1246
1293
|
sender: jwtSubject(c),
|
|
1247
1294
|
bucketsFor: config.bucketsFor
|
|
1248
1295
|
});
|
|
1296
|
+
const sender = jwtSubject(c) ?? apiKeySubject(c);
|
|
1249
1297
|
let system;
|
|
1250
1298
|
try {
|
|
1251
|
-
({ system } = await prepareChat({
|
|
1299
|
+
({ system } = await prepareChat({
|
|
1300
|
+
store,
|
|
1301
|
+
prompts,
|
|
1302
|
+
mode,
|
|
1303
|
+
messages,
|
|
1304
|
+
buckets,
|
|
1305
|
+
sender,
|
|
1306
|
+
rewriteQuery: config.rewriteQuery,
|
|
1307
|
+
rerankContext: config.rerankContext,
|
|
1308
|
+
logger
|
|
1309
|
+
}));
|
|
1252
1310
|
} catch {
|
|
1253
1311
|
return errorJson(c, 400, "Conversation must contain at least one user message");
|
|
1254
1312
|
}
|
|
1255
|
-
const sender = jwtSubject(c) ?? apiKeySubject(c);
|
|
1256
1313
|
const conversationId = clientConversationId(c, body) ?? crypto.randomUUID();
|
|
1257
1314
|
c.header("x-conversation-id", conversationId);
|
|
1258
1315
|
const id = `chatcmpl-${crypto.randomUUID()}`;
|
|
@@ -1299,13 +1356,18 @@ function openaiRoutes(deps) {
|
|
|
1299
1356
|
temperature,
|
|
1300
1357
|
model: serverModel
|
|
1301
1358
|
});
|
|
1359
|
+
const reply = await applyTransformReply(
|
|
1360
|
+
config.transformReply,
|
|
1361
|
+
{ channel: `openai-compat-${mode}`, sender, conversationId, text: out.content },
|
|
1362
|
+
logger
|
|
1363
|
+
);
|
|
1302
1364
|
return c.json({
|
|
1303
1365
|
id,
|
|
1304
1366
|
object: "chat.completion",
|
|
1305
1367
|
created,
|
|
1306
1368
|
model: serverModel,
|
|
1307
1369
|
choices: [
|
|
1308
|
-
{ index: 0, message: { role: "assistant", content:
|
|
1370
|
+
{ index: 0, message: { role: "assistant", content: reply ?? "" }, finish_reason: "stop" }
|
|
1309
1371
|
],
|
|
1310
1372
|
usage: out.usage
|
|
1311
1373
|
});
|
|
@@ -1335,7 +1397,7 @@ function wantsStream(c) {
|
|
|
1335
1397
|
return acc.includes("text/event-stream");
|
|
1336
1398
|
}
|
|
1337
1399
|
function privateRoutes(deps) {
|
|
1338
|
-
const { client, store, config, prompts } = deps;
|
|
1400
|
+
const { client, store, config, prompts, logger } = deps;
|
|
1339
1401
|
const app = new import_hono3.Hono();
|
|
1340
1402
|
const requirePrivateJWT = createJWTMiddleware(config);
|
|
1341
1403
|
const { limitPrivate } = createRateLimiter(config);
|
|
@@ -1357,7 +1419,17 @@ function privateRoutes(deps) {
|
|
|
1357
1419
|
});
|
|
1358
1420
|
let system;
|
|
1359
1421
|
try {
|
|
1360
|
-
({ system } = await prepareChat({
|
|
1422
|
+
({ system } = await prepareChat({
|
|
1423
|
+
store,
|
|
1424
|
+
prompts,
|
|
1425
|
+
mode: "private",
|
|
1426
|
+
messages,
|
|
1427
|
+
buckets,
|
|
1428
|
+
sender,
|
|
1429
|
+
rewriteQuery: config.rewriteQuery,
|
|
1430
|
+
rerankContext: config.rerankContext,
|
|
1431
|
+
logger
|
|
1432
|
+
}));
|
|
1361
1433
|
} catch {
|
|
1362
1434
|
return c.json({ error: "no user message found in conversation" }, 400);
|
|
1363
1435
|
}
|
|
@@ -1390,7 +1462,12 @@ function privateRoutes(deps) {
|
|
|
1390
1462
|
sender,
|
|
1391
1463
|
model
|
|
1392
1464
|
});
|
|
1393
|
-
|
|
1465
|
+
const reply = await applyTransformReply(
|
|
1466
|
+
config.transformReply,
|
|
1467
|
+
{ channel: "widget-private", sender, text: out.content },
|
|
1468
|
+
logger
|
|
1469
|
+
);
|
|
1470
|
+
return c.json({ reply: reply ?? "" });
|
|
1394
1471
|
});
|
|
1395
1472
|
return app;
|
|
1396
1473
|
}
|
|
@@ -1524,7 +1601,16 @@ function publicRoutes(deps) {
|
|
|
1524
1601
|
const buckets = await resolveBuckets({ mode: "public", bucketsFor: config.bucketsFor });
|
|
1525
1602
|
let system;
|
|
1526
1603
|
try {
|
|
1527
|
-
({ system } = await prepareChat({
|
|
1604
|
+
({ system } = await prepareChat({
|
|
1605
|
+
store,
|
|
1606
|
+
prompts,
|
|
1607
|
+
mode: "public",
|
|
1608
|
+
messages,
|
|
1609
|
+
buckets,
|
|
1610
|
+
rewriteQuery: config.rewriteQuery,
|
|
1611
|
+
rerankContext: config.rerankContext,
|
|
1612
|
+
logger
|
|
1613
|
+
}));
|
|
1528
1614
|
} catch {
|
|
1529
1615
|
return c.json({ error: "no user message found in conversation" }, 400);
|
|
1530
1616
|
}
|
|
@@ -1548,7 +1634,12 @@ function publicRoutes(deps) {
|
|
|
1548
1634
|
});
|
|
1549
1635
|
}
|
|
1550
1636
|
const out = await answerOnce({ answerFn, client, system, messages, mode: "public", model });
|
|
1551
|
-
|
|
1637
|
+
const reply = await applyTransformReply(
|
|
1638
|
+
config.transformReply,
|
|
1639
|
+
{ channel: "widget-public", text: out.content },
|
|
1640
|
+
logger
|
|
1641
|
+
);
|
|
1642
|
+
return c.json({ reply: reply ?? "" });
|
|
1552
1643
|
});
|
|
1553
1644
|
return app;
|
|
1554
1645
|
}
|
package/dist/server.mjs
CHANGED
|
@@ -215,6 +215,18 @@ async function answerOnce({
|
|
|
215
215
|
}
|
|
216
216
|
return completeOnce({ client, system, messages, temperature, model });
|
|
217
217
|
}
|
|
218
|
+
async function applyTransformReply(transformReply, input, logger) {
|
|
219
|
+
if (!transformReply) return input.text;
|
|
220
|
+
try {
|
|
221
|
+
return await transformReply(input);
|
|
222
|
+
} catch (error) {
|
|
223
|
+
logger?.error(
|
|
224
|
+
`transformReply threw for channel "${input.channel}"; sending the original reply`,
|
|
225
|
+
error
|
|
226
|
+
);
|
|
227
|
+
return input.text;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
218
230
|
async function* answerStream({
|
|
219
231
|
answerFn,
|
|
220
232
|
client,
|
|
@@ -332,14 +344,35 @@ async function prepareChat({
|
|
|
332
344
|
messages,
|
|
333
345
|
personaLayer,
|
|
334
346
|
channelHint,
|
|
335
|
-
buckets
|
|
347
|
+
buckets,
|
|
348
|
+
sender,
|
|
349
|
+
rewriteQuery,
|
|
350
|
+
rerankContext,
|
|
351
|
+
logger
|
|
336
352
|
}) {
|
|
337
353
|
const lastUserMsg = lastUserMessage(messages);
|
|
338
354
|
if (!lastUserMsg) {
|
|
339
355
|
throw new Error("no user message found in conversation");
|
|
340
356
|
}
|
|
341
357
|
const { topK, label } = MODE_SETTINGS[mode];
|
|
342
|
-
|
|
358
|
+
let query = lastUserMsg.content;
|
|
359
|
+
if (rewriteQuery) {
|
|
360
|
+
try {
|
|
361
|
+
const rewritten = await rewriteQuery({ query, mode, sender });
|
|
362
|
+
if (typeof rewritten === "string" && rewritten.trim()) query = rewritten;
|
|
363
|
+
} catch (error) {
|
|
364
|
+
logger?.error("rewriteQuery threw; falling back to the original query", error);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
let ctx = await store.query(query, topK, buckets ?? defaultBuckets(mode));
|
|
368
|
+
if (rerankContext) {
|
|
369
|
+
try {
|
|
370
|
+
const reranked = await rerankContext({ query, chunks: ctx });
|
|
371
|
+
if (Array.isArray(reranked) && reranked.every((c) => typeof c === "string")) ctx = reranked;
|
|
372
|
+
} catch (error) {
|
|
373
|
+
logger?.error("rerankContext threw; falling back to the original chunks", error);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
343
376
|
const persona = personaLayer?.trim() || (mode === "private" ? prompts.privatePersona : prompts.publicPersona);
|
|
344
377
|
const hint = channelHint?.trim();
|
|
345
378
|
const system = [
|
|
@@ -1016,7 +1049,16 @@ function demoRoutes(deps) {
|
|
|
1016
1049
|
return c.json({ error: "no user message found in conversation" }, 400);
|
|
1017
1050
|
}
|
|
1018
1051
|
const buckets = await resolveBuckets({ mode: "public", bucketsFor: config.bucketsFor });
|
|
1019
|
-
const { system } = await prepareChat({
|
|
1052
|
+
const { system } = await prepareChat({
|
|
1053
|
+
store,
|
|
1054
|
+
prompts,
|
|
1055
|
+
mode: "public",
|
|
1056
|
+
messages,
|
|
1057
|
+
buckets,
|
|
1058
|
+
rewriteQuery: config.rewriteQuery,
|
|
1059
|
+
rerankContext: config.rerankContext,
|
|
1060
|
+
logger
|
|
1061
|
+
});
|
|
1020
1062
|
const model = config.openai.model || DEFAULT_MODEL;
|
|
1021
1063
|
const url = new URL(c.req.url);
|
|
1022
1064
|
const wantsStream3 = url.searchParams.get("stream") === "1";
|
|
@@ -1045,7 +1087,12 @@ function demoRoutes(deps) {
|
|
|
1045
1087
|
mode: "public",
|
|
1046
1088
|
model
|
|
1047
1089
|
});
|
|
1048
|
-
|
|
1090
|
+
const reply = await applyTransformReply(
|
|
1091
|
+
config.transformReply,
|
|
1092
|
+
{ channel: "widget-demo", text: out.content },
|
|
1093
|
+
logger
|
|
1094
|
+
);
|
|
1095
|
+
return c.json({ reply: reply ?? "" });
|
|
1049
1096
|
} catch (error) {
|
|
1050
1097
|
const err = error;
|
|
1051
1098
|
logger.error("Demo chat error:", err);
|
|
@@ -1169,7 +1216,7 @@ function oversizedBodyError(message) {
|
|
|
1169
1216
|
return { error: { message, type: "invalid_request_error" } };
|
|
1170
1217
|
}
|
|
1171
1218
|
function openaiRoutes(deps) {
|
|
1172
|
-
const { client, store, config, prompts, apiKeyManager } = deps;
|
|
1219
|
+
const { client, store, config, prompts, apiKeyManager, logger } = deps;
|
|
1173
1220
|
const app = new Hono2();
|
|
1174
1221
|
const { limitPublic, limitPrivate } = createRateLimiter(config);
|
|
1175
1222
|
const requirePrivateJWT = createJWTMiddleware(config);
|
|
@@ -1211,13 +1258,23 @@ function openaiRoutes(deps) {
|
|
|
1211
1258
|
sender: jwtSubject(c),
|
|
1212
1259
|
bucketsFor: config.bucketsFor
|
|
1213
1260
|
});
|
|
1261
|
+
const sender = jwtSubject(c) ?? apiKeySubject(c);
|
|
1214
1262
|
let system;
|
|
1215
1263
|
try {
|
|
1216
|
-
({ system } = await prepareChat({
|
|
1264
|
+
({ system } = await prepareChat({
|
|
1265
|
+
store,
|
|
1266
|
+
prompts,
|
|
1267
|
+
mode,
|
|
1268
|
+
messages,
|
|
1269
|
+
buckets,
|
|
1270
|
+
sender,
|
|
1271
|
+
rewriteQuery: config.rewriteQuery,
|
|
1272
|
+
rerankContext: config.rerankContext,
|
|
1273
|
+
logger
|
|
1274
|
+
}));
|
|
1217
1275
|
} catch {
|
|
1218
1276
|
return errorJson(c, 400, "Conversation must contain at least one user message");
|
|
1219
1277
|
}
|
|
1220
|
-
const sender = jwtSubject(c) ?? apiKeySubject(c);
|
|
1221
1278
|
const conversationId = clientConversationId(c, body) ?? crypto.randomUUID();
|
|
1222
1279
|
c.header("x-conversation-id", conversationId);
|
|
1223
1280
|
const id = `chatcmpl-${crypto.randomUUID()}`;
|
|
@@ -1264,13 +1321,18 @@ function openaiRoutes(deps) {
|
|
|
1264
1321
|
temperature,
|
|
1265
1322
|
model: serverModel
|
|
1266
1323
|
});
|
|
1324
|
+
const reply = await applyTransformReply(
|
|
1325
|
+
config.transformReply,
|
|
1326
|
+
{ channel: `openai-compat-${mode}`, sender, conversationId, text: out.content },
|
|
1327
|
+
logger
|
|
1328
|
+
);
|
|
1267
1329
|
return c.json({
|
|
1268
1330
|
id,
|
|
1269
1331
|
object: "chat.completion",
|
|
1270
1332
|
created,
|
|
1271
1333
|
model: serverModel,
|
|
1272
1334
|
choices: [
|
|
1273
|
-
{ index: 0, message: { role: "assistant", content:
|
|
1335
|
+
{ index: 0, message: { role: "assistant", content: reply ?? "" }, finish_reason: "stop" }
|
|
1274
1336
|
],
|
|
1275
1337
|
usage: out.usage
|
|
1276
1338
|
});
|
|
@@ -1300,7 +1362,7 @@ function wantsStream(c) {
|
|
|
1300
1362
|
return acc.includes("text/event-stream");
|
|
1301
1363
|
}
|
|
1302
1364
|
function privateRoutes(deps) {
|
|
1303
|
-
const { client, store, config, prompts } = deps;
|
|
1365
|
+
const { client, store, config, prompts, logger } = deps;
|
|
1304
1366
|
const app = new Hono3();
|
|
1305
1367
|
const requirePrivateJWT = createJWTMiddleware(config);
|
|
1306
1368
|
const { limitPrivate } = createRateLimiter(config);
|
|
@@ -1322,7 +1384,17 @@ function privateRoutes(deps) {
|
|
|
1322
1384
|
});
|
|
1323
1385
|
let system;
|
|
1324
1386
|
try {
|
|
1325
|
-
({ system } = await prepareChat({
|
|
1387
|
+
({ system } = await prepareChat({
|
|
1388
|
+
store,
|
|
1389
|
+
prompts,
|
|
1390
|
+
mode: "private",
|
|
1391
|
+
messages,
|
|
1392
|
+
buckets,
|
|
1393
|
+
sender,
|
|
1394
|
+
rewriteQuery: config.rewriteQuery,
|
|
1395
|
+
rerankContext: config.rerankContext,
|
|
1396
|
+
logger
|
|
1397
|
+
}));
|
|
1326
1398
|
} catch {
|
|
1327
1399
|
return c.json({ error: "no user message found in conversation" }, 400);
|
|
1328
1400
|
}
|
|
@@ -1355,7 +1427,12 @@ function privateRoutes(deps) {
|
|
|
1355
1427
|
sender,
|
|
1356
1428
|
model
|
|
1357
1429
|
});
|
|
1358
|
-
|
|
1430
|
+
const reply = await applyTransformReply(
|
|
1431
|
+
config.transformReply,
|
|
1432
|
+
{ channel: "widget-private", sender, text: out.content },
|
|
1433
|
+
logger
|
|
1434
|
+
);
|
|
1435
|
+
return c.json({ reply: reply ?? "" });
|
|
1359
1436
|
});
|
|
1360
1437
|
return app;
|
|
1361
1438
|
}
|
|
@@ -1489,7 +1566,16 @@ function publicRoutes(deps) {
|
|
|
1489
1566
|
const buckets = await resolveBuckets({ mode: "public", bucketsFor: config.bucketsFor });
|
|
1490
1567
|
let system;
|
|
1491
1568
|
try {
|
|
1492
|
-
({ system } = await prepareChat({
|
|
1569
|
+
({ system } = await prepareChat({
|
|
1570
|
+
store,
|
|
1571
|
+
prompts,
|
|
1572
|
+
mode: "public",
|
|
1573
|
+
messages,
|
|
1574
|
+
buckets,
|
|
1575
|
+
rewriteQuery: config.rewriteQuery,
|
|
1576
|
+
rerankContext: config.rerankContext,
|
|
1577
|
+
logger
|
|
1578
|
+
}));
|
|
1493
1579
|
} catch {
|
|
1494
1580
|
return c.json({ error: "no user message found in conversation" }, 400);
|
|
1495
1581
|
}
|
|
@@ -1513,7 +1599,12 @@ function publicRoutes(deps) {
|
|
|
1513
1599
|
});
|
|
1514
1600
|
}
|
|
1515
1601
|
const out = await answerOnce({ answerFn, client, system, messages, mode: "public", model });
|
|
1516
|
-
|
|
1602
|
+
const reply = await applyTransformReply(
|
|
1603
|
+
config.transformReply,
|
|
1604
|
+
{ channel: "widget-public", text: out.content },
|
|
1605
|
+
logger
|
|
1606
|
+
);
|
|
1607
|
+
return c.json({ reply: reply ?? "" });
|
|
1517
1608
|
});
|
|
1518
1609
|
return app;
|
|
1519
1610
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -8,9 +8,10 @@ import type { Client as LibsqlClient } from "@libsql/client";
|
|
|
8
8
|
import type { Hono } from "hono";
|
|
9
9
|
import type OpenAI from "openai";
|
|
10
10
|
import type { Channel, ChannelSenderRegistry } from "./channels";
|
|
11
|
-
import type { AnswerFn } from "./core/answer";
|
|
11
|
+
import type { AnswerFn, TransformReply } from "./core/answer";
|
|
12
12
|
import type { BucketsFor } from "./core/buckets";
|
|
13
13
|
import type { Logger, LogLevel } from "./core/logger";
|
|
14
|
+
import type { RerankContext, RewriteQuery } from "./core/pipeline";
|
|
14
15
|
import type { PromptLoader } from "./core/prompts";
|
|
15
16
|
import type { VectorStore } from "./core/retrieval";
|
|
16
17
|
export type { Logger, LogLevel } from "./core/logger";
|
|
@@ -234,6 +235,22 @@ export interface ChatterConfig {
|
|
|
234
235
|
* errors. Unset: the built-in OpenAI completion is used.
|
|
235
236
|
*/
|
|
236
237
|
answerFn?: AnswerFn;
|
|
238
|
+
/**
|
|
239
|
+
* Modifies or vetoes an outgoing reply after it has already been produced
|
|
240
|
+
* (by `answerFn` or the built-in completion, past guardrails). Return a
|
|
241
|
+
* string to replace the reply, or `null` to veto it — a deliberate drop,
|
|
242
|
+
* treated the same as an empty answer: nothing is delivered, and the
|
|
243
|
+
* channel pipeline never records an assistant turn for it (the user's own
|
|
244
|
+
* turn, already appended before answering, stays recorded either way). A
|
|
245
|
+
* throw/rejection is logged and the ORIGINAL reply is sent.
|
|
246
|
+
*
|
|
247
|
+
* Consulted by the channel pipeline and every non-streaming HTTP chat
|
|
248
|
+
* surface (widget and demo routes, OpenAI-compatible endpoints, MCP chat
|
|
249
|
+
* tools). Streaming responses are delivered incrementally as they're
|
|
250
|
+
* produced, before a final answer exists to transform, so this hook is
|
|
251
|
+
* never consulted for them. Unset: replies pass through unchanged.
|
|
252
|
+
*/
|
|
253
|
+
transformReply?: TransformReply;
|
|
237
254
|
/**
|
|
238
255
|
* Decides which knowledge buckets each chat turn may retrieve from, given
|
|
239
256
|
* the pipeline mode and — where the surface knows it — the sender's
|
|
@@ -249,6 +266,30 @@ export interface ChatterConfig {
|
|
|
249
266
|
* Unset: the mode defaults apply everywhere.
|
|
250
267
|
*/
|
|
251
268
|
bucketsFor?: BucketsFor;
|
|
269
|
+
/**
|
|
270
|
+
* Rewrites the retrieval query for a turn before it reaches the vector
|
|
271
|
+
* store — e.g. expanding an ambiguous follow-up into something embeddable
|
|
272
|
+
* on its own. Receives the same `sender` identity `answerFn` sees (not the
|
|
273
|
+
* retrieval-scope-restricted one `bucketsFor` sees on the public
|
|
274
|
+
* OpenAI-compatible route — rewriting a query widens nothing, so it isn't
|
|
275
|
+
* subject to that clamp).
|
|
276
|
+
*
|
|
277
|
+
* Consulted everywhere `bucketsFor` is. A throw/rejection, or a return
|
|
278
|
+
* value that isn't a non-blank string, falls back to the unmodified query
|
|
279
|
+
* — a broken rewrite degrades relevance, never the chat path. Unset:
|
|
280
|
+
* retrieval runs on the latest user message unmodified.
|
|
281
|
+
*/
|
|
282
|
+
rewriteQuery?: RewriteQuery;
|
|
283
|
+
/**
|
|
284
|
+
* Post-processes the chunks retrieval returned — reordering, filtering, or
|
|
285
|
+
* otherwise reranking — before they're folded into the system prompt.
|
|
286
|
+
*
|
|
287
|
+
* Consulted everywhere `bucketsFor` is, immediately after retrieval runs.
|
|
288
|
+
* A throw/rejection, or a return value that isn't a string array, falls
|
|
289
|
+
* back to the chunks retrieval returned, unmodified. Unset: retrieved
|
|
290
|
+
* chunks are used as-is.
|
|
291
|
+
*/
|
|
292
|
+
rerankContext?: RerankContext;
|
|
252
293
|
/** Custom route handler for advanced use cases. May be async — see {@link CustomRoutes} */
|
|
253
294
|
customRoutes?: CustomRoutes;
|
|
254
295
|
/**
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED