@atomicmail/agent-skill
Advanced tools
| import { type JmapBlobUploadLimits } from "./agent-jmap-blob-limits.js"; | ||
| export type { JmapBlobUploadLimits } from "./agent-jmap-blob-limits.js"; | ||
| export declare const DEFAULT_JMAP_USING: readonly ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"]; | ||
| export declare const BUNDLED_OPS_PRESET_NAMES: readonly ["list_inbox.json", "reply.json", "send_mail.json", "send_mail_attachment.json", "send_mail_blob_attachment.json"]; | ||
| export declare const JMAP_MAIL_URN: "urn:ietf:params:jmap:mail"; | ||
| export declare const JMAP_BLOB_URN: "urn:ietf:params:jmap:blob"; | ||
| export interface JmapEnvelope { | ||
| using: string[]; | ||
| methodCalls: unknown[]; | ||
| } | ||
| export declare function parseJmapEnvelope(raw: string, defaultUsing: string[], source: string): JmapEnvelope; | ||
| export declare function extractPrimaryMailAccountId(session: Record<string, unknown>): string; | ||
| export interface JmapBlobEndpoints { | ||
| uploadUrl: string; | ||
| downloadUrl: string; | ||
| } | ||
| export declare function extractBlobEndpoints(session: Record<string, unknown>): JmapBlobEndpoints; | ||
| export declare function extractJmapApiUrl(session: Record<string, unknown>): string; | ||
| export declare function extractBlobUploadLimits(session: Record<string, unknown>, accountId: string): JmapBlobUploadLimits | null; | ||
| export declare function fetchJmapWellKnown(apiUrl: string, capabilityJwt: string): Promise<Record<string, unknown>>; | ||
| /** Integration JMAP session port (KeyValue-backed AgentSession). */ | ||
| export interface IntegrationJmapSessionPort { | ||
| readonly apiUrl: string; | ||
| getJmapPostUrl(): Promise<string>; | ||
| getPrimaryMailAccountId(): Promise<string>; | ||
| getCapabilityToken(): Promise<string>; | ||
| readonly currentInboxId?: string; | ||
| readonly currentUploadUrl?: string; | ||
| readonly currentDownloadUrl?: string; | ||
| getBlobUploadLimitsForAccount(accountId: string): Promise<JmapBlobUploadLimits | null>; | ||
| } | ||
| export interface RunJmapRequestInput { | ||
| session: IntegrationJmapSessionPort; | ||
| opsJson: string; | ||
| defaultUsing: string[]; | ||
| sourceLabel: string; | ||
| dryRun?: boolean; | ||
| vars?: Record<string, string>; | ||
| } | ||
| export declare function runJmapRequest(input: RunJmapRequestInput): Promise<{ | ||
| ok: boolean; | ||
| status: number; | ||
| bodyText: string; | ||
| }>; | ||
| export declare function fetchInboxMailboxId(port: IntegrationJmapSessionPort): Promise<string>; | ||
| export declare function postJmap(jmapPostUrl: string, capabilityJwt: string, envelope: JmapEnvelope): Promise<{ | ||
| ok: boolean; | ||
| status: number; | ||
| bodyText: string; | ||
| }>; | ||
| export declare function attachJmapNextHints(bodyText: string): string; | ||
| //# sourceMappingURL=agent-jmap-run.d.ts.map |
| {"version":3,"file":"agent-jmap-run.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/jmap/agent-jmap-run.ts"],"names":[],"mappings":"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"} |
| // JMAP execution for integration hosts (n8n bundle) — fetch-only, no node:fs. | ||
| import { JMAP_NEXT_HINTS } from "../../core/jmap-hints.js"; | ||
| import { inboxIdToMailboxEmail } from "../session/inbox-id-to-mailbox-email.js"; | ||
| import { assertBlobUploadEnvelopeWithinLimits, } from "./agent-jmap-blob-limits.js"; | ||
| import { ensureTextCharsetOnEmailSetBlobParts } from "./agent-jmap-email-charset.js"; | ||
| import { substituteVars } from "./agent-vars.js"; | ||
| export const DEFAULT_JMAP_USING = [ | ||
| "urn:ietf:params:jmap:core", | ||
| "urn:ietf:params:jmap:mail", | ||
| ]; | ||
| export const BUNDLED_OPS_PRESET_NAMES = [ | ||
| "list_inbox.json", | ||
| "reply.json", | ||
| "send_mail.json", | ||
| "send_mail_attachment.json", | ||
| "send_mail_blob_attachment.json", | ||
| ]; | ||
| export const JMAP_MAIL_URN = "urn:ietf:params:jmap:mail"; | ||
| export const JMAP_BLOB_URN = "urn:ietf:params:jmap:blob"; | ||
| export function parseJmapEnvelope(raw, defaultUsing, source) { | ||
| let value; | ||
| try { | ||
| value = JSON.parse(raw); | ||
| } | ||
| catch (err) { | ||
| throw new Error(`${source} is not valid JSON: ${err.message}`); | ||
| } | ||
| if (Array.isArray(value)) { | ||
| return { using: [...defaultUsing], methodCalls: value }; | ||
| } | ||
| if (value !== null && | ||
| typeof value === "object" && | ||
| Array.isArray(value.methodCalls)) { | ||
| const obj = value; | ||
| const using = Array.isArray(obj.using) | ||
| ? obj.using.filter((u) => typeof u === "string") | ||
| : [...defaultUsing]; | ||
| return { using, methodCalls: obj.methodCalls }; | ||
| } | ||
| throw new Error(`${source} must be a methodCalls array, e.g. ` + | ||
| '[["Mailbox/get",{...},"m0"]], or an object with a methodCalls array.'); | ||
| } | ||
| export function extractPrimaryMailAccountId(session) { | ||
| const primary = session["primaryAccounts"]; | ||
| if (!primary || typeof primary !== "object") { | ||
| throw new Error("JMAP session missing primaryAccounts."); | ||
| } | ||
| const id = primary[JMAP_MAIL_URN]; | ||
| if (typeof id !== "string" || id.length === 0) { | ||
| throw new Error(`JMAP session missing primaryAccounts['${JMAP_MAIL_URN}'].`); | ||
| } | ||
| return id; | ||
| } | ||
| export function extractBlobEndpoints(session) { | ||
| const uploadUrl = session["uploadUrl"]; | ||
| const downloadUrl = session["downloadUrl"]; | ||
| if (typeof uploadUrl !== "string" || uploadUrl.length === 0) { | ||
| throw new Error("JMAP session missing uploadUrl."); | ||
| } | ||
| if (typeof downloadUrl !== "string" || downloadUrl.length === 0) { | ||
| throw new Error("JMAP session missing downloadUrl."); | ||
| } | ||
| return { uploadUrl, downloadUrl }; | ||
| } | ||
| export function extractJmapApiUrl(session) { | ||
| const u = session["apiUrl"]; | ||
| if (typeof u !== "string" || u.length === 0) { | ||
| throw new Error("JMAP session missing apiUrl."); | ||
| } | ||
| return u; | ||
| } | ||
| function asNonNegativeInt(v) { | ||
| if (typeof v !== "number" || !Number.isFinite(v)) | ||
| return undefined; | ||
| if (!Number.isInteger(v) || v < 0 || v > Number.MAX_SAFE_INTEGER) { | ||
| return undefined; | ||
| } | ||
| return v; | ||
| } | ||
| export function extractBlobUploadLimits(session, accountId) { | ||
| const accounts = session["accounts"]; | ||
| if (!accounts || typeof accounts !== "object") | ||
| return null; | ||
| const acc = accounts[accountId]; | ||
| if (!acc || typeof acc !== "object") | ||
| return null; | ||
| const caps = acc["accountCapabilities"]; | ||
| if (!caps || typeof caps !== "object") | ||
| return null; | ||
| const blob = caps[JMAP_BLOB_URN]; | ||
| if (!blob || typeof blob !== "object") | ||
| return null; | ||
| const b = blob; | ||
| let maxSizeBlobSet = null; | ||
| const rawMax = b["maxSizeBlobSet"]; | ||
| if (rawMax === null) { | ||
| maxSizeBlobSet = null; | ||
| } | ||
| else { | ||
| const n = asNonNegativeInt(rawMax); | ||
| maxSizeBlobSet = n === undefined ? null : n; | ||
| } | ||
| const maxDs = asNonNegativeInt(b["maxDataSources"]); | ||
| const out = { maxSizeBlobSet }; | ||
| if (maxDs !== undefined) { | ||
| out.maxDataSources = maxDs; | ||
| } | ||
| return out; | ||
| } | ||
| export async function fetchJmapWellKnown(apiUrl, capabilityJwt) { | ||
| const base = apiUrl.replace(/\/+$/, ""); | ||
| const res = await fetch(`${base}/.well-known/jmap`, { | ||
| headers: { Authorization: `Bearer ${capabilityJwt}` }, | ||
| }); | ||
| const text = await res.text(); | ||
| if (!res.ok) { | ||
| throw new Error(`JMAP session fetch failed (HTTP ${res.status}): ${text}`); | ||
| } | ||
| try { | ||
| return JSON.parse(text); | ||
| } | ||
| catch { | ||
| throw new Error("JMAP session response is not valid JSON."); | ||
| } | ||
| } | ||
| export async function runJmapRequest(input) { | ||
| const mergedVars = input.vars ?? {}; | ||
| const { text: raw } = await substituteVars({ | ||
| raw: input.opsJson, | ||
| vars: mergedVars, | ||
| autoResolvers: { | ||
| ACCOUNT_ID: () => input.session.getPrimaryMailAccountId(), | ||
| INBOX: async () => { | ||
| const rawInbox = input.session.currentInboxId; | ||
| if (!rawInbox) { | ||
| throw new Error("No inbox in session; run register first."); | ||
| } | ||
| return inboxIdToMailboxEmail(rawInbox); | ||
| }, | ||
| INBOX_MAILBOX_ID: () => fetchInboxMailboxId(input.session), | ||
| UPLOAD_URL: async () => { | ||
| if (input.session.currentUploadUrl) { | ||
| return input.session.currentUploadUrl; | ||
| } | ||
| throw new Error("JMAP session missing uploadUrl."); | ||
| }, | ||
| DOWNLOAD_URL: async () => { | ||
| if (input.session.currentDownloadUrl) { | ||
| return input.session.currentDownloadUrl; | ||
| } | ||
| throw new Error("JMAP session missing downloadUrl."); | ||
| }, | ||
| }, | ||
| }); | ||
| const envelope = parseJmapEnvelope(raw, input.defaultUsing, input.sourceLabel); | ||
| ensureTextCharsetOnEmailSetBlobParts(envelope); | ||
| await enforceJmapBlobUploadLimitsIfApplicable(input.session, envelope); | ||
| const jmapPostUrl = await input.session.getJmapPostUrl(); | ||
| if (input.dryRun) { | ||
| return { | ||
| ok: true, | ||
| status: 200, | ||
| bodyText: JSON.stringify({ dryRun: true, url: jmapPostUrl, envelope }, null, 2), | ||
| }; | ||
| } | ||
| const capabilityJwt = await input.session.getCapabilityToken(); | ||
| const { ok, status, bodyText } = await postJmap(jmapPostUrl, capabilityJwt, envelope); | ||
| if (!ok) { | ||
| return { ok, status, bodyText }; | ||
| } | ||
| return { ok, status, bodyText: attachJmapNextHints(bodyText) }; | ||
| } | ||
| export async function fetchInboxMailboxId(port) { | ||
| const accountId = await port.getPrimaryMailAccountId(); | ||
| const capabilityJwt = await port.getCapabilityToken(); | ||
| const envelope = { | ||
| using: ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], | ||
| methodCalls: [ | ||
| ["Mailbox/query", { accountId, filter: { role: "inbox" } }, "mq0"], | ||
| ], | ||
| }; | ||
| const jmapPostUrl = await port.getJmapPostUrl(); | ||
| const { ok, status, bodyText } = await postJmap(jmapPostUrl, capabilityJwt, envelope); | ||
| if (!ok) { | ||
| throw new Error(`Mailbox/query failed (HTTP ${status}): ${bodyText}`); | ||
| } | ||
| let parsed; | ||
| try { | ||
| parsed = JSON.parse(bodyText); | ||
| } | ||
| catch { | ||
| throw new Error("Mailbox/query response is not valid JSON."); | ||
| } | ||
| const responses = parsed | ||
| .methodResponses; | ||
| const first = responses?.[0]; | ||
| if (!Array.isArray(first) || first[0] === "error") { | ||
| throw new Error(`Mailbox/query failed: ${bodyText}`); | ||
| } | ||
| if (first[0] !== "Mailbox/query") { | ||
| throw new Error(`Mailbox/query failed: ${bodyText}`); | ||
| } | ||
| const payload = first[1]; | ||
| const id = payload.ids?.[0]; | ||
| if (typeof id !== "string" || id.length === 0) { | ||
| throw new Error("Mailbox/query returned no inbox mailbox id."); | ||
| } | ||
| return id; | ||
| } | ||
| function collectBlobUploadAccountIds(envelope) { | ||
| const ids = new Set(); | ||
| for (const call of envelope.methodCalls) { | ||
| if (!Array.isArray(call) || call[0] !== "Blob/upload") | ||
| continue; | ||
| const arg = call[1]; | ||
| if (!arg || typeof arg !== "object") | ||
| continue; | ||
| const aid = arg["accountId"]; | ||
| if (typeof aid === "string" && aid.length > 0) | ||
| ids.add(aid); | ||
| } | ||
| return [...ids]; | ||
| } | ||
| async function enforceJmapBlobUploadLimitsIfApplicable(session, envelope) { | ||
| if (!envelope.using.includes(JMAP_BLOB_URN)) | ||
| return; | ||
| const hasUpload = envelope.methodCalls.some((c) => Array.isArray(c) && c[0] === "Blob/upload"); | ||
| if (!hasUpload) | ||
| return; | ||
| const accountIds = collectBlobUploadAccountIds(envelope); | ||
| const limitsByAccount = new Map(); | ||
| for (const id of accountIds) { | ||
| limitsByAccount.set(id, await session.getBlobUploadLimitsForAccount(id)); | ||
| } | ||
| assertBlobUploadEnvelopeWithinLimits(envelope, limitsByAccount); | ||
| } | ||
| export async function postJmap(jmapPostUrl, capabilityJwt, envelope) { | ||
| const res = await fetch(jmapPostUrl, { | ||
| method: "POST", | ||
| headers: { | ||
| "Content-Type": "application/json", | ||
| Authorization: `Bearer ${capabilityJwt}`, | ||
| }, | ||
| body: JSON.stringify(envelope), | ||
| }); | ||
| const bodyText = await res.text(); | ||
| return { ok: res.ok, status: res.status, bodyText }; | ||
| } | ||
| export function attachJmapNextHints(bodyText) { | ||
| try { | ||
| const obj = JSON.parse(bodyText); | ||
| if (obj && typeof obj === "object" && !Array.isArray(obj)) { | ||
| return JSON.stringify({ ...obj, _next: [...JMAP_NEXT_HINTS] }, null, 2); | ||
| } | ||
| } | ||
| catch { | ||
| // not JSON | ||
| } | ||
| return bodyText; | ||
| } |
| /** Static JMAP success hints (no shared/ filesystem reads). */ | ||
| export declare const JMAP_NEXT_HINTS: readonly ["Use jmap_request with Mailbox/get or Email/query to work with mail data.", "Use presets with $VAR placeholders — $ACCOUNT_ID, $INBOX, and $INBOX_MAILBOX_ID come from the session; pass others via vars / --vars.", "Call help for the JMAP cheatsheet and troubleshooting."]; | ||
| //# sourceMappingURL=jmap-hints.d.ts.map |
| {"version":3,"file":"jmap-hints.d.ts","sourceRoot":"","sources":["../../../src/lib/core/jmap-hints.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,eAAO,MAAM,eAAe,0RAIlB,CAAC"} |
| /** Static JMAP success hints (no shared/ filesystem reads). */ | ||
| export const JMAP_NEXT_HINTS = [ | ||
| "Use jmap_request with Mailbox/get or Email/query to work with mail data.", | ||
| "Use presets with $VAR placeholders — $ACCOUNT_ID, $INBOX, and $INBOX_MAILBOX_ID come from the session; pass others via vars / --vars.", | ||
| "Call help for the JMAP cheatsheet and troubleshooting.", | ||
| ]; |
| // Stateful PoW + capability JWT + optional cached JMAP session (accountId). | ||
| import { FilesystemCredentialStore, writeCredentials, writeJwtFile, } from "./agent-credentials-store.js"; | ||
| import { CAPABILITY_SAFETY_MARGIN_MS, decodeJwtPayload, isJwtExpired, SESSION_SAFETY_MARGIN_MS, } from "../auth/agent-jwt.js"; | ||
| import { extractBlobEndpoints, extractBlobUploadLimits, extractJmapApiUrl, extractPrimaryMailAccountId, fetchJmapWellKnown, } from "../jmap/agent-jmap.js"; | ||
| import { extractBlobEndpoints, extractBlobUploadLimits, extractJmapApiUrl, extractPrimaryMailAccountId, fetchJmapWellKnown, } from "../jmap/agent-jmap-run.js"; | ||
| import { fetchCapability, performPoWAndSession, } from "../auth/agent-auth-http.js"; | ||
@@ -6,0 +6,0 @@ function normalizeUsername(u) { |
@@ -1,2 +0,2 @@ | ||
| /** Subset of `process.env` read for `$INBOX` normalization (tests may pass a stub). */ | ||
| /** Optional inbox domain override for `$INBOX` normalization. */ | ||
| export type InboxEmailEnv = { | ||
@@ -3,0 +3,0 @@ ATOMIC_MAIL_INBOX_DOMAIN?: string; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"inbox-id-to-mailbox-email.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/session/inbox-id-to-mailbox-email.ts"],"names":[],"mappings":"AAEA,uFAAuF;AACvF,MAAM,MAAM,aAAa,GAAG;IAAE,wBAAwB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAYlE,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,aAAa,GAClB,MAAM,CAaR"} | ||
| {"version":3,"file":"inbox-id-to-mailbox-email.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/session/inbox-id-to-mailbox-email.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,MAAM,MAAM,aAAa,GAAG;IAAE,wBAAwB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAYlE,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,aAAa,GAClB,MAAM,CAWR"} |
@@ -1,2 +0,1 @@ | ||
| import process from "node:process"; | ||
| /** | ||
@@ -7,4 +6,4 @@ * Normalizes stored `inboxId` into an RFC5322 mailbox address for `$INBOX` | ||
| * Credentials may store only the local-part (`alice`); production mailboxes | ||
| * live at `alice@atomicmail.ai`. Custom stacks can set | ||
| * `ATOMIC_MAIL_INBOX_DOMAIN` (hostname only, optional leading `@` stripped). | ||
| * live at `alice@atomicmail.ai`. Pass `ATOMIC_MAIL_INBOX_DOMAIN` via `env` | ||
| * when not using the default domain. | ||
| */ | ||
@@ -18,5 +17,3 @@ const DEFAULT_INBOX_DOMAIN = "atomicmail.ai"; | ||
| return trimmed; | ||
| const raw = (env !== undefined | ||
| ? env.ATOMIC_MAIL_INBOX_DOMAIN | ||
| : process.env.ATOMIC_MAIL_INBOX_DOMAIN)?.trim(); | ||
| const raw = env?.ATOMIC_MAIL_INBOX_DOMAIN?.trim(); | ||
| const domain = raw && raw.length > 0 | ||
@@ -23,0 +20,0 @@ ? raw.replace(/^@+/, "") |
+1
-1
| { | ||
| "name": "@atomicmail/agent-skill", | ||
| "version": "0.3.17-rc2", | ||
| "version": "0.3.17-rc3", | ||
| "description": "Atomic Mail AgentSkill — register, jmap_request, and help CLI for AI agents.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
300574
5.31%154
4.05%5373
6.27%34
-2.86%11
22.22%