@diegoaltoworks/chatter 0.42.0 → 0.44.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/whatsapp/inbound.d.ts +23 -0
- package/dist/channels/whatsapp/inbound.d.ts.map +1 -1
- package/dist/channels/whatsapp/index.d.ts +1 -1
- package/dist/channels/whatsapp/index.d.ts.map +1 -1
- package/dist/channels/whatsapp/index.js +24 -6
- package/dist/channels/whatsapp/index.mjs +23 -6
- package/dist/core/messages.d.ts +38 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.test.d.ts +8 -0
- package/dist/core/messages.test.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +62 -50
- package/dist/index.mjs +60 -50
- package/dist/routes/demo.d.ts.map +1 -1
- package/dist/routes/openai.d.ts +0 -7
- 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/package.json +1 -1
|
@@ -82,6 +82,29 @@ export interface WaMessageContext {
|
|
|
82
82
|
export declare function messageContext(message: WAMessage): WaMessageContext;
|
|
83
83
|
/** Text/caption across every shape that can carry one — plain text, a reply, or a photo/video/document caption. */
|
|
84
84
|
export declare function extractText(message: WAMessage): string;
|
|
85
|
+
/**
|
|
86
|
+
* Removes the bot's OWN @mention tokens from a message's text.
|
|
87
|
+
*
|
|
88
|
+
* WhatsApp puts a mention in the raw text as the literal token `@<digits>` —
|
|
89
|
+
* the mentioned jid's user part — and only resolves it to a jid separately,
|
|
90
|
+
* on `contextInfo.mentionedJid`. Handed to a model untouched, the bot's own
|
|
91
|
+
* mention reads as a meaningless number, and the answer derails into asking
|
|
92
|
+
* the sender what `@<botDigits>` means instead of doing what the rest of the
|
|
93
|
+
* message asked.
|
|
94
|
+
*
|
|
95
|
+
* Only the bot's own tokens go: another participant's mention is real
|
|
96
|
+
* context ("tell @<someoneElse> I'm late"), and the numeral is all the model
|
|
97
|
+
* gets of them. Matching is on the digits alone, so both the phone-number and
|
|
98
|
+
* the LID form of the bot's own identity are covered.
|
|
99
|
+
*
|
|
100
|
+
* Everything else in the message is left byte-for-byte alone — indentation
|
|
101
|
+
* and blank lines in a pasted snippet included.
|
|
102
|
+
*
|
|
103
|
+
* A mention-only message ("@bot" and nothing else) keeps its original text:
|
|
104
|
+
* emptying it would make the reply gates read it as blank and drop it, so the
|
|
105
|
+
* bot would go silent on being addressed rather than answer.
|
|
106
|
+
*/
|
|
107
|
+
export declare function stripOwnMentions(text: string, ownIds: string[]): string;
|
|
85
108
|
export interface WhatsAppInboundConfig {
|
|
86
109
|
client: OpenAI;
|
|
87
110
|
store: VectorStore;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/inbound.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,KAAK,QAAQ,EAAc,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,KAAK,UAAU,EAAkB,MAAM,oBAAoB,CAAC;AAErE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAKL,KAAK,uBAAuB,EAE7B,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAIrD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE/C;
|
|
1
|
+
{"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/inbound.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,6 +30,6 @@ export { loadBaileys } from "./baileys";
|
|
|
30
30
|
export { acquireSessionLease, createWhatsAppChannel, type LeaseGatedConnectDeps, reconnectDelayMs, senderNameFor, shutdownWaSessions, type WaSessionHandle, type WhatsAppChannelConfig, type WhatsAppMessageEvent, } from "./channel";
|
|
31
31
|
export { decrypt, encrypt } from "./crypto";
|
|
32
32
|
export { createWhatsAppImageHandler, type DrawRequestDetectorConfig, drawSubject, isDrawRequest, type WhatsAppImageHandler, type WhatsAppImageHandlerDeps, type WhatsAppImageRequestContext, type WhatsAppImageStrings, } from "./images";
|
|
33
|
-
export { createWhatsAppInboundHandler, extractText, isGroupJid, jidsMatch, jidToPhoneNumber, messageContext, senderPhoneFor, type WaMessageContext, type WhatsAppInboundConfig, } from "./inbound";
|
|
33
|
+
export { createWhatsAppInboundHandler, extractText, isGroupJid, jidsMatch, jidToPhoneNumber, messageContext, senderPhoneFor, stripOwnMentions, type WaMessageContext, type WhatsAppInboundConfig, } from "./inbound";
|
|
34
34
|
export { canAcquireLease, createTursoWaLeaseStore, LEASE_HEARTBEAT_MS, LEASE_STALE_MS, LEASE_WAIT_MS, type WaLeaseRow, type WaLeaseStore, } from "./lease";
|
|
35
35
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,qBAAqB,EAC1B,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EACL,0BAA0B,EAC1B,KAAK,yBAAyB,EAC9B,WAAW,EACX,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,EAChC,KAAK,oBAAoB,GAC1B,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,4BAA4B,EAC5B,WAAW,EACX,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,GAC3B,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,qBAAqB,EAC1B,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EACL,0BAA0B,EAC1B,KAAK,yBAAyB,EAC9B,WAAW,EACX,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,EAChC,KAAK,oBAAoB,GAC1B,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,4BAA4B,EAC5B,WAAW,EACX,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,GAC3B,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC"}
|
|
@@ -53,6 +53,7 @@ __export(index_exports, {
|
|
|
53
53
|
senderNameFor: () => senderNameFor,
|
|
54
54
|
senderPhoneFor: () => senderPhoneFor,
|
|
55
55
|
shutdownWaSessions: () => shutdownWaSessions,
|
|
56
|
+
stripOwnMentions: () => stripOwnMentions,
|
|
56
57
|
useTursoAuthState: () => useTursoAuthState
|
|
57
58
|
});
|
|
58
59
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -717,19 +718,21 @@ function isEffectivelyFromSelf(msg, registry) {
|
|
|
717
718
|
function isGroupJid(jid) {
|
|
718
719
|
return jid.endsWith("@g.us");
|
|
719
720
|
}
|
|
721
|
+
function bareUser(jid) {
|
|
722
|
+
return jid.split("@")[0]?.split(":")[0] ?? "";
|
|
723
|
+
}
|
|
720
724
|
function jidsMatch(a, b) {
|
|
721
725
|
if (!a || !b) return false;
|
|
722
|
-
|
|
723
|
-
return bare(a) === bare(b);
|
|
726
|
+
return bareUser(a) === bareUser(b);
|
|
724
727
|
}
|
|
725
728
|
function jidToPhoneNumber(jid) {
|
|
726
|
-
const bare = jid
|
|
729
|
+
const bare = bareUser(jid);
|
|
727
730
|
return bare.startsWith("+") ? bare : `+${bare}`;
|
|
728
731
|
}
|
|
729
732
|
function normalizeJid(jid) {
|
|
730
733
|
const [user = "", domain] = jid.split("@");
|
|
731
|
-
const
|
|
732
|
-
return domain ? `${
|
|
734
|
+
const withoutDevice = user.split(":")[0] ?? user;
|
|
735
|
+
return domain ? `${withoutDevice}@${domain}` : withoutDevice;
|
|
733
736
|
}
|
|
734
737
|
async function senderPhoneFor(sock, message, chatJid) {
|
|
735
738
|
const key = message.key;
|
|
@@ -758,6 +761,19 @@ function extractText(message) {
|
|
|
758
761
|
if (!content) return "";
|
|
759
762
|
return content.conversation ?? content.extendedTextMessage?.text ?? content.imageMessage?.caption ?? content.videoMessage?.caption ?? content.documentMessage?.caption ?? "";
|
|
760
763
|
}
|
|
764
|
+
function stripOwnMentions(text, ownIds) {
|
|
765
|
+
const ownUsers = new Set(ownIds.map(bareUser).filter(Boolean));
|
|
766
|
+
if (!text || ownUsers.size === 0) return text;
|
|
767
|
+
let struck = false;
|
|
768
|
+
const stripped = text.replace(/(?<!\S)@(\d+)[^\S\n]*/g, (token, digits) => {
|
|
769
|
+
if (!ownUsers.has(digits)) return token;
|
|
770
|
+
struck = true;
|
|
771
|
+
return "";
|
|
772
|
+
});
|
|
773
|
+
if (!struck) return text;
|
|
774
|
+
const cleaned = stripped.trim();
|
|
775
|
+
return cleaned ? cleaned : text;
|
|
776
|
+
}
|
|
761
777
|
var DEFAULT_GROUP_RATE_LIMIT = { max: 30, windowMs: 60 * 60 * 1e3 };
|
|
762
778
|
var DEFAULT_DM_RATE_LIMIT = { max: 20, windowMs: 60 * 60 * 1e3 };
|
|
763
779
|
async function resolvePersonaLayer(config, ctx) {
|
|
@@ -780,11 +796,12 @@ function createWhatsAppInboundHandler(config) {
|
|
|
780
796
|
try {
|
|
781
797
|
const chatId = message.key.remoteJid ?? "";
|
|
782
798
|
if (!chatId || chatId === "status@broadcast") return;
|
|
783
|
-
const
|
|
799
|
+
const rawText = extractText(message);
|
|
784
800
|
const context = messageContext(message);
|
|
785
801
|
const senderId = message.key.participant ?? chatId;
|
|
786
802
|
const ownIds = [sock.user?.id, sock.user?.lid].filter((id) => Boolean(id)).map(normalizeJid);
|
|
787
803
|
config.registry.set(sessionId, ownIds);
|
|
804
|
+
const text = stripOwnMentions(rawText, ownIds);
|
|
788
805
|
const fromBot = isEffectivelyFromSelf(
|
|
789
806
|
{ fromBot: message.key.fromMe ?? false, senderId: normalizeJid(senderId) },
|
|
790
807
|
config.registry
|
|
@@ -888,5 +905,6 @@ function createWhatsAppInboundHandler(config) {
|
|
|
888
905
|
senderNameFor,
|
|
889
906
|
senderPhoneFor,
|
|
890
907
|
shutdownWaSessions,
|
|
908
|
+
stripOwnMentions,
|
|
891
909
|
useTursoAuthState
|
|
892
910
|
});
|
|
@@ -658,19 +658,21 @@ function isEffectivelyFromSelf(msg, registry) {
|
|
|
658
658
|
function isGroupJid(jid) {
|
|
659
659
|
return jid.endsWith("@g.us");
|
|
660
660
|
}
|
|
661
|
+
function bareUser(jid) {
|
|
662
|
+
return jid.split("@")[0]?.split(":")[0] ?? "";
|
|
663
|
+
}
|
|
661
664
|
function jidsMatch(a, b) {
|
|
662
665
|
if (!a || !b) return false;
|
|
663
|
-
|
|
664
|
-
return bare(a) === bare(b);
|
|
666
|
+
return bareUser(a) === bareUser(b);
|
|
665
667
|
}
|
|
666
668
|
function jidToPhoneNumber(jid) {
|
|
667
|
-
const bare = jid
|
|
669
|
+
const bare = bareUser(jid);
|
|
668
670
|
return bare.startsWith("+") ? bare : `+${bare}`;
|
|
669
671
|
}
|
|
670
672
|
function normalizeJid(jid) {
|
|
671
673
|
const [user = "", domain] = jid.split("@");
|
|
672
|
-
const
|
|
673
|
-
return domain ? `${
|
|
674
|
+
const withoutDevice = user.split(":")[0] ?? user;
|
|
675
|
+
return domain ? `${withoutDevice}@${domain}` : withoutDevice;
|
|
674
676
|
}
|
|
675
677
|
async function senderPhoneFor(sock, message, chatJid) {
|
|
676
678
|
const key = message.key;
|
|
@@ -699,6 +701,19 @@ function extractText(message) {
|
|
|
699
701
|
if (!content) return "";
|
|
700
702
|
return content.conversation ?? content.extendedTextMessage?.text ?? content.imageMessage?.caption ?? content.videoMessage?.caption ?? content.documentMessage?.caption ?? "";
|
|
701
703
|
}
|
|
704
|
+
function stripOwnMentions(text, ownIds) {
|
|
705
|
+
const ownUsers = new Set(ownIds.map(bareUser).filter(Boolean));
|
|
706
|
+
if (!text || ownUsers.size === 0) return text;
|
|
707
|
+
let struck = false;
|
|
708
|
+
const stripped = text.replace(/(?<!\S)@(\d+)[^\S\n]*/g, (token, digits) => {
|
|
709
|
+
if (!ownUsers.has(digits)) return token;
|
|
710
|
+
struck = true;
|
|
711
|
+
return "";
|
|
712
|
+
});
|
|
713
|
+
if (!struck) return text;
|
|
714
|
+
const cleaned = stripped.trim();
|
|
715
|
+
return cleaned ? cleaned : text;
|
|
716
|
+
}
|
|
702
717
|
var DEFAULT_GROUP_RATE_LIMIT = { max: 30, windowMs: 60 * 60 * 1e3 };
|
|
703
718
|
var DEFAULT_DM_RATE_LIMIT = { max: 20, windowMs: 60 * 60 * 1e3 };
|
|
704
719
|
async function resolvePersonaLayer(config, ctx) {
|
|
@@ -721,11 +736,12 @@ function createWhatsAppInboundHandler(config) {
|
|
|
721
736
|
try {
|
|
722
737
|
const chatId = message.key.remoteJid ?? "";
|
|
723
738
|
if (!chatId || chatId === "status@broadcast") return;
|
|
724
|
-
const
|
|
739
|
+
const rawText = extractText(message);
|
|
725
740
|
const context = messageContext(message);
|
|
726
741
|
const senderId = message.key.participant ?? chatId;
|
|
727
742
|
const ownIds = [sock.user?.id, sock.user?.lid].filter((id) => Boolean(id)).map(normalizeJid);
|
|
728
743
|
config.registry.set(sessionId, ownIds);
|
|
744
|
+
const text = stripOwnMentions(rawText, ownIds);
|
|
729
745
|
const fromBot = isEffectivelyFromSelf(
|
|
730
746
|
{ fromBot: message.key.fromMe ?? false, senderId: normalizeJid(senderId) },
|
|
731
747
|
config.registry
|
|
@@ -828,5 +844,6 @@ export {
|
|
|
828
844
|
senderNameFor,
|
|
829
845
|
senderPhoneFor,
|
|
830
846
|
shutdownWaSessions,
|
|
847
|
+
stripOwnMentions,
|
|
831
848
|
useTursoAuthState
|
|
832
849
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inbound chat message normalization — the trust boundary for conversations.
|
|
3
|
+
*
|
|
4
|
+
* Every HTTP chat surface accepts a caller-supplied conversation, and the
|
|
5
|
+
* server owns the system prompt (guardrails + persona + retrieved context).
|
|
6
|
+
* Nothing a client sends may add to, or masquerade as, that prompt, so the
|
|
7
|
+
* only roles that survive normalization are `user` and `assistant`:
|
|
8
|
+
* `system`, `developer` and `tool` messages are dropped, not forwarded.
|
|
9
|
+
*
|
|
10
|
+
* Content is reduced to a plain string: strings pass through and OpenAI-style
|
|
11
|
+
* content-part arrays are flattened to their text parts. Anything else (image
|
|
12
|
+
* parts, tool calls, objects, numbers) carries no usable text and is skipped.
|
|
13
|
+
*/
|
|
14
|
+
import type { PipelineMessage } from "./pipeline";
|
|
15
|
+
/**
|
|
16
|
+
* Normalize a raw `messages` array to the pipeline format.
|
|
17
|
+
*
|
|
18
|
+
* Returns `null` when the input is not a non-empty array, when any entry is
|
|
19
|
+
* not an object, or when nothing usable remains after filtering.
|
|
20
|
+
*/
|
|
21
|
+
export declare function normalizeMessages(raw: unknown): PipelineMessage[] | null;
|
|
22
|
+
/** Outcome of normalizing a widget chat request body. */
|
|
23
|
+
export type NormalizedChatBody = {
|
|
24
|
+
ok: true;
|
|
25
|
+
messages: PipelineMessage[];
|
|
26
|
+
} | {
|
|
27
|
+
ok: false;
|
|
28
|
+
error: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Normalize the widget chat body shape, which accepts either a single
|
|
32
|
+
* `message` string or a `messages` conversation array.
|
|
33
|
+
*
|
|
34
|
+
* The resulting messages have been through `normalizeMessages`, so a client
|
|
35
|
+
* cannot inject a system turn on these surfaces either.
|
|
36
|
+
*/
|
|
37
|
+
export declare function normalizeChatBody(body: unknown): NormalizedChatBody;
|
|
38
|
+
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/core/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAWlD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,EAAE,GAAG,IAAI,CA8BxE;AAED,yDAAyD;AACzD,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,eAAe,EAAE,CAAA;CAAE,GACzC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,kBAAkB,CA2BnE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.test.d.ts","sourceRoot":"","sources":["../../src/core/messages.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
package/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export { defaultBuckets, resolveBuckets } from "./core/buckets";
|
|
|
22
22
|
export { detectLeakage, guardOutput, scrubOutput } from "./core/guardrails";
|
|
23
23
|
export { completeOnce, completeStream, DEFAULT_MODEL } from "./core/llm";
|
|
24
24
|
export { loadKnowledge } from "./core/loaders";
|
|
25
|
+
export type { NormalizedChatBody } from "./core/messages";
|
|
26
|
+
export { normalizeChatBody, normalizeMessages } from "./core/messages";
|
|
25
27
|
export type { PipelineMessage, PipelineMode, PreparedChat } from "./core/pipeline";
|
|
26
28
|
export { prepareChat } from "./core/pipeline";
|
|
27
29
|
export { PromptLoader } from "./core/prompts";
|
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;AAC1C,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,QAAQ,EACR,eAAe,GAChB,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACrD,YAAY,EACV,QAAQ,EACR,aAAa,EACb,cAAc,EACd,aAAa,EACb,WAAW,GACZ,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,YAAY,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,aAAa,EACb,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,SAAS,CAAC"}
|
|
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;AAC1C,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,QAAQ,EACR,eAAe,GAChB,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACrD,YAAY,EACV,QAAQ,EACR,aAAa,EACb,cAAc,EACd,aAAa,EACb,WAAW,GACZ,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACvE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,YAAY,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,aAAa,EACb,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7559,6 +7559,8 @@ __export(index_exports, {
|
|
|
7559
7559
|
guardOutput: () => guardOutput,
|
|
7560
7560
|
jwtSubject: () => jwtSubject,
|
|
7561
7561
|
loadKnowledge: () => loadKnowledge,
|
|
7562
|
+
normalizeChatBody: () => normalizeChatBody,
|
|
7563
|
+
normalizeMessages: () => normalizeMessages,
|
|
7562
7564
|
openaiRoutes: () => openaiRoutes,
|
|
7563
7565
|
prepareChat: () => prepareChat,
|
|
7564
7566
|
privateRoutes: () => privateRoutes,
|
|
@@ -7845,6 +7847,52 @@ function loadKnowledge(root = "config/knowledge") {
|
|
|
7845
7847
|
return docs;
|
|
7846
7848
|
}
|
|
7847
7849
|
|
|
7850
|
+
// src/core/messages.ts
|
|
7851
|
+
function isClientRole(role) {
|
|
7852
|
+
return role === "user" || role === "assistant";
|
|
7853
|
+
}
|
|
7854
|
+
function normalizeMessages(raw) {
|
|
7855
|
+
if (!Array.isArray(raw) || raw.length === 0) return null;
|
|
7856
|
+
const messages = [];
|
|
7857
|
+
for (const entry of raw) {
|
|
7858
|
+
if (!entry || typeof entry !== "object") return null;
|
|
7859
|
+
const { role, content } = entry;
|
|
7860
|
+
if (!isClientRole(role)) continue;
|
|
7861
|
+
let text = null;
|
|
7862
|
+
if (typeof content === "string") {
|
|
7863
|
+
text = content;
|
|
7864
|
+
} else if (Array.isArray(content)) {
|
|
7865
|
+
text = content.filter(
|
|
7866
|
+
(part) => !!part && typeof part === "object" && part.type === "text" && typeof part.text === "string"
|
|
7867
|
+
).map((part) => part.text).join("");
|
|
7868
|
+
}
|
|
7869
|
+
if (text === null) continue;
|
|
7870
|
+
messages.push({ role, content: text });
|
|
7871
|
+
}
|
|
7872
|
+
return messages.length > 0 ? messages : null;
|
|
7873
|
+
}
|
|
7874
|
+
function normalizeChatBody(body) {
|
|
7875
|
+
const source = body && typeof body === "object" ? body : {};
|
|
7876
|
+
if (Array.isArray(source.messages)) {
|
|
7877
|
+
if (source.messages.length === 0) {
|
|
7878
|
+
return { ok: false, error: "messages array cannot be empty" };
|
|
7879
|
+
}
|
|
7880
|
+
const messages = normalizeMessages(source.messages);
|
|
7881
|
+
if (!messages) {
|
|
7882
|
+
return {
|
|
7883
|
+
ok: false,
|
|
7884
|
+
error: "messages must contain user/assistant messages with text content"
|
|
7885
|
+
};
|
|
7886
|
+
}
|
|
7887
|
+
return { ok: true, messages };
|
|
7888
|
+
}
|
|
7889
|
+
const { message } = source;
|
|
7890
|
+
if (message && typeof message !== "object") {
|
|
7891
|
+
return { ok: true, messages: [{ role: "user", content: String(message) }] };
|
|
7892
|
+
}
|
|
7893
|
+
return { ok: false, error: "either 'message' or 'messages' required" };
|
|
7894
|
+
}
|
|
7895
|
+
|
|
7848
7896
|
// src/core/pipeline.ts
|
|
7849
7897
|
var MODE_SETTINGS = {
|
|
7850
7898
|
public: { topK: 6, label: "Context" },
|
|
@@ -32840,17 +32888,11 @@ function demoRoutes(deps) {
|
|
|
32840
32888
|
app.post("/api/demo/chat", limitDemo(), async (c) => {
|
|
32841
32889
|
try {
|
|
32842
32890
|
const body = await c.req.json().catch(() => ({}));
|
|
32843
|
-
|
|
32844
|
-
if (
|
|
32845
|
-
|
|
32846
|
-
if (messages.length === 0) {
|
|
32847
|
-
return c.json({ error: "messages array cannot be empty" }, 400);
|
|
32848
|
-
}
|
|
32849
|
-
} else if (body?.message) {
|
|
32850
|
-
messages = [{ role: "user", content: String(body.message) }];
|
|
32851
|
-
} else {
|
|
32852
|
-
return c.json({ error: "either 'message' or 'messages' required" }, 400);
|
|
32891
|
+
const normalized = normalizeChatBody(body);
|
|
32892
|
+
if (!normalized.ok) {
|
|
32893
|
+
return c.json({ error: normalized.error }, 400);
|
|
32853
32894
|
}
|
|
32895
|
+
const { messages } = normalized;
|
|
32854
32896
|
const lastUserMsg = [...messages].reverse().find((m) => m.role === "user");
|
|
32855
32897
|
if (!lastUserMsg) {
|
|
32856
32898
|
return c.json({ error: "no user message found in conversation" }, 400);
|
|
@@ -32901,26 +32943,6 @@ ${ctx.join("\n\n")}`
|
|
|
32901
32943
|
// src/routes/openai.ts
|
|
32902
32944
|
var import_hono2 = require("hono");
|
|
32903
32945
|
var import_streaming2 = require("hono/streaming");
|
|
32904
|
-
function normalizeMessages(raw) {
|
|
32905
|
-
if (!Array.isArray(raw) || raw.length === 0) return null;
|
|
32906
|
-
const messages = [];
|
|
32907
|
-
for (const entry of raw) {
|
|
32908
|
-
if (!entry || typeof entry !== "object") return null;
|
|
32909
|
-
const { role, content } = entry;
|
|
32910
|
-
if (role !== "user" && role !== "assistant") continue;
|
|
32911
|
-
let text = null;
|
|
32912
|
-
if (typeof content === "string") {
|
|
32913
|
-
text = content;
|
|
32914
|
-
} else if (Array.isArray(content)) {
|
|
32915
|
-
text = content.filter(
|
|
32916
|
-
(part) => !!part && typeof part === "object" && part.type === "text" && typeof part.text === "string"
|
|
32917
|
-
).map((part) => part.text).join("");
|
|
32918
|
-
}
|
|
32919
|
-
if (text === null) continue;
|
|
32920
|
-
messages.push({ role, content: text });
|
|
32921
|
-
}
|
|
32922
|
-
return messages.length > 0 ? messages : null;
|
|
32923
|
-
}
|
|
32924
32946
|
function errorJson(c, status, message) {
|
|
32925
32947
|
return c.json(
|
|
32926
32948
|
{ error: { message, type: status === 401 ? "authentication_error" : "invalid_request_error" } },
|
|
@@ -33055,17 +33077,11 @@ function privateRoutes(deps) {
|
|
|
33055
33077
|
app.use("/api/private/*", limitPrivate2());
|
|
33056
33078
|
app.post("/api/private/chat", async (c) => {
|
|
33057
33079
|
const body = await c.req.json().catch(() => ({}));
|
|
33058
|
-
|
|
33059
|
-
if (
|
|
33060
|
-
|
|
33061
|
-
if (messages.length === 0) {
|
|
33062
|
-
return c.json({ error: "messages array cannot be empty" }, 400);
|
|
33063
|
-
}
|
|
33064
|
-
} else if (body?.message) {
|
|
33065
|
-
messages = [{ role: "user", content: String(body.message) }];
|
|
33066
|
-
} else {
|
|
33067
|
-
return c.json({ error: "either 'message' or 'messages' required" }, 400);
|
|
33080
|
+
const normalized = normalizeChatBody(body);
|
|
33081
|
+
if (!normalized.ok) {
|
|
33082
|
+
return c.json({ error: normalized.error }, 400);
|
|
33068
33083
|
}
|
|
33084
|
+
const { messages } = normalized;
|
|
33069
33085
|
const buckets = await resolveBuckets({
|
|
33070
33086
|
mode: "private",
|
|
33071
33087
|
sender: jwtSubject(c),
|
|
@@ -33123,17 +33139,11 @@ function publicRoutes(deps) {
|
|
|
33123
33139
|
app.use("/api/public/*", limitPublic2());
|
|
33124
33140
|
app.post("/api/public/chat", async (c) => {
|
|
33125
33141
|
const body = await c.req.json().catch(() => ({}));
|
|
33126
|
-
|
|
33127
|
-
if (
|
|
33128
|
-
|
|
33129
|
-
if (messages.length === 0) {
|
|
33130
|
-
return c.json({ error: "messages array cannot be empty" }, 400);
|
|
33131
|
-
}
|
|
33132
|
-
} else if (body?.message) {
|
|
33133
|
-
messages = [{ role: "user", content: String(body.message) }];
|
|
33134
|
-
} else {
|
|
33135
|
-
return c.json({ error: "either 'message' or 'messages' required" }, 400);
|
|
33142
|
+
const normalized = normalizeChatBody(body);
|
|
33143
|
+
if (!normalized.ok) {
|
|
33144
|
+
return c.json({ error: normalized.error }, 400);
|
|
33136
33145
|
}
|
|
33146
|
+
const { messages } = normalized;
|
|
33137
33147
|
const buckets = await resolveBuckets({ mode: "public", bucketsFor: config2.bucketsFor });
|
|
33138
33148
|
let system;
|
|
33139
33149
|
try {
|
|
@@ -33462,6 +33472,8 @@ function createShortener(config2, fetchImpl = fetch) {
|
|
|
33462
33472
|
guardOutput,
|
|
33463
33473
|
jwtSubject,
|
|
33464
33474
|
loadKnowledge,
|
|
33475
|
+
normalizeChatBody,
|
|
33476
|
+
normalizeMessages,
|
|
33465
33477
|
openaiRoutes,
|
|
33466
33478
|
prepareChat,
|
|
33467
33479
|
privateRoutes,
|
package/dist/index.mjs
CHANGED
|
@@ -7807,6 +7807,52 @@ function loadKnowledge(root = "config/knowledge") {
|
|
|
7807
7807
|
return docs;
|
|
7808
7808
|
}
|
|
7809
7809
|
|
|
7810
|
+
// src/core/messages.ts
|
|
7811
|
+
function isClientRole(role) {
|
|
7812
|
+
return role === "user" || role === "assistant";
|
|
7813
|
+
}
|
|
7814
|
+
function normalizeMessages(raw) {
|
|
7815
|
+
if (!Array.isArray(raw) || raw.length === 0) return null;
|
|
7816
|
+
const messages = [];
|
|
7817
|
+
for (const entry of raw) {
|
|
7818
|
+
if (!entry || typeof entry !== "object") return null;
|
|
7819
|
+
const { role, content } = entry;
|
|
7820
|
+
if (!isClientRole(role)) continue;
|
|
7821
|
+
let text = null;
|
|
7822
|
+
if (typeof content === "string") {
|
|
7823
|
+
text = content;
|
|
7824
|
+
} else if (Array.isArray(content)) {
|
|
7825
|
+
text = content.filter(
|
|
7826
|
+
(part) => !!part && typeof part === "object" && part.type === "text" && typeof part.text === "string"
|
|
7827
|
+
).map((part) => part.text).join("");
|
|
7828
|
+
}
|
|
7829
|
+
if (text === null) continue;
|
|
7830
|
+
messages.push({ role, content: text });
|
|
7831
|
+
}
|
|
7832
|
+
return messages.length > 0 ? messages : null;
|
|
7833
|
+
}
|
|
7834
|
+
function normalizeChatBody(body) {
|
|
7835
|
+
const source = body && typeof body === "object" ? body : {};
|
|
7836
|
+
if (Array.isArray(source.messages)) {
|
|
7837
|
+
if (source.messages.length === 0) {
|
|
7838
|
+
return { ok: false, error: "messages array cannot be empty" };
|
|
7839
|
+
}
|
|
7840
|
+
const messages = normalizeMessages(source.messages);
|
|
7841
|
+
if (!messages) {
|
|
7842
|
+
return {
|
|
7843
|
+
ok: false,
|
|
7844
|
+
error: "messages must contain user/assistant messages with text content"
|
|
7845
|
+
};
|
|
7846
|
+
}
|
|
7847
|
+
return { ok: true, messages };
|
|
7848
|
+
}
|
|
7849
|
+
const { message } = source;
|
|
7850
|
+
if (message && typeof message !== "object") {
|
|
7851
|
+
return { ok: true, messages: [{ role: "user", content: String(message) }] };
|
|
7852
|
+
}
|
|
7853
|
+
return { ok: false, error: "either 'message' or 'messages' required" };
|
|
7854
|
+
}
|
|
7855
|
+
|
|
7810
7856
|
// src/core/pipeline.ts
|
|
7811
7857
|
var MODE_SETTINGS = {
|
|
7812
7858
|
public: { topK: 6, label: "Context" },
|
|
@@ -32802,17 +32848,11 @@ function demoRoutes(deps) {
|
|
|
32802
32848
|
app.post("/api/demo/chat", limitDemo(), async (c) => {
|
|
32803
32849
|
try {
|
|
32804
32850
|
const body = await c.req.json().catch(() => ({}));
|
|
32805
|
-
|
|
32806
|
-
if (
|
|
32807
|
-
|
|
32808
|
-
if (messages.length === 0) {
|
|
32809
|
-
return c.json({ error: "messages array cannot be empty" }, 400);
|
|
32810
|
-
}
|
|
32811
|
-
} else if (body?.message) {
|
|
32812
|
-
messages = [{ role: "user", content: String(body.message) }];
|
|
32813
|
-
} else {
|
|
32814
|
-
return c.json({ error: "either 'message' or 'messages' required" }, 400);
|
|
32851
|
+
const normalized = normalizeChatBody(body);
|
|
32852
|
+
if (!normalized.ok) {
|
|
32853
|
+
return c.json({ error: normalized.error }, 400);
|
|
32815
32854
|
}
|
|
32855
|
+
const { messages } = normalized;
|
|
32816
32856
|
const lastUserMsg = [...messages].reverse().find((m) => m.role === "user");
|
|
32817
32857
|
if (!lastUserMsg) {
|
|
32818
32858
|
return c.json({ error: "no user message found in conversation" }, 400);
|
|
@@ -32863,26 +32903,6 @@ ${ctx.join("\n\n")}`
|
|
|
32863
32903
|
// src/routes/openai.ts
|
|
32864
32904
|
import { Hono as Hono2 } from "hono";
|
|
32865
32905
|
import { stream as stream2 } from "hono/streaming";
|
|
32866
|
-
function normalizeMessages(raw) {
|
|
32867
|
-
if (!Array.isArray(raw) || raw.length === 0) return null;
|
|
32868
|
-
const messages = [];
|
|
32869
|
-
for (const entry of raw) {
|
|
32870
|
-
if (!entry || typeof entry !== "object") return null;
|
|
32871
|
-
const { role, content } = entry;
|
|
32872
|
-
if (role !== "user" && role !== "assistant") continue;
|
|
32873
|
-
let text = null;
|
|
32874
|
-
if (typeof content === "string") {
|
|
32875
|
-
text = content;
|
|
32876
|
-
} else if (Array.isArray(content)) {
|
|
32877
|
-
text = content.filter(
|
|
32878
|
-
(part) => !!part && typeof part === "object" && part.type === "text" && typeof part.text === "string"
|
|
32879
|
-
).map((part) => part.text).join("");
|
|
32880
|
-
}
|
|
32881
|
-
if (text === null) continue;
|
|
32882
|
-
messages.push({ role, content: text });
|
|
32883
|
-
}
|
|
32884
|
-
return messages.length > 0 ? messages : null;
|
|
32885
|
-
}
|
|
32886
32906
|
function errorJson(c, status, message) {
|
|
32887
32907
|
return c.json(
|
|
32888
32908
|
{ error: { message, type: status === 401 ? "authentication_error" : "invalid_request_error" } },
|
|
@@ -33017,17 +33037,11 @@ function privateRoutes(deps) {
|
|
|
33017
33037
|
app.use("/api/private/*", limitPrivate2());
|
|
33018
33038
|
app.post("/api/private/chat", async (c) => {
|
|
33019
33039
|
const body = await c.req.json().catch(() => ({}));
|
|
33020
|
-
|
|
33021
|
-
if (
|
|
33022
|
-
|
|
33023
|
-
if (messages.length === 0) {
|
|
33024
|
-
return c.json({ error: "messages array cannot be empty" }, 400);
|
|
33025
|
-
}
|
|
33026
|
-
} else if (body?.message) {
|
|
33027
|
-
messages = [{ role: "user", content: String(body.message) }];
|
|
33028
|
-
} else {
|
|
33029
|
-
return c.json({ error: "either 'message' or 'messages' required" }, 400);
|
|
33040
|
+
const normalized = normalizeChatBody(body);
|
|
33041
|
+
if (!normalized.ok) {
|
|
33042
|
+
return c.json({ error: normalized.error }, 400);
|
|
33030
33043
|
}
|
|
33044
|
+
const { messages } = normalized;
|
|
33031
33045
|
const buckets = await resolveBuckets({
|
|
33032
33046
|
mode: "private",
|
|
33033
33047
|
sender: jwtSubject(c),
|
|
@@ -33085,17 +33099,11 @@ function publicRoutes(deps) {
|
|
|
33085
33099
|
app.use("/api/public/*", limitPublic2());
|
|
33086
33100
|
app.post("/api/public/chat", async (c) => {
|
|
33087
33101
|
const body = await c.req.json().catch(() => ({}));
|
|
33088
|
-
|
|
33089
|
-
if (
|
|
33090
|
-
|
|
33091
|
-
if (messages.length === 0) {
|
|
33092
|
-
return c.json({ error: "messages array cannot be empty" }, 400);
|
|
33093
|
-
}
|
|
33094
|
-
} else if (body?.message) {
|
|
33095
|
-
messages = [{ role: "user", content: String(body.message) }];
|
|
33096
|
-
} else {
|
|
33097
|
-
return c.json({ error: "either 'message' or 'messages' required" }, 400);
|
|
33102
|
+
const normalized = normalizeChatBody(body);
|
|
33103
|
+
if (!normalized.ok) {
|
|
33104
|
+
return c.json({ error: normalized.error }, 400);
|
|
33098
33105
|
}
|
|
33106
|
+
const { messages } = normalized;
|
|
33099
33107
|
const buckets = await resolveBuckets({ mode: "public", bucketsFor: config2.bucketsFor });
|
|
33100
33108
|
let system;
|
|
33101
33109
|
try {
|
|
@@ -33425,6 +33433,8 @@ export {
|
|
|
33425
33433
|
guardOutput,
|
|
33426
33434
|
jwtSubject,
|
|
33427
33435
|
loadKnowledge,
|
|
33436
|
+
normalizeChatBody,
|
|
33437
|
+
normalizeMessages,
|
|
33428
33438
|
openaiRoutes,
|
|
33429
33439
|
prepareChat,
|
|
33430
33440
|
privateRoutes,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../../src/routes/demo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../../src/routes/demo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAsHnD,wBAAgB,UAAU,CAAC,IAAI,EAAE,kBAAkB,8EA+GlD"}
|
package/dist/routes/openai.d.ts
CHANGED
|
@@ -22,13 +22,6 @@
|
|
|
22
22
|
* Bearer` or `x-api-key`; widget-only session/demo keys are not valid.
|
|
23
23
|
*/
|
|
24
24
|
import { Hono } from "hono";
|
|
25
|
-
import { type PipelineMessage } from "../core/pipeline";
|
|
26
25
|
import type { ServerDependencies } from "../types";
|
|
27
|
-
/**
|
|
28
|
-
* Normalize OpenAI-format messages to the pipeline format.
|
|
29
|
-
* Accepts string content and text content-part arrays; drops system/tool
|
|
30
|
-
* messages. Returns null when nothing usable remains.
|
|
31
|
-
*/
|
|
32
|
-
export declare function normalizeMessages(raw: unknown): PipelineMessage[] | null;
|
|
33
26
|
export declare function openaiRoutes(deps: ServerDependencies): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
34
27
|
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/routes/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/routes/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAS5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AASnD,wBAAgB,YAAY,CAAC,IAAI,EAAE,kBAAkB,8EAwIpD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"private.d.ts","sourceRoot":"","sources":["../../src/routes/private.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"private.d.ts","sourceRoot":"","sources":["../../src/routes/private.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAQ5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AASnD,wBAAgB,aAAa,CAAC,IAAI,EAAE,kBAAkB,8EA4DrD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/routes/public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/routes/public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAU5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AASnD,wBAAgB,YAAY,CAAC,IAAI,EAAE,kBAAkB,8EAkEpD"}
|
package/package.json
CHANGED