@atomicmail/mcp 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +200 -84
- package/esm/_dnt.polyfills.d.ts +101 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +127 -0
- package/esm/lib/agent/auth/agent-auth-http.d.ts.map +1 -0
- package/esm/lib/agent/auth/agent-auth-http.js +85 -0
- package/esm/lib/{src → agent/auth}/agent-jwt.d.ts +0 -2
- package/esm/lib/agent/auth/agent-jwt.d.ts.map +1 -0
- package/esm/lib/{src → agent/auth}/agent-jwt.js +0 -2
- package/esm/lib/agent/auth/agent-pow.d.ts.map +1 -0
- package/esm/lib/{src → agent/jmap}/agent-help-content.d.ts +1 -0
- package/esm/lib/agent/jmap/agent-help-content.d.ts.map +1 -0
- package/esm/lib/{src → agent/jmap}/agent-help-content.js +46 -19
- package/esm/lib/{src → agent/jmap}/agent-jmap.d.ts +7 -0
- package/esm/lib/agent/jmap/agent-jmap.d.ts.map +1 -0
- package/esm/lib/{src → agent/jmap}/agent-jmap.js +63 -3
- package/esm/lib/agent/jmap/agent-vars.d.ts.map +1 -0
- package/esm/lib/{src → agent/session}/agent-credentials-store.d.ts +2 -0
- package/esm/lib/agent/session/agent-credentials-store.d.ts.map +1 -0
- package/esm/lib/{src → agent/session}/agent-credentials-store.js +2 -0
- package/esm/lib/agent/session/agent-resolve-config.d.ts.map +1 -0
- package/esm/lib/{src → agent/session}/agent-resolve-config.js +1 -1
- package/esm/lib/{src → agent/session}/agent-session.d.ts +5 -0
- package/esm/lib/agent/session/agent-session.d.ts.map +1 -0
- package/esm/lib/{src → agent/session}/agent-session.js +46 -10
- package/esm/lib/core/consts.d.ts.map +1 -0
- package/esm/lib/core/read-npm-package-readme.d.ts +6 -0
- package/esm/lib/core/read-npm-package-readme.d.ts.map +1 -0
- package/esm/lib/core/read-npm-package-readme.js +66 -0
- package/esm/lib/core/types.d.ts +2 -0
- package/esm/lib/core/types.d.ts.map +1 -0
- package/esm/lib/core/types.js +1 -0
- package/esm/lib/core/utils.d.ts +10 -0
- package/esm/lib/core/utils.d.ts.map +1 -0
- package/esm/lib/core/utils.js +28 -0
- package/esm/lib/mod.d.ts +15 -0
- package/esm/lib/mod.d.ts.map +1 -0
- package/esm/lib/mod.js +14 -0
- package/esm/lib/network/auth-client.d.ts +57 -0
- package/esm/lib/network/auth-client.d.ts.map +1 -0
- package/esm/lib/network/auth-client.js +211 -0
- package/esm/mcp/main.d.ts +3 -0
- package/esm/mcp/main.d.ts.map +1 -0
- package/esm/mcp/{src/main.js → main.js} +4 -3
- package/esm/mcp/tools/help.d.ts.map +1 -0
- package/esm/mcp/tools/help.js +45 -0
- package/esm/mcp/{src/tools → tools}/jmap.d.ts +1 -1
- package/esm/mcp/tools/jmap.d.ts.map +1 -0
- package/esm/mcp/{src/tools → tools}/jmap.js +5 -4
- package/esm/mcp/{src/tools → tools}/register.d.ts +1 -1
- package/esm/mcp/tools/register.d.ts.map +1 -0
- package/package.json +5 -5
- package/presets/list_inbox.json +39 -0
- package/presets/reply.json +75 -0
- package/presets/send_mail.json +42 -0
- package/esm/lib/src/agent-auth-http.d.ts.map +0 -1
- package/esm/lib/src/agent-auth-http.js +0 -76
- package/esm/lib/src/agent-credentials-store.d.ts.map +0 -1
- package/esm/lib/src/agent-help-content.d.ts.map +0 -1
- package/esm/lib/src/agent-jmap.d.ts.map +0 -1
- package/esm/lib/src/agent-jwt.d.ts.map +0 -1
- package/esm/lib/src/agent-pow.d.ts.map +0 -1
- package/esm/lib/src/agent-resolve-config.d.ts.map +0 -1
- package/esm/lib/src/agent-session.d.ts.map +0 -1
- package/esm/lib/src/agent-vars.d.ts.map +0 -1
- package/esm/lib/src/consts.d.ts.map +0 -1
- package/esm/mcp/src/main.d.ts +0 -3
- package/esm/mcp/src/main.d.ts.map +0 -1
- package/esm/mcp/src/tools/help.d.ts.map +0 -1
- package/esm/mcp/src/tools/help.js +0 -22
- package/esm/mcp/src/tools/jmap.d.ts.map +0 -1
- package/esm/mcp/src/tools/register.d.ts.map +0 -1
- /package/esm/lib/{src → agent/auth}/agent-auth-http.d.ts +0 -0
- /package/esm/lib/{src → agent/auth}/agent-pow.d.ts +0 -0
- /package/esm/lib/{src → agent/auth}/agent-pow.js +0 -0
- /package/esm/lib/{src → agent/jmap}/agent-vars.d.ts +0 -0
- /package/esm/lib/{src → agent/jmap}/agent-vars.js +0 -0
- /package/esm/lib/{src → agent/session}/agent-resolve-config.d.ts +0 -0
- /package/esm/lib/{src → core}/consts.d.ts +0 -0
- /package/esm/lib/{src → core}/consts.js +0 -0
- /package/esm/mcp/{src/tools → tools}/help.d.ts +0 -0
- /package/esm/mcp/{src/tools → tools}/register.js +0 -0
|
@@ -16,10 +16,12 @@ Three operations only:
|
|
|
16
16
|
2. **jmap_request** — Send a JMAP method-call batch. Auth and JWT rotation are
|
|
17
17
|
automatic. Pass inline \`ops\` JSON or an \`ops_file\` preset path (same
|
|
18
18
|
substitution applies to both). Uppercase tokens like \`$ACCOUNT_ID\`,
|
|
19
|
-
\`$INBOX\`, \`$TO\`, \`$SUBJECT\` are
|
|
20
|
-
\`$ACCOUNT_ID\` / \`$INBOX\`
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
\`$INBOX\`, \`$UPLOAD_URL\`, \`$DOWNLOAD_URL\`, \`$TO\`, \`$SUBJECT\` are
|
|
20
|
+
replaced before the request is sent. \`$ACCOUNT_ID\` / \`$INBOX\` /
|
|
21
|
+
\`$UPLOAD_URL\` / \`$DOWNLOAD_URL\` come from the JMAP session and
|
|
22
|
+
credentials; pass any other names via MCP \`vars\` or skill \`--vars\`.
|
|
23
|
+
3. **help** — This documentation (optional \`topic\` / \`--topic\`), or the
|
|
24
|
+
published package README (\`topic\` / \`--topic\` \`readme\`).
|
|
23
25
|
|
|
24
26
|
## Typical workflow
|
|
25
27
|
|
|
@@ -29,7 +31,7 @@ Three operations only:
|
|
|
29
31
|
3. If stuck, read error hints and call \`help\`.
|
|
30
32
|
|
|
31
33
|
Available topics: overview, installation, auth, jmap_cheatsheet, tools,
|
|
32
|
-
presets, troubleshooting
|
|
34
|
+
presets, troubleshooting. Use \`readme\` for the npm package \`README.md\`.`,
|
|
33
35
|
installation: `\
|
|
34
36
|
# Atomic Mail — Installation
|
|
35
37
|
|
|
@@ -51,7 +53,8 @@ presets, troubleshooting.`,
|
|
|
51
53
|
\`\`\`bash
|
|
52
54
|
npx --package=@atomicmail/agent-skill atomicmail register --username "myagent"
|
|
53
55
|
npx --package=@atomicmail/agent-skill atomicmail jmap_request \\
|
|
54
|
-
--ops-file
|
|
56
|
+
--ops-file list_inbox.json \\
|
|
57
|
+
--vars '{"COUNT":"10"}'
|
|
55
58
|
npx --package=@atomicmail/agent-skill atomicmail help
|
|
56
59
|
\`\`\`
|
|
57
60
|
|
|
@@ -85,18 +88,22 @@ See each package README for details.`,
|
|
|
85
88
|
Auth is automatic after \`register\` (or when \`credentials.json\` + API key
|
|
86
89
|
exist).
|
|
87
90
|
|
|
88
|
-
1. **Challenge** — \`POST /api/v1/challenge
|
|
91
|
+
1. **Challenge** — \`POST /api/v1/challenge\`, read challenge JWT from
|
|
92
|
+
\`Authorization: Bearer <challengeJWT>\`
|
|
89
93
|
2. **Proof-of-work** — scrypt until difficulty satisfied
|
|
90
|
-
3. **Session JWT** — \`POST /api/v1/session\`
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
3. **Session JWT** — \`POST /api/v1/session\` with challenge JWT in
|
|
95
|
+
\`Authorization: Bearer ...\` and PoW fields (\`powHex\`, \`nonce\`) in JSON
|
|
96
|
+
body; read session JWT from response \`Authorization: Bearer ...\` (1h TTL);
|
|
97
|
+
signup returns \`apiKey\` once
|
|
98
|
+
4. **Capability JWT** — \`POST /api/v1/capability\` with session JWT in
|
|
99
|
+
\`Authorization: Bearer ...\`; read capability JWT from response
|
|
100
|
+
\`Authorization: Bearer ...\` (2 min TTL) used as the JMAP bearer
|
|
94
101
|
|
|
95
102
|
JWTs are rotated before expiry and written back to disk.
|
|
96
103
|
|
|
97
104
|
## Credential files (mode 0600)
|
|
98
105
|
|
|
99
|
-
\`credentials.json\` — \`{ apiKey, inboxId, authUrl, apiUrl, scryptSalt }\`
|
|
106
|
+
\`credentials.json\` — \`{ apiKey, inboxId, authUrl, apiUrl, scryptSalt, uploadUrl, downloadUrl }\`
|
|
100
107
|
\`session.jwt\` — session token
|
|
101
108
|
\`capability.jwt\` — capability token
|
|
102
109
|
|
|
@@ -118,7 +125,8 @@ JWTs are rotated before expiry and written back to disk.
|
|
|
118
125
|
|
|
119
126
|
## Examples
|
|
120
127
|
|
|
121
|
-
Use \`$ACCOUNT_ID
|
|
128
|
+
Use \`$ACCOUNT_ID\`, \`$INBOX\`, \`$UPLOAD_URL\`, and \`$DOWNLOAD_URL\` for
|
|
129
|
+
session fields; use \`$TO\`, \`$SUBJECT\`,
|
|
122
130
|
etc., and supply values via MCP \`vars\` or \`--vars\` (JSON object of strings).
|
|
123
131
|
|
|
124
132
|
### Mailboxes
|
|
@@ -173,15 +181,23 @@ replaces credentials in the directory and registers a new inbox.
|
|
|
173
181
|
**Skill:** \`help [--topic TOPIC]\`
|
|
174
182
|
|
|
175
183
|
Topics: overview, installation, auth, jmap_cheatsheet, tools, presets,
|
|
176
|
-
troubleshooting
|
|
184
|
+
troubleshooting. Topic \`readme\` prints the published package \`README.md\`
|
|
185
|
+
(same layout as npm; requires install from npm).`,
|
|
177
186
|
presets: `\
|
|
178
187
|
# JMAP presets
|
|
179
188
|
|
|
180
189
|
Save a method-call array or a full \`{ "using", "methodCalls" }\` envelope
|
|
181
190
|
as JSON, then pass \`ops_file\` (MCP) or \`--ops-file\` (skill).
|
|
182
191
|
|
|
183
|
-
Relative paths resolve against the credential directory (MCP) or current
|
|
184
|
-
\`--credentials-dir\` (skill).
|
|
192
|
+
Relative paths first resolve against the credential directory (MCP) or current
|
|
193
|
+
\`--credentials-dir\` (skill). If not found, the runtime falls back to bundled
|
|
194
|
+
presets that ship in both npm packages.
|
|
195
|
+
|
|
196
|
+
## Bundled presets
|
|
197
|
+
|
|
198
|
+
- \`send_mail.json\` — sends one email using \`$TO\`, \`$SUBJECT\`, \`$BODY\`.
|
|
199
|
+
- \`list_inbox.json\` — returns the latest \`$COUNT\` inbox messages.
|
|
200
|
+
- \`reply.json\` — replies in-thread using \`$MAIL_ID\` and \`$BODY\`.
|
|
185
201
|
|
|
186
202
|
## Placeholders
|
|
187
203
|
|
|
@@ -191,11 +207,14 @@ keywords like \`$draft\` stay untouched).
|
|
|
191
207
|
- \`$ACCOUNT_ID\` — primary mail account id (from \`GET /.well-known/jmap\` when
|
|
192
208
|
referenced).
|
|
193
209
|
- \`$INBOX\` — inbox email address from credentials.
|
|
210
|
+
- \`$UPLOAD_URL\` — RFC 8620 upload URL template from JMAP session.
|
|
211
|
+
- \`$DOWNLOAD_URL\` — RFC 8620 download URL template from JMAP session.
|
|
194
212
|
- Any other \`$FOO\` — must appear in MCP \`vars\` or skill \`--vars\` as
|
|
195
213
|
\`"FOO": "..."\` (string values only; JSON escaping in the preset body is your
|
|
196
214
|
responsibility).
|
|
197
215
|
|
|
198
|
-
You may override \`ACCOUNT_ID\` / \`INBOX\`
|
|
216
|
+
You may override \`ACCOUNT_ID\` / \`INBOX\` / \`UPLOAD_URL\` / \`DOWNLOAD_URL\`
|
|
217
|
+
via \`vars\` / \`--vars\` if needed.`,
|
|
199
218
|
troubleshooting: `\
|
|
200
219
|
# Troubleshooting
|
|
201
220
|
|
|
@@ -226,11 +245,19 @@ Pass every custom placeholder in MCP \`vars\` or \`--vars\` as a JSON object of
|
|
|
226
245
|
strings. Ensure \`register\` completed so \`$ACCOUNT_ID\` / \`$INBOX\` can resolve.`,
|
|
227
246
|
};
|
|
228
247
|
export const HELP_TOPIC_LIST = Object.keys(HELP_TOPICS);
|
|
248
|
+
export function normalizeHelpTopic(topic) {
|
|
249
|
+
return topic.toLowerCase().replace(/[\s-]/g, "_");
|
|
250
|
+
}
|
|
229
251
|
export function getHelp(topic) {
|
|
230
252
|
if (!topic) {
|
|
231
253
|
return HELP_TOPICS["overview"];
|
|
232
254
|
}
|
|
233
|
-
const key = topic
|
|
255
|
+
const key = normalizeHelpTopic(topic);
|
|
256
|
+
if (key === "readme") {
|
|
257
|
+
return ("Topic \"readme\" prints the package README.md from the npm install. " +
|
|
258
|
+
"From MCP use {\"topic\":\"readme\"}; from the CLI: " +
|
|
259
|
+
"`atomicmail help --topic readme`.");
|
|
260
|
+
}
|
|
234
261
|
return (HELP_TOPICS[key] ??
|
|
235
|
-
`Unknown topic "${topic}". Available topics: ${HELP_TOPIC_LIST.join(", ")}`);
|
|
262
|
+
`Unknown topic "${topic}". Available topics: ${HELP_TOPIC_LIST.join(", ")}, readme`);
|
|
236
263
|
}
|
|
@@ -8,6 +8,11 @@ export declare function parseJmapEnvelope(raw: string, defaultUsing: string[], s
|
|
|
8
8
|
export declare function resolveOpsFilePath(credentialDir: string, opsFile: string): string;
|
|
9
9
|
export declare function readOpsFile(credentialDir: string, opsFile: string): Promise<string>;
|
|
10
10
|
export declare function extractPrimaryMailAccountId(session: Record<string, unknown>): string;
|
|
11
|
+
export interface JmapBlobEndpoints {
|
|
12
|
+
uploadUrl: string;
|
|
13
|
+
downloadUrl: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function extractBlobEndpoints(session: Record<string, unknown>): JmapBlobEndpoints;
|
|
11
16
|
export declare function fetchJmapWellKnown(apiUrl: string, capabilityJwt: string): Promise<Record<string, unknown>>;
|
|
12
17
|
/** Minimal surface for JMAP execution (implemented by AgentSession). */
|
|
13
18
|
export interface JmapSessionPort {
|
|
@@ -18,6 +23,8 @@ export interface JmapSessionPort {
|
|
|
18
23
|
getPrimaryMailAccountId(): Promise<string>;
|
|
19
24
|
getCapabilityToken(): Promise<string>;
|
|
20
25
|
readonly currentInboxId?: string;
|
|
26
|
+
readonly currentUploadUrl?: string;
|
|
27
|
+
readonly currentDownloadUrl?: string;
|
|
21
28
|
}
|
|
22
29
|
export interface RunJmapRequestInput {
|
|
23
30
|
session: JmapSessionPort;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-jmap.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/jmap/agent-jmap.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,kBAAkB,qEAGrB,CAAC;AAEX,eAAO,MAAM,aAAa,EAAG,2BAAoC,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,OAAO,EAAE,CAAC;CACxB;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EAAE,EACtB,MAAM,EAAE,MAAM,GACb,YAAY,CAyBd;AAED,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED,wBAAsB,WAAW,CAC/B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAiBjB;AA8CD,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,MAAM,CAcR;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,iBAAiB,CAUnB;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAclC;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE;QAAE,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3C,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,eAAe,CAAC;IACzB,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wFAAwF;IACxF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAmD5D;AAED,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAY5D;AAQD,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAU5D"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// JMAP envelope parsing, preset paths, $VAR substitution, and HTTP helpers.
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
|
-
import { isAbsolute, resolve as resolvePath } from "node:path";
|
|
4
|
-
import {
|
|
3
|
+
import { dirname, isAbsolute, resolve as resolvePath } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { readCredentials } from "../session/agent-credentials-store.js";
|
|
5
6
|
import { substituteVars } from "./agent-vars.js";
|
|
6
7
|
export const DEFAULT_JMAP_USING = [
|
|
7
8
|
"urn:ietf:params:jmap:core",
|
|
@@ -36,7 +37,50 @@ export function resolveOpsFilePath(credentialDir, opsFile) {
|
|
|
36
37
|
}
|
|
37
38
|
export async function readOpsFile(credentialDir, opsFile) {
|
|
38
39
|
const filePath = resolveOpsFilePath(credentialDir, opsFile);
|
|
39
|
-
|
|
40
|
+
try {
|
|
41
|
+
return await readFile(filePath, "utf-8");
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
if (!(err instanceof Error) || !isFileNotFound(err) || isAbsolute(opsFile)) {
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const bundledPath = await resolveBundledPresetPath(opsFile);
|
|
49
|
+
if (!bundledPath) {
|
|
50
|
+
return await readFile(filePath, "utf-8");
|
|
51
|
+
}
|
|
52
|
+
return await readFile(bundledPath, "utf-8");
|
|
53
|
+
}
|
|
54
|
+
function isFileNotFound(err) {
|
|
55
|
+
const code = err.code;
|
|
56
|
+
return code === "ENOENT" || code === "ENOTDIR";
|
|
57
|
+
}
|
|
58
|
+
async function resolveBundledPresetPath(opsFile) {
|
|
59
|
+
const moduleDir = dirname(fileURLToPath(globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url));
|
|
60
|
+
let currentDir = moduleDir;
|
|
61
|
+
for (let depth = 0; depth < 8; depth++) {
|
|
62
|
+
const candidates = [
|
|
63
|
+
resolvePath(currentDir, "presets", opsFile),
|
|
64
|
+
resolvePath(currentDir, "agent", "jmap", "presets", opsFile),
|
|
65
|
+
resolvePath(currentDir, "lib", "src", "agent", "jmap", "presets", opsFile),
|
|
66
|
+
];
|
|
67
|
+
for (const candidate of candidates) {
|
|
68
|
+
try {
|
|
69
|
+
await readFile(candidate, "utf-8");
|
|
70
|
+
return candidate;
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
if (!(err instanceof Error) || !isFileNotFound(err)) {
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const parent = resolvePath(currentDir, "..");
|
|
79
|
+
if (parent === currentDir)
|
|
80
|
+
break;
|
|
81
|
+
currentDir = parent;
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
40
84
|
}
|
|
41
85
|
export function extractPrimaryMailAccountId(session) {
|
|
42
86
|
const primary = session["primaryAccounts"];
|
|
@@ -49,6 +93,17 @@ export function extractPrimaryMailAccountId(session) {
|
|
|
49
93
|
}
|
|
50
94
|
return id;
|
|
51
95
|
}
|
|
96
|
+
export function extractBlobEndpoints(session) {
|
|
97
|
+
const uploadUrl = session["uploadUrl"];
|
|
98
|
+
const downloadUrl = session["downloadUrl"];
|
|
99
|
+
if (typeof uploadUrl !== "string" || uploadUrl.length === 0) {
|
|
100
|
+
throw new Error("JMAP session missing uploadUrl.");
|
|
101
|
+
}
|
|
102
|
+
if (typeof downloadUrl !== "string" || downloadUrl.length === 0) {
|
|
103
|
+
throw new Error("JMAP session missing downloadUrl.");
|
|
104
|
+
}
|
|
105
|
+
return { uploadUrl, downloadUrl };
|
|
106
|
+
}
|
|
52
107
|
export async function fetchJmapWellKnown(apiUrl, capabilityJwt) {
|
|
53
108
|
const base = apiUrl.replace(/\/+$/, "");
|
|
54
109
|
const res = await fetch(`${base}/.well-known/jmap`, {
|
|
@@ -76,6 +131,11 @@ export async function runJmapRequest(input) {
|
|
|
76
131
|
ACCOUNT_ID: () => input.session.getPrimaryMailAccountId(),
|
|
77
132
|
INBOX: async () => input.session.currentInboxId ??
|
|
78
133
|
(await readCredentials(input.session.files.credentialsFile)).inboxId,
|
|
134
|
+
UPLOAD_URL: async () => input.session.currentUploadUrl ??
|
|
135
|
+
(await readCredentials(input.session.files.credentialsFile)).uploadUrl,
|
|
136
|
+
DOWNLOAD_URL: async () => input.session.currentDownloadUrl ??
|
|
137
|
+
(await readCredentials(input.session.files.credentialsFile))
|
|
138
|
+
.downloadUrl,
|
|
79
139
|
},
|
|
80
140
|
});
|
|
81
141
|
const envelope = parseJmapEnvelope(raw, input.defaultUsing, input.sourceLabel);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-vars.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/jmap/agent-vars.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,eAAO,MAAM,WAAW,QAAyB,CAAC;AAMlD,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,aAA2C,CAAC;AAE1E,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,iGAAiG;IACjG,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAWvD;AAeD;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CA+B/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-credentials-store.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/session/agent-credentials-store.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAOjE;AAMD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAmCxE;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAOlC;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG3E;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAO7B;AAED,0EAA0E;AAC1E,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,IAAI,CAAC,CAcf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-resolve-config.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/session/agent-resolve-config.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,MAAM,YAAY,GACpB,kBAAkB,GAClB,KAAK,GACL,OAAO,GACP,YAAY,CAAC;AAEjB,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAW7C;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CACxD,mBAAmB,CACpB,CAoDA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Resolve MCP / process credential dir + URLs from env + credentials.json.
|
|
2
2
|
import process from "node:process";
|
|
3
|
-
import { DEFAULT_POW_SCRYPT_SALT_HEX } from "
|
|
3
|
+
import { DEFAULT_POW_SCRYPT_SALT_HEX } from "../../core/consts.js";
|
|
4
4
|
import { defaultFilesFromOutDir, tryReadCredentials, } from "./agent-credentials-store.js";
|
|
5
5
|
/**
|
|
6
6
|
* Default credential directory:
|
|
@@ -28,16 +28,21 @@ export declare class AgentSession {
|
|
|
28
28
|
private sessionJWT;
|
|
29
29
|
private capabilityJWT;
|
|
30
30
|
private cachedMailAccountId;
|
|
31
|
+
private cachedUploadUrl;
|
|
32
|
+
private cachedDownloadUrl;
|
|
31
33
|
constructor(cfg: AgentSessionConfig);
|
|
32
34
|
static create(cfg: AgentSessionConfig): Promise<AgentSession>;
|
|
33
35
|
get hasApiKey(): boolean;
|
|
34
36
|
get currentInboxId(): string | undefined;
|
|
37
|
+
get currentUploadUrl(): string | undefined;
|
|
38
|
+
get currentDownloadUrl(): string | undefined;
|
|
35
39
|
private loadFromDisk;
|
|
36
40
|
/**
|
|
37
41
|
* Primary JMAP mail accountId from GET /.well-known/jmap (cached).
|
|
38
42
|
*/
|
|
39
43
|
getPrimaryMailAccountId(): Promise<string>;
|
|
40
44
|
invalidateJmapSessionCache(): void;
|
|
45
|
+
private refreshJmapSessionData;
|
|
41
46
|
/**
|
|
42
47
|
* Register or return existing inbox when username matches (idempotent).
|
|
43
48
|
* Different username replaces on-disk credentials and creates a new inbox.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/session/agent-session.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,UAAU,EAMhB,MAAM,8BAA8B,CAAC;AActC,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAMD,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAAqB;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAE3B,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,iBAAiB,CAAqB;gBAElC,GAAG,EAAE,kBAAkB;WAUtB,MAAM,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC;IAMnE,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,cAAc,IAAI,MAAM,GAAG,SAAS,CAEvC;IAED,IAAI,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAEzC;IAED,IAAI,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAE3C;YAEa,YAAY;IAY1B;;OAEG;IACG,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC;IAehD,0BAA0B,IAAI,IAAI;YAMpB,sBAAsB;IASpC;;;OAGG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA8EnD,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC;YA4B7B,aAAa;IA2B3B,OAAO,IAAI,IAAI;CAGhB;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,0EAA0E;AAC1E,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA6B9B"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Stateful PoW + capability JWT + optional cached JMAP session (accountId).
|
|
2
2
|
import { tryReadCredentials, tryReadJwtFile, unlinkCredentialArtifacts, writeCredentials, writeJwtFile, } from "./agent-credentials-store.js";
|
|
3
|
-
import { CAPABILITY_SAFETY_MARGIN_MS, decodeJwtPayload, isJwtExpired, SESSION_SAFETY_MARGIN_MS, } from "
|
|
4
|
-
import { extractPrimaryMailAccountId, fetchJmapWellKnown, } from "
|
|
5
|
-
import { fetchCapability, performPoWAndSession } from "
|
|
3
|
+
import { CAPABILITY_SAFETY_MARGIN_MS, decodeJwtPayload, isJwtExpired, SESSION_SAFETY_MARGIN_MS, } from "../auth/agent-jwt.js";
|
|
4
|
+
import { extractBlobEndpoints, extractPrimaryMailAccountId, fetchJmapWellKnown, } from "../jmap/agent-jmap.js";
|
|
5
|
+
import { fetchCapability, performPoWAndSession } from "../auth/agent-auth-http.js";
|
|
6
6
|
function normalizeUsername(u) {
|
|
7
7
|
return u.trim().toLowerCase();
|
|
8
8
|
}
|
|
@@ -24,6 +24,8 @@ export class AgentSession {
|
|
|
24
24
|
sessionJWT;
|
|
25
25
|
capabilityJWT;
|
|
26
26
|
cachedMailAccountId;
|
|
27
|
+
cachedUploadUrl;
|
|
28
|
+
cachedDownloadUrl;
|
|
27
29
|
constructor(cfg) {
|
|
28
30
|
this.authUrl = cfg.authUrl.replace(/\/+$/, "");
|
|
29
31
|
this.apiUrl = cfg.apiUrl.replace(/\/+$/, "");
|
|
@@ -44,6 +46,12 @@ export class AgentSession {
|
|
|
44
46
|
get currentInboxId() {
|
|
45
47
|
return this.inboxId;
|
|
46
48
|
}
|
|
49
|
+
get currentUploadUrl() {
|
|
50
|
+
return this.cachedUploadUrl;
|
|
51
|
+
}
|
|
52
|
+
get currentDownloadUrl() {
|
|
53
|
+
return this.cachedDownloadUrl;
|
|
54
|
+
}
|
|
47
55
|
async loadFromDisk() {
|
|
48
56
|
this.sessionJWT = await tryReadJwtFile(this.files.sessionFile);
|
|
49
57
|
this.capabilityJWT = await tryReadJwtFile(this.files.capabilityFile);
|
|
@@ -51,22 +59,37 @@ export class AgentSession {
|
|
|
51
59
|
if (disk) {
|
|
52
60
|
this.apiKey = this.apiKey ?? disk.apiKey;
|
|
53
61
|
this.inboxId = this.inboxId ?? disk.inboxId;
|
|
62
|
+
this.cachedUploadUrl = disk.uploadUrl;
|
|
63
|
+
this.cachedDownloadUrl = disk.downloadUrl;
|
|
54
64
|
}
|
|
55
65
|
}
|
|
56
66
|
/**
|
|
57
67
|
* Primary JMAP mail accountId from GET /.well-known/jmap (cached).
|
|
58
68
|
*/
|
|
59
69
|
async getPrimaryMailAccountId() {
|
|
60
|
-
if (this.cachedMailAccountId
|
|
70
|
+
if (this.cachedMailAccountId &&
|
|
71
|
+
this.cachedUploadUrl &&
|
|
72
|
+
this.cachedDownloadUrl) {
|
|
61
73
|
return this.cachedMailAccountId;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
}
|
|
75
|
+
await this.refreshJmapSessionData();
|
|
76
|
+
if (!this.cachedMailAccountId) {
|
|
77
|
+
throw new Error("JMAP session missing primary mail account id.");
|
|
78
|
+
}
|
|
79
|
+
return this.cachedMailAccountId;
|
|
67
80
|
}
|
|
68
81
|
invalidateJmapSessionCache() {
|
|
69
82
|
this.cachedMailAccountId = undefined;
|
|
83
|
+
this.cachedUploadUrl = undefined;
|
|
84
|
+
this.cachedDownloadUrl = undefined;
|
|
85
|
+
}
|
|
86
|
+
async refreshJmapSessionData() {
|
|
87
|
+
const cap = await this.getCapabilityToken();
|
|
88
|
+
const session = await fetchJmapWellKnown(this.apiUrl, cap);
|
|
89
|
+
this.cachedMailAccountId = extractPrimaryMailAccountId(session);
|
|
90
|
+
const blobs = extractBlobEndpoints(session);
|
|
91
|
+
this.cachedUploadUrl = blobs.uploadUrl;
|
|
92
|
+
this.cachedDownloadUrl = blobs.downloadUrl;
|
|
70
93
|
}
|
|
71
94
|
/**
|
|
72
95
|
* Register or return existing inbox when username matches (idempotent).
|
|
@@ -115,15 +138,22 @@ export class AgentSession {
|
|
|
115
138
|
}
|
|
116
139
|
this.inboxId = claims.inboxId;
|
|
117
140
|
this.cachedMailAccountId = undefined;
|
|
141
|
+
this.cachedUploadUrl = undefined;
|
|
142
|
+
this.cachedDownloadUrl = undefined;
|
|
143
|
+
const accountId = await this.getPrimaryMailAccountId();
|
|
144
|
+
if (!this.cachedUploadUrl || !this.cachedDownloadUrl) {
|
|
145
|
+
throw new Error("JMAP session did not provide upload/download URLs.");
|
|
146
|
+
}
|
|
118
147
|
const creds = {
|
|
119
148
|
apiKey: this.apiKey,
|
|
120
149
|
inboxId: this.inboxId,
|
|
121
150
|
authUrl: this.authUrl,
|
|
122
151
|
apiUrl: this.apiUrl,
|
|
123
152
|
scryptSalt: this.scryptSalt,
|
|
153
|
+
uploadUrl: this.cachedUploadUrl,
|
|
154
|
+
downloadUrl: this.cachedDownloadUrl,
|
|
124
155
|
};
|
|
125
156
|
await writeCredentials(this.files.credentialsFile, creds);
|
|
126
|
-
const accountId = await this.getPrimaryMailAccountId();
|
|
127
157
|
return {
|
|
128
158
|
inbox: this.inboxId,
|
|
129
159
|
accountId,
|
|
@@ -171,6 +201,8 @@ export class AgentSession {
|
|
|
171
201
|
this.sessionJWT = result.sessionJWT;
|
|
172
202
|
this.capabilityJWT = undefined;
|
|
173
203
|
this.cachedMailAccountId = undefined;
|
|
204
|
+
this.cachedUploadUrl = undefined;
|
|
205
|
+
this.cachedDownloadUrl = undefined;
|
|
174
206
|
await writeJwtFile(this.files.sessionFile, this.sessionJWT);
|
|
175
207
|
}
|
|
176
208
|
destroy() {
|
|
@@ -193,12 +225,16 @@ export async function persistLoginWithApiKey(input) {
|
|
|
193
225
|
if (typeof inboxId !== "string" || inboxId.length === 0) {
|
|
194
226
|
throw new Error("Capability JWT did not contain an inboxId claim.");
|
|
195
227
|
}
|
|
228
|
+
const jmapSession = await fetchJmapWellKnown(apiUrl, capabilityJWT);
|
|
229
|
+
const blobs = extractBlobEndpoints(jmapSession);
|
|
196
230
|
await writeCredentials(input.files.credentialsFile, {
|
|
197
231
|
apiKey: input.apiKey,
|
|
198
232
|
inboxId,
|
|
199
233
|
authUrl,
|
|
200
234
|
apiUrl,
|
|
201
235
|
scryptSalt: input.scryptSalt,
|
|
236
|
+
uploadUrl: blobs.uploadUrl,
|
|
237
|
+
downloadUrl: blobs.downloadUrl,
|
|
202
238
|
});
|
|
203
239
|
await writeJwtFile(input.files.sessionFile, session.sessionJWT);
|
|
204
240
|
await writeJwtFile(input.files.capabilityFile, capabilityJWT);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../../src/lib/core/consts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,qEAC4B,CAAC;AAErE,eAAO,MAAM,UAAU,OAAO,CAAC;AAC/B,eAAO,MAAM,UAAU,QAAkB,CAAC;AAC1C,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,UAAU,QAAmB,CAAC;AAC3C,eAAO,MAAM,YAAY,QAAkB,CAAC;AAC5C,eAAO,MAAM,WAAW,QAAmB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads README.md from the npm package root (next to package.json).
|
|
3
|
+
* Intended for published @atomicmail/mcp and @atomicmail/agent-skill layouts.
|
|
4
|
+
*/
|
|
5
|
+
export declare function readNpmPackageReadme(): Promise<string>;
|
|
6
|
+
//# sourceMappingURL=read-npm-package-readme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-npm-package-readme.d.ts","sourceRoot":"","sources":["../../../src/lib/core/read-npm-package-readme.ts"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,CA+C5D"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
const MAX_DEPTH = 16;
|
|
5
|
+
const ATOMICMAIL_NPM_NAMES = new Set([
|
|
6
|
+
"@atomicmail/mcp",
|
|
7
|
+
"@atomicmail/agent-skill",
|
|
8
|
+
]);
|
|
9
|
+
function isEnoent(err) {
|
|
10
|
+
if (!(err instanceof Error))
|
|
11
|
+
return false;
|
|
12
|
+
const code = err.code;
|
|
13
|
+
return code === "ENOENT" || code === "ENOTDIR";
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Reads README.md from the npm package root (next to package.json).
|
|
17
|
+
* Intended for published @atomicmail/mcp and @atomicmail/agent-skill layouts.
|
|
18
|
+
*/
|
|
19
|
+
export async function readNpmPackageReadme() {
|
|
20
|
+
const moduleDir = dirname(fileURLToPath(globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url));
|
|
21
|
+
let currentDir = moduleDir;
|
|
22
|
+
for (let i = 0; i < MAX_DEPTH; i++) {
|
|
23
|
+
const pkgPath = resolve(currentDir, "package.json");
|
|
24
|
+
const readmePath = resolve(currentDir, "README.md");
|
|
25
|
+
let pkgRaw;
|
|
26
|
+
try {
|
|
27
|
+
pkgRaw = await readFile(pkgPath, "utf-8");
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
if (!isEnoent(err))
|
|
31
|
+
throw err;
|
|
32
|
+
const parent = resolve(currentDir, "..");
|
|
33
|
+
if (parent === currentDir)
|
|
34
|
+
break;
|
|
35
|
+
currentDir = parent;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
let name;
|
|
39
|
+
try {
|
|
40
|
+
name = JSON.parse(pkgRaw).name;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
name = undefined;
|
|
44
|
+
}
|
|
45
|
+
if (!name || !ATOMICMAIL_NPM_NAMES.has(name)) {
|
|
46
|
+
const parent = resolve(currentDir, "..");
|
|
47
|
+
if (parent === currentDir)
|
|
48
|
+
break;
|
|
49
|
+
currentDir = parent;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
return await readFile(readmePath, "utf-8");
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
if (!isEnoent(err))
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
const parent = resolve(currentDir, "..");
|
|
60
|
+
if (parent === currentDir)
|
|
61
|
+
break;
|
|
62
|
+
currentDir = parent;
|
|
63
|
+
}
|
|
64
|
+
throw new Error("Could not find Atomic Mail package README.md — use a published npm install " +
|
|
65
|
+
"(@atomicmail/mcp or @atomicmail/agent-skill) for --topic readme.");
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MaybePromise } from "./types.js";
|
|
2
|
+
export declare function delay(ms: number): Promise<void>;
|
|
3
|
+
export type RetryCfg = {
|
|
4
|
+
maxTimeoutMs?: number;
|
|
5
|
+
startTimeoutMs?: number;
|
|
6
|
+
backoffMul?: number;
|
|
7
|
+
onBeforeRetry?: (e: unknown) => MaybePromise<void>;
|
|
8
|
+
};
|
|
9
|
+
export declare function retry<R>(fn: () => MaybePromise<R>, config: RetryCfg): Promise<R>;
|
|
10
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/core/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;CACpD,CAAC;AASF,wBAAsB,KAAK,CAAC,CAAC,EAC3B,EAAE,EAAE,MAAM,YAAY,CAAC,CAAC,CAAC,EACzB,MAAM,EAAE,QAAQ,GACf,OAAO,CAAC,CAAC,CAAC,CAgBZ"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ONE_SEC_MS } from "./consts.js";
|
|
2
|
+
export function delay(ms) {
|
|
3
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4
|
+
}
|
|
5
|
+
const defaultCfg = {
|
|
6
|
+
maxTimeoutMs: ONE_SEC_MS * 32,
|
|
7
|
+
startTimeoutMs: ONE_SEC_MS,
|
|
8
|
+
backoffMul: 2,
|
|
9
|
+
};
|
|
10
|
+
// retry with exponential backoff, retries the fn on throw, re-throws on max backoff
|
|
11
|
+
export async function retry(fn, config) {
|
|
12
|
+
const cfg = { ...defaultCfg, ...config };
|
|
13
|
+
let curTimeoutMs = cfg.startTimeoutMs;
|
|
14
|
+
while (true) {
|
|
15
|
+
try {
|
|
16
|
+
const res = await fn();
|
|
17
|
+
return res;
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
if (cfg.onBeforeRetry)
|
|
21
|
+
await cfg.onBeforeRetry(e);
|
|
22
|
+
if (curTimeoutMs > cfg.maxTimeoutMs)
|
|
23
|
+
throw e;
|
|
24
|
+
await delay(curTimeoutMs);
|
|
25
|
+
curTimeoutMs = Math.floor(curTimeoutMs * cfg.backoffMul);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
package/esm/lib/mod.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./network/auth-client.js";
|
|
2
|
+
export * from "./core/utils.js";
|
|
3
|
+
export * from "./core/read-npm-package-readme.js";
|
|
4
|
+
export * from "./core/consts.js";
|
|
5
|
+
export * from "./core/types.js";
|
|
6
|
+
export * from "./agent/session/agent-credentials-store.js";
|
|
7
|
+
export * from "./agent/auth/agent-jwt.js";
|
|
8
|
+
export * from "./agent/auth/agent-pow.js";
|
|
9
|
+
export * from "./agent/auth/agent-auth-http.js";
|
|
10
|
+
export * from "./agent/jmap/agent-jmap.js";
|
|
11
|
+
export * from "./agent/session/agent-session.js";
|
|
12
|
+
export * from "./agent/session/agent-resolve-config.js";
|
|
13
|
+
export * from "./agent/jmap/agent-help-content.js";
|
|
14
|
+
export * from "./agent/jmap/agent-vars.js";
|
|
15
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/lib/mod.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mCAAmC,CAAC;AAClD,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAEhC,cAAc,4CAA4C,CAAC;AAC3D,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kCAAkC,CAAC;AACjD,cAAc,yCAAyC,CAAC;AACxD,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC"}
|
package/esm/lib/mod.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./network/auth-client.js";
|
|
2
|
+
export * from "./core/utils.js";
|
|
3
|
+
export * from "./core/read-npm-package-readme.js";
|
|
4
|
+
export * from "./core/consts.js";
|
|
5
|
+
export * from "./core/types.js";
|
|
6
|
+
export * from "./agent/session/agent-credentials-store.js";
|
|
7
|
+
export * from "./agent/auth/agent-jwt.js";
|
|
8
|
+
export * from "./agent/auth/agent-pow.js";
|
|
9
|
+
export * from "./agent/auth/agent-auth-http.js";
|
|
10
|
+
export * from "./agent/jmap/agent-jmap.js";
|
|
11
|
+
export * from "./agent/session/agent-session.js";
|
|
12
|
+
export * from "./agent/session/agent-resolve-config.js";
|
|
13
|
+
export * from "./agent/jmap/agent-help-content.js";
|
|
14
|
+
export * from "./agent/jmap/agent-vars.js";
|