@llmnative/react 2.4.0 → 3.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.
Files changed (52) hide show
  1. package/README.md +3 -2
  2. package/dist/index.js +20 -21
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +6570 -6733
  5. package/dist/index.mjs.map +1 -1
  6. package/dist/modelIdentity-CIXNPtTA.mjs +624 -0
  7. package/dist/modelIdentity-CIXNPtTA.mjs.map +1 -0
  8. package/dist/modelIdentity-DX62i7g2.js +3 -0
  9. package/dist/modelIdentity-DX62i7g2.js.map +1 -0
  10. package/dist/server-B430eH0y.mjs +352 -0
  11. package/dist/server-B430eH0y.mjs.map +1 -0
  12. package/dist/server-CDheNgME.js +2 -0
  13. package/dist/server-CDheNgME.js.map +1 -0
  14. package/dist/server.js +1 -1
  15. package/dist/server.mjs +3 -3
  16. package/dist/types/src/App.d.ts +6 -4
  17. package/dist/types/src/index.d.ts +16 -7
  18. package/dist/types/src/libs/index.d.ts +0 -1
  19. package/dist/types/src/providers/ProviderRegistryContext.d.ts +7 -5
  20. package/dist/types/src/providers/ai/server.d.ts +20 -0
  21. package/dist/types/src/providers/api/ApiProvider.d.ts +1 -1
  22. package/dist/types/src/providers/email/EmailError.d.ts +27 -0
  23. package/dist/types/src/providers/email/EmailProviderContext.d.ts +13 -7
  24. package/dist/types/src/providers/email/EmailRead.d.ts +48 -0
  25. package/dist/types/src/providers/email/EmailSend.d.ts +54 -0
  26. package/dist/types/src/providers/email/brevo/BrevoEmailSender.d.ts +21 -0
  27. package/dist/types/src/providers/email/definitions.d.ts +4 -2
  28. package/dist/types/src/providers/email/gmail/GmailEmailReader.d.ts +37 -0
  29. package/dist/types/src/providers/email/gmail/GmailEmailSender.d.ts +21 -0
  30. package/dist/types/src/providers/email/gmail/browser.d.ts +10 -0
  31. package/dist/types/src/providers/email/gmail/gmailApi.d.ts +53 -0
  32. package/dist/types/src/providers/email/gmail/gmailOAuth.d.ts +25 -0
  33. package/dist/types/src/providers/email/imap/ImapEmailReader.d.ts +70 -0
  34. package/dist/types/src/providers/email/resend/ResendEmailSender.d.ts +20 -0
  35. package/dist/types/src/providers/manifest.d.ts +7 -5
  36. package/dist/vite.js +1 -1
  37. package/dist/vite.mjs +1 -1
  38. package/llms-full.txt +1690 -1657
  39. package/llms.txt +83 -82
  40. package/package.json +18 -1
  41. package/dist/modelIdentity-CGWliGDU.mjs +0 -183
  42. package/dist/modelIdentity-CGWliGDU.mjs.map +0 -1
  43. package/dist/modelIdentity-CgRMrC5H.js +0 -2
  44. package/dist/modelIdentity-CgRMrC5H.js.map +0 -1
  45. package/dist/server-CCbjPJEz.js +0 -2
  46. package/dist/server-CCbjPJEz.js.map +0 -1
  47. package/dist/server-CiWwr3Zg.mjs +0 -107
  48. package/dist/server-CiWwr3Zg.mjs.map +0 -1
  49. package/dist/types/src/libs/email.d.ts +0 -16
  50. package/dist/types/src/providers/email/EmailProvider.d.ts +0 -10
  51. package/dist/types/src/providers/email/google/GmailEmailProvider.d.ts +0 -7
  52. package/dist/types/src/providers/email/google/email.d.ts +0 -13
