@diegoaltoworks/chatter 0.67.0 → 2.0.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/README.md +3 -1
- package/dist/channels/gates.d.ts +21 -2
- package/dist/channels/gates.d.ts.map +1 -1
- package/dist/channels/index.d.ts +5 -3
- package/dist/channels/index.d.ts.map +1 -1
- package/dist/channels/index.js +31 -13
- package/dist/channels/index.mjs +30 -13
- package/dist/channels/matrix/channel.d.ts +2 -0
- package/dist/channels/matrix/channel.d.ts.map +1 -1
- package/dist/channels/matrix/handler.d.ts +9 -0
- package/dist/channels/matrix/handler.d.ts.map +1 -1
- package/dist/channels/matrix/index.d.ts +1 -1
- package/dist/channels/matrix/index.d.ts.map +1 -1
- package/dist/channels/matrix/index.js +75 -20
- package/dist/channels/matrix/index.mjs +74 -20
- package/dist/channels/matrix/updates.d.ts +8 -2
- package/dist/channels/matrix/updates.d.ts.map +1 -1
- package/dist/channels/pipeline.d.ts +34 -4
- package/dist/channels/pipeline.d.ts.map +1 -1
- package/dist/channels/polling.d.ts +11 -0
- package/dist/channels/polling.d.ts.map +1 -1
- package/dist/channels/telegram/channel.d.ts +2 -0
- package/dist/channels/telegram/channel.d.ts.map +1 -1
- package/dist/channels/telegram/handler.d.ts +9 -0
- package/dist/channels/telegram/handler.d.ts.map +1 -1
- package/dist/channels/telegram/index.d.ts +1 -1
- package/dist/channels/telegram/index.d.ts.map +1 -1
- package/dist/channels/telegram/index.js +73 -24
- package/dist/channels/telegram/index.mjs +72 -24
- package/dist/channels/telegram/updates.d.ts +8 -2
- package/dist/channels/telegram/updates.d.ts.map +1 -1
- package/dist/channels/telegram/webhook.d.ts +10 -0
- package/dist/channels/telegram/webhook.d.ts.map +1 -1
- package/dist/channels/whatsapp/channel.d.ts +8 -0
- package/dist/channels/whatsapp/channel.d.ts.map +1 -1
- package/dist/channels/whatsapp/inbound.d.ts +2 -0
- package/dist/channels/whatsapp/inbound.d.ts.map +1 -1
- package/dist/channels/whatsapp/index.js +45 -18
- package/dist/channels/whatsapp/index.mjs +45 -18
- package/dist/core/answer.d.ts +9 -2
- package/dist/core/answer.d.ts.map +1 -1
- package/dist/core/guardrails.d.ts +11 -1
- package/dist/core/guardrails.d.ts.map +1 -1
- package/dist/core/llm.d.ts +3 -1
- package/dist/core/llm.d.ts.map +1 -1
- package/dist/history/index.js +12 -9
- package/dist/history/index.mjs +12 -9
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +50 -27
- package/dist/index.mjs +49 -27
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +16 -11
- package/dist/mcp-server.mjs +16 -11
- package/dist/personas/index.d.ts +1 -1
- package/dist/personas/index.d.ts.map +1 -1
- package/dist/personas/index.js +17 -5
- package/dist/personas/index.mjs +17 -5
- package/dist/personas/resolver.d.ts +35 -8
- package/dist/personas/resolver.d.ts.map +1 -1
- 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/scheduler/index.js +12 -9
- package/dist/scheduler/index.mjs +12 -9
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +44 -25
- package/dist/server.mjs +44 -25
- package/dist/types.d.ts +32 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -11
|
@@ -475,6 +475,7 @@ function createWhatsAppChannel(config) {
|
|
|
475
475
|
assertStrongSecret(config.sessionSecret, "WhatsApp sessionSecret (e.g. WA_SESSION_SECRET)");
|
|
476
476
|
const channelName = config.name ?? "whatsapp";
|
|
477
477
|
const sessionIds = config.sessionIds && config.sessionIds.length > 0 ? config.sessionIds : ["default"];
|
|
478
|
+
const multiEndpoint = config.name !== void 0 || sessionIds.length > 1;
|
|
478
479
|
const now = config.now ?? Date.now;
|
|
479
480
|
const schedule = config.schedule ?? ((fn, ms) => void setTimeout(fn, ms));
|
|
480
481
|
const staleMs = config.staleMs ?? LEASE_STALE_MS;
|
|
@@ -668,7 +669,12 @@ function createWhatsAppChannel(config) {
|
|
|
668
669
|
if (type !== "notify") return;
|
|
669
670
|
for (const message of messages) {
|
|
670
671
|
try {
|
|
671
|
-
await config.onMessage?.({
|
|
672
|
+
await config.onMessage?.({
|
|
673
|
+
sessionId,
|
|
674
|
+
sock,
|
|
675
|
+
message,
|
|
676
|
+
endpointId: multiEndpoint ? sessionId : void 0
|
|
677
|
+
});
|
|
672
678
|
} catch (error) {
|
|
673
679
|
log.warn(`WhatsApp[${sessionId}]: onMessage handler failed:`, error);
|
|
674
680
|
}
|
|
@@ -866,9 +872,10 @@ function detectLeakage(text) {
|
|
|
866
872
|
function scrubOutput(text) {
|
|
867
873
|
return text.replace(/sk-[A-Za-z0-9]{15,}/g, "[REDACTED]").replace(/AIza[0-9A-Za-z_-]{30,}/g, "[REDACTED]");
|
|
868
874
|
}
|
|
869
|
-
|
|
875
|
+
var DEFAULT_REFUSAL = "Sorry, I can't share internal instructions. How else can I help?";
|
|
876
|
+
function guardOutput(text, refusal) {
|
|
870
877
|
if (detectLeakage(text)) {
|
|
871
|
-
return
|
|
878
|
+
return typeof refusal === "string" && refusal.trim() ? refusal : DEFAULT_REFUSAL;
|
|
872
879
|
}
|
|
873
880
|
return scrubOutput(text);
|
|
874
881
|
}
|
|
@@ -880,7 +887,8 @@ async function completeOnce({
|
|
|
880
887
|
system,
|
|
881
888
|
messages,
|
|
882
889
|
temperature = 0.2,
|
|
883
|
-
model = DEFAULT_MODEL
|
|
890
|
+
model = DEFAULT_MODEL,
|
|
891
|
+
refusal
|
|
884
892
|
}) {
|
|
885
893
|
const res = await client.chat.completions.create({
|
|
886
894
|
model,
|
|
@@ -889,19 +897,19 @@ async function completeOnce({
|
|
|
889
897
|
});
|
|
890
898
|
const text = res.choices[0]?.message?.content ?? "";
|
|
891
899
|
return {
|
|
892
|
-
content: guardOutput(text),
|
|
900
|
+
content: guardOutput(text, refusal),
|
|
893
901
|
usage: res.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }
|
|
894
902
|
};
|
|
895
903
|
}
|
|
896
904
|
|
|
897
905
|
// src/core/answer.ts
|
|
898
906
|
var noUsage = () => ({ prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 });
|
|
899
|
-
async function runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }) {
|
|
907
|
+
async function runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }, refusal) {
|
|
900
908
|
const result = await answerFn({ system, messages, mode, sender, conversationId });
|
|
901
909
|
const raw = typeof result === "string" ? result : result?.content;
|
|
902
910
|
const usage = typeof result === "string" ? void 0 : result?.usage;
|
|
903
911
|
return {
|
|
904
|
-
content: guardOutput(typeof raw === "string" ? raw : ""),
|
|
912
|
+
content: guardOutput(typeof raw === "string" ? raw : "", refusal),
|
|
905
913
|
usage: usage ?? noUsage()
|
|
906
914
|
};
|
|
907
915
|
}
|
|
@@ -914,12 +922,13 @@ async function answerOnce({
|
|
|
914
922
|
sender,
|
|
915
923
|
conversationId,
|
|
916
924
|
temperature,
|
|
917
|
-
model
|
|
925
|
+
model,
|
|
926
|
+
refusal
|
|
918
927
|
}) {
|
|
919
928
|
if (answerFn) {
|
|
920
|
-
return runAnswerFn(answerFn, { system, messages, mode, sender, conversationId });
|
|
929
|
+
return runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }, refusal);
|
|
921
930
|
}
|
|
922
|
-
return completeOnce({ client, system, messages, temperature, model });
|
|
931
|
+
return completeOnce({ client, system, messages, temperature, model, refusal });
|
|
923
932
|
}
|
|
924
933
|
async function applyTransformReply(transformReply, input, logger) {
|
|
925
934
|
if (!transformReply) return input.text;
|
|
@@ -1125,9 +1134,17 @@ function resolveBrainHooks(config, fallback) {
|
|
|
1125
1134
|
rewriteQuery: config.rewriteQuery ?? fallback?.rewriteQuery,
|
|
1126
1135
|
rerankContext: config.rerankContext ?? fallback?.rerankContext,
|
|
1127
1136
|
fallbackFn: config.fallbackFn ?? fallback?.fallbackFn,
|
|
1128
|
-
transformReply: config.transformReply ?? fallback?.transformReply
|
|
1137
|
+
transformReply: config.transformReply ?? fallback?.transformReply,
|
|
1138
|
+
refusal: config.refusal ?? fallback?.refusal
|
|
1129
1139
|
};
|
|
1130
1140
|
}
|
|
1141
|
+
function escapeKeyPart(part) {
|
|
1142
|
+
return part.replaceAll("%", "%25").replaceAll("#", "%23");
|
|
1143
|
+
}
|
|
1144
|
+
function conversationKeyFor(chatId, endpointId) {
|
|
1145
|
+
if (!endpointId) return chatId;
|
|
1146
|
+
return `${escapeKeyPart(chatId)}#${escapeKeyPart(endpointId)}`;
|
|
1147
|
+
}
|
|
1131
1148
|
var DEFAULT_HISTORY_LIMIT = 20;
|
|
1132
1149
|
var DEFAULT_GROUP_RATE_LIMIT = { max: 30, windowMs: 60 * 60 * 1e3 };
|
|
1133
1150
|
var DEFAULT_DM_RATE_LIMIT = { max: 20, windowMs: 60 * 60 * 1e3 };
|
|
@@ -1186,11 +1203,15 @@ function createInboundPipeline(deps, config) {
|
|
|
1186
1203
|
return { action: "rate-limited" };
|
|
1187
1204
|
}
|
|
1188
1205
|
const sender = typeof turn.sender === "function" ? await turn.sender() : turn.sender ?? msg.senderId;
|
|
1189
|
-
const conversationId = turn.conversationId ?? msg.chatId;
|
|
1206
|
+
const conversationId = turn.conversationId ?? conversationKeyFor(msg.chatId, msg.endpointId);
|
|
1190
1207
|
if (turn.intercept && await turn.intercept(sender)) {
|
|
1191
1208
|
return { action: "intercepted" };
|
|
1192
1209
|
}
|
|
1193
|
-
const personaLayer = await resolvePersonaLayer(config, {
|
|
1210
|
+
const personaLayer = await resolvePersonaLayer(config, {
|
|
1211
|
+
sender,
|
|
1212
|
+
text: msg.text,
|
|
1213
|
+
endpointId: msg.endpointId
|
|
1214
|
+
});
|
|
1194
1215
|
const buckets = await resolveBuckets({ mode, sender, bucketsFor: config.bucketsFor });
|
|
1195
1216
|
const historyEnabled = config.history ? await isHistoryEnabled(config, sender) : false;
|
|
1196
1217
|
const priorTurns = config.history && historyEnabled ? await config.history.store.load(
|
|
@@ -1223,7 +1244,8 @@ function createInboundPipeline(deps, config) {
|
|
|
1223
1244
|
mode,
|
|
1224
1245
|
sender,
|
|
1225
1246
|
conversationId,
|
|
1226
|
-
model: config.model
|
|
1247
|
+
model: config.model,
|
|
1248
|
+
refusal: config.refusal
|
|
1227
1249
|
});
|
|
1228
1250
|
const content = await applyTransformReply(
|
|
1229
1251
|
config.transformReply,
|
|
@@ -1310,7 +1332,7 @@ function stripOwnMentions(text, ownIds) {
|
|
|
1310
1332
|
return cleaned ? cleaned : text;
|
|
1311
1333
|
}
|
|
1312
1334
|
function resolveWaMessage(event, registry) {
|
|
1313
|
-
const { sessionId, sock, message } = event;
|
|
1335
|
+
const { sessionId, sock, message, endpointId } = event;
|
|
1314
1336
|
const chatId = message.key.remoteJid ?? "";
|
|
1315
1337
|
const rawText = extractText(message);
|
|
1316
1338
|
const context = messageContext(message);
|
|
@@ -1334,7 +1356,13 @@ function resolveWaMessage(event, registry) {
|
|
|
1334
1356
|
// targets. Exposed generically so a caller reaching `msg` through
|
|
1335
1357
|
// `createInboundPipeline` (not just the WhatsApp-specific router) can
|
|
1336
1358
|
// still react to it via `ChannelSenderRegistry.sendReaction`.
|
|
1337
|
-
messageRef: message.key
|
|
1359
|
+
messageRef: message.key,
|
|
1360
|
+
// The session id this channel instance was configured with, not a wire
|
|
1361
|
+
// identity - stable across the number's own SIM or token changing.
|
|
1362
|
+
// Unset for a default single-session channel (see
|
|
1363
|
+
// WhatsAppMessageEvent.endpointId) so a host that hasn't opted into
|
|
1364
|
+
// multiple endpoints sees no change.
|
|
1365
|
+
endpointId
|
|
1338
1366
|
};
|
|
1339
1367
|
return { msg, ownIds };
|
|
1340
1368
|
}
|
|
@@ -1351,7 +1379,7 @@ function createWhatsAppInboundHandler(config) {
|
|
|
1351
1379
|
...resolveBrainHooks(config, config.serverConfig),
|
|
1352
1380
|
model: config.model,
|
|
1353
1381
|
channelHint: config.channelHint ?? "Channel: WhatsApp.",
|
|
1354
|
-
personaResolver: personaResolver ? ({ sender, text }) => personaResolver({ senderPhone: sender, text }) : void 0,
|
|
1382
|
+
personaResolver: personaResolver ? ({ sender, text, endpointId }) => personaResolver({ senderPhone: sender, text, endpointId }) : void 0,
|
|
1355
1383
|
history: config.history,
|
|
1356
1384
|
allowedChats,
|
|
1357
1385
|
muteRegex: config.muteRegex,
|
|
@@ -1388,7 +1416,6 @@ function createWhatsAppInboundHandler(config) {
|
|
|
1388
1416
|
};
|
|
1389
1417
|
await pipeline(msg, {
|
|
1390
1418
|
reply,
|
|
1391
|
-
conversationId: chatId,
|
|
1392
1419
|
sender: () => senderPhoneFor(sock, message, chatId),
|
|
1393
1420
|
intercept: images ? (senderPhone) => images({
|
|
1394
1421
|
sock,
|
|
@@ -410,6 +410,7 @@ function createWhatsAppChannel(config) {
|
|
|
410
410
|
assertStrongSecret(config.sessionSecret, "WhatsApp sessionSecret (e.g. WA_SESSION_SECRET)");
|
|
411
411
|
const channelName = config.name ?? "whatsapp";
|
|
412
412
|
const sessionIds = config.sessionIds && config.sessionIds.length > 0 ? config.sessionIds : ["default"];
|
|
413
|
+
const multiEndpoint = config.name !== void 0 || sessionIds.length > 1;
|
|
413
414
|
const now = config.now ?? Date.now;
|
|
414
415
|
const schedule = config.schedule ?? ((fn, ms) => void setTimeout(fn, ms));
|
|
415
416
|
const staleMs = config.staleMs ?? LEASE_STALE_MS;
|
|
@@ -603,7 +604,12 @@ function createWhatsAppChannel(config) {
|
|
|
603
604
|
if (type !== "notify") return;
|
|
604
605
|
for (const message of messages) {
|
|
605
606
|
try {
|
|
606
|
-
await config.onMessage?.({
|
|
607
|
+
await config.onMessage?.({
|
|
608
|
+
sessionId,
|
|
609
|
+
sock,
|
|
610
|
+
message,
|
|
611
|
+
endpointId: multiEndpoint ? sessionId : void 0
|
|
612
|
+
});
|
|
607
613
|
} catch (error) {
|
|
608
614
|
log.warn(`WhatsApp[${sessionId}]: onMessage handler failed:`, error);
|
|
609
615
|
}
|
|
@@ -801,9 +807,10 @@ function detectLeakage(text) {
|
|
|
801
807
|
function scrubOutput(text) {
|
|
802
808
|
return text.replace(/sk-[A-Za-z0-9]{15,}/g, "[REDACTED]").replace(/AIza[0-9A-Za-z_-]{30,}/g, "[REDACTED]");
|
|
803
809
|
}
|
|
804
|
-
|
|
810
|
+
var DEFAULT_REFUSAL = "Sorry, I can't share internal instructions. How else can I help?";
|
|
811
|
+
function guardOutput(text, refusal) {
|
|
805
812
|
if (detectLeakage(text)) {
|
|
806
|
-
return
|
|
813
|
+
return typeof refusal === "string" && refusal.trim() ? refusal : DEFAULT_REFUSAL;
|
|
807
814
|
}
|
|
808
815
|
return scrubOutput(text);
|
|
809
816
|
}
|
|
@@ -815,7 +822,8 @@ async function completeOnce({
|
|
|
815
822
|
system,
|
|
816
823
|
messages,
|
|
817
824
|
temperature = 0.2,
|
|
818
|
-
model = DEFAULT_MODEL
|
|
825
|
+
model = DEFAULT_MODEL,
|
|
826
|
+
refusal
|
|
819
827
|
}) {
|
|
820
828
|
const res = await client.chat.completions.create({
|
|
821
829
|
model,
|
|
@@ -824,19 +832,19 @@ async function completeOnce({
|
|
|
824
832
|
});
|
|
825
833
|
const text = res.choices[0]?.message?.content ?? "";
|
|
826
834
|
return {
|
|
827
|
-
content: guardOutput(text),
|
|
835
|
+
content: guardOutput(text, refusal),
|
|
828
836
|
usage: res.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }
|
|
829
837
|
};
|
|
830
838
|
}
|
|
831
839
|
|
|
832
840
|
// src/core/answer.ts
|
|
833
841
|
var noUsage = () => ({ prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 });
|
|
834
|
-
async function runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }) {
|
|
842
|
+
async function runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }, refusal) {
|
|
835
843
|
const result = await answerFn({ system, messages, mode, sender, conversationId });
|
|
836
844
|
const raw = typeof result === "string" ? result : result?.content;
|
|
837
845
|
const usage = typeof result === "string" ? void 0 : result?.usage;
|
|
838
846
|
return {
|
|
839
|
-
content: guardOutput(typeof raw === "string" ? raw : ""),
|
|
847
|
+
content: guardOutput(typeof raw === "string" ? raw : "", refusal),
|
|
840
848
|
usage: usage ?? noUsage()
|
|
841
849
|
};
|
|
842
850
|
}
|
|
@@ -849,12 +857,13 @@ async function answerOnce({
|
|
|
849
857
|
sender,
|
|
850
858
|
conversationId,
|
|
851
859
|
temperature,
|
|
852
|
-
model
|
|
860
|
+
model,
|
|
861
|
+
refusal
|
|
853
862
|
}) {
|
|
854
863
|
if (answerFn) {
|
|
855
|
-
return runAnswerFn(answerFn, { system, messages, mode, sender, conversationId });
|
|
864
|
+
return runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }, refusal);
|
|
856
865
|
}
|
|
857
|
-
return completeOnce({ client, system, messages, temperature, model });
|
|
866
|
+
return completeOnce({ client, system, messages, temperature, model, refusal });
|
|
858
867
|
}
|
|
859
868
|
async function applyTransformReply(transformReply, input, logger) {
|
|
860
869
|
if (!transformReply) return input.text;
|
|
@@ -1060,9 +1069,17 @@ function resolveBrainHooks(config, fallback) {
|
|
|
1060
1069
|
rewriteQuery: config.rewriteQuery ?? fallback?.rewriteQuery,
|
|
1061
1070
|
rerankContext: config.rerankContext ?? fallback?.rerankContext,
|
|
1062
1071
|
fallbackFn: config.fallbackFn ?? fallback?.fallbackFn,
|
|
1063
|
-
transformReply: config.transformReply ?? fallback?.transformReply
|
|
1072
|
+
transformReply: config.transformReply ?? fallback?.transformReply,
|
|
1073
|
+
refusal: config.refusal ?? fallback?.refusal
|
|
1064
1074
|
};
|
|
1065
1075
|
}
|
|
1076
|
+
function escapeKeyPart(part) {
|
|
1077
|
+
return part.replaceAll("%", "%25").replaceAll("#", "%23");
|
|
1078
|
+
}
|
|
1079
|
+
function conversationKeyFor(chatId, endpointId) {
|
|
1080
|
+
if (!endpointId) return chatId;
|
|
1081
|
+
return `${escapeKeyPart(chatId)}#${escapeKeyPart(endpointId)}`;
|
|
1082
|
+
}
|
|
1066
1083
|
var DEFAULT_HISTORY_LIMIT = 20;
|
|
1067
1084
|
var DEFAULT_GROUP_RATE_LIMIT = { max: 30, windowMs: 60 * 60 * 1e3 };
|
|
1068
1085
|
var DEFAULT_DM_RATE_LIMIT = { max: 20, windowMs: 60 * 60 * 1e3 };
|
|
@@ -1121,11 +1138,15 @@ function createInboundPipeline(deps, config) {
|
|
|
1121
1138
|
return { action: "rate-limited" };
|
|
1122
1139
|
}
|
|
1123
1140
|
const sender = typeof turn.sender === "function" ? await turn.sender() : turn.sender ?? msg.senderId;
|
|
1124
|
-
const conversationId = turn.conversationId ?? msg.chatId;
|
|
1141
|
+
const conversationId = turn.conversationId ?? conversationKeyFor(msg.chatId, msg.endpointId);
|
|
1125
1142
|
if (turn.intercept && await turn.intercept(sender)) {
|
|
1126
1143
|
return { action: "intercepted" };
|
|
1127
1144
|
}
|
|
1128
|
-
const personaLayer = await resolvePersonaLayer(config, {
|
|
1145
|
+
const personaLayer = await resolvePersonaLayer(config, {
|
|
1146
|
+
sender,
|
|
1147
|
+
text: msg.text,
|
|
1148
|
+
endpointId: msg.endpointId
|
|
1149
|
+
});
|
|
1129
1150
|
const buckets = await resolveBuckets({ mode, sender, bucketsFor: config.bucketsFor });
|
|
1130
1151
|
const historyEnabled = config.history ? await isHistoryEnabled(config, sender) : false;
|
|
1131
1152
|
const priorTurns = config.history && historyEnabled ? await config.history.store.load(
|
|
@@ -1158,7 +1179,8 @@ function createInboundPipeline(deps, config) {
|
|
|
1158
1179
|
mode,
|
|
1159
1180
|
sender,
|
|
1160
1181
|
conversationId,
|
|
1161
|
-
model: config.model
|
|
1182
|
+
model: config.model,
|
|
1183
|
+
refusal: config.refusal
|
|
1162
1184
|
});
|
|
1163
1185
|
const content = await applyTransformReply(
|
|
1164
1186
|
config.transformReply,
|
|
@@ -1245,7 +1267,7 @@ function stripOwnMentions(text, ownIds) {
|
|
|
1245
1267
|
return cleaned ? cleaned : text;
|
|
1246
1268
|
}
|
|
1247
1269
|
function resolveWaMessage(event, registry) {
|
|
1248
|
-
const { sessionId, sock, message } = event;
|
|
1270
|
+
const { sessionId, sock, message, endpointId } = event;
|
|
1249
1271
|
const chatId = message.key.remoteJid ?? "";
|
|
1250
1272
|
const rawText = extractText(message);
|
|
1251
1273
|
const context = messageContext(message);
|
|
@@ -1269,7 +1291,13 @@ function resolveWaMessage(event, registry) {
|
|
|
1269
1291
|
// targets. Exposed generically so a caller reaching `msg` through
|
|
1270
1292
|
// `createInboundPipeline` (not just the WhatsApp-specific router) can
|
|
1271
1293
|
// still react to it via `ChannelSenderRegistry.sendReaction`.
|
|
1272
|
-
messageRef: message.key
|
|
1294
|
+
messageRef: message.key,
|
|
1295
|
+
// The session id this channel instance was configured with, not a wire
|
|
1296
|
+
// identity - stable across the number's own SIM or token changing.
|
|
1297
|
+
// Unset for a default single-session channel (see
|
|
1298
|
+
// WhatsAppMessageEvent.endpointId) so a host that hasn't opted into
|
|
1299
|
+
// multiple endpoints sees no change.
|
|
1300
|
+
endpointId
|
|
1273
1301
|
};
|
|
1274
1302
|
return { msg, ownIds };
|
|
1275
1303
|
}
|
|
@@ -1286,7 +1314,7 @@ function createWhatsAppInboundHandler(config) {
|
|
|
1286
1314
|
...resolveBrainHooks(config, config.serverConfig),
|
|
1287
1315
|
model: config.model,
|
|
1288
1316
|
channelHint: config.channelHint ?? "Channel: WhatsApp.",
|
|
1289
|
-
personaResolver: personaResolver ? ({ sender, text }) => personaResolver({ senderPhone: sender, text }) : void 0,
|
|
1317
|
+
personaResolver: personaResolver ? ({ sender, text, endpointId }) => personaResolver({ senderPhone: sender, text, endpointId }) : void 0,
|
|
1290
1318
|
history: config.history,
|
|
1291
1319
|
allowedChats,
|
|
1292
1320
|
muteRegex: config.muteRegex,
|
|
@@ -1323,7 +1351,6 @@ function createWhatsAppInboundHandler(config) {
|
|
|
1323
1351
|
};
|
|
1324
1352
|
await pipeline(msg, {
|
|
1325
1353
|
reply,
|
|
1326
|
-
conversationId: chatId,
|
|
1327
1354
|
sender: () => senderPhoneFor(sock, message, chatId),
|
|
1328
1355
|
intercept: images ? (senderPhone) => images({
|
|
1329
1356
|
sock,
|
package/dist/core/answer.d.ts
CHANGED
|
@@ -59,11 +59,18 @@ export interface AnswerOptions {
|
|
|
59
59
|
conversationId?: string;
|
|
60
60
|
temperature?: number;
|
|
61
61
|
model?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Wording for the guardrail refusal, for a surface that has already
|
|
64
|
+
* resolved whose voice this answer speaks in. Falls back to the
|
|
65
|
+
* server/channel-level `BrainHooks.refusal` the call site passes, and then
|
|
66
|
+
* to `DEFAULT_REFUSAL`. Detection and scrubbing stay Chatter's either way.
|
|
67
|
+
*/
|
|
68
|
+
refusal?: string;
|
|
62
69
|
}
|
|
63
70
|
/**
|
|
64
71
|
* Produce one complete answer, from `answerFn` when configured.
|
|
65
72
|
*/
|
|
66
|
-
export declare function answerOnce({ answerFn, client, system, messages, mode, sender, conversationId, temperature, model, }: AnswerOptions): Promise<{
|
|
73
|
+
export declare function answerOnce({ answerFn, client, system, messages, mode, sender, conversationId, temperature, model, refusal, }: AnswerOptions): Promise<{
|
|
67
74
|
content: string;
|
|
68
75
|
usage: AnswerUsage;
|
|
69
76
|
}>;
|
|
@@ -114,5 +121,5 @@ export declare function applyTransformReply(transformReply: TransformReply | und
|
|
|
114
121
|
* built-in stream only scrubs each delta, since leakage detection needs text
|
|
115
122
|
* no streamed chunk has yet.
|
|
116
123
|
*/
|
|
117
|
-
export declare function answerStream({ answerFn, client, system, messages, mode, sender, conversationId, temperature, model, }: AnswerOptions): AsyncGenerator<string>;
|
|
124
|
+
export declare function answerStream({ answerFn, client, system, messages, mode, sender, conversationId, temperature, model, refusal, }: AnswerOptions): AsyncGenerator<string>;
|
|
118
125
|
//# sourceMappingURL=answer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"answer.d.ts","sourceRoot":"","sources":["../../src/core/answer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhE,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAKD,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,uCAAuC;IACvC,IAAI,EAAE,YAAY,CAAC;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAE/E;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAAC;AAE1F,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"answer.d.ts","sourceRoot":"","sources":["../../src/core/answer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhE,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAKD,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,uCAAuC;IACvC,IAAI,EAAE,YAAY,CAAC;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAE/E;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAAC;AAE1F,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAsBD;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAC/B,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,cAAc,EACd,WAAW,EACX,KAAK,EACL,OAAO,GACR,EAAE,aAAa,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAAC,CAKlE;AAED,4FAA4F;AAC5F,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAEpG;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,cAAc,EAAE,cAAc,GAAG,SAAS,EAC1C,KAAK,EAAE,mBAAmB,EAC1B,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAYxB;AAED;;;;;;;;GAQG;AACH,wBAAuB,YAAY,CAAC,EAClC,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,cAAc,EACd,WAAW,EACX,KAAK,EACL,OAAO,GACR,EAAE,aAAa,GAAG,cAAc,CAAC,MAAM,CAAC,CAWxC"}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
export declare function detectLeakage(text: string): boolean;
|
|
2
2
|
export declare function scrubOutput(text: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* The refusal sent when leaked instructions are detected and no host has
|
|
5
|
+
* supplied its own wording.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_REFUSAL = "Sorry, I can't share internal instructions. How else can I help?";
|
|
3
8
|
/**
|
|
4
9
|
* Apply the full output guardrails to a complete answer: refuse leaked
|
|
5
10
|
* instructions outright, then scrub credentials from whatever remains.
|
|
6
11
|
*
|
|
7
12
|
* Used for every non-streamed answer, whoever produced it — the built-in
|
|
8
13
|
* completion or a caller-supplied brain (`answerFn`).
|
|
14
|
+
*
|
|
15
|
+
* `refusal` only replaces the wording of the refusal. Detection and scrubbing
|
|
16
|
+
* are not configurable, so a host can voice the guard but never weaken it; a
|
|
17
|
+
* blank or non-string `refusal` falls back to `DEFAULT_REFUSAL` rather than
|
|
18
|
+
* letting a host silence the refusal by supplying an empty line.
|
|
9
19
|
*/
|
|
10
|
-
export declare function guardOutput(text: string): string;
|
|
20
|
+
export declare function guardOutput(text: string, refusal?: string): string;
|
|
11
21
|
//# sourceMappingURL=guardrails.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../src/core/guardrails.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASnD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED
|
|
1
|
+
{"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../src/core/guardrails.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASnD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,qEAAqE,CAAC;AAElG;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAKlE"}
|
package/dist/core/llm.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type OpenAI from "openai";
|
|
2
2
|
export declare const DEFAULT_MODEL = "gpt-4o";
|
|
3
|
-
export declare function completeOnce({ client, system, messages, temperature, model, }: {
|
|
3
|
+
export declare function completeOnce({ client, system, messages, temperature, model, refusal, }: {
|
|
4
4
|
client: OpenAI;
|
|
5
5
|
system: string;
|
|
6
6
|
messages: {
|
|
@@ -9,6 +9,8 @@ export declare function completeOnce({ client, system, messages, temperature, mo
|
|
|
9
9
|
}[];
|
|
10
10
|
temperature?: number;
|
|
11
11
|
model?: string;
|
|
12
|
+
/** Wording for the guardrail refusal; falls back to `DEFAULT_REFUSAL`. */
|
|
13
|
+
refusal?: string;
|
|
12
14
|
}): Promise<{
|
|
13
15
|
content: string;
|
|
14
16
|
usage: OpenAI.CompletionUsage;
|
package/dist/core/llm.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/core/llm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,eAAO,MAAM,aAAa,WAAW,CAAC;AAEtC,wBAAsB,YAAY,CAAC,EACjC,MAAM,EACN,MAAM,EACN,QAAQ,EACR,WAAiB,EACjB,KAAqB,
|
|
1
|
+
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/core/llm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,eAAO,MAAM,aAAa,WAAW,CAAC;AAEtC,wBAAsB,YAAY,CAAC,EACjC,MAAM,EACN,MAAM,EACN,QAAQ,EACR,WAAiB,EACjB,KAAqB,EACrB,OAAO,GACR,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;;;GAWA;AAGD,wBAAuB,cAAc,CAAC,EACpC,MAAM,EACN,MAAM,EACN,QAAQ,EACR,WAAiB,EACjB,KAAqB,GACtB,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,yCAYA"}
|
package/dist/history/index.js
CHANGED
|
@@ -41,9 +41,10 @@ function detectLeakage(text) {
|
|
|
41
41
|
function scrubOutput(text) {
|
|
42
42
|
return text.replace(/sk-[A-Za-z0-9]{15,}/g, "[REDACTED]").replace(/AIza[0-9A-Za-z_-]{30,}/g, "[REDACTED]");
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
var DEFAULT_REFUSAL = "Sorry, I can't share internal instructions. How else can I help?";
|
|
45
|
+
function guardOutput(text, refusal) {
|
|
45
46
|
if (detectLeakage(text)) {
|
|
46
|
-
return
|
|
47
|
+
return typeof refusal === "string" && refusal.trim() ? refusal : DEFAULT_REFUSAL;
|
|
47
48
|
}
|
|
48
49
|
return scrubOutput(text);
|
|
49
50
|
}
|
|
@@ -55,7 +56,8 @@ async function completeOnce({
|
|
|
55
56
|
system,
|
|
56
57
|
messages,
|
|
57
58
|
temperature = 0.2,
|
|
58
|
-
model = DEFAULT_MODEL
|
|
59
|
+
model = DEFAULT_MODEL,
|
|
60
|
+
refusal
|
|
59
61
|
}) {
|
|
60
62
|
const res = await client.chat.completions.create({
|
|
61
63
|
model,
|
|
@@ -64,19 +66,19 @@ async function completeOnce({
|
|
|
64
66
|
});
|
|
65
67
|
const text = res.choices[0]?.message?.content ?? "";
|
|
66
68
|
return {
|
|
67
|
-
content: guardOutput(text),
|
|
69
|
+
content: guardOutput(text, refusal),
|
|
68
70
|
usage: res.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }
|
|
69
71
|
};
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
// src/core/answer.ts
|
|
73
75
|
var noUsage = () => ({ prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 });
|
|
74
|
-
async function runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }) {
|
|
76
|
+
async function runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }, refusal) {
|
|
75
77
|
const result = await answerFn({ system, messages, mode, sender, conversationId });
|
|
76
78
|
const raw = typeof result === "string" ? result : result?.content;
|
|
77
79
|
const usage = typeof result === "string" ? void 0 : result?.usage;
|
|
78
80
|
return {
|
|
79
|
-
content: guardOutput(typeof raw === "string" ? raw : ""),
|
|
81
|
+
content: guardOutput(typeof raw === "string" ? raw : "", refusal),
|
|
80
82
|
usage: usage ?? noUsage()
|
|
81
83
|
};
|
|
82
84
|
}
|
|
@@ -89,12 +91,13 @@ async function answerOnce({
|
|
|
89
91
|
sender,
|
|
90
92
|
conversationId,
|
|
91
93
|
temperature,
|
|
92
|
-
model
|
|
94
|
+
model,
|
|
95
|
+
refusal
|
|
93
96
|
}) {
|
|
94
97
|
if (answerFn) {
|
|
95
|
-
return runAnswerFn(answerFn, { system, messages, mode, sender, conversationId });
|
|
98
|
+
return runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }, refusal);
|
|
96
99
|
}
|
|
97
|
-
return completeOnce({ client, system, messages, temperature, model });
|
|
100
|
+
return completeOnce({ client, system, messages, temperature, model, refusal });
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
// src/history/compaction.ts
|
package/dist/history/index.mjs
CHANGED
|
@@ -12,9 +12,10 @@ function detectLeakage(text) {
|
|
|
12
12
|
function scrubOutput(text) {
|
|
13
13
|
return text.replace(/sk-[A-Za-z0-9]{15,}/g, "[REDACTED]").replace(/AIza[0-9A-Za-z_-]{30,}/g, "[REDACTED]");
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
var DEFAULT_REFUSAL = "Sorry, I can't share internal instructions. How else can I help?";
|
|
16
|
+
function guardOutput(text, refusal) {
|
|
16
17
|
if (detectLeakage(text)) {
|
|
17
|
-
return
|
|
18
|
+
return typeof refusal === "string" && refusal.trim() ? refusal : DEFAULT_REFUSAL;
|
|
18
19
|
}
|
|
19
20
|
return scrubOutput(text);
|
|
20
21
|
}
|
|
@@ -26,7 +27,8 @@ async function completeOnce({
|
|
|
26
27
|
system,
|
|
27
28
|
messages,
|
|
28
29
|
temperature = 0.2,
|
|
29
|
-
model = DEFAULT_MODEL
|
|
30
|
+
model = DEFAULT_MODEL,
|
|
31
|
+
refusal
|
|
30
32
|
}) {
|
|
31
33
|
const res = await client.chat.completions.create({
|
|
32
34
|
model,
|
|
@@ -35,19 +37,19 @@ async function completeOnce({
|
|
|
35
37
|
});
|
|
36
38
|
const text = res.choices[0]?.message?.content ?? "";
|
|
37
39
|
return {
|
|
38
|
-
content: guardOutput(text),
|
|
40
|
+
content: guardOutput(text, refusal),
|
|
39
41
|
usage: res.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }
|
|
40
42
|
};
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
// src/core/answer.ts
|
|
44
46
|
var noUsage = () => ({ prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 });
|
|
45
|
-
async function runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }) {
|
|
47
|
+
async function runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }, refusal) {
|
|
46
48
|
const result = await answerFn({ system, messages, mode, sender, conversationId });
|
|
47
49
|
const raw = typeof result === "string" ? result : result?.content;
|
|
48
50
|
const usage = typeof result === "string" ? void 0 : result?.usage;
|
|
49
51
|
return {
|
|
50
|
-
content: guardOutput(typeof raw === "string" ? raw : ""),
|
|
52
|
+
content: guardOutput(typeof raw === "string" ? raw : "", refusal),
|
|
51
53
|
usage: usage ?? noUsage()
|
|
52
54
|
};
|
|
53
55
|
}
|
|
@@ -60,12 +62,13 @@ async function answerOnce({
|
|
|
60
62
|
sender,
|
|
61
63
|
conversationId,
|
|
62
64
|
temperature,
|
|
63
|
-
model
|
|
65
|
+
model,
|
|
66
|
+
refusal
|
|
64
67
|
}) {
|
|
65
68
|
if (answerFn) {
|
|
66
|
-
return runAnswerFn(answerFn, { system, messages, mode, sender, conversationId });
|
|
69
|
+
return runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }, refusal);
|
|
67
70
|
}
|
|
68
|
-
return completeOnce({ client, system, messages, temperature, model });
|
|
71
|
+
return completeOnce({ client, system, messages, temperature, model, refusal });
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
// src/history/compaction.ts
|
package/dist/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export type { BucketsFor, BucketsForContext } from "./core/buckets";
|
|
|
20
20
|
export { defaultBuckets, resolveBuckets } from "./core/buckets";
|
|
21
21
|
export type { BuildLock, BuildLockRow } from "./core/buildLock";
|
|
22
22
|
export { BUILD_LOCK_KEY, BUILD_LOCK_STALE_MS, canAcquireBuildLock, createTursoBuildLock, } from "./core/buildLock";
|
|
23
|
-
export { detectLeakage, guardOutput, scrubOutput } from "./core/guardrails";
|
|
23
|
+
export { DEFAULT_REFUSAL, detectLeakage, guardOutput, scrubOutput } from "./core/guardrails";
|
|
24
24
|
export { completeOnce, completeStream, DEFAULT_MODEL } from "./core/llm";
|
|
25
25
|
export { loadKnowledge } from "./core/loaders";
|
|
26
26
|
export type { Logger, LogLevel } from "./core/logger";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEzE,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAIvC,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,QAAQ,EACR,eAAe,GAChB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,QAAQ,EACR,aAAa,EACb,cAAc,EACd,aAAa,EACb,WAAW,EACX,cAAc,EACd,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC9E,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|