@absolutejs/absolute 0.19.0-beta.502 → 0.19.0-beta.503

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/ai/index.js CHANGED
@@ -6833,6 +6833,294 @@ var openaiTranscriber = (config) => {
6833
6833
  }
6834
6834
  });
6835
6835
  };
6836
+ // src/ai/rag/emailProviders.ts
6837
+ import { connect as connectTls } from "tls";
6838
+ var defaultFetch = (...args) => fetch(...args);
6839
+ var stripHtml2 = (value) => value.replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<[^>]+>/g, " ").replace(/&nbsp;/gi, " ").replace(/&amp;/gi, "&").replace(/\s+/g, " ").trim();
6840
+ var decodeBase64Url = (value) => {
6841
+ const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
6842
+ const padding = normalized.length % 4 === 0 ? "" : "=".repeat(4 - normalized.length % 4);
6843
+ return Buffer.from(normalized + padding, "base64");
6844
+ };
6845
+ var firstHeader = (headers, name) => headers?.find((header) => header.name?.toLowerCase() === name.toLowerCase())?.value;
6846
+ var collectGmailPayloadParts = (payload) => {
6847
+ if (!payload) {
6848
+ return [];
6849
+ }
6850
+ return [
6851
+ payload,
6852
+ ...(payload.parts ?? []).flatMap((part) => collectGmailPayloadParts(part))
6853
+ ];
6854
+ };
6855
+ var extractGmailBodyText = (payload) => {
6856
+ const parts = collectGmailPayloadParts(payload);
6857
+ const plain = parts.find((part) => part.mimeType?.toLowerCase() === "text/plain" && part.body?.data);
6858
+ if (plain?.body?.data) {
6859
+ return decodeBase64Url(plain.body.data).toString("utf8");
6860
+ }
6861
+ const html = parts.find((part) => part.mimeType?.toLowerCase() === "text/html" && part.body?.data);
6862
+ if (html?.body?.data) {
6863
+ return stripHtml2(decodeBase64Url(html.body.data).toString("utf8"));
6864
+ }
6865
+ if (payload?.body?.data) {
6866
+ return decodeBase64Url(payload.body.data).toString("utf8");
6867
+ }
6868
+ return "";
6869
+ };
6870
+ var toGraphAddressList = (value) => value?.map((entry) => entry.emailAddress?.address).filter(Boolean);
6871
+ var toGraphAttachment = (attachment) => attachment.name && attachment.contentBytes ? {
6872
+ content: attachment.contentBytes,
6873
+ contentType: attachment.contentType,
6874
+ encoding: "base64",
6875
+ id: attachment.id,
6876
+ name: attachment.name
6877
+ } : null;
6878
+ var buildGraphPath = (config) => {
6879
+ const base = config.userId && config.userId !== "me" ? `/users/${encodeURIComponent(config.userId)}` : "/me";
6880
+ return config.folderId ? `${base}/mailFolders/${encodeURIComponent(config.folderId)}/messages` : `${base}/messages`;
6881
+ };
6882
+ var parseRawEmail = (raw) => {
6883
+ const [headerBlock, ...bodyBlocks] = raw.split(/\r?\n\r?\n/);
6884
+ const body = bodyBlocks.join(`
6885
+
6886
+ `).trim();
6887
+ const lines = (headerBlock ?? "").split(/\r?\n/);
6888
+ const headers = new Map;
6889
+ let current = "";
6890
+ for (const line of lines) {
6891
+ if (/^\s/.test(line) && current) {
6892
+ headers.set(current, `${headers.get(current) ?? ""} ${line.trim()}`.trim());
6893
+ continue;
6894
+ }
6895
+ const separator = line.indexOf(":");
6896
+ if (separator < 0) {
6897
+ continue;
6898
+ }
6899
+ current = line.slice(0, separator).trim().toLowerCase();
6900
+ headers.set(current, line.slice(separator + 1).trim());
6901
+ }
6902
+ const toList = (value) => value?.split(",").map((entry) => entry.trim()).filter(Boolean);
6903
+ return {
6904
+ bodyText: body,
6905
+ cc: toList(headers.get("cc")),
6906
+ from: headers.get("from"),
6907
+ id: headers.get("message-id") ?? headers.get("subject") ?? crypto.randomUUID(),
6908
+ receivedAt: headers.get("date"),
6909
+ subject: headers.get("subject"),
6910
+ threadId: headers.get("thread-topic") ?? headers.get("references") ?? headers.get("subject"),
6911
+ to: toList(headers.get("to"))
6912
+ };
6913
+ };
6914
+ var createRAGGmailEmailSyncClient = (config) => ({
6915
+ listMessages: async (input) => {
6916
+ const fetchImpl = config.fetch ?? defaultFetch;
6917
+ const userId = config.userId ?? "me";
6918
+ const listUrl = new URL(`https://gmail.googleapis.com/gmail/v1/users/${encodeURIComponent(userId)}/messages`);
6919
+ listUrl.searchParams.set("maxResults", String(input?.maxResults ?? config.maxResults ?? 100));
6920
+ if (input?.cursor) {
6921
+ listUrl.searchParams.set("pageToken", input.cursor);
6922
+ }
6923
+ if (config.query) {
6924
+ listUrl.searchParams.set("q", config.query);
6925
+ }
6926
+ for (const labelId of config.labelIds ?? []) {
6927
+ listUrl.searchParams.append("labelIds", labelId);
6928
+ }
6929
+ if (config.includeSpamTrash) {
6930
+ listUrl.searchParams.set("includeSpamTrash", "true");
6931
+ }
6932
+ const listResponse = await fetchImpl(listUrl, {
6933
+ headers: { Authorization: `Bearer ${config.accessToken}` }
6934
+ });
6935
+ if (!listResponse.ok) {
6936
+ throw new Error(`Gmail list failed: ${listResponse.status} ${listResponse.statusText}`);
6937
+ }
6938
+ const listJson = await listResponse.json();
6939
+ const messages = await Promise.all((listJson.messages ?? []).map(async (messageRef) => {
6940
+ const getUrl = new URL(`https://gmail.googleapis.com/gmail/v1/users/${encodeURIComponent(userId)}/messages/${encodeURIComponent(messageRef.id)}`);
6941
+ getUrl.searchParams.set("format", "full");
6942
+ const response = await fetchImpl(getUrl, {
6943
+ headers: { Authorization: `Bearer ${config.accessToken}` }
6944
+ });
6945
+ if (!response.ok) {
6946
+ throw new Error(`Gmail get failed for ${messageRef.id}: ${response.status} ${response.statusText}`);
6947
+ }
6948
+ const json = await response.json();
6949
+ const attachments = await Promise.all(collectGmailPayloadParts(json.payload).filter((part) => !!part.filename && !!part.body?.attachmentId).map(async (part) => {
6950
+ const attachmentUrl = new URL(`https://gmail.googleapis.com/gmail/v1/users/${encodeURIComponent(userId)}/messages/${encodeURIComponent(json.id)}/attachments/${encodeURIComponent(part.body?.attachmentId ?? "")}`);
6951
+ const attachmentResponse = await fetchImpl(attachmentUrl, {
6952
+ headers: {
6953
+ Authorization: `Bearer ${config.accessToken}`
6954
+ }
6955
+ });
6956
+ if (!attachmentResponse.ok) {
6957
+ return null;
6958
+ }
6959
+ const attachmentJson = await attachmentResponse.json();
6960
+ if (!attachmentJson.data || !part.filename) {
6961
+ return null;
6962
+ }
6963
+ return {
6964
+ content: decodeBase64Url(attachmentJson.data).toString("base64"),
6965
+ contentType: part.mimeType,
6966
+ encoding: "base64",
6967
+ id: part.body?.attachmentId,
6968
+ name: part.filename
6969
+ };
6970
+ }));
6971
+ return {
6972
+ attachments: attachments.filter(Boolean),
6973
+ bodyText: extractGmailBodyText(json.payload) || json.snippet || "",
6974
+ cc: firstHeader(json.payload?.headers, "Cc")?.split(",").map((entry) => entry.trim()).filter(Boolean),
6975
+ from: firstHeader(json.payload?.headers, "From"),
6976
+ id: json.id,
6977
+ metadata: {
6978
+ gmailLabelIds: json.labelIds,
6979
+ provider: "gmail"
6980
+ },
6981
+ receivedAt: json.internalDate ? Number(json.internalDate) : undefined,
6982
+ subject: firstHeader(json.payload?.headers, "Subject"),
6983
+ threadId: json.threadId ?? messageRef.threadId,
6984
+ to: firstHeader(json.payload?.headers, "To")?.split(",").map((entry) => entry.trim()).filter(Boolean)
6985
+ };
6986
+ }));
6987
+ return {
6988
+ messages,
6989
+ nextCursor: listJson.nextPageToken
6990
+ };
6991
+ }
6992
+ });
6993
+ var createRAGGraphEmailSyncClient = (config) => ({
6994
+ listMessages: async (input) => {
6995
+ const fetchImpl = config.fetch ?? defaultFetch;
6996
+ const url = new URL(`${config.baseUrl ?? "https://graph.microsoft.com/v1.0"}${buildGraphPath(config)}`);
6997
+ url.searchParams.set("$select", "id,conversationId,subject,from,toRecipients,ccRecipients,sentDateTime,receivedDateTime,body,hasAttachments,internetMessageId");
6998
+ url.searchParams.set("$top", String(input?.maxResults ?? config.top ?? 100));
6999
+ if (config.filter) {
7000
+ url.searchParams.set("$filter", config.filter);
7001
+ }
7002
+ if (config.search) {
7003
+ url.searchParams.set("$search", config.search);
7004
+ }
7005
+ if (input?.cursor) {
7006
+ return {
7007
+ messages: [],
7008
+ nextCursor: input.cursor
7009
+ };
7010
+ }
7011
+ const listResponse = await fetchImpl(url, {
7012
+ headers: {
7013
+ Authorization: `Bearer ${config.accessToken}`,
7014
+ Prefer: 'outlook.body-content-type="text"'
7015
+ }
7016
+ });
7017
+ if (!listResponse.ok) {
7018
+ throw new Error(`Graph message list failed: ${listResponse.status} ${listResponse.statusText}`);
7019
+ }
7020
+ const listJson = await listResponse.json();
7021
+ const messages = await Promise.all((listJson.value ?? []).map(async (message) => {
7022
+ const attachments = message.hasAttachments === true ? await (async () => {
7023
+ const attachmentsResponse = await fetchImpl(`${config.baseUrl ?? "https://graph.microsoft.com/v1.0"}${buildGraphPath(config)}/${encodeURIComponent(String(message.id))}/attachments`, {
7024
+ headers: {
7025
+ Authorization: `Bearer ${config.accessToken}`
7026
+ }
7027
+ });
7028
+ if (!attachmentsResponse.ok) {
7029
+ return [];
7030
+ }
7031
+ const attachmentsJson = await attachmentsResponse.json();
7032
+ return (attachmentsJson.value ?? []).map((attachment) => toGraphAttachment(attachment)).filter(Boolean);
7033
+ })() : [];
7034
+ return {
7035
+ attachments,
7036
+ bodyText: typeof message.body?.content === "string" ? String(message.body.content) : "",
7037
+ cc: toGraphAddressList(message.ccRecipients),
7038
+ from: message.from?.emailAddress?.address,
7039
+ id: String(message.id),
7040
+ metadata: {
7041
+ internetMessageId: message.internetMessageId,
7042
+ provider: "graph"
7043
+ },
7044
+ receivedAt: message.receivedDateTime,
7045
+ sentAt: message.sentDateTime,
7046
+ subject: message.subject,
7047
+ threadId: message.conversationId,
7048
+ to: toGraphAddressList(message.toRecipients)
7049
+ };
7050
+ }));
7051
+ return {
7052
+ messages,
7053
+ nextCursor: listJson["@odata.nextLink"]
7054
+ };
7055
+ }
7056
+ });
7057
+ var createRAGIMAPEmailSyncClient = (config) => ({
7058
+ listMessages: async (input) => {
7059
+ const mailbox = config.mailbox ?? "INBOX";
7060
+ const searchTerms = config.search?.length ? config.search : ["ALL"];
7061
+ const maxResults = input?.maxResults ?? config.maxResults ?? 100;
7062
+ const socket = connectTls({
7063
+ host: config.host,
7064
+ port: config.port ?? 993,
7065
+ rejectUnauthorized: true
7066
+ });
7067
+ socket.setEncoding("utf8");
7068
+ let buffer = "";
7069
+ const readUntil = async (predicate) => await new Promise((resolve2, reject) => {
7070
+ const onData = (chunk) => {
7071
+ buffer += chunk;
7072
+ if (predicate(buffer)) {
7073
+ socket.off("data", onData);
7074
+ resolve2(buffer);
7075
+ }
7076
+ };
7077
+ const onError = (error) => {
7078
+ socket.off("data", onData);
7079
+ reject(error);
7080
+ };
7081
+ socket.on("data", onData);
7082
+ socket.once("error", onError);
7083
+ });
7084
+ const send = async (tag, command) => {
7085
+ socket.write(`${tag} ${command}\r
7086
+ `);
7087
+ const response = await readUntil((chunk) => chunk.includes(`\r
7088
+ ${tag} OK`) || chunk.startsWith(`${tag} OK`));
7089
+ buffer = "";
7090
+ return response;
7091
+ };
7092
+ await readUntil((chunk) => chunk.includes(`\r
7093
+ `) || chunk.startsWith("*"));
7094
+ buffer = "";
7095
+ await send("A001", `LOGIN "${config.username}" "${config.password}"`);
7096
+ await send("A002", `SELECT "${mailbox}"`);
7097
+ const searchResponse = await send("A003", `UID SEARCH ${searchTerms.join(" ")}`);
7098
+ const uidLine = searchResponse.split(/\r?\n/).find((line) => line.startsWith("* SEARCH"));
7099
+ const uids = (uidLine?.replace("* SEARCH", "").trim().split(/\s+/) ?? []).filter(Boolean).slice(-maxResults);
7100
+ const messages = [];
7101
+ for (const uid of uids) {
7102
+ const response = await send(`F${uid}`, `UID FETCH ${uid} BODY.PEEK[]`);
7103
+ const rawMatch = response.match(/\{(\d+)\}\r\n([\s\S]*?)\r\nF[^\r\n]+ OK/);
7104
+ const raw = rawMatch?.[2]?.trim();
7105
+ if (!raw) {
7106
+ continue;
7107
+ }
7108
+ const parsed = parseRawEmail(raw);
7109
+ messages.push({
7110
+ ...parsed,
7111
+ metadata: {
7112
+ ...parsed.metadata ?? {},
7113
+ imapMailbox: mailbox,
7114
+ imapUid: uid,
7115
+ provider: "imap"
7116
+ }
7117
+ });
7118
+ }
7119
+ socket.end(`ZZZZ LOGOUT\r
7120
+ `);
7121
+ return { messages };
7122
+ }
7123
+ });
6836
7124
  // src/ai/rag/presentation.ts
6837
7125
  var buildSourceGroupKey = (source) => source.source ?? source.title ?? source.chunkId;
6838
7126
  var buildSourceLabel = (source) => source.source ?? source.title ?? source.chunkId;
@@ -9756,8 +10044,11 @@ export {
9756
10044
  createRAGMediaTranscriber,
9757
10045
  createRAGMediaFileExtractor,
9758
10046
  createRAGImageOCRExtractor,
10047
+ createRAGIMAPEmailSyncClient,
9759
10048
  createRAGHTMXWorkflowRenderConfig,
9760
10049
  createRAGHTMXConfig,
10050
+ createRAGGraphEmailSyncClient,
10051
+ createRAGGmailEmailSyncClient,
9761
10052
  createRAGFileSyncStateStore,
9762
10053
  createRAGFileExtractor,
9763
10054
  createRAGEvaluationSuite,
@@ -9805,5 +10096,5 @@ export {
9805
10096
  aiChat
9806
10097
  };
9807
10098
 
9808
- //# debugId=CE610CD2937858F264756E2164756E21
10099
+ //# debugId=BD95265DF2B97B7764756E2164756E21
9809
10100
  //# sourceMappingURL=index.js.map