@@ -0,0 +1,352 @@
1
+ import { E as e, O as t, T as n, _ as r, b as i, d as a, g as o, h as s, k as c, m as l, p as u, v as d, y as f } from "./modelIdentity-CIXNPtTA.mjs";
2
+ //#region src/providers/auth/github/githubOAuth.ts
3
+ var p = class extends Error {
4
+ status;
5
+ constructor(e, t) {
6
+ super(e), this.status = t;
7
+ }
8
+ }, m = "https://github.com", h = "https://api.github.com";
9
+ function g(e, t = globalThis.fetch) {
10
+ let n = async (e, n) => {
11
+ let r = await t(`${h}${e}`, { headers: {
12
+ Accept: "application/vnd.github+json",
13
+ Authorization: `Bearer ${n}`,
14
+ "X-GitHub-Api-Version": "2022-11-28"
15
+ } });
16
+ if (!r.ok) throw new p(`GitHub ${e}: HTTP ${r.status}`, r.status);
17
+ return r.json();
18
+ };
19
+ return {
20
+ authorizeUrl({ state: t, redirectUri: n, scopes: r = e.scopes, codeChallenge: i }) {
21
+ let a = new URLSearchParams({
22
+ client_id: e.clientId,
23
+ redirect_uri: n,
24
+ state: t
25
+ });
26
+ return r?.length && a.set("scope", r.join(" ")), i && (a.set("code_challenge", i), a.set("code_challenge_method", "S256")), `${m}/login/oauth/authorize?${a.toString()}`;
27
+ },
28
+ async exchangeCode({ code: n, redirectUri: r, codeVerifier: i }) {
29
+ let a = await t(`${m}/login/oauth/access_token`, {
30
+ method: "POST",
31
+ headers: {
32
+ Accept: "application/json",
33
+ "Content-Type": "application/json"
34
+ },
35
+ body: JSON.stringify({
36
+ client_id: e.clientId,
37
+ client_secret: e.clientSecret,
38
+ code: n,
39
+ redirect_uri: r,
40
+ ...i ? { code_verifier: i } : {}
41
+ })
42
+ }), o = await a.json().catch(() => ({}));
43
+ if (!a.ok || typeof o.access_token != "string") throw new p(String(o.error_description ?? o.error ?? `HTTP ${a.status}`), a.status);
44
+ return {
45
+ accessToken: o.access_token,
46
+ scope: String(o.scope ?? "")
47
+ };
48
+ },
49
+ async getUser(e) {
50
+ let t = await n("/user", e);
51
+ return {
52
+ login: t.login,
53
+ name: t.name ?? null,
54
+ avatarUrl: t.avatar_url ?? null,
55
+ email: t.email ?? null
56
+ };
57
+ },
58
+ async getOrganizations(e) {
59
+ return (await n("/user/memberships/orgs?state=active&per_page=100", e)).map(({ role: e, organization: t }) => ({
60
+ login: t.login,
61
+ avatarUrl: t.avatar_url ?? null,
62
+ role: e === "admin" ? "admin" : "member"
63
+ }));
64
+ }
65
+ };
66
+ }
67
+ //#endregion
68
+ //#region src/providers/email/gmail/GmailEmailReader.ts
69
+ var _ = class {
70
+ config;
71
+ constructor(e) {
72
+ this.config = e;
73
+ }
74
+ getConfigurationState() {
75
+ return r("GmailEmailReader", this.config.auth);
76
+ }
77
+ isConfigured() {
78
+ return this.getConfigurationState().configured;
79
+ }
80
+ async session() {
81
+ let e = this.getConfigurationState();
82
+ if (!e.configured) throw new f("not-configured", l, e.reason ?? "Gmail is not configured");
83
+ let t = this.config.fetch ?? globalThis.fetch, n = await o(this.config.auth, t);
84
+ return {
85
+ call: (e, r = {}) => i(l, t, `${a}${e}`, {
86
+ ...r,
87
+ headers: {
88
+ authorization: `Bearer ${n}`,
89
+ ...r.body ? { "content-type": "application/json" } : {}
90
+ }
91
+ }),
92
+ label: this.config.labelId ?? "INBOX"
93
+ };
94
+ }
95
+ async start() {
96
+ let { call: e, label: t } = await this.session();
97
+ if (!this.config.topic) {
98
+ let t = await e("/profile");
99
+ return { cursor: String(t.historyId) };
100
+ }
101
+ let n = await e("/watch", {
102
+ method: "POST",
103
+ body: JSON.stringify({
104
+ topicName: this.config.topic,
105
+ labelIds: [t]
106
+ })
107
+ });
108
+ return {
109
+ cursor: String(n.historyId),
110
+ ...n.expiration ? { expiresAt: new Date(Number(n.expiration)).toISOString() } : {}
111
+ };
112
+ }
113
+ async read(e, { limit: t = 50 } = {}) {
114
+ let { call: n, label: r } = await this.session(), i = [], a = e, o, s = !1;
115
+ try {
116
+ do {
117
+ let c = new URLSearchParams({
118
+ startHistoryId: e,
119
+ historyTypes: "messageAdded",
120
+ labelId: r
121
+ });
122
+ o && c.set("pageToken", o);
123
+ let l = await n(`/history?${c}`);
124
+ for (let e of l.history ?? []) {
125
+ let n = [...new Set((e.messagesAdded ?? []).map((e) => e.message.id))].filter((e) => !i.some((t) => t.id === e));
126
+ if (i.length > 0 && i.length + n.length > t) {
127
+ s = !0;
128
+ break;
129
+ }
130
+ let r = a;
131
+ n.forEach((t, a) => i.push({
132
+ id: t,
133
+ cursor: a === n.length - 1 ? String(e.id) : r
134
+ })), a = String(e.id);
135
+ }
136
+ if (s) break;
137
+ l.historyId && (a = String(l.historyId)), o = l.nextPageToken;
138
+ } while (o);
139
+ } catch (e) {
140
+ if (e instanceof f && e.status === 404) {
141
+ let e = await n("/profile");
142
+ return {
143
+ messages: [],
144
+ cursor: String(e.historyId)
145
+ };
146
+ }
147
+ throw e;
148
+ }
149
+ let c = [];
150
+ for (let { id: e, cursor: t } of i) try {
151
+ c.push(d(await n(`/messages/${encodeURIComponent(e)}?format=full`), t));
152
+ } catch (e) {
153
+ if (!(e instanceof f && e.status === 404)) throw e;
154
+ }
155
+ return {
156
+ messages: c,
157
+ cursor: a
158
+ };
159
+ }
160
+ };
161
+ function v(e) {
162
+ if (!e) return null;
163
+ try {
164
+ let t = JSON.parse(s(e));
165
+ return typeof t.emailAddress != "string" || t.historyId === void 0 ? null : {
166
+ emailAddress: t.emailAddress.toLowerCase(),
167
+ historyId: String(t.historyId)
168
+ };
169
+ } catch {
170
+ return null;
171
+ }
172
+ }
173
+ //#endregion
174
+ //#region src/providers/email/gmail/gmailOAuth.ts
175
+ function y(e) {
176
+ let t = e.fetch ?? globalThis.fetch;
177
+ return {
178
+ authorizationUrl({ state: t, scopes: n, loginHint: r }) {
179
+ let i = new URLSearchParams({
180
+ client_id: e.clientId,
181
+ redirect_uri: e.redirectUri,
182
+ response_type: "code",
183
+ scope: n.join(" "),
184
+ access_type: "offline",
185
+ prompt: "consent",
186
+ include_granted_scopes: "true",
187
+ state: t
188
+ });
189
+ return r && i.set("login_hint", r), `https://accounts.google.com/o/oauth2/v2/auth?${i}`;
190
+ },
191
+ async exchangeCode(n) {
192
+ let r = await i(l, t, u, {
193
+ method: "POST",
194
+ headers: { "content-type": "application/x-www-form-urlencoded" },
195
+ body: new URLSearchParams({
196
+ code: n,
197
+ client_id: e.clientId,
198
+ client_secret: e.clientSecret,
199
+ redirect_uri: e.redirectUri,
200
+ grant_type: "authorization_code"
201
+ })
202
+ });
203
+ if (!r.access_token || !r.refresh_token) throw new f("unauthorized", l, "Google returned no refresh token");
204
+ let o = await i(l, t, `${a}/profile`, { headers: { authorization: `Bearer ${r.access_token}` } });
205
+ return {
206
+ email: String(o.emailAddress ?? "").toLowerCase(),
207
+ refreshToken: r.refresh_token
208
+ };
209
+ }
210
+ };
211
+ }
212
+ //#endregion
213
+ //#region src/providers/email/imap/ImapEmailReader.ts
214
+ var b = "IMAP", x = async () => {
215
+ try {
216
+ let [{ ImapFlow: e }, { simpleParser: t }] = await Promise.all([import("imapflow"), import("mailparser")]);
217
+ return {
218
+ ImapFlow: e,
219
+ simpleParser: t
220
+ };
221
+ } catch (e) {
222
+ throw new f("not-configured", b, "IMAP needs the packages imapflow and mailparser", { cause: e });
223
+ }
224
+ }, S = (e) => (Array.isArray(e) ? e : e ? [e] : []).map((e) => e.text ?? "").filter(Boolean).join(", "), C = (e, t) => `${e}:${t}`, w = (e) => {
225
+ let t = /^(\d+):(\d+)$/.exec(e);
226
+ return t ? {
227
+ uidValidity: t[1],
228
+ lastUid: Number(t[2])
229
+ } : null;
230
+ }, T = class {
231
+ config;
232
+ options;
233
+ constructor(e, t = {}) {
234
+ this.config = e, this.options = t;
235
+ }
236
+ getConfigurationState() {
237
+ return t("ImapEmailReader", c(this.config, [
238
+ "host",
239
+ "user",
240
+ "password"
241
+ ]));
242
+ }
243
+ isConfigured() {
244
+ return this.getConfigurationState().configured;
245
+ }
246
+ async withMailbox(e) {
247
+ let t = this.getConfigurationState();
248
+ if (!t.configured) throw new f("not-configured", b, t.reason ?? "IMAP is not configured");
249
+ let n = await (this.options.modules ?? x)(), r = new n.ImapFlow({
250
+ host: this.config.host,
251
+ port: this.config.port ?? 993,
252
+ secure: this.config.secure ?? !0,
253
+ auth: {
254
+ user: this.config.user,
255
+ pass: this.config.password
256
+ },
257
+ logger: !1,
258
+ socketTimeout: 3e4
259
+ });
260
+ try {
261
+ await r.connect();
262
+ } catch (e) {
263
+ let t = e?.authenticationFailed === !0;
264
+ throw new f(t ? "unauthorized" : "unavailable", b, t ? "The IMAP server refused the credentials" : "The IMAP server did not answer", { cause: e });
265
+ }
266
+ try {
267
+ let t = await r.mailboxOpen(this.config.mailbox ?? "INBOX", { readOnly: !0 });
268
+ return await e(r, {
269
+ uidValidity: String(t.uidValidity),
270
+ lastUid: Math.max(0, Number(t.uidNext) - 1)
271
+ }, n);
272
+ } finally {
273
+ await r.logout().catch(() => void 0);
274
+ }
275
+ }
276
+ async start() {
277
+ return this.withMailbox(async (e, t) => ({ cursor: C(t.uidValidity, t.lastUid) }));
278
+ }
279
+ async read(e, { limit: t = 50 } = {}) {
280
+ return this.withMailbox(async (n, r, { simpleParser: i }) => {
281
+ let a = w(e);
282
+ if (!a || a.uidValidity !== r.uidValidity) return {
283
+ messages: [],
284
+ cursor: C(r.uidValidity, r.lastUid)
285
+ };
286
+ let o = [], s = a.lastUid;
287
+ if (r.lastUid > a.lastUid) for await (let e of n.fetch(`${a.lastUid + 1}:*`, {
288
+ uid: !0,
289
+ source: !0
290
+ }, { uid: !0 })) {
291
+ if (e.uid <= a.lastUid || !e.source) continue;
292
+ let n = await i(e.source), c = `${r.uidValidity}-${e.uid}`, l = (n.text ?? (typeof n.html == "string" ? n.html.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ") : "")).trim();
293
+ if (o.push({
294
+ id: c,
295
+ threadId: n.messageId ?? c,
296
+ from: S(n.from),
297
+ to: S(n.to),
298
+ subject: n.subject ?? "",
299
+ date: (n.date ?? /* @__PURE__ */ new Date()).toISOString(),
300
+ text: l,
301
+ direction: "inbound",
302
+ cursor: C(r.uidValidity, e.uid)
303
+ }), s = Math.max(s, e.uid), o.length >= t) break;
304
+ }
305
+ return {
306
+ messages: o,
307
+ cursor: C(r.uidValidity, s)
308
+ };
309
+ });
310
+ }
311
+ };
312
+ //#endregion
313
+ //#region src/providers/ai/server.ts
314
+ async function E(t, r) {
315
+ let i = [t.url, ...Object.values(t.headers)].flatMap(n);
316
+ if (i.length === 0) return {
317
+ ok: !0,
318
+ url: t.url,
319
+ headers: t.headers
320
+ };
321
+ let a = new URL(t.url), { url: o } = t, s = { ...t.headers }, c = /* @__PURE__ */ new Set();
322
+ for (let { placeholder: t, scope: n, provider: l } of i) {
323
+ if (c.has(t)) continue;
324
+ c.add(t);
325
+ let i = await r(n, l);
326
+ if (!i?.apiKey) return {
327
+ ok: !1,
328
+ status: 404,
329
+ error: "unknown-credential",
330
+ provider: l
331
+ };
332
+ if (!e({
333
+ ...i,
334
+ id: l
335
+ }, a)) return {
336
+ ok: !1,
337
+ status: 403,
338
+ error: "forbidden-target",
339
+ provider: l
340
+ };
341
+ o = o.split(t).join(encodeURIComponent(i.apiKey)), s = Object.fromEntries(Object.entries(s).map(([e, n]) => [e, n.split(t).join(i.apiKey)]));
342
+ }
343
+ return {
344
+ ok: !0,
345
+ url: o,
346
+ headers: s
347
+ };
348
+ }
349
+ //#endregion
350
+ export { v as a, _ as i, T as n, p as o, y as r, g as s, E as t };
351
+
352
+ //# sourceMappingURL=server-B430eH0y.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-B430eH0y.mjs","names":["PROVIDER","PROVIDER","isAIProviderTarget","createConfigurationState","findServerCredentials","gmailConfigurationState","callEmailApi","GMAIL_API","gmailAccessToken","fromBase64Url","getMissingKeys","PROVIDER$1","GOOGLE_TOKEN_URL","toEmailMessage","EmailProviderError","GitHubOAuthError","message","status","GITHUB","API","createGitHubOAuth","api","response","fetchFn","path","token","config","params","redirectUri","scopes","codeChallenge","codeVerifier","body","user","organization","role","GmailEmailReader","state","http","init","profile","call","watch","label","taken","next","cursor","pageToken","full","page","record","added","m","id","limit","before","i","error","messages","after","decodeGmailPushNotification","data","parsed","createGmailOAuth","loginHint","grant","PROVIDER","loadModules","cause","addresses","value","a","cursorOf","uidValidity","lastUid","parseCursor","match","ImapEmailReader","options","modules","client","authFailed","box","work","from","item","mail","simpleParser","text","resolveServerCredentials","found","request","target","headers","done","placeholder","secret","lookup","scope","provider","url","name"],"sources":["../src/providers/auth/github/githubOAuth.ts","../src/providers/email/gmail/GmailEmailReader.ts","../src/providers/email/gmail/gmailOAuth.ts","../src/providers/email/imap/ImapEmailReader.ts","../src/providers/ai/server.ts"],"sourcesContent":["// The GitHub side of the sign-in of an app whose server holds the session (CR-104): the authorize\n// URL, the code exchange (it needs the client secret: server only), the profile and the\n// organizations of the person. Pure: no React, no browser API; `fetchFn` is replaceable in tests.\n\nexport type GitHubOAuthConfig = {\n clientId: string;\n clientSecret: string;\n /** Default scopes, e.g. `['read:org']` to list the organizations of the person. */\n scopes?: string[];\n};\n\nexport type GitHubOAuthUser = { login: string; name: string | null; avatarUrl: string | null; email: string | null };\n\nexport type GitHubOAuthOrganization = { login: string; avatarUrl: string | null; role: 'admin' | 'member' };\n\nexport class GitHubOAuthError extends Error {\n constructor(message: string, readonly status?: number) {\n super(message);\n }\n}\n\nconst GITHUB = 'https://github.com';\nconst API = 'https://api.github.com';\n\nexport function createGitHubOAuth(config: GitHubOAuthConfig, fetchFn: typeof fetch = globalThis.fetch) {\n const api = async <T>(path: string, token: string): Promise<T> => {\n const response = await fetchFn(`${API}${path}`, {\n headers: { Accept: 'application/vnd.github+json', Authorization: `Bearer ${token}`, 'X-GitHub-Api-Version': '2022-11-28' },\n });\n if (!response.ok) throw new GitHubOAuthError(`GitHub ${path}: HTTP ${response.status}`, response.status);\n return response.json() as Promise<T>;\n };\n\n return {\n /** Where the person authorizes the app. `state` ties the callback to this request; `codeChallenge` (S256) adds PKCE. */\n authorizeUrl({ state, redirectUri, scopes = config.scopes, codeChallenge }: { state: string; redirectUri: string; scopes?: string[]; codeChallenge?: string }): string {\n const params = new URLSearchParams({ client_id: config.clientId, redirect_uri: redirectUri, state });\n if (scopes?.length) params.set('scope', scopes.join(' '));\n if (codeChallenge) {\n params.set('code_challenge', codeChallenge);\n params.set('code_challenge_method', 'S256');\n }\n return `${GITHUB}/login/oauth/authorize?${params.toString()}`;\n },\n\n /** The access token for the code GitHub sent back. */\n async exchangeCode({ code, redirectUri, codeVerifier }: { code: string; redirectUri: string; codeVerifier?: string }): Promise<{ accessToken: string; scope: string }> {\n const response = await fetchFn(`${GITHUB}/login/oauth/access_token`, {\n method: 'POST',\n headers: { Accept: 'application/json', 'Content-Type': 'application/json' },\n body: JSON.stringify({\n client_id: config.clientId,\n client_secret: config.clientSecret,\n code,\n redirect_uri: redirectUri,\n ...(codeVerifier ? { code_verifier: codeVerifier } : {}),\n }),\n });\n const body = await response.json().catch(() => ({})) as Record<string, unknown>;\n if (!response.ok || typeof body.access_token !== 'string') {\n throw new GitHubOAuthError(String(body.error_description ?? body.error ?? `HTTP ${response.status}`), response.status);\n }\n return { accessToken: body.access_token, scope: String(body.scope ?? '') };\n },\n\n async getUser(token: string): Promise<GitHubOAuthUser> {\n const user = await api<{ login: string; name?: string | null; avatar_url?: string | null; email?: string | null }>('/user', token);\n return { login: user.login, name: user.name ?? null, avatarUrl: user.avatar_url ?? null, email: user.email ?? null };\n },\n\n /** The organizations the person belongs to, with their role (needs `read:org`). */\n async getOrganizations(token: string): Promise<GitHubOAuthOrganization[]> {\n const memberships = await api<Array<{ role: string; organization: { login: string; avatar_url?: string | null } }>>('/user/memberships/orgs?state=active&per_page=100', token);\n return memberships.map(({ role, organization }) => ({\n login: organization.login,\n avatarUrl: organization.avatar_url ?? null,\n role: role === 'admin' ? 'admin' : 'member',\n }));\n },\n };\n}\n\nexport type GitHubOAuth = ReturnType<typeof createGitHubOAuth>;\n","import type { ProviderConfigurationState } from '../../ProviderConfiguration';\nimport { callEmailApi, EmailProviderError } from '../EmailError';\nimport { DEFAULT_EMAIL_READ_LIMIT, type EmailMessage, type EmailReadAdapter, type EmailReadBatch, type EmailReadOptions, type EmailReadStart } from '../EmailRead';\nimport { fromBase64Url, GMAIL_API, gmailAccessToken, gmailConfigurationState, PROVIDER, toEmailMessage, type GmailApiMessage, type GmailAuth } from './gmailApi';\n\nexport type GmailEmailReaderConfig = {\n auth: GmailAuth;\n /**\n * The Pub/Sub topic Gmail notifies (`projects/<project>/topics/<name>`, with `roles/pubsub.publisher` to\n * `gmail-api-push@system.gserviceaccount.com`). Without it `start()` registers no push: the app reads by polling.\n */\n topic?: string;\n /** The label read (default `INBOX`). */\n labelId?: string;\n fetch?: typeof fetch;\n};\n\ntype HistoryPage = {\n history?: { id: string; messagesAdded?: { message: { id: string } }[] }[];\n historyId?: string;\n nextPageToken?: string;\n};\n\n/**\n * Reads a Gmail mailbox (CR-130) by its history: the cursor is a `historyId`. With a `topic`, `start()` also\n * asks Gmail to notify the topic of every change (the push lasts 7 days: call `start()` again before\n * `expiresAt`); a notification (`decodeGmailPushNotification`) tells the app when to `read()`.\n * Scope `GMAIL_SCOPES.read`.\n */\nexport class GmailEmailReader implements EmailReadAdapter {\n constructor(private readonly config: GmailEmailReaderConfig) {}\n\n getConfigurationState(): ProviderConfigurationState {\n return gmailConfigurationState('GmailEmailReader', this.config.auth);\n }\n\n isConfigured(): boolean {\n return this.getConfigurationState().configured;\n }\n\n private async session() {\n const state = this.getConfigurationState();\n if (!state.configured) throw new EmailProviderError('not-configured', PROVIDER, state.reason ?? 'Gmail is not configured');\n const http = this.config.fetch ?? globalThis.fetch;\n const token = await gmailAccessToken(this.config.auth, http);\n const call = <T>(path: string, init: RequestInit = {}) =>\n callEmailApi<T>(PROVIDER, http, `${GMAIL_API}${path}`, { ...init, headers: { authorization: `Bearer ${token}`, ...(init.body ? { 'content-type': 'application/json' } : {}) } });\n return { call, label: this.config.labelId ?? 'INBOX' };\n }\n\n async start(): Promise<EmailReadStart> {\n const { call, label } = await this.session();\n if (!this.config.topic) {\n const profile = await call<{ historyId: string }>('/profile');\n return { cursor: String(profile.historyId) };\n }\n const watch = await call<{ historyId: string; expiration?: string }>('/watch', {\n method: 'POST',\n body: JSON.stringify({ topicName: this.config.topic, labelIds: [label] }),\n });\n return {\n cursor: String(watch.historyId),\n ...(watch.expiration ? { expiresAt: new Date(Number(watch.expiration)).toISOString() } : {}),\n };\n }\n\n async read(cursor: string, { limit = DEFAULT_EMAIL_READ_LIMIT }: EmailReadOptions = {}): Promise<EmailReadBatch> {\n const { call, label } = await this.session();\n // Each message with the cursor after it: its record's id when it is the record's last message, else the\n // cursor before the record (reading from there gives the rest of the record again).\n const taken: { id: string; cursor: string }[] = [];\n let next = cursor;\n let pageToken: string | undefined;\n let full = false;\n try {\n do {\n const params = new URLSearchParams({ startHistoryId: cursor, historyTypes: 'messageAdded', labelId: label });\n if (pageToken) params.set('pageToken', pageToken);\n const page = await call<HistoryPage>(`/history?${params}`);\n for (const record of page.history ?? []) {\n const added = [...new Set((record.messagesAdded ?? []).map((m) => m.message.id))].filter((id) => !taken.some((t) => t.id === id));\n // A record is taken whole: the cursor stops before the one that would go past the limit.\n if (taken.length > 0 && taken.length + added.length > limit) { full = true; break; }\n const before = next;\n added.forEach((id, i) => taken.push({ id, cursor: i === added.length - 1 ? String(record.id) : before }));\n next = String(record.id);\n }\n if (full) break;\n if (page.historyId) next = String(page.historyId);\n pageToken = page.nextPageToken;\n } while (pageToken);\n } catch (error) {\n // The history no longer reaches the cursor: start again from now.\n if (error instanceof EmailProviderError && error.status === 404) {\n const profile = await call<{ historyId: string }>('/profile');\n return { messages: [], cursor: String(profile.historyId) };\n }\n throw error;\n }\n const messages: EmailMessage[] = [];\n for (const { id, cursor: after } of taken) {\n try {\n messages.push(toEmailMessage(await call<GmailApiMessage>(`/messages/${encodeURIComponent(id)}?format=full`), after));\n } catch (error) {\n // Deleted in the meantime.\n if (!(error instanceof EmailProviderError && error.status === 404)) throw error;\n }\n }\n return { messages, cursor: next };\n }\n}\n\n/**\n * The notification Gmail publishes on the topic: the `data` of the Pub/Sub message (base64 JSON) as\n * `{ emailAddress, historyId }`, or `null` when it is not one.\n */\nexport function decodeGmailPushNotification(data: string | undefined | null): { emailAddress: string; historyId: string } | null {\n if (!data) return null;\n try {\n const parsed = JSON.parse(fromBase64Url(data)) as { emailAddress?: unknown; historyId?: unknown };\n if (typeof parsed.emailAddress !== 'string' || parsed.historyId === undefined) return null;\n return { emailAddress: parsed.emailAddress.toLowerCase(), historyId: String(parsed.historyId) };\n } catch {\n return null;\n }\n}\n","import { callEmailApi, EmailProviderError } from '../EmailError';\nimport { GMAIL_API, GOOGLE_TOKEN_URL, PROVIDER } from './gmailApi';\n\nexport type GmailOAuthConfig = {\n clientId: string;\n clientSecret: string;\n /** Where Google comes back with the code: a route of the app's server. */\n redirectUri: string;\n fetch?: typeof fetch;\n};\n\nexport type GmailOAuth = {\n /** The consent page of Google, with a refresh token (offline, consent asked again). */\n authorizationUrl(options: { state: string; scopes: string[]; loginHint?: string }): string;\n /** The code Google came back with → the address of the mailbox and its refresh token. */\n exchangeCode(code: string): Promise<{ email: string; refreshToken: string }>;\n};\n\n/**\n * Connecting a Gmail mailbox from a server (CR-130): the consent page, then the refresh token the Gmail\n * adapters take as `auth`. The client secret and the refresh token stay on the server.\n */\nexport function createGmailOAuth(config: GmailOAuthConfig): GmailOAuth {\n const http = config.fetch ?? globalThis.fetch;\n return {\n authorizationUrl({ state, scopes, loginHint }) {\n const params = new URLSearchParams({\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: 'code',\n scope: scopes.join(' '),\n access_type: 'offline',\n prompt: 'consent',\n include_granted_scopes: 'true',\n state,\n });\n if (loginHint) params.set('login_hint', loginHint);\n return `https://accounts.google.com/o/oauth2/v2/auth?${params}`;\n },\n\n async exchangeCode(code) {\n const grant = await callEmailApi<{ access_token?: string; refresh_token?: string }>(PROVIDER, http, GOOGLE_TOKEN_URL, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n code,\n client_id: config.clientId,\n client_secret: config.clientSecret,\n redirect_uri: config.redirectUri,\n grant_type: 'authorization_code',\n }),\n });\n if (!grant.access_token || !grant.refresh_token) throw new EmailProviderError('unauthorized', PROVIDER, 'Google returned no refresh token');\n const profile = await callEmailApi<{ emailAddress?: string }>(PROVIDER, http, `${GMAIL_API}/profile`, {\n headers: { authorization: `Bearer ${grant.access_token}` },\n });\n return { email: String(profile.emailAddress ?? '').toLowerCase(), refreshToken: grant.refresh_token };\n },\n };\n}\n","import { createConfigurationState, getMissingKeys, type ProviderConfigurationState } from '../../ProviderConfiguration';\r\nimport { EmailProviderError } from '../EmailError';\r\nimport { DEFAULT_EMAIL_READ_LIMIT, type EmailMessage, type EmailReadAdapter, type EmailReadBatch, type EmailReadOptions, type EmailReadStart } from '../EmailRead';\r\n\r\nexport type ImapEmailReaderConfig = {\r\n host: string;\r\n /** Default 993. */\r\n port?: number;\r\n /** TLS from the start (default `true`, port 993); `false` for STARTTLS or plain (port 143). */\r\n secure?: boolean;\r\n user: string;\r\n /** The password, or an app password where the provider has them. */\r\n password: string;\r\n /** Default `INBOX`. */\r\n mailbox?: string;\r\n};\r\n\r\n/** The parts of `imapflow` and `mailparser` the reader uses: injectable for tests. */\r\nexport type ImapModules = {\r\n ImapFlow: new (options: Record<string, unknown>) => ImapClient;\r\n simpleParser: (source: Buffer) => Promise<ParsedMail>;\r\n};\r\n\r\ntype ImapClient = {\r\n connect(): Promise<void>;\r\n mailboxOpen(path: string, options?: { readOnly?: boolean }): Promise<{ uidValidity: bigint | number; uidNext: number }>;\r\n fetch(range: string, query: { uid?: boolean; source?: boolean }, options?: { uid?: boolean }): AsyncIterable<{ uid: number; source?: Buffer }>;\r\n logout(): Promise<void>;\r\n};\r\n\r\ntype ParsedAddress = { text?: string };\r\ntype ParsedMail = {\r\n messageId?: string;\r\n from?: ParsedAddress;\r\n to?: ParsedAddress | ParsedAddress[];\r\n subject?: string;\r\n date?: Date;\r\n text?: string;\r\n html?: string | false;\r\n};\r\n\r\nconst PROVIDER = 'IMAP';\r\n\r\nconst loadModules = async (): Promise<ImapModules> => {\r\n try {\r\n const [{ ImapFlow }, { simpleParser }] = await Promise.all([import('imapflow'), import('mailparser')]);\r\n return { ImapFlow: ImapFlow as unknown as ImapModules['ImapFlow'], simpleParser: simpleParser as unknown as ImapModules['simpleParser'] };\r\n } catch (cause) {\r\n throw new EmailProviderError('not-configured', PROVIDER, 'IMAP needs the packages imapflow and mailparser', { cause });\r\n }\r\n};\r\n\r\nconst addresses = (value: ParsedAddress | ParsedAddress[] | undefined): string =>\r\n (Array.isArray(value) ? value : value ? [value] : []).map((a) => a.text ?? '').filter(Boolean).join(', ');\r\n\r\n/** `<uidValidity>:<last uid read>`. */\r\nconst cursorOf = (uidValidity: string, lastUid: number) => `${uidValidity}:${lastUid}`;\r\n\r\nconst parseCursor = (cursor: string): { uidValidity: string; lastUid: number } | null => {\r\n const match = /^(\\d+):(\\d+)$/.exec(cursor);\r\n return match ? { uidValidity: match[1], lastUid: Number(match[2]) } : null;\r\n};\r\n\r\n/**\r\n * Reads a mailbox with IMAP (CR-130), for the providers without push: the app calls `read()` every few\r\n * minutes. The cursor is the UIDVALIDITY of the mailbox and the last UID read; a new UIDVALIDITY (the\r\n * mailbox renumbered) starts again from now. Server only: it opens a TCP connection. Needs the optional\r\n * packages `imapflow` and `mailparser`, loaded on the first read.\r\n */\r\nexport class ImapEmailReader implements EmailReadAdapter {\r\n constructor(private readonly config: ImapEmailReaderConfig, private readonly options: { modules?: () => Promise<ImapModules> } = {}) {}\r\n\r\n getConfigurationState(): ProviderConfigurationState {\r\n return createConfigurationState('ImapEmailReader', getMissingKeys(this.config as Record<string, unknown>, ['host', 'user', 'password']));\r\n }\r\n\r\n isConfigured(): boolean {\r\n return this.getConfigurationState().configured;\r\n }\r\n\r\n /** Opens the mailbox read-only, runs `work`, logs out whatever happens. */\r\n private async withMailbox<T>(work: (client: ImapClient, box: { uidValidity: string; lastUid: number }, modules: ImapModules) => Promise<T>): Promise<T> {\r\n const state = this.getConfigurationState();\r\n if (!state.configured) throw new EmailProviderError('not-configured', PROVIDER, state.reason ?? 'IMAP is not configured');\r\n const modules = await (this.options.modules ?? loadModules)();\r\n const client = new modules.ImapFlow({\r\n host: this.config.host,\r\n port: this.config.port ?? 993,\r\n secure: this.config.secure ?? true,\r\n auth: { user: this.config.user, pass: this.config.password },\r\n logger: false,\r\n socketTimeout: 30_000,\r\n });\r\n try {\r\n await client.connect();\r\n } catch (cause) {\r\n const authFailed = (cause as { authenticationFailed?: boolean } | null)?.authenticationFailed === true;\r\n throw new EmailProviderError(authFailed ? 'unauthorized' : 'unavailable', PROVIDER, authFailed ? 'The IMAP server refused the credentials' : 'The IMAP server did not answer', { cause });\r\n }\r\n try {\r\n const box = await client.mailboxOpen(this.config.mailbox ?? 'INBOX', { readOnly: true });\r\n return await work(client, { uidValidity: String(box.uidValidity), lastUid: Math.max(0, Number(box.uidNext) - 1) }, modules);\r\n } finally {\r\n await client.logout().catch(() => undefined);\r\n }\r\n }\r\n\r\n async start(): Promise<EmailReadStart> {\r\n return this.withMailbox(async (_client, box) => ({ cursor: cursorOf(box.uidValidity, box.lastUid) }));\r\n }\r\n\r\n async read(cursor: string, { limit = DEFAULT_EMAIL_READ_LIMIT }: EmailReadOptions = {}): Promise<EmailReadBatch> {\r\n return this.withMailbox(async (client, box, { simpleParser }) => {\r\n const from = parseCursor(cursor);\r\n if (!from || from.uidValidity !== box.uidValidity) return { messages: [], cursor: cursorOf(box.uidValidity, box.lastUid) };\r\n const messages: EmailMessage[] = [];\r\n let lastUid = from.lastUid;\r\n if (box.lastUid > from.lastUid) {\r\n for await (const item of client.fetch(`${from.lastUid + 1}:*`, { uid: true, source: true }, { uid: true })) {\r\n // `n:*` always returns the last message, even when it is older than n.\r\n if (item.uid <= from.lastUid || !item.source) continue;\r\n const mail = await simpleParser(item.source);\r\n const id = `${box.uidValidity}-${item.uid}`;\r\n const text = (mail.text ?? (typeof mail.html === 'string' ? mail.html.replace(/<[^>]*>/g, ' ').replace(/\\s+/g, ' ') : '')).trim();\r\n messages.push({\r\n id,\r\n threadId: mail.messageId ?? id,\r\n from: addresses(mail.from),\r\n to: addresses(mail.to),\r\n subject: mail.subject ?? '',\r\n date: (mail.date ?? new Date()).toISOString(),\r\n text,\r\n direction: 'inbound',\r\n cursor: cursorOf(box.uidValidity, item.uid),\r\n });\r\n lastUid = Math.max(lastUid, item.uid);\r\n if (messages.length >= limit) break;\r\n }\r\n }\r\n return { messages, cursor: cursorOf(box.uidValidity, lastUid) };\r\n });\r\n }\r\n}\r\n","// `@llmnative/react/server`: what a Node server needs: server-held AI credentials (CR-102), GitHub sign-in,\r\n// the email adapters (CR-130).\r\n// No React and no browser API: it runs in the app's own server or in the Vite dev proxy.\r\n\r\nimport { findServerCredentials, isAIProviderTarget, type ServerAIConnection } from './serverCredentials';\r\n\r\nexport { AI_PROVIDER_HOSTS, isAIProviderTarget, serverCredential, SERVER_CREDENTIAL_PREFIX } from './serverCredentials';\r\nexport type { ServerAIConnection } from './serverCredentials';\r\n// Sign-in with GitHub held by the app's server (CR-104): authorize URL, code exchange, profile, organizations.\r\nexport { createGitHubOAuth, GitHubOAuthError } from '../auth/github/githubOAuth';\r\nexport type { GitHubOAuth, GitHubOAuthConfig, GitHubOAuthOrganization, GitHubOAuthUser } from '../auth/github/githubOAuth';\r\n// Provider-agnostic identity of models (CR-103): pure, so a server or a generator can resolve them too.\r\nexport { canonicalModelName, buildModelIdentityIndex, resolveModel, modelOffers, loadModelIdentityIndex } from './modelIdentity';\r\nexport type { ModelIdentity, ModelIdentityEntry, ModelIdentityIndex, ResolvedModel, ModelOffer, ModelCost } from './modelIdentity';\r\n\r\n/** The connection of a provider as the server keeps it, key included. */\r\nexport type ServerAISecret = ServerAIConnection & { apiKey: string };\r\n\r\n/** The key of `provider` for `scope` (e.g. a company), or nothing when it is not connected. */\r\nexport type ServerCredentialLookup = (scope: string, provider: string) => ServerAISecret | undefined | Promise<ServerAISecret | undefined>;\r\n\r\nexport type ServerCredentialRequest = { url: string; headers: Record<string, string> };\r\n\r\nexport type ServerCredentialResolution =\r\n | { ok: true; url: string; headers: Record<string, string> }\r\n /** 404: the provider is not connected for that scope; 403: the target is not a host of that provider. */\r\n | { ok: false; status: 403 | 404; error: 'unknown-credential' | 'forbidden-target'; provider: string };\r\n\r\n/**\r\n * Swaps every server-credential placeholder of a proxied request (headers and URL) for the key it\r\n * stands for. The key only goes to a host of its provider: any other target is refused, so a\r\n * placeholder can never carry a key elsewhere. A request without placeholders passes unchanged.\r\n */\r\nexport async function resolveServerCredentials(request: ServerCredentialRequest, lookup: ServerCredentialLookup): Promise<ServerCredentialResolution> {\r\n const found = [request.url, ...Object.values(request.headers)].flatMap(findServerCredentials);\r\n if (found.length === 0) return { ok: true, url: request.url, headers: request.headers };\r\n\r\n const target = new URL(request.url);\r\n let { url } = request;\r\n let headers = { ...request.headers };\r\n const done = new Set<string>();\r\n for (const { placeholder, scope, provider } of found) {\r\n if (done.has(placeholder)) continue;\r\n done.add(placeholder);\r\n const secret = await lookup(scope, provider);\r\n if (!secret?.apiKey) return { ok: false, status: 404, error: 'unknown-credential', provider };\r\n if (!isAIProviderTarget({ ...secret, id: provider }, target)) return { ok: false, status: 403, error: 'forbidden-target', provider };\r\n url = url.split(placeholder).join(encodeURIComponent(secret.apiKey));\r\n headers = Object.fromEntries(Object.entries(headers).map(([name, value]) => [name, value.split(placeholder).join(secret.apiKey)]));\r\n }\r\n return { ok: true, url, headers };\r\n}\r\n\r\n// Email (CR-130): the adapters of `emailSend` and `emailRead` for a server, Gmail's OAuth and push. IMAP loads\r\n// the optional packages `imapflow` and `mailparser` only when it reads.\r\nexport { EmailProviderError } from '../email/EmailError';\r\nexport type { EmailProviderErrorCode } from '../email/EmailError';\r\nexport type { EmailSendAdapter, EmailSendParams, EmailSendResult, EmailAddress, EmailRecipient } from '../email/EmailSend';\r\nexport type { EmailReadAdapter, EmailMessage, EmailReadStart, EmailReadBatch, EmailReadOptions } from '../email/EmailRead';\r\nexport { EMAIL_SEND_PROVIDER_DEFINITIONS, EMAIL_READ_PROVIDER_DEFINITIONS } from '../email/definitions';\r\nexport type { EmailSendProviderId, EmailReadProviderId } from '../email/definitions';\r\nexport { ResendEmailSender } from '../email/resend/ResendEmailSender';\r\nexport type { ResendEmailSenderConfig } from '../email/resend/ResendEmailSender';\r\nexport { BrevoEmailSender } from '../email/brevo/BrevoEmailSender';\r\nexport type { BrevoEmailSenderConfig } from '../email/brevo/BrevoEmailSender';\r\nexport { GmailEmailSender } from '../email/gmail/GmailEmailSender';\r\nexport type { GmailEmailSenderConfig } from '../email/gmail/GmailEmailSender';\r\nexport { GmailEmailReader, decodeGmailPushNotification } from '../email/gmail/GmailEmailReader';\r\nexport type { GmailEmailReaderConfig } from '../email/gmail/GmailEmailReader';\r\nexport { createGmailOAuth } from '../email/gmail/gmailOAuth';\r\nexport type { GmailOAuth, GmailOAuthConfig } from '../email/gmail/gmailOAuth';\r\nexport { GMAIL_SCOPES } from '../email/gmail/gmailApi';\r\nexport type { GmailAuth } from '../email/gmail/gmailApi';\r\nexport { ImapEmailReader } from '../email/imap/ImapEmailReader';\r\nexport type { ImapEmailReaderConfig, ImapModules } from '../email/imap/ImapEmailReader';\r\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require("./modelIdentity-DX62i7g2.js");var t=class extends Error{status;constructor(e,t){super(e),this.status=t}},n=`https://github.com`,r=`https://api.github.com`;function i(e,i=globalThis.fetch){let a=async(e,n)=>{let a=await i(`${r}${e}`,{headers:{Accept:`application/vnd.github+json`,Authorization:`Bearer ${n}`,"X-GitHub-Api-Version":`2022-11-28`}});if(!a.ok)throw new t(`GitHub ${e}: HTTP ${a.status}`,a.status);return a.json()};return{authorizeUrl({state:t,redirectUri:r,scopes:i=e.scopes,codeChallenge:a}){let o=new URLSearchParams({client_id:e.clientId,redirect_uri:r,state:t});return i?.length&&o.set(`scope`,i.join(` `)),a&&(o.set(`code_challenge`,a),o.set(`code_challenge_method`,`S256`)),`${n}/login/oauth/authorize?${o.toString()}`},async exchangeCode({code:r,redirectUri:a,codeVerifier:o}){let s=await i(`${n}/login/oauth/access_token`,{method:`POST`,headers:{Accept:`application/json`,"Content-Type":`application/json`},body:JSON.stringify({client_id:e.clientId,client_secret:e.clientSecret,code:r,redirect_uri:a,...o?{code_verifier:o}:{}})}),c=await s.json().catch(()=>({}));if(!s.ok||typeof c.access_token!=`string`)throw new t(String(c.error_description??c.error??`HTTP ${s.status}`),s.status);return{accessToken:c.access_token,scope:String(c.scope??``)}},async getUser(e){let t=await a(`/user`,e);return{login:t.login,name:t.name??null,avatarUrl:t.avatar_url??null,email:t.email??null}},async getOrganizations(e){return(await a(`/user/memberships/orgs?state=active&per_page=100`,e)).map(({role:e,organization:t})=>({login:t.login,avatarUrl:t.avatar_url??null,role:e===`admin`?`admin`:`member`}))}}}var a=class{config;constructor(e){this.config=e}getConfigurationState(){return e._(`GmailEmailReader`,this.config.auth)}isConfigured(){return this.getConfigurationState().configured}async session(){let t=this.getConfigurationState();if(!t.configured)throw new e.y(`not-configured`,e.m,t.reason??`Gmail is not configured`);let n=this.config.fetch??globalThis.fetch,r=await e.g(this.config.auth,n);return{call:(t,i={})=>e.b(e.m,n,`${e.d}${t}`,{...i,headers:{authorization:`Bearer ${r}`,...i.body?{"content-type":`application/json`}:{}}}),label:this.config.labelId??`INBOX`}}async start(){let{call:e,label:t}=await this.session();if(!this.config.topic){let t=await e(`/profile`);return{cursor:String(t.historyId)}}let n=await e(`/watch`,{method:`POST`,body:JSON.stringify({topicName:this.config.topic,labelIds:[t]})});return{cursor:String(n.historyId),...n.expiration?{expiresAt:new Date(Number(n.expiration)).toISOString()}:{}}}async read(t,{limit:n=50}={}){let{call:r,label:i}=await this.session(),a=[],o=t,s,c=!1;try{do{let e=new URLSearchParams({startHistoryId:t,historyTypes:`messageAdded`,labelId:i});s&&e.set(`pageToken`,s);let l=await r(`/history?${e}`);for(let e of l.history??[]){let t=[...new Set((e.messagesAdded??[]).map(e=>e.message.id))].filter(e=>!a.some(t=>t.id===e));if(a.length>0&&a.length+t.length>n){c=!0;break}let r=o;t.forEach((n,i)=>a.push({id:n,cursor:i===t.length-1?String(e.id):r})),o=String(e.id)}if(c)break;l.historyId&&(o=String(l.historyId)),s=l.nextPageToken}while(s)}catch(t){if(t instanceof e.y&&t.status===404){let e=await r(`/profile`);return{messages:[],cursor:String(e.historyId)}}throw t}let l=[];for(let{id:t,cursor:n}of a)try{l.push(e.v(await r(`/messages/${encodeURIComponent(t)}?format=full`),n))}catch(t){if(!(t instanceof e.y&&t.status===404))throw t}return{messages:l,cursor:o}}};function o(t){if(!t)return null;try{let n=JSON.parse(e.h(t));return typeof n.emailAddress!=`string`||n.historyId===void 0?null:{emailAddress:n.emailAddress.toLowerCase(),historyId:String(n.historyId)}}catch{return null}}function s(t){let n=t.fetch??globalThis.fetch;return{authorizationUrl({state:e,scopes:n,loginHint:r}){let i=new URLSearchParams({client_id:t.clientId,redirect_uri:t.redirectUri,response_type:`code`,scope:n.join(` `),access_type:`offline`,prompt:`consent`,include_granted_scopes:`true`,state:e});return r&&i.set(`login_hint`,r),`https://accounts.google.com/o/oauth2/v2/auth?${i}`},async exchangeCode(r){let i=await e.b(e.m,n,e.p,{method:`POST`,headers:{"content-type":`application/x-www-form-urlencoded`},body:new URLSearchParams({code:r,client_id:t.clientId,client_secret:t.clientSecret,redirect_uri:t.redirectUri,grant_type:`authorization_code`})});if(!i.access_token||!i.refresh_token)throw new e.y(`unauthorized`,e.m,`Google returned no refresh token`);let a=await e.b(e.m,n,`${e.d}/profile`,{headers:{authorization:`Bearer ${i.access_token}`}});return{email:String(a.emailAddress??``).toLowerCase(),refreshToken:i.refresh_token}}}}var c=`IMAP`,l=async()=>{try{let[{ImapFlow:e},{simpleParser:t}]=await Promise.all([import(`imapflow`),import(`mailparser`)]);return{ImapFlow:e,simpleParser:t}}catch(t){throw new e.y(`not-configured`,c,`IMAP needs the packages imapflow and mailparser`,{cause:t})}},u=e=>(Array.isArray(e)?e:e?[e]:[]).map(e=>e.text??``).filter(Boolean).join(`, `),d=(e,t)=>`${e}:${t}`,f=e=>{let t=/^(\d+):(\d+)$/.exec(e);return t?{uidValidity:t[1],lastUid:Number(t[2])}:null},p=class{config;options;constructor(e,t={}){this.config=e,this.options=t}getConfigurationState(){return e.O(`ImapEmailReader`,e.k(this.config,[`host`,`user`,`password`]))}isConfigured(){return this.getConfigurationState().configured}async withMailbox(t){let n=this.getConfigurationState();if(!n.configured)throw new e.y(`not-configured`,c,n.reason??`IMAP is not configured`);let r=await(this.options.modules??l)(),i=new r.ImapFlow({host:this.config.host,port:this.config.port??993,secure:this.config.secure??!0,auth:{user:this.config.user,pass:this.config.password},logger:!1,socketTimeout:3e4});try{await i.connect()}catch(t){let n=t?.authenticationFailed===!0;throw new e.y(n?`unauthorized`:`unavailable`,c,n?`The IMAP server refused the credentials`:`The IMAP server did not answer`,{cause:t})}try{let e=await i.mailboxOpen(this.config.mailbox??`INBOX`,{readOnly:!0});return await t(i,{uidValidity:String(e.uidValidity),lastUid:Math.max(0,Number(e.uidNext)-1)},r)}finally{await i.logout().catch(()=>void 0)}}async start(){return this.withMailbox(async(e,t)=>({cursor:d(t.uidValidity,t.lastUid)}))}async read(e,{limit:t=50}={}){return this.withMailbox(async(n,r,{simpleParser:i})=>{let a=f(e);if(!a||a.uidValidity!==r.uidValidity)return{messages:[],cursor:d(r.uidValidity,r.lastUid)};let o=[],s=a.lastUid;if(r.lastUid>a.lastUid)for await(let e of n.fetch(`${a.lastUid+1}:*`,{uid:!0,source:!0},{uid:!0})){if(e.uid<=a.lastUid||!e.source)continue;let n=await i(e.source),c=`${r.uidValidity}-${e.uid}`,l=(n.text??(typeof n.html==`string`?n.html.replace(/<[^>]*>/g,` `).replace(/\s+/g,` `):``)).trim();if(o.push({id:c,threadId:n.messageId??c,from:u(n.from),to:u(n.to),subject:n.subject??``,date:(n.date??new Date).toISOString(),text:l,direction:`inbound`,cursor:d(r.uidValidity,e.uid)}),s=Math.max(s,e.uid),o.length>=t)break}return{messages:o,cursor:d(r.uidValidity,s)}})}};async function m(t,n){let r=[t.url,...Object.values(t.headers)].flatMap(e.T);if(r.length===0)return{ok:!0,url:t.url,headers:t.headers};let i=new URL(t.url),{url:a}=t,o={...t.headers},s=new Set;for(let{placeholder:t,scope:c,provider:l}of r){if(s.has(t))continue;s.add(t);let r=await n(c,l);if(!r?.apiKey)return{ok:!1,status:404,error:`unknown-credential`,provider:l};if(!e.E({...r,id:l},i))return{ok:!1,status:403,error:`forbidden-target`,provider:l};a=a.split(t).join(encodeURIComponent(r.apiKey)),o=Object.fromEntries(Object.entries(o).map(([e,n])=>[e,n.split(t).join(r.apiKey)]))}return{ok:!0,url:a,headers:o}}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return m}});
2
+ //# sourceMappingURL=server-CDheNgME.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-CDheNgME.js","names":["gmailConfigurationState","EmailProviderError","PROVIDER","gmailAccessToken","callEmailApi","GMAIL_API","toEmailMessage","fromBase64Url","callEmailApi","PROVIDER","GOOGLE_TOKEN_URL","EmailProviderError","GMAIL_API","EmailProviderError","createConfigurationState","getMissingKeys","findServerCredentials","isAIProviderTarget","require_modelIdentity","GitHubOAuthError","message","status","GITHUB","API","createGitHubOAuth","api","response","fetchFn","path","token","config","params","redirectUri","scopes","codeChallenge","codeVerifier","body","user","organization","role","GmailEmailReader","state","http","init","profile","call","watch","label","taken","next","cursor","pageToken","full","page","record","added","m","id","limit","before","error","messages","after","decodeGmailPushNotification","data","parsed","createGmailOAuth","loginHint","grant","PROVIDER","loadModules","cause","addresses","value","a","cursorOf","uidValidity","lastUid","parseCursor","match","ImapEmailReader","options","modules","client","authFailed","box","work","from","item","mail","simpleParser","text","resolveServerCredentials","found","request","target","headers","done","placeholder","secret","lookup","scope","provider","url","name"],"sources":["../src/providers/auth/github/githubOAuth.ts","../src/providers/email/gmail/GmailEmailReader.ts","../src/providers/email/gmail/gmailOAuth.ts","../src/providers/email/imap/ImapEmailReader.ts","../src/providers/ai/server.ts"],"sourcesContent":["// The GitHub side of the sign-in of an app whose server holds the session (CR-104): the authorize\n// URL, the code exchange (it needs the client secret: server only), the profile and the\n// organizations of the person. Pure: no React, no browser API; `fetchFn` is replaceable in tests.\n\nexport type GitHubOAuthConfig = {\n clientId: string;\n clientSecret: string;\n /** Default scopes, e.g. `['read:org']` to list the organizations of the person. */\n scopes?: string[];\n};\n\nexport type GitHubOAuthUser = { login: string; name: string | null; avatarUrl: string | null; email: string | null };\n\nexport type GitHubOAuthOrganization = { login: string; avatarUrl: string | null; role: 'admin' | 'member' };\n\nexport class GitHubOAuthError extends Error {\n constructor(message: string, readonly status?: number) {\n super(message);\n }\n}\n\nconst GITHUB = 'https://github.com';\nconst API = 'https://api.github.com';\n\nexport function createGitHubOAuth(config: GitHubOAuthConfig, fetchFn: typeof fetch = globalThis.fetch) {\n const api = async <T>(path: string, token: string): Promise<T> => {\n const response = await fetchFn(`${API}${path}`, {\n headers: { Accept: 'application/vnd.github+json', Authorization: `Bearer ${token}`, 'X-GitHub-Api-Version': '2022-11-28' },\n });\n if (!response.ok) throw new GitHubOAuthError(`GitHub ${path}: HTTP ${response.status}`, response.status);\n return response.json() as Promise<T>;\n };\n\n return {\n /** Where the person authorizes the app. `state` ties the callback to this request; `codeChallenge` (S256) adds PKCE. */\n authorizeUrl({ state, redirectUri, scopes = config.scopes, codeChallenge }: { state: string; redirectUri: string; scopes?: string[]; codeChallenge?: string }): string {\n const params = new URLSearchParams({ client_id: config.clientId, redirect_uri: redirectUri, state });\n if (scopes?.length) params.set('scope', scopes.join(' '));\n if (codeChallenge) {\n params.set('code_challenge', codeChallenge);\n params.set('code_challenge_method', 'S256');\n }\n return `${GITHUB}/login/oauth/authorize?${params.toString()}`;\n },\n\n /** The access token for the code GitHub sent back. */\n async exchangeCode({ code, redirectUri, codeVerifier }: { code: string; redirectUri: string; codeVerifier?: string }): Promise<{ accessToken: string; scope: string }> {\n const response = await fetchFn(`${GITHUB}/login/oauth/access_token`, {\n method: 'POST',\n headers: { Accept: 'application/json', 'Content-Type': 'application/json' },\n body: JSON.stringify({\n client_id: config.clientId,\n client_secret: config.clientSecret,\n code,\n redirect_uri: redirectUri,\n ...(codeVerifier ? { code_verifier: codeVerifier } : {}),\n }),\n });\n const body = await response.json().catch(() => ({})) as Record<string, unknown>;\n if (!response.ok || typeof body.access_token !== 'string') {\n throw new GitHubOAuthError(String(body.error_description ?? body.error ?? `HTTP ${response.status}`), response.status);\n }\n return { accessToken: body.access_token, scope: String(body.scope ?? '') };\n },\n\n async getUser(token: string): Promise<GitHubOAuthUser> {\n const user = await api<{ login: string; name?: string | null; avatar_url?: string | null; email?: string | null }>('/user', token);\n return { login: user.login, name: user.name ?? null, avatarUrl: user.avatar_url ?? null, email: user.email ?? null };\n },\n\n /** The organizations the person belongs to, with their role (needs `read:org`). */\n async getOrganizations(token: string): Promise<GitHubOAuthOrganization[]> {\n const memberships = await api<Array<{ role: string; organization: { login: string; avatar_url?: string | null } }>>('/user/memberships/orgs?state=active&per_page=100', token);\n return memberships.map(({ role, organization }) => ({\n login: organization.login,\n avatarUrl: organization.avatar_url ?? null,\n role: role === 'admin' ? 'admin' : 'member',\n }));\n },\n };\n}\n\nexport type GitHubOAuth = ReturnType<typeof createGitHubOAuth>;\n","import type { ProviderConfigurationState } from '../../ProviderConfiguration';\nimport { callEmailApi, EmailProviderError } from '../EmailError';\nimport { DEFAULT_EMAIL_READ_LIMIT, type EmailMessage, type EmailReadAdapter, type EmailReadBatch, type EmailReadOptions, type EmailReadStart } from '../EmailRead';\nimport { fromBase64Url, GMAIL_API, gmailAccessToken, gmailConfigurationState, PROVIDER, toEmailMessage, type GmailApiMessage, type GmailAuth } from './gmailApi';\n\nexport type GmailEmailReaderConfig = {\n auth: GmailAuth;\n /**\n * The Pub/Sub topic Gmail notifies (`projects/<project>/topics/<name>`, with `roles/pubsub.publisher` to\n * `gmail-api-push@system.gserviceaccount.com`). Without it `start()` registers no push: the app reads by polling.\n */\n topic?: string;\n /** The label read (default `INBOX`). */\n labelId?: string;\n fetch?: typeof fetch;\n};\n\ntype HistoryPage = {\n history?: { id: string; messagesAdded?: { message: { id: string } }[] }[];\n historyId?: string;\n nextPageToken?: string;\n};\n\n/**\n * Reads a Gmail mailbox (CR-130) by its history: the cursor is a `historyId`. With a `topic`, `start()` also\n * asks Gmail to notify the topic of every change (the push lasts 7 days: call `start()` again before\n * `expiresAt`); a notification (`decodeGmailPushNotification`) tells the app when to `read()`.\n * Scope `GMAIL_SCOPES.read`.\n */\nexport class GmailEmailReader implements EmailReadAdapter {\n constructor(private readonly config: GmailEmailReaderConfig) {}\n\n getConfigurationState(): ProviderConfigurationState {\n return gmailConfigurationState('GmailEmailReader', this.config.auth);\n }\n\n isConfigured(): boolean {\n return this.getConfigurationState().configured;\n }\n\n private async session() {\n const state = this.getConfigurationState();\n if (!state.configured) throw new EmailProviderError('not-configured', PROVIDER, state.reason ?? 'Gmail is not configured');\n const http = this.config.fetch ?? globalThis.fetch;\n const token = await gmailAccessToken(this.config.auth, http);\n const call = <T>(path: string, init: RequestInit = {}) =>\n callEmailApi<T>(PROVIDER, http, `${GMAIL_API}${path}`, { ...init, headers: { authorization: `Bearer ${token}`, ...(init.body ? { 'content-type': 'application/json' } : {}) } });\n return { call, label: this.config.labelId ?? 'INBOX' };\n }\n\n async start(): Promise<EmailReadStart> {\n const { call, label } = await this.session();\n if (!this.config.topic) {\n const profile = await call<{ historyId: string }>('/profile');\n return { cursor: String(profile.historyId) };\n }\n const watch = await call<{ historyId: string; expiration?: string }>('/watch', {\n method: 'POST',\n body: JSON.stringify({ topicName: this.config.topic, labelIds: [label] }),\n });\n return {\n cursor: String(watch.historyId),\n ...(watch.expiration ? { expiresAt: new Date(Number(watch.expiration)).toISOString() } : {}),\n };\n }\n\n async read(cursor: string, { limit = DEFAULT_EMAIL_READ_LIMIT }: EmailReadOptions = {}): Promise<EmailReadBatch> {\n const { call, label } = await this.session();\n // Each message with the cursor after it: its record's id when it is the record's last message, else the\n // cursor before the record (reading from there gives the rest of the record again).\n const taken: { id: string; cursor: string }[] = [];\n let next = cursor;\n let pageToken: string | undefined;\n let full = false;\n try {\n do {\n const params = new URLSearchParams({ startHistoryId: cursor, historyTypes: 'messageAdded', labelId: label });\n if (pageToken) params.set('pageToken', pageToken);\n const page = await call<HistoryPage>(`/history?${params}`);\n for (const record of page.history ?? []) {\n const added = [...new Set((record.messagesAdded ?? []).map((m) => m.message.id))].filter((id) => !taken.some((t) => t.id === id));\n // A record is taken whole: the cursor stops before the one that would go past the limit.\n if (taken.length > 0 && taken.length + added.length > limit) { full = true; break; }\n const before = next;\n added.forEach((id, i) => taken.push({ id, cursor: i === added.length - 1 ? String(record.id) : before }));\n next = String(record.id);\n }\n if (full) break;\n if (page.historyId) next = String(page.historyId);\n pageToken = page.nextPageToken;\n } while (pageToken);\n } catch (error) {\n // The history no longer reaches the cursor: start again from now.\n if (error instanceof EmailProviderError && error.status === 404) {\n const profile = await call<{ historyId: string }>('/profile');\n return { messages: [], cursor: String(profile.historyId) };\n }\n throw error;\n }\n const messages: EmailMessage[] = [];\n for (const { id, cursor: after } of taken) {\n try {\n messages.push(toEmailMessage(await call<GmailApiMessage>(`/messages/${encodeURIComponent(id)}?format=full`), after));\n } catch (error) {\n // Deleted in the meantime.\n if (!(error instanceof EmailProviderError && error.status === 404)) throw error;\n }\n }\n return { messages, cursor: next };\n }\n}\n\n/**\n * The notification Gmail publishes on the topic: the `data` of the Pub/Sub message (base64 JSON) as\n * `{ emailAddress, historyId }`, or `null` when it is not one.\n */\nexport function decodeGmailPushNotification(data: string | undefined | null): { emailAddress: string; historyId: string } | null {\n if (!data) return null;\n try {\n const parsed = JSON.parse(fromBase64Url(data)) as { emailAddress?: unknown; historyId?: unknown };\n if (typeof parsed.emailAddress !== 'string' || parsed.historyId === undefined) return null;\n return { emailAddress: parsed.emailAddress.toLowerCase(), historyId: String(parsed.historyId) };\n } catch {\n return null;\n }\n}\n","import { callEmailApi, EmailProviderError } from '../EmailError';\nimport { GMAIL_API, GOOGLE_TOKEN_URL, PROVIDER } from './gmailApi';\n\nexport type GmailOAuthConfig = {\n clientId: string;\n clientSecret: string;\n /** Where Google comes back with the code: a route of the app's server. */\n redirectUri: string;\n fetch?: typeof fetch;\n};\n\nexport type GmailOAuth = {\n /** The consent page of Google, with a refresh token (offline, consent asked again). */\n authorizationUrl(options: { state: string; scopes: string[]; loginHint?: string }): string;\n /** The code Google came back with → the address of the mailbox and its refresh token. */\n exchangeCode(code: string): Promise<{ email: string; refreshToken: string }>;\n};\n\n/**\n * Connecting a Gmail mailbox from a server (CR-130): the consent page, then the refresh token the Gmail\n * adapters take as `auth`. The client secret and the refresh token stay on the server.\n */\nexport function createGmailOAuth(config: GmailOAuthConfig): GmailOAuth {\n const http = config.fetch ?? globalThis.fetch;\n return {\n authorizationUrl({ state, scopes, loginHint }) {\n const params = new URLSearchParams({\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: 'code',\n scope: scopes.join(' '),\n access_type: 'offline',\n prompt: 'consent',\n include_granted_scopes: 'true',\n state,\n });\n if (loginHint) params.set('login_hint', loginHint);\n return `https://accounts.google.com/o/oauth2/v2/auth?${params}`;\n },\n\n async exchangeCode(code) {\n const grant = await callEmailApi<{ access_token?: string; refresh_token?: string }>(PROVIDER, http, GOOGLE_TOKEN_URL, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n code,\n client_id: config.clientId,\n client_secret: config.clientSecret,\n redirect_uri: config.redirectUri,\n grant_type: 'authorization_code',\n }),\n });\n if (!grant.access_token || !grant.refresh_token) throw new EmailProviderError('unauthorized', PROVIDER, 'Google returned no refresh token');\n const profile = await callEmailApi<{ emailAddress?: string }>(PROVIDER, http, `${GMAIL_API}/profile`, {\n headers: { authorization: `Bearer ${grant.access_token}` },\n });\n return { email: String(profile.emailAddress ?? '').toLowerCase(), refreshToken: grant.refresh_token };\n },\n };\n}\n","import { createConfigurationState, getMissingKeys, type ProviderConfigurationState } from '../../ProviderConfiguration';\r\nimport { EmailProviderError } from '../EmailError';\r\nimport { DEFAULT_EMAIL_READ_LIMIT, type EmailMessage, type EmailReadAdapter, type EmailReadBatch, type EmailReadOptions, type EmailReadStart } from '../EmailRead';\r\n\r\nexport type ImapEmailReaderConfig = {\r\n host: string;\r\n /** Default 993. */\r\n port?: number;\r\n /** TLS from the start (default `true`, port 993); `false` for STARTTLS or plain (port 143). */\r\n secure?: boolean;\r\n user: string;\r\n /** The password, or an app password where the provider has them. */\r\n password: string;\r\n /** Default `INBOX`. */\r\n mailbox?: string;\r\n};\r\n\r\n/** The parts of `imapflow` and `mailparser` the reader uses: injectable for tests. */\r\nexport type ImapModules = {\r\n ImapFlow: new (options: Record<string, unknown>) => ImapClient;\r\n simpleParser: (source: Buffer) => Promise<ParsedMail>;\r\n};\r\n\r\ntype ImapClient = {\r\n connect(): Promise<void>;\r\n mailboxOpen(path: string, options?: { readOnly?: boolean }): Promise<{ uidValidity: bigint | number; uidNext: number }>;\r\n fetch(range: string, query: { uid?: boolean; source?: boolean }, options?: { uid?: boolean }): AsyncIterable<{ uid: number; source?: Buffer }>;\r\n logout(): Promise<void>;\r\n};\r\n\r\ntype ParsedAddress = { text?: string };\r\ntype ParsedMail = {\r\n messageId?: string;\r\n from?: ParsedAddress;\r\n to?: ParsedAddress | ParsedAddress[];\r\n subject?: string;\r\n date?: Date;\r\n text?: string;\r\n html?: string | false;\r\n};\r\n\r\nconst PROVIDER = 'IMAP';\r\n\r\nconst loadModules = async (): Promise<ImapModules> => {\r\n try {\r\n const [{ ImapFlow }, { simpleParser }] = await Promise.all([import('imapflow'), import('mailparser')]);\r\n return { ImapFlow: ImapFlow as unknown as ImapModules['ImapFlow'], simpleParser: simpleParser as unknown as ImapModules['simpleParser'] };\r\n } catch (cause) {\r\n throw new EmailProviderError('not-configured', PROVIDER, 'IMAP needs the packages imapflow and mailparser', { cause });\r\n }\r\n};\r\n\r\nconst addresses = (value: ParsedAddress | ParsedAddress[] | undefined): string =>\r\n (Array.isArray(value) ? value : value ? [value] : []).map((a) => a.text ?? '').filter(Boolean).join(', ');\r\n\r\n/** `<uidValidity>:<last uid read>`. */\r\nconst cursorOf = (uidValidity: string, lastUid: number) => `${uidValidity}:${lastUid}`;\r\n\r\nconst parseCursor = (cursor: string): { uidValidity: string; lastUid: number } | null => {\r\n const match = /^(\\d+):(\\d+)$/.exec(cursor);\r\n return match ? { uidValidity: match[1], lastUid: Number(match[2]) } : null;\r\n};\r\n\r\n/**\r\n * Reads a mailbox with IMAP (CR-130), for the providers without push: the app calls `read()` every few\r\n * minutes. The cursor is the UIDVALIDITY of the mailbox and the last UID read; a new UIDVALIDITY (the\r\n * mailbox renumbered) starts again from now. Server only: it opens a TCP connection. Needs the optional\r\n * packages `imapflow` and `mailparser`, loaded on the first read.\r\n */\r\nexport class ImapEmailReader implements EmailReadAdapter {\r\n constructor(private readonly config: ImapEmailReaderConfig, private readonly options: { modules?: () => Promise<ImapModules> } = {}) {}\r\n\r\n getConfigurationState(): ProviderConfigurationState {\r\n return createConfigurationState('ImapEmailReader', getMissingKeys(this.config as Record<string, unknown>, ['host', 'user', 'password']));\r\n }\r\n\r\n isConfigured(): boolean {\r\n return this.getConfigurationState().configured;\r\n }\r\n\r\n /** Opens the mailbox read-only, runs `work`, logs out whatever happens. */\r\n private async withMailbox<T>(work: (client: ImapClient, box: { uidValidity: string; lastUid: number }, modules: ImapModules) => Promise<T>): Promise<T> {\r\n const state = this.getConfigurationState();\r\n if (!state.configured) throw new EmailProviderError('not-configured', PROVIDER, state.reason ?? 'IMAP is not configured');\r\n const modules = await (this.options.modules ?? loadModules)();\r\n const client = new modules.ImapFlow({\r\n host: this.config.host,\r\n port: this.config.port ?? 993,\r\n secure: this.config.secure ?? true,\r\n auth: { user: this.config.user, pass: this.config.password },\r\n logger: false,\r\n socketTimeout: 30_000,\r\n });\r\n try {\r\n await client.connect();\r\n } catch (cause) {\r\n const authFailed = (cause as { authenticationFailed?: boolean } | null)?.authenticationFailed === true;\r\n throw new EmailProviderError(authFailed ? 'unauthorized' : 'unavailable', PROVIDER, authFailed ? 'The IMAP server refused the credentials' : 'The IMAP server did not answer', { cause });\r\n }\r\n try {\r\n const box = await client.mailboxOpen(this.config.mailbox ?? 'INBOX', { readOnly: true });\r\n return await work(client, { uidValidity: String(box.uidValidity), lastUid: Math.max(0, Number(box.uidNext) - 1) }, modules);\r\n } finally {\r\n await client.logout().catch(() => undefined);\r\n }\r\n }\r\n\r\n async start(): Promise<EmailReadStart> {\r\n return this.withMailbox(async (_client, box) => ({ cursor: cursorOf(box.uidValidity, box.lastUid) }));\r\n }\r\n\r\n async read(cursor: string, { limit = DEFAULT_EMAIL_READ_LIMIT }: EmailReadOptions = {}): Promise<EmailReadBatch> {\r\n return this.withMailbox(async (client, box, { simpleParser }) => {\r\n const from = parseCursor(cursor);\r\n if (!from || from.uidValidity !== box.uidValidity) return { messages: [], cursor: cursorOf(box.uidValidity, box.lastUid) };\r\n const messages: EmailMessage[] = [];\r\n let lastUid = from.lastUid;\r\n if (box.lastUid > from.lastUid) {\r\n for await (const item of client.fetch(`${from.lastUid + 1}:*`, { uid: true, source: true }, { uid: true })) {\r\n // `n:*` always returns the last message, even when it is older than n.\r\n if (item.uid <= from.lastUid || !item.source) continue;\r\n const mail = await simpleParser(item.source);\r\n const id = `${box.uidValidity}-${item.uid}`;\r\n const text = (mail.text ?? (typeof mail.html === 'string' ? mail.html.replace(/<[^>]*>/g, ' ').replace(/\\s+/g, ' ') : '')).trim();\r\n messages.push({\r\n id,\r\n threadId: mail.messageId ?? id,\r\n from: addresses(mail.from),\r\n to: addresses(mail.to),\r\n subject: mail.subject ?? '',\r\n date: (mail.date ?? new Date()).toISOString(),\r\n text,\r\n direction: 'inbound',\r\n cursor: cursorOf(box.uidValidity, item.uid),\r\n });\r\n lastUid = Math.max(lastUid, item.uid);\r\n if (messages.length >= limit) break;\r\n }\r\n }\r\n return { messages, cursor: cursorOf(box.uidValidity, lastUid) };\r\n });\r\n }\r\n}\r\n","// `@llmnative/react/server`: what a Node server needs: server-held AI credentials (CR-102), GitHub sign-in,\r\n// the email adapters (CR-130).\r\n// No React and no browser API: it runs in the app's own server or in the Vite dev proxy.\r\n\r\nimport { findServerCredentials, isAIProviderTarget, type ServerAIConnection } from './serverCredentials';\r\n\r\nexport { AI_PROVIDER_HOSTS, isAIProviderTarget, serverCredential, SERVER_CREDENTIAL_PREFIX } from './serverCredentials';\r\nexport type { ServerAIConnection } from './serverCredentials';\r\n// Sign-in with GitHub held by the app's server (CR-104): authorize URL, code exchange, profile, organizations.\r\nexport { createGitHubOAuth, GitHubOAuthError } from '../auth/github/githubOAuth';\r\nexport type { GitHubOAuth, GitHubOAuthConfig, GitHubOAuthOrganization, GitHubOAuthUser } from '../auth/github/githubOAuth';\r\n// Provider-agnostic identity of models (CR-103): pure, so a server or a generator can resolve them too.\r\nexport { canonicalModelName, buildModelIdentityIndex, resolveModel, modelOffers, loadModelIdentityIndex } from './modelIdentity';\r\nexport type { ModelIdentity, ModelIdentityEntry, ModelIdentityIndex, ResolvedModel, ModelOffer, ModelCost } from './modelIdentity';\r\n\r\n/** The connection of a provider as the server keeps it, key included. */\r\nexport type ServerAISecret = ServerAIConnection & { apiKey: string };\r\n\r\n/** The key of `provider` for `scope` (e.g. a company), or nothing when it is not connected. */\r\nexport type ServerCredentialLookup = (scope: string, provider: string) => ServerAISecret | undefined | Promise<ServerAISecret | undefined>;\r\n\r\nexport type ServerCredentialRequest = { url: string; headers: Record<string, string> };\r\n\r\nexport type ServerCredentialResolution =\r\n | { ok: true; url: string; headers: Record<string, string> }\r\n /** 404: the provider is not connected for that scope; 403: the target is not a host of that provider. */\r\n | { ok: false; status: 403 | 404; error: 'unknown-credential' | 'forbidden-target'; provider: string };\r\n\r\n/**\r\n * Swaps every server-credential placeholder of a proxied request (headers and URL) for the key it\r\n * stands for. The key only goes to a host of its provider: any other target is refused, so a\r\n * placeholder can never carry a key elsewhere. A request without placeholders passes unchanged.\r\n */\r\nexport async function resolveServerCredentials(request: ServerCredentialRequest, lookup: ServerCredentialLookup): Promise<ServerCredentialResolution> {\r\n const found = [request.url, ...Object.values(request.headers)].flatMap(findServerCredentials);\r\n if (found.length === 0) return { ok: true, url: request.url, headers: request.headers };\r\n\r\n const target = new URL(request.url);\r\n let { url } = request;\r\n let headers = { ...request.headers };\r\n const done = new Set<string>();\r\n for (const { placeholder, scope, provider } of found) {\r\n if (done.has(placeholder)) continue;\r\n done.add(placeholder);\r\n const secret = await lookup(scope, provider);\r\n if (!secret?.apiKey) return { ok: false, status: 404, error: 'unknown-credential', provider };\r\n if (!isAIProviderTarget({ ...secret, id: provider }, target)) return { ok: false, status: 403, error: 'forbidden-target', provider };\r\n url = url.split(placeholder).join(encodeURIComponent(secret.apiKey));\r\n headers = Object.fromEntries(Object.entries(headers).map(([name, value]) => [name, value.split(placeholder).join(secret.apiKey)]));\r\n }\r\n return { ok: true, url, headers };\r\n}\r\n\r\n// Email (CR-130): the adapters of `emailSend` and `emailRead` for a server, Gmail's OAuth and push. IMAP loads\r\n// the optional packages `imapflow` and `mailparser` only when it reads.\r\nexport { EmailProviderError } from '../email/EmailError';\r\nexport type { EmailProviderErrorCode } from '../email/EmailError';\r\nexport type { EmailSendAdapter, EmailSendParams, EmailSendResult, EmailAddress, EmailRecipient } from '../email/EmailSend';\r\nexport type { EmailReadAdapter, EmailMessage, EmailReadStart, EmailReadBatch, EmailReadOptions } from '../email/EmailRead';\r\nexport { EMAIL_SEND_PROVIDER_DEFINITIONS, EMAIL_READ_PROVIDER_DEFINITIONS } from '../email/definitions';\r\nexport type { EmailSendProviderId, EmailReadProviderId } from '../email/definitions';\r\nexport { ResendEmailSender } from '../email/resend/ResendEmailSender';\r\nexport type { ResendEmailSenderConfig } from '../email/resend/ResendEmailSender';\r\nexport { BrevoEmailSender } from '../email/brevo/BrevoEmailSender';\r\nexport type { BrevoEmailSenderConfig } from '../email/brevo/BrevoEmailSender';\r\nexport { GmailEmailSender } from '../email/gmail/GmailEmailSender';\r\nexport type { GmailEmailSenderConfig } from '../email/gmail/GmailEmailSender';\r\nexport { GmailEmailReader, decodeGmailPushNotification } from '../email/gmail/GmailEmailReader';\r\nexport type { GmailEmailReaderConfig } from '../email/gmail/GmailEmailReader';\r\nexport { createGmailOAuth } from '../email/gmail/gmailOAuth';\r\nexport type { GmailOAuth, GmailOAuthConfig } from '../email/gmail/gmailOAuth';\r\nexport { GMAIL_SCOPES } from '../email/gmail/gmailApi';\r\nexport type { GmailAuth } from '../email/gmail/gmailApi';\r\nexport { ImapEmailReader } from '../email/imap/ImapEmailReader';\r\nexport type { ImapEmailReaderConfig, ImapModules } from '../email/imap/ImapEmailReader';\r\n"],"mappings":"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"}
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./modelIdentity-CgRMrC5H.js"),t=require("./server-CCbjPJEz.js");exports.AI_PROVIDER_HOSTS=e.s,exports.GitHubOAuthError=t.n,exports.SERVER_CREDENTIAL_PREFIX=e.c,exports.buildModelIdentityIndex=e.t,exports.canonicalModelName=e.n,exports.createGitHubOAuth=t.r,exports.isAIProviderTarget=e.d,exports.loadModelIdentityIndex=e.r,exports.modelOffers=e.i,exports.resolveModel=e.a,exports.resolveServerCredentials=t.t,exports.serverCredential=e.f;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./modelIdentity-DX62i7g2.js"),t=require("./server-CDheNgME.js");exports.AI_PROVIDER_HOSTS=e.S,exports.BrevoEmailSender=e.o,exports.EMAIL_READ_PROVIDER_DEFINITIONS=e.c,exports.EMAIL_SEND_PROVIDER_DEFINITIONS=e.l,exports.EmailProviderError=e.y,exports.GMAIL_SCOPES=e.f,exports.GitHubOAuthError=t.o,exports.GmailEmailReader=t.i,exports.GmailEmailSender=e.u,exports.ImapEmailReader=t.n,exports.ResendEmailSender=e.s,exports.SERVER_CREDENTIAL_PREFIX=e.C,exports.buildModelIdentityIndex=e.t,exports.canonicalModelName=e.n,exports.createGitHubOAuth=t.s,exports.createGmailOAuth=t.r,exports.decodeGmailPushNotification=t.a,exports.isAIProviderTarget=e.E,exports.loadModelIdentityIndex=e.r,exports.modelOffers=e.i,exports.resolveModel=e.a,exports.resolveServerCredentials=t.t,exports.serverCredential=e.D;
package/dist/server.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { a as e, c as t, d as n, f as r, i, n as a, r as o, s, t as c } from "./modelIdentity-CGWliGDU.mjs";
2
- import { n as l, r as u, t as d } from "./server-CiWwr3Zg.mjs";
3
- export { s as AI_PROVIDER_HOSTS, l as GitHubOAuthError, t as SERVER_CREDENTIAL_PREFIX, c as buildModelIdentityIndex, a as canonicalModelName, u as createGitHubOAuth, n as isAIProviderTarget, o as loadModelIdentityIndex, i as modelOffers, e as resolveModel, d as resolveServerCredentials, r as serverCredential };
1
+ import { C as e, D as t, E as n, S as r, a as i, c as a, f as o, i as s, l as c, n as l, o as u, r as d, s as f, t as p, u as m, y as h } from "./modelIdentity-CIXNPtTA.mjs";
2
+ import { a as g, i as _, n as v, o as y, r as b, s as x, t as S } from "./server-B430eH0y.mjs";
3
+ export { r as AI_PROVIDER_HOSTS, u as BrevoEmailSender, a as EMAIL_READ_PROVIDER_DEFINITIONS, c as EMAIL_SEND_PROVIDER_DEFINITIONS, h as EmailProviderError, o as GMAIL_SCOPES, y as GitHubOAuthError, _ as GmailEmailReader, m as GmailEmailSender, v as ImapEmailReader, f as ResendEmailSender, e as SERVER_CREDENTIAL_PREFIX, p as buildModelIdentityIndex, l as canonicalModelName, x as createGitHubOAuth, b as createGmailOAuth, g as decodeGmailPushNotification, n as isAIProviderTarget, d as loadModelIdentityIndex, s as modelOffers, i as resolveModel, S as resolveServerCredentials, t as serverCredential };
@@ -6,7 +6,8 @@ import type { AIProviderAdapter } from "./providers/ai";
6
6
  import type { DataProviderAdapter } from "./providers/data/DataProvider";
7
7
  import type { StorageProviderAdapter } from "./providers/storage/StorageProvider";
8
8
  import type { AuthProviderAdapter } from "./providers/auth/AuthProvider";
9
- import type { EmailProviderAdapter } from "./providers/email/EmailProvider";
9
+ import type { EmailSendAdapter } from "./providers/email/EmailSend";
10
+ import type { EmailReadAdapter } from "./providers/email/EmailRead";
10
11
  import type { CredentialsAdapter } from "./providers/credentials/CredentialsProvider";
11
12
  import { type AppIconProviderConfig } from "./providers/icon/IconProviderContext";
12
13
  import type { GoogleMapsConfig } from "./providers/googleMaps/loadGoogleMaps";
@@ -47,7 +48,7 @@ export type AppProvidersConfig = {
47
48
  proxy?: ProxyConfig;
48
49
  /**
49
50
  * Pre-built adapter instances, registered directly rather than resolved from a
50
- * vendor config above. The 6 named categories are typed for convenience, but any
51
+ * vendor config above. The 7 named categories are typed for convenience, but any
51
52
  * other key works too — an entirely new category the framework has no built-in
52
53
  * knowledge of (e.g. `{ payments: { stripe: new StripeAdapter() } }`). Consume a
53
54
  * custom category with useProvider('payments', 'stripe') — see ProviderRegistryContext.
@@ -56,7 +57,8 @@ export type AppProvidersConfig = {
56
57
  data?: Record<string, DataProviderAdapter> | DataProviderAdapter;
57
58
  storage?: Record<string, StorageProviderAdapter> | StorageProviderAdapter;
58
59
  auth?: Record<string, AuthProviderAdapter> | AuthProviderAdapter;
59
- email?: Record<string, EmailProviderAdapter> | EmailProviderAdapter;
60
+ emailSend?: Record<string, EmailSendAdapter> | EmailSendAdapter;
61
+ emailRead?: Record<string, EmailReadAdapter> | EmailReadAdapter;
60
62
  ai?: Record<string, AIProviderAdapter> | AIProviderAdapter;
61
63
  credentials?: Record<string, CredentialsAdapter> | CredentialsAdapter;
62
64
  [category: string]: unknown;
@@ -127,7 +129,7 @@ export declare const menuTitleOf: (path: string) => string | undefined;
127
129
  *
128
130
  * Wraps children with: ErrorBoundary → BrowserRouter → RuntimeProvider →
129
131
  * AuthProvider → CredentialsProvider → DataProvider → StorageProvider →
130
- * EmailProvider → AIProvider → IconProvider → GoogleMapsProvider → HeadProvider →
132
+ * EmailSendProvider → EmailReadProvider → AIProvider → IconProvider → GoogleMapsProvider → HeadProvider →
131
133
  * I18nProvider → ThemeProvider → [contextProviders] → children.
132
134
  *
133
135
  * `contextProviders` runs inside DataProvider, so vertical-specific providers